15c4224e5SLoGin use crate::arch::{
2*0102d69fSLoGin asm::csr::{CSR_SCAUSE, CSR_SEPC, CSR_SSCRATCH, CSR_SSTATUS, CSR_STVAL, SR_SPP},
35c4224e5SLoGin cpu::LocalContext,
45c4224e5SLoGin interrupt::TrapFrame,
55c4224e5SLoGin };
69621ab16SLoGin use asm_macros::{restore_from_x6_to_x31, save_from_x6_to_x31};
75c4224e5SLoGin use core::arch::asm;
85c4224e5SLoGin use kdepends::memoffset::offset_of;
95c4224e5SLoGin
105c4224e5SLoGin /// Riscv64中断处理入口
115c4224e5SLoGin #[naked]
125c4224e5SLoGin #[no_mangle]
135c4224e5SLoGin #[repr(align(4))]
handle_exception() -> !145c4224e5SLoGin pub unsafe extern "C" fn handle_exception() -> ! {
155c4224e5SLoGin asm!(
165c4224e5SLoGin concat!("
175c4224e5SLoGin /*
185c4224e5SLoGin * If coming from userspace, preserve the user thread pointer and load
195c4224e5SLoGin * the kernel thread pointer. If we came from the kernel, the scratch
205c4224e5SLoGin * register will contain 0, and we should continue on the current TP.
215c4224e5SLoGin */
225c4224e5SLoGin
235c4224e5SLoGin csrrw tp, {csr_scratch}, tp
245c4224e5SLoGin bnez tp, _save_context
255c4224e5SLoGin
265c4224e5SLoGin /* 从内核态进入中断 */
275c4224e5SLoGin j {_restore_kernel_tpsp}
285c4224e5SLoGin "),
295c4224e5SLoGin csr_scratch = const CSR_SSCRATCH,
305c4224e5SLoGin _restore_kernel_tpsp = sym _restore_kernel_tpsp,
315c4224e5SLoGin options(noreturn),
325c4224e5SLoGin )
335c4224e5SLoGin }
345c4224e5SLoGin
355c4224e5SLoGin #[naked]
365c4224e5SLoGin #[no_mangle]
_restore_kernel_tpsp() -> !375c4224e5SLoGin unsafe extern "C" fn _restore_kernel_tpsp() -> ! {
385c4224e5SLoGin asm!(
395c4224e5SLoGin concat!("
405c4224e5SLoGin // 这次是从内核态进入中断
415c4224e5SLoGin // 从sscratch寄存器加载当前cpu的上下文
425c4224e5SLoGin csrr tp, {csr_scratch}
435c4224e5SLoGin
445c4224e5SLoGin // 把当前的sp寄存器的值保存到当前cpu的上下文的kernel_sp字段
455c4224e5SLoGin sd sp, {lc_off_kernel_sp}(tp)
465c4224e5SLoGin
475c4224e5SLoGin j {_save_context}
485c4224e5SLoGin "),
495c4224e5SLoGin csr_scratch = const CSR_SSCRATCH,
505c4224e5SLoGin lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp),
515c4224e5SLoGin _save_context = sym _save_context,
525c4224e5SLoGin
535c4224e5SLoGin options(noreturn),
545c4224e5SLoGin )
555c4224e5SLoGin }
565c4224e5SLoGin
575c4224e5SLoGin #[naked]
585c4224e5SLoGin #[no_mangle]
_save_context() -> !595c4224e5SLoGin unsafe extern "C" fn _save_context() -> ! {
605c4224e5SLoGin asm!(
615c4224e5SLoGin concat!("
625c4224e5SLoGin
635c4224e5SLoGin
645c4224e5SLoGin // 保存当前cpu的上下文
655c4224e5SLoGin
665c4224e5SLoGin // 保存用户sp
675c4224e5SLoGin sd sp, {lc_off_user_sp}(tp)
685c4224e5SLoGin // 加载内核sp
695c4224e5SLoGin ld sp, {lc_off_kernel_sp}(tp)
705c4224e5SLoGin
715c4224e5SLoGin addi sp, sp, -{trap_frame_size_on_stack}
725c4224e5SLoGin sd x1, {off_ra}(sp)
735c4224e5SLoGin sd x3, {off_gp}(sp)
745c4224e5SLoGin sd x5, {off_t0}(sp)
755c4224e5SLoGin ",
765c4224e5SLoGin save_from_x6_to_x31!(),
775c4224e5SLoGin "
785c4224e5SLoGin /*
795c4224e5SLoGin * Disable user-mode memory access as it should only be set in the
805c4224e5SLoGin * actual user copy routines.
815c4224e5SLoGin *
825c4224e5SLoGin * Disable the FPU/Vector to detect illegal usage of floating point
835c4224e5SLoGin * or vector in kernel space.
845c4224e5SLoGin */
855c4224e5SLoGin
865c4224e5SLoGin li t0, {sr_sum_and_fsvs}
875c4224e5SLoGin
885c4224e5SLoGin ld s0, {lc_off_user_sp}(tp)
895c4224e5SLoGin csrrc s1, {csr_status}, t0
905c4224e5SLoGin csrr s2, {csr_epc}
915c4224e5SLoGin csrr s3, {csr_tval}
925c4224e5SLoGin csrr s4, {csr_cause}
935c4224e5SLoGin csrr s5, {csr_scratch}
945c4224e5SLoGin sd s0, {off_sp}(sp)
955c4224e5SLoGin sd s1, {off_status}(sp)
965c4224e5SLoGin sd s2, {off_epc}(sp)
975c4224e5SLoGin sd s3, {off_badaddr}(sp)
985c4224e5SLoGin sd s4, {off_cause}(sp)
995c4224e5SLoGin sd s5, {off_tp}(sp)
1005c4224e5SLoGin
1015c4224e5SLoGin /*
1025c4224e5SLoGin * Set the scratch register to 0, so that if a recursive exception
1035c4224e5SLoGin * occurs, the exception vector knows it came from the kernel
1045c4224e5SLoGin */
1055c4224e5SLoGin
1065c4224e5SLoGin csrw {csr_scratch}, x0
1075c4224e5SLoGin
1085c4224e5SLoGin /* Load the global pointer */
1095c4224e5SLoGin // linux 加载了global pointer,但是我们暂时没有用到
1105c4224e5SLoGin
1115c4224e5SLoGin // .option push
1125c4224e5SLoGin // .option norelax
1135c4224e5SLoGin // la gp, __global_pointer$
1145c4224e5SLoGin // .option pop
1155c4224e5SLoGin
1165c4224e5SLoGin mv a0, sp
1175c4224e5SLoGin la ra, ret_from_exception
1185c4224e5SLoGin
1195c4224e5SLoGin tail riscv64_do_irq
1205c4224e5SLoGin "
1215c4224e5SLoGin ),
1225c4224e5SLoGin
1235c4224e5SLoGin lc_off_user_sp = const offset_of!(LocalContext, user_sp),
1245c4224e5SLoGin lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp),
1255c4224e5SLoGin trap_frame_size_on_stack = const TrapFrame::SIZE_ON_STACK,
1265c4224e5SLoGin off_ra = const offset_of!(TrapFrame, ra),
1275c4224e5SLoGin off_gp = const offset_of!(TrapFrame, gp),
1285c4224e5SLoGin off_t0 = const offset_of!(TrapFrame, t0),
1295c4224e5SLoGin off_t1 = const offset_of!(TrapFrame, t1),
1305c4224e5SLoGin off_t2 = const offset_of!(TrapFrame, t2),
1315c4224e5SLoGin off_s0 = const offset_of!(TrapFrame, s0),
1325c4224e5SLoGin off_s1 = const offset_of!(TrapFrame, s1),
1335c4224e5SLoGin off_a0 = const offset_of!(TrapFrame, a0),
1345c4224e5SLoGin off_a1 = const offset_of!(TrapFrame, a1),
1355c4224e5SLoGin off_a2 = const offset_of!(TrapFrame, a2),
1365c4224e5SLoGin off_a3 = const offset_of!(TrapFrame, a3),
1375c4224e5SLoGin off_a4 = const offset_of!(TrapFrame, a4),
1385c4224e5SLoGin off_a5 = const offset_of!(TrapFrame, a5),
1395c4224e5SLoGin off_a6 = const offset_of!(TrapFrame, a6),
1405c4224e5SLoGin off_a7 = const offset_of!(TrapFrame, a7),
1415c4224e5SLoGin off_s2 = const offset_of!(TrapFrame, s2),
1425c4224e5SLoGin off_s3 = const offset_of!(TrapFrame, s3),
1435c4224e5SLoGin off_s4 = const offset_of!(TrapFrame, s4),
1445c4224e5SLoGin off_s5 = const offset_of!(TrapFrame, s5),
1455c4224e5SLoGin off_s6 = const offset_of!(TrapFrame, s6),
1465c4224e5SLoGin off_s7 = const offset_of!(TrapFrame, s7),
1475c4224e5SLoGin off_s8 = const offset_of!(TrapFrame, s8),
1485c4224e5SLoGin off_s9 = const offset_of!(TrapFrame, s9),
1495c4224e5SLoGin off_s10 = const offset_of!(TrapFrame, s10),
1505c4224e5SLoGin off_s11 = const offset_of!(TrapFrame, s11),
1515c4224e5SLoGin off_t3 = const offset_of!(TrapFrame, t3),
1525c4224e5SLoGin off_t4 = const offset_of!(TrapFrame, t4),
1535c4224e5SLoGin off_t5 = const offset_of!(TrapFrame, t5),
1545c4224e5SLoGin off_t6 = const offset_of!(TrapFrame, t6),
1555c4224e5SLoGin off_sp = const offset_of!(TrapFrame, sp),
1565c4224e5SLoGin off_status = const offset_of!(TrapFrame, status),
1575c4224e5SLoGin off_badaddr = const offset_of!(TrapFrame, badaddr),
1585c4224e5SLoGin off_cause = const offset_of!(TrapFrame, cause),
1595c4224e5SLoGin off_tp = const offset_of!(TrapFrame, tp),
1605c4224e5SLoGin off_epc = const offset_of!(TrapFrame, epc),
161471d65cfSLoGin sr_sum_and_fsvs = const (0), // 暂时在内核中不禁用FPU和Vector,以及不禁用用户内存访问
162471d65cfSLoGin // sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM),
1635c4224e5SLoGin csr_status = const CSR_SSTATUS,
1645c4224e5SLoGin csr_epc = const CSR_SEPC,
1655c4224e5SLoGin csr_tval = const CSR_STVAL,
1665c4224e5SLoGin csr_cause = const CSR_SCAUSE,
1675c4224e5SLoGin csr_scratch = const CSR_SSCRATCH,
1685c4224e5SLoGin options(noreturn),
1695c4224e5SLoGin )
1705c4224e5SLoGin }
1715c4224e5SLoGin
1725c4224e5SLoGin #[naked]
1735c4224e5SLoGin #[no_mangle]
ret_from_exception() -> !174e8eab1acSLoGin pub unsafe extern "C" fn ret_from_exception() -> ! {
1755c4224e5SLoGin asm!(
1765c4224e5SLoGin concat!("
1775c4224e5SLoGin ld s0, {off_status}(sp)
1785c4224e5SLoGin andi s0, s0, {sr_spp}
1795c4224e5SLoGin
1805c4224e5SLoGin bnez s0, 3f
1815c4224e5SLoGin
1825c4224e5SLoGin // Save unwound kernel stack pointer in thread_info
1835c4224e5SLoGin addi s0, sp, {trap_frame_size_on_stack}
1845c4224e5SLoGin sd s0, {lc_off_kernel_sp}(tp)
1855c4224e5SLoGin
1865c4224e5SLoGin /*
1875c4224e5SLoGin * Save TP into the scratch register , so we can find the kernel data
1885c4224e5SLoGin * structures again.
1895c4224e5SLoGin */
1905c4224e5SLoGin csrw {csr_scratch}, tp
1915c4224e5SLoGin 3:
1925c4224e5SLoGin
1935c4224e5SLoGin ld a0, {off_status}(sp)
1945c4224e5SLoGin
1955c4224e5SLoGin ld a2, {off_epc}(sp)
1965c4224e5SLoGin sc.d x0, a2, {off_epc}(sp)
1975c4224e5SLoGin
1985c4224e5SLoGin csrw {csr_status}, a0
1995c4224e5SLoGin csrw {csr_epc}, a2
2005c4224e5SLoGin
2015c4224e5SLoGin ld x1, {off_ra}(sp)
2025c4224e5SLoGin ld x3, {off_gp}(sp)
2035c4224e5SLoGin ld x4, {off_tp}(sp)
2045c4224e5SLoGin ld x5, {off_t0}(sp)
2055c4224e5SLoGin
2065c4224e5SLoGin ",
2075c4224e5SLoGin restore_from_x6_to_x31!(),
2085c4224e5SLoGin "
2095c4224e5SLoGin ld x2, {off_sp}(sp)
2105c4224e5SLoGin
2115c4224e5SLoGin sret
2125c4224e5SLoGin "
2135c4224e5SLoGin ),
2145c4224e5SLoGin off_status = const offset_of!(TrapFrame, status),
2155c4224e5SLoGin sr_spp = const SR_SPP,
2165c4224e5SLoGin trap_frame_size_on_stack = const TrapFrame::SIZE_ON_STACK,
2175c4224e5SLoGin lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp),
2185c4224e5SLoGin csr_scratch = const CSR_SSCRATCH,
2195c4224e5SLoGin csr_status = const CSR_SSTATUS,
2205c4224e5SLoGin csr_epc = const CSR_SEPC,
2215c4224e5SLoGin off_ra = const offset_of!(TrapFrame, ra),
2225c4224e5SLoGin off_gp = const offset_of!(TrapFrame, gp),
2235c4224e5SLoGin off_t0 = const offset_of!(TrapFrame, t0),
2245c4224e5SLoGin off_t1 = const offset_of!(TrapFrame, t1),
2255c4224e5SLoGin off_t2 = const offset_of!(TrapFrame, t2),
2265c4224e5SLoGin off_s0 = const offset_of!(TrapFrame, s0),
2275c4224e5SLoGin off_s1 = const offset_of!(TrapFrame, s1),
2285c4224e5SLoGin off_a0 = const offset_of!(TrapFrame, a0),
2295c4224e5SLoGin off_a1 = const offset_of!(TrapFrame, a1),
2305c4224e5SLoGin off_a2 = const offset_of!(TrapFrame, a2),
2315c4224e5SLoGin off_a3 = const offset_of!(TrapFrame, a3),
2325c4224e5SLoGin off_a4 = const offset_of!(TrapFrame, a4),
2335c4224e5SLoGin off_a5 = const offset_of!(TrapFrame, a5),
2345c4224e5SLoGin off_a6 = const offset_of!(TrapFrame, a6),
2355c4224e5SLoGin off_a7 = const offset_of!(TrapFrame, a7),
2365c4224e5SLoGin off_s2 = const offset_of!(TrapFrame, s2),
2375c4224e5SLoGin off_s3 = const offset_of!(TrapFrame, s3),
2385c4224e5SLoGin off_s4 = const offset_of!(TrapFrame, s4),
2395c4224e5SLoGin off_s5 = const offset_of!(TrapFrame, s5),
2405c4224e5SLoGin off_s6 = const offset_of!(TrapFrame, s6),
2415c4224e5SLoGin off_s7 = const offset_of!(TrapFrame, s7),
2425c4224e5SLoGin off_s8 = const offset_of!(TrapFrame, s8),
2435c4224e5SLoGin off_s9 = const offset_of!(TrapFrame, s9),
2445c4224e5SLoGin off_s10 = const offset_of!(TrapFrame, s10),
2455c4224e5SLoGin off_s11 = const offset_of!(TrapFrame, s11),
2465c4224e5SLoGin off_t3 = const offset_of!(TrapFrame, t3),
2475c4224e5SLoGin off_t4 = const offset_of!(TrapFrame, t4),
2485c4224e5SLoGin off_t5 = const offset_of!(TrapFrame, t5),
2495c4224e5SLoGin off_t6 = const offset_of!(TrapFrame, t6),
2505c4224e5SLoGin off_sp = const offset_of!(TrapFrame, sp),
2515c4224e5SLoGin off_tp = const offset_of!(TrapFrame, tp),
2525c4224e5SLoGin off_epc = const offset_of!(TrapFrame, epc),
2535c4224e5SLoGin
2545c4224e5SLoGin options(noreturn),
2555c4224e5SLoGin )
2565c4224e5SLoGin }
257