Skip to content

Commit

Permalink
KVM: VMX: Move LOAD_IA32_PERF_GLOBAL_CTRL errata handling out of setu…
Browse files Browse the repository at this point in the history
…p_vmcs_config()

As a preparation to reusing the result of setup_vmcs_config() for setting
up nested VMX control MSRs, move LOAD_IA32_PERF_GLOBAL_CTRL errata handling
to vmx_vmexit_ctrl()/vmx_vmentry_ctrl() and print the warning from
hardware_setup(). While it seems reasonable to not expose
LOAD_IA32_PERF_GLOBAL_CTRL controls to L1 hypervisor on buggy CPUs,
such change would inevitably break live migration from older KVMs
where the controls are exposed. Keep the status quo for now, L1 hypervisor
itself is supposed to take care of the errata.

Reviewed-by: Maxim Levitsky <mlevitsk@redhat.com>
Signed-off-by: Vitaly Kuznetsov <vkuznets@redhat.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
Link: https://lore.kernel.org/r/20220830133737.1539624-30-vkuznets@redhat.com
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
  • Loading branch information
Vitaly Kuznetsov authored and Paolo Bonzini committed Sep 26, 2022
1 parent aef46a6 commit 9d78d6f
Showing 1 changed file with 35 additions and 24 deletions.
59 changes: 35 additions & 24 deletions arch/x86/kvm/vmx/vmx.c
Original file line number Diff line number Diff line change
Expand Up @@ -2493,6 +2493,30 @@ static bool cpu_has_sgx(void)
return cpuid_eax(0) >= 0x12 && (cpuid_eax(0x12) & BIT(0));
}

/*
* Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they
* can't be used due to errata where VM Exit may incorrectly clear
* IA32_PERF_GLOBAL_CTRL[34:32]. Work around the errata by using the
* MSR load mechanism to switch IA32_PERF_GLOBAL_CTRL.
*/
static bool cpu_has_perf_global_ctrl_bug(void)
{
if (boot_cpu_data.x86 == 0x6) {
switch (boot_cpu_data.x86_model) {
case INTEL_FAM6_NEHALEM_EP: /* AAK155 */
case INTEL_FAM6_NEHALEM: /* AAP115 */
case INTEL_FAM6_WESTMERE: /* AAT100 */
case INTEL_FAM6_WESTMERE_EP: /* BC86,AAY89,BD102 */
case INTEL_FAM6_NEHALEM_EX: /* BA97 */
return true;
default:
break;
}
}

return false;
}

static __init int adjust_vmx_controls(u32 ctl_min, u32 ctl_opt,
u32 msr, u32 *result)
{
Expand Down Expand Up @@ -2648,30 +2672,6 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
_vmexit_control &= ~x_ctrl;
}

/*
* Some cpus support VM_{ENTRY,EXIT}_IA32_PERF_GLOBAL_CTRL but they
* can't be used due to an errata where VM Exit may incorrectly clear
* IA32_PERF_GLOBAL_CTRL[34:32]. Workaround the errata by using the
* MSR load mechanism to switch IA32_PERF_GLOBAL_CTRL.
*/
if (boot_cpu_data.x86 == 0x6) {
switch (boot_cpu_data.x86_model) {
case INTEL_FAM6_NEHALEM_EP: /* AAK155 */
case INTEL_FAM6_NEHALEM: /* AAP115 */
case INTEL_FAM6_WESTMERE: /* AAT100 */
case INTEL_FAM6_WESTMERE_EP: /* BC86,AAY89,BD102 */
case INTEL_FAM6_NEHALEM_EX: /* BA97 */
_vmentry_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
_vmexit_control &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
pr_warn_once("kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
"does not work properly. Using workaround\n");
break;
default:
break;
}
}


rdmsr(MSR_IA32_VMX_BASIC, vmx_msr_low, vmx_msr_high);

/* IA-32 SDM Vol 3B: VMCS size is never greater than 4kB. */
Expand Down Expand Up @@ -4267,6 +4267,9 @@ static u32 vmx_vmentry_ctrl(void)
VM_ENTRY_LOAD_IA32_EFER |
VM_ENTRY_IA32E_MODE);

if (cpu_has_perf_global_ctrl_bug())
vmentry_ctrl &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;

return vmentry_ctrl;
}

Expand All @@ -4284,6 +4287,10 @@ static u32 vmx_vmexit_ctrl(void)
if (vmx_pt_mode_is_system())
vmexit_ctrl &= ~(VM_EXIT_PT_CONCEAL_PIP |
VM_EXIT_CLEAR_IA32_RTIT_CTL);

if (cpu_has_perf_global_ctrl_bug())
vmexit_ctrl &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;

/* Loading of EFER and PERF_GLOBAL_CTRL are toggled dynamically */
return vmexit_ctrl &
~(VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL | VM_EXIT_LOAD_IA32_EFER);
Expand Down Expand Up @@ -8190,6 +8197,10 @@ static __init int hardware_setup(void)
if (setup_vmcs_config(&vmcs_config, &vmx_capability) < 0)
return -EIO;

if (cpu_has_perf_global_ctrl_bug())
pr_warn_once("kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
"does not work properly. Using workaround\n");

if (boot_cpu_has(X86_FEATURE_NX))
kvm_enable_efer_bits(EFER_NX);

Expand Down

0 comments on commit 9d78d6f

Please sign in to comment.