1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
use crate::spinlock::Mutex;
use crate::process::my_cpu;
use crate::arch::hart_id;
pub const PLIC_BASE: usize = 0x0c00_0000;
pub const PLIC_PRIORITY: usize = PLIC_BASE + 0x0;
pub const PLIC_PENDING: usize = PLIC_BASE + 0x1000;
pub const PLIC_MENABLE_BASE: usize = PLIC_BASE + 0x2000;
pub const PLIC_SENABLE_BASE: usize = PLIC_BASE + 0x2080;
pub const PLIC_MPRIORITY_BASE: usize = PLIC_BASE + 0x200000;
pub const PLIC_SPRIORITY_BASE: usize = PLIC_BASE + 0x201000;
pub const PLIC_MCLAIM_BASE: usize = PLIC_BASE + 0x200004;
pub const PLIC_SCLAIM_BASE: usize = PLIC_BASE + 0x201004;
#[allow(non_snake_case)]
pub const fn PLIC_MENABLE(hart: usize) -> usize { PLIC_MENABLE_BASE + hart * 0x100 }
#[allow(non_snake_case)]
pub const fn PLIC_SENABLE(hart: usize) -> usize { PLIC_SENABLE_BASE + hart * 0x100 }
#[allow(non_snake_case)]
pub const fn PLIC_MPRIORITY(hart: usize) -> usize { PLIC_MPRIORITY_BASE + hart * 0x2000 }
#[allow(non_snake_case)]
pub const fn PLIC_SPRIORITY(hart: usize) -> usize { PLIC_SPRIORITY_BASE + hart * 0x2000 }
#[allow(non_snake_case)]
pub const fn PLIC_MCLAIM(hart: usize) -> usize { PLIC_MCLAIM_BASE + hart * 0x2000 }
#[allow(non_snake_case)]
pub const fn PLIC_SCLAIM(hart: usize) -> usize { PLIC_SCLAIM_BASE + hart * 0x2000 }
pub const UART0_IRQ: u32 = 10;
pub const VIRTIO0_IRQ: u32 = 1;
pub struct Plic {}
impl Plic {
pub const fn new() -> Self {
Self {}
}
pub fn next(&mut self) -> Option<u32> {
let claim_reg = PLIC_SCLAIM(hart_id()) as *const u32;
let claim_no;
unsafe {
claim_no = claim_reg.read_volatile();
}
if claim_no == 0 {
None
} else {
Some(claim_no)
}
}
pub fn complete(&mut self, id: u32) {
let complete_reg = PLIC_SCLAIM(hart_id()) as *mut u32;
unsafe {
complete_reg.write_volatile(id);
}
}
pub unsafe fn init(&mut self, id: u32) {
let enables = PLIC_BASE as *mut u32;
enables.add(id as usize).write_volatile(1);
}
pub unsafe fn is_pending(&mut self, id: u32) -> bool {
let pend = PLIC_PENDING as *const u32;
let actual_id = 1 << id;
let pend_ids;
pend_ids = pend.read_volatile();
actual_id & pend_ids != 0
}
pub fn enable(&mut self, id: u32) {
let enables = PLIC_SENABLE(hart_id()) as *mut u32;
let actual_id = 1 << id;
unsafe {
enables.write_volatile(enables.read_volatile() | actual_id);
}
}
pub fn set_threshold(&mut self, tsh: u8) {
let actual_tsh = tsh & 7;
let tsh_reg = PLIC_SPRIORITY(hart_id()) as *mut u32;
unsafe {
tsh_reg.write_volatile(actual_tsh as u32);
}
}
pub fn set_priority(&mut self, id: u32, prio: u8) {
let actual_prio = prio as u32 & 7;
let prio_reg = PLIC_SPRIORITY(hart_id()) as *mut u32;
unsafe {
prio_reg.add(id as usize).write_volatile(actual_prio);
}
}
}
static mut __PLIC: Plic = Plic::new();
#[allow(non_snake_case)]
pub fn PLIC() -> &'static mut Plic { unsafe { &mut __PLIC } }
pub unsafe fn init() {
let plic = PLIC();
plic.init(UART0_IRQ);
plic.init(VIRTIO0_IRQ);
}
pub fn hartinit() {
let plic = PLIC();
plic.enable(UART0_IRQ);
plic.enable(VIRTIO0_IRQ);
plic.set_threshold(0);
plic.set_priority(UART0_IRQ, 1);
plic.set_priority(VIRTIO0_IRQ, 1);
}