aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sh/kernel/process_32.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sh/kernel/process_32.c')
-rw-r--r--arch/sh/kernel/process_32.c42
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}
148EXPORT_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}
193EXPORT_SYMBOL(dump_fpu);
194
195/*
196 * This gets called before we allocate a new thread and copy
197 * the current task into it.
198 */
199void prepare_to_copy(struct task_struct *tsk)
200{
201 unlazy_fpu(tsk, task_pt_regs(tsk));
202}
189 203
190asmlinkage void ret_from_fork(void); 204asmlinkage 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