Skip to content

Commit b29f386

Browse files
authored
Merge pull request #240 from comix-kernel/hal-refactor
Hal refactor
2 parents ac0cd03 + cefac50 commit b29f386

119 files changed

Lines changed: 4541 additions & 3613 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

os/.cargo/config.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,3 +22,15 @@ runner = "./qemu-loongarch-run.sh"
2222

2323
[net]
2424
retry = 3
25+
26+
# x86_64 宿主测试(Mock 模式)的编译设置
27+
# 使用方式: cargo +nightly check --tests --target x86_64-unknown-linux-gnu
28+
# 或: RUSTFLAGS="-Cpanic=abort -Zpanic_abort_tests" cargo +nightly check --tests --target x86_64-unknown-linux-gnu
29+
#
30+
# 注意: cargo test 在 x86_64 上会因为 hashbrown -> allocator-api2 的
31+
# duplicate lang item 问题无法链接,这是已知问题。cargo check --tests 可以正常通过。
32+
[target.x86_64-unknown-linux-gnu]
33+
rustflags = [
34+
"-Cpanic=abort",
35+
"-Zpanic_abort_tests",
36+
]

os/Cargo.toml

Lines changed: 24 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,26 +4,38 @@ version = "0.1.0"
44
edition = "2024"
55

66
[dependencies]
7-
talc = { version = "4" }
7+
# 基础依赖(始终需要)
88
lock_api = "0.4"
99
bitflags = { version = "2.10.0" }
1010
lazy_static = { version = "1.4.0", features = ["spin_no_std"] }
1111
once_cell = { version = "1.21.3", default-features = false, features = [
1212
"alloc",
1313
"race",
1414
] }
15-
xmas-elf = "0.9"
1615
paste = "1.0"
17-
ext4_rs = "1.3.2"
18-
virtio-drivers = "0.12.0"
19-
fdt = "0.1.5"
20-
smoltcp = { version = "0.12.0", default-features = false, features = ["alloc", "medium-ethernet", "proto-ipv4", "proto-ipv6", "socket-raw", "socket-tcp", "socket-udp"] }
21-
chrono = { version = "0.4", default-features = false, features = ["alloc"] }
22-
uart_16550 = "0.4.0"
23-
hashbrown = "0.16.1"
16+
17+
# 功能分层依赖(optional,通过 feature gate 引入)
18+
talc = { version = "4", default-features = false, features = ["nightly_api", "lock_api"], optional = true }
19+
hashbrown = { version = "0.16.1", optional = true }
20+
xmas-elf = { version = "0.9", optional = true }
21+
ext4_rs = { version = "1.3.2", optional = true }
22+
virtio-drivers = { version = "0.12.0", optional = true }
23+
fdt = { version = "0.1.5", optional = true }
24+
smoltcp = { version = "0.12.0", default-features = false, features = ["alloc", "medium-ethernet", "proto-ipv4", "proto-ipv6", "socket-raw", "socket-tcp", "socket-udp"], optional = true }
25+
chrono = { version = "0.4", default-features = false, features = ["alloc"], optional = true }
26+
uart_16550 = { version = "0.4.0", optional = true }
2427

2528
[features]
26-
default = []
29+
default = ["sync", "alloc", "paging", "proc_vm", "fs", "net", "device"]
30+
sync = []
31+
alloc = ["sync", "dep:talc"]
32+
# device: 驱动层(virtio, fdt, uart, rtc)
33+
device = ["alloc", "dep:virtio-drivers", "dep:fdt", "dep:uart_16550", "dep:chrono"]
34+
paging = ["alloc"]
35+
proc = ["sync", "dep:hashbrown", "dep:xmas-elf"]
36+
fs = ["proc", "device", "dep:ext4_rs"]
37+
proc_vm = ["paging", "fs"]
38+
net = ["sync", "device", "dep:smoltcp"]
2739
proto-ipv6 = []
2840

