aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorIngo Molnar <mingo@elte.hu>2012-01-27 06:07:57 -0500
committerIngo Molnar <mingo@elte.hu>2012-01-27 06:08:09 -0500
commit44a683971119bafb5bc30778f92ee773680ebb6f (patch)
tree58648459f29d45c447bd2352e81844d4d9aa3a15
parent801493c2e249a7314e9e8e54ad60d613d0a86f14 (diff)
parent08aa0d1f376e9b966568316bd2019b3c1274d885 (diff)
Merge branch 'perf/fast' into perf/core
Merge reason: Lets ready it for v3.4 Signed-off-by: Ingo Molnar <mingo@elte.hu>
-rw-r--r--arch/arm/include/asm/perf_event.h4
-rw-r--r--arch/frv/include/asm/perf_event.h2
-rw-r--r--arch/hexagon/include/asm/perf_event.h2
-rw-r--r--arch/powerpc/include/asm/perf_event_server.h2
-rw-r--r--arch/powerpc/kernel/perf_event.c6
-rw-r--r--arch/s390/include/asm/perf_event.h1
-rw-r--r--arch/x86/include/asm/perf_event.h2
-rw-r--r--arch/x86/kernel/cpu/perf_event.c82
-rw-r--r--arch/x86/kernel/cpu/perf_event.h8
-rw-r--r--include/linux/perf_event.h11
-rw-r--r--kernel/events/core.c53
-rw-r--r--kernel/events/hw_breakpoint.c7
-rw-r--r--tools/perf/builtin-test.c177
13 files changed, 328 insertions, 29 deletions
diff --git a/arch/arm/include/asm/perf_event.h b/arch/arm/include/asm/perf_event.h
index 99cfe3607989..7523340afb8a 100644
--- a/arch/arm/include/asm/perf_event.h
+++ b/arch/arm/include/asm/perf_event.h
@@ -12,10 +12,6 @@
12#ifndef __ARM_PERF_EVENT_H__ 12#ifndef __ARM_PERF_EVENT_H__
13#define __ARM_PERF_EVENT_H__ 13#define __ARM_PERF_EVENT_H__
14 14
15/* ARM performance counters start from 1 (in the cp15 accesses) so use the
16 * same indexes here for consistency. */
17#define PERF_EVENT_INDEX_OFFSET 1
18
19/* ARM perf PMU IDs for use by internal perf clients. */ 15/* ARM perf PMU IDs for use by internal perf clients. */
20enum arm_perf_pmu_ids { 16enum arm_perf_pmu_ids {
21 ARM_PERF_PMU_ID_XSCALE1 = 0, 17 ARM_PERF_PMU_ID_XSCALE1 = 0,
diff --git a/arch/frv/include/asm/perf_event.h b/arch/frv/include/asm/perf_event.h
index a69e0155d146..c52ea5546b5b 100644
--- a/arch/frv/include/asm/perf_event.h
+++ b/arch/frv/include/asm/perf_event.h
@@ -12,6 +12,4 @@
12#ifndef _ASM_PERF_EVENT_H 12#ifndef _ASM_PERF_EVENT_H
13#define _ASM_PERF_EVENT_H 13#define _ASM_PERF_EVENT_H
14 14
15#define PERF_EVENT_INDEX_OFFSET 0
16
17#endif /* _ASM_PERF_EVENT_H */ 15#endif /* _ASM_PERF_EVENT_H */
diff --git a/arch/hexagon/include/asm/perf_event.h b/arch/hexagon/include/asm/perf_event.h
index 6c2910f91180..8b8526b491c7 100644
--- a/arch/hexagon/include/asm/perf_event.h
+++ b/arch/hexagon/include/asm/perf_event.h
@@ -19,6 +19,4 @@
19#ifndef _ASM_PERF_EVENT_H 19#ifndef _ASM_PERF_EVENT_H
20#define _ASM_PERF_EVENT_H 20#define _ASM_PERF_EVENT_H
21 21
22#define PERF_EVENT_INDEX_OFFSET 0
23
24#endif /* _ASM_PERF_EVENT_H */ 22#endif /* _ASM_PERF_EVENT_H */
diff --git a/arch/powerpc/include/asm/perf_event_server.h b/arch/powerpc/include/asm/perf_event_server.h
index 8f1df1208d23..1a8093fa8f71 100644
--- a/arch/powerpc/include/asm/perf_event_server.h
+++ b/arch/powerpc/include/asm/perf_event_server.h
@@ -61,8 +61,6 @@ struct pt_regs;
61extern unsigned long perf_misc_flags(struct pt_regs *regs); 61extern unsigned long perf_misc_flags(struct pt_regs *regs);
62extern unsigned long perf_instruction_pointer(struct pt_regs *regs); 62extern unsigned long perf_instruction_pointer(struct pt_regs *regs);
63 63
64#define PERF_EVENT_INDEX_OFFSET 1
65
66/* 64/*
67 * Only override the default definitions in include/linux/perf_event.h 65 * Only override the default definitions in include/linux/perf_event.h
68 * if we have hardware PMU support. 66 * if we have hardware PMU support.
diff --git a/arch/powerpc/kernel/perf_event.c b/arch/powerpc/kernel/perf_event.c
index 10a140f82cb8..d614ab57ccca 100644
--- a/arch/powerpc/kernel/perf_event.c
+++ b/arch/powerpc/kernel/perf_event.c
@@ -1187,6 +1187,11 @@ static int power_pmu_event_init(struct perf_event *event)
1187 return err; 1187 return err;
1188} 1188}
1189 1189
1190static int power_pmu_event_idx(struct perf_event *event)
1191{
1192 return event->hw.idx;
1193}
1194
1190struct pmu power_pmu = { 1195struct pmu power_pmu = {
1191 .pmu_enable = power_pmu_enable, 1196 .pmu_enable = power_pmu_enable,
1192 .pmu_disable = power_pmu_disable, 1197 .pmu_disable = power_pmu_disable,
@@ -1199,6 +1204,7 @@ struct pmu power_pmu = {
1199 .start_txn = power_pmu_start_txn, 1204 .start_txn = power_pmu_start_txn,
1200 .cancel_txn = power_pmu_cancel_txn, 1205 .cancel_txn = power_pmu_cancel_txn,
1201 .commit_txn = power_pmu_commit_txn, 1206 .commit_txn = power_pmu_commit_txn,
1207 .event_idx = power_pmu_event_idx,
1202}; 1208};
1203 1209
1204/* 1210/*
diff --git a/arch/s390/include/asm/perf_event.h b/arch/s390/include/asm/perf_event.h
index a75f168d2718..4eb444edbe49 100644
--- a/arch/s390/include/asm/perf_event.h
+++ b/arch/s390/include/asm/perf_event.h
@@ -6,4 +6,3 @@
6 6
7/* Empty, just to avoid compiling error */ 7/* Empty, just to avoid compiling error */
8 8
9#define PERF_EVENT_INDEX_OFFSET 0
diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h
index 096c975e099f..9b922c136254 100644
--- a/arch/x86/include/asm/perf_event.h
+++ b/arch/x86/include/asm/perf_event.h
@@ -188,8 +188,6 @@ extern u32 get_ibs_caps(void);
188#ifdef CONFIG_PERF_EVENTS 188#ifdef CONFIG_PERF_EVENTS
189extern void perf_events_lapic_init(void); 189extern void perf_events_lapic_init(void);
190 190
191#define PERF_EVENT_INDEX_OFFSET 0
192
193/* 191/*
194 * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups. 192 * Abuse bit 3 of the cpu eflags register to indicate proper PEBS IP fixups.
195 * This flag is otherwise unused and ABI specified to be 0, so nobody should 193 * This flag is otherwise unused and ABI specified to be 0, so nobody should
diff --git a/arch/x86/kernel/cpu/perf_event.c b/arch/x86/kernel/cpu/perf_event.c
index 5adce1040b11..f8bddb5b0600 100644
--- a/arch/x86/kernel/cpu/perf_event.c
+++ b/arch/x86/kernel/cpu/perf_event.c
@@ -24,6 +24,7 @@
24#include <linux/slab.h> 24#include <linux/slab.h>
25#include <linux/cpu.h> 25#include <linux/cpu.h>
26#include <linux/bitops.h> 26#include <linux/bitops.h>
27#include <linux/device.h>
27 28
28#include <asm/apic.h> 29#include <asm/apic.h>
29#include <asm/stacktrace.h> 30#include <asm/stacktrace.h>
@@ -31,6 +32,7 @@
31#include <asm/compat.h> 32#include <asm/compat.h>
32#include <asm/smp.h> 33#include <asm/smp.h>
33#include <asm/alternative.h> 34#include <asm/alternative.h>
35#include <asm/timer.h>
34 36
35#include "perf_event.h" 37#include "perf_event.h"
36 38
@@ -1210,6 +1212,8 @@ x86_pmu_notifier(struct notifier_block *self, unsigned long action, void *hcpu)
1210 break; 1212 break;
1211 1213
1212 case CPU_STARTING: 1214 case CPU_STARTING:
1215 if (x86_pmu.attr_rdpmc)
1216 set_in_cr4(X86_CR4_PCE);
1213 if (x86_pmu.cpu_starting) 1217 if (x86_pmu.cpu_starting)
1214 x86_pmu.cpu_starting(cpu); 1218 x86_pmu.cpu_starting(cpu);
1215 break; 1219 break;
@@ -1319,6 +1323,8 @@ static int __init init_hw_perf_events(void)
1319 } 1323 }
1320 } 1324 }
1321 1325
1326 x86_pmu.attr_rdpmc = 1; /* enable userspace RDPMC usage by default */
1327
1322 pr_info("... version: %d\n", x86_pmu.version); 1328 pr_info("... version: %d\n", x86_pmu.version);
1323 pr_info("... bit width: %d\n", x86_pmu.cntval_bits); 1329 pr_info("... bit width: %d\n", x86_pmu.cntval_bits);
1324 pr_info("... generic registers: %d\n", x86_pmu.num_counters); 1330 pr_info("... generic registers: %d\n", x86_pmu.num_counters);
@@ -1542,10 +1548,71 @@ static int x86_pmu_event_init(struct perf_event *event)
1542 return err; 1548 return err;
1543} 1549}
1544 1550
1551static int x86_pmu_event_idx(struct perf_event *event)
1552{
1553 int idx = event->hw.idx;
1554
1555 if (x86_pmu.num_counters_fixed && idx >= X86_PMC_IDX_FIXED) {
1556 idx -= X86_PMC_IDX_FIXED;
1557 idx |= 1 << 30;
1558 }
1559
1560 return idx + 1;
1561}
1562
1563static ssize_t get_attr_rdpmc(struct device *cdev,
1564 struct device_attribute *attr,
1565 char *buf)
1566{
1567 return snprintf(buf, 40, "%d\n", x86_pmu.attr_rdpmc);
1568}
1569
1570static void change_rdpmc(void *info)
1571{
1572 bool enable = !!(unsigned long)info;
1573
1574 if (enable)
1575 set_in_cr4(X86_CR4_PCE);
1576 else
1577 clear_in_cr4(X86_CR4_PCE);
1578}
1579
1580static ssize_t set_attr_rdpmc(struct device *cdev,
1581 struct device_attribute *attr,
1582 const char *buf, size_t count)
1583{
1584 unsigned long val = simple_strtoul(buf, NULL, 0);
1585
1586 if (!!val != !!x86_pmu.attr_rdpmc) {
1587 x86_pmu.attr_rdpmc = !!val;
1588 smp_call_function(change_rdpmc, (void *)val, 1);
1589 }
1590
1591 return count;
1592}
1593
1594static DEVICE_ATTR(rdpmc, S_IRUSR | S_IWUSR, get_attr_rdpmc, set_attr_rdpmc);
1595
1596static struct attribute *x86_pmu_attrs[] = {
1597 &dev_attr_rdpmc.attr,
1598 NULL,
1599};
1600
1601static struct attribute_group x86_pmu_attr_group = {
1602 .attrs = x86_pmu_attrs,
1603};
1604
1605static const struct attribute_group *x86_pmu_attr_groups[] = {
1606 &x86_pmu_attr_group,
1607 NULL,
1608};
1609
1545static struct pmu pmu = { 1610static struct pmu pmu = {
1546 .pmu_enable = x86_pmu_enable, 1611 .pmu_enable = x86_pmu_enable,
1547 .pmu_disable = x86_pmu_disable, 1612 .pmu_disable = x86_pmu_disable,
1548 1613
1614 .attr_groups = x86_pmu_attr_groups,
1615
1549 .event_init = x86_pmu_event_init, 1616 .event_init = x86_pmu_event_init,
1550 1617
1551 .add = x86_pmu_add, 1618 .add = x86_pmu_add,
@@ -1557,8 +1624,23 @@ static struct pmu pmu = {
1557 .start_txn = x86_pmu_start_txn, 1624 .start_txn = x86_pmu_start_txn,
1558 .cancel_txn = x86_pmu_cancel_txn, 1625 .cancel_txn = x86_pmu_cancel_txn,
1559 .commit_txn = x86_pmu_commit_txn, 1626 .commit_txn = x86_pmu_commit_txn,
1627
1628 .event_idx = x86_pmu_event_idx,
1560}; 1629};
1561 1630
1631void perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now)
1632{
1633 if (!boot_cpu_has(X86_FEATURE_CONSTANT_TSC))
1634 return;
1635
1636 if (!boot_cpu_has(X86_FEATURE_NONSTOP_TSC))
1637 return;
1638
1639 userpg->time_mult = this_cpu_read(cyc2ns);
1640 userpg->time_shift = CYC2NS_SCALE_FACTOR;
1641 userpg->time_offset = this_cpu_read(cyc2ns_offset) - now;
1642}
1643
1562/* 1644/*
1563 * callchain support 1645 * callchain support
1564 */ 1646 */
diff --git a/arch/x86/kernel/cpu/perf_event.h b/arch/x86/kernel/cpu/perf_event.h
index 8944062f46e2..513d617b93c4 100644
--- a/arch/x86/kernel/cpu/perf_event.h
+++ b/arch/x86/kernel/cpu/perf_event.h
@@ -307,6 +307,14 @@ struct x86_pmu {
307 struct x86_pmu_quirk *quirks; 307 struct x86_pmu_quirk *quirks;
308 int perfctr_second_write; 308 int perfctr_second_write;
309 309
310 /*
311 * sysfs attrs
312 */
313 int attr_rdpmc;
314
315 /*
316 * CPU Hotplug hooks
317 */
310 int (*cpu_prepare)(int cpu); 318 int (*cpu_prepare)(int cpu);
311 void (*cpu_starting)(int cpu); 319 void (*cpu_starting)(int cpu);
312 void (*cpu_dying)(int cpu); 320 void (*cpu_dying)(int cpu);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 08855613ceb3..0b91db2522cc 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -291,12 +291,14 @@ struct perf_event_mmap_page {
291 __s64 offset; /* add to hardware event value */ 291 __s64 offset; /* add to hardware event value */
292 __u64 time_enabled; /* time event active */ 292 __u64 time_enabled; /* time event active */
293 __u64 time_running; /* time event on cpu */ 293 __u64 time_running; /* time event on cpu */
294 __u32 time_mult, time_shift;
295 __u64 time_offset;
294 296
295 /* 297 /*
296 * Hole for extension of the self monitor capabilities 298 * Hole for extension of the self monitor capabilities
297 */ 299 */
298 300
299 __u64 __reserved[123]; /* align to 1k */ 301 __u64 __reserved[121]; /* align to 1k */
300 302
301 /* 303 /*
302 * Control data for the mmap() data buffer. 304 * Control data for the mmap() data buffer.
@@ -615,6 +617,7 @@ struct pmu {
615 struct list_head entry; 617 struct list_head entry;
616 618
617 struct device *dev; 619 struct device *dev;
620 const struct attribute_group **attr_groups;
618 char *name; 621 char *name;
619 int type; 622 int type;
620 623
@@ -680,6 +683,12 @@ struct pmu {
680 * for each successful ->add() during the transaction. 683 * for each successful ->add() during the transaction.
681 */ 684 */
682 void (*cancel_txn) (struct pmu *pmu); /* optional */ 685 void (*cancel_txn) (struct pmu *pmu); /* optional */
686
687 /*
688 * Will return the value for perf_event_mmap_page::index for this event,
689 * if no implementation is provided it will default to: event->hw.idx + 1.
690 */
691 int (*event_idx) (struct perf_event *event); /*optional */
683}; 692};
684 693
685/** 694/**
diff --git a/kernel/events/core.c b/kernel/events/core.c
index 32b48c889711..de859fb4038f 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -3208,10 +3208,6 @@ int perf_event_task_disable(void)
3208 return 0; 3208 return 0;
3209} 3209}
3210 3210
3211#ifndef PERF_EVENT_INDEX_OFFSET
3212# define PERF_EVENT_INDEX_OFFSET 0
3213#endif
3214
3215static int perf_event_index(struct perf_event *event) 3211static int perf_event_index(struct perf_event *event)
3216{ 3212{
3217 if (event->hw.state & PERF_HES_STOPPED) 3213 if (event->hw.state & PERF_HES_STOPPED)
@@ -3220,21 +3216,26 @@ static int perf_event_index(struct perf_event *event)
3220 if (event->state != PERF_EVENT_STATE_ACTIVE) 3216 if (event->state != PERF_EVENT_STATE_ACTIVE)
3221 return 0; 3217 return 0;
3222 3218
3223 return event->hw.idx + 1 - PERF_EVENT_INDEX_OFFSET; 3219 return event->pmu->event_idx(event);
3224} 3220}
3225 3221
3226static void calc_timer_values(struct perf_event *event, 3222static void calc_timer_values(struct perf_event *event,
3223 u64 *now,
3227 u64 *enabled, 3224 u64 *enabled,
3228 u64 *running) 3225 u64 *running)
3229{ 3226{
3230 u64 now, ctx_time; 3227 u64 ctx_time;
3231 3228
3232 now = perf_clock(); 3229 *now = perf_clock();
3233 ctx_time = event->shadow_ctx_time + now; 3230 ctx_time = event->shadow_ctx_time + *now;
3234 *enabled = ctx_time - event->tstamp_enabled; 3231 *enabled = ctx_time - event->tstamp_enabled;
3235 *running = ctx_time - event->tstamp_running; 3232 *running = ctx_time - event->tstamp_running;
3236} 3233}
3237 3234
3235void __weak perf_update_user_clock(struct perf_event_mmap_page *userpg, u64 now)
3236{
3237}
3238
3238/* 3239/*
3239 * Callers need to ensure there can be no nesting of this function, otherwise 3240 * Callers need to ensure there can be no nesting of this function, otherwise
3240 * the seqlock logic goes bad. We can not serialize this because the arch 3241 * the seqlock logic goes bad. We can not serialize this because the arch
@@ -3244,7 +3245,7 @@ void perf_event_update_userpage(struct perf_event *event)
3244{ 3245{
3245 struct perf_event_mmap_page *userpg; 3246 struct perf_event_mmap_page *userpg;
3246 struct ring_buffer *rb; 3247 struct ring_buffer *rb;
3247 u64 enabled, running; 3248 u64 enabled, running, now;
3248 3249
3249 rcu_read_lock(); 3250 rcu_read_lock();
3250 /* 3251 /*
@@ -3256,7 +3257,7 @@ void perf_event_update_userpage(struct perf_event *event)
3256 * because of locking issue as we can be called in 3257 * because of locking issue as we can be called in
3257 * NMI context 3258 * NMI context
3258 */ 3259 */
3259 calc_timer_values(event, &enabled, &running); 3260 calc_timer_values(event, &now, &enabled, &running);
3260 rb = rcu_dereference(event->rb); 3261 rb = rcu_dereference(event->rb);
3261 if (!rb) 3262 if (!rb)
3262 goto unlock; 3263 goto unlock;
@@ -3272,7 +3273,7 @@ void perf_event_update_userpage(struct perf_event *event)
3272 barrier(); 3273 barrier();
3273 userpg->index = perf_event_index(event); 3274 userpg->index = perf_event_index(event);
3274 userpg->offset = perf_event_count(event); 3275 userpg->offset = perf_event_count(event);
3275 if (event->state == PERF_EVENT_STATE_ACTIVE) 3276 if (userpg->index)
3276 userpg->offset -= local64_read(&event->hw.prev_count); 3277 userpg->offset -= local64_read(&event->hw.prev_count);
3277 3278
3278 userpg->time_enabled = enabled + 3279 userpg->time_enabled = enabled +
@@ -3281,6 +3282,8 @@ void perf_event_update_userpage(struct perf_event *event)
3281 userpg->time_running = running + 3282 userpg->time_running = running +
3282 atomic64_read(&event->child_total_time_running); 3283 atomic64_read(&event->child_total_time_running);
3283 3284
3285 perf_update_user_clock(userpg, now);
3286
3284 barrier(); 3287 barrier();
3285 ++userpg->lock; 3288 ++userpg->lock;
3286 preempt_enable(); 3289 preempt_enable();
@@ -3538,6 +3541,8 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
3538 event->mmap_user = get_current_user(); 3541 event->mmap_user = get_current_user();
3539 vma->vm_mm->pinned_vm += event->mmap_locked; 3542 vma->vm_mm->pinned_vm += event->mmap_locked;
3540 3543
3544 perf_event_update_userpage(event);
3545
3541unlock: 3546unlock:
3542 if (!ret) 3547 if (!ret)
3543 atomic_inc(&event->mmap_count); 3548 atomic_inc(&event->mmap_count);
@@ -3769,7 +3774,7 @@ static void perf_output_read_group(struct perf_output_handle *handle,
3769static void perf_output_read(struct perf_output_handle *handle, 3774static void perf_output_read(struct perf_output_handle *handle,
3770 struct perf_event *event) 3775 struct perf_event *event)
3771{ 3776{
3772 u64 enabled = 0, running = 0; 3777 u64 enabled = 0, running = 0, now;
3773 u64 read_format = event->attr.read_format; 3778 u64 read_format = event->attr.read_format;
3774 3779
3775 /* 3780 /*
@@ -3782,7 +3787,7 @@ static void perf_output_read(struct perf_output_handle *handle,
3782 * NMI context 3787 * NMI context
3783 */ 3788 */
3784 if (read_format & PERF_FORMAT_TOTAL_TIMES) 3789 if (read_format & PERF_FORMAT_TOTAL_TIMES)
3785 calc_timer_values(event, &enabled, &running); 3790 calc_timer_values(event, &now, &enabled, &running);
3786 3791
3787 if (event->attr.read_format & PERF_FORMAT_GROUP) 3792 if (event->attr.read_format & PERF_FORMAT_GROUP)
3788 perf_output_read_group(handle, event, enabled, running); 3793 perf_output_read_group(handle, event, enabled, running);
@@ -4994,6 +4999,11 @@ static int perf_swevent_init(struct perf_event *event)
4994 return 0; 4999 return 0;
4995} 5000}
4996 5001
5002static int perf_swevent_event_idx(struct perf_event *event)
5003{
5004 return 0;
5005}
5006
4997static struct pmu perf_swevent = { 5007static struct pmu perf_swevent = {
4998 .task_ctx_nr = perf_sw_context, 5008 .task_ctx_nr = perf_sw_context,
4999 5009
@@ -5003,6 +5013,8 @@ static struct pmu perf_swevent = {
5003 .start = perf_swevent_start, 5013 .start = perf_swevent_start,
5004 .stop = perf_swevent_stop, 5014 .stop = perf_swevent_stop,
5005 .read = perf_swevent_read, 5015 .read = perf_swevent_read,
5016
5017 .event_idx = perf_swevent_event_idx,
5006}; 5018};
5007 5019
5008#ifdef CONFIG_EVENT_TRACING 5020#ifdef CONFIG_EVENT_TRACING
@@ -5089,6 +5101,8 @@ static struct pmu perf_tracepoint = {
5089 .start = perf_swevent_start, 5101 .start = perf_swevent_start,
5090 .stop = perf_swevent_stop, 5102 .stop = perf_swevent_stop,
5091 .read = perf_swevent_read, 5103 .read = perf_swevent_read,
5104
5105 .event_idx = perf_swevent_event_idx,
5092}; 5106};
5093 5107
5094static inline void perf_tp_register(void) 5108static inline void perf_tp_register(void)
@@ -5308,6 +5322,8 @@ static struct pmu perf_cpu_clock = {
5308 .start = cpu_clock_event_start, 5322 .start = cpu_clock_event_start,
5309 .stop = cpu_clock_event_stop, 5323 .stop = cpu_clock_event_stop,
5310 .read = cpu_clock_event_read, 5324 .read = cpu_clock_event_read,
5325
5326 .event_idx = perf_swevent_event_idx,
5311}; 5327};
5312 5328
5313/* 5329/*
@@ -5380,6 +5396,8 @@ static struct pmu perf_task_clock = {
5380 .start = task_clock_event_start, 5396 .start = task_clock_event_start,
5381 .stop = task_clock_event_stop, 5397 .stop = task_clock_event_stop,
5382 .read = task_clock_event_read, 5398 .read = task_clock_event_read,
5399
5400 .event_idx = perf_swevent_event_idx,
5383}; 5401};
5384 5402
5385static void perf_pmu_nop_void(struct pmu *pmu) 5403static void perf_pmu_nop_void(struct pmu *pmu)
@@ -5407,6 +5425,11 @@ static void perf_pmu_cancel_txn(struct pmu *pmu)
5407 perf_pmu_enable(pmu); 5425 perf_pmu_enable(pmu);
5408} 5426}
5409 5427
5428static int perf_event_idx_default(struct perf_event *event)
5429{
5430 return event->hw.idx + 1;
5431}
5432
5410/* 5433/*
5411 * Ensures all contexts with the same task_ctx_nr have the same 5434 * Ensures all contexts with the same task_ctx_nr have the same
5412 * pmu_cpu_context too. 5435 * pmu_cpu_context too.
@@ -5493,6 +5516,7 @@ static int pmu_dev_alloc(struct pmu *pmu)
5493 if (!pmu->dev) 5516 if (!pmu->dev)
5494 goto out; 5517 goto out;
5495 5518
5519 pmu->dev->groups = pmu->attr_groups;
5496 device_initialize(pmu->dev); 5520 device_initialize(pmu->dev);
5497 ret = dev_set_name(pmu->dev, "%s", pmu->name); 5521 ret = dev_set_name(pmu->dev, "%s", pmu->name);
5498 if (ret) 5522 if (ret)
@@ -5596,6 +5620,9 @@ got_cpu_context:
5596 pmu->pmu_disable = perf_pmu_nop_void; 5620 pmu->pmu_disable = perf_pmu_nop_void;
5597 } 5621 }
5598 5622
5623 if (!pmu->event_idx)
5624 pmu->event_idx = perf_event_idx_default;
5625
5599 list_add_rcu(&pmu->entry, &pmus); 5626 list_add_rcu(&pmu->entry, &pmus);
5600 ret = 0; 5627 ret = 0;
5601unlock: 5628unlock:
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index b7971d6f38bf..b0309f76d777 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -613,6 +613,11 @@ static void hw_breakpoint_stop(struct perf_event *bp, int flags)
613 bp->hw.state = PERF_HES_STOPPED; 613 bp->hw.state = PERF_HES_STOPPED;
614} 614}
615 615
616static int hw_breakpoint_event_idx(struct perf_event *bp)
617{
618 return 0;
619}
620
616static struct pmu perf_breakpoint = { 621static struct pmu perf_breakpoint = {
617 .task_ctx_nr = perf_sw_context, /* could eventually get its own */ 622 .task_ctx_nr = perf_sw_context, /* could eventually get its own */
618 623
@@ -622,6 +627,8 @@ static struct pmu perf_breakpoint = {
622 .start = hw_breakpoint_start, 627 .start = hw_breakpoint_start,
623 .stop = hw_breakpoint_stop, 628 .stop = hw_breakpoint_stop,
624 .read = hw_breakpoint_pmu_read, 629 .read = hw_breakpoint_pmu_read,
630
631 .event_idx = hw_breakpoint_event_idx,
625}; 632};
626 633
627int __init init_hw_breakpoint(void) 634int __init init_hw_breakpoint(void)
diff --git a/tools/perf/builtin-test.c b/tools/perf/builtin-test.c
index 3ce709e97462..70c4eb2bdf72 100644
--- a/tools/perf/builtin-test.c
+++ b/tools/perf/builtin-test.c
@@ -15,6 +15,8 @@
15#include "util/thread_map.h" 15#include "util/thread_map.h"
16#include "../../include/linux/hw_breakpoint.h" 16#include "../../include/linux/hw_breakpoint.h"
17 17
18#include <sys/mman.h>
19
18static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym) 20static int vmlinux_matches_kallsyms_filter(struct map *map __used, struct symbol *sym)
19{ 21{
20 bool *visited = symbol__priv(sym); 22 bool *visited = symbol__priv(sym);
@@ -1296,6 +1298,173 @@ out:
1296 return (err < 0 || errs > 0) ? -1 : 0; 1298 return (err < 0 || errs > 0) ? -1 : 0;
1297} 1299}
1298 1300
1301
1302#if defined(__x86_64__) || defined(__i386__)
1303
1304#define barrier() asm volatile("" ::: "memory")
1305
1306static u64 rdpmc(unsigned int counter)
1307{
1308 unsigned int low, high;
1309
1310 asm volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (counter));
1311
1312 return low | ((u64)high) << 32;
1313}
1314
1315static u64 rdtsc(void)
1316{
1317 unsigned int low, high;
1318
1319 asm volatile("rdtsc" : "=a" (low), "=d" (high));
1320
1321 return low | ((u64)high) << 32;
1322}
1323
1324static u64 mmap_read_self(void *addr)
1325{
1326 struct perf_event_mmap_page *pc = addr;
1327 u32 seq, idx, time_mult = 0, time_shift = 0;
1328 u64 count, cyc = 0, time_offset = 0, enabled, running, delta;
1329
1330 do {
1331 seq = pc->lock;
1332 barrier();
1333
1334 enabled = pc->time_enabled;
1335 running = pc->time_running;
1336
1337 if (enabled != running) {
1338 cyc = rdtsc();
1339 time_mult = pc->time_mult;
1340 time_shift = pc->time_shift;
1341 time_offset = pc->time_offset;
1342 }
1343
1344 idx = pc->index;
1345 count = pc->offset;
1346 if (idx)
1347 count += rdpmc(idx - 1);
1348
1349 barrier();
1350 } while (pc->lock != seq);
1351
1352 if (enabled != running) {
1353 u64 quot, rem;
1354
1355 quot = (cyc >> time_shift);
1356 rem = cyc & ((1 << time_shift) - 1);
1357 delta = time_offset + quot * time_mult +
1358 ((rem * time_mult) >> time_shift);
1359
1360 enabled += delta;
1361 if (idx)
1362 running += delta;
1363
1364 quot = count / running;
1365 rem = count % running;
1366 count = quot * enabled + (rem * enabled) / running;
1367 }
1368
1369 return count;
1370}
1371
1372/*
1373 * If the RDPMC instruction faults then signal this back to the test parent task:
1374 */
1375static void segfault_handler(int sig __used, siginfo_t *info __used, void *uc __used)
1376{
1377 exit(-1);
1378}
1379
1380static int __test__rdpmc(void)
1381{
1382 long page_size = sysconf(_SC_PAGE_SIZE);
1383 volatile int tmp = 0;
1384 u64 i, loops = 1000;
1385 int n;
1386 int fd;
1387 void *addr;
1388 struct perf_event_attr attr = {
1389 .type = PERF_TYPE_HARDWARE,
1390 .config = PERF_COUNT_HW_INSTRUCTIONS,
1391 .exclude_kernel = 1,
1392 };
1393 u64 delta_sum = 0;
1394 struct sigaction sa;
1395
1396 sigfillset(&sa.sa_mask);
1397 sa.sa_sigaction = segfault_handler;
1398 sigaction(SIGSEGV, &sa, NULL);
1399
1400 fprintf(stderr, "\n\n");
1401
1402 fd = sys_perf_event_open(&attr, 0, -1, -1, 0);
1403 if (fd < 0) {
1404 die("Error: sys_perf_event_open() syscall returned "
1405 "with %d (%s)\n", fd, strerror(errno));
1406 }
1407
1408 addr = mmap(NULL, page_size, PROT_READ, MAP_SHARED, fd, 0);
1409 if (addr == (void *)(-1)) {
1410 die("Error: mmap() syscall returned "
1411 "with (%s)\n", strerror(errno));
1412 }
1413
1414 for (n = 0; n < 6; n++) {
1415 u64 stamp, now, delta;
1416
1417 stamp = mmap_read_self(addr);
1418
1419 for (i = 0; i < loops; i++)
1420 tmp++;
1421
1422 now = mmap_read_self(addr);
1423 loops *= 10;
1424
1425 delta = now - stamp;
1426 fprintf(stderr, "%14d: %14Lu\n", n, (long long)delta);
1427
1428 delta_sum += delta;
1429 }
1430
1431 munmap(addr, page_size);
1432 close(fd);
1433
1434 fprintf(stderr, " ");
1435
1436 if (!delta_sum)
1437 return -1;
1438
1439 return 0;
1440}
1441
1442static int test__rdpmc(void)
1443{
1444 int status = 0;
1445 int wret = 0;
1446 int ret;
1447 int pid;
1448
1449 pid = fork();
1450 if (pid < 0)
1451 return -1;
1452
1453 if (!pid) {
1454 ret = __test__rdpmc();
1455
1456 exit(ret);
1457 }
1458
1459 wret = waitpid(pid, &status, 0);
1460 if (wret < 0 || status)
1461 return -1;
1462
1463 return 0;
1464}
1465
1466#endif
1467
1299static struct test { 1468static struct test {
1300 const char *desc; 1469 const char *desc;
1301 int (*func)(void); 1470 int (*func)(void);
@@ -1320,6 +1489,12 @@ static struct test {
1320 .desc = "parse events tests", 1489 .desc = "parse events tests",
1321 .func = test__parse_events, 1490 .func = test__parse_events,
1322 }, 1491 },
1492#if defined(__x86_64__) || defined(__i386__)
1493 {
1494 .desc = "x86 rdpmc test",
1495 .func = test__rdpmc,
1496 },
1497#endif
1323 { 1498 {
1324 .desc = "Validate PERF_RECORD_* events & perf_sample fields", 1499 .desc = "Validate PERF_RECORD_* events & perf_sample fields",
1325 .func = test__PERF_RECORD, 1500 .func = test__PERF_RECORD,
@@ -1412,7 +1587,5 @@ int cmd_test(int argc, const char **argv, const char *prefix __used)
1412 if (symbol__init() < 0) 1587 if (symbol__init() < 0)
1413 return -1; 1588 return -1;
1414 1589
1415 setup_pager();
1416
1417 return __cmd_test(argc, argv); 1590 return __cmd_test(argc, argv);
1418} 1591}