diff options
| author | Jeremy Fitzhardinge <jeremy@goop.org> | 2009-02-27 16:25:21 -0500 |
|---|---|---|
| committer | Ingo Molnar <mingo@elte.hu> | 2009-03-02 06:07:48 -0500 |
| commit | db949bba3c7cf2e664ac12e237c6d4c914f0c69d (patch) | |
| tree | 4de65831dd1de95f642bed15bc9788edd74c48da | |
| parent | 645af4e9e0e32481e3336dda813688732c7e5f0f (diff) | |
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: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
| -rw-r--r-- | arch/x86/include/asm/processor.h | 6 | ||||
| -rw-r--r-- | arch/x86/kernel/ioport.c | 11 | ||||
| -rw-r--r-- | arch/x86/kernel/process_32.c | 36 | ||||
| -rw-r--r-- | arch/x86/kernel/traps.c | 46 |
4 files changed, 9 insertions, 90 deletions
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index c7a98f738210..76139506c3e4 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h | |||
| @@ -248,7 +248,6 @@ struct x86_hw_tss { | |||
| 248 | #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long)) | 248 | #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long)) |
| 249 | #define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap) | 249 | #define IO_BITMAP_OFFSET offsetof(struct tss_struct, io_bitmap) |
| 250 | #define INVALID_IO_BITMAP_OFFSET 0x8000 | 250 | #define INVALID_IO_BITMAP_OFFSET 0x8000 |
| 251 | #define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000 | ||
| 252 | 251 | ||
| 253 | struct tss_struct { | 252 | struct tss_struct { |
| 254 | /* | 253 | /* |
| @@ -263,11 +262,6 @@ struct tss_struct { | |||
| 263 | * be within the limit. | 262 | * be within the limit. |
| 264 | */ | 263 | */ |
| 265 | unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; | 264 | unsigned long io_bitmap[IO_BITMAP_LONGS + 1]; |
| 266 | /* | ||
| 267 | * Cache the current maximum and the last task that used the bitmap: | ||
| 268 | */ | ||
| 269 | unsigned long io_bitmap_max; | ||
| 270 | struct thread_struct *io_bitmap_owner; | ||
| 271 | 265 | ||
| 272 | /* | 266 | /* |
| 273 | * .. and then another 0x100 bytes for the emergency kernel stack: | 267 | * .. and then another 0x100 bytes for the emergency kernel stack: |
diff --git a/arch/x86/kernel/ioport.c b/arch/x86/kernel/ioport.c index e41980a373ab..99c4d308f16b 100644 --- a/arch/x86/kernel/ioport.c +++ b/arch/x86/kernel/ioport.c | |||
| @@ -85,19 +85,8 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on) | |||
| 85 | 85 | ||
| 86 | t->io_bitmap_max = bytes; | 86 | t->io_bitmap_max = bytes; |
| 87 | 87 | ||
| 88 | #ifdef CONFIG_X86_32 | ||
| 89 | /* | ||
| 90 | * Sets the lazy trigger so that the next I/O operation will | ||
| 91 | * reload the correct bitmap. | ||
| 92 | * Reset the owner so that a process switch will not set | ||
| 93 | * tss->io_bitmap_base to IO_BITMAP_OFFSET. | ||
| 94 | */ | ||
| 95 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; | ||
| 96 | tss->io_bitmap_owner = NULL; | ||
| 97 | #else | ||
| 98 | /* Update the TSS: */ | 88 | /* Update the TSS: */ |
| 99 | memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); | 89 | memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); |
| 100 | #endif | ||
| 101 | 90 | ||
| 102 | put_cpu(); | 91 | put_cpu(); |
| 103 | 92 | ||
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 646da41a620a..a59314e877f0 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c | |||
| @@ -248,11 +248,8 @@ void exit_thread(void) | |||
| 248 | /* | 248 | /* |
| 249 | * Careful, clear this in the TSS too: | 249 | * Careful, clear this in the TSS too: |
| 250 | */ | 250 | */ |
| 251 | memset(tss->io_bitmap, 0xff, tss->io_bitmap_max); | 251 | memset(tss->io_bitmap, 0xff, t->io_bitmap_max); |
| 252 | t->io_bitmap_max = 0; | 252 | t->io_bitmap_max = 0; |
| 253 | tss->io_bitmap_owner = NULL; | ||
| 254 | tss->io_bitmap_max = 0; | ||
| 255 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | ||
| 256 | put_cpu(); | 253 | put_cpu(); |
| 257 | } | 254 | } |
| 258 | 255 | ||
| @@ -458,34 +455,19 @@ __switch_to_xtra(struct task_struct *prev_p, struct task_struct *next_p, | |||
| 458 | hard_enable_TSC(); | 455 | hard_enable_TSC(); |
| 459 | } | 456 | } |
| 460 | 457 | ||
| 461 | if (!test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { | 458 | if (test_tsk_thread_flag(next_p, TIF_IO_BITMAP)) { |
| 462 | /* | 459 | /* |
| 463 | * Disable the bitmap via an invalid offset. We still cache | 460 | * Copy the relevant range of the IO bitmap. |
| 464 | * the previous bitmap owner and the IO bitmap contents: | 461 | * Normally this is 128 bytes or less: |
| 465 | */ | 462 | */ |
| 466 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET; | 463 | memcpy(tss->io_bitmap, next->io_bitmap_ptr, |
| 467 | return; | 464 | max(prev->io_bitmap_max, next->io_bitmap_max)); |
| 468 | } | 465 | } else if (test_tsk_thread_flag(prev_p, TIF_IO_BITMAP)) { |
| 469 | |||
| 470 | if (likely(next == tss->io_bitmap_owner)) { | ||
| 471 | /* | 466 | /* |
| 472 | * Previous owner of the bitmap (hence the bitmap content) | 467 | * Clear any possible leftover bits: |
| 473 | * matches the next task, we dont have to do anything but | ||
| 474 | * to set a valid offset in the TSS: | ||
| 475 | */ | 468 | */ |
| 476 | tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; | 469 | memset(tss->io_bitmap, 0xff, prev->io_bitmap_max); |
| 477 | return; | ||
| 478 | } | 470 | } |
| 479 | /* | ||
| 480 | * Lazy TSS's I/O bitmap copy. We set an invalid offset here | ||
| 481 | * and we let the task to get a GPF in case an I/O instruction | ||
| 482 | * is performed. The handler of the GPF will verify that the | ||
| 483 | * faulting task has a valid I/O bitmap and, it true, does the | ||
| 484 | * real copy and restart the instruction. This will save us | ||
| 485 | * redundant copies when the currently switched task does not | ||
| 486 | * perform any I/O during its timeslice. | ||
| 487 | */ | ||
| 488 | tss->x86_tss.io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; | ||
| 489 | } | 471 | } |
| 490 | 472 | ||
| 491 | /* | 473 | /* |
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index c05430ac1b44..a1d288327ff0 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
| @@ -118,47 +118,6 @@ die_if_kernel(const char *str, struct pt_regs *regs, long err) | |||
| 118 | if (!user_mode_vm(regs)) | 118 | if (!user_mode_vm(regs)) |
| 119 | die(str, regs, err); | 119 | die(str, regs, err); |
| 120 | } | 120 | } |
| 121 | |||
| 122 | /* | ||
| 123 | * Perform the lazy TSS's I/O bitmap copy. If the TSS has an | ||
| 124 | * invalid offset set (the LAZY one) and the faulting thread has | ||
| 125 | * a valid I/O bitmap pointer, we copy the I/O bitmap in the TSS, | ||
| 126 | * we set the offset field correctly and return 1. | ||
| 127 | */ | ||
| 128 | static int lazy_iobitmap_copy(void) | ||
| 129 | { | ||
| 130 | struct thread_struct *thread; | ||
| 131 | struct tss_struct *tss; | ||
| 132 | int cpu; | ||
| 133 | |||
| 134 | cpu = get_cpu(); | ||
| 135 | tss = &per_cpu(init_tss, cpu); | ||
| 136 | thread = ¤t->thread; | ||
| 137 | |||
| 138 | if (tss->x86_tss.io_bitmap_base == INVALID_IO_BITMAP_OFFSET_LAZY && | ||
| 139 | thread->io_bitmap_ptr) { | ||
| 140 | memcpy(tss->io_bitmap, thread->io_bitmap_ptr, | ||
| 141 | thread->io_bitmap_max); | ||
| 142 | /* | ||
| 143 | * If the previously set map was extending to higher ports | ||
| 144 | * than the current one, pad extra space with 0xff (no access). | ||
| 145 | */ | ||
| 146 | if (thread->io_bitmap_max < tss->io_bitmap_max) { | ||
| 147 | memset((char *) tss->io_bitmap + | ||
| 148 | thread->io_bitmap_max, 0xff, | ||
| 149 | tss->io_bitmap_max - thread->io_bitmap_max); | ||
| 150 | } | ||
| 151 | tss->io_bitmap_max = thread->io_bitmap_max; | ||
| 152 | tss->x86_tss.io_bitmap_base = IO_BITMAP_OFFSET; | ||
| 153 | tss->io_bitmap_owner = thread; | ||
| 154 | put_cpu(); | ||
| 155 | |||
| 156 | return 1; | ||
| 157 | } | ||
| 158 | put_cpu(); | ||
| 159 | |||
| 160 | return 0; | ||
| 161 | } | ||
| 162 | #endif | 121 | #endif |
| 163 | 122 | ||
| 164 | static void __kprobes | 123 | static void __kprobes |
| @@ -309,11 +268,6 @@ do_general_protection(struct pt_regs *regs, long error_code) | |||
| 309 | conditional_sti(regs); | 268 | conditional_sti(regs); |
| 310 | 269 | ||
| 311 | #ifdef CONFIG_X86_32 | 270 | #ifdef CONFIG_X86_32 |
| 312 | if (lazy_iobitmap_copy()) { | ||
| 313 | /* restart the faulting instruction */ | ||
| 314 | return; | ||
| 315 | } | ||
| 316 | |||
| 317 | if (regs->flags & X86_VM_MASK) | 271 | if (regs->flags & X86_VM_MASK) |
| 318 | goto gp_in_vm86; | 272 | goto gp_in_vm86; |
| 319 | #endif | 273 | #endif |
