ARM: KVM: Add panic handling code
authorMarc Zyngier <marc.zyngier@arm.com>
Wed, 6 Jan 2016 09:12:42 +0000 (09:12 +0000)
committerMarc Zyngier <marc.zyngier@arm.com>
Mon, 29 Feb 2016 18:34:14 +0000 (18:34 +0000)
Instead of spinning forever, let's "properly" handle any unexpected
exception ("properly" meaning "print a spat on the console and die").

This has proved useful quite a few times...

Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org>
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
arch/arm/kvm/hyp/hyp-entry.S
arch/arm/kvm/hyp/switch.c

index 1b4aa02fd36415b6ea023f83330578b798513345..54a8d67ad980e4b7cc1b204f1dcf6bd6c840f09c 100644 (file)
@@ -75,15 +75,29 @@ __kvm_hyp_vector:
 
 .macro invalid_vector label, cause
        .align
-\label:        b       .
+\label:        mov     r0, #\cause
+       b       __hyp_panic
 .endm
 
-       invalid_vector  hyp_reset
-       invalid_vector  hyp_undef
-       invalid_vector  hyp_svc
-       invalid_vector  hyp_pabt
-       invalid_vector  hyp_dabt
-       invalid_vector  hyp_fiq
+       invalid_vector  hyp_reset       ARM_EXCEPTION_RESET
+       invalid_vector  hyp_undef       ARM_EXCEPTION_UNDEFINED
+       invalid_vector  hyp_svc         ARM_EXCEPTION_SOFTWARE
+       invalid_vector  hyp_pabt        ARM_EXCEPTION_PREF_ABORT
+       invalid_vector  hyp_dabt        ARM_EXCEPTION_DATA_ABORT
+       invalid_vector  hyp_fiq         ARM_EXCEPTION_FIQ
+
+ENTRY(__hyp_do_panic)
+       mrs     lr, cpsr
+       bic     lr, lr, #MODE_MASK
+       orr     lr, lr, #SVC_MODE
+THUMB( orr     lr, lr, #PSR_T_BIT      )
+       msr     spsr_cxsf, lr
+       ldr     lr, =panic
+       msr     ELR_hyp, lr
+       ldr     lr, =kvm_call_hyp
+       clrex
+       eret
+ENDPROC(__hyp_do_panic)
 
 hyp_hvc:
        /*
index 0dd0ba33b8a759c02c2a2e8d86c3def88fd3ed07..abbe90b5f2fffe142ba9e2ea83a38831dbca7325 100644 (file)
@@ -192,3 +192,41 @@ again:
 }
 
 __alias(__guest_run) int __weak __kvm_vcpu_run(struct kvm_vcpu *vcpu);
+
+static const char * const __hyp_panic_string[] = {
+       [ARM_EXCEPTION_RESET]      = "\nHYP panic: RST   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_UNDEFINED]  = "\nHYP panic: UNDEF PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_SOFTWARE]   = "\nHYP panic: SVC   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_PREF_ABORT] = "\nHYP panic: PABRT PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_DATA_ABORT] = "\nHYP panic: DABRT PC:%08x ADDR:%08x",
+       [ARM_EXCEPTION_IRQ]        = "\nHYP panic: IRQ   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_FIQ]        = "\nHYP panic: FIQ   PC:%08x CPSR:%08x",
+       [ARM_EXCEPTION_HVC]        = "\nHYP panic: HVC   PC:%08x CPSR:%08x",
+};
+
+void __hyp_text __noreturn __hyp_panic(int cause)
+{
+       u32 elr = read_special(ELR_hyp);
+       u32 val;
+
+       if (cause == ARM_EXCEPTION_DATA_ABORT)
+               val = read_sysreg(HDFAR);
+       else
+               val = read_special(SPSR);
+
+       if (read_sysreg(VTTBR)) {
+               struct kvm_vcpu *vcpu;
+               struct kvm_cpu_context *host_ctxt;
+
+               vcpu = (struct kvm_vcpu *)read_sysreg(HTPIDR);
+               host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context);
+               __deactivate_traps(vcpu);
+               __deactivate_vm(vcpu);
+               __sysreg_restore_state(host_ctxt);
+       }
+
+       /* Call panic for real */
+       __hyp_do_panic(__hyp_panic_string[cause], elr, val);
+
+       unreachable();
+}