Skip to content

启动部分汇编代码解析

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