KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts [Linux 3.16.72]

This Linux kernel change "KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts" is included in the Linux 3.16.72 release. This change is authored by Sean Christopherson <sean.j.christopherson [at] intel.com> on Thu Mar 7 15:43:02 2019 -0800. The commit for this change in Linux stable tree is 25f144c (patch) which is from upstream commit 0cf9135. The same Linux upstream change may have been applied to various maintained Linux releases and you can find all Linux releases containing changes from upstream 0cf9135.

KVM: x86: Emulate MSR_IA32_ARCH_CAPABILITIES on AMD hosts

commit 0cf9135b773bf32fba9dd8e6699c1b331ee4b749 upstream.

The CPUID flag ARCH_CAPABILITIES is unconditioinally exposed to host
userspace for all x86 hosts, i.e. KVM advertises ARCH_CAPABILITIES
regardless of hardware support under the pretense that KVM fully
emulates MSR_IA32_ARCH_CAPABILITIES.  Unfortunately, only VMX hosts
handle accesses to MSR_IA32_ARCH_CAPABILITIES (despite KVM_GET_MSRS
also reporting MSR_IA32_ARCH_CAPABILITIES for all hosts).

Move the MSR_IA32_ARCH_CAPABILITIES handling to common x86 code so
that it's emulated on AMD hosts.

Fixes: 1eaafe91a0df4 ("kvm: x86: IA32_ARCH_CAPABILITIES is always supported")
Reported-by: Xiaoyao Li <[email protected]>
Cc: Jim Mattson <[email protected]>
Signed-off-by: Sean Christopherson <[email protected]>
Signed-off-by: Paolo Bonzini <[email protected]>
[bwh: Backported to 3.16:
 - Keep using guest_cpuid_has_arch_capabilities() to check the CPUID
 - Keep using rdmsrl() to get the initial value of IA32_ARCH_CAPABILITIES
 - Adjust filenames, context]
Signed-off-by: Ben Hutchings <[email protected]>

There are 30 lines of Linux source code added/deleted in this change. Code changes to Linux kernel are as follows.

 arch/x86/include/asm/kvm_host.h |  1 +
 arch/x86/kvm/vmx.c              | 15 ---------------
 arch/x86/kvm/x86.c              | 14 ++++++++++++++
 3 files changed, 15 insertions(+), 15 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index e9eae4f..de6c067 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -363,6 +363,7 @@ struct kvm_vcpu_arch {
    int mp_state;
    u64 ia32_misc_enable_msr;
    bool tpr_access_reporting;
+   u64 arch_capabilities;

    /*
     * Paging state of the vcpu
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index bd6b883..00dd9ea 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -433,7 +433,6 @@ struct vcpu_vmx {
    u64               msr_guest_kernel_gs_base;
 #endif

-   u64               arch_capabilities;
    u64               spec_ctrl;

    u32 vm_entry_controls_shadow;
@@ -2481,12 +2480,6 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)

        msr_info->data = to_vmx(vcpu)->spec_ctrl;
        break;
-   case MSR_IA32_ARCH_CAPABILITIES:
-       if (!msr_info->host_initiated &&
-           !guest_cpuid_has_arch_capabilities(vcpu))
-           return 1;
-       msr_info->data = to_vmx(vcpu)->arch_capabilities;
-       break;
    case MSR_IA32_SYSENTER_CS:
        msr_info->data = vmcs_read32(GUEST_SYSENTER_CS);
        break;
@@ -2636,11 +2629,6 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        vmx_disable_intercept_for_msr(vmx->vmcs01.msr_bitmap, MSR_IA32_PRED_CMD,
                          MSR_TYPE_W);
        break;
-   case MSR_IA32_ARCH_CAPABILITIES:
-       if (!msr_info->host_initiated)
-           return 1;
-       vmx->arch_capabilities = data;
-       break;
    case MSR_IA32_CR_PAT:
        if (vmcs_config.vmentry_ctrl & VM_ENTRY_LOAD_IA32_PAT) {
            if (!kvm_mtrr_valid(vcpu, MSR_IA32_CR_PAT, data))
@@ -4583,9 +4571,6 @@ static int vmx_vcpu_setup(struct vcpu_vmx *vmx)
        ++vmx->nmsrs;
    }

-   if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
-       rdmsrl(MSR_IA32_ARCH_CAPABILITIES, vmx->arch_capabilities);
-
    vm_exit_controls_init(vmx, vmcs_config.vmexit_ctrl);

    /* 22.2.1, 20.8.1 */
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index cab3ca9..7773e28 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -2089,6 +2089,11 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
    case MSR_F15H_EX_CFG:
        break;

+   case MSR_IA32_ARCH_CAPABILITIES:
+       if (!msr_info->host_initiated)
+           return 1;
+       vcpu->arch.arch_capabilities = data;
+       break;
    case MSR_EFER:
        return set_efer(vcpu, data);
    case MSR_K7_HWCR:
@@ -2479,6 +2484,12 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
    case MSR_IA32_UCODE_REV:
        msr_info->data = 0x100000000ULL;
        break;
+   case MSR_IA32_ARCH_CAPABILITIES:
+       if (!msr_info->host_initiated &&
+           !guest_cpuid_has_arch_capabilities(vcpu))
+           return 1;
+       msr_info->data = vcpu->arch.arch_capabilities;
+       break;
    case MSR_MTRRcap:
        msr_info->data = 0x500 | KVM_NR_VAR_MTRR;
        break;
@@ -6957,6 +6968,9 @@ int kvm_arch_vcpu_setup(struct kvm_vcpu *vcpu)
 {
    int r;

+   if (boot_cpu_has(X86_FEATURE_ARCH_CAPABILITIES))
+       rdmsrl(MSR_IA32_ARCH_CAPABILITIES,
+              vcpu->arch.arch_capabilities);
    vcpu->arch.mtrr_state.have_fixed = 1;
    r = vcpu_load(vcpu);
    if (r)

Leave a Reply

Your email address will not be published. Required fields are marked *