2018-02-27 02:36:42

by Wanpeng Li

[permalink] [raw]
Subject: [PATCH v4] KVM: X86: Allow userspace to define the microcode version

From: Wanpeng Li <[email protected]>

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 <[email protected]>
Cc: Paolo Bonzini <[email protected]>
Cc: Radim Krčmář <[email protected]>
Cc: Liran Alon <[email protected]>
Cc: Nadav Amit <[email protected]>
Signed-off-by: Wanpeng Li <[email protected]>
---
v3 -> v4:
* add the shifts back
v2 -> v3:
* remove the shifts
* add the MSR_IA32_UCODE_REV version to the "feature MSRs"
v1 -> v2:
* add MSR_IA32_UCODE_REV to emulated_msrs

arch/x86/include/asm/kvm_host.h | 1 +
arch/x86/kvm/x86.c | 19 +++++++++++++++----
2 files changed, 16 insertions(+), 4 deletions(-)

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 938d453..6e13f2f 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
u64 smi_count;
bool tpr_access_reporting;
u64 ia32_xss;
+ u32 microcode_version;

/*
* Paging state of the vcpu
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d4985a9..0299b6e 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1058,6 +1058,7 @@ static unsigned num_emulated_msrs;
static u32 msr_based_features[] = {
MSR_IA32_ARCH_CAPABILITIES,
MSR_F10H_DECFG,
+ MSR_IA32_UCODE_REV,
};

static unsigned int num_msr_based_features;
@@ -1067,8 +1068,14 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
struct kvm_msr_entry msr;

msr.index = index;
- if (kvm_x86_ops->get_msr_feature(&msr))
- return 1;
+ 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;
+ }

*data = msr.data;

@@ -2248,7 +2255,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:
@@ -2256,6 +2262,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 >> 32;
+ break;
case MSR_EFER:
return set_efer(vcpu, data);
case MSR_K7_HWCR:
@@ -2551,7 +2561,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 = (u64)vcpu->arch.microcode_version << 32;
break;
case MSR_MTRRcap:
case 0x200 ... 0x2ff:
@@ -8233,6 +8243,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
vcpu->arch.regs_dirty = ~0;

vcpu->arch.ia32_xss = 0;
+ vcpu->arch.microcode_version = 0x1;

kvm_x86_ops->vcpu_reset(vcpu, init_event);
}
--
2.7.4



2018-02-27 08:56:31

by Paolo Bonzini

[permalink] [raw]
Subject: Re: [PATCH v4] KVM: X86: Allow userspace to define the microcode version

On 27/02/2018 03:35, Wanpeng Li wrote:
> From: Wanpeng Li <[email protected]>
>
> 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 <[email protected]>
> Cc: Paolo Bonzini <[email protected]>
> Cc: Radim Krčmář <[email protected]>
> Cc: Liran Alon <[email protected]>
> Cc: Nadav Amit <[email protected]>
> Signed-off-by: Wanpeng Li <[email protected]>
> ---
> v3 -> v4:
> * add the shifts back

Please wait for a review instead of pushing new versions continuously.
Leaving the shifts means that MSR_IA32_UCODE_REV's bits 0-31 are zeroed
even if KVM_SET_MSRS makes them nonzero.

Paolo

> v2 -> v3:
> * remove the shifts
> * add the MSR_IA32_UCODE_REV version to the "feature MSRs"
> v1 -> v2:
> * add MSR_IA32_UCODE_REV to emulated_msrs
>
> arch/x86/include/asm/kvm_host.h | 1 +
> arch/x86/kvm/x86.c | 19 +++++++++++++++----
> 2 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 938d453..6e13f2f 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
> u64 smi_count;
> bool tpr_access_reporting;
> u64 ia32_xss;
> + u32 microcode_version;
>
> /*
> * Paging state of the vcpu
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index d4985a9..0299b6e 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1058,6 +1058,7 @@ static unsigned num_emulated_msrs;
> static u32 msr_based_features[] = {
> MSR_IA32_ARCH_CAPABILITIES,
> MSR_F10H_DECFG,
> + MSR_IA32_UCODE_REV,
> };
>
> static unsigned int num_msr_based_features;
> @@ -1067,8 +1068,14 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
> struct kvm_msr_entry msr;
>
> msr.index = index;
> - if (kvm_x86_ops->get_msr_feature(&msr))
> - return 1;
> + 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;
> + }
>
> *data = msr.data;
>
> @@ -2248,7 +2255,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:
> @@ -2256,6 +2262,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 >> 32;
> + break;
> case MSR_EFER:
> return set_efer(vcpu, data);
> case MSR_K7_HWCR:
> @@ -2551,7 +2561,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 = (u64)vcpu->arch.microcode_version << 32;
> break;
> case MSR_MTRRcap:
> case 0x200 ... 0x2ff:
> @@ -8233,6 +8243,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
> vcpu->arch.regs_dirty = ~0;
>
> vcpu->arch.ia32_xss = 0;
> + vcpu->arch.microcode_version = 0x1;
>
> kvm_x86_ops->vcpu_reset(vcpu, init_event);
> }
>


2018-02-27 09:43:26

by Wanpeng Li

[permalink] [raw]
Subject: Re: [PATCH v4] KVM: X86: Allow userspace to define the microcode version

2018-02-27 16:38 GMT+08:00 Paolo Bonzini <[email protected]>:
> On 27/02/2018 03:35, Wanpeng Li wrote:
>> From: Wanpeng Li <[email protected]>
>>
>> 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 <[email protected]>
>> Cc: Paolo Bonzini <[email protected]>
>> Cc: Radim Krčmář <[email protected]>
>> Cc: Liran Alon <[email protected]>
>> Cc: Nadav Amit <[email protected]>
>> Signed-off-by: Wanpeng Li <[email protected]>
>> ---
>> v3 -> v4:
>> * add the shifts back
>
> Please wait for a review instead of pushing new versions continuously.
> Leaving the shifts means that MSR_IA32_UCODE_REV's bits 0-31 are zeroed
> even if KVM_SET_MSRS makes them nonzero.

How about something like this?

diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
index 938d453..df6720f 100644
--- a/arch/x86/include/asm/kvm_host.h
+++ b/arch/x86/include/asm/kvm_host.h
@@ -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
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c
index f874798..312f33f 100644
--- a/arch/x86/kvm/svm.c
+++ b/arch/x86/kvm/svm.c
@@ -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;
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 9968906..2cdbea7 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -5781,6 +5781,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);

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d4985a9..7afffd3 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -1058,6 +1058,7 @@ static unsigned num_emulated_msrs;
static u32 msr_based_features[] = {
MSR_IA32_ARCH_CAPABILITIES,
MSR_F10H_DECFG,
+ MSR_IA32_UCODE_REV,
};

static unsigned int num_msr_based_features;
@@ -1067,8 +1068,14 @@ static int do_get_msr_feature(struct kvm_vcpu
*vcpu, unsigned index, u64 *data)
struct kvm_msr_entry msr;

msr.index = index;
- if (kvm_x86_ops->get_msr_feature(&msr))
- return 1;
+ 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;
+ }

*data = msr.data;

@@ -2248,7 +2255,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:
@@ -2256,6 +2262,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:
@@ -2551,7 +2561,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:

2018-02-27 09:44:49

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCH v4] KVM: X86: Allow userspace to define the microcode version

On Tue, Feb 27, 2018 at 09:38:12AM +0100, Paolo Bonzini wrote:
> On 27/02/2018 03:35, Wanpeng Li wrote:
> > From: Wanpeng Li <[email protected]>
> >
> > 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 <[email protected]>
> > Cc: Paolo Bonzini <[email protected]>
> > Cc: Radim Krčmář <[email protected]>
> > Cc: Liran Alon <[email protected]>
> > Cc: Nadav Amit <[email protected]>
> > Signed-off-by: Wanpeng Li <[email protected]>
> > ---
> > v3 -> v4:
> > * add the shifts back
>
> Please wait for a review instead of pushing new versions continuously.

... and pls CC me on your submissions.

Thx.

--
Regards/Gruss,
Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.

2018-02-27 10:56:25

by Paolo Bonzini

[permalink] [raw]
Subject: Re: [PATCH v4] KVM: X86: Allow userspace to define the microcode version

On 27/02/2018 10:26, Wanpeng Li wrote:
> 2018-02-27 16:38 GMT+08:00 Paolo Bonzini <[email protected]>:
>> On 27/02/2018 03:35, Wanpeng Li wrote:
>>> From: Wanpeng Li <[email protected]>
>>>
>>> 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 <[email protected]>
>>> Cc: Paolo Bonzini <[email protected]>
>>> Cc: Radim Krčmář <[email protected]>
>>> Cc: Liran Alon <[email protected]>
>>> Cc: Nadav Amit <[email protected]>
>>> Signed-off-by: Wanpeng Li <[email protected]>
>>> ---
>>> v3 -> v4:
>>> * add the shifts back
>>
>> Please wait for a review instead of pushing new versions continuously.
>> Leaving the shifts means that MSR_IA32_UCODE_REV's bits 0-31 are zeroed
>> even if KVM_SET_MSRS makes them nonzero.
>
> How about something like this?

Yes, that's okay.

Paolo

2018-02-27 14:26:55

by Tom Lendacky

[permalink] [raw]
Subject: Re: [PATCH v4] KVM: X86: Allow userspace to define the microcode version

On 2/26/2018 8:35 PM, Wanpeng Li wrote:
> From: Wanpeng Li <[email protected]>
>
> 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 <[email protected]>
> Cc: Paolo Bonzini <[email protected]>
> Cc: Radim Krčmář <[email protected]>
> Cc: Liran Alon <[email protected]>
> Cc: Nadav Amit <[email protected]>
> Signed-off-by: Wanpeng Li <[email protected]>
> ---
> v3 -> v4:
> * add the shifts back
> v2 -> v3:
> * remove the shifts
> * add the MSR_IA32_UCODE_REV version to the "feature MSRs"
> v1 -> v2:
> * add MSR_IA32_UCODE_REV to emulated_msrs
>
> arch/x86/include/asm/kvm_host.h | 1 +
> arch/x86/kvm/x86.c | 19 +++++++++++++++----
> 2 files changed, 16 insertions(+), 4 deletions(-)
>
> diff --git a/arch/x86/include/asm/kvm_host.h b/arch/x86/include/asm/kvm_host.h
> index 938d453..6e13f2f 100644
> --- a/arch/x86/include/asm/kvm_host.h
> +++ b/arch/x86/include/asm/kvm_host.h
> @@ -507,6 +507,7 @@ struct kvm_vcpu_arch {
> u64 smi_count;
> bool tpr_access_reporting;
> u64 ia32_xss;
> + u32 microcode_version;
>
> /*
> * Paging state of the vcpu
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index d4985a9..0299b6e 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -1058,6 +1058,7 @@ static unsigned num_emulated_msrs;
> static u32 msr_based_features[] = {
> MSR_IA32_ARCH_CAPABILITIES,
> MSR_F10H_DECFG,
> + MSR_IA32_UCODE_REV,
> };
>
> static unsigned int num_msr_based_features;
> @@ -1067,8 +1068,14 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data)
> struct kvm_msr_entry msr;
>
> msr.index = index;
> - if (kvm_x86_ops->get_msr_feature(&msr))
> - return 1;
> + switch (msr.index) {
> + case MSR_IA32_UCODE_REV:
> + rdmsrl(msr.index, msr.data);
> + break;

By not putting this support into the svm/vmx get_msr_feature() functions
this MSR will be removed from the list of msr_based_features (see the
kvm_init_msr_list() function). You will need to either add this to each
of the get_msr_feature() functions, put similar code to this into the
kvm_init_msr_list() function or create a "common" function that can
be called if the svm/vmx function doesn't directly support the MSR in
question (similar to the get/set msr functions).

Thanks,
Tom

> + default:
> + if (kvm_x86_ops->get_msr_feature(&msr))
> + return 1;
> + }
>
> *data = msr.data;
>
> @@ -2248,7 +2255,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:
> @@ -2256,6 +2262,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 >> 32;
> + break;
> case MSR_EFER:
> return set_efer(vcpu, data);
> case MSR_K7_HWCR:
> @@ -2551,7 +2561,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 = (u64)vcpu->arch.microcode_version << 32;
> break;
> case MSR_MTRRcap:
> case 0x200 ... 0x2ff:
> @@ -8233,6 +8243,7 @@ void kvm_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
> vcpu->arch.regs_dirty = ~0;
>
> vcpu->arch.ia32_xss = 0;
> + vcpu->arch.microcode_version = 0x1;
>
> kvm_x86_ops->vcpu_reset(vcpu, init_event);
> }
>