From 714abb122a2cc4819b05a3893dfd2c61a9204c5e Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Fri, 18 Jul 2025 18:03:48 +0200 Subject: [PATCH 076/115] i386/tdx: Add supported CPUID bits relates to XFAM RH-Author: Paolo Bonzini RH-MergeRequest: 391: TDX support, including attestation and device assignment RH-Jira: RHEL-15710 RHEL-20798 RHEL-49728 RH-Acked-by: Yash Mankad RH-Acked-by: Peter Xu RH-Acked-by: David Hildenbrand RH-Commit: [76/115] 459d99074c90bfd8048585dec42749cb18493ee9 (bonzini/rhel-qemu-kvm) Some CPUID bits are controlled by XFAM. They are not covered by tdx_caps.cpuid (which only contians the directly configurable bits), but they are actually supported when the related XFAM bit is supported. Add these XFAM controlled bits to TDX supported CPUID bits based on the supported_xfam. Besides, incorporate the supported_xfam into the supported CPUID leaf of 0xD. Signed-off-by: Xiaoyao Li Link: https://lore.kernel.org/r/20250508150002.689633-48-xiaoyao.li@intel.com Signed-off-by: Paolo Bonzini (cherry picked from commit 8c94c84cb9e0140b48acc9c9d404525ca7ef7457) Signed-off-by: Paolo Bonzini --- target/i386/cpu.c | 12 ------- target/i386/cpu.h | 16 ++++++++++ target/i386/kvm/tdx.c | 73 +++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 89 insertions(+), 12 deletions(-) diff --git a/target/i386/cpu.c b/target/i386/cpu.c index 2da456da64..cd6d9e8c1c 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -1660,15 +1660,6 @@ bool is_feature_word_cpuid(uint32_t feature, uint32_t index, int reg) return false; } -typedef struct FeatureMask { - FeatureWord index; - uint64_t mask; -} FeatureMask; - -typedef struct FeatureDep { - FeatureMask from, to; -} FeatureDep; - static FeatureDep feature_dependencies[] = { { .from = { FEAT_7_0_EDX, CPUID_7_0_EDX_ARCH_CAPABILITIES }, @@ -1837,9 +1828,6 @@ static const X86RegisterInfo32 x86_reg_info_32[CPU_NB_REGS32] = { }; #undef REGISTER -/* CPUID feature bits available in XSS */ -#define CPUID_XSTATE_XSS_MASK (XSTATE_ARCH_LBR_MASK) - ExtSaveArea x86_ext_save_areas[XSAVE_STATE_AREA_COUNT] = { [XSTATE_FP_BIT] = { /* x87 FP state component is always enabled if XSAVE is supported */ diff --git a/target/i386/cpu.h b/target/i386/cpu.h index e02cb75619..3a7a409809 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -589,6 +589,7 @@ typedef enum X86Seg { #define XSTATE_OPMASK_BIT 5 #define XSTATE_ZMM_Hi256_BIT 6 #define XSTATE_Hi16_ZMM_BIT 7 +#define XSTATE_PT_BIT 8 #define XSTATE_PKRU_BIT 9 #define XSTATE_ARCH_LBR_BIT 15 #define XSTATE_XTILE_CFG_BIT 17 @@ -602,6 +603,7 @@ typedef enum X86Seg { #define XSTATE_OPMASK_MASK (1ULL << XSTATE_OPMASK_BIT) #define XSTATE_ZMM_Hi256_MASK (1ULL << XSTATE_ZMM_Hi256_BIT) #define XSTATE_Hi16_ZMM_MASK (1ULL << XSTATE_Hi16_ZMM_BIT) +#define XSTATE_PT_MASK (1ULL << XSTATE_PT_BIT) #define XSTATE_PKRU_MASK (1ULL << XSTATE_PKRU_BIT) #define XSTATE_ARCH_LBR_MASK (1ULL << XSTATE_ARCH_LBR_BIT) #define XSTATE_XTILE_CFG_MASK (1ULL << XSTATE_XTILE_CFG_BIT) @@ -624,6 +626,11 @@ typedef enum X86Seg { XSTATE_Hi16_ZMM_MASK | XSTATE_PKRU_MASK | \ XSTATE_XTILE_CFG_MASK | XSTATE_XTILE_DATA_MASK) +/* CPUID feature bits available in XSS */ +#define CPUID_XSTATE_XSS_MASK (XSTATE_ARCH_LBR_MASK) + +#define CPUID_XSTATE_MASK (CPUID_XSTATE_XCR0_MASK | CPUID_XSTATE_XSS_MASK) + /* CPUID feature words */ typedef enum FeatureWord { FEAT_1_EDX, /* CPUID[1].EDX */ @@ -671,6 +678,15 @@ typedef enum FeatureWord { FEATURE_WORDS, } FeatureWord; +typedef struct FeatureMask { + FeatureWord index; + uint64_t mask; +} FeatureMask; + +typedef struct FeatureDep { + FeatureMask from, to; +} FeatureDep; + typedef uint64_t FeatureWordArray[FEATURE_WORDS]; uint64_t x86_cpu_get_supported_feature_word(X86CPU *cpu, FeatureWord w); diff --git a/target/i386/kvm/tdx.c b/target/i386/kvm/tdx.c index 60dd239c05..feb9cd7466 100644 --- a/target/i386/kvm/tdx.c +++ b/target/i386/kvm/tdx.c @@ -23,6 +23,8 @@ #include +#include "cpu.h" +#include "cpu-internal.h" #include "hw/i386/e820_memory_layout.h" #include "hw/i386/tdvf.h" #include "hw/i386/x86.h" @@ -486,6 +488,32 @@ static TdxAttrsMap tdx_attrs_maps[] = { .feat_mask = CPUID_7_0_ECX_KeyLocker,}, }; +typedef struct TdxXFAMDep { + int xfam_bit; + FeatureMask feat_mask; +} TdxXFAMDep; + +/* + * Note, only the CPUID bits whose virtualization type are "XFAM & Native" are + * defiend here. + * + * For those whose virtualization type are "XFAM & Configured & Native", they + * are reported as configurable bits. And they are not supported if not in the + * configureable bits list from KVM even if the corresponding XFAM bit is + * supported. + */ +TdxXFAMDep tdx_xfam_deps[] = { + { XSTATE_YMM_BIT, { FEAT_1_ECX, CPUID_EXT_FMA }}, + { XSTATE_YMM_BIT, { FEAT_7_0_EBX, CPUID_7_0_EBX_AVX2 }}, + { XSTATE_OPMASK_BIT, { FEAT_7_0_ECX, CPUID_7_0_ECX_AVX512_VBMI}}, + { XSTATE_OPMASK_BIT, { FEAT_7_0_EDX, CPUID_7_0_EDX_AVX512_FP16}}, + { XSTATE_PT_BIT, { FEAT_7_0_EBX, CPUID_7_0_EBX_INTEL_PT}}, + { XSTATE_PKRU_BIT, { FEAT_7_0_ECX, CPUID_7_0_ECX_PKU}}, + { XSTATE_XTILE_CFG_BIT, { FEAT_7_0_EDX, CPUID_7_0_EDX_AMX_BF16 }}, + { XSTATE_XTILE_CFG_BIT, { FEAT_7_0_EDX, CPUID_7_0_EDX_AMX_TILE }}, + { XSTATE_XTILE_CFG_BIT, { FEAT_7_0_EDX, CPUID_7_0_EDX_AMX_INT8 }}, +}; + static struct kvm_cpuid_entry2 *find_in_supported_entry(uint32_t function, uint32_t index) { @@ -553,6 +581,50 @@ static void tdx_add_supported_cpuid_by_attrs(void) } } +static void tdx_add_supported_cpuid_by_xfam(void) +{ + struct kvm_cpuid_entry2 *e; + int i; + + const TdxXFAMDep *xfam_dep; + const FeatureWordInfo *f; + for (i = 0; i < ARRAY_SIZE(tdx_xfam_deps); i++) { + xfam_dep = &tdx_xfam_deps[i]; + if (!((1ULL << xfam_dep->xfam_bit) & tdx_caps->supported_xfam)) { + continue; + } + + f = &feature_word_info[xfam_dep->feat_mask.index]; + if (f->type != CPUID_FEATURE_WORD) { + continue; + } + + e = find_in_supported_entry(f->cpuid.eax, f->cpuid.ecx); + switch(f->cpuid.reg) { + case R_EAX: + e->eax |= xfam_dep->feat_mask.mask; + break; + case R_EBX: + e->ebx |= xfam_dep->feat_mask.mask; + break; + case R_ECX: + e->ecx |= xfam_dep->feat_mask.mask; + break; + case R_EDX: + e->edx |= xfam_dep->feat_mask.mask; + break; + } + } + + e = find_in_supported_entry(0xd, 0); + e->eax |= (tdx_caps->supported_xfam & CPUID_XSTATE_XCR0_MASK); + e->edx |= (tdx_caps->supported_xfam & CPUID_XSTATE_XCR0_MASK) >> 32; + + e = find_in_supported_entry(0xd, 1); + e->ecx |= (tdx_caps->supported_xfam & CPUID_XSTATE_XSS_MASK); + e->edx |= (tdx_caps->supported_xfam & CPUID_XSTATE_XSS_MASK) >> 32; +} + static void tdx_setup_supported_cpuid(void) { if (tdx_supported_cpuid) { @@ -568,6 +640,7 @@ static void tdx_setup_supported_cpuid(void) tdx_add_supported_cpuid_by_fixed1_bits(); tdx_add_supported_cpuid_by_attrs(); + tdx_add_supported_cpuid_by_xfam(); } static int tdx_kvm_init(ConfidentialGuestSupport *cgs, Error **errp) -- 2.50.1