Commit 303d6da1 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

ARM: iwmmxt: Use undef hook to enable coprocessor for task



Define a undef hook to deal with undef exceptions triggered by iwmmxt
instructions that were issued with the coprocessor disabled. This
removes the dependency on the coprocessor dispatch code in entry-armv.S,
which will be made NWFPE-only in a subsequent patch.

Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
parent 8bcba70c
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -40,6 +40,7 @@ struct task_struct;
DECLARE_PER_CPU(struct task_struct *, __entry_task);

#include <asm/types.h>
#include <asm/traps.h>

struct cpu_context_save {
	__u32	r4;
@@ -104,6 +105,21 @@ extern void iwmmxt_task_restore(struct thread_info *, void *);
extern void iwmmxt_task_release(struct thread_info *);
extern void iwmmxt_task_switch(struct thread_info *);

extern int iwmmxt_undef_handler(struct pt_regs *, u32);

static inline void register_iwmmxt_undef_handler(void)
{
	static struct undef_hook iwmmxt_undef_hook = {
		.instr_mask	= 0x0c000e00,
		.instr_val	= 0x0c000000,
		.cpsr_mask	= MODE_MASK | PSR_T_BIT,
		.cpsr_val	= USR_MODE,
		.fn		= iwmmxt_undef_handler,
	};

	register_undef_hook(&iwmmxt_undef_hook);
}

extern void vfp_sync_hwstate(struct thread_info *);
extern void vfp_flush_hwstate(struct thread_info *);

+1 −0
Original line number Diff line number Diff line
@@ -507,6 +507,7 @@ ARM_BE8(rev r0, r0) @ little endian instruction
	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	)
+14 −4
Original line number Diff line number Diff line
@@ -58,9 +58,19 @@
	.text
	.arm

ENTRY(iwmmxt_undef_handler)
	push		{r9, r10, lr}
	get_thread_info	r10
	mov		r9, pc
	b		iwmmxt_task_enable
	mov		r0, #0
	pop		{r9, r10, pc}
ENDPROC(iwmmxt_undef_handler)

/*
 * Lazy switching of Concan coprocessor context
 *
 * r0  = struct pt_regs pointer
 * r10 = struct thread_info pointer
 * r9  = ret_from_exception
 * lr  = undefined instr exit
@@ -84,12 +94,12 @@ ENTRY(iwmmxt_task_enable)
	PJ4(mcr	p15, 0, r2, c1, c0, 2)

	ldr	r3, =concan_owner
	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
	ldr	r2, [sp, #60]			@ current task pc value
	ldr	r2, [r0, #S_PC]			@ current task pc value
	ldr	r1, [r3]			@ get current Concan owner
	str	r0, [r3]			@ this task now owns Concan regs
	sub	r2, r2, #4			@ adjust pc back
	str	r2, [sp, #60]
	str	r2, [r0, #S_PC]
	add	r0, r10, #TI_IWMMXT_STATE	@ get task Concan save area
	str	r0, [r3]			@ this task now owns Concan regs

	mrc	p15, 0, r2, c2, c0, 0
	mov	r2, r2				@ cpwait
+1 −0
Original line number Diff line number Diff line
@@ -126,6 +126,7 @@ static int __init pj4_cp0_init(void)
	pr_info("PJ4 iWMMXt v%d coprocessor enabled.\n", vers);
	elf_hwcap |= HWCAP_IWMMXT;
	thread_register_notifier(&iwmmxt_notifier_block);
	register_iwmmxt_undef_handler();
#endif

	return 0;
+1 −0
Original line number Diff line number Diff line
@@ -166,6 +166,7 @@ static int __init xscale_cp0_init(void)
		pr_info("XScale iWMMXt coprocessor detected.\n");
		elf_hwcap |= HWCAP_IWMMXT;
		thread_register_notifier(&iwmmxt_notifier_block);
		register_iwmmxt_undef_handler();
#endif
	} else {
		pr_info("XScale DSP coprocessor detected.\n");