Commit 47ba5f39 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

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: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 303d6da1
Loading
Loading
Loading
Loading
+2 −91
Original line number Diff line number Diff line
@@ -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
+77 −0
Original line number Diff line number Diff line
@@ -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)