Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9c4c5fd9 authored by Ingo Molnar's avatar Ingo Molnar
Browse files

Merge tag 'perf-core-for-mingo' of...

Merge tag 'perf-core-for-mingo' of git://git.kernel.org/pub/scm/linux/kernel/git/acme/linux

 into perf/core

Pull perf/core improvements and fixes from Arnaldo Carvalho de Melo:

. Make some POWER7 events available in sysfs, equivalent to
  what was done on x86, from Sukadev Bhattiprolu.

. Add event group view, from Namyung Kim:

  To use it, 'perf record' should group events when recording. And then perf
  report parses the saved group relation from file header and prints them
  together if --group option is provided.  You can use 'perf evlist' command to
  see event group information:

    $ perf record -e '{ref-cycles,cycles}' noploop 1
    [ perf record: Woken up 2 times to write data ]
    [ perf record: Captured and wrote 0.385 MB perf.data (~16807 samples) ]

    $ perf evlist --group
    {ref-cycles,cycles}

  With this example, default perf report will show you each event
  separately like this:

    $ perf report
    ...
    # group: {ref-cycles,cycles}
    # ========
    # Samples: 3K of event 'ref-cycles'
    # Event count (approx.): 3153797218
    #
    # Overhead  Command      Shared Object                      Symbol
    # ........  .......  .................  ..........................
        99.84%  noploop  noploop            [.] main
         0.07%  noploop  ld-2.15.so         [.] strcmp
         0.03%  noploop  [kernel.kallsyms]  [k] timerqueue_del
         0.03%  noploop  [kernel.kallsyms]  [k] sched_clock_cpu
         0.02%  noploop  [kernel.kallsyms]  [k] account_user_time
         0.01%  noploop  [kernel.kallsyms]  [k] __alloc_pages_nodemask
         0.00%  noploop  [kernel.kallsyms]  [k] native_write_msr_safe

    # Samples: 3K of event 'cycles'
    # Event count (approx.): 3722310525
    #
    # Overhead  Command      Shared Object                     Symbol
    # ........  .......  .................  .........................
        99.76%  noploop  noploop            [.] main
         0.11%  noploop  [kernel.kallsyms]  [k] _raw_spin_lock
         0.06%  noploop  [kernel.kallsyms]  [k] find_get_page
         0.03%  noploop  [kernel.kallsyms]  [k] sched_clock_cpu
         0.02%  noploop  [kernel.kallsyms]  [k] rcu_check_callbacks
         0.02%  noploop  [kernel.kallsyms]  [k] __current_kernel_time
         0.00%  noploop  [kernel.kallsyms]  [k] native_write_msr_safe

  In this case the event group information will be shown in the end of
  header area.  So you can use --group option to enable event group view.

    $ perf report --group
    ...
    # group: {ref-cycles,cycles}
    # ========
    # Samples: 7K of event 'anon group { ref-cycles, cycles }'
    # Event count (approx.): 6876107743
    #
    #         Overhead  Command      Shared Object                      Symbol
    # ................  .......  .................  ..........................
        99.84%  99.76%  noploop  noploop            [.] main
         0.07%   0.00%  noploop  ld-2.15.so         [.] strcmp
         0.03%   0.00%  noploop  [kernel.kallsyms]  [k] timerqueue_del
         0.03%   0.03%  noploop  [kernel.kallsyms]  [k] sched_clock_cpu
         0.02%   0.00%  noploop  [kernel.kallsyms]  [k] account_user_time
         0.01%   0.00%  noploop  [kernel.kallsyms]  [k] __alloc_pages_nodemask
         0.00%   0.00%  noploop  [kernel.kallsyms]  [k] native_write_msr_safe
         0.00%   0.11%  noploop  [kernel.kallsyms]  [k] _raw_spin_lock
         0.00%   0.06%  noploop  [kernel.kallsyms]  [k] find_get_page
         0.00%   0.02%  noploop  [kernel.kallsyms]  [k] rcu_check_callbacks
         0.00%   0.02%  noploop  [kernel.kallsyms]  [k] __current_kernel_time

  As you can see the Overhead column now contains both of ref-cycles and
  cycles and header line shows group information also - 'anon group {
  ref-cycles, cycles }'.  The output is sorted by period of group leader
  first.

  If perf.data file doesn't contain group information, this --group
  option does nothing.  So if you want enable event group view by
  default you can set it in ~/.perfconfig file:

    $ cat ~/.perfconfig
    [report]
    group = true

  It can be overridden with command line if you want:

    $ perf report --no-group

