1 From a4443267800af240072280c44521caab61924e55 Mon Sep 17 00:00:00 2001
2 From: Vitaly Kuznetsov <vkuznets@redhat.com>
3 Date: Thu, 20 Feb 2020 18:22:04 +0100
4 Subject: KVM: nVMX: clear PIN_BASED_POSTED_INTR from nested pinbased_ctls only when apicv is globally disabled
6 From: Vitaly Kuznetsov <vkuznets@redhat.com>
8 commit a4443267800af240072280c44521caab61924e55 upstream.
10 When apicv is disabled on a vCPU (e.g. by enabling KVM_CAP_HYPERV_SYNIC*),
11 nothing happens to VMX MSRs on the already existing vCPUs, however, all new
12 ones are created with PIN_BASED_POSTED_INTR filtered out. This is very
13 confusing and results in the following picture inside the guest:
21 This is observed with QEMU and 4-vCPU guest: QEMU creates vCPU0, does
22 KVM_CAP_HYPERV_SYNIC2 and then creates the remaining three.
24 L1 hypervisor may only check CPU0's controls to find out what features
25 are available and it will be very confused later. Switch to setting
26 PIN_BASED_POSTED_INTR control based on global 'enable_apicv' setting.
28 Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
29 Cc: stable@vger.kernel.org
30 Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
31 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
34 arch/x86/kvm/vmx/capabilities.h | 1 +
35 arch/x86/kvm/vmx/nested.c | 5 ++---
36 arch/x86/kvm/vmx/nested.h | 3 +--
37 arch/x86/kvm/vmx/vmx.c | 10 ++++------
38 4 files changed, 8 insertions(+), 11 deletions(-)
40 --- a/arch/x86/kvm/vmx/capabilities.h
41 +++ b/arch/x86/kvm/vmx/capabilities.h
42 @@ -12,6 +12,7 @@ extern bool __read_mostly enable_ept;
43 extern bool __read_mostly enable_unrestricted_guest;
44 extern bool __read_mostly enable_ept_ad_bits;
45 extern bool __read_mostly enable_pml;
46 +extern bool __read_mostly enable_apicv;
47 extern int __read_mostly pt_mode;
49 #define PT_MODE_SYSTEM 0
50 --- a/arch/x86/kvm/vmx/nested.c
51 +++ b/arch/x86/kvm/vmx/nested.c
52 @@ -5807,8 +5807,7 @@ void nested_vmx_vcpu_setup(void)
53 * bit in the high half is on if the corresponding bit in the control field
54 * may be on. See also vmx_control_verify().
56 -void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
58 +void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps)
61 * Note that as a general rule, the high half of the MSRs (bits in
62 @@ -5835,7 +5834,7 @@ void nested_vmx_setup_ctls_msrs(struct n
63 PIN_BASED_EXT_INTR_MASK |
64 PIN_BASED_NMI_EXITING |
65 PIN_BASED_VIRTUAL_NMIS |
66 - (apicv ? PIN_BASED_POSTED_INTR : 0);
67 + (enable_apicv ? PIN_BASED_POSTED_INTR : 0);
68 msrs->pinbased_ctls_high |=
69 PIN_BASED_ALWAYSON_WITHOUT_TRUE_MSR |
70 PIN_BASED_VMX_PREEMPTION_TIMER;
71 --- a/arch/x86/kvm/vmx/nested.h
72 +++ b/arch/x86/kvm/vmx/nested.h
73 @@ -17,8 +17,7 @@ enum nvmx_vmentry_status {
76 void vmx_leave_nested(struct kvm_vcpu *vcpu);
77 -void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
79 +void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps);
80 void nested_vmx_hardware_unsetup(void);
81 __init int nested_vmx_hardware_setup(int (*exit_handlers[])(struct kvm_vcpu *));
82 void nested_vmx_vcpu_setup(void);
83 --- a/arch/x86/kvm/vmx/vmx.c
84 +++ b/arch/x86/kvm/vmx/vmx.c
85 @@ -95,7 +95,7 @@ module_param(emulate_invalid_guest_state
86 static bool __read_mostly fasteoi = 1;
87 module_param(fasteoi, bool, S_IRUGO);
89 -static bool __read_mostly enable_apicv = 1;
90 +bool __read_mostly enable_apicv = 1;
91 module_param(enable_apicv, bool, S_IRUGO);
94 @@ -6802,8 +6802,7 @@ static struct kvm_vcpu *vmx_create_vcpu(
97 nested_vmx_setup_ctls_msrs(&vmx->nested.msrs,
99 - kvm_vcpu_apicv_active(&vmx->vcpu));
100 + vmx_capability.ept);
102 memset(&vmx->nested.msrs, 0, sizeof(vmx->nested.msrs));
104 @@ -6885,8 +6884,7 @@ static int __init vmx_check_processor_co
105 if (setup_vmcs_config(&vmcs_conf, &vmx_cap) < 0)
108 - nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept,
110 + nested_vmx_setup_ctls_msrs(&vmcs_conf.nested, vmx_cap.ept);
111 if (memcmp(&vmcs_config, &vmcs_conf, sizeof(struct vmcs_config)) != 0) {
112 printk(KERN_ERR "kvm: CPU %d feature inconsistency!\n",
114 @@ -7781,7 +7779,7 @@ static __init int hardware_setup(void)
117 nested_vmx_setup_ctls_msrs(&vmcs_config.nested,
118 - vmx_capability.ept, enable_apicv);
119 + vmx_capability.ept);
121 r = nested_vmx_hardware_setup(kvm_vmx_exit_handlers);