diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 19:15:23 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2013-07-02 19:15:23 -0400 |
commit | f0bb4c0ab064a8aeeffbda1cee380151a594eaab (patch) | |
tree | 14d55a89c5db455aa10ff9a96ca14c474a9c4d55 /kernel | |
parent | a4883ef6af5e513a1e8c2ab9aab721604aa3a4f5 (diff) | |
parent | 983433b5812c5cf33a9008fa38c6f9b407fedb76 (diff) |
Merge branch 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf updates from Ingo Molnar:
"Kernel improvements:
- watchdog driver improvements by Li Zefan
- Power7 CPI stack events related improvements by Sukadev Bhattiprolu
- event multiplexing via hrtimers and other improvements by Stephane
Eranian
- kernel stack use optimization by Andrew Hunter
- AMD IOMMU uncore PMU support by Suravee Suthikulpanit
- NMI handling rate-limits by Dave Hansen
- various hw_breakpoint fixes by Oleg Nesterov
- hw_breakpoint overflow period sampling and related signal handling
fixes by Jiri Olsa
- Intel Haswell PMU support by Andi Kleen
Tooling improvements:
- Reset SIGTERM handler in workload child process, fix from David
Ahern.
- Makefile reorganization, prep work for Kconfig patches, from Jiri
Olsa.
- Add automated make test suite, from Jiri Olsa.
- Add --percent-limit option to 'top' and 'report', from Namhyung
Kim.
- Sorting improvements, from Namhyung Kim.
- Expand definition of sysfs format attribute, from Michael Ellerman.
Tooling fixes:
- 'perf tests' fixes from Jiri Olsa.
- Make Power7 CPI stack events available in sysfs, from Sukadev
Bhattiprolu.
- Handle death by SIGTERM in 'perf record', fix from David Ahern.
- Fix printing of perf_event_paranoid message, from David Ahern.
- Handle realloc failures in 'perf kvm', from David Ahern.
- Fix divide by 0 in variance, from David Ahern.
- Save parent pid in thread struct, from David Ahern.
- Handle JITed code in shared memory, from Andi Kleen.
- Fixes for 'perf diff', from Jiri Olsa.
- Remove some unused struct members, from Jiri Olsa.
- Add missing liblk.a dependency for python/perf.so, fix from Jiri
Olsa.
- Respect CROSS_COMPILE in liblk.a, from Rabin Vincent.
- No need to do locking when adding hists in perf report, only 'top'
needs that, from Namhyung Kim.
- Fix alignment of symbol column in in the hists browser (top,
report) when -v is given, from NAmhyung Kim.
- Fix 'perf top' -E option behavior, from Namhyung Kim.
- Fix bug in isupper() and islower(), from Sukadev Bhattiprolu.
- Fix compile errors in bp_signal 'perf test', from Sukadev
Bhattiprolu.
... and more things"
* 'perf-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (102 commits)
perf/x86: Disable PEBS-LL in intel_pmu_pebs_disable()
perf/x86: Fix shared register mutual exclusion enforcement
perf/x86/intel: Support full width counting
x86: Add NMI duration tracepoints
perf: Drop sample rate when sampling is too slow
x86: Warn when NMI handlers take large amounts of time
hw_breakpoint: Introduce "struct bp_cpuinfo"
hw_breakpoint: Simplify *register_wide_hw_breakpoint()
hw_breakpoint: Introduce cpumask_of_bp()
hw_breakpoint: Simplify the "weight" usage in toggle_bp_slot() paths
hw_breakpoint: Simplify list/idx mess in toggle_bp_slot() paths
perf/x86/intel: Add mem-loads/stores support for Haswell
perf/x86/intel: Support Haswell/v4 LBR format
perf/x86/intel: Move NMI clearing to end of PMI handler
perf/x86/intel: Add Haswell PEBS support
perf/x86/intel: Add simple Haswell PMU support
perf/x86/intel: Add Haswell PEBS record support
perf/x86/intel: Fix sparse warning
perf/x86/amd: AMD IOMMU Performance Counter PERF uncore PMU implementation
perf/x86/amd: Add IOMMU Performance Counter resource management
...
Diffstat (limited to 'kernel')
-rw-r--r-- | kernel/events/core.c | 278 | ||||
-rw-r--r-- | kernel/events/hw_breakpoint.c | 191 | ||||
-rw-r--r-- | kernel/sysctl.c | 12 |
3 files changed, 350 insertions, 131 deletions
diff --git a/kernel/events/core.c b/kernel/events/core.c index b391907d5352..1db3af933704 100644 --- a/kernel/events/core.c +++ b/kernel/events/core.c | |||
@@ -165,10 +165,28 @@ int sysctl_perf_event_mlock __read_mostly = 512 + (PAGE_SIZE / 1024); /* 'free' | |||
165 | /* | 165 | /* |
166 | * max perf event sample rate | 166 | * max perf event sample rate |
167 | */ | 167 | */ |
168 | #define DEFAULT_MAX_SAMPLE_RATE 100000 | 168 | #define DEFAULT_MAX_SAMPLE_RATE 100000 |
169 | int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE; | 169 | #define DEFAULT_SAMPLE_PERIOD_NS (NSEC_PER_SEC / DEFAULT_MAX_SAMPLE_RATE) |
170 | static int max_samples_per_tick __read_mostly = | 170 | #define DEFAULT_CPU_TIME_MAX_PERCENT 25 |
171 | DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ); | 171 | |
172 | int sysctl_perf_event_sample_rate __read_mostly = DEFAULT_MAX_SAMPLE_RATE; | ||
173 | |||
174 | static int max_samples_per_tick __read_mostly = DIV_ROUND_UP(DEFAULT_MAX_SAMPLE_RATE, HZ); | ||
175 | static int perf_sample_period_ns __read_mostly = DEFAULT_SAMPLE_PERIOD_NS; | ||
176 | |||
177 | static atomic_t perf_sample_allowed_ns __read_mostly = | ||
178 | ATOMIC_INIT( DEFAULT_SAMPLE_PERIOD_NS * DEFAULT_CPU_TIME_MAX_PERCENT / 100); | ||
179 | |||
180 | void update_perf_cpu_limits(void) | ||
181 | { | ||
182 | u64 tmp = perf_sample_period_ns; | ||
183 | |||
184 | tmp *= sysctl_perf_cpu_time_max_percent; | ||
185 | tmp = do_div(tmp, 100); | ||
186 | atomic_set(&perf_sample_allowed_ns, tmp); | ||
187 | } | ||
188 | |||
189 | static int perf_rotate_context(struct perf_cpu_context *cpuctx); | ||
172 | 190 | ||
173 | int perf_proc_update_handler(struct ctl_table *table, int write, | 191 | int perf_proc_update_handler(struct ctl_table *table, int write, |
174 | void __user *buffer, size_t *lenp, | 192 | void __user *buffer, size_t *lenp, |
@@ -180,10 +198,78 @@ int perf_proc_update_handler(struct ctl_table *table, int write, | |||
180 | return ret; | 198 | return ret; |
181 | 199 | ||
182 | max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ); | 200 | max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ); |
201 | perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; | ||
202 | update_perf_cpu_limits(); | ||
183 | 203 | ||
184 | return 0; | 204 | return 0; |
185 | } | 205 | } |
186 | 206 | ||
207 | int sysctl_perf_cpu_time_max_percent __read_mostly = DEFAULT_CPU_TIME_MAX_PERCENT; | ||
208 | |||
209 | int perf_cpu_time_max_percent_handler(struct ctl_table *table, int write, | ||
210 | void __user *buffer, size_t *lenp, | ||
211 | loff_t *ppos) | ||
212 | { | ||
213 | int ret = proc_dointvec(table, write, buffer, lenp, ppos); | ||
214 | |||
215 | if (ret || !write) | ||
216 | return ret; | ||
217 | |||
218 | update_perf_cpu_limits(); | ||
219 | |||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | /* | ||
224 | * perf samples are done in some very critical code paths (NMIs). | ||
225 | * If they take too much CPU time, the system can lock up and not | ||
226 | * get any real work done. This will drop the sample rate when | ||
227 | * we detect that events are taking too long. | ||
228 | */ | ||
229 | #define NR_ACCUMULATED_SAMPLES 128 | ||
230 | DEFINE_PER_CPU(u64, running_sample_length); | ||
231 | |||
232 | void perf_sample_event_took(u64 sample_len_ns) | ||
233 | { | ||
234 | u64 avg_local_sample_len; | ||
235 | u64 local_samples_len = __get_cpu_var(running_sample_length); | ||
236 | |||
237 | if (atomic_read(&perf_sample_allowed_ns) == 0) | ||
238 | return; | ||
239 | |||
240 | /* decay the counter by 1 average sample */ | ||
241 | local_samples_len = __get_cpu_var(running_sample_length); | ||
242 | local_samples_len -= local_samples_len/NR_ACCUMULATED_SAMPLES; | ||
243 | local_samples_len += sample_len_ns; | ||
244 | __get_cpu_var(running_sample_length) = local_samples_len; | ||
245 | |||
246 | /* | ||
247 | * note: this will be biased artifically low until we have | ||
248 | * seen NR_ACCUMULATED_SAMPLES. Doing it this way keeps us | ||
249 | * from having to maintain a count. | ||
250 | */ | ||
251 | avg_local_sample_len = local_samples_len/NR_ACCUMULATED_SAMPLES; | ||
252 | |||
253 | if (avg_local_sample_len <= atomic_read(&perf_sample_allowed_ns)) | ||
254 | return; | ||
255 | |||
256 | if (max_samples_per_tick <= 1) | ||
257 | return; | ||
258 | |||
259 | max_samples_per_tick = DIV_ROUND_UP(max_samples_per_tick, 2); | ||
260 | sysctl_perf_event_sample_rate = max_samples_per_tick * HZ; | ||
261 | perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate; | ||
262 | |||
263 | printk_ratelimited(KERN_WARNING | ||
264 | "perf samples too long (%lld > %d), lowering " | ||
265 | "kernel.perf_event_max_sample_rate to %d\n", | ||
266 | avg_local_sample_len, | ||
267 | atomic_read(&perf_sample_allowed_ns), | ||
268 | sysctl_perf_event_sample_rate); | ||
269 | |||
270 | update_perf_cpu_limits(); | ||
271 | } | ||
272 | |||
187 | static atomic64_t perf_event_id; | 273 | static atomic64_t perf_event_id; |
188 | 274 | ||
189 | static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx, | 275 | static void cpu_ctx_sched_out(struct perf_cpu_context *cpuctx, |
@@ -655,6 +741,106 @@ perf_cgroup_mark_enabled(struct perf_event *event, | |||
655 | } | 741 | } |
656 | #endif | 742 | #endif |
657 | 743 | ||
744 | /* | ||
745 | * set default to be dependent on timer tick just | ||
746 | * like original code | ||
747 | */ | ||
748 | #define PERF_CPU_HRTIMER (1000 / HZ) | ||
749 | /* | ||
750 | * function must be called with interrupts disbled | ||
751 | */ | ||
752 | static enum hrtimer_restart perf_cpu_hrtimer_handler(struct hrtimer *hr) | ||
753 | { | ||
754 | struct perf_cpu_context *cpuctx; | ||
755 | enum hrtimer_restart ret = HRTIMER_NORESTART; | ||
756 | int rotations = 0; | ||
757 | |||
758 | WARN_ON(!irqs_disabled()); | ||
759 | |||
760 | cpuctx = container_of(hr, struct perf_cpu_context, hrtimer); | ||
761 | |||
762 | rotations = perf_rotate_context(cpuctx); | ||
763 | |||
764 | /* | ||
765 | * arm timer if needed | ||
766 | */ | ||
767 | if (rotations) { | ||
768 | hrtimer_forward_now(hr, cpuctx->hrtimer_interval); | ||
769 | ret = HRTIMER_RESTART; | ||
770 | } | ||
771 | |||
772 | return ret; | ||
773 | } | ||
774 | |||
775 | /* CPU is going down */ | ||
776 | void perf_cpu_hrtimer_cancel(int cpu) | ||
777 | { | ||
778 | struct perf_cpu_context *cpuctx; | ||
779 | struct pmu *pmu; | ||
780 | unsigned long flags; | ||
781 | |||
782 | if (WARN_ON(cpu != smp_processor_id())) | ||
783 | return; | ||
784 | |||
785 | local_irq_save(flags); | ||
786 | |||
787 | rcu_read_lock(); | ||
788 | |||
789 | list_for_each_entry_rcu(pmu, &pmus, entry) { | ||
790 | cpuctx = this_cpu_ptr(pmu->pmu_cpu_context); | ||
791 | |||
792 | if (pmu->task_ctx_nr == perf_sw_context) | ||
793 | continue; | ||
794 | |||
795 | hrtimer_cancel(&cpuctx->hrtimer); | ||
796 | } | ||
797 | |||
798 | rcu_read_unlock(); | ||
799 | |||
800 | local_irq_restore(flags); | ||
801 | } | ||
802 | |||
803 | static void __perf_cpu_hrtimer_init(struct perf_cpu_context *cpuctx, int cpu) | ||
804 | { | ||
805 | struct hrtimer *hr = &cpuctx->hrtimer; | ||
806 | struct pmu *pmu = cpuctx->ctx.pmu; | ||
807 | int timer; | ||
808 | |||
809 | /* no multiplexing needed for SW PMU */ | ||
810 | if (pmu->task_ctx_nr == perf_sw_context) | ||
811 | return; | ||
812 | |||
813 | /* | ||
814 | * check default is sane, if not set then force to | ||
815 | * default interval (1/tick) | ||
816 | */ | ||
817 | timer = pmu->hrtimer_interval_ms; | ||
818 | if (timer < 1) | ||
819 | timer = pmu->hrtimer_interval_ms = PERF_CPU_HRTIMER; | ||
820 | |||
821 | cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); | ||
822 | |||
823 | hrtimer_init(hr, CLOCK_MONOTONIC, HRTIMER_MODE_REL_PINNED); | ||
824 | hr->function = perf_cpu_hrtimer_handler; | ||
825 | } | ||
826 | |||
827 | static void perf_cpu_hrtimer_restart(struct perf_cpu_context *cpuctx) | ||
828 | { | ||
829 | struct hrtimer *hr = &cpuctx->hrtimer; | ||
830 | struct pmu *pmu = cpuctx->ctx.pmu; | ||
831 | |||
832 | /* not for SW PMU */ | ||
833 | if (pmu->task_ctx_nr == perf_sw_context) | ||
834 | return; | ||
835 | |||
836 | if (hrtimer_active(hr)) | ||
837 | return; | ||
838 | |||
839 | if (!hrtimer_callback_running(hr)) | ||
840 | __hrtimer_start_range_ns(hr, cpuctx->hrtimer_interval, | ||
841 | 0, HRTIMER_MODE_REL_PINNED, 0); | ||
842 | } | ||
843 | |||
658 | void perf_pmu_disable(struct pmu *pmu) | 844 | void perf_pmu_disable(struct pmu *pmu) |
659 | { | 845 | { |
660 | int *count = this_cpu_ptr(pmu->pmu_disable_count); | 846 | int *count = this_cpu_ptr(pmu->pmu_disable_count); |
@@ -1503,6 +1689,7 @@ group_sched_in(struct perf_event *group_event, | |||
1503 | 1689 | ||
1504 | if (event_sched_in(group_event, cpuctx, ctx)) { | 1690 | if (event_sched_in(group_event, cpuctx, ctx)) { |
1505 | pmu->cancel_txn(pmu); | 1691 | pmu->cancel_txn(pmu); |
1692 | perf_cpu_hrtimer_restart(cpuctx); | ||
1506 | return -EAGAIN; | 1693 | return -EAGAIN; |
1507 | } | 1694 | } |
1508 | 1695 | ||
@@ -1549,6 +1736,8 @@ group_error: | |||
1549 | 1736 | ||
1550 | pmu->cancel_txn(pmu); | 1737 | pmu->cancel_txn(pmu); |
1551 | 1738 | ||
1739 | perf_cpu_hrtimer_restart(cpuctx); | ||
1740 | |||
1552 | return -EAGAIN; | 1741 | return -EAGAIN; |
1553 | } | 1742 | } |
1554 | 1743 | ||
@@ -1804,8 +1993,10 @@ static int __perf_event_enable(void *info) | |||
1804 | * If this event can't go on and it's part of a | 1993 | * If this event can't go on and it's part of a |
1805 | * group, then the whole group has to come off. | 1994 | * group, then the whole group has to come off. |
1806 | */ | 1995 | */ |
1807 | if (leader != event) | 1996 | if (leader != event) { |
1808 | group_sched_out(leader, cpuctx, ctx); | 1997 | group_sched_out(leader, cpuctx, ctx); |
1998 | perf_cpu_hrtimer_restart(cpuctx); | ||
1999 | } | ||
1809 | if (leader->attr.pinned) { | 2000 | if (leader->attr.pinned) { |
1810 | update_group_times(leader); | 2001 | update_group_times(leader); |
1811 | leader->state = PERF_EVENT_STATE_ERROR; | 2002 | leader->state = PERF_EVENT_STATE_ERROR; |
@@ -2552,7 +2743,7 @@ static void rotate_ctx(struct perf_event_context *ctx) | |||
2552 | * because they're strictly cpu affine and rotate_start is called with IRQs | 2743 | * because they're strictly cpu affine and rotate_start is called with IRQs |
2553 | * disabled, while rotate_context is called from IRQ context. | 2744 | * disabled, while rotate_context is called from IRQ context. |
2554 | */ | 2745 | */ |
2555 | static void perf_rotate_context(struct perf_cpu_context *cpuctx) | 2746 | static int perf_rotate_context(struct perf_cpu_context *cpuctx) |
2556 | { | 2747 | { |
2557 | struct perf_event_context *ctx = NULL; | 2748 | struct perf_event_context *ctx = NULL; |
2558 | int rotate = 0, remove = 1; | 2749 | int rotate = 0, remove = 1; |
@@ -2591,6 +2782,8 @@ static void perf_rotate_context(struct perf_cpu_context *cpuctx) | |||
2591 | done: | 2782 | done: |
2592 | if (remove) | 2783 | if (remove) |
2593 | list_del_init(&cpuctx->rotation_list); | 2784 | list_del_init(&cpuctx->rotation_list); |
2785 | |||
2786 | return rotate; | ||
2594 | } | 2787 | } |
2595 | 2788 | ||
2596 | #ifdef CONFIG_NO_HZ_FULL | 2789 | #ifdef CONFIG_NO_HZ_FULL |
@@ -2622,10 +2815,6 @@ void perf_event_task_tick(void) | |||
2622 | ctx = cpuctx->task_ctx; | 2815 | ctx = cpuctx->task_ctx; |
2623 | if (ctx) | 2816 | if (ctx) |
2624 | perf_adjust_freq_unthr_context(ctx, throttled); | 2817 | perf_adjust_freq_unthr_context(ctx, throttled); |
2625 | |||
2626 | if (cpuctx->jiffies_interval == 1 || | ||
2627 | !(jiffies % cpuctx->jiffies_interval)) | ||
2628 | perf_rotate_context(cpuctx); | ||
2629 | } | 2818 | } |
2630 | } | 2819 | } |
2631 | 2820 | ||
@@ -5036,7 +5225,7 @@ static DEFINE_PER_CPU(struct swevent_htable, swevent_htable); | |||
5036 | * sign as trigger. | 5225 | * sign as trigger. |
5037 | */ | 5226 | */ |
5038 | 5227 | ||
5039 | static u64 perf_swevent_set_period(struct perf_event *event) | 5228 | u64 perf_swevent_set_period(struct perf_event *event) |
5040 | { | 5229 | { |
5041 | struct hw_perf_event *hwc = &event->hw; | 5230 | struct hw_perf_event *hwc = &event->hw; |
5042 | u64 period = hwc->last_period; | 5231 | u64 period = hwc->last_period; |
@@ -5979,9 +6168,56 @@ type_show(struct device *dev, struct device_attribute *attr, char *page) | |||
5979 | return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type); | 6168 | return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->type); |
5980 | } | 6169 | } |
5981 | 6170 | ||
6171 | static ssize_t | ||
6172 | perf_event_mux_interval_ms_show(struct device *dev, | ||
6173 | struct device_attribute *attr, | ||
6174 | char *page) | ||
6175 | { | ||
6176 | struct pmu *pmu = dev_get_drvdata(dev); | ||
6177 | |||
6178 | return snprintf(page, PAGE_SIZE-1, "%d\n", pmu->hrtimer_interval_ms); | ||
6179 | } | ||
6180 | |||
6181 | static ssize_t | ||
6182 | perf_event_mux_interval_ms_store(struct device *dev, | ||
6183 | struct device_attribute *attr, | ||
6184 | const char *buf, size_t count) | ||
6185 | { | ||
6186 | struct pmu *pmu = dev_get_drvdata(dev); | ||
6187 | int timer, cpu, ret; | ||
6188 | |||
6189 | ret = kstrtoint(buf, 0, &timer); | ||
6190 | if (ret) | ||
6191 | return ret; | ||
6192 | |||
6193 | if (timer < 1) | ||
6194 | return -EINVAL; | ||
6195 | |||
6196 | /* same value, noting to do */ | ||
6197 | if (timer == pmu->hrtimer_interval_ms) | ||
6198 | return count; | ||
6199 | |||
6200 | pmu->hrtimer_interval_ms = timer; | ||
6201 | |||
6202 | /* update all cpuctx for this PMU */ | ||
6203 | for_each_possible_cpu(cpu) { | ||
6204 | struct perf_cpu_context *cpuctx; | ||
6205 | cpuctx = per_cpu_ptr(pmu->pmu_cpu_context, cpu); | ||
6206 | cpuctx->hrtimer_interval = ns_to_ktime(NSEC_PER_MSEC * timer); | ||
6207 | |||
6208 | if (hrtimer_active(&cpuctx->hrtimer)) | ||
6209 | hrtimer_forward_now(&cpuctx->hrtimer, cpuctx->hrtimer_interval); | ||
6210 | } | ||
6211 | |||
6212 | return count; | ||
6213 | } | ||
6214 | |||
6215 | #define __ATTR_RW(attr) __ATTR(attr, 0644, attr##_show, attr##_store) | ||
6216 | |||
5982 | static struct device_attribute pmu_dev_attrs[] = { | 6217 | static struct device_attribute pmu_dev_attrs[] = { |
5983 | __ATTR_RO(type), | 6218 | __ATTR_RO(type), |
5984 | __ATTR_NULL, | 6219 | __ATTR_RW(perf_event_mux_interval_ms), |
6220 | __ATTR_NULL, | ||
5985 | }; | 6221 | }; |
5986 | 6222 | ||
5987 | static int pmu_bus_running; | 6223 | static int pmu_bus_running; |
@@ -6027,7 +6263,7 @@ free_dev: | |||
6027 | static struct lock_class_key cpuctx_mutex; | 6263 | static struct lock_class_key cpuctx_mutex; |
6028 | static struct lock_class_key cpuctx_lock; | 6264 | static struct lock_class_key cpuctx_lock; |
6029 | 6265 | ||
6030 | int perf_pmu_register(struct pmu *pmu, char *name, int type) | 6266 | int perf_pmu_register(struct pmu *pmu, const char *name, int type) |
6031 | { | 6267 | { |
6032 | int cpu, ret; | 6268 | int cpu, ret; |
6033 | 6269 | ||
@@ -6076,7 +6312,9 @@ skip_type: | |||
6076 | lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); | 6312 | lockdep_set_class(&cpuctx->ctx.lock, &cpuctx_lock); |
6077 | cpuctx->ctx.type = cpu_context; | 6313 | cpuctx->ctx.type = cpu_context; |
6078 | cpuctx->ctx.pmu = pmu; | 6314 | cpuctx->ctx.pmu = pmu; |
6079 | cpuctx->jiffies_interval = 1; | 6315 | |
6316 | __perf_cpu_hrtimer_init(cpuctx, cpu); | ||
6317 | |||
6080 | INIT_LIST_HEAD(&cpuctx->rotation_list); | 6318 | INIT_LIST_HEAD(&cpuctx->rotation_list); |
6081 | cpuctx->unique_pmu = pmu; | 6319 | cpuctx->unique_pmu = pmu; |
6082 | } | 6320 | } |
@@ -6402,11 +6640,6 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, | |||
6402 | if (!(mask & ~PERF_SAMPLE_BRANCH_PLM_ALL)) | 6640 | if (!(mask & ~PERF_SAMPLE_BRANCH_PLM_ALL)) |
6403 | return -EINVAL; | 6641 | return -EINVAL; |
6404 | 6642 | ||
6405 | /* kernel level capture: check permissions */ | ||
6406 | if ((mask & PERF_SAMPLE_BRANCH_PERM_PLM) | ||
6407 | && perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) | ||
6408 | return -EACCES; | ||
6409 | |||
6410 | /* propagate priv level, when not set for branch */ | 6643 | /* propagate priv level, when not set for branch */ |
6411 | if (!(mask & PERF_SAMPLE_BRANCH_PLM_ALL)) { | 6644 | if (!(mask & PERF_SAMPLE_BRANCH_PLM_ALL)) { |
6412 | 6645 | ||
@@ -6424,6 +6657,10 @@ static int perf_copy_attr(struct perf_event_attr __user *uattr, | |||
6424 | */ | 6657 | */ |
6425 | attr->branch_sample_type = mask; | 6658 | attr->branch_sample_type = mask; |
6426 | } | 6659 | } |
6660 | /* privileged levels capture (kernel, hv): check permissions */ | ||
6661 | if ((mask & PERF_SAMPLE_BRANCH_PERM_PLM) | ||
6662 | && perf_paranoid_kernel() && !capable(CAP_SYS_ADMIN)) | ||
6663 | return -EACCES; | ||
6427 | } | 6664 | } |
6428 | 6665 | ||
6429 | if (attr->sample_type & PERF_SAMPLE_REGS_USER) { | 6666 | if (attr->sample_type & PERF_SAMPLE_REGS_USER) { |
@@ -7476,7 +7713,6 @@ perf_cpu_notify(struct notifier_block *self, unsigned long action, void *hcpu) | |||
7476 | case CPU_DOWN_PREPARE: | 7713 | case CPU_DOWN_PREPARE: |
7477 | perf_event_exit_cpu(cpu); | 7714 | perf_event_exit_cpu(cpu); |
7478 | break; | 7715 | break; |
7479 | |||
7480 | default: | 7716 | default: |
7481 | break; | 7717 | break; |
7482 | } | 7718 | } |
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c index 20185ea64aa6..1559fb0b9296 100644 --- a/kernel/events/hw_breakpoint.c +++ b/kernel/events/hw_breakpoint.c | |||
@@ -46,23 +46,26 @@ | |||
46 | #include <linux/smp.h> | 46 | #include <linux/smp.h> |
47 | 47 | ||
48 | #include <linux/hw_breakpoint.h> | 48 | #include <linux/hw_breakpoint.h> |
49 | |||
50 | |||
51 | /* | 49 | /* |
52 | * Constraints data | 50 | * Constraints data |
53 | */ | 51 | */ |
52 | struct bp_cpuinfo { | ||
53 | /* Number of pinned cpu breakpoints in a cpu */ | ||
54 | unsigned int cpu_pinned; | ||
55 | /* tsk_pinned[n] is the number of tasks having n+1 breakpoints */ | ||
56 | unsigned int *tsk_pinned; | ||
57 | /* Number of non-pinned cpu/task breakpoints in a cpu */ | ||
58 | unsigned int flexible; /* XXX: placeholder, see fetch_this_slot() */ | ||
59 | }; | ||
54 | 60 | ||
55 | /* Number of pinned cpu breakpoints in a cpu */ | 61 | static DEFINE_PER_CPU(struct bp_cpuinfo, bp_cpuinfo[TYPE_MAX]); |
56 | static DEFINE_PER_CPU(unsigned int, nr_cpu_bp_pinned[TYPE_MAX]); | ||
57 | |||
58 | /* Number of pinned task breakpoints in a cpu */ | ||
59 | static DEFINE_PER_CPU(unsigned int *, nr_task_bp_pinned[TYPE_MAX]); | ||
60 | |||
61 | /* Number of non-pinned cpu/task breakpoints in a cpu */ | ||
62 | static DEFINE_PER_CPU(unsigned int, nr_bp_flexible[TYPE_MAX]); | ||
63 | |||
64 | static int nr_slots[TYPE_MAX]; | 62 | static int nr_slots[TYPE_MAX]; |
65 | 63 | ||
64 | static struct bp_cpuinfo *get_bp_info(int cpu, enum bp_type_idx type) | ||
65 | { | ||
66 | return per_cpu_ptr(bp_cpuinfo + type, cpu); | ||
67 | } | ||
68 | |||
66 | /* Keep track of the breakpoints attached to tasks */ | 69 | /* Keep track of the breakpoints attached to tasks */ |
67 | static LIST_HEAD(bp_task_head); | 70 | static LIST_HEAD(bp_task_head); |
68 | 71 | ||
@@ -96,8 +99,8 @@ static inline enum bp_type_idx find_slot_idx(struct perf_event *bp) | |||
96 | */ | 99 | */ |
97 | static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type) | 100 | static unsigned int max_task_bp_pinned(int cpu, enum bp_type_idx type) |
98 | { | 101 | { |
102 | unsigned int *tsk_pinned = get_bp_info(cpu, type)->tsk_pinned; | ||
99 | int i; | 103 | int i; |
100 | unsigned int *tsk_pinned = per_cpu(nr_task_bp_pinned[type], cpu); | ||
101 | 104 | ||
102 | for (i = nr_slots[type] - 1; i >= 0; i--) { | 105 | for (i = nr_slots[type] - 1; i >= 0; i--) { |
103 | if (tsk_pinned[i] > 0) | 106 | if (tsk_pinned[i] > 0) |
@@ -127,6 +130,13 @@ static int task_bp_pinned(int cpu, struct perf_event *bp, enum bp_type_idx type) | |||
127 | return count; | 130 | return count; |
128 | } | 131 | } |
129 | 132 | ||
133 | static const struct cpumask *cpumask_of_bp(struct perf_event *bp) | ||
134 | { | ||
135 | if (bp->cpu >= 0) | ||
136 | return cpumask_of(bp->cpu); | ||
137 | return cpu_possible_mask; | ||
138 | } | ||
139 | |||
130 | /* | 140 | /* |
131 | * Report the number of pinned/un-pinned breakpoints we have in | 141 | * Report the number of pinned/un-pinned breakpoints we have in |
132 | * a given cpu (cpu > -1) or in all of them (cpu = -1). | 142 | * a given cpu (cpu > -1) or in all of them (cpu = -1). |
@@ -135,25 +145,15 @@ static void | |||
135 | fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, | 145 | fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, |
136 | enum bp_type_idx type) | 146 | enum bp_type_idx type) |
137 | { | 147 | { |
138 | int cpu = bp->cpu; | 148 | const struct cpumask *cpumask = cpumask_of_bp(bp); |
139 | struct task_struct *tsk = bp->hw.bp_target; | 149 | int cpu; |
140 | |||
141 | if (cpu >= 0) { | ||
142 | slots->pinned = per_cpu(nr_cpu_bp_pinned[type], cpu); | ||
143 | if (!tsk) | ||
144 | slots->pinned += max_task_bp_pinned(cpu, type); | ||
145 | else | ||
146 | slots->pinned += task_bp_pinned(cpu, bp, type); | ||
147 | slots->flexible = per_cpu(nr_bp_flexible[type], cpu); | ||
148 | |||
149 | return; | ||
150 | } | ||
151 | 150 | ||
152 | for_each_possible_cpu(cpu) { | 151 | for_each_cpu(cpu, cpumask) { |
153 | unsigned int nr; | 152 | struct bp_cpuinfo *info = get_bp_info(cpu, type); |
153 | int nr; | ||
154 | 154 | ||
155 | nr = per_cpu(nr_cpu_bp_pinned[type], cpu); | 155 | nr = info->cpu_pinned; |
156 | if (!tsk) | 156 | if (!bp->hw.bp_target) |
157 | nr += max_task_bp_pinned(cpu, type); | 157 | nr += max_task_bp_pinned(cpu, type); |
158 | else | 158 | else |
159 | nr += task_bp_pinned(cpu, bp, type); | 159 | nr += task_bp_pinned(cpu, bp, type); |
@@ -161,8 +161,7 @@ fetch_bp_busy_slots(struct bp_busy_slots *slots, struct perf_event *bp, | |||
161 | if (nr > slots->pinned) | 161 | if (nr > slots->pinned) |
162 | slots->pinned = nr; | 162 | slots->pinned = nr; |
163 | 163 | ||
164 | nr = per_cpu(nr_bp_flexible[type], cpu); | 164 | nr = info->flexible; |
165 | |||
166 | if (nr > slots->flexible) | 165 | if (nr > slots->flexible) |
167 | slots->flexible = nr; | 166 | slots->flexible = nr; |
168 | } | 167 | } |
@@ -182,29 +181,19 @@ fetch_this_slot(struct bp_busy_slots *slots, int weight) | |||
182 | /* | 181 | /* |
183 | * Add a pinned breakpoint for the given task in our constraint table | 182 | * Add a pinned breakpoint for the given task in our constraint table |
184 | */ | 183 | */ |
185 | static void toggle_bp_task_slot(struct perf_event *bp, int cpu, bool enable, | 184 | static void toggle_bp_task_slot(struct perf_event *bp, int cpu, |
186 | enum bp_type_idx type, int weight) | 185 | enum bp_type_idx type, int weight) |
187 | { | 186 | { |
188 | unsigned int *tsk_pinned; | 187 | unsigned int *tsk_pinned = get_bp_info(cpu, type)->tsk_pinned; |
189 | int old_count = 0; | 188 | int old_idx, new_idx; |
190 | int old_idx = 0; | 189 | |
191 | int idx = 0; | 190 | old_idx = task_bp_pinned(cpu, bp, type) - 1; |
192 | 191 | new_idx = old_idx + weight; | |
193 | old_count = task_bp_pinned(cpu, bp, type); | 192 | |
194 | old_idx = old_count - 1; | 193 | if (old_idx >= 0) |
195 | idx = old_idx + weight; | 194 | tsk_pinned[old_idx]--; |
196 | 195 | if (new_idx >= 0) | |
197 | /* tsk_pinned[n] is the number of tasks having n breakpoints */ | 196 | tsk_pinned[new_idx]++; |
198 | tsk_pinned = per_cpu(nr_task_bp_pinned[type], cpu); | ||
199 | if (enable) { | ||
200 | tsk_pinned[idx]++; | ||
201 | if (old_count > 0) | ||
202 | tsk_pinned[old_idx]--; | ||
203 | } else { | ||
204 | tsk_pinned[idx]--; | ||
205 | if (old_count > 0) | ||
206 | tsk_pinned[old_idx]++; | ||
207 | } | ||
208 | } | 197 | } |
209 | 198 | ||
210 | /* | 199 | /* |
@@ -214,33 +203,26 @@ static void | |||
214 | toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type, | 203 | toggle_bp_slot(struct perf_event *bp, bool enable, enum bp_type_idx type, |
215 | int weight) | 204 | int weight) |
216 | { | 205 | { |
217 | int cpu = bp->cpu; | 206 | const struct cpumask *cpumask = cpumask_of_bp(bp); |
218 | struct task_struct *tsk = bp->hw.bp_target; | 207 | int cpu; |
219 | 208 | ||
220 | /* Pinned counter cpu profiling */ | 209 | if (!enable) |
221 | if (!tsk) { | 210 | weight = -weight; |
222 | 211 | ||
223 | if (enable) | 212 | /* Pinned counter cpu profiling */ |
224 | per_cpu(nr_cpu_bp_pinned[type], bp->cpu) += weight; | 213 | if (!bp->hw.bp_target) { |
225 | else | 214 | get_bp_info(bp->cpu, type)->cpu_pinned += weight; |
226 | per_cpu(nr_cpu_bp_pinned[type], bp->cpu) -= weight; | ||
227 | return; | 215 | return; |
228 | } | 216 | } |
229 | 217 | ||
230 | /* Pinned counter task profiling */ | 218 | /* Pinned counter task profiling */ |
231 | 219 | for_each_cpu(cpu, cpumask) | |
232 | if (!enable) | 220 | toggle_bp_task_slot(bp, cpu, type, weight); |
233 | list_del(&bp->hw.bp_list); | ||
234 | |||
235 | if (cpu >= 0) { | ||
236 | toggle_bp_task_slot(bp, cpu, enable, type, weight); | ||
237 | } else { | ||
238 | for_each_possible_cpu(cpu) | ||
239 | toggle_bp_task_slot(bp, cpu, enable, type, weight); | ||
240 | } | ||
241 | 221 | ||
242 | if (enable) | 222 | if (enable) |
243 | list_add_tail(&bp->hw.bp_list, &bp_task_head); | 223 | list_add_tail(&bp->hw.bp_list, &bp_task_head); |
224 | else | ||
225 | list_del(&bp->hw.bp_list); | ||
244 | } | 226 | } |
245 | 227 | ||
246 | /* | 228 | /* |
@@ -261,8 +243,8 @@ __weak void arch_unregister_hw_breakpoint(struct perf_event *bp) | |||
261 | * | 243 | * |
262 | * - If attached to a single cpu, check: | 244 | * - If attached to a single cpu, check: |
263 | * | 245 | * |
264 | * (per_cpu(nr_bp_flexible, cpu) || (per_cpu(nr_cpu_bp_pinned, cpu) | 246 | * (per_cpu(info->flexible, cpu) || (per_cpu(info->cpu_pinned, cpu) |
265 | * + max(per_cpu(nr_task_bp_pinned, cpu)))) < HBP_NUM | 247 | * + max(per_cpu(info->tsk_pinned, cpu)))) < HBP_NUM |
266 | * | 248 | * |
267 | * -> If there are already non-pinned counters in this cpu, it means | 249 | * -> If there are already non-pinned counters in this cpu, it means |
268 | * there is already a free slot for them. | 250 | * there is already a free slot for them. |
@@ -272,8 +254,8 @@ __weak void arch_unregister_hw_breakpoint(struct perf_event *bp) | |||
272 | * | 254 | * |
273 | * - If attached to every cpus, check: | 255 | * - If attached to every cpus, check: |
274 | * | 256 | * |
275 | * (per_cpu(nr_bp_flexible, *) || (max(per_cpu(nr_cpu_bp_pinned, *)) | 257 | * (per_cpu(info->flexible, *) || (max(per_cpu(info->cpu_pinned, *)) |
276 | * + max(per_cpu(nr_task_bp_pinned, *)))) < HBP_NUM | 258 | * + max(per_cpu(info->tsk_pinned, *)))) < HBP_NUM |
277 | * | 259 | * |
278 | * -> This is roughly the same, except we check the number of per cpu | 260 | * -> This is roughly the same, except we check the number of per cpu |
279 | * bp for every cpu and we keep the max one. Same for the per tasks | 261 | * bp for every cpu and we keep the max one. Same for the per tasks |
@@ -284,16 +266,16 @@ __weak void arch_unregister_hw_breakpoint(struct perf_event *bp) | |||
284 | * | 266 | * |
285 | * - If attached to a single cpu, check: | 267 | * - If attached to a single cpu, check: |
286 | * | 268 | * |
287 | * ((per_cpu(nr_bp_flexible, cpu) > 1) + per_cpu(nr_cpu_bp_pinned, cpu) | 269 | * ((per_cpu(info->flexible, cpu) > 1) + per_cpu(info->cpu_pinned, cpu) |
288 | * + max(per_cpu(nr_task_bp_pinned, cpu))) < HBP_NUM | 270 | * + max(per_cpu(info->tsk_pinned, cpu))) < HBP_NUM |
289 | * | 271 | * |
290 | * -> Same checks as before. But now the nr_bp_flexible, if any, must keep | 272 | * -> Same checks as before. But now the info->flexible, if any, must keep |
291 | * one register at least (or they will never be fed). | 273 | * one register at least (or they will never be fed). |
292 | * | 274 | * |
293 | * - If attached to every cpus, check: | 275 | * - If attached to every cpus, check: |
294 | * | 276 | * |
295 | * ((per_cpu(nr_bp_flexible, *) > 1) + max(per_cpu(nr_cpu_bp_pinned, *)) | 277 | * ((per_cpu(info->flexible, *) > 1) + max(per_cpu(info->cpu_pinned, *)) |
296 | * + max(per_cpu(nr_task_bp_pinned, *))) < HBP_NUM | 278 | * + max(per_cpu(info->tsk_pinned, *))) < HBP_NUM |
297 | */ | 279 | */ |
298 | static int __reserve_bp_slot(struct perf_event *bp) | 280 | static int __reserve_bp_slot(struct perf_event *bp) |
299 | { | 281 | { |
@@ -518,8 +500,8 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr, | |||
518 | perf_overflow_handler_t triggered, | 500 | perf_overflow_handler_t triggered, |
519 | void *context) | 501 | void *context) |
520 | { | 502 | { |
521 | struct perf_event * __percpu *cpu_events, **pevent, *bp; | 503 | struct perf_event * __percpu *cpu_events, *bp; |
522 | long err; | 504 | long err = 0; |
523 | int cpu; | 505 | int cpu; |
524 | 506 | ||
525 | cpu_events = alloc_percpu(typeof(*cpu_events)); | 507 | cpu_events = alloc_percpu(typeof(*cpu_events)); |
@@ -528,31 +510,21 @@ register_wide_hw_breakpoint(struct perf_event_attr *attr, | |||
528 | 510 | ||
529 | get_online_cpus(); | 511 | get_online_cpus(); |
530 | for_each_online_cpu(cpu) { | 512 | for_each_online_cpu(cpu) { |
531 | pevent = per_cpu_ptr(cpu_events, cpu); | ||
532 | bp = perf_event_create_kernel_counter(attr, cpu, NULL, | 513 | bp = perf_event_create_kernel_counter(attr, cpu, NULL, |
533 | triggered, context); | 514 | triggered, context); |
534 | |||
535 | *pevent = bp; | ||
536 | |||
537 | if (IS_ERR(bp)) { | 515 | if (IS_ERR(bp)) { |
538 | err = PTR_ERR(bp); | 516 | err = PTR_ERR(bp); |
539 | goto fail; | 517 | break; |
540 | } | 518 | } |
541 | } | ||
542 | put_online_cpus(); | ||
543 | 519 | ||
544 | return cpu_events; | 520 | per_cpu(*cpu_events, cpu) = bp; |
545 | |||
546 | fail: | ||
547 | for_each_online_cpu(cpu) { | ||
548 | pevent = per_cpu_ptr(cpu_events, cpu); | ||
549 | if (IS_ERR(*pevent)) | ||
550 | break; | ||
551 | unregister_hw_breakpoint(*pevent); | ||
552 | } | 521 | } |
553 | put_online_cpus(); | 522 | put_online_cpus(); |
554 | 523 | ||
555 | free_percpu(cpu_events); | 524 | if (likely(!err)) |
525 | return cpu_events; | ||
526 | |||
527 | unregister_wide_hw_breakpoint(cpu_events); | ||
556 | return (void __percpu __force *)ERR_PTR(err); | 528 | return (void __percpu __force *)ERR_PTR(err); |
557 | } | 529 | } |
558 | EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint); | 530 | EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint); |
@@ -564,12 +536,10 @@ EXPORT_SYMBOL_GPL(register_wide_hw_breakpoint); | |||
564 | void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) | 536 | void unregister_wide_hw_breakpoint(struct perf_event * __percpu *cpu_events) |
565 | { | 537 | { |
566 | int cpu; | 538 | int cpu; |
567 | struct perf_event **pevent; | ||
568 | 539 | ||
569 | for_each_possible_cpu(cpu) { | 540 | for_each_possible_cpu(cpu) |
570 | pevent = per_cpu_ptr(cpu_events, cpu); | 541 | unregister_hw_breakpoint(per_cpu(*cpu_events, cpu)); |
571 | unregister_hw_breakpoint(*pevent); | 542 | |
572 | } | ||
573 | free_percpu(cpu_events); | 543 | free_percpu(cpu_events); |
574 | } | 544 | } |
575 | EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint); | 545 | EXPORT_SYMBOL_GPL(unregister_wide_hw_breakpoint); |
@@ -612,6 +582,11 @@ static int hw_breakpoint_add(struct perf_event *bp, int flags) | |||
612 | if (!(flags & PERF_EF_START)) | 582 | if (!(flags & PERF_EF_START)) |
613 | bp->hw.state = PERF_HES_STOPPED; | 583 | bp->hw.state = PERF_HES_STOPPED; |
614 | 584 | ||
585 | if (is_sampling_event(bp)) { | ||
586 | bp->hw.last_period = bp->hw.sample_period; | ||
587 | perf_swevent_set_period(bp); | ||
588 | } | ||
589 | |||
615 | return arch_install_hw_breakpoint(bp); | 590 | return arch_install_hw_breakpoint(bp); |
616 | } | 591 | } |
617 | 592 | ||
@@ -650,7 +625,6 @@ static struct pmu perf_breakpoint = { | |||
650 | 625 | ||
651 | int __init init_hw_breakpoint(void) | 626 | int __init init_hw_breakpoint(void) |
652 | { | 627 | { |
653 | unsigned int **task_bp_pinned; | ||
654 | int cpu, err_cpu; | 628 | int cpu, err_cpu; |
655 | int i; | 629 | int i; |
656 | 630 | ||
@@ -659,10 +633,11 @@ int __init init_hw_breakpoint(void) | |||
659 | 633 | ||
660 | for_each_possible_cpu(cpu) { | 634 | for_each_possible_cpu(cpu) { |
661 | for (i = 0; i < TYPE_MAX; i++) { | 635 | for (i = 0; i < TYPE_MAX; i++) { |
662 | task_bp_pinned = &per_cpu(nr_task_bp_pinned[i], cpu); | 636 | struct bp_cpuinfo *info = get_bp_info(cpu, i); |
663 | *task_bp_pinned = kzalloc(sizeof(int) * nr_slots[i], | 637 | |
664 | GFP_KERNEL); | 638 | info->tsk_pinned = kcalloc(nr_slots[i], sizeof(int), |
665 | if (!*task_bp_pinned) | 639 | GFP_KERNEL); |
640 | if (!info->tsk_pinned) | ||
666 | goto err_alloc; | 641 | goto err_alloc; |
667 | } | 642 | } |
668 | } | 643 | } |
@@ -676,7 +651,7 @@ int __init init_hw_breakpoint(void) | |||
676 | err_alloc: | 651 | err_alloc: |
677 | for_each_possible_cpu(err_cpu) { | 652 | for_each_possible_cpu(err_cpu) { |
678 | for (i = 0; i < TYPE_MAX; i++) | 653 | for (i = 0; i < TYPE_MAX; i++) |
679 | kfree(per_cpu(nr_task_bp_pinned[i], err_cpu)); | 654 | kfree(get_bp_info(err_cpu, i)->tsk_pinned); |
680 | if (err_cpu == cpu) | 655 | if (err_cpu == cpu) |
681 | break; | 656 | break; |
682 | } | 657 | } |
diff --git a/kernel/sysctl.c b/kernel/sysctl.c index 9edcf456e0fc..4ce13c3cedb9 100644 --- a/kernel/sysctl.c +++ b/kernel/sysctl.c | |||
@@ -120,7 +120,6 @@ extern int blk_iopoll_enabled; | |||
120 | /* Constants used for minimum and maximum */ | 120 | /* Constants used for minimum and maximum */ |
121 | #ifdef CONFIG_LOCKUP_DETECTOR | 121 | #ifdef CONFIG_LOCKUP_DETECTOR |
122 | static int sixty = 60; | 122 | static int sixty = 60; |
123 | static int neg_one = -1; | ||
124 | #endif | 123 | #endif |
125 | 124 | ||
126 | static int zero; | 125 | static int zero; |
@@ -814,7 +813,7 @@ static struct ctl_table kern_table[] = { | |||
814 | .maxlen = sizeof(int), | 813 | .maxlen = sizeof(int), |
815 | .mode = 0644, | 814 | .mode = 0644, |
816 | .proc_handler = proc_dowatchdog, | 815 | .proc_handler = proc_dowatchdog, |
817 | .extra1 = &neg_one, | 816 | .extra1 = &zero, |
818 | .extra2 = &sixty, | 817 | .extra2 = &sixty, |
819 | }, | 818 | }, |
820 | { | 819 | { |
@@ -1044,6 +1043,15 @@ static struct ctl_table kern_table[] = { | |||
1044 | .mode = 0644, | 1043 | .mode = 0644, |
1045 | .proc_handler = perf_proc_update_handler, | 1044 | .proc_handler = perf_proc_update_handler, |
1046 | }, | 1045 | }, |
1046 | { | ||
1047 | .procname = "perf_cpu_time_max_percent", | ||
1048 | .data = &sysctl_perf_cpu_time_max_percent, | ||
1049 | .maxlen = sizeof(sysctl_perf_cpu_time_max_percent), | ||
1050 | .mode = 0644, | ||
1051 | .proc_handler = perf_cpu_time_max_percent_handler, | ||
1052 | .extra1 = &zero, | ||
1053 | .extra2 = &one_hundred, | ||
1054 | }, | ||
1047 | #endif | 1055 | #endif |
1048 | #ifdef CONFIG_KMEMCHECK | 1056 | #ifdef CONFIG_KMEMCHECK |
1049 | { | 1057 | { |