[PATCH 4/8] perf/x86/uncore: Add L3 PMU support for Hygon family 18h model 6h

Fu Hao posted 8 patches 6 days, 8 hours ago
[PATCH 4/8] perf/x86/uncore: Add L3 PMU support for Hygon family 18h model 6h
Posted by Fu Hao 6 days, 8 hours ago
Adjust the L3 PMU slicemask and threadmask for Hygon family 18h
model 6h processor.

Signed-off-by: Fu Hao <fuhao@open-hieco.net>
---
 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