| 1 | From: Catalin Marinas <catalin.marinas@arm.com> |
| 2 | Date: Sat, 30 May 2009 13:00:18 +0000 (+0100) |
| 3 | Subject: Fix the VFP handling on the Feroceon CPU |
| 4 | X-Git-Url: http://www.linux-arm.org/git?p=linux-2.6.git;a=commitdiff_plain;h=85d6943af50537d3aec58b967ffbd3fec88453e9;hp=26584853a44c58f3d6ac7360d697a2ddcd1a3efa |
| 5 | |
| 6 | Fix the VFP handling on the Feroceon CPU |
| 7 | |
| 8 | This CPU generates synchronous VFP exceptions in a non-standard way - |
| 9 | the FPEXC.EX bit set but without the FPSCR.IXE bit being set like in the |
| 10 | VFP subarchitecture 1 or just the FPEXC.DEX bit like in VFP |
| 11 | subarchitecture 2. The main problem is that the faulty instruction |
| 12 | (which needs to be emulated in software) will be restarted several times |
| 13 | (normally until a context switch disables the VFP). This patch ensures |
| 14 | that the VFP exception is treated as synchronous. |
| 15 | |
| 16 | Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> |
| 17 | Cc: Nicolas Pitre <nico@cam.org> |
| 18 | --- |
| 19 | |
| 20 | --- a/arch/arm/vfp/vfphw.S |
| 21 | +++ b/arch/arm/vfp/vfphw.S |
| 22 | @@ -100,6 +100,7 @@ ENTRY(vfp_support_entry) |
| 23 | beq no_old_VFP_process |
| 24 | VFPFSTMIA r4, r5 @ save the working registers |
| 25 | VFPFMRX r5, FPSCR @ current status |
| 26 | +#ifndef CONFIG_CPU_FEROCEON |
| 27 | tst r1, #FPEXC_EX @ is there additional state to save? |
| 28 | beq 1f |
| 29 | VFPFMRX r6, FPINST @ FPINST (only if FPEXC.EX is set) |
| 30 | @@ -107,6 +108,7 @@ ENTRY(vfp_support_entry) |
| 31 | beq 1f |
| 32 | VFPFMRX r8, FPINST2 @ FPINST2 if needed (and present) |
| 33 | 1: |
| 34 | +#endif |
| 35 | stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 |
| 36 | @ and point r4 at the word at the |
| 37 | @ start of the register dump |
| 38 | @@ -119,6 +121,7 @@ no_old_VFP_process: |
| 39 | VFPFLDMIA r10, r5 @ reload the working registers while |
| 40 | @ FPEXC is in a safe state |
| 41 | ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 |
| 42 | +#ifndef CONFIG_CPU_FEROCEON |
| 43 | tst r1, #FPEXC_EX @ is there additional state to restore? |
| 44 | beq 1f |
| 45 | VFPFMXR FPINST, r6 @ restore FPINST (only if FPEXC.EX is set) |
| 46 | @@ -126,6 +129,7 @@ no_old_VFP_process: |
| 47 | beq 1f |
| 48 | VFPFMXR FPINST2, r8 @ FPINST2 if needed (and present) |
| 49 | 1: |
| 50 | +#endif |
| 51 | VFPFMXR FPSCR, r5 @ restore status |
| 52 | |
| 53 | check_for_exception: |
| 54 | --- a/arch/arm/vfp/vfpmodule.c |
| 55 | +++ b/arch/arm/vfp/vfpmodule.c |
| 56 | @@ -253,12 +253,14 @@ void VFP_bounce(u32 trigger, u32 fpexc, |
| 57 | } |
| 58 | |
| 59 | if (fpexc & FPEXC_EX) { |
| 60 | +#ifndef CONFIG_CPU_FEROCEON |
| 61 | /* |
| 62 | * Asynchronous exception. The instruction is read from FPINST |
| 63 | * and the interrupted instruction has to be restarted. |
| 64 | */ |
| 65 | trigger = fmrx(FPINST); |
| 66 | regs->ARM_pc -= 4; |
| 67 | +#endif |
| 68 | } else if (!(fpexc & FPEXC_DEX)) { |
| 69 | /* |
| 70 | * Illegal combination of bits. It can be caused by an |
| 71 | |