动态平台 axplat-dyn
axplat-dyn 是当前仓库默认维护的平台实现(platforms/axplat-dyn)。它不把板级常量写死在 Cargo feature 中,而是通过 someboot / somehal 在启动时获取平台事实,再把这些事实适配成 ax-plat 接口。
crate 元数据与 feature
Cargo.toml 中的 [package.metadata.axplat]:
[package.metadata.axplat]
platform = "dyn"
arch = "aarch64"
crate = "axplat_dyn"
dynamic = true
dynamic = true 表示它由启动时发现平台事实,而不是静态板级平台包提供固定事实;该标志会被 axbuild xtask 识别。
| feature | 默认 | 启用的能力 |
|---|---|---|
smp | ✓ | 多核 boot;转发到 ax-plat/smp |
irq | ✓ | IRQ 接口;转发到 ax-plat/irq |
rtc | ✗ | LoongArch RTC epoch offset 初始化 |
efi | ✗ | somehal/efi → UEFI 启动路径 |
fp-simd | ✗ | ax-cpu/fp-simd,aarch64/loongarch64 启用 FP/SIMD |
uspace | ✗ | somehal/uspace + 用户态地址空间 |
hv | ✗ | somehal/hv + ax-cpu/arm-el2,hypervisor 模式 |
thead-mae | ✗ | T-Head 扩展;somehal/thead-mae + ax-cpu/xuantie-c9xx |
依赖:anyhow、ax-cpu、ax-driver、ax-errno、axklib(buddy-slab)、ax-plat、heapless、log、ax-memory-addr、ax-percpu(custom-base)、rdrive、somehal、spin。
lib.rs 总览
platforms/axplat-dyn/src/lib.rs:
#![no_std]
extern crate alloc;
extern crate ax_driver as _;
extern crate somehal;
#[macro_use] extern crate ax_plat;
#[macro_use] extern crate log;
mod boot;
mod console;
pub mod drivers;
mod generic_timer;
mod init;
#[cfg(feature = "irq")]
mod irq;
mod mem;
mod platform;
mod power;
pub use boot::{boot_stack_bounds, bootargs};
pub use generic_timer::try_init_epoch_offset;
#[cfg(feature = "irq")]
pub fn enable_timer_irq() { somehal::timer::irq_enable(); }
#[cfg(feature = "irq")]
pub fn ipi_irq() -> ax_plat::irq::IrqId { somehal::irq::ipi_irq() }
#[cfg(all(feature = "irq", target_arch = "riscv64", feature = "hv"))]
pub use irq::register_virtual_irq_injector;
注意:extern crate ax_driver as _ 与 extern crate somehal 只是为了把它们拉入依赖图,并不在 axplat-dyn 内直接调用。
组件分工
| 组件 | 职责 |
|---|---|
someboot(platforms/someboot) | 固件入口、UEFI/FDT 获取、重定位、早期页表、BSS、boot stack、SMP 启动准备 |
somehal(platforms/somehal) | 运行时平台事实:内存图、console、timer、IRQ、power、CPU 拓扑;架构后端实现 PlatOp |
axplat-dyn | 将 somehal 能力实现为 ax-plat 接口;接入 rdrive 设备发现;提供链接脚本 |
ax-hal | 对上提供稳定 HAL facade |
axplat-dyn 默认假设更早的架构级 bring-up 已由 someboot / somehal 完成。它主要完成接口适配和运行时后期初始化,不重新实现最早期的 CPU 模式切换、固件退出和页表建立。
初始化主线
boot.rs — 入口与 boot stack
platforms/axplat-dyn/src/boot.rs 把 somehal::entry 与 ax_plat::call_main 桥接:
#[somehal::entry(Kernel)]
fn main() {
let cpu_idx = somehal::smp::early_current_cpu_idx();
ax_percpu::init_percpu_reg(cpu_idx);
ax_plat::call_main(cpu_idx, args)
}
#[somehal::secondary_entry]
fn secondary_main() {
let cpu_idx = somehal::smp::early_current_cpu_idx();
ax_percpu::init_percpu_reg(cpu_idx);
ax_plat::call_secondary_main(cpu_idx)
}
struct Kernel 同时实现 somehal::KernelOp 与 somehal::setup::MmioOp:后者把 ioremap 委托给 axklib::mmio::op(),前者把 current_cpu_idx 委托给 somehal::cpu::current_cpu_idx。
boot_stack_bounds(cpu_idx) 查询 somehal::smp::cpu_meta(cpu_idx),返回 (stack_top_virt - stack_size, stack_size),供 ax-percpu 与 stack overflow 检查使用。
bootargs() 直接 re-export somehal::bootargs。