Skip to content

Commit d3a4f48

Browse files
Stephane EranianAndi Kleen
authored andcommitted
[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>
1 parent 2f766d1 commit d3a4f48

File tree

5 files changed

+60
-33
lines changed

5 files changed

+60
-33
lines changed

arch/x86_64/ia32/ptrace32.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,10 @@ static int putreg32(struct task_struct *child, unsigned regno, u32 val)
117117
if ((0x5454 >> ((val >> (16 + 4*i)) & 0xf)) & 1)
118118
return -EIO;
119119
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);
120124
break;
121125

122126
default:

arch/x86_64/kernel/ioport.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
5656

5757
memset(bitmap, 0xff, IO_BITMAP_BYTES);
5858
t->io_bitmap_ptr = bitmap;
59+
set_thread_flag(TIF_IO_BITMAP);
5960
}
6061

6162
/*

arch/x86_64/kernel/process.c

Lines changed: 42 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -350,6 +350,7 @@ void exit_thread(void)
350350

351351
kfree(t->io_bitmap_ptr);
352352
t->io_bitmap_ptr = NULL;
353+
clear_thread_flag(TIF_IO_BITMAP);
353354
/*
354355
* Careful, clear this in the TSS too:
355356
*/
@@ -369,6 +370,7 @@ void flush_thread(void)
369370
if (t->flags & _TIF_IA32)
370371
current_thread_info()->status |= TS_COMPAT;
371372
}
373+
t->flags &= ~_TIF_DEBUG;
372374

373375
tsk->thread.debugreg0 = 0;
374376
tsk->thread.debugreg1 = 0;
@@ -461,14 +463,15 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
461463
asm("mov %%es,%0" : "=m" (p->thread.es));
462464
asm("mov %%ds,%0" : "=m" (p->thread.ds));
463465

464-
if (unlikely(me->thread.io_bitmap_ptr != NULL)) {
466+
if (unlikely(test_tsk_thread_flag(me, TIF_IO_BITMAP))) {
465467
p->thread.io_bitmap_ptr = kmalloc(IO_BITMAP_BYTES, GFP_KERNEL);
466468
if (!p->thread.io_bitmap_ptr) {
467469
p->thread.io_bitmap_max = 0;
468470
return -ENOMEM;
469471
}
470472
memcpy(p->thread.io_bitmap_ptr, me->thread.io_bitmap_ptr,
471473
IO_BITMAP_BYTES);
474+
set_tsk_thread_flag(p, TIF_IO_BITMAP);
472475
}
473476

474477
/*
@@ -498,6 +501,40 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long rsp,
498501
*/
499502
#define loaddebug(thread,r) set_debugreg(thread->debugreg ## r, r)
500503

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+
501538
/*
502539
* switch_to(x,y) should switch tasks from x to y.
503540
*
@@ -586,37 +623,11 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
586623
task_stack_page(next_p) + THREAD_SIZE - PDA_STACKOFFSET);
587624

588625
/*
589-
* Now maybe reload the debug registers
626+
* Now maybe reload the debug registers and handle I/O bitmaps
590627
*/
591-
if (unlikely(next->debugreg7)) {
592-
loaddebug(next, 0);
593-
loaddebug(next, 1);
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-
}
628+
if (unlikely((task_thread_info(next_p)->flags & _TIF_WORK_CTXSW))
629+
|| test_tsk_thread_flag(prev_p, TIF_IO_BITMAP))
630+
__switch_to_xtra(prev_p, next_p, tss);
620631

621632
return prev_p;
622633
}

arch/x86_64/kernel/ptrace.c

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -420,9 +420,13 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data)
420420
if ((0x5554 >> ((data >> (16 + 4*i)) & 0xf)) & 1)
421421
break;
422422
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);
424428
ret = 0;
425-
}
429+
}
426430
break;
427431
}
428432
break;

include/asm-x86_64/thread_info.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,8 @@ static inline struct thread_info *stack_thread_info(void)
120120
#define TIF_FORK 18 /* ret_from_fork */
121121
#define TIF_ABI_PENDING 19
122122
#define TIF_MEMDIE 20
123+
#define TIF_DEBUG 21 /* uses debug registers */
124+
#define TIF_IO_BITMAP 22 /* uses I/O bitmap */
123125

124126
#define _TIF_SYSCALL_TRACE (1<<TIF_SYSCALL_TRACE)
125127
#define _TIF_NOTIFY_RESUME (1<<TIF_NOTIFY_RESUME)
@@ -133,13 +135,18 @@ static inline struct thread_info *stack_thread_info(void)
133135
#define _TIF_IA32 (1<<TIF_IA32)
134136
#define _TIF_FORK (1<<TIF_FORK)
135137
#define _TIF_ABI_PENDING (1<<TIF_ABI_PENDING)
138+
#define _TIF_DEBUG (1<<TIF_DEBUG)
139+
#define _TIF_IO_BITMAP (1<<TIF_IO_BITMAP)
136140

137141
/* work to do on interrupt/exception return */
138142
#define _TIF_WORK_MASK \
139143
(0x0000FFFF & ~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP|_TIF_SECCOMP))
140144
/* work to do on any return to user space */
141145
#define _TIF_ALLWORK_MASK (0x0000FFFF & ~_TIF_SECCOMP)
142146

147+
/* flags to check in __switch_to() */
148+
#define _TIF_WORK_CTXSW (_TIF_DEBUG|_TIF_IO_BITMAP)
149+
143150
#define PREEMPT_ACTIVE 0x10000000
144151

145152
/*

0 commit comments

Comments
 (0)