aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorStephane Eranian <eranian@hpl.hp.com>2006-09-26 04:52:28 -0400
committerAndi Kleen <andi@basil.nowhere.org>2006-09-26 04:52:28 -0400
commitd3a4f48d4866b8623ca9adde8ce4e5fde979c132 (patch)
tree04413a1f18c6f49688d6008b583b20a287920a0f /arch
parent2f766d16062d0147edff91be15de4a950667ca42 (diff)
[PATCH] x86-64 TIF flags for debug regs and io bitmap in ctxsw
Hello, Following my discussion with Andi. Here is a patch that introduces two new TIF flags to simplify the context switch code in __switch_to(). The idea is to minimize the number of cache lines accessed in the common case, i.e., when neither the debug registers nor the I/O bitmap are used. This patch covers the x86-64 modifications. A patch for i386 follows. Changelog: - 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 <signed-off-by>: eranian@hpl.hp.com Signed-off-by: Andi Kleen <ak@suse.de>
Diffstat (limited to 'arch')
-rw-r--r--arch/x86_64/ia32/ptrace32.c4
-rw-r--r--arch/x86_64/kernel/ioport.c1
-rw-r--r--arch/x86_64/kernel/process.c73
-rw-r--r--arch/x86_64/kernel/ptrace.c8
4 files changed, 53 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
504static 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;