aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/linux/perf_counter.h11
-rw-r--r--kernel/perf_counter.c18
2 files changed, 25 insertions, 4 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 89698d8aba5c..e7213e46cf9c 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -669,7 +669,16 @@ static inline int is_software_counter(struct perf_counter *counter)
669 (counter->attr.type != PERF_TYPE_HW_CACHE); 669 (counter->attr.type != PERF_TYPE_HW_CACHE);
670} 670}
671 671
672extern void perf_swcounter_event(u32, u64, int, struct pt_regs *, u64); 672extern atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX];
673
674extern void __perf_swcounter_event(u32, u64, int, struct pt_regs *, u64);
675
676static inline void
677perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr)
678{
679 if (atomic_read(&perf_swcounter_enabled[event]))
680 __perf_swcounter_event(event, nr, nmi, regs, addr);
681}
673 682
674extern void __perf_counter_mmap(struct vm_area_struct *vma); 683extern void __perf_counter_mmap(struct vm_area_struct *vma);
675 684
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 1a933a221ea4..7515c7695428 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -3317,8 +3317,8 @@ out:
3317 put_cpu_var(perf_cpu_context); 3317 put_cpu_var(perf_cpu_context);
3318} 3318}
3319 3319
3320void 3320void __perf_swcounter_event(u32 event, u64 nr, int nmi,
3321perf_swcounter_event(u32 event, u64 nr, int nmi, struct pt_regs *regs, u64 addr) 3321 struct pt_regs *regs, u64 addr)
3322{ 3322{
3323 struct perf_sample_data data = { 3323 struct perf_sample_data data = {
3324 .regs = regs, 3324 .regs = regs,
@@ -3509,9 +3509,19 @@ static const struct pmu *tp_perf_counter_init(struct perf_counter *counter)
3509} 3509}
3510#endif 3510#endif
3511 3511
3512atomic_t perf_swcounter_enabled[PERF_COUNT_SW_MAX];
3513
3514static void sw_perf_counter_destroy(struct perf_counter *counter)
3515{
3516 u64 event = counter->attr.config;
3517
3518 atomic_dec(&perf_swcounter_enabled[event]);
3519}
3520
3512static const struct pmu *sw_perf_counter_init(struct perf_counter *counter) 3521static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
3513{ 3522{
3514 const struct pmu *pmu = NULL; 3523 const struct pmu *pmu = NULL;
3524 u64 event = counter->attr.config;
3515 3525
3516 /* 3526 /*
3517 * Software counters (currently) can't in general distinguish 3527 * Software counters (currently) can't in general distinguish
@@ -3520,7 +3530,7 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
3520 * to be kernel events, and page faults are never hypervisor 3530 * to be kernel events, and page faults are never hypervisor
3521 * events. 3531 * events.
3522 */ 3532 */
3523 switch (counter->attr.config) { 3533 switch (event) {
3524 case PERF_COUNT_SW_CPU_CLOCK: 3534 case PERF_COUNT_SW_CPU_CLOCK:
3525 pmu = &perf_ops_cpu_clock; 3535 pmu = &perf_ops_cpu_clock;
3526 3536
@@ -3541,6 +3551,8 @@ static const struct pmu *sw_perf_counter_init(struct perf_counter *counter)
3541 case PERF_COUNT_SW_PAGE_FAULTS_MAJ: 3551 case PERF_COUNT_SW_PAGE_FAULTS_MAJ:
3542 case PERF_COUNT_SW_CONTEXT_SWITCHES: 3552 case PERF_COUNT_SW_CONTEXT_SWITCHES:
3543 case PERF_COUNT_SW_CPU_MIGRATIONS: 3553 case PERF_COUNT_SW_CPU_MIGRATIONS:
3554 atomic_inc(&perf_swcounter_enabled[event]);
3555 counter->destroy = sw_perf_counter_destroy;
3544 pmu = &perf_ops_generic; 3556 pmu = &perf_ops_generic;
3545 break; 3557 break;
3546 } 3558 }