summaryrefslogtreecommitdiffstats
path: root/arch/arm64/kvm/hyp/nvhe/switch.c
diff options
context:
space:
mode:
authorAndrew Scull <ascull@google.com>2020-09-15 11:46:37 +0100
committerMarc Zyngier <maz@kernel.org>2020-09-15 18:39:03 +0100
commita2e102e20fd69ce26ea9fe7bd0df26d25dafff59 (patch)
tree113e3f9b2f50bc15bf23856fb3414c79c54555ed /arch/arm64/kvm/hyp/nvhe/switch.c
parent4e3393a969a0bdaae83263918b6824b2d08c3996 (diff)
downloadlinux-a2e102e20fd69ce26ea9fe7bd0df26d25dafff59.tar.bz2
KVM: arm64: nVHE: Handle hyp panics
Restore the host context when panicking from hyp to give the best chance of the panic being clean. The host requires that registers be preserved such as x18 for the shadow callstack. If the panic is caused by an exception from EL1, the host context is still valid so the panic can return straight back to the host. If the panic comes from EL2 then it's most likely that the hyp context is active and the host context needs to be restored. There are windows before and after the host context is saved and restored that restoration is attempted incorrectly and the panic won't be clean. Signed-off-by: Andrew Scull <ascull@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Link: https://lore.kernel.org/r/20200915104643.2543892-14-ascull@google.com
Diffstat (limited to 'arch/arm64/kvm/hyp/nvhe/switch.c')
-rw-r--r--arch/arm64/kvm/hyp/nvhe/switch.c18
1 files changed, 5 insertions, 13 deletions
diff --git a/arch/arm64/kvm/hyp/nvhe/switch.c b/arch/arm64/kvm/hyp/nvhe/switch.c
index c99945cda779..29febf9a93f2 100644
--- a/arch/arm64/kvm/hyp/nvhe/switch.c
+++ b/arch/arm64/kvm/hyp/nvhe/switch.c
@@ -242,6 +242,8 @@ int __kvm_vcpu_run(struct kvm_vcpu *vcpu)
if (system_uses_irq_prio_masking())
gic_write_pmr(GIC_PRIO_IRQOFF);
+ host_ctxt->__hyp_running_vcpu = NULL;
+
return exit_code;
}
@@ -250,31 +252,21 @@ void __noreturn hyp_panic(void)
u64 spsr = read_sysreg_el2(SYS_SPSR);
u64 elr = read_sysreg_el2(SYS_ELR);
u64 par = read_sysreg(par_el1);
+ bool restore_host = true;
struct kvm_cpu_context *host_ctxt;
struct kvm_vcpu *vcpu;
- unsigned long str_va;
host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt;
vcpu = host_ctxt->__hyp_running_vcpu;
- if (read_sysreg(vttbr_el2)) {
+ if (vcpu) {
__timer_disable_traps(vcpu);
__deactivate_traps(vcpu);
__load_host_stage2();
__sysreg_restore_state_nvhe(host_ctxt);
}
- /*
- * Force the panic string to be loaded from the literal pool,
- * making sure it is a kernel address and not a PC-relative
- * reference.
- */
- asm volatile("ldr %0, =%1" : "=r" (str_va) : "S" (__hyp_panic_string));
-
- __hyp_do_panic(str_va,
- spsr, elr,
- read_sysreg(esr_el2), read_sysreg_el2(SYS_FAR),
- read_sysreg(hpfar_el2), par, vcpu);
+ __hyp_do_panic(restore_host, spsr, elr, par);
unreachable();
}