perf_event: e500 support
Subsystems (2)
PATCH 1/1 perf_event: e500 support
This implements perf_event support for the Freescale embedded performance monitor, based on the existing perf_event.c that supports server/classic chips. Eventually we may want to factor out some of the common bits.
Some limitations:
- No threshold support -- need to figure out how to represent it in the event struct from userspace.
- Performance monitor interrupts are regular EE interrupts, and thus you can't profile places with interrupts disabled. We may want to implement soft IRQ-disabling on 32-bit, with perfmon interrupts exempted and treated as NMIs.
- When trying to schedule multiple event groups at once, and using restricted events, situations could arise where scheduling fails even though it would be possible. Consider three groups, each with two events. One group has restricted events, the others don't. The two non-restricted groups are scheduled, then one is removed, which happens to occupy the two counters that can't do restricted events. The remaining non-restricted group will not be moved to the non-restricted-capable counters to make room if the restricted group tries to be scheduled. Since thresholds are not yet supported (though you can use the events with a threshold of zero), and threshold events are the only restricted events, this seems like a low priority issue.
---
I did some basic testing with "perf top" and "perf stat"; the results looked reasonable.
arch/powerpc/include/asm/perf_event.h | 35 ++- arch/powerpc/include/asm/reg_fsl_emb.h | 2 +- arch/powerpc/kernel/Makefile | 5 +- arch/powerpc/kernel/cputable.c | 2 +- arch/powerpc/kernel/e500-pmu.c | 120 ++++++ arch/powerpc/kernel/perf_event_fsl_emb.c | 658 ++++++++++++++++++++++++++++++ arch/powerpc/platforms/Kconfig.cputype | 10 + 7 files changed, 828 insertions(+), 4 deletions(-) create mode 100644 arch/powerpc/kernel/e500-pmu.c create mode 100644 arch/powerpc/kernel/perf_event_fsl_emb.c
arch/powerpc/include/asm/perf_event.h +34 -1
@@ -2,6 +2,7 @@* Performance event support - PowerPC-specific definitions. * * Copyright 2008-2009 Paul Mackerras, IBM Corporation. +* Copyright 2010 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License
@@ -12,6 +13,36 @@#include <asm/hw_irq.h> +#ifdef CONFIG_FSL_EMB_PERFMON +#define MAX_HWEVENTS 4 + +/* event flags */ +#define FSL_EMB_EVENT_VALID 1 +#define FSL_EMB_EVENT_RESTRICTED 2 + +struct power_pmu { +const char *name; +int n_counter;/* total number of counters */ + +/* +* The number of contiguous counters starting at zero that +* can hold restricted events, or zero if there are no +* restricted events. +* +* This isn't a very flexible method of expressing constraints, +* but it's very simple and is adequate for existing chips. +*/ +int n_restricted; + +int (*get_event_flags)(u64 event_id); + +int n_generic; +int *generic_events; +int (*cache_events)[PERF_COUNT_HW_CACHE_MAX ] + [PERF_COUNT_HW_CACHE_OP_MAX ] + [PERF_COUNT_HW_CACHE_RESULT_MAX ]; +}; +#else #define MAX_HWEVENTS 8#define MAX_EVENT_ALTERNATIVES 8#define MAX_LIMITED_HWCOUNTERS 2
@@ -55,7 +86,6 @@ struct power_pmu {#define PPMU_LIMITED_PMC_REQD 2/* have to put this on a limited PMC */ #define PPMU_ONLY_COUNT_RUN 4/* only counting in run state */ -extern int register_power_pmu (struct power_pmu *);struct pt_regs ;extern unsigned long perf_misc_flags (struct pt_regs *regs);
@@ -108,3 +138,6 @@ extern unsigned long perf_instruction_pointer(struct pt_regs *regs);* If an event_id is not subject to the constraint expressed by a particular * field, then it will have 0 in both the mask and value for that field. */ +#endif /* !CONFIG_FSL_EMB_PERFMON */ + +extern int register_power_pmu (struct power_pmu *);
arch/powerpc/include/asm/reg_fsl_emb.h +1 -1
@@ -31,7 +31,7 @@#define PMLCA_FCM0 0x08000000/* Freeze when PMM==0 */ #define PMLCA_CE 0x04000000/* Condition Enable */ -#define PMLCA_EVENT_MASK 0x007f0000/* Event field */ +#define PMLCA_EVENT_MASK 0x00ff0000/* Event field */ #define PMLCA_EVENT_SHIFT 16#define PMRN_PMLCB0 0x110/* PM Local Control B0 */
arch/powerpc/kernel/Makefile +4 -1
@@ -98,7 +98,10 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o -obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o +obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o +obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o obj64-$(CONFIG_PPC_PERF_CTRS) += power4-pmu.o ppc970-pmu.o power5-pmu.o \ power5+-pmu.o power6-pmu.o power7-pmu.o obj32-$(CONFIG_PPC_PERF_CTRS) += mpc7450-pmu.o
arch/powerpc/kernel/cputable.c +1 -1
@@ -1808,7 +1808,7 @@ static struct cpu_spec __initdata cpu_specs[] = { .icache_bsize = 64, .dcache_bsize = 64, .num_pmcs = 4, - .oprofile_cpu_type = "ppc/e500", /* xxx - galak, e500mc? */ + .oprofile_cpu_type = "ppc/e500mc", .oprofile_type = PPC_OPROFILE_FSL_EMB, .cpu_setup = __setup_cpu_e500mc, .machine_check = machine_check_e500,
arch/powerpc/kernel/e500-pmu.c new file +120 -0
120 lines not on this page · raw message
arch/powerpc/kernel/perf_event_fsl_emb.c new file +658 -0
658 lines not on this page · raw message
arch/powerpc/platforms/Kconfig.cputype +10 -0
@@ -144,6 +144,16 @@ config FSL_EMB_PERFMON and some e300 cores (c3 and c4). Select this only if your core supports the Embedded Performance Monitor APU +config FSL_EMB_PERF_EVENT + bool + depends on FSL_EMB_PERFMON && PERF_EVENTS + default y + +config FSL_EMB_PERF_EVENT_E500 + bool + depends on FSL_EMB_PERF_EVENT && E500 + default y + config 4xx bool depends on 40x || 44x
Signature · 1 line
1.6.4.4
Quoted 3 lines · Scott Wood
This implements
perf_eventsupport for the Freescale embedded performance monitor, based on the existingperf_event.cthat supports server/classic chips. Eventually we may want to factor out some of the common bits.
Cool! I agree we will want to factor out some things, such as collect_events() for instance. We could create a perf_helper.c for those bits.
Quoted 3 lines
Some limitations:
- No threshold support -- need to figure out how to represent it in the event struct from userspace.
What does "threshold support" mean in this context? Does it mean something different from getting an interrupt after N events have been counted? Or does it mean counting instances where something takes longer than a specific number of cycles?
Quoted 11 lines
- When trying to schedule multiple event groups at once, and using restricted events, situations could arise where scheduling fails even though it would be possible. Consider three groups, each with two events. One group has restricted events, the others don't. The two non-restricted groups are scheduled, then one is removed, which happens to occupy the two counters that can't do restricted events. The remaining non-restricted group will not be moved to the non-restricted-capable counters to make room if the restricted group tries to be scheduled. Since thresholds are not yet supported (though you can use the events with a threshold of zero), and threshold events are the only restricted events, this seems like a low priority issue.
Which way around are the restrictions? That some events can only be counted on certain counters, or that some counters can only count a subset of the available events?
Did you look at the constraint satisfaction code in the existing perf_event.c and p*-pmu.c? That lets you express both sorts of restrictions and automatically find the best solution (including moving events from one counter to another like you describe).
Some specific comments:
Quoted 14 lines
arch/powerpc/include/asm/perf_event.h +1
-0@@ -2,6 +2,7 @@* Performance event support - PowerPC-specific definitions. * * Copyright 2008-2009 Paul Mackerras, IBM Corporation. +* Copyright 2010 Freescale Semiconductor, Inc. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License @@ -12,6 +13,36 @@
arch/powerpc/include/asm/perf_event.h line 23
Quoted 10 lines
arch/powerpc/include/asm/perf_event.h +8
-0#include <asm/hw_irq.h> +#ifdef CONFIG_FSL_EMB_PERFMON +#define MAX_HWEVENTS 4 + +/* event flags */ +#define FSL_EMB_EVENT_VALID 1 +#define FSL_EMB_EVENT_RESTRICTED 2 + +struct power_pmu {
I wonder if we should have just the stuff exported to the core in asm/perf_event.h and move MAX_HWEVENTS, struct power_pmu etc. to separate headers for fsl_embedded, classic, etc.?
arch/powerpc/kernel/Makefile obj64-$(CONFIG_AUDIT) += compat_audit.o · line 104
Quoted 11 lines
arch/powerpc/kernel/Makefile +4
-1@@ -98,7 +98,10 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o -obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o +obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o +obj-$(CONFIG_PERF_EVENTS) += perf_callchain.o
This is because we want perf_callchain.o even if we don't have hardware PMU support, is it? If so this is a separate fix that deserves its own patch.
Paul.
Quoted 8 lines · Paul Mackerras
Quoted 3 lines
Some limitations:
- No threshold support -- need to figure out how to represent it in the event struct from userspace.What does "threshold support" mean in this context? Does it mean something different from getting an interrupt after N events have been counted? Or does it mean counting instances where something takes longer than a specific number of cycles?
The latter.
Quoted 12 lines
Quoted 11 lines
- When trying to schedule multiple event groups at once, and using restricted events, situations could arise where scheduling fails even though it would be possible. Consider three groups, each with two events. One group has restricted events, the others don't. The two non-restricted groups are scheduled, then one is removed, which happens to occupy the two counters that can't do restricted events. The remaining non-restricted group will not be moved to the non-restricted-capable counters to make room if the restricted group tries to be scheduled. Since thresholds are not yet supported (though you can use the events with a threshold of zero), and threshold events are the only restricted events, this seems like a low priority issue.
Quoted 3 lines
Which way around are the restrictions? That some events can only be counted on certain counters, or that some counters can only count a subset of the available events?
You could look at it either way -- threshold-capable events can only go on counters 0-1, or counters 2-3 can only count non-threshold-capable events.
Quoted 4 lines
Did you look at the constraint satisfaction code in the existing
perf_event.cand p*-pmu.c? That lets you express both sorts of restrictions and automatically find the best solution (including moving events from one counter to another like you describe).
I did look at it -- but I had a hard time understanding it, and went with the simpler approach for now since the constraints are minimal on these chips. I'm open to converting with a little help, if it doesn't add too much complexity or if future chips need it.
Quoted 4 lines
Quoted 4 lines
arch/powerpc/include/asm/perf_event.h +4
-0+#ifdef CONFIG_FSL_EMB_PERFMON +#define MAX_HWEVENTS 4 + +/* event flags */
Quoted 8 lines
arch/powerpc/include/asm/perf_event.h line 23
Quoted 4 lines
arch/powerpc/include/asm/perf_event.h +4
-0+#define FSL_EMB_EVENT_VALID 1 +#define FSL_EMB_EVENT_RESTRICTED 2 + +struct power_pmu {I wonder if we should have just the stuff exported to the core in
asm/perf_event.hand moveMAX_HWEVENTS, structpower_pmuetc. to separate headers forfsl_embedded, classic, etc.?
Maybe. We may also want to consider making it runtime selectable, as later revisions of e300 have an e500-style performance counter. There's also a separate platform-level performance counter on some of our chips; having arch infrastructure that can delegate to multiple counter types would help there as well.
Quoted 4 lines
Quoted 4 lines
arch/powerpc/kernel/Makefile +0
-0@@ -98,7 +98,10 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o
Quoted 11 lines
arch/powerpc/kernel/Makefile obj64-$(CONFIG_AUDIT) += compat_audit.o · line 104
Quoted 7 lines
arch/powerpc/kernel/Makefile +4
-1obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.o obj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o -obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o +obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o +obj-$(CONFIG_PERF_EVENTS) += perf_callchain.oThis is because we want perf_callchain.o even if we don't have hardware PMU support, is it? If so this is a separate fix that deserves its own patch.
OK.
-Scott
Quoted 11 lines · Scott Wood
Quoted 8 lines · Paul Mackerras
Quoted 3 lines
Some limitations:
- No threshold support -- need to figure out how to represent it in the event struct from userspace.What does "threshold support" mean in this context? Does it mean something different from getting an interrupt after N events have been counted? Or does it mean counting instances where something takes longer than a specific number of cycles?
The latter.
OK. I handled that on classic by using some extra high bits in the event config for the threshold value. If you have a single threshold value in hardware but more than one event that uses that threshold value, then you will need to add a constraint that all threshold events have to specify the same threshold.
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
- When trying to schedule multiple event groups at once, and using restricted events, situations could arise where scheduling fails even though it would be possible. Consider three groups, each with two events. One group has restricted events, the others don't. The two non-restricted groups are scheduled, then one is removed, which happens to occupy the two counters that can't do restricted events. The remaining non-restricted group will not be moved to the non-restricted-capable counters to make room if the restricted group tries to be scheduled. Since thresholds are not yet supported (though you can use the events with a threshold of zero), and threshold events are the only restricted events, this seems like a low priority issue.
Quoted 7 lines
Quoted 3 lines
Which way around are the restrictions? That some events can only be counted on certain counters, or that some counters can only count a subset of the available events?
You could look at it either way -- threshold-capable events can only go on counters 0-1, or counters 2-3 can only count non-threshold-capable events.
So, it sounds like you have a class of events which are the thresholding events, and two constraints:
* at most two events in the thresholding event class
* at most four events in total
Are there other constraints? Apart from the thresholding events, can any event go on any counter, or can some events only be counted on one particular counter?
Quoted 9 lines
Quoted 4 lines
Did you look at the constraint satisfaction code in the existing
perf_event.cand p*-pmu.c? That lets you express both sorts of restrictions and automatically find the best solution (including moving events from one counter to another like you describe).I did look at it -- but I had a hard time understanding it, and went with the simpler approach for now since the constraints are minimal on these chips. I'm open to converting with a little help, if it doesn't add too much complexity or if future chips need it.
Well, the first thing is that it separates out the question "can the PMU handle this set of events?" from the question "which counter should each event go on?". The second question is handled by model-specific code, and turns out to be fairly straightforward once you know the answer to the first question is yes. In general you just work from the most constrained events to the least constrained.
For the first question, you have to look at the specific hardware details of the PMU and turn its programming model into a set of constraints. The two main sorts of constraints I used were:
* Some events require a particular hardware register bitfield to be programmed to a specific value, so if you have two such events, they must require the same value in that bitfield, or else they conflict. There can be several such bitfields, each with an associated class of events.
* For some events, there is a limit on how many such events the PMU can support (for example, your threshold events, where you can have at most 2). For each such limit, there is a class of events which are subject to that limit. There is always the "all events" class, which is subject to the limit imposed by the number of PMCs.
Now, obviously you can represent each such constraint with a variable and have a piece of code for each constraint that checks whether it is satisfied or not. What I did with the code for the POWER cpus was to work out a way to represent all the constraint information in a pair of unsigned long values ("value" and "mask"). This means that the constraint checking can be done with some simple integer arithmetic, and it can be done by generic code that doesn't need to know what the individual constraints are.
If your constraints are just the two listed above (<= 2 threshold events, <= 4 events total), then doing it the obvious straightforward way is fine. If there are other constraints as well, such as certain events only being available on one specific PMC, then you should consider reusing the constraint checking machinery from ppc64.
Paul.
Quoted 6 lines · Paul Mackerras
Quoted 4 lines · Scott Wood
Quoted 3 lines · Paul Mackerras
Quoted 3 lines
Some limitations:
- No threshold support -- need to figure out how to represent it in the event struct from userspace.
Quoted 8 lines
Quoted 5 lines
Quoted 4 lines
What does "threshold support" mean in this context? Does it mean something different from getting an interrupt after N events have been counted? Or does it mean counting instances where something takes longer than a specific number of cycles?
The latter.
OK. I handled that on classic by using some extra high bits in the event config for the threshold value.
OK.
Quoted 4 lines
If you have a single threshold
value in hardware but more than one event that uses that threshold value, then you will need to add a constraint that all threshold events have to specify the same threshold.
There's a separate threshold for each counter.
Quoted 9 lines
So, it sounds like you have a class of events which are the thresholding events, and two constraints:
* at most two events in the thresholding event class
* at most four events in totalAre there other constraints? Apart from the thresholding events, can any event go on any counter, or can some events only be counted on one particular counter?
No, those are the only constraints.
Quoted 5 lines
If your constraints are just the two listed above (<= 2 threshold events, <= 4 events total), then doing it the obvious straightforward way is fine. If there are other constraints as well, such as certain events only being available on one specific PMC, then you should consider reusing the constraint checking machinery from ppc64.
I'll stick with the straightforward approach then. If future chips have more complicated constraints we can revisit using the more general scheme.
-Scott
Quoted 5 lines · Scott Wood
Quoted 4 lines · Paul Mackerras
Quoted 3 lines · Scott Wood
Quoted 2 lines · Paul Mackerras
Quoted 2 lines
Some limitations:
- No threshold support -- need to figure out how to represent it =
in
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 3 lines
Quoted 1 line
the event struct from userspace.
What does "threshold support" mean in this context? Does it mean something different from getting an interrupt after N events have =
been
Quoted 8 lines
Quoted 5 lines
Quoted 3 lines
Quoted 2 lines
counted? Or does it mean counting instances where something takes longer than a specific number of cycles?
The latter.
OK. I handled that on classic by using some extra high bits in the event config for the threshold value.=20
=20
OK.
=20
Quoted 13 lines
Quoted 4 lines
If you have a single threshold
value in hardware but more than one event that uses that threshold value, then you will need to add a constraint that all threshold events have to specify the same threshold.=20
There's a separate threshold for each counter.
=20Quoted 6 lines
So, it sounds like you have a class of events which are the thresholding events, and two constraints:
* at most two events in the thresholding event class
* at most four events in total
Are there other constraints? Apart from the thresholding events, can any event go on any counter, or can some events only be counted on =
one
Quoted 6 lines
Quoted 1 line
particular counter?
=20
No, those are the only constraints.
=20Quoted 2 lines
If your constraints are just the two listed above (<=3D 2 threshold events, <=3D 4 events total), then doing it the obvious =
straightforward
Quoted 5 lines
Quoted 3 lines
way is fine. If there are other constraints as well, such as certain events only being available on one specific PMC, then you should consider reusing the constraint checking machinery from ppc64.
=20
I'll stick with the straightforward approach then. If future chips =
have more complicated constraints we can revisit using the more general = scheme.
Paul,
Other than splitting the patch did you have any other changes you wanted = to see before we'd get an Ack. I'd like to see this go in for .34.
- k=
Quoted 3 lines · Kumar Gala
Other than splitting the patch did you have any other changes you wanted to see before we'd get an Ack. I'd like to see this go in for .34.
I thought it was a bit ugly having two different definitions of struct power_pmu in perf_event.h with ifdefs. Either give the two structs different names or put them in different files. That plus the splitting out of the perf_callchain patch were my two main concerns.
Paul.
Quoted 15 lines · Scott Wood
Quoted 14 lines
arch/powerpc/kernel/Makefile obj64-$(CONFIG_AUDIT) += compat_audit.o · line 104
Quoted 11 lines
arch/powerpc/kernel/Makefile +0
-0@@ -98,7 +98,10 @@ obj64-$(CONFIG_AUDIT) += compat_audit.o obj-$(CONFIG_DYNAMIC_FTRACE) += ftrace.oobj-$(CONFIG_FUNCTION_GRAPH_TRACER) += ftrace.o
arch/powerpc/kernel/Makefile +4
-1-obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o perf_callchain.o +obj-$(CONFIG_PPC_PERF_CTRS) += perf_event.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT) += perf_event_fsl_emb.o +obj-$(CONFIG_FSL_EMB_PERF_EVENT_E500) += e500-pmu.o +obj-$(CONFIG_PERF_EVENTS) += perf_callchain.oThis is because we want perf_callchain.o even if we don't have hardware PMU support, is it? If so this is a separate fix that deserves its own patch.
Quoted 1 line
OK.
You going to repost with this broken up into two patches?
- k