All of lore.kernel.org
 help / color / mirror / Atom feed
From: Eduardo Habkost <ehabkost@redhat.com>
To: Yang Weijiang <weijiang.yang@intel.com>
Cc: pbonzini@redhat.com, richard.henderson@linaro.org,
	mtosatti@redhat.com, sean.j.christopherson@intel.com,
	qemu-devel@nongnu.org, kvm@vger.kernel.org
Subject: Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
Date: Thu, 6 May 2021 18:16:47 -0400	[thread overview]
Message-ID: <20210506221647.zaq4or66rqspxssb@habkost.net> (raw)
In-Reply-To: <20210226022058.24562-3-weijiang.yang@intel.com>

On Fri, Feb 26, 2021 at 10:20:54AM +0800, Yang Weijiang wrote:
> Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
> XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
> components, and XSS bits indicate supervisor-mode XSAVE components.
> 
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>  target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
>  target/i386/cpu.h | 12 ++++++++++++
>  2 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 89edab4240..f3923988ed 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1058,6 +1058,24 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          },
>          .tcg_features = TCG_XSAVE_FEATURES,
>      },
> +    [FEAT_XSAVE_XSS_LO] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_ECX,
> +        },
> +    },
> +    [FEAT_XSAVE_XSS_HI] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_EDX
> +        },
> +    },
>      [FEAT_6_EAX] = {
>          .type = CPUID_FEATURE_WORD,
>          .feat_names = {
> @@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
>      for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
>          if ((mask >> i) & 1) {
> +            if (i >= 2 && !esa->offset) {

Maybe a few comments at the definition of ExtSaveArea to explain
that offset can now be zero (and what it means when it's zero)
would be helpful.  I took a while to understand why this is safe.

Would it be valid to say "ExtSaveArea.offset has a valid offset
only if the component is in CPUID_XSTATE_XCR0_MASK"?  If so,
can't this check be simply replaced with:
  if ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

Or maybe this function should just contain a:
  assert(!(mask & CPUID_XSTATE_XCR0_MASK));
at the beginning?


> +                continue;
> +            }
>              ret = MAX(ret, esa->offset + esa->size);
>          }
>      }
> @@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
>      return kvm_enabled() || hvf_enabled();
>  }
>  
> -static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
> +static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu)
>  {
>      return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
>             cpu->env.features[FEAT_XSAVE_XCR0_LO];
>  }
>  
> +static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu)
> +{
> +    return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 |
> +           cpu->env.features[FEAT_XSAVE_XSS_LO];
> +}
> +
>  const char *get_register_name_32(unsigned int reg)
>  {
>      if (reg >= CPU_NB_REGS32) {
> @@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>          }
>  
>          if (count == 0) {
> -            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
> +            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
>              *eax = env->features[FEAT_XSAVE_XCR0_LO];
>              *edx = env->features[FEAT_XSAVE_XCR0_HI];
>              /*
> @@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>              *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
>          } else if (count == 1) {
>              *eax = env->features[FEAT_XSAVE];
> +            *ecx = env->features[FEAT_XSAVE_XSS_LO];
> +            *edx = env->features[FEAT_XSAVE_XSS_HI];

What about EBX?  It is documented as "The size in bytes of the
XSAVE area containing all states enabled by XCRO | IA32_XSS".

The Intel SDM is not clear, but I assume this would be
necessarily the size of the area in compacted format?


>          } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
> -            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
> -                const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
>                  *eax = esa->size;
>                  *ebx = esa->offset;
> +            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
> +                *eax = esa->size;
> +                *ebx = 0;
> +                *ecx = 1;
>              }
>          }
>          break;
> @@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
>      }
>      for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> +        if (!esa->offset) {
> +            continue;

Most of the comments at the xsave_area_size() hunk would apply
here.  I miss some clarity on what esa->offset==0 really means.

Would it be valid to replace this with a check for
  ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

> +        }
>          if (env->features[esa->feature] & esa->bits) {
>              xcr0 |= 1ull << i;
>          }
> @@ -6295,8 +6331,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
>          }
>      }
>  
> -    env->features[FEAT_XSAVE_XCR0_LO] = mask;
> +    env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
>      env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
> +    env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
> +    env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
>  }
>  
>  /***** Steps involved on loading and filtering CPUID data
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 52f31335c4..8aeaa8869a 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -504,6 +504,16 @@ typedef enum X86Seg {
>  #define XSTATE_Hi16_ZMM_MASK            (1ULL << XSTATE_Hi16_ZMM_BIT)
>  #define XSTATE_PKRU_MASK                (1ULL << XSTATE_PKRU_BIT)
>  
> +/* CPUID feature bits available in XCR0 */
> +#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
> +                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
> +                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
> +                                 XSTATE_ZMM_Hi256_MASK | \
> +                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
> +
> +/* CPUID feature bits available in XSS */
> +#define CPUID_XSTATE_XSS_MASK    0

Do you expect this to be used outside target/i386/cpu.c?  If not,
maybe it could be moved close to the x86_ext_save_areas[]
definition, as any updates to x86_ext_save_areas will require an
update to these macros.

> +
>  /* CPUID feature words */
>  typedef enum FeatureWord {
>      FEAT_1_EDX,         /* CPUID[1].EDX */
> @@ -541,6 +551,8 @@ typedef enum FeatureWord {
>      FEAT_VMX_EPT_VPID_CAPS,
>      FEAT_VMX_BASIC,
>      FEAT_VMX_VMFUNC,
> +    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> +    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
>      FEATURE_WORDS,
>  } FeatureWord;
>  
> -- 
> 2.26.2
> 
> 

-- 
Eduardo


WARNING: multiple messages have this Message-ID (diff)
From: Eduardo Habkost <ehabkost@redhat.com>
To: Yang Weijiang <weijiang.yang@intel.com>
Cc: kvm@vger.kernel.org, mtosatti@redhat.com,
	richard.henderson@linaro.org, qemu-devel@nongnu.org,
	sean.j.christopherson@intel.com, pbonzini@redhat.com
Subject: Re: [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID
Date: Thu, 6 May 2021 18:16:47 -0400	[thread overview]
Message-ID: <20210506221647.zaq4or66rqspxssb@habkost.net> (raw)
In-Reply-To: <20210226022058.24562-3-weijiang.yang@intel.com>

On Fri, Feb 26, 2021 at 10:20:54AM +0800, Yang Weijiang wrote:
> Currently, CPUID.(EAX=0DH,ECX=01H) doesn't enumerate features in
> XSS properly, add the support here. XCR0 bits indicate user-mode XSAVE
> components, and XSS bits indicate supervisor-mode XSAVE components.
> 
> Signed-off-by: Yang Weijiang <weijiang.yang@intel.com>
> ---
>  target/i386/cpu.c | 48 ++++++++++++++++++++++++++++++++++++++++++-----
>  target/i386/cpu.h | 12 ++++++++++++
>  2 files changed, 55 insertions(+), 5 deletions(-)
> 
> diff --git a/target/i386/cpu.c b/target/i386/cpu.c
> index 89edab4240..f3923988ed 100644
> --- a/target/i386/cpu.c
> +++ b/target/i386/cpu.c
> @@ -1058,6 +1058,24 @@ static FeatureWordInfo feature_word_info[FEATURE_WORDS] = {
>          },
>          .tcg_features = TCG_XSAVE_FEATURES,
>      },
> +    [FEAT_XSAVE_XSS_LO] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_ECX,
> +        },
> +    },
> +    [FEAT_XSAVE_XSS_HI] = {
> +        .type = CPUID_FEATURE_WORD,
> +        .cpuid = {
> +            .eax = 0xD,
> +            .needs_ecx = true,
> +            .ecx = 1,
> +            .reg = R_EDX
> +        },
> +    },
>      [FEAT_6_EAX] = {
>          .type = CPUID_FEATURE_WORD,
>          .feat_names = {
> @@ -1478,6 +1496,9 @@ static uint32_t xsave_area_size(uint64_t mask)
>      for (i = 0; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
>          if ((mask >> i) & 1) {
> +            if (i >= 2 && !esa->offset) {

Maybe a few comments at the definition of ExtSaveArea to explain
that offset can now be zero (and what it means when it's zero)
would be helpful.  I took a while to understand why this is safe.

Would it be valid to say "ExtSaveArea.offset has a valid offset
only if the component is in CPUID_XSTATE_XCR0_MASK"?  If so,
can't this check be simply replaced with:
  if ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

Or maybe this function should just contain a:
  assert(!(mask & CPUID_XSTATE_XCR0_MASK));
at the beginning?


> +                continue;
> +            }
>              ret = MAX(ret, esa->offset + esa->size);
>          }
>      }
> @@ -1489,12 +1510,18 @@ static inline bool accel_uses_host_cpuid(void)
>      return kvm_enabled() || hvf_enabled();
>  }
>  
> -static inline uint64_t x86_cpu_xsave_components(X86CPU *cpu)
> +static inline uint64_t x86_cpu_xsave_xcr0_components(X86CPU *cpu)
>  {
>      return ((uint64_t)cpu->env.features[FEAT_XSAVE_XCR0_HI]) << 32 |
>             cpu->env.features[FEAT_XSAVE_XCR0_LO];
>  }
>  
> +static inline uint64_t x86_cpu_xsave_xss_components(X86CPU *cpu)
> +{
> +    return ((uint64_t)cpu->env.features[FEAT_XSAVE_XSS_HI]) << 32 |
> +           cpu->env.features[FEAT_XSAVE_XSS_LO];
> +}
> +
>  const char *get_register_name_32(unsigned int reg)
>  {
>      if (reg >= CPU_NB_REGS32) {
> @@ -5716,7 +5743,7 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>          }
>  
>          if (count == 0) {
> -            *ecx = xsave_area_size(x86_cpu_xsave_components(cpu));
> +            *ecx = xsave_area_size(x86_cpu_xsave_xcr0_components(cpu));
>              *eax = env->features[FEAT_XSAVE_XCR0_LO];
>              *edx = env->features[FEAT_XSAVE_XCR0_HI];
>              /*
> @@ -5728,11 +5755,17 @@ void cpu_x86_cpuid(CPUX86State *env, uint32_t index, uint32_t count,
>              *ebx = kvm_enabled() ? *ecx : xsave_area_size(env->xcr0);
>          } else if (count == 1) {
>              *eax = env->features[FEAT_XSAVE];
> +            *ecx = env->features[FEAT_XSAVE_XSS_LO];
> +            *edx = env->features[FEAT_XSAVE_XSS_HI];

What about EBX?  It is documented as "The size in bytes of the
XSAVE area containing all states enabled by XCRO | IA32_XSS".

The Intel SDM is not clear, but I assume this would be
necessarily the size of the area in compacted format?


>          } else if (count < ARRAY_SIZE(x86_ext_save_areas)) {
> -            if ((x86_cpu_xsave_components(cpu) >> count) & 1) {
> -                const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            const ExtSaveArea *esa = &x86_ext_save_areas[count];
> +            if ((x86_cpu_xsave_xcr0_components(cpu) >> count) & 1) {
>                  *eax = esa->size;
>                  *ebx = esa->offset;
> +            } else if ((x86_cpu_xsave_xss_components(cpu) >> count) & 1) {
> +                *eax = esa->size;
> +                *ebx = 0;
> +                *ecx = 1;
>              }
>          }
>          break;
> @@ -6059,6 +6092,9 @@ static void x86_cpu_reset(DeviceState *dev)
>      }
>      for (i = 2; i < ARRAY_SIZE(x86_ext_save_areas); i++) {
>          const ExtSaveArea *esa = &x86_ext_save_areas[i];
> +        if (!esa->offset) {
> +            continue;

Most of the comments at the xsave_area_size() hunk would apply
here.  I miss some clarity on what esa->offset==0 really means.

Would it be valid to replace this with a check for
  ((1 << i) & CPUID_XSTATE_XCR0_MASK)
?

> +        }
>          if (env->features[esa->feature] & esa->bits) {
>              xcr0 |= 1ull << i;
>          }
> @@ -6295,8 +6331,10 @@ static void x86_cpu_enable_xsave_components(X86CPU *cpu)
>          }
>      }
>  
> -    env->features[FEAT_XSAVE_XCR0_LO] = mask;
> +    env->features[FEAT_XSAVE_XCR0_LO] = mask & CPUID_XSTATE_XCR0_MASK;
>      env->features[FEAT_XSAVE_XCR0_HI] = mask >> 32;
> +    env->features[FEAT_XSAVE_XSS_LO] = mask & CPUID_XSTATE_XSS_MASK;
> +    env->features[FEAT_XSAVE_XSS_HI] = mask >> 32;
>  }
>  
>  /***** Steps involved on loading and filtering CPUID data
> diff --git a/target/i386/cpu.h b/target/i386/cpu.h
> index 52f31335c4..8aeaa8869a 100644
> --- a/target/i386/cpu.h
> +++ b/target/i386/cpu.h
> @@ -504,6 +504,16 @@ typedef enum X86Seg {
>  #define XSTATE_Hi16_ZMM_MASK            (1ULL << XSTATE_Hi16_ZMM_BIT)
>  #define XSTATE_PKRU_MASK                (1ULL << XSTATE_PKRU_BIT)
>  
> +/* CPUID feature bits available in XCR0 */
> +#define CPUID_XSTATE_XCR0_MASK  (XSTATE_FP_MASK | XSTATE_SSE_MASK | \
> +                                 XSTATE_YMM_MASK | XSTATE_BNDREGS_MASK | \
> +                                 XSTATE_BNDCSR_MASK | XSTATE_OPMASK_MASK | \
> +                                 XSTATE_ZMM_Hi256_MASK | \
> +                                 XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK)
> +
> +/* CPUID feature bits available in XSS */
> +#define CPUID_XSTATE_XSS_MASK    0

Do you expect this to be used outside target/i386/cpu.c?  If not,
maybe it could be moved close to the x86_ext_save_areas[]
definition, as any updates to x86_ext_save_areas will require an
update to these macros.

> +
>  /* CPUID feature words */
>  typedef enum FeatureWord {
>      FEAT_1_EDX,         /* CPUID[1].EDX */
> @@ -541,6 +551,8 @@ typedef enum FeatureWord {
>      FEAT_VMX_EPT_VPID_CAPS,
>      FEAT_VMX_BASIC,
>      FEAT_VMX_VMFUNC,
> +    FEAT_XSAVE_XSS_LO,     /* CPUID[EAX=0xd,ECX=1].ECX */
> +    FEAT_XSAVE_XSS_HI,     /* CPUID[EAX=0xd,ECX=1].EDX */
>      FEATURE_WORDS,
>  } FeatureWord;
>  
> -- 
> 2.26.2
> 
> 

-- 
Eduardo



  reply	other threads:[~2021-05-06 22:16 UTC|newest]

Thread overview: 11+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2021-02-26  2:20 [PATCH v7 0/6] Enable CET support for guest Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 1/6] target/i386: Change XSAVE related feature-word names Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 2/6] target/i386: Enable XSS feature enumeration for CPUID Yang Weijiang
2021-05-06 22:16   ` Eduardo Habkost [this message]
2021-05-06 22:16     ` Eduardo Habkost
2021-05-07  6:25     ` Yang Weijiang
2021-05-07  6:25       ` Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 3/6] target/i386: Enable CET components support for XSAVES Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 4/6] target/i386: Add user-space MSR access interface for CET Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 5/6] target/i386: Add CET state support for guest migration Yang Weijiang
2021-02-26  2:20 ` [PATCH v7 6/6] target/i386: Advise CET bits in CPU/MSR feature words Yang Weijiang

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20210506221647.zaq4or66rqspxssb@habkost.net \
    --to=ehabkost@redhat.com \
    --cc=kvm@vger.kernel.org \
    --cc=mtosatti@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=richard.henderson@linaro.org \
    --cc=sean.j.christopherson@intel.com \
    --cc=weijiang.yang@intel.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.