aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kvm
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2015-11-17 09:07:45 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2016-02-29 13:34:18 -0500
commit253dcbd39adb00890f3c350230ae310fcfeeb760 (patch)
tree58863536a7c23df4df654d5fcf11d14656dec8a4 /arch/arm64/kvm
parent77cb2d91333312d7426055d4369f3821e5e8bda0 (diff)
arm64: KVM: VHE: Add alternative panic handling
As the kernel fully runs in HYP when VHE is enabled, we can directly branch to the kernel's panic() implementation, and not perform an exception return. Add the alternative code to deal with this. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm64/kvm')
-rw-r--r--arch/arm64/kvm/hyp/switch.c35
1 files changed, 27 insertions, 8 deletions
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c
index e609942ef79c..731f0a2ffee0 100644
--- a/arch/arm64/kvm/hyp/switch.c
+++ b/arch/arm64/kvm/hyp/switch.c
@@ -210,11 +210,34 @@ __alias(__guest_run) int __kvm_vcpu_run(struct kvm_vcpu *vcpu);
210 210
211static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; 211static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n";
212 212
213void __hyp_text __noreturn __hyp_panic(void) 213static void __hyp_text __hyp_call_panic_nvhe(u64 spsr, u64 elr, u64 par)
214{ 214{
215 unsigned long str_va = (unsigned long)__hyp_panic_string; 215 unsigned long str_va = (unsigned long)__hyp_panic_string;
216 u64 spsr = read_sysreg(spsr_el2); 216
217 u64 elr = read_sysreg(elr_el2); 217 __hyp_do_panic(hyp_kern_va(str_va),
218 spsr, elr,
219 read_sysreg(esr_el2), read_sysreg_el2(far),
220 read_sysreg(hpfar_el2), par,
221 (void *)read_sysreg(tpidr_el2));
222}
223
224static void __hyp_text __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par)
225{
226 panic(__hyp_panic_string,
227 spsr, elr,
228 read_sysreg_el2(esr), read_sysreg_el2(far),
229 read_sysreg(hpfar_el2), par,
230 (void *)read_sysreg(tpidr_el2));
231}
232
233static hyp_alternate_select(__hyp_call_panic,
234 __hyp_call_panic_nvhe, __hyp_call_panic_vhe,
235 ARM64_HAS_VIRT_HOST_EXTN);
236
237void __hyp_text __noreturn __hyp_panic(void)
238{
239 u64 spsr = read_sysreg_el2(spsr);
240 u64 elr = read_sysreg_el2(elr);
218 u64 par = read_sysreg(par_el1); 241 u64 par = read_sysreg(par_el1);
219 242
220 if (read_sysreg(vttbr_el2)) { 243 if (read_sysreg(vttbr_el2)) {
@@ -229,11 +252,7 @@ void __hyp_text __noreturn __hyp_panic(void)
229 } 252 }
230 253
231 /* Call panic for real */ 254 /* Call panic for real */
232 __hyp_do_panic(hyp_kern_va(str_va), 255 __hyp_call_panic()(spsr, elr, par);
233 spsr, elr,
234 read_sysreg(esr_el2), read_sysreg(far_el2),
235 read_sysreg(hpfar_el2), par,
236 (void *)read_sysreg(tpidr_el2));
237 256
238 unreachable(); 257 unreachable();
239} 258}