Skip to content

Commit 232ea34

Browse files
committed
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
* 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: perf: Fix loss of notification with multi-event perf, x86: Force IBS LVT offset assignment for family 10h perf, x86: Disable PEBS on SandyBridge chips trace_events_filter: Use rcu_assign_pointer() when setting ftrace_event_call->filter perf session: Fix crash with invalid CPU list perf python: Fix undefined symbol problem perf/x86: Enable raw event access to Intel offcore events perf: Don't use -ENOSPC for out of PMU resources perf: Do not set task_ctx pointer in cpuctx if there are no events in the context perf/x86: Fix PEBS instruction unwind oprofile, x86: Fix crash when unloading module (nmi timer mode) oprofile: Fix crash when unloading module (hr timer mode)
2 parents 40c043b + dc440d1 commit 232ea34

File tree

19 files changed

+185
-55
lines changed

19 files changed

+185
-55
lines changed

arch/arm/kernel/perf_event.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -353,15 +353,15 @@ validate_group(struct perf_event *event)
353353
fake_pmu.used_mask = fake_used_mask;
354354

355355
if (!validate_event(&fake_pmu, leader))
356-
return -ENOSPC;
356+
return -EINVAL;
357357

358358
list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
359359
if (!validate_event(&fake_pmu, sibling))
360-
return -ENOSPC;
360+
return -EINVAL;
361361
}
362362

363363
if (!validate_event(&fake_pmu, event))
364-
return -ENOSPC;
364+
return -EINVAL;
365365

366366
return 0;
367367
}

arch/mips/kernel/perf_event_mipsxx.c

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,7 +623,7 @@ static int mipspmu_event_init(struct perf_event *event)
623623
if (!atomic_inc_not_zero(&active_events)) {
624624
if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
625625
atomic_dec(&active_events);
626-
return -ENOSPC;
626+
return -EINVAL;
627627
}
628628

629629
mutex_lock(&pmu_reserve_mutex);
@@ -732,15 +732,15 @@ static int validate_group(struct perf_event *event)
732732
memset(&fake_cpuc, 0, sizeof(fake_cpuc));
733733

734734
if (!validate_event(&fake_cpuc, leader))
735-
return -ENOSPC;
735+
return -EINVAL;
736736

737737
list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
738738
if (!validate_event(&fake_cpuc, sibling))
739-
return -ENOSPC;
739+
return -EINVAL;
740740
}
741741

742742
if (!validate_event(&fake_cpuc, event))
743-
return -ENOSPC;
743+
return -EINVAL;
744744

745745
return 0;
746746
}

arch/x86/kernel/cpu/perf_event.c

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -312,12 +312,8 @@ int x86_setup_perfctr(struct perf_event *event)
312312
return -EOPNOTSUPP;
313313
}
314314

315-
/*
316-
* Do not allow config1 (extended registers) to propagate,
317-
* there's no sane user-space generalization yet:
318-
*/
319315
if (attr->type == PERF_TYPE_RAW)
320-
return 0;
316+
return x86_pmu_extra_regs(event->attr.config, event);
321317

322318
if (attr->type == PERF_TYPE_HW_CACHE)
323319
return set_ext_hw_attr(hwc, event);
@@ -588,7 +584,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
588584
x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]);
589585
}
590586
}
591-
return num ? -ENOSPC : 0;
587+
return num ? -EINVAL : 0;
592588
}
593589

