arm64: hyp/kvm: Make hyp-stub reject kvm_call_hyp()
authorJames Morse <james.morse@arm.com>
Wed, 27 Apr 2016 16:47:04 +0000 (17:47 +0100)
committerWill Deacon <will.deacon@arm.com>
Thu, 28 Apr 2016 11:05:46 +0000 (12:05 +0100)
A later patch implements kvm_arch_hardware_disable(), to remove kvm
from el2, and re-instate the hyp-stub.

This can happen while guests are running, particularly when kvm_reboot()
calls kvm_arch_hardware_disable() on each cpu. This can interrupt a guest,
remove kvm, then allow the guest to be scheduled again. This causes
kvm_call_hyp() to be run against the hyp-stub.

Change the hyp-stub to return a new exception type when this happens,
and add code to kvm's handle_exit() to tell userspace we failed to
enter the guest.

Signed-off-by: James Morse <james.morse@arm.com>
Acked-by: Marc Zyngier <marc.zyngier@arm.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
arch/arm64/include/asm/kvm_asm.h
arch/arm64/kernel/hyp-stub.S
arch/arm64/kvm/handle_exit.c

index eb7490d232a0f39328c42fd646de8b5548feb178..dbfbc5fb5d3513159f00374decb2dbde2e032523 100644 (file)
@@ -22,6 +22,8 @@
 
 #define ARM_EXCEPTION_IRQ        0
 #define ARM_EXCEPTION_TRAP       1
+/* The hyp-stub will return this for any kvm_call_hyp() call */
+#define ARM_EXCEPTION_HYP_GONE   2
 
 #define KVM_ARM64_DEBUG_DIRTY_SHIFT    0
 #define KVM_ARM64_DEBUG_DIRTY          (1 << KVM_ARM64_DEBUG_DIRTY_SHIFT)
index 894fb40fb378b5fcd79f66597a4bfe6c5eeff911..8727f44907725445efd25735b9638672a2599cb0 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <asm/assembler.h>
 #include <asm/kvm_arm.h>
+#include <asm/kvm_asm.h>
 #include <asm/ptrace.h>
 #include <asm/virt.h>
 
@@ -70,8 +71,8 @@ el1_sync:
        msr     vbar_el2, x1
        b       9f
 
-       /* Unrecognised call type */
-2:     mov     x0, xzr
+       /* Someone called kvm_call_hyp() against the hyp-stub... */
+2:     mov     x0, #ARM_EXCEPTION_HYP_GONE
 
 9:     eret
 ENDPROC(el1_sync)
index eba89e42f0ed377f76588f2821d2b4b224d0280e..3246c4aba5b1161e7b45c9f896acacdb1ec52577 100644 (file)
@@ -186,6 +186,13 @@ int handle_exit(struct kvm_vcpu *vcpu, struct kvm_run *run,
                exit_handler = kvm_get_exit_handler(vcpu);
 
                return exit_handler(vcpu, run);
+       case ARM_EXCEPTION_HYP_GONE:
+               /*
+                * EL2 has been reset to the hyp-stub. This happens when a guest
+                * is pre-empted by kvm_reboot()'s shutdown call.
+                */
+               run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+               return 0;
        default:
                kvm_pr_unimpl("Unsupported exception type: %d",
                              exception_index);