[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[PATCH v4 19/28] x86/CPUID: TMUL subleaf 1


  • To: "xen-devel@xxxxxxxxxxxxxxxxxxxx" <xen-devel@xxxxxxxxxxxxxxxxxxxx>
  • From: Jan Beulich <jbeulich@xxxxxxxx>
  • Date: Wed, 11 Nov 2026 16:15:53 +0100
  • Authentication-results: eu.smtp.expurgate.cloud; dkim=pass header.s=google header.d=suse.com header.i="@suse.com" header.h="Content-Transfer-Encoding:Content-Type:In-Reply-To:Autocrypt:Content-Language:References:Cc:To:From:Subject:User-Agent:MIME-Version:Date:Message-ID"
  • Autocrypt: addr=jbeulich@xxxxxxxx; keydata= xsDiBFk3nEQRBADAEaSw6zC/EJkiwGPXbWtPxl2xCdSoeepS07jW8UgcHNurfHvUzogEq5xk hu507c3BarVjyWCJOylMNR98Yd8VqD9UfmX0Hb8/BrA+Hl6/DB/eqGptrf4BSRwcZQM32aZK 7Pj2XbGWIUrZrd70x1eAP9QE3P79Y2oLrsCgbZJfEwCgvz9JjGmQqQkRiTVzlZVCJYcyGGsD /0tbFCzD2h20ahe8rC1gbb3K3qk+LpBtvjBu1RY9drYk0NymiGbJWZgab6t1jM7sk2vuf0Py O9Hf9XBmK0uE9IgMaiCpc32XV9oASz6UJebwkX+zF2jG5I1BfnO9g7KlotcA/v5ClMjgo6Gl MDY4HxoSRu3i1cqqSDtVlt+AOVBJBACrZcnHAUSuCXBPy0jOlBhxPqRWv6ND4c9PH1xjQ3NP nxJuMBS8rnNg22uyfAgmBKNLpLgAGVRMZGaGoJObGf72s6TeIqKJo/LtggAS9qAUiuKVnygo 3wjfkS9A3DRO+SpU7JqWdsveeIQyeyEJ/8PTowmSQLakF+3fote9ybzd880fSmFuIEJldWxp Y2ggPGpiZXVsaWNoQHN1c2UuY29tPsJgBBMRAgAgBQJZN5xEAhsDBgsJCAcDAgQVAggDBBYC AwECHgECF4AACgkQoDSui/t3IH4J+wCfQ5jHdEjCRHj23O/5ttg9r9OIruwAn3103WUITZee e7Sbg12UgcQ5lv7SzsFNBFk3nEQQCACCuTjCjFOUdi5Nm244F+78kLghRcin/awv+IrTcIWF hUpSs1Y91iQQ7KItirz5uwCPlwejSJDQJLIS+QtJHaXDXeV6NI0Uef1hP20+y8qydDiVkv6l IreXjTb7DvksRgJNvCkWtYnlS3mYvQ9NzS9PhyALWbXnH6sIJd2O9lKS1Mrfq+y0IXCP10eS FFGg+Av3IQeFatkJAyju0PPthyTqxSI4lZYuJVPknzgaeuJv/2NccrPvmeDg6Coe7ZIeQ8Yj t0ARxu2xytAkkLCel1Lz1WLmwLstV30g80nkgZf/wr+/BXJW/oIvRlonUkxv+IbBM3dX2OV8 AmRv1ySWPTP7AAMFB/9PQK/VtlNUJvg8GXj9ootzrteGfVZVVT4XBJkfwBcpC/XcPzldjv+3 HYudvpdNK3lLujXeA5fLOH+Z/G9WBc5pFVSMocI71I8bT8lIAzreg0WvkWg5V2WZsUMlnDL9 mpwIGFhlbM3gfDMs7MPMu8YQRFVdUvtSpaAs8OFfGQ0ia3LGZcjA6Ik2+xcqscEJzNH+qh8V m5jjp28yZgaqTaRbg3M/+MTbMpicpZuqF4rnB0AQD12/3BNWDR6bmh+EkYSMcEIpQmBM51qM EKYTQGybRCjpnKHGOxG0rfFY1085mBDZCH5Kx0cl0HVJuQKC+dV2ZY5AqjcKwAxpE75MLFkr wkkEGBECAAkFAlk3nEQCGwwACgkQoDSui/t3IH7nnwCfcJWUDUFKdCsBH/E5d+0ZnMQi+G0A nAuWpQkjM1ASeQwSHEeAWPgskBQL
  • Cc: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>, Teddy Astie <teddy.astie@xxxxxxxxxx>, Roger Pau Monné <roger@xxxxxxxxxxxxxx>
  • Delivery-date: Wed, 11 Nov 2026 15:15:57 +0000
  • List-id: Xen developer discussion <xen-devel.lists.xenproject.org>

EAX holds yet another set of feature bits. Sadly some duplicate pre-
existing bits in the feature subleaves.

Note that the dependency on just AVX512F (and not AVX10) is sufficient,
as long as we synthesize AVX512* when we find AVX10 available.

Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
---
RFC: The handling of the duplicated bits is minimal so far. Where / how
     the syncing between both instances should happen is tbd. The naming
     of the duplicate bits is also subject to better suggestions.
---
v4: New.

--- a/tools/libs/light/libxl_cpuid.c
+++ b/tools/libs/light/libxl_cpuid.c
@@ -345,6 +345,7 @@ int libxl_cpuid_parse_config(libxl_cpuid
         CPUID_ENTRY(0x80000021, NA, CPUID_REG_ECX),
         CPUID_ENTRY(0x00000024,  1, CPUID_REG_ECX),
         CPUID_ENTRY(0x00000029,  0, CPUID_REG_EBX),
+        CPUID_ENTRY(0x0000001e,  1, CPUID_REG_EAX),
 #undef MSR_ENTRY
 #undef CPUID_ENTRY
     };
--- a/tools/misc/xen-cpuid.c
+++ b/tools/misc/xen-cpuid.c
@@ -40,6 +40,7 @@ static const struct {
     { "CPUID 0x80000021.ecx",      "e21c" },
     { "CPUID 0x00000024:1.ecx",    "24c1" },
     { "CPUID 0x00000029:0.ebx",    "29b0" },
+    { "CPUID 0x0000001e:1.eax",    "1Ea1" },
 };
 
 #define COL_ALIGN "24"
--- a/tools/tests/cpu-policy/test-cpu-policy.c
+++ b/tools/tests/cpu-policy/test-cpu-policy.c
@@ -218,7 +218,7 @@ static void test_cpuid_serialise_success
             .nr_leaves = 4 + 0x1d + 1 + 1,
         },
 
