一句话摘要
axhal 是 ArceOS 的硬件抽象层,通过 features 实现模块化,封装 axplat 并提供统一的硬件访问接口,支持多平台编译和按需功能裁剪。
核心要点
- 平台抽象:支持默认 qemu 平台和自定义平台两种导入方式
- 模块化设计:通过 features 控制功能编译,axfeat 统一启用各模块 feature
- 无堆初始化:启动初期无需堆内存,使用 LazyInit 保证线程安全
- 多架构支持:x86_64、AArch64、RISC-V 的 TLS 布局各有适配
平台抽象机制
默认平台(qemu): 上层代码通过 extern crate 直接导入,无需关心具体平台,统一使用 axplat:: 访问。
自定义平台: 需在上层 APP 代码中自行导入,通过 APP_FEATURE 传入 feature,随后在 build.mk 中通过 cargo --feature 启用;若传入不存在的平台包,则会报错退出。
axhal 实质上是对 axplat 的封装与进一步扩展。
模块详解
mem.rs
物理内存区域结构:
PhysMemRegion {
paddr: PhysAddr, // 物理起始地址
size: usize, // 区域大小(字节)
flags: MemRegionFlags, // 内存区域标志
name: &'static str, // 区域名称(用于调试)
}unsafe clear_bss() 说明:
unsafe 的原因:直接操作内存,将函数指针转换为裸指针。
初始化步骤:
- 创建 Vec 作为容器,并声明添加区域的辅助闭包函数
- 注册代码段、只读数据段、数据段、内核初始化栈、BSS 段
- 注册 MMIO 和保留区域(由具体的 axplat 实现)
- 排序后寻找已保留内存与总内存的差集,计算可分配内存并插入
all_regions - 再次排序,检查是否存在重叠区域
- 使用
all_regions初始化全局变量ALL_MEM_REGIONS
设计要点:
- 无堆设计:确保在系统启动初期可用
- LazyInit:原子类型保证线程安全
paging.rs
axhal 中 paging 仅包含两部分:条件编译选择页表类型、使用 ZST 实现 PagingHandler Trait。大部分逻辑拆分到外部 crate(如 page_table_multiarch)。
调用关系:
alloc_frame -> alloc_table()
dealloc_frame -> dealloc_tree() / drop()
|
axmm 中使用(copy_from, try_new)time.rs
axhal 仅 re-export axplat 中 time 的实现(与平台相关)。
irq.rs
- Re-export
axplat的 irq 相关函数 - 为 irq 的
trap_handler提供实现 - 可通过
ipifeature 控制跨处理器中断功能是否编译
percpu.rs
使用 #[percpu::def_percpu] 宏,为每个 CPU 生成独立的存储空间和访问方法。
提供的访问方法:
this_cpu_id()this_cpu_is_bsp()current_task_ptr()/set_current_task_ptr()init_primary()/init_secondary()cache_current_task_ptr()(aarch64 专属)
Bootstrap Processor(BSP)的职责:
- 执行引导加载程序
- 初始化内核数据结构
- 启动其他 CPU
- 分配全局资源
- 初始化设备驱动
tls.rs
Layout 存储内存区域的大小和对齐要求,用于后续释放操作。
pub struct TlsArea {
base: NonNull<u8>, // TLS 区域的基地址
layout: Layout, // 内存布局信息(大小和对齐)
}同时为该结构实现了 Drop Trait。
核心方法:
tls_ptr():获取线程指针alloc():计算大小、分配并清零、将 tdata 和 tbss 段数据赋值到分配区域中(x86 架构最后还会初始化一个指向自己的指针)
TLS 内存布局
x86_64:
aligned --> +-------------------------+- static_tls_offset
allocation | | \
| .tdata | |
| address | | |
| grow up + - - - - - - - - - - - - + > Static TLS block
v | | | (length: static_tls_size)
| .tbss | |
| | |
+-------------------------+ |
| / PADDING / / / / / / / | /
+-------------------------+
tls_ptr -+-> self pointer (void *) | \
(tp_offset) | | |
| Custom TCB format | > Thread Control Block (TCB)
| (might be used | | (length: TCB_SIZE)
| by a libC) | |
| | /
+-------------------------+- (total length: tls_area_size)AArch64 / RISC-V:
+-------------------------+
| | \
| Custom TCB format | |
| (might be used | > Thread Control Block (TCB)
| by a libC) | | (length: TCB_SIZE)
| | /
tls_ptr -+-------------------------+
(tp_offset) | GAP_ABOVE_TP |
+-------------------------+- static_tls_offset
| | \
| .tdata | |
| | |
+ - - - - - - - - - - - - + > Static TLS block
| | | (length: static_tls_size)
| .tbss | |
| | /
+-------------------------+- (total length: tls_area_size)延伸思考
- axhal 通过 features 实现按需裁剪,既减小了编译产物大小,又保持了接口统一性;axfeat 作为统一入口进一步简化了上层模块的 feature 管理
- 不同架构的 TLS 布局差异(x86_64 地址向下增长 vs AArch64/RISC-V 向上增长)直接反映了各自的 ABI 规范,理解这一差异有助于在移植时正确处理线程局部存储
没有评论