Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

[PATCH] i386: use thread_info flags for debug regs and IO bitmaps

Use thread info flags to track use of debug registers and IO bitmaps.

- add TIF_DEBUG to track when debug registers are active
- add TIF_IO_BITMAP to track when I/O bitmap is used
- modify __switch_to() to use the new TIF flags

Performance tested on Pentium II, ten runs of LMbench context switch
benchmark (smaller is better:)

before after
avg 3.65 3.39
min 3.55 3.33

Signed-off-by: Stephane Eranian <eranian@hpl.hp.com>
Signed-off-by: Chuck Ebbert <76306.1226@compuserve.com>
Acked-by: Andi Kleen <ak@suse.de>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>

authored by

Stephane Eranian and committed by
Linus Torvalds
b3cf2576 09075ef0

+41 -22
+1
arch/i386/kernel/ioport.c
··· 79 79 80 80 memset(bitmap, 0xff, IO_BITMAP_BYTES); 81 81 t->io_bitmap_ptr = bitmap; 82 + set_thread_flag(TIF_IO_BITMAP); 82 83 } 83 84 84 85 /*
+29 -21
arch/i386/kernel/process.c
··· 359 359 */ 360 360 void exit_thread(void) 361 361 { 362 - struct task_struct *tsk = current; 363 - struct thread_struct *t = &tsk->thread; 364 - 365 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 366 int cpu = get_cpu(); 368 367 struct tss_struct *tss = &per_cpu(init_tss, cpu); 369 368 370 369 kfree(t->io_bitmap_ptr); 371 370 t->io_bitmap_ptr = NULL; 371 + clear_thread_flag(TIF_IO_BITMAP); 372 372 /* 373 373 * Careful, clear this in the TSS too: 374 374 */ ··· 387 387 388 388 memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8); 389 389 memset(tsk->thread.tls_array, 0, sizeof(tsk->thread.tls_array)); 390 + clear_tsk_thread_flag(tsk, TIF_DEBUG); 390 391 /* 391 392 * Forget coprocessor state.. 392 393 */ ··· 432 431 savesegment(gs,p->thread.gs); 433 432 434 433 tsk = current; 435 - if (unlikely(NULL != tsk->thread.io_bitmap_ptr)) { 434 + if (unlikely(test_tsk_thread_flag(tsk, TIF_IO_BITMAP))) { 436 435 p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); 437 436 if (!p->thread.io_bitmap_ptr) { 438 437 p->thread.io_bitmap_max = 0; ··· 440 439 } 441 440 memcpy(p->thread.io_bitmap_ptr, tsk->thread.io_bitmap_ptr, 442 441 IO_BITMAP_BYTES); 442 + set_tsk_thread_flag(p, TIF_IO_BITMAP); 443 443 } 444 444 445 445 /* ··· 535 533 return 1; 536 534 } 537 535 538 - static inline void 539 - handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss) 536 + static noinline void __switch_to_xtra(struct task_struct *next_p, 537 + struct tss_struct *tss) 540 538 { 541 - if (!next->io_bitmap_ptr) { 539 + struct thread_struct *next; 540 + 541 + next = &next_p->thread; 542 + 543 + if (test_tsk_thread_flag(next_p, TIF_DEBUG)) { 544 + set_debugreg(next->debugreg[0], 0); 545 + set_debugreg(next->debugreg[1], 1); 546 + set_debugreg(next->debugreg[2], 2); 547 + set_debugreg(next->debugreg[3], 3); 548 + /* no 4 and 5 */ 549 + set_debugreg(next->debugreg[6], 6); 550 + set_debugreg(next->debugreg[7], 7); 551 + } 552 + 553 + if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { 542 554 /* 543 555 * Disable the bitmap via an invalid offset. We still cache 544 556 * the previous bitmap owner and the IO bitmap contents: ··· 560 544 tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET; 561 545 return; 562 546 } 547 + 563 548 if (likely(next == tss->io_bitmap_owner)) { 564 549 /* 565 550 * Previous owner of the bitmap (hence the bitmap content) ··· 688 671 set_iopl_mask(next->iopl); 689 672 690 673 /* 691 - * Now maybe reload the debug registers 674 + * Now maybe handle debug registers and/or IO bitmaps 692 675 */ 693 - if (unlikely(next->debugreg[7])) { 694 - set_debugreg(next->debugreg[0], 0); 695 - set_debugreg(next->debugreg[1], 1); 696 - set_debugreg(next->debugreg[2], 2); 697 - set_debugreg(next->debugreg[3], 3); 698 - /* no 4 and 5 */ 699 - set_debugreg(next->debugreg[6], 6); 700 - set_debugreg(next->debugreg[7], 7); 701 - } 702 - 703 - if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) 704 - handle_io_bitmap(next, tss); 676 + if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW)) 677 + || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) 678 + __switch_to_xtra(next_p, tss); 705 679 706 680 disable_tsc(prev_p, next_p); 707 681
+4 -1
arch/i386/kernel/ptrace.c
··· 468 468 for(i=0; i<4; i++) 469 469 if ((0x5f54 >> ((data >> (16 + 4*i)) & 0xf)) & 1) 470 470 goto out_tsk; 471 + if (data) 472 + set_tsk_thread_flag(child, TIF_DEBUG); 473 + else 474 + clear_tsk_thread_flag(child, TIF_DEBUG); 471 475 } 472 - 473 476 addr -= (long) &dummy->u_debugreg; 474 477 addr = addr >> 2; 475 478 child->thread.debugreg[addr] = data;
+7
include/asm-i386/thread_info.h
··· 140 140 #define TIF_SECCOMP 8 /* secure computing */ 141 141 #define TIF_RESTORE_SIGMASK 9 /* restore signal mask in do_signal() */ 142 142 #define TIF_MEMDIE 16 143 + #define TIF_DEBUG 17 /* uses debug registers */ 144 + #define TIF_IO_BITMAP 18 /* uses I/O bitmap */ 143 145 144 146 #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) 145 147 #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) ··· 153 151 #define _TIF_SYSCALL_AUDIT (1<<TIF_SYSCALL_AUDIT) 154 152 #define _TIF_SECCOMP (1<<TIF_SECCOMP) 155 153 #define _TIF_RESTORE_SIGMASK (1<<TIF_RESTORE_SIGMASK) 154 + #define _TIF_DEBUG (1<<TIF_DEBUG) 155 + #define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP) 156 156 157 157 /* work to do on interrupt/exception return */ 158 158 #define _TIF_WORK_MASK \ ··· 162 158 _TIF_SECCOMP | _TIF_SYSCALL_EMU)) 163 159 /* work to do on any return to u-space */ 164 160 #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) 161 + 162 + /* flags to check in __switch_to() */ 163 + #define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP) 165 164 166 165 /* 167 166 * Thread-synchronous status.