Skip to content

Commit 4a2b88e

Browse files
committed
Merge tag 'perf-core-2021-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 perf event updates from Ingo Molnar: - Add support for Intel Sapphire Rapids server CPU uncore events - Allow the AMD uncore driver to be built as a module - Misc cleanups and fixes * tag 'perf-core-2021-08-30' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (24 commits) perf/x86/amd/ibs: Add bitfield definitions in new <asm/amd-ibs.h> header perf/amd/uncore: Allow the driver to be built as a module x86/cpu: Add get_llc_id() helper function perf/amd/uncore: Clean up header use, use <linux/ include paths instead of <asm/ perf/amd/uncore: Simplify code, use free_percpu()'s built-in check for NULL perf/hw_breakpoint: Replace deprecated CPU-hotplug functions perf/x86/intel: Replace deprecated CPU-hotplug functions perf/x86: Remove unused assignment to pointer 'e' perf/x86/intel/uncore: Fix IIO cleanup mapping procedure for SNR/ICX perf/x86/intel/uncore: Support IMC free-running counters on Sapphire Rapids server perf/x86/intel/uncore: Support IIO free-running counters on Sapphire Rapids server perf/x86/intel/uncore: Factor out snr_uncore_mmio_map() perf/x86/intel/uncore: Add alias PMU name perf/x86/intel/uncore: Add Sapphire Rapids server MDF support perf/x86/intel/uncore: Add Sapphire Rapids server M3UPI support perf/x86/intel/uncore: Add Sapphire Rapids server UPI support perf/x86/intel/uncore: Add Sapphire Rapids server M2M support perf/x86/intel/uncore: Add Sapphire Rapids server IMC support perf/x86/intel/uncore: Add Sapphire Rapids server PCU support perf/x86/intel/uncore: Add Sapphire Rapids server M2PCIe support ...
2 parents 5d3c0db + 6a371ba commit 4a2b88e

File tree

18 files changed

+858
-90
lines changed

18 files changed

+858
-90
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
What: /sys/bus/event_source/devices/uncore_*/alias
2+
Date: June 2021
3+
KernelVersion: 5.15
4+
Contact: Linux kernel mailing list <[email protected]>
5+
Description: Read-only. An attribute to describe the alias name of
6+
the uncore PMU if an alias exists on some platforms.
7+
The 'perf(1)' tool should treat both names the same.
8+
They both can be used to access the uncore PMU.
9+
10+
Example:
11+
12+
$ cat /sys/devices/uncore_cha_2/alias
13+
uncore_type_0_2

arch/x86/events/Kconfig

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,4 +34,14 @@ config PERF_EVENTS_AMD_POWER
3434
(CPUID Fn8000_0007_EDX[12]) interface to calculate the
3535
average power consumption on Family 15h processors.
3636

37+
config PERF_EVENTS_AMD_UNCORE
38+
tristate "AMD Uncore performance events"
39+
depends on PERF_EVENTS && CPU_SUP_AMD
40+
default y
41+
help
42+
Include support for AMD uncore performance events for use with
43+
e.g., perf stat -e amd_l3/.../,amd_df/.../.
44+
45+
To compile this driver as a module, choose M here: the
46+
module will be called 'amd-uncore'.
3747
endmenu

arch/x86/events/amd/Makefile

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
# SPDX-License-Identifier: GPL-2.0
2-
obj-$(CONFIG_CPU_SUP_AMD) += core.o uncore.o
2+
obj-$(CONFIG_CPU_SUP_AMD) += core.o
33
obj-$(CONFIG_PERF_EVENTS_AMD_POWER) += power.o
44
obj-$(CONFIG_X86_LOCAL_APIC) += ibs.o
5+
obj-$(CONFIG_PERF_EVENTS_AMD_UNCORE) += amd-uncore.o
6+
amd-uncore-objs := uncore.o
57
ifdef CONFIG_AMD_IOMMU
68
obj-$(CONFIG_CPU_SUP_AMD) += iommu.o
79
endif
8-

arch/x86/events/amd/ibs.c

Lines changed: 9 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ static u32 ibs_caps;
2626
#include <linux/hardirq.h>
2727

2828
#include <asm/nmi.h>
29+
#include <asm/amd-ibs.h>
2930

3031
#define IBS_FETCH_CONFIG_MASK (IBS_FETCH_RAND_EN | IBS_FETCH_MAX_CNT)
3132
#define IBS_OP_CONFIG_MASK IBS_OP_MAX_CNT
@@ -100,15 +101,6 @@ struct perf_ibs {
100101
u64 (*get_count)(u64 config);
101102
};
102103

