diff options
-rw-r--r-- | include/linux/perf_counter.h | 2 | ||||
-rw-r--r-- | kernel/perf_counter.c | 27 | ||||
-rw-r--r-- | kernel/sysctl.c | 6 |
3 files changed, 23 insertions, 12 deletions
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h index 386be915baa1..95c797c480e8 100644 --- a/include/linux/perf_counter.h +++ b/include/linux/perf_counter.h | |||
@@ -650,7 +650,7 @@ extern struct perf_callchain_entry *perf_callchain(struct pt_regs *regs); | |||
650 | 650 | ||
651 | extern int sysctl_perf_counter_paranoid; | 651 | extern int sysctl_perf_counter_paranoid; |
652 | extern int sysctl_perf_counter_mlock; | 652 | extern int sysctl_perf_counter_mlock; |
653 | extern int sysctl_perf_counter_limit; | 653 | extern int sysctl_perf_counter_sample_rate; |
654 | 654 | ||
655 | extern void perf_counter_init(void); | 655 | extern void perf_counter_init(void); |
656 | 656 | ||
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c index 63f1987c1c1c..3b2829de5590 100644 --- a/kernel/perf_counter.c +++ b/kernel/perf_counter.c | |||
@@ -44,11 +44,12 @@ static atomic_t nr_mmap_counters __read_mostly; | |||
44 | static atomic_t nr_comm_counters __read_mostly; | 44 | static atomic_t nr_comm_counters __read_mostly; |
45 | 45 | ||
46 | /* | 46 | /* |
47 | * 0 - not paranoid | 47 | * perf counter paranoia level: |
48 | * 1 - disallow cpu counters to unpriv | 48 | * 0 - not paranoid |
49 | * 2 - disallow kernel profiling to unpriv | 49 | * 1 - disallow cpu counters to unpriv |
50 | * 2 - disallow kernel profiling to unpriv | ||
50 | */ | 51 | */ |
51 | int sysctl_perf_counter_paranoid __read_mostly; /* do we need to be privileged */ | 52 | int sysctl_perf_counter_paranoid __read_mostly; |
52 | 53 | ||
53 | static inline bool perf_paranoid_cpu(void) | 54 | static inline bool perf_paranoid_cpu(void) |
54 | { | 55 | { |
@@ -61,7 +62,11 @@ static inline bool perf_paranoid_kernel(void) | |||
61 | } | 62 | } |
62 | 63 | ||
63 | int sysctl_perf_counter_mlock __read_mostly = 512; /* 'free' kb per user */ | 64 | int sysctl_perf_counter_mlock __read_mostly = 512; /* 'free' kb per user */ |
64 | int sysctl_perf_counter_limit __read_mostly = 100000; /* max NMIs per second */ | 65 | |
66 | /* | ||
67 | * max perf counter sample rate | ||
68 | */ | ||
69 | int sysctl_perf_counter_sample_rate __read_mostly = 100000; | ||
65 | 70 | ||
66 | static atomic64_t perf_counter_id; | 71 | static atomic64_t perf_counter_id; |
67 | 72 | ||
@@ -1244,7 +1249,7 @@ static void perf_ctx_adjust_freq(struct perf_counter_context *ctx) | |||
1244 | if (interrupts == MAX_INTERRUPTS) { | 1249 | if (interrupts == MAX_INTERRUPTS) { |
1245 | perf_log_throttle(counter, 1); | 1250 | perf_log_throttle(counter, 1); |
1246 | counter->pmu->unthrottle(counter); | 1251 | counter->pmu->unthrottle(counter); |
1247 | interrupts = 2*sysctl_perf_counter_limit/HZ; | 1252 | interrupts = 2*sysctl_perf_counter_sample_rate/HZ; |
1248 | } | 1253 | } |
1249 | 1254 | ||
1250 | if (!counter->attr.freq || !counter->attr.sample_freq) | 1255 | if (!counter->attr.freq || !counter->attr.sample_freq) |
@@ -1682,7 +1687,7 @@ static int perf_counter_period(struct perf_counter *counter, u64 __user *arg) | |||
1682 | 1687 | ||
1683 | spin_lock_irq(&ctx->lock); | 1688 | spin_lock_irq(&ctx->lock); |
1684 | if (counter->attr.freq) { | 1689 | if (counter->attr.freq) { |
1685 | if (value > sysctl_perf_counter_limit) { | 1690 | if (value > sysctl_perf_counter_sample_rate) { |
1686 | ret = -EINVAL; | 1691 | ret = -EINVAL; |
1687 | goto unlock; | 1692 | goto unlock; |
1688 | } | 1693 | } |
@@ -2979,7 +2984,8 @@ int perf_counter_overflow(struct perf_counter *counter, int nmi, | |||
2979 | } else { | 2984 | } else { |
2980 | if (hwc->interrupts != MAX_INTERRUPTS) { | 2985 | if (hwc->interrupts != MAX_INTERRUPTS) { |
2981 | hwc->interrupts++; | 2986 | hwc->interrupts++; |
2982 | if (HZ * hwc->interrupts > (u64)sysctl_perf_counter_limit) { | 2987 | if (HZ * hwc->interrupts > |
2988 | (u64)sysctl_perf_counter_sample_rate) { | ||
2983 | hwc->interrupts = MAX_INTERRUPTS; | 2989 | hwc->interrupts = MAX_INTERRUPTS; |
2984 | perf_log_throttle(counter, 0); | 2990 | perf_log_throttle(counter, 0); |
2985 | ret = 1; | 2991 | ret = 1; |
@@ -3639,6 +3645,11 @@ SYSCALL_DEFINE5(perf_counter_open, | |||
3639 | return -EACCES; | 3645 | return -EACCES; |
3640 | } | 3646 | } |
3641 | 3647 | ||
3648 | if (attr.freq) { | ||
3649 | if (attr.sample_freq > sysctl_perf_counter_sample_rate) | ||
3650 | return -EINVAL; | ||
3651 | } | ||
3652 | |||
3642 | /* | 3653 | /* |
3643 | * Get the target context (task or percpu): | 3654 | * Get the target context (task or percpu): |
3644 | */ | 3655 | */ |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 344a65981dee..9fd4e436b696 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -932,9 +932,9 @@ static struct ctl_table kern_table[] = { | |||
932 | }, | 932 | }, |
933 | { | 933 | { |
934 | .ctl_name = CTL_UNNUMBERED, | 934 | .ctl_name = CTL_UNNUMBERED, |
935 | .procname = "perf_counter_int_limit", | 935 | .procname = "perf_counter_max_sample_rate", |
936 | .data = &sysctl_perf_counter_limit, | 936 | .data = &sysctl_perf_counter_sample_rate, |
937 | .maxlen = sizeof(sysctl_perf_counter_limit), | 937 | .maxlen = sizeof(sysctl_perf_counter_sample_rate), |
938 | .mode = 0644, | 938 | .mode = 0644, |
939 | .proc_handler = &proc_dointvec, | 939 | .proc_handler = &proc_dointvec, |
940 | }, | 940 | }, |