Commit d3a4f48d authored by Stephane Eranian's avatar Stephane Eranian Committed by Andi Kleen

[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: default avatarAndi Kleen <ak@suse.de>
parent 2f766d16
...@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val) ...@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1) if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)
return -EIO; return -EIO;
child->thread.debugreg7 = val; child->thread.debugreg7 = val;
if (val)
set_tsk_thread_flag(child, TIF_DEBUG);
else
clear_tsk_thread_flag(child, TIF_DEBUG);
break; break;
default: default:
......
...@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) ...@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
memset(bitmap, 0xff, IO_BITMAP_BYTES); memset(bitmap, 0xff, IO_BITMAP_BYTES);
t->io_bitmap_ptr = bitmap; t->io_bitmap_ptr = bitmap;
set_thread_flag(TIF_IO_BITMAP);
} }
/* /*
......
...@@ -350,6 +350,7 @@ void exit_thread(void) ...@@ -350,6 +350,7 @@ void exit_thread(void)
kfree(t->io_bitmap_ptr); kfree(t->io_bitmap_ptr);
t->io_bitmap_ptr = NULL; t->io_bitmap_ptr = NULL;
clear_thread_flag(TIF_IO_BITMAP);
/* /*
* Careful, clear this in the TSS too: * Careful, clear this in the TSS too:
*/ */
...@@ -369,6 +370,7 @@ void flush_thread(void) ...@@ -369,6 +370,7 @@ void flush_thread(void)
if (t->flags & _TIF_IA32) if (t->flags & _TIF_IA32)
current_thread_info()->status |= TS_COMPAT; current_thread_info()->status |= TS_COMPAT;
} }
t->flags &= ~_TIF_DEBUG;
tsk->thread.debugreg0 = 0; tsk->thread.debugreg0 = 0;
tsk->thread.debugreg1 = 0; tsk->thread.debugreg1 = 0;
...@@ -461,7 +463,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, ...@@ -461,7 +463,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
asm("mov %%es,%0" : "=m" (p->thread.es)); asm("mov %%es,%0" : "=m" (p->thread.es));
asm("mov %%ds,%0" : "=m" (p->thread.ds)); asm("mov %%ds,%0" : "=m" (p->thread.ds));
if (unlikely(me->thread.io_bitmap_ptr != NULL)) { if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL); p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
if (!p->thread.io_bitmap_ptr) { if (!p->thread.io_bitmap_ptr) {
p->thread.io_bitmap_max = 0; p->thread.io_bitmap_max = 0;
...@@ -469,6 +471,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, ...@@ -469,6 +471,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
} }
memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr, memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
IO_BITMAP_BYTES); IO_BITMAP_BYTES);
set_tsk_thread_flag(p, TIF_IO_BITMAP);
} }
/* /*
...@@ -498,6 +501,40 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp, ...@@ -498,6 +501,40 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
*/ */
#define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r) #define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
static inline void __switch_to_xtra(struct task_struct *prev_p,
struct task_struct *next_p,
struct tss_struct *tss)
{
struct thread_struct *prev, *next;
prev = &prev_p->thread,
next = &next_p->thread;
if (test_tsk_thread_flag(next_p, TIF_DEBUG)) {
loaddebug(next, 0);
loaddebug(next, 1);
loaddebug(next, 2);
loaddebug(next, 3);
/* no 4 and 5 */
loaddebug(next, 6);
loaddebug(next, 7);
}
if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
/*
* Copy the relevant range of the IO bitmap.
* Normally this is 128 bytes or less:
*/
memcpy(tss->io_bitmap, next->io_bitmap_ptr,
max(prev->io_bitmap_max, next->io_bitmap_max));
} else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
/*
* Clear any possible leftover bits:
*/
memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
}
}
/* /*
* switch_to(x,y) should switch tasks from x to y. * switch_to(x,y) should switch tasks from x to y.
* *
...@@ -586,37 +623,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p) ...@@ -586,37 +623,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET); task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
/* /*
* Now maybe reload the debug registers * Now maybe reload the debug registers and handle I/O bitmaps
*/ */
if (unlikely(next->debugreg7)) { if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
loaddebug(next, 0); || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
loaddebug(next, 1); __switch_to_xtra(prev_p, next_p, tss);
loaddebug(next, 2);
loaddebug(next, 3);
/* no 4 and 5 */
loaddebug(next, 6);
loaddebug(next, 7);
}
/*
* Handle the IO bitmap
*/
if (unlikely(prev->io_bitmap_ptr || next->io_bitmap_ptr)) {
if (next->io_bitmap_ptr)
/*
* Copy the relevant range of the IO bitmap.
* Normally this is 128 bytes or less:
*/
memcpy(tss->io_bitmap, next->io_bitmap_ptr,
max(prev->io_bitmap_max, next->io_bitmap_max));
else {
/*
* Clear any possible leftover bits:
*/
memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
}
}
return prev_p; return prev_p;
} }
......
...@@ -420,9 +420,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) ...@@ -420,9 +420,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1) if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
break; break;
if (i == 4) { if (i == 4) {
child->thread.debugreg7 = data; child->thread.debugreg7 = data;
if (data)
set_tsk_thread_flag(child, TIF_DEBUG);
else
clear_tsk_thread_flag(child, TIF_DEBUG);
ret = 0; ret = 0;
} }
break; break;
} }
break; break;
......
...@@ -120,6 +120,8 @@ static inline struct thread_info *stack_thread_info(void) ...@@ -120,6 +120,8 @@ static inline struct thread_info *stack_thread_info(void)
#define TIF_FORK 18 /* ret_from_fork */ #define TIF_FORK 18 /* ret_from_fork */
#define TIF_ABI_PENDING 19 #define TIF_ABI_PENDING 19
#define TIF_MEMDIE 20 #define TIF_MEMDIE 20
#define TIF_DEBUG 21 /* uses debug registers */
#define TIF_IO_BITMAP 22 /* uses I/O bitmap */
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE) #define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME) #define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
...@@ -133,6 +135,8 @@ static inline struct thread_info *stack_thread_info(void) ...@@ -133,6 +135,8 @@ static inline struct thread_info *stack_thread_info(void)
#define _TIF_IA32 (1<<TIF_IA32) #define _TIF_IA32 (1<<TIF_IA32)
#define _TIF_FORK (1<<TIF_FORK) #define _TIF_FORK (1<<TIF_FORK)
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING) #define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
#define _TIF_DEBUG (1<<TIF_DEBUG)
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
/* work to do on interrupt/exception return */ /* work to do on interrupt/exception return */
#define _TIF_WORK_MASK \ #define _TIF_WORK_MASK \
...@@ -140,6 +144,9 @@ static inline struct thread_info *stack_thread_info(void) ...@@ -140,6 +144,9 @@ static inline struct thread_info *stack_thread_info(void)
/* work to do on any return to user space */ /* work to do on any return to user space */
#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP) #define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
/* flags to check in __switch_to() */
#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
#define PREEMPT_ACTIVE 0x10000000 #define PREEMPT_ACTIVE 0x10000000
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment