Patches contributed by Eötvös Lorand University
commit 79202ba9ff8cf570a75596f42e011167734d1c4b
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue May 26 08:10:00 2009 +0200
perf_counter, x86: Fix APIC NMI programming
My Nehalem box locks up in certain situations (with an
always-asserted NMI causing a lockup) if the PMU LVT
entry is programmed between NMI and IRQ mode with a
high frequency.
Standardize exlusively on NMIs instead.
[ Impact: fix lockup ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Mike Galbraith <efault@gmx.de>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index 189bf9d7cdab..ece3813c7a3c 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -285,14 +285,10 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
hwc->config |= ARCH_PERFMON_EVENTSEL_OS;
/*
- * If privileged enough, allow NMI events:
+ * Use NMI events all the time:
*/
- hwc->nmi = 0;
- if (hw_event->nmi) {
- if (sysctl_perf_counter_priv && !capable(CAP_SYS_ADMIN))
- return -EACCES;
- hwc->nmi = 1;
- }
+ hwc->nmi = 1;
+ hw_event->nmi = 1;
if (!hwc->irq_period)
hwc->irq_period = x86_pmu.max_period;
@@ -553,9 +549,6 @@ fixed_mode_idx(struct perf_counter *counter, struct hw_perf_counter *hwc)
if (!x86_pmu.num_counters_fixed)
return -1;
- if (unlikely(hwc->nmi))
- return -1;
-
event = hwc->config & ARCH_PERFMON_EVENT_MASK;
if (unlikely(event == x86_pmu.event_map(PERF_COUNT_INSTRUCTIONS)))
@@ -806,9 +799,6 @@ static int amd_pmu_handle_irq(struct pt_regs *regs, int nmi)
counter = cpuc->counters[idx];
hwc = &counter->hw;
- if (counter->hw_event.nmi != nmi)
- continue;
-
val = x86_perf_counter_update(counter, hwc, idx);
if (val & (1ULL << (x86_pmu.counter_bits - 1)))
continue;
commit 0127c3ea082ee9f1034789b978dfc7fd83254617
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 25 22:03:26 2009 +0200
perf_counter: fix warning & lockup
- remove bogus warning
- fix wakeup from NMI path lockup
- also fix up whitespace noise in perf_counter.h
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <20090525153931.703093461@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index e3a7585d3e43..2b16ed37b74c 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -73,7 +73,7 @@ enum sw_event_ids {
PERF_SW_EVENTS_MAX = 7,
};
-#define __PERF_COUNTER_MASK(name) \
+#define __PERF_COUNTER_MASK(name) \
(((1ULL << PERF_COUNTER_##name##_BITS) - 1) << \
PERF_COUNTER_##name##_SHIFT)
@@ -98,14 +98,14 @@ enum sw_event_ids {
* in the overflow packets.
*/
enum perf_counter_record_format {
- PERF_RECORD_IP = 1U << 0,
- PERF_RECORD_TID = 1U << 1,
- PERF_RECORD_TIME = 1U << 2,
- PERF_RECORD_ADDR = 1U << 3,
- PERF_RECORD_GROUP = 1U << 4,
- PERF_RECORD_CALLCHAIN = 1U << 5,
- PERF_RECORD_CONFIG = 1U << 6,
- PERF_RECORD_CPU = 1U << 7,
+ PERF_RECORD_IP = 1U << 0,
+ PERF_RECORD_TID = 1U << 1,
+ PERF_RECORD_TIME = 1U << 2,
+ PERF_RECORD_ADDR = 1U << 3,
+ PERF_RECORD_GROUP = 1U << 4,
+ PERF_RECORD_CALLCHAIN = 1U << 5,
+ PERF_RECORD_CONFIG = 1U << 6,
+ PERF_RECORD_CPU = 1U << 7,
};
/*
@@ -235,13 +235,13 @@ enum perf_event_type {
* correlate userspace IPs to code. They have the following structure:
*
* struct {
- * struct perf_event_header header;
+ * struct perf_event_header header;
*
- * u32 pid, tid;
- * u64 addr;
- * u64 len;
- * u64 pgoff;
- * char filename[];
+ * u32 pid, tid;
+ * u64 addr;
+ * u64 len;
+ * u64 pgoff;
+ * char filename[];
* };
*/
PERF_EVENT_MMAP = 1,
@@ -249,27 +249,27 @@ enum perf_event_type {
/*
* struct {
- * struct perf_event_header header;
+ * struct perf_event_header header;
*
- * u32 pid, tid;
- * char comm[];
+ * u32 pid, tid;
+ * char comm[];
* };
*/
PERF_EVENT_COMM = 3,
/*
* struct {
- * struct perf_event_header header;
- * u64 time;
- * u64 irq_period;
+ * struct perf_event_header header;
+ * u64 time;
+ * u64 irq_period;
* };
*/
PERF_EVENT_PERIOD = 4,
/*
* struct {
- * struct perf_event_header header;
- * u64 time;
+ * struct perf_event_header header;
+ * u64 time;
* };
*/
PERF_EVENT_THROTTLE = 5,
@@ -280,23 +280,23 @@ enum perf_event_type {
* will be PERF_RECORD_*
*
* struct {
- * struct perf_event_header header;
+ * struct perf_event_header header;
*
- * { u64 ip; } && PERF_RECORD_IP
- * { u32 pid, tid; } && PERF_RECORD_TID
- * { u64 time; } && PERF_RECORD_TIME
- * { u64 addr; } && PERF_RECORD_ADDR
- * { u64 config; } && PERF_RECORD_CONFIG
- * { u32 cpu, res; } && PERF_RECORD_CPU
+ * { u64 ip; } && PERF_RECORD_IP
+ * { u32 pid, tid; } && PERF_RECORD_TID
+ * { u64 time; } && PERF_RECORD_TIME
+ * { u64 addr; } && PERF_RECORD_ADDR
+ * { u64 config; } && PERF_RECORD_CONFIG
+ * { u32 cpu, res; } && PERF_RECORD_CPU
*
- * { u64 nr;
- * { u64 event, val; } cnt[nr]; } && PERF_RECORD_GROUP
+ * { u64 nr;
+ * { u64 event, val; } cnt[nr]; } && PERF_RECORD_GROUP
*
- * { u16 nr,
- * hv,
- * kernel,
- * user;
- * u64 ips[nr]; } && PERF_RECORD_CALLCHAIN
+ * { u16 nr,
+ * hv,
+ * kernel,
+ * user;
+ * u64 ips[nr]; } && PERF_RECORD_CALLCHAIN
* };
*/
};
@@ -406,7 +406,7 @@ struct perf_mmap_data {
atomic_t wakeup; /* needs a wakeup */
struct perf_counter_mmap_page *user_page;
- void *data_pages[0];
+ void *data_pages[0];
};
struct perf_pending_entry {
@@ -422,7 +422,7 @@ struct perf_counter {
struct list_head list_entry;
struct list_head event_entry;
struct list_head sibling_list;
- int nr_siblings;
+ int nr_siblings;
struct perf_counter *group_leader;
const struct pmu *pmu;
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index ec9c4007a7f9..070f92d3232a 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -2576,7 +2576,7 @@ static void perf_log_throttle(struct perf_counter *counter, int enable)
.time = sched_clock(),
};
- ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 0, 0);
+ ret = perf_output_begin(&handle, counter, sizeof(throttle_event), 1, 0);
if (ret)
return;
@@ -3449,8 +3449,6 @@ void perf_counter_exit_task(struct task_struct *child)
struct perf_counter_context *child_ctx;
unsigned long flags;
- WARN_ON_ONCE(child != current);
-
child_ctx = child->perf_counter_ctxp;
if (likely(!child_ctx))
commit 53b441a565bf4036ab49c8ea04c5ad06ace7dd6b
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 25 21:41:28 2009 +0200
Revert "perf_counter, x86: speed up the scheduling fast-path"
This reverts commit b68f1d2e7aa21029d73c7d453a8046e95d351740.
It is causing problems (stuck/stuttering profiling) - when mixed
NMI and non-NMI counters are used.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
LKML-Reference: <20090525153931.703093461@chello.nl>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index c4b543d1a86f..189bf9d7cdab 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -293,7 +293,6 @@ static int __hw_perf_counter_init(struct perf_counter *counter)
return -EACCES;
hwc->nmi = 1;
}
- perf_counters_lapic_init(hwc->nmi);
if (!hwc->irq_period)
hwc->irq_period = x86_pmu.max_period;
@@ -612,6 +611,8 @@ static int x86_pmu_enable(struct perf_counter *counter)
hwc->counter_base = x86_pmu.perfctr;
}
+ perf_counters_lapic_init(hwc->nmi);
+
x86_pmu.disable(hwc, idx);
cpuc->counters[idx] = counter;
@@ -1037,7 +1038,7 @@ void __init init_hw_perf_counters(void)
pr_info("... counter mask: %016Lx\n", perf_counter_mask);
- perf_counters_lapic_init(1);
+ perf_counters_lapic_init(0);
register_die_notifier(&perf_counter_nmi_notifier);
}
commit d3f4b3855ba87caff8f35e738c7e7e3bad0a6ab1
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 25 14:40:01 2009 +0200
perf stat: flip around ':k' and ':u' flags
This output:
$ perf stat -e 0:1:k -e 0:1:u ./hello
Performance counter stats for './hello':
140131 instructions (events)
1906968 instructions (events)
Is quite confusing - as :k means "user instructions", :u means
"kernel instructions".
Flip them around - as the 'exclude' property is not intuitive in
the flag naming.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/builtin-stat.c b/Documentation/perf_counter/builtin-stat.c
index 8ae01d51f291..88c70be99031 100644
--- a/Documentation/perf_counter/builtin-stat.c
+++ b/Documentation/perf_counter/builtin-stat.c
@@ -266,9 +266,9 @@ static __u64 match_event_symbols(char *str)
switch (sscanf(str, "%d:%llu:%2s", &type, &id, mask_str)) {
case 3:
- if (strchr(mask_str, 'u'))
- event_mask[nr_counters] |= EVENT_MASK_USER;
if (strchr(mask_str, 'k'))
+ event_mask[nr_counters] |= EVENT_MASK_USER;
+ if (strchr(mask_str, 'u'))
event_mask[nr_counters] |= EVENT_MASK_KERNEL;
case 2:
return EID(type, id);
commit e4cbb4e3ac8b09fdb11e39e5a5611bfab0a7cd1a
Author: Ingo Molnar <mingo@elte.hu>
Date: Tue May 19 15:50:30 2009 +0200
perf_counter: Move child perfcounter init to after scheduler init
Initialize a task's perfcounters (inherit from parent, etc.) after
the child task's scheduler fields have been initialized already.
[ Impact: cleanup ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/kernel/fork.c b/kernel/fork.c
index e72a09f5355b..675e01e9072a 100644
--- a/kernel/fork.c
+++ b/kernel/fork.c
@@ -984,7 +984,6 @@ static struct task_struct *copy_process(unsigned long clone_flags,
goto fork_out;
rt_mutex_init_task(p);
- perf_counter_init_task(p);
#ifdef CONFIG_PROVE_LOCKING
DEBUG_LOCKS_WARN_ON(!p->hardirqs_enabled);
@@ -1096,6 +1095,7 @@ static struct task_struct *copy_process(unsigned long clone_flags,
/* Perform scheduler related setup. Assign this task to a CPU. */
sched_fork(p, clone_flags);
+ perf_counter_init_task(p);
if ((retval = audit_alloc(p)))
goto bad_fork_cleanup_policy;
commit 85a9f9200226ddffc2ea50dae6a8df04c033ecd4
Author: Ingo Molnar <mingo@elte.hu>
Date: Mon May 25 09:59:50 2009 +0200
perf_counter tools: increase limits, fix
NR_CPUS and NR_COUNTERS goes up quadratic ... 1024x4096 was far
too ambitious upper limit - go for 256x256 which is still plenty.
[ Impact: reduce perf tool memory consumption ]
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/perf.h b/Documentation/perf_counter/perf.h
index a517683fc661..5a2520bb7e55 100644
--- a/Documentation/perf_counter/perf.h
+++ b/Documentation/perf_counter/perf.h
@@ -61,8 +61,8 @@ sys_perf_counter_open(struct perf_counter_hw_event *hw_event_uptr,
group_fd, flags);
}
-#define MAX_COUNTERS 1024
-#define MAX_NR_CPUS 4096
+#define MAX_COUNTERS 256
+#define MAX_NR_CPUS 256
#define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id))
commit a3862d3f814ce7dfca9eed56ac23d29db3aee8d5
Author: Ingo Molnar <mingo@elte.hu>
Date: Sun May 24 09:02:37 2009 +0200
perf_counter: Increase mmap limit
In a default 'perf top' run the tool will create a counter for
each online CPU. With enough CPUs this will eventually exhaust
the default limit.
So scale it up with the number of online CPUs.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: John Kacur <jkacur@redhat.com>
Cc: Mike Galbraith <efault@gmx.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index cb4062559b47..6cdf8248eda2 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -1704,6 +1704,12 @@ static int perf_mmap(struct file *file, struct vm_area_struct *vma)
user_extra = nr_pages + 1;
user_lock_limit = sysctl_perf_counter_mlock >> (PAGE_SHIFT - 10);
+
+ /*
+ * Increase the limit linearly with more CPUs:
+ */
+ user_lock_limit *= num_online_cpus();
+
user_locked = atomic_long_read(&user->locked_vm) + user_extra;
extra = 0;
commit c6eb13847ba081552d2af644219bddeff7110caf
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri May 22 18:18:28 2009 +0200
perf_counter tools: increase limits
I tried to run with 300 active counters and the tools bailed out
because our limit was at 64. So increase the counter limit to 1024
and the CPU limit to 4096.
Cc: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/Documentation/perf_counter/perf.h b/Documentation/perf_counter/perf.h
index 6fa3656399f4..81a737444c8f 100644
--- a/Documentation/perf_counter/perf.h
+++ b/Documentation/perf_counter/perf.h
@@ -54,8 +54,8 @@ sys_perf_counter_open(struct perf_counter_hw_event *hw_event_uptr,
group_fd, flags);
}
-#define MAX_COUNTERS 64
-#define MAX_NR_CPUS 256
+#define MAX_COUNTERS 1024
+#define MAX_NR_CPUS 4096
#define EID(type, id) (((__u64)(type) << PERF_COUNTER_TYPE_SHIFT) | (id))
commit 910431c7f2e963017d767b29c80ae706421e569f
Author: Ingo Molnar <mingo@elte.hu>
Date: Fri May 22 12:32:15 2009 +0200
perf_counter: fix !PERF_COUNTERS build failure
Update the !CONFIG_PERF_COUNTERS prototype too, for
perf_counter_task_sched_out().
[ Impact: build fix ]
Signed-off-by: Paul Mackerras <paulus@samba.org>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Marcelo Tosatti <mtosatti@redhat.com>
Cc: Arnaldo Carvalho de Melo <acme@redhat.com>
LKML-Reference: <18966.10666.517218.332164@cargo.ozlabs.ibm.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/include/linux/perf_counter.h b/include/linux/perf_counter.h
index 4cae01a50450..2eedae8498d3 100644
--- a/include/linux/perf_counter.h
+++ b/include/linux/perf_counter.h
@@ -625,7 +625,8 @@ extern void perf_counter_init(void);
static inline void
perf_counter_task_sched_in(struct task_struct *task, int cpu) { }
static inline void
-perf_counter_task_sched_out(struct task_struct *task, int cpu) { }
+perf_counter_task_sched_out(struct task_struct *task,
+ struct task_struct *next, int cpu) { }
static inline void
perf_counter_task_tick(struct task_struct *task, int cpu) { }
static inline void perf_counter_init_task(struct task_struct *child) { }
commit 34adc8062227f41b04ade0ff3fbd1dbe3002669e
Author: Ingo Molnar <mingo@elte.hu>
Date: Wed May 20 20:13:28 2009 +0200
perf_counter: Fix context removal deadlock
Disable the PMU globally before removing a counter from a
context. This fixes the following lockup:
[22081.741922] ------------[ cut here ]------------
[22081.746668] WARNING: at arch/x86/kernel/cpu/perf_counter.c:803 intel_pmu_handle_irq+0x9b/0x24e()
[22081.755624] Hardware name: X8DTN
[22081.758903] perfcounters: irq loop stuck!
[22081.762985] Modules linked in:
[22081.766136] Pid: 11082, comm: perf Not tainted 2.6.30-rc6-tip #226
[22081.772432] Call Trace:
[22081.774940] <NMI> [<ffffffff81019aed>] ? intel_pmu_handle_irq+0x9b/0x24e
[22081.781993] [<ffffffff81019aed>] ? intel_pmu_handle_irq+0x9b/0x24e
[22081.788368] [<ffffffff8104505c>] ? warn_slowpath_common+0x77/0xa3
[22081.794649] [<ffffffff810450d3>] ? warn_slowpath_fmt+0x40/0x45
[22081.800696] [<ffffffff81019aed>] ? intel_pmu_handle_irq+0x9b/0x24e
[22081.807080] [<ffffffff814d1a72>] ? perf_counter_nmi_handler+0x3f/0x4a
[22081.813751] [<ffffffff814d2d09>] ? notifier_call_chain+0x58/0x86
[22081.819951] [<ffffffff8105b250>] ? notify_die+0x2d/0x32
[22081.825392] [<ffffffff814d1414>] ? do_nmi+0x8e/0x242
[22081.830538] [<ffffffff814d0f0a>] ? nmi+0x1a/0x20
[22081.835342] [<ffffffff8117e102>] ? selinux_file_free_security+0x0/0x1a
[22081.842105] [<ffffffff81018793>] ? x86_pmu_disable_counter+0x15/0x41
[22081.848673] <<EOE>> [<ffffffff81018f3d>] ? x86_pmu_disable+0x86/0x103
[22081.855512] [<ffffffff8108fedd>] ? __perf_counter_remove_from_context+0x0/0xfe
[22081.862926] [<ffffffff8108fcbc>] ? counter_sched_out+0x30/0xce
[22081.868909] [<ffffffff8108ff36>] ? __perf_counter_remove_from_context+0x59/0xfe
[22081.876382] [<ffffffff8106808a>] ? smp_call_function_single+0x6c/0xe6
[22081.882955] [<ffffffff81091b96>] ? perf_release+0x86/0x14c
[22081.888600] [<ffffffff810c4c84>] ? __fput+0xe7/0x195
[22081.893718] [<ffffffff810c213e>] ? filp_close+0x5b/0x62
[22081.899107] [<ffffffff81046a70>] ? put_files_struct+0x64/0xc2
[22081.905031] [<ffffffff8104841a>] ? do_exit+0x1e2/0x6ef
[22081.910360] [<ffffffff814d0a60>] ? _spin_lock_irqsave+0x9/0xe
[22081.916292] [<ffffffff8104898e>] ? do_group_exit+0x67/0x93
[22081.921953] [<ffffffff810489cc>] ? sys_exit_group+0x12/0x16
[22081.927759] [<ffffffff8100baab>] ? system_call_fastpath+0x16/0x1b
[22081.934076] ---[ end trace 3a3936ce3e1b4505 ]---
And could potentially also fix the lockup reported by Marcelo Tosatti.
Also, print more debug info in case of a detected lockup.
[ Impact: fix lockup ]
Reported-by: Marcelo Tosatti <mtosatti@redhat.com>
Acked-by: Peter Zijlstra <a.p.zijlstra@chello.nl>
Cc: Paul Mackerras <paulus@samba.org>
Cc: Corey Ashford <cjashfor@linux.vnet.ibm.com>
Cc: Thomas Gleixner <tglx@linutronix.de>
LKML-Reference: <new-submission>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
diff --git a/arch/x86/kernel/cpu/perf_counter.c b/arch/x86/kernel/cpu/perf_counter.c
index c109819c2cb9..6cc1660db8d6 100644
--- a/arch/x86/kernel/cpu/perf_counter.c
+++ b/arch/x86/kernel/cpu/perf_counter.c
@@ -740,6 +740,7 @@ static int intel_pmu_handle_irq(struct pt_regs *regs, int nmi)
again:
if (++loops > 100) {
WARN_ONCE(1, "perfcounters: irq loop stuck!\n");
+ perf_counter_print_debug();
return 1;
}
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index 69d4de815963..08584c16049f 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -208,18 +208,17 @@ static void __perf_counter_remove_from_context(void *info)
return;
spin_lock_irqsave(&ctx->lock, flags);
+ /*
+ * Protect the list operation against NMI by disabling the
+ * counters on a global level.
+ */
+ perf_disable();
counter_sched_out(counter, cpuctx, ctx);
counter->task = NULL;
- /*
- * Protect the list operation against NMI by disabling the
- * counters on a global level. NOP for non NMI based counters.
- */
- perf_disable();
list_del_counter(counter, ctx);
- perf_enable();
if (!ctx->task) {
/*
@@ -231,6 +230,7 @@ static void __perf_counter_remove_from_context(void *info)
perf_max_counters - perf_reserved_percpu);
}
+ perf_enable();
spin_unlock_irqrestore(&ctx->lock, flags);
}