Commit 518e7b94 authored by Wanpeng Li's avatar Wanpeng Li Committed by Radim Krčmář

KVM: X86: Allow userspace to define the microcode version

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: default avatarFilippo 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: default avatarWanpeng Li <wanpengli@tencent.com>
Reviewed-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarRadim Krčmář <rkrcmar@redhat.com>
parent 66421c1e
...@@ -507,6 +507,7 @@ struct kvm_vcpu_arch { ...@@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
u64 smi_count; u64 smi_count;
bool tpr_access_reporting; bool tpr_access_reporting;
u64 ia32_xss; u64 ia32_xss;
u64 microcode_version;
/* /*
* Paging state of the vcpu * Paging state of the vcpu
......
...@@ -1907,6 +1907,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) ...@@ -1907,6 +1907,7 @@ static void svm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
u32 dummy; u32 dummy;
u32 eax = 1; u32 eax = 1;
vcpu->arch.microcode_version = 0x01000065;
svm->spec_ctrl = 0; svm->spec_ctrl = 0;
if (!init_event) { if (!init_event) {
...@@ -3962,9 +3963,6 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -3962,9 +3963,6 @@ static int svm_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = svm->spec_ctrl; msr_info->data = svm->spec_ctrl;
break; break;
case MSR_IA32_UCODE_REV:
msr_info->data = 0x01000065;
break;
case MSR_F15H_IC_CFG: { case MSR_F15H_IC_CFG: {
int family, model; int family, model;
......
...@@ -5771,6 +5771,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) ...@@ -5771,6 +5771,7 @@ static void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vmx->rmode.vm86_active = 0; vmx->rmode.vm86_active = 0;
vmx->spec_ctrl = 0; vmx->spec_ctrl = 0;
vcpu->arch.microcode_version = 0x100000000ULL;
vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val(); vmx->vcpu.arch.regs[VCPU_REGS_RDX] = get_rdx_init_val();
kvm_set_cr8(vcpu, 0); kvm_set_cr8(vcpu, 0);
......
...@@ -1055,6 +1055,7 @@ static unsigned num_emulated_msrs; ...@@ -1055,6 +1055,7 @@ static unsigned num_emulated_msrs;
*/ */
static u32 msr_based_features[] = { static u32 msr_based_features[] = {
MSR_F10H_DECFG, MSR_F10H_DECFG,
MSR_IA32_UCODE_REV,
}; };
static unsigned int num_msr_based_features; static unsigned int num_msr_based_features;
...@@ -1062,6 +1063,9 @@ 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) static int kvm_get_msr_feature(struct kvm_msr_entry *msr)
{ {
switch (msr->index) { switch (msr->index) {
case MSR_IA32_UCODE_REV:
rdmsrl(msr->index, msr->data);
break;
default: default:
if (kvm_x86_ops->get_msr_feature(msr)) if (kvm_x86_ops->get_msr_feature(msr))
return 1; return 1;
...@@ -2257,7 +2261,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2257,7 +2261,6 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
switch (msr) { switch (msr) {
case MSR_AMD64_NB_CFG: case MSR_AMD64_NB_CFG:
case MSR_IA32_UCODE_REV:
case MSR_IA32_UCODE_WRITE: case MSR_IA32_UCODE_WRITE:
case MSR_VM_HSAVE_PA: case MSR_VM_HSAVE_PA:
case MSR_AMD64_PATCH_LOADER: case MSR_AMD64_PATCH_LOADER:
...@@ -2265,6 +2268,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2265,6 +2268,10 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_AMD64_DC_CFG: case MSR_AMD64_DC_CFG:
break; break;
case MSR_IA32_UCODE_REV:
if (msr_info->host_initiated)
vcpu->arch.microcode_version = data;
break;
case MSR_EFER: case MSR_EFER:
return set_efer(vcpu, data); return set_efer(vcpu, data);
case MSR_K7_HWCR: case MSR_K7_HWCR:
...@@ -2560,7 +2567,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info) ...@@ -2560,7 +2567,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
msr_info->data = 0; msr_info->data = 0;
break; break;
case MSR_IA32_UCODE_REV: case MSR_IA32_UCODE_REV:
msr_info->data = 0x100000000ULL; msr_info->data = vcpu->arch.microcode_version;
break; break;
case MSR_MTRRcap: case MSR_MTRRcap:
case 0x200 ... 0x2ff: case 0x200 ... 0x2ff:
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment