2021-03-04 11:04:09

by Like Xu

[permalink] [raw]
Subject: [PATCH v3 9/9] KVM: x86: Add XSAVE Support for Architectural LBRs

On processors whose XSAVE feature set supports XSAVES and XRSTORS,
the availability of support for Architectural LBR configuration state save
and restore can be determined from CPUID.(EAX=0DH, ECX=1):EDX:ECX[bit 15].
The detailed leaf for Arch LBRs is enumerated in CPUID.(EAX=0DH, ECX=0FH).

XSAVES provides a faster means than RDMSR for guest to read all LBRs.
When guest IA32_XSS[bit 15] is set, the Arch LBRs state can be saved using
XSAVES and restored by XRSTORS with the appropriate RFBM.

If the KVM fails to pass-through the LBR msrs to the guest, the LBR msrs
will be reset to prevent the leakage of host records via XSAVES. In this
case, the guest results may be inaccurate as the legacy LBR.

Signed-off-by: Like Xu <[email protected]>
---
arch/x86/kvm/vmx/pmu_intel.c | 2 ++
arch/x86/kvm/vmx/vmx.c | 2 ++
arch/x86/kvm/x86.c | 2 ++
3 files changed, 6 insertions(+)

diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 48a817be60ab..08114f70c496 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -768,6 +768,8 @@ void vmx_passthrough_lbr_msrs(struct kvm_vcpu *vcpu)
return;

warn:
+ if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+ wrmsrl(MSR_ARCH_LBR_DEPTH, lbr_desc->records.nr);
pr_warn_ratelimited("kvm: vcpu-%d: fail to passthrough LBR.\n",
vcpu->vcpu_id);
}
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 034708a3df20..ec4593e0ee6d 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7268,6 +7268,8 @@ static __init void vmx_set_cpu_caps(void)
supported_xss = 0;
if (!cpu_has_vmx_xsaves())
kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
+ else if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
+ supported_xss |= XFEATURE_MASK_LBR;

/* CPUID 0x80000001 */
if (!cpu_has_vmx_rdtscp())
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d773836ceb7a..bca2e318ff24 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -10433,6 +10433,8 @@ int kvm_arch_hardware_setup(void *opaque)

if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
supported_xss = 0;
+ else
+ supported_xss &= host_xss;

#define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
--
2.29.2


2021-03-04 14:42:23

by Like Xu

[permalink] [raw]
Subject: Re: [PATCH v3 9/9] KVM: x86: Add XSAVE Support for Architectural LBRs

On 2021/3/4 2:03, Sean Christopherson wrote:
> On Wed, Mar 03, 2021, Like Xu wrote:
>> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
>> index 034708a3df20..ec4593e0ee6d 100644
>> --- a/arch/x86/kvm/vmx/vmx.c
>> +++ b/arch/x86/kvm/vmx/vmx.c
>> @@ -7268,6 +7268,8 @@ static __init void vmx_set_cpu_caps(void)
>> supported_xss = 0;
>> if (!cpu_has_vmx_xsaves())
>> kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
>> + else if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
>> + supported_xss |= XFEATURE_MASK_LBR;
>>
>> /* CPUID 0x80000001 */
>> if (!cpu_has_vmx_rdtscp())
>> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
>> index d773836ceb7a..bca2e318ff24 100644
>> --- a/arch/x86/kvm/x86.c
>> +++ b/arch/x86/kvm/x86.c
>> @@ -10433,6 +10433,8 @@ int kvm_arch_hardware_setup(void *opaque)
>>
>> if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
>> supported_xss = 0;
>> + else
>> + supported_xss &= host_xss;
>
> Not your fault by any means, but I would prefer to have matching logic for XSS
> and XCR0. The existing clearing of supported_xss here is pointless. E.g. I'd
> prefer something like the following, though Paolo may have a different opinion.

I have no preference for where to do rdmsrl() in kvm_arch_init()
or kvm_arch_hardware_setup().

It's true the assignment of supported_xss in the kvm/intel
tree is redundant and introducing KVM_SUPPORTED_XSS is also fine to me.


>
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 6d7e760fdfa0..c781034463e5 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -7244,12 +7244,15 @@ static __init void vmx_set_cpu_caps(void)
> kvm_cpu_cap_clear(X86_FEATURE_INVPCID);
> if (vmx_pt_mode_is_host_guest())
> kvm_cpu_cap_check_and_set(X86_FEATURE_INTEL_PT);
> + if (!cpu_has_vmx_arch_lbr()) {
> + kvm_cpu_cap_clear(X86_FEATURE_ARCH_LBR);
> + supported_xss &= ~XFEATURE_MASK_LBR;
> + }
>

I will move the above part to the LBR patch
and leave the left part as a pre-patch for Paolo's review.

> if (vmx_umip_emulated())
> kvm_cpu_cap_set(X86_FEATURE_UMIP);
>
> /* CPUID 0xD.1 */
> - supported_xss = 0;
> if (!cpu_has_vmx_xsaves())
> kvm_cpu_cap_clear(X86_FEATURE_XSAVES);

if (!cpu_has_vmx_xsaves())
supported_xss = 0;
kvm_cpu_cap_clear(X86_FEATURE_XSAVES);

>
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 7b0adebec1ef..5f9eb1f5b840 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -205,6 +205,8 @@ static struct kvm_user_return_msrs __percpu *user_return_msrs;
> | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \
> | XFEATURE_MASK_PKRU)
>
> +#define KVM_SUPPORTED_XSS XFEATURE_MASK_LBR
> +
> u64 __read_mostly host_efer;
> EXPORT_SYMBOL_GPL(host_efer);
>
> @@ -8037,6 +8039,11 @@ int kvm_arch_init(void *opaque)
> supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
> }
>
> + if (boot_cpu_has(X86_FEATURE_XSAVES))

{

> + rdmsrl(MSR_IA32_XSS, host_xss);
> + supported_xss = host_xss & KVM_SUPPORTED_XSS;
> + }
> +
> if (pi_inject_timer == -1)
> pi_inject_timer = housekeeping_enabled(HK_FLAG_TIMER);
> #ifdef CONFIG_X86_64
> @@ -10412,9 +10419,6 @@ int kvm_arch_hardware_setup(void *opaque)
>
> rdmsrl_safe(MSR_EFER, &host_efer);
>
> - if (boot_cpu_has(X86_FEATURE_XSAVES))
> - rdmsrl(MSR_IA32_XSS, host_xss);
> -
> r = ops->hardware_setup();
> if (r != 0)
> return r;
> @@ -10422,9 +10426,6 @@ int kvm_arch_hardware_setup(void *opaque)
> memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
> kvm_ops_static_call_update();
>
> - if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> - supported_xss = 0;
> -
> #define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
> cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
> #undef __kvm_cpu_cap_has
>

2021-03-04 23:26:52

by Sean Christopherson

[permalink] [raw]
Subject: Re: [PATCH v3 9/9] KVM: x86: Add XSAVE Support for Architectural LBRs

On Wed, Mar 03, 2021, Like Xu wrote:
> diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
> index 034708a3df20..ec4593e0ee6d 100644
> --- a/arch/x86/kvm/vmx/vmx.c
> +++ b/arch/x86/kvm/vmx/vmx.c
> @@ -7268,6 +7268,8 @@ static __init void vmx_set_cpu_caps(void)
> supported_xss = 0;
> if (!cpu_has_vmx_xsaves())
> kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
> + else if (kvm_cpu_cap_has(X86_FEATURE_ARCH_LBR))
> + supported_xss |= XFEATURE_MASK_LBR;
>
> /* CPUID 0x80000001 */
> if (!cpu_has_vmx_rdtscp())
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index d773836ceb7a..bca2e318ff24 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -10433,6 +10433,8 @@ int kvm_arch_hardware_setup(void *opaque)
>
> if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> supported_xss = 0;
> + else
> + supported_xss &= host_xss;

Not your fault by any means, but I would prefer to have matching logic for XSS
and XCR0. The existing clearing of supported_xss here is pointless. E.g. I'd
prefer something like the following, though Paolo may have a different opinion.

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 6d7e760fdfa0..c781034463e5 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7244,12 +7244,15 @@ static __init void vmx_set_cpu_caps(void)
kvm_cpu_cap_clear(X86_FEATURE_INVPCID);
if (vmx_pt_mode_is_host_guest())
kvm_cpu_cap_check_and_set(X86_FEATURE_INTEL_PT);
+ if (!cpu_has_vmx_arch_lbr()) {
+ kvm_cpu_cap_clear(X86_FEATURE_ARCH_LBR);
+ supported_xss &= ~XFEATURE_MASK_LBR;
+ }

if (vmx_umip_emulated())
kvm_cpu_cap_set(X86_FEATURE_UMIP);

