Skip to content

Commit

Permalink
ARM: 7417/1: vfp: ensure preemption is disabled when enabling VFP access
Browse files Browse the repository at this point in the history
The vfp_enable function enables access to the VFP co-processor register
space (cp10 and cp11) on the current CPU and must be called with
preemption disabled. Unfortunately, the vfp_init late initcall does not
disable preemption and can lead to an oops during boot if thread
migration occurs at the wrong time and we end up attempting to access
the FPSID on a CPU with VFP access disabled.

This patch fixes the initcall to call vfp_enable from a non-preemptible
context on each CPU and adds a BUG_ON(preemptible) to ensure that any
similar problems are easily spotted in the future.

Cc: stable@vger.kernel.org
Reported-by: Hyungwoo Yang <hwoo.yang@gmail.com>
Signed-off-by: Hyungwoo Yang <hyungwooy@nvidia.com>
Signed-off-by: Will Deacon <will.deacon@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Will Deacon authored and Russell King committed May 12, 2012
1 parent fde165b commit 998de4a
Showing 1 changed file with 6 additions and 4 deletions.
10 changes: 6 additions & 4 deletions arch/arm/vfp/vfpmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -657,7 +661,7 @@ 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.
Expand All @@ -678,8 +682,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,
Expand Down

0 comments on commit 998de4a

Please sign in to comment.