Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kernel/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,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 = "cc4d3ea82a", features = [ "s-mode" ] }
riscv = { git = "https://git.mirrors.dragonos.org.cn/DragonOS-Community/riscv.git", rev = "4241a97", features = [ "s-mode" ] }
sbi-rt = { version = "=0.0.3", features = ["legacy"] }


Expand Down
2 changes: 2 additions & 0 deletions kernel/src/arch/riscv64/driver/of.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ use system_error::SystemError;
use crate::{
driver::open_firmware::fdt::OpenFirmwareFdtDriver,
init::boot_params,
kdebug,
libs::align::page_align_up,
mm::{mmio_buddy::mmio_pool, MemoryManagementArch, PhysAddr},
};
Expand All @@ -28,6 +29,7 @@ impl OpenFirmwareFdtDriver {

// drop the boot params guard in order to avoid deadlock
drop(bp_guard);
// kdebug!("map_fdt: map fdt to {:?}, size: {}", map_paddr, map_size);
mmio_guard.map_phys(map_paddr, map_size)?;
let mut bp_guard = boot_params().write();
let vaddr = mmio_guard.vaddr() + offset;
Expand Down
2 changes: 1 addition & 1 deletion kernel/src/arch/riscv64/init/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ pub fn early_setup_arch() -> Result<(), SystemError> {
arch_boot_params_guard.arch.fdt_paddr = fdt_paddr;
arch_boot_params_guard.arch.fdt_size = fdt.total_size();
arch_boot_params_guard.arch.boot_hartid = ProcessorId::new(hartid);

// kdebug!("fdt_paddr: {:?}, fdt_size: {}", fdt_paddr, fdt.total_size());
drop(arch_boot_params_guard);

kinfo!(
Expand Down
3 changes: 2 additions & 1 deletion kernel/src/arch/riscv64/interrupt/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,8 @@ unsafe extern "C" fn _save_context() -> ! {
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),
sr_sum_and_fsvs = const (0), // 暂时在内核中不禁用FPU和Vector,以及不禁用用户内存访问
// 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,
Expand Down
25 changes: 17 additions & 8 deletions kernel/src/arch/riscv64/interrupt/handle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,6 @@ fn riscv64_do_interrupt(trap_frame: &mut TrapFrame) {

/// 处理异常
fn riscv64_do_exception(trap_frame: &mut TrapFrame) {
kdebug!(
"riscv64_do_exception: from_user: {}",
trap_frame.is_from_user()
);
let code = trap_frame.cause.code();

if code < EXCEPTION_HANDLERS.len() {
Expand Down Expand Up @@ -153,8 +149,16 @@ fn do_trap_user_env_call(trap_frame: &mut TrapFrame) -> Result<(), SystemError>
// 9-11 reserved

/// 处理指令页错误异常 #12
fn do_trap_insn_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!("riscv64_do_irq: do_insn_page_fault");
fn do_trap_insn_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
let vaddr = trap_frame.badaddr;
let cause = trap_frame.cause;
let epc = trap_frame.epc;
kerror!(
"riscv64_do_irq: do_insn_page_fault vaddr: {:#x}, cause: {:?} epc: {:#x}",
vaddr,
cause,
epc
);
loop {
spin_loop();
}
Expand All @@ -179,8 +183,13 @@ fn do_trap_load_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError
// 14 reserved

/// 处理页存储错误异常 #15
fn do_trap_store_page_fault(_trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!("riscv64_do_irq: do_trap_store_page_fault");
fn do_trap_store_page_fault(trap_frame: &mut TrapFrame) -> Result<(), SystemError> {
kerror!(
"riscv64_do_irq: do_trap_store_page_fault: epc: {:#x}, vaddr={:#x}, cause={:?}",
trap_frame.epc,
trap_frame.badaddr,
trap_frame.cause
);
loop {
spin_loop();
}
Expand Down
6 changes: 4 additions & 2 deletions kernel/src/arch/riscv64/mm/init.rs
Original file line number Diff line number Diff line change
Expand Up @@ -69,14 +69,16 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
mem_block_manager()
.reserve_block(KERNEL_BEGIN_PA, KERNEL_END_PA - KERNEL_BEGIN_PA)
.expect("Failed to reserve kernel memory");
// 开启S-mode User Memory Access,允许内核访问用户空间
riscv::register::sstatus::set_sum();

let mut bump_allocator = BumpAllocator::<RiscV64MMArch>::new(0);
let _old_page_table = MMArch::table(PageTableKind::Kernel);
let new_page_table: PhysAddr;

// 使用bump分配器,把所有的内存页都映射到页表
{
kdebug!("to create new page table");
// kdebug!("to create new page table");
// 用bump allocator创建新的页表
let mut mapper: crate::mm::page::PageMapper<MMArch, &mut BumpAllocator<MMArch>> =
crate::mm::page::PageMapper::<MMArch, _>::create(
Expand All @@ -85,7 +87,7 @@ pub(super) unsafe fn riscv_mm_init() -> Result<(), SystemError> {
)
.expect("Failed to create page mapper");
new_page_table = mapper.table().phys();
kdebug!("PageMapper created");
// kdebug!("PageMapper created");

// 取消最开始时候,在head.S中指定的映射(暂时不刷新TLB)
{
Expand Down
4 changes: 3 additions & 1 deletion kernel/src/arch/riscv64/mm/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,9 @@ impl MemoryManagementArch for RiscV64MMArch {

const ENTRY_FLAG_PRESENT: usize = 1 << 0;

const ENTRY_FLAG_READONLY: usize = 0;
const ENTRY_FLAG_READONLY: usize = (1 << 1);

const ENTRY_FLAG_WRITEABLE: usize = (1 << 2);

const ENTRY_FLAG_READWRITE: usize = (1 << 2) | (1 << 1);

Expand Down
2 changes: 1 addition & 1 deletion kernel/src/arch/riscv64/process/idle.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ impl ProcessManager {
spin_loop();
}

kdebug!("idle loop");
// kdebug!("idle loop");
}
}
}
1 change: 1 addition & 0 deletions kernel/src/arch/riscv64/process/kthread.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ impl KernelThreadMechanism {
// 使能中断
frame.status.update_sie(true);
frame.status.update_spp(SPP::Supervisor);
frame.status.update_sum(true);

frame.ra = kernel_thread_bootstrap_stage1 as usize;

Expand Down
94 changes: 78 additions & 16 deletions kernel/src/arch/riscv64/process/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ use crate::{
PROCESS_SWITCH_RESULT,
},
smp::cpu::ProcessorId,
syscall::Syscall,
};

use super::{
Expand All @@ -53,7 +54,64 @@ static BSP_IDLE_STACK_SPACE: InitProcUnion = InitProcUnion {
};

pub unsafe fn arch_switch_to_user(path: String, argv: Vec<String>, envp: Vec<String>) -> ! {
unimplemented!("RiscV64 arch_switch_to_user")
// 以下代码不能发生中断
CurrentIrqArch::interrupt_disable();

let current_pcb = ProcessManager::current_pcb();
let trap_frame_vaddr = VirtAddr::new(
current_pcb.kernel_stack().stack_max_address().data() - core::mem::size_of::<TrapFrame>(),
);
let new_pc = VirtAddr::new(ret_from_exception as usize);

let mut arch_guard = current_pcb.arch_info_irqsave();
arch_guard.ksp = trap_frame_vaddr.data();

arch_guard.ra = new_pc.data();
drop(arch_guard);

// 删除kthread的标志
current_pcb.flags().remove(ProcessFlags::KTHREAD);
current_pcb.worker_private().take();

*current_pcb.sched_info().sched_policy.write_irqsave() = crate::sched::SchedPolicy::CFS;

let mut trap_frame = TrapFrame::new();

compiler_fence(Ordering::SeqCst);
Syscall::do_execve(path, argv, envp, &mut trap_frame).unwrap_or_else(|e| {
panic!(
"arch_switch_to_user(): pid: {pid:?}, Failed to execve: , error: {e:?}",
pid = current_pcb.pid(),
e = e
);
});
compiler_fence(Ordering::SeqCst);

// 重要!在这里之后,一定要保证上面的引用计数变量、动态申请的变量、锁的守卫都被drop了,否则可能导致内存安全问题!

drop(current_pcb);

*(trap_frame_vaddr.data() as *mut TrapFrame) = trap_frame;

compiler_fence(Ordering::SeqCst);
ready_to_switch_to_user(trap_frame_vaddr.data(), new_pc.data());
}

#[naked]
unsafe extern "C" fn ready_to_switch_to_user(trap_frame: usize, new_pc: usize) -> ! {
asm!(
concat!(
"
// 设置trap frame
mv sp, a0
// 设置返回地址

jr a1

"
),
options(noreturn)
);
}

impl ProcessManager {
Expand Down Expand Up @@ -98,6 +156,7 @@ impl ProcessManager {
let current_arch_guard = current_pcb.arch_info_irqsave();
// 拷贝浮点寄存器的状态
new_arch_guard.fp_state = current_arch_guard.fp_state;
new_arch_guard.sstatus = current_arch_guard.sstatus;

drop(current_arch_guard);

Expand Down Expand Up @@ -128,11 +187,11 @@ impl ProcessManager {
/// 参考: https://code.dragonos.org.cn/xref/linux-6.6.21/arch/riscv/include/asm/switch_to.h#76
pub unsafe fn switch_process(prev: Arc<ProcessControlBlock>, next: Arc<ProcessControlBlock>) {
assert!(!CurrentIrqArch::is_irq_enabled());
kdebug!(
"riscv switch process: prev: {:?}, next: {:?}",
prev.pid(),
next.pid()
);
// kdebug!(
// "riscv switch process: prev: {:?}, next: {:?}",
// prev.pid(),
// next.pid()
// );
Self::switch_process_fpu(&prev, &next);
Self::switch_local_context(&prev, &next);

Expand All @@ -144,6 +203,8 @@ impl ProcessManager {
drop(next_addr_space);
compiler_fence(Ordering::SeqCst);

// kdebug!("current sum={}, prev sum={}, next_sum={}", riscv::register::sstatus::read().sum(), prev.arch_info_irqsave().sstatus.sum(), next.arch_info_irqsave().sstatus.sum());

// 获取arch info的锁,并强制泄露其守卫(切换上下文后,在switch_finish_hook中会释放锁)
let next_arch = SpinLockGuard::leak(next.arch_info_irqsave()) as *mut ArchPCBInfo;
let prev_arch = SpinLockGuard::leak(prev.arch_info_irqsave()) as *mut ArchPCBInfo;
Expand All @@ -153,7 +214,7 @@ impl ProcessManager {
ProcessManager::current_pcb().preempt_enable();
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().prev_pcb = Some(prev);
PROCESS_SWITCH_RESULT.as_mut().unwrap().get_mut().next_pcb = Some(next);
kdebug!("riscv switch process: before to inner");
// kdebug!("riscv switch process: before to inner");
compiler_fence(Ordering::SeqCst);
// 正式切换上下文
switch_to_inner(prev_arch, next_arch);
Expand Down Expand Up @@ -206,8 +267,8 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI

addi sp , sp, -8
sd a1, 0(sp)
csrr a0, sstatus
sd a0, {off_sstatus}(a1)
csrr a1, sstatus
sd a1, {off_sstatus}(a0)
ld a1, 0(sp)
addi sp, sp, 8

Expand Down Expand Up @@ -271,13 +332,12 @@ unsafe extern "C" fn switch_to_inner(prev: *mut ArchPCBInfo, next: *mut ArchPCBI
/// 在切换上下文完成后的钩子函数(必须在这里加一个跳转函数,否则会出现relocation truncated to fit: R_RISCV_JAL错误)
unsafe extern "C" fn before_switch_finish_hook() {
let pcb = ProcessManager::current_pcb();
kdebug!(
"before_switch_finish_hook, pid: {:?}, name: {:?}",
pcb.pid(),
pcb.basic().name()
);
// kdebug!(
// "before_switch_finish_hook, pid: {:?}, name: {:?}",
// pcb.pid(),
// pcb.basic().name()
// );
switch_finish_hook();
kdebug!("after switch_finish_hook");
}

impl ProcessControlBlock {
Expand Down Expand Up @@ -344,6 +404,8 @@ impl ArchPCBInfo {
///
/// 返回一个新的ArchPCBInfo
pub fn new(kstack: &KernelStack) -> Self {
let mut sstatus = Sstatus::from(0);
sstatus.update_sum(true);
Self {
ra: 0,
ksp: kstack.stack_max_address().data(),
Expand All @@ -359,7 +421,7 @@ impl ArchPCBInfo {
s9: 0,
s10: 0,
s11: 0,
sstatus: Sstatus::from(0),
sstatus,
fp_state: FpDExtState::new(),
local_context: LocalContext::new(ProcessorId::new(0)),
}
Expand Down
Loading