[PATCH 4/8] perf/x86/uncore: Add L3 PMU support for Hygon family 18h model 6h
From: Fu Hao
Date: Fri Mar 27 2026 - 04:11:34 EST
Adjust the L3 PMU slicemask and threadmask for Hygon family 18h
model 6h processor.
Signed-off-by: Fu Hao <fuhao@xxxxxxxxxxxxxx>
---
arch/x86/events/amd/uncore.c | 48 ++++++++++++++++++++++++++++++-
arch/x86/include/asm/perf_event.h | 8 ++++++
2 files changed, 55 insertions(+), 1 deletion(-)
diff --git a/arch/x86/events/amd/uncore.c b/arch/x86/events/amd/uncore.c
index dd956cfca..e71d9e784 100644
--- a/arch/x86/events/amd/uncore.c
+++ b/arch/x86/events/amd/uncore.c
@@ -308,6 +308,14 @@ amd_f17h_uncore_is_visible(struct kobject *kobj, struct attribute *attr, int i)
attr->mode : 0;
}
+static umode_t
+hygon_f18h_m6h_uncore_is_visible(struct kobject *kobj, struct attribute *attr, int i)
+{
+ return boot_cpu_data.x86 == 0x18 &&
+ boot_cpu_data.x86_model >= 0x6 && boot_cpu_data.x86_model <= 0xf ?
+ attr->mode : 0;
+}
+
static umode_t
amd_f19h_uncore_is_visible(struct kobject *kobj, struct attribute *attr, int i)
{
@@ -359,6 +367,8 @@ DEFINE_UNCORE_FORMAT_ATTR(enallslices, enallslices, "config:46"); /* F19h L3
DEFINE_UNCORE_FORMAT_ATTR(enallcores, enallcores, "config:47"); /* F19h L3 */
DEFINE_UNCORE_FORMAT_ATTR(sliceid, sliceid, "config:48-50"); /* F19h L3 */
DEFINE_UNCORE_FORMAT_ATTR(rdwrmask, rdwrmask, "config:8-9"); /* PerfMonV2 UMC */
+DEFINE_UNCORE_FORMAT_ATTR(slicemask4, slicemask, "config:28-31"); /* F18h L3 */
+DEFINE_UNCORE_FORMAT_ATTR(threadmask32, threadmask, "config:32-63"); /* F18h L3 */
/* Common DF and NB attributes */
static struct attribute *amd_uncore_df_format_attr[] = {
@@ -388,6 +398,12 @@ static struct attribute *amd_f17h_uncore_l3_format_attr[] = {
NULL,
};
+/* F18h M06h unique L3 attributes */
+static struct attribute *hygon_f18h_m6h_uncore_l3_format_attr[] = {
+ &format_attr_slicemask4.attr, /* slicemask */
+ NULL,
+};
+
/* F19h unique L3 attributes */
static struct attribute *amd_f19h_uncore_l3_format_attr[] = {
&format_attr_coreid.attr, /* coreid */
@@ -413,6 +429,12 @@ static struct attribute_group amd_f17h_uncore_l3_format_group = {
.is_visible = amd_f17h_uncore_is_visible,
};
+static struct attribute_group hygon_f18h_m6h_uncore_l3_format_group = {
+ .name = "format",
+ .attrs = hygon_f18h_m6h_uncore_l3_format_attr,
+ .is_visible = hygon_f18h_m6h_uncore_is_visible,
+};
+
static struct attribute_group amd_f19h_uncore_l3_format_group = {
.name = "format",
.attrs = amd_f19h_uncore_l3_format_attr,
@@ -442,6 +464,11 @@ static const struct attribute_group *amd_uncore_l3_attr_update[] = {
NULL,
};
+static const struct attribute_group *hygon_uncore_l3_attr_update[] = {
+ &hygon_f18h_m6h_uncore_l3_format_group,
+ NULL,
+};
+
static const struct attribute_group *amd_uncore_umc_attr_groups[] = {
&amd_uncore_attr_group,
&amd_uncore_umc_format_group,
@@ -820,6 +847,12 @@ static int amd_uncore_l3_event_init(struct perf_event *event)
mask = AMD64_L3_F19H_THREAD_MASK | AMD64_L3_EN_ALL_SLICES |
AMD64_L3_EN_ALL_CORES;
+ if (boot_cpu_data.x86 == 0x18 &&
+ boot_cpu_data.x86_model >= 0x6 &&
+ boot_cpu_data.x86_model <= 0xf)
+ mask = ((config & HYGON_L3_SLICE_MASK) ? : HYGON_L3_SLICE_MASK) |
+ ((config & HYGON_L3_THREAD_MASK) ? : HYGON_L3_THREAD_MASK);
+
hwc->config |= mask;
return 0;
@@ -877,7 +910,8 @@ int amd_uncore_l3_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
pmu->rdpmc_base = RDPMC_BASE_LLC;
pmu->group = amd_uncore_ctx_gid(uncore, cpu);
- if (boot_cpu_data.x86 >= 0x17) {
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_AMD &&
+ boot_cpu_data.x86 >= 0x17) {
*l3_attr++ = &format_attr_event8.attr;
*l3_attr++ = &format_attr_umask8.attr;
*l3_attr++ = boot_cpu_data.x86 >= 0x19 ?
@@ -904,6 +938,18 @@ int amd_uncore_l3_ctx_init(struct amd_uncore *uncore, unsigned int cpu)
.module = THIS_MODULE,
};
+ if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON &&
+ boot_cpu_data.x86 == 0x18) {
+ *l3_attr++ = &format_attr_event8.attr;
+ *l3_attr++ = &format_attr_umask8.attr;
+ if (boot_cpu_data.x86_model >= 0x6 && boot_cpu_data.x86_model <= 0xf) {
+ *l3_attr++ = &format_attr_threadmask32.attr;
+ pmu->pmu.attr_update = hygon_uncore_l3_attr_update;
+ } else {
+ *l3_attr++ = &format_attr_threadmask8.attr;
+ }
+ }
+
if (perf_pmu_register(&pmu->pmu, pmu->pmu.name, -1)) {
free_percpu(pmu->ctx);
pmu->ctx = NULL;
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index ff5acb8b1..404752601 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -89,6 +89,14 @@
#define AMD64_L3_COREID_MASK \
(0x7ULL << AMD64_L3_COREID_SHIFT)
+#define HYGON_L3_SLICE_SHIFT 28
+#define HYGON_L3_SLICE_MASK \
+ (0xFULL << HYGON_L3_SLICE_SHIFT)
+
+#define HYGON_L3_THREAD_SHIFT 32
+#define HYGON_L3_THREAD_MASK \
+ (0xFFFFFFFFULL << HYGON_L3_THREAD_SHIFT)
+
#define X86_RAW_EVENT_MASK \
(ARCH_PERFMON_EVENTSEL_EVENT | \
ARCH_PERFMON_EVENTSEL_UMASK | \
--
2.34.1