diff --git a/os/src/arch/cpu_ops.rs b/os/src/arch/cpu_ops.rs index 54d14c28..534333f7 100644 --- a/os/src/arch/cpu_ops.rs +++ b/os/src/arch/cpu_ops.rs @@ -33,6 +33,9 @@ pub trait CpuOps: 'static { /// 显式启用中断 fn enable_interrupts(); + /// 当前中断是否处于启用状态 + fn interrupts_enabled() -> bool; + /// 检查 `disable_interrupts()` 返回的 flags 中中断是否处于启用状态 /// /// 默认实现假定 flags 的 bit 0 表示中断启用状态。 diff --git a/os/src/arch/loongarch/boot/mod.rs b/os/src/arch/loongarch/boot/mod.rs index fd64f1a4..f20da6be 100644 --- a/os/src/arch/loongarch/boot/mod.rs +++ b/os/src/arch/loongarch/boot/mod.rs @@ -4,62 +4,18 @@ use core::arch::global_asm; global_asm!(include_str!("entry.S")); -use crate::{ - arch::{intr, platform, timer, trap}, - earlyprintln, - kernel::{self, current_cpu, time}, - mm, - sync::PreemptGuard, - test::run_early_tests, -}; +use crate::kernel; /// LoongArch 主核启动入口 pub fn main(hartid: usize) { - kernel::boot::clear_bss(); + let mut ops = kernel::boot::PrimaryBootOps::new("LoongArch", "CPU"); + ops.after_clear_bss = enable_base_fp; + kernel::boot::run_primary_boot(hartid, ops); +} +fn enable_base_fp(_hartid: usize) { // Enable base floating-point instructions (EUEN.FPE). Many LoongArch Linux-ABI // user programs are built with floating-point enabled and may execute FP // instructions very early during startup. loongArch64::register::euen::set_fpe(true); - - run_early_tests(); - - earlyprintln!("[Boot] Hello, world!"); - earlyprintln!("[Boot] LoongArch CPU {} is up!", hartid); - - let kernel_space = mm::init(); - - // 激活内核地址空间 - { - let _guard = PreemptGuard::new(); - current_cpu().switch_space(kernel_space); - } - - #[cfg(test)] - crate::test_main(); - - // 早期引导陷阱(覆盖平台初始化窗口) - trap::init_boot_trap(); - platform::init(); - time::init(); - timer::init(); - - // 创建 idle 并设为当前任务(KScratch0 就绪) - let idle = kernel::boot::create_idle_task(0, kernel::boot::idle_loop); - { - let _guard = PreemptGuard::new(); - current_cpu().idle_task = Some(idle.clone()); - current_cpu().switch_task(idle); - } - - // 完整陷阱处理(KScratch0 已有效) - trap::init(); - - // 创建 init 任务并入队(中断仍禁用,避免竞争) - kernel::boot::rest_init(); - - // 启用中断并进入 idle 循环 - // 时钟中断触发后调度器自动选中 init 并切换上下文 - unsafe { intr::enable_interrupts() }; - kernel::boot::idle_loop(); } diff --git a/os/src/arch/loongarch/cpu_ops.rs b/os/src/arch/loongarch/cpu_ops.rs index db8cca98..946a91eb 100644 --- a/os/src/arch/loongarch/cpu_ops.rs +++ b/os/src/arch/loongarch/cpu_ops.rs @@ -4,7 +4,7 @@ //! 将现有的 CSR 内联汇编操作映射到 trait 方法。 use crate::arch::CpuOps; -use crate::arch::constant::{CSR_CRMD_IE, SSTATUS_SIE}; +use crate::arch::constant::CSR_CRMD_IE; /// LoongArch64 架构标记类型 pub struct LoongArch64; @@ -68,10 +68,8 @@ impl CpuOps for LoongArch64 { /// 根据保存的 CRMD 值恢复 IE 位。 #[inline] fn restore_interrupt_state(flags: usize) { - if flags & SSTATUS_SIE != 0 { - unsafe { - Self::enable_interrupts(); - } + if flags & CSR_CRMD_IE != 0 { + Self::enable_interrupts(); } } @@ -96,8 +94,21 @@ impl CpuOps for LoongArch64 { } } + #[inline] + fn interrupts_enabled() -> bool { + let crmd: usize; + unsafe { + core::arch::asm!( + "csrrd {crmd}, 0x0", + crmd = out(reg) crmd, + options(nostack, preserves_flags) + ); + } + crmd & CSR_CRMD_IE != 0 + } + #[inline] fn interrupt_was_enabled(flags: usize) -> bool { - flags & SSTATUS_SIE != 0 + flags & CSR_CRMD_IE != 0 } } diff --git a/os/src/arch/loongarch/kernel/task.rs b/os/src/arch/loongarch/kernel/task.rs index bebdd9a8..b1084356 100644 --- a/os/src/arch/loongarch/kernel/task.rs +++ b/os/src/arch/loongarch/kernel/task.rs @@ -223,14 +223,16 @@ pub fn setup_exec_stack_layout( } /// Restore a freshly scheduled task for the first time. -pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, is_kernel_thread: bool) { - if is_kernel_thread { - let (entry, sp) = unsafe { ((*tf_ptr).era, (*tf_ptr).kernel_sp) }; +pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, _is_kernel_thread: bool) { + if unsafe { is_kernel_entry(tf_ptr) } { + let (entry, sp, ra) = unsafe { ((*tf_ptr).era, (*tf_ptr).kernel_sp, (*tf_ptr).regs[1]) }; unsafe { core::arch::asm!( "addi.d $sp, {sp}, 0", + "addi.d $ra, {ra}, 0", "jirl $zero, {entry}, 0", sp = in(reg) sp, + ra = in(reg) ra, entry = in(reg) entry, options(noreturn) ); @@ -239,6 +241,28 @@ pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, is_kern crate::arch::trap::restore(unsafe { &*tf_ptr }); } +unsafe fn is_kernel_entry(tf_ptr: *mut crate::arch::trap::TrapFrame) -> bool { + unsafe { (*tf_ptr).era >= crate::arch::constant::KERNEL_BASE } +} + +/// Initialize the trap frame used to enter a kernel task. +pub unsafe fn init_kernel_trap_frame( + tf_ptr: *mut crate::arch::trap::TrapFrame, + entry: usize, + terminal: usize, + kernel_sp: usize, +) { + unsafe { + core::ptr::write(tf_ptr, crate::arch::trap::TrapFrame::zero_init()); + (*tf_ptr).set_kernel_trap_frame(entry, terminal, kernel_sp); + let cpu_ptr = { + let _guard = crate::sync::PreemptGuard::new(); + crate::kernel::current_cpu() as *const _ as usize + }; + crate::arch::trap::set_trap_frame_cpu_ptr(tf_ptr, cpu_ptr); + } +} + /// Final architecture-specific preparation before restoring to user mode. pub unsafe fn prepare_user_restore( tfp: *mut crate::arch::trap::TrapFrame, diff --git a/os/src/arch/loongarch/timer.rs b/os/src/arch/loongarch/timer.rs index 6112988f..12a61d5a 100644 --- a/os/src/arch/loongarch/timer.rs +++ b/os/src/arch/loongarch/timer.rs @@ -52,21 +52,15 @@ pub fn set_next_trigger() { unsafe { // 1. 先彻底关闭定时器并清除周期模式 (TCFG bit 0 and 1 = 0) 防止配置过程中的竞争 - core::arch::asm!("csrwr $r0, 0x410"); + core::arch::asm!("csrwr $r0, {tcfg}", tcfg = const CSR_TCFG); - // 2. 写入 TVAL (0x420) - // 在 En=0 时写入 TVAL 会直接重置当前倒计时器 + // 2. 开启定时器,设为周期模式。 + // TCFG[63:2] 存放初始计数值;TVAL 是只读当前计数值,不能用于重装。 + let cfg = (delta & !0b11usize) | 0b11usize; core::arch::asm!( - "csrwr {val}, 0x420", - val = in(reg) delta - ); - - // 3. 开启定时器,设为单次触发模式 (En=1, Periodic=0) - // 这样定时器倒数到 0 后会停下并触发中断 - let cfg = 0b01usize; - core::arch::asm!( - "csrwr {val}, 0x410", - val = in(reg) cfg + "csrwr {val}, {tcfg}", + val = in(reg) cfg, + tcfg = const CSR_TCFG ); } } diff --git a/os/src/arch/loongarch/trap/trap_frame.rs b/os/src/arch/loongarch/trap/trap_frame.rs index bd92ee1b..bf40e9c3 100644 --- a/os/src/arch/loongarch/trap/trap_frame.rs +++ b/os/src/arch/loongarch/trap/trap_frame.rs @@ -126,8 +126,9 @@ impl TrapFrame { } /// 设置内核态陷阱帧 - pub fn set_kernel_trap_frame(&mut self, entry: usize, _terminal: usize, kernel_sp: usize) { + pub fn set_kernel_trap_frame(&mut self, entry: usize, terminal: usize, kernel_sp: usize) { self.era = entry; + self.regs[1] = terminal; // ra self.regs[3] = kernel_sp; // sp self.kernel_sp = kernel_sp; } diff --git a/os/src/arch/mock/arch.rs b/os/src/arch/mock/arch.rs index 652afa26..99dc1283 100644 --- a/os/src/arch/mock/arch.rs +++ b/os/src/arch/mock/arch.rs @@ -44,6 +44,10 @@ impl CpuOps for MockCpuOps { fn restore_interrupt_state(_flags: usize) {} fn enable_interrupts() {} + + fn interrupts_enabled() -> bool { + false + } } // ============================================================================ @@ -175,6 +179,9 @@ impl CpuOps for MockArch { fn enable_interrupts() { MockCpuOps::enable_interrupts() } + fn interrupts_enabled() -> bool { + MockCpuOps::interrupts_enabled() + } } impl VirtualMemory for MockArch { diff --git a/os/src/arch/mock/kernel.rs b/os/src/arch/mock/kernel.rs index eee2e5b3..5e823444 100644 --- a/os/src/arch/mock/kernel.rs +++ b/os/src/arch/mock/kernel.rs @@ -95,6 +95,19 @@ pub mod task { unsafe { crate::arch::trap::restore(&*tf_ptr) }; } + pub unsafe fn init_kernel_trap_frame( + tf_ptr: *mut crate::arch::trap::TrapFrame, + entry: usize, + terminal: usize, + kernel_sp: usize, + ) { + unsafe { + core::ptr::write(tf_ptr, crate::arch::trap::TrapFrame::zero_init()); + (*tf_ptr).set_kernel_trap_frame(entry, terminal, kernel_sp); + crate::arch::trap::set_trap_frame_cpu_ptr(tf_ptr, 0); + } + } + pub unsafe fn prepare_user_restore( _tfp: *mut crate::arch::trap::TrapFrame, _initial_pc: VA, diff --git a/os/src/arch/mock/trap.rs b/os/src/arch/mock/trap.rs index 88f8851d..544f8e3e 100644 --- a/os/src/arch/mock/trap.rs +++ b/os/src/arch/mock/trap.rs @@ -1,5 +1,9 @@ use crate::uapi::signal::MContextT; +pub fn init_boot_trap() {} + +pub fn init() {} + /// Mock trap frame for host compilation #[repr(C)] #[derive(Debug, Clone, Copy)] diff --git a/os/src/arch/mod.rs b/os/src/arch/mod.rs index d31035cc..5a139ec8 100644 --- a/os/src/arch/mod.rs +++ b/os/src/arch/mod.rs @@ -84,6 +84,12 @@ pub fn enable_interrupts() { ArchImpl::enable_interrupts() } +/// 当前中断是否处于启用状态 +#[inline] +pub fn interrupts_enabled() -> bool { + ArchImpl::interrupts_enabled() +} + /// 禁用中断并返回之前的中断状态 #[inline] pub fn disable_interrupts() -> usize { diff --git a/os/src/arch/riscv/boot/mod.rs b/os/src/arch/riscv/boot/mod.rs index a3bdd090..5392bb84 100644 --- a/os/src/arch/riscv/boot/mod.rs +++ b/os/src/arch/riscv/boot/mod.rs @@ -7,12 +7,11 @@ global_asm!(include_str!("entry.S")); use crate::mm::address::UsizeConvert; use crate::{ - arch::{intr, platform, timer, trap}, + arch::{timer, trap}, earlyprintln, - kernel::{self, NUM_CPU, current_cpu, time}, - mm, pr_debug, pr_err, pr_info, pr_warn, + kernel::{self, NUM_CPU, current_cpu}, + pr_debug, pr_err, pr_info, pr_warn, sync::PreemptGuard, - test::run_early_tests, }; /// 已上线 CPU 位掩码 @@ -31,26 +30,23 @@ pub extern "C" fn secondary_debug_entry(hartid: usize) { /// RISC-V 主核启动入口 pub fn main(hartid: usize) { - // 提前设置 tp 指向一个临时值,确保 mm::init 期间 IntrGuard::new() 调用 - // CPU::id() 时 tp 已指向有效内存(cpuid = 0)。后续在 CPUS 初始化完成后 - // 会重新指向真正的 Cpu 结构体。 + let mut ops = kernel::boot::PrimaryBootOps::new("RISC-V", "Hart"); + ops.before_clear_bss = setup_boot_cpu_dummy; + ops.after_mm_init = setup_boot_cpu; + ops.after_time_init = boot_secondaries; + kernel::boot::run_primary_boot(hartid, ops); +} + +fn setup_boot_cpu_dummy(_hartid: usize) { { static BOOT_CPU_DUMMY: usize = 0; unsafe { core::arch::asm!("mv tp, {}", in(reg) &raw const BOOT_CPU_DUMMY); } } +} - kernel::boot::clear_bss(); - - run_early_tests(); - - earlyprintln!("[Boot] Hello, world!"); - earlyprintln!("[Boot] RISC-V Hart {} is up!", hartid); - - let kernel_space = mm::init(); - - // 初始化 CPUS 并设置 tp 指向 CPU 0 +fn setup_boot_cpu(_hartid: usize) { { use crate::kernel::CPUS; let cpu_ptr = CPUS.get_of(0) as *const _ as usize; @@ -59,48 +55,13 @@ pub fn main(hartid: usize) { } earlyprintln!("[Boot] Initialized CPUS, tp = 0x{:x}", cpu_ptr); } +} - // 激活内核地址空间 - { - let _guard = PreemptGuard::new(); - current_cpu().switch_space(kernel_space); - earlyprintln!("[Boot] Activated kernel address space"); - } - - #[cfg(test)] - crate::test_main(); - - // 早期引导陷阱(覆盖平台初始化窗口) - trap::init_boot_trap(); - platform::init(); - time::init(); - - // 启动从核 +fn boot_secondaries(_hartid: usize) { let num_cpus = unsafe { NUM_CPU }; if num_cpus > 1 { boot_secondary_cpus(num_cpus); } - - timer::init(); - - // 创建 idle 并设为当前任务(sscratch 就绪) - let idle = kernel::boot::create_idle_task(0, kernel::boot::idle_loop); - { - let _guard = PreemptGuard::new(); - current_cpu().idle_task = Some(idle.clone()); - current_cpu().switch_task(idle); - } - - // 完整陷阱处理(sscratch 已有效) - trap::init(); - - // 创建 init 任务并入队(中断仍禁用,避免竞争) - kernel::boot::rest_init(); - - // 启用中断并进入 idle 循环 - // 时钟中断触发后调度器自动选中 init 并切换上下文 - unsafe { intr::enable_interrupts() }; - kernel::boot::idle_loop(); } // SBI HSM 从核入口(在 entry.S 中定义) @@ -141,7 +102,7 @@ pub extern "C" fn secondary_start(hartid: usize) -> ! { let root_ppn = kernel_space.lock().root_ppn(); { let _guard = PreemptGuard::new(); - current_cpu().switch_space(kernel_space.clone()); + current_cpu().switch_space(kernel_space); } pr_info!( "[SMP] CPU {} switched to global kernel space, root PPN: 0x{:x}", @@ -158,9 +119,7 @@ pub extern "C" fn secondary_start(hartid: usize) -> ! { // 完整陷阱 + 定时器 + 中断 trap::init(); timer::init(); - unsafe { - intr::enable_interrupts(); - } + crate::arch::enable_interrupts(); pr_debug!("[SMP] CPU {} entering idle loop", hartid); kernel::boot::idle_loop(); diff --git a/os/src/arch/riscv/cpu_ops.rs b/os/src/arch/riscv/cpu_ops.rs index 0be1654b..472d9d35 100644 --- a/os/src/arch/riscv/cpu_ops.rs +++ b/os/src/arch/riscv/cpu_ops.rs @@ -84,6 +84,11 @@ impl CpuOps for Riscv64 { unsafe { sstatus::set_sie() }; } + #[inline] + fn interrupts_enabled() -> bool { + sstatus::read().sie() + } + #[inline] fn interrupt_was_enabled(flags: usize) -> bool { flags & crate::arch::constant::SSTATUS_SIE != 0 diff --git a/os/src/arch/riscv/kernel/task.rs b/os/src/arch/riscv/kernel/task.rs index 850a777c..60e09b75 100644 --- a/os/src/arch/riscv/kernel/task.rs +++ b/os/src/arch/riscv/kernel/task.rs @@ -217,6 +217,24 @@ pub unsafe fn forkret_restore(tf_ptr: *mut crate::arch::trap::TrapFrame, _is_ker unsafe { crate::arch::trap::restore(&*tf_ptr) }; } +/// Initialize the trap frame used to enter a kernel task. +pub unsafe fn init_kernel_trap_frame( + tf_ptr: *mut crate::arch::trap::TrapFrame, + entry: usize, + terminal: usize, + kernel_sp: usize, +) { + unsafe { + core::ptr::write(tf_ptr, crate::arch::trap::TrapFrame::zero_init()); + (*tf_ptr).set_kernel_trap_frame(entry, terminal, kernel_sp); + let cpu_ptr = { + let _guard = crate::sync::PreemptGuard::new(); + crate::kernel::current_cpu() as *const _ as usize + }; + crate::arch::trap::set_trap_frame_cpu_ptr(tf_ptr, cpu_ptr); + } +} + /// Final architecture-specific preparation before restoring to user mode. pub unsafe fn prepare_user_restore( tfp: *mut crate::arch::trap::TrapFrame, diff --git a/os/src/kernel/boot.rs b/os/src/kernel/boot.rs index 40359576..f3d8b15f 100644 --- a/os/src/kernel/boot.rs +++ b/os/src/kernel/boot.rs @@ -6,15 +6,19 @@ use alloc::sync::Arc; use crate::{ - arch::CpuOps, + arch::{CpuOps, platform, timer, trap}, + earlyprintln, ipc::{SignalHandlerTable, SignalPending}, kernel::{ - FsStruct, Scheduler, TASK_MANAGER, TaskManagerTrait, TaskStruct, current_memory_space, - current_task, kernel_execve, kthread_spawn, kworker, scheduler_of, sleep_task, yield_task, + FsStruct, Scheduler, TASK_MANAGER, TaskManagerTrait, TaskStruct, current_cpu, + current_memory_space, current_task, kernel_execve, kthread_spawn, kworker, scheduler_of, + sleep_task, time, yield_task, }, + mm, mm::frame_allocator::{alloc_contig_frames, alloc_frame}, pr_err, pr_info, pr_warn, - sync::SpinLock, + sync::{PreemptGuard, SpinLock}, + test::run_early_tests, uapi::{ resource::{INIT_RLIMITS, RlimitStruct}, signal::SignalFlags, @@ -23,19 +27,95 @@ use crate::{ vfs::{create_stdio_files, fd_table::FDTable, get_root_dentry}, }; +fn noop_boot_hook(_hartid: usize) {} + +/// 架构主核启动差异点。 +/// +/// 架构代码只填充必要 hook,公共启动顺序由 `run_primary_boot()` 统一维护。 +pub struct PrimaryBootOps { + pub arch_name: &'static str, + pub cpu_label: &'static str, + pub before_clear_bss: fn(usize), + pub after_clear_bss: fn(usize), + pub after_mm_init: fn(usize), + pub after_time_init: fn(usize), +} + +impl PrimaryBootOps { + pub const fn new(arch_name: &'static str, cpu_label: &'static str) -> Self { + Self { + arch_name, + cpu_label, + before_clear_bss: noop_boot_hook, + after_clear_bss: noop_boot_hook, + after_mm_init: noop_boot_hook, + after_time_init: noop_boot_hook, + } + } +} + +/// 架构无关的主核启动流程。 +pub fn run_primary_boot(hartid: usize, ops: PrimaryBootOps) -> ! { + (ops.before_clear_bss)(hartid); + + clear_bss(); + + (ops.after_clear_bss)(hartid); + + run_early_tests(); + + earlyprintln!("[Boot] Hello, world!"); + earlyprintln!( + "[Boot] {} {} {} is up!", + ops.arch_name, + ops.cpu_label, + hartid + ); + + let kernel_space = mm::init(); + + (ops.after_mm_init)(hartid); + + { + let _guard = PreemptGuard::new(); + current_cpu().switch_space(kernel_space); + earlyprintln!("[Boot] Activated kernel address space"); + } + + #[cfg(test)] + crate::test_main(); + + trap::init_boot_trap(); + platform::init(); + time::init(); + + (ops.after_time_init)(hartid); + + timer::init(); + + let idle = create_idle_task(0, idle_loop); + { + let _guard = PreemptGuard::new(); + current_cpu().idle_task = Some(idle.clone()); + current_cpu().switch_task(idle); + } + + trap::init(); + rest_init(); + + crate::arch::enable_interrupts(); + idle_loop(); +} + /// 架构无关的 idle 循环 /// /// 确保中断开启后持续等待中断,唤醒后立即重新等待。 /// 使用 `ArchImpl::halt()` 执行具体的 halt 指令(wfi / idle 0)。 pub fn idle_loop() -> ! { - loop { - if !crate::arch::intr::are_interrupts_enabled() { - unsafe { - crate::arch::intr::enable_interrupts(); - } - } - crate::arch::ArchImpl::halt(); + if !crate::arch::interrupts_enabled() { + crate::arch::enable_interrupts(); } + crate::arch::ArchImpl::halt(); } /// 清除 BSS 段 @@ -96,12 +176,16 @@ pub fn rest_init() { fs, ); - let tf = task + let task_frame = task .trap_frame_ptr .load(core::sync::atomic::Ordering::SeqCst); unsafe { - core::ptr::write(tf, crate::arch::trap::TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(init as usize, 0, task.kstack_base.as_usize()); + crate::arch::kernel::task::init_kernel_trap_frame( + task_frame, + init as usize, + 0, + task.kstack_base.as_usize(), + ); } task.memory_space = Some(current_memory_space()); @@ -179,12 +263,16 @@ fn create_kthreadd() { Arc::new(SpinLock::new(fs)), ); - let tf = task + let task_frame = task .trap_frame_ptr .load(core::sync::atomic::Ordering::SeqCst); unsafe { - core::ptr::write(tf, crate::arch::trap::TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(kthreadd as usize, 0, task.kstack_base.as_usize()); + crate::arch::kernel::task::init_kernel_trap_frame( + task_frame, + kthreadd as usize, + 0, + task.kstack_base.as_usize(), + ); } let task = task.into_shared(); TASK_MANAGER.lock().add_task(task.clone()); @@ -217,12 +305,16 @@ pub fn create_idle_task(cpu_id: usize, idle_fn: fn() -> !) -> crate::kernel::Sha Arc::new(SpinLock::new(FsStruct::new(None, None))), ); - let tf = task + let task_frame = task .trap_frame_ptr .load(core::sync::atomic::Ordering::SeqCst); unsafe { - core::ptr::write(tf, crate::arch::trap::TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(idle_fn as usize, 0, task.kstack_base.as_usize()); + crate::arch::kernel::task::init_kernel_trap_frame( + task_frame, + idle_fn as usize, + 0, + task.kstack_base.as_usize(), + ); } task.on_cpu = Some(cpu_id); diff --git a/os/src/kernel/syscall/fs.rs b/os/src/kernel/syscall/fs.rs index a6dd7f0f..73812ce1 100644 --- a/os/src/kernel/syscall/fs.rs +++ b/os/src/kernel/syscall/fs.rs @@ -3,7 +3,6 @@ use core::ffi::c_char; use crate::arch::Arch; -use alloc::string::ToString; use crate::{ kernel::{ @@ -109,7 +108,7 @@ pub fn ftruncate(fd: usize, length: i64) -> isize { pub fn openat(dirfd: i32, pathname: *const c_char, flags: u32, mode: u32) -> isize { // 解析路径字符串 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -187,7 +186,7 @@ pub fn openat(dirfd: i32, pathname: *const c_char, flags: u32, mode: u32) -> isi pub fn mkdirat(dirfd: i32, pathname: *const c_char, mode: u32) -> isize { // 解析路径 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -217,7 +216,7 @@ pub fn mkdirat(dirfd: i32, pathname: *const c_char, mode: u32) -> isize { pub fn unlinkat(dirfd: i32, pathname: *const c_char, flags: u32) -> isize { // 解析路径 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -276,7 +275,7 @@ pub fn unlinkat(dirfd: i32, pathname: *const c_char, flags: u32) -> isize { pub fn chdir(path: *const c_char) -> isize { // 解析路径 let path_str = match get_path_safe(path as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -469,7 +468,7 @@ pub fn statfs(path: *const c_char, buf: *mut LinuxStatFs) -> isize { // 解析路径字符串 let path_str = match get_path_safe(path as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -523,7 +522,7 @@ pub fn statfs(path: *const c_char, buf: *mut LinuxStatFs) -> isize { pub fn faccessat(dirfd: i32, pathname: *const c_char, mode: i32, flags: u32) -> isize { // 解析路径字符串 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -604,7 +603,7 @@ pub fn readlinkat(dirfd: i32, pathname: *const c_char, buf: *mut u8, bufsiz: usi // 解析路径字符串 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -654,7 +653,7 @@ pub fn newfstatat(dirfd: i32, pathname: *const c_char, statbuf: *mut Stat, flags // 解析路径 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -710,7 +709,7 @@ pub fn statx( // 解析路径 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -762,7 +761,7 @@ pub fn statx( pub fn utimensat(dirfd: i32, pathname: *const c_char, times: *const TimeSpec, flags: u32) -> isize { // 解析路径 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -855,7 +854,7 @@ pub fn renameat2( // 解析旧路径 let old_path_str = match get_path_safe(oldpath as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -863,7 +862,7 @@ pub fn renameat2( // 解析新路径 let new_path_str = match get_path_safe(newpath as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -1183,7 +1182,7 @@ pub fn mount( // 解析目标路径 let target_str = match get_path_safe(target as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -1192,7 +1191,7 @@ pub fn mount( // 解析 source (可能为空) let source_str = if !source.is_null() { match get_path_safe(source as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -1204,7 +1203,7 @@ pub fn mount( // 解析 filesystemtype (可能为空) let fstype_str = if !filesystemtype.is_null() { match get_path_safe(filesystemtype as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -1362,7 +1361,7 @@ pub fn umount2(target: *const c_char, _flags: i32) -> isize { // 解析目标路径 let target_str = match get_path_safe(target as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -1444,7 +1443,7 @@ pub fn fchownat(dirfd: i32, pathname: *const c_char, owner: u32, group: u32, fla // 解析路径字符串 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -1512,7 +1511,7 @@ pub fn fchmodat(dirfd: i32, pathname: *const c_char, mode: u32, flags: u32) -> i // 解析路径字符串 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return -(EINVAL as isize); } @@ -1556,7 +1555,7 @@ pub fn fchmodat(dirfd: i32, pathname: *const c_char, mode: u32, flags: u32) -> i pub fn mknodat(dirfd: i32, pathname: *const c_char, mode: u32, dev: u64) -> isize { // 安全地读取路径字符串 let path_str = match get_path_safe(pathname as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -1607,7 +1606,7 @@ pub fn mknodat(dirfd: i32, pathname: *const c_char, mode: u32, dev: u64) -> isiz pub fn symlinkat(target: *const c_char, newdirfd: i32, linkpath: *const c_char) -> isize { // 解析 target 路径 let target_str = match get_path_safe(target as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } @@ -1615,7 +1614,7 @@ pub fn symlinkat(target: *const c_char, newdirfd: i32, linkpath: *const c_char) // 解析 linkpath 路径 let link_str = match get_path_safe(linkpath as usize) { - Ok(s) => s.to_string(), + Ok(s) => s, Err(_) => { return FsError::InvalidArgument.to_errno(); } diff --git a/os/src/kernel/syscall/io.rs b/os/src/kernel/syscall/io.rs index f4c4fa60..641ee58a 100644 --- a/os/src/kernel/syscall/io.rs +++ b/os/src/kernel/syscall/io.rs @@ -10,6 +10,13 @@ use crate::util::user_buffer::{ }; use crate::vfs::File; +fn empty_iovec() -> IoVec { + IoVec { + iov_base: core::ptr::null_mut(), + iov_len: 0, + } +} + /// 向文件描述符写入数据 pub fn write(fd: usize, buf: *const u8, count: usize) -> isize { loop { @@ -108,9 +115,8 @@ pub fn readv(fd: usize, iov: *const IoVec, iovcnt: usize) -> isize { } // 读取 iovec 数组 - let mut iovec_array = alloc::vec::Vec::::with_capacity(iovcnt); + let mut iovec_array = alloc::vec![empty_iovec(); iovcnt]; unsafe { - iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, @@ -178,9 +184,8 @@ pub fn writev(fd: usize, iov: *const IoVec, iovcnt: usize) -> isize { return -(EFAULT as isize); } - let mut iovec_array = alloc::vec::Vec::::with_capacity(iovcnt); + let mut iovec_array = alloc::vec![empty_iovec(); iovcnt]; unsafe { - iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, @@ -326,9 +331,8 @@ pub fn preadv(fd: usize, iov: *const IoVec, iovcnt: usize, offset: i64) -> isize Err(e) => return e.to_errno(), }; - let mut iovec_array = alloc::vec::Vec::::with_capacity(iovcnt); + let mut iovec_array = alloc::vec![empty_iovec(); iovcnt]; unsafe { - iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, @@ -404,9 +408,8 @@ pub fn pwritev(fd: usize, iov: *const IoVec, iovcnt: usize, offset: i64) -> isiz Err(e) => return e.to_errno(), }; - let mut iovec_array = alloc::vec::Vec::::with_capacity(iovcnt); + let mut iovec_array = alloc::vec![empty_iovec(); iovcnt]; unsafe { - iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, @@ -558,6 +561,14 @@ pub struct PollFd { pub revents: i16, } +fn empty_pollfd() -> PollFd { + PollFd { + fd: 0, + events: 0, + revents: 0, + } +} + /// poll 事件标志 pub const POLLIN: i16 = 0x0001; pub const POLLOUT: i16 = 0x0004; @@ -612,9 +623,8 @@ fn poll_with_timeout( { let size = nfds * core::mem::size_of::(); - let mut pollfds_buf = alloc::vec::Vec::::with_capacity(nfds); + let mut pollfds_buf = alloc::vec![empty_pollfd(); nfds]; unsafe { - pollfds_buf.set_len(nfds); crate::arch::ArchImpl::copy_from_user( crate::arch::address::UA::from_usize(fds), pollfds_buf.as_mut_ptr() as *mut u8, diff --git a/os/src/kernel/task/ktask.rs b/os/src/kernel/task/ktask.rs index 34d6a0bb..b26d4c3b 100644 --- a/os/src/kernel/task/ktask.rs +++ b/os/src/kernel/task/ktask.rs @@ -9,7 +9,7 @@ use alloc::string::ToString; use alloc::sync::Arc; use crate::{ - arch::{intr::disable_interrupts, trap::restore}, + arch::{disable_interrupts, trap::restore}, kernel::{ TaskState, cpu::current_cpu, @@ -78,18 +78,12 @@ pub fn kthread_spawn(entry_point: fn()) -> u32 { let tf = task.trap_frame_ptr.load(Ordering::SeqCst); // SAFETY: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效 unsafe { - // 先初始化 TrapFrame 为全 0 - core::ptr::write(tf, crate::arch::trap::TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame( + crate::arch::kernel::task::init_kernel_trap_frame( + tf, entry_point as usize, super::terminate_task as usize, task.kstack_base.as_usize(), ); - let cpu_ptr = { - let _guard = crate::sync::PreemptGuard::new(); - crate::kernel::current_cpu() as *const _ as usize - }; - crate::arch::trap::set_trap_frame_cpu_ptr(tf, cpu_ptr); } let tid = task.tid; let task = task.into_shared(); @@ -191,7 +185,7 @@ pub fn kernel_execve(path: &str, argv: &[&str], envp: &[&str]) -> ! { // execve伪造进程上下文用的trapframe和当前进程的是同一个 // 这时候发生中断会破坏创建到一半/创建好的的上下文 // 不必显式恢复中断,它会在restore中由sret指令自动恢复 - unsafe { disable_interrupts() }; + disable_interrupts(); { let mut t = task.lock(); t.exe_path = Some(path.to_string());