diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-01-06 04:12:42 -0500 |
---|---|---|
committer | Marc Zyngier <marc.zyngier@arm.com> | 2016-02-29 13:34:14 -0500 |
commit | c36b6db5f3e4c1bd21659aee8e67226352d254ae (patch) | |
tree | f4a002e0cc3e0876a29724bdf25e534720a11eb5 /arch/arm/kvm | |
parent | bafc6c2a22553193d1d1ce83783b7faa0924158e (diff) |
ARM: KVM: Add panic handling code
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>
Diffstat (limited to 'arch/arm/kvm')
-rw-r--r-- | arch/arm/kvm/hyp/hyp-entry.S | 28 | ||||
-rw-r--r-- | arch/arm/kvm/hyp/switch.c | 38 |
2 files changed, 59 insertions, 7 deletions
diff --git a/arch/arm/kvm/hyp/hyp-entry.S b/arch/arm/kvm/hyp/hyp-entry.S index 1b4aa02fd364..54a8d67ad980 100644 --- a/arch/arm/kvm/hyp/hyp-entry.S +++ b/arch/arm/kvm/hyp/hyp-entry.S | |||
@@ -75,15 +75,29 @@ __kvm_hyp_vector: | |||
75 | 75 | ||
76 | .macro invalid_vector label, cause | 76 | .macro invalid_vector label, cause |
77 | .align | 77 | .align |
78 | \label: b . | 78 | \label: mov r0, #\cause |
79 | b __hyp_panic | ||
79 | .endm | 80 | .endm |
80 | 81 | ||
81 | invalid_vector hyp_reset | 82 | invalid_vector hyp_reset ARM_EXCEPTION_RESET |
82 | invalid_vector hyp_undef | 83 | invalid_vector hyp_undef ARM_EXCEPTION_UNDEFINED |
83 | invalid_vector hyp_svc | 84 | invalid_vector hyp_svc ARM_EXCEPTION_SOFTWARE |
84 | invalid_vector hyp_pabt | 85 | invalid_vector hyp_pabt ARM_EXCEPTION_PREF_ABORT |
85 | invalid_vector hyp_dabt | 86 | invalid_vector hyp_dabt ARM_EXCEPTION_DATA_ABORT |
86 | invalid_vector hyp_fiq | 87 | invalid_vector hyp_fiq ARM_EXCEPTION_FIQ |
88 | |||
89 | ENTRY(__hyp_do_panic) | ||
90 | mrs lr, cpsr | ||
91 | bic lr, lr, #MODE_MASK | ||
92 | orr lr, lr, #SVC_MODE | ||
93 | THUMB( orr lr, lr, #PSR_T_BIT ) | ||
94 | msr spsr_cxsf, lr | ||
95 | ldr lr, =panic | ||
96 | msr ELR_hyp, lr | ||
97 | ldr lr, =kvm_call_hyp | ||
98 | clrex | ||
99 | eret | ||
100 | ENDPROC(__hyp_do_panic) | ||
87 | 101 | ||
88 | hyp_hvc: | 102 | hyp_hvc: |
89 | /* | 103 | /* |
diff --git a/arch/arm/kvm/hyp/switch.c b/arch/arm/kvm/hyp/switch.c index 0dd0ba33b8a7..abbe90b5f2ff 100644 --- a/arch/arm/kvm/hyp/switch.c +++ b/arch/arm/kvm/hyp/switch.c | |||
@@ -192,3 +192,41 @@ again: | |||
192 | } | 192 | } |
193 | 193 | ||
194 | __alias(__guest_run) int __weak __kvm_vcpu_run(struct kvm_vcpu *vcpu); | 194 | __alias(__guest_run) int __weak __kvm_vcpu_run(struct kvm_vcpu *vcpu); |
195 | |||
196 | static const char * const __hyp_panic_string[] = { | ||
197 | [ARM_EXCEPTION_RESET] = "\nHYP panic: RST PC:%08x CPSR:%08x", | ||
198 | [ARM_EXCEPTION_UNDEFINED] = "\nHYP panic: UNDEF PC:%08x CPSR:%08x", | ||
199 | [ARM_EXCEPTION_SOFTWARE] = "\nHYP panic: SVC PC:%08x CPSR:%08x", | ||
200 | [ARM_EXCEPTION_PREF_ABORT] = "\nHYP panic: PABRT PC:%08x CPSR:%08x", | ||
201 | [ARM_EXCEPTION_DATA_ABORT] = "\nHYP panic: DABRT PC:%08x ADDR:%08x", | ||
202 | [ARM_EXCEPTION_IRQ] = "\nHYP panic: IRQ PC:%08x CPSR:%08x", | ||
203 | [ARM_EXCEPTION_FIQ] = "\nHYP panic: FIQ PC:%08x CPSR:%08x", | ||
204 | [ARM_EXCEPTION_HVC] = "\nHYP panic: HVC PC:%08x CPSR:%08x", | ||
205 | }; | ||
206 | |||
207 | void __hyp_text __noreturn __hyp_panic(int cause) | ||
208 | { | ||
209 | u32 elr = read_special(ELR_hyp); | ||
210 | u32 val; | ||
211 | |||
212 | if (cause == ARM_EXCEPTION_DATA_ABORT) | ||
213 | val = read_sysreg(HDFAR); | ||
214 | else | ||
215 | val = read_special(SPSR); | ||
216 | |||
217 | if (read_sysreg(VTTBR)) { | ||
218 | struct kvm_vcpu *vcpu; | ||
219 | struct kvm_cpu_context *host_ctxt; | ||
220 | |||
221 | vcpu = (struct kvm_vcpu *)read_sysreg(HTPIDR); | ||
222 | host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); | ||
223 | __deactivate_traps(vcpu); | ||
224 | __deactivate_vm(vcpu); | ||
225 | __sysreg_restore_state(host_ctxt); | ||
226 | } | ||
227 | |||
228 | /* Call panic for real */ | ||
229 | __hyp_do_panic(__hyp_panic_string[cause], elr, val); | ||
230 | |||
231 | unreachable(); | ||
232 | } | ||