KVM: arm64: Fix hVHE init on CPUs where HCR_EL2.E2H is not RES1
authorMarc Zyngier <maz@kernel.org>
Wed, 14 Jun 2023 15:51:29 +0000 (16:51 +0100)
committerOliver Upton <oliver.upton@linux.dev>
Thu, 15 Jun 2023 09:27:51 +0000 (09:27 +0000)
On CPUs where E2H is RES1, we very quickly set the scene for
running EL2 with a VHE configuration, as we do not have any other
choice.

However, CPUs that conform to the current writing of the architecture
start with E2H=0, and only later upgrade with E2H=1. This is all
good, but nothing there is actually reconfiguring EL2 to be able
to correctly run the kernel at EL1. Huhuh...

The "obvious" solution is not to just reinitialise the timer
controls like we do, but to really intitialise *everything*
unconditionally.

This requires a bit of surgery, and is a good opportunity to
remove the macro that messes with SPSR_EL2 in init_el2_state.

With that, hVHE now works correctly on my trusted A55 machine!

Reported-by: Oliver Upton <oliver.upton@linux.dev>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20230614155129.2697388-1-maz@kernel.org
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/include/asm/el2_setup.h
arch/arm64/kernel/head.S
arch/arm64/kvm/hyp/nvhe/hyp-init.S

index bba508f..5a353f9 100644 (file)
        __init_el2_nvhe_idregs
        __init_el2_cptr
        __init_el2_fgt
-       __init_el2_nvhe_prepare_eret
 .endm
 
 #ifndef __KVM_NVHE_HYPERVISOR__
index e92caeb..2395505 100644 (file)
@@ -603,6 +603,8 @@ SYM_INNER_LABEL(init_el2, SYM_L_LOCAL)
        msr     sctlr_el1, x1
        mov     x2, xzr
 2:
+       __init_el2_nvhe_prepare_eret
+
        mov     w0, #BOOT_CPU_MODE_EL2
        orr     x0, x0, x2
        eret
index f9ee10e..74ee77d 100644 (file)
@@ -83,9 +83,6 @@ SYM_CODE_END(__kvm_hyp_init)
  * x0: struct kvm_nvhe_init_params PA
  */
 SYM_CODE_START_LOCAL(___kvm_hyp_init)
-       ldr     x1, [x0, #NVHE_INIT_TPIDR_EL2]
-       msr     tpidr_el2, x1
-
        ldr     x1, [x0, #NVHE_INIT_STACK_HYP_VA]
        mov     sp, x1
 
@@ -99,11 +96,18 @@ SYM_CODE_START_LOCAL(___kvm_hyp_init)
        and     x2, x1, x2
        cbz     x2, 1f
 
-       mrs     x1, cnthctl_el2
-       and     x1, x1, #~(BIT(0) | BIT(1))
-       orr     x1, x1, #(BIT(10) | BIT(11))
-       msr     cnthctl_el2, x1
+       // hVHE: Replay the EL2 setup to account for the E2H bit
+       // TPIDR_EL2 is used to preserve x0 across the macro maze...
+       isb
+       msr     tpidr_el2, x0
+       init_el2_state
+       finalise_el2_state
+       mrs     x0, tpidr_el2
+
 1:
+       ldr     x1, [x0, #NVHE_INIT_TPIDR_EL2]
+       msr     tpidr_el2, x1
+
        ldr     x1, [x0, #NVHE_INIT_VTTBR]
        msr     vttbr_el2, x1
 
@@ -193,6 +197,7 @@ SYM_CODE_START_LOCAL(__kvm_hyp_init_cpu)
        /* Initialize EL2 CPU state to sane values. */
        init_el2_state                          // Clobbers x0..x2
        finalise_el2_state
+       __init_el2_nvhe_prepare_eret
 
        /* Enable MMU, set vectors and stack. */
        mov     x0, x28