aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorRussell King <rmk@dyn-67.arm.linux.org.uk>2006-06-21 08:31:52 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2006-06-22 05:24:18 -0400
commitd6551e884cf66de072b81f8b6d23259462c40baf (patch)
treefd8af193bd045e4b16ce911d392d7ffd109d7284 /arch/arm/kernel
parent52ab3f3dc711eeccbfbcc5d4f5c5d9b9ff59650f (diff)
[ARM] Add thread_notify infrastructure
Some machine classes need to allow VFP support to be built into the kernel, but still allow the kernel to run even though VFP isn't present. Unfortunately, the kernel hard-codes VFP instructions into the thread switch, which prevents this being run-time selectable. Solve this by introducing a notifier which things such as VFP can hook into to be informed of events which affect the VFP subsystem (eg, creation and destruction of threads, switches between threads.) Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/entry-armv.S24
-rw-r--r--arch/arm/kernel/iwmmxt.S2
-rw-r--r--arch/arm/kernel/process.c24
3 files changed, 22 insertions, 28 deletions
diff --git a/arch/arm/kernel/entry-armv.S b/arch/arm/kernel/entry-armv.S
index ab8e600c18c8..86c92523a346 100644
--- a/arch/arm/kernel/entry-armv.S
+++ b/arch/arm/kernel/entry-armv.S
@@ -20,6 +20,7 @@
20#include <asm/glue.h> 20#include <asm/glue.h>
21#include <asm/vfpmacros.h> 21#include <asm/vfpmacros.h>
22#include <asm/arch/entry-macro.S> 22#include <asm/arch/entry-macro.S>
23#include <asm/thread_notify.h>
23 24
24#include "entry-header.S" 25#include "entry-header.S"
25 26
@@ -560,10 +561,8 @@ ENTRY(__switch_to)
560 add ip, r1, #TI_CPU_SAVE 561 add ip, r1, #TI_CPU_SAVE
561 ldr r3, [r2, #TI_TP_VALUE] 562 ldr r3, [r2, #TI_TP_VALUE]
562 stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack 563 stmia ip!, {r4 - sl, fp, sp, lr} @ Store most regs on stack
563#ifndef CONFIG_MMU 564#ifdef CONFIG_MMU
564 add r2, r2, #TI_CPU_DOMAIN 565 ldr r6, [r2, #TI_CPU_DOMAIN]
565#else
566 ldr r6, [r2, #TI_CPU_DOMAIN]!
567#endif 566#endif
568#if __LINUX_ARM_ARCH__ >= 6 567#if __LINUX_ARM_ARCH__ >= 6
569#ifdef CONFIG_CPU_32v6K 568#ifdef CONFIG_CPU_32v6K
@@ -585,21 +584,20 @@ ENTRY(__switch_to)
585#ifdef CONFIG_MMU 584#ifdef CONFIG_MMU
586 mcr p15, 0, r6, c3, c0, 0 @ Set domain register 585 mcr p15, 0, r6, c3, c0, 0 @ Set domain register
587#endif 586#endif
588#ifdef CONFIG_VFP
589 @ Always disable VFP so we can lazily save/restore the old
590 @ state. This occurs in the context of the previous thread.
591 VFPFMRX r4, FPEXC
592 bic r4, r4, #FPEXC_ENABLE
593 VFPFMXR FPEXC, r4
594#endif
595#if defined(CONFIG_IWMMXT) 587#if defined(CONFIG_IWMMXT)
596 bl iwmmxt_task_switch 588 bl iwmmxt_task_switch
597#elif defined(CONFIG_CPU_XSCALE) 589#elif defined(CONFIG_CPU_XSCALE)
598 add r4, r2, #40 @ cpu_context_save->extra 590 add r4, r2, #TI_CPU_DOMAIN + 40 @ cpu_context_save->extra
599 ldmib r4, {r4, r5} 591 ldmib r4, {r4, r5}
600 mar acc0, r4, r5 592 mar acc0, r4, r5
601#endif 593#endif
602 ldmib r2, {r4 - sl, fp, sp, pc} @ Load all regs saved previously 594 mov r5, r0
595 add r4, r2, #TI_CPU_SAVE
596 ldr r0, =thread_notify_head
597 mov r1, #THREAD_NOTIFY_SWITCH
598 bl atomic_notifier_call_chain
599 mov r0, r5
600 ldmia r4, {r4 - sl, fp, sp, pc} @ Load all regs saved previously
603 601
604 __INIT 602 __INIT
605 603
diff --git a/arch/arm/kernel/iwmmxt.S b/arch/arm/kernel/iwmmxt.S
index 24c7b0477a09..af9e0ae952d5 100644
--- a/arch/arm/kernel/iwmmxt.S
+++ b/arch/arm/kernel/iwmmxt.S
@@ -285,7 +285,7 @@ ENTRY(iwmmxt_task_switch)
285 bne 1f @ yes: block them for next task 285 bne 1f @ yes: block them for next task
286 286
287 ldr r5, =concan_owner 287 ldr r5, =concan_owner
288 add r6, r2, #(TI_IWMMXT_STATE - TI_CPU_DOMAIN) @ get next task Concan save area 288 add r6, r2, #TI_IWMMXT_STATE @ get next task Concan save area
289 ldr r5, [r5] @ get current Concan owner 289 ldr r5, [r5] @ get current Concan owner
290 teq r5, r6 @ next task owns it? 290 teq r5, r6 @ next task owns it?
291 movne pc, lr @ no: leave Concan disabled 291 movne pc, lr @ no: leave Concan disabled
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 17c38dbf2f3c..e1c77ee885a7 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -33,6 +33,7 @@
33#include <asm/leds.h> 33#include <asm/leds.h>
34#include <asm/processor.h> 34#include <asm/processor.h>
35#include <asm/system.h> 35#include <asm/system.h>
36#include <asm/thread_notify.h>
36#include <asm/uaccess.h> 37#include <asm/uaccess.h>
37#include <asm/mach/time.h> 38#include <asm/mach/time.h>
38 39
@@ -338,13 +339,9 @@ void exit_thread(void)
338{ 339{
339} 340}
340 341
341static void default_fp_init(union fp_state *fp) 342ATOMIC_NOTIFIER_HEAD(thread_notify_head);
342{
343 memset(fp, 0, sizeof(union fp_state));
344}
345 343
346void (*fp_init)(union fp_state *) = default_fp_init; 344EXPORT_SYMBOL_GPL(thread_notify_head);
347EXPORT_SYMBOL(fp_init);
348 345
349void flush_thread(void) 346void flush_thread(void)
350{ 347{
@@ -353,22 +350,21 @@ void flush_thread(void)
353 350
354 memset(thread->used_cp, 0, sizeof(thread->used_cp)); 351 memset(thread->used_cp, 0, sizeof(thread->used_cp));
355 memset(&tsk->thread.debug, 0, sizeof(struct debug_info)); 352 memset(&tsk->thread.debug, 0, sizeof(struct debug_info));
353 memset(&thread->fpstate, 0, sizeof(union fp_state));
354
355 thread_notify(THREAD_NOTIFY_FLUSH, thread);
356#if defined(CONFIG_IWMMXT) 356#if defined(CONFIG_IWMMXT)
357 iwmmxt_task_release(thread); 357 iwmmxt_task_release(thread);
358#endif 358#endif
359 fp_init(&thread->fpstate);
360#if defined(CONFIG_VFP)
361 vfp_flush_thread(&thread->vfpstate);
362#endif
363} 359}
364 360
365void release_thread(struct task_struct *dead_task) 361void release_thread(struct task_struct *dead_task)
366{ 362{
367#if defined(CONFIG_VFP) 363 struct thread_info *thread = task_thread_info(dead_task);
368 vfp_release_thread(&task_thread_info(dead_task)->vfpstate); 364
369#endif 365 thread_notify(THREAD_NOTIFY_RELEASE, thread);
370#if defined(CONFIG_IWMMXT) 366#if defined(CONFIG_IWMMXT)
371 iwmmxt_task_release(task_thread_info(dead_task)); 367 iwmmxt_task_release(thread);
372#endif 368#endif
373} 369}
374 370