Browse Source

在riscv上实现异常处理,能够进入异常处理程序 (#564)

LoGin 1 year ago
parent
commit
5c4224e5a8

+ 1 - 2
kernel/Cargo.toml

@@ -42,7 +42,6 @@ linkme = "=0.2"
 num = { version = "=0.4.0", default-features = false }
 num-derive = "=0.3"
 num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false }
-
 smoltcp = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/smoltcp.git", rev = "9027825", default-features = false, features = ["log", "alloc",  "socket-raw", "socket-udp", "socket-tcp", "socket-icmp", "socket-dhcpv4", "socket-dns", "proto-ipv4", "proto-ipv6"]}
 system_error = { path = "crates/system_error" }
 unified-init = { path = "crates/unified-init" }
@@ -62,7 +61,7 @@ x86_64 = "=0.14.10"
 
 # target为riscv64时,使用下面的依赖
 [target.'cfg(target_arch = "riscv64")'.dependencies]
-riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "5c01a8320e", features = [ "s-mode" ] }
+riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", revision = "79d27d0f3a", features = [ "s-mode" ] }
 sbi-rt = { version = "=0.0.3", features = ["legacy"] }
 
 

+ 20 - 0
kernel/src/arch/riscv64/asm/csr.rs

@@ -0,0 +1,20 @@
+pub const CSR_SSTATUS: usize = 0x100;
+pub const CSR_SSCRATCH: usize = 0x140;
+pub const CSR_SEPC: usize = 0x141;
+pub const CSR_SCAUSE: usize = 0x142;
+pub const CSR_STVAL: usize = 0x143;
+
+// === Status register flags ===
+
+/// Previously Supervisor
+pub const SR_SPP: usize = 0x00000100;
+/// Supervisor User Memory Access
+pub const SR_SUM: usize = 0x00040000;
+
+/// Floating-Point Status
+pub const SR_FS: usize = 0x00006000;
+/// Vector status
+pub const SR_VS: usize = 0x00000600;
+
+/// Vector and Floating-Point Unit
+pub const SR_FS_VS: usize = SR_FS | SR_VS;

+ 8 - 27
kernel/src/arch/riscv64/asm/head.S

@@ -1,31 +1,8 @@
 #include "common/asm.h"
+#include "asm/csr.h"
 
 .section .bootstrap
 
-#define CSR_SSTATUS		0x100
-#define CSR_SIE			0x104
-#define CSR_STVEC		0x105
-#define CSR_SIP			0x144
-
-# define CSR_TVEC	CSR_STVEC
-
-# define CSR_STATUS	CSR_SSTATUS
-#define CSR_IE CSR_SIE
-#define CSR_IP CSR_SIP
-
-#define SR_FS 0x00006000
-#define SR_VS 0x00000600
-#define SR_FS_VS	(SR_FS | SR_VS) /* Vector and Floating-Point Unit */
-
-#define SATP_MODE_39 0x8000000000000000ULL
-#define SATP_MODE_48 0x9000000000000000ULL
-#define SATP_MODE_57 0xa000000000000000ULL
-
-#define PAGE_OFFSET 0xffffffc000000000
-#define KERNEL_LINK_OFFSET 0x1000000
-#define KERNEL_VIRT_START (PAGE_OFFSET + KERNEL_LINK_OFFSET)
-
-
 // 内核入口(从DragonStub跳转到这里)
 // 参数:
 //   a0: hartid (核心ID)
@@ -86,9 +63,11 @@ ENTRY(_start)
 __init_set_pgtable_loop_end:
 	call __initial_reloacate_enable_mmu
 
+
+
 .option push
 .option norelax
-	
+	// 设置栈指针
 	la a0, BSP_IDLE_STACK_SPACE
 	mv sp, a0
 	li t0, 32752	// 预留16字节防止越界
@@ -100,6 +79,7 @@ __init_set_pgtable_loop_end:
 	 */
 	li t0, SR_FS_VS
 	csrc CSR_STATUS, t0
+
 	
 	/* Call the kernel */
 	la a0, __initial_hartid_ptr
@@ -128,7 +108,7 @@ __initial_reloacate_enable_mmu:
 
 	/* Point stvec to virtual address of intruction after satp write */
 	/* Set trap vector to spin forever to help debug */
-	la a2, 1f
+	la a2, 3f
 	add a2, a2, t1
 	csrw CSR_TVEC, a2
 	// enable MMU
@@ -142,7 +122,7 @@ __initial_reloacate_enable_mmu:
 	sfence.vma
 	csrw satp, a2
 	
-1:
+3:
 	la a0, __initial_Lsecondary_park
 	add a0, a0, t1
 	csrw CSR_TVEC, a0