594590
/*
@@ -607,7 +603,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
607603

608604
if (is_x86_event(leader)) {
609605
if (n >= max_count)
610-
return -ENOSPC;
606+
return -EINVAL;
611607
cpuc->event_list[n] = leader;
612608
n++;
613609
}
@@ -620,7 +616,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
620616
continue;
621617

622618
if (n >= max_count)
623-
return -ENOSPC;
619+
return -EINVAL;
624620

625621
cpuc->event_list[n] = event;
626622
n++;
@@ -1316,7 +1312,7 @@ static int validate_event(struct perf_event *event)
13161312
c = x86_pmu.get_event_constraints(fake_cpuc, event);
13171313

13181314
if (!c || !c->weight)
1319-
ret = -ENOSPC;
1315+
ret = -EINVAL;
13201316

13211317
if (x86_pmu.put_event_constraints)
13221318
x86_pmu.put_event_constraints(fake_cpuc, event);
@@ -1341,7 +1337,7 @@ static int validate_group(struct perf_event *event)
13411337
{
13421338
struct perf_event *leader = event->group_leader;
13431339
struct cpu_hw_events *fake_cpuc;
1344-
int ret = -ENOSPC, n;
1340+
int ret = -EINVAL, n;
13451341

13461342
fake_cpuc = allocate_fake_cpuc();
13471343
if (IS_ERR(fake_cpuc))

arch/x86/kernel/cpu/perf_event_amd_ibs.c

Lines changed: 18 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -199,8 +199,7 @@ static int force_ibs_eilvt_setup(void)
199199
goto out;
200200
}
201201

202-
pr_err(FW_BUG "using offset %d for IBS interrupts\n", offset);
203-
pr_err(FW_BUG "workaround enabled for IBS LVT offset\n");
202+
pr_info("IBS: LVT offset %d assigned\n", offset);
204203

205204
return 0;
206205
out:
@@ -265,19 +264,23 @@ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *h
265264
static __init int amd_ibs_init(void)
266265
{
267266
u32 caps;
268-
int ret;
267+
int ret = -EINVAL;
269268

270269
caps = __get_ibs_caps();
271270
if (!caps)
272271
return -ENODEV; /* ibs not supported by the cpu */
273272

274-
if (!ibs_eilvt_valid()) {
275-
ret = force_ibs_eilvt_setup();
276-
if (ret) {
277-
pr_err("Failed to setup IBS, %d\n", ret);
278-
return ret;
279-
}
280-
}
273+
/*
274+
* Force LVT offset assignment for family 10h: The offsets are
275+
* not assigned by the BIOS for this family, so the OS is
276+
* responsible for doing it. If the OS assignment fails, fall
277+
* back to BIOS settings and try to setup this.
278+
*/
279+
if (boot_cpu_data.x86 == 0x10)
280+
force_ibs_eilvt_setup();
281+
282+
if (!ibs_eilvt_valid())
283+
goto out;
281284

282285
get_online_cpus();
283286
ibs_caps = caps;
@@ -287,7 +290,11 @@ static __init int amd_ibs_init(void)
287290
smp_call_function(setup_APIC_ibs, NULL, 1);
288291
put_online_cpus();
289292

290-
return perf_event_ibs_init();
293+
ret = perf_event_ibs_init();
294+
out:
295+
if (ret)
296+
pr_err("Failed to setup IBS, %d\n", ret);
297+
return ret;
291298
}
292299

293300
/* Since we need the pci subsystem to init ibs we can't do this earlier: */

arch/x86/kernel/cpu/perf_event_intel.c

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1545,6 +1545,13 @@ static void intel_clovertown_quirks(void)
15451545
x86_pmu.pebs_constraints = NULL;
15461546
}
15471547

1548+
static void intel_sandybridge_quirks(void)
1549+
{
1550+
printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
1551+
x86_pmu.pebs = 0;
1552+
x86_pmu.pebs_constraints = NULL;
1553+
}
1554+
15481555
__init int intel_pmu_init(void)
15491556
{
15501557
union cpuid10_edx edx;
@@ -1694,6 +1701,7 @@ __init int intel_pmu_init(void)
16941701
break;
16951702

16961703
case 42: /* SandyBridge */
1704+
x86_pmu.quirks = intel_sandybridge_quirks;
16971705
case 45: /* SandyBridge, "Romely-EP" */
16981706
memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
16991707
sizeof(hw_cache_event_ids));

arch/x86/kernel/cpu/perf_event_intel_ds.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -493,6 +493,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
493493
unsigned long from = cpuc->lbr_entries[0].from;
494494
unsigned long old_to, to = cpuc->lbr_entries[0].to;
495495
unsigned long ip = regs->ip;
496+
int is_64bit = 0;
496497

