ARM: entry: Make asm coproc dispatch code NWFPE only
authorArd Biesheuvel <ardb@kernel.org>
Sun, 19 Mar 2023 23:25:18 +0000 (00:25 +0100)
committerArd Biesheuvel <ardb@kernel.org>
Wed, 17 May 2023 13:08:22 +0000 (15:08 +0200)
Now that we can dispatch all VFP and iWMMXT related undef exceptions
using undef hooks implemented in C code, we no longer need the asm entry
code that takes care of this unless we are using FPE, so we can move it
into the FPE entry code. As this means it is ARM only, we can remove the
Thumb2 specific decorations as well.

It also means the non-standard, asm-only calling convention where
returning via LR means failure and returning via R9 means success is now
only used on legacy platforms that lack any kind of function return
prediction, avoiding the associated performance impact.

Reviewed-by: Linus Walleij <linus.walleij@linaro.org>
Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
arch/arm/kernel/entry-armv.S
arch/arm/nwfpe/entry.S

index 822b2c8..682e926 100644 (file)
@@ -454,8 +454,10 @@ __und_usr:
        tst     r5, #PSR_T_BIT                  @ Thumb mode?
        mov     r1, #2                          @ set insn size to 2 for Thumb
        bne     0f                              @ handle as Thumb undef exception
+#ifdef CONFIG_FPE_NWFPE
        adr     r9, ret_from_exception
        bl      call_fpe                        @ returns via R9 on success
+#endif
        mov     r1, #4                          @ set insn size to 4 for ARM
 0:     mov     r0, sp
        uaccess_disable ip
@@ -464,97 +466,6 @@ __und_usr:
  UNWIND(.fnend)
 ENDPROC(__und_usr)
 
