diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 13:59:07 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2012-05-23 13:59:07 -0400 |
commit | ec0d7f18ab7b5097d7c0c8f3d909ca1031b9d5cd (patch) | |
tree | 7d62c924592145f819ecaa5d60460a05a10dfdbd | |
parent | 269af9a1a08d368b46d72e74126564d04c354f7e (diff) | |
parent | 1dcc8d7ba235a316a056f993e88f0d18b92c60d9 (diff) |
Merge branch 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull fpu state cleanups from Ingo Molnar:
"This tree streamlines further aspects of FPU handling by eliminating
the prepare_to_copy() complication and moving that logic to
arch_dup_task_struct().
It also fixes the FPU dumps in threaded core dumps, removes and old
(and now invalid) assumption plus micro-optimizes the exit path by
avoiding an FPU save for dead tasks."
Fixed up trivial add-add conflict in arch/sh/kernel/process.c that came
in because we now do the FPU handling in arch_dup_task_struct() rather
than the legacy (and now gone) prepare_to_copy().
* 'x86-fpu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86, fpu: drop the fpu state during thread exit
x86, xsave: remove thread_has_fpu() bug check in __sanitize_i387_state()
coredump: ensure the fpu state is flushed for proper multi-threaded core dump
fork: move the real prepare_to_copy() users to arch_dup_task_struct()
41 files changed, 63 insertions, 149 deletions
diff --git a/arch/alpha/include/asm/processor.h b/arch/alpha/include/asm/processor.h index 94afe5859301..e37b887b3d9f 100644 --- a/arch/alpha/include/asm/processor.h +++ b/arch/alpha/include/asm/processor.h | |||
@@ -49,9 +49,6 @@ extern void start_thread(struct pt_regs *, unsigned long, unsigned long); | |||
49 | /* Free all resources held by a thread. */ | 49 | /* Free all resources held by a thread. */ |
50 | extern void release_thread(struct task_struct *); | 50 | extern void release_thread(struct task_struct *); |
51 | 51 | ||
52 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
53 | #define prepare_to_copy(tsk) do { } while (0) | ||
54 | |||
55 | /* Create a kernel thread without removing it from tasklists. */ | 52 | /* Create a kernel thread without removing it from tasklists. */ |
56 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | 53 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
57 | 54 | ||
diff --git a/arch/arm/include/asm/processor.h b/arch/arm/include/asm/processor.h index d7038fa22343..99afa7498260 100644 --- a/arch/arm/include/asm/processor.h +++ b/arch/arm/include/asm/processor.h | |||
@@ -77,9 +77,6 @@ struct task_struct; | |||
77 | /* Free all resources held by a thread. */ | 77 | /* Free all resources held by a thread. */ |
78 | extern void release_thread(struct task_struct *); | 78 | extern void release_thread(struct task_struct *); |
79 | 79 | ||
80 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
81 | #define prepare_to_copy(tsk) do { } while (0) | ||
82 | |||
83 | unsigned long get_wchan(struct task_struct *p); | 80 | unsigned long get_wchan(struct task_struct *p); |
84 | 81 | ||
85 | #if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327) | 82 | #if __LINUX_ARM_ARCH__ == 6 || defined(CONFIG_ARM_ERRATA_754327) |
diff --git a/arch/avr32/include/asm/processor.h b/arch/avr32/include/asm/processor.h index 108502bc6770..87d8baccc60e 100644 --- a/arch/avr32/include/asm/processor.h +++ b/arch/avr32/include/asm/processor.h | |||
@@ -145,9 +145,6 @@ extern void release_thread(struct task_struct *); | |||
145 | /* Create a kernel thread without removing it from tasklists */ | 145 | /* Create a kernel thread without removing it from tasklists */ |
146 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | 146 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
147 | 147 | ||
148 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
149 | #define prepare_to_copy(tsk) do { } while(0) | ||
150 | |||
151 | /* Return saved PC of a blocked thread */ | 148 | /* Return saved PC of a blocked thread */ |
152 | #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) | 149 | #define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc) |
153 | 150 | ||
diff --git a/arch/blackfin/include/asm/processor.h b/arch/blackfin/include/asm/processor.h index 8af7772e84cc..4ef7cfe43ceb 100644 --- a/arch/blackfin/include/asm/processor.h +++ b/arch/blackfin/include/asm/processor.h | |||
@@ -75,8 +75,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
75 | { | 75 | { |
76 | } | 76 | } |
77 | 77 | ||
78 | #define prepare_to_copy(tsk) do { } while (0) | ||
79 | |||
80 | extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags); | 78 | extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags); |
81 | 79 | ||
82 | /* | 80 | /* |
diff --git a/arch/c6x/include/asm/processor.h b/arch/c6x/include/asm/processor.h index 3ff7fab956ba..c50af7ef1c96 100644 --- a/arch/c6x/include/asm/processor.h +++ b/arch/c6x/include/asm/processor.h | |||
@@ -92,9 +92,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
92 | { | 92 | { |
93 | } | 93 | } |
94 | 94 | ||
95 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
96 | #define prepare_to_copy(tsk) do { } while (0) | ||
97 | |||
98 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 95 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
99 | 96 | ||
100 | #define copy_segments(tsk, mm) do { } while (0) | 97 | #define copy_segments(tsk, mm) do { } while (0) |
diff --git a/arch/cris/include/asm/processor.h b/arch/cris/include/asm/processor.h index 8dc56ef08712..ef4e1bc3efc8 100644 --- a/arch/cris/include/asm/processor.h +++ b/arch/cris/include/asm/processor.h | |||
@@ -49,10 +49,6 @@ struct task_struct; | |||
49 | #define task_pt_regs(task) user_regs(task_thread_info(task)) | 49 | #define task_pt_regs(task) user_regs(task_thread_info(task)) |
50 | #define current_regs() task_pt_regs(current) | 50 | #define current_regs() task_pt_regs(current) |
51 | 51 | ||
52 | static inline void prepare_to_copy(struct task_struct *tsk) | ||
53 | { | ||
54 | } | ||
55 | |||
56 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 52 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
57 | 53 | ||
58 | unsigned long get_wchan(struct task_struct *p); | 54 | unsigned long get_wchan(struct task_struct *p); |
diff --git a/arch/frv/include/asm/processor.h b/arch/frv/include/asm/processor.h index 9b1a92b73f60..a8311d364e2a 100644 --- a/arch/frv/include/asm/processor.h +++ b/arch/frv/include/asm/processor.h | |||
@@ -103,8 +103,6 @@ do { \ | |||
103 | __frame->sp = (_usp); \ | 103 | __frame->sp = (_usp); \ |
104 | } while(0) | 104 | } while(0) |
105 | 105 | ||
106 | extern void prepare_to_copy(struct task_struct *tsk); | ||
107 | |||
108 | /* Free all resources held by a thread. */ | 106 | /* Free all resources held by a thread. */ |
109 | static inline void release_thread(struct task_struct *dead_task) | 107 | static inline void release_thread(struct task_struct *dead_task) |
110 | { | 108 | { |
diff --git a/arch/frv/kernel/process.c b/arch/frv/kernel/process.c index ed09e9e2c653..ff95f50efea5 100644 --- a/arch/frv/kernel/process.c +++ b/arch/frv/kernel/process.c | |||
@@ -165,17 +165,6 @@ asmlinkage int sys_clone(unsigned long clone_flags, unsigned long newsp, | |||
165 | return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr); | 165 | return do_fork(clone_flags, newsp, __frame, 0, parent_tidptr, child_tidptr); |
166 | } /* end sys_clone() */ | 166 | } /* end sys_clone() */ |
167 | 167 | ||
168 | /*****************************************************************************/ | ||
169 | /* | ||
170 | * This gets called before we allocate a new thread and copy | ||
171 | * the current task into it. | ||
172 | */ | ||
173 | void prepare_to_copy(struct task_struct *tsk) | ||
174 | { | ||
175 | //unlazy_fpu(tsk); | ||
176 | } /* end prepare_to_copy() */ | ||
177 | |||
178 | /*****************************************************************************/ | ||
179 | /* | 168 | /* |
180 | * set up the kernel stack and exception frames for a new process | 169 | * set up the kernel stack and exception frames for a new process |
181 | */ | 170 | */ |
diff --git a/arch/h8300/include/asm/processor.h b/arch/h8300/include/asm/processor.h index 61fabf1788c6..4c9f6f87b617 100644 --- a/arch/h8300/include/asm/processor.h +++ b/arch/h8300/include/asm/processor.h | |||
@@ -109,8 +109,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
109 | 109 | ||
110 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 110 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
111 | 111 | ||
112 | #define prepare_to_copy(tsk) do { } while (0) | ||
113 | |||
114 | /* | 112 | /* |
115 | * Free current thread data structures etc.. | 113 | * Free current thread data structures etc.. |
116 | */ | 114 | */ |
diff --git a/arch/hexagon/include/asm/processor.h b/arch/hexagon/include/asm/processor.h index 20c5ddabbd8b..e8ea459002a4 100644 --- a/arch/hexagon/include/asm/processor.h +++ b/arch/hexagon/include/asm/processor.h | |||
@@ -59,13 +59,6 @@ struct thread_struct { | |||
59 | #define cpu_relax() __vmyield() | 59 | #define cpu_relax() __vmyield() |
60 | 60 | ||
61 | /* | 61 | /* |
62 | * "Unlazying all lazy status" occurs here. | ||
63 | */ | ||
64 | static inline void prepare_to_copy(struct task_struct *tsk) | ||
65 | { | ||
66 | } | ||
67 | |||
68 | /* | ||
69 | * Decides where the kernel will search for a free chunk of vm space during | 62 | * Decides where the kernel will search for a free chunk of vm space during |
70 | * mmaps. | 63 | * mmaps. |
71 | * See also arch_get_unmapped_area. | 64 | * See also arch_get_unmapped_area. |
diff --git a/arch/ia64/include/asm/processor.h b/arch/ia64/include/asm/processor.h index f92f67aba618..5a994ec8f06d 100644 --- a/arch/ia64/include/asm/processor.h +++ b/arch/ia64/include/asm/processor.h | |||
@@ -343,9 +343,6 @@ struct task_struct; | |||
343 | */ | 343 | */ |
344 | #define release_thread(dead_task) | 344 | #define release_thread(dead_task) |
345 | 345 | ||
346 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
347 | #define prepare_to_copy(tsk) do { } while (0) | ||
348 | |||
349 | /* | 346 | /* |
350 | * This is the mechanism for creating a new kernel thread. | 347 | * This is the mechanism for creating a new kernel thread. |
351 | * | 348 | * |
diff --git a/arch/m32r/include/asm/processor.h b/arch/m32r/include/asm/processor.h index e1f46d757460..da17253b5735 100644 --- a/arch/m32r/include/asm/processor.h +++ b/arch/m32r/include/asm/processor.h | |||
@@ -118,8 +118,6 @@ struct mm_struct; | |||
118 | /* Free all resources held by a thread. */ | 118 | /* Free all resources held by a thread. */ |
119 | extern void release_thread(struct task_struct *); | 119 | extern void release_thread(struct task_struct *); |
120 | 120 | ||
121 | #define prepare_to_copy(tsk) do { } while (0) | ||
122 | |||
123 | /* | 121 | /* |
124 | * create a kernel thread without removing it from tasklists | 122 | * create a kernel thread without removing it from tasklists |
125 | */ | 123 | */ |
diff --git a/arch/m68k/include/asm/processor.h b/arch/m68k/include/asm/processor.h index 46460fa15d5c..f17c42aff7ff 100644 --- a/arch/m68k/include/asm/processor.h +++ b/arch/m68k/include/asm/processor.h | |||
@@ -153,9 +153,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
153 | { | 153 | { |
154 | } | 154 | } |
155 | 155 | ||
156 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
157 | #define prepare_to_copy(tsk) do { } while (0) | ||
158 | |||
159 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 156 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
160 | 157 | ||
161 | /* | 158 | /* |
diff --git a/arch/microblaze/include/asm/processor.h b/arch/microblaze/include/asm/processor.h index bffb54527299..af2bb9652392 100644 --- a/arch/microblaze/include/asm/processor.h +++ b/arch/microblaze/include/asm/processor.h | |||
@@ -23,7 +23,6 @@ extern const struct seq_operations cpuinfo_op; | |||
23 | 23 | ||
24 | # define cpu_relax() barrier() | 24 | # define cpu_relax() barrier() |
25 | # define cpu_sleep() do {} while (0) | 25 | # define cpu_sleep() do {} while (0) |
26 | # define prepare_to_copy(tsk) do {} while (0) | ||
27 | 26 | ||
28 | #define task_pt_regs(tsk) \ | 27 | #define task_pt_regs(tsk) \ |
29 | (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1) | 28 | (((struct pt_regs *)(THREAD_SIZE + task_stack_page(tsk))) - 1) |
diff --git a/arch/mips/include/asm/processor.h b/arch/mips/include/asm/processor.h index 20e9dcf42b27..5e33fabe354d 100644 --- a/arch/mips/include/asm/processor.h +++ b/arch/mips/include/asm/processor.h | |||
@@ -310,9 +310,6 @@ struct task_struct; | |||
310 | /* Free all resources held by a thread. */ | 310 | /* Free all resources held by a thread. */ |
311 | #define release_thread(thread) do { } while(0) | 311 | #define release_thread(thread) do { } while(0) |
312 | 312 | ||
313 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
314 | #define prepare_to_copy(tsk) do { } while (0) | ||
315 | |||
316 | extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 313 | extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
317 | 314 | ||
318 | extern unsigned long thread_saved_pc(struct task_struct *tsk); | 315 | extern unsigned long thread_saved_pc(struct task_struct *tsk); |
diff --git a/arch/mn10300/include/asm/processor.h b/arch/mn10300/include/asm/processor.h index f7b3c9ab2cb5..247928c9f549 100644 --- a/arch/mn10300/include/asm/processor.h +++ b/arch/mn10300/include/asm/processor.h | |||
@@ -139,9 +139,6 @@ static inline void start_thread(struct pt_regs *regs, | |||
139 | /* Free all resources held by a thread. */ | 139 | /* Free all resources held by a thread. */ |
140 | extern void release_thread(struct task_struct *); | 140 | extern void release_thread(struct task_struct *); |
141 | 141 | ||
142 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
143 | extern void prepare_to_copy(struct task_struct *tsk); | ||
144 | |||
145 | /* | 142 | /* |
146 | * create a kernel thread without removing it from tasklists | 143 | * create a kernel thread without removing it from tasklists |
147 | */ | 144 | */ |
diff --git a/arch/mn10300/kernel/process.c b/arch/mn10300/kernel/process.c index 14707f25153b..7dab0cd36466 100644 --- a/arch/mn10300/kernel/process.c +++ b/arch/mn10300/kernel/process.c | |||
@@ -208,12 +208,14 @@ void copy_segments(struct task_struct *p, struct mm_struct *new_mm) | |||
208 | } | 208 | } |
209 | 209 | ||
210 | /* | 210 | /* |
211 | * this gets called before we allocate a new thread and copy the current task | 211 | * this gets called so that we can store lazy state into memory and copy the |
212 | * into it so that we can store lazy state into memory | 212 | * current task into the new thread. |
213 | */ | 213 | */ |
214 | void prepare_to_copy(struct task_struct *tsk) | 214 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
215 | { | 215 | { |
216 | unlazy_fpu(tsk); | 216 | unlazy_fpu(src); |
217 | *dst = *src; | ||
218 | return 0; | ||
217 | } | 219 | } |
218 | 220 | ||
219 | /* | 221 | /* |
diff --git a/arch/openrisc/include/asm/processor.h b/arch/openrisc/include/asm/processor.h index f7516fa78b58..30462f1fe959 100644 --- a/arch/openrisc/include/asm/processor.h +++ b/arch/openrisc/include/asm/processor.h | |||
@@ -72,10 +72,6 @@ struct thread_struct { | |||
72 | #define task_pt_regs(task) user_regs(task_thread_info(task)) | 72 | #define task_pt_regs(task) user_regs(task_thread_info(task)) |
73 | #define current_regs() user_regs(current_thread_info()) | 73 | #define current_regs() user_regs(current_thread_info()) |
74 | 74 | ||
75 | extern inline void prepare_to_copy(struct task_struct *tsk) | ||
76 | { | ||
77 | } | ||
78 | |||
79 | #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) | 75 | #define INIT_SP (sizeof(init_stack) + (unsigned long) &init_stack) |
80 | 76 | ||
81 | #define INIT_THREAD { } | 77 | #define INIT_THREAD { } |
diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index acdf4cad6125..0e8b7b8ce8a2 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h | |||
@@ -328,9 +328,6 @@ struct mm_struct; | |||
328 | extern void release_thread(struct task_struct *); | 328 | extern void release_thread(struct task_struct *); |
329 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 329 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
330 | 330 | ||
331 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
332 | #define prepare_to_copy(tsk) do { } while (0) | ||
333 | |||
334 | extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); | 331 | extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); |
335 | 332 | ||
336 | extern unsigned long get_wchan(struct task_struct *p); | 333 | extern unsigned long get_wchan(struct task_struct *p); |
diff --git a/arch/powerpc/include/asm/processor.h b/arch/powerpc/include/asm/processor.h index 48a26d379222..55e85631c42e 100644 --- a/arch/powerpc/include/asm/processor.h +++ b/arch/powerpc/include/asm/processor.h | |||
@@ -74,9 +74,6 @@ struct task_struct; | |||
74 | void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); | 74 | void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); |
75 | void release_thread(struct task_struct *); | 75 | void release_thread(struct task_struct *); |
76 | 76 | ||
77 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
78 | extern void prepare_to_copy(struct task_struct *tsk); | ||
79 | |||
80 | /* Create a new kernel thread. */ | 77 | /* Create a new kernel thread. */ |
81 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | 78 | extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
82 | 79 | ||
diff --git a/arch/powerpc/kernel/process.c b/arch/powerpc/kernel/process.c index 7f8ec1de0ace..710f400476de 100644 --- a/arch/powerpc/kernel/process.c +++ b/arch/powerpc/kernel/process.c | |||
@@ -711,18 +711,21 @@ release_thread(struct task_struct *t) | |||
711 | } | 711 | } |
712 | 712 | ||
713 | /* | 713 | /* |
714 | * This gets called before we allocate a new thread and copy | 714 | * this gets called so that we can store coprocessor state into memory and |
715 | * the current task into it. | 715 | * copy the current task into the new thread. |
716 | */ | 716 | */ |
717 | void prepare_to_copy(struct task_struct *tsk) | 717 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
718 | { | 718 | { |
719 | flush_fp_to_thread(current); | 719 | flush_fp_to_thread(src); |
720 | flush_altivec_to_thread(current); | 720 | flush_altivec_to_thread(src); |
721 | flush_vsx_to_thread(current); | 721 | flush_vsx_to_thread(src); |
722 | flush_spe_to_thread(current); | 722 | flush_spe_to_thread(src); |
723 | #ifdef CONFIG_HAVE_HW_BREAKPOINT | 723 | #ifdef CONFIG_HAVE_HW_BREAKPOINT |
724 | flush_ptrace_hw_breakpoint(tsk); | 724 | flush_ptrace_hw_breakpoint(src); |
725 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ | 725 | #endif /* CONFIG_HAVE_HW_BREAKPOINT */ |
726 | |||
727 | *dst = *src; | ||
728 | return 0; | ||
726 | } | 729 | } |
727 | 730 | ||
728 | /* | 731 | /* |
diff --git a/arch/s390/include/asm/processor.h b/arch/s390/include/asm/processor.h index d499b30ea487..6cbf31311673 100644 --- a/arch/s390/include/asm/processor.h +++ b/arch/s390/include/asm/processor.h | |||
@@ -141,9 +141,6 @@ struct seq_file; | |||
141 | extern void release_thread(struct task_struct *); | 141 | extern void release_thread(struct task_struct *); |
142 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 142 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
143 | 143 | ||
144 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
145 | #define prepare_to_copy(tsk) do { } while (0) | ||
146 | |||
147 | /* | 144 | /* |
148 | * Return saved PC of a blocked thread. | 145 | * Return saved PC of a blocked thread. |
149 | */ | 146 | */ |
diff --git a/arch/score/include/asm/processor.h b/arch/score/include/asm/processor.h index 7e22f216d771..ab3aceb54209 100644 --- a/arch/score/include/asm/processor.h +++ b/arch/score/include/asm/processor.h | |||
@@ -26,7 +26,6 @@ extern unsigned long get_wchan(struct task_struct *p); | |||
26 | 26 | ||
27 | #define cpu_relax() barrier() | 27 | #define cpu_relax() barrier() |
28 | #define release_thread(thread) do {} while (0) | 28 | #define release_thread(thread) do {} while (0) |
29 | #define prepare_to_copy(tsk) do {} while (0) | ||
30 | 29 | ||
31 | /* | 30 | /* |
32 | * User space process size: 2GB. This is hardcoded into a few places, | 31 | * User space process size: 2GB. This is hardcoded into a few places, |
diff --git a/arch/sh/include/asm/processor_32.h b/arch/sh/include/asm/processor_32.h index 900f8d72ffe2..b6311fd2d066 100644 --- a/arch/sh/include/asm/processor_32.h +++ b/arch/sh/include/asm/processor_32.h | |||
@@ -126,9 +126,6 @@ extern void start_thread(struct pt_regs *regs, unsigned long new_pc, unsigned lo | |||
126 | /* Free all resources held by a thread. */ | 126 | /* Free all resources held by a thread. */ |
127 | extern void release_thread(struct task_struct *); | 127 | extern void release_thread(struct task_struct *); |
128 | 128 | ||
129 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
130 | void prepare_to_copy(struct task_struct *tsk); | ||
131 | |||
132 | /* | 129 | /* |
133 | * create a kernel thread without removing it from tasklists | 130 | * create a kernel thread without removing it from tasklists |
134 | */ | 131 | */ |
diff --git a/arch/sh/include/asm/processor_64.h b/arch/sh/include/asm/processor_64.h index 740e26876596..cd6029fb2c01 100644 --- a/arch/sh/include/asm/processor_64.h +++ b/arch/sh/include/asm/processor_64.h | |||
@@ -169,7 +169,6 @@ extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | |||
169 | #define copy_segments(p, mm) do { } while (0) | 169 | #define copy_segments(p, mm) do { } while (0) |
170 | #define release_segments(mm) do { } while (0) | 170 | #define release_segments(mm) do { } while (0) |
171 | #define forget_segments() do { } while (0) | 171 | #define forget_segments() do { } while (0) |
172 | #define prepare_to_copy(tsk) do { } while (0) | ||
173 | /* | 172 | /* |
174 | * FPU lazy state save handling. | 173 | * FPU lazy state save handling. |
175 | */ | 174 | */ |
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c index e77feaf117ab..9b7a459a4613 100644 --- a/arch/sh/kernel/process.c +++ b/arch/sh/kernel/process.c | |||
@@ -13,8 +13,15 @@ unsigned long __stack_chk_guard __read_mostly; | |||
13 | EXPORT_SYMBOL(__stack_chk_guard); | 13 | EXPORT_SYMBOL(__stack_chk_guard); |
14 | #endif | 14 | #endif |
15 | 15 | ||
16 | /* | ||
17 | * this gets called so that we can store lazy state into memory and copy the | ||
18 | * current task into the new thread. | ||
19 | */ | ||
16 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | 20 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
17 | { | 21 | { |
22 | #ifdef CONFIG_SUPERH32 | ||
23 | unlazy_fpu(src, task_pt_regs(src)); | ||
24 | #endif | ||
18 | *dst = *src; | 25 | *dst = *src; |
19 | 26 | ||
20 | if (src->thread.xstate) { | 27 | if (src->thread.xstate) { |
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index f78cc421e665..59521e8a164d 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
@@ -156,15 +156,6 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
156 | } | 156 | } |
157 | EXPORT_SYMBOL(dump_fpu); | 157 | EXPORT_SYMBOL(dump_fpu); |
158 | 158 | ||
159 | /* | ||
160 | * This gets called before we allocate a new thread and copy | ||
161 | * the current task into it. | ||
162 | */ | ||
163 | void prepare_to_copy(struct task_struct *tsk) | ||
164 | { | ||
165 | unlazy_fpu(tsk, task_pt_regs(tsk)); | ||
166 | } | ||
167 | |||
168 | asmlinkage void ret_from_fork(void); | 159 | asmlinkage void ret_from_fork(void); |
169 | 160 | ||
170 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 161 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
diff --git a/arch/sparc/include/asm/processor_32.h b/arch/sparc/include/asm/processor_32.h index 9cbd854fdfdd..f74ac9ee33a8 100644 --- a/arch/sparc/include/asm/processor_32.h +++ b/arch/sparc/include/asm/processor_32.h | |||
@@ -108,9 +108,6 @@ static inline void start_thread(struct pt_regs * regs, unsigned long pc, | |||
108 | #define release_thread(tsk) do { } while(0) | 108 | #define release_thread(tsk) do { } while(0) |
109 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 109 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
110 | 110 | ||
111 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
112 | #define prepare_to_copy(tsk) do { } while (0) | ||
113 | |||
114 | extern unsigned long get_wchan(struct task_struct *); | 111 | extern unsigned long get_wchan(struct task_struct *); |
115 | 112 | ||
116 | #define task_pt_regs(tsk) ((tsk)->thread.kregs) | 113 | #define task_pt_regs(tsk) ((tsk)->thread.kregs) |
diff --git a/arch/sparc/include/asm/processor_64.h b/arch/sparc/include/asm/processor_64.h index e713db249931..67df5cc10011 100644 --- a/arch/sparc/include/asm/processor_64.h +++ b/arch/sparc/include/asm/processor_64.h | |||
@@ -186,9 +186,6 @@ do { \ | |||
186 | /* Free all resources held by a thread. */ | 186 | /* Free all resources held by a thread. */ |
187 | #define release_thread(tsk) do { } while (0) | 187 | #define release_thread(tsk) do { } while (0) |
188 | 188 | ||
189 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
190 | #define prepare_to_copy(tsk) do { } while (0) | ||
191 | |||
192 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 189 | extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
193 | 190 | ||
194 | extern unsigned long get_wchan(struct task_struct *task); | 191 | extern unsigned long get_wchan(struct task_struct *task); |
diff --git a/arch/tile/include/asm/processor.h b/arch/tile/include/asm/processor.h index 34c1e01ffb5e..15cd8a4a06ce 100644 --- a/arch/tile/include/asm/processor.h +++ b/arch/tile/include/asm/processor.h | |||
@@ -210,9 +210,6 @@ static inline void release_thread(struct task_struct *dead_task) | |||
210 | /* Nothing for now */ | 210 | /* Nothing for now */ |
211 | } | 211 | } |
212 | 212 | ||
213 | /* Prepare to copy thread state - unlazy all lazy status. */ | ||
214 | #define prepare_to_copy(tsk) do { } while (0) | ||
215 | |||
216 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | 213 | extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
217 | 214 | ||
218 | extern int do_work_pending(struct pt_regs *regs, u32 flags); | 215 | extern int do_work_pending(struct pt_regs *regs, u32 flags); |
diff --git a/arch/um/include/asm/processor-generic.h b/arch/um/include/asm/processor-generic.h index 7827394a5b6c..69f1c57a8d0d 100644 --- a/arch/um/include/asm/processor-generic.h +++ b/arch/um/include/asm/processor-generic.h | |||
@@ -74,11 +74,6 @@ static inline void release_thread(struct task_struct *task) | |||
74 | 74 | ||
75 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 75 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
76 | 76 | ||
77 | static inline void prepare_to_copy(struct task_struct *tsk) | ||
78 | { | ||
79 | } | ||
80 | |||
81 | |||
82 | extern unsigned long thread_saved_pc(struct task_struct *t); | 77 | extern unsigned long thread_saved_pc(struct task_struct *t); |
83 | 78 | ||
84 | static inline void mm_copy_segments(struct mm_struct *from_mm, | 79 | static inline void mm_copy_segments(struct mm_struct *from_mm, |
diff --git a/arch/unicore32/include/asm/processor.h b/arch/unicore32/include/asm/processor.h index f0d780a51f9b..14382cb09657 100644 --- a/arch/unicore32/include/asm/processor.h +++ b/arch/unicore32/include/asm/processor.h | |||
@@ -68,9 +68,6 @@ struct task_struct; | |||
68 | /* Free all resources held by a thread. */ | 68 | /* Free all resources held by a thread. */ |
69 | extern void release_thread(struct task_struct *); | 69 | extern void release_thread(struct task_struct *); |
70 | 70 | ||
71 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
72 | #define prepare_to_copy(tsk) do { } while (0) | ||
73 | |||
74 | unsigned long get_wchan(struct task_struct *p); | 71 | unsigned long get_wchan(struct task_struct *p); |
75 | 72 | ||
76 | #define cpu_relax() barrier() | 73 | #define cpu_relax() barrier() |
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index ccbb1ea99ccb..7745b257f035 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
@@ -579,9 +579,6 @@ extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | |||
579 | /* Free all resources held by a thread. */ | 579 | /* Free all resources held by a thread. */ |
580 | extern void release_thread(struct task_struct *); | 580 | extern void release_thread(struct task_struct *); |
581 | 581 | ||
582 | /* Prepare to copy thread state - unlazy all lazy state */ | ||
583 | extern void prepare_to_copy(struct task_struct *tsk); | ||
584 | |||
585 | unsigned long get_wchan(struct task_struct *p); | 582 | unsigned long get_wchan(struct task_struct *p); |
586 | 583 | ||
587 | /* | 584 | /* |
diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index f2e8c0f951d6..735279e54e59 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c | |||
@@ -56,10 +56,16 @@ EXPORT_SYMBOL_GPL(idle_notifier_unregister); | |||
56 | struct kmem_cache *task_xstate_cachep; | 56 | struct kmem_cache *task_xstate_cachep; |
57 | EXPORT_SYMBOL_GPL(task_xstate_cachep); | 57 | EXPORT_SYMBOL_GPL(task_xstate_cachep); |
58 | 58 | ||
59 | /* | ||
60 | * this gets called so that we can store lazy state into memory and copy the | ||
61 | * current task into the new thread. | ||
62 | */ | ||
59 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) | 63 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
60 | { | 64 | { |
61 | int ret; | 65 | int ret; |
62 | 66 | ||
67 | unlazy_fpu(src); | ||
68 | |||
63 | *dst = *src; | 69 | *dst = *src; |
64 | if (fpu_allocated(&src->thread.fpu)) { | 70 | if (fpu_allocated(&src->thread.fpu)) { |
65 | memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu)); | 71 | memset(&dst->thread.fpu, 0, sizeof(dst->thread.fpu)); |
@@ -89,6 +95,16 @@ void arch_task_cache_init(void) | |||
89 | SLAB_PANIC | SLAB_NOTRACK, NULL); | 95 | SLAB_PANIC | SLAB_NOTRACK, NULL); |
90 | } | 96 | } |
91 | 97 | ||
98 | static inline void drop_fpu(struct task_struct *tsk) | ||
99 | { | ||
100 | /* | ||
101 | * Forget coprocessor state.. | ||
102 | */ | ||
103 | tsk->fpu_counter = 0; | ||
104 | clear_fpu(tsk); | ||
105 | clear_used_math(); | ||
106 | } | ||
107 | |||
92 | /* | 108 | /* |
93 | * Free current thread data structures etc.. | 109 | * Free current thread data structures etc.. |
94 | */ | 110 | */ |
@@ -111,6 +127,8 @@ void exit_thread(void) | |||
111 | put_cpu(); | 127 | put_cpu(); |
112 | kfree(bp); | 128 | kfree(bp); |
113 | } | 129 | } |
130 | |||
131 | drop_fpu(me); | ||
114 | } | 132 | } |
115 | 133 | ||
116 | void show_regs_common(void) | 134 | void show_regs_common(void) |
@@ -145,12 +163,7 @@ void flush_thread(void) | |||
145 | 163 | ||
146 | flush_ptrace_hw_breakpoint(tsk); | 164 | flush_ptrace_hw_breakpoint(tsk); |
147 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 165 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
148 | /* | 166 | drop_fpu(tsk); |
149 | * Forget coprocessor state.. | ||
150 | */ | ||
151 | tsk->fpu_counter = 0; | ||
152 | clear_fpu(tsk); | ||
153 | clear_used_math(); | ||
154 | } | 167 | } |
155 | 168 | ||
156 | static void hard_disable_TSC(void) | 169 | static void hard_disable_TSC(void) |
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 01d8d40ccaf6..516fa186121b 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
@@ -126,15 +126,6 @@ void release_thread(struct task_struct *dead_task) | |||
126 | release_vm86_irqs(dead_task); | 126 | release_vm86_irqs(dead_task); |
127 | } | 127 | } |
128 | 128 | ||
129 | /* | ||
130 | * This gets called before we allocate a new thread and copy | ||
131 | * the current task into it. | ||
132 | */ | ||
133 | void prepare_to_copy(struct task_struct *tsk) | ||
134 | { | ||
135 | unlazy_fpu(tsk); | ||
136 | } | ||
137 | |||
138 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 129 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
139 | unsigned long unused, | 130 | unsigned long unused, |
140 | struct task_struct *p, struct pt_regs *regs) | 131 | struct task_struct *p, struct pt_regs *regs) |
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c index 28e810255a0a..61cdf7fdf099 100644 --- a/arch/x86/kernel/process_64.c +++ b/arch/x86/kernel/process_64.c | |||
@@ -145,15 +145,6 @@ static inline u32 read_32bit_tls(struct task_struct *t, int tls) | |||
145 | return get_desc_base(&t->thread.tls_array[tls]); | 145 | return get_desc_base(&t->thread.tls_array[tls]); |
146 | } | 146 | } |
147 | 147 | ||
148 | /* | ||
149 | * This gets called before we allocate a new thread and copy | ||
150 | * the current task into it. | ||
151 | */ | ||
152 | void prepare_to_copy(struct task_struct *tsk) | ||
153 | { | ||
154 | unlazy_fpu(tsk); | ||
155 | } | ||
156 | |||
157 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 148 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
158 | unsigned long unused, | 149 | unsigned long unused, |
159 | struct task_struct *p, struct pt_regs *regs) | 150 | struct task_struct *p, struct pt_regs *regs) |
diff --git a/arch/x86/kernel/xsave.c b/arch/x86/kernel/xsave.c index e62728e30b01..bd18149b2b0f 100644 --- a/arch/x86/kernel/xsave.c +++ b/arch/x86/kernel/xsave.c | |||
@@ -48,8 +48,6 @@ void __sanitize_i387_state(struct task_struct *tsk) | |||
48 | if (!fx) | 48 | if (!fx) |
49 | return; | 49 | return; |
50 | 50 | ||
51 | BUG_ON(__thread_has_fpu(tsk)); | ||
52 | |||
53 | xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv; | 51 | xstate_bv = tsk->thread.fpu.state->xsave.xsave_hdr.xstate_bv; |
54 | 52 | ||
55 | /* | 53 | /* |
diff --git a/arch/xtensa/include/asm/processor.h b/arch/xtensa/include/asm/processor.h index 3acb26e8dead..5c371d8d4528 100644 --- a/arch/xtensa/include/asm/processor.h +++ b/arch/xtensa/include/asm/processor.h | |||
@@ -168,9 +168,6 @@ struct mm_struct; | |||
168 | /* Free all resources held by a thread. */ | 168 | /* Free all resources held by a thread. */ |
169 | #define release_thread(thread) do { } while(0) | 169 | #define release_thread(thread) do { } while(0) |
170 | 170 | ||
171 | /* Prepare to copy thread state - unlazy all lazy status */ | ||
172 | extern void prepare_to_copy(struct task_struct*); | ||
173 | |||
174 | /* Create a kernel thread without removing it from tasklists */ | 171 | /* Create a kernel thread without removing it from tasklists */ |
175 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); | 172 | extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); |
176 | 173 | ||
diff --git a/arch/xtensa/kernel/process.c b/arch/xtensa/kernel/process.c index 6a2d6edf8f72..9b306e550e3f 100644 --- a/arch/xtensa/kernel/process.c +++ b/arch/xtensa/kernel/process.c | |||
@@ -140,13 +140,16 @@ void flush_thread(void) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | /* | 142 | /* |
143 | * This is called before the thread is copied. | 143 | * this gets called so that we can store coprocessor state into memory and |
144 | * copy the current task into the new thread. | ||
144 | */ | 145 | */ |
145 | void prepare_to_copy(struct task_struct *tsk) | 146 | int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) |
146 | { | 147 | { |
147 | #if XTENSA_HAVE_COPROCESSORS | 148 | #if XTENSA_HAVE_COPROCESSORS |
148 | coprocessor_flush_all(task_thread_info(tsk)); | 149 | coprocessor_flush_all(task_thread_info(src)); |
149 | #endif | 150 | #endif |
151 | *dst = *src; | ||
152 | return 0; | ||
150 | } | 153 | } |
151 | 154 | ||
152 | /* | 155 | /* |
@@ -1938,8 +1938,21 @@ static int coredump_wait(int exit_code, struct core_state *core_state) | |||
1938 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); | 1938 | core_waiters = zap_threads(tsk, mm, core_state, exit_code); |
1939 | up_write(&mm->mmap_sem); | 1939 | up_write(&mm->mmap_sem); |
1940 | 1940 | ||
1941 | if (core_waiters > 0) | 1941 | if (core_waiters > 0) { |
1942 | struct core_thread *ptr; | ||
1943 | |||
1942 | wait_for_completion(&core_state->startup); | 1944 | wait_for_completion(&core_state->startup); |
1945 | /* | ||
1946 | * Wait for all the threads to become inactive, so that | ||
1947 | * all the thread context (extended register state, like | ||
1948 | * fpu etc) gets copied to the memory. | ||
1949 | */ | ||
1950 | ptr = core_state->dumper.next; | ||
1951 | while (ptr != NULL) { | ||
1952 | wait_task_inactive(ptr->task, 0); | ||
1953 | ptr = ptr->next; | ||
1954 | } | ||
1955 | } | ||
1943 | 1956 | ||
1944 | return core_waiters; | 1957 | return core_waiters; |
1945 | } | 1958 | } |
diff --git a/kernel/fork.c b/kernel/fork.c index ad54c833116a..05c813dc9ecc 100644 --- a/kernel/fork.c +++ b/kernel/fork.c | |||
@@ -292,8 +292,6 @@ static struct task_struct *dup_task_struct(struct task_struct *orig) | |||
292 | int node = tsk_fork_get_node(orig); | 292 | int node = tsk_fork_get_node(orig); |
293 | int err; | 293 | int err; |
294 | 294 | ||
295 | prepare_to_copy(orig); | ||
296 | |||
297 | tsk = alloc_task_struct_node(node); | 295 | tsk = alloc_task_struct_node(node); |
298 | if (!tsk) | 296 | if (!tsk) |
299 | return NULL; | 297 | return NULL; |