diff options
author | Akira Takeuchi <takeuchi.akr@jp.panasonic.com> | 2010-10-27 12:28:52 -0400 |
---|---|---|
committer | David Howells <dhowells@redhat.com> | 2010-10-27 12:28:52 -0400 |
commit | 278d91c4609d55202c1e63d5fc5f01466cc7bbab (patch) | |
tree | 8b0c863837508959430c1741e2e5a2d37d2890d4 /arch/mn10300/include/asm/fpu.h | |
parent | 965ea4bbb9ae926358273368144ba838c561bc38 (diff) |
MN10300: Make the FPU operate in non-lazy mode under SMP
Make the FPU operate in non-lazy mode under SMP so that when the process that
is currently using the FPU migrates to a different CPU, we don't have to ping
its previous CPU to flush the FPU context.
Signed-off-by: Akira Takeuchi <takeuchi.akr@jp.panasonic.com>
Signed-off-by: Kiyoshi Owada <owada.kiyoshi@jp.panasonic.com>
Signed-off-by: David Howells <dhowells@redhat.com>
Diffstat (limited to 'arch/mn10300/include/asm/fpu.h')
-rw-r--r-- | arch/mn10300/include/asm/fpu.h | 157 |
1 files changed, 104 insertions, 53 deletions
diff --git a/arch/mn10300/include/asm/fpu.h b/arch/mn10300/include/asm/fpu.h index 64a2b83a7a6a..b7625de8eade 100644 --- a/arch/mn10300/include/asm/fpu.h +++ b/arch/mn10300/include/asm/fpu.h | |||
@@ -12,74 +12,125 @@ | |||
12 | #ifndef _ASM_FPU_H | 12 | #ifndef _ASM_FPU_H |
13 | #define _ASM_FPU_H | 13 | #define _ASM_FPU_H |
14 | 14 | ||
15 | #include <asm/processor.h> | 15 | #ifndef __ASSEMBLY__ |
16 | |||
17 | #include <linux/sched.h> | ||
18 | #include <asm/exceptions.h> | ||
16 | #include <asm/sigcontext.h> | 19 | #include <asm/sigcontext.h> |
17 | #include <asm/user.h> | ||
18 | 20 | ||
19 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ |
20 | 22 | ||
21 | /* the task that owns the FPU state */ | 23 | extern asmlinkage void fpu_disabled(void); |
24 | |||
25 | #ifdef CONFIG_FPU | ||
26 | |||
27 | #ifdef CONFIG_LAZY_SAVE_FPU | ||
28 | /* the task that currently owns the FPU state */ | ||
22 | extern struct task_struct *fpu_state_owner; | 29 | extern struct task_struct *fpu_state_owner; |
30 | #endif | ||
23 | 31 | ||
24 | #define set_using_fpu(tsk) \ | 32 | #if (THREAD_USING_FPU & ~0xff) |
25 | do { \ | 33 | #error THREAD_USING_FPU must be smaller than 0x100. |
26 | (tsk)->thread.fpu_flags |= THREAD_USING_FPU; \ | 34 | #endif |
27 | } while (0) | ||
28 | 35 | ||
29 | #define clear_using_fpu(tsk) \ | 36 | static inline void set_using_fpu(struct task_struct *tsk) |
30 | do { \ | 37 | { |
31 | (tsk)->thread.fpu_flags &= ~THREAD_USING_FPU; \ | 38 | asm volatile( |
32 | } while (0) | 39 | "bset %0,(0,%1)" |
40 | : | ||
41 | : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags) | ||
42 | : "memory", "cc"); | ||
43 | } | ||
33 | 44 | ||
34 | #define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU) | 45 | static inline void clear_using_fpu(struct task_struct *tsk) |
46 | { | ||
47 | asm volatile( | ||
48 | "bclr %0,(0,%1)" | ||
49 | : | ||
50 | : "i"(THREAD_USING_FPU), "a"(&tsk->thread.fpu_flags) | ||
51 | : "memory", "cc"); | ||
52 | } | ||
35 | 53 | ||
36 | #define unlazy_fpu(tsk) \ | 54 | #define is_using_fpu(tsk) ((tsk)->thread.fpu_flags & THREAD_USING_FPU) |
37 | do { \ | ||
38 | preempt_disable(); \ | ||
39 | if (fpu_state_owner == (tsk)) \ | ||
40 | fpu_save(&tsk->thread.fpu_state); \ | ||
41 | preempt_enable(); \ | ||
42 | } while (0) | ||
43 | |||
44 | #define exit_fpu() \ | ||
45 | do { \ | ||
46 | struct task_struct *__tsk = current; \ | ||
47 | preempt_disable(); \ | ||
48 | if (fpu_state_owner == __tsk) \ | ||
49 | fpu_state_owner = NULL; \ | ||
50 | preempt_enable(); \ | ||
51 | } while (0) | ||
52 | |||
53 | #define flush_fpu() \ | ||
54 | do { \ | ||
55 | struct task_struct *__tsk = current; \ | ||
56 | preempt_disable(); \ | ||
57 | if (fpu_state_owner == __tsk) { \ | ||
58 | fpu_state_owner = NULL; \ | ||
59 | __tsk->thread.uregs->epsw &= ~EPSW_FE; \ | ||
60 | } \ | ||
61 | preempt_enable(); \ | ||
62 | clear_using_fpu(__tsk); \ | ||
63 | } while (0) | ||
64 | 55 | ||
65 | extern asmlinkage void fpu_init_state(void); | ||
66 | extern asmlinkage void fpu_kill_state(struct task_struct *); | 56 | extern asmlinkage void fpu_kill_state(struct task_struct *); |
67 | extern asmlinkage void fpu_disabled(struct pt_regs *, enum exception_code); | ||
68 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); | 57 | extern asmlinkage void fpu_exception(struct pt_regs *, enum exception_code); |
69 | 58 | extern asmlinkage void fpu_invalid_op(struct pt_regs *, enum exception_code); | |
70 | #ifdef CONFIG_FPU | 59 | extern asmlinkage void fpu_init_state(void); |
71 | extern asmlinkage void fpu_save(struct fpu_state_struct *); | 60 | extern asmlinkage void fpu_save(struct fpu_state_struct *); |
72 | extern asmlinkage void fpu_restore(struct fpu_state_struct *); | ||
73 | #else | ||
74 | #define fpu_save(a) | ||
75 | #define fpu_restore(a) | ||
76 | #endif /* CONFIG_FPU */ | ||
77 | |||
78 | /* | ||
79 | * signal frame handlers | ||
80 | */ | ||
81 | extern int fpu_setup_sigcontext(struct fpucontext *buf); | 61 | extern int fpu_setup_sigcontext(struct fpucontext *buf); |
82 | extern int fpu_restore_sigcontext(struct fpucontext *buf); | 62 | extern int fpu_restore_sigcontext(struct fpucontext *buf); |
83 | 63 | ||
64 | static inline void unlazy_fpu(struct task_struct *tsk) | ||
65 | { | ||
66 | preempt_disable(); | ||
67 | #ifndef CONFIG_LAZY_SAVE_FPU | ||
68 | if (tsk->thread.fpu_flags & THREAD_HAS_FPU) { | ||
69 | fpu_save(&tsk->thread.fpu_state); | ||
70 | tsk->thread.fpu_flags &= ~THREAD_HAS_FPU; | ||
71 | tsk->thread.uregs->epsw &= ~EPSW_FE; | ||
72 | } | ||
73 | #else | ||
74 | if (fpu_state_owner == tsk) | ||
75 | fpu_save(&tsk->thread.fpu_state); | ||
76 | #endif | ||
77 | preempt_enable(); | ||
78 | } | ||
79 | |||
80 | static inline void exit_fpu(void) | ||
81 | { | ||
82 | #ifdef CONFIG_LAZY_SAVE_FPU | ||
83 | struct task_struct *tsk = current; | ||
84 | |||
85 | preempt_disable(); | ||
86 | if (fpu_state_owner == tsk) | ||
87 | fpu_state_owner = NULL; | ||
88 | preempt_enable(); | ||
89 | #endif | ||
90 | } | ||
91 | |||
92 | static inline void flush_fpu(void) | ||
93 | { | ||
94 | struct task_struct *tsk = current; | ||
95 | |||
96 | preempt_disable(); | ||
97 | #ifndef CONFIG_LAZY_SAVE_FPU | ||
98 | if (tsk->thread.fpu_flags & THREAD_HAS_FPU) { | ||
99 | tsk->thread.fpu_flags &= ~THREAD_HAS_FPU; | ||
100 | tsk->thread.uregs->epsw &= ~EPSW_FE; | ||
101 | } | ||
102 | #else | ||
103 | if (fpu_state_owner == tsk) { | ||
104 | fpu_state_owner = NULL; | ||
105 | tsk->thread.uregs->epsw &= ~EPSW_FE; | ||
106 | } | ||
107 | #endif | ||
108 | preempt_enable(); | ||
109 | clear_using_fpu(tsk); | ||
110 | } | ||
111 | |||
112 | #else /* CONFIG_FPU */ | ||
113 | |||
114 | extern asmlinkage | ||
115 | void unexpected_fpu_exception(struct pt_regs *, enum exception_code); | ||
116 | #define fpu_invalid_op unexpected_fpu_exception | ||
117 | #define fpu_exception unexpected_fpu_exception | ||
118 | |||
119 | struct task_struct; | ||
120 | struct fpu_state_struct; | ||
121 | static inline bool is_using_fpu(struct task_struct *tsk) { return false; } | ||
122 | static inline void set_using_fpu(struct task_struct *tsk) {} | ||
123 | static inline void clear_using_fpu(struct task_struct *tsk) {} | ||
124 | static inline void fpu_init_state(void) {} | ||
125 | static inline void fpu_save(struct fpu_state_struct *s) {} | ||
126 | static inline void fpu_kill_state(struct task_struct *tsk) {} | ||
127 | static inline void unlazy_fpu(struct task_struct *tsk) {} | ||
128 | static inline void exit_fpu(void) {} | ||
129 | static inline void flush_fpu(void) {} | ||
130 | static inline int fpu_setup_sigcontext(struct fpucontext *buf) { return 0; } | ||
131 | static inline int fpu_restore_sigcontext(struct fpucontext *buf) { return 0; } | ||
132 | #endif /* CONFIG_FPU */ | ||
133 | |||
84 | #endif /* __KERNEL__ */ | 134 | #endif /* __KERNEL__ */ |
135 | #endif /* !__ASSEMBLY__ */ | ||
85 | #endif /* _ASM_FPU_H */ | 136 | #endif /* _ASM_FPU_H */ |