Commit db949bba authored by Jeremy Fitzhardinge's avatar Jeremy Fitzhardinge Committed by Ingo Molnar

x86-32: use non-lazy io bitmap context switching

Impact: remove 32-bit optimization to prepare unification

x86-32 and -64 differ in the way they context-switch tasks
with io permission bitmaps.  x86-64 simply copies the next
tasks io bitmap into place (if any) on context switch.  x86-32
invalidates the bitmap on context switch, so that the next
IO instruction will fault; at that point it installs the
appropriate IO bitmap.

This makes context switching IO-bitmap-using tasks a bit more
less expensive, at the cost of making the next IO instruction
slower due to the extra fault.  This tradeoff only makes sense
if IO-bitmap-using processes are relatively common, but they
don't actually use IO instructions very often.

However, in a typical desktop system, the only process likely
to be using IO bitmaps is the X server, and nothing at all on
a server.  Therefore the lazy context switch doesn't really win
all that much, and its just a gratuitious difference from
64-bit code.

This patch removes the lazy context switch, with a view to
unifying this code in a later change.
Signed-off-by: default avatarJeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 645af4e9
...@@ -248,7 +248,6 @@ struct x86_hw_tss { ...@@ -248,7 +248,6 @@ struct x86_hw_tss {
#define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long)) #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long))
#define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap) #define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap)
#define INVALID_IO_BITMAP_OFFSET 0x8000 #define INVALID_IO_BITMAP_OFFSET 0x8000
#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000
struct tss_struct { struct tss_struct {
/* /*
...@@ -263,11 +262,6 @@ struct tss_struct { ...@@ -263,11 +262,6 @@ struct tss_struct {
* be within the limit. * be within the limit.
*/ */
unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; unsigned long io_bitmap[IO_BITMAP_LONGS + 1];
/*
* Cache the current maximum and the last task that used the bitmap:
*/
unsigned long io_bitmap_max;
struct thread_struct *io_bitmap_owner;
/* /*
* .. and then another 0x100 bytes for the emergency kernel stack: * .. and then another 0x100 bytes for the emergency kernel stack:
......
...@@ -85,19 +85,8 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) ...@@ -85,19 +85,8 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
t->io_bitmap_max = bytes; t->io_bitmap_max = bytes;
#ifdef CONFIG_X86_32
/*
* Sets the lazy trigger so that the next I/O operation will
* reload the correct bitmap.
* Reset the owner so that a process switch will not set
* tss->io_bitmap_base to IO_BITMAP_OFFSET.
*/
tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
tss->io_bitmap_owner = NULL;
#else
/* Update the TSS: */ /* Update the TSS: */
memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated);
#endif
put_cpu(); put_cpu();
......
...@@ -248,11 +248,8 @@ void exit_thread(void) ...@@ -248,11 +248,8 @@ void exit_thread(void)
/* /*
* Careful, clear this in the TSS too: * Careful, clear this in the TSS too:
*/ */
memset(tss->io_bitmap, 0xff, tss->io_bitmap_max); memset(tss->io_bitmap, 0xff, t->io_bitmap_max);
t->io_bitmap_max = 0; t->io_bitmap_max = 0;
tss->io_bitmap_owner = NULL;
tss->io_bitmap_max = 0;
tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET;
put_cpu(); put_cpu();
} }
...@@ -458,34 +455,19 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, ...@@ -458,34 +455,19 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p,
hard_enable_TSC(); hard_enable_TSC();
} }
if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) {
/* /*
* Disable the bitmap via an invalid offset. We still cache * Copy the relevant range of the IO bitmap.
* the previous bitmap owner and the IO bitmap contents: * Normally this is 128 bytes or less:
*/ */
tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; memcpy(tss->io_bitmap, next->io_bitmap_ptr,
return; max(prev->io_bitmap_max, next->io_bitmap_max));
} } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) {
if (likely(next == tss->io_bitmap_owner)) {
/* /*
* Previous owner of the bitmap (hence the bitmap content) * Clear any possible leftover bits:
* matches the next task, we dont have to do anything but
* to set a valid offset in the TSS:
*/ */
tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; memset(tss->io_bitmap, 0xff, prev->io_bitmap_max);
return;
} }
/*
* Lazy TSS's I/O bitmap copy. We set an invalid offset here
* and we let the task to get a GPF in case an I/O instruction
* is performed. The handler of the GPF will verify that the
* faulting task has a valid I/O bitmap and, it true, does the
* real copy and restart the instruction. This will save us
* redundant copies when the currently switched task does not
* perform any I/O during its timeslice.
*/
tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY;
} }
/* /*
......
...@@ -118,47 +118,6 @@ die_if_kernel(const char *str, struct pt_regs *regs, long err) ...@@ -118,47 +118,6 @@ die_if_kernel(const char *str, struct pt_regs *regs, long err)
if (!user_mode_vm(regs)) if (!user_mode_vm(regs))
die(str, regs, err); die(str, regs, err);
} }
/*
* Perform the lazy TSS's I/O bitmap copy. If the TSS has an
* invalid offset set (the LAZY one) and the faulting thread has
* a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS,
* we set the offset field correctly and return 1.
*/
static int lazy_iobitmap_copy(void)
{
struct thread_struct *thread;
struct tss_struct *tss;
int cpu;
cpu = get_cpu();
tss = &per_cpu(init_tss, cpu);
thread = &current->thread;
if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY &&
thread->io_bitmap_ptr) {
memcpy(tss->io_bitmap, thread->io_bitmap_ptr,
thread->io_bitmap_max);
/*
* If the previously set map was extending to higher ports
* than the current one, pad extra space with 0xff (no access).
*/
if (thread->io_bitmap_max < tss->io_bitmap_max) {
memset((char *) tss->io_bitmap +
thread->io_bitmap_max, 0xff,
tss->io_bitmap_max - thread->io_bitmap_max);
}
tss->io_bitmap_max = thread->io_bitmap_max;
tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET;
tss->io_bitmap_owner = thread;
put_cpu();
return 1;
}
put_cpu();
return 0;
}
#endif #endif
static void __kprobes static void __kprobes
...@@ -309,11 +268,6 @@ do_general_protection(struct pt_regs *regs, long error_code) ...@@ -309,11 +268,6 @@ do_general_protection(struct pt_regs *regs, long error_code)
conditional_sti(regs); conditional_sti(regs);
#ifdef CONFIG_X86_32 #ifdef CONFIG_X86_32
if (lazy_iobitmap_copy()) {
/* restart the faulting instruction */
return;
}
if (regs->flags & X86_VM_MASK) if (regs->flags & X86_VM_MASK)
goto gp_in_vm86; goto gp_in_vm86;
#endif #endif
......
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