Skip to content

Commit

Permalink
Merge branch 'perf-urgent-for-linus' of git://git.kernel.org/pub/scm/…
Browse files Browse the repository at this point in the history
…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)
  • Loading branch information
torvalds committed Dec 6, 2011
2 parents 40c043b + dc440d1 commit 232ea34
Show file tree
Hide file tree
Showing 19 changed files with 185 additions and 55 deletions.
6 changes: 3 additions & 3 deletions arch/arm/kernel/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -353,15 +353,15 @@ validate_group(struct perf_event *event)
fake_pmu.used_mask = fake_used_mask;

if (!validate_event(&fake_pmu, leader))
return -ENOSPC;
return -EINVAL;

list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
if (!validate_event(&fake_pmu, sibling))
return -ENOSPC;
return -EINVAL;
}

if (!validate_event(&fake_pmu, event))
return -ENOSPC;
return -EINVAL;

return 0;
}
Expand Down
8 changes: 4 additions & 4 deletions arch/mips/kernel/perf_event_mipsxx.c
Original file line number Diff line number Diff line change
Expand Up @@ -623,7 +623,7 @@ static int mipspmu_event_init(struct perf_event *event)
if (!atomic_inc_not_zero(&active_events)) {
if (atomic_read(&active_events) > MIPS_MAX_HWEVENTS) {
atomic_dec(&active_events);
return -ENOSPC;
return -EINVAL;
}

mutex_lock(&pmu_reserve_mutex);
Expand Down Expand Up @@ -732,15 +732,15 @@ static int validate_group(struct perf_event *event)
memset(&fake_cpuc, 0, sizeof(fake_cpuc));

if (!validate_event(&fake_cpuc, leader))
return -ENOSPC;
return -EINVAL;

list_for_each_entry(sibling, &leader->sibling_list, group_entry) {
if (!validate_event(&fake_cpuc, sibling))
return -ENOSPC;
return -EINVAL;
}

if (!validate_event(&fake_cpuc, event))
return -ENOSPC;
return -EINVAL;

return 0;
}
Expand Down
16 changes: 6 additions & 10 deletions arch/x86/kernel/cpu/perf_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,12 +312,8 @@ int x86_setup_perfctr(struct perf_event *event)
return -EOPNOTSUPP;
}

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

if (attr->type == PERF_TYPE_HW_CACHE)
return set_ext_hw_attr(hwc, event);
Expand Down Expand Up @@ -588,7 +584,7 @@ int x86_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign)
x86_pmu.put_event_constraints(cpuc, cpuc->event_list[i]);
}
}
return num ? -ENOSPC : 0;
return num ? -EINVAL : 0;
}

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

if (is_x86_event(leader)) {
if (n >= max_count)
return -ENOSPC;
return -EINVAL;
cpuc->event_list[n] = leader;
n++;
}
Expand All @@ -620,7 +616,7 @@ static int collect_events(struct cpu_hw_events *cpuc, struct perf_event *leader,
continue;

if (n >= max_count)
return -ENOSPC;
return -EINVAL;

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

if (!c || !c->weight)
ret = -ENOSPC;
ret = -EINVAL;

if (x86_pmu.put_event_constraints)
x86_pmu.put_event_constraints(fake_cpuc, event);
Expand All @@ -1341,7 +1337,7 @@ static int validate_group(struct perf_event *event)
{
struct perf_event *leader = event->group_leader;
struct cpu_hw_events *fake_cpuc;
int ret = -ENOSPC, n;
int ret = -EINVAL, n;

fake_cpuc = allocate_fake_cpuc();
if (IS_ERR(fake_cpuc))
Expand Down
29 changes: 18 additions & 11 deletions arch/x86/kernel/cpu/perf_event_amd_ibs.c
Original file line number Diff line number Diff line change
Expand Up @@ -199,8 +199,7 @@ static int force_ibs_eilvt_setup(void)
goto out;
}

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

return 0;
out:
Expand Down Expand Up @@ -265,19 +264,23 @@ perf_ibs_cpu_notifier(struct notifier_block *self, unsigned long action, void *h
static __init int amd_ibs_init(void)
{
u32 caps;
int ret;
int ret = -EINVAL;

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

if (!ibs_eilvt_valid()) {
ret = force_ibs_eilvt_setup();
if (ret) {
pr_err("Failed to setup IBS, %d\n", ret);
return ret;
}
}
/*
* Force LVT offset assignment for family 10h: The offsets are
* not assigned by the BIOS for this family, so the OS is
* responsible for doing it. If the OS assignment fails, fall
* back to BIOS settings and try to setup this.
*/
if (boot_cpu_data.x86 == 0x10)
force_ibs_eilvt_setup();

if (!ibs_eilvt_valid())
goto out;

get_online_cpus();
ibs_caps = caps;
Expand All @@ -287,7 +290,11 @@ static __init int amd_ibs_init(void)
smp_call_function(setup_APIC_ibs, NULL, 1);
put_online_cpus();

return perf_event_ibs_init();
ret = perf_event_ibs_init();
out:
if (ret)
pr_err("Failed to setup IBS, %d\n", ret);
return ret;
}

/* Since we need the pci subsystem to init ibs we can't do this earlier: */
Expand Down
8 changes: 8 additions & 0 deletions arch/x86/kernel/cpu/perf_event_intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -1545,6 +1545,13 @@ static void intel_clovertown_quirks(void)
x86_pmu.pebs_constraints = NULL;
}

static void intel_sandybridge_quirks(void)
{
printk(KERN_WARNING "PEBS disabled due to CPU errata.\n");
x86_pmu.pebs = 0;
x86_pmu.pebs_constraints = NULL;
}

__init int intel_pmu_init(void)
{
union cpuid10_edx edx;
Expand Down Expand Up @@ -1694,6 +1701,7 @@ __init int intel_pmu_init(void)
break;

case 42: /* SandyBridge */
x86_pmu.quirks = intel_sandybridge_quirks;
case 45: /* SandyBridge, "Romely-EP" */
memcpy(hw_cache_event_ids, snb_hw_cache_event_ids,
sizeof(hw_cache_event_ids));
Expand Down
6 changes: 5 additions & 1 deletion arch/x86/kernel/cpu/perf_event_intel_ds.c
Original file line number Diff line number Diff line change
Expand Up @@ -493,6 +493,7 @@ static int intel_pmu_pebs_fixup_ip(struct pt_regs *regs)
unsigned long from = cpuc->lbr_entries[0].from;
unsigned long old_to, to = cpuc->lbr_entries[0].to;
unsigned long ip = regs->ip;
int is_64bit = 0;

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

kernel_insn_init(&insn, kaddr);
#ifdef CONFIG_X86_64
is_64bit = kernel_ip(to) || !test_thread_flag(TIF_IA32);
#endif
insn_init(&insn, kaddr, is_64bit);
insn_get_length(&insn);
to += insn.length;
} while (to < ip);
Expand Down
2 changes: 1 addition & 1 deletion arch/x86/kernel/cpu/perf_event_p4.c
Original file line number Diff line number Diff line change
Expand Up @@ -1268,7 +1268,7 @@ static int p4_pmu_schedule_events(struct cpu_hw_events *cpuc, int n, int *assign
}

done:
return num ? -ENOSPC : 0;
return num ? -EINVAL : 0;
}