-/*
- * The out of line fixup for the ldrt instruction below.
- */
-       .pushsection .text.fixup, "ax"
-       .align  2
-4:     str     r4, [sp, #S_PC]                 @ retry current instruction
-       ret     r9
-       .popsection
-
-/*
- * Check whether the instruction is a co-processor instruction.
- * If yes, we need to call the relevant co-processor handler.
- *
- * Note that we don't do a full check here for the co-processor
- * instructions; all instructions with bit 27 set are well
- * defined.  The only instructions that should fault are the
- * co-processor instructions.  However, we have to watch out
- * for the ARM6/ARM7 SWI bug.
- *
- * Emulators may wish to make use of the following registers:
- *  r4  = PC value to resume execution after successful emulation
- *  r9  = normal "successful" return address
- *  r10 = this threads thread_info structure
- *  lr  = unrecognised instruction return address
- * IRQs enabled, FIQs enabled.
- */
-call_fpe:
-       mov     r2, r4
-       sub     r4, r4, #4                      @ ARM instruction at user PC - 4
-USERL( 4b,     ldrt r0, [r4])                  @ load opcode from user space
-ARM_BE8(rev    r0, r0)                         @ little endian instruction
-
-       uaccess_disable ip
-
-       get_thread_info r10                     @ get current thread
-       tst     r0, #0x08000000                 @ only CDP/CPRT/LDC/STC have bit 27
-       reteq   lr
-       and     r8, r0, #0x00000f00             @ mask out CP number
-#ifdef CONFIG_IWMMXT
-       @ Test if we need to give access to iWMMXt coprocessors
-       ldr     r5, [r10, #TI_FLAGS]
-       rsbs    r7, r8, #(1 << 8)               @ CP 0 or 1 only
-       movscs  r7, r5, lsr #(TIF_USING_IWMMXT + 1)
-       movcs   r0, sp                          @ pass struct pt_regs
-       bcs     iwmmxt_task_enable
-#endif
- ARM(  add     pc, pc, r8, lsr #6      )
- THUMB(        lsr     r8, r8, #6              )
- THUMB(        add     pc, r8                  )
-       nop
-
-       ret.w   lr                              @ CP#0
-       W(b)    do_fpe                          @ CP#1 (FPE)
-       W(b)    do_fpe                          @ CP#2 (FPE)
-       ret.w   lr                              @ CP#3
-       ret.w   lr                              @ CP#4
-       ret.w   lr                              @ CP#5
-       ret.w   lr                              @ CP#6
-       ret.w   lr                              @ CP#7
-       ret.w   lr                              @ CP#8
-       ret.w   lr                              @ CP#9
-       ret.w   lr                              @ CP#10 (VFP)
-       ret.w   lr                              @ CP#11 (VFP)
-       ret.w   lr                              @ CP#12
-       ret.w   lr                              @ CP#13
-       ret.w   lr                              @ CP#14 (Debug)
-       ret.w   lr                              @ CP#15 (Control)
-
-do_fpe:
-       add     r10, r10, #TI_FPSTATE           @ r10 = workspace
-       ldr_va  pc, fp_enter, tmp=r4            @ Call FP module USR entry point
-
-/*
- * The FP module is called with these registers set:
- *  r0  = instruction
- *  r2  = PC+4
- *  r9  = normal "successful" return address
- *  r10 = FP workspace
- *  lr  = unrecognised FP instruction return address
- */
-
-       .pushsection .data
-       .align  2
-ENTRY(fp_enter)
-       .word   no_fp
-       .popsection
-
-ENTRY(no_fp)
-       ret     lr
-ENDPROC(no_fp)
-
        .align  5
 __pabt_usr:
        usr_entry
index d8f9915..354d297 100644 (file)
@@ -7,6 +7,7 @@
     Direct questions, comments to Scott Bambrough <scottb@netwinder.org>
 
 */
+#include <linux/linkage.h>
 #include <asm/assembler.h>
 #include <asm/opcodes.h>
 
@@ -104,6 +105,7 @@ next:
        @ plain LDR instruction.  Weird, but it seems harmless.
        .pushsection .text.fixup,"ax"
        .align  2
+.Lrep: str     r4, [sp, #S_PC]         @ retry current instruction
 .Lfix: ret     r9                      @ let the user eat segfaults
        .popsection
 
@@ -111,3 +113,78 @@ next:
        .align  3
        .long   .Lx1, .Lfix
        .popsection
+
+       @
+       @ Check whether the instruction is a co-processor instruction.
+       @ If yes, we need to call the relevant co-processor handler.
+       @ Only FPE instructions are dispatched here, everything else
+       @ is handled by undef hooks.
+       @
+       @ Emulators may wish to make use of the following registers:
+       @  r4  = PC value to resume execution after successful emulation
+       @  r9  = normal "successful" return address
+       @  lr  = unrecognised instruction return address
+       @ IRQs enabled, FIQs enabled.
+       @
+ENTRY(call_fpe)
+       mov     r2, r4
+       sub     r4, r4, #4                      @ ARM instruction at user PC - 4
+USERL( .Lrep,  ldrt r0, [r4])                  @ load opcode from user space
+ARM_BE8(rev    r0, r0)                         @ little endian instruction
+
+       uaccess_disable ip
+
+       get_thread_info r10                     @ get current thread
+       tst     r0, #0x08000000                 @ only CDP/CPRT/LDC/STC have bit 27
+       reteq   lr
+       and     r8, r0, #0x00000f00             @ mask out CP number
+#ifdef CONFIG_IWMMXT
+       @ Test if we need to give access to iWMMXt coprocessors
+       ldr     r5, [r10, #TI_FLAGS]
+       rsbs    r7, r8, #(1 << 8)               @ CP 0 or 1 only
+       movscs  r7, r5, lsr #(TIF_USING_IWMMXT + 1)
+       movcs   r0, sp                          @ pass struct pt_regs
+       bcs     iwmmxt_task_enable
+#endif
+       add     pc, pc, r8, lsr #6
+       nop
+
+       ret     lr                              @ CP#0
+       b       do_fpe                          @ CP#1 (FPE)
+       b       do_fpe                          @ CP#2 (FPE)
+       ret     lr                              @ CP#3
+       ret     lr                              @ CP#4
+       ret     lr                              @ CP#5
+       ret     lr                              @ CP#6
+       ret     lr                              @ CP#7
+       ret     lr                              @ CP#8
+       ret     lr                              @ CP#9
+       ret     lr                              @ CP#10 (VFP)
+       ret     lr                              @ CP#11 (VFP)
+       ret     lr                              @ CP#12
+       ret     lr                              @ CP#13
+       ret     lr                              @ CP#14 (Debug)
+       ret     lr                              @ CP#15 (Control)
+
+do_fpe:
+       add     r10, r10, #TI_FPSTATE           @ r10 = workspace
+       ldr_va  pc, fp_enter, tmp=r4            @ Call FP module USR entry point
+
+       @
+       @ The FP module is called with these registers set:
+       @  r0  = instruction
+       @  r2  = PC+4
+       @  r9  = normal "successful" return address
+       @  r10 = FP workspace
+       @  lr  = unrecognised FP instruction return address
+       @
+
+       .pushsection .data
+       .align  2
+ENTRY(fp_enter)
+       .word   no_fp
+       .popsection
+
+no_fp:
+       ret     lr
+ENDPROC(no_fp)