kernel/arch/riscv64/
mod.rs1use core::arch::asm;
2use core::mem::transmute;
3use instruction::sbi::sbi_system_reset;
4use trap::kernel::arch_kernel_trap_handler;
5use trap::kernel::_kernel_trap_entry;
6use trap::user::_user_trap_entry;
7use trap::user::arch_user_trap_handler;
8use vcpu::Mode;
9use vm::get_page_table;
10use vm::get_root_page_table_idx;
11
12use crate::early_println;
13use crate::environment::NUM_OF_CPUS;
14use crate::environment::STACK_SIZE;
15use crate::mem::KERNEL_STACK;
16
17pub mod boot;
18pub mod instruction;
19pub mod kernel;
20pub mod trap;
21pub mod earlycon;
22pub mod vcpu;
23pub mod timer;
24pub mod vm;
25pub mod registers;
26
27pub use earlycon::*;
28pub use registers::Registers;
29
30pub type Arch = Riscv64;
31pub type Trapframe = Riscv64;
32
33#[unsafe(link_section = ".trampoline.data")]
34static mut TRAPFRAME: [Riscv64; NUM_OF_CPUS] = [const { Riscv64::new(0) }; NUM_OF_CPUS];
35
36#[repr(align(4))]
37#[derive(Debug)]
38pub struct Riscv64 {
39 pub regs: Registers,
40 pub epc: u64,
41 pub hartid: u64,
42 satp: u64,
43 kernel_stack: u64,
44 kernel_trap: u64,
45}
46
47pub fn init_arch(cpu_id: usize) {
48 early_println!("[riscv64] Hart {}: Initializing core....", cpu_id);
49 let riscv: &mut Riscv64 = unsafe { transmute(&TRAPFRAME[cpu_id] as *const _ as usize ) };
51 trap_init(riscv);
52}
53
54impl Riscv64 {
55 pub const fn new(cpu_id: usize) -> Self {
56 Riscv64 { hartid: cpu_id as u64, epc: 0, regs: Registers::new(), kernel_stack: 0, kernel_trap: 0, satp: 0 }
57 }
58
59 pub fn get_cpuid(&self) -> usize {
60 self.hartid as usize
61 }
62
63 pub fn get_trapframe_paddr(&self) -> usize {
64 let addr = unsafe { &raw mut TRAPFRAME[self.hartid as usize] } as *const _ as usize;
66 addr
67 }
68
69 pub fn get_trapframe(&mut self) -> &mut Trapframe {
70 self
71 }
72}
73
74impl Trapframe {
75 pub fn set_trap_handler(&mut self, addr: usize) {
76 self.kernel_trap = addr as u64;
77 }
78
79 pub fn set_next_address_space(&mut self, asid: usize) {
80 let root_page_table_idx = get_root_page_table_idx(asid);
81 if root_page_table_idx.is_none() {
82 panic!("No root page table found for ASID {}", asid);
83 }
84 let root_page_table = get_page_table(root_page_table_idx.unwrap()).unwrap();
85
86 let satp = root_page_table.get_val_for_satp(asid);
87 self.satp = satp as u64;
88 }
89
90
91 pub fn get_syscall_number(&self) -> usize {
92 self.regs.reg[17] }
94
95 pub fn set_syscall_number(&mut self, syscall_number: usize) {
96 self.regs.reg[17] = syscall_number; }
98
99 pub fn get_return_value(&self) -> usize {
100 self.regs.reg[10] }
102
103 pub fn set_return_value(&mut self, value: usize) {
104 self.regs.reg[10] = value; }
106
107 pub fn get_arg(&self, index: usize) -> usize {
108 self.regs.reg[index + 10] }
110
111 pub fn set_arg(&mut self, index: usize, value: usize) {
112 self.regs.reg[index + 10] = value; }
114}
115
116pub fn get_user_trapvector_paddr() -> usize {
117 _user_trap_entry as usize
118}
119
120pub fn get_kernel_trapvector_paddr() -> usize {
121 _kernel_trap_entry as usize
122}
123
124pub fn get_kernel_trap_handler() -> usize {
125 arch_kernel_trap_handler as usize
126}
127
128pub fn get_user_trap_handler() -> usize {
129 arch_user_trap_handler as usize
130}
131
132#[allow(static_mut_refs)]
133fn trap_init(riscv: &mut Riscv64) {
134 early_println!("[riscv64] Hart {}: Initializing trap....", riscv.hartid);
135
136 let trap_stack_top = unsafe { KERNEL_STACK.top() };
137 let stack_size = STACK_SIZE;
138
139 let trap_stack = trap_stack_top + stack_size * (riscv.hartid + 1) as usize;
140 early_println!("[riscv64] Hart {}: Trap stack top : {:#x}", riscv.hartid, trap_stack_top);
141 early_println!("[riscv64] Hart {}: Trap stack bottom : {:#x}", riscv.hartid, trap_stack);
142
143 early_println!("[riscv64] Hart {}: Trap stack size : {:#x}", riscv.hartid, stack_size);
144
145 early_println!("[riscv64] Hart {}: Setting up scratch space....", riscv.hartid);
147 riscv.kernel_stack = trap_stack as u64;
148 riscv.kernel_trap = arch_kernel_trap_handler as u64;
149
150 let scratch_addr = riscv as *const _ as usize;
151 early_println!("[riscv64] Hart {}: Scratch address : {:#x}", riscv.hartid, scratch_addr);
152 let sie: usize = 0x20;
153 unsafe {
154 asm!("
155 csrw sie, {0}
156 csrsi sstatus, 0x2
157 csrw stvec, {1}
158 csrw sscratch, {2}
159 ",
160 in(reg) sie,
161 in(reg) _kernel_trap_entry as usize,
162 in(reg) scratch_addr,
163 );
164 }
165}
166
167pub fn set_trapvector(addr: usize) {
168 unsafe {
169 asm!("
170 csrw stvec, {0}
171 ",
172 in(reg) addr,
173 );
174 }
175}
176
177pub fn set_trapframe(addr: usize) {
178 unsafe {
179 asm!("
180 csrw sscratch, {0}
181 ",
182 in(reg) addr,
183 );
184 }
185}
186
187pub fn enable_interrupt() {
188 unsafe {
189 asm!("
190 csrsi sstatus, 0x2
191 ");
192 }
193}
194
195pub fn disable_interrupt() {
196 unsafe {
197 asm!("
198 csrci sstatus, 0x2
199 ");
200 }
201}
202
203pub fn get_cpu() -> &'static mut Riscv64 {
204 let scratch: usize;
205
206 unsafe {
207 asm!("
208 csrr {0}, sscratch
209 ",
210 out(reg) scratch,
211 );
212 }
213 unsafe { transmute(scratch) }
214}
215
216pub fn set_next_mode(mode: Mode) {
217 match mode {
218 Mode::User => {
219 unsafe {
220 let mut sstatus: usize;
222 asm!(
223 "csrr {sstatus}, sstatus",
224 sstatus = out(reg) sstatus,
225 );
226 sstatus &= !(1 << 8); asm!(
228 "csrw sstatus, {sstatus}",
229 sstatus = in(reg) sstatus,
230 );
231 }
232 },
233 Mode::Kernel => {
234 unsafe {
235 let mut sstatus: usize;
237 asm!(
238 "csrr {sstatus}, sstatus",
239 sstatus = out(reg) sstatus,
240 );
241 sstatus |= 1 << 8; asm!(
243 "csrw sstatus, {sstatus}",
244 sstatus = in(reg) sstatus,
245 );
246 }
247 },
248 }
249}
250
251pub fn shutdown() -> ! {
252 sbi_system_reset(0, 0);
253}
254
255pub fn reboot() -> ! {
256 sbi_system_reset(1, 0);
257}