/* CPUID 0xD.1 */
- supported_xss = 0;
if (!cpu_has_vmx_xsaves())
kvm_cpu_cap_clear(X86_FEATURE_XSAVES);

diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 7b0adebec1ef..5f9eb1f5b840 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -205,6 +205,8 @@ static struct kvm_user_return_msrs __percpu *user_return_msrs;
| XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \
| XFEATURE_MASK_PKRU)

+#define KVM_SUPPORTED_XSS XFEATURE_MASK_LBR
+
u64 __read_mostly host_efer;
EXPORT_SYMBOL_GPL(host_efer);

@@ -8037,6 +8039,11 @@ int kvm_arch_init(void *opaque)
supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
}

+ if (boot_cpu_has(X86_FEATURE_XSAVES))
+ rdmsrl(MSR_IA32_XSS, host_xss);
+ supported_xss = host_xss & KVM_SUPPORTED_XSS;
+ }
+
if (pi_inject_timer == -1)
pi_inject_timer = housekeeping_enabled(HK_FLAG_TIMER);
#ifdef CONFIG_X86_64
@@ -10412,9 +10419,6 @@ int kvm_arch_hardware_setup(void *opaque)

rdmsrl_safe(MSR_EFER, &host_efer);

- if (boot_cpu_has(X86_FEATURE_XSAVES))
- rdmsrl(MSR_IA32_XSS, host_xss);
-
r = ops->hardware_setup();
if (r != 0)
return r;
@@ -10422,9 +10426,6 @@ int kvm_arch_hardware_setup(void *opaque)
memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
kvm_ops_static_call_update();

- if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
- supported_xss = 0;
-
#define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
#undef __kvm_cpu_cap_has

2021-03-05 00:50:52

by Sean Christopherson

[permalink] [raw]
Subject: Re: [PATCH v3 9/9] KVM: x86: Add XSAVE Support for Architectural LBRs

On Thu, Mar 04, 2021, Like Xu wrote:
> On 2021/3/4 2:03, Sean Christopherson wrote:
> > if (vmx_umip_emulated())
> > kvm_cpu_cap_set(X86_FEATURE_UMIP);
> >
> > /* CPUID 0xD.1 */
> > - supported_xss = 0;
> > if (!cpu_has_vmx_xsaves())
> > kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
>
> if (!cpu_has_vmx_xsaves())
> supported_xss = 0;

Argh, I forgot XSAVES has a VMCS control. That's why kvm_arch_hardware_setup()
clears supported_xss if !XSAVES. I guess just leave that existing code, but
maybe add a comment.

Paolo, any thoughts on how to keep supported_xss aligned with support_xcr0,
without spreading the logic around too much?

> kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
>
> >
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index 7b0adebec1ef..5f9eb1f5b840 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -205,6 +205,8 @@ static struct kvm_user_return_msrs __percpu *user_return_msrs;
> > | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \
> > | XFEATURE_MASK_PKRU)
> >
> > +#define KVM_SUPPORTED_XSS XFEATURE_MASK_LBR
> > +
> > u64 __read_mostly host_efer;
> > EXPORT_SYMBOL_GPL(host_efer);
> >
> > @@ -8037,6 +8039,11 @@ int kvm_arch_init(void *opaque)
> > supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
> > }
> >
> > + if (boot_cpu_has(X86_FEATURE_XSAVES))
>
> {
>
> > + rdmsrl(MSR_IA32_XSS, host_xss);
> > + supported_xss = host_xss & KVM_SUPPORTED_XSS;
> > + }
> > +
> > if (pi_inject_timer == -1)
> > pi_inject_timer = housekeeping_enabled(HK_FLAG_TIMER);
> > #ifdef CONFIG_X86_64
> > @@ -10412,9 +10419,6 @@ int kvm_arch_hardware_setup(void *opaque)
> >
> > rdmsrl_safe(MSR_EFER, &host_efer);
> >
> > - if (boot_cpu_has(X86_FEATURE_XSAVES))
> > - rdmsrl(MSR_IA32_XSS, host_xss);
> > -
> > r = ops->hardware_setup();
> > if (r != 0)
> > return r;
> > @@ -10422,9 +10426,6 @@ int kvm_arch_hardware_setup(void *opaque)
> > memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
> > kvm_ops_static_call_update();
> >
> > - if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
> > - supported_xss = 0;
> > -
> > #define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
> > cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
> > #undef __kvm_cpu_cap_has
> >
>

2021-03-05 02:58:19

by Xu, Like

