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