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;
9
10use crate::arch::instruction::Instruction;
11use crate::arch::vm::get_root_pagetable;
12use crate::early_println;
13use crate::environment::NUM_OF_CPUS;
14use crate::environment::STACK_SIZE;
15use crate::mem::KERNEL_STACK;
16use crate::task::Task;
17
18pub mod boot;
19pub mod instruction;
20pub mod interrupt;
21pub mod kernel;
22pub mod trap;
23pub mod earlycon;
24pub mod vcpu;
25pub mod timer;
26pub mod vm;
27pub mod registers;
28
29pub use earlycon::*;
30pub use registers::Registers;
31
32pub type Arch = Riscv64;
33pub type Trapframe = Riscv64;
34
35#[unsafe(link_section = ".trampoline.data")]
36static mut TRAPFRAME: [Riscv64; NUM_OF_CPUS] = [const { Riscv64::new(0) }; NUM_OF_CPUS];
37
38#[repr(align(4))]
39#[derive(Debug, Clone)]
40pub struct Riscv64 {
41 pub regs: Registers,
42 pub epc: u64,
43 pub hartid: u64,
44 satp: u64,
45 kernel_stack: u64,
46 kernel_trap: u64,
47}
48
49pub fn init_arch(cpu_id: usize) {
50 early_println!("[riscv64] Hart {}: Initializing core....", cpu_id);
51 let riscv: &mut Riscv64 = unsafe { transmute(&TRAPFRAME[cpu_id] as *const _ as usize ) };
53 trap_init(riscv);
54}
55
56impl Riscv64 {
57 pub const fn new(cpu_id: usize) -> Self {
58 Riscv64 { hartid: cpu_id as u64, epc: 0, regs: Registers::new(), kernel_stack: 0, kernel_trap: 0, satp: 0 }
59 }
60
61 pub fn get_cpuid(&self) -> usize {
62 self.hartid as usize
63 }
64
65 pub fn get_trapframe_paddr(&self) -> usize {
66 let addr = unsafe { &raw mut TRAPFRAME[self.hartid as usize] } as *const _ as usize;
68 addr
69 }
70
71 pub fn get_trapframe(&mut self) -> &mut Trapframe {
72 self
73 }
74}
75
76impl Trapframe {
77 pub fn set_trap_handler(&mut self, addr: usize) {
78 self.kernel_trap = addr as u64;
79 }
80
81 pub fn set_next_address_space(&mut self, asid: u16) {
82 let root_pagetable = get_root_pagetable(asid).expect("No root page table found for ASID");
83
84 let satp = root_pagetable.get_val_for_satp(asid);
85 self.satp = satp as u64;
86 }
87
88
89 pub fn get_syscall_number(&self) -> usize {
90 self.regs.reg[17] }
92
93 pub fn set_syscall_number(&mut self, syscall_number: usize) {
94 self.regs.reg[17] = syscall_number; }
96
97 pub fn get_return_value(&self) -> usize {
98 self.regs.reg[10] }
100
101 pub fn set_return_value(&mut self, value: usize) {
102 self.regs.reg[10] = value; }
104
105 pub fn get_arg(&self, index: usize) -> usize {
106 self.regs.reg[index + 10] }
108
109 pub fn set_arg(&mut self, index: usize, value: usize) {
110 self.regs.reg[index + 10] = value; }
112
113 pub fn increment_pc_next(&mut self, task: &Task) {
117 let instruction = Instruction::fetch(
118 task.vm_manager.translate_vaddr(self.epc as usize).unwrap()
119 );
120 let len = instruction.len();
121 if len == 0 {
122 debug_assert!(len > 0, "Invalid instruction length: {}", len);
123 early_println!("Warning: Invalid instruction length encountered. Defaulting to 4 bytes.");
124 self.epc += 4; } else {
126 self.epc += len as u64;
127 }
128 }
129}
130
131pub fn get_user_trapvector_paddr() -> usize {
132 _user_trap_entry as usize
133}
134
135pub fn get_kernel_trapvector_paddr() -> usize {
136 _kernel_trap_entry as usize
137}
138
139pub fn get_kernel_trap_handler() -> usize {
140 arch_kernel_trap_handler as usize
141}
142
143pub fn get_user_trap_handler() -> usize {
144 arch_user_trap_handler as usize
145}
146
147#[allow(static_mut_refs)]
148fn trap_init(riscv: &mut Riscv64) {
149 early_println!("[riscv64] Hart {}: Initializing trap....", riscv.hartid);
150
151 let trap_stack_top = unsafe { KERNEL_STACK.top() };
152 let stack_size = STACK_SIZE;
153
154 let trap_stack = trap_stack_top + stack_size * (riscv.hartid + 1) as usize;
155 early_println!("[riscv64] Hart {}: Trap stack top : {:#x}", riscv.hartid, trap_stack_top);
156 early_println!("[riscv64] Hart {}: Trap stack bottom : {:#x}", riscv.hartid, trap_stack);
157
158 early_println!("[riscv64] Hart {}: Trap stack size : {:#x}", riscv.hartid, stack_size);
159
160 early_println!("[riscv64] Hart {}: Setting up scratch space....", riscv.hartid);
162 riscv.kernel_stack = trap_stack as u64;
163 riscv.kernel_trap = arch_kernel_trap_handler as u64;
164
165 let scratch_addr = riscv as *const _ as usize;
166 early_println!("[riscv64] Hart {}: Scratch address : {:#x}", riscv.hartid, scratch_addr);
167 let sie: usize = 0x20;
168 unsafe {
169 asm!("
170 csrw sie, {0}
171 csrsi sstatus, 0x2
172 csrw stvec, {1}
173 csrw sscratch, {2}
174 ",
175 in(reg) sie,
176 in(reg) _kernel_trap_entry as usize,
177 in(reg) scratch_addr,
178 );
179 }
180}
181
182pub fn set_trapvector(addr: usize) {
183 unsafe {
184 asm!("
185 csrw stvec, {0}
186 ",
187 in(reg) addr,
188 );
189 }
190}
191
192pub fn set_trapframe(addr: usize) {
193 unsafe {
194 asm!("
195 csrw sscratch, {0}
196 ",
197 in(reg) addr,
198 );
199 }
200}
201
202pub fn enable_interrupt() {
203 unsafe {
204 asm!("
205 csrsi sstatus, 0x2
206 ");
207 }
208}
209
210pub fn disable_interrupt() {
211 unsafe {
212 asm!("
213 csrci sstatus, 0x2
214 ");
215 }
216}
217
218pub fn get_cpu() -> &'static mut Riscv64 {
219 let scratch: usize;
220
221 unsafe {
222 asm!("
223 csrr {0}, sscratch
224 ",
225 out(reg) scratch,
226 );
227 }
228 unsafe { transmute(scratch) }
229}
230
231pub fn set_next_mode(mode: Mode) {
232 match mode {
233 Mode::User => {
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 Mode::Kernel => {
249 unsafe {
250 let mut sstatus: usize;
252 asm!(
253 "csrr {sstatus}, sstatus",
254 sstatus = out(reg) sstatus,
255 );
256 sstatus |= 1 << 8; asm!(
258 "csrw sstatus, {sstatus}",
259 sstatus = in(reg) sstatus,
260 );
261 }
262 },
263 }
264}
265
266pub fn shutdown() -> ! {
267 sbi_system_reset(0, 0);
268}
269
270pub fn shutdown_with_code(exit_code: u32) -> ! {
271 sbi_system_reset(0, exit_code);
273}
274
275pub fn reboot() -> ! {
276 sbi_system_reset(1, 0);
277}