497498
/*
498499
* We don't need to fixup if the PEBS assist is fault like
@@ -544,7 +545,10 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
544545
} else
545546
kaddr = (void *)to;
546547

547-
kernel_insn_init(&insn, kaddr);
548+
#ifdef CONFIG_X86_64
549+
is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
550+
#endif
551+
insn_init(&insn, kaddr, is_64bit);
548552
insn_get_length(&insn);
549553
to += insn.length;
550554
} while (to < ip);

arch/x86/kernel/cpu/perf_event_p4.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1268,7 +1268,7 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
12681268
}
12691269

12701270
done:
1271-
return num ? -ENOSPC : 0;
1271+
return num ? -EINVAL : 0;
12721272
}
12731273

12741274
static __initconst const struct x86_pmu p4_pmu = {

arch/x86/oprofile/init.c

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops);
2121
extern void op_nmi_exit(void);
2222
extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);
2323

24+
static int nmi_timer;
2425

2526
int __init oprofile_arch_init(struct oprofile_operations *ops)
2627
{
@@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
3132
#ifdef CONFIG_X86_LOCAL_APIC
3233
ret = op_nmi_init(ops);
3334
#endif
35+
nmi_timer = (ret != 0);
3436
#ifdef CONFIG_X86_IO_APIC
35-
if (ret < 0)
37+
if (nmi_timer)
3638
ret = op_nmi_timer_init(ops);
3739
#endif
3840
ops->backtrace = x86_backtrace;
@@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
4446
void oprofile_arch_exit(void)
4547
{
4648
#ifdef CONFIG_X86_LOCAL_APIC
47-
op_nmi_exit();
49+
if (!nmi_timer)
50+
op_nmi_exit();
4851
#endif
4952
}

drivers/oprofile/oprof.c

Lines changed: 24 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -239,26 +239,45 @@ int oprofile_set_ulong(unsigned long *addr, unsigned long val)
239239
return err;
240240
}
241241

242+
static int timer_mode;
243+
242244
static int __init oprofile_init(void)
243245
{
244246
int err;
245247

248+
/* always init architecture to setup backtrace support */
246249
err = oprofile_arch_init(&oprofile_ops);
247-
if (err < 0 || timer) {
248-
printk(KERN_INFO "oprofile: using timer interrupt.\n");
250+
251+
timer_mode = err || timer; /* fall back to timer mode on errors */
252+
if (timer_mode) {
253+
if (!err)
254+
oprofile_arch_exit();
249255
err = oprofile_timer_init(&oprofile_ops);
250256
if (err)
251257
return err;
252258
}
253-
return oprofilefs_register();
259+
260+
err = oprofilefs_register();
261+
if (!err)
262+
return 0;
263+
264+
/* failed */
265+
if (timer_mode)
266+
oprofile_timer_exit();
267+
else
268+
oprofile_arch_exit();
269+
270+
return err;
254271
}
255272

256273

257274
static void __exit oprofile_exit(void)
258275
{
259-
oprofile_timer_exit();
260276
oprofilefs_unregister();
261-
oprofile_arch_exit();
277+
if (timer_mode)
278+
oprofile_timer_exit();
279+
else
280+
oprofile_arch_exit();
262281
}
263282

264283

drivers/oprofile/timer_int.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -110,6 +110,7 @@ int oprofile_timer_init(struct oprofile_operations *ops)
110110
ops->start = oprofile_hrtimer_start;
111111
ops->stop = oprofile_hrtimer_stop;
112112
ops->cpu_type = "timer";
113+
printk(KERN_INFO "oprofile: using timer interrupt.\n");
113114
return 0;
114115
}
115116

include/linux/perf_event.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -822,6 +822,7 @@ struct perf_event {
822822
int mmap_locked;
823823
struct user_struct *mmap_user;
824824
struct ring_buffer *rb;
825+
struct list_head rb_entry;
825826

826827
/* poll related */
827828
wait_queue_head_t waitq;

0 commit comments

Comments
 (0)