Skip to content

Commit

Permalink
ARM: 6203/1: Make VFPv3 usable on ARMv6
Browse files Browse the repository at this point in the history
MVFR0 and MVFR1 are only available starting with ARM1136 r1p0 release
according to "B.5 VFP changes" in DDI0211F_arm1136_r1p0_trm.pdf. This is
also when TLS register got added, so we can use HAS_TLS also to test for
MVFR0 and MVFR1.

Otherwise VFPFMRX and VFPFMXR access fails and we get:

Internal error: Oops - undefined instruction: 0 [#1]
PC is at no_old_VFP_process+0x8/0x3c
LR is at __und_svc+0x48/0x80
...

Signed-off-by: Tony Lindgren <tony@atomide.com>
Acked-by: Catalin Marinas <catalin.marinas@arm.com>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
  • Loading branch information
Tony Lindgren authored and Russell King committed Jul 9, 2010
1 parent e513f8b commit 5aaf254
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 3 deletions.
18 changes: 18 additions & 0 deletions arch/arm/include/asm/vfpmacros.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
*
* Assembler-only file containing VFP macros and register definitions.
*/
#include <asm/hwcap.h>

#include "vfp.h"

@ Macros to allow building with old toolkits (with no VFP support)
Expand All @@ -22,11 +24,19 @@
LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15}
#endif
#ifdef CONFIG_VFPv3
#if __LINUX_ARM_ARCH__ <= 6
ldr \tmp, =elf_hwcap @ may not have MVFR regs
ldr \tmp, [\tmp, #0]
tst \tmp, #HWCAP_VFPv3D16
ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space
#else
VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
cmp \tmp, #2 @ 32 x 64bit registers?
ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space
#endif
#endif
.endm

Expand All @@ -38,10 +48,18 @@
STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15}
#endif
#ifdef CONFIG_VFPv3
#if __LINUX_ARM_ARCH__ <= 6
ldr \tmp, =elf_hwcap @ may not have MVFR regs
ldr \tmp, [\tmp, #0]
tst \tmp, #HWCAP_VFPv3D16
stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space
#else
VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
cmp \tmp, #2 @ 32 x 64bit registers?
stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
addne \base, \base, #32*4 @ step over unused register space
#endif
#endif
.endm
10 changes: 7 additions & 3 deletions arch/arm/vfp/vfpmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <linux/sched.h>
#include <linux/init.h>

#include <asm/cputype.h>
#include <asm/thread_notify.h>
#include <asm/vfp.h>

Expand Down Expand Up @@ -549,10 +550,13 @@ static int __init vfp_init(void)
/*
* Check for the presence of the Advanced SIMD
* load/store instructions, integer and single
* precision floating point operations.
* precision floating point operations. Only check
* for NEON if the hardware has the MVFR registers.
*/
if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
elf_hwcap |= HWCAP_NEON;
if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) {
if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100)
elf_hwcap |= HWCAP_NEON;
}
#endif
}
return 0;
Expand Down

0 comments on commit 5aaf254

Please sign in to comment.