2941
# RISC-V 架构特定依赖
@@ -51,6 +63,8 @@ redundant_clone = "deny"
5163

5264
[profile.dev]
5365
opt-level = 1 # 启用基本优化以减小代码体积
66+
panic = "abort"
5467

5568
[profile.test]
5669
opt-level = 1 # 测试模式也启用基本优化
70+
panic = "abort"

os/build.rs

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,11 @@ fn main() {
2727
println!("cargo:rerun-if-changed=../user");
2828
println!("cargo:rerun-if-changed=../scripts/make_init_simple_fs.py");
2929

30-
// 步骤 1: 编译用户程序
31-
if user_dir.exists() {
30+
// 步骤 1: 编译用户程序(仅在目标架构上编译)
31+
let target = env::var("TARGET").unwrap_or_default();
32+
let is_target_arch = target.contains("riscv64") || target.contains("loongarch");
33+
34+
if is_target_arch && user_dir.exists() {
3235
println!("cargo:warning=[build.rs] Building user programs...");
3336
let status = Command::new("make")
3437
.current_dir(&user_dir)
@@ -57,8 +60,13 @@ fn main() {
5760
);
5861
}
5962
}
60-
} else {
63+
} else if is_target_arch {
6164
println!("cargo:warning=[build.rs] User directory not found, skipping user build");
65+
} else {
66+
println!(
67+
"cargo:warning=[build.rs] Skipping user program build (target: {})",
68+
target
69+
);
6270
}
6371

6472
// 步骤 2: 打包 simple_fs 镜像 (暂时禁用,直接创建空镜像)
@@ -135,8 +143,8 @@ fn main() {
135143
println!("cargo:rustc-env=EXT4_FS_IMAGE={}", dummy_img.display());
136144
}
137145

