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

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions os/.cargo/config.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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 = [
Expand Down
35 changes: 11 additions & 24 deletions os/build.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
88 changes: 88 additions & 0 deletions os/src/arch/abi.rs
Original file line number Diff line number Diff line change
@@ -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<RelocationKind> {
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"
}
}
71 changes: 28 additions & 43 deletions os/src/arch/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {}

// ============================================================================
// 地址种类标记类型
Expand Down Expand Up @@ -77,11 +74,6 @@ pub type VA = Address<Virtual, ()>;
/// 无类型标记的用户空间地址
pub type UA = Address<User, ()>;

/// 带类型标记的物理地址指针
pub type TPA<T> = Address<Physical, T>;
/// 带类型标记的虚拟地址指针
pub type TVA<T> = Address<Virtual, T>;

// ============================================================================
// Address 基本方法
// ============================================================================
Expand Down Expand Up @@ -138,18 +130,18 @@ impl<K: MemKind, T> Address<K, T> {
}

/// 增加字节偏移
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)
}

/// 计算与另一地址的差值
Expand All @@ -168,8 +160,8 @@ impl<T> Address<Physical, T> {
/// # Safety
///
/// 裸物理地址访问需要显式承诺:调用者必须确保物理地址有效且已映射。
pub unsafe fn as_ptr(&self) -> *const T {
self.inner as *const T
pub unsafe fn as_ptr<U>(&self) -> *const U {
self.inner as *const U
}

/// 将物理地址转换为可变裸指针
Expand All @@ -178,8 +170,8 @@ impl<T> Address<Physical, T> {
///
/// 裸物理地址访问需要显式承诺:调用者必须确保物理地址有效且已映射,
/// 并且没有其他活跃引用指向同一内存。
pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
self.inner as *mut T
pub unsafe fn as_mut_ptr<U>(&mut self) -> *mut U {
self.inner as *mut U
}
}

Expand All @@ -191,31 +183,43 @@ impl<T> Address<Virtual, T> {
/// 将虚拟地址转换为裸指针(只读)
///
/// 虚拟地址已通过 MMU 映射,因此此操作不是 unsafe。
pub fn as_ptr(&self) -> *const T {
self.inner as *const T
pub fn as_ptr<U>(&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<U>(&mut self) -> *mut U {
self.inner as *mut U
}

/// 将虚拟地址转换为不可变引用
///
/// # 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) }
}

/// 将虚拟地址转换为可变引用
///
/// # 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<Virtual, ()> {
/// 从一个不可变引用创建虚拟地址。
pub fn from_ref<T>(r: &T) -> Self {
Self::from_ptr(r as *const T)
}

/// 从一个常量指针创建虚拟地址。
pub fn from_ptr<T>(p: *const T) -> Self {
Self::from_usize(p as usize)
}
}

Expand All @@ -232,25 +236,6 @@ impl<T> Address<User, T> {
}
}

// ============================================================================
// AddressTranslator — 跨地址空间转换
// ============================================================================

/// 地址转换器 trait。
///
/// 只有通过 `Translator` 才能跨地址空间转换。
///
/// # 类型参数
///
/// * `T` - 要转换的地址携带的数据类型
pub trait AddressTranslator<T>: 'static + Send + Sync {
/// 虚拟地址 → 物理地址
fn virt_to_phys(va: TVA<T>) -> TPA<T>;

/// 物理地址 → 虚拟地址
fn phys_to_virt(pa: TPA<T>) -> TVA<T>;
}

// ============================================================================
// unsafe impl Send/Sync
// ============================================================================
Expand Down
Loading
Loading