Skip to content

Commit f187e9f

Browse files
committed
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates and fixes from Ingo Molnar: "It's mostly fixes, but there's also two late items: - preliminary GTK GUI support for perf report - PMU raw event format descriptors in sysfs, to be parsed by tooling The raw event format in sysfs is a new ABI. For example for the 'CPU' PMU we have: aldebaran:~> ll /sys/bus/event_source/devices/cpu/format/* -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/any -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/cmask -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/edge -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/event -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/inv -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/offcore_rsp -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/pc -r--r--r--. 1 root root 4096 Mar 31 10:29 /sys/bus/event_source/devices/cpu/format/umask those lists of fields contain a specific format: aldebaran:~> cat /sys/bus/event_source/devices/cpu/format/offcore_rsp config1:0-63 So, those who wish to specify raw events can now use the following event format: -e cpu/cmask=1,event=2,umask=3 Most people will not want to specify any events (let alone raw events), they'll just use whatever default event the tools use. But for more obscure PMU events that have no cross-architecture generic events the above syntax is more usable and a bit more structured than specifying hex numbers." * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (41 commits) perf tools: Remove auto-generated bison/flex files perf annotate: Fix off by one symbol hist size allocation and hit accounting perf tools: Add missing ref-cycles event back to event parser perf annotate: addr2line wants addresses in same format as objdump perf probe: Finder fails to resolve function name to address tracing: Fix ent_size in trace output perf symbols: Handle NULL dso in dso__name_len perf symbols: Do not include libgen.h perf tools: Fix bug in raw sample parsing perf tools: Fix display of first level of callchains perf tools: Switch module.h into export.h perf: Move mmap page data_head offset assertion out of header perf: Fix mmap_page capabilities and docs perf diff: Fix to work with new hists design perf tools: Fix modifier to be applied on correct events perf tools: Fix various casting issues for 32 bits perf tools: Simplify event_read_id exit path tracing: Fix ftrace stack trace entries tracing: Move the tracing_on/off() declarations into CONFIG_TRACING perf report: Add a simple GTK2-based 'perf report' browser ...
2 parents adb3b1f + 8ebfdf2 commit f187e9f

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

52 files changed

+2531
-584
lines changed
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
Where: /sys/bus/event_source/devices/<dev>/format
2+
Date: January 2012
3+
Kernel Version: 3.3
4+
Contact: Jiri Olsa <[email protected]>
5+
Description:
6+
Attribute group to describe the magic bits that go into
7+
perf_event_attr::config[012] for a particular pmu.
8+
Each attribute of this group defines the 'hardware' bitmask
9+
we want to export, so that userspace can deal with sane
10+
name/value pairs.
11+
12+
Example: 'config1:1,6-10,44'
13+
Defines contents of attribute that occupies bits 1,6-10,44 of
14+
perf_event_attr::config1.

arch/x86/kernel/cpu/perf_event.c

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1313,6 +1313,11 @@ static void __init pmu_check_apic(void)
13131313
pr_info("no hardware sampling interrupt available.\n");
13141314
}
13151315

1316+
static struct attribute_group x86_pmu_format_group = {
1317+
.name = "format",
1318+
.attrs = NULL,
1319+
};
1320+
13161321
static int __init init_hw_perf_events(void)
13171322
{
13181323
struct x86_pmu_quirk *quirk;
@@ -1387,6 +1392,7 @@ static int __init init_hw_perf_events(void)
13871392
}
13881393

13891394
x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
1395+
x86_pmu_format_group.attrs = x86_pmu.format_attrs;
13901396

