diff options
-rw-r--r-- | arch/arm64/kvm/hyp/hyp-entry.S | 11 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/hyp.h | 1 | ||||
-rw-r--r-- | arch/arm64/kvm/hyp/switch.c | 30 |
3 files changed, 41 insertions, 1 deletions
diff --git a/arch/arm64/kvm/hyp/hyp-entry.S b/arch/arm64/kvm/hyp/hyp-entry.S index 818731a5f61c..8e58a3ba6139 100644 --- a/arch/arm64/kvm/hyp/hyp-entry.S +++ b/arch/arm64/kvm/hyp/hyp-entry.S | |||
@@ -155,7 +155,16 @@ el1_irq: | |||
155 | mov x1, #ARM_EXCEPTION_IRQ | 155 | mov x1, #ARM_EXCEPTION_IRQ |
156 | b __guest_exit | 156 | b __guest_exit |
157 | 157 | ||
158 | .macro invalid_vector label, target = __kvm_hyp_panic | 158 | ENTRY(__hyp_do_panic) |
159 | mov lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\ | ||
160 | PSR_MODE_EL1h) | ||
161 | msr spsr_el2, lr | ||
162 | ldr lr, =panic | ||
163 | msr elr_el2, lr | ||
164 | eret | ||
165 | ENDPROC(__hyp_do_panic) | ||
166 | |||
167 | .macro invalid_vector label, target = __hyp_panic | ||
159 | .align 2 | 168 | .align 2 |
160 | \label: | 169 | \label: |
161 | b \target | 170 | b \target |
diff --git a/arch/arm64/kvm/hyp/hyp.h b/arch/arm64/kvm/hyp/hyp.h index 70d4f696c862..fb275178b6af 100644 --- a/arch/arm64/kvm/hyp/hyp.h +++ b/arch/arm64/kvm/hyp/hyp.h | |||
@@ -84,6 +84,7 @@ static inline bool __fpsimd_enabled(void) | |||
84 | } | 84 | } |
85 | 85 | ||
86 | u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt); | 86 | u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt); |
87 | void __noreturn __hyp_do_panic(unsigned long, ...); | ||
87 | 88 | ||
88 | #endif /* __ARM64_KVM_HYP_H__ */ | 89 | #endif /* __ARM64_KVM_HYP_H__ */ |
89 | 90 | ||
diff --git a/arch/arm64/kvm/hyp/switch.c b/arch/arm64/kvm/hyp/switch.c index 608155f5b856..b012870a92e7 100644 --- a/arch/arm64/kvm/hyp/switch.c +++ b/arch/arm64/kvm/hyp/switch.c | |||
@@ -141,3 +141,33 @@ int __hyp_text __guest_run(struct kvm_vcpu *vcpu) | |||
141 | 141 | ||
142 | return exit_code; | 142 | return exit_code; |
143 | } | 143 | } |
144 | |||
145 | static const char __hyp_panic_string[] = "HYP panic:\nPS:%08llx PC:%016llx ESR:%08llx\nFAR:%016llx HPFAR:%016llx PAR:%016llx\nVCPU:%p\n"; | ||
146 | |||
147 | void __hyp_text __noreturn __hyp_panic(void) | ||
148 | { | ||
149 | unsigned long str_va = (unsigned long)__hyp_panic_string; | ||
150 | u64 spsr = read_sysreg(spsr_el2); | ||
151 | u64 elr = read_sysreg(elr_el2); | ||
152 | u64 par = read_sysreg(par_el1); | ||
153 | |||
154 | if (read_sysreg(vttbr_el2)) { | ||
155 | struct kvm_vcpu *vcpu; | ||
156 | struct kvm_cpu_context *host_ctxt; | ||
157 | |||
158 | vcpu = (struct kvm_vcpu *)read_sysreg(tpidr_el2); | ||
159 | host_ctxt = kern_hyp_va(vcpu->arch.host_cpu_context); | ||
160 | __deactivate_traps(vcpu); | ||
161 | __deactivate_vm(vcpu); | ||
162 | __sysreg_restore_state(host_ctxt); | ||
163 | } | ||
164 | |||
165 | /* Call panic for real */ | ||
166 | __hyp_do_panic(hyp_kern_va(str_va), | ||
167 | spsr, elr, | ||
168 | read_sysreg(esr_el2), read_sysreg(far_el2), | ||
169 | read_sysreg(hpfar_el2), par, | ||
170 | (void *)read_sysreg(tpidr_el2)); | ||
171 | |||
172 | unreachable(); | ||
173 | } | ||