From: Tu Dinh <ngoc-tu.dinh@vates.tech>
Expose ARCH_LBR feature to guests.
Extend CPU featureset with 3 words for CPUID leaf 0x1c.
Signed-off-by: Tu Dinh <ngoc-tu.dinh@vates.tech>
---
tools/libs/guest/xg_cpuid_x86.c | 2 +-
tools/misc/xen-cpuid.c | 3 ++
xen/arch/x86/cpu-policy.c | 3 ++
xen/arch/x86/cpu/common.c | 7 ++++
xen/include/public/arch-x86/cpufeatureset.h | 28 ++++++++++++++-
xen/include/xen/lib/x86/cpu-policy.h | 38 ++++++++++++++++++++-
xen/lib/x86/cpuid.c | 6 ++++
7 files changed, 84 insertions(+), 3 deletions(-)
diff --git a/tools/libs/guest/xg_cpuid_x86.c b/tools/libs/guest/xg_cpuid_x86.c
index 4453178100..64d9baa538 100644
--- a/tools/libs/guest/xg_cpuid_x86.c
+++ b/tools/libs/guest/xg_cpuid_x86.c
@@ -656,7 +656,7 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore,
p->policy.feat.mpx = test_bit(X86_FEATURE_MPX, host_featureset);
}
- p->policy.basic.max_leaf = min(p->policy.basic.max_leaf, 0xdu);
+ p->policy.basic.max_leaf = min(p->policy.basic.max_leaf, 0x1cu);
p->policy.feat.max_subleaf = 0;
p->policy.extd.max_leaf = min(p->policy.extd.max_leaf, 0x8000001c);
}
diff --git a/tools/misc/xen-cpuid.c b/tools/misc/xen-cpuid.c
index 4c4593528d..4f0fb0a6ea 100644
--- a/tools/misc/xen-cpuid.c
+++ b/tools/misc/xen-cpuid.c
@@ -37,6 +37,9 @@ static const struct {
{ "CPUID 0x00000007:1.edx", "7d1" },
{ "MSR_ARCH_CAPS.lo", "m10Al" },
{ "MSR_ARCH_CAPS.hi", "m10Ah" },
+ { "CPUID 0x0000001c.eax", "1Ca" },
+ { "CPUID 0x0000001c.ebx", "1Cb" },
+ { "CPUID 0x0000001c.ecx", "1Cc" },
};
#define COL_ALIGN "24"
diff --git a/xen/arch/x86/cpu-policy.c b/xen/arch/x86/cpu-policy.c
index 78bc9872b0..cf6b212fb6 100644
--- a/xen/arch/x86/cpu-policy.c
+++ b/xen/arch/x86/cpu-policy.c
@@ -271,6 +271,8 @@ static void recalculate_misc(struct cpu_policy *p)
p->basic.raw[0xc] = EMPTY_LEAF;
+ zero_leaves(p->basic.raw, 0xe, 0x1b);
+
p->extd.e1d &= ~CPUID_COMMON_1D_FEATURES;
/* Most of Power/RAS hidden from guests. */
@@ -303,6 +305,7 @@ static void recalculate_misc(struct cpu_policy *p)
zero_leaves(p->basic.raw, 0x2, 0x3);
memset(p->cache.raw, 0, sizeof(p->cache.raw));
zero_leaves(p->basic.raw, 0x9, 0xa);
+ p->basic.raw[0x1c] = EMPTY_LEAF;
p->extd.vendor_ebx = p->basic.vendor_ebx;
p->extd.vendor_ecx = p->basic.vendor_ecx;
diff --git a/xen/arch/x86/cpu/common.c b/xen/arch/x86/cpu/common.c
index 067d855bad..4c8eb188e9 100644
--- a/xen/arch/x86/cpu/common.c
+++ b/xen/arch/x86/cpu/common.c
@@ -505,6 +505,13 @@ static void generic_identify(struct cpuinfo_x86 *c)
&c->x86_capability[FEATURESET_Da1],
&tmp, &tmp, &tmp);
+ if (c->cpuid_level >= 0x1c)
+ cpuid(0x1c,
+ &c->x86_capability[FEATURESET_1Ca],
+ &c->x86_capability[FEATURESET_1Cb],
+ &c->x86_capability[FEATURESET_1Cc],
+ &tmp);
+
if (test_bit(X86_FEATURE_ARCH_CAPS, c->x86_capability))
rdmsr(MSR_ARCH_CAPABILITIES,
c->x86_capability[FEATURESET_m10Al],
diff --git a/xen/include/public/arch-x86/cpufeatureset.h b/xen/include/public/arch-x86/cpufeatureset.h
index 8fa3fb711a..9304856fba 100644
--- a/xen/include/public/arch-x86/cpufeatureset.h
+++ b/xen/include/public/arch-x86/cpufeatureset.h
@@ -284,7 +284,7 @@ XEN_CPUFEATURE(SERIALIZE, 9*32+14) /*A SERIALIZE insn */
XEN_CPUFEATURE(HYBRID, 9*32+15) /* Heterogeneous platform */
XEN_CPUFEATURE(TSXLDTRK, 9*32+16) /*a TSX load tracking suspend/resume insns */
XEN_CPUFEATURE(PCONFIG, 9*32+18) /* PCONFIG instruction */
-XEN_CPUFEATURE(ARCH_LBR, 9*32+19) /* Architectural Last Branch Record */
+XEN_CPUFEATURE(ARCH_LBR, 9*32+19) /*S Architectural Last Branch Record */
XEN_CPUFEATURE(CET_IBT, 9*32+20) /* CET - Indirect Branch Tracking */
XEN_CPUFEATURE(AMX_BF16, 9*32+22) /* AMX BFloat16 instruction */
XEN_CPUFEATURE(AVX512_FP16, 9*32+23) /*A AVX512 FP16 instructions */
@@ -379,6 +379,32 @@ XEN_CPUFEATURE(RFDS_CLEAR, 16*32+28) /*!A| Register File(s) cleared by V
/* Intel-defined CPU features, MSR_ARCH_CAPS 0x10a.edx, word 17 */
+/* Intel-defined CPU features, CPUID level 0x0000001c.eax, word 18 */
+XEN_CPUFEATURE(LBR_DEPTH_8, 18*32+ 0) /*S Depth 8 */
+XEN_CPUFEATURE(LBR_DEPTH_16, 18*32+ 1) /*S Depth 16 */
+XEN_CPUFEATURE(LBR_DEPTH_24, 18*32+ 2) /*S Depth 24 */
+XEN_CPUFEATURE(LBR_DEPTH_32, 18*32+ 3) /*S Depth 32 */
+XEN_CPUFEATURE(LBR_DEPTH_40, 18*32+ 4) /*S Depth 40 */
+XEN_CPUFEATURE(LBR_DEPTH_48, 18*32+ 5) /*S Depth 48 */
+XEN_CPUFEATURE(LBR_DEPTH_56, 18*32+ 6) /*S Depth 56 */
+XEN_CPUFEATURE(LBR_DEPTH_64, 18*32+ 7) /*S Depth 64 */
+XEN_CPUFEATURE(LBR_DCST_RST, 18*32+30) /*S Deep C-state reset */
+XEN_CPUFEATURE(LBR_LIP, 18*32+31) /*S IP is linear IP */
+
+/* Intel-defined CPU features, CPUID level 0x0000001c.ebx, word 19 */
+XEN_CPUFEATURE(LBR_CPL_FILTER, 19*32+ 0) /*S CPL filtering */
+XEN_CPUFEATURE(LBR_BR_FILTER, 19*32+ 1) /*S Branch filtering */
+XEN_CPUFEATURE(LBR_CALL_STACK_MODE, 19*32+ 2) /*S Call stack mode */
+
+/* Intel-defined CPU features, CPUID level 0x0000001c.ecx, word 20 */
+XEN_CPUFEATURE(LBR_MISPRED, 20*32+ 0) /*S Mispredict mode */
+XEN_CPUFEATURE(LBR_TIMED, 20*32+ 1) /*S Timed mode */
+XEN_CPUFEATURE(LBR_BR_TYPE, 20*32+ 2) /*S Branch type */
+XEN_CPUFEATURE(LBR_EVT_FMT0, 20*32+16) /*!S Event type format bit 0 */
+XEN_CPUFEATURE(LBR_EVT_FMT1, 20*32+17) /*!S Event type format bit 1 */
+XEN_CPUFEATURE(LBR_EVT_FMT2, 20*32+18) /*!S Event type format bit 2 */
+XEN_CPUFEATURE(LBR_EVT_FMT3, 20*32+19) /*!S Event type format bit 3 */
+
#endif /* XEN_CPUFEATURE */
/* Clean up from a default include. Close the enum (for C). */
diff --git a/xen/include/xen/lib/x86/cpu-policy.h b/xen/include/xen/lib/x86/cpu-policy.h
index f43e1a3b21..afd66b4158 100644
--- a/xen/include/xen/lib/x86/cpu-policy.h
+++ b/xen/include/xen/lib/x86/cpu-policy.h
@@ -22,6 +22,9 @@
#define FEATURESET_7d1 15 /* 0x00000007:1.edx */
#define FEATURESET_m10Al 16 /* 0x0000010a.eax */
#define FEATURESET_m10Ah 17 /* 0x0000010a.edx */
+#define FEATURESET_1Ca 18 /* 0x0000001c.eax */
+#define FEATURESET_1Cb 19 /* 0x0000001c.ebx */
+#define FEATURESET_1Cc 20 /* 0x0000001c.ecx */
struct cpuid_leaf
{
@@ -85,7 +88,7 @@ unsigned int x86_cpuid_lookup_vendor(uint32_t ebx, uint32_t ecx, uint32_t edx);
*/
const char *x86_cpuid_vendor_to_str(unsigned int vendor);
-#define CPUID_GUEST_NR_BASIC (0xdu + 1)
+#define CPUID_GUEST_NR_BASIC (0x1cu + 1)
#define CPUID_GUEST_NR_CACHE (5u + 1)
#define CPUID_GUEST_NR_FEAT (2u + 1)
#define CPUID_GUEST_NR_TOPO (1u + 1)
@@ -158,6 +161,39 @@ struct cpu_policy
uint64_t :64, :64; /* Leaf 0xb - Topology. */
uint64_t :64, :64; /* Leaf 0xc - rsvd */
uint64_t :64, :64; /* Leaf 0xd - XSTATE. */
+
+ uint64_t :64, :64; /* Leaf 0xe - rsvd */
+ uint64_t :64, :64; /* Leaf 0xf - rsvd */
+ uint64_t :64, :64; /* Leaf 0x10 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x11 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x12 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x13 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x14 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x15 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x16 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x17 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x18 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x19 - rsvd */
+ uint64_t :64, :64; /* Leaf 0x1a - rsvd */
+ uint64_t :64, :64; /* Leaf 0x1b - rsvd */
+
+ union {
+ uint32_t _1Ca;
+ struct {
+ uint32_t supported_depths:8;
+ uint32_t :22;
+ uint32_t deep_cstate_reset:1;
+ uint32_t ip_contains_lip:1;
+ };
+ };
+ union {
+ uint32_t _1Cb;
+ struct { DECL_BITFIELD(1Cb); };
+ };
+ union {
+ uint32_t _1Cc;
+ struct { DECL_BITFIELD(1Cc); };
+ };
};
} basic;
diff --git a/xen/lib/x86/cpuid.c b/xen/lib/x86/cpuid.c
index eb7698dc73..4d19349b17 100644
--- a/xen/lib/x86/cpuid.c
+++ b/xen/lib/x86/cpuid.c
@@ -81,6 +81,9 @@ void x86_cpu_policy_to_featureset(
fs[FEATURESET_7d1] = p->feat._7d1;
fs[FEATURESET_m10Al] = p->arch_caps.lo;
fs[FEATURESET_m10Ah] = p->arch_caps.hi;
+ fs[FEATURESET_1Ca] = p->basic._1Ca;
+ fs[FEATURESET_1Cb] = p->basic._1Cb;
+ fs[FEATURESET_1Cc] = p->basic._1Cc;
}
void x86_cpu_featureset_to_policy(
@@ -104,6 +107,9 @@ void x86_cpu_featureset_to_policy(
p->feat._7d1 = fs[FEATURESET_7d1];
p->arch_caps.lo = fs[FEATURESET_m10Al];
p->arch_caps.hi = fs[FEATURESET_m10Ah];
+ p->basic._1Ca = fs[FEATURESET_1Ca];
+ p->basic._1Cb = fs[FEATURESET_1Cb];
+ p->basic._1Cc = fs[FEATURESET_1Cc];
}
void x86_cpu_policy_recalc_synth(struct cpu_policy *p)
--
2.43.0
Ngoc Tu Dinh | Vates XCP-ng Developer
XCP-ng & Xen Orchestra - Vates solutions
web: https://vates.tech
On 18.11.2024 09:49, ngoc-tu.dinh@vates.tech wrote: > --- a/tools/libs/guest/xg_cpuid_x86.c > +++ b/tools/libs/guest/xg_cpuid_x86.c > @@ -656,7 +656,7 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore, > p->policy.feat.mpx = test_bit(X86_FEATURE_MPX, host_featureset); > } > > - p->policy.basic.max_leaf = min(p->policy.basic.max_leaf, 0xdu); > + p->policy.basic.max_leaf = min(p->policy.basic.max_leaf, 0x1cu); > p->policy.feat.max_subleaf = 0; > p->policy.extd.max_leaf = min(p->policy.extd.max_leaf, 0x8000001c); > } When I saw this change I took note of there being an omission in the AVX10 series I'm carrying. Yet now that I wanted to make the adjustment there, I found that this code needs leaving alone (also in your case). Please see the comment at the top of the enclosing if(). Jan
On 18.11.2024 09:49, ngoc-tu.dinh@vates.tech wrote: > From: Tu Dinh <ngoc-tu.dinh@vates.tech> > > Expose ARCH_LBR feature to guests. > > Extend CPU featureset with 3 words for CPUID leaf 0x1c. > > Signed-off-by: Tu Dinh <ngoc-tu.dinh@vates.tech> First a general remark: Please Cc maintainers on patch submissions. > --- a/tools/libs/guest/xg_cpuid_x86.c > +++ b/tools/libs/guest/xg_cpuid_x86.c > @@ -656,7 +656,7 @@ int xc_cpuid_apply_policy(xc_interface *xch, uint32_t domid, bool restore, > p->policy.feat.mpx = test_bit(X86_FEATURE_MPX, host_featureset); > } > > - p->policy.basic.max_leaf = min(p->policy.basic.max_leaf, 0xdu); > + p->policy.basic.max_leaf = min(p->policy.basic.max_leaf, 0x1cu); We'll need to update this again and again (AMXC, AVX10) if we continue using literal numbers here. This wants switching to ARRAY_SIZE(), and imo ideally in a separate prereq patch (which could likely go straight in). > --- a/tools/misc/xen-cpuid.c > --- a/xen/arch/x86/cpu-policy.c > +++ b/xen/arch/x86/cpu-policy.c > @@ -271,6 +271,8 @@ static void recalculate_misc(struct cpu_policy *p) > > p->basic.raw[0xc] = EMPTY_LEAF; > > + zero_leaves(p->basic.raw, 0xe, 0x1b); > + > p->extd.e1d &= ~CPUID_COMMON_1D_FEATURES; > > /* Most of Power/RAS hidden from guests. */ > @@ -303,6 +305,7 @@ static void recalculate_misc(struct cpu_policy *p) > zero_leaves(p->basic.raw, 0x2, 0x3); > memset(p->cache.raw, 0, sizeof(p->cache.raw)); > zero_leaves(p->basic.raw, 0x9, 0xa); > + p->basic.raw[0x1c] = EMPTY_LEAF; I'm not convinced this wants to live here. The leaf rather wants clearing when the feature isn't there in the policy. See e.g. [1] and [2]. > --- a/xen/arch/x86/cpu/common.c > +++ b/xen/arch/x86/cpu/common.c > @@ -505,6 +505,13 @@ static void generic_identify(struct cpuinfo_x86 *c) > &c->x86_capability[FEATURESET_Da1], > &tmp, &tmp, &tmp); > > + if (c->cpuid_level >= 0x1c) > + cpuid(0x1c, > + &c->x86_capability[FEATURESET_1Ca], > + &c->x86_capability[FEATURESET_1Cb], > + &c->x86_capability[FEATURESET_1Cc], > + &tmp); Nit: Indentation (arguments want to align vertically). > --- a/xen/include/public/arch-x86/cpufeatureset.h > +++ b/xen/include/public/arch-x86/cpufeatureset.h > @@ -284,7 +284,7 @@ XEN_CPUFEATURE(SERIALIZE, 9*32+14) /*A SERIALIZE insn */ > XEN_CPUFEATURE(HYBRID, 9*32+15) /* Heterogeneous platform */ > XEN_CPUFEATURE(TSXLDTRK, 9*32+16) /*a TSX load tracking suspend/resume insns */ > XEN_CPUFEATURE(PCONFIG, 9*32+18) /* PCONFIG instruction */ > -XEN_CPUFEATURE(ARCH_LBR, 9*32+19) /* Architectural Last Branch Record */ > +XEN_CPUFEATURE(ARCH_LBR, 9*32+19) /*S Architectural Last Branch Record */ 'S' is too early. You first need to implement everything, and only then you can make the feature visible to guests. It'll also only be by that time that it'll be (halfway) clear whether 'S' is appropriate, or whether for starters it wouldn't better be 's'. Same for the other markers below. Jan
© 2016 - 2026 Red Hat, Inc.