forked from ~ljy/RK356X_SDK_RELEASE

hc
2023-12-08 01573e231f18eb2d99162747186f59511f56b64d
kernel/arch/x86/events/amd/uncore.c
....@@ -1,11 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0-only
12 /*
23 * Copyright (C) 2013 Advanced Micro Devices, Inc.
34 *
45 * Author: Jacob Shin <jacob.shin@amd.com>
5
- *
6
- * This program is free software; you can redistribute it and/or modify
7
- * it under the terms of the GNU General Public License version 2 as
8
- * published by the Free Software Foundation.
96 */
107
118 #include <linux/perf_event.h>
....@@ -183,6 +180,31 @@
183180 hwc->idx = -1;
184181 }
185182
183
+/*
184
+ * Return a full thread and slice mask unless user
185
+ * has provided them
186
+ */
187
+static u64 l3_thread_slice_mask(u64 config)
188
+{
189
+ if (boot_cpu_data.x86 <= 0x18)
190
+ return ((config & AMD64_L3_SLICE_MASK) ? : AMD64_L3_SLICE_MASK) |
191
+ ((config & AMD64_L3_THREAD_MASK) ? : AMD64_L3_THREAD_MASK);
192
+
193
+ /*
194
+ * If the user doesn't specify a threadmask, they're not trying to
195
+ * count core 0, so we enable all cores & threads.
196
+ * We'll also assume that they want to count slice 0 if they specify
197
+ * a threadmask and leave sliceid and enallslices unpopulated.
198
+ */
199
+ if (!(config & AMD64_L3_F19H_THREAD_MASK))
200
+ return AMD64_L3_F19H_THREAD_MASK | AMD64_L3_EN_ALL_SLICES |
201
+ AMD64_L3_EN_ALL_CORES;
202
+
203
+ return config & (AMD64_L3_F19H_THREAD_MASK | AMD64_L3_SLICEID_MASK |
204
+ AMD64_L3_EN_ALL_CORES | AMD64_L3_EN_ALL_SLICES |
205
+ AMD64_L3_COREID_MASK);
206
+}
207
+
186208 static int amd_uncore_event_init(struct perf_event *event)
187209 {
188210 struct amd_uncore *uncore;
....@@ -199,12 +221,6 @@
199221 * out. So we do not support sampling and per-thread events via
200222 * CAP_NO_INTERRUPT, and we do not enable counter overflow interrupts:
201223 */
202
-
203
- /* NB and Last level cache counters do not have usr/os/guest/host bits */
204
- if (event->attr.exclude_user || event->attr.exclude_kernel ||
205
- event->attr.exclude_host || event->attr.exclude_guest)
206
- return -EINVAL;
207
-
208224 hwc->config = event->attr.config & AMD64_RAW_EVENT_MASK_NB;
209225 hwc->idx = -1;
210226
....@@ -212,18 +228,11 @@
212228 return -EINVAL;
213229
214230 /*
215
- * SliceMask and ThreadMask need to be set for certain L3 events in
216
- * Family 17h. For other events, the two fields do not affect the count.
231
+ * SliceMask and ThreadMask need to be set for certain L3 events.
232
+ * For other events, the two fields do not affect the count.
217233 */
218
- if (l3_mask && is_llc_event(event)) {
219
- int thread = 2 * (cpu_data(event->cpu).cpu_core_id % 4);
220
-
221
- if (smp_num_siblings > 1)
222
- thread += cpu_data(event->cpu).apicid & 1;
223
-
224
- hwc->config |= (1ULL << (AMD64_L3_THREAD_SHIFT + thread) &
225
- AMD64_L3_THREAD_MASK) | AMD64_L3_SLICE_MASK;
226
- }
234
+ if (l3_mask && is_llc_event(event))
235
+ hwc->config |= l3_thread_slice_mask(event->attr.config);
227236
228237 uncore = event_to_amd_uncore(event);
229238 if (!uncore)
....@@ -265,65 +274,92 @@
265274 .attrs = amd_uncore_attrs,
266275 };
267276
268
-/*
269
- * Similar to PMU_FORMAT_ATTR but allowing for format_attr to be assigned based
270
- * on family
271
- */
272
-#define AMD_FORMAT_ATTR(_dev, _name, _format) \
273
-static ssize_t \
274
-_dev##_show##_name(struct device *dev, \
275
- struct device_attribute *attr, \
276
- char *page) \
277
-{ \
278
- BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
279
- return sprintf(page, _format "\n"); \
280
-} \
281
-static struct device_attribute format_attr_##_dev##_name = __ATTR_RO(_dev);
277
+#define DEFINE_UNCORE_FORMAT_ATTR(_var, _name, _format) \
278
+static ssize_t __uncore_##_var##_show(struct device *dev, \
279
+ struct device_attribute *attr, \
280
+ char *page) \
281
+{ \
282
+ BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
283
+ return sprintf(page, _format "\n"); \
284
+} \
285
+static struct device_attribute format_attr_##_var = \
286
+ __ATTR(_name, 0444, __uncore_##_var##_show, NULL)
282287
283
-/* Used for each uncore counter type */
284
-#define AMD_ATTRIBUTE(_name) \
285
-static struct attribute *amd_uncore_format_attr_##_name[] = { \
286
- &format_attr_event_##_name.attr, \
287
- &format_attr_umask.attr, \
288
- NULL, \
289
-}; \
290
-static struct attribute_group amd_uncore_format_group_##_name = { \
291
- .name = "format", \
292
- .attrs = amd_uncore_format_attr_##_name, \
293
-}; \
294
-static const struct attribute_group *amd_uncore_attr_groups_##_name[] = { \
295
- &amd_uncore_attr_group, \
296
- &amd_uncore_format_group_##_name, \
297
- NULL, \
288
+DEFINE_UNCORE_FORMAT_ATTR(event12, event, "config:0-7,32-35");
289
+DEFINE_UNCORE_FORMAT_ATTR(event14, event, "config:0-7,32-35,59-60"); /* F17h+ DF */
290
+DEFINE_UNCORE_FORMAT_ATTR(event8, event, "config:0-7"); /* F17h+ L3 */
291
+DEFINE_UNCORE_FORMAT_ATTR(umask, umask, "config:8-15");
292
+DEFINE_UNCORE_FORMAT_ATTR(coreid, coreid, "config:42-44"); /* F19h L3 */
293
+DEFINE_UNCORE_FORMAT_ATTR(slicemask, slicemask, "config:48-51"); /* F17h L3 */
294
+DEFINE_UNCORE_FORMAT_ATTR(threadmask8, threadmask, "config:56-63"); /* F17h L3 */
295
+DEFINE_UNCORE_FORMAT_ATTR(threadmask2, threadmask, "config:56-57"); /* F19h L3 */
296
+DEFINE_UNCORE_FORMAT_ATTR(enallslices, enallslices, "config:46"); /* F19h L3 */
297
+DEFINE_UNCORE_FORMAT_ATTR(enallcores, enallcores, "config:47"); /* F19h L3 */
298
+DEFINE_UNCORE_FORMAT_ATTR(sliceid, sliceid, "config:48-50"); /* F19h L3 */
299
+
300
+static struct attribute *amd_uncore_df_format_attr[] = {
301
+ &format_attr_event12.attr, /* event14 if F17h+ */
302
+ &format_attr_umask.attr,
303
+ NULL,
298304 };
299305
300
-AMD_FORMAT_ATTR(event, , "config:0-7,32-35");
301
-AMD_FORMAT_ATTR(umask, , "config:8-15");
302
-AMD_FORMAT_ATTR(event, _df, "config:0-7,32-35,59-60");
303
-AMD_FORMAT_ATTR(event, _l3, "config:0-7");
304
-AMD_ATTRIBUTE(df);
305
-AMD_ATTRIBUTE(l3);
306
+static struct attribute *amd_uncore_l3_format_attr[] = {
307
+ &format_attr_event12.attr, /* event8 if F17h+ */
308
+ &format_attr_umask.attr,
309
+ NULL, /* slicemask if F17h, coreid if F19h */
310
+ NULL, /* threadmask8 if F17h, enallslices if F19h */
311
+ NULL, /* enallcores if F19h */
312
+ NULL, /* sliceid if F19h */
313
+ NULL, /* threadmask2 if F19h */
314
+ NULL,
315
+};
316
+
317
+static struct attribute_group amd_uncore_df_format_group = {
318
+ .name = "format",
319
+ .attrs = amd_uncore_df_format_attr,
320
+};
321
+
322
+static struct attribute_group amd_uncore_l3_format_group = {
323
+ .name = "format",
324
+ .attrs = amd_uncore_l3_format_attr,
325
+};
326
+
327
+static const struct attribute_group *amd_uncore_df_attr_groups[] = {
328
+ &amd_uncore_attr_group,
329
+ &amd_uncore_df_format_group,
330
+ NULL,
331
+};
332
+
333
+static const struct attribute_group *amd_uncore_l3_attr_groups[] = {
334
+ &amd_uncore_attr_group,
335
+ &amd_uncore_l3_format_group,
336
+ NULL,
337
+};
306338
307339 static struct pmu amd_nb_pmu = {
308340 .task_ctx_nr = perf_invalid_context,
341
+ .attr_groups = amd_uncore_df_attr_groups,
342
+ .name = "amd_nb",
309343 .event_init = amd_uncore_event_init,
310344 .add = amd_uncore_add,
311345 .del = amd_uncore_del,
312346 .start = amd_uncore_start,
313347 .stop = amd_uncore_stop,
314348 .read = amd_uncore_read,
315
- .capabilities = PERF_PMU_CAP_NO_INTERRUPT,
349
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
316350 };
317351
318352 static struct pmu amd_llc_pmu = {
319353 .task_ctx_nr = perf_invalid_context,
354
+ .attr_groups = amd_uncore_l3_attr_groups,
355
+ .name = "amd_l2",
320356 .event_init = amd_uncore_event_init,
321357 .add = amd_uncore_add,
322358 .del = amd_uncore_del,
323359 .start = amd_uncore_start,
324360 .stop = amd_uncore_stop,
325361 .read = amd_uncore_read,
326
- .capabilities = PERF_PMU_CAP_NO_INTERRUPT,
362
+ .capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
327363 };
328364
329365 static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
....@@ -520,41 +556,36 @@
520556
521557 static int __init amd_uncore_init(void)
522558 {
559
+ struct attribute **df_attr = amd_uncore_df_format_attr;
560
+ struct attribute **l3_attr = amd_uncore_l3_format_attr;
523561 int ret = -ENODEV;
524562
525
- if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD)
563
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD &&
564
+ boot_cpu_data.x86_vendor != X86_VENDOR_HYGON)
526565 return -ENODEV;
527566
528567 if (!boot_cpu_has(X86_FEATURE_TOPOEXT))
529568 return -ENODEV;
530569
531
- if (boot_cpu_data.x86 == 0x17) {
570
+ num_counters_nb = NUM_COUNTERS_NB;
571
+ num_counters_llc = NUM_COUNTERS_L2;
572
+ if (boot_cpu_data.x86 >= 0x17) {
532573 /*
533
- * For F17h, the Northbridge counters are repurposed as Data
534
- * Fabric counters. Also, L3 counters are supported too. The PMUs
535
- * are exported based on family as either L2 or L3 and NB or DF.
574
+ * For F17h and above, the Northbridge counters are
575
+ * repurposed as Data Fabric counters. Also, L3
576
+ * counters are supported too. The PMUs are exported
577
+ * based on family as either L2 or L3 and NB or DF.
536578 */
537
- num_counters_nb = NUM_COUNTERS_NB;
538579 num_counters_llc = NUM_COUNTERS_L3;
539580 amd_nb_pmu.name = "amd_df";
540581 amd_llc_pmu.name = "amd_l3";
541
- format_attr_event_df.show = &event_show_df;
542
- format_attr_event_l3.show = &event_show_l3;
543582 l3_mask = true;
544
- } else {
545
- num_counters_nb = NUM_COUNTERS_NB;
546
- num_counters_llc = NUM_COUNTERS_L2;
547
- amd_nb_pmu.name = "amd_nb";
548
- amd_llc_pmu.name = "amd_l2";
549
- format_attr_event_df = format_attr_event;
550
- format_attr_event_l3 = format_attr_event;
551
- l3_mask = false;
552583 }
553584
554
- amd_nb_pmu.attr_groups = amd_uncore_attr_groups_df;
555
- amd_llc_pmu.attr_groups = amd_uncore_attr_groups_l3;
556
-
557585 if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
586
+ if (boot_cpu_data.x86 >= 0x17)
587
+ *df_attr = &format_attr_event14.attr;
588
+
558589 amd_uncore_nb = alloc_percpu(struct amd_uncore *);
559590 if (!amd_uncore_nb) {
560591 ret = -ENOMEM;
....@@ -564,11 +595,29 @@
564595 if (ret)
565596 goto fail_nb;
566597
567
- pr_info("AMD NB counters detected\n");
598
+ pr_info("%d %s %s counters detected\n", num_counters_nb,
599
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ? "HYGON" : "",
600
+ amd_nb_pmu.name);
601
+
568602 ret = 0;
569603 }
570604
571605 if (boot_cpu_has(X86_FEATURE_PERFCTR_LLC)) {
606
+ if (boot_cpu_data.x86 >= 0x19) {
607
+ *l3_attr++ = &format_attr_event8.attr;
608
+ *l3_attr++ = &format_attr_umask.attr;
609
+ *l3_attr++ = &format_attr_coreid.attr;
610
+ *l3_attr++ = &format_attr_enallslices.attr;
611
+ *l3_attr++ = &format_attr_enallcores.attr;
612
+ *l3_attr++ = &format_attr_sliceid.attr;
613
+ *l3_attr++ = &format_attr_threadmask2.attr;
614
+ } else if (boot_cpu_data.x86 >= 0x17) {
615
+ *l3_attr++ = &format_attr_event8.attr;
616
+ *l3_attr++ = &format_attr_umask.attr;
617
+ *l3_attr++ = &format_attr_slicemask.attr;
618
+ *l3_attr++ = &format_attr_threadmask8.attr;
619
+ }
620
+
572621 amd_uncore_llc = alloc_percpu(struct amd_uncore *);
573622 if (!amd_uncore_llc) {
574623 ret = -ENOMEM;
....@@ -578,7 +627,9 @@
578627 if (ret)
579628 goto fail_llc;
580629
581
- pr_info("AMD LLC counters detected\n");
630
+ pr_info("%d %s %s counters detected\n", num_counters_llc,
631
+ boot_cpu_data.x86_vendor == X86_VENDOR_HYGON ? "HYGON" : "",
632
+ amd_llc_pmu.name);
582633 ret = 0;
583634 }
584635