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 94afe585930..e37b887b3d9 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 d7038fa2234..99afa749826 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 108502bc677..87d8baccc60 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 8af7772e84c..4ef7cfe43ce 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 3ff7fab956b..c50af7ef1c9 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 8dc56ef0871..ef4e1bc3efc 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 9b1a92b73f6..a8311d364e2 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 ed09e9e2c65..ff95f50efea 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 61fabf1788c..4c9f6f87b61 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 20c5ddabbd8..e8ea459002a 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 f92f67aba61..5a994ec8f06 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 e1f46d75746..da17253b573 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 46460fa15d5..f17c42aff7f 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 bffb5452729..af2bb965239 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 20e9dcf42b2..5e33fabe354 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 f7b3c9ab2cb..247928c9f54 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 14707f25153..7dab0cd3646 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 f7516fa78b5..30462f1fe95 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 acdf4cad612..0e8b7b8ce8a 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 48a26d37922..55e85631c42 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 7f8ec1de0ac..710f400476d 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 d499b30ea48..6cbf3131167 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 7e22f216d77..ab3aceb5420 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 900f8d72ffe..b6311fd2d06 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 740e2687659..cd6029fb2c0 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 e77feaf117a..9b7a459a461 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 f78cc421e66..59521e8a164 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 9cbd854fdfd..f74ac9ee33a 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 e713db24993..67df5cc1001 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 34c1e01ffb5..15cd8a4a06c 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 7827394a5b6..69f1c57a8d0 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 f0d780a51f9..14382cb0965 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 ccbb1ea99cc..7745b257f03 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 f2e8c0f951d..735279e54e5 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 01d8d40ccaf..516fa186121 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 28e810255a0..61cdf7fdf09 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 e62728e30b0..bd18149b2b0 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 3acb26e8dea..5c371d8d452 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 6a2d6edf8f7..9b306e550e3 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 ad54c833116..05c813dc9ec 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; |
