Commit 5aaf254409f8d58229107b59507a8235b715a960
Committed by
Russell King
1 parent
e513f8bf24
Exists in
master
and in
7 other branches
ARM: 6203/1: Make VFPv3 usable on ARMv6
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>
Showing 2 changed files with 25 additions and 3 deletions Side-by-side Diff
arch/arm/include/asm/vfpmacros.h
... | ... | @@ -3,6 +3,8 @@ |
3 | 3 | * |
4 | 4 | * Assembler-only file containing VFP macros and register definitions. |
5 | 5 | */ |
6 | +#include <asm/hwcap.h> | |
7 | + | |
6 | 8 | #include "vfp.h" |
7 | 9 | |
8 | 10 | @ Macros to allow building with old toolkits (with no VFP support) |
9 | 11 | |
... | ... | @@ -22,12 +24,20 @@ |
22 | 24 | LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15} |
23 | 25 | #endif |
24 | 26 | #ifdef CONFIG_VFPv3 |
27 | +#if __LINUX_ARM_ARCH__ <= 6 | |
28 | + ldr \tmp, =elf_hwcap @ may not have MVFR regs | |
29 | + ldr \tmp, [\tmp, #0] | |
30 | + tst \tmp, #HWCAP_VFPv3D16 | |
31 | + ldceq p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} | |
32 | + addne \base, \base, #32*4 @ step over unused register space | |
33 | +#else | |
25 | 34 | VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 |
26 | 35 | and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field |
27 | 36 | cmp \tmp, #2 @ 32 x 64bit registers? |
28 | 37 | ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31} |
29 | 38 | addne \base, \base, #32*4 @ step over unused register space |
30 | 39 | #endif |
40 | +#endif | |
31 | 41 | .endm |
32 | 42 | |
33 | 43 | @ write all the working registers out of the VFP |
34 | 44 | |
... | ... | @@ -38,11 +48,19 @@ |
38 | 48 | STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15} |
39 | 49 | #endif |
40 | 50 | #ifdef CONFIG_VFPv3 |
51 | +#if __LINUX_ARM_ARCH__ <= 6 | |
52 | + ldr \tmp, =elf_hwcap @ may not have MVFR regs | |
53 | + ldr \tmp, [\tmp, #0] | |
54 | + tst \tmp, #HWCAP_VFPv3D16 | |
55 | + stceq p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} | |
56 | + addne \base, \base, #32*4 @ step over unused register space | |
57 | +#else | |
41 | 58 | VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0 |
42 | 59 | and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field |
43 | 60 | cmp \tmp, #2 @ 32 x 64bit registers? |
44 | 61 | stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31} |
45 | 62 | addne \base, \base, #32*4 @ step over unused register space |
63 | +#endif | |
46 | 64 | #endif |
47 | 65 | .endm |
arch/arm/vfp/vfpmodule.c
... | ... | @@ -15,6 +15,7 @@ |
15 | 15 | #include <linux/sched.h> |
16 | 16 | #include <linux/init.h> |
17 | 17 | |
18 | +#include <asm/cputype.h> | |
18 | 19 | #include <asm/thread_notify.h> |
19 | 20 | #include <asm/vfp.h> |
20 | 21 | |
21 | 22 | |
... | ... | @@ -549,10 +550,13 @@ |
549 | 550 | /* |
550 | 551 | * Check for the presence of the Advanced SIMD |
551 | 552 | * load/store instructions, integer and single |
552 | - * precision floating point operations. | |
553 | + * precision floating point operations. Only check | |
554 | + * for NEON if the hardware has the MVFR registers. | |
553 | 555 | */ |
554 | - if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) | |
555 | - elf_hwcap |= HWCAP_NEON; | |
556 | + if ((read_cpuid_id() & 0x000f0000) == 0x000f0000) { | |
557 | + if ((fmrx(MVFR1) & 0x000fff00) == 0x00011100) | |
558 | + elf_hwcap |= HWCAP_NEON; | |
559 | + } | |
556 | 560 | #endif |
557 | 561 | } |
558 | 562 | return 0; |