arceos分析
arceos分析
arceos 启动流程
建立启动阶段的运行环境
根据 ld
链接文件可以知道整个系统的入口是从 _start()
函数开始,riscv
的 _start()
在 modules/axhal/src/platform/riscv64_qemu_virt/boot.rs
文件中。
#[no_mangle]
#[link_section = ".text.boot"]
unsafe extern "C" fn _start() -> ! {
// PC = 0x8020_0000
// a0 = hartid
// a1 = dtb
core::arch::asm!("
mv s0, a0 // save hartid
mv s1, a1 // save DTB pointer
la sp, {boot_stack}
li t0, {boot_stack_size}
add sp, sp, t0 // setup boot stack
call {init_boot_page_table}
call {init_mmu} // setup boot page table and enabel MMU
li s2, {phys_virt_offset} // fix up virtual high address
add sp, sp, s2
mv a0, s0
mv a1, s1
la a2, {entry}
add a2, a2, s2
jalr a2 // call rust_entry(hartid, dtb)
j .",
phys_virt_offset = const PHYS_VIRT_OFFSET,
boot_stack_size = const TASK_STACK_SIZE,
boot_stack = sym BOOT_STACK,
init_boot_page_table = sym init_boot_page_table,
init_mmu = sym init_mmu,
entry = sym super::rust_entry,
options(noreturn),
)
}
整个程序的起始从此 _start()
开始,由于刚开始代码的运行环境还没有建立,所以只能先使用汇编来进行环境的建立:
- 首先保存了硬件
id
和设备树的首地址; - 建立了启动阶段的栈用于启动阶段的函数调用;
- 初始化
mmu
; - 建立虚拟高端地址映射;
- 跳转到
rust_entry()
函数去执行,参数为hardid
和dtb
首地址。
riscv 的栈是向下增长的,所以这里先设定栈底的地址,再偏移栈长度就将栈设定到栈顶的位置。
phys_virt_offset
所有物理地址到虚拟地址的偏移量,paddr = vaddr - PHYS_VIRT_OFFSET
arceos 运行环境初始化
modules/axhal/src/platform/riscv64_qemu_virt/mod.rs
unsafe extern "C" fn rust_entry(cpu_id: usize, dtb: usize) {
crate