@@ -337,6 +317,7 @@ __initial_clear_pgtable_loop:
 
 	ret
 
+
 .align 2
 __initial_Lsecondary_park:
 	/* We lack SMP support or have too many harts, so park this hart */

+ 1 - 0
kernel/src/arch/riscv64/asm/mod.rs

@@ -1 +1,2 @@
 pub mod bitops;
+pub(super) mod csr;

+ 40 - 6
kernel/src/arch/riscv64/cpu.rs

@@ -7,10 +7,13 @@ use crate::{
     smp::cpu::{ProcessorId, SmpCpuManager},
 };
 
+/// 栈对齐
+pub(super) const STACK_ALIGN: usize = 16;
+
 /// 获取当前cpu的id
 #[inline]
 pub fn current_cpu_id() -> ProcessorId {
-    let ptr: *const LocalContext = riscv::register::sscratch::read() as *const LocalContext;
+    let ptr: *const LocalContext = riscv::register::tp::read() as *const LocalContext;
 
     if core::intrinsics::unlikely(ptr.is_null()) {
         return boot_params().read_irqsave().arch.boot_hartid;
@@ -34,16 +37,29 @@ pub(super) fn local_context() -> &'static PerCpuVar<LocalContext> {
 
 /// Per cpu的上下文数据
 ///
-/// 每个CPU的sscratch寄存器指向这个结构体
+/// 每个CPU的tp寄存器指向这个结构体
+///
+/// 注意:
+///
+/// - 从用户态进入内核态时,会从sscratch寄存器加载这个结构体的地址到tp寄存器,并把sscratch寄存器清零
+/// - 从内核态进入用户态时,会将tp寄存器的值保存到sscratch寄存器
 #[derive(Debug)]
 pub(super) struct LocalContext {
     /// 当前cpu的id
-    current_cpu: ProcessorId,
+    pub current_cpu: ProcessorId,
+    // 当前进程的内核栈指针(暂存,当进入中断处理程序的时候需要保存到pcb,进程切换的时候需要重新设置这个值)
+    pub kernel_sp: usize,
+    // 当前进程的用户栈指针(暂存,当进入中断处理程序的时候需要保存到pcb,进程切换的时候需要重新设置这个值)
+    pub user_sp: usize,
 }
 
 impl LocalContext {
     fn new(cpu: ProcessorId) -> Self {
-        Self { current_cpu: cpu }
+        Self {
+            current_cpu: cpu,
+            kernel_sp: 0,
+            user_sp: 0,
+        }
     }
     pub fn current_cpu(&self) -> ProcessorId {
         self.current_cpu
@@ -53,16 +69,34 @@ impl LocalContext {
         self.current_cpu = cpu;
     }
 
+    pub fn kernel_sp(&self) -> usize {
+        self.kernel_sp
+    }
+
+    pub fn set_kernel_sp(&mut self, sp: usize) {
+        self.kernel_sp = sp;
+    }
+
+    pub fn user_sp(&self) -> usize {
+        self.user_sp
+    }
+
+    pub fn set_user_sp(&mut self, sp: usize) {
+        self.user_sp = sp;
+    }
+
     fn sync_to_cpu(&self) {
         let ptr = self as *const Self as usize;
-        riscv::register::sscratch::write(ptr);
+        riscv::register::sscratch::write(0);
+
+        // 写入tp寄存器
+        riscv::register::tp::write(ptr);
     }
 }
 
 /// 初始化本地上下文
 #[inline(never)]
 pub(super) fn init_local_context() {
-    kdebug!("init_local_context");
     let mut data = Vec::new();
 
     for i in 0..PerCpu::MAX_CPU_NUM {

+ 22 - 27
kernel/src/arch/riscv64/include/asm/asm.h

@@ -1,8 +1,8 @@
 #pragma once
 
-#include <DragonOS/stdint.h>
-#include <stdbool.h>
+#include "DragonOS/stdint.h"
 #include <common/stddef.h>
+#include <stdbool.h>
 
 // RISC-V 没有直接的开启/关闭中断的指令,你需要通过修改CSR寄存器来实现
 // 你可能需要在你的中断处理程序中处理这些操作
@@ -15,44 +15,38 @@
 // RISC-V 没有 pause 指令,你可能需要使用其他方法来实现处理器等待
 
 // RISC-V 使用 fence 指令来实现内存屏障
-#define io_mfence() __asm__ __volatile__("fence rw,rw\n\t" :: \
-                                             : "memory")
-#define io_sfence() __asm__ __volatile__("fence w,w\n\t" :: \
-                                             : "memory")
-#define io_lfence() __asm__ __volatile__("fence r,r\n\t" :: \
-                                             : "memory")
+#define io_mfence() __asm__ __volatile__("fence rw,rw\n\t" ::: "memory")
+#define io_sfence() __asm__ __volatile__("fence w,w\n\t" ::: "memory")
+#define io_lfence() __asm__ __volatile__("fence r,r\n\t" ::: "memory")
 
 // 开启中断
-#define sti() __asm__ __volatile__("csrsi mstatus, 8\n\t" :: \
-                                       : "memory")
+#define sti() __asm__ __volatile__("csrsi mstatus, 8\n\t" ::: "memory")
 
 // 关闭中断
-#define cli() __asm__ __volatile__("csrci mstatus, 8\n\t" :: \
-                                       : "memory")
-
+#define cli() __asm__ __volatile__("csrci mstatus, 8\n\t" ::: "memory")
 
 // 从io口读入8个bit