[permalink] [raw]
Subject: Re: [PATCH v3 9/9] KVM: x86: Add XSAVE Support for Architectural LBRs

On 2021/3/5 0:31, Sean Christopherson wrote:
> Paolo, any thoughts on how to keep supported_xss aligned with support_xcr0,
> without spreading the logic around too much?

From 58be4152ced441395dfc439f446c5ad53bd48576 Mon Sep 17 00:00:00 2001
From: Like Xu <[email protected]>
Date: Thu, 4 Mar 2021 13:21:38 +0800
Subject: [PATCH] KVM: x86: Refine the matching and clearing logic for
supported_xss

"The existing clearing of supported_xss here is pointless".
Let's refine the code path in this way: initialize the supported_xss
with the filter of KVM_SUPPORTED_XSS mask and update its value in
a bit clear manner (rather than bit setting).

Before:
(1) kvm_arch_hardware_setup
    if (boot_cpu_has(X86_FEATURE_XSAVES))
        rdmsrl(MSR_IA32_XSS, host_xss);
    if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
        supported_xss = 0;
    else supported_xss &= host_xss;
(2) vmx_set_cpu_caps
    supported_xss = 0;
    if (!cpu_has_vmx_xsaves())
        kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
    else set available bits to supported_xss

After:
(1) kvm_arch_init
    if (boot_cpu_has(X86_FEATURE_XSAVES))
        rdmsrl(MSR_IA32_XSS, host_xss);
        supported_xss = host_xss & KVM_SUPPORTED_XSS;
(2) vmx_set_cpu_caps
    if (!cpu_has_vmx_xsaves())
        kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
        supported_xss = 0;
    else clear un-available bits for supported_xss

Suggested-by: Sean Christopherson <[email protected]>
Original-by: Sean Christopherson <[email protected]>
Signed-off-by: Like Xu <[email protected]>
---
 arch/x86/kvm/vmx/vmx.c |  5 +++--
 arch/x86/kvm/x86.c     | 13 +++++++------
 2 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 4bc4bb49aaa9..8706323547c4 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -7288,9 +7288,10 @@ static __init void vmx_set_cpu_caps(void)
         kvm_cpu_cap_set(X86_FEATURE_UMIP);

     /* CPUID 0xD.1 */
-    supported_xss = 0;
-    if (!cpu_has_vmx_xsaves())
+    if (!cpu_has_vmx_xsaves()) {
         kvm_cpu_cap_clear(X86_FEATURE_XSAVES);
+        supported_xss = 0;
+    }

     /* CPUID 0x80000001 */
     if (!cpu_has_vmx_rdtscp())
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d773836ceb7a..99cb62035bb2 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -205,6 +205,8 @@ static struct kvm_user_return_msrs __percpu
*user_return_msrs;
                 | XFEATURE_MASK_BNDCSR | XFEATURE_MASK_AVX512 \
                 | XFEATURE_MASK_PKRU)

+#define KVM_SUPPORTED_XSS     0
+
 u64 __read_mostly host_efer;
 EXPORT_SYMBOL_GPL(host_efer);

@@ -8046,6 +8048,11 @@ int kvm_arch_init(void *opaque)
         supported_xcr0 = host_xcr0 & KVM_SUPPORTED_XCR0;
     }

+    if (boot_cpu_has(X86_FEATURE_XSAVES)) {
+        rdmsrl(MSR_IA32_XSS, host_xss);
+        supported_xss = host_xss & KVM_SUPPORTED_XSS;
+    }
+
     if (pi_inject_timer == -1)
         pi_inject_timer = housekeeping_enabled(HK_FLAG_TIMER);
 #ifdef CONFIG_X86_64
@@ -10421,9 +10428,6 @@ int kvm_arch_hardware_setup(void *opaque)

     rdmsrl_safe(MSR_EFER, &host_efer);

-    if (boot_cpu_has(X86_FEATURE_XSAVES))
-        rdmsrl(MSR_IA32_XSS, host_xss);
-
     r = ops->hardware_setup();
     if (r != 0)
         return r;
@@ -10431,9 +10435,6 @@ int kvm_arch_hardware_setup(void *opaque)
     memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
     kvm_ops_static_call_update();

-    if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
-        supported_xss = 0;
-
 #define __kvm_cpu_cap_has(UNUSED_, f) kvm_cpu_cap_has(f)
     cr4_reserved_bits = __cr4_reserved_bits(__kvm_cpu_cap_has, UNUSED_);
 #undef __kvm_cpu_cap_has
--
2.29.2