linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts
@ 2014-09-08 18:26 Stephen Boyd
  2014-09-09 11:39 ` Will Deacon
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Boyd @ 2014-09-08 18:26 UTC (permalink / raw)
  To: Will Deacon; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Rob Clark

Rob Clark reports a sleeping while atomic bug when using perf.

BUG: sleeping function called from invalid context at ../kernel/locking/mutex.c:583
in_atomic(): 1, irqs_disabled(): 128, pid: 0, name: swapper/0
------------[ cut here ]------------
WARNING: CPU: 2 PID: 4828 at ../kernel/locking/mutex.c:479 mutex_lock_nested+0x3a0/0x3e8()
DEBUG_LOCKS_WARN_ON(in_interrupt())
Modules linked in:
CPU: 2 PID: 4828 Comm: Xorg.bin Tainted: G        W      3.17.0-rc3-00234-gd535c45-dirty #819
[<c0216690>] (unwind_backtrace) from [<c0212174>] (show_stack+0x10/0x14)
[<c0212174>] (show_stack) from [<c0867cc0>] (dump_stack+0x98/0xb8)
[<c0867cc0>] (dump_stack) from [<c02492a4>] (warn_slowpath_common+0x70/0x8c)
[<c02492a4>] (warn_slowpath_common) from [<c02492f0>] (warn_slowpath_fmt+0x30/0x40)
[<c02492f0>] (warn_slowpath_fmt) from [<c086a3f8>] (mutex_lock_nested+0x3a0/0x3e8)
[<c086a3f8>] (mutex_lock_nested) from [<c0294d08>] (irq_find_host+0x20/0x9c)
[<c0294d08>] (irq_find_host) from [<c0769d50>] (of_irq_get+0x28/0x48)
[<c0769d50>] (of_irq_get) from [<c057d104>] (platform_get_irq+0x1c/0x8c)
[<c057d104>] (platform_get_irq) from [<c021a06c>] (cpu_pmu_enable_percpu_irq+0x14/0x38)
[<c021a06c>] (cpu_pmu_enable_percpu_irq) from [<c02b1634>] (flush_smp_call_function_queue+0x88/0x178)
[<c02b1634>] (flush_smp_call_function_queue) from [<c0214dc0>] (handle_IPI+0x88/0x160)
[<c0214dc0>] (handle_IPI) from [<c0208930>] (gic_handle_irq+0x64/0x68)
[<c0208930>] (gic_handle_irq) from [<c0212d04>] (__irq_svc+0x44/0x5c)
Exception stack(0xe63ddea0 to 0xe63ddee8)
dea0: 00000001 00000001 00000000 c2f3b200 c16db380 c032d4a0 e63ddf40 60010013
dec0: 00000000 001fbfd4 00000100 00000000 00000001 e63ddee8 c0284770 c02a2e30
dee0: 20010013 ffffffff
[<c0212d04>] (__irq_svc) from [<c02a2e30>] (ktime_get_ts64+0x1c8/0x200)
[<c02a2e30>] (ktime_get_ts64) from [<c032d4a0>] (poll_select_set_timeout+0x60/0xa8)
[<c032d4a0>] (poll_select_set_timeout) from [<c032df64>] (SyS_select+0xa8/0x118)
[<c032df64>] (SyS_select) from [<c020e8e0>] (ret_fast_syscall+0x0/0x48)
---[ end trace 0bb583b46342da6f ]---
INFO: lockdep is turned off.

We don't really need to get the platform irq again when we're
enabling or disabling the per-cpu irq. Instead we can pass along
the two pieces of data we need to the enable/disable functions.
This should be slightly more efficient and also fix the
scheduling while atomic bug.

Reported-by: Rob Clark <robdclark@gmail.com>
Fixes: bbd64559376f "ARM: perf: support percpu irqs for the CPU PMU"
Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>
---
 arch/arm/kernel/perf_event_cpu.c | 27 +++++++++++++++++++--------
 1 file changed, 19 insertions(+), 8 deletions(-)

diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index e6a6edbec613..1f24b47cd81e 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -74,11 +74,16 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 	return this_cpu_ptr(&cpu_hw_events);
 }
 
+struct pmu_enable {
+	struct arm_pmu *pmu;
+	int irq;
+};
+
 static void cpu_pmu_enable_percpu_irq(void *data)
 {
-	struct arm_pmu *cpu_pmu = data;
-	struct platform_device *pmu_device = cpu_pmu->plat_device;
-	int irq = platform_get_irq(pmu_device, 0);
+	struct pmu_enable *pmu_enable = data;
+	struct arm_pmu *cpu_pmu = pmu_enable->pmu;
+	int irq = pmu_enable->irq;
 
 	enable_percpu_irq(irq, IRQ_TYPE_NONE);
 	cpumask_set_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
@@ -86,9 +91,9 @@ static void cpu_pmu_enable_percpu_irq(void *data)
 
 static void cpu_pmu_disable_percpu_irq(void *data)
 {
-	struct arm_pmu *cpu_pmu = data;
-	struct platform_device *pmu_device = cpu_pmu->plat_device;
-	int irq = platform_get_irq(pmu_device, 0);
+	struct pmu_enable *pmu_enable = data;
+	struct arm_pmu *cpu_pmu = pmu_enable->pmu;
+	int irq = pmu_enable->irq;
 
 	cpumask_clear_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
 	disable_percpu_irq(irq);
@@ -98,12 +103,15 @@ static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 {
 	int i, irq, irqs;
 	struct platform_device *pmu_device = cpu_pmu->plat_device;
+	struct pmu_enable pmu_enable;
 
 	irqs = min(pmu_device->num_resources, num_possible_cpus());
 
 	irq = platform_get_irq(pmu_device, 0);
 	if (irq >= 0 && irq_is_percpu(irq)) {
-		on_each_cpu(cpu_pmu_disable_percpu_irq, cpu_pmu, 1);
+		pmu_enable.pmu = cpu_pmu;
+		pmu_enable.irq = irq;
+		on_each_cpu(cpu_pmu_disable_percpu_irq, &pmu_enable, 1);
 		free_percpu_irq(irq, &percpu_pmu);
 	} else {
 		for (i = 0; i < irqs; ++i) {
@@ -120,6 +128,7 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 {
 	int i, err, irq, irqs;
 	struct platform_device *pmu_device = cpu_pmu->plat_device;
+	struct pmu_enable pmu_enable;
 
 	if (!pmu_device)
 		return -ENODEV;
@@ -138,7 +147,9 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 				irq);
 			return err;
 		}
-		on_each_cpu(cpu_pmu_enable_percpu_irq, cpu_pmu, 1);
+		pmu_enable.pmu = cpu_pmu;
+		pmu_enable.irq = irq;
+		on_each_cpu(cpu_pmu_enable_percpu_irq, &pmu_enable, 1);
 	} else {
 		for (i = 0; i < irqs; ++i) {
 			err = 0;
-- 
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts
  2014-09-08 18:26 [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts Stephen Boyd
@ 2014-09-09 11:39 ` Will Deacon
  2014-09-09 17:54   ` Stephen Boyd
  0 siblings, 1 reply; 5+ messages in thread
From: Will Deacon @ 2014-09-09 11:39 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Rob Clark

Hi Stephen,

On Mon, Sep 08, 2014 at 07:26:54PM +0100, Stephen Boyd wrote:
> Rob Clark reports a sleeping while atomic bug when using perf.
> 
> BUG: sleeping function called from invalid context at ../kernel/locking/mutex.c:583
> in_atomic(): 1, irqs_disabled(): 128, pid: 0, name: swapper/0
> ------------[ cut here ]------------
> WARNING: CPU: 2 PID: 4828 at ../kernel/locking/mutex.c:479 mutex_lock_nested+0x3a0/0x3e8()
> DEBUG_LOCKS_WARN_ON(in_interrupt())
> Modules linked in:
> CPU: 2 PID: 4828 Comm: Xorg.bin Tainted: G        W      3.17.0-rc3-00234-gd535c45-dirty #819
> [<c0216690>] (unwind_backtrace) from [<c0212174>] (show_stack+0x10/0x14)
> [<c0212174>] (show_stack) from [<c0867cc0>] (dump_stack+0x98/0xb8)
> [<c0867cc0>] (dump_stack) from [<c02492a4>] (warn_slowpath_common+0x70/0x8c)
> [<c02492a4>] (warn_slowpath_common) from [<c02492f0>] (warn_slowpath_fmt+0x30/0x40)
> [<c02492f0>] (warn_slowpath_fmt) from [<c086a3f8>] (mutex_lock_nested+0x3a0/0x3e8)
> [<c086a3f8>] (mutex_lock_nested) from [<c0294d08>] (irq_find_host+0x20/0x9c)
> [<c0294d08>] (irq_find_host) from [<c0769d50>] (of_irq_get+0x28/0x48)
> [<c0769d50>] (of_irq_get) from [<c057d104>] (platform_get_irq+0x1c/0x8c)
> [<c057d104>] (platform_get_irq) from [<c021a06c>] (cpu_pmu_enable_percpu_irq+0x14/0x38)
> [<c021a06c>] (cpu_pmu_enable_percpu_irq) from [<c02b1634>] (flush_smp_call_function_queue+0x88/0x178)
> [<c02b1634>] (flush_smp_call_function_queue) from [<c0214dc0>] (handle_IPI+0x88/0x160)
> [<c0214dc0>] (handle_IPI) from [<c0208930>] (gic_handle_irq+0x64/0x68)
> [<c0208930>] (gic_handle_irq) from [<c0212d04>] (__irq_svc+0x44/0x5c)
> Exception stack(0xe63ddea0 to 0xe63ddee8)
> dea0: 00000001 00000001 00000000 c2f3b200 c16db380 c032d4a0 e63ddf40 60010013
> dec0: 00000000 001fbfd4 00000100 00000000 00000001 e63ddee8 c0284770 c02a2e30
> dee0: 20010013 ffffffff
> [<c0212d04>] (__irq_svc) from [<c02a2e30>] (ktime_get_ts64+0x1c8/0x200)
> [<c02a2e30>] (ktime_get_ts64) from [<c032d4a0>] (poll_select_set_timeout+0x60/0xa8)
> [<c032d4a0>] (poll_select_set_timeout) from [<c032df64>] (SyS_select+0xa8/0x118)
> [<c032df64>] (SyS_select) from [<c020e8e0>] (ret_fast_syscall+0x0/0x48)
> ---[ end trace 0bb583b46342da6f ]---
> INFO: lockdep is turned off.
> 
> We don't really need to get the platform irq again when we're
> enabling or disabling the per-cpu irq. Instead we can pass along
> the two pieces of data we need to the enable/disable functions.
> This should be slightly more efficient and also fix the
> scheduling while atomic bug.
> 
> Reported-by: Rob Clark <robdclark@gmail.com>
> Fixes: bbd64559376f "ARM: perf: support percpu irqs for the CPU PMU"
> Signed-off-by: Stephen Boyd <sboyd@codeaurora.org>

It's interesting that arm64 isn't affected by this problem, since we don't
update the active_irqs mask for PPIs there and consequently just pass the
irq instead of the cpu_pmu. I can't see why we actually need to update the
active_irqs mask for arch/arm/, so could we remove that and follow arm64's
lead instead? That would remove the need for a new struct definition too.

Will

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts
  2014-09-09 11:39 ` Will Deacon
@ 2014-09-09 17:54   ` Stephen Boyd
  2014-09-10 18:21     ` Will Deacon
  0 siblings, 1 reply; 5+ messages in thread
From: Stephen Boyd @ 2014-09-09 17:54 UTC (permalink / raw)
  To: Will Deacon; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Rob Clark

On 09/09/14 04:39, Will Deacon wrote:
> It's interesting that arm64 isn't affected by this problem, since we don't
> update the active_irqs mask for PPIs there and consequently just pass the
> irq instead of the cpu_pmu. I can't see why we actually need to update the
> active_irqs mask for arch/arm/, so could we remove that and follow arm64's
> lead instead? That would remove the need for a new struct definition too.
>

I guess you're saying that we don't need the active_irqs mask in the
percpu irq case? It looks like we still use it to determine when the
last CPU PMU has been disabled in the non-percpu case.

Here's the interdiff. Is there a reason arm64 casts data to an unsigned
int pointer when what's passed is an int pointer?

----8<-----

diff --git a/arch/arm/kernel/perf_event_cpu.c b/arch/arm/kernel/perf_event_cpu.c
index 1f24b47cd81e..4bf4cce759fe 100644
--- a/arch/arm/kernel/perf_event_cpu.c
+++ b/arch/arm/kernel/perf_event_cpu.c
@@ -74,28 +74,17 @@ static struct pmu_hw_events *cpu_pmu_get_cpu_events(void)
 	return this_cpu_ptr(&cpu_hw_events);
 }
 
-struct pmu_enable {
-	struct arm_pmu *pmu;
-	int irq;
-};
-
 static void cpu_pmu_enable_percpu_irq(void *data)
 {
-	struct pmu_enable *pmu_enable = data;
-	struct arm_pmu *cpu_pmu = pmu_enable->pmu;
-	int irq = pmu_enable->irq;
+	int irq = *(int *)data;
 
 	enable_percpu_irq(irq, IRQ_TYPE_NONE);
-	cpumask_set_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
 }
 
 static void cpu_pmu_disable_percpu_irq(void *data)
 {
-	struct pmu_enable *pmu_enable = data;
-	struct arm_pmu *cpu_pmu = pmu_enable->pmu;
-	int irq = pmu_enable->irq;
+	int irq = *(int *)data;
 
-	cpumask_clear_cpu(smp_processor_id(), &cpu_pmu->active_irqs);
 	disable_percpu_irq(irq);
 }
 
@@ -103,15 +92,12 @@ static void cpu_pmu_free_irq(struct arm_pmu *cpu_pmu)
 {
 	int i, irq, irqs;
 	struct platform_device *pmu_device = cpu_pmu->plat_device;
-	struct pmu_enable pmu_enable;
 
 	irqs = min(pmu_device->num_resources, num_possible_cpus());
 
 	irq = platform_get_irq(pmu_device, 0);
 	if (irq >= 0 && irq_is_percpu(irq)) {
-		pmu_enable.pmu = cpu_pmu;
-		pmu_enable.irq = irq;
-		on_each_cpu(cpu_pmu_disable_percpu_irq, &pmu_enable, 1);
+		on_each_cpu(cpu_pmu_disable_percpu_irq, &irq, 1);
 		free_percpu_irq(irq, &percpu_pmu);
 	} else {
 		for (i = 0; i < irqs; ++i) {
@@ -128,7 +114,6 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 {
 	int i, err, irq, irqs;
 	struct platform_device *pmu_device = cpu_pmu->plat_device;
-	struct pmu_enable pmu_enable;
 
 	if (!pmu_device)
 		return -ENODEV;
@@ -147,9 +132,7 @@ static int cpu_pmu_request_irq(struct arm_pmu *cpu_pmu, irq_handler_t handler)
 				irq);
 			return err;
 		}
-		pmu_enable.pmu = cpu_pmu;
-		pmu_enable.irq = irq;
-		on_each_cpu(cpu_pmu_enable_percpu_irq, &pmu_enable, 1);
+		on_each_cpu(cpu_pmu_enable_percpu_irq, &irq, 1);
 	} else {
 		for (i = 0; i < irqs; ++i) {
 			err = 0;


-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* Re: [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts
  2014-09-09 17:54   ` Stephen Boyd
@ 2014-09-10 18:21     ` Will Deacon
  2014-09-10 18:51       ` Stephen Boyd
  0 siblings, 1 reply; 5+ messages in thread
From: Will Deacon @ 2014-09-10 18:21 UTC (permalink / raw)
  To: Stephen Boyd; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Rob Clark

On Tue, Sep 09, 2014 at 06:54:45PM +0100, Stephen Boyd wrote:
> On 09/09/14 04:39, Will Deacon wrote:
> > It's interesting that arm64 isn't affected by this problem, since we don't
> > update the active_irqs mask for PPIs there and consequently just pass the
> > irq instead of the cpu_pmu. I can't see why we actually need to update the
> > active_irqs mask for arch/arm/, so could we remove that and follow arm64's
> > lead instead? That would remove the need for a new struct definition too.
> >
> 
> I guess you're saying that we don't need the active_irqs mask in the
> percpu irq case? It looks like we still use it to determine when the
> last CPU PMU has been disabled in the non-percpu case.

Correct.

> Here's the interdiff. Is there a reason arm64 casts data to an unsigned
> int pointer when what's passed is an int pointer?

There has to be a cast to something because data is a void *.
enable_percpu_irq takes an unsigned int, so I guess that's why it was
chosen. I'm not fussed either way.

Feel free to submit the full patch with my ack:

  Acked-by: Will Deacon <will.deacon@arm.com>

Will

^ permalink raw reply	[flat|nested] 5+ messages in thread

* Re: [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts
  2014-09-10 18:21     ` Will Deacon
@ 2014-09-10 18:51       ` Stephen Boyd
  0 siblings, 0 replies; 5+ messages in thread
From: Stephen Boyd @ 2014-09-10 18:51 UTC (permalink / raw)
  To: Will Deacon; +Cc: linux-kernel, linux-arm-msm, linux-arm-kernel, Rob Clark

On 09/10/14 11:21, Will Deacon wrote:
> On Tue, Sep 09, 2014 at 06:54:45PM +0100, Stephen Boyd wrote:
>
>> Here's the interdiff. Is there a reason arm64 casts data to an unsigned
>> int pointer when what's passed is an int pointer?
> There has to be a cast to something because data is a void *.
> enable_percpu_irq takes an unsigned int, so I guess that's why it was
> chosen. I'm not fussed either way.

Right, I'm just annoyed that what's passed in the void * is not an
unsigned int, it's an int. I agree that eventually we'll hand it to
enable_percpu_irq and there it will be implicitly casted to an unsigned
int so it really doesn't matter.

>
> Feel free to submit the full patch with my ack:
>
>   Acked-by: Will Deacon <will.deacon@arm.com>
>

Ok thanks.

-- 
Qualcomm Innovation Center, Inc. is a member of Code Aurora Forum,
hosted by The Linux Foundation


^ permalink raw reply	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2014-09-10 18:51 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-09-08 18:26 [PATCH] ARM: perf: Don't sleep while atomic when enabling per-cpu interrupts Stephen Boyd
2014-09-09 11:39 ` Will Deacon
2014-09-09 17:54   ` Stephen Boyd
2014-09-10 18:21     ` Will Deacon
2014-09-10 18:51       ` Stephen Boyd

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).