diff options
-rw-r--r-- | arch/x86_64/ia32/ptrace32.c | 4 | ||||
-rw-r--r-- | arch/x86_64/kernel/ioport.c | 1 | ||||
-rw-r--r-- | arch/x86_64/kernel/process.c | 73 | ||||
-rw-r--r-- | arch/x86_64/kernel/ptrace.c | 8 | ||||
-rw-r--r-- | include/asm-x86_64/thread_info.h | 7 |
5 files changed, 60 insertions, 33 deletions
diff --git a/arch/x86_64/ia32/ptrace32.c b/arch/x86_64/ia32/ptrace32.c index 659c0722f6b8..72bf92a9d375 100644 --- a/arch/x86_64/ia32/ptrace32.c +++ b/arch/x86_64/ia32/ptrace32.c | |||
@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) | |||
117 | if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) | 117 | if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) |
118 | return -EIO; | 118 | return -EIO; |
119 | child->thread.debugreg7 = val; | 119 | child->thread.debugreg7 = val; |
120 | if (val) | ||
121 | set_tsk_thread_flag(child, TIF_DEBUG); | ||
122 | else | ||
123 | clear_tsk_thread_flag(child, TIF_DEBUG); | ||
120 | break; | 124 | break; |
121 | 125 | ||
122 | default: | 126 | default: |
diff --git a/arch/x86_64/kernel/ioport.c b/arch/x86_64/kernel/ioport.c index b81614970ecc..fe063d3cfe42 100644 --- a/arch/x86_64/kernel/ioport.c +++ b/arch/x86_64/kernel/ioport.c | |||
@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
56 | 56 | ||
57 | memset(bitmap, 0xff, IO_BITMAP_BYTES); | 57 | memset(bitmap, 0xff, IO_BITMAP_BYTES); |
58 | t->io_bitmap_ptr = bitmap; | 58 | t->io_bitmap_ptr = bitmap; |
59 | set_thread_flag(TIF_IO_BITMAP); | ||
59 | } | 60 | } |
60 | 61 | ||
61 | /* | 62 | /* |
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 | } |
diff --git a/arch/x86_64/kernel/ptrace.c b/arch/x86_64/kernel/ptrace.c index 2d50024c9f30..d35ec1bc696a 100644 --- a/arch/x86_64/kernel/ptrace.c +++ b/arch/x86_64/kernel/ptrace.c | |||
@@ -420,9 +420,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) | |||
420 | if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1) | 420 | if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1) |
421 | break; | 421 | break; |
422 | if (i == 4) { | 422 | if (i == 4) { |
423 | child->thread.debugreg7 = data; | 423 | child->thread.debugreg7 = data; |
424 | if (data) | ||
425 | set_tsk_thread_flag(child, TIF_DEBUG); | ||
426 | else | ||
427 | clear_tsk_thread_flag(child, TIF_DEBUG); | ||
424 | ret = 0; | 428 | ret = 0; |
425 | } | 429 | } |
426 | break; | 430 | break; |
427 | } | 431 | } |
428 | break; | 432 | break; |
diff --git a/include/asm-x86_64/thread_info.h b/include/asm-x86_64/thread_info.h index 790c512a4369..787a08114b48 100644 --- a/include/asm-x86_64/thread_info.h +++ b/include/asm-x86_64/thread_info.h | |||
@@ -120,6 +120,8 @@ static inline struct thread_info *stack_thread_info(void) | |||
120 | #define TIF_FORK 18 /* ret_from_fork */ | 120 | #define TIF_FORK 18 /* ret_from_fork */ |
121 | #define TIF_ABI_PENDING 19 | 121 | #define TIF_ABI_PENDING 19 |
122 | #define TIF_MEMDIE 20 | 122 | #define TIF_MEMDIE 20 |
123 | #define TIF_DEBUG 21 /* uses debug registers */ | ||
124 | #define TIF_IO_BITMAP 22 /* uses I/O bitmap */ | ||
123 | 125 | ||
124 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) | 126 | #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) |
125 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) | 127 | #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) |
@@ -133,6 +135,8 @@ static inline struct thread_info *stack_thread_info(void) | |||
133 | #define _TIF_IA32 (1<<TIF_IA32) | 135 | #define _TIF_IA32 (1<<TIF_IA32) |
134 | #define _TIF_FORK (1<<TIF_FORK) | 136 | #define _TIF_FORK (1<<TIF_FORK) |
135 | #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) | 137 | #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) |
138 | #define _TIF_DEBUG (1<<TIF_DEBUG) | ||
139 | #define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP) | ||
136 | 140 | ||
137 | /* work to do on interrupt/exception return */ | 141 | /* work to do on interrupt/exception return */ |
138 | #define _TIF_WORK_MASK \ | 142 | #define _TIF_WORK_MASK \ |
@@ -140,6 +144,9 @@ static inline struct thread_info *stack_thread_info(void) | |||
140 | /* work to do on any return to user space */ | 144 | /* work to do on any return to user space */ |
141 | #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) | 145 | #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) |
142 | 146 | ||
147 | /* flags to check in __switch_to() */ | ||
148 | #define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP) | ||
149 | |||
143 | #define PREEMPT_ACTIVE 0x10000000 | 150 | #define PREEMPT_ACTIVE 0x10000000 |
144 | 151 | ||
145 | /* | 152 | /* |