-
Notifications
You must be signed in to change notification settings - Fork 19
启动部分汇编代码解析
Kangxu Liu edited this page Jun 26, 2016
·
3 revisions
作为整个内核中最先被执行的代码,启动部分的汇编代码起到了配置 CPU、建立 C 语言环境、建立页表及初始化 MMU、从 EL2 跳转至 EL1 的作用。这些代码存放在 init.s 中。
首先说明一下内核加载的地址。当把内核镜像命名为 kernel8.img 后,内核将自动被加载到内存 0x8 0000 的位置上。虽然如此,由于必须将操作系统内核与用户程序区分开,我们还是希望最终把内核挂载到高地址上。而在 MMU 启动之前,我们又必须使用低地址寻址。因此,我们的内核镜像分为两部分:一部分用于初始化 MMU,使用物理地址寻址;另一部分是内核的其他部分,使用虚拟地址寻址。首先是初始化部分的简略说明:
由于树莓派 3 的处理器是多核心的,而我们暂时用不到那么多核心,因此我们只在一个核心中运行后续代码,并在其他的核心上运行空循环。通过读取 MPIDR_EL1 寄存器的相关内容,我们能够分辨正在运行的核心:
skip:
mrs x0,mpidr_el1
mov x1,#0xC1000000
bic x0,x0,x1
cbz x0,master
b hang
hang:
b hang
接下来我们设置栈指针,为 C 语言提供必要的运行环境。只有主核心才能够执行接下来的代码:
master:
ldr x0, =0x1000000
mov sp, x0 // set el2 sp
在 C 语言环境搭建好后,我们就可以运行 C 语言代码了。首先要完成的工作就是建立页表,只有虚拟内存系统建立完成,操作系统才能正常运行。通过调用 mm/mm_init.c 中的函数来建立页表:
bl vm_init
下一项工作是跳转到 EL1。其余的操作系统代码都将在 EL1 下完成:
jump_to_el1:
mrs x0, currentel // check if already in el1
cmp x0, #4
beq 1f
ldr x0, =0xffffff0001000000
msr sp_el1, x0 // init the stack of el1
// disable coprocessor traps
mov x0, #0x33ff
msr cptr_el2, x0 // disable coprocessor traps to el2
msr hstr_el2, xzr // disable coprocessor traps to el2
mov x0, #3 << 20
msr cpacr_el1, x0 // enable fp/simd at el1
// initialize hcr_el2
mov x0, #(1 << 31)
msr hcr_el2, x0 // set el1 to 64 bit
mov x0, #0x0800
movk x0, #0x30d0, lsl #16
msr sctlr_el1, x0
// return to the el1_sp1 mode from el2
mov x0, #0x5
msr spsr_el2, x0 // el1_sp1 with DAIF = 0
adr x0, 1f
msr elr_el2, x0
eret
在此之后,系统将打开指令缓存,设置异常处理向量:
1:
mrs x0, sctlr_el1
orr x0, x0, #(1 << 12)
msr sctlr_el1, x0 // enable instruction cache
ldr x0, =vectors
msr vbar_el1, x0 // init exception vector table
最后是 MMU 的启动。MMU 启动以后,程序将控制权交给由 C 语言完成的 main 函数,由它继续接下来的初始化。操作系统接下来的代码都会使用高地址寻址。
el1_mmu_activate:
ldr x0, =0x04cc
msr mair_el1, x0
isb
ldr x1, =0x01000000
msr ttbr0_el1, x1
msr ttbr1_el1, x1
isb
mrs x2, tcr_el1
ldr x3, =0x70040ffbf
bic x2, x2, x3
ldr x3, =0x2bf183f18
orr x2, x2, x3
msr tcr_el1, x2
isb
ldr x5, =main
mrs x3, sctlr_el1
ldr x4, =0x80000
bic x3, x3, x4
ldr x4, =0x1005
orr x3, x3, x4
msr sctlr_el1, x3
isb
br x5