From ae95bfbb2b67eba5d67a0478a8715682a87e2616 Mon Sep 17 00:00:00 2001 From: Lennert Buytenhek Date: Sat, 1 Jul 2006 19:56:48 +0100 Subject: [PATCH] [ARM] 3707/1: iwmmxt: use the generic thread notifier infrastructure Patch from Lennert Buytenhek This patch makes the iWMMXt context switch hook use the generic thread notifier infrastructure that was recently merged in commit d6551e884cf66de072b81f8b6d23259462c40baf. Signed-off-by: Lennert Buytenhek Signed-off-by: Russell King --- arch/arm/kernel/Makefile | 2 +- arch/arm/kernel/entry-armv.S | 4 +- arch/arm/kernel/iwmmxt-notifier.c | 64 +++++++++++++++++++++++++++++++ arch/arm/kernel/iwmmxt.S | 27 ++++++------- arch/arm/kernel/process.c | 6 --- include/asm-arm/thread_info.h | 1 + 6 files changed, 79 insertions(+), 25 deletions(-) create mode 100644 arch/arm/kernel/iwmmxt-notifier.c diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile index 7cffbaef06..f0c0cdb1c1 100644 --- a/arch/arm/kernel/Makefile +++ b/arch/arm/kernel/Makefile @@ -25,7 +25,7 @@ obj-$(CONFIG_OABI_COMPAT) += sys_oabi-compat.o obj-$(CONFIG_CRUNCH) += crunch.o crunch-bits.o AFLAGS_crunch-bits.o := -Wa,-mcpu=ep9312 -obj-$(CONFIG_IWMMXT) += iwmmxt.o +obj-$(CONFIG_IWMMXT) += iwmmxt.o iwmmxt-notifier.o AFLAGS_iwmmxt.o := -Wa,-mcpu=iwmmxt ifneq ($(CONFIG_ARCH_EBSA110),y) diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S index 6423a38839..0e8aeaf9ff 100644 --- a/arch/arm/kernel/entry-armv.S +++ b/arch/arm/kernel/entry-armv.S @@ -590,9 +590,7 @@ ENTRY(__switch_to) #ifdef CONFIG_MMU mcr p15, 0, r6, c3, c0, 0 @ Set domain register #endif -#if defined(CONFIG_IWMMXT) - bl iwmmxt_task_switch -#elif defined(CONFIG_CPU_XSCALE) +#if defined(CONFIG_CPU_XSCALE) && !defined(CONFIG_IWMMXT) add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra ldmib r4, {r4, r5} mar acc0, r4, r5 diff --git a/arch/arm/kernel/iwmmxt-notifier.c b/arch/arm/kernel/iwmmxt-notifier.c new file mode 100644 index 0000000000..44a86c3379 --- /dev/null +++ b/arch/arm/kernel/iwmmxt-notifier.c @@ -0,0 +1,64 @@ +/* + * linux/arch/arm/kernel/iwmmxt-notifier.c + * + * XScale iWMMXt (Concan) context switching and handling + * + * Initial code: + * Copyright (c) 2003, Intel Corporation + * + * Full lazy switching support, optimizations and more, by Nicolas Pitre + * Copyright (c) 2003-2004, MontaVista Software, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +static int iwmmxt_do(struct notifier_block *self, unsigned long cmd, void *t) +{ + struct thread_info *thread = t; + + switch (cmd) { + case THREAD_NOTIFY_FLUSH: + /* + * flush_thread() zeroes thread->fpstate, so no need + * to do anything here. + * + * FALLTHROUGH: Ensure we don't try to overwrite our newly + * initialised state information on the first fault. + */ + + case THREAD_NOTIFY_RELEASE: + iwmmxt_task_release(thread); + break; + + case THREAD_NOTIFY_SWITCH: + iwmmxt_task_switch(thread); + break; + } + + return NOTIFY_DONE; +} + +static struct notifier_block iwmmxt_notifier_block = { + .notifier_call = iwmmxt_do, +}; + +static int __init iwmmxt_init(void) +{ + thread_register_notifier(&iwmmxt_notifier_block); + + return 0; +} + +late_initcall(iwmmxt_init); diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S index a3bae95e53..b63b528f22 100644 --- a/arch/arm/kernel/iwmmxt.S +++ b/arch/arm/kernel/iwmmxt.S @@ -271,30 +271,27 @@ ENTRY(iwmmxt_task_restore) /* * Concan handling on task switch * - * r0 = previous task_struct pointer (must be preserved) - * r1 = previous thread_info pointer - * r2 = next thread_info pointer (must be preserved) + * r0 = next thread_info pointer * - * Called only from __switch_to with task preemption disabled. - * No need to care about preserving r4 and above. + * Called only from the iwmmxt notifier with task preemption disabled. */ ENTRY(iwmmxt_task_switch) - mrc p15, 0, r4, c15, c1, 0 - tst r4, #0x3 @ CP0 and CP1 accessible? + mrc p15, 0, r1, c15, c1, 0 + tst r1, #0x3 @ CP0 and CP1 accessible? bne 1f @ yes: block them for next task - ldr r5, =concan_owner - add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area - ldr r5, [r5] @ get current Concan owner - teq r5, r6 @ next task owns it? + ldr r2, =concan_owner + add r3, r0, #TI_IWMMXT_STATE @ get next task Concan save area + ldr r2, [r2] @ get current Concan owner + teq r2, r3 @ next task owns it? movne pc, lr @ no: leave Concan disabled -1: eor r4, r4, #3 @ flip Concan access - mcr p15, 0, r4, c15, c1, 0 +1: eor r1, r1, #3 @ flip Concan access + mcr p15, 0, r1, c15, c1, 0 - mrc p15, 0, r4, c2, c0, 0 - sub pc, lr, r4, lsr #32 @ cpwait and return + mrc p15, 0, r1, c2, c0, 0 + sub pc, lr, r1, lsr #32 @ cpwait and return /* * Remove Concan ownership of given task diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index e1c77ee885..b5773a2549 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c @@ -353,9 +353,6 @@ void flush_thread(void) memset(&thread->fpstate, 0, sizeof(union fp_state)); thread_notify(THREAD_NOTIFY_FLUSH, thread); -#if defined(CONFIG_IWMMXT) - iwmmxt_task_release(thread); -#endif } void release_thread(struct task_struct *dead_task) @@ -363,9 +360,6 @@ void release_thread(struct task_struct *dead_task) struct thread_info *thread = task_thread_info(dead_task); thread_notify(THREAD_NOTIFY_RELEASE, thread); -#if defined(CONFIG_IWMMXT) - iwmmxt_task_release(thread); -#endif } asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); diff --git a/include/asm-arm/thread_info.h b/include/asm-arm/thread_info.h index c46b5c8427..c52e0bf753 100644 --- a/include/asm-arm/thread_info.h +++ b/include/asm-arm/thread_info.h @@ -111,6 +111,7 @@ extern void iwmmxt_task_disable(struct thread_info *); extern void iwmmxt_task_copy(struct thread_info *, void *); 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 *); #endif -- 2.39.5