From e1141053241886bfe8b6c3902398b45a48e40192 Mon Sep 17 00:00:00 2001 From: ZIYAN137 Date: Sun, 24 May 2026 18:19:20 +0800 Subject: [PATCH] refactor: clean up cross-module arch constants --- os/src/arch/arch_impl.rs | 7 ++++--- os/src/arch/mock/arch.rs | 1 + os/src/arch/mod.rs | 2 ++ os/src/arch/virtual_memory.rs | 3 +++ os/src/config.rs | 13 ++++++++----- os/src/device/irq/plic.rs | 2 +- os/src/util/address.rs | 2 +- os/src/util/user_buffer.rs | 9 ++++----- 8 files changed, 24 insertions(+), 15 deletions(-) diff --git a/os/src/arch/arch_impl.rs b/os/src/arch/arch_impl.rs index c1323ad3..bf1615a0 100644 --- a/os/src/arch/arch_impl.rs +++ b/os/src/arch/arch_impl.rs @@ -22,6 +22,7 @@ macro_rules! impl_arch { type KernelAddressSpace = $kernel_space; const PAGE_OFFSET: usize = mm::VADDR_START; + const USER_TOP: usize = constant::USER_TOP; fn kern_address_space() -> &'static SpinLock { &KERN_ADDR_SPACE @@ -85,7 +86,7 @@ macro_rules! impl_arch { max_len: usize, ) -> Result { let src = src.as_usize(); - if src < constant::USER_BASE || src > constant::USER_TOP { + if !(constant::USER_BASE..=<$arch as VirtualMemory>::USER_TOP).contains(&src) { return Err(()); } if max_len != 0 && dst.is_null() { @@ -143,12 +144,12 @@ macro_rules! impl_arch { if len == 0 { return Ok(()); } - if start < constant::USER_BASE || start > constant::USER_TOP { + if !(constant::USER_BASE..=<$arch as VirtualMemory>::USER_TOP).contains(&start) { return Err(()); } let end = start.checked_add(len).ok_or(())?; let last = end.checked_sub(1).ok_or(())?; - if last > constant::USER_TOP { + if last > <$arch as VirtualMemory>::USER_TOP { return Err(()); } diff --git a/os/src/arch/mock/arch.rs b/os/src/arch/mock/arch.rs index 99dc1283..8d10658b 100644 --- a/os/src/arch/mock/arch.rs +++ b/os/src/arch/mock/arch.rs @@ -189,6 +189,7 @@ impl VirtualMemory for MockArch { type ProcessAddressSpace = MockAddressSpace; type KernelAddressSpace = MockAddressSpace; const PAGE_OFFSET: usize = 0xffff_ffc0_0000_0000; + const USER_TOP: usize = super::constant::USER_TOP; fn kern_address_space() -> &'static SpinLock { static KERN_SPACE: SpinLock = SpinLock::new(MockAddressSpace::new()); diff --git a/os/src/arch/mod.rs b/os/src/arch/mod.rs index 5a139ec8..5f447b35 100644 --- a/os/src/arch/mod.rs +++ b/os/src/arch/mod.rs @@ -51,6 +51,8 @@ mod mock; #[cfg(not(any(target_arch = "riscv64", target_arch = "loongarch64")))] pub use mock::*; +pub use constant::SUPERVISOR_EXTERNAL; + // ---- ArchImpl 类型别名 ---- // 内核其余部分通过 ArchImpl 访问架构特定功能,无需关心具体架构。 #[cfg(target_arch = "riscv64")] diff --git a/os/src/arch/virtual_memory.rs b/os/src/arch/virtual_memory.rs index 4da52c4f..8c8f70a1 100644 --- a/os/src/arch/virtual_memory.rs +++ b/os/src/arch/virtual_memory.rs @@ -166,6 +166,9 @@ pub trait VirtualMemory: CpuOps + Sized { /// 对于直接映射,`paddr + PAGE_OFFSET = vaddr`。 const PAGE_OFFSET: usize; + /// 用户地址空间最高可访问地址 + const USER_TOP: usize; + /// 获取全局内核地址空间 fn kern_address_space() -> &'static SpinLock; } diff --git a/os/src/config.rs b/os/src/config.rs index 2681f0c0..4bd94797 100644 --- a/os/src/config.rs +++ b/os/src/config.rs @@ -12,6 +12,9 @@ pub const USER_STACK_SIZE: usize = 4 * 1024 * 1024; // 4MB pub const MAX_ARGV: usize = 256; +use crate::arch::{ArchImpl, virtual_memory::VirtualMemory}; +use crate::util::address::align_down; + // User space memory layout constants // Memory layout (from high to low address): // [USER_STACK] <-- @@ -20,13 +23,15 @@ pub const MAX_ARGV: usize = 256; // [USER_DATA] // [USER_TEXT] -pub const USER_STACK_TOP: usize = SV39_BOT_HALF_TOP - PAGE_SIZE; // leave another guard page +/// Leave one guard page below the top of the user address space. +pub const USER_STACK_TOP: usize = ::USER_TOP - PAGE_SIZE; /// Userspace rt_sigreturn trampoline address (one RX page). /// /// Must not overlap with the user stack mapping. With the current (non page-aligned) `USER_STACK_TOP`, -/// the stack mapping ends at `align_down(SV39_BOT_HALF_TOP, PAGE_SIZE)`, so we place the trampoline there. -pub const USER_SIGRETURN_TRAMPOLINE: usize = SV39_BOT_HALF_TOP & !(PAGE_SIZE - 1); +/// the stack mapping ends at `align_down(USER_TOP, PAGE_SIZE)`, so we place the trampoline there. +pub const USER_SIGRETURN_TRAMPOLINE: usize = + align_down(::USER_TOP, PAGE_SIZE); /// Maximum heap size (prevent OOM) pub const MAX_USER_HEAP_SIZE: usize = 64 * 1024 * 1024; // 64MB @@ -40,5 +45,3 @@ pub const EXT4_BLOCK_SIZE: usize = 4096; pub const VIRTIO_BLK_SECTOR_SIZE: usize = 512; /// 文件系统镜像大小 (与 qemu-run.sh 中的 fs.img 大小一致) pub const FS_IMAGE_SIZE: usize = 1024 * 1024 * 1024; // 1 GB - -use crate::arch::constant::SV39_BOT_HALF_TOP; diff --git a/os/src/device/irq/plic.rs b/os/src/device/irq/plic.rs index b5601ad5..9678e435 100644 --- a/os/src/device/irq/plic.rs +++ b/os/src/device/irq/plic.rs @@ -3,7 +3,7 @@ //! PLIC 提供对外设中断的集中管理,支持优先级和中断分发功能。 use super::{super::DRIVERS, IrqManager}; -use crate::arch::constant::SUPERVISOR_EXTERNAL; +use crate::arch::SUPERVISOR_EXTERNAL; use crate::device::device_tree::{DEVICE_TREE_INTC, DEVICE_TREE_REGISTRY}; use crate::device::irq::IntcDriver; use crate::device::{DeviceType, Driver, IRQ_MANAGER}; diff --git a/os/src/util/address.rs b/os/src/util/address.rs index f1cb3f57..f990667c 100644 --- a/os/src/util/address.rs +++ b/os/src/util/address.rs @@ -2,7 +2,7 @@ /// 这是一个安全且常见的 align_down 实现 /// T 必须是整数类型 -pub fn align_down(addr: usize, align: usize) -> usize { +pub const fn align_down(addr: usize, align: usize) -> usize { // 对齐值必须是 2 的幂,否则行为可能不正确 debug_assert!(align.is_power_of_two()); diff --git a/os/src/util/user_buffer.rs b/os/src/util/user_buffer.rs index 1aa88b73..1ecf2df8 100644 --- a/os/src/util/user_buffer.rs +++ b/os/src/util/user_buffer.rs @@ -6,8 +6,7 @@ use alloc::vec::Vec; use core::mem::MaybeUninit; -use crate::arch::constant::USER_TOP; -use crate::arch::{Arch, address::UA}; +use crate::arch::{Arch, ArchImpl, address::UA, virtual_memory::VirtualMemory}; /// 向用户空间写入数据 /// # 参数 @@ -104,7 +103,7 @@ impl UserBuffer { let Some(end) = start.checked_add(self.len) else { return false; }; - end <= USER_TOP + end <= ::USER_TOP } /// 返回用户缓冲区长度 @@ -147,13 +146,13 @@ pub fn validate_user_ptr(ptr: *const T) -> bool { // 检查起始地址是否在用户空间范围内 // USER_BASE 为 0,所以只需检查上界 - if addr > USER_TOP { + if addr > ::USER_TOP { return false; } // 检查是否会溢出用户空间 if let Some(end_addr) = addr.checked_add(size) { - if end_addr > USER_TOP + 1 { + if end_addr > ::USER_TOP + 1 { return false; } } else {