[PATCH] Prevent process migration during vfp_init()
Hyungwoo Yang
hwoo.yang at gmail.com
Tue May 8 13:24:27 EDT 2012
Hello Will,
Thank you for your comments. I didn't check the implementation of
preempt_disable() on non-preemptible kernel case.
I think we don't need preempt_disable()/preempt_enable() call in your proposal.
I mean, since we have enabled on every VFPs in cores online(
on_each_cpu() ), we don't need to worry about accessing a VFP which is
disabled. So we don't need to worry about migration after
"on_each_cpu()", right?
- Hyungwoo Yang
On Tue, May 8, 2012 at 4:13 AM, Will Deacon <will.deacon at arm.com> wrote:
> On Fri, May 04, 2012 at 09:28:15PM +0100, Hyungwoo Yang wrote:
>> Hello,
>
> Hi,
>
> Some comments inline and a proposed v2.
>
>> From f96fc79d508235706462336239eb30d66e2e6c0b Mon Sep 17 00:00:00 2001
>> From: Hyungwoo Yang <hyungwooy at nvidia.com>
>> Date: Fri, 4 May 2012 11:22:59 -0700
>> Subject: [PATCH] System crashes if there is process migration during
>> vfp_init() call.
>>
>> During vfp_init(), if a process which called vfp_enable() is migrated just
>> after the call, then the process executing the rest of code will access
>> a VFP unit which is not ENABLED and also smp_call_function() will not work
>> as it is expected.
>>
>> This patch prevents accessing VFP unit disabled by preventing migration
>> and also replaces smp_call_function() with on_each_cpu() to make sure that
>> no VFP remains disabled.
>>
>> Signed-off-by: Hyungwoo Yang <hyungwooy at nvidia.com>
>>
>> diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
>> index bc683b8..6f33e4d 100644
>> --- a/arch/arm/vfp/vfpmodule.c
>> +++ b/arch/arm/vfp/vfpmodule.c
>> @@ -655,7 +655,9 @@ static int __init vfp_init(void)
>> {
>> unsigned int vfpsid;
>> unsigned int cpu_arch = cpu_architecture();
>> -
>> +#ifdef CONFIG_SMP
>> + preempt_disable();
>> +#endif
>
> I don't think it's worth having the SMP guards for this.
>
>> if (cpu_arch >= CPU_ARCH_ARMv6)
>> vfp_enable(NULL);
>
> I think we can avoid this redundant enable if we move some code around (see
> below).
>
>> @@ -667,7 +669,9 @@ static int __init vfp_init(void)
>> vfp_vector = vfp_testing_entry;
>> barrier();
>> vfpsid = fmrx(FPSID);
>> - barrier();
>> +#ifdef CONFIG_SMP
>> + preempt_enable();
>> +#endif
>
> If we're not running a PREEMPT kernel, you just removed a compiler barrier.
>
> How about something like the following instead? I've also added a BUG_ON to
> vfp_enable to stop this catching us out in future:
>
> diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
> index bc683b8..8e08983 100644
> --- a/arch/arm/vfp/vfpmodule.c
> +++ b/arch/arm/vfp/vfpmodule.c
> @@ -11,6 +11,7 @@
> #include <linux/types.h>
> #include <linux/cpu.h>
> #include <linux/cpu_pm.h>
> +#include <linux/hardirq.h>
> #include <linux/kernel.h>
> #include <linux/notifier.h>
> #include <linux/signal.h>
> @@ -432,7 +433,10 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
>
> static void vfp_enable(void *unused)
> {
> - u32 access = get_copro_access();
> + u32 access;
> +
> + BUG_ON(preemptible());
> + access = get_copro_access();
>
> /*
> * Enable full access to VFP (cp10 and cp11)
> @@ -657,18 +661,20 @@ static int __init vfp_init(void)
> unsigned int cpu_arch = cpu_architecture();
>
> if (cpu_arch >= CPU_ARCH_ARMv6)
> - vfp_enable(NULL);
> + on_each_cpu(vfp_enable, NULL, 1);
>
> /*
> * First check that there is a VFP that we can use.
> * The handler is already setup to just log calls, so
> * we just need to read the VFPSID register.
> */
> + preempt_disable();
> vfp_vector = vfp_testing_entry;
> barrier();
> vfpsid = fmrx(FPSID);
> barrier();
> vfp_vector = vfp_null_entry;
> + preempt_enable();
>
> printk(KERN_INFO "VFP support v0.3: ");
> if (VFP_arch)
> @@ -678,8 +684,6 @@ static int __init vfp_init(void)
> } else {
> hotcpu_notifier(vfp_hotplug, 0);
>
> - smp_call_function(vfp_enable, NULL, 1);
> -
> VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */
> printk("implementor %02x architecture %d part %02x variant %x rev %x\n",
> (vfpsid & FPSID_IMPLEMENTER_MASK) >> FPSID_IMPLEMENTER_BIT,
>
> Will
More information about the linux-arm-kernel
mailing list