xref: /DragonOS/kernel/src/arch/riscv64/interrupt/entry.rs (revision c635d8a9cfe25bc11779f323ef0c7d7a0f597d4a)
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))]
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]
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]
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]
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