Skip to content

Commit 55bcf6e

Browse files
Kan LiangPeter Zijlstra
authored andcommitted
perf: Extend PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE
Current Hardware events and Hardware cache events have special perf types, PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE. The two types don't pass the PMU type in the user interface. For a hybrid system, the perf subsystem doesn't know which PMU the events belong to. The first capable PMU will always be assigned to the events. The events never get a chance to run on the other capable PMUs. Extend the two types to become PMU aware types. The PMU type ID is stored at attr.config[63:32]. Add a new PMU capability, PERF_PMU_CAP_EXTENDED_HW_TYPE, to indicate a PMU which supports the extended PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE. The PMU type is only required when searching a specific PMU. The PMU specific codes will only be interested in the 'real' config value, which is stored in the low 32 bit of the event->attr.config. Update the event->attr.config in the generic code, so the PMU specific codes don't need to calculate it separately. If a user specifies a PMU type, but the PMU doesn't support the extended type, error out. If an event cannot be initialized in a PMU specified by a user, error out immediately. Perf should not try to open it on other PMUs. The new PMU capability is only set for the X86 hybrid PMUs for now. Other architectures, e.g., ARM, may need it as well. The support on ARM may be implemented later separately. Suggested-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Kan Liang <kan.liang@linux.intel.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lkml.kernel.org/r/1618237865-33448-22-git-send-email-kan.liang@linux.intel.com
1 parent f83d2f9 commit 55bcf6e

File tree

4 files changed

+42
-12
lines changed

4 files changed

+42
-12
lines changed

arch/x86/events/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2173,6 +2173,7 @@ static int __init init_hw_perf_events(void)
21732173
hybrid_pmu->pmu.type = -1;
21742174
hybrid_pmu->pmu.attr_update = x86_pmu.attr_update;
21752175
hybrid_pmu->pmu.capabilities |= PERF_PMU_CAP_HETEROGENEOUS_CPUS;
2176+
hybrid_pmu->pmu.capabilities |= PERF_PMU_CAP_EXTENDED_HW_TYPE;
21762177

21772178
err = perf_pmu_register(&hybrid_pmu->pmu, hybrid_pmu->name,
21782179
(hybrid_pmu->cpu_type == hybrid_big) ? PERF_TYPE_RAW : -1);

include/linux/perf_event.h

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -260,15 +260,16 @@ struct perf_event;
260260
/**
261261
* pmu::capabilities flags
262262
*/
263-
#define PERF_PMU_CAP_NO_INTERRUPT 0x01
264-
#define PERF_PMU_CAP_NO_NMI 0x02
265-
#define PERF_PMU_CAP_AUX_NO_SG 0x04
266-
#define PERF_PMU_CAP_EXTENDED_REGS 0x08
267-
#define PERF_PMU_CAP_EXCLUSIVE 0x10
268-
#define PERF_PMU_CAP_ITRACE 0x20
269-
#define PERF_PMU_CAP_HETEROGENEOUS_CPUS 0x40
270-
#define PERF_PMU_CAP_NO_EXCLUDE 0x80
271-
#define PERF_PMU_CAP_AUX_OUTPUT 0x100
263+
#define PERF_PMU_CAP_NO_INTERRUPT 0x0001
264+
#define PERF_PMU_CAP_NO_NMI 0x0002
265+
#define PERF_PMU_CAP_AUX_NO_SG 0x0004
266+
#define PERF_PMU_CAP_EXTENDED_REGS 0x0008
267+
#define PERF_PMU_CAP_EXCLUSIVE 0x0010
268+
#define PERF_PMU_CAP_ITRACE 0x0020
269+
#define PERF_PMU_CAP_HETEROGENEOUS_CPUS 0x0040
270+
#define PERF_PMU_CAP_NO_EXCLUDE 0x0080
271+
#define PERF_PMU_CAP_AUX_OUTPUT 0x0100
272+
#define PERF_PMU_CAP_EXTENDED_HW_TYPE 0x0200
272273

273274
struct perf_output_handle;
274275

include/uapi/linux/perf_event.h

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,21 @@ enum perf_type_id {
3737
PERF_TYPE_MAX, /* non-ABI */
3838
};
3939

40+
/*
41+
* attr.config layout for type PERF_TYPE_HARDWARE and PERF_TYPE_HW_CACHE
42+
* PERF_TYPE_HARDWARE: 0xEEEEEEEE000000AA
43+
* AA: hardware event ID
44+
* EEEEEEEE: PMU type ID
45+
* PERF_TYPE_HW_CACHE: 0xEEEEEEEE00DDCCBB
46+
* BB: hardware cache ID
47+
* CC: hardware cache op ID
48+
* DD: hardware cache op result ID
49+
* EEEEEEEE: PMU type ID
50+
* If the PMU type ID is 0, the PERF_TYPE_RAW will be applied.
51+
*/
52+
#define PERF_PMU_TYPE_SHIFT 32
53+
#define PERF_HW_EVENT_MASK 0xffffffff
54+
4055
/*
4156
* Generalized performance event event_id types, used by the
4257
* attr.event_id parameter of the sys_perf_event_open()

kernel/events/core.c

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11220,6 +11220,7 @@ static int perf_try_init_event(struct pmu *pmu, struct perf_event *event)
1122011220

1122111221
static struct pmu *perf_init_event(struct perf_event *event)
1122211222
{
11223+
bool extended_type = false;
1122311224
int idx, type, ret;
1122411225
struct pmu *pmu;
1122511226

@@ -11238,16 +11239,27 @@ static struct pmu *perf_init_event(struct perf_event *event)
1123811239
* are often aliases for PERF_TYPE_RAW.
1123911240
*/
1124011241
type = event->attr.type;
11241-
if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE)
11242-
type = PERF_TYPE_RAW;
11242+
if (type == PERF_TYPE_HARDWARE || type == PERF_TYPE_HW_CACHE) {
11243+
type = event->attr.config >> PERF_PMU_TYPE_SHIFT;
11244+
if (!type) {
11245+
type = PERF_TYPE_RAW;
11246+
} else {
11247+
extended_type = true;
11248+
event->attr.config &= PERF_HW_EVENT_MASK;
11249+
}
11250+
}
1124311251

1124411252
again:
1124511253
rcu_read_lock();
1124611254
pmu = idr_find(&pmu_idr, type);
1124711255
rcu_read_unlock();
1124811256
if (pmu) {
11257+
if (event->attr.type != type && type != PERF_TYPE_RAW &&
11258+
!(pmu->capabilities & PERF_PMU_CAP_EXTENDED_HW_TYPE))
11259+
goto fail;
11260+
1124911261
ret = perf_try_init_event(pmu, event);
11250-
if (ret == -ENOENT && event->attr.type != type) {
11262+
if (ret == -ENOENT && event->attr.type != type && !extended_type) {
1125111263
type = event->attr.type;
1125211264
goto again;
1125311265
}
@@ -11268,6 +11280,7 @@ static struct pmu *perf_init_event(struct perf_event *event)
1126811280
goto unlock;
1126911281
}
1127011282
}
11283+
fail:
1127111284
pmu = ERR_PTR(-ENOENT);
1127211285
unlock:
1127311286
srcu_read_unlock(&pmus_srcu, idx);

0 commit comments

Comments
 (0)