aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2009-05-30 09:00:18 -0400
committerCatalin Marinas <catalin.marinas@arm.com>2009-05-30 09:00:18 -0400
commit85d6943af50537d3aec58b967ffbd3fec88453e9 (patch)
tree2033d95a7a57f792856cc08e1bd77f01386c5ed6 /arch/arm/vfp
parent26584853a44c58f3d6ac7360d697a2ddcd1a3efa (diff)
Fix the VFP handling on the Feroceon CPU
This CPU generates synchronous VFP exceptions in a non-standard way - the FPEXC.EX bit set but without the FPSCR.IXE bit being set like in the VFP subarchitecture 1 or just the FPEXC.DEX bit like in VFP subarchitecture 2. The main problem is that the faulty instruction (which needs to be emulated in software) will be restarted several times (normally until a context switch disables the VFP). This patch ensures that the VFP exception is treated as synchronous. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Cc: Nicolas Pitre <nico@cam.org>
Diffstat (limited to 'arch/arm/vfp')
-rw-r--r--arch/arm/vfp/vfphw.S4
-rw-r--r--arch/arm/vfp/vfpmodule.c2
2 files changed, 6 insertions, 0 deletions
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 83c4e384b16..1aeae38725d 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -100,6 +100,7 @@ ENTRY(vfp_support_entry)
100 beq no_old_VFP_process 100 beq no_old_VFP_process
101 VFPFSTMIA r4, r5 @ save the working registers 101 VFPFSTMIA r4, r5 @ save the working registers
102 VFPFMRX r5, FPSCR @ current status 102 VFPFMRX r5, FPSCR @ current status
103#ifndef CONFIG_CPU_FEROCEON
103 tst r1, #FPEXC_EX @ is there additional state to save? 104 tst r1, #FPEXC_EX @ is there additional state to save?
104 beq 1f 105 beq 1f
105 VFPFMRX r6, FPINST @ FPINST (only if FPEXC.EX is set) 106 VFPFMRX r6, FPINST @ FPINST (only if FPEXC.EX is set)
@@ -107,6 +108,7 @@ ENTRY(vfp_support_entry)
107 beq 1f 108 beq 1f
108 VFPFMRX r8, FPINST2 @ FPINST2 if needed (and present) 109 VFPFMRX r8, FPINST2 @ FPINST2 if needed (and present)
1091: 1101:
111#endif
110 stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 112 stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2
111 @ and point r4 at the word at the 113 @ and point r4 at the word at the
112 @ start of the register dump 114 @ start of the register dump
@@ -119,6 +121,7 @@ no_old_VFP_process:
119 VFPFLDMIA r10, r5 @ reload the working registers while 121 VFPFLDMIA r10, r5 @ reload the working registers while
120 @ FPEXC is in a safe state 122 @ FPEXC is in a safe state
121 ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 123 ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2
124#ifndef CONFIG_CPU_FEROCEON
122 tst r1, #FPEXC_EX @ is there additional state to restore? 125 tst r1, #FPEXC_EX @ is there additional state to restore?
123 beq 1f 126 beq 1f
124 VFPFMXR FPINST, r6 @ restore FPINST (only if FPEXC.EX is set) 127 VFPFMXR FPINST, r6 @ restore FPINST (only if FPEXC.EX is set)
@@ -126,6 +129,7 @@ no_old_VFP_process:
126 beq 1f 129 beq 1f
127 VFPFMXR FPINST2, r8 @ FPINST2 if needed (and present) 130 VFPFMXR FPINST2, r8 @ FPINST2 if needed (and present)
1281: 1311:
132#endif
129 VFPFMXR FPSCR, r5 @ restore status 133 VFPFMXR FPSCR, r5 @ restore status
130 134
131check_for_exception: 135check_for_exception:
diff --git a/arch/arm/vfp/vfpmodule.c b/arch/arm/vfp/vfpmodule.c
index 01599c4ef72..2d7423af119 100644
--- a/arch/arm/vfp/vfpmodule.c
+++ b/arch/arm/vfp/vfpmodule.c
@@ -253,12 +253,14 @@ void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs)
253 } 253 }
254 254
255 if (fpexc & FPEXC_EX) { 255 if (fpexc & FPEXC_EX) {
256#ifndef CONFIG_CPU_FEROCEON
256 /* 257 /*
257 * Asynchronous exception. The instruction is read from FPINST 258 * Asynchronous exception. The instruction is read from FPINST
258 * and the interrupted instruction has to be restarted. 259 * and the interrupted instruction has to be restarted.
259 */ 260 */
260 trigger = fmrx(FPINST); 261 trigger = fmrx(FPINST);
261 regs->ARM_pc -= 4; 262 regs->ARM_pc -= 4;
263#endif
262 } else if (!(fpexc & FPEXC_DEX)) { 264 } else if (!(fpexc & FPEXC_DEX)) {
263 /* 265 /*
264 * Illegal combination of bits. It can be caused by an 266 * Illegal combination of bits. It can be caused by an