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 | ||
