Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

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

[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
Loading
Loading
Loading
Loading
+4 −0
Original line number Diff line number Diff line
@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
			if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)
			       return -EIO;
		child->thread.debugreg7 = val; 
		if (val)
			set_tsk_thread_flag(child, TIF_DEBUG);
		else
			clear_tsk_thread_flag(child, TIF_DEBUG);
		break; 
		    
	default:
+1 −0
Original line number Diff line number Diff line
@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)

		memset(bitmap, 0xff, IO_BITMAP_BYTES);
		t->io_bitmap_ptr = bitmap;
		set_thread_flag(TIF_IO_BITMAP);
	}

	/*
+42 −31
Original line number Diff line number Diff line
@@ -350,6 +350,7 @@ void exit_thread(void)

		kfree(t->io_bitmap_ptr);
		t->io_bitmap_ptr = NULL;
		clear_thread_flag(TIF_IO_BITMAP);
		/*
		 * Careful, clear this in the TSS too:
		 */
@@ -369,6 +370,7 @@ void flush_thread(void)
		if (t->flags & _TIF_IA32)
			current_thread_info()->status |= TS_COMPAT;
	}
	t->flags &= ~_TIF_DEBUG;

	tsk->thread.debugreg0 = 0;
	tsk->thread.debugreg1 = 0;
@@ -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 %%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);
		if (!p->thread.io_bitmap_ptr) {
			p->thread.io_bitmap_max = 0;
@@ -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,
				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,
 */
#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.
 *
@@ -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);

	/*
	 * Now maybe reload the debug registers
	 * Now maybe reload the debug registers and handle I/O bitmaps
	 */
	if (unlikely(next->debugreg7)) {
		loaddebug(next, 0);
		loaddebug(next, 1);
		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);
		}
	}
	if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
	    || test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
		__switch_to_xtra(prev_p, next_p, tss);

	return prev_p;
}
+6 −2
Original line number Diff line number Diff line
@@ -421,6 +421,10 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
					break;
			if (i == 4) {
			  child->thread.debugreg7 = data;
			  if (data)
			  	set_tsk_thread_flag(child, TIF_DEBUG);
			  else
			  	clear_tsk_thread_flag(child, TIF_DEBUG);
			  ret = 0;
		  	}
		  break;
+7 −0
Original line number Diff line number Diff line
@@ -120,6 +120,8 @@ static inline struct thread_info *stack_thread_info(void)
#define TIF_FORK		18	/* ret_from_fork */
#define TIF_ABI_PENDING		19
#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_NOTIFY_RESUME	(1<<TIF_NOTIFY_RESUME)
@@ -133,6 +135,8 @@ static inline struct thread_info *stack_thread_info(void)
#define _TIF_IA32		(1<<TIF_IA32)
#define _TIF_FORK		(1<<TIF_FORK)
#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 */
#define _TIF_WORK_MASK \
@@ -140,6 +144,9 @@ static inline struct thread_info *stack_thread_info(void)
/* work to do on any return to user space */
#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

/*