aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/vfp/vfphw.S
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2012-07-30 14:42:10 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2012-07-31 07:04:30 -0400
commit15ac49b65024f55c4371a53214879a9c77c4fbf9 (patch)
treebcff50c21d64e51e672697771fc6a0cc29af1afd /arch/arm/vfp/vfphw.S
parentc5dff4ffd327088d85035bec535b7d0c9ea03151 (diff)
ARM: Fix undefined instruction exception handling
While trying to get a v3.5 kernel booted on the cubox, I noticed that VFP does not work correctly with VFP bounce handling. This is because of the confusion over 16-bit vs 32-bit instructions, and where PC is supposed to point to. The rule is that FP handlers are entered with regs->ARM_pc pointing at the _next_ instruction to be executed. However, if the exception is not handled, regs->ARM_pc points at the faulting instruction. This is easy for ARM mode, because we know that the next instruction and previous instructions are separated by four bytes. This is not true of Thumb2 though. Since all FP instructions are 32-bit in Thumb2, it makes things easy. We just need to select the appropriate adjustment. Do this by moving the adjustment out of do_undefinstr() into the assembly code, as only the assembly code knows whether it's dealing with a 32-bit or 16-bit instruction. Cc: <stable@vger.kernel.org> Acked-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/vfp/vfphw.S')
-rw-r--r--arch/arm/vfp/vfphw.S19
1 files changed, 11 insertions, 8 deletions
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 2d30c7f6edd3..3a0efaad6090 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -61,13 +61,13 @@
61 61
62@ VFP hardware support entry point. 62@ VFP hardware support entry point.
63@ 63@
64@ r0 = faulted instruction 64@ r0 = instruction opcode (32-bit ARM or two 16-bit Thumb)
65@ r2 = faulted PC+4 65@ r2 = PC value to resume execution after successful emulation
66@ r9 = successful return 66@ r9 = normal "successful" return address
67@ r10 = vfp_state union 67@ r10 = vfp_state union
68@ r11 = CPU number 68@ r11 = CPU number
69@ lr = failure return 69@ lr = unrecognised instruction return address
70 70@ IRQs enabled.
71ENTRY(vfp_support_entry) 71ENTRY(vfp_support_entry)
72 DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10 72 DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
73 73
@@ -161,9 +161,12 @@ vfp_hw_state_valid:
161 @ exception before retrying branch 161 @ exception before retrying branch
162 @ out before setting an FPEXC that 162 @ out before setting an FPEXC that
163 @ stops us reading stuff 163 @ stops us reading stuff
164 VFPFMXR FPEXC, r1 @ restore FPEXC last 164 VFPFMXR FPEXC, r1 @ Restore FPEXC last
165 sub r2, r2, #4 165 sub r2, r2, #4 @ Retry current instruction - if Thumb
166 str r2, [sp, #S_PC] @ retry the instruction 166 str r2, [sp, #S_PC] @ mode it's two 16-bit instructions,
167 @ else it's one 32-bit instruction, so
168 @ always subtract 4 from the following
169 @ instruction address.
167#ifdef CONFIG_PREEMPT 170#ifdef CONFIG_PREEMPT
168 get_thread_info r10 171 get_thread_info r10
169 ldr r4, [r10, #TI_PREEMPT] @ get preempt count 172 ldr r4, [r10, #TI_PREEMPT] @ get preempt count