static __initconst const struct x86_pmu p4_pmu = {
Expand Down
7 changes: 5 additions & 2 deletions arch/x86/oprofile/init.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ extern int op_nmi_timer_init(struct oprofile_operations *ops);
extern void op_nmi_exit(void);
extern void x86_backtrace(struct pt_regs * const regs, unsigned int depth);

static int nmi_timer;

int __init oprofile_arch_init(struct oprofile_operations *ops)
{
Expand All @@ -31,8 +32,9 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
#ifdef CONFIG_X86_LOCAL_APIC
ret = op_nmi_init(ops);
#endif
nmi_timer = (ret != 0);
#ifdef CONFIG_X86_IO_APIC
if (ret < 0)
if (nmi_timer)
ret = op_nmi_timer_init(ops);
#endif
ops->backtrace = x86_backtrace;
Expand All @@ -44,6 +46,7 @@ int __init oprofile_arch_init(struct oprofile_operations *ops)
void oprofile_arch_exit(void)
{
#ifdef CONFIG_X86_LOCAL_APIC
op_nmi_exit();
if (!nmi_timer)
op_nmi_exit();
#endif
}
29 changes: 24 additions & 5 deletions drivers/oprofile/oprof.c
Original file line number Diff line number Diff line change
Expand Up @@ -239,26 +239,45 @@ int oprofile_set_ulong(unsigned long *addr, unsigned long val)
return err;
}

static int timer_mode;

static int __init oprofile_init(void)
{
int err;

/* always init architecture to setup backtrace support */
err = oprofile_arch_init(&oprofile_ops);
if (err < 0 || timer) {
printk(KERN_INFO "oprofile: using timer interrupt.\n");

timer_mode = err || timer; /* fall back to timer mode on errors */
if (timer_mode) {
if (!err)
oprofile_arch_exit();
err = oprofile_timer_init(&oprofile_ops);
if (err)
return err;
}
return oprofilefs_register();

err = oprofilefs_register();
if (!err)
return 0;

/* failed */
if (timer_mode)
oprofile_timer_exit();
else
oprofile_arch_exit();

return err;
}


static void __exit oprofile_exit(void)
{
oprofile_timer_exit();
oprofilefs_unregister();
oprofile_arch_exit();
if (timer_mode)
oprofile_timer_exit();
else
oprofile_arch_exit();
}


Expand Down
1 change: 1 addition & 0 deletions drivers/oprofile/timer_int.c
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ int oprofile_timer_init(struct oprofile_operations *ops)
ops->start = oprofile_hrtimer_start;
ops->stop = oprofile_hrtimer_stop;
ops->cpu_type = "timer";
printk(KERN_INFO "oprofile: using timer interrupt.\n");
return 0;
}

Expand Down
1 change: 1 addition & 0 deletions include/linux/perf_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -822,6 +822,7 @@ struct perf_event {
int mmap_locked;
struct user_struct *mmap_user;
struct ring_buffer *rb;
struct list_head rb_entry;

/* poll related */
wait_queue_head_t waitq;
Expand Down
Loading

0 comments on commit 232ea34

Please sign in to comment.