1 use crate::arch::{ 2 asm::csr::{ 3 CSR_SCAUSE, CSR_SEPC, CSR_SSCRATCH, CSR_SSTATUS, CSR_STVAL, SR_FS_VS, SR_SPP, SR_SUM, 4 }, 5 cpu::LocalContext, 6 interrupt::TrapFrame, 7 }; 8 use asm_macros::{restore_from_x6_to_x31, save_from_x6_to_x31}; 9 use core::arch::asm; 10 use kdepends::memoffset::offset_of; 11 12 /// Riscv64中断处理入口 13 #[naked] 14 #[no_mangle] 15 #[repr(align(4))] 16 pub unsafe extern "C" fn handle_exception() -> ! { 17 asm!( 18 concat!(" 19 /* 20 * If coming from userspace, preserve the user thread pointer and load 21 * the kernel thread pointer. If we came from the kernel, the scratch 22 * register will contain 0, and we should continue on the current TP. 23 */ 24 25 csrrw tp, {csr_scratch}, tp 26 bnez tp, _save_context 27 28 /* 从内核态进入中断 */ 29 j {_restore_kernel_tpsp} 30 "), 31 csr_scratch = const CSR_SSCRATCH, 32 _restore_kernel_tpsp = sym _restore_kernel_tpsp, 33 options(noreturn), 34 ) 35 } 36 37 #[naked] 38 #[no_mangle] 39 unsafe extern "C" fn _restore_kernel_tpsp() -> ! { 40 asm!( 41 concat!(" 42 // 这次是从内核态进入中断 43 // 从sscratch寄存器加载当前cpu的上下文 44 csrr tp, {csr_scratch} 45 46 // 把当前的sp寄存器的值保存到当前cpu的上下文的kernel_sp字段 47 sd sp, {lc_off_kernel_sp}(tp) 48 49 j {_save_context} 50 "), 51 csr_scratch = const CSR_SSCRATCH, 52 lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp), 53 _save_context = sym _save_context, 54 55 options(noreturn), 56 ) 57 } 58 59 #[naked] 60 #[no_mangle] 61 unsafe extern "C" fn _save_context() -> ! { 62 asm!( 63 concat!(" 64 65 66 // 保存当前cpu的上下文 67 68 // 保存用户sp 69 sd sp, {lc_off_user_sp}(tp) 70 // 加载内核sp 71 ld sp, {lc_off_kernel_sp}(tp) 72 73 addi sp, sp, -{trap_frame_size_on_stack} 74 sd x1, {off_ra}(sp) 75 sd x3, {off_gp}(sp) 76 sd x5, {off_t0}(sp) 77 ", 78 save_from_x6_to_x31!(), 79 " 80 /* 81 * Disable user-mode memory access as it should only be set in the 82 * actual user copy routines. 83 * 84 * Disable the FPU/Vector to detect illegal usage of floating point 85 * or vector in kernel space. 86 */ 87 88 li t0, {sr_sum_and_fsvs} 89 90 ld s0, {lc_off_user_sp}(tp) 91 csrrc s1, {csr_status}, t0 92 csrr s2, {csr_epc} 93 csrr s3, {csr_tval} 94 csrr s4, {csr_cause} 95 csrr s5, {csr_scratch} 96 sd s0, {off_sp}(sp) 97 sd s1, {off_status}(sp) 98 sd s2, {off_epc}(sp) 99 sd s3, {off_badaddr}(sp) 100 sd s4, {off_cause}(sp) 101 sd s5, {off_tp}(sp) 102 103 /* 104 * Set the scratch register to 0, so that if a recursive exception 105 * occurs, the exception vector knows it came from the kernel 106 */ 107 108 csrw {csr_scratch}, x0 109 110 /* Load the global pointer */ 111 // linux 加载了global pointer,但是我们暂时没有用到 112 113 // .option push 114 // .option norelax 115 // la gp, __global_pointer$ 116 // .option pop 117 118 mv a0, sp 119 la ra, ret_from_exception 120 121 tail riscv64_do_irq 122 " 123 ), 124 125 lc_off_user_sp = const offset_of!(LocalContext, user_sp), 126 lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp), 127 trap_frame_size_on_stack = const TrapFrame::SIZE_ON_STACK, 128 off_ra = const offset_of!(TrapFrame, ra), 129 off_gp = const offset_of!(TrapFrame, gp), 130 off_t0 = const offset_of!(TrapFrame, t0), 131 off_t1 = const offset_of!(TrapFrame, t1), 132 off_t2 = const offset_of!(TrapFrame, t2), 133 off_s0 = const offset_of!(TrapFrame, s0), 134 off_s1 = const offset_of!(TrapFrame, s1), 135 off_a0 = const offset_of!(TrapFrame, a0), 136 off_a1 = const offset_of!(TrapFrame, a1), 137 off_a2 = const offset_of!(TrapFrame, a2), 138 off_a3 = const offset_of!(TrapFrame, a3), 139 off_a4 = const offset_of!(TrapFrame, a4), 140 off_a5 = const offset_of!(TrapFrame, a5), 141 off_a6 = const offset_of!(TrapFrame, a6), 142 off_a7 = const offset_of!(TrapFrame, a7), 143 off_s2 = const offset_of!(TrapFrame, s2), 144 off_s3 = const offset_of!(TrapFrame, s3), 145 off_s4 = const offset_of!(TrapFrame, s4), 146 off_s5 = const offset_of!(TrapFrame, s5), 147 off_s6 = const offset_of!(TrapFrame, s6), 148 off_s7 = const offset_of!(TrapFrame, s7), 149 off_s8 = const offset_of!(TrapFrame, s8), 150 off_s9 = const offset_of!(TrapFrame, s9), 151 off_s10 = const offset_of!(TrapFrame, s10), 152 off_s11 = const offset_of!(TrapFrame, s11), 153 off_t3 = const offset_of!(TrapFrame, t3), 154 off_t4 = const offset_of!(TrapFrame, t4), 155 off_t5 = const offset_of!(TrapFrame, t5), 156 off_t6 = const offset_of!(TrapFrame, t6), 157 off_sp = const offset_of!(TrapFrame, sp), 158 off_status = const offset_of!(TrapFrame, status), 159 off_badaddr = const offset_of!(TrapFrame, badaddr), 160 off_cause = const offset_of!(TrapFrame, cause), 161 off_tp = const offset_of!(TrapFrame, tp), 162 off_epc = const offset_of!(TrapFrame, epc), 163 sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM), 164 csr_status = const CSR_SSTATUS, 165 csr_epc = const CSR_SEPC, 166 csr_tval = const CSR_STVAL, 167 csr_cause = const CSR_SCAUSE, 168 csr_scratch = const CSR_SSCRATCH, 169 options(noreturn), 170 ) 171 } 172 173 #[naked] 174 #[no_mangle] 175 pub unsafe extern "C" fn ret_from_exception() -> ! { 176 asm!( 177 concat!(" 178 ld s0, {off_status}(sp) 179 andi s0, s0, {sr_spp} 180 181 bnez s0, 3f 182 183 // Save unwound kernel stack pointer in thread_info 184 addi s0, sp, {trap_frame_size_on_stack} 185 sd s0, {lc_off_kernel_sp}(tp) 186 187 /* 188 * Save TP into the scratch register , so we can find the kernel data 189 * structures again. 190 */ 191 csrw {csr_scratch}, tp 192 3: 193 194 ld a0, {off_status}(sp) 195 196 ld a2, {off_epc}(sp) 197 sc.d x0, a2, {off_epc}(sp) 198 199 csrw {csr_status}, a0 200 csrw {csr_epc}, a2 201 202 ld x1, {off_ra}(sp) 203 ld x3, {off_gp}(sp) 204 ld x4, {off_tp}(sp) 205 ld x5, {off_t0}(sp) 206 207 ", 208 restore_from_x6_to_x31!(), 209 " 210 ld x2, {off_sp}(sp) 211 212 sret 213 " 214 ), 215 off_status = const offset_of!(TrapFrame, status), 216 sr_spp = const SR_SPP, 217 trap_frame_size_on_stack = const TrapFrame::SIZE_ON_STACK, 218 lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp), 219 csr_scratch = const CSR_SSCRATCH, 220 csr_status = const CSR_SSTATUS, 221 csr_epc = const CSR_SEPC, 222 off_ra = const offset_of!(TrapFrame, ra), 223 off_gp = const offset_of!(TrapFrame, gp), 224 off_t0 = const offset_of!(TrapFrame, t0), 225 off_t1 = const offset_of!(TrapFrame, t1), 226 off_t2 = const offset_of!(TrapFrame, t2), 227 off_s0 = const offset_of!(TrapFrame, s0), 228 off_s1 = const offset_of!(TrapFrame, s1), 229 off_a0 = const offset_of!(TrapFrame, a0), 230 off_a1 = const offset_of!(TrapFrame, a1), 231 off_a2 = const offset_of!(TrapFrame, a2), 232 off_a3 = const offset_of!(TrapFrame, a3), 233 off_a4 = const offset_of!(TrapFrame, a4), 234 off_a5 = const offset_of!(TrapFrame, a5), 235 off_a6 = const offset_of!(TrapFrame, a6), 236 off_a7 = const offset_of!(TrapFrame, a7), 237 off_s2 = const offset_of!(TrapFrame, s2), 238 off_s3 = const offset_of!(TrapFrame, s3), 239 off_s4 = const offset_of!(TrapFrame, s4), 240 off_s5 = const offset_of!(TrapFrame, s5), 241 off_s6 = const offset_of!(TrapFrame, s6), 242 off_s7 = const offset_of!(TrapFrame, s7), 243 off_s8 = const offset_of!(TrapFrame, s8), 244 off_s9 = const offset_of!(TrapFrame, s9), 245 off_s10 = const offset_of!(TrapFrame, s10), 246 off_s11 = const offset_of!(TrapFrame, s11), 247 off_t3 = const offset_of!(TrapFrame, t3), 248 off_t4 = const offset_of!(TrapFrame, t4), 249 off_t5 = const offset_of!(TrapFrame, t5), 250 off_t6 = const offset_of!(TrapFrame, t6), 251 off_sp = const offset_of!(TrapFrame, sp), 252 off_tp = const offset_of!(TrapFrame, tp), 253 off_epc = const offset_of!(TrapFrame, epc), 254 255 options(noreturn), 256 ) 257 } 258