[Devel] [PATCH RHEL9 COMMIT] ms/KVM: VMX: Reset eVMCS controls in VP assist page during hardware disabling
Konstantin Khorenko
khorenko at virtuozzo.com
Wed Nov 1 16:42:52 MSK 2023
The commit is pushed to "branch-rh9-5.14.0-284.25.1.vz9.30.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh9-5.14.0-284.25.1.vz9.30.6
------>
commit f89a8ad38faf4eec2e6cd0888bb42cdde1dd676e
Author: Maxim Levitsky <mlevitsk at redhat.com>
Date: Tue Apr 25 08:56:47 2023 +0300
ms/KVM: VMX: Reset eVMCS controls in VP assist page during hardware disabling
Bugzilla: https://bugzilla.redhat.com/show_bug.cgi?id=2177720
commit 2916b70fc342719f570640de07251b7f91feebdb
Author: Sean Christopherson <seanjc at google.com>
Date: Wed Nov 30 23:08:54 2022 +0000
KVM: VMX: Reset eVMCS controls in VP assist page during hardware disabling
Reset the eVMCS controls in the per-CPU VP assist page during hardware
disabling instead of waiting until kvm-intel's module exit. The controls
are activated if and only if KVM creates a VM, i.e. don't need to be
reset if hardware is never enabled.
Doing the reset during hardware disabling will naturally fix a potential
NULL pointer deref bug once KVM disables CPU hotplug while enabling and
disabling hardware (which is necessary to fix a variety of bugs). If the
kernel is running as the root partition, the VP assist page is unmapped
during CPU hot unplug, and so KVM's clearing of the eVMCS controls needs
to occur with CPU hot(un)plug disabled, otherwise KVM could attempt to
write to a CPU's VP assist page after it's unmapped.
Reported-by: Vitaly Kuznetsov <vkuznets at redhat.com>
Signed-off-by: Sean Christopherson <seanjc at google.com>
Reviewed-by: Vitaly Kuznetsov <vkuznets at redhat.com>
Message-Id: <20221130230934.1014142-11-seanjc at google.com>
Signed-off-by: Paolo Bonzini <pbonzini at redhat.com>
Signed-off-by: Maxim Levitsky <mlevitsk at redhat.com>
(cherry picked from CentOS 9 Stream commit 9828ea8dc4fb)
https://pmc.acronis.work/browse/VSTOR-76102
Signed-off-by: Konstantin Khorenko <khorenko at virtuozzo.com>
Feature: fix ms/KVM
---
arch/x86/kvm/vmx/vmx.c | 50 ++++++++++++++++++++++++++++++--------------------
1 file changed, 30 insertions(+), 20 deletions(-)
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 2f792d84226c..e0c507fcd09e 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -552,6 +552,33 @@ static int hv_enable_direct_tlbflush(struct kvm_vcpu *vcpu)
return 0;
}
+static void hv_reset_evmcs(void)
+{
+ struct hv_vp_assist_page *vp_ap;
+
+ if (!static_branch_unlikely(&enable_evmcs))
+ return;
+
+ /*
+ * KVM should enable eVMCS if and only if all CPUs have a VP assist
+ * page, and should reject CPU onlining if eVMCS is enabled the CPU
+ * doesn't have a VP assist page allocated.
+ */
+ vp_ap = hv_get_vp_assist_page(smp_processor_id());
+ if (WARN_ON_ONCE(!vp_ap))
+ return;
+
+ /*
+ * Reset everything to support using non-enlightened VMCS access later
+ * (e.g. when we reload the module with enlightened_vmcs=0)
+ */
+ vp_ap->nested_control.features.directhypercall = 0;
+ vp_ap->current_nested_vmcs = 0;
+ vp_ap->enlighten_vmentry = 0;
+}
+
+#else /* IS_ENABLED(CONFIG_HYPERV) */
+static void hv_reset_evmcs(void) {}
#endif /* IS_ENABLED(CONFIG_HYPERV) */
/*
@@ -2483,6 +2510,8 @@ static void vmx_hardware_disable(void)
if (cpu_vmxoff())
kvm_spurious_fault();
+ hv_reset_evmcs();
+
intel_pt_handle_vmx(0);
}
@@ -8410,27 +8439,8 @@ static void vmx_exit(void)
kvm_exit();
#if IS_ENABLED(CONFIG_HYPERV)
- if (static_branch_unlikely(&enable_evmcs)) {
- int cpu;
- struct hv_vp_assist_page *vp_ap;
- /*
- * Reset everything to support using non-enlightened VMCS
- * access later (e.g. when we reload the module with
- * enlightened_vmcs=0)
- */
- for_each_online_cpu(cpu) {
- vp_ap = hv_get_vp_assist_page(cpu);
-
- if (!vp_ap)
- continue;
-
- vp_ap->nested_control.features.directhypercall = 0;
- vp_ap->current_nested_vmcs = 0;
- vp_ap->enlighten_vmentry = 0;
- }
-
+ if (static_branch_unlikely(&enable_evmcs))
static_branch_disable(&enable_evmcs);
- }
#endif
vmx_cleanup_l1d_flush();
More information about the Devel
mailing list