aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp
diff options
context:
space:
mode:
authorArd Biesheuvel <ard.biesheuvel@linaro.org>2013-05-24 10:23:28 -0400
committerArd Biesheuvel <ard.biesheuvel@linaro.org>2013-07-08 17:07:38 -0400
commitab3da15643469ab2d206dee3d9cfa4194ba77f25 (patch)
treee332a19c18476b01934d0d2b10551daac0abd5b6 /arch/arm/vfp
parent0773d73d818702191dd568e1e20bcafc5c64661a (diff)
ARM: be strict about FP exceptions in kernel mode
The support code in vfp_support_entry does not care whether the exception that caused it to be invoked occurred in kernel mode or in user mode. However, neither condition that could trigger this exception (lazy restore and VFP bounce to support code) is currently allowable in kernel mode. In either case, print a message describing the condition before letting the undefined instruction handler run its course and trigger an oops. Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org> Acked-by: Nicolas Pitre <nico@linaro.org>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r--arch/arm/vfp/vfphw.S5
-rw-r--r--arch/arm/vfp/vfpmodule.c20
2 files changed, 25 insertions, 0 deletions
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 8d10dc8a1e17..3e5d3115a2a6 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -78,6 +78,11 @@
78ENTRY(vfp_support_entry) 78ENTRY(vfp_support_entry)
79 DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10 79 DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
80 80
81 ldr r3, [sp, #S_PSR] @ Neither lazy restore nor FP exceptions
82 and r3, r3, #MODE_MASK @ are supported in kernel mode
83 teq r3, #USR_MODE
84 bne vfp_kmode_exception @ Returns through lr
85
81 VFPFMRX r1, FPEXC @ Is the VFP enabled? 86 VFPFMRX r1, FPEXC @ Is the VFP enabled?
82 DBGSTR1 "fpexc %08x", r1 87 DBGSTR1 "fpexc %08x", r1
83 tst r1, #FPEXC_EN 88 tst r1, #FPEXC_EN
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 791993aed75a..7620831a0c66 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -648,6 +648,26 @@ static int vfp_hotplug(struct notifier_block *b, unsigned long action,
648 return NOTIFY_OK; 648 return NOTIFY_OK;
649} 649}
650 650
651void vfp_kmode_exception(void)
652{
653 /*
654 * If we reach this point, a floating point exception has been raised
655 * while running in kernel mode. If the NEON/VFP unit was enabled at the
656 * time, it means a VFP instruction has been issued that requires
657 * software assistance to complete, something which is not currently
658 * supported in kernel mode.
659 * If the NEON/VFP unit was disabled, and the location pointed to below
660 * is properly preceded by a call to kernel_neon_begin(), something has
661 * caused the task to be scheduled out and back in again. In this case,
662 * rebuilding and running with CONFIG_DEBUG_ATOMIC_SLEEP enabled should
663 * be helpful in localizing the problem.
664 */
665 if (fmrx(FPEXC) & FPEXC_EN)
666 pr_crit("BUG: unsupported FP instruction in kernel mode\n");
667 else
668 pr_crit("BUG: FP instruction issued in kernel mode with FP unit disabled\n");
669}
670
651/* 671/*
652 * VFP support code initialisation. 672 * VFP support code initialisation.
653 */ 673 */