1. 程式人生 > 其它 >linux aarch64 head.S enable_mmu primary_switch primary_switched

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)