aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-09-14 20:43:45 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-09-14 20:43:45 -0400
commit7ef6e97380a1cb0f38cab795fe696f43c71d3ae9 (patch)
tree0557d01616fb4a41bfc98e6908ace912fa6d717c
parent7076cca9a700af5ccb0bd5eb7261dcfd7356dc5a (diff)
parente4390fa632d7c592e68e8106b7daea923ac995f5 (diff)
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull perf fixes from Ingo Molnar: "This tree includes various fixes" Ingo really needs to improve on the whole "explain git pull" part. "Various fixes" indeed. * 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf/hwpb: Invoke __perf_event_disable() if interrupts are already disabled perf/x86: Enable Intel Cedarview Atom suppport perf_event: Switch to internal refcount, fix race with close() oprofile, s390: Fix uninitialized memory access when writing to oprofilefs perf/x86: Fix microcode revision check for SNB-PEBS
-rw-r--r--arch/s390/oprofile/init.c10
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel.c1
-rw-r--r--arch/x86/kernel/cpu/perf_event_intel_lbr.c3
-rw-r--r--arch/x86/kernel/microcode_core.c3
-rw-r--r--include/linux/perf_event.h4
-rw-r--r--kernel/events/core.c64
-rw-r--r--kernel/events/hw_breakpoint.c11
7 files changed, 58 insertions, 38 deletions
diff --git a/arch/s390/oprofile/init.c b/arch/s390/oprofile/init.c
index a1e9d69a9c90..584b93674ea4 100644
--- a/arch/s390/oprofile/init.c
+++ b/arch/s390/oprofile/init.c
@@ -169,7 +169,7 @@ static ssize_t hw_interval_write(struct file *file, char const __user *buf,
169 if (*offset) 169 if (*offset)
170 return -EINVAL; 170 return -EINVAL;
171 retval = oprofilefs_ulong_from_user(&val, buf, count); 171 retval = oprofilefs_ulong_from_user(&val, buf, count);
172 if (retval) 172 if (retval <= 0)
173 return retval; 173 return retval;
174 if (val < oprofile_min_interval) 174 if (val < oprofile_min_interval)
175 oprofile_hw_interval = oprofile_min_interval; 175 oprofile_hw_interval = oprofile_min_interval;
@@ -212,7 +212,7 @@ static ssize_t hwsampler_zero_write(struct file *file, char const __user *buf,
212 return -EINVAL; 212 return -EINVAL;
213 213
214 retval = oprofilefs_ulong_from_user(&val, buf, count); 214 retval = oprofilefs_ulong_from_user(&val, buf, count);
215 if (retval) 215 if (retval <= 0)
216 return retval; 216 return retval;
217 if (val != 0) 217 if (val != 0)
218 return -EINVAL; 218 return -EINVAL;
@@ -243,7 +243,7 @@ static ssize_t hwsampler_kernel_write(struct file *file, char const __user *buf,
243 return -EINVAL; 243 return -EINVAL;
244 244
245 retval = oprofilefs_ulong_from_user(&val, buf, count); 245 retval = oprofilefs_ulong_from_user(&val, buf, count);
246 if (retval) 246 if (retval <= 0)
247 return retval; 247 return retval;
248 248
249 if (val != 0 && val != 1) 249 if (val != 0 && val != 1)
@@ -278,7 +278,7 @@ static ssize_t hwsampler_user_write(struct file *file, char const __user *buf,
278 return -EINVAL; 278 return -EINVAL;
279 279
280 retval = oprofilefs_ulong_from_user(&val, buf, count); 280 retval = oprofilefs_ulong_from_user(&val, buf, count);
281 if (retval) 281 if (retval <= 0)
282 return retval; 282 return retval;
283 283
284 if (val != 0 && val != 1) 284 if (val != 0 && val != 1)
@@ -317,7 +317,7 @@ static ssize_t timer_enabled_write(struct file *file, char const __user *buf,
317 return -EINVAL; 317 return -EINVAL;
318 318
319 retval = oprofilefs_ulong_from_user(&val, buf, count); 319 retval = oprofilefs_ulong_from_user(&val, buf, count);
320 if (retval) 320 if (retval <= 0)
321 return retval; 321 return retval;
322 322
323 if (val != 0 && val != 1) 323 if (val != 0 && val != 1)
diff --git a/arch/x86/kernel/cpu/perf_event_intel.c b/arch/x86/kernel/cpu/perf_event_intel.c
index 7f2739e03e79..0d3d63afa76a 100644
--- a/arch/x86/kernel/cpu/perf_event_intel.c
+++ b/arch/x86/kernel/cpu/perf_event_intel.c
@@ -2008,6 +2008,7 @@ __init int intel_pmu_init(void)
2008 break; 2008 break;
2009 2009
2010 case 28: /* Atom */ 2010 case 28: /* Atom */
2011 case 54: /* Cedariew */
2011 memcpy(hw_cache_event_ids, atom_hw_cache_event_ids, 2012 memcpy(hw_cache_event_ids, atom_hw_cache_event_ids,
2012 sizeof(hw_cache_event_ids)); 2013 sizeof(hw_cache_event_ids));
2013 2014
diff --git a/arch/x86/kernel/cpu/perf_event_intel_lbr.c b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
index 520b4265fcd2..da02e9cc3754 100644
--- a/arch/x86/kernel/cpu/perf_event_intel_lbr.c
+++ b/arch/x86/kernel/cpu/perf_event_intel_lbr.c
@@ -686,7 +686,8 @@ void intel_pmu_lbr_init_atom(void)
686 * to have an operational LBR which can freeze 686 * to have an operational LBR which can freeze
687 * on PMU interrupt 687 * on PMU interrupt
688 */ 688 */
689 if (boot_cpu_data.x86_mask < 10) { 689 if (boot_cpu_data.x86_model == 28
690 && boot_cpu_data.x86_mask < 10) {
690 pr_cont("LBR disabled due to erratum"); 691 pr_cont("LBR disabled due to erratum");
691 return; 692 return;
692 } 693 }
diff --git a/arch/x86/kernel/microcode_core.c b/arch/x86/kernel/microcode_core.c
index 4873e62db6a1..9e5bcf1e2376 100644
--- a/arch/x86/kernel/microcode_core.c
+++ b/arch/x86/kernel/microcode_core.c
@@ -225,6 +225,9 @@ static ssize_t microcode_write(struct file *file, const char __user *buf,
225 if (do_microcode_update(buf, len) == 0) 225 if (do_microcode_update(buf, len) == 0)
226 ret = (ssize_t)len; 226 ret = (ssize_t)len;
227 227
228 if (ret > 0)
229 perf_check_microcode();
230
228 mutex_unlock(&microcode_mutex); 231 mutex_unlock(&microcode_mutex);
229 put_online_cpus(); 232 put_online_cpus();
230 233
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 7602ccb3f40e..33ed9d605f91 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -926,7 +926,7 @@ struct perf_event {
926 struct hw_perf_event hw; 926 struct hw_perf_event hw;
927 927
928 struct perf_event_context *ctx; 928 struct perf_event_context *ctx;
929 struct file *filp; 929 atomic_long_t refcount;
930 930
931 /* 931 /*
932 * These accumulate total time (in nanoseconds) that children 932 * These accumulate total time (in nanoseconds) that children
@@ -1296,6 +1296,7 @@ extern int perf_swevent_get_recursion_context(void);
1296extern void perf_swevent_put_recursion_context(int rctx); 1296extern void perf_swevent_put_recursion_context(int rctx);
1297extern void perf_event_enable(struct perf_event *event); 1297extern void perf_event_enable(struct perf_event *event);
1298extern void perf_event_disable(struct perf_event *event); 1298extern void perf_event_disable(struct perf_event *event);
1299extern int __perf_event_disable(void *info);
1299extern void perf_event_task_tick(void); 1300extern void perf_event_task_tick(void);
1300#else 1301#else
1301static inline void 1302static inline void
@@ -1334,6 +1335,7 @@ static inline int perf_swevent_get_recursion_context(void) { return -1; }
1334static inline void perf_swevent_put_recursion_context(int rctx) { } 1335static inline void perf_swevent_put_recursion_context(int rctx) { }
1335static inline void perf_event_enable(struct perf_event *event) { } 1336static inline void perf_event_enable(struct perf_event *event) { }
1336static inline void perf_event_disable(struct perf_event *event) { } 1337static inline void perf_event_disable(struct perf_event *event) { }
1338static inline int __perf_event_disable(void *info) { return -1; }
1337static inline void perf_event_task_tick(void) { } 1339static inline void perf_event_task_tick(void) { }
1338#endif 1340#endif
1339 1341
diff --git a/kernel/events/core.c b/kernel/events/core.c
index b7935fcec7d9..7fee567153f0 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -1253,7 +1253,7 @@ retry:
1253/* 1253/*
1254 * Cross CPU call to disable a performance event 1254 * Cross CPU call to disable a performance event
1255 */ 1255 */
1256static int __perf_event_disable(void *info) 1256int __perf_event_disable(void *info)
1257{ 1257{
1258 struct perf_event *event = info; 1258 struct perf_event *event = info;
1259 struct perf_event_context *ctx = event->ctx; 1259 struct perf_event_context *ctx = event->ctx;
@@ -2935,12 +2935,12 @@ EXPORT_SYMBOL_GPL(perf_event_release_kernel);
2935/* 2935/*
2936 * Called when the last reference to the file is gone. 2936 * Called when the last reference to the file is gone.
2937 */ 2937 */
2938static int perf_release(struct inode *inode, struct file *file) 2938static void put_event(struct perf_event *event)
2939{ 2939{
2940 struct perf_event *event = file->private_data;
2941 struct task_struct *owner; 2940 struct task_struct *owner;
2942 2941
2943 file->private_data = NULL; 2942 if (!atomic_long_dec_and_test(&event->refcount))
2943 return;
2944 2944
2945 rcu_read_lock(); 2945 rcu_read_lock();
2946 owner = ACCESS_ONCE(event->owner); 2946 owner = ACCESS_ONCE(event->owner);
@@ -2975,7 +2975,13 @@ static int perf_release(struct inode *inode, struct file *file)
2975 put_task_struct(owner); 2975 put_task_struct(owner);
2976 } 2976 }
2977 2977
2978 return perf_event_release_kernel(event); 2978 perf_event_release_kernel(event);
2979}
2980
2981static int perf_release(struct inode *inode, struct file *file)
2982{
2983 put_event(file->private_data);
2984 return 0;
2979} 2985}
2980 2986
2981u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running) 2987u64 perf_event_read_value(struct perf_event *event, u64 *enabled, u64 *running)
@@ -3227,7 +3233,7 @@ unlock:
3227 3233
3228static const struct file_operations perf_fops; 3234static const struct file_operations perf_fops;
3229 3235
3230static struct perf_event *perf_fget_light(int fd, int *fput_needed) 3236static struct file *perf_fget_light(int fd, int *fput_needed)
3231{ 3237{
3232 struct file *file; 3238 struct file *file;
3233 3239
@@ -3241,7 +3247,7 @@ static struct perf_event *perf_fget_light(int fd, int *fput_needed)
3241 return ERR_PTR(-EBADF); 3247 return ERR_PTR(-EBADF);
3242 } 3248 }
3243 3249
3244 return file->private_data; 3250 return file;
3245} 3251}
3246 3252
3247static int perf_event_set_output(struct perf_event *event, 3253static int perf_event_set_output(struct perf_event *event,
@@ -3273,19 +3279,21 @@ static long perf_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
3273 3279
3274 case PERF_EVENT_IOC_SET_OUTPUT: 3280 case PERF_EVENT_IOC_SET_OUTPUT:
3275 { 3281 {
3282 struct file *output_file = NULL;
3276 struct perf_event *output_event = NULL; 3283 struct perf_event *output_event = NULL;
3277 int fput_needed = 0; 3284 int fput_needed = 0;
3278 int ret; 3285 int ret;
3279 3286
3280 if (arg != -1) { 3287 if (arg != -1) {
3281 output_event = perf_fget_light(arg, &fput_needed); 3288 output_file = perf_fget_light(arg, &fput_needed);
3282 if (IS_ERR(output_event)) 3289 if (IS_ERR(output_file))
3283 return PTR_ERR(output_event); 3290 return PTR_ERR(output_file);
3291 output_event = output_file->private_data;
3284 } 3292 }
3285 3293
3286 ret = perf_event_set_output(event, output_event); 3294 ret = perf_event_set_output(event, output_event);
3287 if (output_event) 3295 if (output_event)
3288 fput_light(output_event->filp, fput_needed); 3296 fput_light(output_file, fput_needed);
3289 3297
3290 return ret; 3298 return ret;
3291 } 3299 }
@@ -5950,6 +5958,7 @@ perf_event_alloc(struct perf_event_attr *attr, int cpu,
5950 5958
5951 mutex_init(&event->mmap_mutex); 5959 mutex_init(&event->mmap_mutex);
5952 5960
5961 atomic_long_set(&event->refcount, 1);
5953 event->cpu = cpu; 5962 event->cpu = cpu;
5954 event->attr = *attr; 5963 event->attr = *attr;
5955 event->group_leader = group_leader; 5964 event->group_leader = group_leader;
@@ -6260,12 +6269,12 @@ SYSCALL_DEFINE5(perf_event_open,
6260 return event_fd; 6269 return event_fd;
6261 6270
6262 if (group_fd != -1) { 6271 if (group_fd != -1) {
6263 group_leader = perf_fget_light(group_fd, &fput_needed); 6272 group_file = perf_fget_light(group_fd, &fput_needed);
6264 if (IS_ERR(group_leader)) { 6273 if (IS_ERR(group_file)) {
6265 err = PTR_ERR(group_leader); 6274 err = PTR_ERR(group_file);
6266 goto err_fd; 6275 goto err_fd;
6267 } 6276 }
6268 group_file = group_leader->filp; 6277 group_leader = group_file->private_data;
6269 if (flags & PERF_FLAG_FD_OUTPUT) 6278 if (flags & PERF_FLAG_FD_OUTPUT)
6270 output_event = group_leader; 6279 output_event = group_leader;
6271 if (flags & PERF_FLAG_FD_NO_GROUP) 6280 if (flags & PERF_FLAG_FD_NO_GROUP)
@@ -6402,7 +6411,6 @@ SYSCALL_DEFINE5(perf_event_open,
6402 put_ctx(gctx); 6411 put_ctx(gctx);
6403 } 6412 }
6404 6413
6405 event->filp = event_file;
6406 WARN_ON_ONCE(ctx->parent_ctx); 6414 WARN_ON_ONCE(ctx->parent_ctx);
6407 mutex_lock(&ctx->mutex); 6415 mutex_lock(&ctx->mutex);
6408 6416
@@ -6496,7 +6504,6 @@ perf_event_create_kernel_counter(struct perf_event_attr *attr, int cpu,
6496 goto err_free; 6504 goto err_free;
6497 } 6505 }
6498 6506
6499 event->filp = NULL;
6500 WARN_ON_ONCE(ctx->parent_ctx); 6507 WARN_ON_ONCE(ctx->parent_ctx);
6501 mutex_lock(&ctx->mutex); 6508 mutex_lock(&ctx->mutex);
6502 perf_install_in_context(ctx, event, cpu); 6509 perf_install_in_context(ctx, event, cpu);
@@ -6578,7 +6585,7 @@ static void sync_child_event(struct perf_event *child_event,
6578 * Release the parent event, if this was the last 6585 * Release the parent event, if this was the last
6579 * reference to it. 6586 * reference to it.
6580 */ 6587 */
6581 fput(parent_event->filp); 6588 put_event(parent_event);
6582} 6589}
6583 6590
6584static void 6591static void
@@ -6654,9 +6661,8 @@ static void perf_event_exit_task_context(struct task_struct *child, int ctxn)
6654 * 6661 *
6655 * __perf_event_exit_task() 6662 * __perf_event_exit_task()
6656 * sync_child_event() 6663 * sync_child_event()
6657 * fput(parent_event->filp) 6664 * put_event()
6658 * perf_release() 6665 * mutex_lock(&ctx->mutex)
6659 * mutex_lock(&ctx->mutex)
6660 * 6666 *
6661 * But since its the parent context it won't be the same instance. 6667 * But since its the parent context it won't be the same instance.
6662 */ 6668 */
@@ -6724,7 +6730,7 @@ static void perf_free_event(struct perf_event *event,
6724 list_del_init(&event->child_list); 6730 list_del_init(&event->child_list);
6725 mutex_unlock(&parent->child_mutex); 6731 mutex_unlock(&parent->child_mutex);
6726 6732
6727 fput(parent->filp); 6733 put_event(parent);
6728 6734
6729 perf_group_detach(event); 6735 perf_group_detach(event);
6730 list_del_event(event, ctx); 6736 list_del_event(event, ctx);
@@ -6804,6 +6810,12 @@ inherit_event(struct perf_event *parent_event,
6804 NULL, NULL); 6810 NULL, NULL);
6805 if (IS_ERR(child_event)) 6811 if (IS_ERR(child_event))
6806 return child_event; 6812 return child_event;
6813
6814 if (!atomic_long_inc_not_zero(&parent_event->refcount)) {
6815 free_event(child_event);
6816 return NULL;
6817 }
6818
6807 get_ctx(child_ctx); 6819 get_ctx(child_ctx);
6808 6820
6809 /* 6821 /*
@@ -6845,14 +6857,6 @@ inherit_event(struct perf_event *parent_event,
6845 raw_spin_unlock_irqrestore(&child_ctx->lock, flags); 6857 raw_spin_unlock_irqrestore(&child_ctx->lock, flags);
6846 6858
6847 /* 6859 /*
6848 * Get a reference to the parent filp - we will fput it
6849 * when the child event exits. This is safe to do because
6850 * we are in the parent and we know that the filp still
6851 * exists and has a nonzero count:
6852 */
6853 atomic_long_inc(&parent_event->filp->f_count);
6854
6855 /*
6856 * Link this into the parent event's child list 6860 * Link this into the parent event's child list
6857 */ 6861 */
6858 WARN_ON_ONCE(parent_event->ctx->parent_ctx); 6862 WARN_ON_ONCE(parent_event->ctx->parent_ctx);
diff --git a/kernel/events/hw_breakpoint.c b/kernel/events/hw_breakpoint.c
index bb38c4d3ee12..9a7b487c6fe2 100644
--- a/kernel/events/hw_breakpoint.c
+++ b/kernel/events/hw_breakpoint.c
@@ -453,7 +453,16 @@ int modify_user_hw_breakpoint(struct perf_event *bp, struct perf_event_attr *att
453 int old_type = bp->attr.bp_type; 453 int old_type = bp->attr.bp_type;
454 int err = 0; 454 int err = 0;
455 455
456 perf_event_disable(bp); 456 /*
457 * modify_user_hw_breakpoint can be invoked with IRQs disabled and hence it
458 * will not be possible to raise IPIs that invoke __perf_event_disable.
459 * So call the function directly after making sure we are targeting the
460 * current task.
461 */
462 if (irqs_disabled() && bp->ctx && bp->ctx->task == current)
463 __perf_event_disable(bp);
464 else
465 perf_event_disable(bp);
457 466
458 bp->attr.bp_addr = attr->bp_addr; 467 bp->attr.bp_addr = attr->bp_addr;
459 bp->attr.bp_type = attr->bp_type; 468 bp->attr.bp_type = attr->bp_type;