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

This commit is contained in:
LoGin 2024-03-08 23:23:06 +08:00 committed by GitHub
parent c3dc6f2ff9
commit 5c4224e5a8
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 701 additions and 80 deletions

View File

@ -42,7 +42,6 @@ linkme = "=0.2"
num = { version = "=0.4.0", default-features = false } num = { version = "=0.4.0", default-features = false }
num-derive = "=0.3" num-derive = "=0.3"
num-traits = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/num-traits.git", rev="1597c1c", default-features = false } 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"]} 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" } system_error = { path = "crates/system_error" }
unified-init = { path = "crates/unified-init" } unified-init = { path = "crates/unified-init" }
@ -62,7 +61,7 @@ x86_64 = "=0.14.10"
# target为riscv64时使用下面的依赖 # target为riscv64时使用下面的依赖
[target.'cfg(target_arch = "riscv64")'.dependencies] [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"] } sbi-rt = { version = "=0.0.3", features = ["legacy"] }

View File

@ -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;

View File

@ -1,31 +1,8 @@
#include "common/asm.h" #include "common/asm.h"
#include "asm/csr.h"
.section .bootstrap .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 // DragonStub
// //
// a0: hartid ID // a0: hartid ID
@ -86,9 +63,11 @@ ENTRY(_start)
__init_set_pgtable_loop_end: __init_set_pgtable_loop_end:
call __initial_reloacate_enable_mmu call __initial_reloacate_enable_mmu
.option push .option push
.option norelax .option norelax
//
la a0, BSP_IDLE_STACK_SPACE la a0, BSP_IDLE_STACK_SPACE
mv sp, a0 mv sp, a0
li t0, 32752 // 16 li t0, 32752 // 16
@ -100,6 +79,7 @@ __init_set_pgtable_loop_end:
*/ */
li t0, SR_FS_VS li t0, SR_FS_VS
csrc CSR_STATUS, t0 csrc CSR_STATUS, t0
/* Call the kernel */ /* Call the kernel */
la a0, __initial_hartid_ptr la a0, __initial_hartid_ptr
@ -128,7 +108,7 @@ __initial_reloacate_enable_mmu:
/* Point stvec to virtual address of intruction after satp write */ /* Point stvec to virtual address of intruction after satp write */
/* Set trap vector to spin forever to help debug */ /* Set trap vector to spin forever to help debug */
la a2, 1f la a2, 3f
add a2, a2, t1 add a2, a2, t1
csrw CSR_TVEC, a2 csrw CSR_TVEC, a2
// enable MMU // enable MMU
@ -142,7 +122,7 @@ __initial_reloacate_enable_mmu:
sfence.vma sfence.vma
csrw satp, a2 csrw satp, a2
1: 3:
la a0, __initial_Lsecondary_park la a0, __initial_Lsecondary_park
add a0, a0, t1 add a0, a0, t1
csrw CSR_TVEC, a0 csrw CSR_TVEC, a0
@ -337,6 +317,7 @@ __initial_clear_pgtable_loop:
ret ret
.align 2 .align 2
__initial_Lsecondary_park: __initial_Lsecondary_park:
/* We lack SMP support or have too many harts, so park this hart */ /* We lack SMP support or have too many harts, so park this hart */

View File

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

View File

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

View File

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

View File

@ -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)

View File

@ -3,10 +3,7 @@ use system_error::SystemError;
use crate::{ use crate::{
arch::{driver::sbi::SbiDriver, mm::init::mm_early_init}, arch::{driver::sbi::SbiDriver, mm::init::mm_early_init},
driver::{ driver::{firmware::efi::init::efi_init, open_firmware::fdt::open_firmware_fdt_driver},
firmware::efi::init::efi_init, irqchip::riscv_intc::riscv_intc_init,
open_firmware::fdt::open_firmware_fdt_driver,
},
init::{boot_params, init::start_kernel}, init::{boot_params, init::start_kernel},
kdebug, kinfo, kdebug, kinfo,
mm::{memblock::mem_block_manager, PhysAddr, VirtAddr}, mm::{memblock::mem_block_manager, PhysAddr, VirtAddr},
@ -14,7 +11,7 @@ use crate::{
smp::cpu::ProcessorId, 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)] #[derive(Debug)]
pub struct ArchBootParams { pub struct ArchBootParams {
@ -52,10 +49,22 @@ unsafe extern "C" fn kernel_main(hartid: usize, fdt_paddr: usize) -> ! {
BOOT_HARTID = hartid as u32; BOOT_HARTID = hartid as u32;
BOOT_FDT_PADDR = fdt_paddr; BOOT_FDT_PADDR = fdt_paddr;
} }
setup_trap_vector();
start_kernel(); 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)] #[inline(never)]
fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) { fn print_node(node: FdtNode<'_, '_>, n_spaces: usize) {
(0..n_spaces).for_each(|_| print!(" ")); (0..n_spaces).for_each(|_| print!(" "));

View File

@ -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),
)
}

View File

@ -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();
}
}

View File

@ -1,10 +1,16 @@
use riscv::register::{scause::Scause, sstatus::Sstatus};
use system_error::SystemError; use system_error::SystemError;
use crate::{ use crate::{
driver::irqchip::riscv_intc::riscv_intc_init, driver::irqchip::riscv_intc::riscv_intc_init,
exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber}, exception::{InterruptArch, IrqFlags, IrqFlagsGuard, IrqNumber},
libs::align::align_up,
}; };
use super::cpu::STACK_ALIGN;
pub(super) mod entry;
mod handle;
pub mod ipi; pub mod ipi;
pub struct RiscV64InterruptArch; pub struct RiscV64InterruptArch;
@ -55,12 +61,54 @@ impl InterruptArch for RiscV64InterruptArch {
#[repr(C)] #[repr(C)]
#[derive(Debug, Copy, Clone)] #[derive(Debug, Copy, Clone)]
pub struct TrapFrame { 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 { 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 { pub fn from_user(&self) -> bool {
unimplemented!("TrapFrame::from_user") self.status.spp() == riscv::register::sstatus::SPP::User
} }
} }

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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