diff --git a/kernel/Cargo.toml b/kernel/Cargo.toml index 6b1305ac..5f5abded 100644 --- a/kernel/Cargo.toml +++ b/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"] } diff --git a/kernel/src/arch/riscv64/asm/csr.rs b/kernel/src/arch/riscv64/asm/csr.rs new file mode 100644 index 00000000..70bfa537 --- /dev/null +++ b/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; diff --git a/kernel/src/arch/riscv64/asm/head.S b/kernel/src/arch/riscv64/asm/head.S index eb3939e3..34d78cf4 100644 --- a/kernel/src/arch/riscv64/asm/head.S +++ b/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 */ diff --git a/kernel/src/arch/riscv64/asm/mod.rs b/kernel/src/arch/riscv64/asm/mod.rs index 7d9ea44b..01dca862 100644 --- a/kernel/src/arch/riscv64/asm/mod.rs +++ b/kernel/src/arch/riscv64/asm/mod.rs @@ -1 +1,2 @@ pub mod bitops; +pub(super) mod csr; diff --git a/kernel/src/arch/riscv64/cpu.rs b/kernel/src/arch/riscv64/cpu.rs index cc26b93d..cb65b753 100644 --- a/kernel/src/arch/riscv64/cpu.rs +++ b/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 { /// 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 { diff --git a/kernel/src/arch/riscv64/include/asm/asm.h b/kernel/src/arch/riscv64/include/asm/asm.h index 64631adc..6f1b1a70 100644 --- a/kernel/src/arch/riscv64/include/asm/asm.h +++ b/kernel/src/arch/riscv64/include/asm/asm.h @@ -1,8 +1,8 @@ #pragma once -#include -#include +#include "DragonOS/stdint.h" #include +#include // 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) + ; } \ No newline at end of file diff --git a/kernel/src/arch/riscv64/include/asm/csr.h b/kernel/src/arch/riscv64/include/asm/csr.h new file mode 100644 index 00000000..7b42a6b9 --- /dev/null +++ b/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) \ No newline at end of file diff --git a/kernel/src/arch/riscv64/init/mod.rs b/kernel/src/arch/riscv64/init/mod.rs index 41421d86..a22d7530 100644 --- a/kernel/src/arch/riscv64/init/mod.rs +++ b/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!(" ")); diff --git a/kernel/src/arch/riscv64/interrupt/entry.rs b/kernel/src/arch/riscv64/interrupt/entry.rs new file mode 100644 index 00000000..a5942c38 --- /dev/null +++ b/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), + ) +} diff --git a/kernel/src/arch/riscv64/interrupt/handle.rs b/kernel/src/arch/riscv64/interrupt/handle.rs new file mode 100644 index 00000000..3750d936 --- /dev/null +++ b/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(); + } +} diff --git a/kernel/src/arch/riscv64/interrupt/mod.rs b/kernel/src/arch/riscv64/interrupt/mod.rs index 3c5ba43d..4053f706 100644 --- a/kernel/src/arch/riscv64/interrupt/mod.rs +++ b/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::(); + + /// 中断栈帧在栈上的大小 + 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 } } diff --git a/kernel/src/arch/riscv64/ipc/signal.rs b/kernel/src/arch/riscv64/ipc/signal.rs index 053ff7ea..3ebb66c1 100644 --- a/kernel/src/arch/riscv64/ipc/signal.rs +++ b/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)] diff --git a/kernel/src/arch/riscv64/smp/mod.rs b/kernel/src/arch/riscv64/smp/mod.rs index 973bd86a..5cc93a1a 100644 --- a/kernel/src/arch/riscv64/smp/mod.rs +++ b/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!() } diff --git a/kernel/src/common/sys/types.h b/kernel/src/common/sys/types.h index fe06d39a..7d1d8cbc 100644 --- a/kernel/src/common/sys/types.h +++ b/kernel/src/common/sys/types.h @@ -1,6 +1,6 @@ #pragma once -#include +#include "DragonOS/stdint.h" #include typedef unsigned char u_char; diff --git a/kernel/src/init/init.rs b/kernel/src/init/init.rs index 5e839385..47bc4a89 100644 --- a/kernel/src/init/init.rs +++ b/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(); diff --git a/kernel/src/lib.rs b/kernel/src/lib.rs index 6eb7334c..484ede91 100644 --- a/kernel/src/lib.rs +++ b/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)] diff --git a/kernel/src/libs/align.rs b/kernel/src/libs/align.rs index 7d5748d2..4303dd61 100644 --- a/kernel/src/libs/align.rs +++ b/kernel/src/libs/align.rs @@ -126,16 +126,26 @@ unsafe impl 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)); +} + /// ## 检查是否对齐 /// /// 检查给定的值是否对齐到给定的对齐要求。