aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/process_32.c
diff options
context:
space:
mode:
authorJeremy Fitzhardinge <jeremy@goop.org>2009-02-27 16:25:28 -0500
committerIngo Molnar <mingo@elte.hu>2009-03-02 06:07:48 -0500
commit389d1fb11e5f2a16b5e34c547756f0c4dec641f7 (patch)
tree83962a579c85d43356bfc67302d83594d6163034 /arch/x86/kernel/process_32.c
parentdb949bba3c7cf2e664ac12e237c6d4c914f0c69d (diff)
x86: unify chunks of kernel/process*.c
With x86-32 and -64 using the same mechanism for managing the tss io permissions bitmap, large chunks of process*.c are trivially unifyable, including: - exit_thread - flush_thread - __switch_to_xtra (along with tsc enable/disable) and as bonus pickups: - sys_fork - sys_vfork (Note: asmlinkage expands to empty on x86-64) Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com> Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/process_32.c')
-rw-r--r--arch/x86/kernel/process_32.c172
1 files changed, 0 insertions, 172 deletions
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index a59314e877f0..14014d766cad 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -230,52 +230,6 @@ int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
230} 230}
231EXPORT_SYMBOL(kernel_thread); 231EXPORT_SYMBOL(kernel_thread);
232 232
233/*
234 * Free current thread data structures etc..
235 */
236void exit_thread(void)
237{
238 /* The process may have allocated an io port bitmap... nuke it. */
239 if (unlikely(test_thread_flag(TIF_IO_BITMAP))) {
240 struct task_struct *tsk = current;
241 struct thread_struct *t = &tsk->thread;
242 int cpu = get_cpu();
243 struct tss_struct *tss = &per_cpu(init_tss, cpu);
244
245 kfree(t->io_bitmap_ptr);
246 t->io_bitmap_ptr = NULL;
247 clear_thread_flag(TIF_IO_BITMAP);
248 /*
249 * Careful, clear this in the TSS too:
250 */
251 memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
252 t->io_bitmap_max = 0;
253 put_cpu();
254 }
255
256 ds_exit_thread(current);
257}
258
259void flush_thread(void)
260{
261 struct task_struct *tsk = current;
262
263 tsk->thread.debugreg0 = 0;
264 tsk->thread.debugreg1 = 0;
265 tsk->thread.debugreg2 = 0;
266 tsk->thread.debugreg3 = 0;
267 tsk->thread.debugreg6 = 0;
268 tsk->thread.debugreg7 = 0;
269 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array));
270 clear_tsk_thread_flag(tsk, TIF_DEBUG);
271 /*
272 * Forget coprocessor state..
273 */
274 tsk->fpu_counter = 0;
275 clear_fpu(tsk);
276 clear_used_math();
277}
278
279void release_thread(struct task_struct *dead_task) 233void release_thread(struct task_struct *dead_task)
280{ 234{
281 BUG_ON(dead_task->mm); 235 BUG_ON(dead_task->mm);
@@ -363,112 +317,6 @@ start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp)
363} 317}
364EXPORT_SYMBOL_GPL(start_thread); 318EXPORT_SYMBOL_GPL(start_thread);
365 319
366static void hard_disable_TSC(void)
367{
368 write_cr4(read_cr4() | X86_CR4_TSD);
369}
370
371void disable_TSC(void)
372{
373 preempt_disable();
374 if (!test_and_set_thread_flag(TIF_NOTSC))
375 /*
376 * Must flip the CPU state synchronously with
377 * TIF_NOTSC in the current running context.
378 */
379 hard_disable_TSC();
380 preempt_enable();
381}
382
383static void hard_enable_TSC(void)
384{
385 write_cr4(read_cr4() & ~X86_CR4_TSD);
386}
387
388static void enable_TSC(void)
389{
390 preempt_disable();
391 if (test_and_clear_thread_flag(TIF_NOTSC))
392 /*
393 * Must flip the CPU state synchronously with
394 * TIF_NOTSC in the current running context.
395 */
396 hard_enable_TSC();
397 preempt_enable();
398}
399
400int get_tsc_mode(unsigned long adr)
401{
402 unsigned int val;
403
404 if (test_thread_flag(TIF_NOTSC))
405 val = PR_TSC_SIGSEGV;
406 else
407 val = PR_TSC_ENABLE;
408
409 return put_user(val, (unsigned int __user *)adr);
410}
411
412int set_tsc_mode(unsigned int val)
413{
414 if (val == PR_TSC_SIGSEGV)
415 disable_TSC();
416 else if (val == PR_TSC_ENABLE)
417 enable_TSC();
418 else
419 return -EINVAL;
420
421 return 0;
422}
423
424static noinline void
425__switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
426 struct tss_struct *tss)
427{
428 struct thread_struct *prev, *next;
429
430 prev = &prev_p->thread;
431 next = &next_p->thread;
432
433 if (test_tsk_thread_flag(next_p, TIF_DS_AREA_MSR) ||
434 test_tsk_thread_flag(prev_p, TIF_DS_AREA_MSR))
435 ds_switch_to(prev_p, next_p);
436 else if (next->debugctlmsr != prev->debugctlmsr)
437 update_debugctlmsr(next->debugctlmsr);
438
439 if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
440 set_debugreg(next->debugreg0, 0);
441 set_debugreg(next->debugreg1, 1);
442 set_debugreg(next->debugreg2, 2);
443 set_debugreg(next->debugreg3, 3);
444 /* no 4 and 5 */
445 set_debugreg(next->debugreg6, 6);
446 set_debugreg(next->debugreg7, 7);
447 }
448
449 if (test_tsk_thread_flag(prev_p, TIF_NOTSC) ^
450 test_tsk_thread_flag(next_p, TIF_NOTSC)) {
451 /* prev and next are different */
452 if (test_tsk_thread_flag(next_p, TIF_NOTSC))
453 hard_disable_TSC();
454 else
455 hard_enable_TSC();
456 }
457
458 if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
459 /*
460 * Copy the relevant range of the IO bitmap.
461 * Normally this is 128 bytes or less:
462 */
463 memcpy(tss->io_bitmap, next->io_bitmap_ptr,
464 max(prev->io_bitmap_max, next->io_bitmap_max));
465 } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
466 /*
467 * Clear any possible leftover bits:
468 */
469 memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
470 }
471}
472 320
473/* 321/*
474 * switch_to(x,yn) should switch tasks from x to y. 322 * switch_to(x,yn) should switch tasks from x to y.
@@ -582,11 +430,6 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
582 return prev_p; 430 return prev_p;
583} 431}
584 432
585int sys_fork(struct pt_regs *regs)
586{
587 return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL);
588}
589
590int sys_clone(struct pt_regs *regs) 433int sys_clone(struct pt_regs *regs)
591{ 434{
592 unsigned long clone_flags; 435 unsigned long clone_flags;
@@ -603,21 +446,6 @@ int sys_clone(struct pt_regs *regs)
603} 446}
604 447
605/* 448/*
606 * This is trivial, and on the face of it looks like it
607 * could equally well be done in user mode.
608 *
609 * Not so, for quite unobvious reasons - register pressure.
610 * In user mode vfork() cannot have a stack frame, and if
611 * done by calling the "clone()" system call directly, you
612 * do not have enough call-clobbered registers to hold all
613 * the information you need.
614 */
615int sys_vfork(struct pt_regs *regs)
616{
617 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs, 0, NULL, NULL);
618}
619
620/*
621 * sys_execve() executes a new program. 449 * sys_execve() executes a new program.
622 */ 450 */
623int sys_execve(struct pt_regs *regs) 451int sys_execve(struct pt_regs *regs)