103-
struct perf_ibs_data {
104-
u32 size;
105-
union {
106-
u32 data[0]; /* data buffer starts here */
107-
u32 caps;
108-
};
109-
u64 regs[MSR_AMD64_IBS_REG_COUNT_MAX];
110-
};
111-
112104
static int
113105
perf_event_set_period(struct hw_perf_event *hwc, u64 min, u64 max, u64 *hw_period)
114106
{
@@ -329,24 +321,27 @@ static int perf_ibs_set_period(struct perf_ibs *perf_ibs,
329321

330322
static u64 get_ibs_fetch_count(u64 config)
331323
{
332-
return (config & IBS_FETCH_CNT) >> 12;
324+
union ibs_fetch_ctl fetch_ctl = (union ibs_fetch_ctl)config;
325+
326+
return fetch_ctl.fetch_cnt << 4;
333327
}
334328

335329
static u64 get_ibs_op_count(u64 config)
336330
{
331+
union ibs_op_ctl op_ctl = (union ibs_op_ctl)config;
337332
u64 count = 0;
338333

339334
/*
340335
* If the internal 27-bit counter rolled over, the count is MaxCnt
341336
* and the lower 7 bits of CurCnt are randomized.
342337
* Otherwise CurCnt has the full 27-bit current counter value.
343338
*/
344-
if (config & IBS_OP_VAL) {
345-
count = (config & IBS_OP_MAX_CNT) << 4;
339+
if (op_ctl.op_val) {
340+
count = op_ctl.opmaxcnt << 4;
346341
if (ibs_caps & IBS_CAPS_OPCNTEXT)
347-
count += config & IBS_OP_MAX_CNT_EXT_MASK;
342+
count += op_ctl.opmaxcnt_ext << 20;
348343
} else if (ibs_caps & IBS_CAPS_RDWROPCNT) {
349-
count = (config & IBS_OP_CUR_CNT) >> 32;
344+
count = op_ctl.opcurcnt;
350345
}
351346

352347
return count;

arch/x86/events/amd/uncore.c

Lines changed: 32 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,11 +12,11 @@
1212
#include <linux/init.h>
1313
#include <linux/cpu.h>
1414
#include <linux/cpumask.h>
15+
#include <linux/cpufeature.h>
16+
#include <linux/smp.h>
1517

16-
#include <asm/cpufeature.h>
1718
#include <asm/perf_event.h>
1819
#include <asm/msr.h>
19-
#include <asm/smp.h>
2020

2121
#define NUM_COUNTERS_NB 4
2222
#define NUM_COUNTERS_L2 4
@@ -347,6 +347,7 @@ static struct pmu amd_nb_pmu = {
347347
.stop = amd_uncore_stop,
348348
.read = amd_uncore_read,
349349
.capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
350+
.module = THIS_MODULE,
350351
};
351352

352353
static struct pmu amd_llc_pmu = {
@@ -360,6 +361,7 @@ static struct pmu amd_llc_pmu = {
360361
.stop = amd_uncore_stop,
361362
.read = amd_uncore_read,
362363
.capabilities = PERF_PMU_CAP_NO_EXCLUDE | PERF_PMU_CAP_NO_INTERRUPT,
364+
.module = THIS_MODULE,
363365
};
364366

365367
static struct amd_uncore *amd_uncore_alloc(unsigned int cpu)
@@ -452,7 +454,7 @@ static int amd_uncore_cpu_starting(unsigned int cpu)
452454

453455
if (amd_uncore_llc) {
454456
uncore = *per_cpu_ptr(amd_uncore_llc, cpu);
455-
uncore->id = per_cpu(cpu_llc_id, cpu);
457+
uncore->id = get_llc_id(cpu);
456458

457459
uncore = amd_uncore_find_online_sibling(uncore, amd_uncore_llc);
458460
*per_cpu_ptr(amd_uncore_llc, cpu) = uncore;
@@ -659,12 +661,34 @@ static int __init amd_uncore_init(void)
659661
fail_llc:
660662
if (boot_cpu_has(X86_FEATURE_PERFCTR_NB))
661663
perf_pmu_unregister(&amd_nb_pmu);
662-
if (amd_uncore_llc)
663-
free_percpu(amd_uncore_llc);
664+
free_percpu(amd_uncore_llc);
664665
fail_nb:
665-
if (amd_uncore_nb)
666-
free_percpu(amd_uncore_nb);
666+
free_percpu(amd_uncore_nb);
667667

668668
return ret;
669669
}
670-
device_initcall(amd_uncore_init);
670+
671+
static void __exit amd_uncore_exit(void)
672+
{
673+
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_ONLINE);
674+
cpuhp_remove_state(CPUHP_AP_PERF_X86_AMD_UNCORE_STARTING);
675+
cpuhp_remove_state(CPUHP_PERF_X86_AMD_UNCORE_PREP);
676+
677+
if (boot_cpu_has(X86_FEATURE_PERFCTR_LLC)) {
678+
perf_pmu_unregister(&amd_llc_pmu);
679+
free_percpu(amd_uncore_llc);
680+
amd_uncore_llc = NULL;
681+
}
682+
683+
if (boot_cpu_has(X86_FEATURE_PERFCTR_NB)) {
684+
perf_pmu_unregister(&amd_nb_pmu);
685+
free_percpu(amd_uncore_nb);
686+
amd_uncore_nb = NULL;
687+
}
688+
}
689+
690+
module_init(amd_uncore_init);
691+
module_exit(amd_uncore_exit);
692+
693+
MODULE_DESCRIPTION("AMD Uncore Driver");
694+
MODULE_LICENSE("GPL v2");

arch/x86/events/core.c

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1087,10 +1087,8 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
10871087
* validate an event group (assign == NULL)
10881088
*/
10891089
if (!unsched && assign) {
1090-
for (i = 0; i < n; i++) {
1091-
e = cpuc->event_list[i];
1090+
for (i = 0; i < n; i++)
10921091
static_call_cond(x86_pmu_commit_scheduling)(cpuc, i, assign[i]);
1093-
}
10941092
} else {
10951093
for (i = n0; i < n; i++) {
10961094
e = cpuc->event_list[i];

arch/x86/events/intel/core.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5032,9 +5032,9 @@ static ssize_t freeze_on_smi_store(struct device *cdev,
50325032

50335033
x86_pmu.attr_freeze_on_smi = val;
50345034

5035-
get_online_cpus();
5035+
cpus_read_lock();
50365036
on_each_cpu(flip_smm_bit, &val, 1);
5037-
put_online_cpus();
5037+
cpus_read_unlock();
50385038
done:
50395039
mutex_unlock(&freeze_on_smi_mutex);
50405040

@@ -5077,9 +5077,9 @@ static ssize_t set_sysctl_tfa(struct device *cdev,
50775077

50785078
allow_tsx_force_abort = val;
50795079

5080-
get_online_cpus();
5080+
cpus_read_lock();
50815081
on_each_cpu(update_tfa_sched, NULL, 1);
5082-
put_online_cpus();
5082+
cpus_read_unlock();
50835083

50845084
return count;
50855085
}

arch/x86/events/intel/pt.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1708,15 +1708,15 @@ static __init int pt_init(void)
17081708
if (!boot_cpu_has(X86_FEATURE_INTEL_PT))
17091709
return -ENODEV;
17101710

1711-
get_online_cpus();
1711+
cpus_read_lock();
17121712
for_each_online_cpu(cpu) {
17131713
u64 ctl;
17141714

17151715
ret = rdmsrl_safe_on_cpu(cpu, MSR_IA32_RTIT_CTL, &ctl);
17161716
if (!ret && (ctl & RTIT_CTL_TRACEEN))
17171717
prior_warn++;
17181718
}
1719-
put_online_cpus();
1719+
cpus_read_unlock();
17201720

17211721
if (prior_warn) {
17221722
x86_add_exclusive(x86_lbr_exclusive_pt);

arch/x86/events/intel/uncore.c

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -842,6 +842,18 @@ static const struct attribute_group uncore_pmu_attr_group = {
842842
.attrs = uncore_pmu_attrs,
843843
};
844844

845+
void uncore_get_alias_name(char *pmu_name, struct intel_uncore_pmu *pmu)
846+
{
847+
struct intel_uncore_type *type = pmu->type;
848+
849+
if (type->num_boxes == 1)
850+
sprintf(pmu_name, "uncore_type_%u", type->type_id);
851+
else {
852+
sprintf(pmu_name, "uncore_type_%u_%d",
853+
type->type_id, type->box_ids[pmu->pmu_idx]);
854+
}
855+
}
856+
845857
static void uncore_get_pmu_name(struct intel_uncore_pmu *pmu)
846858
{
847859
struct intel_uncore_type *type = pmu->type;
@@ -851,12 +863,7 @@ static void uncore_get_pmu_name(struct intel_uncore_pmu *pmu)
851863
* Use uncore_type_&typeid_&boxid as name.
852864
*/
853865
if (!type->name) {
854-
if (type->num_boxes == 1)
855-
sprintf(pmu->name, "uncore_type_%u", type->type_id);
856-
else {
857-
sprintf(pmu->name, "uncore_type_%u_%d",
858-
type->type_id, type->box_ids[pmu->pmu_idx]);
859-
}
866+
uncore_get_alias_name(pmu->name, pmu);
860867
return;
861868
}
862869

@@ -865,9 +872,13 @@ static void uncore_get_pmu_name(struct intel_uncore_pmu *pmu)
865872
sprintf(pmu->name, "uncore_%s", type->name);
866873
else
867874
sprintf(pmu->name, "uncore");
868-
} else
869-
sprintf(pmu->name, "uncore_%s_%d", type->name, pmu->pmu_idx);
870-
875+
} else {
876+
/*
877+
* Use the box ID from the discovery table if applicable.
878+
*/
879+
sprintf(pmu->name, "uncore_%s_%d", type->name,
880+
type->box_ids ? type->box_ids[pmu->pmu_idx] : pmu->pmu_idx);
881+
}
871882
}
872883

873884
static int uncore_pmu_register(struct intel_uncore_pmu *pmu)
@@ -1663,6 +1674,7 @@ struct intel_uncore_init_fun {
16631674
void (*cpu_init)(void);
16641675
int (*pci_init)(void);
16651676
void (*mmio_init)(void);
1677+
bool use_discovery;
16661678
};
16671679

16681680
static const struct intel_uncore_init_fun nhm_uncore_init __initconst = {
@@ -1765,6 +1777,13 @@ static const struct intel_uncore_init_fun snr_uncore_init __initconst = {
17651777
.mmio_init = snr_uncore_mmio_init,
17661778
};
17671779

1780+
static const struct intel_uncore_init_fun spr_uncore_init __initconst = {
1781+
.cpu_init = spr_uncore_cpu_init,
1782+
.pci_init = spr_uncore_pci_init,
1783+
.mmio_init = spr_uncore_mmio_init,
1784+
.use_discovery = true,
1785+
};
1786+
17681787
static const struct intel_uncore_init_fun generic_uncore_init __initconst = {
17691788
.cpu_init = intel_uncore_generic_uncore_cpu_init,
17701789
.pci_init = intel_uncore_generic_uncore_pci_init,
@@ -1809,6 +1828,7 @@ static const struct x86_cpu_id intel_uncore_match[] __initconst = {
18091828
X86_MATCH_INTEL_FAM6_MODEL(ROCKETLAKE, &rkl_uncore_init),
18101829
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE, &adl_uncore_init),
18111830
X86_MATCH_INTEL_FAM6_MODEL(ALDERLAKE_L, &adl_uncore_init),
1831+
X86_MATCH_INTEL_FAM6_MODEL(SAPPHIRERAPIDS_X, &spr_uncore_init),
18121832
X86_MATCH_INTEL_FAM6_MODEL(ATOM_TREMONT_D, &snr_uncore_init),
18131833
{},
18141834
};
@@ -1832,8 +1852,13 @@ static int __init intel_uncore_init(void)
18321852
uncore_init = (struct intel_uncore_init_fun *)&generic_uncore_init;
18331853
else
18341854
return -ENODEV;
1835-
} else
1855+
} else {
18361856
uncore_init = (struct intel_uncore_init_fun *)id->driver_data;
1857+
if (uncore_no_discover && uncore_init->use_discovery)
1858+
return -ENODEV;
1859+
if (uncore_init->use_discovery && !intel_uncore_has_discovery_tables())
1860+
return -ENODEV;
1861+
}
18371862

18381863
if (uncore_init->pci_init) {
18391864
pret = uncore_init->pci_init();

arch/x86/events/intel/uncore.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -561,6 +561,7 @@ struct event_constraint *
561561
uncore_get_constraint(struct intel_uncore_box *box, struct perf_event *event);
562562
void uncore_put_constraint(struct intel_uncore_box *box, struct perf_event *event);
563563
u64 uncore_shared_reg_config(struct intel_uncore_box *box, int idx);
564+
void uncore_get_alias_name(char *pmu_name, struct intel_uncore_pmu *pmu);
564565

565566
extern struct intel_uncore_type *empty_uncore[];
566567
extern struct intel_uncore_type **uncore_msr_uncores;
@@ -608,6 +609,9 @@ void snr_uncore_mmio_init(void);
608609
int icx_uncore_pci_init(void);
609610
void icx_uncore_cpu_init(void);
610611
void icx_uncore_mmio_init(void);
612+
int spr_uncore_pci_init(void);
613+
void spr_uncore_cpu_init(void);
614+
void spr_uncore_mmio_init(void);
611615

612616
/* uncore_nhmex.c */
613617
void nhmex_uncore_cpu_init(void);

0 commit comments

Comments
 (0)