-unsigned char io_in8(unsigned short port)
-{
-    while(1);
+unsigned char io_in8(unsigned short port) {
+  while (1)
+    ;
 }
 
 // 从io口读入32个bit
-unsigned int io_in32(unsigned short port)
-{
-    while(1);
+unsigned int io_in32(unsigned short port) {
+  while (1)
+    ;
 }
 
 // 输出8个bit到输出端口
-void io_out8(unsigned short port, unsigned char value)
-{
-    while(1);
+void io_out8(unsigned short port, unsigned char value) {
+  while (1)
+    ;
 }
 
 // 输出32个bit到输出端口
-void io_out32(unsigned short port, unsigned int value)
-{
-    while(1);
+void io_out32(unsigned short port, unsigned int value) {
+  while (1)
+    ;
 }
 
 /**
@@ -63,6 +57,7 @@ void io_out32(unsigned short port, unsigned int value)
  * @return true
  * @return false
  */
-bool verify_area(uint64_t addr_start, uint64_t length){
-    while(1);
+bool verify_area(uint64_t addr_start, uint64_t length) {
+  while (1)
+    ;
 }

+ 26 - 0
kernel/src/arch/riscv64/include/asm/csr.h

@@ -0,0 +1,26 @@
+#pragma once
+
+#define CSR_SSTATUS 0x100
+#define CSR_SIE 0x104
+#define CSR_STVEC 0x105
+#define CSR_SIP 0x144
+#define CSR_SSCRATCH 0x140
+
+#define CSR_TVEC CSR_STVEC
+#define CSR_SCRATCH CSR_SSCRATCH
+
+#define CSR_STATUS CSR_SSTATUS
+#define CSR_IE CSR_SIE
+#define CSR_IP CSR_SIP
+
+#define SR_FS 0x00006000
+#define SR_VS 0x00000600
+#define SR_FS_VS (SR_FS | SR_VS) /* Vector and Floating-Point Unit */
+
+#define SATP_MODE_39 0x8000000000000000ULL
+#define SATP_MODE_48 0x9000000000000000ULL
+#define SATP_MODE_57 0xa000000000000000ULL
+
+#define PAGE_OFFSET 0xffffffc000000000
+#define KERNEL_LINK_OFFSET 0x1000000
+#define KERNEL_VIRT_START (PAGE_OFFSET + KERNEL_LINK_OFFSET)

+ 15 - 6
kernel/src/arch/riscv64/init/mod.rs

@@ -3,10 +3,7 @@ use system_error::SystemError;
 
 use crate::{
     arch::{driver::sbi::SbiDriver, mm::init::mm_early_init},
-    driver::{
-        firmware::efi::init::efi_init, irqchip::riscv_intc::riscv_intc_init,
-        open_firmware::fdt::open_firmware_fdt_driver,
-    },
+    driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
     init::{boot_params, init::start_kernel},
     kdebug, kinfo,
     mm::{memblock::mem_block_manager, PhysAddr, VirtAddr},
@@ -14,7 +11,7 @@ use crate::{
     smp::cpu::ProcessorId,
 };
 
-use super::{cpu::init_local_context, driver::sbi::console_putstr};
+use super::{cpu::init_local_context, interrupt::entry::handle_exception};
 
 #[derive(Debug)]
 pub struct ArchBootParams {
@@ -52,10 +49,22 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
         BOOT_HARTID = hartid as u32;
         BOOT_FDT_PADDR = fdt_paddr;
     }
-
+    setup_trap_vector();
     start_kernel();
 }
 
+/// 设置中断、异常处理函数
+fn setup_trap_vector() {
+    let ptr = handle_exception as *const () as usize;
+
+    unsafe {
+        riscv::register::stvec::write(ptr, riscv::register::stvec::TrapMode::Direct);
+        // Set sup0 scratch register to 0, indicating to exception vector that
+        // we are presently executing in kernel.
+        riscv::register::sscratch::write(0);
+    }
+}
+
 #[inline(never)]
 fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
     (0..n_spaces).for_each(|_| print!(" "));

+ 327 - 0
kernel/src/arch/riscv64/interrupt/entry.rs

@@ -0,0 +1,327 @@
+use crate::arch::{
+    asm::csr::{
+        CSR_SCAUSE, CSR_SEPC, CSR_SSCRATCH, CSR_SSTATUS, CSR_STVAL, SR_FS_VS, SR_SPP, SR_SUM,
+    },
+    cpu::LocalContext,
+    interrupt::TrapFrame,
+};
+use core::arch::asm;
+use kdepends::memoffset::offset_of;
+
+/// 保存x6-x31寄存器
+macro_rules! save_from_x6_to_x31 {
+    () => {
+        concat!(
+            "
+            sd x6, {off_t1}(sp)
+            sd x7, {off_t2}(sp)
+            sd x8, {off_s0}(sp)
+            sd x9, {off_s1}(sp)
+            sd x10, {off_a0}(sp)
+            sd x11, {off_a1}(sp)
+            sd x12, {off_a2}(sp)
+            sd x13, {off_a3}(sp)
+            sd x14, {off_a4}(sp)
+            sd x15, {off_a5}(sp)
+            sd x16, {off_a6}(sp)
+            sd x17, {off_a7}(sp)
+            sd x18, {off_s2}(sp)
+            sd x19, {off_s3}(sp)
+            sd x20, {off_s4}(sp)
+            sd x21, {off_s5}(sp)
+            sd x22, {off_s6}(sp)
+            sd x23, {off_s7}(sp)
+            sd x24, {off_s8}(sp)
+            sd x25, {off_s9}(sp)
+            sd x26, {off_s10}(sp)
+            sd x27, {off_s11}(sp)
+            sd x28, {off_t3}(sp)
+            sd x29, {off_t4}(sp)
+            sd x30, {off_t5}(sp)
+            sd x31, {off_t6}(sp)
+
+        "
+        )
+    };
+}
+
+macro_rules! restore_from_x6_to_x31 {
+    () => {
+        concat!("
+        
+            ld x6, {off_t1}(sp)
+            ld x7, {off_t2}(sp)
+            ld x8, {off_s0}(sp)
+            ld x9, {off_s1}(sp)
+            ld x10, {off_a0}(sp)
+            ld x11, {off_a1}(sp)
+            ld x12, {off_a2}(sp)
+            ld x13, {off_a3}(sp)
+            ld x14, {off_a4}(sp)
+            ld x15, {off_a5}(sp)
+            ld x16, {off_a6}(sp)
+            ld x17, {off_a7}(sp)
+            ld x18, {off_s2}(sp)
+            ld x19, {off_s3}(sp)
+            ld x20, {off_s4}(sp)
+            ld x21, {off_s5}(sp)
+            ld x22, {off_s6}(sp)
+            ld x23, {off_s7}(sp)
+            ld x24, {off_s8}(sp)
+            ld x25, {off_s9}(sp)
+            ld x26, {off_s10}(sp)
+            ld x27, {off_s11}(sp)
+            ld x28, {off_t3}(sp)
+            ld x29, {off_t4}(sp)
+            ld x30, {off_t5}(sp)
+            ld x31, {off_t6}(sp)
+        ")
+    };
+}
+
+/// Riscv64中断处理入口
+#[naked]
+#[no_mangle]
+#[repr(align(4))]
+pub unsafe extern "C" fn handle_exception() -> ! {
+    asm!(
+        concat!("
+        /*
+	        * If coming from userspace, preserve the user thread pointer and load
+	        * the kernel thread pointer.  If we came from the kernel, the scratch
+	        * register will contain 0, and we should continue on the current TP.
+        */
+            
+            csrrw tp, {csr_scratch}, tp
+            bnez tp, _save_context
+
+            /* 从内核态进入中断 */
+            j {_restore_kernel_tpsp}
+        "),
+        csr_scratch = const CSR_SSCRATCH,
+        _restore_kernel_tpsp = sym _restore_kernel_tpsp,
+        options(noreturn),
+    )
+}
+
+#[naked]
+#[no_mangle]
+unsafe extern "C" fn _restore_kernel_tpsp() -> ! {
+    asm!(
+        concat!("
+            // 这次是从内核态进入中断
+            // 从sscratch寄存器加载当前cpu的上下文
+            csrr tp, {csr_scratch}
+
+            // 把当前的sp寄存器的值保存到当前cpu的上下文的kernel_sp字段
+            sd sp, {lc_off_kernel_sp}(tp)
+
+            j {_save_context}
+        "),
+        csr_scratch = const CSR_SSCRATCH,
+        lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp),
+        _save_context = sym _save_context,
+
+        options(noreturn),
+    )
+}
+
+#[naked]
+#[no_mangle]
+unsafe extern "C" fn _save_context() -> ! {
+    asm!(
+        concat!("
+
+
+            // 保存当前cpu的上下文
+
+            // 保存用户sp
+            sd sp, {lc_off_user_sp}(tp)
+            // 加载内核sp
+            ld sp, {lc_off_kernel_sp}(tp)
+
+            addi sp, sp, -{trap_frame_size_on_stack}
+            sd x1, {off_ra}(sp)
+            sd x3, {off_gp}(sp)
+            sd x5, {off_t0}(sp)
+        ",
+        save_from_x6_to_x31!(),
+        "
+        /*
+	        * Disable user-mode memory access as it should only be set in the
+	        * actual user copy routines.
+	        *
+	        * Disable the FPU/Vector to detect illegal usage of floating point
+	        * or vector in kernel space.
+        */
+
+        li t0, {sr_sum_and_fsvs}
+        
+        ld s0, {lc_off_user_sp}(tp)
+        csrrc s1, {csr_status}, t0
+        csrr s2, {csr_epc}
+        csrr s3, {csr_tval}
+        csrr s4, {csr_cause}
+        csrr s5, {csr_scratch}
+        sd s0, {off_sp}(sp)
+        sd s1, {off_status}(sp)
+        sd s2, {off_epc}(sp)
+        sd s3, {off_badaddr}(sp)
+        sd s4, {off_cause}(sp)
+        sd s5, {off_tp}(sp)
+
+        /*
+	    * Set the scratch register to 0, so that if a recursive exception
+	    * occurs, the exception vector knows it came from the kernel
+	    */
+
+        csrw {csr_scratch}, x0
+
+        /* Load the global pointer */
+        // linux 加载了global pointer,但是我们暂时没有用到
+
+        // .option push
+        // .option norelax
+        //     la gp, __global_pointer$
+        // .option pop
+
+        mv a0, sp
+        la ra, ret_from_exception
+
+        tail riscv64_do_irq
+        "
+    ),
+
+        lc_off_user_sp = const offset_of!(LocalContext, user_sp),
+        lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp),
+        trap_frame_size_on_stack = const TrapFrame::SIZE_ON_STACK,
+        off_ra = const offset_of!(TrapFrame, ra),
+        off_gp = const offset_of!(TrapFrame, gp),
+        off_t0 = const offset_of!(TrapFrame, t0),
+        off_t1 = const offset_of!(TrapFrame, t1),
+        off_t2 = const offset_of!(TrapFrame, t2),
+        off_s0 = const offset_of!(TrapFrame, s0),
+        off_s1 = const offset_of!(TrapFrame, s1),
+        off_a0 = const offset_of!(TrapFrame, a0),
+        off_a1 = const offset_of!(TrapFrame, a1),
+        off_a2 = const offset_of!(TrapFrame, a2),
+        off_a3 = const offset_of!(TrapFrame, a3),
+        off_a4 = const offset_of!(TrapFrame, a4),
+        off_a5 = const offset_of!(TrapFrame, a5),
+        off_a6 = const offset_of!(TrapFrame, a6),
+        off_a7 = const offset_of!(TrapFrame, a7),
+        off_s2 = const offset_of!(TrapFrame, s2),
+        off_s3 = const offset_of!(TrapFrame, s3),
+        off_s4 = const offset_of!(TrapFrame, s4),
+        off_s5 = const offset_of!(TrapFrame, s5),
+        off_s6 = const offset_of!(TrapFrame, s6),
+        off_s7 = const offset_of!(TrapFrame, s7),
+        off_s8 = const offset_of!(TrapFrame, s8),
+        off_s9 = const offset_of!(TrapFrame, s9),
+        off_s10 = const offset_of!(TrapFrame, s10),
+        off_s11 = const offset_of!(TrapFrame, s11),
+        off_t3 = const offset_of!(TrapFrame, t3),
+        off_t4 = const offset_of!(TrapFrame, t4),
+        off_t5 = const offset_of!(TrapFrame, t5),
+        off_t6 = const offset_of!(TrapFrame, t6),
+        off_sp = const offset_of!(TrapFrame, sp),
+        off_status = const offset_of!(TrapFrame, status),
+        off_badaddr = const offset_of!(TrapFrame, badaddr),
+        off_cause = const offset_of!(TrapFrame, cause),
+        off_tp = const offset_of!(TrapFrame, tp),
+        off_epc = const offset_of!(TrapFrame, epc),
+        sr_sum_and_fsvs = const (SR_FS_VS | SR_SUM),
+        csr_status = const CSR_SSTATUS,
+        csr_epc = const CSR_SEPC,
+        csr_tval = const CSR_STVAL,
+        csr_cause = const CSR_SCAUSE,
+        csr_scratch = const CSR_SSCRATCH,
+        options(noreturn),
+    )
+}
+
+#[naked]
+#[no_mangle]
+unsafe extern "C" fn ret_from_exception() -> ! {
+    asm!(
+        concat!("
+            ld s0, {off_status}(sp)
+            andi s0, s0, {sr_spp}
+            
+            bnez s0, 3f
+
+            // Save unwound kernel stack pointer in thread_info
+            addi s0, sp, {trap_frame_size_on_stack}
+            sd s0, {lc_off_kernel_sp}(tp)
+
+            /*
+	        * Save TP into the scratch register , so we can find the kernel data
+	        * structures again.
+	        */
+            csrw {csr_scratch}, tp
+        3:
+
+            ld a0, {off_status}(sp)
+
+            ld a2, {off_epc}(sp)
+            sc.d x0, a2, {off_epc}(sp)
+
+            csrw {csr_status}, a0
+            csrw {csr_epc}, a2
+
+            ld x1, {off_ra}(sp)
+            ld x3, {off_gp}(sp)
+            ld x4, {off_tp}(sp)
+            ld x5, {off_t0}(sp)
+
+        ",
+        restore_from_x6_to_x31!(),
+        "
+            ld x2, {off_sp}(sp)
+
+            sret
+        "
+        ),
+        off_status = const offset_of!(TrapFrame, status),
+        sr_spp = const SR_SPP,
+        trap_frame_size_on_stack = const TrapFrame::SIZE_ON_STACK,
+        lc_off_kernel_sp = const offset_of!(LocalContext, kernel_sp),
+        csr_scratch = const CSR_SSCRATCH,
+        csr_status = const CSR_SSTATUS,
+        csr_epc = const CSR_SEPC,
+        off_ra = const offset_of!(TrapFrame, ra),
+        off_gp = const offset_of!(TrapFrame, gp),
+        off_t0 = const offset_of!(TrapFrame, t0),
+        off_t1 = const offset_of!(TrapFrame, t1),
+        off_t2 = const offset_of!(TrapFrame, t2),
+        off_s0 = const offset_of!(TrapFrame, s0),
+        off_s1 = const offset_of!(TrapFrame, s1),
+        off_a0 = const offset_of!(TrapFrame, a0),
+        off_a1 = const offset_of!(TrapFrame, a1),
+        off_a2 = const offset_of!(TrapFrame, a2),
+        off_a3 = const offset_of!(TrapFrame, a3),
+        off_a4 = const offset_of!(TrapFrame, a4),
+        off_a5 = const offset_of!(TrapFrame, a5),
+        off_a6 = const offset_of!(TrapFrame, a6),
+        off_a7 = const offset_of!(TrapFrame, a7),
+        off_s2 = const offset_of!(TrapFrame, s2),
+        off_s3 = const offset_of!(TrapFrame, s3),
+        off_s4 = const offset_of!(TrapFrame, s4),
+        off_s5 = const offset_of!(TrapFrame, s5),
+        off_s6 = const offset_of!(TrapFrame, s6),
+        off_s7 = const offset_of!(TrapFrame, s7),
+        off_s8 = const offset_of!(TrapFrame, s8),
+        off_s9 = const offset_of!(TrapFrame, s9),
+        off_s10 = const offset_of!(TrapFrame, s10),
+        off_s11 = const offset_of!(TrapFrame, s11),
+        off_t3 = const offset_of!(TrapFrame, t3),
+        off_t4 = const offset_of!(TrapFrame, t4),
+        off_t5 = const offset_of!(TrapFrame, t5),
+        off_t6 = const offset_of!(TrapFrame, t6),
+        off_sp = const offset_of!(TrapFrame, sp),
+        off_tp = const offset_of!(TrapFrame, tp),
+        off_epc = const offset_of!(TrapFrame, epc),
+
+        options(noreturn),
+    )
+}

+ 172 - 0
kernel/src/arch/riscv64/interrupt/handle.rs

@@ -0,0 +1,172 @@
+use core::hint::spin_loop;
+
+use system_error::SystemError;
+
+use crate::{kdebug, kerror};
+
+use super::TrapFrame;
+
+type ExceptionHandler = fn(&mut TrapFrame) -> Result<(), SystemError>;
+
+static EXCEPTION_HANDLERS: [ExceptionHandler; 16] = [
+    do_trap_insn_misaligned,    // 0
+    do_trap_insn_access_fault,  // 1
+    do_trap_insn_illegal,       // 2
+    do_trap_break,              // 3
+    do_trap_load_misaligned,    // 4
+    do_trap_load_access_fault,  // 5
+    do_trap_store_misaligned,   // 6
+    do_trap_store_access_fault, // 7
+    do_trap_user_env_call,      // 8
+    default_handler,            // 9
+    default_handler,            // 10
+    default_handler,            // 11
+    do_trap_insn_page_fault,    // 12
+    do_trap_load_page_fault,    // 13
+    default_handler,            // 14
+    do_trap_store_page_fault,   // 15
+];
+
+#[no_mangle]
+unsafe extern "C" fn riscv64_do_irq(trap_frame: &mut TrapFrame) {
+    if trap_frame.cause.is_interrupt() {
+        riscv64_do_interrupt(trap_frame);
+    } else if trap_frame.cause.is_exception() {
+        riscv64_do_exception(trap_frame);
+    }
+}
+
+/// 处理中断
+fn riscv64_do_interrupt(_trap_frame: &mut TrapFrame) {
+    kdebug!("todo: riscv64_do_irq: interrupt");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理异常
+fn riscv64_do_exception(trap_frame: &mut TrapFrame) {
+    kdebug!(
+        "riscv64_do_exception: from_user: {}",
+        trap_frame.from_user()
+    );
+    let code = trap_frame.cause.code();
+
+    if code < EXCEPTION_HANDLERS.len() {
+        let handler = EXCEPTION_HANDLERS[code];
+        handler(trap_frame).ok();
+    } else {
+        kerror!("riscv64_do_irq: exception code out of range");
+        loop {
+            // kernel die
+            spin_loop();
+        }
+    };
+}
+
+fn default_handler(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: handler not found");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理指令地址不对齐异常 #0
+fn do_trap_insn_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_insn_misaligned");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理指令访问异常 #1
+fn do_trap_insn_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_insn_access_fault");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理非法指令异常 #2
+fn do_trap_insn_illegal(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_insn_illegal");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理断点异常 #3
+fn do_trap_break(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_break");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理加载地址不对齐异常 #4
+fn do_trap_load_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_load_misaligned");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理加载访问异常 #5
+fn do_trap_load_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_load_access_fault");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理存储地址不对齐异常 #6
+fn do_trap_store_misaligned(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_store_misaligned");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理存储访问异常 #7
+fn do_trap_store_access_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_store_access_fault");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理环境调用异常 #8
+fn do_trap_user_env_call(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_user_env_call");
+    loop {
+        spin_loop();
+    }
+}
+
+// 9-11 reserved
+
+/// 处理指令页错误异常 #12
+fn do_trap_insn_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_insn_page_fault");
+    loop {
+        spin_loop();
+    }
+}
+
+/// 处理页加载错误异常 #13
+fn do_trap_load_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_load_page_fault");
+    loop {
+        spin_loop();
+    }
+}
+
+// 14 reserved
+
+/// 处理页存储错误异常 #15
+fn do_trap_store_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
+    kerror!("riscv64_do_irq: do_trap_store_page_fault");
+    loop {
+        spin_loop();
+    }
+}

+ 50 - 2
kernel/src/arch/riscv64/interrupt/mod.rs

@@ -1,10 +1,16 @@
+use riscv::register::{scause::Scause, sstatus::Sstatus};
 use system_error::SystemError;
 
 use crate::{
     driver::irqchip::riscv_intc::riscv_intc_init,
     exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
+    libs::align::align_up,
 };
 
+use super::cpu::STACK_ALIGN;
+
+pub(super) mod entry;
+mod handle;
 pub mod ipi;
 
 pub struct RiscV64InterruptArch;
@@ -55,12 +61,54 @@ impl InterruptArch for RiscV64InterruptArch {
 #[repr(C)]
 #[derive(Debug, Copy, Clone)]
 pub struct TrapFrame {
-    // todo
+    epc: usize,
+    ra: usize,
+    sp: usize,
+    gp: usize,
+    tp: usize,
+    t0: usize,
+    t1: usize,
+    t2: usize,
+    s0: usize,
+    s1: usize,
+    a0: usize,
+    a1: usize,
+    a2: usize,
+    a3: usize,
+    a4: usize,
+    a5: usize,
+    a6: usize,
+    a7: usize,
+    s2: usize,
+    s3: usize,
+    s4: usize,
+    s5: usize,
+    s6: usize,
+    s7: usize,
+    s8: usize,
+    s9: usize,
+    s10: usize,
+    s11: usize,
+    t3: usize,
+    t4: usize,
+    t5: usize,
+    t6: usize,
+    // 以下是中断发生时自动保存的寄存器
+    status: Sstatus,
+    badaddr: usize,
+    cause: Scause,
+    /// a0 value before the syscall
+    origin_a0: usize,
 }
 
 impl TrapFrame {
+    /// 中断栈帧结构体的大小
+    pub const SIZE: usize = core::mem::size_of::<TrapFrame>();
+
+    /// 中断栈帧在栈上的大小
+    pub const SIZE_ON_STACK: usize = align_up(Self::SIZE, STACK_ALIGN);
     /// 判断当前中断是否来自用户模式
     pub fn from_user(&self) -> bool {
-        unimplemented!("TrapFrame::from_user")
+        self.status.spp() == riscv::register::sstatus::SPP::User
     }
 }

+ 0 - 2
kernel/src/arch/riscv64/ipc/signal.rs

@@ -5,8 +5,6 @@ use crate::{
     process::ProcessManager,
 };
 
-/// 信号处理的栈的栈指针的最小对齐数量
-pub const STACK_ALIGN: u64 = 16;
 /// 信号最大值
 pub const MAX_SIG_NUM: usize = 64;
 #[allow(dead_code)]

+ 1 - 0
kernel/src/arch/riscv64/smp/mod.rs

@@ -5,6 +5,7 @@ use crate::smp::SMPArch;
 pub struct RiscV64SMPArch;
 
 impl SMPArch for RiscV64SMPArch {
+    #[inline(never)]
     fn prepare_cpus() -> Result<(), SystemError> {
         todo!()
     }

+ 1 - 1
kernel/src/common/sys/types.h

@@ -1,6 +1,6 @@
 #pragma once
 
-#include <DragonOS/stdint.h>
+#include "DragonOS/stdint.h"
 #include <stdbool.h>
 
 typedef unsigned char u_char;

+ 1 - 2
kernel/src/init/init.rs

@@ -62,9 +62,8 @@ fn do_start_kernel() {
 
     early_smp_init().expect("early smp init failed");
     irq_init().expect("irq init failed");
-    CurrentSMPArch::prepare_cpus().expect("prepare_cpus failed");
-
     setup_arch().expect("setup_arch failed");
+    CurrentSMPArch::prepare_cpus().expect("prepare_cpus failed");
 
     process_init();
     sched_init();

+ 4 - 3
kernel/src/lib.rs

@@ -3,6 +3,7 @@
 #![feature(allocator_api)]
 #![feature(arbitrary_self_types)]
 #![feature(asm_const)]
+#![feature(concat_idents)]
 #![feature(const_for)]
 #![feature(const_mut_refs)]
 #![feature(const_trait_impl)]
@@ -11,16 +12,16 @@
 #![feature(core_intrinsics)]
 #![feature(c_void_variant)]
 #![feature(extract_if)]
+#![feature(fn_align)]
 #![feature(inline_const)]
 #![feature(naked_functions)]
+#![feature(new_uninit)]
 #![feature(panic_info_message)]
 #![feature(ptr_internals)]
+#![feature(ptr_to_from_bits)]
 #![feature(trait_upcasting)]
 #![feature(slice_ptr_get)]
 #![feature(vec_into_raw_parts)]
-#![feature(new_uninit)]
-#![feature(ptr_to_from_bits)]
-#![feature(concat_idents)]
 #![cfg_attr(target_os = "none", no_std)]
 
 #[cfg(test)]

+ 12 - 2
kernel/src/libs/align.rs

@@ -126,16 +126,26 @@ unsafe impl<const NUM: usize> SafeForZero for [u8; NUM] {}
 /// 参数 `addr`:要对齐的地址。
 ///
 /// 返回值:对齐后的地址。
-pub fn page_align_up(addr: usize) -> usize {
+pub const fn page_align_up(addr: usize) -> usize {
     let page_size = MMArch::PAGE_SIZE;
     return (addr + page_size - 1) & (!(page_size - 1));
 }
 
-pub fn page_align_down(addr: usize) -> usize {
+pub const fn page_align_down(addr: usize) -> usize {
     let page_size = MMArch::PAGE_SIZE;
     return addr & (!(page_size - 1));
 }
 
+pub const fn align_up(addr: usize, align: usize) -> usize {
+    assert!(align != 0 && align.is_power_of_two());
+    return (addr + align - 1) & (!(align - 1));
+}
+
+pub const fn align_down(addr: usize, align: usize) -> usize {
+    assert!(align != 0 && align.is_power_of_two());
+    return addr & (!(align - 1));
+}
+
 /// ## 检查是否对齐
 ///
 /// 检查给定的值是否对齐到给定的对齐要求。