linux aarch64 head.S enable_mmu primary_switch primary_switched

 

enable_mmu

输入

 X0  SCTRL_EL1  的值,见   setup_cpu 的返回值。

X1 TTBT1_EL1 的值, 见 primary_switch  964 行设置 x1

 

以下内容来自   https://blog.csdn.net/lgjjeff/article/details/93376624

797 ~ 800  读取ID_AA64MMFR0_EL1寄存器的值,该寄存器的定义如下。bit [31:20]表示当前支持的地址转换粒度(即页的大小),此处读取该寄存器就是为了校验寄存器中的值是否支持内核中配置的页表size。

将提取的位与内核中配置的页大小值比较

若它们不相等,说明内核配置页大小不被支持,则跳到__no_granule_support 函数处

801  该函数用于将启动状态值0赋值给变量__early_cpu_boot_status,以给后续代码使用
802 ~ 805 将idmap页表的PGD基地址idmap_pg_dir写入寄存器ttbr0_el1中。将其存入ttbr0_el1,保证内核 MMU 刚启动VA 转换时,预取的地址和指令依然有效,可以被执行。

806 ~ 807 将swapper页表的PGD基地址swapper_pg_dir写入寄存器ttbr1_el1中
809  设置sctlr_el1寄存器,其中x0在__cpu_setup函数中通过mov_q x0, SCTLR_EL1_SET设置,

          SCTLR_EL1_SET定义在arch/arm64/include/asm/sysreg.h中,具体内容可以参考kernel源码。该寄存器是系统控制寄存器,其定义如下。其中第0位M即是用来使能MMU的,因此在这条命令执行完成后MMU即被使能。

 784/*
 785 * Enable the MMU.
 786 *
 787 *  x0  = SCTLR_EL1 value for turning on the MMU.
 788 *  x1  = TTBR1_EL1 value
 789 *
 790 * Returns to the caller via x30/lr. This requires the caller to be covered
 791 * by the .idmap.text section.
 792 *
 793 * Checks if the selected granule size is supported by the CPU.
 794 * If it isn't, park the CPU
 795 */
 796SYM_FUNC_START(__enable_mmu)
 797        mrs     x2, ID_AA64MMFR0_EL1
 798        ubfx    x2, x2, #ID_AA64MMFR0_TGRAN_SHIFT, 4
 799        cmp     x2, #ID_AA64MMFR0_TGRAN_SUPPORTED
 800        b.ne    __no_granule_support
 801        update_early_cpu_boot_status 0, x2, x3
 802        adrp    x2, idmap_pg_dir
 803        phys_to_ttbr x1, x1
 804        phys_to_ttbr x2, x2
 805        msr     ttbr0_el1, x2                   // load TTBR0
 806        offset_ttbr1 x1, x3
 807        msr     ttbr1_el1, x1                   // load TTBR1
 808        isb
 809        msr     sctlr_el1, x0
 810        isb
 811        /*
 812         * Invalidate the local I-cache so that any instructions fetched
 813         * speculatively from the PoC are discarded, since they may have
 814         * been dynamically patched at the PoU.
 815         */
 816        ic      iallu
 817        dsb     nsh
 818        isb
 819        ret
 820SYM_FUNC_END(__enable_mmu)

 

primary_switch

下面是 CONFIG_RANDOMIZE_BASE   CONFIG_RELOCATABLE  都没有 配置时的场景。

963 ~ 965 准备和调用 enable_mmu

998 ~ 1000 调用 primary_switched

 958SYM_FUNC_START_LOCAL(__primary_switch)
 
 963
 964        adrp    x1, init_pg_dir
 965        bl      __enable_mmu
 
 998        ldr     x8, =__primary_switched
 999        adrp    x0, __PHYS_OFFSET
1000        br      x8

1001SYM_FUNC_END(__primary_switch)

 

primary_switched

以下来自  https://blog.csdn.net/lgjjeff/article/details/93376624

 

输入 x0 __PHYS_OFFSET

417 ~ 420  代码用于设置当前栈指针和el0的栈指针
426  ~ 428 设置异常向量表
430 将lr地址入栈
431 保存栈帧指针
437 将dtb地址从x21寄存器保存到__fdt_pointer变量中,以给后续代码使用。该值是在head.s开始时由x0寄存器暂存到x21寄存器的
439 ~ 441 计算kernel image起始地址相对于内存起始地址的偏移,并将其存放到kimage_voffset变量中
443 ~ 449 清空bss段的内容
465 ~ 467 更新栈指针,并清除lr和fp指针寄存器的值,为跳转到start_kernel做准备
468 跳转到C语言函数start_kernel

 411/*
 412 * The following fragment of code is executed with the MMU enabled.
 413 *
 414 *   x0 = __PHYS_OFFSET
 415 */
 416SYM_FUNC_START_LOCAL(__primary_switched)
 417        adrp    x4, init_thread_union
 418        add     sp, x4, #THREAD_SIZE
 419        adr_l   x5, init_task
 420        msr     sp_el0, x5                      // Save thread_info
 421
 422#ifdef CONFIG_ARM64_PTR_AUTH
 423        __ptrauth_keys_init_cpu x5, x6, x7, x8
 424#endif
 425
 426        adr_l   x8, vectors                     // load VBAR_EL1 with virtual
 427        msr     vbar_el1, x8                    // vector table address
 428        isb
 429
 430        stp     xzr, x30, [sp, #-16]!
 431        mov     x29, sp
 432
 433#ifdef CONFIG_SHADOW_CALL_STACK
 434        adr_l   scs_sp, init_shadow_call_stack  // Set shadow call stack
 435#endif
 436
 437        str_l   x21, __fdt_pointer, x5          // Save FDT pointer
 438
 439        ldr_l   x4, kimage_vaddr                // Save the offset between
 440        sub     x4, x4, x0                      // the kernel virtual and
 441        str_l   x4, kimage_voffset, x5          // physical mappings
 442
 443        // Clear BSS
 444        adr_l   x0, __bss_start
 445        mov     x1, xzr
 446        adr_l   x2, __bss_stop
 447        sub     x2, x2, x0
 448        bl      __pi_memset
 449        dsb     ishst                           // Make zero page visible to PTW
 450
 451#ifdef CONFIG_KASAN
 452        bl      kasan_early_init
 453#endif
465        add     sp, sp, #16
 466        mov     x29, #0
 467        mov     x30, #0
 468        b       start_kernel
 469SYM_FUNC_END(__primary_switched)

 

posted @ 2022-03-20 18:59  张志伟122  阅读(519)  评论(0编辑  收藏  举报