13911397
pr_info("... version: %d\n", x86_pmu.version);
13921398
pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
@@ -1615,6 +1621,9 @@ static int x86_pmu_event_idx(struct perf_event *event)
16151621
{
16161622
int idx = event->hw.idx;
16171623

1624+
if (!x86_pmu.attr_rdpmc)
1625+
return 0;
1626+
16181627
if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) {
16191628
idx -= X86_PMC_IDX_FIXED;
16201629
idx |= 1 << 30;
@@ -1667,6 +1676,7 @@ static struct attribute_group x86_pmu_attr_group = {
16671676

16681677
static const struct attribute_group *x86_pmu_attr_groups[] = {
16691678
&x86_pmu_attr_group,
1679+
&x86_pmu_format_group,
16701680
NULL,
16711681
};
16721682

@@ -1698,14 +1708,19 @@ static struct pmu pmu = {
16981708
.flush_branch_stack = x86_pmu_flush_branch_stack,
16991709
};
17001710

1701-
void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now)
1711+
void arch_perf_update_userpage(struct perf_event_mmap_page *userpg, u64 now)
17021712
{
1713+
userpg->cap_usr_time = 0;
1714+
userpg->cap_usr_rdpmc = x86_pmu.attr_rdpmc;
1715+
userpg->pmc_width = x86_pmu.cntval_bits;
1716+
17031717
if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
17041718
return;
17051719

17061720
if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
17071721
return;
17081722

1723+
userpg->cap_usr_time = 1;
17091724
userpg->time_mult = this_cpu_read(cyc2ns);
17101725
userpg->time_shift = CYC2NS_SCALE_FACTOR;
17111726
userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;

arch/x86/kernel/cpu/perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,7 @@ struct x86_pmu {
339339
* sysfs attrs
340340
*/
341341
int attr_rdpmc;
342+
struct attribute **format_attrs;
342343

343344
/*
344345
* CPU Hotplug hooks

arch/x86/kernel/cpu/perf_event_amd.c

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -404,6 +404,21 @@ static void amd_pmu_cpu_dead(int cpu)
404404
}
405405
}
406406

407+
PMU_FORMAT_ATTR(event, "config:0-7,32-35");
408+
PMU_FORMAT_ATTR(umask, "config:8-15" );
409+
PMU_FORMAT_ATTR(edge, "config:18" );
410+
PMU_FORMAT_ATTR(inv, "config:23" );
411+
PMU_FORMAT_ATTR(cmask, "config:24-31" );
412+
413+
static struct attribute *amd_format_attr[] = {
414+
&format_attr_event.attr,
415+
&format_attr_umask.attr,
416+
&format_attr_edge.attr,
417+
&format_attr_inv.attr,
418+
&format_attr_cmask.attr,
419+
NULL,
420+
};
421+
407422
static __initconst const struct x86_pmu amd_pmu = {
408423
.name = "AMD",
409424
.handle_irq = x86_pmu_handle_irq,
@@ -426,6 +441,8 @@ static __initconst const struct x86_pmu amd_pmu = {
426441
.get_event_constraints = amd_get_event_constraints,
427442
.put_event_constraints = amd_put_event_constraints,
428443

444+
.format_attrs = amd_format_attr,
445+
429446
.cpu_prepare = amd_pmu_cpu_prepare,
430447
.cpu_starting = amd_pmu_cpu_starting,
431448
.cpu_dead = amd_pmu_cpu_dead,
@@ -596,6 +613,7 @@ static __initconst const struct x86_pmu amd_pmu_f15h = {
596613
.cpu_dead = amd_pmu_cpu_dead,
597614
#endif
598615
.cpu_starting = amd_pmu_cpu_starting,
616+
.format_attrs = amd_format_attr,
599617
};
600618

601619
__init int amd_pmu_init(void)

arch/x86/kernel/cpu/perf_event_intel.c

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1431,6 +1431,24 @@ static void core_pmu_enable_all(int added)
14311431
}
14321432
}
14331433

1434+
PMU_FORMAT_ATTR(event, "config:0-7" );
1435+
PMU_FORMAT_ATTR(umask, "config:8-15" );
1436+
PMU_FORMAT_ATTR(edge, "config:18" );
1437+
PMU_FORMAT_ATTR(pc, "config:19" );
1438+
PMU_FORMAT_ATTR(any, "config:21" ); /* v3 + */
1439+
PMU_FORMAT_ATTR(inv, "config:23" );
1440+
PMU_FORMAT_ATTR(cmask, "config:24-31" );
1441+
1442+
static struct attribute *intel_arch_formats_attr[] = {
1443+
&format_attr_event.attr,
1444+
&format_attr_umask.attr,
1445+
&format_attr_edge.attr,
1446+
&format_attr_pc.attr,
1447+
&format_attr_inv.attr,
1448+
&format_attr_cmask.attr,
1449+
NULL,
1450+
};
1451+
14341452
static __initconst const struct x86_pmu core_pmu = {
14351453
.name = "core",
14361454
.handle_irq = x86_pmu_handle_irq,
@@ -1455,6 +1473,7 @@ static __initconst const struct x86_pmu core_pmu = {
14551473
.put_event_constraints = intel_put_event_constraints,
14561474
.event_constraints = intel_core_event_constraints,
14571475
.guest_get_msrs = core_guest_get_msrs,
1476+
.format_attrs = intel_arch_formats_attr,
14581477
};
14591478

14601479
struct intel_shared_regs *allocate_shared_regs(int cpu)
@@ -1553,6 +1572,21 @@ static void intel_pmu_flush_branch_stack(void)
15531572
intel_pmu_lbr_reset();
15541573
}
15551574

1575+
PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
1576+
1577+
static struct attribute *intel_arch3_formats_attr[] = {
1578+
&format_attr_event.attr,
1579+
&format_attr_umask.attr,
1580+
&format_attr_edge.attr,
1581+
&format_attr_pc.attr,
1582+
&format_attr_any.attr,
1583+
&format_attr_inv.attr,
1584+
&format_attr_cmask.attr,
1585+
1586+
&format_attr_offcore_rsp.attr, /* XXX do NHM/WSM + SNB breakout */
1587+
NULL,
1588+
};
1589+
15561590
static __initconst const struct x86_pmu intel_pmu = {
15571591
.name = "Intel",
15581592
.handle_irq = intel_pmu_handle_irq,
@@ -1576,6 +1610,8 @@ static __initconst const struct x86_pmu intel_pmu = {
15761610
.get_event_constraints = intel_get_event_constraints,
15771611
.put_event_constraints = intel_put_event_constraints,
15781612

1613+
.format_attrs = intel_arch3_formats_attr,
1614+
15791615
.cpu_prepare = intel_pmu_cpu_prepare,
15801616
.cpu_starting = intel_pmu_cpu_starting,
15811617
.cpu_dying = intel_pmu_cpu_dying,

arch/x86/kernel/cpu/perf_event_p6.c

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,23 @@ static void p6_pmu_enable_event(struct perf_event *event)
8787
(void)checking_wrmsrl(hwc->config_base, val);
8888
}
8989

90+
PMU_FORMAT_ATTR(event, "config:0-7" );
91+
PMU_FORMAT_ATTR(umask, "config:8-15" );
92+
PMU_FORMAT_ATTR(edge, "config:18" );
93+
PMU_FORMAT_ATTR(pc, "config:19" );
94+
PMU_FORMAT_ATTR(inv, "config:23" );
95+
PMU_FORMAT_ATTR(cmask, "config:24-31" );
96+
97+
static struct attribute *intel_p6_formats_attr[] = {
98+
&format_attr_event.attr,
99+
&format_attr_umask.attr,
100+
&format_attr_edge.attr,
101+
&format_attr_pc.attr,
102+
&format_attr_inv.attr,
103+
&format_attr_cmask.attr,
104+
NULL,
105+
};
106+
90107
static __initconst const struct x86_pmu p6_pmu = {
91108
.name = "p6",
92109
.handle_irq = x86_pmu_handle_irq,
@@ -115,6 +132,8 @@ static __initconst const struct x86_pmu p6_pmu = {
115132
.cntval_mask = (1ULL << 32) - 1,
116133
.get_event_constraints = x86_get_event_constraints,
117134
.event_constraints = p6_event_constraints,
135+
136+
.format_attrs = intel_p6_formats_attr,
118137
};
119138

120139
__init int p6_pmu_init(void)

include/linux/ftrace_event.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -144,12 +144,14 @@ struct event_filter;
144144
enum trace_reg {
145145
TRACE_REG_REGISTER,
146146
TRACE_REG_UNREGISTER,
147+
#ifdef CONFIG_PERF_EVENTS
147148
TRACE_REG_PERF_REGISTER,
148149
TRACE_REG_PERF_UNREGISTER,
149150
TRACE_REG_PERF_OPEN,
150151
TRACE_REG_PERF_CLOSE,
151152
TRACE_REG_PERF_ADD,
152153
TRACE_REG_PERF_DEL,
154+
#endif
153155
};
154156

155157
struct ftrace_event_call;

include/linux/kernel.h

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -430,16 +430,10 @@ extern int __must_check hex2bin(u8 *dst, const char *src, size_t count);
430430
* Most likely, you want to use tracing_on/tracing_off.
431431
*/
432432
#ifdef CONFIG_RING_BUFFER
433-
void tracing_on(void);
434-
void tracing_off(void);
435433
/* trace_off_permanent stops recording with no way to bring it back */
436434
void tracing_off_permanent(void);
437-
int tracing_is_on(void);
438435
#else
439-
static inline void tracing_on(void) { }
440-
static inline void tracing_off(void) { }
441436
static inline void tracing_off_permanent(void) { }
442-
static inline int tracing_is_on(void) { return 0; }
443437
#endif
444438

445439
enum ftrace_dump_mode {
@@ -449,6 +443,10 @@ enum ftrace_dump_mode {
449443
};
450444

451445
#ifdef CONFIG_TRACING
446+
void tracing_on(void);
447+
void tracing_off(void);
448+
int tracing_is_on(void);
449+
452450
extern void tracing_start(void);
453451
extern void tracing_stop(void);
454452
extern void ftrace_off_permanent(void);
@@ -533,6 +531,11 @@ static inline void tracing_start(void) { }
533531
static inline void tracing_stop(void) { }
534532
static inline void ftrace_off_permanent(void) { }
535533
static inline void trace_dump_stack(void) { }
534+
535+
static inline void tracing_on(void) { }
536+
static inline void tracing_off(void) { }
537+
static inline int tracing_is_on(void) { return 0; }
538+
536539
static inline int
537540
trace_printk(const char *fmt, ...)
538541
{

include/linux/perf_event.h

Lines changed: 80 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -299,18 +299,31 @@ struct perf_event_mmap_page {
299299
/*
300300
* Bits needed to read the hw events in user-space.
301301
*
302-
* u32 seq;
303-
* s64 count;
302+
* u32 seq, time_mult, time_shift, idx, width;
303+
* u64 count, enabled, running;
304+
* u64 cyc, time_offset;
305+
* s64 pmc = 0;
304306
*
305307
* do {
306308
* seq = pc->lock;
307-
*
308309
* barrier()
309-
* if (pc->index) {
310-
* count = pmc_read(pc->index - 1);
311-
* count += pc->offset;
312-
* } else
313-
* goto regular_read;
310+
*
311+
* enabled = pc->time_enabled;
312+
* running = pc->time_running;
313+
*
314+
* if (pc->cap_usr_time && enabled != running) {
315+
* cyc = rdtsc();
316+
* time_offset = pc->time_offset;
317+
* time_mult = pc->time_mult;
318+
* time_shift = pc->time_shift;
319+
* }
320+
*
321+
* idx = pc->index;
322+
* count = pc->offset;
323+
* if (pc->cap_usr_rdpmc && idx) {
324+
* width = pc->pmc_width;
325+
* pmc = rdpmc(idx - 1);
326+
* }
314327
*
315328
* barrier();
316329
* } while (pc->lock != seq);
@@ -323,14 +336,57 @@ struct perf_event_mmap_page {
323336
__s64 offset; /* add to hardware event value */
324337
__u64 time_enabled; /* time event active */
325338
__u64 time_running; /* time event on cpu */
326-
__u32 time_mult, time_shift;
339+
union {
340+
__u64 capabilities;
341+
__u64 cap_usr_time : 1,
342+
cap_usr_rdpmc : 1,
343+
cap_____res : 62;
344+
};
345+
346+
/*
347+
* If cap_usr_rdpmc this field provides the bit-width of the value
348+
* read using the rdpmc() or equivalent instruction. This can be used
349+
* to sign extend the result like:
350+
*
351+
* pmc <<= 64 - width;
352+
* pmc >>= 64 - width; // signed shift right
353+
* count += pmc;
354+
*/
355+
__u16 pmc_width;
356+
357+
/*
358+
* If cap_usr_time the below fields can be used to compute the time
359+
* delta since time_enabled (in ns) using rdtsc or similar.
360+
*
361+
* u64 quot, rem;
362+
* u64 delta;
363+
*
364+
* quot = (cyc >> time_shift);
365+
* rem = cyc & ((1 << time_shift) - 1);
366+
* delta = time_offset + quot * time_mult +
367+
* ((rem * time_mult) >> time_shift);
368+
*
369+
* Where time_offset,time_mult,time_shift and cyc are read in the
370+
* seqcount loop described above. This delta can then be added to
371+
* enabled and possible running (if idx), improving the scaling:
372+
*
373+
* enabled += delta;
374+
* if (idx)
375+
* running += delta;
376+
*
377+
* quot = count / running;
378+
* rem = count % running;
379+
* count = quot * enabled + (rem * enabled) / running;
380+
*/
381+
__u16 time_shift;
382+
__u32 time_mult;
327383
__u64 time_offset;
328384

329385
/*
330386
* Hole for extension of the self monitor capabilities
331387
*/
332388

333-
__u64 __reserved[121]; /* align to 1k */
389+
__u64 __reserved[120]; /* align to 1k */
334390

335391
/*
336392
* Control data for the mmap() data buffer.
@@ -550,6 +606,7 @@ struct perf_guest_info_callbacks {
550606
#include <linux/irq_work.h>
551607
#include <linux/static_key.h>
552608
#include <linux/atomic.h>
609+
#include <linux/sysfs.h>
553610
#include <asm/local.h>
554611

555612
#define PERF_MAX_STACK_DEPTH 255
@@ -1291,5 +1348,18 @@ do { \
12911348
register_cpu_notifier(&fn##_nb); \
12921349
} while (0)
12931350

1351+
1352+
#define PMU_FORMAT_ATTR(_name, _format) \
1353+
static ssize_t \
1354+
_name##_show(struct device *dev, \
1355+
struct device_attribute *attr, \
1356+
char *page) \
1357+
{ \
1358+
BUILD_BUG_ON(sizeof(_format) >= PAGE_SIZE); \
1359+
return sprintf(page, _format "\n"); \
1360+
} \
1361+
\
1362+
static struct device_attribute format_attr_##_name = __ATTR_RO(_name)
1363+
12941364
#endif /* __KERNEL__ */
12951365
#endif /* _LINUX_PERF_EVENT_H */

0 commit comments

Comments
 (0)