summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kvm/svm/svm.c13
1 files changed, 13 insertions, 0 deletions
diff --git a/arch/x86/kvm/svm/svm.c b/arch/x86/kvm/svm/svm.c
index 2c511f86b79d..4bf0f5d7167f 100644
--- a/arch/x86/kvm/svm/svm.c
+++ b/arch/x86/kvm/svm/svm.c
@@ -217,6 +217,19 @@ int svm_set_efer(struct kvm_vcpu *vcpu, u64 efer)
if ((old_efer & EFER_SVME) != (efer & EFER_SVME)) {
if (!(efer & EFER_SVME)) {
+ /*
+ * Architecturally, clearing EFER.SVME while a guest is
+ * running yields undefined behavior, i.e. KVM can do
+ * literally anything. Force the vCPU back into L1 as
+ * that is the safest option for KVM, but synthesize a
+ * triple fault (for L1!) so that KVM at least doesn't
+ * run random L2 code in the context of L1. Do so if
+ * and only if the vCPU is actively running, e.g. to
+ * avoid positives if userspace is stuffing state.
+ */
+ if (is_guest_mode(vcpu) && vcpu->wants_to_run)
+ kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+
svm_leave_nested(vcpu);
/* #GP intercept is still needed for vmware backdoor */
if (!enable_vmware_backdoor)