diff --git a/os/.cargo/config.toml b/os/.cargo/config.toml index 7131a95a..30612029 100644 --- a/os/.cargo/config.toml +++ b/os/.cargo/config.toml @@ -3,8 +3,12 @@ target = "riscv64gc-unknown-none-elf" # target = "loongarch64-unknown-none" [unstable] -build-std = ["core", "compiler_builtins", "alloc"] -build-std-features = ["compiler-builtins-mem"] +# build-std 与 cargo test 冲突会导致 "duplicate lang item" 错误 +# riscv64gc-unknown-none-elf 的预编译 target 库已包含所需的 core/alloc/compiler_builtins +# 如需 build-std(例如启用 compiler-builtins-mem),可通过命令行覆盖: +# cargo build -Zbuild-std=core,compiler_builtins,alloc -Zbuild-std-features=compiler-builtins-mem +# build-std = ["core", "compiler_builtins", "alloc"] +# build-std-features = ["compiler-builtins-mem"] [target.riscv64gc-unknown-none-elf] rustflags = [ diff --git a/os/build.rs b/os/build.rs index 04764900..77208f74 100644 --- a/os/build.rs +++ b/os/build.rs @@ -114,34 +114,21 @@ fn main() { println!("cargo:rustc-env=SIMPLE_FS_IMAGE={}", img_path.display()); // 步骤 3: 创建 ext4 镜像 - // 检测是否为测试模式 - // 注意: CARGO_CFG_TEST 只在运行测试时设置,编译时不会设置 - // 因此我们检查 TEST 环境变量 (由 Makefile 传递) 或检查是否有测试相关的 cfg - let is_test = env::var("TEST").is_ok() - || env::var("CARGO_CFG_TEST").is_ok() - || env::var("PROFILE").map(|p| p == "test").unwrap_or(false); - - // 3.1: 创建用于 include_bytes! 嵌入的镜像 + // EXT4_FS_IMAGE 仅被 #[cfg(test)] 代码通过 include_bytes! 使用, + // 因此始终创建真实镜像也不会影响普通构建的二进制体积。 + // 不再依赖环境变量检测 is_test,因为 cargo test 直接运行时 + // build.rs 运行在库编译阶段(非 test cfg 阶段),CARGO_CFG_TEST 不可用。 let ext4_embed_img = PathBuf::from(&out_dir).join("ext4_test.img"); - if is_test { - // 测试模式: 创建 8MB 镜像用于测试 - // 只有在测试模式下才需要这个环境变量 + if !ext4_embed_img.exists() { println!("cargo:warning=[build.rs] Creating ext4 test image for embedding (8MB)..."); create_ext4_test_image(&ext4_embed_img); - println!("cargo:rustc-env=EXT4_FS_IMAGE={}", ext4_embed_img.display()); - } else { - // IDE 修复: 即使不在测试模式下,也需要定义 EXT4_FS_IMAGE 环境变量 - // 这里的代码会被 rust-analyzer 分析,如果缺少环境变量会报错 - // 我们创建一个空的伪文件来满足 include_bytes! 的需求 - let dummy_img = PathBuf::from(&out_dir).join("ext4_test_dummy.img"); - if !dummy_img.exists() { - let _ = fs::write(&dummy_img, []); - } - println!( - "cargo:warning=[build.rs] Skipping real test image creation (using dummy for IDE)" - ); - println!("cargo:rustc-env=EXT4_FS_IMAGE={}", dummy_img.display()); } + println!("cargo:rustc-env=EXT4_FS_IMAGE={}", ext4_embed_img.display()); + + // 检测是否为测试模式(用于跳过 3.2 的运行时镜像生成) + let is_test = env::var("TEST").is_ok() + || env::var("CARGO_CFG_TEST").is_ok() + || env::var("PROFILE").map(|p| p == "test").unwrap_or(false); // 3.2: 非测试模式下创建完整的运行时镜像(仅目标架构) if !is_test && is_target_arch { diff --git a/os/src/arch/abi.rs b/os/src/arch/abi.rs new file mode 100644 index 00000000..81bca7c1 --- /dev/null +++ b/os/src/arch/abi.rs @@ -0,0 +1,88 @@ +//! Architecture-specific ABI constants and ELF relocation classification. + +/// RISC-V ELF machine number. +pub const EM_RISCV: u16 = 243; +/// LoongArch ELF machine number. +pub const EM_LOONGARCH: u16 = 258; + +/// Absolute 64-bit relocation. +#[derive(Debug, Clone, Copy, PartialEq, Eq)] +pub enum RelocationKind { + /// Write `load_bias + addend`. + Relative, + /// Write `load_bias + symbol_value + addend`. + Absolute64, +} + +#[cfg(target_arch = "riscv64")] +const ELF_MACHINE: u16 = EM_RISCV; +#[cfg(target_arch = "loongarch64")] +const ELF_MACHINE: u16 = EM_LOONGARCH; +#[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] +const ELF_MACHINE: u16 = EM_RISCV; + +#[cfg(target_arch = "loongarch64")] +const R_ABS64: u32 = 2; +#[cfg(target_arch = "loongarch64")] +const R_RELATIVE: u32 = 3; + +#[cfg(not(target_arch = "loongarch64"))] +const R_ABS64: u32 = 2; +#[cfg(not(target_arch = "loongarch64"))] +const R_RELATIVE: u32 = 3; + +/// Architecture-specific `getifaddrs` syscall number used by this kernel. +#[cfg(target_arch = "loongarch64")] +pub const SYS_GETIFADDRS: usize = 1000; +/// Architecture-specific `getifaddrs` syscall number used by this kernel. +#[cfg(not(target_arch = "loongarch64"))] +pub const SYS_GETIFADDRS: usize = 500; + +/// Returns true if the ELF machine number matches the active target. +pub fn is_supported_elf_machine(machine: u16) -> bool { + machine == ELF_MACHINE +} + +/// Classifies an architecture-specific relocation type. +pub fn classify_relocation(r_type: u32) -> Option { + match r_type { + R_RELATIVE => Some(RelocationKind::Relative), + R_ABS64 => Some(RelocationKind::Absolute64), + _ => None, + } +} + +/// Resolves a relocation value once its optional symbol value is known. +pub fn resolve_relocation_value( + kind: RelocationKind, + load_bias: usize, + symbol_value: usize, + addend: isize, +) -> usize { + let base = match kind { + RelocationKind::Relative => load_bias, + RelocationKind::Absolute64 => load_bias + symbol_value, + }; + (base as isize + addend) as usize +} + +/// Static `/proc/cpuinfo` content for the active target. +pub fn proc_cpuinfo_bytes() -> &'static [u8] { + #[cfg(target_arch = "riscv64")] + { + b"processor\t: 0\n\ +hart\t\t: 0\n\ +isa\t\t: rv64imafdcsu\n\ +mmu\t\t: sv39\n\ +uarch\t\t: qemu,virt\n\n" + } + #[cfg(target_arch = "loongarch64")] + { + b"processor\t: 0\n\ +arch\t\t: loongarch64\n\n" + } + #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] + { + b"processor\t: 0\narch\t\t: mock\n\n" + } +} diff --git a/os/src/arch/address.rs b/os/src/arch/address.rs index 1984d41b..1a4274e0 100644 --- a/os/src/arch/address.rs +++ b/os/src/arch/address.rs @@ -16,10 +16,7 @@ mod sealed { } /// 内存地址种类标记 trait(sealed — 外部无法实现) -pub trait MemKind: - sealed::Sealed + Ord + Clone + Copy + PartialEq + Eq + core::fmt::Debug -{ -} +pub trait MemKind: sealed::Sealed + Ord + Clone + Copy + PartialEq + Eq + core::fmt::Debug {} // ============================================================================ // 地址种类标记类型 @@ -77,11 +74,6 @@ pub type VA = Address; /// 无类型标记的用户空间地址 pub type UA = Address; -/// 带类型标记的物理地址指针 -pub type TPA = Address; -/// 带类型标记的虚拟地址指针 -pub type TVA = Address; - // ============================================================================ // Address 基本方法 // ============================================================================ @@ -138,18 +130,18 @@ impl Address { } /// 增加字节偏移 - pub fn add(self, offset: usize) -> Self { + pub fn add_bytes(self, offset: usize) -> Self { Self::from_usize(self.inner + offset) } /// 减去字节偏移 - pub fn sub(self, offset: usize) -> Self { + pub fn sub_bytes(self, offset: usize) -> Self { Self::from_usize(self.inner - offset) } /// 增加页数 pub fn add_pages(self, count: usize) -> Self { - self.add(count * crate::config::PAGE_SIZE) + self.add_bytes(count * crate::config::PAGE_SIZE) } /// 计算与另一地址的差值 @@ -168,8 +160,8 @@ impl Address { /// # Safety /// /// 裸物理地址访问需要显式承诺:调用者必须确保物理地址有效且已映射。 - pub unsafe fn as_ptr(&self) -> *const T { - self.inner as *const T + pub unsafe fn as_ptr(&self) -> *const U { + self.inner as *const U } /// 将物理地址转换为可变裸指针 @@ -178,8 +170,8 @@ impl Address { /// /// 裸物理地址访问需要显式承诺:调用者必须确保物理地址有效且已映射, /// 并且没有其他活跃引用指向同一内存。 - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - self.inner as *mut T + pub unsafe fn as_mut_ptr(&mut self) -> *mut U { + self.inner as *mut U } } @@ -191,13 +183,13 @@ impl Address { /// 将虚拟地址转换为裸指针(只读) /// /// 虚拟地址已通过 MMU 映射,因此此操作不是 unsafe。 - pub fn as_ptr(&self) -> *const T { - self.inner as *const T + pub fn as_ptr(&self) -> *const U { + self.inner as *const U } /// 将虚拟地址转换为可变裸指针 - pub fn as_mut_ptr(&mut self) -> *mut T { - self.inner as *mut T + pub fn as_mut_ptr(&mut self) -> *mut U { + self.inner as *mut U } /// 将虚拟地址转换为不可变引用 @@ -205,8 +197,8 @@ impl Address { /// # Safety /// /// 调用者必须确保地址指向的内存已初始化且未被其他可变引用借用。 - pub unsafe fn as_ref<'a>(&self) -> &'a T { - unsafe { &*(self.inner as *const T) } + pub unsafe fn as_ref<'a, U>(&self) -> &'a U { + unsafe { &*(self.inner as *const U) } } /// 将虚拟地址转换为可变引用 @@ -214,8 +206,20 @@ impl Address { /// # Safety /// /// 调用者必须确保地址指向的内存已初始化且无其他活跃引用。 - pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T { - unsafe { &mut *(self.inner as *mut T) } + pub unsafe fn as_mut<'a, U>(&mut self) -> &'a mut U { + unsafe { &mut *(self.inner as *mut U) } + } +} + +impl Address { + /// 从一个不可变引用创建虚拟地址。 + pub fn from_ref(r: &T) -> Self { + Self::from_ptr(r as *const T) + } + + /// 从一个常量指针创建虚拟地址。 + pub fn from_ptr(p: *const T) -> Self { + Self::from_usize(p as usize) } } @@ -232,25 +236,6 @@ impl Address { } } -// ============================================================================ -// AddressTranslator — 跨地址空间转换 -// ============================================================================ - -/// 地址转换器 trait。 -/// -/// 只有通过 `Translator` 才能跨地址空间转换。 -/// -/// # 类型参数 -/// -/// * `T` - 要转换的地址携带的数据类型 -pub trait AddressTranslator: 'static + Send + Sync { - /// 虚拟地址 → 物理地址 - fn virt_to_phys(va: TVA) -> TPA; - - /// 物理地址 → 虚拟地址 - fn phys_to_virt(pa: TPA) -> TVA; -} - // ============================================================================ // unsafe impl Send/Sync // ============================================================================ diff --git a/os/src/arch/arch.rs b/os/src/arch/arch.rs index 75f13e7f..b0bf1950 100644 --- a/os/src/arch/arch.rs +++ b/os/src/arch/arch.rs @@ -1,21 +1,26 @@ //! Arch trait — 顶层架构抽象 //! //! 组合 `CpuOps + VirtualMemory`,并添加进程管理、信号处理、 -//! 用户/内核内存复制、系统信息、电源管理等高层操作。 +//! 用户/内核内存复制等高层 CPU/MMU 操作。 +//! +//! 平台级操作(控制台 I/O、电源管理、地址映射)已移至 [`crate::arch::platform::Platform`]。 //! //! 注意:此 trait 使用关联类型来避免直接引用内核数据结构, //! 确保架构层与内核其余部分的解耦。 -use crate::arch::cpu_ops::CpuOps; -use crate::arch::virtual_memory::VirtualMemory; +use crate::arch::{address::UA, cpu_ops::CpuOps, virtual_memory::VirtualMemory}; + /// 顶层架构抽象 trait。 /// /// 组合了 `CpuOps` 和 `VirtualMemory`,并添加了进程管理、信号处理、 -/// 用户/内核内存复制等高层架构特定操作。 +/// 用户/内核内存复制、时间、IPI 等架构级操作。 /// /// # 移植要点 /// /// 这是移植新架构时需要实现的第三个 trait(在 `CpuOps` 和 `VirtualMemory` 之后)。 +/// [`Platform`] 应同时实现以覆盖控制台、电源等平台操作。 +/// +/// [`Platform`]: crate::arch::platform::Platform pub trait Arch: CpuOps + VirtualMemory { /// 用户上下文类型(保存/恢复寄存器状态) type UserContext: Sized + Send + Sync + Clone; @@ -43,13 +48,13 @@ pub trait Arch: CpuOps + VirtualMemory { /// - `src` 必须是有效的用户空间虚拟地址 /// - `dst` 必须指向足够大的内核缓冲区 /// - `len` 字节必须在合法范围内 - unsafe fn copy_from_user(src: usize, dst: *mut u8, len: usize) -> Result<(), ()>; + unsafe fn copy_from_user(src: UA, dst: *mut u8, len: usize) -> Result<(), ()>; /// 尝试从用户空间复制数据(非阻塞版本,不处理缺页) /// /// # Safety /// 同上 - unsafe fn try_copy_from_user(src: usize, dst: *mut u8, len: usize) -> Result<(), ()>; + unsafe fn try_copy_from_user(src: UA, dst: *mut u8, len: usize) -> Result<(), ()>; /// 从内核空间复制数据到用户空间 /// @@ -58,23 +63,13 @@ pub trait Arch: CpuOps + VirtualMemory { /// - `dst` 必须是有效的用户空间虚拟地址 /// - `src` 必须指向有效内核数据 /// - `len` 字节必须在合法范围内 - unsafe fn copy_to_user(src: *const u8, dst: usize, len: usize) -> Result<(), ()>; + unsafe fn copy_to_user(src: *const u8, dst: UA, len: usize) -> Result<(), ()>; /// 从用户空间复制以 '\0' 结尾的字符串 /// /// # Safety /// 同上 - unsafe fn copy_strn_from_user(src: usize, dst: *mut u8, max_len: usize) -> Result; - - // ---- 控制台 I/O ---- - - /// 向调试控制台输出一个字节 - fn console_putchar(c: u8); - - /// 从调试控制台读取一个字节(非阻塞) - /// - /// 返回 `None` 表示没有可用输入。 - fn console_getchar() -> Option; + unsafe fn copy_strn_from_user(src: UA, dst: *mut u8, max_len: usize) -> Result; // ---- 系统信息 ---- @@ -84,11 +79,6 @@ pub trait Arch: CpuOps + VirtualMemory { /// CPU 核心数量 fn cpu_count() -> usize; - /// 获取内核命令行参数 - fn get_cmdline() -> Option; - - // ---- 电源管理 ---- - // ---- 任务切换辅助 ---- /// 任务切换时更新 trap frame 中的 CPU 指针 @@ -115,27 +105,4 @@ pub trait Arch: CpuOps + VirtualMemory { /// 向目标 CPU 发送重调度 IPI fn send_reschedule_ipi(target_cpu: usize); - - // ---- 地址翻译 ---- - - /// 物理地址 → 虚拟地址(直接映射区域) - fn paddr_to_vaddr(paddr: usize) -> usize { - paddr + Self::PAGE_OFFSET - } - - /// 虚拟地址 → 物理地址(直接映射区域) - /// - /// # Safety - /// 调用者需确保 `vaddr` 处于直接映射范围内。 - unsafe fn vaddr_to_paddr(vaddr: usize) -> usize { - vaddr - Self::PAGE_OFFSET - } - - // ---- 电源管理 ---- - - /// 关机,永不返回 - fn power_off() -> !; - - /// 重启,永不返回 - fn restart() -> !; } diff --git a/os/src/arch/arch_impl.rs b/os/src/arch/arch_impl.rs index bc1cf50c..c1323ad3 100644 --- a/os/src/arch/arch_impl.rs +++ b/os/src/arch/arch_impl.rs @@ -1,13 +1,11 @@ -//! Arch trait 实现生成宏 +//! Arch / Platform trait 实现生成宏 //! -//! 为不同架构生成 `VirtualMemory` 和 `Arch` 的通用方法实现。 -//! 两个架构的绝大多数方法完全相同,仅 `restart` 有架构差异。 +//! 为不同架构生成 `VirtualMemory`、`Arch` 和 `Platform` 的通用方法实现。 +//! 两个架构的绝大多数方法完全相同,可通过宏复用。 -/// 为指定架构生成 `VirtualMemory` impl 和 `Arch` impl 的通用方法。 -/// -/// `restart` 方法不在此宏中生成——每个架构需单独提供。 +/// 为指定架构生成 `VirtualMemory` impl 和 `Arch` impl。 #[macro_export] -macro_rules! impl_arch_common { +macro_rules! impl_arch { ($arch:ty, $process_space:ty, $kernel_space:ty) => { use $crate::arch::virtual_memory::VirtualMemory; use $crate::mm::address::Ppn; @@ -39,21 +37,18 @@ macro_rules! impl_arch_common { ctx } - unsafe fn context_switch( - old: *mut Self::UserContext, - new: *const Self::UserContext, - ) { + unsafe fn context_switch(old: *mut Self::UserContext, new: *const Self::UserContext) { unsafe { kernel::switch(old, new) }; } unsafe fn copy_from_user( - src: usize, + src: $crate::arch::address::UA, dst: *mut u8, len: usize, ) -> Result<(), ()> { - if src > constant::USER_TOP - || src.checked_add(len).ok_or(())? > constant::USER_TOP + 1 - { + let src = src.as_usize(); + validate_user_copy_range(src, len, false)?; + if len != 0 && dst.is_null() { return Err(()); } let _guard = trap::SumGuard::new(); @@ -62,7 +57,7 @@ macro_rules! impl_arch_common { } unsafe fn try_copy_from_user( - src: usize, + src: $crate::arch::address::UA, dst: *mut u8, len: usize, ) -> Result<(), ()> { @@ -71,12 +66,12 @@ macro_rules! impl_arch_common { unsafe fn copy_to_user( src: *const u8, - dst: usize, + dst: $crate::arch::address::UA, len: usize, ) -> Result<(), ()> { - if dst > constant::USER_TOP - || dst.checked_add(len).ok_or(())? > constant::USER_TOP + 1 - { + let dst = dst.as_usize(); + validate_user_copy_range(dst, len, true)?; + if len != 0 && src.is_null() { return Err(()); } let _guard = trap::SumGuard::new(); @@ -85,18 +80,23 @@ macro_rules! impl_arch_common { } unsafe fn copy_strn_from_user( - src: usize, + src: $crate::arch::address::UA, dst: *mut u8, max_len: usize, ) -> Result { - if src > constant::USER_TOP { + let src = src.as_usize(); + if src < constant::USER_BASE || src > constant::USER_TOP { + return Err(()); + } + if max_len != 0 && dst.is_null() { return Err(()); } let _guard = trap::SumGuard::new(); let mut i = 0; while i < max_len { - let byte = - unsafe { core::ptr::read_volatile((src + i) as *const u8) }; + let cur = src.checked_add(i).ok_or(())?; + validate_user_copy_range(cur, 1, false)?; + let byte = unsafe { core::ptr::read_volatile(cur as *const u8) }; unsafe { *dst.add(i) = byte }; if byte == 0 { return Ok(i); @@ -131,6 +131,61 @@ macro_rules! impl_arch_common { constant::ARCH } + fn cpu_count() -> usize { + unsafe { $crate::kernel::NUM_CPU } + } + } + + fn validate_user_copy_range(start: usize, len: usize, write: bool) -> Result<(), ()> { + use $crate::mm::address::{PageNum, VA, Vpn}; + use $crate::mm::page_table::{PageTableInner, UniversalPTEFlag}; + + if len == 0 { + return Ok(()); + } + if start < constant::USER_BASE || start > constant::USER_TOP { + return Err(()); + } + let end = start.checked_add(len).ok_or(())?; + let last = end.checked_sub(1).ok_or(())?; + if last > constant::USER_TOP { + return Err(()); + } + + let space = $crate::kernel::current_memory_space(); + let guard = space.lock(); + let mut cur = start; + while cur < end { + let vpn = Vpn::from_addr_floor(VA::from_usize(cur)); + let (_, _, flags) = guard.page_table().walk(vpn).map_err(|_| ())?; + let required = UniversalPTEFlag::VALID | UniversalPTEFlag::USER_ACCESSIBLE; + if !flags.contains(required) { + return Err(()); + } + if write { + if !flags.contains(UniversalPTEFlag::WRITEABLE) { + return Err(()); + } + } else if !flags.contains(UniversalPTEFlag::READABLE) { + return Err(()); + } + let next_page = (cur & !($crate::config::PAGE_SIZE - 1)) + .checked_add($crate::config::PAGE_SIZE) + .ok_or(())?; + cur = core::cmp::min(next_page, end); + } + Ok(()) + } + }; +} + +/// 为指定架构生成 `Platform` impl。 +/// +/// 此宏依赖 `lib` 和 `device` 模块提供底层实现。 +#[macro_export] +macro_rules! impl_platform { + ($arch:ty) => { + impl $crate::arch::plat::Platform for $arch { fn console_putchar(c: u8) { lib::console_putchar(c as usize); } @@ -144,10 +199,6 @@ macro_rules! impl_arch_common { } } - fn cpu_count() -> usize { - unsafe { $crate::kernel::NUM_CPU } - } - fn get_cmdline() -> Option { Some($crate::device::CMDLINE.read().clone()) } diff --git a/os/src/arch/loongarch/boot/mod.rs b/os/src/arch/loongarch/boot/mod.rs index 637a8c81..fd64f1a4 100644 --- a/os/src/arch/loongarch/boot/mod.rs +++ b/os/src/arch/loongarch/boot/mod.rs @@ -1,271 +1,21 @@ //! LoongArch64 架构相关的启动代码 -use core::{ - arch::{asm, global_asm}, - sync::atomic::Ordering, -}; +use core::arch::global_asm; -use alloc::sync::Arc; +global_asm!(include_str!("entry.S")); use crate::{ - arch::{ - intr, - mm::{paddr_to_vaddr, vaddr_to_paddr}, - platform, timer, trap, - }, + arch::{intr, platform, timer, trap}, earlyprintln, - ipc::{SignalHandlerTable, SignalPending}, - kernel::{ - FsStruct, Scheduler, TASK_MANAGER, TaskManagerTrait, TaskStruct, current_cpu, current_task, - kernel_execve, kthread_spawn, kworker, sleep_task_with_block, time, yield_task, - }, - mm::{ - self, - frame_allocator::{alloc_contig_frames, alloc_frame}, - }, - pr_err, pr_info, println, - sync::SpinLock, + kernel::{self, current_cpu, time}, + mm, + sync::PreemptGuard, test::run_early_tests, - uapi::{ - resource::{INIT_RLIMITS, RlimitStruct}, - signal::SignalFlags, - uts_namespace::UtsNamespace, - }, - vfs::{create_stdio_files, fd_table, get_root_dentry}, }; -global_asm!(include_str!("entry.S")); - -/// 内核的第一个任务启动函数 -/// 并且当这个函数结束时,应该切换到第一个任务的上下文 -pub fn rest_init() { - earlyprintln!("[Boot] rest_init: creating init task"); - // init 进程必须使用 TID/PID 1,不从分配器获取(分配器从 2 开始)。 - let tid = 1; - let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack"); - let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame"); - let fd_table = fd_table::FDTable::new(); - let (stdin, stdout, stderr) = create_stdio_files(); - fd_table - .install_at(0, stdin) - .expect("Failed to install stdin"); - fd_table - .install_at(1, stdout) - .expect("Failed to install stdout"); - fd_table - .install_at(2, stderr) - .expect("Failed to install stderr"); - let cwd = get_root_dentry().ok(); - let root = cwd.clone(); - let fs = Arc::new(SpinLock::new(FsStruct::new(cwd, root))); - let mut task = TaskStruct::ktask_create( - tid, - tid, - 0, - TaskStruct::empty_children(), - kstack_tracker, - trap_frame_tracker, - Arc::new(SpinLock::new(SignalHandlerTable::new())), - SignalFlags::empty(), - Arc::new(SpinLock::new(SignalPending::empty())), - Arc::new(SpinLock::new(UtsNamespace::default())), - Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))), - Arc::new(fd_table), - fs, - ); // init 没有父任务 - - let tf = task.trap_frame_ptr.load(Ordering::SeqCst); - // Safety: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效 - unsafe { - core::ptr::write(tf, crate::arch::trap::TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(init as usize, 0, task.kstack_base); - } - - let ra = task.context.ra; - let sp = task.context.sp; - let ptr = task.trap_frame_ptr.load(Ordering::SeqCst); - // init 任务运行在 CPU 0 - task.on_cpu = Some(0); - let task = task.into_shared(); - - // 为 CPU0 创建 idle 任务,避免调度器在 runqueue 为空时 panic。 - // idle 任务不加入运行队列,但会作为兜底任务被切换运行。 - { - let _guard = crate::sync::PreemptGuard::new(); - let cpu = current_cpu(); - if cpu.idle_task.is_none() { - cpu.idle_task = Some(create_idle_task(0)); - } - } - - unsafe { - // KScratch0 <- TrapFrame 指针 - asm!("csrwr {0}, 0x30", in(reg) ptr as usize, options(nostack, preserves_flags)); - } - TASK_MANAGER.lock().add_task(task.clone()); - { - let _guard = crate::sync::PreemptGuard::new(); - current_cpu().switch_task(task); - } - - earlyprintln!("[Boot] rest_init: switching to init"); - - // 切入 kinit:设置 sp 并跳到 ra;此调用不返回 - // SAFETY: 在 Task 创建时已正确初始化 ra 和 sp - unsafe { - asm!( - "addi.d $sp, {sp}, 0", - "jirl $zero, {ra}, 0", - sp = in(reg) sp, - ra = in(reg) ra, - options(noreturn) - ); - } -} - -/// Idle 循环:等待中断;被定时器中断唤醒后由 trap/scheduler 决定是否调度。 -fn idle_loop() -> ! { - loop { - if !crate::arch::intr::are_interrupts_enabled() { - unsafe { crate::arch::intr::enable_interrupts() }; - } - unsafe { - core::arch::asm!("idle 0"); - } - } -} - -/// 为指定 CPU 创建 idle 任务(LoongArch 版本) -fn create_idle_task(cpu_id: usize) -> crate::kernel::SharedTask { - use crate::arch::trap::TrapFrame; - use crate::mm::frame_allocator::alloc_contig_frames; - use crate::vfs::fd_table::FDTable; - - // idle 任务从 TID 分配器正常分配(从 2 开始) - let tid = TASK_MANAGER.lock().allocate_tid(); - - // 分配最小资源 - let kstack_tracker = - alloc_contig_frames(1).expect("Failed to allocate kernel stack for idle task"); - let trap_frame_tracker = alloc_frame().expect("Failed to allocate trap frame for idle task"); - - // 创建最小化的内核线程 - let mut task = TaskStruct::ktask_create( - tid, - tid, // pid = tid - 0, // ppid = 0 (no parent) - TaskStruct::empty_children(), - kstack_tracker, - trap_frame_tracker, - Arc::new(SpinLock::new(SignalHandlerTable::new())), - SignalFlags::empty(), - Arc::new(SpinLock::new(SignalPending::empty())), - Arc::new(SpinLock::new(UtsNamespace::default())), - Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))), - Arc::new(FDTable::new()), - Arc::new(SpinLock::new(FsStruct::new(None, None))), - ); - - // 设置 TrapFrame 指向 idle_loop - let tf = task.trap_frame_ptr.load(Ordering::SeqCst); - unsafe { - core::ptr::write(tf, TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(idle_loop as usize, 0, task.kstack_base); - } - - task.on_cpu = Some(cpu_id); - let task = task.into_shared(); - TASK_MANAGER.lock().add_task(task.clone()); - task -} - -/// 内核的第一个任务 -/// PID = 1 -/// 负责进行剩余的初始化工作 -/// 创建 kthreadd 任务 -/// 并在一切结束后转化为第一个用户态任务 -fn init() { - earlyprintln!("[Init] entered init()"); - super::trap::init(); - - // 启用中断(在设置好 trap 处理与 KScratch0 之后) - unsafe { intr::enable_interrupts() }; - - create_kthreadd(); - - // 初始化 Ext4 文件系统(从真实块设备) - // 必须在任务上下文中进行,因为 VFS 需要 current_task() - if let Err(e) = crate::fs::init_ext4_from_block_device() { - pr_err!( - "[Init] Warning: Failed to initialize Ext4 filesystem: {:?}", - e - ); - pr_info!("[Init] Continuing without filesystem..."); - } - - // /dev(/proc,/sys,/tmp) 的挂载交给用户态 rcS: - // - rcS 会执行 `mount -t tmpfs none /dev` 等 - // - 内核在 mount("/dev") 的系统调用里会自动 init_dev() 创建设备节点 - kernel_execve("/sbin/init", &["/sbin/init"], &[]); -} - -/// 内核守护线程 -/// PID = 2 -/// 负责创建内核任务,回收僵尸任务等工作 -fn kthreadd() { - kthread_spawn(kworker); - loop { - // 休眠等待任务 - sleep_task_with_block(current_task(), true); - yield_task(); - } -} - -/// 创建内核守护线程 kthreadd -fn create_kthreadd() { - let tid = TASK_MANAGER.lock().allocate_tid(); - let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack"); - let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame"); - let (uts, rlimit, fd_table, fs) = { - let task = current_task(); - let t = task.lock(); - ( - t.uts_namespace.clone(), - t.rlimit.clone(), - t.fd_table.clone_table(), - t.fs.lock().clone(), - ) - }; - let task = TaskStruct::ktask_create( - tid, - tid, - 0, - TaskStruct::empty_children(), - kstack_tracker, - trap_frame_tracker, - Arc::new(SpinLock::new(SignalHandlerTable::new())), - SignalFlags::empty(), - Arc::new(SpinLock::new(SignalPending::empty())), - uts, - rlimit, - Arc::new(fd_table), - Arc::new(SpinLock::new(fs)), - ); // kthreadd 没有父任务 - - let tf = task.trap_frame_ptr.load(Ordering::SeqCst); - // Safety: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效 - unsafe { - core::ptr::write(tf, crate::arch::trap::TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(kthreadd as usize, 0, task.kstack_base); - } - let task = task.into_shared(); - TASK_MANAGER.lock().add_task(task.clone()); - task.lock().on_cpu = Some(0); - crate::kernel::scheduler_of(0).lock().add_task(task); -} - +/// LoongArch 主核启动入口 pub fn main(hartid: usize) { - clear_bss(); + kernel::boot::clear_bss(); // Enable base floating-point instructions (EUEN.FPE). Many LoongArch Linux-ABI // user programs are built with floating-point enabled and may execute FP @@ -279,83 +29,37 @@ pub fn main(hartid: usize) { let kernel_space = mm::init(); - // 激活内核地址空间并设置 current_memory_space(供 rest_init/current_memory_space 使用) + // 激活内核地址空间 { - let _guard = crate::sync::PreemptGuard::new(); + let _guard = PreemptGuard::new(); current_cpu().switch_space(kernel_space); } #[cfg(test)] crate::test_main(); - // 初始化工作 + // 早期引导陷阱(覆盖平台初始化窗口) trap::init_boot_trap(); platform::init(); time::init(); - earlyprintln!("[Boot] time::init finished"); timer::init(); - earlyprintln!("[Boot] timer::init finished"); - earlyprintln!("[Boot] entering rest_init"); - rest_init(); -} - -/// 清除 BSS 段,将其全部置零 -/// BSS 段包含所有未初始化的静态变量 -/// 在进入 Rust 代码之前调用此函数非常重要 -fn clear_bss() { - unsafe extern "C" { - fn sbss(); - fn ebss(); + // 创建 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); } - let sbss_paddr = unsafe { vaddr_to_paddr(sbss as usize) }; - let ebss_paddr = unsafe { vaddr_to_paddr(ebss as usize) }; + // 完整陷阱处理(KScratch0 已有效) + trap::init(); - (sbss_paddr..ebss_paddr).for_each(|a| unsafe { - let va = paddr_to_vaddr(a); - (va as *mut u8).write_volatile(0) - }); -} + // 创建 init 任务并入队(中断仍禁用,避免竞争) + kernel::boot::rest_init(); -// 由于最近的更新使得create_kthreadd内部会调用current_task等函数 -// 该单元测试已无法在不完整的测试环境下运行 -// #[cfg(test)] -// mod tests { - -// use core::sync::atomic::Ordering; - -// // 测试 create_kthreadd:应创建一个任务并加入 TASK_MANAGER -// use crate::{ -// arch::boot::{create_kthreadd, kthreadd}, -// kassert, -// kernel::{TASK_MANAGER, TaskManagerTrait}, -// test_case, -// }; - -// test_case!(test_create_kthreadd, { -// // 记录当前已有任务数量 -// let before_count = { -// let mgr = TASK_MANAGER.lock(); -// mgr.task_count() -// }; -// create_kthreadd(); -// // 找到新增的任务(PID=tid,入口=kthreadd) -// let after_count = { -// let mgr = TASK_MANAGER.lock(); -// mgr.task_count() -// }; -// kassert!(after_count == before_count + 1); -// // 查找新 tid -// let new_tid = after_count as u32; // 简单假设 tid 连续分配 -// let task = TASK_MANAGER.lock().get_task(new_tid).expect("task missing"); -// let g = task.lock(); -// let tf = g.trap_frame_ptr.load(Ordering::SeqCst); -// kassert!(g.tid == new_tid); -// kassert!(g.pid == new_tid); // kthreadd 设 pid=tid -// kassert!(unsafe { (*tf).sepc } as usize == kthreadd as usize); -// }); - -// // 由于 kernel_execve / rest_init / init / kthreadd 涉及不可返回的流控与实际陷入/页表切换, -// // 在单元测试环境下不执行它们(需要集成测试或仿真环境)。 -// } + // 启用中断并进入 idle 循环 + // 时钟中断触发后调度器自动选中 init 并切换上下文 + unsafe { intr::enable_interrupts() }; + kernel::boot::idle_loop(); +} diff --git a/os/src/arch/loongarch/compiler_builtins.rs b/os/src/arch/loongarch/compiler_builtins.rs new file mode 100644 index 00000000..ef48f60c --- /dev/null +++ b/os/src/arch/loongarch/compiler_builtins.rs @@ -0,0 +1,48 @@ +//! Minimal compiler builtin shims required by the LoongArch target. + +use core::ptr; + +/// C ABI `memcpy` replacement for LoongArch bare-metal builds. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn memcpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 { + for i in 0..n { + unsafe { + ptr::write(dst.add(i), ptr::read(src.add(i))); + } + } + dst +} + +/// C ABI `memmove` replacement for LoongArch bare-metal builds. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn memmove(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 { + if dst as usize == src as usize || n == 0 { + return dst; + } + if (dst as usize) < (src as usize) || (dst as usize) >= (src as usize + n) { + for i in 0..n { + unsafe { + ptr::write(dst.add(i), ptr::read(src.add(i))); + } + } + } else { + for i in (0..n).rev() { + unsafe { + ptr::write(dst.add(i), ptr::read(src.add(i))); + } + } + } + dst +} + +/// C ABI `memset` replacement for LoongArch bare-metal builds. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn memset(dst: *mut u8, c: i32, n: usize) -> *mut u8 { + let val = c as u8; + for i in 0..n { + unsafe { + ptr::write(dst.add(i), val); + } + } + dst +} diff --git a/os/src/arch/loongarch/cpu_ops.rs b/os/src/arch/loongarch/cpu_ops.rs index 6e839383..db8cca98 100644 --- a/os/src/arch/loongarch/cpu_ops.rs +++ b/os/src/arch/loongarch/cpu_ops.rs @@ -3,8 +3,8 @@ //! 提供 `LoongArch64` 结构体,实现 `arch::CpuOps` trait。 //! 将现有的 CSR 内联汇编操作映射到 trait 方法。 -use crate::arch::constant::{CSR_CRMD_IE, SSTATUS_SIE}; use crate::arch::CpuOps; +use crate::arch::constant::{CSR_CRMD_IE, SSTATUS_SIE}; /// LoongArch64 架构标记类型 pub struct LoongArch64; diff --git a/os/src/arch/loongarch/kernel/task.rs b/os/src/arch/loongarch/kernel/task.rs index e0e2909f..bebdd9a8 100644 --- a/os/src/arch/loongarch/kernel/task.rs +++ b/os/src/arch/loongarch/kernel/task.rs @@ -5,13 +5,9 @@ use core::{mem::size_of, ptr}; use super::context::TaskContext; use crate::{ - arch::{constant::STACK_ALIGN_MASK, mm::paddr_to_vaddr}, + arch::{address::VA, constant::STACK_ALIGN_MASK, task::ExecStackLayout}, config::PAGE_SIZE, - mm::{ - address::{UsizeConvert, Vaddr}, - frame_allocator::FrameTracker, - memory_space::MemorySpace, - }, + mm::{frame_allocator::FrameTracker, memory_space::MemorySpace}, }; /// 初始化内核任务上下文 @@ -194,6 +190,168 @@ pub fn setup_stack_layout( (sp, argc, argv_vec_ptr, envp_vec_ptr, tls_tp) } +/// Architecture-neutral wrapper for `execve` stack setup. +pub fn setup_exec_stack_layout( + space: &MemorySpace, + sp: VA, + argv: &[&str], + envp: &[&str], + phdr_addr: VA, + phnum: usize, + phent: usize, + at_base: VA, + at_entry: VA, +) -> ExecStackLayout { + let (sp, argc, argv, envp, tls) = setup_stack_layout( + space, + sp.as_usize(), + argv, + envp, + phdr_addr.as_usize(), + phnum, + phent, + at_base.as_usize(), + at_entry.as_usize(), + ); + ExecStackLayout { + sp: VA::from_usize(sp), + argc, + argv: VA::from_usize(argv), + envp: VA::from_usize(envp), + tls: VA::from_usize(tls), + } +} + +/// 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) }; + unsafe { + core::arch::asm!( + "addi.d $sp, {sp}, 0", + "jirl $zero, {entry}, 0", + sp = in(reg) sp, + entry = in(reg) entry, + options(noreturn) + ); + } + } + crate::arch::trap::restore(unsafe { &*tf_ptr }); +} + +/// Final architecture-specific preparation before restoring to user mode. +pub unsafe fn prepare_user_restore( + tfp: *mut crate::arch::trap::TrapFrame, + initial_pc: VA, + user_sp_high: VA, +) { + if tfp.is_null() { + crate::pr_err!("[kernel_execve] trap_frame_ptr is null"); + panic!("kernel_execve: null trap_frame_ptr"); + } + crate::pr_debug!("[kernel_execve] trap_frame_ptr={:#x}", tfp as usize); + unsafe { + crate::pr_debug!( + "[kernel_execve] trapframe: era={:#x}, sp={:#x}, prmd={:#x}, crmd={:#x}, a0={:#x}, a1={:#x}, a2={:#x}", + (*tfp).get_sepc(), + (*tfp).get_sp(), + (*tfp).prmd, + (*tfp).crmd, + (*tfp).get_a0(), + (*tfp).regs[5], + (*tfp).regs[6], + ); + } + + use crate::mm::address::PageNum; + let tlbrent: usize; + let crmd: usize; + let pgdl: usize; + let pgdh: usize; + let ecfg: usize; + let ks0: usize; + let asid: usize; + let tlbrehi: usize; + let tlbrelo0: usize; + let tlbrelo1: usize; + unsafe { + core::arch::asm!("csrrd {0}, 0x88", out(reg) tlbrent, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x0", out(reg) crmd, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x19", out(reg) pgdl, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x1a", out(reg) pgdh, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x4", out(reg) ecfg, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x30", out(reg) ks0, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x18", out(reg) asid, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x8e", out(reg) tlbrehi, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x8c", out(reg) tlbrelo0, options(nostack, preserves_flags)); + core::arch::asm!("csrrd {0}, 0x8d", out(reg) tlbrelo1, options(nostack, preserves_flags)); + } + let space = crate::kernel::current_memory_space(); + let space = space.lock(); + let root_ppn = space.root_ppn(); + let root_paddr = root_ppn.start_addr().as_usize(); + let entry_va = initial_pc; + let sp_va = user_sp_high; + unsafe extern "C" { + fn tlb_refill_entry(); + } + let tlbr_entry_vaddr = tlb_refill_entry as usize; + let tlbr_entry_paddr = + unsafe { crate::arch::va_to_pa(VA::from_usize(tlbr_entry_vaddr)) }.as_usize() & !0xfff; + let tlbr_entry_dm_vaddr = + crate::arch::pa_to_va(crate::arch::address::PA::from_usize(tlbr_entry_paddr)).as_usize(); + crate::pr_debug!( + "[kernel_execve] va translate: entry={:?}, sp={:?}", + space.translate(entry_va), + space.translate(sp_va) + ); + use crate::mm::address::Vpn; + use crate::mm::page_table::PageTableInner; + let entry_vpn = Vpn::from_addr_floor(entry_va); + if let Ok((ppn, _, flags)) = space.page_table().walk(entry_vpn) { + crate::pr_debug!( + "[kernel_execve] entry PTE: vpn={:#x}, ppn={:#x}, flags={:?}", + entry_vpn.0, + ppn.0, + flags + ); + } else { + crate::pr_err!("[kernel_execve] entry page not mapped!"); + } + crate::pr_debug!( + "[kernel_execve] root_ppn={:#x}, root_paddr={:#x}", + root_ppn.0, + root_paddr + ); + crate::pr_debug!( + "[kernel_execve] tlbrent={:#x}, crmd={:#x}, pgdl={:#x}, pgdh={:#x}, ecfg={:#x}, ks0={:#x}", + tlbrent, + crmd, + pgdl, + pgdh, + ecfg, + ks0 + ); + crate::pr_debug!( + "[kernel_execve] asid={:#x} (full_csr={:#x}), tlbrehi={:#x}, tlbrelo0={:#x}, tlbrelo1={:#x}", + asid & 0x3ff, + asid, + tlbrehi, + tlbrelo0, + tlbrelo1 + ); + crate::pr_debug!( + "[kernel_execve] tlb_refill_entry: vaddr={:#x}, paddr={:#x}, dm_vaddr={:#x}", + tlbr_entry_vaddr, + tlbr_entry_paddr, + tlbr_entry_dm_vaddr + ); + unsafe { + core::arch::asm!("csrwr {0}, 0x30", in(reg) tfp as usize, options(nostack, preserves_flags)); + core::arch::asm!("csrwr $zero, 0x8b", options(nostack, preserves_flags)); + } +} + fn write_user_usize(space: &MemorySpace, dst: usize, val: usize) { let bytes = val.to_ne_bytes(); write_user_bytes(space, dst, &bytes); @@ -202,15 +360,15 @@ fn write_user_usize(space: &MemorySpace, dst: usize, val: usize) { fn write_user_bytes(space: &MemorySpace, dst: usize, data: &[u8]) { let mut offset = 0usize; while offset < data.len() { - let vaddr = ::from_usize(dst + offset); + let vaddr = VA::from_usize(dst + offset); let paddr = space .translate(vaddr) .expect("write_user_bytes: translate failed"); let page_off = (dst + offset) & (PAGE_SIZE - 1); let chunk = core::cmp::min(PAGE_SIZE - page_off, data.len() - offset); unsafe { - let dst_va = paddr_to_vaddr(paddr.as_usize()); - let dst_ptr = dst_va as *mut u8; + let dst_va = crate::arch::pa_to_va(paddr); + let dst_ptr = dst_va.as_usize() as *mut u8; let src_ptr = data.as_ptr().add(offset); for i in 0..chunk { ptr::write(dst_ptr.add(i), ptr::read(src_ptr.add(i))); diff --git a/os/src/arch/loongarch/memory.rs b/os/src/arch/loongarch/memory.rs index 5a53ffcd..19fe883e 100644 --- a/os/src/arch/loongarch/memory.rs +++ b/os/src/arch/loongarch/memory.rs @@ -4,4 +4,7 @@ use crate::impl_virtual_memory; -impl_virtual_memory!(LoongArch64ProcessAddressSpace, LoongArch64KernelAddressSpace); +impl_virtual_memory!( + LoongArch64ProcessAddressSpace, + LoongArch64KernelAddressSpace +); diff --git a/os/src/arch/loongarch/mm/mod.rs b/os/src/arch/loongarch/mm/mod.rs index 682ca417..8969cf1e 100644 --- a/os/src/arch/loongarch/mm/mod.rs +++ b/os/src/arch/loongarch/mm/mod.rs @@ -25,6 +25,7 @@ mod page_table; mod page_table_entry; +use crate::arch::address::{PA, VA}; pub use page_table::{PageTableInner, TlbBatchContext}; pub use page_table_entry::PageTableEntry; @@ -52,8 +53,8 @@ pub const PADDR_MASK: usize = 0x0000_FFFF_FFFF_FFFF; /// /// 调用者必须确保虚拟地址在直接映射区域内。 #[inline] -pub const unsafe fn vaddr_to_paddr(vaddr: usize) -> usize { - vaddr & PADDR_MASK +pub const unsafe fn va_to_pa(va: VA) -> PA { + PA::from_usize(va.as_usize() & PADDR_MASK) } /// 物理地址转虚拟地址 @@ -66,6 +67,6 @@ pub const unsafe fn vaddr_to_paddr(vaddr: usize) -> usize { /// /// 对应的虚拟地址(在直接映射区域内) #[inline] -pub const fn paddr_to_vaddr(paddr: usize) -> usize { - paddr | VADDR_START +pub const fn pa_to_va(pa: PA) -> VA { + VA::from_usize(pa.as_usize() | VADDR_START) } diff --git a/os/src/arch/loongarch/mm/page_table.rs b/os/src/arch/loongarch/mm/page_table.rs index f2e8006f..d155d331 100644 --- a/os/src/arch/loongarch/mm/page_table.rs +++ b/os/src/arch/loongarch/mm/page_table.rs @@ -12,7 +12,7 @@ //! 每级页表有 512 个条目(2^9),每个条目 8 字节。 use super::PageTableEntry; -use crate::mm::address::{ConvertablePaddr, Paddr, PageNum, Ppn, UsizeConvert, Vaddr, Vpn}; +use crate::mm::address::{ConvertablePA, PA, PageNum, Ppn, UsizeConvert, VA, Vpn}; use crate::mm::frame_allocator::{FrameTracker, alloc_frame}; use crate::mm::page_table::{ PageSize, PageTableEntry as PageTableEntryTrait, PageTableInner as PageTableInnerTrait, @@ -231,7 +231,7 @@ impl PageTableInnerTrait for PageTableInner { } /// 虚拟地址转物理地址 - fn translate(&self, vaddr: Vaddr) -> Option { + fn translate(&self, vaddr: VA) -> Option { let vpn = Vpn::from_addr_floor(vaddr); let offset = vaddr.as_usize() & 0xfff; // 页内偏移 @@ -241,7 +241,7 @@ impl PageTableInnerTrait for PageTableInner { PageSize::Size4K => ppn.start_addr().as_usize(), _ => ppn.start_addr().as_usize(), // 暂时按 4K 处理 }; - Some(Paddr::from_usize(paddr_base + offset)) + Some(PA::from_usize(paddr_base + offset)) } Err(_) => None, } @@ -496,7 +496,7 @@ impl PageTableInner { fn read_pte(ppn: Ppn, index: usize) -> PageTableEntry { let pte_array = unsafe { core::slice::from_raw_parts( - ppn.start_addr().to_vaddr().as_usize() as *const PageTableEntry, + ppn.start_addr().to_va().as_usize() as *const PageTableEntry, 512, ) }; @@ -508,7 +508,7 @@ impl PageTableInner { fn write_pte(ppn: Ppn, index: usize, pte: PageTableEntry) { let pte_array = unsafe { core::slice::from_raw_parts_mut( - ppn.start_addr().to_vaddr().as_usize() as *mut PageTableEntry, + ppn.start_addr().to_va().as_usize() as *mut PageTableEntry, 512, ) }; @@ -519,7 +519,7 @@ impl PageTableInner { fn clear_page_table(ppn: Ppn) { let pte_array = unsafe { core::slice::from_raw_parts_mut( - ppn.start_addr().to_vaddr().as_usize() as *mut PageTableEntry, + ppn.start_addr().to_va().as_usize() as *mut PageTableEntry, 512, ) }; diff --git a/os/src/arch/loongarch/mod.rs b/os/src/arch/loongarch/mod.rs index 8f04c4d6..a60d8bcd 100644 --- a/os/src/arch/loongarch/mod.rs +++ b/os/src/arch/loongarch/mod.rs @@ -1,6 +1,7 @@ //! LoongArch64 架构模块 pub mod boot; +pub mod compiler_builtins; pub mod constant; pub mod cpu_ops; pub mod intr; @@ -13,10 +14,12 @@ pub mod platform; pub mod timer; pub mod trap; -use crate::impl_arch_common; +use crate::{impl_arch, impl_platform}; -impl_arch_common!( +impl_arch!( cpu_ops::LoongArch64, memory::LoongArch64ProcessAddressSpace, memory::LoongArch64KernelAddressSpace ); + +impl_platform!(cpu_ops::LoongArch64); diff --git a/os/src/arch/loongarch/platform.rs b/os/src/arch/loongarch/platform.rs index 1e3542c4..defa9632 100644 --- a/os/src/arch/loongarch/platform.rs +++ b/os/src/arch/loongarch/platform.rs @@ -61,4 +61,3 @@ pub fn init() { crate::device::bus::pcie::init_virtio_pci(); crate::device::console::init(); } - diff --git a/os/src/arch/loongarch/trap/trap_frame.rs b/os/src/arch/loongarch/trap/trap_frame.rs index d28f8025..bd92ee1b 100644 --- a/os/src/arch/loongarch/trap/trap_frame.rs +++ b/os/src/arch/loongarch/trap/trap_frame.rs @@ -169,6 +169,29 @@ impl TrapFrame { ); } + /// 设置用户态 TrapFrame(架构无关 execve 包装)。 + pub fn set_exec_trap_frame_from_layout( + &mut self, + entry: usize, + kernel_sp: usize, + layout: &crate::arch::task::ExecStackLayout, + ) { + self.set_exec_trap_frame( + entry, + layout.sp.as_usize(), + kernel_sp, + layout.argc, + layout.argv.as_usize(), + layout.envp.as_usize(), + layout.tls.as_usize(), + ); + } + + /// 设置用户态 TLS/thread pointer。 + pub fn set_tls(&mut self, tls: usize) { + self.regs[2] = tls; + } + /// 设置克隆线程的 TrapFrame pub unsafe fn set_clone_trap_frame( &mut self, diff --git a/os/src/arch/loongarch/trap/trap_handler.rs b/os/src/arch/loongarch/trap/trap_handler.rs index 645bee1d..c3915f28 100644 --- a/os/src/arch/loongarch/trap/trap_handler.rs +++ b/os/src/arch/loongarch/trap/trap_handler.rs @@ -5,14 +5,14 @@ use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; use crate::arch::constant::{ CSR_BADI, CSR_BADV, CSR_CRMD_PLV_MASK, CSR_EENTRY, CSR_ESTAT_IS_MASK, CSR_TLBRENT, }; -use crate::kernel::syscall::dispatch::dispatch_syscall; use crate::arch::timer::{ TIMER_TICKS, ack_timer_interrupt, clock_freq, get_time, set_next_trigger, }; use crate::arch::trap::restore; use crate::earlyprintln; use crate::ipc::check_signal; -use crate::kernel::{TIMER, TIMER_QUEUE, schedule, send_signal_process, wake_up_with_block}; +use crate::kernel::syscall::dispatch::dispatch_syscall; +use crate::kernel::{TIMER, TIMER_QUEUE, schedule, send_signal_process, wake_up_task}; use super::TrapFrame; @@ -114,8 +114,13 @@ fn install_trap_entry() { ); // TLB refill 入口使用独立处理,进行软件页表遍历与 tlbfill // TLBRENT 必须使用物理地址,因为 TLB refill 时 CPU 处于直接地址翻译模式 - let tlbr_entry_paddr = - unsafe { crate::arch::mm::vaddr_to_paddr(tlb_refill_entry as usize) } & !0xfff; + let tlbr_entry_paddr = unsafe { + crate::arch::mm::va_to_pa(crate::arch::address::VA::from_usize( + tlb_refill_entry as usize, + )) + } + .as_usize() + & !0xfff; core::arch::asm!( "csrwr {val}, {csr}", val = in(reg) tlbr_entry_paddr, @@ -250,7 +255,7 @@ fn user_panic(estat: usize, era: usize, trap_frame: &TrapFrame) { fn check_timer() { let _ticks = TIMER_TICKS.fetch_add(1, Ordering::Relaxed); while let Some(task) = TIMER_QUEUE.lock().pop_due_task(get_time()) { - wake_up_with_block(task); + wake_up_task(task); } while let Some(entry) = TIMER.lock().pop_due_entry(get_time()) { send_signal_process(&entry.task, entry.sig); diff --git a/os/src/arch/memory_impl.rs b/os/src/arch/memory_impl.rs index 61594f1a..ede40a25 100644 --- a/os/src/arch/memory_impl.rs +++ b/os/src/arch/memory_impl.rs @@ -11,15 +11,15 @@ macro_rules! impl_virtual_memory { ($process_type:ident, $kernel_type:ident) => { use alloc::vec::Vec; - use crate::config::PAGE_SIZE; use crate::arch::virtual_memory::{ KernAddressSpace, PageFrame, PageInfo, PhysMemoryRegion, PtePermissions, UserAddressSpace, VirtMemoryRegion, }; + use crate::config::PAGE_SIZE; use crate::mm::address::{ - ConvertablePaddr, Paddr, PageNum, Ppn, UsizeConvert, Vaddr, Vpn, VpnRange, + ConvertablePA, PA, PageNum, Ppn, UsizeConvert, VA, Vpn, VpnRange, }; - use crate::mm::memory_space::{with_kernel_space, MemorySpace}; + use crate::mm::memory_space::{MemorySpace, with_kernel_space}; use crate::mm::page_table::PageTableInner; use crate::mm::page_table::{PageSize, UniversalPTEFlag}; @@ -64,7 +64,7 @@ macro_rules! impl_virtual_memory { perms: PtePermissions, ) -> Result<(), ()> { let ppn = Ppn::from_usize(page.ppn); - let vaddr = Vaddr::from_usize(va); + let vaddr = VA::from_usize(va); let vpn = Vpn::from_addr_floor(vaddr); let flags = UniversalPTEFlag::from_bits_truncate(perms.bits()); self.inner @@ -74,10 +74,9 @@ macro_rules! impl_virtual_memory { } fn unmap(&mut self, va: usize) -> Result { - let vaddr = Vaddr::from_usize(va); + let vaddr = VA::from_usize(va); let vpn = Vpn::from_addr_floor(vaddr); - let (ppn, _size, _flags) = - self.inner.page_table().walk(vpn).map_err(|_| ())?; + let (ppn, _size, _flags) = self.inner.page_table().walk(vpn).map_err(|_| ())?; self.inner.page_table_mut().unmap(vpn).map_err(|_| ())?; Ok(PageFrame { ppn: ppn.as_usize(), @@ -100,10 +99,8 @@ macro_rules! impl_virtual_memory { region: VirtMemoryRegion, perms: PtePermissions, ) -> Result<(), ()> { - let start_vpn = - Vpn::from_addr_floor(Vaddr::from_usize(region.start_va)); - let end_vpn = - Vpn::from_addr_ceil(Vaddr::from_usize(region.start_va + region.len)); + let start_vpn = Vpn::from_addr_floor(VA::from_usize(region.start_va)); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(region.start_va + region.len)); let flags = UniversalPTEFlag::from_bits_truncate(perms.bits()); for vpn in VpnRange::new(start_vpn, end_vpn) { @@ -115,14 +112,9 @@ macro_rules! impl_virtual_memory { Ok(()) } - fn unmap_range( - &mut self, - region: VirtMemoryRegion, - ) -> Result, ()> { - let start_vpn = - Vpn::from_addr_floor(Vaddr::from_usize(region.start_va)); - let end_vpn = - Vpn::from_addr_ceil(Vaddr::from_usize(region.start_va + region.len)); + fn unmap_range(&mut self, region: VirtMemoryRegion) -> Result, ()> { + let start_vpn = Vpn::from_addr_floor(VA::from_usize(region.start_va)); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(region.start_va + region.len)); let range = VpnRange::new(start_vpn, end_vpn); let mut frames = Vec::new(); @@ -138,14 +130,16 @@ macro_rules! impl_virtual_memory { } fn translate(&self, va: usize) -> Option { - let vaddr = Vaddr::from_usize(va); + let vaddr = VA::from_usize(va); let vpn = Vpn::from_addr_floor(vaddr); - self.inner.page_table().walk(vpn).ok().map( - |(ppn, _size, flags)| PageInfo { + self.inner + .page_table() + .walk(vpn) + .ok() + .map(|(ppn, _size, flags)| PageInfo { ppn: ppn.as_usize(), perms: PtePermissions::from_bits_truncate(flags.bits()), - }, - ) + }) } fn protect_and_clone_region( @@ -155,12 +149,11 @@ macro_rules! impl_virtual_memory { perms: PtePermissions, ) -> Result<(), ()> { let start_va = region.start_va & !(PAGE_SIZE - 1); - let end_va = - (region.start_va + region.len + PAGE_SIZE - 1) & !(PAGE_SIZE - 1); + let end_va = (region.start_va + region.len + PAGE_SIZE - 1) & !(PAGE_SIZE - 1); let flags = UniversalPTEFlag::from_bits_truncate(perms.bits()); for va in (start_va..end_va).step_by(PAGE_SIZE) { - let vaddr = Vaddr::from_usize(va); + let vaddr = VA::from_usize(va); let vpn = Vpn::from_addr_floor(vaddr); if let Ok((ppn, _size, _flags)) = self.inner.page_table().walk(vpn) { other @@ -189,8 +182,8 @@ macro_rules! impl_virtual_memory { impl KernAddressSpace for $kernel_type { fn map_mmio(&mut self, region: PhysMemoryRegion) -> Result { - let pa = Paddr::from_usize(region.start_pa); - let va = pa.to_vaddr(); + let pa = PA::from_usize(region.start_pa); + let va = pa.to_va(); with_kernel_space(|ks| { let start_pa = region.start_pa & !(PAGE_SIZE - 1); @@ -199,15 +192,10 @@ macro_rules! impl_virtual_memory { let mut cur_va = va.as_usize() & !(PAGE_SIZE - 1); while cur_pa < end_pa { - let ppn = Ppn::from_addr_floor(Paddr::from_usize(cur_pa)); - let vpn = Vpn::from_addr_floor(Vaddr::from_usize(cur_va)); + let ppn = Ppn::from_addr_floor(PA::from_usize(cur_pa)); + let vpn = Vpn::from_addr_floor(VA::from_usize(cur_va)); ks.page_table_mut() - .map( - vpn, - ppn, - PageSize::Size4K, - UniversalPTEFlag::kernel_rw(), - ) + .map(vpn, ppn, PageSize::Size4K, UniversalPTEFlag::kernel_rw()) .map_err(|_| ())?; cur_pa += PAGE_SIZE; cur_va += PAGE_SIZE; @@ -231,10 +219,8 @@ macro_rules! impl_virtual_memory { let mut offset = 0usize; while start_pa + offset < end_pa { - let ppn = - Ppn::from_addr_floor(Paddr::from_usize(start_pa + offset)); - let vpn = - Vpn::from_addr_floor(Vaddr::from_usize(start_va + offset)); + let ppn = Ppn::from_addr_floor(PA::from_usize(start_pa + offset)); + let vpn = Vpn::from_addr_floor(VA::from_usize(start_va + offset)); let flags = UniversalPTEFlag::from_bits_truncate(perms.bits()); ks.page_table_mut() .map(vpn, ppn, PageSize::Size4K, flags) diff --git a/os/src/arch/mock/arch.rs b/os/src/arch/mock/arch.rs index 2201b7e1..652afa26 100644 --- a/os/src/arch/mock/arch.rs +++ b/os/src/arch/mock/arch.rs @@ -10,7 +10,7 @@ use crate::arch::arch::Arch; use crate::arch::cpu_ops::CpuOps; use crate::arch::virtual_memory::{ KernAddressSpace, PageFrame, PageInfo, PhysMemoryRegion, PtePermissions, UserAddressSpace, - VirtualMemory, VirtMemoryRegion, + VirtMemoryRegion, VirtualMemory, }; use crate::sync::SpinLock; @@ -192,6 +192,7 @@ impl VirtualMemory for MockArch { #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] mod mock_arch_impl { use super::*; + use crate::arch::plat::Platform; impl Arch for MockArch { type UserContext = MockUserContext; @@ -204,24 +205,59 @@ mod mock_arch_impl { unsafe fn context_switch(_old: *mut Self::UserContext, _new: *const Self::UserContext) {} - unsafe fn copy_from_user(_src: usize, _dst: *mut u8, _len: usize) -> Result<(), ()> { + unsafe fn copy_from_user( + src: crate::arch::address::UA, + dst: *mut u8, + len: usize, + ) -> Result<(), ()> { + let src = src.as_usize(); + if len != 0 && (src == 0 || dst.is_null()) { + return Err(()); + } + unsafe { core::ptr::copy_nonoverlapping(src as *const u8, dst, len) }; Ok(()) } - unsafe fn try_copy_from_user(_src: usize, _dst: *mut u8, _len: usize) -> Result<(), ()> { - Ok(()) + unsafe fn try_copy_from_user( + src: crate::arch::address::UA, + dst: *mut u8, + len: usize, + ) -> Result<(), ()> { + unsafe { Self::copy_from_user(src, dst, len) } } - unsafe fn copy_to_user(_src: *const u8, _dst: usize, _len: usize) -> Result<(), ()> { + unsafe fn copy_to_user( + src: *const u8, + dst: crate::arch::address::UA, + len: usize, + ) -> Result<(), ()> { + let dst = dst.as_usize(); + if len != 0 && (src.is_null() || dst == 0) { + return Err(()); + } + unsafe { core::ptr::copy_nonoverlapping(src, dst as *mut u8, len) }; Ok(()) } unsafe fn copy_strn_from_user( - _src: usize, - _dst: *mut u8, - _max_len: usize, + src: crate::arch::address::UA, + dst: *mut u8, + max_len: usize, ) -> Result { - Ok(0) + let src = src.as_usize(); + if max_len != 0 && (src == 0 || dst.is_null()) { + return Err(()); + } + let mut i = 0; + while i < max_len { + let byte = unsafe { core::ptr::read((src + i) as *const u8) }; + unsafe { *dst.add(i) = byte }; + if byte == 0 { + return Ok(i); + } + i += 1; + } + Ok(max_len) } fn name() -> &'static str { @@ -232,16 +268,6 @@ mod mock_arch_impl { 1 } - fn get_cmdline() -> Option { - None - } - - fn console_putchar(_c: u8) {} - - fn console_getchar() -> Option { - None - } - fn on_task_switch(_trap_frame_ptr: usize, _cpu_ptr: usize) {} fn get_ticks() -> usize { @@ -261,6 +287,18 @@ mod mock_arch_impl { } fn send_reschedule_ipi(_target_cpu: usize) {} + } + + impl Platform for MockArch { + fn console_putchar(_c: u8) {} + + fn console_getchar() -> Option { + None + } + + fn get_cmdline() -> Option { + None + } fn power_off() -> ! { loop { diff --git a/os/src/arch/mock/boot.rs b/os/src/arch/mock/boot.rs index 03b928c7..11aee6ce 100644 --- a/os/src/arch/mock/boot.rs +++ b/os/src/arch/mock/boot.rs @@ -1,5 +1,3 @@ pub fn main(_hartid: usize) -> ! { - loop { - core::hint::spin_loop(); - } + crate::kernel::boot::idle_loop() } diff --git a/os/src/arch/mock/kernel.rs b/os/src/arch/mock/kernel.rs index 0da0a3be..eee2e5b3 100644 --- a/os/src/arch/mock/kernel.rs +++ b/os/src/arch/mock/kernel.rs @@ -32,7 +32,7 @@ pub mod cpu { pub fn on_task_switch(trap_frame_ptr: usize, cpu_ptr: usize) { if trap_frame_ptr != 0 { unsafe { - if let Some(tf) = (trap_frame_ptr as *mut super::trap::TrapFrame).as_mut() { + if let Some(tf) = (trap_frame_ptr as *mut crate::arch::trap::TrapFrame).as_mut() { tf.cpu_ptr = cpu_ptr; } } @@ -41,6 +41,9 @@ pub mod cpu { } pub mod task { + use crate::arch::{address::VA, task::ExecStackLayout}; + use crate::mm::memory_space::MemorySpace; + pub fn setup_stack_layout( sp: usize, _argv: &[&str], @@ -54,6 +57,50 @@ pub mod task { let sp = sp & !(core::mem::size_of::() - 1); (sp - 1024, 0, 0, 0) } + + pub fn setup_exec_stack_layout( + _space: &MemorySpace, + sp: VA, + argv: &[&str], + envp: &[&str], + phdr_addr: VA, + phnum: usize, + phent: usize, + at_base: VA, + at_entry: VA, + ) -> ExecStackLayout { + let (sp, argc, argv, envp) = setup_stack_layout( + sp.as_usize(), + argv, + envp, + phdr_addr.as_usize(), + phnum, + phent, + at_base.as_usize(), + at_entry.as_usize(), + ); + ExecStackLayout { + sp: VA::from_usize(sp), + argc, + argv: VA::from_usize(argv), + envp: VA::from_usize(envp), + tls: VA::null(), + } + } + + pub unsafe fn forkret_restore( + tf_ptr: *mut crate::arch::trap::TrapFrame, + _is_kernel_thread: bool, + ) { + unsafe { crate::arch::trap::restore(&*tf_ptr) }; + } + + pub unsafe fn prepare_user_restore( + _tfp: *mut crate::arch::trap::TrapFrame, + _initial_pc: VA, + _user_sp_high: VA, + ) { + } } pub unsafe fn switch(_old: *mut context::Context, _new: *const context::Context) {} diff --git a/os/src/arch/mock/mm.rs b/os/src/arch/mock/mm.rs index ec6ad509..c57634fd 100644 --- a/os/src/arch/mock/mm.rs +++ b/os/src/arch/mock/mm.rs @@ -1,15 +1,15 @@ -use crate::mm::address::{Paddr, Ppn, UsizeConvert, Vaddr, Vpn}; +use crate::mm::address::{PA, Ppn, UsizeConvert, VA, Vpn}; use crate::mm::page_table::{ PageSize, PageTableEntry as PageTableEntryTrait, PageTableInner as PageTableInnerTrait, PagingError, PagingResult, UniversalPTEFlag, }; -pub fn paddr_to_vaddr(pa: usize) -> usize { - pa + super::constant::SV39_BOT_HALF_TOP +pub fn pa_to_va(pa: PA) -> VA { + VA::from_usize(pa.as_usize() + super::constant::SV39_BOT_HALF_TOP) } -pub unsafe fn vaddr_to_paddr(va: usize) -> usize { - va - super::constant::SV39_BOT_HALF_TOP +pub unsafe fn va_to_pa(va: VA) -> PA { + PA::from_usize(va.as_usize() - super::constant::SV39_BOT_HALF_TOP) } // ---- Mock PageTableEntry ---- @@ -149,7 +149,7 @@ impl PageTableInnerTrait for PageTableInner { None } - fn translate(&self, _vaddr: Vaddr) -> Option { + fn translate(&self, _vaddr: VA) -> Option { None } diff --git a/os/src/arch/mock/trap.rs b/os/src/arch/mock/trap.rs index c30ac428..88f8851d 100644 --- a/os/src/arch/mock/trap.rs +++ b/os/src/arch/mock/trap.rs @@ -157,6 +157,26 @@ impl TrapFrame { self.x12_a2 = envp; } + pub fn set_exec_trap_frame_from_layout( + &mut self, + entry: usize, + kernel_sp: usize, + layout: &crate::arch::task::ExecStackLayout, + ) { + self.set_exec_trap_frame( + entry, + layout.sp.as_usize(), + kernel_sp, + layout.argc, + layout.argv.as_usize(), + layout.envp.as_usize(), + ); + } + + pub fn set_tls(&mut self, tls: usize) { + self.x4_tp = tls; + } + pub unsafe fn set_fork_trap_frame(&mut self, parent_frame: &TrapFrame) { *self = *parent_frame; self.x10_a0 = 0; diff --git a/os/src/arch/mod.rs b/os/src/arch/mod.rs index 9d8e9bbf..d31035cc 100644 --- a/os/src/arch/mod.rs +++ b/os/src/arch/mod.rs @@ -12,20 +12,22 @@ // ---- trait 定义 ---- +pub mod abi; pub mod address; pub mod arch; pub mod cpu_ops; +pub mod plat; +pub mod task; pub mod virtual_memory; pub use arch::Arch; pub use cpu_ops::CpuOps; -pub use virtual_memory::{UserAddressSpace, KernAddressSpace, VirtualMemory}; +pub use plat::Platform; // ---- 共享模块(架构无关) ---- -pub mod syscall; -mod memory_impl; mod arch_impl; +mod memory_impl; // ---- 目标架构:RISC-V / LoongArch ---- @@ -61,11 +63,20 @@ pub use loongarch::cpu_ops::LoongArch64 as ArchImpl; #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] pub use crate::arch::mock::MockArch as ArchImpl; -// ---- 便捷包装函数 ---- -// 将 Arch trait 方法暴露为普通函数,避免调用者显式导入 trait。 -// 内部委托给 ArchImpl,保持与旧代码的兼容性。 +// ---- PlatformImpl 类型别名 ---- +// 与 ArchImpl 对应,内核其余部分通过 PlatformImpl 访问平台功能。 -use crate::arch::cpu_ops::CpuOps as _; +#[cfg(target_arch = "riscv64")] +pub use riscv::cpu_ops::Riscv64 as PlatformImpl; + +#[cfg(target_arch = "loongarch64")] +pub use loongarch::cpu_ops::LoongArch64 as PlatformImpl; + +#[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] +pub use crate::arch::mock::MockArch as PlatformImpl; + +// ---- 便捷包装函数 ---- +// 将 Arch / Platform trait 方法暴露为普通函数。 /// 启用中断 #[inline] @@ -129,15 +140,21 @@ pub fn send_reschedule_ipi(target: usize) { /// 物理地址 → 虚拟地址(直接映射) #[inline] -pub fn paddr_to_vaddr(paddr: usize) -> usize { - ArchImpl::paddr_to_vaddr(paddr) +pub fn pa_to_va(pa: address::PA) -> address::VA { + PlatformImpl::pa_to_va(pa) } /// 虚拟地址 → 物理地址(直接映射) /// /// # Safety -/// 调用者需确保 vaddr 处于直接映射区域。 +/// 调用者需确保 `va` 处于直接映射区域。 +#[inline] +pub unsafe fn va_to_pa(va: address::VA) -> address::PA { + unsafe { PlatformImpl::va_to_pa(va) } +} + +/// 判断虚拟地址是否位于直接映射区域。 #[inline] -pub unsafe fn vaddr_to_paddr(vaddr: usize) -> usize { - unsafe { ArchImpl::vaddr_to_paddr(vaddr) } +pub fn is_direct_mapped_va(va: address::VA) -> bool { + va.as_usize() >= ::PAGE_OFFSET } diff --git a/os/src/arch/plat.rs b/os/src/arch/plat.rs new file mode 100644 index 00000000..0eaaa531 --- /dev/null +++ b/os/src/arch/plat.rs @@ -0,0 +1,58 @@ +//! Platform trait — 平台抽象层 +//! +//! 从 `Arch` trait 剥离的平台级操作(控制台 I/O、电源管理、 +//! 地址映射策略、启动参数)。此 trait 关注的是 *板级/机器级* +//! 差异,而非 CPU 架构差异。 +//! +//! 默认物理→虚拟地址映射使用 `PAGE_OFFSET` 偏移,架构可覆写。 + +use crate::arch::{ + address::{PA, VA}, + virtual_memory::VirtualMemory, +}; + +/// 平台抽象 trait。 +/// +/// 负责控制台 I/O、电源管理、地址映射等平台级操作。 +/// +/// # 移植要点 +/// +/// 实现 `CpuOps` + `VirtualMemory` + `Arch` 后实现本 trait。 +/// 多数方法有基于 `PAGE_OFFSET` 的默认实现。 +pub trait Platform: VirtualMemory { + /// 向调试控制台输出一个字节 + fn console_putchar(c: u8); + + /// 从调试控制台读取一个字节(非阻塞),`None` 表示无输入 + fn console_getchar() -> Option; + + /// 获取内核命令行参数 + fn get_cmdline() -> Option; + + /// 物理地址 → 虚拟地址(直接映射区域) + fn pa_to_va(pa: PA) -> VA { + VA::from_usize( + pa.as_usize() + .checked_add(Self::PAGE_OFFSET) + .expect("pa_to_va: direct-map address overflow"), + ) + } + + /// 虚拟地址 → 物理地址(直接映射区域) + /// + /// # Safety + /// 调用者需确保 `va` 处于直接映射范围内。 + unsafe fn va_to_pa(va: VA) -> PA { + assert!( + va.as_usize() >= Self::PAGE_OFFSET, + "va_to_pa: address is below direct-map base" + ); + PA::from_usize(va.as_usize() - Self::PAGE_OFFSET) + } + + /// 关机,永不返回 + fn power_off() -> !; + + /// 重启,永不返回 + fn restart() -> !; +} diff --git a/os/src/arch/riscv/boot/mod.rs b/os/src/arch/riscv/boot/mod.rs index f4737270..a3bdd090 100644 --- a/os/src/arch/riscv/boot/mod.rs +++ b/os/src/arch/riscv/boot/mod.rs @@ -3,229 +3,45 @@ use core::arch::global_asm; use core::sync::atomic::{AtomicUsize, Ordering}; -use alloc::sync::Arc; -use riscv::register::sscratch; - global_asm!(include_str!("entry.S")); +use crate::mm::address::UsizeConvert; use crate::{ - arch::{intr, mm::vaddr_to_paddr, platform, timer, trap, trap::TrapFrame}, + arch::{intr, platform, timer, trap}, earlyprintln, - ipc::{SignalHandlerTable, SignalPending}, - kernel::{ - FsStruct, NUM_CPU, Scheduler, TASK_MANAGER, TaskManagerTrait, TaskStruct, current_cpu, - current_memory_space, current_task, kernel_execve, kthread_spawn, kworker, - sleep_task_with_block, time, yield_task, - }, - mm::{ - self, - frame_allocator::{alloc_contig_frames, alloc_frame}, - }, - pr_debug, pr_err, pr_info, pr_warn, - sync::SpinLock, + kernel::{self, NUM_CPU, current_cpu, time}, + mm, pr_debug, pr_err, pr_info, pr_warn, + sync::PreemptGuard, test::run_early_tests, - uapi::{ - resource::{INIT_RLIMITS, RlimitStruct}, - signal::SignalFlags, - uts_namespace::UtsNamespace, - }, - vfs::{create_stdio_files, fd_table, get_root_dentry}, }; -// Needed for Ppn::as_usize -use crate::mm::address::UsizeConvert; /// 已上线 CPU 位掩码 -/// -/// 每个位代表一个 CPU,位 i 为 1 表示 CPU i 已上线。 -/// 使用原子操作确保多核环境下的线程安全。 static CPU_ONLINE_MASK: AtomicUsize = AtomicUsize::new(0); -/// 从核启动标志(在 entry.S 中定义) -/// -/// 主核设置此标志为 1 后,所有从核将从 WFI 中唤醒并开始启动。 +// 从核启动标志(在 entry.S 中定义) unsafe extern "C" { static mut secondary_boot_flag: u64; } -/// 从核调试入口(在启用分页后立即调用) +/// 从核调试入口 #[unsafe(no_mangle)] pub extern "C" fn secondary_debug_entry(hartid: usize) { crate::earlyprintln!("[DEBUG] Hart {} reached secondary_wait_high", hartid); } -/// 内核的第一个任务启动函数 -/// 并且当这个函数结束时,应该切换到第一个任务的上下文 -pub fn rest_init() { - // init进程必须使用TID 1,不从分配器获取 - // TID分配器从2开始,所以idle任务会获得TID 2, 3, ... - let tid = 1; - let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack"); - let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame"); - let fd_table = fd_table::FDTable::new(); - let (stdin, stdout, stderr) = create_stdio_files(); - fd_table - .install_at(0, stdin) - .expect("Failed to install stdin"); - fd_table - .install_at(1, stdout) - .expect("Failed to install stdout"); - fd_table - .install_at(2, stderr) - .expect("Failed to install stderr"); - let cwd = get_root_dentry().ok(); - let root = cwd.clone(); - let fs = Arc::new(SpinLock::new(FsStruct::new(cwd, root))); - let mut task = TaskStruct::ktask_create( - tid, - tid, - 0, - TaskStruct::empty_children(), - kstack_tracker, - trap_frame_tracker, - Arc::new(SpinLock::new(SignalHandlerTable::new())), - SignalFlags::empty(), - Arc::new(SpinLock::new(SignalPending::empty())), - Arc::new(SpinLock::new(UtsNamespace::default())), - Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))), - Arc::new(fd_table), - fs, - ); // init 没有父任务 - - let tf = task.trap_frame_ptr.load(Ordering::SeqCst); - // Safety: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效 - unsafe { - // 先初始化 TrapFrame 为全 0 - core::ptr::write(tf, TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(init as usize, 0, task.kstack_base); - } - - let ra = task.context.ra; - let sp = task.context.sp; - let ptr = task.trap_frame_ptr.load(Ordering::SeqCst); - // init 进程不同于其他内核线程,需要有一个独立的内存空间 - task.memory_space = Some(current_memory_space()); - // init 任务运行在 CPU 0 - task.on_cpu = Some(0); - let task = task.into_shared(); - unsafe { - sscratch::write(ptr as usize); - } - TASK_MANAGER.lock().add_task(task.clone()); +/// RISC-V 主核启动入口 +pub fn main(hartid: usize) { + // 提前设置 tp 指向一个临时值,确保 mm::init 期间 IntrGuard::new() 调用 + // CPU::id() 时 tp 已指向有效内存(cpuid = 0)。后续在 CPUS 初始化完成后 + // 会重新指向真正的 Cpu 结构体。 { - let _guard = crate::sync::PreemptGuard::new(); - current_cpu().switch_task(task); - } - - // 切入 kinit:设置 sp 并跳到 ra;此调用不返回 - // SAFETY: 在 Task 创建时已正确初始化 ra 和 sp - unsafe { - core::arch::asm!( - "mv sp, {sp}", - "jr {ra}", - sp = in(reg) sp, - ra = in(reg) ra, - options(noreturn) - ); - } -} - -/// 内核的第一个任务 -/// PID = 1 -/// 负责进行剩余的初始化工作 -/// 创建 kthreadd 任务 -/// 并在一切结束后转化为第一个用户态任务 -fn init() { - super::trap::init(); - - // 启用中断(在设置好 trap 处理和 sscratch 之后) - unsafe { intr::enable_interrupts() }; - - create_kthreadd(); - - // 初始化 Ext4 文件系统(从真实块设备) - // 必须在任务上下文中进行,因为 VFS 需要 current_task() - if let Err(e) = crate::fs::init_ext4_from_block_device() { - pr_err!( - "[Init] Warning: Failed to initialize Ext4 filesystem: {:?}", - e - ); - pr_info!("[Init] Continuing without filesystem..."); - } - - // 初始化默认网络配置(eth0 + 127.0.0.1 loopback + NetworkStack runtime) - if let Err(e) = crate::net::config::NetworkConfigManager::init_default_interface() { - pr_warn!( - "[Init] Warning: Failed to init default network interface: {:?}", - e - ); - } - - // /dev 的挂载与设备节点创建交给用户态 rcS: - // - rcS 会执行 `mount -t tmpfs none /dev` - // - 内核在 mount("/dev") 的系统调用中对该挂载点做了特殊处理,会在挂载 tmpfs 后自动 init_dev() - - kernel_execve("/sbin/init", &["/sbin/init"], &[]); -} - -/// 内核守护线程 -/// PID = 2 -/// 负责创建内核任务,回收僵尸任务等工作 -fn kthreadd() { - kthread_spawn(kworker); - loop { - // 休眠等待任务 - sleep_task_with_block(current_task(), true); - yield_task(); - } -} - -/// 创建内核守护线程 kthreadd -fn create_kthreadd() { - let tid = TASK_MANAGER.lock().allocate_tid(); - let kstack_tracker = alloc_contig_frames(4).expect("kthread_spawn: failed to alloc kstack"); - let trap_frame_tracker = alloc_frame().expect("kthread_spawn: failed to alloc trap_frame"); - let (uts, rlimit, fd_table, fs) = { - let task = current_task(); - let t = task.lock(); - ( - t.uts_namespace.clone(), - t.rlimit.clone(), - t.fd_table.clone_table(), - t.fs.lock().clone(), - ) - }; - let task = TaskStruct::ktask_create( - tid, - tid, - 0, - TaskStruct::empty_children(), - kstack_tracker, - trap_frame_tracker, - Arc::new(SpinLock::new(SignalHandlerTable::new())), - SignalFlags::empty(), - Arc::new(SpinLock::new(SignalPending::empty())), - uts, - rlimit, - Arc::new(fd_table), - Arc::new(SpinLock::new(fs)), - ); // kthreadd 没有父任务 - - let tf = task.trap_frame_ptr.load(Ordering::SeqCst); - // Safety: 此时 trap_frame_tracker 已经分配完毕且不可变更,所有权在 task 中,指针有效 - unsafe { - // 先初始化 TrapFrame 为全 0 - core::ptr::write(tf, TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(kthreadd as usize, 0, task.kstack_base); + static BOOT_CPU_DUMMY: usize = 0; + unsafe { + core::arch::asm!("mv tp, {}", in(reg) &raw const BOOT_CPU_DUMMY); + } } - let task = task.into_shared(); - // kthreadd 任务运行在 CPU 0 - task.lock().on_cpu = Some(0); - TASK_MANAGER.lock().add_task(task.clone()); - crate::kernel::scheduler_of(0).lock().add_task(task); -} -pub fn main(hartid: usize) { - clear_bss(); + kernel::boot::clear_bss(); run_early_tests(); @@ -235,7 +51,6 @@ pub fn main(hartid: usize) { let kernel_space = mm::init(); // 初始化 CPUS 并设置 tp 指向 CPU 0 - // 必须在任何可能调用 cpu_id() 的代码之前完成 { use crate::kernel::CPUS; let cpu_ptr = CPUS.get_of(0) as *const _ as usize; @@ -245,9 +60,9 @@ pub fn main(hartid: usize) { earlyprintln!("[Boot] Initialized CPUS, tp = 0x{:x}", cpu_ptr); } - // 激活内核地址空间并设置 current_memory_space + // 激活内核地址空间 { - let _guard = crate::sync::PreemptGuard::new(); + let _guard = PreemptGuard::new(); current_cpu().switch_space(kernel_space); earlyprintln!("[Boot] Activated kernel address space"); } @@ -255,194 +70,49 @@ pub fn main(hartid: usize) { #[cfg(test)] crate::test_main(); - // 初始化工作 + // 早期引导陷阱(覆盖平台初始化窗口) trap::init_boot_trap(); - platform::init(); // 完整的平台初始化 (包括 device_tree::init()) + platform::init(); time::init(); - // 启动从核(在启用定时器中断之前) + // 启动从核 let num_cpus = unsafe { NUM_CPU }; if num_cpus > 1 { boot_secondary_cpus(num_cpus); } - // 在从核启动完成后再初始化定时器,避免主核在等待时收到中断 timer::init(); - // 为 CPU0 创建并登记 idle 任务(不加入调度队列,仅作兜底) + // 创建 idle 并设为当前任务(sscratch 就绪) + let idle = kernel::boot::create_idle_task(0, kernel::boot::idle_loop); { - let _guard = crate::sync::PreemptGuard::new(); - if current_cpu().idle_task.is_none() { - let idle0 = create_idle_task(0); - current_cpu().idle_task = Some(idle0); - } - } - - // 注意:中断在 init() 函数中启用,在设置好 sscratch 之后 - rest_init(); -} - -/// 清除 BSS 段,将其全部置零 -/// BSS 段包含所有未初始化的静态变量 -/// 在进入 Rust 代码之前调用此函数非常重要 -fn clear_bss() { - unsafe extern "C" { - fn sbss(); - fn ebss(); + let _guard = PreemptGuard::new(); + current_cpu().idle_task = Some(idle.clone()); + current_cpu().switch_task(idle); } - let sbss_paddr = unsafe { vaddr_to_paddr(sbss as usize) }; - let ebss_paddr = unsafe { vaddr_to_paddr(ebss as usize) }; - - (sbss_paddr..ebss_paddr).for_each(|a| unsafe { - // 访问物理地址需要通过 paddr_to_vaddr 转换 - let va = crate::arch::mm::paddr_to_vaddr(a); - (va as *mut u8).write_volatile(0) - }); -} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{kassert, test_case}; - - /// 测试 NUM_CPU 设置正确 - test_case!(test_num_cpu, { - let num_cpu = unsafe { crate::kernel::NUM_CPU }; - kassert!(num_cpu >= 1); - kassert!(num_cpu <= crate::config::MAX_CPU_COUNT); - }); - - /// 测试 CPU 上线掩码(多核环境) - test_case!(test_cpu_online_mask, { - use core::sync::atomic::Ordering; - - let num_cpu = unsafe { crate::kernel::NUM_CPU }; - let actual_mask = CPU_ONLINE_MASK.load(Ordering::Acquire); - - // 在测试模式下,如果 CPU_ONLINE_MASK 为 0,说明 boot_secondary_cpus 未被调用 - // 这是正常的,因为测试框架跳过了正常的启动流程 - if actual_mask == 0 { - // 跳过此测试 - return; - } - - let expected_mask = (1 << num_cpu) - 1; - - // 验证所有 CPU 都已上线 - kassert!(actual_mask == expected_mask); - - // 验证主核已上线 - kassert!((actual_mask & 1) != 0); - - // 如果是多核,验证从核也已上线 - if num_cpu > 1 { - for hartid in 1..num_cpu { - kassert!((actual_mask & (1 << hartid)) != 0); - } - } - }); -} + // 完整陷阱处理(sscratch 已有效) + trap::init(); -/// 从核入口函数 -/// -/// 由 SBI HSM 调用启动,hartid 通过 a0 寄存器传递。 -/// -/// Idle循环:等待中断;被 S 态时钟中断唤醒后,trap_handler 会决定是否调度 -fn idle_loop() -> ! { - loop { - // 确保中断启用 - if !crate::arch::intr::are_interrupts_enabled() { - unsafe { - crate::arch::intr::enable_interrupts(); - } - } + // 创建 init 任务并入队(中断仍禁用,避免竞争) + kernel::boot::rest_init(); - // 等待中断(timer或IPI会触发调度) - unsafe { - core::arch::asm!("wfi"); - } - } + // 启用中断并进入 idle 循环 + // 时钟中断触发后调度器自动选中 init 并切换上下文 + unsafe { intr::enable_interrupts() }; + kernel::boot::idle_loop(); } -/// 为指定CPU创建idle任务 -fn create_idle_task(cpu_id: usize) -> crate::kernel::SharedTask { - use crate::arch::trap::TrapFrame; - use crate::ipc::{SignalHandlerTable, SignalPending}; - use crate::kernel::FsStruct; - use crate::kernel::{TASK_MANAGER, TaskStruct}; - use crate::mm::frame_allocator::alloc_contig_frames; - use crate::sync::SpinLock; - use crate::uapi::resource::{INIT_RLIMITS, RlimitStruct}; - use crate::uapi::signal::SignalFlags; - use crate::uapi::uts_namespace::UtsNamespace; - use crate::vfs::fd_table::FDTable; - use alloc::sync::Arc; - use core::sync::atomic::Ordering; - - // idle任务从TID分配器正常分配TID - // TID分配器从2开始,所以idle任务会获得TID 2, 3, ... - // init进程会手动设置为TID 1 - let tid = TASK_MANAGER.lock().allocate_tid(); - - // 分配最小资源 - let kstack_tracker = - alloc_contig_frames(1).expect("Failed to allocate kernel stack for idle task"); - let trap_frame_tracker = alloc_frame().expect("Failed to allocate trap frame for idle task"); - - // 创建最小化的任务结构 - let mut task = TaskStruct::ktask_create( - tid, - tid, // pid = tid - 0, // ppid = 0 (no parent) - TaskStruct::empty_children(), - kstack_tracker, - trap_frame_tracker, - Arc::new(SpinLock::new(SignalHandlerTable::new())), - SignalFlags::empty(), - Arc::new(SpinLock::new(SignalPending::empty())), - Arc::new(SpinLock::new(UtsNamespace::default())), - Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))), - Arc::new(FDTable::new()), - Arc::new(SpinLock::new(FsStruct::new(None, None))), - ); - - // 设置trap frame指向idle_loop - let tf = task.trap_frame_ptr.load(Ordering::SeqCst); - unsafe { - core::ptr::write(tf, TrapFrame::zero_init()); - (*tf).set_kernel_trap_frame(idle_loop as usize, 0, task.kstack_base); - } - - // 设置CPU亲和性 - task.on_cpu = Some(cpu_id); - - let task = task.into_shared(); - - // 将idle任务加入TaskManager - // 现在idle任务使用正常的TID(2, 3, ...),不会冲突 - TASK_MANAGER.lock().add_task(task.clone()); - - pr_info!("[SMP] Created idle task {} for CPU {}", tid, cpu_id); - - task +// SBI HSM 从核入口(在 entry.S 中定义) +unsafe extern "C" { + fn secondary_sbi_entry(); } -/// # 初始化流程 -/// 1. 初始化 boot trap 处理(设置 stvec) -/// 2. 设置 tp 指向对应的 Cpu 结构体 -/// 3. 标记 CPU 上线 -/// 4. 禁用中断(避免 trap 处理问题) -/// 5. 进入 WFI 循环等待多核调度器实现 +/// 从核入口 /// -/// # 注意事项 -/// - 从核使用 boot_trap_entry(不需要 sscratch) -/// - 从核禁用中断,避免在没有完整 trap 上下文时响应中断 -/// - 等待多核调度器实现后,从核将被唤醒并启用中断 +/// 与主核对称:创建 idle → switch_task → trap::init → 启用中断 → idle_loop。 #[unsafe(no_mangle)] pub extern "C" fn secondary_start(hartid: usize) -> ! { - // 初始化 boot trap 处理,确保 stvec 指向 boot_trap_entry - // boot_trap_entry 不需要 sscratch,使用栈保存上下文 trap::init_boot_trap(); // 设置 tp 指向对应的 Cpu 结构体 @@ -454,44 +124,25 @@ pub extern "C" fn secondary_start(hartid: usize) -> ! { } } - // 标记当前 CPU 上线 CPU_ONLINE_MASK.fetch_or(1 << hartid, Ordering::Release); - pr_info!("[SMP] CPU {} is online", hartid); - // 初始化完整的 trap 处理 - trap::init(); - - // 创建并设置idle任务 - let idle_task = create_idle_task(hartid); - - // 设置sscratch指向idle任务的TrapFrame - let tf_ptr = idle_task.lock().trap_frame_ptr.load(Ordering::SeqCst); - unsafe { - riscv::register::sscratch::write(tf_ptr as usize); - } - pr_debug!( - "[SMP] CPU {} set sscratch to {:#x}", - hartid, - tf_ptr as usize - ); - - // 设置idle任务为当前任务,并记录为本CPU的idle句柄 + // 创建 idle 并设为当前任务 + let idle_task = kernel::boot::create_idle_task(hartid, kernel::boot::idle_loop); { - let _guard = crate::sync::PreemptGuard::new(); + let _guard = PreemptGuard::new(); let cpu = current_cpu(); cpu.idle_task = Some(idle_task.clone()); cpu.switch_task(idle_task); } - pr_info!("[SMP] CPU {} set idle task as current_task", hartid); - // 切换到最终的内核页表(与 CPU0 共享),避免长期停留在 boot_pagetable + // 切换到全局内核页表 if let Some(kernel_space) = crate::mm::get_global_kernel_space() { + let root_ppn = kernel_space.lock().root_ppn(); { - let _guard = crate::sync::PreemptGuard::new(); + let _guard = PreemptGuard::new(); current_cpu().switch_space(kernel_space.clone()); } - let root_ppn = kernel_space.lock().root_ppn(); pr_info!( "[SMP] CPU {} switched to global kernel space, root PPN: 0x{:x}", hartid, @@ -504,66 +155,23 @@ pub extern "C" fn secondary_start(hartid: usize) -> ! { ); } - // 初始化定时器 + // 完整陷阱 + 定时器 + 中断 + trap::init(); timer::init(); - - // 启用中断 unsafe { intr::enable_interrupts(); } - // 检查中断配置状态 - unsafe { - let sstatus: usize; - let sie: usize; - let sip: usize; - core::arch::asm!("csrr {}, sstatus", out(reg) sstatus); - core::arch::asm!("csrr {}, sie", out(reg) sie); - core::arch::asm!("csrr {}, sip", out(reg) sip); - pr_debug!( - "[SMP] CPU {} interrupt status: sstatus={:#x}, sie={:#x}, sip={:#x}", - hartid, - sstatus, - sie, - sip - ); - pr_debug!( - "[SMP] CPU {} SIE bit: {}, SSIE bit: {}, SSIP bit: {}", - hartid, - (sstatus >> 1) & 1, - (sie >> 1) & 1, - (sip >> 1) & 1 - ); - } - - // 注意:mideleg 是 M-mode CSR,S-mode 无法读取 - // 如果尝试读取会触发非法指令异常 - // 我们需要通过其他方式验证中断委托配置 - pr_debug!("[SMP] CPU {} entering idle loop", hartid); - - // 进入idle循环(永不返回) - idle_loop(); -} - -/// SBI HSM 从核入口(在 entry.S 中定义) -unsafe extern "C" { - fn secondary_sbi_entry(); + kernel::boot::idle_loop(); } /// 启动从核(由主核调用) -/// -/// # 参数 -/// - num_cpus: 总 CPU 数量(包括主核) -/// -/// # Panics -/// - 如果从核启动超时 pub fn boot_secondary_cpus(num_cpus: usize) { use crate::arch::timer::{clock_freq, get_time}; if num_cpus <= 1 { pr_info!("[SMP] Single CPU mode, skipping secondary boot"); - // 标记主核在线 CPU_ONLINE_MASK.fetch_or(1, Ordering::Release); unsafe { NUM_CPU = 1 }; return; @@ -571,14 +179,14 @@ pub fn boot_secondary_cpus(num_cpus: usize) { pr_info!("[SMP] Booting up to {} secondary CPUs...", num_cpus - 1); - // 主核标记在线 CPU_ONLINE_MASK.fetch_or(1, Ordering::Release); - // 尝试启动每个从核,记录预期应当在线的掩码(仅统计成功发起的启动请求) - let mut expected_mask: usize = 1; // CPU0 已在线 + let mut expected_mask: usize = 1; for hartid in 1..num_cpus { let start_vaddr = secondary_sbi_entry as usize; - let start_paddr = unsafe { crate::arch::mm::vaddr_to_paddr(start_vaddr) }; + let start_paddr = + unsafe { crate::arch::mm::va_to_pa(crate::arch::address::VA::from_usize(start_vaddr)) } + .as_usize(); pr_info!( "[SMP] Starting hart {} at vaddr=0x{:x}, paddr=0x{:x}", hartid, @@ -588,7 +196,6 @@ pub fn boot_secondary_cpus(num_cpus: usize) { let ret = crate::arch::lib::hart_start(hartid, start_paddr, hartid); if ret.error != 0 { - // HSM 不支持或被拒绝等,降级单核/少核而不是 panic pr_err!( "[SMP] Failed to start hart {}: SBI error {}", hartid, @@ -600,15 +207,12 @@ pub fn boot_secondary_cpus(num_cpus: usize) { pr_info!("[SMP] Hart {} SBI call accepted", hartid); } - // 若没有任何从核被接受启动请求,立即降级到单核 if expected_mask == 1 { pr_warn!("[SMP] No secondary hart could be started; falling back to single-core"); unsafe { NUM_CPU = 1 }; return; } - // 基于时间的超时等待(避免与主机性能相关的固定次数循环) - // 设定 2 秒的上线等待窗口 let deadline = get_time().saturating_add(clock_freq() * 2); while CPU_ONLINE_MASK.load(Ordering::Acquire) != expected_mask { if get_time() >= deadline { @@ -623,7 +227,6 @@ pub fn boot_secondary_cpus(num_cpus: usize) { core::hint::spin_loop(); } - // 以实际在线核数为准,更新 NUM_CPU,避免后续调度把任务分配到离线 CPU let online_mask = CPU_ONLINE_MASK.load(Ordering::Acquire); let online_cnt = online_mask.count_ones() as usize; unsafe { NUM_CPU = core::cmp::max(online_cnt, 1) }; @@ -638,3 +241,34 @@ pub fn boot_secondary_cpus(num_cpus: usize) { ); } } + +#[cfg(test)] +mod tests { + use super::*; + use crate::{kassert, test_case}; + + test_case!(test_num_cpu, { + let num_cpu = unsafe { crate::kernel::NUM_CPU }; + kassert!(num_cpu >= 1); + kassert!(num_cpu <= crate::config::MAX_CPU_COUNT); + }); + + test_case!(test_cpu_online_mask, { + let num_cpu = unsafe { crate::kernel::NUM_CPU }; + let actual_mask = CPU_ONLINE_MASK.load(Ordering::Acquire); + + if actual_mask == 0 { + return; + } + + let expected_mask = (1 << num_cpu) - 1; + kassert!(actual_mask == expected_mask); + kassert!((actual_mask & 1) != 0); + + if num_cpu > 1 { + for hartid in 1..num_cpu { + kassert!((actual_mask & (1 << hartid)) != 0); + } + } + }); +} diff --git a/os/src/arch/riscv/cpu_ops.rs b/os/src/arch/riscv/cpu_ops.rs index 068bb550..0be1654b 100644 --- a/os/src/arch/riscv/cpu_ops.rs +++ b/os/src/arch/riscv/cpu_ops.rs @@ -14,13 +14,25 @@ impl CpuOps for Riscv64 { /// /// 从 tp 寄存器指向的 Cpu 结构体中读取首个字段 (cpu_id)。 /// 在内核态,tp 指向 Cpu 结构体。 + /// 如果 tp 为 0(尚未初始化),返回 0。 #[inline] fn id() -> usize { + let tp_val: usize; + unsafe { + core::arch::asm!( + "mv {}, tp", + out(reg) tp_val + ); + } + if tp_val == 0 { + return 0; + } let id: usize; unsafe { core::arch::asm!( - "ld {}, 0(tp)", - out(reg) id + "ld {}, 0({})", + out(reg) id, + in(reg) tp_val ); } id diff --git a/os/src/arch/riscv/kernel/task.rs b/os/src/arch/riscv/kernel/task.rs index 3e72f1b1..850a777c 100644 --- a/os/src/arch/riscv/kernel/task.rs +++ b/os/src/arch/riscv/kernel/task.rs @@ -6,6 +6,8 @@ use alloc::vec::Vec; use riscv::register::sstatus; use crate::arch::constant::STACK_ALIGN_MASK; +use crate::arch::{address::VA, task::ExecStackLayout}; +use crate::mm::memory_space::MemorySpace; /// 为新任务设置用户栈布局,包含命令行参数和环境变量 /// 返回新的栈指针位置,以及 argc, argv, envp 的地址 @@ -178,3 +180,58 @@ pub fn setup_stack_layout( // sp &= !STACK_ALIGN_MASK; (sp, argc, argv_vec_ptr, envp_vec_ptr) } + +/// Architecture-neutral wrapper for `execve` stack setup. +pub fn setup_exec_stack_layout( + _space: &MemorySpace, + sp: VA, + argv: &[&str], + envp: &[&str], + phdr_addr: VA, + phnum: usize, + phent: usize, + at_base: VA, + at_entry: VA, +) -> ExecStackLayout { + let (sp, argc, argv, envp) = setup_stack_layout( + sp.as_usize(), + argv, + envp, + phdr_addr.as_usize(), + phnum, + phent, + at_base.as_usize(), + at_entry.as_usize(), + ); + ExecStackLayout { + sp: VA::from_usize(sp), + argc, + argv: VA::from_usize(argv), + envp: VA::from_usize(envp), + tls: VA::null(), + } +} + +/// 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) { + unsafe { crate::arch::trap::restore(&*tf_ptr) }; +} + +/// Final architecture-specific preparation before restoring to user mode. +pub unsafe fn prepare_user_restore( + tfp: *mut crate::arch::trap::TrapFrame, + _initial_pc: VA, + _user_sp_high: VA, +) { + unsafe { + crate::pr_info!( + "[kernel_execve] trapframe: sepc={:#x}, sp={:#x}, sstatus={:#x}, a0={:#x}, a1={:#x}, a2={:#x}", + (*tfp).sepc, + (*tfp).x2_sp, + (*tfp).sstatus, + (*tfp).x10_a0, + (*tfp).x11_a1, + (*tfp).x12_a2, + ); + } +} diff --git a/os/src/arch/riscv/mm/mod.rs b/os/src/arch/riscv/mm/mod.rs index 4b22d785..a6be4e0d 100644 --- a/os/src/arch/riscv/mm/mod.rs +++ b/os/src/arch/riscv/mm/mod.rs @@ -20,6 +20,7 @@ mod page_table; // 模块:页表 mod page_table_entry; // 模块:页表项 +use crate::arch::address::{PA, VA}; pub use page_table::{PageTableInner, TlbBatchContext}; // 导出:页表内部结构和TLB批处理上下文 pub use page_table_entry::PageTableEntry; // 导出:页表项结构体 @@ -48,8 +49,8 @@ pub const PADDR_MASK: usize = 0x0000_003f_ffff_ffff; /// # 注意 /// /// 此函数必须在所有架构特定的内存管理模块中实现。 -pub const unsafe fn vaddr_to_paddr(vaddr: usize) -> usize { - vaddr & PADDR_MASK +pub const unsafe fn va_to_pa(va: VA) -> PA { + PA::from_usize(va.as_usize() & PADDR_MASK) } /// 转换物理地址到虚拟地址 @@ -65,6 +66,6 @@ pub const unsafe fn vaddr_to_paddr(vaddr: usize) -> usize { /// # 注意 /// /// 此函数必须在所有架构特定的内存管理模块中实现。 -pub const fn paddr_to_vaddr(paddr: usize) -> usize { - paddr | VADDR_START +pub const fn pa_to_va(pa: PA) -> VA { + VA::from_usize(pa.as_usize() | VADDR_START) } diff --git a/os/src/arch/riscv/mm/page_table.rs b/os/src/arch/riscv/mm/page_table.rs index 36bdf99d..188b7343 100644 --- a/os/src/arch/riscv/mm/page_table.rs +++ b/os/src/arch/riscv/mm/page_table.rs @@ -1,7 +1,7 @@ // TODO: 这个模块的安全性论证没有完成 use super::PageTableEntry; use crate::arch::ipi::send_tlb_flush_ipi_all; -use crate::mm::address::{ConvertablePaddr, Paddr, PageNum, Ppn, UsizeConvert, Vaddr, Vpn}; +use crate::mm::address::{ConvertablePA, PA, PageNum, Ppn, UsizeConvert, VA, Vpn}; use crate::mm::frame_allocator::{FrameTracker, alloc_frame}; use crate::mm::page_table::{ PageSize, PageTableEntry as PageTableEntryTrait, PageTableInner as PageTableInnerTrait, @@ -133,7 +133,7 @@ impl PageTableInnerTrait for PageTableInner { // Unsafe: 将 PPN 转换为虚拟地址并获取页表项数组的不可变引用 let pte_array = unsafe { core::slice::from_raw_parts( - ppn.start_addr().to_vaddr().as_usize() as *const PageTableEntry, + ppn.start_addr().to_va().as_usize() as *const PageTableEntry, 512, // 每级页表有 512 个 PTE ) }; @@ -164,7 +164,7 @@ impl PageTableInnerTrait for PageTableInner { } // 虚拟地址到物理地址的转换 (Translate) - fn translate(&self, vaddr: Vaddr) -> Option { + fn translate(&self, vaddr: VA) -> Option { // 注意:translate 必须使用 floor(页内地址应落在当前页),否则会把非对齐地址错误映射到下一页。 let vpn = Vpn::from_addr_floor(vaddr); // 页内偏移量:低 12 位 @@ -189,7 +189,7 @@ impl PageTableInnerTrait for PageTableInner { _ => ppn.start_addr().as_usize(), // 默认按 4K 页处理基地址 }; // 物理地址 = 物理页基地址 + 页内偏移 - Some(Paddr::from_usize(paddr_base + offset)) + Some(PA::from_usize(paddr_base + offset)) } Err(_) => None, } @@ -229,7 +229,7 @@ impl PageTableInnerTrait for PageTableInner { // Unsafe: 获取可变的页表项数组引用 let pte_array = unsafe { core::slice::from_raw_parts_mut( - current_ppn.start_addr().to_vaddr().as_usize() as *mut PageTableEntry, + current_ppn.start_addr().to_va().as_usize() as *mut PageTableEntry, 512, ) }; @@ -255,7 +255,7 @@ impl PageTableInnerTrait for PageTableInner { // Unsafe: 获取可变的页表项数组引用并清零 let new_table = unsafe { core::slice::from_raw_parts_mut( - new_ppn.start_addr().to_vaddr().as_usize() as *mut PageTableEntry, + new_ppn.start_addr().to_va().as_usize() as *mut PageTableEntry, 512, ) }; @@ -291,7 +291,7 @@ impl PageTableInnerTrait for PageTableInner { // Unsafe: 获取可变的页表项数组引用 let pte_array = unsafe { core::slice::from_raw_parts_mut( - current_ppn.start_addr().to_vaddr().as_usize() as *mut PageTableEntry, + current_ppn.start_addr().to_va().as_usize() as *mut PageTableEntry, 512, ) }; @@ -341,7 +341,7 @@ impl PageTableInnerTrait for PageTableInner { // Unsafe: 获取可变的页表项数组引用 let pte_array = unsafe { core::slice::from_raw_parts_mut( - current_ppn.start_addr().to_vaddr().as_usize() as *mut PageTableEntry, + current_ppn.start_addr().to_va().as_usize() as *mut PageTableEntry, 512, ) }; @@ -378,7 +378,7 @@ impl PageTableInnerTrait for PageTableInner { // Unsafe: 获取页表项数组的不可变引用 let pte_array = unsafe { core::slice::from_raw_parts( - ppn.start_addr().to_vaddr().as_usize() as *const PageTableEntry, + ppn.start_addr().to_va().as_usize() as *const PageTableEntry, 512, ) }; diff --git a/os/src/arch/riscv/mod.rs b/os/src/arch/riscv/mod.rs index 606390be..d8bed57d 100644 --- a/os/src/arch/riscv/mod.rs +++ b/os/src/arch/riscv/mod.rs @@ -12,10 +12,12 @@ pub mod platform; pub mod timer; pub mod trap; -use crate::impl_arch_common; +use crate::{impl_arch, impl_platform}; -impl_arch_common!( +impl_arch!( cpu_ops::Riscv64, memory::Riscv64ProcessAddressSpace, memory::Riscv64KernelAddressSpace ); + +impl_platform!(cpu_ops::Riscv64); diff --git a/os/src/arch/riscv/platform.rs b/os/src/arch/riscv/platform.rs index 959b374b..f8f13100 100644 --- a/os/src/arch/riscv/platform.rs +++ b/os/src/arch/riscv/platform.rs @@ -98,4 +98,3 @@ pub fn mmio_of(dev: VirtDevice) -> Option<(usize, usize)> { .find(|(d, _, _)| *d as u32 == dev as u32) .map(|(_, b, s)| (*b, *s)) } - diff --git a/os/src/arch/riscv/trap/trap_frame.rs b/os/src/arch/riscv/trap/trap_frame.rs index 57b2d507..ee16e5d1 100644 --- a/os/src/arch/riscv/trap/trap_frame.rs +++ b/os/src/arch/riscv/trap/trap_frame.rs @@ -266,6 +266,28 @@ impl TrapFrame { // x1_ra is 0 } + /// 设置用户态 TrapFrame(架构无关 execve 包装)。 + pub fn set_exec_trap_frame_from_layout( + &mut self, + entry: usize, + kernel_sp: usize, + layout: &crate::arch::task::ExecStackLayout, + ) { + self.set_exec_trap_frame( + entry, + layout.sp.as_usize(), + kernel_sp, + layout.argc, + layout.argv.as_usize(), + layout.envp.as_usize(), + ); + } + + /// 设置用户态 TLS/thread pointer。 + pub fn set_tls(&mut self, tls: usize) { + self.x4_tp = tls; + } + /// 设置 fork 后子进程的 TrapFrame /// # 参数: /// * `tpr`: 父进程的 TrapFrame 引用 diff --git a/os/src/arch/riscv/trap/trap_handler.rs b/os/src/arch/riscv/trap/trap_handler.rs index b55dbe7e..5036ece4 100644 --- a/os/src/arch/riscv/trap/trap_handler.rs +++ b/os/src/arch/riscv/trap/trap_handler.rs @@ -11,11 +11,11 @@ use riscv::register::sstatus::SPP; use riscv::register::{sepc, sscratch, sstatus, stval}; use crate::arch::constant::SUPERVISOR_EXTERNAL; -use crate::kernel::syscall::dispatch::dispatch_syscall; use crate::arch::timer::{TIMER_TICKS, clock_freq, get_time}; use crate::arch::trap::restore; use crate::device::IRQ_MANAGER; -use crate::kernel::{TIMER, TIMER_QUEUE, schedule, send_signal_process, wake_up_with_block}; +use crate::kernel::syscall::dispatch::dispatch_syscall; +use crate::kernel::{TIMER, TIMER_QUEUE, schedule, send_signal_process, wake_up_task}; /// 陷阱处理程序 /// 从中断处理入口跳转到这里时, @@ -336,7 +336,7 @@ pub fn check_timer() { crate::kernel::syscall::io::wake_poll_waiters(); while let Some(task) = TIMER_QUEUE.lock().pop_due_task(get_time()) { - wake_up_with_block(task); + wake_up_task(task); } while let Some(entry) = TIMER.lock().pop_due_entry(get_time()) { send_signal_process(&entry.task, entry.sig); @@ -359,6 +359,6 @@ pub fn check_timer() { /// 处理设备中断 pub fn check_device() { IRQ_MANAGER - .read() + .lock() .try_handle_interrupt(Some(SUPERVISOR_EXTERNAL)); } diff --git a/os/src/arch/task.rs b/os/src/arch/task.rs new file mode 100644 index 00000000..c592bbc5 --- /dev/null +++ b/os/src/arch/task.rs @@ -0,0 +1,18 @@ +//! Architecture-neutral task setup data. + +use crate::arch::address::VA; + +/// Result of laying out a new userspace stack for `execve`. +#[derive(Debug, Clone, Copy)] +pub struct ExecStackLayout { + /// Initial userspace stack pointer. + pub sp: VA, + /// Argument count. + pub argc: usize, + /// Userspace address of the argv vector. + pub argv: VA, + /// Userspace address of the envp vector. + pub envp: VA, + /// Architecture-specific thread pointer/TLS value. + pub tls: VA, +} diff --git a/os/src/console.rs b/os/src/console.rs index 67c9b016..3145384a 100644 --- a/os/src/console.rs +++ b/os/src/console.rs @@ -7,7 +7,7 @@ use core::fmt::{self, Write}; use core::sync::atomic::{AtomicBool, Ordering}; -use crate::arch::Arch; +use crate::arch::Platform; use crate::sync::SpinLock; /// 控制台是否已切换到运行时模式 diff --git a/os/src/device/block/virtio_blk.rs b/os/src/device/block/virtio_blk.rs index 76d5f287..2643d250 100644 --- a/os/src/device/block/virtio_blk.rs +++ b/os/src/device/block/virtio_blk.rs @@ -135,7 +135,7 @@ pub fn init(transport: MmioTransport<'static>) { let blk = VirtIOBlk::new(transport).expect("failed to init blk driver"); let driver = Arc::new(VirtIOBlkDriver(Mutex::new(blk))); DRIVERS.write().push(driver.clone()); - IRQ_MANAGER.write().register_all(driver.clone()); + IRQ_MANAGER.lock().register_all(driver.clone()); BLK_DRIVERS.write().push(driver); pr_info!("[Device] Block driver (virtio-blk) is initialized"); } @@ -145,7 +145,7 @@ pub fn init_pci(transport: PciTransport) { let blk = VirtIOBlk::new(transport).expect("failed to init pci blk driver"); let driver = Arc::new(VirtIOBlkPciDriver(Mutex::new(blk))); DRIVERS.write().push(driver.clone()); - IRQ_MANAGER.write().register_all(driver.clone()); + IRQ_MANAGER.lock().register_all(driver.clone()); BLK_DRIVERS.write().push(driver); pr_info!("[Device] Block driver (virtio-blk-pci) is initialized"); } diff --git a/os/src/device/bus/pcie.rs b/os/src/device/bus/pcie.rs index f5cddda4..4c7dff75 100644 --- a/os/src/device/bus/pcie.rs +++ b/os/src/device/bus/pcie.rs @@ -5,7 +5,7 @@ use crate::{ device::{block::virtio_blk, device_tree::FDT, net::virtio_net}, kernel::current_memory_space, mm::{ - address::{ConvertablePaddr, Paddr, UsizeConvert}, + address::{ConvertablePA, PA, VA}, page_table::PagingError, }, pr_info, pr_warn, @@ -31,13 +31,13 @@ pub struct PciDriver {} #[derive(Clone, Copy)] pub struct PcieHost { /// ECAM 物理地址 - ecam_paddr: usize, + ecam_paddr: PA, /// ECAM 虚拟地址 - ecam_vaddr: usize, + ecam_vaddr: VA, /// ECAM 大小 ecam_size: usize, /// MMIO 基地址 - mmio_base: usize, + mmio_base: PA, /// MMIO 大小 mmio_size: usize, /// 总线起始号 @@ -248,13 +248,15 @@ impl PcieHost { mmio_size ); - let ecam_vaddr = Paddr::to_vaddr(&Paddr::from_usize(ecam_base)).as_usize(); + let ecam_paddr = PA::from_usize(ecam_base); + let ecam_vaddr = ecam_paddr.to_va(); + let mmio_paddr = PA::from_usize(mmio_base); Some(Self { - ecam_paddr: ecam_base, + ecam_paddr, ecam_vaddr, ecam_size, - mmio_base, + mmio_base: mmio_paddr, mmio_size, bus_start, bus_end, @@ -265,13 +267,14 @@ impl PcieHost { pub fn from_platform_defaults() -> Option { let (ecam_base, ecam_size) = mmio_of(VirtDevice::VirtPcieEcam)?; let (mmio_base, mmio_size) = mmio_of(VirtDevice::VirtPcieMmio)?; - let ecam_vaddr = Paddr::to_vaddr(&Paddr::from_usize(ecam_base)).as_usize(); + let ecam_paddr = PA::from_usize(ecam_base); + let ecam_vaddr = ecam_paddr.to_va(); Some(Self { - ecam_paddr: ecam_base, + ecam_paddr, ecam_vaddr, ecam_size, - mmio_base, + mmio_base: PA::from_usize(mmio_base), mmio_size, bus_start: 0, bus_end: 255, // 后续可由 FDT 的 bus-range 收缩 @@ -286,7 +289,7 @@ impl PcieHost { | ((dev as usize) << 15) | ((func as usize) << 12) | ((offset as usize) & 0xfff); - (self.ecam_vaddr + off) as *mut u32 + (self.ecam_vaddr.as_usize() + off) as *mut u32 } /// 读取 PCIe 配置空间 @@ -305,9 +308,9 @@ impl PcieHost { pub fn enumerate(&self) { pr_info!( "[PCIe] ECAM @ {:#x} (size {:#x}), MMIO @ {:#x} (size {:#x})", - self.ecam_paddr, + self.ecam_paddr.as_usize(), self.ecam_size, - self.mmio_base, + self.mmio_base.as_usize(), self.mmio_size ); @@ -377,19 +380,19 @@ pub fn init_virtio_pci() { let ecam_vaddr = match current_memory_space() .lock() - .map_mmio(Paddr::from_usize(host.ecam_paddr), host.ecam_size) + .map_mmio(host.ecam_paddr, host.ecam_size) { Ok(vaddr) => vaddr.as_usize(), - Err(PagingError::AlreadyMapped) => crate::arch::paddr_to_vaddr(host.ecam_paddr), + Err(PagingError::AlreadyMapped) => crate::arch::pa_to_va(host.ecam_paddr).as_usize(), Err(e) => { pr_warn!("[PCIe] failed to map ECAM: {:?}", e); - crate::arch::paddr_to_vaddr(host.ecam_paddr) + crate::arch::pa_to_va(host.ecam_paddr).as_usize() } }; match current_memory_space() .lock() - .map_mmio(Paddr::from_usize(host.mmio_base), host.mmio_size) + .map_mmio(host.mmio_base, host.mmio_size) { Ok(_) | Err(PagingError::AlreadyMapped) => {} Err(e) => { @@ -400,7 +403,7 @@ pub fn init_virtio_pci() { let cam = unsafe { MmioCam::new(ecam_vaddr as *mut u8, Cam::Ecam) }; let mut root = PciRoot::new(cam); let mut next_mmio = host.mmio_base; - let mmio_end = host.mmio_base.saturating_add(host.mmio_size); + let mmio_end = PA::from_usize(host.mmio_base.as_usize().saturating_add(host.mmio_size)); for bus in host.bus_start..=host.bus_end { for (df, info) in root.enumerate_bus(bus) { @@ -444,8 +447,8 @@ pub fn init_virtio_pci() { fn allocate_bars( root: &mut PciRoot>, df: virtio_drivers::transport::pci::bus::DeviceFunction, - next_mmio: &mut usize, - mmio_end: usize, + next_mmio: &mut PA, + mmio_end: PA, ) { let bars = match root.bars(df) { Ok(bars) => bars, @@ -483,8 +486,8 @@ fn allocate_bars( } let size_usize = size as usize; let align = size_usize.max(0x1000); - let base = align_up(*next_mmio, align); - if base.saturating_add(size_usize) > mmio_end { + let base = align_up(next_mmio.as_usize(), align); + if base.saturating_add(size_usize) > mmio_end.as_usize() { pr_warn!( "[PCIe] MMIO window exhausted for BAR{} (need {:#x} bytes)", bar_index, @@ -497,7 +500,7 @@ fn allocate_bars( MemoryBarType::Width64 => root.set_bar_64(df, bar_index, base as u64), _ => root.set_bar_32(df, bar_index, base as u32), } - *next_mmio = base.saturating_add(size_usize); + *next_mmio = PA::from_usize(base.saturating_add(size_usize)); } bar_index += step; diff --git a/os/src/device/bus/virtio_mmio.rs b/os/src/device/bus/virtio_mmio.rs index c5f15bca..bf217fca 100644 --- a/os/src/device/bus/virtio_mmio.rs +++ b/os/src/device/bus/virtio_mmio.rs @@ -17,13 +17,13 @@ use crate::{ net::virtio_net, }, kernel::current_memory_space, - mm::address::{Paddr, UsizeConvert}, + mm::address::PA, pr_warn, }; pub fn driver_init() { DEVICE_TREE_REGISTRY - .write() + .lock() .insert("virtio,mmio", virtio_probe); } @@ -46,7 +46,7 @@ fn virtio_probe(node: &FdtNode) { //判 断 virtio 设 备 类 型 let vaddr = current_memory_space() .lock() - .map_mmio(Paddr::from_usize(paddr), size) + .map_mmio(PA::from_usize(paddr), size) .ok() .expect("Failed to map MMIO region"); let header = NonNull::new(vaddr.as_usize() as *mut VirtIOHeader).unwrap(); diff --git a/os/src/device/device_tree.rs b/os/src/device/device_tree.rs index 8e320b80..ca6a2407 100644 --- a/os/src/device/device_tree.rs +++ b/os/src/device/device_tree.rs @@ -3,9 +3,9 @@ use crate::{ device::{CMDLINE, irq::IntcDriver}, kernel::{CLOCK_FREQ, NUM_CPU}, - mm::address::{ConvertablePaddr, Paddr, UsizeConvert}, + mm::address::{ConvertablePA, PA}, pr_info, pr_warn, - sync::RwLock, + sync::SpinLock, }; use alloc::{collections::btree_map::BTreeMap, string::String, sync::Arc}; use fdt::{Fdt, node::FdtNode}; @@ -19,7 +19,7 @@ lazy_static::lazy_static! { /// XXX: 是否需要这个? pub static ref FDT: Fdt<'static> = { unsafe { - let addr = Paddr::to_vaddr(&Paddr::from_usize(DTP)); + let addr = PA::to_va(&PA::from_usize(DTP)); fdt::Fdt::from_ptr(addr.as_usize() as *mut u8).expect("Failed to parse device tree") } }; @@ -27,14 +27,14 @@ lazy_static::lazy_static! { /// Compatible 字符串到探测函数的映射表 /// 键为设备的 compatible 字符串,值为对应的探测函数 /// 用于在设备树中查找和初始化设备 - pub static ref DEVICE_TREE_REGISTRY: RwLock> = - RwLock::new(BTreeMap::new()); + pub static ref DEVICE_TREE_REGISTRY: SpinLock> = + SpinLock::new(BTreeMap::new()); /// 设备树中断控制器映射表 /// 键为中断控制器的 phandle,值为对应的中断控制器驱动程序 /// 用于在设备树中查找和管理中断控制器 - pub static ref DEVICE_TREE_INTC: RwLock>> = - RwLock::new(BTreeMap::new()); + pub static ref DEVICE_TREE_INTC: SpinLock>> = + SpinLock::new(BTreeMap::new()); } /// 早期初始化: 只解析 CPU 数量和时钟频率 @@ -110,7 +110,7 @@ fn walk_dt(fdt: &Fdt, intc_only: bool) { && node.property("interrupt-controller").is_some() == intc_only { pr_info!("[Device] Found device: {}", node.name); - let registry = DEVICE_TREE_REGISTRY.read(); + let registry = DEVICE_TREE_REGISTRY.lock(); for c in compatible.all() { if let Some(f) = registry.get(c) { f(&node); diff --git a/os/src/device/irq/plic.rs b/os/src/device/irq/plic.rs index 580481a4..b5601ad5 100644 --- a/os/src/device/irq/plic.rs +++ b/os/src/device/irq/plic.rs @@ -8,9 +8,9 @@ use crate::device::device_tree::{DEVICE_TREE_INTC, DEVICE_TREE_REGISTRY}; use crate::device::irq::IntcDriver; use crate::device::{DeviceType, Driver, IRQ_MANAGER}; use crate::kernel::current_memory_space; -use crate::mm::address::{Paddr, UsizeConvert}; +use crate::mm::address::{PA, VA}; use crate::{pr_info, pr_warn}; -use crate::{sync::SpinLock as Mutex, util::read, util::write}; +use crate::{sync::SpinLock, util::read, util::write}; use alloc::format; use alloc::string::String; use alloc::sync::Arc; @@ -18,8 +18,8 @@ use fdt::node::FdtNode; /// Platform Level Interrupt Controller (PLIC) 结构体 pub struct Plic { - base: usize, - manager: Mutex, + base: VA, + manager: SpinLock, } impl Driver for Plic { @@ -29,12 +29,13 @@ impl Driver for Plic { /// # 返回值 /// 如果中断被处理则返回 true,否则返回 false fn try_handle_interrupt(&self, _irq: Option) -> bool { - let pending: u32 = read(self.base + 0x1000); + let base = self.base.as_usize(); + let pending: u32 = read(base + 0x1000); if pending != 0 { - let claim: u32 = read(self.base + 0x201004); + let claim: u32 = read(base + 0x201004); let manager = self.manager.lock(); let res = manager.try_handle_interrupt(Some(claim as usize)); - write(self.base + 0x201004, claim); + write(base + 0x201004, claim); res } else { false @@ -52,7 +53,7 @@ impl Driver for Plic { /// # 返回值 /// 设备标识符字符串 fn get_id(&self) -> String { - format!("plic_{}", self.base) + format!("plic_{:#x}", self.base.as_usize()) } } @@ -63,10 +64,10 @@ impl IntcDriver for Plic { /// * `driver` - 要注册的驱动程序 fn register_local_irq(&self, irq: usize, driver: Arc) { write( - self.base + 0x2080, - read::(self.base + 0x2080) | (1 << irq), + self.base.as_usize() + 0x2080, + read::(self.base.as_usize() + 0x2080) | (1 << irq), ); - write(self.base + irq * 4, 7); + write(self.base.as_usize() + irq * 4, 7); let mut manager = self.manager.lock(); manager.register_irq(irq, driver); } @@ -85,7 +86,7 @@ pub fn init_dt(dt: &FdtNode) { } let vaddr = current_memory_space() .lock() - .map_mmio(Paddr::from_usize(paddr), size) + .map_mmio(PA::from_usize(paddr), size) .ok() .expect("Failed to map MMIO region"); let phandle = dt @@ -93,22 +94,21 @@ pub fn init_dt(dt: &FdtNode) { .unwrap() .as_usize() .expect("Failed to convert 'phandle' property to usize"); - let base = vaddr.as_usize(); let plic = Arc::new(Plic { - base, - manager: Mutex::new(IrqManager::new(false)), + base: vaddr, + manager: SpinLock::new(IrqManager::new(false)), }); // set prio threshold to 0 for context 1 - write(base + 0x201000, 0); + write(vaddr.as_usize() + 0x201000, 0); DRIVERS.write().push(plic.clone()); // register under root irq manager IRQ_MANAGER - .write() + .lock() .register_irq(SUPERVISOR_EXTERNAL, plic.clone()); // register interrupt controller DEVICE_TREE_INTC - .write() + .lock() .insert(phandle.try_into().unwrap(), plic); } else { pr_warn!( @@ -124,5 +124,5 @@ pub fn init_dt(dt: &FdtNode) { /// 注册 PLIC 驱动初始化函数 pub fn driver_init() { - DEVICE_TREE_REGISTRY.write().insert("riscv,plic0", init_dt); + DEVICE_TREE_REGISTRY.lock().insert("riscv,plic0", init_dt); } diff --git a/os/src/device/mod.rs b/os/src/device/mod.rs index 5f61ec1e..d72c7dc0 100644 --- a/os/src/device/mod.rs +++ b/os/src/device/mod.rs @@ -15,6 +15,7 @@ pub mod virtio_hal; pub mod device_tree; use crate::sync::RwLock; +use crate::sync::SpinLock; use alloc::sync::Arc; pub use block::ram_disk::RamDisk; @@ -101,8 +102,8 @@ lazy_static! { pub static ref DRIVERS: RwLock>> = RwLock::new(Vec::new()); pub static ref BLK_DRIVERS: RwLock>> = RwLock::new(Vec::new()); pub static ref RTC_DRIVERS: RwLock>> = RwLock::new(Vec::new()); - pub static ref SERIAL_DRIVERS: RwLock>> = RwLock::new(Vec::new()); - pub static ref IRQ_MANAGER: RwLock = RwLock::new(irq::IrqManager::new(true)); + pub static ref SERIAL_DRIVERS: SpinLock>> = SpinLock::new(Vec::new()); + pub static ref IRQ_MANAGER: SpinLock = SpinLock::new(irq::IrqManager::new(true)); } lazy_static! { diff --git a/os/src/device/rtc/rtc_goldfish.rs b/os/src/device/rtc/rtc_goldfish.rs index 8a1d9165..980167ae 100644 --- a/os/src/device/rtc/rtc_goldfish.rs +++ b/os/src/device/rtc/rtc_goldfish.rs @@ -6,7 +6,7 @@ use crate::{ DRIVERS, DeviceType, Driver, RTC_DRIVERS, device_tree::DEVICE_TREE_REGISTRY, rtc::RtcDriver, }, kernel::current_memory_space, - mm::address::{Paddr, UsizeConvert}, + mm::address::{PA, VA}, pr_info, pr_warn, util::read, }; @@ -15,7 +15,7 @@ const TIMER_TIME_LOW: usize = 0x00; const TIMER_TIME_HIGH: usize = 0x04; pub struct RtcGoldfish { - base: usize, + base: VA, } impl Driver for RtcGoldfish { @@ -39,8 +39,9 @@ impl Driver for RtcGoldfish { impl RtcDriver for RtcGoldfish { // read seconds since 1970-01-01 fn read_epoch(&self) -> u64 { - let low: u32 = read(self.base + TIMER_TIME_LOW); - let high: u32 = read(self.base + TIMER_TIME_HIGH); + let base = self.base.as_usize(); + let low: u32 = read(base + TIMER_TIME_LOW); + let high: u32 = read(base + TIMER_TIME_HIGH); let ns = ((high as u64) << 32) | (low as u64); ns / 1_000_000_000u64 } @@ -62,12 +63,10 @@ fn init_dt(dt: &FdtNode) { } let vaddr = current_memory_space() .lock() - .map_mmio(Paddr::from_usize(paddr), size) + .map_mmio(PA::from_usize(paddr), size) .ok() .expect("Failed to map MMIO region for goldfish-rtc"); - let rtc = Arc::new(RtcGoldfish { - base: vaddr.as_usize(), - }); + let rtc = Arc::new(RtcGoldfish { base: vaddr }); DRIVERS.write().push(rtc.clone()); RTC_DRIVERS.write().push(rtc); pr_info!("[Device] RTC Goldfish initialized"); @@ -75,6 +74,6 @@ fn init_dt(dt: &FdtNode) { pub fn driver_init() { DEVICE_TREE_REGISTRY - .write() + .lock() .insert("google,goldfish-rtc", init_dt); } diff --git a/os/src/device/serial/uart16550.rs b/os/src/device/serial/uart16550.rs index 9ad8fbf9..9f2aae85 100644 --- a/os/src/device/serial/uart16550.rs +++ b/os/src/device/serial/uart16550.rs @@ -10,7 +10,7 @@ use crate::{ device_tree::DEVICE_TREE_REGISTRY, serial::SerialDriver, }, kernel::current_memory_space, - mm::address::{Paddr, UsizeConvert}, + mm::address::PA, pr_info, pr_warn, sync::SpinLock, }; @@ -71,7 +71,7 @@ pub fn init(node: &FdtNode) { } let vaddr = current_memory_space() .lock() - .map_mmio(Paddr::from_usize(paddr), size) + .map_mmio(PA::from_usize(paddr), size) .ok() .expect("Failed to map MMIO region"); let mut serial_port = unsafe { MmioSerialPort::new(vaddr.as_usize()) }; @@ -80,11 +80,11 @@ pub fn init(node: &FdtNode) { serial_port: SpinLock::new(serial_port), }); DRIVERS.write().push(driver.clone()); - SERIAL_DRIVERS.write().push(driver.clone()); + SERIAL_DRIVERS.lock().push(driver.clone()); uart_console::init(driver); pr_info!("[Device] Serial driver (uart16550) is initialized"); } pub fn driver_init() { - DEVICE_TREE_REGISTRY.write().insert("ns16550a", init); + DEVICE_TREE_REGISTRY.lock().insert("ns16550a", init); } diff --git a/os/src/device/virtio_hal.rs b/os/src/device/virtio_hal.rs index 430f728f..e88f6ef1 100644 --- a/os/src/device/virtio_hal.rs +++ b/os/src/device/virtio_hal.rs @@ -1,6 +1,6 @@ //! HAL (硬件抽象层) 实现,用于适配 virtio-drivers 0.12.0 库 -use crate::mm::address::{ConvertablePaddr, PageNum, UsizeConvert}; +use crate::mm::address::{ConvertablePA, PA, PageNum, VA}; use crate::mm::frame_allocator::FrameRangeTracker; use crate::sync::SpinLock; use alloc::collections::btree_map::BTreeMap; @@ -36,7 +36,7 @@ unsafe impl Hal for VirtIOHal { let phys_addr = PhysAddr::from(start_ppn.start_addr().as_usize() as u64); // 将物理地址转换为虚拟地址 - let virt_addr = unsafe { start_ppn.start_addr().to_vaddr().as_mut_ptr::() }; + let virt_addr = start_ppn.start_addr().to_va().as_mut_ptr::(); let virt_ptr = NonNull::new(virt_addr).unwrap(); // 清零 DMA 缓冲区(VirtIO HAL trait 要求) @@ -77,20 +77,20 @@ unsafe impl Hal for VirtIOHal { /// 将MMIO物理地址转换为虚拟地址 unsafe fn mmio_phys_to_virt(paddr: PhysAddr, _size: usize) -> NonNull { // 提取物理地址值并使用架构特定的转换函数 - let phys_addr = paddr as usize; - let virt = crate::arch::paddr_to_vaddr(phys_addr); + let phys_addr = PA::from_usize(paddr as usize); + let virt = crate::arch::pa_to_va(phys_addr); // 验证虚拟地址的合法性 - NonNull::new(virt as *mut u8).expect("mmio_phys_to_virt returned null pointer") + NonNull::new(virt.as_usize() as *mut u8).expect("mmio_phys_to_virt returned null pointer") } /// 共享内存区域给设备,并返回设备可访问的物理地址 unsafe fn share(buffer: NonNull<[u8]>, _direction: BufferDirection) -> PhysAddr { let vaddr = buffer.as_ptr() as *const u8 as usize; - let paddr = unsafe { crate::arch::vaddr_to_paddr(vaddr) }; + let paddr = unsafe { crate::arch::va_to_pa(VA::from_usize(vaddr)) }; - PhysAddr::from(paddr as u64) + PhysAddr::from(paddr.as_usize() as u64) } /// 取消共享内存区域,并在必要时将数据复制回原始缓冲区 diff --git a/os/src/fs/proc/generators/cpuinfo.rs b/os/src/fs/proc/generators/cpuinfo.rs index c3d833d2..f721421e 100644 --- a/os/src/fs/proc/generators/cpuinfo.rs +++ b/os/src/fs/proc/generators/cpuinfo.rs @@ -7,28 +7,6 @@ pub struct CpuinfoGenerator; impl ContentGenerator for CpuinfoGenerator { fn generate(&self) -> Result, FsError> { - Ok(proc_cpuinfo()) + Ok(crate::arch::abi::proc_cpuinfo_bytes().to_vec()) } } - -#[cfg(target_arch = "riscv64")] -fn proc_cpuinfo() -> Vec { - b"processor\t: 0\n\ -hart\t\t: 0\n\ -isa\t\t: rv64imafdcsu\n\ -mmu\t\t: sv39\n\ -uarch\t\t: qemu,virt\n\n" - .to_vec() -} - -#[cfg(target_arch = "loongarch64")] -fn proc_cpuinfo() -> Vec { - b"processor\t: 0\n\ -arch\t\t: loongarch64\n\n" - .to_vec() -} - -#[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] -fn proc_cpuinfo() -> Vec { - b"processor\t: 0\narch\t\t: mock\n\n".to_vec() -} diff --git a/os/src/fs/proc/generators/process/maps.rs b/os/src/fs/proc/generators/process/maps.rs index 30472ed6..94baa5eb 100644 --- a/os/src/fs/proc/generators/process/maps.rs +++ b/os/src/fs/proc/generators/process/maps.rs @@ -4,7 +4,7 @@ use crate::{ config::PAGE_SIZE, fs::proc::ContentGenerator, kernel::TaskStruct, - mm::address::{PageNum, UsizeConvert}, + mm::address::PageNum, mm::memory_space::mapping_area::{AreaType, MapType}, sync::SpinLock, vfs::FsError, diff --git a/os/src/fs/proc/inode.rs b/os/src/fs/proc/inode.rs index 63ee830b..e0337c14 100644 --- a/os/src/fs/proc/inode.rs +++ b/os/src/fs/proc/inode.rs @@ -306,13 +306,11 @@ impl ProcInode { impl Inode for ProcInode { fn metadata(&self) -> Result { let mut meta = self.metadata.lock().clone(); - // 对符号链接,返回更符合 Linux 预期的 size(目标路径长度)。 + // 对静态符号链接,返回目标路径长度;动态符号链接的 size 保持创建时的值(动态解析需要 task 上下文) if meta.inode_type == InodeType::Symlink { - meta.size = match &self.content { - ProcInodeContent::Symlink(target) => target.len(), - ProcInodeContent::DynamicSymlink(generator) => generator().len(), - _ => meta.size, - }; + if let ProcInodeContent::Symlink(target) = &self.content { + meta.size = target.len(); + } } Ok(meta) } diff --git a/os/src/fs/tmpfs/inode.rs b/os/src/fs/tmpfs/inode.rs index 2261777f..422e996e 100644 --- a/os/src/fs/tmpfs/inode.rs +++ b/os/src/fs/tmpfs/inode.rs @@ -8,7 +8,7 @@ use alloc::sync::{Arc, Weak}; use alloc::vec::Vec; use crate::config::PAGE_SIZE; -use crate::mm::address::{ConvertablePaddr, PageNum, UsizeConvert}; +use crate::mm::address::{ConvertablePA, PageNum}; use crate::mm::frame_allocator::{FrameTracker, alloc_frame}; use crate::sync::{Mutex, SpinLock}; use crate::uapi::time::TimeSpec; @@ -226,7 +226,7 @@ impl Inode for TmpfsInode { } else { // 通过内核直接映射读取 let frame = data[page_index].as_ref().unwrap(); - let kernel_vaddr = frame.ppn().start_addr().to_vaddr(); + let kernel_vaddr = frame.ppn().start_addr().to_va(); unsafe { core::ptr::copy_nonoverlapping( @@ -286,7 +286,7 @@ impl Inode for TmpfsInode { // 通过内核直接映射写入 let frame = data[page_index].as_ref().unwrap(); - let kernel_vaddr = frame.ppn().start_addr().to_vaddr(); + let kernel_vaddr = frame.ppn().start_addr().to_va(); unsafe { core::ptr::copy_nonoverlapping( diff --git a/os/src/ipc/signal.rs b/os/src/ipc/signal.rs index 69045d72..f9a34a18 100644 --- a/os/src/ipc/signal.rs +++ b/os/src/ipc/signal.rs @@ -18,7 +18,7 @@ use crate::{ }, kernel::{ SharedTask, TASK_MANAGER, TaskManagerTrait, TaskState, current_cpu, current_task, - exit_process, exit_task_with_block, sleep_task_with_block, wake_up_with_block, yield_task, + exit_process, exit_task, sleep_task, wake_up_task, yield_task, }, pr_err, uapi::signal::*, @@ -264,7 +264,7 @@ fn sig_stop(sig_num: usize) { } // 从运行队列移除(不可被信号唤醒,外部需用 SIGCONT) - sleep_task_with_block(task, false); + sleep_task(task, false); } yield_task(); } @@ -283,7 +283,7 @@ fn sig_continue(sig_num: usize) { } } if resume { - wake_up_with_block(task); + wake_up_task(task); } } } diff --git a/os/src/kernel/boot.rs b/os/src/kernel/boot.rs new file mode 100644 index 00000000..40359576 --- /dev/null +++ b/os/src/kernel/boot.rs @@ -0,0 +1,235 @@ +//! 架构无关的启动代码 +//! +//! 包含内核早期初始化、init/idle 任务创建等所有架构共享的启动逻辑。 +//! 新架构移植时只需实现 arch::boot::main() 和 idle_loop(),其余自动复用。 + +use alloc::sync::Arc; + +use crate::{ + arch::CpuOps, + 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, + }, + mm::frame_allocator::{alloc_contig_frames, alloc_frame}, + pr_err, pr_info, pr_warn, + sync::SpinLock, + uapi::{ + resource::{INIT_RLIMITS, RlimitStruct}, + signal::SignalFlags, + uts_namespace::UtsNamespace, + }, + vfs::{create_stdio_files, fd_table::FDTable, get_root_dentry}, +}; + +/// 架构无关的 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(); + } +} + +/// 清除 BSS 段 +/// +/// 将 BSS 段全部置零。通过 Arch 的地址翻译方法访问物理内存。 +pub fn clear_bss() { + unsafe extern "C" { + fn sbss(); + fn ebss(); + } + + let sbss_paddr = + unsafe { crate::arch::va_to_pa(crate::arch::address::VA::from_usize(sbss as usize)) }; + let ebss_paddr = + unsafe { crate::arch::va_to_pa(crate::arch::address::VA::from_usize(ebss as usize)) }; + + (sbss_paddr.as_usize()..ebss_paddr.as_usize()).for_each(|a| unsafe { + let va = crate::arch::pa_to_va(crate::arch::address::PA::from_usize(a)); + (va.as_usize() as *mut u8).write_volatile(0) + }); +} + +/// 创建 init 任务 (PID=1) 并加入调度队列 +/// +/// 调用后 init 任务在运行队列中就绪,调用者应进入 idle_loop 等待 +/// 下一次时钟中断触发调度,由调度器自动选中 init 并切换上下文。 +pub fn rest_init() { + let tid = 1; + let kstack_tracker = alloc_contig_frames(4).expect("rest_init: failed to alloc kstack"); + let trap_frame_tracker = alloc_frame().expect("rest_init: failed to alloc trap_frame"); + let fd_table = FDTable::new(); + let (stdin, stdout, stderr) = create_stdio_files(); + fd_table + .install_at(0, stdin) + .expect("Failed to install stdin"); + fd_table + .install_at(1, stdout) + .expect("Failed to install stdout"); + fd_table + .install_at(2, stderr) + .expect("Failed to install stderr"); + let cwd = get_root_dentry().ok(); + let root = cwd.clone(); + let fs = Arc::new(SpinLock::new(FsStruct::new(cwd, root))); + let mut task = TaskStruct::ktask_create( + tid, + tid, + 0, + TaskStruct::empty_children(), + kstack_tracker, + trap_frame_tracker, + Arc::new(SpinLock::new(SignalHandlerTable::new())), + SignalFlags::empty(), + Arc::new(SpinLock::new(SignalPending::empty())), + Arc::new(SpinLock::new(UtsNamespace::default())), + Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))), + Arc::new(fd_table), + fs, + ); + + let tf = 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()); + } + + task.memory_space = Some(current_memory_space()); + task.on_cpu = Some(0); + let task = task.into_shared(); + + TASK_MANAGER.lock().add_task(task.clone()); + scheduler_of(0).lock().add_task(task); +} + +/// PID = 1: 完成剩余初始化,然后 exec /sbin/init +/// +/// 此时 trap::init() 和 enable_interrupts() 已在 main() 中完成, +/// 调度器正常运行,本函数作为 init 任务入口在 forkret 之后被调度执行。 +fn init() { + create_kthreadd(); + + if let Err(e) = crate::fs::init_ext4_from_block_device() { + pr_err!( + "[Init] Warning: Failed to initialize Ext4 filesystem: {:?}", + e + ); + pr_info!("[Init] Continuing without filesystem..."); + } + + if let Err(e) = crate::net::config::NetworkConfigManager::init_default_interface() { + pr_warn!( + "[Init] Warning: Failed to init default network interface: {:?}", + e + ); + } + + kernel_execve("/sbin/init", &["/sbin/init"], &[]); +} + +/// 内核守护线程 PID = 2 +/// +/// 负责创建内核任务,回收僵尸任务等工作 +fn kthreadd() { + kthread_spawn(kworker); + loop { + sleep_task(current_task(), true); + yield_task(); + } +} + +/// 创建 kthreadd 任务 (PID=2) +fn create_kthreadd() { + let tid = TASK_MANAGER.lock().allocate_tid(); + let kstack_tracker = alloc_contig_frames(4).expect("create_kthreadd: failed to alloc kstack"); + let trap_frame_tracker = alloc_frame().expect("create_kthreadd: failed to alloc trap_frame"); + let (uts, rlimit, fd_table, fs) = { + let task = current_task(); + let t = task.lock(); + ( + t.uts_namespace.clone(), + t.rlimit.clone(), + t.fd_table.clone_table(), + t.fs.lock().clone(), + ) + }; + let task = TaskStruct::ktask_create( + tid, + tid, + 0, + TaskStruct::empty_children(), + kstack_tracker, + trap_frame_tracker, + Arc::new(SpinLock::new(SignalHandlerTable::new())), + SignalFlags::empty(), + Arc::new(SpinLock::new(SignalPending::empty())), + uts, + rlimit, + Arc::new(fd_table), + Arc::new(SpinLock::new(fs)), + ); + + let tf = 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()); + } + let task = task.into_shared(); + TASK_MANAGER.lock().add_task(task.clone()); + task.lock().on_cpu = Some(0); + scheduler_of(0).lock().add_task(task); +} + +/// 为指定 CPU 创建 idle 任务 +/// +/// idle 任务使用 `idle_fn` 作为入口(各架构自行提供 wfi/idle 0 循环)。 +pub fn create_idle_task(cpu_id: usize, idle_fn: fn() -> !) -> crate::kernel::SharedTask { + let tid = TASK_MANAGER.lock().allocate_tid(); + let kstack_tracker = + alloc_contig_frames(1).expect("Failed to allocate kernel stack for idle task"); + let trap_frame_tracker = alloc_frame().expect("Failed to allocate trap frame for idle task"); + + let mut task = TaskStruct::ktask_create( + tid, + tid, + 0, + TaskStruct::empty_children(), + kstack_tracker, + trap_frame_tracker, + Arc::new(SpinLock::new(SignalHandlerTable::new())), + SignalFlags::empty(), + Arc::new(SpinLock::new(SignalPending::empty())), + Arc::new(SpinLock::new(UtsNamespace::default())), + Arc::new(SpinLock::new(RlimitStruct::new(INIT_RLIMITS))), + Arc::new(FDTable::new()), + Arc::new(SpinLock::new(FsStruct::new(None, None))), + ); + + let tf = 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()); + } + + task.on_cpu = Some(cpu_id); + let task = task.into_shared(); + TASK_MANAGER.lock().add_task(task.clone()); + + pr_info!("[SMP] Created idle task {} for CPU {}", tid, cpu_id); + + task +} diff --git a/os/src/kernel/mod.rs b/os/src/kernel/mod.rs index 300af855..ad73b7c7 100644 --- a/os/src/kernel/mod.rs +++ b/os/src/kernel/mod.rs @@ -4,6 +4,7 @@ //! 以及与 CPU 相关的操作 //! 实现内核的核心功能 +pub mod boot; mod cpu; mod scheduler; mod task; diff --git a/os/src/kernel/scheduler/mod.rs b/os/src/kernel/scheduler/mod.rs index 8775f9ff..0ffc191e 100644 --- a/os/src/kernel/scheduler/mod.rs +++ b/os/src/kernel/scheduler/mod.rs @@ -8,11 +8,11 @@ mod wait_queue; use core::sync::atomic::{AtomicUsize, Ordering}; use crate::{ + arch::Arch, arch::kernel::context::Context, config::MAX_CPU_COUNT, - arch::Arch, kernel::{TaskState, TaskStruct, scheduler::rr_scheduler::RRScheduler, task::SharedTask}, - sync::{SpinLock, SpinLockGuard}, + sync::SpinLock, }; pub use task_queue::TaskQueue; @@ -66,20 +66,19 @@ pub trait Scheduler { /// 参数: /// * `task`: 需要终止的任务 fn exit_task(&mut self, task: SharedTask); - /// 带保护地阻塞任务 - /// 修改任务状态并从运行队列中移除 - /// 参数: - /// * `task`: 需要阻塞的任务(带锁保护) - /// * `stask`: 需要阻塞的任务(共享指针) - /// * `receive_signal`: 是否可被信号中断 - /// HACK: 这个函数被设计用来避免信号处理过程中丢失唤醒的问题。 - /// 尽量不要使用该函数,除非你非常清楚自己在做什么 - fn sleep_task_with_guard( + /// 原子地检查条件并睡眠 + /// + /// 在持有调度器锁和 task 锁的情况下执行 `prepare` 闭包。 + /// 如果 `prepare` 返回 `true`(条件满足,不需要睡眠), + /// 则任务保持唤醒并返回 `false`。 + /// 如果 `prepare` 返回 `false`,则将任务设为睡眠态并从运行队列中移除, + /// 返回 `true`。 + fn sleep_task_prepare( &mut self, - task: &mut SpinLockGuard<'_, TaskStruct>, - stask: SharedTask, + task: SharedTask, receive_signal: bool, - ); + prepare: impl FnOnce(&mut crate::kernel::TaskStruct) -> bool, + ) -> bool; } /// 获取当前 CPU 的调度器 @@ -151,7 +150,7 @@ pub fn yield_task() { /// * `task`: 需要阻塞的任务 /// * `receive_signal`: 是否可被信号中断 /// 注意: 该函数仅设置状态,不负责切换任务 -pub fn sleep_task_with_block(task: SharedTask, receive_signal: bool) { +pub fn sleep_task(task: SharedTask, receive_signal: bool) { let cpu_id = { let t = task.lock(); t.on_cpu.unwrap_or_else(crate::arch::cpu_id) @@ -163,7 +162,7 @@ pub fn sleep_task_with_block(task: SharedTask, receive_signal: bool) { /// 修改任务状态并将其添加到运行队列 /// 参数: /// * `task`: 需要唤醒的任务 -pub fn wake_up_with_block(task: SharedTask) { +pub fn wake_up_task(task: SharedTask) { let target_cpu = pick_cpu(); let current_cpu = crate::arch::cpu_id(); let task_tid = { task.lock().tid }; @@ -213,7 +212,7 @@ pub fn wake_up_with_block(task: SharedTask) { /// 修改任务状态并从调度器中移除 /// 参数: /// * `task`: 需要终止的任务 -pub fn exit_task_with_block(task: SharedTask) { +pub fn exit_task(task: SharedTask) { let cpu_id = { let t = task.lock(); t.on_cpu.unwrap_or_else(crate::arch::cpu_id) @@ -221,21 +220,24 @@ pub fn exit_task_with_block(task: SharedTask) { scheduler_of(cpu_id).lock().exit_task(task); } -/// 带保护地阻塞任务 -/// 修改任务状态并从运行队列中移除 -/// 参数: -/// * `task`: 需要阻塞的任务(带锁保护) -/// * `stask`: 需要阻塞的任务(共享指针) -/// * `receive_signal`: 是否可被信号中断 -/// HACK: 这个函数被设计用来避免信号处理过程中丢失唤醒的问题。 -/// 尽量不要使用该函数,除非你非常清楚自己在做什么 -pub fn sleep_task_with_guard_and_block( - task: &mut SpinLockGuard<'_, TaskStruct>, - stask: SharedTask, +/// 原子地检查条件并阻塞任务 +/// +/// 在持有调度器锁和 task 锁的情况下执行 `prepare` 闭包。 +/// 如果 `prepare` 返回 `true`(条件满足),任务保持唤醒并返回 `false`。 +/// 如果 `prepare` 返回 `false`,任务将被设为睡眠态并从运行队列移除, +/// 返回 `true`。 +/// +/// 这消除了 TOCTOU 竞态条件:条件检查和状态转换在锁内原子地完成。 +pub fn sleep_task_prepare( + task: SharedTask, receive_signal: bool, -) { - let cpu_id = task.on_cpu.unwrap_or_else(crate::arch::cpu_id); + prepare: impl FnOnce(&mut TaskStruct) -> bool, +) -> bool { + let cpu_id = { + let t = task.lock(); + t.on_cpu.unwrap_or_else(crate::arch::cpu_id) + }; scheduler_of(cpu_id) .lock() - .sleep_task_with_guard(task, stask, receive_signal); + .sleep_task_prepare(task, receive_signal, prepare) } diff --git a/os/src/kernel/scheduler/rr_scheduler.rs b/os/src/kernel/scheduler/rr_scheduler.rs index 8b57f32e..96448c35 100644 --- a/os/src/kernel/scheduler/rr_scheduler.rs +++ b/os/src/kernel/scheduler/rr_scheduler.rs @@ -219,19 +219,23 @@ impl Scheduler for RRScheduler { self.run_queue.remove_task(&task); } - fn sleep_task_with_guard( + fn sleep_task_prepare( &mut self, - task: &mut crate::sync::SpinLockGuard<'_, crate::kernel::TaskStruct>, - stask: SharedTask, + task: SharedTask, receive_signal: bool, - ) { - task.state = if receive_signal { + prepare: impl FnOnce(&mut crate::kernel::TaskStruct) -> bool, + ) -> bool { + let mut t = task.lock(); + if prepare(&mut t) { + return false; // 条件满足,不需要睡眠 + } + t.state = if receive_signal { TaskState::Interruptible } else { TaskState::Uninterruptible }; - - self.run_queue.remove_task(&stask); + self.run_queue.remove_task(&task); + true // 已进入睡眠 } } @@ -351,12 +355,13 @@ mod tests { kassert!(!rr.run_queue.contains(&t)); }); - // 时间片更新:手动将 current_slice 置 1,update 后应返回 true 并重置为 time_slice + // 时间片更新:手动将 current_slice 置 1,update 后应递减到 0 并报告到期。 + // update_time_slice 自身不重置时间片,重置由 reset_time_slice 负责。 test_case!(test_rr_update_time_slice, { let mut rr = RRScheduler::new(); - rr.current_slice = 1; // 直接操纵以触发用尽路径 + rr.current_slice = 1; let expired = rr.update_time_slice(); kassert!(expired); - kassert!(rr.current_slice == rr.time_slice); + kassert!(rr.current_slice == 0); }); } diff --git a/os/src/kernel/scheduler/wait_queue.rs b/os/src/kernel/scheduler/wait_queue.rs index 3818fda8..e4548a69 100644 --- a/os/src/kernel/scheduler/wait_queue.rs +++ b/os/src/kernel/scheduler/wait_queue.rs @@ -2,7 +2,7 @@ //! //! 定义了等待队列结构体及其相关操作 use crate::kernel::task::SharedTask; -use crate::kernel::{TaskQueue, sleep_task_with_block, wake_up_with_block}; +use crate::kernel::{TaskQueue, sleep_task, wake_up_task}; use crate::sync::RawSpinLock; use alloc::vec::Vec; @@ -37,7 +37,7 @@ impl WaitQueue { pub fn sleep(&mut self, task: SharedTask) { let _g = self.lock.lock(); self.tasks.add_task(task.clone()); - sleep_task_with_block(task, true); + sleep_task(task, true); } /// 从等待队列中移除指定任务并在锁释放后唤醒 @@ -52,7 +52,7 @@ impl WaitQueue { } }; if should_wake { - wake_up_with_block(task.clone()); + wake_up_task(task.clone()); } } @@ -63,7 +63,7 @@ impl WaitQueue { self.tasks.pop_task() }; if let Some(t) = maybe_task { - wake_up_with_block(t); + wake_up_task(t); } } @@ -77,7 +77,7 @@ impl WaitQueue { } } for t in to_wake { - wake_up_with_block(t); + wake_up_task(t); } } @@ -116,7 +116,7 @@ impl WaitQueue { return false; // 条件满足,不睡眠 } self.tasks.add_task(task.clone()); - sleep_task_with_block(task, true); + sleep_task(task, true); true // 已睡眠 } } diff --git a/os/src/kernel/syscall/dispatch.rs b/os/src/kernel/syscall/dispatch.rs index dd86723c..af3feef3 100644 --- a/os/src/kernel/syscall/dispatch.rs +++ b/os/src/kernel/syscall/dispatch.rs @@ -23,166 +23,166 @@ pub fn dispatch_syscall(frame: &mut impl SyscallFrame) { ); match frame.syscall_id() { // 文件系统/目录操作 - crate::arch::syscall::SYS_GETCWD => sys_getcwd(frame), + crate::kernel::syscall::numbers::SYS_GETCWD => sys_getcwd(frame), // Epoll & Duplication - crate::arch::syscall::SYS_DUP => sys_dup(frame), - crate::arch::syscall::SYS_DUP3 => sys_dup3(frame), - crate::arch::syscall::SYS_FCNTL => sys_fcntl(frame), - crate::arch::syscall::SYS_IOCTL => sys_ioctl(frame), + crate::kernel::syscall::numbers::SYS_DUP => sys_dup(frame), + crate::kernel::syscall::numbers::SYS_DUP3 => sys_dup3(frame), + crate::kernel::syscall::numbers::SYS_FCNTL => sys_fcntl(frame), + crate::kernel::syscall::numbers::SYS_IOCTL => sys_ioctl(frame), // 文件/目录创建与链接 - crate::arch::syscall::SYS_MKNODAT => sys_mknodat(frame), - crate::arch::syscall::SYS_MKDIRAT => sys_mkdirat(frame), - crate::arch::syscall::SYS_UNLINKAT => sys_unlinkat(frame), - crate::arch::syscall::SYS_SYMLINKAT => sys_symlinkat(frame), + crate::kernel::syscall::numbers::SYS_MKNODAT => sys_mknodat(frame), + crate::kernel::syscall::numbers::SYS_MKDIRAT => sys_mkdirat(frame), + crate::kernel::syscall::numbers::SYS_UNLINKAT => sys_unlinkat(frame), + crate::kernel::syscall::numbers::SYS_SYMLINKAT => sys_symlinkat(frame), // 挂载/文件系统信息 - crate::arch::syscall::SYS_MOUNT => sys_mount(frame), - crate::arch::syscall::SYS_UMOUNT2 => sys_umount2(frame), - crate::arch::syscall::SYS_STATFS => sys_statfs(frame), + crate::kernel::syscall::numbers::SYS_MOUNT => sys_mount(frame), + crate::kernel::syscall::numbers::SYS_UMOUNT2 => sys_umount2(frame), + crate::kernel::syscall::numbers::SYS_STATFS => sys_statfs(frame), // 文件大小/权限/所有权 - crate::arch::syscall::SYS_FACCESSAT => sys_faccessat(frame), - crate::arch::syscall::SYS_CHDIR => sys_chdir(frame), - crate::arch::syscall::SYS_FCHMODAT => sys_fchmodat(frame), - crate::arch::syscall::SYS_FCHOWNAT => sys_fchownat(frame), + crate::kernel::syscall::numbers::SYS_FACCESSAT => sys_faccessat(frame), + crate::kernel::syscall::numbers::SYS_CHDIR => sys_chdir(frame), + crate::kernel::syscall::numbers::SYS_FCHMODAT => sys_fchmodat(frame), + crate::kernel::syscall::numbers::SYS_FCHOWNAT => sys_fchownat(frame), // 文件描述符操作 - crate::arch::syscall::SYS_OPENAT => sys_openat(frame), - crate::arch::syscall::SYS_CLOSE => sys_close(frame), - crate::arch::syscall::SYS_PIPE2 => sys_pipe2(frame), - crate::arch::syscall::SYS_GETDENTS64 => sys_getdents64(frame), - crate::arch::syscall::SYS_LSEEK => sys_lseek(frame), - crate::arch::syscall::SYS_FTRUNCATE => sys_ftruncate(frame), + crate::kernel::syscall::numbers::SYS_OPENAT => sys_openat(frame), + crate::kernel::syscall::numbers::SYS_CLOSE => sys_close(frame), + crate::kernel::syscall::numbers::SYS_PIPE2 => sys_pipe2(frame), + crate::kernel::syscall::numbers::SYS_GETDENTS64 => sys_getdents64(frame), + crate::kernel::syscall::numbers::SYS_LSEEK => sys_lseek(frame), + crate::kernel::syscall::numbers::SYS_FTRUNCATE => sys_ftruncate(frame), // I/O 操作 - crate::arch::syscall::SYS_READ => sys_read(frame), - crate::arch::syscall::SYS_WRITE => sys_write(frame), - crate::arch::syscall::SYS_READV => sys_readv(frame), - crate::arch::syscall::SYS_WRITEV => sys_writev(frame), - crate::arch::syscall::SYS_PREAD64 => sys_pread64(frame), - crate::arch::syscall::SYS_PWRITE64 => sys_pwrite64(frame), - crate::arch::syscall::SYS_PREADV => sys_preadv(frame), - crate::arch::syscall::SYS_PWRITEV => sys_pwritev(frame), - crate::arch::syscall::SYS_SENDFILE => sys_sendfile(frame), - crate::arch::syscall::SYS_PSELECT6 => sys_pselect6(frame), - crate::arch::syscall::SYS_PPOLL => sys_ppoll(frame), + crate::kernel::syscall::numbers::SYS_READ => sys_read(frame), + crate::kernel::syscall::numbers::SYS_WRITE => sys_write(frame), + crate::kernel::syscall::numbers::SYS_READV => sys_readv(frame), + crate::kernel::syscall::numbers::SYS_WRITEV => sys_writev(frame), + crate::kernel::syscall::numbers::SYS_PREAD64 => sys_pread64(frame), + crate::kernel::syscall::numbers::SYS_PWRITE64 => sys_pwrite64(frame), + crate::kernel::syscall::numbers::SYS_PREADV => sys_preadv(frame), + crate::kernel::syscall::numbers::SYS_PWRITEV => sys_pwritev(frame), + crate::kernel::syscall::numbers::SYS_SENDFILE => sys_sendfile(frame), + crate::kernel::syscall::numbers::SYS_PSELECT6 => sys_pselect6(frame), + crate::kernel::syscall::numbers::SYS_PPOLL => sys_ppoll(frame), // 文件元数据与同步 - crate::arch::syscall::SYS_READLINKAT => sys_readlinkat(frame), - crate::arch::syscall::SYS_FSTATAT => sys_newfstatat(frame), - crate::arch::syscall::SYS_FSTAT => sys_fstat(frame), - crate::arch::syscall::SYS_SYNC => sys_sync(frame), - crate::arch::syscall::SYS_FSYNC => sys_fsync(frame), - crate::arch::syscall::SYS_FDATASYNC => sys_fdatasync(frame), + crate::kernel::syscall::numbers::SYS_READLINKAT => sys_readlinkat(frame), + crate::kernel::syscall::numbers::SYS_FSTATAT => sys_newfstatat(frame), + crate::kernel::syscall::numbers::SYS_FSTAT => sys_fstat(frame), + crate::kernel::syscall::numbers::SYS_SYNC => sys_sync(frame), + crate::kernel::syscall::numbers::SYS_FSYNC => sys_fsync(frame), + crate::kernel::syscall::numbers::SYS_FDATASYNC => sys_fdatasync(frame), // 定时器 - crate::arch::syscall::SYS_UTIMENSAT => sys_utimensat(frame), + crate::kernel::syscall::numbers::SYS_UTIMENSAT => sys_utimensat(frame), // 进程与控制 - crate::arch::syscall::SYS_EXIT => sys_exit(frame), - crate::arch::syscall::SYS_EXIT_GROUP => sys_exit_group(frame), - crate::arch::syscall::SYS_SET_TID_ADDRESS => sys_set_tid_address(frame), + crate::kernel::syscall::numbers::SYS_EXIT => sys_exit(frame), + crate::kernel::syscall::numbers::SYS_EXIT_GROUP => sys_exit_group(frame), + crate::kernel::syscall::numbers::SYS_SET_TID_ADDRESS => sys_set_tid_address(frame), // 同步/休眠 - crate::arch::syscall::SYS_FUTEX => sys_futex(frame), - crate::arch::syscall::SYS_SET_ROBUST_LIST => sys_set_robust_list(frame), - crate::arch::syscall::SYS_GET_ROBUST_LIST => sys_get_robust_list(frame), - crate::arch::syscall::SYS_NANOSLEEP => sys_nanosleep(frame), - crate::arch::syscall::SYS_GETITIMER => sys_getitimmer(frame), - crate::arch::syscall::SYS_SETITIMER => sys_setitimmer(frame), + crate::kernel::syscall::numbers::SYS_FUTEX => sys_futex(frame), + crate::kernel::syscall::numbers::SYS_SET_ROBUST_LIST => sys_set_robust_list(frame), + crate::kernel::syscall::numbers::SYS_GET_ROBUST_LIST => sys_get_robust_list(frame), + crate::kernel::syscall::numbers::SYS_NANOSLEEP => sys_nanosleep(frame), + crate::kernel::syscall::numbers::SYS_GETITIMER => sys_getitimmer(frame), + crate::kernel::syscall::numbers::SYS_SETITIMER => sys_setitimmer(frame), // POSIX 定时器 - crate::arch::syscall::SYS_CLOCK_SETTIME => sys_clock_settime(frame), - crate::arch::syscall::SYS_CLOCK_GETTIME => sys_clock_gettime(frame), - crate::arch::syscall::SYS_CLOCK_GETRES => sys_clock_getres(frame), - crate::arch::syscall::SYS_SYSLOG => sys_syslog(frame), + crate::kernel::syscall::numbers::SYS_CLOCK_SETTIME => sys_clock_settime(frame), + crate::kernel::syscall::numbers::SYS_CLOCK_GETTIME => sys_clock_gettime(frame), + crate::kernel::syscall::numbers::SYS_CLOCK_GETRES => sys_clock_getres(frame), + crate::kernel::syscall::numbers::SYS_SYSLOG => sys_syslog(frame), // 信号 - crate::arch::syscall::SYS_KILL => sys_kill(frame), - crate::arch::syscall::SYS_TKILL => sys_tkill(frame), - crate::arch::syscall::SYS_TGKILL => sys_tgkill(frame), - crate::arch::syscall::SYS_SIGALTSTACK => sys_sigaltstack(frame), - crate::arch::syscall::SYS_RT_SIGSUSPEND => sys_rt_sigsuspend(frame), - crate::arch::syscall::SYS_RT_SIGACTION => sys_rt_sigaction(frame), - crate::arch::syscall::SYS_RT_SIGPROCMASK => sys_rt_sigprocmask(frame), - crate::arch::syscall::SYS_RT_SIGPENDING => sys_rt_sigpending(frame), - crate::arch::syscall::SYS_RT_SIGTIMEDWAIT => sys_rt_sigtimedwait(frame), - crate::arch::syscall::SYS_RT_SIGRETURN => sys_rt_sigreturn(frame), + crate::kernel::syscall::numbers::SYS_KILL => sys_kill(frame), + crate::kernel::syscall::numbers::SYS_TKILL => sys_tkill(frame), + crate::kernel::syscall::numbers::SYS_TGKILL => sys_tgkill(frame), + crate::kernel::syscall::numbers::SYS_SIGALTSTACK => sys_sigaltstack(frame), + crate::kernel::syscall::numbers::SYS_RT_SIGSUSPEND => sys_rt_sigsuspend(frame), + crate::kernel::syscall::numbers::SYS_RT_SIGACTION => sys_rt_sigaction(frame), + crate::kernel::syscall::numbers::SYS_RT_SIGPROCMASK => sys_rt_sigprocmask(frame), + crate::kernel::syscall::numbers::SYS_RT_SIGPENDING => sys_rt_sigpending(frame), + crate::kernel::syscall::numbers::SYS_RT_SIGTIMEDWAIT => sys_rt_sigtimedwait(frame), + crate::kernel::syscall::numbers::SYS_RT_SIGRETURN => sys_rt_sigreturn(frame), // 进程属性 - crate::arch::syscall::SYS_REBOOT => sys_reboot(frame), - crate::arch::syscall::SYS_SETGID => sys_setgid(frame), - crate::arch::syscall::SYS_SETUID => sys_setuid(frame), - crate::arch::syscall::SYS_SETRESUID => sys_setresuid(frame), - crate::arch::syscall::SYS_GETRESUID => sys_getresuid(frame), - crate::arch::syscall::SYS_SETRESGID => sys_setresgid(frame), - crate::arch::syscall::SYS_GETRESGID => sys_getresgid(frame), - crate::arch::syscall::SYS_SETPGID => sys_setpgid(frame), - crate::arch::syscall::SYS_SETSID => sys_setsid(frame), + crate::kernel::syscall::numbers::SYS_REBOOT => sys_reboot(frame), + crate::kernel::syscall::numbers::SYS_SETGID => sys_setgid(frame), + crate::kernel::syscall::numbers::SYS_SETUID => sys_setuid(frame), + crate::kernel::syscall::numbers::SYS_SETRESUID => sys_setresuid(frame), + crate::kernel::syscall::numbers::SYS_GETRESUID => sys_getresuid(frame), + crate::kernel::syscall::numbers::SYS_SETRESGID => sys_setresgid(frame), + crate::kernel::syscall::numbers::SYS_GETRESGID => sys_getresgid(frame), + crate::kernel::syscall::numbers::SYS_SETPGID => sys_setpgid(frame), + crate::kernel::syscall::numbers::SYS_SETSID => sys_setsid(frame), // 系统信息 - crate::arch::syscall::SYS_UNAME => sys_uname(frame), - crate::arch::syscall::SYS_SETHOSTNAME => sys_sethostname(frame), - crate::arch::syscall::SYS_GETRLIMIT => sys_getrlimit(frame), - crate::arch::syscall::SYS_SETRLIMIT => sys_setrlimit(frame), - crate::arch::syscall::SYS_UMASK => sys_umask(frame), - crate::arch::syscall::SYS_GETPID => sys_getpid(frame), - crate::arch::syscall::SYS_GETPPID => sys_getppid(frame), - crate::arch::syscall::SYS_GETPGID => sys_getpgid(frame), - crate::arch::syscall::SYS_GETUID => sys_getuid(frame), - crate::arch::syscall::SYS_GETEUID => sys_geteuid(frame), - crate::arch::syscall::SYS_GETGID => sys_getgid(frame), - crate::arch::syscall::SYS_GETEGID => sys_getegid(frame), - crate::arch::syscall::SYS_GETTID => sys_gettid(frame), - crate::arch::syscall::SYS_SYSINFO => sys_sysinfo(frame), + crate::kernel::syscall::numbers::SYS_UNAME => sys_uname(frame), + crate::kernel::syscall::numbers::SYS_SETHOSTNAME => sys_sethostname(frame), + crate::kernel::syscall::numbers::SYS_GETRLIMIT => sys_getrlimit(frame), + crate::kernel::syscall::numbers::SYS_SETRLIMIT => sys_setrlimit(frame), + crate::kernel::syscall::numbers::SYS_UMASK => sys_umask(frame), + crate::kernel::syscall::numbers::SYS_GETPID => sys_getpid(frame), + crate::kernel::syscall::numbers::SYS_GETPPID => sys_getppid(frame), + crate::kernel::syscall::numbers::SYS_GETPGID => sys_getpgid(frame), + crate::kernel::syscall::numbers::SYS_GETUID => sys_getuid(frame), + crate::kernel::syscall::numbers::SYS_GETEUID => sys_geteuid(frame), + crate::kernel::syscall::numbers::SYS_GETGID => sys_getgid(frame), + crate::kernel::syscall::numbers::SYS_GETEGID => sys_getegid(frame), + crate::kernel::syscall::numbers::SYS_GETTID => sys_gettid(frame), + crate::kernel::syscall::numbers::SYS_SYSINFO => sys_sysinfo(frame), // 网络 - crate::arch::syscall::SYS_SOCKET => sys_socket(frame), - crate::arch::syscall::SYS_BIND => sys_bind(frame), - crate::arch::syscall::SYS_LISTEN => sys_listen(frame), - crate::arch::syscall::SYS_ACCEPT => sys_accept(frame), - crate::arch::syscall::SYS_CONNECT => sys_connect(frame), - crate::arch::syscall::SYS_GETSOCKNAME => sys_getsockname(frame), - crate::arch::syscall::SYS_GETPEERNAME => sys_getpeername(frame), - crate::arch::syscall::SYS_SENDTO => sys_sendto(frame), - crate::arch::syscall::SYS_RECVFROM => sys_recvfrom(frame), - crate::arch::syscall::SYS_SETSOCKOPT => sys_setsockopt(frame), - crate::arch::syscall::SYS_GETSOCKOPT => sys_getsockopt(frame), - crate::arch::syscall::SYS_SHUTDOWN => sys_shutdown(frame), + crate::kernel::syscall::numbers::SYS_SOCKET => sys_socket(frame), + crate::kernel::syscall::numbers::SYS_BIND => sys_bind(frame), + crate::kernel::syscall::numbers::SYS_LISTEN => sys_listen(frame), + crate::kernel::syscall::numbers::SYS_ACCEPT => sys_accept(frame), + crate::kernel::syscall::numbers::SYS_CONNECT => sys_connect(frame), + crate::kernel::syscall::numbers::SYS_GETSOCKNAME => sys_getsockname(frame), + crate::kernel::syscall::numbers::SYS_GETPEERNAME => sys_getpeername(frame), + crate::kernel::syscall::numbers::SYS_SENDTO => sys_sendto(frame), + crate::kernel::syscall::numbers::SYS_RECVFROM => sys_recvfrom(frame), + crate::kernel::syscall::numbers::SYS_SETSOCKOPT => sys_setsockopt(frame), + crate::kernel::syscall::numbers::SYS_GETSOCKOPT => sys_getsockopt(frame), + crate::kernel::syscall::numbers::SYS_SHUTDOWN => sys_shutdown(frame), // 进程创建/执行 - crate::arch::syscall::SYS_CLONE => sys_clone(frame), - crate::arch::syscall::SYS_EXECVE => sys_execve(frame), + crate::kernel::syscall::numbers::SYS_CLONE => sys_clone(frame), + crate::kernel::syscall::numbers::SYS_EXECVE => sys_execve(frame), // 网络 I/O (续) - crate::arch::syscall::SYS_ACCEPT4 => sys_accept4(frame), + crate::kernel::syscall::numbers::SYS_ACCEPT4 => sys_accept4(frame), // 进程与控制 (续) - crate::arch::syscall::SYS_WAIT4 => sys_wait4(frame), - crate::arch::syscall::SYS_PRLIMIT64 => sys_prlimit(frame), + crate::kernel::syscall::numbers::SYS_WAIT4 => sys_wait4(frame), + crate::kernel::syscall::numbers::SYS_PRLIMIT64 => sys_prlimit(frame), // 内存管理 - crate::arch::syscall::SYS_BRK => sys_brk(frame), - crate::arch::syscall::SYS_MUNMAP => sys_munmap(frame), - crate::arch::syscall::SYS_MMAP => sys_mmap(frame), - crate::arch::syscall::SYS_MPROTECT => sys_mprotect(frame), + crate::kernel::syscall::numbers::SYS_BRK => sys_brk(frame), + crate::kernel::syscall::numbers::SYS_MUNMAP => sys_munmap(frame), + crate::kernel::syscall::numbers::SYS_MMAP => sys_mmap(frame), + crate::kernel::syscall::numbers::SYS_MPROTECT => sys_mprotect(frame), // 文件系统同步 (续) - crate::arch::syscall::SYS_SYNCFS => sys_syncfs(frame), + crate::kernel::syscall::numbers::SYS_SYNCFS => sys_syncfs(frame), // 调度 (续) - crate::arch::syscall::SYS_RENAMEAT2 => sys_renameat2(frame), + crate::kernel::syscall::numbers::SYS_RENAMEAT2 => sys_renameat2(frame), // 随机数与内存文件 - crate::arch::syscall::SYS_GETRANDOM => sys_getrandom(frame), + crate::kernel::syscall::numbers::SYS_GETRANDOM => sys_getrandom(frame), // 扩展文件元数据 - crate::arch::syscall::SYS_STATX => sys_statx(frame), + crate::kernel::syscall::numbers::SYS_STATX => sys_statx(frame), // 获取网络接口地址列表 - crate::arch::syscall::SYS_GETIFADDRS => sys_getifaddrs(frame), + crate::kernel::syscall::numbers::SYS_GETIFADDRS => sys_getifaddrs(frame), _ => { frame.set_ret((-ENOSYS) as usize); @@ -201,7 +201,9 @@ macro_rules! impl_syscall { // noreturn, 6 args ($sys_name:ident, $kernel:path, noreturn, ($t0:ty, $t1:ty, $t2:ty, $t3:ty, $t4:ty, $t5:ty)) => { #[allow(non_snake_case)] - pub fn $sys_name(frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { let a0 = frame.arg0() as $t0; let a1 = frame.arg1() as $t1; let a2 = frame.arg2() as $t2; @@ -215,20 +217,26 @@ macro_rules! impl_syscall { // noreturn, 0..5 args ($sys_name:ident, $kernel:path, noreturn, ()) => { #[allow(non_snake_case)] - pub fn $sys_name(_frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + _frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { $kernel() } }; ($sys_name:ident, $kernel:path, noreturn, ($t0:ty)) => { #[allow(non_snake_case)] - pub fn $sys_name(frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { let a0 = frame.arg0() as $t0; $kernel(a0) } }; ($sys_name:ident, $kernel:path, noreturn, ($t0:ty, $t1:ty)) => { #[allow(non_snake_case)] - pub fn $sys_name(frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { let a0 = frame.arg0() as $t0; let a1 = frame.arg1() as $t1; $kernel(a0, a1) @@ -236,7 +244,9 @@ macro_rules! impl_syscall { }; ($sys_name:ident, $kernel:path, noreturn, ($t0:ty, $t1:ty, $t2:ty)) => { #[allow(non_snake_case)] - pub fn $sys_name(frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { let a0 = frame.arg0() as $t0; let a1 = frame.arg1() as $t1; let a2 = frame.arg2() as $t2; @@ -245,7 +255,9 @@ macro_rules! impl_syscall { }; ($sys_name:ident, $kernel:path, noreturn, ($t0:ty, $t1:ty, $t2:ty, $t3:ty)) => { #[allow(non_snake_case)] - pub fn $sys_name(frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { let a0 = frame.arg0() as $t0; let a1 = frame.arg1() as $t1; let a2 = frame.arg2() as $t2; @@ -255,7 +267,9 @@ macro_rules! impl_syscall { }; ($sys_name:ident, $kernel:path, noreturn, ($t0:ty, $t1:ty, $t2:ty, $t3:ty, $t4:ty)) => { #[allow(non_snake_case)] - pub fn $sys_name(frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame) -> ! { + pub fn $sys_name( + frame: &mut impl $crate::kernel::syscall::syscall_frame::SyscallFrame, + ) -> ! { let a0 = frame.arg0() as $t0; let a1 = frame.arg1() as $t1; let a2 = frame.arg2() as $t2; diff --git a/os/src/kernel/syscall/fcntl.rs b/os/src/kernel/syscall/fcntl.rs index ba11b5e0..d3ec5f07 100644 --- a/os/src/kernel/syscall/fcntl.rs +++ b/os/src/kernel/syscall/fcntl.rs @@ -1,9 +1,9 @@ //! fcntl 系统调用实现 use crate::kernel::current_task; -use crate::util::user_buffer::{read_from_user, write_to_user}; use crate::uapi::errno::EINVAL; use crate::uapi::fcntl::{FcntlCmd, FdFlags, FileStatusFlags, Flock, LockType}; +use crate::util::user_buffer::{read_from_user, write_to_user}; use crate::vfs::{FsError, OpenFlags, file_lock_manager}; use alloc::sync::Arc; diff --git a/os/src/kernel/syscall/fs.rs b/os/src/kernel/syscall/fs.rs index 510f14d3..a6dd7f0f 100644 --- a/os/src/kernel/syscall/fs.rs +++ b/os/src/kernel/syscall/fs.rs @@ -6,7 +6,6 @@ use crate::arch::Arch; use alloc::string::ToString; use crate::{ - util::user_buffer::write_to_user, kernel::{ current_task, syscall::util::{ @@ -19,6 +18,7 @@ use crate::{ fs::{AtFlags, F_OK, FileSystemType, LinuxStatFs, R_OK, W_OK, X_OK}, time::TimeSpec, }, + util::user_buffer::write_to_user, vfs::{ DENTRY_CACHE, Dentry, FileMode, FsError, InodeType, OpenFlags, SeekWhence, Stat, Statx, split_path, vfs_lookup, @@ -321,7 +321,12 @@ pub fn getcwd(buf: *mut u8, size: usize) -> isize { // 复制到用户态缓冲区 unsafe { - crate::arch::ArchImpl::copy_to_user(path_bytes.as_ptr(), buf as usize, path_bytes.len()).ok(); + crate::arch::ArchImpl::copy_to_user( + path_bytes.as_ptr(), + crate::arch::address::UA::from_usize(buf as usize), + path_bytes.len(), + ) + .ok(); write_to_user(buf.add(path_bytes.len()), 0u8); } @@ -427,7 +432,7 @@ pub fn getdents64(fd: usize, dirp: *mut u8, count: usize) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( name_bytes.as_ptr(), - dirp as usize + name_offset, + crate::arch::address::UA::from_usize(dirp as usize + name_offset), name_bytes.len(), ) .ok(); @@ -630,7 +635,12 @@ pub fn readlinkat(dirfd: i32, pathname: *const c_char, buf: *mut u8, bufsiz: usi // 复制到用户空间(注意:readlink 不添加 null 终止符) unsafe { - crate::arch::ArchImpl::copy_to_user(target.as_bytes().as_ptr(), buf as usize, bytes_read).ok(); + crate::arch::ArchImpl::copy_to_user( + target.as_bytes().as_ptr(), + crate::arch::address::UA::from_usize(buf as usize), + bytes_read, + ) + .ok(); } bytes_read as isize diff --git a/os/src/kernel/syscall/io.rs b/os/src/kernel/syscall/io.rs index 8bd1c852..f4c4fa60 100644 --- a/os/src/kernel/syscall/io.rs +++ b/os/src/kernel/syscall/io.rs @@ -5,7 +5,9 @@ use crate::kernel::current_task; use crate::uapi::errno::EFAULT; use crate::uapi::errno::EINVAL; use crate::uapi::iovec::IoVec; -use crate::util::user_buffer::{read_from_user, validate_user_ptr, validate_user_ptr_mut, write_to_user}; +use crate::util::user_buffer::{ + read_from_user, validate_user_ptr, validate_user_ptr_mut, write_to_user, +}; use crate::vfs::File; /// 向文件描述符写入数据 @@ -20,7 +22,7 @@ pub fn write(fd: usize, buf: *const u8, count: usize) -> isize { let mut kernel_buf = alloc::vec![0u8; count]; unsafe { crate::arch::ArchImpl::copy_from_user( - buf as usize, + crate::arch::address::UA::from_usize(buf as usize), kernel_buf.as_mut_ptr(), count, ) @@ -66,7 +68,7 @@ pub fn read(fd: usize, buf: *mut u8, count: usize) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( kernel_buf.as_ptr(), - buf as usize, + crate::arch::address::UA::from_usize(buf as usize), n, ) .ok(); @@ -110,10 +112,11 @@ pub fn readv(fd: usize, iov: *const IoVec, iovcnt: usize) -> isize { unsafe { iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( - iov as usize, + crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, iovcnt * core::mem::size_of::(), - ).ok(); + ) + .ok(); } let task = current_task(); @@ -142,9 +145,10 @@ pub fn readv(fd: usize, iov: *const IoVec, iovcnt: usize) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( kernel_buf.as_ptr(), - vec.iov_base as usize, + crate::arch::address::UA::from_usize(vec.iov_base as usize), n, - ).ok(); + ) + .ok(); } total_read += n; if n < vec.iov_len { @@ -178,10 +182,11 @@ pub fn writev(fd: usize, iov: *const IoVec, iovcnt: usize) -> isize { unsafe { iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( - iov as usize, + crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, iovcnt * core::mem::size_of::(), - ).ok(); + ) + .ok(); } let task = current_task(); @@ -207,10 +212,11 @@ pub fn writev(fd: usize, iov: *const IoVec, iovcnt: usize) -> isize { let mut kernel_buf = alloc::vec![0u8; vec.iov_len]; unsafe { crate::arch::ArchImpl::copy_from_user( - vec.iov_base as usize, + crate::arch::address::UA::from_usize(vec.iov_base as usize), kernel_buf.as_mut_ptr(), vec.iov_len, - ).ok(); + ) + .ok(); } match file.write(&kernel_buf) { Ok(n) => { @@ -255,9 +261,10 @@ pub fn pread64(fd: usize, buf: *mut u8, count: usize, offset: i64) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( kernel_buf.as_ptr(), - buf as usize, + crate::arch::address::UA::from_usize(buf as usize), n, - ).ok(); + ) + .ok(); } n as isize } @@ -285,10 +292,11 @@ pub fn pwrite64(fd: usize, buf: *const u8, count: usize, offset: i64) -> isize { let mut kernel_buf = alloc::vec![0u8; count]; unsafe { crate::arch::ArchImpl::copy_from_user( - buf as usize, + crate::arch::address::UA::from_usize(buf as usize), kernel_buf.as_mut_ptr(), count, - ).ok(); + ) + .ok(); } match file.write_at(offset as usize, &kernel_buf) { Ok(n) => n as isize, @@ -322,10 +330,11 @@ pub fn preadv(fd: usize, iov: *const IoVec, iovcnt: usize, offset: i64) -> isize unsafe { iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( - iov as usize, + crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, iovcnt * core::mem::size_of::(), - ).ok(); + ) + .ok(); } let mut total_read = 0usize; @@ -349,9 +358,10 @@ pub fn preadv(fd: usize, iov: *const IoVec, iovcnt: usize, offset: i64) -> isize unsafe { crate::arch::ArchImpl::copy_to_user( kernel_buf.as_ptr(), - vec.iov_base as usize, + crate::arch::address::UA::from_usize(vec.iov_base as usize), n, - ).ok(); + ) + .ok(); } total_read += n; current_offset += n; @@ -398,10 +408,11 @@ pub fn pwritev(fd: usize, iov: *const IoVec, iovcnt: usize, offset: i64) -> isiz unsafe { iovec_array.set_len(iovcnt); crate::arch::ArchImpl::copy_from_user( - iov as usize, + crate::arch::address::UA::from_usize(iov as usize), iovec_array.as_mut_ptr() as *mut u8, iovcnt * core::mem::size_of::(), - ).ok(); + ) + .ok(); } let mut total_written = 0usize; @@ -422,10 +433,11 @@ pub fn pwritev(fd: usize, iov: *const IoVec, iovcnt: usize, offset: i64) -> isiz let mut kernel_buf = alloc::vec![0u8; vec.iov_len]; unsafe { crate::arch::ArchImpl::copy_from_user( - vec.iov_base as usize, + crate::arch::address::UA::from_usize(vec.iov_base as usize), kernel_buf.as_mut_ptr(), vec.iov_len, - ).ok(); + ) + .ok(); } match file.write_at(current_offset, &kernel_buf) { Ok(n) => { @@ -586,7 +598,8 @@ fn poll_with_timeout( return -(EINVAL as isize); } let duration_ns = (ts.tv_sec as u64 * 1_000_000_000) + ts.tv_nsec as u64; - let duration_ticks = (duration_ns * crate::arch::clock_freq() as u64 / 1_000_000_000) as usize; + let duration_ticks = + (duration_ns * crate::arch::clock_freq() as u64 / 1_000_000_000) as usize; Some(crate::arch::get_time() + duration_ticks) } }; @@ -603,10 +616,11 @@ fn poll_with_timeout( unsafe { pollfds_buf.set_len(nfds); crate::arch::ArchImpl::copy_from_user( - fds, + crate::arch::address::UA::from_usize(fds), pollfds_buf.as_mut_ptr() as *mut u8, size, - ).ok(); + ) + .ok(); } for pollfd in pollfds_buf.iter_mut() { @@ -642,9 +656,10 @@ fn poll_with_timeout( unsafe { crate::arch::ArchImpl::copy_to_user( pollfds_buf.as_ptr() as *const u8, - fds, + crate::arch::address::UA::from_usize(fds), size, - ).ok(); + ) + .ok(); } } @@ -698,7 +713,8 @@ pub fn ppoll(fds: usize, nfds: usize, timeout: usize, _sigmask: usize) -> isize let timeout_spec = if timeout == 0 { None } else { - let ts: crate::uapi::time::TimeSpec = read_from_user(timeout as *const crate::uapi::time::TimeSpec); + let ts: crate::uapi::time::TimeSpec = + read_from_user(timeout as *const crate::uapi::time::TimeSpec); if ts.tv_nsec < 0 || ts.tv_nsec >= 1_000_000_000 { return -(EINVAL as isize); } diff --git a/os/src/kernel/syscall/ioctl.rs b/os/src/kernel/syscall/ioctl.rs index 44956fd3..b9127042 100644 --- a/os/src/kernel/syscall/ioctl.rs +++ b/os/src/kernel/syscall/ioctl.rs @@ -307,8 +307,7 @@ fn handle_ifreq(_file: &alloc::sync::Arc, request: u32, ar // TODO: 实现实际的网络接口操作 match request { - SIOCGIFADDR | SIOCGIFFLAGS | SIOCGIFNETMASK | SIOCGIFMTU | SIOCGIFHWADDR - | SIOCGIFINDEX => { + SIOCGIFADDR | SIOCGIFFLAGS | SIOCGIFNETMASK | SIOCGIFMTU | SIOCGIFHWADDR | SIOCGIFINDEX => { pr_debug!("ioctl: network get request {:#x} not implemented", request); -EOPNOTSUPP as isize } diff --git a/os/src/kernel/syscall/mm.rs b/os/src/kernel/syscall/mm.rs index 9a06c53e..dad5b5e3 100644 --- a/os/src/kernel/syscall/mm.rs +++ b/os/src/kernel/syscall/mm.rs @@ -2,7 +2,7 @@ use core::ffi::c_void; use crate::config::PAGE_SIZE; use crate::kernel::{current_memory_space, current_task}; -use crate::mm::address::{PageNum, UsizeConvert, Vaddr, Vpn, VpnRange}; +use crate::mm::address::{PageNum, VA, Vpn, VpnRange}; use crate::mm::memory_space::MmapFile; use crate::mm::memory_space::mapping_area::AreaType; use crate::mm::page_table::UniversalPTEFlag; @@ -30,7 +30,7 @@ pub fn brk(new_brk: usize) -> isize { let mut space = memory_space.lock(); // 获取当前的 brk 值 - let current = space.current_brk().unwrap_or(0); + let current = space.current_brk().map(|addr| addr.as_usize()).unwrap_or(0); // 如果 new_brk 为 0,返回当前 brk(查询模式) if new_brk == 0 { @@ -38,8 +38,8 @@ pub fn brk(new_brk: usize) -> isize { } // 尝试设置新的 brk - match space.brk(new_brk) { - Ok(addr) => addr as isize, + match space.brk(VA::from_usize(new_brk)) { + Ok(addr) => addr.as_usize() as isize, Err(e) => { pr_err!( "brk failed: {:?}, new_brk=0x{:x}, current=0x{:x}", @@ -177,7 +177,7 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse let start_addr = if map_flags.contains(MapFlags::FIXED) { // MAP_FIXED: 强制使用指定地址,覆盖现有映射 - match space.munmap(hint, len) { + match space.munmap(VA::from_usize(hint), len) { Ok(_) => hint, Err(e) => { pr_err!("mmap: MAP_FIXED munmap failed: {:?}", e); @@ -191,8 +191,8 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse return -EINVAL as isize; } - let start_vpn = Vpn::from_addr_floor(Vaddr::from_usize(hint)); - let end_vpn = Vpn::from_addr_ceil(Vaddr::from_usize(hint + len)); + let start_vpn = Vpn::from_addr_floor(VA::from_usize(hint)); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(hint + len)); let range = VpnRange::new(start_vpn, end_vpn); // 检查是否与现有区域重叠 @@ -209,7 +209,7 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse if hint == 0 { // hint == 0: 内核选择地址 match space.find_free_region(len, PAGE_SIZE) { - Some(addr) => addr, + Some(addr) => addr.as_usize(), None => { pr_err!("mmap: out of memory"); return -ENOMEM as isize; @@ -219,8 +219,8 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse // hint != 0: 尝试使用 hint,失败则内核选择 let aligned_hint = hint & !(PAGE_SIZE - 1); - let start_vpn = Vpn::from_addr_floor(Vaddr::from_usize(aligned_hint)); - let end_vpn = Vpn::from_addr_ceil(Vaddr::from_usize(aligned_hint + len)); + let start_vpn = Vpn::from_addr_floor(VA::from_usize(aligned_hint)); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(aligned_hint + len)); let range = VpnRange::new(start_vpn, end_vpn); let hint_available = !space.areas().iter().any(|a| a.vpn_range().overlaps(&range)); @@ -230,7 +230,7 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse } else { // hint 不可用,内核选择 match space.find_free_region(len, PAGE_SIZE) { - Some(addr) => addr, + Some(addr) => addr.as_usize(), None => { pr_err!("mmap: out of memory"); return -ENOMEM as isize; @@ -266,8 +266,8 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse } // 创建映射 - let start_vpn = Vpn::from_addr_floor(Vaddr::from_usize(start_addr)); - let end_vpn = Vpn::from_addr_ceil(Vaddr::from_usize(start_addr + len)); + let start_vpn = Vpn::from_addr_floor(VA::from_usize(start_addr)); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(start_addr + len)); let vpn_range = VpnRange::new(start_vpn, end_vpn); // 插入映射区域(PROT_NONE 用 Reserved 占位,不建立页表映射) @@ -301,7 +301,7 @@ pub fn mmap(addr: *mut c_void, len: usize, prot: i32, flags: i32, fd: i32, offse fd ); // 加载失败,清理已创建的映射 - if let Err(unmap_err) = space.munmap(start_addr, len) { + if let Err(unmap_err) = space.munmap(VA::from_usize(start_addr), len) { pr_warn!( "mmap: failed to clean up mapping on load error: {:?}", unmap_err @@ -339,7 +339,7 @@ pub fn munmap(addr: *mut c_void, len: usize) -> isize { let memory_space = current_memory_space(); let mut space = memory_space.lock(); - match space.munmap(start, len) { + match space.munmap(VA::from_usize(start), len) { Ok(()) => 0, Err(e) => { pr_err!( @@ -414,7 +414,7 @@ pub fn mprotect(addr: *mut c_void, len: usize, prot: i32) -> isize { let memory_space = current_memory_space(); let mut space = memory_space.lock(); - match space.mprotect(start, len, pte_flags) { + match space.mprotect(VA::from_usize(start), len, pte_flags) { Ok(()) => 0, Err(e) => { pr_err!( diff --git a/os/src/kernel/syscall/mod.rs b/os/src/kernel/syscall/mod.rs index 5a73458f..e60fe511 100644 --- a/os/src/kernel/syscall/mod.rs +++ b/os/src/kernel/syscall/mod.rs @@ -12,6 +12,7 @@ mod ioctl; mod ipc; mod mm; mod network; +pub mod numbers; mod signal; mod sys; pub mod syscall_frame; diff --git a/os/src/kernel/syscall/network.rs b/os/src/kernel/syscall/network.rs index 3532dd0f..c389c44c 100644 --- a/os/src/kernel/syscall/network.rs +++ b/os/src/kernel/syscall/network.rs @@ -815,7 +815,14 @@ pub fn send(sockfd: i32, buf: *const u8, len: usize, _flags: i32) -> isize { let result = { let mut kernel_buf = alloc::vec![0u8; len]; - unsafe { crate::arch::ArchImpl::copy_from_user(buf as usize, kernel_buf.as_mut_ptr(), len).ok(); } + unsafe { + crate::arch::ArchImpl::copy_from_user( + crate::arch::address::UA::from_usize(buf as usize), + kernel_buf.as_mut_ptr(), + len, + ) + .ok(); + } file.write(&kernel_buf) }; @@ -869,7 +876,14 @@ pub fn recv(sockfd: i32, buf: *mut u8, len: usize, _flags: i32) -> isize { let mut kernel_buf = alloc::vec![0u8; len]; match file.read(&mut kernel_buf) { Ok(n) => { - unsafe { crate::arch::ArchImpl::copy_to_user(kernel_buf.as_ptr(), buf as usize, n).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + kernel_buf.as_ptr(), + crate::arch::address::UA::from_usize(buf as usize), + n, + ) + .ok(); + } Ok(n) } Err(e) => Err(e), @@ -921,7 +935,13 @@ fn copy_c_str_from_user(ptr: *const c_char) -> Option { return None; } let mut buf = [0u8; 256]; - match unsafe { crate::arch::ArchImpl::copy_strn_from_user(ptr as usize, buf.as_mut_ptr(), buf.len()) } { + match unsafe { + crate::arch::ArchImpl::copy_strn_from_user( + crate::arch::address::UA::from_usize(ptr as usize), + buf.as_mut_ptr(), + buf.len(), + ) + } { Ok(len) if len > 0 => { let s = core::str::from_utf8(&buf[..len]).ok()?; Some(s.to_string()) @@ -972,7 +992,14 @@ fn get_interface_stats(ifname: *const c_char, stats: *mut u8, size: usize) -> is // 清零整个统计结构 (struct rtnl_link_stats64) let zero_buf = alloc::vec![0u8; size]; - unsafe { crate::arch::ArchImpl::copy_to_user(zero_buf.as_ptr(), stats as usize, size).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + zero_buf.as_ptr(), + crate::arch::address::UA::from_usize(stats as usize), + size, + ) + .ok(); + } 0 // 成功 } @@ -1157,7 +1184,14 @@ pub fn getifaddrs(ifap: *mut *mut u8) -> isize { // 最后一个节点的 next 指针已经填充为 0(初始化时) // 复制整个结构到用户空间 - unsafe { crate::arch::ArchImpl::copy_to_user(kernel_buf.as_ptr(), user_mem_start, total_size).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + kernel_buf.as_ptr(), + crate::arch::address::UA::from_usize(user_mem_start), + total_size, + ) + .ok(); + } // 返回第一个 ifaddrs 的地址给用户 write_to_user(ifap, first_ifaddrs_addr as *mut u8); @@ -1405,7 +1439,14 @@ pub fn getsockopt( // Return a dummy congestion control name. iperf3 mainly uses this for display. let cc = b"cubic\0"; let n = core::cmp::min(available_len, cc.len()); - unsafe { crate::arch::ArchImpl::copy_to_user(cc.as_ptr(), optval as usize, n).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + cc.as_ptr(), + crate::arch::address::UA::from_usize(optval as usize), + n, + ) + .ok(); + } written_len = n; } TCP_INFO => { @@ -1413,7 +1454,14 @@ pub fn getsockopt( let info = TcpInfo::dummy_established(); let src = &info as *const TcpInfo as *const u8; let n = core::cmp::min(available_len, core::mem::size_of::()); - unsafe { crate::arch::ArchImpl::copy_to_user(src, optval as usize, n).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + src, + crate::arch::address::UA::from_usize(optval as usize), + n, + ) + .ok(); + } written_len = n; } _ => return -(ENOPROTOOPT as isize), @@ -1499,7 +1547,14 @@ pub fn sendto( use crate::net::socket::socket_sendto; let result = { let mut kernel_buf = alloc::vec![0u8; len]; - unsafe { crate::arch::ArchImpl::copy_from_user(buf as usize, kernel_buf.as_mut_ptr(), len).ok(); } + unsafe { + crate::arch::ArchImpl::copy_from_user( + crate::arch::address::UA::from_usize(buf as usize), + kernel_buf.as_mut_ptr(), + len, + ) + .ok(); + } socket_sendto(handle, &kernel_buf, endpoint) }; match result { @@ -1547,7 +1602,14 @@ pub fn recvfrom( let mut kernel_buf = alloc::vec![0u8; len]; match file.recvfrom(&mut kernel_buf) { Ok((n, addr)) => { - unsafe { crate::arch::ArchImpl::copy_to_user(kernel_buf.as_ptr(), buf as usize, n).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + kernel_buf.as_ptr(), + crate::arch::address::UA::from_usize(buf as usize), + n, + ) + .ok(); + } Ok((n, addr)) } Err(e) => Err(e), @@ -1559,7 +1621,14 @@ pub fn recvfrom( if !src_addr.is_null() && !addrlen.is_null() { let user_addrlen = read_from_user(addrlen as *const u32) as usize; let copy_len = user_addrlen.min(addr_buf.len()); - unsafe { crate::arch::ArchImpl::copy_to_user(addr_buf.as_ptr(), src_addr as usize, copy_len).ok(); } + unsafe { + crate::arch::ArchImpl::copy_to_user( + addr_buf.as_ptr(), + crate::arch::address::UA::from_usize(src_addr as usize), + copy_len, + ) + .ok(); + } write_to_user(addrlen, copy_len as u32); } pr_debug!( diff --git a/os/src/arch/syscall.rs b/os/src/kernel/syscall/numbers.rs similarity index 96% rename from os/src/arch/syscall.rs rename to os/src/kernel/syscall/numbers.rs index f15a0919..688e0792 100644 --- a/os/src/arch/syscall.rs +++ b/os/src/kernel/syscall/numbers.rs @@ -152,7 +152,4 @@ pub const SYS_STATX: usize = 291; // ---- 自定义内核扩展 ---- // 注意:此调用号在不同架构上可能不同 -#[cfg(target_arch = "loongarch64")] -pub const SYS_GETIFADDRS: usize = 1000; -#[cfg(not(target_arch = "loongarch64"))] -pub const SYS_GETIFADDRS: usize = 500; +pub const SYS_GETIFADDRS: usize = crate::arch::abi::SYS_GETIFADDRS; diff --git a/os/src/kernel/syscall/signal.rs b/os/src/kernel/syscall/signal.rs index b54b5bb3..75b4f0b5 100644 --- a/os/src/kernel/syscall/signal.rs +++ b/os/src/kernel/syscall/signal.rs @@ -11,8 +11,8 @@ use crate::{ arch::{timer::clock_freq, trap::restore}, ipc::{create_siginfo_for_signal, do_sigpending}, kernel::{ - SharedTask, TASK_MANAGER, TIMER_QUEUE, TaskManagerTrait, current_task, - sleep_task_with_guard_and_block, yield_task, + SharedTask, TASK_MANAGER, TIMER_QUEUE, TaskManagerTrait, current_task, sleep_task_prepare, + yield_task, }, sync::SpinLock, uapi::{ @@ -206,13 +206,12 @@ pub fn rt_sigsuspend(unewset: *const SigSetT, sigsetsize: c_uint) -> c_int { return -EINVAL; }; let task = current_task(); - let old_set; - { - let mut t = task.lock(); + let mut old_set = SignalFlags::empty(); + sleep_task_prepare(task.clone(), true, |t| { old_set = t.blocked; t.blocked = new_set; - sleep_task_with_guard_and_block(&mut t, task.clone(), true); - } + false + }); yield_task(); { let mut t = task.lock(); @@ -394,13 +393,13 @@ fn wait_for_signal( signal: SignalFlags, timeout: Option, ) -> Result<(usize, SigInfoT), i32> { - let mut t = task.lock(); if let Some(timeout) = timeout { if timeout.tv_sec < 0 || timeout.tv_nsec < 0 || timeout.tv_nsec >= 1_000_000_000 { return Err(-EINVAL); } if timeout.tv_sec == 0 && timeout.tv_nsec == 0 { // 轮询, 不阻塞 + let mut t = task.lock(); if t.pending.has_deliverable_signal(signal) || t.shared_pending.lock().has_deliverable_signal(signal) { @@ -418,51 +417,58 @@ fn wait_for_signal( } else { // 带超时的阻塞等待 let start = TimeSpec::now(); - while !t.pending.has_deliverable_signal(signal) - && !t.shared_pending.lock().has_deliverable_signal(signal) - { + loop { let now = TimeSpec::now(); if now - start > timeout { return Err(-EAGAIN); // 超时返回 } - TIMER_QUEUE - .lock() - .push(timeout.into_freq(clock_freq()), task.clone()); - sleep_task_with_guard_and_block(&mut t, task.clone(), true); - drop(t); + let slept = sleep_task_prepare(task.clone(), true, |t| { + if t.pending.has_deliverable_signal(signal) + || t.shared_pending.lock().has_deliverable_signal(signal) + { + return true; // 信号已到达,不睡眠 + } + TIMER_QUEUE + .lock() + .push(timeout.into_freq(clock_freq()), task.clone()); + false // 进入睡眠 + }); + if !slept { + TIMER_QUEUE.lock().remove_task(&task); + let mut t = task.lock(); + let flag = t + .pending + .first_deliverable_signal(signal) + .or_else(|| t.shared_pending.lock().first_deliverable_signal(signal)) + .unwrap(); + let sig_num = flag.to_signal_number(); + t.pending.signals.remove(flag); + return Ok((sig_num, create_siginfo_for_signal(flag))); + } yield_task(); - t = task.lock(); } - TIMER_QUEUE.lock().remove_task(&task); - let flag = t - .pending - .first_deliverable_signal(signal) - .or_else(|| t.shared_pending.lock().first_deliverable_signal(signal)) - .unwrap(); - let sig_num = flag.to_signal_number(); - t.pending.signals.remove(flag); - Ok((sig_num, create_siginfo_for_signal(flag))) } } else { // 阻塞等待 - while t - .pending - .first_target_signal(signal) - .or_else(|| t.shared_pending.lock().first_target_signal(signal)) - .is_none() - { - sleep_task_with_guard_and_block(&mut t, task.clone(), true); - drop(t); + loop { + let slept = sleep_task_prepare(task.clone(), true, |t| { + t.pending + .first_target_signal(signal) + .or_else(|| t.shared_pending.lock().first_target_signal(signal)) + .is_some() // 信号已到达则不睡眠 + }); + if !slept { + let mut t = task.lock(); + let flag = t + .pending + .first_target_signal(signal) + .or_else(|| t.shared_pending.lock().first_target_signal(signal)) + .unwrap(); + let sig_num = flag.to_signal_number(); + t.pending.signals.remove(flag); + return Ok((sig_num, create_siginfo_for_signal(flag))); + } yield_task(); - t = task.lock(); } - let flag = t - .pending - .first_target_signal(signal) - .or_else(|| t.shared_pending.lock().first_target_signal(signal)) - .unwrap(); - let sig_num = flag.to_signal_number(); - t.pending.signals.remove(flag); - Ok((sig_num, create_siginfo_for_signal(flag))) } } diff --git a/os/src/kernel/syscall/sys.rs b/os/src/kernel/syscall/sys.rs index 90f7a94b..e472bf92 100644 --- a/os/src/kernel/syscall/sys.rs +++ b/os/src/kernel/syscall/sys.rs @@ -272,7 +272,7 @@ pub fn syslog(type_: i32, bufp: *mut u8, len: i32) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( bytes.as_ptr(), - bufp as usize + total_written, + crate::arch::address::UA::from_usize(bufp as usize + total_written), bytes.len(), ) .ok(); @@ -311,7 +311,7 @@ pub fn syslog(type_: i32, bufp: *mut u8, len: i32) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( bytes.as_ptr(), - bufp as usize + total_written, + crate::arch::address::UA::from_usize(bufp as usize + total_written), bytes.len(), ) .ok(); @@ -344,7 +344,7 @@ pub fn syslog(type_: i32, bufp: *mut u8, len: i32) -> isize { unsafe { crate::arch::ArchImpl::copy_to_user( bytes.as_ptr(), - bufp as usize + total_written, + crate::arch::address::UA::from_usize(bufp as usize + total_written), bytes.len(), ) .ok(); diff --git a/os/src/kernel/syscall/task.rs b/os/src/kernel/syscall/task.rs index 94908b28..987f15a7 100644 --- a/os/src/kernel/syscall/task.rs +++ b/os/src/kernel/syscall/task.rs @@ -9,6 +9,7 @@ use alloc::{string::ToString, sync::Arc, vec::Vec}; use crate::{ arch::{ + address::UA, timer::{clock_freq, get_time}, trap::restore, }, @@ -16,13 +17,13 @@ use crate::{ kernel::{ FUTEX_MANAGER, Scheduler, SharedTask, TASK_MANAGER, TIMER, TIMER_QUEUE, TaskManagerTrait, TaskState, TaskStruct, TimerEntry, current_cpu, current_task, exit_process, schedule, - sleep_task_with_block, sleep_task_with_guard_and_block, + sleep_task, sleep_task_prepare, syscall::util::{get_args_safe, get_path_safe}, time::{REALTIME, realtime_now}, yield_task, }, mm::{ - address::{UsizeConvert, Vaddr}, + address::VA, frame_allocator::{alloc_contig_frames, alloc_frame}, memory_space::MemorySpace, }, @@ -100,15 +101,11 @@ fn clear_child_tid_and_wake() { let task = current_task(); let clear_addr = { let mut t = task.lock(); - let addr = t.clear_child_tid; // 避免重复清理 - t.clear_child_tid = 0; - addr + t.clear_child_tid.take() }; - if clear_addr == 0 { - return; - } + let Some(clear_addr) = clear_addr else { return }; // If the task has already dropped its user address space (e.g. forced exit paths), // we cannot touch userspace or translate the address. Best-effort: just skip. @@ -122,13 +119,13 @@ fn clear_child_tid_and_wake() { // 1) write 0 to userspace tid address unsafe { - write_to_user(clear_addr as *mut c_int, 0); + write_to_user(clear_addr.as_usize() as *mut c_int, 0); } // 2) futex wake let Some(paddr) = memory_space .lock() - .translate(Vaddr::from_usize(clear_addr as usize)) + .translate(VA::from_usize(clear_addr.as_usize())) .map(|p| p.as_usize()) else { return; @@ -282,25 +279,16 @@ pub fn clone( let tf = child_task.trap_frame_ptr.load(Ordering::SeqCst); unsafe { - (*tf).set_clone_trap_frame(&*ptf, child_task.kstack_base, stack as usize); + (*tf).set_clone_trap_frame(&*ptf, child_task.kstack_base.as_usize(), stack as usize); if requested_flags.contains(CloneFlags::SETTLS) { - #[cfg(target_arch = "riscv64")] - { - // RISC-V userspace uses tp register as thread pointer (TLS base) - (*tf).x4_tp = tls as usize; - } - #[cfg(target_arch = "loongarch64")] - { - // LoongArch userspace uses r2 (tp) register as thread pointer (TLS base) - (*tf).regs[2] = tls as usize; - } + (*tf).set_tls(tls as usize); } } if requested_flags.contains(CloneFlags::CHILD_SETTID) { - child_task.set_child_tid = ctid as usize; + child_task.set_child_tid = Some(UA::from_usize(ctid as usize)); } if requested_flags.contains(CloneFlags::CHILD_CLEARTID) { - child_task.clear_child_tid = ctid as usize; + child_task.clear_child_tid = Some(UA::from_usize(ctid as usize)); } let child_task = child_task.into_shared(); current_task() @@ -529,23 +517,34 @@ pub fn wait4(pid: c_int, wstatus: *mut c_int, options: c_int, _rusage: *mut Rusa }; let task = loop { - { - let mut t = cur_task.lock(); + let mut found: Option = None; + let mut nohang = false; + + let slept = sleep_task_prepare(cur_task.clone(), true, |t| { if let Some(res) = t.check_child(cond, !opt.contains(WaitFlags::NOWAIT)) { crate::pr_debug!("wait4: found child pid={}", res.lock().pid); + found = Some(res); + return true; + } + if opt.contains(WaitFlags::NOHANG) { + nohang = true; + return true; + } + let mut wc = t.wait_child.lock(); + if !wc.contains(&cur_task) { + wc.add_task(cur_task.clone()); + } + false + }); + + if !slept { + if let Some(res) = found { break res; - } else if opt.contains(WaitFlags::NOHANG) { - return 0; } - { - let mut wc = t.wait_child.lock(); - if !wc.contains(&cur_task) { - wc.add_task(cur_task.clone()); - } + if nohang { + return 0; } - sleep_task_with_guard_and_block(&mut t, cur_task.clone(), true); } - // 在没有持有任何锁的情况下调用调度相关操作 yield_task(); }; @@ -793,7 +792,7 @@ pub fn nanosleep(duration: *const TimeSpec, rem: *mut TimeSpec) -> c_int { let mut timer_q = TIMER_QUEUE.lock(); timer_q.push(trigger, task.clone()); - sleep_task_with_block(task.clone(), true); + sleep_task(task.clone(), true); drop(timer_q); yield_task(); @@ -859,7 +858,7 @@ pub fn clock_nanosleep( let mut timer_q = TIMER_QUEUE.lock(); timer_q.push(trigger, task.clone()); - sleep_task_with_block(task.clone(), true); + sleep_task(task.clone(), true); drop(timer_q); yield_task(); @@ -1028,7 +1027,7 @@ pub fn futex( .clone(); let paddr = if let Some(paddr) = memory_space .lock() - .translate(Vaddr::from_usize(uaddr as usize)) + .translate(VA::from_usize(uaddr as usize)) { paddr.as_usize() } else { @@ -1041,7 +1040,7 @@ pub fn futex( let task = current_task(); let waitq = fm.get_wait_queue(paddr); waitq.sleep(task.clone()); - sleep_task_with_block(task.clone(), true); + sleep_task(task.clone(), true); if !timeout.is_null() { let ts = unsafe { read_from_user(timeout) }; @@ -1093,7 +1092,7 @@ pub fn futex( .clone(); if let Some(paddr) = memory_space .lock() - .translate(Vaddr::from_usize(uaddr as usize)) + .translate(VA::from_usize(uaddr as usize)) { paddr.as_usize() } else { @@ -1124,7 +1123,7 @@ pub fn futex( /// - 返回当前线程的线程 ID (TID) pub fn set_tid_address(tidptr: *mut c_int) -> c_int { let task = current_task(); - task.lock().clear_child_tid = tidptr as usize; + task.lock().clear_child_tid = Some(UA::from_usize(tidptr as usize)); current_task().lock().tid as c_int } @@ -1148,7 +1147,7 @@ pub fn get_robust_list(pid: c_int, head_ptr: *mut *mut RobustListHead, sizep: *m let (head, size) = { let t = task.lock(); let head = match t.robust_list { - Some(h) => h as *mut RobustListHead, + Some(h) => h.as_usize() as *mut RobustListHead, None => core::ptr::null_mut(), }; let size = size_of::() as SizeT; @@ -1172,7 +1171,7 @@ pub fn set_robust_list(head: *const RobustListHead, size: SizeT) -> c_int { return -EINVAL; } let task = current_task(); - task.lock().robust_list = Some(head as usize); + task.lock().robust_list = Some(UA::from_usize(head as usize)); 0 } @@ -1228,19 +1227,7 @@ fn parse_hashbang(data: &[u8]) -> Result<(&str, Option<&str>), ()> { /// 执行一个新程序(execve)的准备阶段:解析 ELF 并创建新的地址空间 fn do_execve_prepare( path: &str, -) -> Result< - ( - Arc>, - usize, - usize, - usize, - usize, - usize, - usize, - usize, - ), - c_int, -> { +) -> Result<(Arc>, VA, VA, VA, usize, usize, VA, VA), c_int> { let prepared = match crate::kernel::task::prepare_exec_image_from_path(path) { Ok(p) => p, Err(crate::kernel::task::ExecImageError::Fs(FsError::NotFound)) => return Err(-ENOENT), @@ -1269,16 +1256,16 @@ fn do_execve_prepare( /// 注意:此函数不会返回! fn do_execve_switch( space: Arc>, - initial_pc: usize, - sp: usize, + initial_pc: VA, + sp: VA, exe_path: alloc::string::String, argv: Vec, envp: Vec, - phdr_addr: usize, + phdr_addr: VA, phnum: usize, phent: usize, - at_base: usize, - at_entry: usize, + at_base: VA, + at_entry: VA, ) -> c_int { let task = current_task(); diff --git a/os/src/kernel/syscall/util.rs b/os/src/kernel/syscall/util.rs index 5ef7f1c2..fdd19210 100644 --- a/os/src/kernel/syscall/util.rs +++ b/os/src/kernel/syscall/util.rs @@ -26,15 +26,19 @@ const PATH_MAX: usize = 4096; fn copy_str_from_user(user_ptr: usize) -> Result { let mut buf = [0u8; PATH_MAX]; let len = unsafe { - crate::arch::ArchImpl::copy_strn_from_user(user_ptr, buf.as_mut_ptr(), PATH_MAX) - .map_err(|_| "Failed to read string from user space")? + crate::arch::ArchImpl::copy_strn_from_user( + crate::arch::address::UA::from_usize(user_ptr), + buf.as_mut_ptr(), + PATH_MAX, + ) + .map_err(|_| "Failed to read string from user space")? }; if len == PATH_MAX { return Err("Path exceeds PATH_MAX"); } // copy_strn_from_user 在遇到 '\0' 时返回其索引(含 '\0') - let c_str = CStr::from_bytes_until_nul(&buf[..=len]) - .map_err(|_| "String is not null-terminated")?; + let c_str = + CStr::from_bytes_until_nul(&buf[..=len]).map_err(|_| "String is not null-terminated")?; c_str .to_str() .map(|s| s.to_string()) @@ -61,10 +65,7 @@ pub fn get_path_safe(path: usize) -> Result { /// # 返回值 /// - 成功时返回包含参数字符串的 `Vec` /// - 失败时返回错误字符串 -pub fn get_args_safe( - ptr_array: usize, - name: &str, -) -> Result, String> { +pub fn get_args_safe(ptr_array: usize, name: &str) -> Result, String> { let mut args = Vec::new(); if ptr_array == 0 { @@ -78,7 +79,7 @@ pub fn get_args_safe( let mut val = 0usize; unsafe { crate::arch::ArchImpl::copy_from_user( - ptr_array + offset, + crate::arch::address::UA::from_usize(ptr_array + offset), (&mut val) as *mut usize as *mut u8, core::mem::size_of::(), ) @@ -91,8 +92,8 @@ pub fn get_args_safe( break; // NULL 终止 } - let s = copy_str_from_user(ptr_val) - .map_err(|e| format!("{}[{}]: {}", name, args.len(), e))?; + let s = + copy_str_from_user(ptr_val).map_err(|e| format!("{}[{}]: {}", name, args.len(), e))?; args.push(s); offset += core::mem::size_of::(); diff --git a/os/src/kernel/task/exec_loader.rs b/os/src/kernel/task/exec_loader.rs index 6cdc739c..884f0f53 100644 --- a/os/src/kernel/task/exec_loader.rs +++ b/os/src/kernel/task/exec_loader.rs @@ -2,7 +2,8 @@ use alloc::string::{String, ToString}; use alloc::vec; use alloc::vec::Vec; -use crate::mm::address::{PageNum, UsizeConvert, Vaddr, Vpn}; +use crate::arch::abi::{RelocationKind, classify_relocation, resolve_relocation_value}; +use crate::mm::address::{PageNum, VA, Vpn}; use crate::mm::memory_space::MemorySpace; use crate::mm::memory_space::mapping_area::AreaType; use crate::mm::page_table::{PagingError, UniversalPTEFlag}; @@ -18,13 +19,13 @@ pub enum ExecImageError { pub struct PreparedExecImage { pub space: MemorySpace, /// 初始 PC:无动态链接器时为程序入口;有 PT_INTERP 时为动态链接器入口 - pub initial_pc: usize, - pub user_sp_high: usize, + pub initial_pc: VA, + pub user_sp_high: VA, /// auxv AT_BASE:动态链接器 load bias(无动态链接器时为 0) - pub at_base: usize, + pub at_base: VA, /// auxv AT_ENTRY:主程序入口(非动态链接器入口) - pub at_entry: usize, - pub phdr_addr: usize, + pub at_entry: VA, + pub phdr_addr: VA, pub phnum: usize, pub phent: usize, } @@ -34,9 +35,6 @@ const ELFDATA2LSB: u8 = 1; const ET_DYN: u16 = 3; -const EM_RISCV: u16 = 243; -const EM_LOONGARCH: u16 = 258; - const PT_LOAD: u32 = 1; const PT_DYNAMIC: u32 = 2; const PT_INTERP: u32 = 3; @@ -53,14 +51,6 @@ const DT_RELASZ: i64 = 8; const DT_RELAENT: i64 = 9; const DT_SYMENT: i64 = 11; -// riscv64 relocations -const R_RISCV_64: u32 = 2; -const R_RISCV_RELATIVE: u32 = 3; - -// loongarch64 relocations -const R_LARCH_64: u32 = 2; -const R_LARCH_RELATIVE: u32 = 3; - #[derive(Clone, Copy, Debug)] struct ElfHdr { e_type: u16, @@ -123,12 +113,7 @@ fn parse_elf_header(inode: &dyn Inode) -> Result { let e_phentsize = le_u16(&hdr[54..56]); let e_phnum = le_u16(&hdr[56..58]); - #[cfg(target_arch = "riscv64")] - if e_machine != EM_RISCV { - return Err(ExecImageError::InvalidElf); - } - #[cfg(target_arch = "loongarch64")] - if e_machine != EM_LOONGARCH { + if !crate::arch::abi::is_supported_elf_machine(e_machine) { return Err(ExecImageError::InvalidElf); } if e_phentsize as usize != 56 { @@ -239,7 +224,7 @@ fn load_segments_into_space( let map_start = space .find_free_region(total_size, crate::config::PAGE_SIZE) .ok_or(ExecImageError::Paging(PagingError::OutOfMemory))?; - map_start.saturating_sub(seg_start) + map_start.as_usize().saturating_sub(seg_start) } } else { 0 @@ -268,8 +253,8 @@ fn load_segments_into_space( } let vpn_range = crate::mm::address::VpnRange::new( - Vpn::from_addr_floor(Vaddr::from_usize(start_va)), - Vpn::from_addr_ceil(Vaddr::from_usize(end_va)), + Vpn::from_addr_floor(VA::from_usize(start_va)), + Vpn::from_addr_ceil(VA::from_usize(end_va)), ); let mut perm = UniversalPTEFlag::USER_ACCESSIBLE | UniversalPTEFlag::VALID; @@ -417,10 +402,10 @@ fn apply_static_pie_relocs( let r_sym = (r_info >> 32) as usize; let target_va = load_bias + r_offset; - #[cfg(target_arch = "riscv64")] - let value = match r_type { - R_RISCV_RELATIVE => (load_bias as isize + r_addend) as usize, - R_RISCV_64 => { + let kind = classify_relocation(r_type).ok_or(ExecImageError::InvalidElf)?; + let symbol_value = match kind { + RelocationKind::Relative => 0, + RelocationKind::Absolute64 => { if dt_symtab == 0 { return Err(ExecImageError::InvalidElf); } @@ -428,29 +413,10 @@ fn apply_static_pie_relocs( let st_value = space .read_u64_at(sym_addr + 8) .map_err(ExecImageError::Paging)? as usize; - let s = load_bias + st_value; - (s as isize + r_addend) as usize + st_value } - _ => return Err(ExecImageError::InvalidElf), }; - #[cfg(target_arch = "loongarch64")] - let value = match r_type { - R_LARCH_RELATIVE => (load_bias as isize + r_addend) as usize, - R_LARCH_64 => { - if dt_symtab == 0 { - return Err(ExecImageError::InvalidElf); - } - let sym_addr = load_bias + dt_symtab + r_sym * dt_syment; - let st_value = space - .read_u64_at(sym_addr + 8) - .map_err(ExecImageError::Paging)? as usize; - let s = load_bias + st_value; - (s as isize + r_addend) as usize - } - _ => return Err(ExecImageError::InvalidElf), - }; - #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] - let value = 0usize; + let value = resolve_relocation_value(kind, load_bias, symbol_value, r_addend); space .write_usize_at(target_va, value) @@ -490,14 +456,14 @@ pub fn prepare_exec_image_from_path(path: &str) -> Result Result u32 { (*tf).set_kernel_trap_frame( entry_point as usize, super::terminate_task as usize, - task.kstack_base, + task.kstack_base.as_usize(), ); let cpu_ptr = { let _guard = crate::sync::PreemptGuard::new(); @@ -168,9 +168,9 @@ pub fn kernel_execve(path: &str, argv: &[&str], envp: &[&str]) -> ! { super::prepare_exec_image_from_path(path).expect("kernel_execve: failed to prepare image"); crate::pr_info!( "[kernel_execve] Prepared image, pc=0x{:x}, at_base=0x{:x}, at_entry=0x{:x}", - prepared.initial_pc, - prepared.at_base, - prepared.at_entry + prepared.initial_pc.as_usize(), + prepared.at_base.as_usize(), + prepared.at_entry.as_usize() ); // 2. 包装内存空间 @@ -212,177 +212,11 @@ pub fn kernel_execve(path: &str, argv: &[&str], envp: &[&str]) -> ! { crate::pr_info!("[kernel_execve] Switching to user mode"); let tfp = task.lock().trap_frame_ptr.load(Ordering::SeqCst); - #[cfg(target_arch = "loongarch64")] - { - if tfp.is_null() { - crate::pr_err!("[kernel_execve] trap_frame_ptr is null"); - panic!("kernel_execve: null trap_frame_ptr"); - } - crate::pr_debug!("[kernel_execve] trap_frame_ptr={:#x}", tfp as usize); - } - #[cfg(target_arch = "loongarch64")] - unsafe { - crate::pr_debug!( - "[kernel_execve] trapframe: era={:#x}, sp={:#x}, prmd={:#x}, crmd={:#x}, a0={:#x}, a1={:#x}, a2={:#x}", - (*tfp).get_sepc(), - (*tfp).get_sp(), - (*tfp).prmd, - (*tfp).crmd, - (*tfp).get_a0(), - (*tfp).regs[5], - (*tfp).regs[6], - ); - } - #[cfg(target_arch = "loongarch64")] - { - use crate::mm::address::PageNum; - use crate::mm::address::{UsizeConvert, Vaddr}; - let tlbrent: usize; - let crmd: usize; - let pgdl: usize; - let pgdh: usize; - let ecfg: usize; - let ks0: usize; - let asid: usize; - let tlbrehi: usize; - let tlbrelo0: usize; - let tlbrelo1: usize; - unsafe { - core::arch::asm!( - "csrrd {0}, 0x88", - out(reg) tlbrent, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x0", - out(reg) crmd, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x19", - out(reg) pgdl, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x1a", - out(reg) pgdh, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x4", - out(reg) ecfg, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x30", - out(reg) ks0, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x18", - out(reg) asid, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x8e", - out(reg) tlbrehi, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x8c", - out(reg) tlbrelo0, - options(nostack, preserves_flags) - ); - core::arch::asm!( - "csrrd {0}, 0x8d", - out(reg) tlbrelo1, - options(nostack, preserves_flags) - ); - } - let space = crate::kernel::current_memory_space(); - let space = space.lock(); - let root_ppn = space.root_ppn(); - let root_paddr = root_ppn.start_addr().as_usize(); - let entry_va = ::from_usize(prepared.initial_pc); - let sp_va = ::from_usize(prepared.user_sp_high); - unsafe extern "C" { - fn tlb_refill_entry(); - } - let tlbr_entry_vaddr = tlb_refill_entry as usize; - let tlbr_entry_paddr = - unsafe { crate::arch::vaddr_to_paddr(tlbr_entry_vaddr) } & !0xfff; - let tlbr_entry_dm_vaddr = crate::arch::paddr_to_vaddr(tlbr_entry_paddr); - crate::pr_debug!( - "[kernel_execve] va translate: entry={:?}, sp={:?}", - space.translate(entry_va), - space.translate(sp_va) - ); - // 检查页表项内容 - use crate::mm::address::Vpn; - use crate::mm::page_table::PageTableInner; - let entry_vpn = Vpn::from_addr_floor(entry_va); - if let Ok((ppn, _, flags)) = space.page_table().walk(entry_vpn) { - crate::pr_debug!( - "[kernel_execve] entry PTE: vpn={:#x}, ppn={:#x}, flags={:?}", - entry_vpn.0, - ppn.0, - flags - ); - } else { - crate::pr_err!("[kernel_execve] entry page not mapped!"); - } - crate::pr_debug!( - "[kernel_execve] root_ppn={:#x}, root_paddr={:#x}", - root_ppn.0, - root_paddr - ); - crate::pr_debug!( - "[kernel_execve] tlbrent={:#x}, crmd={:#x}, pgdl={:#x}, pgdh={:#x}, ecfg={:#x}, ks0={:#x}", - tlbrent, - crmd, - pgdl, - pgdh, - ecfg, - ks0 - ); - crate::pr_debug!( - "[kernel_execve] asid={:#x} (full_csr={:#x}), tlbrehi={:#x}, tlbrelo0={:#x}, tlbrelo1={:#x}", - asid & 0x3ff, - asid, - tlbrehi, - tlbrelo0, - tlbrelo1 - ); - crate::pr_debug!( - "[kernel_execve] tlb_refill_entry: vaddr={:#x}, paddr={:#x}, dm_vaddr={:#x}", - tlbr_entry_vaddr, - tlbr_entry_paddr, - tlbr_entry_dm_vaddr - ); - // TLB refill 运行在直接地址翻译模式,无法安全访问全局变量做统计 - } - #[cfg(target_arch = "loongarch64")] unsafe { - // Ensure KScratch0 points to the current task's trap frame before returning to user mode. - core::arch::asm!( - "csrwr {0}, 0x30", - in(reg) tfp as usize, - options(nostack, preserves_flags) - ); - // Reset TLB refill debug counter (CSR.TLBRSAVE) so we can observe the first refill after - // entering user mode. - core::arch::asm!("csrwr $zero, 0x8b", options(nostack, preserves_flags)); - } - #[cfg(target_arch = "riscv64")] - unsafe { - crate::pr_info!( - "[kernel_execve] trapframe: sepc={:#x}, sp={:#x}, sstatus={:#x}, a0={:#x}, a1={:#x}, a2={:#x}", - (*tfp).sepc, - (*tfp).x2_sp, - (*tfp).sstatus, - (*tfp).x10_a0, - (*tfp).x11_a1, - (*tfp).x12_a2, + crate::arch::kernel::task::prepare_user_restore( + tfp, + prepared.initial_pc, + prepared.user_sp_high, ); } // SAFETY: tfp 指向的内存已经被分配且由当前任务拥有 diff --git a/os/src/kernel/task/mod.rs b/os/src/kernel/task/mod.rs index 6ea82a9e..53c2bc69 100644 --- a/os/src/kernel/task/mod.rs +++ b/os/src/kernel/task/mod.rs @@ -39,17 +39,11 @@ use crate::mm::memory_space::MemorySpace; use crate::sync::SpinLock; use crate::uapi::signal::NUM_SIGCHLD; use crate::{ - arch::trap::restore, kernel::{cpu::current_cpu, schedule}, vfs::{FDTable, File, FsError}, }; -#[cfg(not(target_arch = "loongarch64"))] -use crate::arch::trap::TrapFrame; - -/// 新创建的线程发生第一次调度时会从 forkret 开始执行 -/// 该函数负责恢复任务的陷阱帧,从而进入任务的实际执行上下文 -#[cfg(target_arch = "loongarch64")] +/// 新创建的线程发生第一次调度时会从 forkret 开始执行。 pub(crate) fn forkret() { let (tf_ptr, is_kernel_thread) = { let _guard = crate::sync::PreemptGuard::new(); @@ -65,39 +59,7 @@ pub(crate) fn forkret() { t.memory_space.is_none(), ) }; - - // LoongArch: 内核线程首次运行不走 “ertn” 的异常返回路径, - // 否则会错误改写 CRMD/翻译模式导致卡死;直接切换栈并跳转到 entry 即可。 - if is_kernel_thread { - // SAFETY: tf_ptr 指向当前任务拥有的 TrapFrame;entry/sp 由创建逻辑填充 - let (entry, sp) = unsafe { ((*tf_ptr).era, (*tf_ptr).kernel_sp) }; - unsafe { - core::arch::asm!( - "addi.d $sp, {sp}, 0", - "jirl $zero, {entry}, 0", - sp = in(reg) sp, - entry = in(reg) entry, - options(noreturn) - ); - } - } - - // 用户任务:仍然通过 restore->ertn 进入用户态 - // SAFETY: tf_ptr 指向的内存已经被分配且由当前任务拥有 - unsafe { restore(&*tf_ptr) }; -} - -#[cfg(not(target_arch = "loongarch64"))] -pub(crate) fn forkret() { - let fp: *mut TrapFrame; - { - let _guard = crate::sync::PreemptGuard::new(); - let cpu = current_cpu(); - let task = cpu.current_task.as_ref().unwrap(); - fp = task.lock().trap_frame_ptr.load(Ordering::SeqCst); - } - // SAFETY: fp 指向的内存已经被分配且由当前任务拥有 - unsafe { restore(&*fp) }; + unsafe { crate::arch::kernel::task::forkret_restore(tf_ptr, is_kernel_thread) }; } /// 在任务结束时调用的函数 diff --git a/os/src/kernel/task/process.rs b/os/src/kernel/task/process.rs index fbf88bd1..ae96bd50 100644 --- a/os/src/kernel/task/process.rs +++ b/os/src/kernel/task/process.rs @@ -4,9 +4,7 @@ //! 故此模块变得相对简单,主要负责适配传统的进程概念与内核任务之间的关系。 use crate::{ - kernel::{ - SharedTask, TASK_MANAGER, TaskManagerTrait, TaskState, notify_parent, wake_up_with_block, - }, + kernel::{SharedTask, TASK_MANAGER, TaskManagerTrait, TaskState, notify_parent, wake_up_task}, uapi::signal::SignalFlags, }; @@ -77,7 +75,7 @@ pub fn send_signal_process(task: &SharedTask, sig: usize) { t.state == TaskState::Interruptible && !t.blocked.contains(flag) }; if should_wake { - wake_up_with_block(thr); + wake_up_task(thr); break; } } diff --git a/os/src/kernel/task/task_manager.rs b/os/src/kernel/task/task_manager.rs index fb22e572..c14a4cf0 100644 --- a/os/src/kernel/task/task_manager.rs +++ b/os/src/kernel/task/task_manager.rs @@ -11,7 +11,7 @@ use alloc::vec::Vec; use crate::kernel::task::SharedTask; use crate::kernel::task::tid_allocator::TidAllocator; -use crate::kernel::{TaskState, exit_task_with_block, wake_up_with_block}; +use crate::kernel::{TaskState, exit_task, wake_up_task}; use crate::sync::SpinLock; use crate::uapi::signal::SignalFlags; @@ -135,7 +135,7 @@ impl TaskManagerTrait for TaskManager { // 线程组共享的地址空间由 Arc 计数管理:最后一个线程退出时自动释放。 task.memory_space = None; } - exit_task_with_block(task); + exit_task(task); } fn release_task(&mut self, task: SharedTask) { @@ -177,7 +177,7 @@ impl TaskManagerTrait for TaskManager { t.pending.signals.insert(signal_flag); if t.state == TaskState::Interruptible { drop(t); - wake_up_with_block(task.clone()); + wake_up_task(task.clone()); } true } else { @@ -227,15 +227,15 @@ mod tests { Arc::new(SpinLock::new(task)) } - // 通过 TaskManager 分配 tid:应从 1 开始递增 + // 通过 TaskManager 分配 tid:TidAllocator 从 2 开始(1 保留给 init 进程) test_case!(test_task_manager_allocate_sequence, { let mut tm = TaskManager::new(); let t1 = tm.allocate_tid(); let t2 = tm.allocate_tid(); let t3 = tm.allocate_tid(); - kassert!(t1 == 1); - kassert!(t2 == 2); - kassert!(t3 == 3); + kassert!(t1 == 2); + kassert!(t2 == 3); + kassert!(t3 == 4); }); // 对不存在的 tid 进行查询与退出 diff --git a/os/src/kernel/task/task_struct.rs b/os/src/kernel/task/task_struct.rs index 265fec88..5360520a 100644 --- a/os/src/kernel/task/task_struct.rs +++ b/os/src/kernel/task/task_struct.rs @@ -8,7 +8,7 @@ use alloc::{string::String, sync::Arc, vec::Vec}; use crate::{ arch::{ - kernel::{context::Context, task::setup_stack_layout}, + kernel::{context::Context, task::setup_exec_stack_layout}, trap::TrapFrame, }, ipc::{SignalHandlerTable, SignalPending}, @@ -17,7 +17,7 @@ use crate::{ task::{forkret, task_state::TaskState}, }, mm::{ - address::{ConvertablePaddr, PageNum, UsizeConvert}, + address::{ConvertablePA, PageNum, UA, VA}, frame_allocator::{FrameRangeTracker, FrameTracker}, memory_space::MemorySpace, }, @@ -89,7 +89,7 @@ pub struct Task { /// 任务的等待队列 pub wait_child: Arc>, /// 内核栈基址 - pub kstack_base: usize, + pub kstack_base: VA, /// 中断上下文。指向当前任务内核栈上的 TrapFrame,仅在任务被中断时有效。 pub trap_frame_ptr: AtomicPtr, /// 任务的内存空间 @@ -121,11 +121,11 @@ pub struct Task { /// 资源限制结构体 pub rlimit: Arc>, /// 健壮列表头地址及其大小 - pub robust_list: Option, + pub robust_list: Option, /// 线程ID地址 - pub set_child_tid: usize, + pub set_child_tid: Option, /// 线程退出时清除的线程ID地址 - pub clear_child_tid: usize, + pub clear_child_tid: Option, // === 权限和凭证 === /// 任务凭证(用户、组、能力) @@ -202,7 +202,7 @@ impl Task { fs, ); task.context - .set_init_context(forkret as usize, task.kstack_base); + .set_init_context(forkret as usize, task.kstack_base.as_usize()); task } @@ -252,7 +252,7 @@ impl Task { fs, ); task.context - .set_init_context(forkret as usize, task.kstack_base); + .set_init_context(forkret as usize, task.kstack_base.as_usize()); task } @@ -266,15 +266,15 @@ impl Task { pub fn execve( &mut self, new_memory_space: Arc>, - initial_pc: usize, - sp_high: usize, + initial_pc: VA, + sp_high: VA, argv: &[&str], envp: &[&str], - phdr_addr: usize, + phdr_addr: VA, phnum: usize, phent: usize, - at_base: usize, - at_entry: usize, + at_base: VA, + at_entry: VA, ) { // 1. 切换任务的地址空间对象 self.memory_space = Some(new_memory_space); @@ -292,45 +292,26 @@ impl Task { // 也就是说,new_memory_space 已经被激活(切换 satp) // 否则必须实现类似 copy_to_user 的函数来完成拷贝,不然会引发页错误 // 3. 设置用户栈布局,包含命令行参数和环境变量 - #[cfg(target_arch = "loongarch64")] - let (new_sp, argc, argv_vec_ptr, envp_vec_ptr, tls_tp) = { + let stack_layout = { let space = self .memory_space .as_ref() .expect("execve: memory_space not set") .lock(); - setup_stack_layout( + setup_exec_stack_layout( &space, sp_high, argv, envp, phdr_addr, phnum, phent, at_base, at_entry, ) }; - #[cfg(target_arch = "riscv64")] - let (new_sp, argc, argv_vec_ptr, envp_vec_ptr) = setup_stack_layout( - sp_high, argv, envp, phdr_addr, phnum, phent, at_base, at_entry, - ); // 4. 配置 TrapFrame (新的上下文) // SAFETY: tfptr 指向的内存已经被分配且可写,并由 task 拥有 unsafe { // 清零整个 TrapFrame,避免旧值泄漏到用户态 core::ptr::write_bytes(tf_ptr, 0, 1); - #[cfg(target_arch = "loongarch64")] - (*tf_ptr).set_exec_trap_frame( - initial_pc, - new_sp, - self.kstack_base, - argc, - argv_vec_ptr, - envp_vec_ptr, - tls_tp, - ); - #[cfg(target_arch = "riscv64")] - (*tf_ptr).set_exec_trap_frame( - initial_pc, - new_sp, - self.kstack_base, - argc, - argv_vec_ptr, - envp_vec_ptr, + (*tf_ptr).set_exec_trap_frame_from_layout( + initial_pc.as_usize(), + self.kstack_base.as_usize(), + &stack_layout, ); let cpu_ptr = { let _guard = crate::sync::PreemptGuard::new(); @@ -409,8 +390,8 @@ impl Task { fd_table: Arc, fs: Arc>, ) -> Self { - let trap_frame_ptr = trap_frame_tracker.ppn().start_addr().to_vaddr().as_usize(); - let kstack_base = kstack_tracker.end_ppn().start_addr().to_vaddr().as_usize(); + let trap_frame_ptr = trap_frame_tracker.ppn().start_addr().to_va().as_usize(); + let kstack_base = kstack_tracker.end_ppn().start_addr().to_va(); Task { context: Context::zero_init(), @@ -442,8 +423,8 @@ impl Task { pending: SignalPending::empty(), shared_pending, robust_list: None, - set_child_tid: 0, - clear_child_tid: 0, + set_child_tid: None, + clear_child_tid: None, credential: super::Credential::root(), umask: 0o022, fd_table, diff --git a/os/src/kernel/task/work_queue.rs b/os/src/kernel/task/work_queue.rs index 569f7c8c..d9c91492 100644 --- a/os/src/kernel/task/work_queue.rs +++ b/os/src/kernel/task/work_queue.rs @@ -8,9 +8,7 @@ use alloc::{collections::vec_deque::VecDeque, vec::Vec}; use crate::{ - kernel::{ - SharedTask, TaskState, current_task, sleep_task_with_block, wake_up_with_block, yield_task, - }, + kernel::{SharedTask, TaskState, current_task, sleep_task, wake_up_task, yield_task}, sync::SpinLock, }; @@ -57,7 +55,7 @@ impl WorkQueue { if self.sleeping > 0 { for task in &self.worker { if task.lock().state == TaskState::Interruptible { - wake_up_with_block(task.clone()); + wake_up_task(task.clone()); break; } } @@ -80,7 +78,7 @@ pub fn kworker() { (work.task)(); } else { queue.sleeping += 1; - sleep_task_with_block(current_task(), true); + sleep_task(current_task(), true); drop(queue); yield_task(); GLOBAL_WORK_QUEUE.lock().sleeping -= 1; diff --git a/os/src/main.rs b/os/src/main.rs index 1b743fed..203bccd1 100644 --- a/os/src/main.rs +++ b/os/src/main.rs @@ -28,17 +28,15 @@ mod util; #[macro_use] mod log; -mod mm; mod device; mod fs; mod ipc; +mod mm; mod net; mod security; mod vfs; -use crate::arch::Arch; -#[cfg(target_arch = "loongarch64")] -use core::arch::asm; +use crate::arch::Platform; use core::panic::PanicInfo; #[cfg(test)] use test::test_runner; diff --git a/os/src/mm/address/mod.rs b/os/src/mm/address/mod.rs index c9893619..888f230d 100644 --- a/os/src/mm/address/mod.rs +++ b/os/src/mm/address/mod.rs @@ -6,16 +6,16 @@ //! # 地址类型 //! //! - Address - 表示内存地址(物理或虚拟)的 Trait -//! - [`Paddr`] - 物理地址类型 -//! - [`Vaddr`] - 虚拟地址类型 -//! - [`ConvertablePaddr`] - 将物理地址转换为虚拟地址的 Trait -//! - ConvertableVaddr - 将虚拟地址转换为物理地址的 Trait +//! - [`PA`] - 物理地址类型 +//! - [`VA`] - 虚拟地址类型 +//! - [`ConvertablePA`] - 将物理地址转换为虚拟地址的 Trait +//! - ConvertableVA - 将虚拟地址转换为物理地址的 Trait //! //! # 地址范围 //! //! - AddressRange - 泛型地址范围 -//! - PaddrRange - 物理地址范围的类型别名 -//! - VaddrRange - 虚拟地址范围的类型别名 +//! - PARange - 物理地址范围的类型别名 +//! - VARange - 虚拟地址范围的类型别名 //! - AddressRangeIterator - 地址范围的迭代器 //! //! # 页码 @@ -38,10 +38,13 @@ //! - [`UsizeConvert`] - 在类型和 usize 之间进行转换 //! - CalcOps - 算术和位操作 //! - AlignOps - 地址对齐操作 -mod types; mod operations; mod page_num; +mod types; -pub use types::{ConvertablePaddr, Paddr, Vaddr}; pub use operations::UsizeConvert; pub use page_num::{PageNum, Ppn, PpnRange, Vpn, VpnRange}; +#[allow(unused_imports)] +pub use types::{ + Address, AddressRange, ConvertablePA, ConvertableVA, PA, PARange, UA, VA, VARange, +}; diff --git a/os/src/mm/address/operations.rs b/os/src/mm/address/operations.rs index 723ed16d..0e16e224 100644 --- a/os/src/mm/address/operations.rs +++ b/os/src/mm/address/operations.rs @@ -1,6 +1,6 @@ //! Address Operations Module //! -//! 此模块定义了用于自定义地址类型(如 Paddr 和 Vaddr)的数学、位操作和对齐 Trait。 +//! 此模块定义了用于自定义地址类型(如 PA 和 VA)的数学、位操作和对齐 Trait。 //! 目标是使强类型地址在使用时具备与 `usize` 相同的运算能力,同时保持类型安全。 use crate::config::PAGE_SIZE; @@ -12,7 +12,7 @@ use core::ops::{ /// [UsizeConvert] Trait /// --------------------- /// 允许类型与 usize 之间互相转换。 -/// 任何自定义的地址或页码类型 (例如 Paddr, Vaddr) 必须实现此 Trait, +/// 任何自定义的地址或页码类型 (例如 PA, VA) 必须实现此 Trait, /// 以便进行底层数值操作。 pub trait UsizeConvert: Copy + Clone + PartialEq + PartialOrd + Eq + Ord { /// 将类型转换为 usize。 diff --git a/os/src/mm/address/page_num.rs b/os/src/mm/address/page_num.rs index 84359ff0..25b80eec 100644 --- a/os/src/mm/address/page_num.rs +++ b/os/src/mm/address/page_num.rs @@ -6,8 +6,8 @@ //! 页码是地址空间中页 (Page) 的索引,它将内存管理抽象与底层硬件地址解耦。 use crate::config::PAGE_SIZE; -use crate::mm::address::types::{Address, Paddr, Vaddr}; use crate::mm::address::operations::{AlignOps, CalcOps, UsizeConvert}; +use crate::mm::address::types::{Address, PA, VA}; use core::ops::Range; /// [PageNum] Trait @@ -18,7 +18,7 @@ use core::ops::Range; pub trait PageNum: CalcOps + UsizeConvert + Copy + Clone + PartialEq + PartialOrd + Eq + Ord { - /// 此页码类型关联的地址类型(例如 Ppn 关联 Paddr,Vpn 关联 Vaddr)。 + /// 此页码类型关联的地址类型(例如 Ppn 关联 PA,Vpn 关联 VA)。 type TAddress: Address + AlignOps; // PageNum 的地址需要支持 AlignOps /// 将页码增加 1。 @@ -111,7 +111,7 @@ pub trait PageNum: /// #[repr(transparent)] /// #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] /// pub struct MyPpn(pub usize); -/// impl_page_num!(MyPpn, Paddr); // Paddr 是关联的地址类型 +/// impl_page_num!(MyPpn, PA); // PA 是关联的地址类型 /// ``` #[macro_export] macro_rules! impl_page_num { @@ -139,19 +139,19 @@ macro_rules! impl_page_num { /// [Ppn] (Physical Page Number) /// --------------------- -/// 物理页码,对应物理地址 (Paddr)。 +/// 物理页码,对应物理地址 (PA)。 #[repr(transparent)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Ppn(pub usize); -impl_page_num!(Ppn, Paddr); +impl_page_num!(Ppn, PA); /// [Vpn] (Virtual Page Number) /// --------------------- -/// 虚拟页码,对应虚拟地址 (Vaddr)。 +/// 虚拟页码,对应虚拟地址 (VA)。 #[repr(transparent)] #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] pub struct Vpn(pub usize); -impl_page_num!(Vpn, Vaddr); +impl_page_num!(Vpn, VA); /// [PageNumRange] /// --------------------- @@ -292,7 +292,7 @@ pub type VpnRange = PageNumRange; #[cfg(test)] mod page_num_tests { use super::*; - use crate::mm::address::{Paddr, PageNum, Ppn, Vpn}; + use crate::mm::address::{PA, PageNum, Ppn, Vpn}; use crate::{kassert, test_case}; // 1. Ppn/Vpn 基本转换测试 @@ -307,7 +307,7 @@ mod page_num_tests { // 2. 地址到页码的转换测试 test_case!(test_pagenum_from_addr, { - let paddr = Paddr::from_usize(0x8000_1234); + let paddr = PA::from_usize(0x8000_1234); // 向下取整 (floor): 0x8000_1234 位于页 0x80001 let ppn_floor = Ppn::from_addr_floor(paddr); @@ -322,7 +322,7 @@ mod page_num_tests { test_case!(test_pagenum_to_addr, { let ppn = Ppn::from_usize(0x80000); - // 起始地址 (Paddr::from_usize(0x80000 * 0x1000)) + // 起始地址 (PA::from_usize(0x80000 * 0x1000)) let start = ppn.start_addr(); kassert!(start.as_usize() == 0x8000_0000); @@ -370,13 +370,13 @@ mod page_num_tests { // 7. floor 和 ceil 转换的差异测试 test_case!(test_floor_ceil_difference, { // 对齐的地址: floor == ceil (页码一样) - let aligned = Paddr::from_usize(0x8000_0000); + let aligned = PA::from_usize(0x8000_0000); let floor1 = Ppn::from_addr_floor(aligned); let ceil1 = Ppn::from_addr_ceil(aligned); kassert!(floor1.as_usize() == ceil1.as_usize()); // 未对齐的地址: ceil = floor + 1 (向上取整到下一页) - let unaligned = Paddr::from_usize(0x8000_0001); + let unaligned = PA::from_usize(0x8000_0001); let floor2 = Ppn::from_addr_floor(unaligned); // 0x80000 let ceil2 = Ppn::from_addr_ceil(unaligned); // 0x80001 kassert!(ceil2.as_usize() == floor2.as_usize() + 1); diff --git a/os/src/mm/address/types.rs b/os/src/mm/address/types.rs index 68be4c4c..5feaedf3 100644 --- a/os/src/mm/address/types.rs +++ b/os/src/mm/address/types.rs @@ -1,9 +1,10 @@ //! 地址抽象模块 //! //! 此模块定义了表示内存地址的核心 Trait ([Address]),以及具体的 -//! 地址类型 ([Paddr] 物理地址, [Vaddr] 虚拟地址),并提供了地址算术、 +//! 架构地址类型 ([PA] 物理地址, [VA] 虚拟地址, [UA] 用户地址),并提供了地址算术、 //! 对齐操作以及地址范围 ([AddressRange]) 的支持。 +pub use crate::arch::address::{PA, UA, VA}; use crate::mm::address::operations::{AlignOps, CalcOps, UsizeConvert}; use core::mem::size_of; use core::ops::Range; @@ -103,172 +104,65 @@ pub trait Address: } } -/// `impl_address!` 宏 -/// --------------------- -/// 快速为地址类型实现所有必需的 Trait: [UsizeConvert], [CalcOps], [AlignOps], [Address]。 -/// -/// 注意:这里使用 `transmute` 在地址类型 (例如 `Paddr(*const ())`) 和 `usize` 之间进行 -/// 零开销转换,这是操作地址类型时的标准做法。 -#[macro_export] -macro_rules! impl_address { - ($type:ty) => { - impl $crate::mm::address::operations::UsizeConvert for $type { - /// 将地址类型转换为其原始的 `usize` 值。 +macro_rules! impl_arch_address { + ($addr:ty) => { + impl UsizeConvert for $addr { fn as_usize(&self) -> usize { - // SAFETY: 地址类型 (Paddr/Vaddr) 是 transparent 的,并且保证和 usize 大小相同。 - unsafe { core::mem::transmute::(*self) } + <$addr>::as_usize(self) } - /// 从 `usize` 值创建地址类型。 fn from_usize(value: usize) -> Self { - // SAFETY: 这是一个零开销的转换,将原始值转换为地址类型。 - unsafe { core::mem::transmute::(value) } + <$addr>::from_usize(value) } } - $crate::impl_calc_ops!($type); - impl $crate::mm::address::operations::AlignOps for $type {} - - impl $crate::mm::address::types::Address for $type {} - - // 地址类型通常需要在多线程环境下传递和共享 - unsafe impl Sync for $type {} - unsafe impl Send for $type {} + crate::impl_calc_ops!($addr); + impl AlignOps for $addr {} + impl Address for $addr {} }; } -/// [ConvertablePaddr] Trait +impl_arch_address!(PA); +impl_arch_address!(VA); +impl_arch_address!(UA); + +/// [ConvertablePA] Trait /// --------------------- /// 物理地址转换为虚拟地址的能力。 -pub trait ConvertablePaddr { +pub trait ConvertablePA { /// 检查地址是否是有效的物理地址。 - fn is_valid_paddr(&self) -> bool; + fn is_valid_pa(&self) -> bool; /// 将物理地址转换为虚拟地址。 - fn to_vaddr(&self) -> Vaddr; -} - -/// [Paddr] (Physical Address) -/// --------------------- -/// 物理内存地址,对应于内存芯片上的实际位置。 -/// -/// 内部封装 `hal::address::PA`(`Address`), -/// 通过 sealed trait 模式在编译期防止地址空间混用。 -#[repr(transparent)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct Paddr(pub crate::arch::address::PA); - -impl UsizeConvert for Paddr { - fn as_usize(&self) -> usize { - self.0.as_usize() - } - fn from_usize(value: usize) -> Self { - Self(crate::arch::address::PA::from_usize(value)) - } + fn to_va(&self) -> VA; } -crate::impl_calc_ops!(Paddr); -impl AlignOps for Paddr {} -impl Address for Paddr {} -unsafe impl Sync for Paddr {} -unsafe impl Send for Paddr {} -impl ConvertablePaddr for Paddr { - fn is_valid_paddr(&self) -> bool { - self.as_usize() == unsafe { crate::arch::vaddr_to_paddr(self.as_usize()) } +impl ConvertablePA for PA { + fn is_valid_pa(&self) -> bool { + unsafe { crate::arch::va_to_pa(crate::arch::pa_to_va(*self)) == *self } } - fn to_vaddr(&self) -> Vaddr { - Vaddr::from_usize(crate::arch::paddr_to_vaddr(self.as_usize())) + fn to_va(&self) -> VA { + crate::arch::pa_to_va(*self) } } -/// [ConvertableVaddr] Trait +/// [ConvertableVA] Trait /// --------------------- /// 虚拟地址转换为物理地址的能力。 -pub trait ConvertableVaddr { +pub trait ConvertableVA { /// 检查地址是否是有效的虚拟地址。 - fn is_valid_vaddr(&self) -> bool; + fn is_valid_va(&self) -> bool; /// 将虚拟地址转换为物理地址。 - fn to_paddr(&self) -> Paddr; + fn to_pa(&self) -> PA; } -/// [Vaddr] (Virtual Address) -/// --------------------- -/// 虚拟内存地址,对应于进程或内核的页表映射空间中的位置。 -/// -/// 内部封装 `hal::address::VA`(`Address`), -/// 通过 sealed trait 模式在编译期防止地址空间混用。 -#[repr(transparent)] -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] -pub struct Vaddr(pub crate::arch::address::VA); - -impl UsizeConvert for Vaddr { - fn as_usize(&self) -> usize { - self.0.as_usize() - } - fn from_usize(value: usize) -> Self { - Self(crate::arch::address::VA::from_usize(value)) - } -} -crate::impl_calc_ops!(Vaddr); -impl AlignOps for Vaddr {} -impl Address for Vaddr {} -unsafe impl Sync for Vaddr {} -unsafe impl Send for Vaddr {} - -impl ConvertableVaddr for Vaddr { - fn is_valid_vaddr(&self) -> bool { - self.as_usize() == crate::arch::paddr_to_vaddr(self.as_usize()) +impl ConvertableVA for VA { + fn is_valid_va(&self) -> bool { + crate::arch::is_direct_mapped_va(*self) } - fn to_paddr(&self) -> Paddr { - Paddr::from_usize(unsafe { crate::arch::vaddr_to_paddr(self.as_usize()) }) - } -} - -impl Vaddr { - /// 从一个不可变引用创建虚拟地址。 - pub fn from_ref(r: &T) -> Self { - Self::from_ptr(r as *const T) - } - - /// 从一个常量指针创建虚拟地址。 - pub fn from_ptr(p: *const T) -> Self { - Self::from_usize(p as usize) - } - - /// 将虚拟地址转换为一个不可变引用。 - /// - /// # Safety (不安全函数) - /// 调用者必须确保: - /// 1. 地址指向的内存是 **有效** 的且 **已初始化** 的 `T` 类型数据。 - /// 2. 内存在引用的生命周期内不会被修改 (即引用是不可变的)。 - /// 3. 地址已经正确映射,且对齐满足 `T` 的要求。 - pub unsafe fn as_ref(&self) -> &T { - unsafe { &*(self.as_usize() as *const T) } - } - - /// 将虚拟地址转换为一个可变引用。 - /// - /// # Safety (不安全函数) - /// 调用者必须确保: - /// 1. 地址指向的内存是 **有效** 的且 **已初始化** 的 `T` 类型数据。 - /// 2. 内存是 **独占** 的 (没有其他活跃的引用或指针指向它)。 - /// 3. 地址已经正确映射,且对齐满足 `T` 的要求。 - pub unsafe fn as_mut(&mut self) -> &mut T { - unsafe { &mut *(self.as_usize() as *mut T) } - } - - /// 将虚拟地址转换为一个常量指针。 - pub fn as_ptr(&self) -> *const T { - self.as_usize() as *const T - } - - /// 将虚拟地址转换为一个可变指针。 - /// - /// # Safety (不安全函数) - /// 调用者必须确保地址在被解引用时是有效的。 - pub unsafe fn as_mut_ptr(&mut self) -> *mut T { - self.as_usize() as *mut T + fn to_pa(&self) -> PA { + unsafe { crate::arch::va_to_pa(*self) } } } @@ -449,62 +343,34 @@ where } /// 物理地址范围的类型别名 -pub type PaddrRange = AddressRange; +pub type PARange = AddressRange; /// 虚拟地址范围的类型别名 -pub type VaddrRange = AddressRange; - -// ============================================================================ -// 与 hal::address 的类型转换 -// ============================================================================ - -impl From for crate::arch::address::PA { - fn from(p: Paddr) -> Self { - p.0 - } -} - -impl From for Paddr { - fn from(a: crate::arch::address::PA) -> Self { - Paddr(a) - } -} - -impl From for crate::arch::address::VA { - fn from(v: Vaddr) -> Self { - v.0 - } -} - -impl From for Vaddr { - fn from(a: crate::arch::address::VA) -> Self { - Vaddr(a) - } -} +pub type VARange = AddressRange; #[cfg(test)] mod address_basic_tests { use super::*; - // 假设 arch 模块提供了 paddr_to_vaddr 的桩实现 - use crate::arch::paddr_to_vaddr; + // 假设 arch 模块提供了 pa_to_va 的桩实现 + use crate::arch::{Platform, PlatformImpl}; use crate::{kassert, test_case}; - // 1.1 Paddr/Vaddr 创建和转换测试 + // 1.1 PA/VA 创建和转换测试 test_case!(test_address_roundtrip, { let test_values = [0x0, 0x1000, 0x8000_0000, 0x8000_1234]; for &val in &test_values { - let paddr = Paddr::from_usize(val); + let paddr = PA::from_usize(val); kassert!(paddr.as_usize() == val); - let vaddr = Vaddr::from_usize(val); + let vaddr = VA::from_usize(val); kassert!(vaddr.as_usize() == val); } }); // 1.2 空地址测试 test_case!(test_null_address, { - let paddr = Paddr::null(); + let paddr = PA::null(); kassert!(paddr.is_null()); kassert!(paddr.as_usize() == 0); }); @@ -513,30 +379,30 @@ mod address_basic_tests { test_case!(test_page_offset, { let cases = [(0x8000_0000, 0), (0x8000_0123, 0x123), (0x8000_0FFF, 0xFFF)]; for &(addr, expected) in &cases { - // Vaddr 和 Paddr 的行为应该相同 - kassert!(Paddr::from_usize(addr).page_offset() == expected); - kassert!(Vaddr::from_usize(addr).page_offset() == expected); + // VA 和 PA 的行为应该相同 + kassert!(PA::from_usize(addr).page_offset() == expected); + kassert!(VA::from_usize(addr).page_offset() == expected); } }); - // 1.4 Paddr ↔ Vaddr 转换测试 (依赖于 arch/mm 桩实现) - test_case!(test_paddr_vaddr_conversion, { + // 1.4 PA ↔ VA 转换测试 (依赖于 arch/mm 桩实现) + test_case!(test_pa_va_conversion, { let paddrs = [0x8000_0000, 0x8000_1000, 0x8020_0000]; for &paddr_val in &paddrs { - let paddr = Paddr::from_usize(paddr_val); - let vaddr = paddr.to_vaddr(); - let back = vaddr.to_paddr(); + let paddr = PA::from_usize(paddr_val); + let vaddr = paddr.to_va(); + let back = vaddr.to_pa(); kassert!(back.as_usize() == paddr_val); - kassert!(vaddr.as_usize() == paddr_to_vaddr(paddr_val)); + kassert!(vaddr.as_usize() == PlatformImpl::pa_to_va(paddr).as_usize()); } }); // 1.5 地址比较测试 test_case!(test_address_comparison, { - let a1 = Paddr::from_usize(0x8000_0000); - let a2 = Paddr::from_usize(0x8000_0000); - let a3 = Paddr::from_usize(0x8000_1000); + let a1 = PA::from_usize(0x8000_0000); + let a2 = PA::from_usize(0x8000_0000); + let a3 = PA::from_usize(0x8000_1000); kassert!(a1 == a2); kassert!(a1 < a3); @@ -545,7 +411,7 @@ mod address_basic_tests { // 1.6 地址算术和步进测试 test_case!(test_address_arithmetic, { - let start = Paddr::from_usize(0x1000); + let start = PA::from_usize(0x1000); // add_by kassert!(start.add_by(0x123).as_usize() == 0x1123); @@ -556,13 +422,13 @@ mod address_basic_tests { // add_n (size_of::() * 3 == 6) kassert!(start.add_n::(3).as_usize() == 0x1006); - // step (Paddr::size_of() == size_of::()) + // step (PA::size_of() == size_of::()) let mut p = start; p.step(); - kassert!(p.as_usize() == start.as_usize() + size_of::()); + kassert!(p.as_usize() == start.as_usize() + size_of::()); // step_back_by - let mut p = Paddr::from_usize(0x2000); + let mut p = PA::from_usize(0x2000); p.step_back_by(0x10); kassert!(p.as_usize() == 0x1FF0); }); diff --git a/os/src/mm/frame_allocator/allocator.rs b/os/src/mm/frame_allocator/allocator.rs index 9bde34d4..d8933479 100644 --- a/os/src/mm/frame_allocator/allocator.rs +++ b/os/src/mm/frame_allocator/allocator.rs @@ -5,7 +5,7 @@ //! 在超出作用域时自动被回收。 use crate::config::PAGE_SIZE; -use crate::mm::address::{ConvertablePaddr, PageNum, Ppn, PpnRange, UsizeConvert}; +use crate::mm::address::{ConvertablePA, PageNum, Ppn, PpnRange, UsizeConvert}; use crate::sync::SpinLock; use alloc::vec::Vec; use lazy_static::lazy_static; @@ -33,7 +33,7 @@ impl FrameTracker { fn clear_frame(ppn: Ppn) { unsafe { // 将 Ppn 转换为虚拟地址指针 - let va = ppn.start_addr().to_vaddr().as_mut_ptr::(); + let va = ppn.start_addr().to_va().as_mut_ptr::(); // 写入 PAGE_SIZE 字节的 0 core::ptr::write_bytes(va, 0, PAGE_SIZE); } diff --git a/os/src/mm/frame_allocator/mod.rs b/os/src/mm/frame_allocator/mod.rs index df7e9910..ff58027e 100644 --- a/os/src/mm/frame_allocator/mod.rs +++ b/os/src/mm/frame_allocator/mod.rs @@ -17,7 +17,7 @@ mod allocator; use alloc::vec::Vec; pub use allocator::{FrameRangeTracker, FrameTracker, TrackedFrames}; -use crate::mm::address::{Paddr, PageNum, Ppn, UsizeConvert}; +use crate::mm::address::{PA, PageNum, Ppn}; use allocator::FRAME_ALLOCATOR; /// 使用可用的物理内存范围初始化全局帧分配器。 @@ -26,11 +26,11 @@ use allocator::FRAME_ALLOCATOR; /// /// * `start_addr` - 可用物理内存的起始地址 /// * `end_addr` - 可用物理内存的结束地址 -pub fn init_frame_allocator(start_addr: usize, end_addr: usize) { +pub fn init_frame_allocator(start_addr: PA, end_addr: PA) { // 将起始地址向上取整到页号 - let start_ppn = Ppn::from_addr_ceil(Paddr::from_usize(start_addr)); + let start_ppn = Ppn::from_addr_ceil(start_addr); // 将结束地址向下取整到页号 - let end_ppn = Ppn::from_addr_floor(Paddr::from_usize(end_addr)); + let end_ppn = Ppn::from_addr_floor(end_addr); let mut allocator = FRAME_ALLOCATOR.lock(); allocator.init(start_ppn, end_ppn); @@ -135,7 +135,11 @@ pub fn get_stats() -> (usize, usize, usize, usize, usize) { #[cfg(test)] mod frame_allocator_tests { use super::*; - use crate::{kassert, mm::address::ConvertablePaddr, test_case}; + use crate::{ + kassert, + mm::address::{ConvertablePA, UsizeConvert}, + test_case, + }; // 1. 单帧分配测试 test_case!(test_single_frame_alloc, { @@ -145,7 +149,7 @@ mod frame_allocator_tests { kassert!(ppn.as_usize() > 0); // 帧已自动清零 - 需要转换为 vaddr 才能访问 - let vaddr = ppn.start_addr().to_vaddr(); + let vaddr = ppn.start_addr().to_va(); let page_ptr = vaddr.as_ptr::(); unsafe { for i in 0..512 { diff --git a/os/src/mm/global_allocator/mod.rs b/os/src/mm/global_allocator/mod.rs index ac9afebc..fe2da263 100644 --- a/os/src/mm/global_allocator/mod.rs +++ b/os/src/mm/global_allocator/mod.rs @@ -6,9 +6,9 @@ //! //! - [`init_heap`]:初始化全局堆分配器。 +mod heap; #[cfg(feature = "alloc")] mod talc_alloc; -mod heap; #[cfg(feature = "alloc")] pub use talc_alloc::init_heap; diff --git a/os/src/mm/global_allocator/talc_alloc.rs b/os/src/mm/global_allocator/talc_alloc.rs index 0c55a869..d5156538 100644 --- a/os/src/mm/global_allocator/talc_alloc.rs +++ b/os/src/mm/global_allocator/talc_alloc.rs @@ -8,18 +8,18 @@ //! - 由链接器符号定义的堆内存区域。 //! - 用于设置堆的初始化函数。 -use crate::{earlyprintln, sync::RawSpinLockWithoutGuard}; +use crate::{earlyprintln, sync::RawSpinLock}; use talc::{Span, Talc, Talck}; /// 全局堆分配器实例 /// -/// 使用 talc 的基于锁的分配器 (**Talck**) 和我们自定义的 **`RawSpinLockWithoutGuard`**。 +/// 使用 talc 的基于锁的分配器 (**Talck**) 和我们自定义的 **`RawSpinLock`**。 /// 此锁实现了 `lock_api::RawMutex` 并提供了中断保护, /// 以防止当中断处理程序尝试分配内存时发生死锁。 /// /// 初始化时使用一个空范围 (**Span::empty()**);实际内存将在 `init_heap()` 中声明。 #[global_allocator] -static ALLOCATOR: Talck = +static ALLOCATOR: Talck = Talc::new(unsafe { talc::ClaimOnOom::new(Span::empty()) }).lock(); /// 使用链接器脚本中定义的堆内存区域初始化堆分配器 diff --git a/os/src/mm/memory_space/mapping_area.rs b/os/src/mm/memory_space/mapping_area.rs index b68d2961..c00e5960 100644 --- a/os/src/mm/memory_space/mapping_area.rs +++ b/os/src/mm/memory_space/mapping_area.rs @@ -3,7 +3,7 @@ use core::cmp::min; use crate::arch::mm::TlbBatchContext; use crate::config::PAGE_SIZE; -use crate::mm::address::{Paddr, PageNum, Ppn, UsizeConvert, Vpn, VpnRange}; +use crate::mm::address::{PA, PageNum, Ppn, UsizeConvert, Vpn, VpnRange}; use crate::mm::frame_allocator::{TrackedFrames, alloc_frame}; use crate::mm::memory_space::MmapFile; use crate::mm::page_table::{ @@ -162,8 +162,8 @@ impl MappingArea { MapType::Direct => { // 对于直接映射,VPN 等于 PPN + 偏移量 let vaddr = vpn.start_addr(); - let paddr = unsafe { crate::arch::vaddr_to_paddr(vaddr.as_usize()) }; - Ppn::from_addr_floor(Paddr::from_usize(paddr)) + let paddr = unsafe { crate::arch::va_to_pa(vaddr) }; + Ppn::from_addr_floor(paddr) } MapType::Framed => { // 分配一个新的帧 @@ -267,8 +267,8 @@ impl MappingArea { // 复制数据到物理页 unsafe { - let dst_va = crate::arch::paddr_to_vaddr(paddr); - let dst = dst_va as *mut u8; + let dst_va = crate::arch::pa_to_va(PA::from_usize(paddr)); + let dst = dst_va.as_usize() as *mut u8; let src = data.as_ptr().add(copied); core::ptr::copy_nonoverlapping(src, dst, to_copy); } @@ -324,12 +324,12 @@ impl MappingArea { // 复制数据到新帧 unsafe { - let src_va = crate::arch::paddr_to_vaddr(src_ppn.start_addr().as_usize()); - let dst_va = crate::arch::paddr_to_vaddr(new_ppn.start_addr().as_usize()); + let src_va = crate::arch::pa_to_va(src_ppn.start_addr()); + let dst_va = crate::arch::pa_to_va(new_ppn.start_addr()); core::ptr::copy_nonoverlapping( - src_va as *const u8, - dst_va as *mut u8, + src_va.as_usize() as *const u8, + dst_va.as_usize() as *mut u8, crate::config::PAGE_SIZE, ); } @@ -359,12 +359,12 @@ impl MappingArea { // 复制数据到新帧 unsafe { - let src_va = crate::arch::paddr_to_vaddr(src_ppn.start_addr().as_usize()); - let dst_va = crate::arch::paddr_to_vaddr(new_ppn.start_addr().as_usize()); + let src_va = crate::arch::pa_to_va(src_ppn.start_addr()); + let dst_va = crate::arch::pa_to_va(new_ppn.start_addr()); core::ptr::copy_nonoverlapping( - src_va as *const u8, - dst_va as *mut u8, + src_va.as_usize() as *const u8, + dst_va.as_usize() as *mut u8, crate::config::PAGE_SIZE, ); } @@ -401,8 +401,8 @@ impl MappingArea { // // // 复制数据到新帧 // unsafe { - // let src_va = crate::arch::paddr_to_vaddr(src_ppn.start_addr().as_usize()); - // let dst_va = crate::arch::paddr_to_vaddr(new_ppn.start_addr().as_usize()); + // let src_va = crate::arch::pa_to_va(src_ppn.start_addr().as_usize()); + // let dst_va = crate::arch::pa_to_va(new_ppn.start_addr().as_usize()); // // core::ptr::copy_nonoverlapping( // src_va as *const u8, @@ -857,9 +857,10 @@ impl MappingArea { }; let paddr = ppn.start_addr(); - let kernel_vaddr = crate::arch::paddr_to_vaddr(paddr.as_usize()); - let buffer = - unsafe { core::slice::from_raw_parts_mut(kernel_vaddr as *mut u8, PAGE_SIZE) }; + let kernel_vaddr = crate::arch::pa_to_va(paddr); + let buffer = unsafe { + core::slice::from_raw_parts_mut(kernel_vaddr.as_usize() as *mut u8, PAGE_SIZE) + }; // 计算实际读取长度(处理文件末尾) let read_len = min( @@ -944,9 +945,9 @@ impl MappingArea { }; let paddr = ppn.start_addr(); - let kernel_vaddr = crate::arch::paddr_to_vaddr(paddr.as_usize()); + let kernel_vaddr = crate::arch::pa_to_va(paddr); let buffer = unsafe { - core::slice::from_raw_parts(kernel_vaddr as *const u8, PAGE_SIZE) + core::slice::from_raw_parts(kernel_vaddr.as_usize() as *const u8, PAGE_SIZE) }; // 计算实际写入长度(处理文件末尾) diff --git a/os/src/mm/memory_space/mod.rs b/os/src/mm/memory_space/mod.rs index abd441ce..74637291 100644 --- a/os/src/mm/memory_space/mod.rs +++ b/os/src/mm/memory_space/mod.rs @@ -3,8 +3,8 @@ //! 本模块定义了内存空间(Memory Space)的相关结构和功能, //! 包括内存空间的创建、管理以及与映射区域(Mapping Area)的交互。 pub mod mapping_area; -mod space; mod mmap_file; +mod space; -pub use space::*; pub use mmap_file::MmapFile; +pub use space::*; diff --git a/os/src/mm/memory_space/space.rs b/os/src/mm/memory_space/space.rs index fba43aa5..48966bc3 100644 --- a/os/src/mm/memory_space/space.rs +++ b/os/src/mm/memory_space/space.rs @@ -2,10 +2,9 @@ use core::cmp::Ordering; use crate::arch::platform::MEMORY_END; use crate::config::{ - MAX_USER_HEAP_SIZE, PAGE_SIZE, USER_SIGRETURN_TRAMPOLINE, USER_STACK_SIZE, - USER_STACK_TOP, + MAX_USER_HEAP_SIZE, PAGE_SIZE, USER_SIGRETURN_TRAMPOLINE, USER_STACK_SIZE, USER_STACK_TOP, }; -use crate::mm::address::{Paddr, PageNum, Ppn, UsizeConvert, Vaddr, Vpn, VpnRange}; +use crate::mm::address::{PA, PageNum, Ppn, UsizeConvert, VA, Vpn, VpnRange}; use crate::mm::memory_space::MmapFile; use crate::mm::memory_space::mapping_area::{AreaType, MapType, MappingArea}; use crate::mm::page_table::{ActivePageTableInner, PageTableInner, PagingError, UniversalPTEFlag}; @@ -109,12 +108,12 @@ impl MemorySpace { /// - 如果堆区域存在,返回堆的结束地址(current brk) /// - 如果堆区域不存在,返回堆的起始地址 /// - 如果堆未初始化,返回 None - pub fn current_brk(&self) -> Option { + pub fn current_brk(&self) -> Option { self.areas .iter() .find(|a| a.area_type() == AreaType::UserHeap) - .map(|a| a.vpn_range().end().start_addr().as_usize()) - .or_else(|| self.heap_start.map(|vpn| vpn.start_addr().as_usize())) + .map(|a| a.vpn_range().end().start_addr()) + .or_else(|| self.heap_start.map(|vpn| vpn.start_addr())) } /// 创建一个新的用户地址空间,并克隆当前地址空间的内核映射。 @@ -163,8 +162,8 @@ impl MemorySpace { .checked_add(PAGE_SIZE) .ok_or(PagingError::InvalidAddress)?; let vpn_range = VpnRange::new( - Vpn::from_addr_floor(Vaddr::from_usize(start)), - Vpn::from_addr_ceil(Vaddr::from_usize(end)), + Vpn::from_addr_floor(VA::from_usize(start)), + Vpn::from_addr_ceil(VA::from_usize(end)), ); // If already mapped (layout differences), don't fail hard. @@ -199,14 +198,15 @@ impl MemorySpace { let cur_va = va.checked_add(written).ok_or(PagingError::InvalidAddress)?; let paddr = self .page_table - .translate(Vaddr::from_usize(cur_va)) + .translate(VA::from_usize(cur_va)) .ok_or(PagingError::InvalidAddress)?; let paddr_usize = paddr.as_usize(); let page_base = paddr_usize & !(PAGE_SIZE - 1); let page_off = paddr_usize & (PAGE_SIZE - 1); let take = core::cmp::min(bytes.len() - written, PAGE_SIZE - page_off); - let dst = (crate::arch::paddr_to_vaddr(page_base) + page_off) as *mut u8; + let dst = + (crate::arch::pa_to_va(PA::from_usize(page_base)).as_usize() + page_off) as *mut u8; unsafe { core::ptr::copy_nonoverlapping(bytes[written..].as_ptr(), dst, take); } @@ -227,14 +227,15 @@ impl MemorySpace { let cur_va = va.checked_add(read).ok_or(PagingError::InvalidAddress)?; let paddr = self .page_table - .translate(Vaddr::from_usize(cur_va)) + .translate(VA::from_usize(cur_va)) .ok_or(PagingError::InvalidAddress)?; let paddr_usize = paddr.as_usize(); let page_base = paddr_usize & !(PAGE_SIZE - 1); let page_off = paddr_usize & (PAGE_SIZE - 1); let take = core::cmp::min(out.len() - read, PAGE_SIZE - page_off); - let src = (crate::arch::paddr_to_vaddr(page_base) + page_off) as *const u8; + let src = (crate::arch::pa_to_va(PA::from_usize(page_base)).as_usize() + page_off) + as *const u8; unsafe { core::ptr::copy_nonoverlapping(src, out[read..].as_mut_ptr(), take); } @@ -354,12 +355,12 @@ impl MemorySpace { )?; // 5. 映射物理内存(从 ekernel 到 MEMORY_END 的直接映射) - let ekernel_paddr = unsafe { crate::arch::vaddr_to_paddr(ekernel as usize) }; - let phys_mem_start_vaddr = crate::arch::paddr_to_vaddr(ekernel_paddr); - let phys_mem_end_vaddr = crate::arch::paddr_to_vaddr(MEMORY_END); + let ekernel_paddr = unsafe { crate::arch::va_to_pa(VA::from_usize(ekernel as usize)) }; + let phys_mem_start_vaddr = crate::arch::pa_to_va(ekernel_paddr); + let phys_mem_end_vaddr = crate::arch::pa_to_va(PA::from_usize(MEMORY_END)); - let phys_mem_start = Vpn::from_addr_ceil(Vaddr::from_usize(phys_mem_start_vaddr)); - let phys_mem_end = Vpn::from_addr_floor(Vaddr::from_usize(phys_mem_end_vaddr)); + let phys_mem_start = Vpn::from_addr_ceil(phys_mem_start_vaddr); + let phys_mem_end = Vpn::from_addr_floor(phys_mem_end_vaddr); let mut phys_mem_area = MappingArea::new( VpnRange::new(phys_mem_start, phys_mem_end), AreaType::KernelHeap, @@ -374,7 +375,7 @@ impl MemorySpace { // 暂时移除自动 MMIO 映射 // // 6. 映射 MMIO 区域 // for &(_device, mmio_base, mmio_size) in crate::config::MMIO { - // let mmio_vaddr = crate::arch::paddr_to_vaddr(mmio_base); + // let mmio_vaddr = crate::arch::pa_to_va(mmio_base); // self.map_mmio_region(mmio_vaddr, mmio_size)?; // } @@ -522,8 +523,8 @@ impl MemorySpace { area_type: AreaType, flags: UniversalPTEFlag, ) -> Result<(), PagingError> { - let vpn_start = Vpn::from_addr_floor(Vaddr::from_usize(start)); - let vpn_end = Vpn::from_addr_ceil(Vaddr::from_usize(end)); + let vpn_start = Vpn::from_addr_floor(VA::from_usize(start)); + let vpn_end = Vpn::from_addr_ceil(VA::from_usize(end)); let mut area = MappingArea::new( VpnRange::new(vpn_start, vpn_end), @@ -541,15 +542,15 @@ impl MemorySpace { /// 映射一个 MMIO 区域 /// /// # 参数 - /// - `addr`: MMIO 设备的虚拟地址(已通过 paddr_to_vaddr 转换) + /// - `addr`: MMIO 设备的虚拟地址(已通过 pa_to_va 转换) /// - `size`: MMIO 区域的大小(字节) /// /// # 返回 /// - `Ok(())`: 映射成功 /// - `Err(PagingError)`: 映射失败 - pub fn map_mmio_region(&mut self, addr: usize, size: usize) -> Result<(), PagingError> { - let vpn_start = Vpn::from_addr_floor(Vaddr::from_usize(addr)); - let vpn_end = Vpn::from_addr_ceil(Vaddr::from_usize(addr + size)); + pub fn map_mmio_region(&mut self, addr: VA, size: usize) -> Result<(), PagingError> { + let vpn_start = Vpn::from_addr_floor(addr); + let vpn_end = Vpn::from_addr_ceil(VA::from_usize(addr.as_usize() + size)); let mut area = MappingArea::new( VpnRange::new(vpn_start, vpn_end), @@ -594,24 +595,17 @@ impl MemorySpace { // 检查架构 let machine = elf.header.pt2.machine().as_machine(); - #[cfg(target_arch = "riscv64")] - if machine != xmas_elf::header::Machine::RISC_V { - crate::pr_err!( - "[from_elf] machine mismatch: expected RISC-V, got {:?}", - machine - ); - return Err(PagingError::InvalidAddress); - } - #[cfg(target_arch = "loongarch64")] + let machine_number = match machine { + xmas_elf::header::Machine::RISC_V => Some(crate::arch::abi::EM_RISCV), + xmas_elf::header::Machine::Other(value) => Some(value), + _ => None, + }; + if !machine_number + .map(crate::arch::abi::is_supported_elf_machine) + .unwrap_or(false) { - const EM_LOONGARCH: u16 = 258; - if machine != xmas_elf::header::Machine::Other(EM_LOONGARCH) { - crate::pr_err!( - "[from_elf] machine mismatch: expected LoongArch (EM=258), got {:?}", - machine - ); - return Err(PagingError::InvalidAddress); - } + crate::pr_err!("[from_elf] machine mismatch: got {:?}", machine); + return Err(PagingError::InvalidAddress); } // 对 ET_DYN (PIE/static-pie) 采用固定 load bias,避免把可执行映射放到 VA=0。 @@ -674,8 +668,8 @@ impl MemorySpace { } let vpn_range = VpnRange::new( - Vpn::from_addr_floor(Vaddr::from_usize(start_va)), - Vpn::from_addr_ceil(Vaddr::from_usize(end_va)), + Vpn::from_addr_floor(VA::from_usize(start_va)), + Vpn::from_addr_ceil(VA::from_usize(end_va)), ); max_end_vpn = if max_end_vpn.as_usize() > vpn_range.end().as_usize() { @@ -731,14 +725,11 @@ impl MemorySpace { } } - // 1.5 对静态 PIE/PIE 应用最小化重定位:R_RISCV_RELATIVE + // 1.5 对静态 PIE/PIE 应用最小化重定位:RELATIVE/64 // - // 典型的 riscv64 static-pie(如 data/bin/iperf3)会把 GOT/函数指针以 0 填充, + // 典型的 static-pie(如 data/bin/iperf3)会把 GOT/函数指针以 0 填充, // 依赖 .rela.dyn 的 RELATIVE relocations 在加载时写入正确地址。 // 如果不做这一步,程序往往会在某个间接调用点跳到 sepc=0 执行到 ELF header。 - const R_RISCV_64: u32 = 2; - const R_RISCV_RELATIVE: u32 = 3; - enum Symtab64<'a> { Dyn(&'a [xmas_elf::symbol_table::DynEntry64]), Std(&'a [xmas_elf::symbol_table::Entry64]), @@ -747,12 +738,12 @@ impl MemorySpace { let write_usize_at = |va: usize, value: usize| -> Result<(), PagingError> { let paddr = space .page_table - .translate(Vaddr::from_usize(va)) + .translate(VA::from_usize(va)) .ok_or(PagingError::InvalidAddress)?; let paddr_usize = paddr.as_usize(); let page_base = paddr_usize & !(PAGE_SIZE - 1); let off = paddr_usize & (PAGE_SIZE - 1); - let kva = crate::arch::paddr_to_vaddr(page_base) + off; + let kva = crate::arch::pa_to_va(PA::from_usize(page_base)).as_usize() + off; unsafe { core::ptr::write_unaligned(kva as *mut usize, value); } @@ -792,14 +783,23 @@ impl MemorySpace { let target_va = load_bias + r_offset; - let value = match r_type { - R_RISCV_RELATIVE => (load_bias as isize + addend) as usize, - R_RISCV_64 => { - let sym_val = if r_sym == 0 { - 0usize + let kind = match crate::arch::abi::classify_relocation(r_type) { + Some(kind) => kind, + None => { + pr_err!("[ELF] Unsupported relocation type: {}", r_type); + return Err(PagingError::InvalidAddress); + } + }; + let sym_val = match kind { + crate::arch::abi::RelocationKind::Relative => 0, + crate::arch::abi::RelocationKind::Absolute64 => { + if r_sym == 0 { + 0 } else { let Some(symtab) = symtab.as_ref() else { - pr_err!("[ELF] R_RISCV_64 requires symtab, but sh_link is missing"); + pr_err!( + "[ELF] absolute relocation requires symtab, but sh_link is missing" + ); return Err(PagingError::InvalidAddress); }; match symtab { @@ -812,15 +812,11 @@ impl MemorySpace { as usize } } - }; - let s = load_bias + sym_val; - (s as isize + addend) as usize - } - _ => { - pr_err!("[ELF] Unsupported relocation type: {}", r_type); - return Err(PagingError::InvalidAddress); + } } }; + let value = + crate::arch::abi::resolve_relocation_value(kind, load_bias, sym_val, addend); write_usize_at(target_va, value)?; } @@ -831,8 +827,8 @@ impl MemorySpace { // 3. 映射用户栈(带保护页) let user_stack_bottom = - Vpn::from_addr_floor(Vaddr::from_usize(USER_STACK_TOP - USER_STACK_SIZE)); - let user_stack_top = Vpn::from_addr_ceil(Vaddr::from_usize(USER_STACK_TOP)); + Vpn::from_addr_floor(VA::from_usize(USER_STACK_TOP - USER_STACK_SIZE)); + let user_stack_top = Vpn::from_addr_ceil(VA::from_usize(USER_STACK_TOP)); space.insert_framed_area( VpnRange::new(user_stack_bottom, user_stack_top), @@ -884,22 +880,23 @@ impl MemorySpace { /// - 堆未初始化 /// - 新的 brk 会超出 MAX_USER_HEAP_SIZE /// - 新的 brk 会与现有区域重叠 - pub fn brk(&mut self, new_brk: usize) -> Result { + pub fn brk(&mut self, new_brk: VA) -> Result { let heap_bottom = self.heap_start.ok_or(PagingError::InvalidAddress)?; - let new_end_vpn = Vpn::from_addr_ceil(Vaddr::from_usize(new_brk)); + let new_brk_usize = new_brk.as_usize(); + let new_end_vpn = Vpn::from_addr_ceil(new_brk); // 边界检查 - if new_brk < heap_bottom.start_addr().as_usize() { + if new_brk_usize < heap_bottom.start_addr().as_usize() { return Err(PagingError::InvalidAddress); } - let heap_size = new_brk - heap_bottom.start_addr().as_usize(); + let heap_size = new_brk_usize - heap_bottom.start_addr().as_usize(); if heap_size > MAX_USER_HEAP_SIZE { return Err(PagingError::InvalidAddress); } // 检查是否与栈重叠 - if new_brk >= USER_STACK_TOP - USER_STACK_SIZE { + if new_brk_usize >= USER_STACK_TOP - USER_STACK_SIZE { return Err(PagingError::InvalidAddress); } @@ -977,7 +974,7 @@ impl MemorySpace { /// # 返回值 /// - `Some(addr)`: 找到的空闲区域起始地址(已对齐) /// - `None`: 没有足够大的空闲区域 - pub fn find_free_region(&self, size: usize, align: usize) -> Option { + pub fn find_free_region(&self, size: usize, align: usize) -> Option { // 获取堆的起始和结束 let heap_start = self.heap_start?.start_addr().as_usize(); @@ -1047,7 +1044,7 @@ impl MemorySpace { if gap_end > lowest_ok && gap_end - lowest_ok >= size { let candidate = align_down(gap_end - size, align); if candidate >= lowest_ok { - return Some(candidate); + return Some(VA::from_usize(candidate)); } } } @@ -1065,7 +1062,7 @@ impl MemorySpace { if gap_end >= heap_end + size { let candidate = align_down(gap_end - size, align); if candidate >= heap_end { - return Some(candidate); + return Some(VA::from_usize(candidate)); } } @@ -1093,6 +1090,7 @@ impl MemorySpace { // 内核选择地址:查找空闲区域 self.find_free_region(len, crate::config::PAGE_SIZE) .ok_or(PagingError::OutOfMemory)? + .as_usize() } else { // 用户指定地址 @@ -1106,8 +1104,8 @@ impl MemorySpace { // 检查对齐后的区域是否可用 let vpn_range_check = VpnRange::new( - Vpn::from_addr_floor(Vaddr::from_usize(aligned_hint)), - Vpn::from_addr_ceil(Vaddr::from_usize(aligned_hint + len)), + Vpn::from_addr_floor(VA::from_usize(aligned_hint)), + Vpn::from_addr_ceil(VA::from_usize(aligned_hint + len)), ); // 检查是否与现有区域重叠 @@ -1122,6 +1120,7 @@ impl MemorySpace { // 更好的实现应该优先查找 hint 附近的区域 self.find_free_region(len, crate::config::PAGE_SIZE) .ok_or(PagingError::AlreadyMapped)? + .as_usize() } else { aligned_hint } @@ -1129,8 +1128,8 @@ impl MemorySpace { // 计算 VPN 范围(start 已经是页对齐的) let vpn_range = VpnRange::new( - Vpn::from_addr_floor(Vaddr::from_usize(start)), - Vpn::from_addr_ceil(Vaddr::from_usize(start + len)), + Vpn::from_addr_floor(VA::from_usize(start)), + Vpn::from_addr_ceil(VA::from_usize(start + len)), ); // 最终重叠检查(防御性编程) @@ -1162,15 +1161,15 @@ impl MemorySpace { /// - 如果范围跨越多个区域,会部分解除映射每个区域 /// - 如果只覆盖区域的一部分,会拆分区域 /// - 如果地址未映射,返回成功(幂等) - pub fn munmap(&mut self, start: usize, len: usize) -> Result<(), PagingError> { + pub fn munmap(&mut self, start: VA, len: usize) -> Result<(), PagingError> { // 参数验证 if len == 0 { return Ok(()); // POSIX: len=0 是合法的,什么都不做 } // 计算需要解除映射的 VPN 范围 - let start_vpn = Vpn::from_addr_floor(Vaddr::from_usize(start)); - let end_vpn = Vpn::from_addr_ceil(Vaddr::from_usize(start + len)); + let start_vpn = Vpn::from_addr_floor(start); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(start.as_usize() + len)); let unmap_range = VpnRange::new(start_vpn, end_vpn); // 收集需要处理的区域 @@ -1248,7 +1247,7 @@ impl MemorySpace { /// - 只能修改 Framed 类型的映射区域 pub fn mprotect( &mut self, - start: usize, + start: VA, len: usize, prot: UniversalPTEFlag, ) -> Result<(), PagingError> { @@ -1258,13 +1257,13 @@ impl MemorySpace { } // 检查地址对齐 - if !start.is_multiple_of(PAGE_SIZE) { + if !start.as_usize().is_multiple_of(PAGE_SIZE) { return Err(PagingError::InvalidAddress); } // 计算需要修改权限的 VPN 范围 - let start_vpn = Vpn::from_addr_floor(Vaddr::from_usize(start)); - let end_vpn = Vpn::from_addr_ceil(Vaddr::from_usize(start + len)); + let start_vpn = Vpn::from_addr_floor(start); + let end_vpn = Vpn::from_addr_ceil(VA::from_usize(start.as_usize() + len)); let change_range = VpnRange::new(start_vpn, end_vpn); // 收集需要处理的区域 @@ -1353,14 +1352,14 @@ impl MemorySpace { } /// 进程手动映射MMIO区域 - pub fn map_mmio(&mut self, paddr: Paddr, size: usize) -> Result { + pub fn map_mmio(&mut self, paddr: PA, size: usize) -> Result { // 将物理地址转换为虚拟地址 - let vaddr_usize = crate::arch::paddr_to_vaddr(paddr.as_usize()); - let vaddr = Vaddr::from_usize(vaddr_usize); + let vaddr = crate::arch::pa_to_va(paddr); + let vaddr_usize = vaddr.as_usize(); // 计算VPN范围 let vpn_start = Vpn::from_addr_floor(vaddr); - let vpn_end = Vpn::from_addr_ceil(Vaddr::from_usize(vaddr_usize + size)); + let vpn_end = Vpn::from_addr_ceil(VA::from_usize(vaddr_usize + size)); // 检查是否已经映射 let mut some_unmapped = false; @@ -1390,15 +1389,15 @@ impl MemorySpace { } // 如果没有映射,调用map_mmio_region进行映射 - self.map_mmio_region(vaddr_usize, size)?; + self.map_mmio_region(VA::from_usize(vaddr_usize), size)?; Ok(vaddr) } /// 进程手动取消映射MMIO区域 - pub fn unmap_mmio(&mut self, vaddr: Vaddr, size: usize) -> Result<(), PagingError> { + pub fn unmap_mmio(&mut self, vaddr: VA, size: usize) -> Result<(), PagingError> { // 计算VPN范围 let vpn_start = Vpn::from_addr_floor(vaddr); - let vpn_end = Vpn::from_addr_ceil(Vaddr::from_usize(vaddr.as_usize() + size)); + let vpn_end = Vpn::from_addr_ceil(VA::from_usize(vaddr.as_usize() + size)); // 使用 BTreeSet 以提高去重效率 let mut areas_to_remove = alloc::collections::BTreeSet::new(); @@ -1438,7 +1437,7 @@ impl MemorySpace { Ok(()) } - pub fn translate(&self, vaddr: Vaddr) -> Option { + pub fn translate(&self, vaddr: VA) -> Option { self.page_table.translate(vaddr) } } @@ -1465,7 +1464,7 @@ impl Drop for MemorySpace { #[cfg(test)] mod memory_space_tests { use super::*; - use crate::mm::address::{Vpn, VpnRange}; + use crate::mm::address::{PA, Vpn, VpnRange}; use crate::mm::page_table::UniversalPTEFlag; use crate::{kassert, println, test_case}; @@ -1476,10 +1475,12 @@ mod memory_space_tests { // 应该已初始化页表 }); - // 2. 直接映射 + // 2. 直接映射:VA 必须 >= PAGE_OFFSET,从已知 PA 经 pa_to_va 计算 Vpn test_case!(test_direct_mapping, { let mut ms = MemorySpace::new(); - let vpn_range = VpnRange::new(Vpn::from_usize(0x80000), Vpn::from_usize(0x80010)); + let va_base = crate::arch::pa_to_va(PA::from_usize(0x8000_0000)); + let vpn_start = Vpn::from_addr_ceil(va_base); + let vpn_range = VpnRange::new(vpn_start, Vpn::from_usize(vpn_start.as_usize() + 0x10)); let area = MappingArea::new( vpn_range, @@ -1549,7 +1550,7 @@ mod memory_space_tests { ); // 手动映射 MMIO 区域 - let paddr = Paddr::from_usize(TEST_MMIO_PADDR); + let paddr = PA::from_usize(TEST_MMIO_PADDR); let result = ms.map_mmio(paddr, TEST_MMIO_SIZE); kassert!(result.is_ok()); @@ -1569,7 +1570,7 @@ mod memory_space_tests { } // 测试页表翻译 - let translated_paddr = ms.page_table().translate(Vaddr::from_usize(mmio_vaddr)); + let translated_paddr = ms.page_table().translate(VA::from_usize(mmio_vaddr)); kassert!(translated_paddr.is_some()); if let Some(paddr) = translated_paddr { @@ -1605,7 +1606,7 @@ mod memory_space_tests { // // XXX: 疑似因为不再使用KERNEL_SPACE作为全局内核页表导致这里失效 // with_kernel_space(|space| { // // 手动映射 TEST 设备 - // let paddr = Paddr::from_usize(TEST_DEVICE_PADDR); + // let paddr = PA::from_usize(TEST_DEVICE_PADDR); // let result = space.map_mmio(paddr, TEST_DEVICE_SIZE); // kassert!(result.is_ok()); @@ -1641,11 +1642,12 @@ mod memory_space_tests { const CUSTOM_MMIO_PADDR: usize = 0x5000_0000; const CUSTOM_MMIO_SIZE: usize = 0x1000; - let custom_vaddr = crate::arch::paddr_to_vaddr(CUSTOM_MMIO_PADDR); + let custom_vaddr = crate::arch::pa_to_va(PA::from_usize(CUSTOM_MMIO_PADDR)); println!( "Adding custom MMIO mapping at PA=0x{:x}, VA=0x{:x}", - CUSTOM_MMIO_PADDR, custom_vaddr + CUSTOM_MMIO_PADDR, + custom_vaddr.as_usize() ); // 动态添加 MMIO 映射 @@ -1653,7 +1655,7 @@ mod memory_space_tests { kassert!(result.is_ok()); // 验证映射存在 - let vpn = Vpn::from_addr_floor(Vaddr::from_usize(custom_vaddr)); + let vpn = Vpn::from_addr_floor(custom_vaddr); let area = ms.find_area(vpn); kassert!(area.is_some()); @@ -1671,7 +1673,7 @@ mod memory_space_tests { const TEST_PADDR: usize = 0x6000_0000; const TEST_SIZE: usize = 0x2000; - let paddr = Paddr::from_usize(TEST_PADDR); + let paddr = PA::from_usize(TEST_PADDR); println!("Testing map_mmio with new mapping at PA=0x{:x}", TEST_PADDR); @@ -1702,7 +1704,7 @@ mod memory_space_tests { const TEST_PADDR: usize = 0x7000_0000; const TEST_SIZE: usize = 0x1000; - let paddr = Paddr::from_usize(TEST_PADDR); + let paddr = PA::from_usize(TEST_PADDR); println!( "Testing map_mmio with existing mapping at PA=0x{:x}", @@ -1737,10 +1739,10 @@ mod memory_space_tests { const TEST_PADDR: usize = 0x8000_0000; const TEST_SIZE: usize = 0x1000; - // 先通过 paddr_to_vaddr 获取虚拟地址 - let test_vaddr = crate::arch::paddr_to_vaddr(TEST_PADDR); - let vpn_start = Vpn::from_addr_floor(Vaddr::from_usize(test_vaddr)); - let vpn_end = Vpn::from_addr_ceil(Vaddr::from_usize(test_vaddr + TEST_SIZE)); + // 先通过 pa_to_va 获取虚拟地址 + let test_vaddr = crate::arch::pa_to_va(PA::from_usize(TEST_PADDR)).as_usize(); + let vpn_start = Vpn::from_addr_floor(VA::from_usize(test_vaddr)); + let vpn_end = Vpn::from_addr_ceil(VA::from_usize(test_vaddr + TEST_SIZE)); println!( "Testing map_mmio conflict detection at VA=0x{:x}", @@ -1759,7 +1761,7 @@ mod memory_space_tests { ms.insert_area(area).expect("Failed to insert test area"); // 现在尝试用 map_mmio 映射同一物理地址 - let paddr = Paddr::from_usize(TEST_PADDR); + let paddr = PA::from_usize(TEST_PADDR); let result = ms.map_mmio(paddr, TEST_SIZE); // 应该返回 AlreadyMapped 错误,因为该区域已经被映射为非MMIO类型 @@ -1785,7 +1787,7 @@ mod memory_space_tests { const TEST_PADDR: usize = 0x9000_0000; const TEST_SIZE: usize = 0x1000; - let paddr = Paddr::from_usize(TEST_PADDR); + let paddr = PA::from_usize(TEST_PADDR); println!( "Testing unmap_mmio with normal unmapping at PA=0x{:x}", @@ -1817,7 +1819,7 @@ mod memory_space_tests { let mut ms = MemorySpace::new(); // 尝试取消映射一个未映射的区域 - let vaddr = Vaddr::from_usize(0xffff_ffc0_a000_0000); + let vaddr = VA::from_usize(0xffff_ffc0_a000_0000); const TEST_SIZE: usize = 0x1000; println!("Testing unmap_mmio with non-existent mapping"); @@ -1833,8 +1835,10 @@ mod memory_space_tests { test_case!(test_unmap_mmio_wrong_type, { let mut ms = MemorySpace::new(); - // 映射一个非MMIO区域 - let vpn_range = VpnRange::new(Vpn::from_usize(0xb000), Vpn::from_usize(0xb010)); + // 映射一个非MMIO区域:Direct 映射的 VA 必须 >= PAGE_OFFSET + let va_base = crate::arch::pa_to_va(PA::from_usize(0xb000_0000)); + let vpn_start = Vpn::from_addr_ceil(va_base); + let vpn_range = VpnRange::new(vpn_start, Vpn::from_usize(vpn_start.as_usize() + 0x10)); let area = MappingArea::new( vpn_range, AreaType::KernelData, @@ -1847,7 +1851,7 @@ mod memory_space_tests { println!("Testing unmap_mmio with wrong area type"); // 尝试用 unmap_mmio 取消映射非MMIO区域 - let vaddr = Vpn::from_usize(0xb000).start_addr(); + let vaddr = vpn_start.start_addr(); let result = ms.unmap_mmio(vaddr, 0x1000); // 应该返回错误 @@ -1869,8 +1873,8 @@ mod memory_space_tests { const REGION2_PADDR: usize = 0xd000_0000; const REGION_SIZE: usize = 0x1000; - let paddr1 = Paddr::from_usize(REGION1_PADDR); - let paddr2 = Paddr::from_usize(REGION2_PADDR); + let paddr1 = PA::from_usize(REGION1_PADDR); + let paddr2 = PA::from_usize(REGION2_PADDR); let vaddr1 = ms .map_mmio(paddr1, REGION_SIZE) @@ -2038,7 +2042,7 @@ mod memory_space_tests { println!(" Created area with R/W permissions"); // 修改为只读 - let start = vpn_range.start().start_addr().as_usize(); + let start = vpn_range.start().start_addr(); let len = (vpn_range.end().as_usize() - vpn_range.start().as_usize()) * PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); @@ -2060,17 +2064,25 @@ mod memory_space_tests { let mut ms = MemorySpace::new(); // 测试未对齐的地址 - let result = ms.mprotect(0x1001, PAGE_SIZE, UniversalPTEFlag::user_read()); + let result = ms.mprotect( + VA::from_usize(0x1001), + PAGE_SIZE, + UniversalPTEFlag::user_read(), + ); kassert!(result.is_err()); println!(" Correctly rejected unaligned address"); // 测试未映射的区域 - let result = ms.mprotect(0x5000 * PAGE_SIZE, PAGE_SIZE, UniversalPTEFlag::user_read()); + let result = ms.mprotect( + VA::from_usize(0x5000 * PAGE_SIZE), + PAGE_SIZE, + UniversalPTEFlag::user_read(), + ); kassert!(result.is_err()); println!(" Correctly rejected unmapped region"); // 测试 len=0 - let result = ms.mprotect(0x1000, 0, UniversalPTEFlag::user_read()); + let result = ms.mprotect(VA::from_usize(0x1000), 0, UniversalPTEFlag::user_read()); kassert!(result.is_ok()); println!(" Correctly handled len=0"); @@ -2108,7 +2120,7 @@ mod memory_space_tests { println!(" Created 2 consecutive areas"); // 修改跨越两个区域的权限 - let start = vpn_range1.start().start_addr().as_usize(); + let start = vpn_range1.start().start_addr(); let len = (vpn_range2.end().as_usize() - vpn_range1.start().as_usize()) * PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); @@ -2138,7 +2150,7 @@ mod memory_space_tests { println!(" Created 4-page area with RW permissions"); // 只修改前2页的权限为只读 - let start = vpn_range.start().start_addr().as_usize(); + let start = vpn_range.start().start_addr(); let len = 2 * PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); kassert!(result.is_ok()); @@ -2188,7 +2200,7 @@ mod memory_space_tests { println!(" Created 4-page area with RW permissions"); // 只修改后2页的权限为只读 - let start = Vpn::from_usize(0x8002).start_addr().as_usize(); + let start = Vpn::from_usize(0x8002).start_addr(); let len = 2 * PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); kassert!(result.is_ok()); @@ -2238,7 +2250,7 @@ mod memory_space_tests { println!(" Created 6-page area with RW permissions"); // 只修改中间2页(第2-3页,索引从0开始)的权限为只读 - let start = Vpn::from_usize(0x9002).start_addr().as_usize(); + let start = Vpn::from_usize(0x9002).start_addr(); let len = 2 * PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); kassert!(result.is_ok()); @@ -2296,7 +2308,7 @@ mod memory_space_tests { println!(" Created 4-page area with RW permissions"); // 修改前2页的权限为只读 - let start = vpn_range.start().start_addr().as_usize(); + let start = vpn_range.start().start_addr(); let len = 2 * PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); kassert!(result.is_ok()); @@ -2351,7 +2363,7 @@ mod memory_space_tests { println!(" Created 3-page area with RW permissions"); // 只修改中间1页的权限为只读 - let start = Vpn::from_usize(0xb001).start_addr().as_usize(); + let start = Vpn::from_usize(0xb001).start_addr(); let len = PAGE_SIZE; let result = ms.mprotect(start, len, UniversalPTEFlag::user_read()); kassert!(result.is_ok()); diff --git a/os/src/mm/mod.rs b/os/src/mm/mod.rs index 39d0cbc2..d5b41227 100644 --- a/os/src/mm/mod.rs +++ b/os/src/mm/mod.rs @@ -24,6 +24,7 @@ pub use global_allocator::init_heap; use crate::arch::platform::MEMORY_END; use crate::config::PAGE_SIZE; use crate::earlyprintln; +use crate::mm::address::PA; use crate::mm::address::{Ppn, UsizeConvert}; use crate::sync::SpinLock; use alloc::sync::Arc; @@ -46,13 +47,14 @@ pub fn init() -> alloc::sync::Arc where @@ -30,7 +30,7 @@ where fn get_entry(&self, vpn: Vpn, level: usize) -> Option<(T, PageSize)>; - fn translate(&self, vaddr: Vaddr) -> Option; + fn translate(&self, vaddr: VA) -> Option; fn map( &mut self, diff --git a/os/src/net/socket.rs b/os/src/net/socket.rs index 945bffee..9a1f9054 100644 --- a/os/src/net/socket.rs +++ b/os/src/net/socket.rs @@ -345,8 +345,14 @@ pub fn parse_sockaddr_in(addr: *const u8, addrlen: u32) -> Result>) -> bool { - let timestamp = - smoltcp::time::Instant::from_millis(crate::arch::get_time_ms() as i64); + let timestamp = smoltcp::time::Instant::from_millis(crate::arch::get_time_ms() as i64); let mut dev = self.device.lock(); let queue_len = dev.loopback_queue_len(); diff --git a/os/src/sync/intr_guard.rs b/os/src/sync/intr_guard.rs index 8314471e..03e119e0 100644 --- a/os/src/sync/intr_guard.rs +++ b/os/src/sync/intr_guard.rs @@ -3,7 +3,8 @@ //! 基于 RAII 实现中断保护。在创建时通过 `CpuOps` 禁用中断并保存之前的状态; //! 在销毁时自动恢复之前的中断状态。 //! -//! 不可重入 (即不能嵌套调用 IntrGuard::new())。 +//! 支持嵌套:内部使用 per-CPU 引用计数,只有最外层守卫在 drop +//! 时才真正恢复中断状态。 //! //! # 泛型参数 //! @@ -11,39 +12,85 @@ use crate::arch::ArchImpl; use crate::arch::CpuOps; +use crate::config::MAX_CPU_COUNT; use core::marker::PhantomData; use core::ops::Drop; +use core::sync::atomic::{AtomicUsize, Ordering}; + +/// 缓存行对齐的原子计数器 +#[repr(align(64))] +struct CacheAlignedAtomic(AtomicUsize); + +impl CacheAlignedAtomic { + const fn new() -> Self { + CacheAlignedAtomic(AtomicUsize::new(0)) + } +} + +/// 每个 CPU 的中断保护嵌套深度 +static INTR_DEPTH: [CacheAlignedAtomic; MAX_CPU_COUNT] = + [const { CacheAlignedAtomic::new() }; MAX_CPU_COUNT]; + +/// 每个 CPU 保存的中断标志(仅最外层有效) +static SAVED_INTR_FLAGS: [CacheAlignedAtomic; MAX_CPU_COUNT] = + [const { CacheAlignedAtomic::new() }; MAX_CPU_COUNT]; /// 中断保护器,基于 RAII 实现中断保护。 /// /// 在创建时原子地禁用中断并保存之前的状态; /// 在销毁时自动恢复之前的中断状态。 +/// +/// 支持嵌套:内部使用 per-CPU 引用计数。 pub struct IntrGuard { - flags: usize, _marker: PhantomData, + /// 此 guard 创建时是否已处于临界区内(即是否嵌套) + was_nested: bool, } impl IntrGuard { - /// 原子地禁用中断并返回一个 IntrGuard 实例。 + /// 禁用中断并返回一个 IntrGuard 实例。 /// - /// 该实例在离开作用域时会自动恢复中断状态。 + /// 只有最外层的守卫会真正禁用中断。嵌套的守卫仅递增引用计数。 + /// 当最外层守卫被 drop 时,中断状态会被恢复。 pub fn new() -> Self { - let flags = CPU::disable_interrupts(); + let cpu_id = CPU::id(); + let depth = INTR_DEPTH[cpu_id].0.load(Ordering::Relaxed); + let was_nested = depth > 0; + if !was_nested { + let flags = CPU::disable_interrupts(); + SAVED_INTR_FLAGS[cpu_id].0.store(flags, Ordering::Relaxed); + } + INTR_DEPTH[cpu_id].0.fetch_add(1, Ordering::Relaxed); + core::sync::atomic::fence(Ordering::Acquire); IntrGuard { - flags, _marker: PhantomData, + was_nested, } } - /// 检查进入临界区前,中断是否处于启用状态。 + /// 检查进入此临界区前,中断是否处于启用状态。 + /// + /// 嵌套 guard 创建时中断已被外层禁用,因此返回 false。 + /// 必须在创建该守卫的同一 CPU 上调用。 pub fn was_enabled(&self) -> bool { - CPU::interrupt_was_enabled(self.flags) + if self.was_nested { + return false; + } + let cpu_id = CPU::id(); + let flags = SAVED_INTR_FLAGS[cpu_id].0.load(Ordering::Relaxed); + CPU::interrupt_was_enabled(flags) } } impl Drop for IntrGuard { fn drop(&mut self) { - CPU::restore_interrupt_state(self.flags); + let cpu_id = CPU::id(); + core::sync::atomic::fence(Ordering::Release); + let prev = INTR_DEPTH[cpu_id].0.fetch_sub(1, Ordering::Relaxed); + if prev == 1 { + let flags = SAVED_INTR_FLAGS[cpu_id].0.load(Ordering::Relaxed); + CPU::restore_interrupt_state(flags); + } } } @@ -52,7 +99,6 @@ mod tests { use super::*; use crate::{arch::intr::*, kassert, println, test_case}; - // 测试 IntrGuard::new() 是否成功禁用中断,并检查 was_enabled test_case!(test_guard_disables_interrupts, { println!("Testing: test_guard_disables_interrupts"); unsafe { enable_interrupts() }; @@ -61,11 +107,12 @@ mod tests { let guard = IntrGuard::::new(); kassert!(guard.was_enabled()); - kassert!(!are_interrupts_enabled()); + + drop(guard); + kassert!(are_interrupts_enabled()); }); - // 测试 IntrGuard 在离开作用域时是否恢复中断状态 test_case!(test_guard_restores_on_drop, { println!("Testing: test_guard_restores_on_drop"); let initial_flags: usize = { @@ -74,18 +121,41 @@ mod tests { flags }; - let initial_state = are_interrupts_enabled(); - - kassert!(initial_state); + kassert!(are_interrupts_enabled()); { let guard = IntrGuard::::new(); kassert!(!are_interrupts_enabled()); - kassert!(ArchImpl::interrupt_was_enabled(guard.flags)); + kassert!(guard.was_enabled()); } kassert!(are_interrupts_enabled()); unsafe { restore_interrupts(initial_flags) }; }); + + test_case!(test_nested_intr_guard, { + println!("Testing: test_nested_intr_guard"); + unsafe { enable_interrupts() }; + kassert!(are_interrupts_enabled()); + + { + let outer = IntrGuard::::new(); + kassert!(!are_interrupts_enabled()); + kassert!(outer.was_enabled()); + + { + let inner = IntrGuard::::new(); + kassert!(!are_interrupts_enabled()); + // 内层守卫: 进入时中断已禁用, 所以 was_enabled 应该是 false + kassert!(!inner.was_enabled()); + } + + // 内层 drop 后中断仍应禁用 (因为外层还持有) + kassert!(!are_interrupts_enabled()); + } + + // 外层 drop 后中断应恢复 + kassert!(are_interrupts_enabled()); + }); } diff --git a/os/src/sync/mod.rs b/os/src/sync/mod.rs index f0c29672..0fe2f4fa 100644 --- a/os/src/sync/mod.rs +++ b/os/src/sync/mod.rs @@ -7,15 +7,12 @@ mod mutex; mod per_cpu; mod preempt; mod raw_spin_lock; -mod raw_spin_lock_without_guard; mod rwlock; mod spin_lock; -mod ticket_lock; pub use mutex::*; pub use per_cpu::PerCpu; pub use preempt::PreemptGuard; pub use raw_spin_lock::*; -pub use raw_spin_lock_without_guard::*; pub use rwlock::*; pub use spin_lock::*; diff --git a/os/src/sync/mutex.rs b/os/src/sync/mutex.rs index fbbc1380..2a641dbd 100644 --- a/os/src/sync/mutex.rs +++ b/os/src/sync/mutex.rs @@ -8,7 +8,6 @@ //! * `T` - 被保护的数据类型 //! * `CPU` - 实现 `CpuOps` 的类型,默认使用 `ArchImpl` -#![allow(dead_code)] use core::cell::UnsafeCell; use core::sync::atomic::{AtomicBool, Ordering}; diff --git a/os/src/sync/preempt.rs b/os/src/sync/preempt.rs index b367d79d..eefd9948 100644 --- a/os/src/sync/preempt.rs +++ b/os/src/sync/preempt.rs @@ -8,8 +8,8 @@ use core::sync::atomic::{AtomicUsize, Ordering}; use crate::arch::ArchImpl; -use crate::config::MAX_CPU_COUNT; use crate::arch::CpuOps; +use crate::config::MAX_CPU_COUNT; /// 缓存行对齐的原子计数器 #[repr(align(64))] diff --git a/os/src/sync/raw_spin_lock.rs b/os/src/sync/raw_spin_lock.rs index f8f4a4bc..9c1ac90b 100644 --- a/os/src/sync/raw_spin_lock.rs +++ b/os/src/sync/raw_spin_lock.rs @@ -13,12 +13,13 @@ use crate::sync::intr_guard::IntrGuard; use core::{ hint, marker::PhantomData, - sync::atomic::{AtomicBool, Ordering}, + sync::atomic::{AtomicBool, AtomicUsize, Ordering}, }; /// 自旋锁结构体,提供互斥访问临界区的能力。 pub struct RawSpinLock { lock: AtomicBool, + saved_intr_flags: AtomicUsize, _marker: PhantomData, } @@ -34,6 +35,7 @@ impl RawSpinLock { pub const fn new() -> Self { RawSpinLock { lock: AtomicBool::new(false), + saved_intr_flags: AtomicUsize::new(0), _marker: PhantomData, } } @@ -104,6 +106,52 @@ impl Drop for RawSpinLockGuard<'_, CPU> { } } +unsafe impl lock_api::RawMutex for RawSpinLock { + #[allow(clippy::declare_interior_mutable_const)] + const INIT: Self = Self::new(); + + type GuardMarker = lock_api::GuardNoSend; + + fn lock(&self) { + let flags = CPU::disable_interrupts(); + + while self + .lock + .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed) + .is_err() + { + core::hint::spin_loop(); + } + + self.saved_intr_flags.store(flags, Ordering::Release); + } + + fn try_lock(&self) -> bool { + let flags = CPU::disable_interrupts(); + + if self + .lock + .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) + .is_ok() + { + self.saved_intr_flags.store(flags, Ordering::Release); + true + } else { + CPU::restore_interrupt_state(flags); + false + } + } + + unsafe fn unlock(&self) { + let flags = self.saved_intr_flags.load(Ordering::Acquire); + self.lock.store(false, Ordering::Release); + CPU::restore_interrupt_state(flags); + } +} + +unsafe impl Send for RawSpinLock {} +unsafe impl Sync for RawSpinLock {} + #[cfg(test)] mod tests { use super::*; diff --git a/os/src/sync/raw_spin_lock_without_guard.rs b/os/src/sync/raw_spin_lock_without_guard.rs deleted file mode 100644 index 9ce7073d..00000000 --- a/os/src/sync/raw_spin_lock_without_guard.rs +++ /dev/null @@ -1,143 +0,0 @@ -//! 无 Guard 的底层自旋锁,专门为全局分配器集成设计 -//! -//! 实现 `lock_api::RawMutex` trait,用于 `talc` 分配器的 `Talck` 类型。 -//! -//! # 与 `RawSpinLock` 的主要区别 -//! -//! - 实现 `lock_api::RawMutex` trait -//! - `lock()` 方法不返回 Guard -//! - 使用 `AtomicUsize` 在内部存储中断状态 -//! - `unlock()` 操作恢复中断状态 -//! -//! # 泛型参数 -//! -//! * `CPU` - 实现 `CpuOps` 的类型,默认使用 `ArchImpl` - -use crate::arch::ArchImpl; -use crate::arch::CpuOps; -use core::marker::PhantomData; -use core::sync::atomic::{AtomicBool, AtomicUsize, Ordering}; - -/// 自旋锁结构体,不返回 Guard,集成了中断状态保存与恢复功能。 -pub struct RawSpinLockWithoutGuard { - locked: AtomicBool, - saved_intr_flags: AtomicUsize, - _marker: PhantomData, -} - -impl RawSpinLockWithoutGuard { - pub const fn new() -> Self { - Self { - locked: AtomicBool::new(false), - saved_intr_flags: AtomicUsize::new(0), - _marker: PhantomData, - } - } -} - -unsafe impl lock_api::RawMutex for RawSpinLockWithoutGuard { - #[allow(clippy::declare_interior_mutable_const)] - const INIT: Self = Self::new(); - - type GuardMarker = lock_api::GuardNoSend; - - fn lock(&self) { - let flags = CPU::disable_interrupts(); - - while self - .locked - .compare_exchange_weak(false, true, Ordering::Acquire, Ordering::Relaxed) - .is_err() - { - core::hint::spin_loop(); - } - - self.saved_intr_flags.store(flags, Ordering::Release); - } - - fn try_lock(&self) -> bool { - let flags = CPU::disable_interrupts(); - - if self - .locked - .compare_exchange(false, true, Ordering::Acquire, Ordering::Relaxed) - .is_ok() - { - self.saved_intr_flags.store(flags, Ordering::Release); - true - } else { - CPU::restore_interrupt_state(flags); - false - } - } - - unsafe fn unlock(&self) { - let flags = self.saved_intr_flags.load(Ordering::Acquire); - self.locked.store(false, Ordering::Release); - CPU::restore_interrupt_state(flags); - } -} - -unsafe impl Send for RawSpinLockWithoutGuard {} -unsafe impl Sync for RawSpinLockWithoutGuard {} - -#[cfg(test)] -mod tests { - use lock_api::RawMutex; - - use super::*; - use crate::{kassert, test_case}; - - test_case!(test_mutex_wrapper_guard_basic, { - let m = lock_api::Mutex::::new(0); - - { - let mut g = m.lock(); - *g = 42; - } - - { - let g = m.lock(); - kassert!(*g == 42); - } - }); - - test_case!(test_try_lock_and_unlock_roundtrip, { - let raw = RawSpinLockWithoutGuard::::new(); - - let ok = raw.try_lock(); - kassert!(ok); - - let fail = raw.try_lock(); - kassert!(!fail); - - unsafe { - raw.unlock(); - } - - let ok2 = raw.try_lock(); - kassert!(ok2); - - unsafe { - raw.unlock(); - } - }); - - test_case!(test_lock_then_unlock, { - let raw = RawSpinLockWithoutGuard::::new(); - - raw.lock(); - - let fail = raw.try_lock(); - kassert!(!fail); - - unsafe { - raw.unlock(); - } - let ok = raw.try_lock(); - kassert!(ok); - unsafe { - raw.unlock(); - } - }); -} diff --git a/os/src/sync/ticket_lock.rs b/os/src/sync/ticket_lock.rs deleted file mode 100644 index fa584178..00000000 --- a/os/src/sync/ticket_lock.rs +++ /dev/null @@ -1,183 +0,0 @@ -//! 票号锁实现 -//! -//! 提供公平的 FIFO 顺序锁获取机制,避免饥饿问题。 -//! -//! # 泛型参数 -//! -//! * `T` - 被保护的数据类型 -//! * `CPU` - 实现 `CpuOps` 的类型,默认使用 `ArchImpl` - -use crate::arch::ArchImpl; -use crate::arch::CpuOps; -use crate::sync::intr_guard::IntrGuard; -use core::{ - cell::UnsafeCell, - hint, - ops::{Deref, DerefMut}, - sync::atomic::{AtomicUsize, Ordering}, -}; - -/// 票号锁,提供公平的 FIFO 顺序获取 -pub struct TicketLock { - next_ticket: AtomicUsize, - serving_ticket: AtomicUsize, - data: UnsafeCell, - _marker: core::marker::PhantomData, -} - -/// 票号锁的 RAII 保护器 -pub struct TicketLockGuard<'a, T, CPU: CpuOps = ArchImpl> { - lock: &'a TicketLock, - intr_guard: IntrGuard, -} - -impl TicketLock { - pub const fn new(data: T) -> Self { - TicketLock { - next_ticket: AtomicUsize::new(0), - serving_ticket: AtomicUsize::new(0), - data: UnsafeCell::new(data), - _marker: core::marker::PhantomData, - } - } - - pub fn lock(&self) -> TicketLockGuard<'_, T, CPU> { - let intr_guard = IntrGuard::::new(); - - let my_ticket = self.next_ticket.fetch_add(1, Ordering::Relaxed); - - while self.serving_ticket.load(Ordering::Acquire) != my_ticket { - hint::spin_loop(); - } - - TicketLockGuard { - lock: self, - intr_guard, - } - } - - pub fn try_lock(&self) -> Option> { - let intr_guard = IntrGuard::::new(); - - let serving = self.serving_ticket.load(Ordering::Relaxed); - let next = self.next_ticket.load(Ordering::Relaxed); - - if serving == next { - if self - .next_ticket - .compare_exchange(next, next + 1, Ordering::Acquire, Ordering::Relaxed) - .is_ok() - { - return Some(TicketLockGuard { - lock: self, - intr_guard, - }); - } - } - - None - } - - #[cfg(test)] - pub fn is_locked(&self) -> bool { - self.next_ticket.load(Ordering::Relaxed) != self.serving_ticket.load(Ordering::Relaxed) - } -} - -impl Deref for TicketLockGuard<'_, T, CPU> { - type Target = T; - - fn deref(&self) -> &T { - unsafe { &*self.lock.data.get() } - } -} - -impl DerefMut for TicketLockGuard<'_, T, CPU> { - fn deref_mut(&mut self) -> &mut T { - unsafe { &mut *self.lock.data.get() } - } -} - -impl Drop for TicketLockGuard<'_, T, CPU> { - fn drop(&mut self) { - self.lock.serving_ticket.fetch_add(1, Ordering::Release); - } -} - -unsafe impl Send for TicketLock {} -unsafe impl Sync for TicketLock {} - -#[cfg(test)] -mod tests { - use super::*; - use crate::{arch::intr::are_interrupts_enabled, kassert, test_case}; - - test_case!(test_ticket_lock_basic, { - let lock: TicketLock = TicketLock::new(42); - kassert!(!lock.is_locked()); - - let guard = lock.lock(); - kassert!(lock.is_locked()); - kassert!(*guard == 42); - - drop(guard); - kassert!(!lock.is_locked()); - }); - - test_case!(test_ticket_lock_raii, { - let lock: TicketLock = TicketLock::new(100); - - { - let mut guard = lock.lock(); - kassert!(lock.is_locked()); - *guard = 200; - } - - kassert!(!lock.is_locked()); - - let guard = lock.lock(); - kassert!(*guard == 200); - }); - - test_case!(test_ticket_lock_fairness, { - let lock: TicketLock = TicketLock::new(0); - - let guard1 = lock.lock(); - kassert!(lock.next_ticket.load(Ordering::Relaxed) == 1); - kassert!(lock.serving_ticket.load(Ordering::Relaxed) == 0); - - drop(guard1); - - let guard2 = lock.lock(); - kassert!(lock.next_ticket.load(Ordering::Relaxed) == 2); - kassert!(lock.serving_ticket.load(Ordering::Relaxed) == 1); - - drop(guard2); - }); - - test_case!(test_ticket_lock_interrupt_disable, { - let lock: TicketLock = TicketLock::new(0); - - let guard = lock.lock(); - kassert!(!are_interrupts_enabled()); - - drop(guard); - kassert!(are_interrupts_enabled()); - }); - - test_case!(test_ticket_lock_try_lock, { - let lock: TicketLock = TicketLock::new(42); - - let guard = lock.try_lock(); - kassert!(guard.is_some()); - kassert!(lock.is_locked()); - - let guard2 = lock.try_lock(); - kassert!(guard2.is_none()); - - drop(guard); - - let guard3 = lock.try_lock(); - kassert!(guard3.is_some()); - }); -} diff --git a/os/src/test/guard.rs b/os/src/test/guard.rs index 201d0824..c2c8e63a 100644 --- a/os/src/test/guard.rs +++ b/os/src/test/guard.rs @@ -36,7 +36,7 @@ impl TestEnvGuard { TestEnvironment::None => {} TestEnvironment::Interrupt(_handler) => { crate::arch::enable_interrupts(); - }, + } } guard diff --git a/os/src/test/mod.rs b/os/src/test/mod.rs index 372df540..201a140b 100644 --- a/os/src/test/mod.rs +++ b/os/src/test/mod.rs @@ -9,7 +9,7 @@ use crate::{ /// 测试运行器。它由测试框架自动调用,并传入一个包含所有测试的切片。 #[cfg(test)] pub fn test_runner(tests: &[&dyn Fn()]) { - use crate::arch::Arch; + use crate::arch::Platform; use crate::{earlyprintln, test::macros::TEST_FAILED}; use core::sync::atomic::Ordering; earlyprintln!("\n\x1b[33m--- Running {} tests ---\x1b[0m", tests.len()); diff --git a/os/src/uapi/uts_namespace.rs b/os/src/uapi/uts_namespace.rs index 7012c59c..031dfe32 100644 --- a/os/src/uapi/uts_namespace.rs +++ b/os/src/uapi/uts_namespace.rs @@ -1,7 +1,7 @@ //! 工具函数模块 - UTS 命名空间 -use crate::arch::ArchImpl; use crate::arch::Arch; +use crate::arch::ArchImpl; /// UTS 名称最大长度 pub const UTS_NAME_LEN: usize = 65; diff --git a/os/src/util/mem.rs b/os/src/util/mem.rs index d9f22a7e..e4d09596 100644 --- a/os/src/util/mem.rs +++ b/os/src/util/mem.rs @@ -1,43 +1,3 @@ -//! 编译器内建函数替代实现 (LoongArch) +//! Portable memory utility placeholder. //! -//! LoongArch64 目标的 compiler_builtins crate 不完全支持, -//! 因此提供纯 Rust 的 memcpy/memmove/memset 实现。 -#[cfg(target_arch = "loongarch64")] -use core::ptr; - -#[cfg(target_arch = "loongarch64")] -#[unsafe(no_mangle)] -pub unsafe extern "C" fn memcpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 { - for i in 0..n { - ptr::write(dst.add(i), ptr::read(src.add(i))); - } - dst -} - -#[cfg(target_arch = "loongarch64")] -#[unsafe(no_mangle)] -pub unsafe extern "C" fn memmove(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 { - if dst as usize == src as usize || n == 0 { - return dst; - } - if (dst as usize) < (src as usize) || (dst as usize) >= (src as usize + n) { - for i in 0..n { - ptr::write(dst.add(i), ptr::read(src.add(i))); - } - } else { - for i in (0..n).rev() { - ptr::write(dst.add(i), ptr::read(src.add(i))); - } - } - dst -} - -#[cfg(target_arch = "loongarch64")] -#[unsafe(no_mangle)] -pub unsafe extern "C" fn memset(dst: *mut u8, c: i32, n: usize) -> *mut u8 { - let val = c as u8; - for i in 0..n { - ptr::write(dst.add(i), val); - } - dst -} +//! Architecture-specific compiler builtin shims live under `arch/`. diff --git a/os/src/util/user_buffer.rs b/os/src/util/user_buffer.rs index bbc76321..1aa88b73 100644 --- a/os/src/util/user_buffer.rs +++ b/os/src/util/user_buffer.rs @@ -7,7 +7,7 @@ use alloc::vec::Vec; use core::mem::MaybeUninit; use crate::arch::constant::USER_TOP; -use crate::arch::Arch; +use crate::arch::{Arch, address::UA}; /// 向用户空间写入数据 /// # 参数 @@ -18,7 +18,7 @@ pub fn write_to_user(user_ptr: *mut T, value: T) { unsafe { crate::arch::ArchImpl::copy_to_user( (&value) as *const T as *const u8, - user_ptr as usize, + UA::from_usize(user_ptr as usize), size, ) .ok(); @@ -35,7 +35,7 @@ pub fn read_from_user(user_ptr: *const T) -> T { let mut val = MaybeUninit::::uninit(); unsafe { crate::arch::ArchImpl::copy_from_user( - user_ptr as usize, + UA::from_usize(user_ptr as usize), val.as_mut_ptr() as *mut u8, size, ) @@ -46,7 +46,7 @@ pub fn read_from_user(user_ptr: *const T) -> T { /// 用户缓冲区结构体 pub struct UserBuffer { - data: *mut u8, + data: UA, len: usize, } @@ -56,7 +56,10 @@ impl UserBuffer { /// - `data`: 指向用户缓冲区的指针 /// - `len`: 缓冲区的长度 pub fn new(data: *mut u8, len: usize) -> Self { - Self { data, len } + Self { + data: UA::from_usize(data as usize), + len, + } } /// 从用户缓冲区向内核缓冲区复制数据 @@ -70,13 +73,11 @@ impl UserBuffer { } let mut vec = Vec::with_capacity(self.len); unsafe { + let dst = vec.spare_capacity_mut().as_mut_ptr() as *mut u8; + if crate::arch::ArchImpl::copy_from_user(self.data, dst, self.len).is_err() { + return Vec::new(); + } vec.set_len(self.len); - crate::arch::ArchImpl::copy_from_user( - self.data as usize, - vec.as_mut_ptr(), - self.len, - ) - .ok(); } vec } @@ -92,14 +93,14 @@ impl UserBuffer { } let n = core::cmp::min(self.len, data.len()); unsafe { - crate::arch::ArchImpl::copy_to_user(data.as_ptr(), self.data as usize, n).ok(); + crate::arch::ArchImpl::copy_to_user(data.as_ptr(), self.data, n).ok(); } } /// TODO: 运行时做一次”粗略”范围校验(不保证已映射,仅做地址区间与溢出检查) /// 建议在 syscall 层或结合 MemorySpace 做页表级校验。 pub fn range_sane(&self) -> bool { - let start = self.data as usize; + let start = self.data.as_usize(); let Some(end) = start.checked_add(self.len) else { return false; }; diff --git a/os/src/vfs/devno.rs b/os/src/vfs/devno.rs index d6204b99..2fabbe69 100644 --- a/os/src/vfs/devno.rs +++ b/os/src/vfs/devno.rs @@ -51,7 +51,7 @@ pub fn get_chrdev_driver(dev: u64) -> Option> { // 串口设备:ttyS0-ttyS63 (minor 64-127) let idx = (min - 64) as usize; SERIAL_DRIVERS - .read() + .lock() .get(idx) .map(|d| d.clone() as Arc) } else { @@ -64,7 +64,7 @@ pub fn get_chrdev_driver(dev: u64) -> Option> { // 控制台设备 (minor 1) // 使用第一个串口作为控制台 SERIAL_DRIVERS - .read() + .lock() .first() .map(|d| d.clone() as Arc) } diff --git a/os/src/vfs/impls/char_dev_file.rs b/os/src/vfs/impls/char_dev_file.rs index fd8099c9..006e51e2 100644 --- a/os/src/vfs/impls/char_dev_file.rs +++ b/os/src/vfs/impls/char_dev_file.rs @@ -379,7 +379,9 @@ impl CharDeviceFile { } let winsize = *self.winsize.lock(); - let zeroed = unsafe { core::mem::MaybeUninit::::zeroed().assume_init() }; + let zeroed = unsafe { + core::mem::MaybeUninit::::zeroed().assume_init() + }; unsafe { write_to_user(winsize_ptr, zeroed) }; unsafe { write_to_user(winsize_ptr, winsize) }; Ok(0) @@ -444,7 +446,8 @@ impl CharDeviceFile { tm_isdst: 0, }; - let zeroed = unsafe { core::mem::MaybeUninit::::zeroed().assume_init() }; + let zeroed = + unsafe { core::mem::MaybeUninit::::zeroed().assume_init() }; unsafe { write_to_user(rtc_time_ptr, zeroed) }; unsafe { write_to_user(rtc_time_ptr, rtc_time) }; return Ok(0); diff --git a/os/src/vfs/impls/pipe_file.rs b/os/src/vfs/impls/pipe_file.rs index 0a215ad4..5144df15 100644 --- a/os/src/vfs/impls/pipe_file.rs +++ b/os/src/vfs/impls/pipe_file.rs @@ -175,53 +175,30 @@ impl PipeFile { impl File for PipeFile { fn readable(&self) -> bool { - if self.end_type != PipeEnd::Read { - return false; - } - let buf = self.buffer.lock(); - // Readable if buffer has data OR write end is closed (EOF) - !buf.buffer.is_empty() || buf.write_end_count == 0 + // 读端始终可读;buffer 为空且写端未关闭时 read() 返回 Ok(0) 或 WouldBlock + self.end_type == PipeEnd::Read } fn writable(&self) -> bool { if self.end_type != PipeEnd::Write { return false; } - let buf = self.buffer.lock(); - // Writable if buffer has space AND read end is open - buf.read_end_count > 0 && buf.buffer.len() < buf.capacity + // 写端可写当读端仍然打开(buffer 满时 write() 返回 Ok(0) 或 WouldBlock) + self.buffer.lock().read_end_count > 0 } fn read(&self, buf: &mut [u8]) -> Result { - if !self.readable() { + if self.end_type != PipeEnd::Read { return Err(FsError::InvalidArgument); } - - let mut ring_buf = self.buffer.lock(); - let result = ring_buf.read(buf); - // Only wake up writers if we actually freed buffer space - if let Ok(bytes_read) = result - && bytes_read > 0 - { - crate::kernel::syscall::io::wake_poll_waiters(); - } - result + self.buffer.lock().read(buf) } fn write(&self, buf: &[u8]) -> Result { - if !self.writable() { + if self.end_type != PipeEnd::Write { return Err(FsError::InvalidArgument); } - - let mut ring_buf = self.buffer.lock(); - let result = ring_buf.write(buf); - // Only wake up readers if we actually wrote data - if let Ok(bytes_written) = result - && bytes_written > 0 - { - crate::kernel::syscall::io::wake_poll_waiters(); - } - result + self.buffer.lock().write(buf) } fn metadata(&self) -> Result { diff --git a/os/src/vfs/impls/stdio_file.rs b/os/src/vfs/impls/stdio_file.rs index 00e683b9..1d735eaa 100644 --- a/os/src/vfs/impls/stdio_file.rs +++ b/os/src/vfs/impls/stdio_file.rs @@ -312,7 +312,9 @@ fn stdio_ioctl(request: u32, arg: usize) -> Result { } let winsize = *STDIO_WINSIZE.lock(); - let zeroed = unsafe { core::mem::MaybeUninit::::zeroed().assume_init() }; + let zeroed = unsafe { + core::mem::MaybeUninit::::zeroed().assume_init() + }; unsafe { write_to_user(winsize_ptr, zeroed) }; unsafe { write_to_user(winsize_ptr, winsize) };