diff options
Diffstat (limited to 'arch/sh/kernel/process_32.c')
| -rw-r--r-- | arch/sh/kernel/process_32.c | 42 |
1 files changed, 32 insertions, 10 deletions
diff --git a/arch/sh/kernel/process_32.c b/arch/sh/kernel/process_32.c index 0673c4746be3..d8af889366a4 100644 --- a/arch/sh/kernel/process_32.c +++ b/arch/sh/kernel/process_32.c | |||
| @@ -134,7 +134,10 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
| 134 | regs.regs[5] = (unsigned long)fn; | 134 | regs.regs[5] = (unsigned long)fn; |
| 135 | 135 | ||
| 136 | regs.pc = (unsigned long)kernel_thread_helper; | 136 | regs.pc = (unsigned long)kernel_thread_helper; |
| 137 | regs.sr = (1 << 30); | 137 | regs.sr = SR_MD; |
| 138 | #if defined(CONFIG_SH_FPU) | ||
| 139 | regs.sr |= SR_FD; | ||
| 140 | #endif | ||
| 138 | 141 | ||
| 139 | /* Ok, create the new process.. */ | 142 | /* Ok, create the new process.. */ |
| 140 | pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, | 143 | pid = do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, |
| @@ -142,6 +145,7 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) | |||
| 142 | 145 | ||
| 143 | return pid; | 146 | return pid; |
| 144 | } | 147 | } |
| 148 | EXPORT_SYMBOL(kernel_thread); | ||
| 145 | 149 | ||
| 146 | /* | 150 | /* |
| 147 | * Free current thread data structures etc.. | 151 | * Free current thread data structures etc.. |
| @@ -186,6 +190,16 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *fpu) | |||
| 186 | 190 | ||
| 187 | return fpvalid; | 191 | return fpvalid; |
| 188 | } | 192 | } |
| 193 | EXPORT_SYMBOL(dump_fpu); | ||
| 194 | |||
| 195 | /* | ||
| 196 | * This gets called before we allocate a new thread and copy | ||
| 197 | * the current task into it. | ||
| 198 | */ | ||
| 199 | void prepare_to_copy(struct task_struct *tsk) | ||
| 200 | { | ||
| 201 | unlazy_fpu(tsk, task_pt_regs(tsk)); | ||
| 202 | } | ||
| 189 | 203 | ||
| 190 | asmlinkage void ret_from_fork(void); | 204 | asmlinkage void ret_from_fork(void); |
| 191 | 205 | ||
| @@ -195,16 +209,10 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 195 | { | 209 | { |
| 196 | struct thread_info *ti = task_thread_info(p); | 210 | struct thread_info *ti = task_thread_info(p); |
| 197 | struct pt_regs *childregs; | 211 | struct pt_regs *childregs; |
| 198 | #if defined(CONFIG_SH_FPU) || defined(CONFIG_SH_DSP) | 212 | #if defined(CONFIG_SH_DSP) |
| 199 | struct task_struct *tsk = current; | 213 | struct task_struct *tsk = current; |
| 200 | #endif | 214 | #endif |
| 201 | 215 | ||
| 202 | #if defined(CONFIG_SH_FPU) | ||
| 203 | unlazy_fpu(tsk, regs); | ||
| 204 | p->thread.fpu = tsk->thread.fpu; | ||
| 205 | copy_to_stopped_child_used_math(p); | ||
| 206 | #endif | ||
| 207 | |||
| 208 | #if defined(CONFIG_SH_DSP) | 216 | #if defined(CONFIG_SH_DSP) |
| 209 | if (is_dsp_enabled(tsk)) { | 217 | if (is_dsp_enabled(tsk)) { |
| 210 | /* We can use the __save_dsp or just copy the struct: | 218 | /* We can use the __save_dsp or just copy the struct: |
| @@ -224,6 +232,8 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, | |||
| 224 | } else { | 232 | } else { |
| 225 | childregs->regs[15] = (unsigned long)childregs; | 233 | childregs->regs[15] = (unsigned long)childregs; |
| 226 | ti->addr_limit = KERNEL_DS; | 234 | ti->addr_limit = KERNEL_DS; |
| 235 | ti->status &= ~TS_USEDFPU; | ||
| 236 | p->fpu_counter = 0; | ||
| 227 | } | 237 | } |
| 228 | 238 | ||
| 229 | if (clone_flags & CLONE_SETTLS) | 239 | if (clone_flags & CLONE_SETTLS) |
| @@ -288,9 +298,13 @@ static void ubc_set_tracing(int asid, unsigned long pc) | |||
| 288 | __notrace_funcgraph struct task_struct * | 298 | __notrace_funcgraph struct task_struct * |
| 289 | __switch_to(struct task_struct *prev, struct task_struct *next) | 299 | __switch_to(struct task_struct *prev, struct task_struct *next) |
| 290 | { | 300 | { |
| 291 | #if defined(CONFIG_SH_FPU) | 301 | struct thread_struct *next_t = &next->thread; |
| 302 | |||
| 292 | unlazy_fpu(prev, task_pt_regs(prev)); | 303 | unlazy_fpu(prev, task_pt_regs(prev)); |
| 293 | #endif | 304 | |
| 305 | /* we're going to use this soon, after a few expensive things */ | ||
| 306 | if (next->fpu_counter > 5) | ||
| 307 | prefetch(&next_t->fpu.hard); | ||
| 294 | 308 | ||
| 295 | #ifdef CONFIG_MMU | 309 | #ifdef CONFIG_MMU |
| 296 | /* | 310 | /* |
| @@ -321,6 +335,14 @@ __switch_to(struct task_struct *prev, struct task_struct *next) | |||
| 321 | #endif | 335 | #endif |
| 322 | } | 336 | } |
| 323 | 337 | ||
| 338 | /* | ||
| 339 | * If the task has used fpu the last 5 timeslices, just do a full | ||
| 340 | * restore of the math state immediately to avoid the trap; the | ||
| 341 | * chances of needing FPU soon are obviously high now | ||
| 342 | */ | ||
| 343 | if (next->fpu_counter > 5) | ||
| 344 | fpu_state_restore(task_pt_regs(next)); | ||
| 345 | |||
| 324 | return prev; | 346 | return prev; |
| 325 | } | 347 | } |
| 326 | 348 | ||
