KVM: X86: Allow userspace to define the microcode version
authorWanpeng Li <wanpengli@tencent.com>
Wed, 28 Feb 2018 06:03:31 +0000 (14:03 +0800)
committerRadim Krčmář <rkrcmar@redhat.com>
Thu, 1 Mar 2018 21:32:44 +0000 (22:32 +0100)
Linux (among the others) has checks to make sure that certain features
aren't enabled on a certain family/model/stepping if the microcode version
isn't greater than or equal to a known good version.

By exposing the real microcode version, we're preventing buggy guests that
don't check that they are running virtualized (i.e., they should trust the
hypervisor) from disabling features that are effectively not buggy.

Suggested-by: Filippo Sironi <sironi@amazon.de>
Cc: Paolo Bonzini <pbonzini@redhat.com>
Cc: Radim Krčmář <rkrcmar@redhat.com>
Cc: Liran Alon <liran.alon@oracle.com>
Cc: Nadav Amit <nadav.amit@gmail.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Tom Lendacky <thomas.lendacky@amd.com>
Signed-off-by: Wanpeng Li <wanpengli@tencent.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Radim Krčmář <rkrcmar@redhat.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/svm.c
arch/x86/kvm/vmx.c
arch/x86/kvm/x86.c

index bab0694b35c3d2d0c8ae323e027c86c89b7e4cf6..b605a5b6a30c38f1bdcf647be241516b5e1310b8 100644 (file)
@@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
        u64 smi_count;
        bool tpr_access_reporting;
        u64 ia32_xss;
+       u64 microcode_version;
 
        /*
         * Paging state of the vcpu
index f874798f82099230d9f52f7e20e4ea8aac73297c..312f33f4ed36aca16825411945ab01a3cdce14eb 100644 (file)
@@ -1907,6 +1907,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        u32 dummy;
        u32 eax = 1;
 
+       vcpu->arch.microcode_version = 0x01000065;
        svm->spec_ctrl = 0;
 
        if (!init_event) {
@@ -3962,9 +3963,6 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
                msr_info->data = svm->spec_ctrl;
                break;
-       case MSR_IA32_UCODE_REV:
-               msr_info->data = 0x01000065;
-               break;
        case MSR_F15H_IC_CFG: {
 
                int family, model;
index fafc1f6d8987c26d631ce08ec12beafa385bb19b..59121484304655c17a68582a3708abaef527621b 100644 (file)
@@ -5771,6 +5771,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
        vmx->rmode.vm86_active = 0;
        vmx->spec_ctrl = 0;
 
+       vcpu->arch.microcode_version = 0x100000000ULL;
        vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
        kvm_set_cr8(vcpu, 0);
 
index d97620eeb394f5bc92885b9f4753ec5c5abbf83c..11649d290b9363fd7bc971ea7a48223b3975a3e1 100644 (file)
@@ -1055,6 +1055,7 @@ static unsigned num_emulated_msrs;
  */
 static u32 msr_based_features[] = {
        MSR_F10H_DECFG,
+       MSR_IA32_UCODE_REV,
 };
 
 static unsigned int num_msr_based_features;
@@ -1062,6 +1063,9 @@ static unsigned int num_msr_based_features;
 static int kvm_get_msr_feature(struct kvm_msr_entry *msr)
 {
        switch (msr->index) {
+       case MSR_IA32_UCODE_REV:
+               rdmsrl(msr->index, msr->data);
+               break;
        default:
                if (kvm_x86_ops->get_msr_feature(msr))
                        return 1;
@@ -2257,7 +2261,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 
        switch (msr) {
        case MSR_AMD64_NB_CFG:
-       case MSR_IA32_UCODE_REV:
        case MSR_IA32_UCODE_WRITE:
        case MSR_VM_HSAVE_PA:
        case MSR_AMD64_PATCH_LOADER:
@@ -2265,6 +2268,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
        case MSR_AMD64_DC_CFG:
                break;
 
+       case MSR_IA32_UCODE_REV:
+               if (msr_info->host_initiated)
+                       vcpu->arch.microcode_version = data;
+               break;
        case MSR_EFER:
                return set_efer(vcpu, data);
        case MSR_K7_HWCR:
@@ -2560,7 +2567,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                msr_info->data = 0;
                break;
        case MSR_IA32_UCODE_REV:
-               msr_info->data = 0x100000000ULL;
+               msr_info->data = vcpu->arch.microcode_version;
                break;
        case MSR_MTRRcap:
        case 0x200 ... 0x2ff: