2012-05-23 19:57:52

by Pantelis Antoniou

[permalink] [raw]
Subject: [PATCH] [ARM] Unconditional call to smp_cross_call on UP crashes

omap2plus_defconfig builds with SMP & SMP_ON_UP set.
On beagle (which is UP) is_smp() returns false and we don't call
smp_init_cpus which in turn does not initialize smp_cross_call which
remains NULL.

When issuing a reboot we OOPS with a NULL dereference on stop smp_call.

Fixed by checking is_smp in smp_send_stop()

Restarting system.
Unable to handle kernel NULL pointer dereference at virtual address 00000000
pgd = dda50000
[00000000] *pgd=9e723831, *pte=00000000, *ppte=00000000
Internal error: Oops: 80000007 [#1] SMP ARM
Modules linked in:
CPU: 0 Not tainted (3.4.0-00001-gb15b046 #30)
PC is at 0x0
LR is at smp_send_stop+0x4c/0xe8
pc : [<00000000>] lr : [<c00188cc>] psr: 60000013
sp : de7b5e70 ip : 00000000 fp : 00000001
r10: 00000000 r9 : de7b4000 r8 : c07263d0
r7 : 00000000 r6 : c06e1294 r5 : 000f4240 r4 : de7b5e74
r3 : 00000000 r2 : 00000000 r1 : 00000006 r0 : de7b5e74
Flags: nZCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
Control: 10c5387d Table: 9da50019 DAC: 00000015
Process reboot (pid: 2229, stack limit = 0xde7b42f8)
Stack: (0xde7b5e70 to 0xde7b6000)
5e60: 00000000 00000000 00000000 01234567
5e80: de7b4000 c001475c 4321fedc c0052570 0000003e 00000000 c081db78 0000003e
5ea0: 00000001 00000002 00000002 c00891f0 00000002 dd5ba0ac 00000002 00000000
5ec0: dd5ba0ac de7b4000 c009eef4 de7b4000 c00f44dc de7b4000 c00f44dc 00000000
5ee0: c0c94d24 de7b4000 00000000 00000000 00000002 00000002 00000000 c00891f0
5f00: 00000002 00000000 00000000 c011286c 00000000 dd5ba060 60000013 00000000
5f20: dd688d8c 00000000 de7b4000 c06e20f8 dec14760 dec14750 de7b4000 c06e20f8
5f40: 00011f10 c01128a0 00000002 00000000 c011286c c00fa014 dd8c3180 de7b4000
5f60: c0013380 de508bc0 00000001 60000010 00000001 ef000000 00000001 c0089bfc
5f80: 00000000 00000001 00000004 00000058 00000000 00000001 00000004 00000058
5fa0: c0013428 c0013260 00000000 00000001 fee1dead 28121969 01234567 00000000
5fc0: 00000000 00000001 00000004 00000058 00000001 00000001 00000000 00000001
5fe0: b6e76200 beba4c90 00009210 b6e76218 60000010 fee1dead 00000000 00000000
[<c00188cc>] (smp_send_stop+0x4c/0xe8) from [<c001475c>] (machine_restart+0xc/0x54)
[<c001475c>] (machine_restart+0xc/0x54) from [<c0052570>] (sys_reboot+0x140/0x204)
[<c0052570>] (sys_reboot+0x140/0x204) from [<c0013260>] (ret_fast_syscall+0x0/0x3c)
Code: bad PC value
---[ end trace f5035e8726d1f51b ]---

Signed-off-by: Pantelis Antoniou <[email protected]>
Cc: [email protected]
---
arch/arm/kernel/smp.c | 4 ++++
1 files changed, 4 insertions(+), 0 deletions(-)

diff --git a/arch/arm/kernel/smp.c b/arch/arm/kernel/smp.c
index 8f46446..2a61335 100644
--- a/arch/arm/kernel/smp.c
+++ b/arch/arm/kernel/smp.c
@@ -588,6 +588,10 @@ void smp_send_stop(void)
unsigned long timeout;
struct cpumask mask;

+ /* make sure we don't bother if not SMP */
+ if (!is_smp())
+ return;
+
cpumask_copy(&mask, cpu_online_mask);
cpumask_clear_cpu(smp_processor_id(), &mask);
smp_cross_call(&mask, IPI_CPU_STOP);
--
1.7.1


2012-05-24 16:17:44

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH] [ARM] Unconditional call to smp_cross_call on UP crashes

On Thu, May 24, 2012 at 07:50:24PM +0000, Pantelis Antoniou wrote:
> omap2plus_defconfig builds with SMP & SMP_ON_UP set.
> On beagle (which is UP) is_smp() returns false and we don't call
> smp_init_cpus which in turn does not initialize smp_cross_call which
> remains NULL.
>
> When issuing a reboot we OOPS with a NULL dereference on stop smp_call.

I've been wondering whether we should make smp_cross_call() a no-op instead
by default, rather than a NULL pointer.

Alternatively, if may be well worth changing this to do:

if (!cpumask_empty(&mask))
smp_cross_call(&mask, IPI_CPU_STOP);

instead, so we avoid calling smp_cross_call() when we're on a SMP system
with only one CPU online. I like this approach better because it removes
a potential call into platform code which is inappropriate.

2012-05-24 16:56:08

by Pantelis Antoniou

[permalink] [raw]
Subject: Re: [PATCH] [ARM] Unconditional call to smp_cross_call on UP crashes

Hi Russell,

On May 24, 2012, at 7:17 PM, Russell King - ARM Linux wrote:

> On Thu, May 24, 2012 at 07:50:24PM +0000, Pantelis Antoniou wrote:
>> omap2plus_defconfig builds with SMP & SMP_ON_UP set.
>> On beagle (which is UP) is_smp() returns false and we don't call
>> smp_init_cpus which in turn does not initialize smp_cross_call which
>> remains NULL.
>>
>> When issuing a reboot we OOPS with a NULL dereference on stop smp_call.
>
> I've been wondering whether we should make smp_cross_call() a no-op instead
> by default, rather than a NULL pointer.
>
> Alternatively, if may be well worth changing this to do:
>
> if (!cpumask_empty(&mask))
> smp_cross_call(&mask, IPI_CPU_STOP);
>
> instead, so we avoid calling smp_cross_call() when we're on a SMP system
> with only one CPU online. I like this approach better because it removes
> a potential call into platform code which is inappropriate.

Both of these can work, and in fact have been tried.

I am partial on both to be honest. Have a default no-op function for smp_cross_call()
and guard with cpumask_empty().

Which do you want me to make a patch for?

Regards

-- Pantelis

-

2012-05-24 17:15:34

by Russell King - ARM Linux

[permalink] [raw]
Subject: Re: [PATCH] [ARM] Unconditional call to smp_cross_call on UP crashes

On Thu, May 24, 2012 at 07:55:56PM +0300, Pantelis Antoniou wrote:
> Hi Russell,
>
> On May 24, 2012, at 7:17 PM, Russell King - ARM Linux wrote:
>
> > On Thu, May 24, 2012 at 07:50:24PM +0000, Pantelis Antoniou wrote:
> >> omap2plus_defconfig builds with SMP & SMP_ON_UP set.
> >> On beagle (which is UP) is_smp() returns false and we don't call
> >> smp_init_cpus which in turn does not initialize smp_cross_call which
> >> remains NULL.
> >>
> >> When issuing a reboot we OOPS with a NULL dereference on stop smp_call.
> >
> > I've been wondering whether we should make smp_cross_call() a no-op instead
> > by default, rather than a NULL pointer.
> >
> > Alternatively, if may be well worth changing this to do:
> >
> > if (!cpumask_empty(&mask))
> > smp_cross_call(&mask, IPI_CPU_STOP);
> >
> > instead, so we avoid calling smp_cross_call() when we're on a SMP system
> > with only one CPU online. I like this approach better because it removes
> > a potential call into platform code which is inappropriate.
>
> Both of these can work, and in fact have been tried.
>
> I am partial on both to be honest. Have a default no-op function for smp_cross_call()
> and guard with cpumask_empty().
>
> Which do you want me to make a patch for?

I think the cpumask_empty() is the best approach, thanks.