diff options
Diffstat (limited to 'arch/i386/kernel/process.c')
-rw-r--r-- | arch/i386/kernel/process.c | 50 |
1 files changed, 29 insertions, 21 deletions
diff --git a/arch/i386/kernel/process.c b/arch/i386/kernel/process.c index 94e2c87edeaa..923bb292f47f 100644 --- a/arch/i386/kernel/process.c +++ b/arch/i386/kernel/process.c | |||
@@ -359,16 +359,16 @@ EXPORT_SYMBOL(kernel_thread); | |||
359 | */ | 359 | */ |
360 | void exit_thread(void) | 360 | void exit_thread(void) |
361 | { | 361 | { |
362 | struct task_struct *tsk = current; | ||
363 | struct thread_struct *t = &tsk->thread; | ||
364 | |||
365 | /* The process may have allocated an io port bitmap... nuke it. */ | 362 | /* The process may have allocated an io port bitmap... nuke it. */ |
366 | if (unlikely(NULL != t->io_bitmap_ptr)) { | 363 | if (unlikely(test_thread_flag(TIF_IO_BITMAP))) { |
364 | struct task_struct *tsk = current; | ||
365 | struct thread_struct *t = &tsk->thread; | ||
367 | int cpu = get_cpu(); | 366 | int cpu = get_cpu(); |
368 | struct tss_struct *tss = &per_cpu(init_tss, cpu); | 367 | struct tss_struct *tss = &per_cpu(init_tss, cpu); |
369 | 368 | ||
370 | kfree(t->io_bitmap_ptr); | 369 | kfree(t->io_bitmap_ptr); |
371 | t->io_bitmap_ptr = NULL; | 370 | t->io_bitmap_ptr = NULL; |
371 | clear_thread_flag(TIF_IO_BITMAP); | ||
372 | /* | 372 | /* |
373 | * Careful, clear this in the TSS too: | 373 | * Careful, clear this in the TSS too: |
374 | */ | 374 | */ |
@@ -387,6 +387,7 @@ void flush_thread(void) | |||
387 | 387 | ||
388 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); | 388 | memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); |
389 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); | 389 | memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); |
390 | clear_tsk_thread_flag(tsk, TIF_DEBUG); | ||
390 | /* | 391 | /* |
391 | * Forget coprocessor state.. | 392 | * Forget coprocessor state.. |
392 | */ | 393 | */ |
@@ -431,7 +432,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, | |||
431 | savesegment(gs,p->thread.gs); | 432 | savesegment(gs,p->thread.gs); |
432 | 433 | ||
433 | tsk = current; | 434 | tsk = current; |
434 | if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) { | 435 | if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { |
435 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | 436 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); |
436 | if (!p->thread.io_bitmap_ptr) { | 437 | if (!p->thread.io_bitmap_ptr) { |
437 | p->thread.io_bitmap_max = 0; | 438 | p->thread.io_bitmap_max = 0; |
@@ -439,6 +440,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp, | |||
439 | } | 440 | } |
440 | memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, | 441 | memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, |
441 | IO_BITMAP_BYTES); | 442 | IO_BITMAP_BYTES); |
443 | set_tsk_thread_flag(p, TIF_IO_BITMAP); | ||
442 | } | 444 | } |
443 | 445 | ||
444 | /* | 446 | /* |
@@ -533,10 +535,24 @@ int dump_task_regs(struct task_struct *tsk, elf_gregset_t *regs) | |||
533 | return 1; | 535 | return 1; |
534 | } | 536 | } |
535 | 537 | ||
536 | static inline void | 538 | static noinline void __switch_to_xtra(struct task_struct *next_p, |
537 | handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) | 539 | struct tss_struct *tss) |
538 | { | 540 | { |
539 | if (!next->io_bitmap_ptr) { | 541 | struct thread_struct *next; |
542 | |||
543 | next = &next_p->thread; | ||
544 | |||
545 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
546 | set_debugreg(next->debugreg[0], 0); | ||
547 | set_debugreg(next->debugreg[1], 1); | ||
548 | set_debugreg(next->debugreg[2], 2); | ||
549 | set_debugreg(next->debugreg[3], 3); | ||
550 | /* no 4 and 5 */ | ||
551 | set_debugreg(next->debugreg[6], 6); | ||
552 | set_debugreg(next->debugreg[7], 7); | ||
553 | } | ||
554 | |||
555 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
540 | /* | 556 | /* |
541 | * Disable the bitmap via an invalid offset. We still cache | 557 | * Disable the bitmap via an invalid offset. We still cache |
542 | * the previous bitmap owner and the IO bitmap contents: | 558 | * the previous bitmap owner and the IO bitmap contents: |
@@ -544,6 +560,7 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) | |||
544 | tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | 560 | tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; |
545 | return; | 561 | return; |
546 | } | 562 | } |
563 | |||
547 | if (likely(next == tss->io_bitmap_owner)) { | 564 | if (likely(next == tss->io_bitmap_owner)) { |
548 | /* | 565 | /* |
549 | * Previous owner of the bitmap (hence the bitmap content) | 566 | * Previous owner of the bitmap (hence the bitmap content) |
@@ -671,20 +688,11 @@ struct task_struct fastcall * __switch_to(struct task_struct *prev_p, struct tas | |||
671 | set_iopl_mask(next->iopl); | 688 | set_iopl_mask(next->iopl); |
672 | 689 | ||
673 | /* | 690 | /* |
674 | * Now maybe reload the debug registers | 691 | * Now maybe handle debug registers and/or IO bitmaps |
675 | */ | 692 | */ |
676 | if (unlikely(next->debugreg[7])) { | 693 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)) |
677 | set_debugreg(next->debugreg[0], 0); | 694 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) |
678 | set_debugreg(next->debugreg[1], 1); | 695 | __switch_to_xtra(next_p, tss); |
679 | set_debugreg(next->debugreg[2], 2); | ||
680 | set_debugreg(next->debugreg[3], 3); | ||
681 | /* no 4 and 5 */ | ||
682 | set_debugreg(next->debugreg[6], 6); | ||
683 | set_debugreg(next->debugreg[7], 7); | ||
684 | } | ||
685 | |||
686 | if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) | ||
687 | handle_io_bitmap(next, tss); | ||
688 | 696 | ||
689 | disable_tsc(prev_p, next_p); | 697 | disable_tsc(prev_p, next_p); |
690 | 698 | ||