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:
parent
303d6da167
commit
47ba5f39ea
@ -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
|
||||
|
@ -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)
|
||||
|
Loading…
Reference in New Issue
Block a user