diff options
author | Jeremy Fitzhardinge <jeremy@goop.org> | 2009-02-27 16:25:28 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-03-02 06:07:48 -0500 |
commit | 389d1fb11e5f2a16b5e34c547756f0c4dec641f7 (patch) | |
tree | 83962a579c85d43356bfc67302d83594d6163034 /arch/x86/kernel/process_32.c | |
parent | db949bba3c7cf2e664ac12e237c6d4c914f0c69d (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.c | 172 |
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 | } |
231 | EXPORT_SYMBOL(kernel_thread); | 231 | EXPORT_SYMBOL(kernel_thread); |
232 | 232 | ||
233 | /* | ||
234 | * Free current thread data structures etc.. | ||
235 | */ | ||
236 | void 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 | |||
259 | void 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 | |||
279 | void release_thread(struct task_struct *dead_task) | 233 | void 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 | } |
364 | EXPORT_SYMBOL_GPL(start_thread); | 318 | EXPORT_SYMBOL_GPL(start_thread); |
365 | 319 | ||
366 | static void hard_disable_TSC(void) | ||
367 | { | ||
368 | write_cr4(read_cr4() | X86_CR4_TSD); | ||
369 | } | ||
370 | |||
371 | void 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 | |||
383 | static void hard_enable_TSC(void) | ||
384 | { | ||
385 | write_cr4(read_cr4() & ~X86_CR4_TSD); | ||
386 | } | ||
387 | |||
388 | static 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 | |||
400 | int 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 | |||
412 | int 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 | |||
424 | static 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 | ||
585 | int sys_fork(struct pt_regs *regs) | ||
586 | { | ||
587 | return do_fork(SIGCHLD, regs->sp, regs, 0, NULL, NULL); | ||
588 | } | ||
589 | |||
590 | int sys_clone(struct pt_regs *regs) | 433 | int 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 | */ | ||
615 | int 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 | */ |
623 | int sys_execve(struct pt_regs *regs) | 451 | int sys_execve(struct pt_regs *regs) |