Commit 998de4acb2ba188d20768d1065658377a2e7d29b
Committed by
Russell King
1 parent
fde165b2a2
Exists in
smarc-l5.0.0_1.0.0-ga
and in
5 other branches
ARM: 7417/1: vfp: ensure preemption is disabled when enabling VFP access
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>
Showing 1 changed file with 6 additions and 4 deletions Side-by-side Diff
arch/arm/vfp/vfpmodule.c
... | ... | @@ -11,6 +11,7 @@ |
11 | 11 | #include <linux/types.h> |
12 | 12 | #include <linux/cpu.h> |
13 | 13 | #include <linux/cpu_pm.h> |
14 | +#include <linux/hardirq.h> | |
14 | 15 | #include <linux/kernel.h> |
15 | 16 | #include <linux/notifier.h> |
16 | 17 | #include <linux/signal.h> |
17 | 18 | |
... | ... | @@ -432,8 +433,11 @@ |
432 | 433 | |
433 | 434 | static void vfp_enable(void *unused) |
434 | 435 | { |
435 | - u32 access = get_copro_access(); | |
436 | + u32 access; | |
436 | 437 | |
438 | + BUG_ON(preemptible()); | |
439 | + access = get_copro_access(); | |
440 | + | |
437 | 441 | /* |
438 | 442 | * Enable full access to VFP (cp10 and cp11) |
439 | 443 | */ |
... | ... | @@ -657,7 +661,7 @@ |
657 | 661 | unsigned int cpu_arch = cpu_architecture(); |
658 | 662 | |
659 | 663 | if (cpu_arch >= CPU_ARCH_ARMv6) |
660 | - vfp_enable(NULL); | |
664 | + on_each_cpu(vfp_enable, NULL, 1); | |
661 | 665 | |
662 | 666 | /* |
663 | 667 | * First check that there is a VFP that we can use. |
... | ... | @@ -677,8 +681,6 @@ |
677 | 681 | printk("no double precision support\n"); |
678 | 682 | } else { |
679 | 683 | hotcpu_notifier(vfp_hotplug, 0); |
680 | - | |
681 | - smp_call_function(vfp_enable, NULL, 1); | |
682 | 684 | |
683 | 685 | VFP_arch = (vfpsid & FPSID_ARCH_MASK) >> FPSID_ARCH_BIT; /* Extract the architecture version */ |
684 | 686 | printk("implementor %02x architecture %d part %02x variant %x rev %x\n", |