Signed-off-by: default avatarArnaldo Carvalho de Melo <acme@redhat.com>
Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parents 152fefa9 2ac3634a
Loading
Loading
Loading
Loading
+62 −0
Original line number Diff line number Diff line
What:		/sys/devices/cpu/events/
		/sys/devices/cpu/events/branch-misses
		/sys/devices/cpu/events/cache-references
		/sys/devices/cpu/events/cache-misses
		/sys/devices/cpu/events/stalled-cycles-frontend
		/sys/devices/cpu/events/branch-instructions
		/sys/devices/cpu/events/stalled-cycles-backend
		/sys/devices/cpu/events/instructions
		/sys/devices/cpu/events/cpu-cycles

Date:		2013/01/08

Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>

Description:	Generic performance monitoring events

		A collection of performance monitoring events that may be
		supported by many/most CPUs. These events can be monitored
		using the 'perf(1)' tool.

		The contents of each file would look like:

			event=0xNNNN

		where 'N' is a hex digit and the number '0xNNNN' shows the
		"raw code" for the perf event identified by the file's
		"basename".


What: 		/sys/devices/cpu/events/PM_LD_MISS_L1
		/sys/devices/cpu/events/PM_LD_REF_L1
		/sys/devices/cpu/events/PM_CYC
		/sys/devices/cpu/events/PM_BRU_FIN
		/sys/devices/cpu/events/PM_GCT_NOSLOT_CYC
		/sys/devices/cpu/events/PM_BRU_MPRED
		/sys/devices/cpu/events/PM_INST_CMPL
		/sys/devices/cpu/events/PM_CMPLU_STALL

Date:		2013/01/08

Contact:	Linux kernel mailing list <linux-kernel@vger.kernel.org>
		Linux Powerpc mailing list <linuxppc-dev@ozlabs.org>

Description:	POWER-systems specific performance monitoring events

		A collection of performance monitoring events that may be
		supported by the POWER CPU. These events can be monitored
		using the 'perf(1)' tool.

		These events may not be supported by other CPUs.

		The contents of each file would look like:

			event=0xNNNN

		where 'N' is a hex digit and the number '0xNNNN' shows the
		"raw code" for the perf event identified by the file's
		"basename".

		Further, multiple terms like 'event=0xNNNN' can be specified
		and separated with comma. All available terms are defined in
		the /sys/bus/event_source/devices/<dev>/format file.
+26 −0
Original line number Diff line number Diff line
@@ -11,6 +11,7 @@

#include <linux/types.h>
#include <asm/hw_irq.h>
#include <linux/device.h>

#define MAX_HWEVENTS		8
#define MAX_EVENT_ALTERNATIVES	8
@@ -35,6 +36,7 @@ struct power_pmu {
	void		(*disable_pmc)(unsigned int pmc, unsigned long mmcr[]);
	int		(*limited_pmc_event)(u64 event_id);
	u32		flags;
	const struct attribute_group	**attr_groups;
	int		n_generic;
	int		*generic_events;
	int		(*cache_events)[PERF_COUNT_HW_CACHE_MAX]
@@ -109,3 +111,27 @@ 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.
 */

extern ssize_t power_events_sysfs_show(struct device *dev,
				struct device_attribute *attr, char *page);

/*
 * EVENT_VAR() is same as PMU_EVENT_VAR with a suffix.
 *
 * Having a suffix allows us to have aliases in sysfs - eg: the generic
 * event 'cpu-cycles' can have two entries in sysfs: 'cpu-cycles' and
 * 'PM_CYC' where the latter is the name by which the event is known in
 * POWER CPU specification.
 */
#define	EVENT_VAR(_id, _suffix)		event_attr_##_id##_suffix
#define	EVENT_PTR(_id, _suffix)		&EVENT_VAR(_id, _suffix)

#define	EVENT_ATTR(_name, _id, _suffix)					\
	PMU_EVENT_ATTR(_name, EVENT_VAR(_id, _suffix), PME_PM_##_id,	\
			power_events_sysfs_show)

#define	GENERIC_EVENT_ATTR(_name, _id)	EVENT_ATTR(_name, _id, _g)
#define	GENERIC_EVENT_PTR(_id)		EVENT_PTR(_id, _g)

#define	POWER_EVENT_ATTR(_name, _id)	EVENT_ATTR(PM_##_name, _id, _p)
#define	POWER_EVENT_PTR(_id)		EVENT_PTR(_id, _p)
+12 −0
Original line number Diff line number Diff line
@@ -1305,6 +1305,16 @@ static int power_pmu_event_idx(struct perf_event *event)
	return event->hw.idx;
}

