1. 程式人生 > 其它 >linux aarch64 head.S el2_setup

linux aarch64 head.S el2_setup

el2_setup

檢查執行級別,如果是 EL1,簡單設定 SCTRL_EL1 後就退出。

如果是 EL2級別,就要作很多EL2 需要的設定,然後切換到EL1 級別,然後退出。

<1> 使用 SP_EL{1,2} 暫存器作為 SP 暫存器。

<2> 獲取當前執行 級別到 X0,然後和 EL2 級別進行比較。 如果不相等,說明當前執行級別是 EL1, 進入 <3>; 如果相等,說明當前是 EL2 級別, 進入 <4>

<3> 設定 SCTRL_EL1 暫存器的 大小端 模式後就退出,返回 值在 X0 中,為 #BOOT_CPU_MODE_EL1

 1 /*
 2  * If we're fortunate enough to boot at EL2, ensure that the world is
 3  * sane before dropping to EL1.
 4  *
 5  * Returns either BOOT_CPU_MODE_EL1 or BOOT_CPU_MODE_EL2 in w0 if
 6  * booted in EL1 or EL2 respectively.
 7  */
 8 SYM_FUNC_START(el2_setup)
 9     msr    SPsel, #1            // We want to use SP_EL{1,2}                                 (1)
10 mrs x0, CurrentEL 11 cmp x0, #CurrentEL_EL2 <2> 12 b.eq 1f 13 mov_q x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1) 14 msr sctlr_el1, x0 <3>
15 mov w0, #BOOT_CPU_MODE_EL1 // This cpu booted in EL1 16 isb 17 ret 18 19 1: mov_q x0, (SCTLR_EL2_RES1 | ENDIAN_SET_EL2) <4> 20 msr sctlr_el2, x0 21 22 這兒省略很多程式碼 23 24 25 /* Stage-2 translation */ 26 msr vttbr_el2, xzr 27 28 cbz x2, install_el2_stub <5> 29 30 mov w0, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2 31 isb 32 ret 33 34 SYM_INNER_LABEL(install_el2_stub, SYM_L_LOCAL) <6> 35 /* 36 * When VHE is not in use, early init of EL2 and EL1 needs to be 37 * done here. 38 * When VHE _is_ in use, EL1 will not be used in the host and 39 * requires no configuration, and all non-hyp-specific EL2 setup 40 * will be done via the _EL1 system register aliases in __cpu_setup. 41 */ 42 mov_q x0, (SCTLR_EL1_RES1 | ENDIAN_SET_EL1) 43 msr sctlr_el1, x0 44 45 /* Coprocessor traps. */ 46 mov x0, #0x33ff 47 msr cptr_el2, x0 // Disable copro. traps to EL2 48 49 /* SVE register access */ 50 mrs x1, id_aa64pfr0_el1 51 ubfx x1, x1, #ID_AA64PFR0_SVE_SHIFT, #4 52 cbz x1, 7f 53 54 bic x0, x0, #CPTR_EL2_TZ // Also disable SVE traps 55 msr cptr_el2, x0 // Disable copro. traps to EL2 56 isb 57 mov x1, #ZCR_ELx_LEN_MASK // SVE: Enable full vector 58 msr_s SYS_ZCR_EL2, x1 // length for EL1. 59 60 /* Hypervisor stub */ 61 7: adr_l x0, __hyp_stub_vectors 62 msr vbar_el2, x0 63 64 /* spsr */ 65 mov x0, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ 66 PSR_MODE_EL1h) <7> 67 msr spsr_el2, x0 68 msr elr_el2, lr 69 mov w0, #BOOT_CPU_MODE_EL2 // This CPU booted in EL2 70 eret <8> 71 SYM_FUNC_END(el2_setup)

<4> 設定SCTRL_EL2 暫存器,大小端

省略 很多 設定 EL2 模式下面需要設定的東西

<5> 呼叫 <6>處的函式install_el2_stub ,函式返回時,已經切換回 EL1 級別,然後返回 值在 X0 中,為 #BOOT_CPU_MODE_EL2

<6> 被 <5> 呼叫,裡面作了一些設定,我們只關心 <7> 這個地方,設定了 SPSR_EL2 暫存器,

<7> SPSR_EL2 暫存器裡面填入 PSR_MODE_EL1h, 偽裝成 從 EL1 級別 轉入了 EL2 級別。

<8> 執行 ERET,PSTATE 裝填 <7> 裡面設定的 SPSR_EL2 暫存器裡面的值,回到 EL1 級別。