diff options
author | Ard Biesheuvel <ardb@kernel.org> | 2023-03-20 02:25:18 +0300 |
---|---|---|
committer | Ard Biesheuvel <ardb@kernel.org> | 2023-05-17 16:08:22 +0300 |
commit | 47ba5f39eab3c2a9a1ba878159a6050f2bbfc0e2 (patch) | |
tree | d0d0485f5f614e0070bab6ff1b53d56aec7c2d8e /arch | |
parent | 303d6da167dcbc3dd89adf3ca4e36c369950ed01 (diff) | |
download | linux-47ba5f39eab3c2a9a1ba878159a6050f2bbfc0e2.tar.xz |
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>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/arm/kernel/entry-armv.S | 93 | ||||
-rw-r--r-- | arch/arm/nwfpe/entry.S | 77 |
2 files changed, 79 insertions, 91 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 822b2c83bf08..682e92664b07 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -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 diff --git a/arch/arm/nwfpe/entry.S b/arch/arm/nwfpe/entry.S index d8f9915566e1..354d297a193b 100644 --- a/arch/arm/nwfpe/entry.S +++ b/arch/arm/nwfpe/entry.S @@ -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) |