-        /* Leaf 0x1e serialisation stops at 0. */
+        /* Leaf 0x1e serialisation stops at max_subleaf. */
         {
             .name = "empty leaf 0x1e",
             .p = {
@@ -230,9 +230,10 @@ static void test_cpuid_serialise_success
             .name = "partial leaf 0x1e",
             .p = {
                 .basic.max_leaf = 0x1e,
+                .tmul.max_subleaf = 1,
                 .tmul.maxk = 16,
             },
-            .nr_leaves = 4 + 0x1e + 1,
+            .nr_leaves = 4 + 0x1e + 1 + 1,
         },
     };
 
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -594,6 +594,16 @@ void identify_cpu(struct cpuinfo_x86 *c)
                            &c->x86_capability[FEATURESET_Da1],
                            &tmp, &tmp, &tmp);
 
+       if (cpu_has(c, X86_FEATURE_AMX_TILE) && c->cpuid_level >= 0x1e) {
+               uint32_t max_subleaf;
+
+               cpuid_count(0x1e, 0, &max_subleaf, &tmp, &tmp, &tmp);
+               if (max_subleaf >= 1)
+                       cpuid_count(0x1e, 1,
+                                   &c->x86_capability[FEATURESET_1Ea1],
+                                   &tmp, &tmp, &tmp);
+       }
+
        if (cpu_has(c, X86_FEATURE_AVX10) && c->cpuid_level >= 0x24) {
                uint32_t max_subleaf;
 
--- a/xen/arch/x86/cpu-policy.c
+++ b/xen/arch/x86/cpu-policy.c
@@ -282,6 +282,10 @@ static void recalculate_tile(struct cpu_
     p->tmul.raw[0].b &= 0x00ffffff;
     p->tmul.raw[0].c = 0,
     p->tmul.raw[0].d = 0;
+
+    p->tmul.raw[1].b = 0;
+    p->tmul.raw[1].c = 0; 
+    p->tmul.raw[1].d = 0;
 }
 
 /*
--- a/xen/arch/x86/lib/cpu-policy/copy-to-buffer.c
+++ b/xen/arch/x86/lib/cpu-policy/copy-to-buffer.c
@@ -132,7 +132,8 @@ int x86_cpuid_copy_to_buffer(const struc
 
         case 0x1e:
             for ( subleaf = 0;
-                  subleaf <= ARRAY_SIZE(p->tmul.raw) - 1; ++subleaf )
+                  subleaf <= MIN(p->tmul.max_subleaf,
+                                 ARRAY_SIZE(p->tmul.raw) - 1); ++subleaf )
                 COPY_LEAF(leaf, subleaf, &p->tmul.raw[subleaf]);
             break;
 
--- a/xen/arch/x86/lib/cpu-policy/cpuid.c
+++ b/xen/arch/x86/lib/cpu-policy/cpuid.c
@@ -84,6 +84,7 @@ void x86_cpu_policy_to_featureset(
     fs[FEATURESET_e21c]      = p->extd.e21c;
     fs[FEATURESET_24c1]      = p->avx10._24c1;
     fs[FEATURESET_29b0]      = p->apx._29b0;
+    fs[FEATURESET_1Ea1]      = p->tmul._1Ea1;
 }
 
 void x86_cpu_featureset_to_policy(
@@ -110,6 +111,7 @@ void x86_cpu_featureset_to_policy(
     p->extd.e21c             = fs[FEATURESET_e21c];
     p->avx10._24c1           = fs[FEATURESET_24c1];
     p->apx._29b0             = fs[FEATURESET_29b0];
+    p->tmul._1Ea1            = fs[FEATURESET_1Ea1];
 }
 
 void x86_cpu_policy_recalc_synth(struct cpu_policy *p)
@@ -233,8 +235,14 @@ void x86_cpu_policy_fill_native(struct c
     }
 
     if ( p->basic.max_leaf >= 0x1e )
+    {
         cpuid_count_leaf(0x1e, 0, &p->tmul.raw[0]);
 
+        for ( i = 1; i <= MIN(p->tmul.max_subleaf,
+                              ARRAY_SIZE(p->tmul.raw) - 1); ++i )
+            cpuid_count_leaf(0x1e, i, &p->tmul.raw[i]);
+    }
+
     if ( p->basic.max_leaf >= 0x24 )
     {
         cpuid_count_leaf(0x24, 0, &p->avx10.raw[0]);
@@ -333,8 +341,12 @@ void x86_cpu_policy_clear_out_of_range_l
 
     if ( p->basic.max_leaf < 0x1e || !p->tile.max_palette ||
          (!p->feat.amx_int8 && !p->feat.amx_bf16 &&
-          !p->feat.amx_fp16 && !p->feat.amx_complex) )
+          !p->feat.amx_fp16 && !p->feat.amx_complex &&
+          !p->tmul._1Ea1) )
         memset(p->tmul.raw, 0, sizeof(p->tmul.raw));
+    else
+        zero_leaves(p->tmul.raw, p->tmul.max_subleaf + 1,
+                    ARRAY_SIZE(p->tmul.raw) - 1);
 
     if ( p->basic.max_leaf < 0x24 )
         memset(p->avx10.raw, 0, sizeof(p->avx10.raw));
@@ -356,6 +368,8 @@ void __init x86_cpu_policy_bound_max_lea
         min_t(uint32_t, p->feat.max_subleaf, ARRAY_SIZE(p->feat.raw) - 1);
     p->tile.max_palette =
         min_t(uint32_t, p->tile.max_palette, ARRAY_SIZE(p->tile.raw) - 1);
+    p->tmul.max_subleaf =
+        min_t(uint32_t, p->tmul.max_subleaf, ARRAY_SIZE(p->tmul.raw) - 1);
     p->avx10.max_subleaf =
         min_t(uint32_t, p->avx10.max_subleaf, ARRAY_SIZE(p->avx10.raw) - 1);
     p->apx.max_subleaf =
@@ -400,7 +414,12 @@ void x86_cpu_policy_shrink_max_leaves(st
     }
     p->basic.raw[0x1d] = p->tile.raw[0];
 
-    p->basic.raw[0x1e] = p->tmul.raw[0];
+    for ( i = p->tmul.max_subleaf; i; --i )
+        if ( p->tmul.raw[i].a | p->tmul.raw[i].b |
+             p->tmul.raw[i].c | p->tmul.raw[i].d )
+            break;
+    p->tmul.max_subleaf = i;
+    p->basic.raw[0x1e] = p->tmul.raw[i];
 
     p->basic.raw[0x24] = p->avx10.raw[0];
 
--- a/xen/arch/x86/lib/cpu-policy/policy.c
+++ b/xen/arch/x86/lib/cpu-policy/policy.c
@@ -41,8 +41,10 @@ int x86_cpu_policies_are_compatible(cons
             FAIL_CPUID(0x1d, 1);
     }
 
-    if ( ((guest->feat.amx_int8 || guest->feat.amx_bf16 ||
-           guest->feat.amx_fp16 || guest->feat.amx_complex) &&
+    if ( guest->tmul.max_subleaf > host->tmul.max_subleaf ||
+         ((guest->feat.amx_int8 || guest->feat.amx_bf16 ||
+           guest->feat.amx_fp16 || guest->feat.amx_complex ||
+           guest->tmul._1Ea1) &&
           (!guest->tmul.maxk || !guest->tmul.maxn)) ||
          guest->tmul.maxk > host->tmul.maxk ||
          guest->tmul.maxn > host->tmul.maxn )
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -419,6 +419,15 @@ XEN_CPUFEATURE(AVX10_V2_AUX,       19*32
 /* Intel-defined CPU features, CPUID level 0x00000029:0.ebx, word 20 */
 XEN_CPUFEATURE(APX_NCI_NDD_NF,     20*32+ 0) /*a  APX NCI/NDD/NF instruction 
forms */
 
+/* Intel-defined CPU features, CPUID level 0x0000001e:1.eax, word 21 */
+XEN_CPUFEATURE(AMX__INT8,          21*32+ 0) /*a  AMX-INT8 Instructions */
+XEN_CPUFEATURE(AMX__BF16,          21*32+ 1) /*a  AMX-BF16 Instructions */
+XEN_CPUFEATURE(AMX__COMPLEX,       21*32+ 2) /*a  AMX-COMPLEX Instructions */
+XEN_CPUFEATURE(AMX__FP16,          21*32+ 3) /*a  AMX-FP16 Instructions */
+XEN_CPUFEATURE(AMX_FP8,            21*32+ 4) /*   AMX-FP8 Instructions */
+XEN_CPUFEATURE(AMX_AVX512,         21*32+ 7) /*   AMX-AVX512 Instructions */
+XEN_CPUFEATURE(AMX_MOVRS,          21*32+ 8) /*   AMX-MOVRS Instructions */
+
 #endif /* XEN_CPUFEATURE */
 
 /* Clean up from a default include.  Close the enum (for C). */
--- a/xen/include/xen/lib/x86/cpu-policy.h
+++ b/xen/include/xen/lib/x86/cpu-policy.h
@@ -25,6 +25,7 @@
 #define FEATURESET_e21c      18 /* 0x80000021.ecx      */
 #define FEATURESET_24c1      19 /* 0x00000024:1.ecx    */
 #define FEATURESET_29b0      20 /* 0x00000029:0.ebx    */
+#define FEATURESET_1Ea1      21 /* 0x0000001e:1.eax    */
 
 struct cpuid_leaf
 {
@@ -67,7 +68,7 @@ const char *x86_cpuid_vendor_to_str(unsi
 #define CPUID_GUEST_NR_TOPO       (1u + 1)
 #define CPUID_GUEST_NR_XSTATE     (62u + 1)
 #define CPUID_GUEST_NR_PALETTE    (1u + 1)
-#define CPUID_GUEST_NR_TMUL       (0u + 1)
+#define CPUID_GUEST_NR_TMUL       (1u + 1)
 #define CPUID_GUEST_NR_AVX10      (1u + 1)
 #define CPUID_GUEST_NR_APX        (0u + 1)
 #define CPUID_GUEST_NR_EXTD_INTEL (0x8u + 1)
@@ -293,9 +294,16 @@ struct cpu_policy
         struct cpuid_leaf raw[CPUID_GUEST_NR_TMUL];
         struct {
             /* Subleaf 0. */
-            uint32_t /* a */:32;
+            uint32_t max_subleaf;
             uint32_t maxk:8, maxn:16, :8;
             uint32_t /* c */:32, /* d */:32;
+
+            /* Subleaf 1. */
+            union {
+                uint32_t _1Ea1;
+                struct { DECL_BITFIELD(1Ea1); };
+            };
+            uint32_t /* b */:32, /* c */:32, /* d */:32;
         };
     } tmul;
 
--- a/xen/tools/gen-cpuid.py
+++ b/xen/tools/gen-cpuid.py
@@ -302,7 +302,8 @@ def crunch_numbers(state):
         # AVX512 features are built on top of AVX512F
         AVX512F: [AVX512DQ, AVX512_IFMA, AVX512PF, AVX512ER, AVX512CD,
                   AVX512BW, AVX512VL, AVX512_4VNNIW, AVX512_4FMAPS,
-                  AVX512_VNNI, AVX512_VPOPCNTDQ, AVX512_VP2INTERSECT],
+                  AVX512_VNNI, AVX512_VPOPCNTDQ, AVX512_VP2INTERSECT,
+                  AMX_AVX512],
 
         # AVX512 extensions acting on vectors of bytes/words are made
         # dependents of AVX512BW (as to requiring wider than 16-bit mask
@@ -354,7 +355,8 @@ def crunch_numbers(state):
         # AMX-TILE means hardware support for tile registers and general non-
         # computational instructions.  All further AMX features are built on 
top
         # of AMX-TILE.
-        AMX_TILE: [AMX_BF16, AMX_INT8, AMX_FP16, AMX_COMPLEX],
+        AMX_TILE: [AMX_BF16, AMX_INT8, AMX_FP16, AMX_COMPLEX, AMX_FP8,
+                   AMX_AVX512, AMX_MOVRS],
 
         # APX discrete features.
         APX_F: [APX_NCI_NDD_NF],




 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.