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