summaryrefslogtreecommitdiffstats
path: root/arch/arm/kvm/hyp/entry.S
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2016-09-06 15:02:12 +0200
committerChristoffer Dall <christoffer.dall@linaro.org>2016-09-08 12:53:00 +0200
commitc39798f471259dacf56df6bfb2bd071dfe074486 (patch)
tree00f8627556aa1260b71828f69186c94be11eedc2 /arch/arm/kvm/hyp/entry.S
parentarm: KVM: Allow an exit code to be tagged with a Virtual Abort (diff)
downloadlinux-c39798f471259dacf56df6bfb2bd071dfe074486.tar.xz
linux-c39798f471259dacf56df6bfb2bd071dfe074486.zip
arm: KVM: Handle async aborts delivered while at HYP
Just like for arm64, we can handle asynchronous aborts being delivered at HYP while being caused by the guest. We use the exact same method to catch such an abort, and soldier on. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'arch/arm/kvm/hyp/entry.S')
-rw-r--r--arch/arm/kvm/hyp/entry.S31
1 files changed, 31 insertions, 0 deletions
diff --git a/arch/arm/kvm/hyp/entry.S b/arch/arm/kvm/hyp/entry.S
index 21c238871c9e..60783f3b57cc 100644
--- a/arch/arm/kvm/hyp/entry.S
+++ b/arch/arm/kvm/hyp/entry.S
@@ -18,6 +18,7 @@
#include <linux/linkage.h>
#include <asm/asm-offsets.h>
#include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
.arch_extension virt
@@ -63,6 +64,36 @@ ENTRY(__guest_exit)
ldr lr, [r0, #4]
mov r0, r1
+ mrs r1, SPSR
+ mrs r2, ELR_hyp
+ mrc p15, 4, r3, c5, c2, 0 @ HSR
+
+ /*
+ * Force loads and stores to complete before unmasking aborts
+ * and forcing the delivery of the exception. This gives us a
+ * single instruction window, which the handler will try to
+ * match.
+ */
+ dsb sy
+ cpsie a
+
+ .global abort_guest_exit_start
+abort_guest_exit_start:
+
+ isb
+
+ .global abort_guest_exit_end
+abort_guest_exit_end:
+
+ /*
+ * If we took an abort, r0[31] will be set, and cmp will set
+ * the N bit in PSTATE.
+ */
+ cmp r0, #0
+ msrmi SPSR_cxsf, r1
+ msrmi ELR_hyp, r2
+ mcrmi p15, 4, r3, c5, c2, 0 @ HSR
+
bx lr
ENDPROC(__guest_exit)