aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 13:59:07 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2012-05-23 13:59:07 -0400
commitec0d7f18ab7b5097d7c0c8f3d909ca1031b9d5cd (patch)
tree7d62c924592145f819ecaa5d60460a05a10dfdbd
parent269af9a1a08d368b46d72e74126564d04c354f7e (diff)
parent1dcc8d7ba235a316a056f993e88f0d18b92c60d9 (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()
-rw-r--r--arch/alpha/include/asm/processor.h3
-rw-r--r--arch/arm/include/asm/processor.h3
-rw-r--r--arch/avr32/include/asm/processor.h3
-rw-r--r--arch/blackfin/include/asm/processor.h2
-rw-r--r--arch/c6x/include/asm/processor.h3
-rw-r--r--arch/cris/include/asm/processor.h4
-rw-r--r--arch/frv/include/asm/processor.h2
-rw-r--r--arch/frv/kernel/process.c11
-rw-r--r--arch/h8300/include/asm/processor.h2
-rw-r--r--arch/hexagon/include/asm/processor.h7
-rw-r--r--arch/ia64/include/asm/processor.h3
-rw-r--r--arch/m32r/include/asm/processor.h2
-rw-r--r--arch/m68k/include/asm/processor.h3
-rw-r--r--arch/microblaze/include/asm/processor.h1
-rw-r--r--arch/mips/include/asm/processor.h3
-rw-r--r--arch/mn10300/include/asm/processor.h3
-rw-r--r--arch/mn10300/kernel/process.c10
-rw-r--r--arch/openrisc/include/asm/processor.h4
-rw-r--r--arch/parisc/include/asm/processor.h3
-rw-r--r--arch/powerpc/include/asm/processor.h3
-rw-r--r--arch/powerpc/kernel/process.c19
-rw-r--r--arch/s390/include/asm/processor.h3
-rw-r--r--arch/score/include/asm/processor.h1
-rw-r--r--arch/sh/include/asm/processor_32.h3
-rw-r--r--arch/sh/include/asm/processor_64.h1
-rw-r--r--arch/sh/kernel/process.c7
-rw-r--r--arch/sh/kernel/process_32.c9
-rw-r--r--arch/sparc/include/asm/processor_32.h3
-rw-r--r--arch/sparc/include/asm/processor_64.h3
-rw-r--r--arch/tile/include/asm/processor.h3
-rw-r--r--arch/um/include/asm/processor-generic.h5
-rw-r--r--arch/unicore32/include/asm/processor.h3
-rw-r--r--arch/x86/include/asm/processor.h3
-rw-r--r--arch/x86/kernel/process.c25
-rw-r--r--arch/x86/kernel/process_32.c9
-rw-r--r--arch/x86/kernel/process_64.c9
-rw-r--r--arch/x86/kernel/xsave.c2
-rw-r--r--arch/xtensa/include/asm/processor.h3
-rw-r--r--arch/xtensa/kernel/process.c9
-rw-r--r--fs/exec.c15
-rw-r--r--kernel/fork.c2
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. */
50extern void release_thread(struct task_struct *); 50extern 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. */
56extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 53extern 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. */
78extern void release_thread(struct task_struct *); 78extern 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
83unsigned long get_wchan(struct task_struct *p); 80unsigned 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 */
146extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 146extern 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
80extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags); 78extern 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
98extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 95extern 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
52static inline void prepare_to_copy(struct task_struct *tsk)
53{
54}
55
56extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 52extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
57 53
58unsigned long get_wchan(struct task_struct *p); 54unsigned 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
106extern 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. */
109static inline void release_thread(struct task_struct *dead_task) 107static 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 */
173void 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
110extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 110extern 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 */
64static 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. */
119extern void release_thread(struct task_struct *); 119extern 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
159extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 156extern 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
316extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 313extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
317 314
318extern unsigned long thread_saved_pc(struct task_struct *tsk); 315extern 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. */
140extern void release_thread(struct task_struct *); 140extern void release_thread(struct task_struct *);
141 141
142/* Prepare to copy thread state - unlazy all lazy status */
143extern 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 */
214void prepare_to_copy(struct task_struct *tsk) 214int 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
75extern 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;
328extern void release_thread(struct task_struct *); 328extern void release_thread(struct task_struct *);
329extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 329extern 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
334extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm); 331extern void map_hpux_gateway_page(struct task_struct *tsk, struct mm_struct *mm);
335 332
336extern unsigned long get_wchan(struct task_struct *p); 333extern 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;
74void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp); 74void start_thread(struct pt_regs *regs, unsigned long fdptr, unsigned long sp);
75void release_thread(struct task_struct *); 75void release_thread(struct task_struct *);
76 76
77/* Prepare to copy thread state - unlazy all lazy status */
78extern void prepare_to_copy(struct task_struct *tsk);
79
80/* Create a new kernel thread. */ 77/* Create a new kernel thread. */
81extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 78extern 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 */
717void prepare_to_copy(struct task_struct *tsk) 717int 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;
141extern void release_thread(struct task_struct *); 141extern void release_thread(struct task_struct *);
142extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 142extern 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. */
127extern void release_thread(struct task_struct *); 127extern void release_thread(struct task_struct *);
128 128
129/* Prepare to copy thread state - unlazy all lazy status */
130void 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;
13EXPORT_SYMBOL(__stack_chk_guard); 13EXPORT_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 */
16int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 20int 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}
157EXPORT_SYMBOL(dump_fpu); 157EXPORT_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 */
163void prepare_to_copy(struct task_struct *tsk)
164{
165 unlazy_fpu(tsk, task_pt_regs(tsk));
166}
167
168asmlinkage void ret_from_fork(void); 159asmlinkage void ret_from_fork(void);
169 160
170int copy_thread(unsigned long clone_flags, unsigned long usp, 161int 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)
109extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 109extern 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
114extern unsigned long get_wchan(struct task_struct *); 111extern 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
192extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 189extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
193 190
194extern unsigned long get_wchan(struct task_struct *task); 191extern 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
216extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); 213extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);
217 214
218extern int do_work_pending(struct pt_regs *regs, u32 flags); 215extern 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
75extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 75extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);
76 76
77static inline void prepare_to_copy(struct task_struct *tsk)
78{
79}
80
81
82extern unsigned long thread_saved_pc(struct task_struct *t); 77extern unsigned long thread_saved_pc(struct task_struct *t);
83 78
84static inline void mm_copy_segments(struct mm_struct *from_mm, 79static 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. */
69extern void release_thread(struct task_struct *); 69extern 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
74unsigned long get_wchan(struct task_struct *p); 71unsigned 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. */
580extern void release_thread(struct task_struct *); 580extern void release_thread(struct task_struct *);
581 581
582/* Prepare to copy thread state - unlazy all lazy state */
583extern void prepare_to_copy(struct task_struct *tsk);
584
585unsigned long get_wchan(struct task_struct *p); 582unsigned 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);
56struct kmem_cache *task_xstate_cachep; 56struct kmem_cache *task_xstate_cachep;
57EXPORT_SYMBOL_GPL(task_xstate_cachep); 57EXPORT_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 */
59int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 63int 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
98static 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
116void show_regs_common(void) 134void 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
156static void hard_disable_TSC(void) 169static 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 */
133void prepare_to_copy(struct task_struct *tsk)
134{
135 unlazy_fpu(tsk);
136}
137
138int copy_thread(unsigned long clone_flags, unsigned long sp, 129int 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 */
152void prepare_to_copy(struct task_struct *tsk)
153{
154 unlazy_fpu(tsk);
155}
156
157int copy_thread(unsigned long clone_flags, unsigned long sp, 148int 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 */
172extern 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 */
175extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags); 172extern 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 */
145void prepare_to_copy(struct task_struct *tsk) 146int 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/*
diff --git a/fs/exec.c b/fs/exec.c
index d038968b54b4..1e8efdc80412 100644
--- a/fs/exec.c
+++ b/fs/exec.c
@@ -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;