138-
// 3.2: 非测试模式下创建完整的运行时镜像
139-
if !is_test {
146+
// 3.2: 非测试模式下创建完整的运行时镜像(仅目标架构)
147+
if !is_test && is_target_arch {
140148
let target = env::var("TARGET").unwrap_or_default();
141149
let arch_key = match env::var("ARCH") {
142150
Ok(val) if !val.is_empty() => {

os/src/arch/address.rs

Lines changed: 259 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,259 @@
1+
//! 类型安全的架构地址抽象
2+
//!
3+
//! 借鉴 moss-kernel 的地址类型体系设计:
4+
//! - Sealed trait 防止外部实现(安全边界)
5+
//! - 泛型 `Address<K, T>` 带 `MemKind` 和数据类型标记
6+
//! - 编译期防止地址空间混用
7+
//! - 安全访问控制:`PA::as_ptr()` unsafe, `VA::as_ptr()` safe, `UA` 不能直接转指针
8+
9+
use core::marker::PhantomData;
10+
11+
// ============================================================================
12+
// Sealed trait — 外部无法实现 MemKind
13+
// ============================================================================
14+
mod sealed {
15+
pub trait Sealed {}
16+
}
17+
18+
/// 内存地址种类标记 trait(sealed — 外部无法实现)
19+
pub trait MemKind:
20+
sealed::Sealed + Ord + Clone + Copy + PartialEq + Eq + core::fmt::Debug
21+
{
22+
}
23+
24+
// ============================================================================
25+
// 地址种类标记类型
26+
// ============================================================================
27+
28+
/// 虚拟地址标记
29+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
30+
pub struct Virtual;
31+
impl sealed::Sealed for Virtual {}
32+
impl MemKind for Virtual {}
33+
34+
/// 物理地址标记
35+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
36+
pub struct Physical;
37+
impl sealed::Sealed for Physical {}
38+
impl MemKind for Physical {}
39+
40+
/// 用户空间地址标记
41+
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
42+
pub struct User;
43+
impl sealed::Sealed for User {}
44+
impl MemKind for User {}
45+
46+
// ============================================================================
47+
// 泛型地址类型
48+
// ============================================================================
49+
50+
/// 带地址种类 `K` 和数据类型 `T` 标记的地址
51+
///
52+
/// - `K`: 地址空间种类(Virtual / Physical / User)
53+
/// - `T`: 指向的数据类型(`()` 表示无类型标记)
54+
#[repr(transparent)]
55+
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord)]
56+
pub struct Address<K: MemKind, T> {
57+
inner: usize,
58+
_phantom: PhantomData<(K, T)>,
59+
}
60+
61+
impl<K: MemKind, T> core::fmt::Debug for Address<K, T> {
62+
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
63+
f.debug_struct("Address")
64+
.field("inner", &format_args!("0x{:x}", self.inner))
65+
.finish()
66+
}
67+
}
68+
69+
// ============================================================================
70+
// 类型别名
71+
// ============================================================================
72+
73+
/// 无类型标记的物理地址
74+
pub type PA = Address<Physical, ()>;
75+
/// 无类型标记的虚拟地址
76+
pub type VA = Address<Virtual, ()>;
77+
/// 无类型标记的用户空间地址
78+
pub type UA = Address<User, ()>;
79+
80+
/// 带类型标记的物理地址指针
81+
pub type TPA<T> = Address<Physical, T>;
82+
/// 带类型标记的虚拟地址指针
83+
pub type TVA<T> = Address<Virtual, T>;
84+
85+
// ============================================================================
86+
// Address 基本方法
87+
// ============================================================================
88+
89+
impl<K: MemKind, T> Address<K, T> {
90+
/// 从 `usize` 创建地址
91+
pub const fn from_usize(addr: usize) -> Self {
92+
Self {
93+
inner: addr,
94+
_phantom: PhantomData,
95+
}
96+
}
97+
98+
/// 获取地址的 `usize` 值
99+
pub const fn as_usize(&self) -> usize {
100+
self.inner
101+
}
102+
103+
/// 检查地址是否为零
104+
pub fn is_null(self) -> bool {
105+
self.inner == 0
106+
}
107+
108+
/// 返回零地址
109+
pub const fn null() -> Self {
110+
Self::from_usize(0)
111+
}
112+
113+
/// 获取页内偏移
114+
pub fn page_offset(self) -> usize {
115+
self.inner & (crate::config::PAGE_SIZE - 1)
116+
}
117+
118+
/// 检查地址是否页对齐
119+
pub fn is_page_aligned(self) -> bool {
120+
self.page_offset() == 0
121+
}
122+
123+
/// 向上对齐到页边界
124+
pub fn page_aligned(self) -> Self {
125+
let page_size = crate::config::PAGE_SIZE;
126+
Self::from_usize((self.inner + page_size - 1) & !(page_size - 1))
127+
}
128+
129+
/// 向下对齐到页边界
130+
pub fn align_down_to_page(self) -> Self {
131+
let page_size = crate::config::PAGE_SIZE;
132+
Self::from_usize(self.inner & !(page_size - 1))
133+
}
134+
135+
/// 向上对齐到指定对齐值
136+
pub fn align_up(self, align: usize) -> Self {
137+
Self::from_usize((self.inner + align - 1) & !(align - 1))
138+
}
139+
140+
/// 增加字节偏移
141+
pub fn add(self, offset: usize) -> Self {
142+
Self::from_usize(self.inner + offset)
143+
}
144+
145+
/// 减去字节偏移
146+
pub fn sub(self, offset: usize) -> Self {
147+
Self::from_usize(self.inner - offset)
148+
}
149+
150+
/// 增加页数
151+
pub fn add_pages(self, count: usize) -> Self {
152+
self.add(count * crate::config::PAGE_SIZE)
153+
}
154+
155+
/// 计算与另一地址的差值
156+
pub fn diff(self, other: Self) -> isize {
157+
self.inner as isize - other.inner as isize
158+
}
159+
}
160+
161+
// ============================================================================
162+
// 物理地址 (PA) 特有方法
163+
// ============================================================================
164+
165+
impl<T> Address<Physical, T> {
166+
/// 将物理地址转换为裸指针(只读)
167+
///
168+
/// # Safety
169+
///
170+
/// 裸物理地址访问需要显式承诺:调用者必须确保物理地址有效且已映射。
171+
pub unsafe fn as_ptr(&self) -> *const T {
172+
self.inner as *const T
173+
}
174+
175+
/// 将物理地址转换为可变裸指针
176+
///
177+
/// # Safety
178+
///
179+
/// 裸物理地址访问需要显式承诺:调用者必须确保物理地址有效且已映射,
180+
/// 并且没有其他活跃引用指向同一内存。
181+
pub unsafe fn as_mut_ptr(&mut self) -> *mut T {
182+
self.inner as *mut T
183+
}
184+
}
185+
186+
// ============================================================================
187+
// 虚拟地址 (VA) 特有方法
188+
// ============================================================================
189+
190+
impl<T> Address<Virtual, T> {
191+
/// 将虚拟地址转换为裸指针(只读)
192+
///
193+
/// 虚拟地址已通过 MMU 映射,因此此操作不是 unsafe。
194+
pub fn as_ptr(&self) -> *const T {
195+
self.inner as *const T
196+
}
197+
198+
/// 将虚拟地址转换为可变裸指针
199+
pub fn as_mut_ptr(&mut self) -> *mut T {
200+
self.inner as *mut T
201+
}
202+
203+
/// 将虚拟地址转换为不可变引用
204+
///
205+
/// # Safety
206+
///
207+
/// 调用者必须确保地址指向的内存已初始化且未被其他可变引用借用。
208+
pub unsafe fn as_ref<'a>(&self) -> &'a T {
209+
unsafe { &*(self.inner as *const T) }
210+
}
211+
212+
/// 将虚拟地址转换为可变引用
213+
///
214+
/// # Safety
215+
///
216+
/// 调用者必须确保地址指向的内存已初始化且无其他活跃引用。
217+
pub unsafe fn as_mut<'a>(&mut self) -> &'a mut T {
218+
unsafe { &mut *(self.inner as *mut T) }
219+
}
220+
}
221+
222+
// ============================================================================
223+
// 用户地址 (UA) — 不能直接转指针,必须通过安全机制访问
224+
// ============================================================================
225+
226+
impl<T> Address<User, T> {
227+
/// 用户地址不能直接转换为裸指针。
228+
/// 必须通过 `copy_from_user`/`copy_to_user` 等安全机制访问。
229+
#[deprecated(note = "UA 不能直接转指针,请使用 copy_from_user/copy_to_user")]
230+
pub fn as_ptr(&self) -> *const T {
231+
panic!("UA::as_ptr() is forbidden; use copy_from_user/copy_to_user")
232+
}
233+
}
234+
235+
// ============================================================================
236+
// AddressTranslator — 跨地址空间转换
237+
// ============================================================================
238+
239+
/// 地址转换器 trait。
240+
///
241+
/// 只有通过 `Translator` 才能跨地址空间转换。
242+
///
243+
/// # 类型参数
244+
///
245+
/// * `T` - 要转换的地址携带的数据类型
246+
pub trait AddressTranslator<T>: 'static + Send + Sync {
247+
/// 虚拟地址 → 物理地址
248+
fn virt_to_phys(va: TVA<T>) -> TPA<T>;
249+
250+
/// 物理地址 → 虚拟地址
251+
fn phys_to_virt(pa: TPA<T>) -> TVA<T>;
252+
}
253+
254+
// ============================================================================
255+
// unsafe impl Send/Sync
256+
// ============================================================================
257+
258+
unsafe impl<K: MemKind, T> Send for Address<K, T> {}
259+
unsafe impl<K: MemKind, T> Sync for Address<K, T> {}

0 commit comments

Comments
 (0)