ARM: entry: Make asm coproc dispatch code NWFPE only

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>
This commit is contained in:
Ard Biesheuvel 2023-03-20 00:25:18 +01:00
parent 303d6da167
commit 47ba5f39ea
2 changed files with 79 additions and 91 deletions

View 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

View 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)