Kernel启动流程源码解析 1 head.S

  1. bootloader在跳转到kernel前,需要确保如下设置:
MMU = off, D-cache = off, I-cache = on or off
x0 = physical address to the FDT blob

  1. kernel的入口在arch\arm64\kernel\head.S中。

b     stext // 跳转到stext


  1.  stext。

ENTRY(stext)
    mov    x21, x0                // x21=FDT 将x0的值(device tree的地址)暂存在x21寄存器中
    bl    el2_setup            // Drop to EL1, w20=cpu_boot_mode 从EL2或者non-secure EL1回退到EL1;bl 带返回的跳转指令
// 补充知识:ARMv8-a 划分了4 个Exception level,EL0归属于non-privilege level,EL1/2/3属于privilege level。Application位于特权等级最低的EL0,Guest OS(Linux kernel、window等)位于EL1,提供虚拟化支持的Hypervisor位于EL2(可选),提供Security支持的Seurity Monitor位于EL3(可选)。EL0,EL1,EL2,El3之前的切换,分别通过指令svc,hvc,smc。

    bl    __calc_phys_offset        // x24=PHYS_OFFSET, x28=PHYS_OFFSET-PAGE_OFFSET 计算出起始物理地址并保存在x24中
    bl    set_cpu_boot_mode_flag // 将cpu启动的模式保存到全局变量__boot_cpu_mode中
    mrs    x22, midr_el1            // Move from State register to Register,x22=cpuid 获取当前cpu id
    mov    x0, x22  // 将当前cpuid作为参数传递给lookup_processor_type

    bl    lookup_processor_type // 查看cpu类型
    mov    x23, x0                // x23=current cpu_table
    /*
     * __error_p may end up out of range for cbz if text areas are
     * aligned up to section sizes.
     */
    cbnz    x23, 1f                // invalid processor (x23=0)? // x23非0,跳转到标号1处
    b    __error_p
1:
    bl    __vet_fdt // 检查device tree的合法性
    bl    __create_page_tables        // x25=TTBR0, x26=TTBR1 // 创建临时页表
    /*
     * The following calls CPU specific code in a position independent
     * manner. See arch/arm64/mm/proc.S for details. x23 = base of
     * cpu_info structure selected by lookup_processor_type above.
     * On return, the CPU will be ready for the MMU to be turned on and
     * the TCR will have been set.
     */
    ldr    x27, __switch_data        // address to jump to after // 由函数__enable_mmu中调用
                        // MMU has been enabled
    adrp    lr, __enable_mmu        // return (PIC) address //  // adr伪指令用于将一个地址加载到寄存器,取到的是相对于PC寄存器的地址,由于此刻PC寄存器中值是物理地址,所以lr中取到的即是标号 __enable_mmu 处的物理地址(页对齐)。
    add    lr, lr, #:lo12:__enable_mmu // 加上 __enable_mmu的页内偏移
    ldr    x12, [x23, #CPU_INFO_SETUP] // x23保存的是 cpu_table, CPU_INFO_SETUP =  offsetof(struct cpu_info, cpu_setup),那么x12就等于 __cpu_setup
    add    x12, x12, x28            // __virt_to_phys // 转化成物理地址
    br    x12                // initialise processor // 跳转到 __cpu_setup继续执行,由于lr等于 __enable_mmu,因此从 __cpu_setup时,会跳转到 __enable_mmu继续执行
ENDPROC(stext)


  1. el2_setup。

/*
 * If we're fortunate enough to boot at EL2, ensure that the world is
 * sane before dropping to EL1.
 *
 * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in x20 if
 * booted in EL1 or EL2 respectively.
 */
ENTRY(el2_setup)
    mrs    x0, CurrentEL // 当前的exception level保存在PSTATE中,程序可以通过MRS或者MSR来访问PSTATE,CurrentEL就是获取PSTATE中current exception level域的特殊寄存器。
     // 补充知识:MRS Move to Register from State register, MSR Move from State register to Register, 分别用于对状态寄存器(AARCH64对应PSTATE,AARCH32对应CPSP)进行读写。
    cmp    x0, #CurrentEL_EL2 // #define CurrentEL_EL2        (2 << 2)
    b.ne    1f // 当cpu不处于EL2时跳转到标号1
    mrs    x0, sctlr_el2 // 读取EL2状态的系统控制寄存器,该寄存器可以控制整个系统的行为
CPU_BE(    orr    x0, x0, #(1 << 25)    )    // Set the EE bit for EL2 // 大端置位EE位  
CPU_LE(    bic    x0, x0, #(1 << 25)    )    // Clear the EE bit for EL2  // 小端清除EE位
    msr    sctlr_el2, x0 // 写入 EL2状态的系统控制寄存器
    b    2f
1:    mrs    x0, sctlr_el1  // 读取EL1状态的系统控制寄存器
CPU_BE(    orr    x0, x0, #(3 << 24)    )    // Set the EE and E0E bits for EL1 // 大端置位EE位和EOE位
CPU_LE(    bic    x0, x0, #(3 << 24)    )    // Clear the EE and E0E bits for EL1 // 小端清除EE位和EOE位
    msr    sctlr_el1, x0  // 写入 EL1状态的系统控制寄存器
    mov    w20, #BOOT_CPU_MODE_EL1        // This cpu booted in EL1 // #define BOOT_CPU_MODE_EL1    (0xe11) // 将 BOOT_CPU_MODE_EL1保存到通用寄存器w20
    isb // 指令同步屏障,确保之前的指令已执行完成
    ret // 当cpu处于EL1,在这里就返回了

    /* Hyp configuration. */
2:    mov    x0, #(1 << 31)            // 64-bit EL1
    msr    hcr_el2, x0 // Hypervisor   Configuration   Register // Controls virtualization settings and trapping of exceptions to   EL2
  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值