mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-29 17:22:07 +00:00
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: Linus Walleij <linus.walleij@linaro.org> Signed-off-by: Ard Biesheuvel <ardb@kernel.org>
This commit is contained in:
parent
8bcba70cb5
commit
303d6da167
@ -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 *);
|
||||
|
||||
|
@ -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 )
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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");
|
||||
|
Loading…
Reference in New Issue
Block a user