ssize_t power_events_sysfs_show(struct device *dev,
				struct device_attribute *attr, char *page)
{
	struct perf_pmu_events_attr *pmu_attr;

	pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);

	return sprintf(page, "event=0x%02llx\n", pmu_attr->id);
}

struct pmu power_pmu = {
	.pmu_enable	= power_pmu_enable,
	.pmu_disable	= power_pmu_disable,
@@ -1537,6 +1547,8 @@ int __cpuinit register_power_pmu(struct power_pmu *pmu)
	pr_info("%s performance monitor hardware support registered\n",
		pmu->name);

	power_pmu.attr_groups = ppmu->attr_groups;

#ifdef MSR_HV
	/*
	 * Use FCHV to ignore kernel events if MSR.HV is set.
+72 −8
Original line number Diff line number Diff line
@@ -50,6 +50,18 @@
#define MMCR1_PMCSEL_SH(n)	(MMCR1_PMC1SEL_SH - (n) * 8)
#define MMCR1_PMCSEL_MSK	0xff

/*
 * Power7 event codes.
 */
#define	PME_PM_CYC			0x1e
#define	PME_PM_GCT_NOSLOT_CYC		0x100f8
#define	PME_PM_CMPLU_STALL		0x4000a
#define	PME_PM_INST_CMPL		0x2
#define	PME_PM_LD_REF_L1		0xc880
#define	PME_PM_LD_MISS_L1		0x400f0
#define	PME_PM_BRU_FIN			0x10068
#define	PME_PM_BRU_MPRED		0x400f6

/*
 * Layout of constraint bits:
 * 6666555555555544444444443333333333222222222211111111110000000000
@@ -307,14 +319,14 @@ static void power7_disable_pmc(unsigned int pmc, unsigned long mmcr[])
}

static int power7_generic_events[] = {
	[PERF_COUNT_HW_CPU_CYCLES] = 0x1e,
	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] = 0x100f8, /* GCT_NOSLOT_CYC */
	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] = 0x4000a,  /* CMPLU_STALL */
	[PERF_COUNT_HW_INSTRUCTIONS] = 2,
	[PERF_COUNT_HW_CACHE_REFERENCES] = 0xc880,	/* LD_REF_L1_LSU*/
	[PERF_COUNT_HW_CACHE_MISSES] = 0x400f0,		/* LD_MISS_L1	*/
	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = 0x10068,	/* BRU_FIN	*/
	[PERF_COUNT_HW_BRANCH_MISSES] = 0x400f6,	/* BR_MPRED	*/
	[PERF_COUNT_HW_CPU_CYCLES] =			PME_PM_CYC,
	[PERF_COUNT_HW_STALLED_CYCLES_FRONTEND] =	PME_PM_GCT_NOSLOT_CYC,
	[PERF_COUNT_HW_STALLED_CYCLES_BACKEND] =	PME_PM_CMPLU_STALL,
	[PERF_COUNT_HW_INSTRUCTIONS] =			PME_PM_INST_CMPL,
	[PERF_COUNT_HW_CACHE_REFERENCES] =		PME_PM_LD_REF_L1,
	[PERF_COUNT_HW_CACHE_MISSES] =			PME_PM_LD_MISS_L1,
	[PERF_COUNT_HW_BRANCH_INSTRUCTIONS] =		PME_PM_BRU_FIN,
	[PERF_COUNT_HW_BRANCH_MISSES] =			PME_PM_BRU_MPRED,
};

#define C(x)	PERF_COUNT_HW_CACHE_##x
@@ -362,6 +374,57 @@ static int power7_cache_events[C(MAX)][C(OP_MAX)][C(RESULT_MAX)] = {
	},
};


