diff options
Diffstat (limited to 'arch/x86_64/kernel/process.c')
-rw-r--r-- | arch/x86_64/kernel/process.c | 73 |
1 files changed, 42 insertions, 31 deletions
diff --git a/arch/x86_64/kernel/process.c b/arch/x86_64/kernel/process.c index bb6745d13b8f..6e0527635b4c 100644 --- a/arch/x86_64/kernel/process.c +++ b/arch/x86_64/kernel/process.c | |||
@@ -350,6 +350,7 @@ void exit_thread(void) | |||
350 | 350 | ||
351 | kfree(t->io_bitmap_ptr); | 351 | kfree(t->io_bitmap_ptr); |
352 | t->io_bitmap_ptr = NULL; | 352 | t->io_bitmap_ptr = NULL; |
353 | clear_thread_flag(TIF_IO_BITMAP); | ||
353 | /* | 354 | /* |
354 | * Careful, clear this in the TSS too: | 355 | * Careful, clear this in the TSS too: |
355 | */ | 356 | */ |
@@ -369,6 +370,7 @@ void flush_thread(void) | |||
369 | if (t->flags & _TIF_IA32) | 370 | if (t->flags & _TIF_IA32) |
370 | current_thread_info()->status |= TS_COMPAT; | 371 | current_thread_info()->status |= TS_COMPAT; |
371 | } | 372 | } |
373 | t->flags &= ~_TIF_DEBUG; | ||
372 | 374 | ||
373 | tsk->thread.debugreg0 = 0; | 375 | tsk->thread.debugreg0 = 0; |
374 | tsk->thread.debugreg1 = 0; | 376 | tsk->thread.debugreg1 = 0; |
@@ -461,7 +463,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
461 | asm("mov %%es,%0" : "=m" (p->thread.es)); | 463 | asm("mov %%es,%0" : "=m" (p->thread.es)); |
462 | asm("mov %%ds,%0" : "=m" (p->thread.ds)); | 464 | asm("mov %%ds,%0" : "=m" (p->thread.ds)); |
463 | 465 | ||
464 | if (unlikely(me->thread.io_bitmap_ptr != NULL)) { | 466 | if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) { |
465 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); | 467 | p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); |
466 | if (!p->thread.io_bitmap_ptr) { | 468 | if (!p->thread.io_bitmap_ptr) { |
467 | p->thread.io_bitmap_max = 0; | 469 | p->thread.io_bitmap_max = 0; |
@@ -469,6 +471,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, | |||
469 | } | 471 | } |
470 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, | 472 | memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, |
471 | IO_BITMAP_BYTES); | 473 | IO_BITMAP_BYTES); |
474 | set_tsk_thread_flag(p, TIF_IO_BITMAP); | ||
472 | } | 475 | } |
473 | 476 | ||
474 | /* | 477 | /* |
@@ -498,6 +501,40 @@ out: | |||
498 | */ | 501 | */ |
499 | #define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r) | 502 | #define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r) |
500 | 503 | ||
504 | static inline void __switch_to_xtra(struct task_struct *prev_p, | ||
505 | struct task_struct *next_p, | ||
506 | struct tss_struct *tss) | ||
507 | { | ||
508 | struct thread_struct *prev, *next; | ||
509 | |||
510 | prev = &prev_p->thread, | ||
511 | next = &next_p->thread; | ||
512 | |||
513 | if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { | ||
514 | loaddebug(next, 0); | ||
515 | loaddebug(next, 1); | ||
516 | loaddebug(next, 2); | ||
517 | loaddebug(next, 3); | ||
518 | /* no 4 and 5 */ | ||
519 | loaddebug(next, 6); | ||
520 | loaddebug(next, 7); | ||
521 | } | ||
522 | |||
523 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | ||
524 | /* | ||
525 | * Copy the relevant range of the IO bitmap. | ||
526 | * Normally this is 128 bytes or less: | ||
527 | */ | ||
528 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | ||
529 | max(prev->io_bitmap_max, next->io_bitmap_max)); | ||
530 | } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { | ||
531 | /* | ||
532 | * Clear any possible leftover bits: | ||
533 | */ | ||
534 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | ||
535 | } | ||
536 | } | ||
537 | |||
501 | /* | 538 | /* |
502 | * switch_to(x,y) should switch tasks from x to y. | 539 | * switch_to(x,y) should switch tasks from x to y. |
503 | * | 540 | * |
@@ -586,37 +623,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) | |||
586 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); | 623 | task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); |
587 | 624 | ||
588 | /* | 625 | /* |
589 | * Now maybe reload the debug registers | 626 | * Now maybe reload the debug registers and handle I/O bitmaps |
590 | */ | 627 | */ |
591 | if (unlikely(next->debugreg7)) { | 628 | if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)) |
592 | loaddebug(next, 0); | 629 | || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) |
593 | loaddebug(next, 1); | 630 | __switch_to_xtra(prev_p, next_p, tss); |
594 | loaddebug(next, 2); | ||
595 | loaddebug(next, 3); | ||
596 | /* no 4 and 5 */ | ||
597 | loaddebug(next, 6); | ||
598 | loaddebug(next, 7); | ||
599 | } | ||
600 | |||
601 | |||
602 | /* | ||
603 | * Handle the IO bitmap | ||
604 | */ | ||
605 | if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) { | ||
606 | if (next->io_bitmap_ptr) | ||
607 | /* | ||
608 | * Copy the relevant range of the IO bitmap. | ||
609 | * Normally this is 128 bytes or less: | ||
610 | */ | ||
611 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, | ||
612 | max(prev->io_bitmap_max, next->io_bitmap_max)); | ||
613 | else { | ||
614 | /* | ||
615 | * Clear any possible leftover bits: | ||
616 | */ | ||
617 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); | ||
618 | } | ||
619 | } | ||
620 | 631 | ||
621 | return prev_p; | 632 | return prev_p; |
622 | } | 633 | } |