KVM: arm64: Fix nVHE hyp panic host context restore
authorAndrew Scull <ascull@google.com>
Fri, 5 Mar 2021 18:52:49 +0000 (18:52 +0000)
committerPaolo Bonzini <pbonzini@redhat.com>
Sat, 6 Mar 2021 09:18:40 +0000 (04:18 -0500)
When panicking from the nVHE hyp and restoring the host context, x29 is
expected to hold a pointer to the host context. This wasn't being done
so fix it to make sure there's a valid pointer the host context being
used.

Rather than passing a boolean indicating whether or not the host context
should be restored, instead pass the pointer to the host context. NULL
is passed to indicate that no context should be restored.

Fixes: a2e102e20fd6 ("KVM: arm64: nVHE: Handle hyp panics")
Cc: stable@vger.kernel.org
Signed-off-by: Andrew Scull <ascull@google.com>
[maz: partial rewrite to fit 5.12-rc1]
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20210219122406.1337626-1-ascull@google.com
Message-Id: <20210305185254.3730990-4-maz@kernel.org>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
arch/arm64/include/asm/kvm_hyp.h
arch/arm64/kvm/hyp/nvhe/host.S
arch/arm64/kvm/hyp/nvhe/switch.c

index 385bd7dd3d390f1f7edc9a593f7a80e0bc3ac5e4..32ae676236b6b4dc85d101be97976fecc3f2fcf8 100644 (file)
@@ -102,7 +102,8 @@ bool kvm_host_psci_handler(struct kvm_cpu_context *host_ctxt);
 
 void __noreturn hyp_panic(void);
 #ifdef __KVM_NVHE_HYPERVISOR__
-void __noreturn __hyp_do_panic(bool restore_host, u64 spsr, u64 elr, u64 par);
+void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr,
+                              u64 elr, u64 par);
 #endif
 
 #endif /* __ARM64_KVM_HYP_H__ */
index 6585a7cbbc566212fab4e9409c47a5b96643d708..5d94584840ccfe06b0e11945eeed5bbba7252f50 100644 (file)
@@ -71,7 +71,8 @@ SYM_FUNC_START(__host_enter)
 SYM_FUNC_END(__host_enter)
 
 /*
- * void __noreturn __hyp_do_panic(bool restore_host, u64 spsr, u64 elr, u64 par);
+ * void __noreturn __hyp_do_panic(struct kvm_cpu_context *host_ctxt, u64 spsr,
+ *                               u64 elr, u64 par);
  */
 SYM_FUNC_START(__hyp_do_panic)
        /* Prepare and exit to the host's panic funciton. */
@@ -82,9 +83,11 @@ SYM_FUNC_START(__hyp_do_panic)
        hyp_kimg_va lr, x6
        msr     elr_el2, lr
 
-       /* Set the panic format string. Use the, now free, LR as scratch. */
-       ldr     lr, =__hyp_panic_string
-       hyp_kimg_va lr, x6
+       mov     x29, x0
+
+       /* Load the format string into x0 and arguments into x1-7 */
+       ldr     x0, =__hyp_panic_string
+       hyp_kimg_va x0, x6
 
        /* Load the format arguments into x1-7. */
        mov     x6, x3
@@ -94,9 +97,7 @@ SYM_FUNC_START(__hyp_do_panic)
        mrs     x5, hpfar_el2
 
        /* Enter the host, conditionally restoring the host context. */
-       cmp     x0, xzr
-       mov     x0, lr
-       b.eq    __host_enter_without_restoring
+       cbz     x29, __host_enter_without_restoring
        b       __host_enter_for_panic
 SYM_FUNC_END(__hyp_do_panic)
 
index 59aa1045fdafc2072f623c2d9db7f97172c5c83e..68ab6b4d5141401346bcf4247f05e159f0262a20 100644 (file)
@@ -266,7 +266,6 @@ void __noreturn hyp_panic(void)
        u64 spsr = read_sysreg_el2(SYS_SPSR);
        u64 elr = read_sysreg_el2(SYS_ELR);
        u64 par = read_sysreg_par();
-       bool restore_host = true;
        struct kvm_cpu_context *host_ctxt;
        struct kvm_vcpu *vcpu;
 
@@ -280,7 +279,7 @@ void __noreturn hyp_panic(void)
                __sysreg_restore_state_nvhe(host_ctxt);
        }
 
-       __hyp_do_panic(restore_host, spsr, elr, par);
+       __hyp_do_panic(host_ctxt, spsr, elr, par);
        unreachable();
 }