GENERIC_EVENT_ATTR(cpu-cycles,			CYC);
GENERIC_EVENT_ATTR(stalled-cycles-frontend,	GCT_NOSLOT_CYC);
GENERIC_EVENT_ATTR(stalled-cycles-backend,	CMPLU_STALL);
GENERIC_EVENT_ATTR(instructions,		INST_CMPL);
GENERIC_EVENT_ATTR(cache-references,		LD_REF_L1);
GENERIC_EVENT_ATTR(cache-misses,		LD_MISS_L1);
GENERIC_EVENT_ATTR(branch-instructions,		BRU_FIN);
GENERIC_EVENT_ATTR(branch-misses,		BRU_MPRED);

POWER_EVENT_ATTR(CYC,				CYC);
POWER_EVENT_ATTR(GCT_NOSLOT_CYC,		GCT_NOSLOT_CYC);
POWER_EVENT_ATTR(CMPLU_STALL,			CMPLU_STALL);
POWER_EVENT_ATTR(INST_CMPL,			INST_CMPL);
POWER_EVENT_ATTR(LD_REF_L1,			LD_REF_L1);
POWER_EVENT_ATTR(LD_MISS_L1,			LD_MISS_L1);
POWER_EVENT_ATTR(BRU_FIN,			BRU_FIN)
POWER_EVENT_ATTR(BRU_MPRED,			BRU_MPRED);

static struct attribute *power7_events_attr[] = {
	GENERIC_EVENT_PTR(CYC),
	GENERIC_EVENT_PTR(GCT_NOSLOT_CYC),
	GENERIC_EVENT_PTR(CMPLU_STALL),
	GENERIC_EVENT_PTR(INST_CMPL),
	GENERIC_EVENT_PTR(LD_REF_L1),
	GENERIC_EVENT_PTR(LD_MISS_L1),
	GENERIC_EVENT_PTR(BRU_FIN),
	GENERIC_EVENT_PTR(BRU_MPRED),

	POWER_EVENT_PTR(CYC),
	POWER_EVENT_PTR(GCT_NOSLOT_CYC),
	POWER_EVENT_PTR(CMPLU_STALL),
	POWER_EVENT_PTR(INST_CMPL),
	POWER_EVENT_PTR(LD_REF_L1),
	POWER_EVENT_PTR(LD_MISS_L1),
	POWER_EVENT_PTR(BRU_FIN),
	POWER_EVENT_PTR(BRU_MPRED),
	NULL
};


static struct attribute_group power7_pmu_events_group = {
	.name = "events",
	.attrs = power7_events_attr,
};

static const struct attribute_group *power7_pmu_attr_groups[] = {
	&power7_pmu_events_group,
	NULL,
};

static struct power_pmu power7_pmu = {
	.name			= "POWER7",
	.n_counter		= 6,
@@ -373,6 +436,7 @@ static struct power_pmu power7_pmu = {
	.get_alternatives	= power7_get_alternatives,
	.disable_pmc		= power7_disable_pmc,
	.flags			= PPMU_ALT_SIPR,
	.attr_groups		= power7_pmu_attr_groups,
	.n_generic		= ARRAY_SIZE(power7_generic_events),
	.generic_events		= power7_generic_events,
	.cache_events		= &power7_cache_events,
+3 −10
Original line number Diff line number Diff line
@@ -1310,11 +1310,6 @@ static struct attribute_group x86_pmu_format_group = {
	.attrs = NULL,
};

struct perf_pmu_events_attr {
	struct device_attribute attr;
	u64 id;
};

/*
 * Remove all undefined events (x86_pmu.event_map(id) == 0)
 * out of events_attr attributes.
@@ -1349,10 +1344,8 @@ static ssize_t events_sysfs_show(struct device *dev, struct device_attribute *at
#define EVENT_PTR(_id) &event_attr_##_id.attr.attr

#define EVENT_ATTR(_name, _id)						\
static struct perf_pmu_events_attr EVENT_VAR(_id) = {		\
	.attr = __ATTR(_name, 0444, events_sysfs_show, NULL),	\
	.id   =  PERF_COUNT_HW_##_id,				\
};
	PMU_EVENT_ATTR(_name, EVENT_VAR(_id), PERF_COUNT_HW_##_id,	\
			events_sysfs_show)

EVENT_ATTR(cpu-cycles,			CPU_CYCLES		);
EVENT_ATTR(instructions,		INSTRUCTIONS		);
Loading