Skip to contentSkip to conversation

perf_event: e500 support

PATCH In review Scott Wood 3 participants 8 messages Jan 15, 2010 – Feb 18, 2010

Subsystems (2)
lore
Share & tools
lore

Scott Wood

author
#0 lore raw

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
index 3288ce3..2fd2781 100644
@@ -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
index 0de404d..77bb71c 100644
@@ -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
index c002b04..ab98a88 100644
@@ -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
index 2fc82ba..8af4949 100644
@@ -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
index fa0f690..f78d629 100644
@@ -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
#1 lore raw
Quoted 3 lines · Scott Wood

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.

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
index 3288ce3..2fd2781 100644
@@ -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.

author
#2 lore raw
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.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).

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.h and move MAX_HWEVENTS, struct power_pmu etc. to separate headers for fsl_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 -1
 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.

OK.

-Scott

#3 lore raw
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.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).

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.

author
#4 lore raw
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 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?

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

#5 lore raw
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.
=20

Quoted 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.
=20

Quoted 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=

#6 lore raw
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.

#7 lore raw
In reply to Scott Wood
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.o

obj-$(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.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.

Quoted 1 line

OK.

You going to repost with this broken up into two patches?

- k