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