From: Ingo Molnar This uses Davide's do_general_protection() fault based io-bitmap lazy update code and combines it with the ioport-owner cache. Signed-off-by: Ingo Molnar Signed-off-by: Andrew Morton --- 25-akpm/arch/i386/kernel/ioport.c | 10 +++++----- 25-akpm/arch/i386/kernel/process.c | 17 ++++++++--------- 25-akpm/arch/i386/kernel/traps.c | 30 ++++++++++++++++++++++++++++++ 25-akpm/include/asm-i386/processor.h | 1 + 4 files changed, 44 insertions(+), 14 deletions(-) diff -puN arch/i386/kernel/ioport.c~ioport-cache-gpf-2.6.9-rc1-mm5-A3 arch/i386/kernel/ioport.c --- 25/arch/i386/kernel/ioport.c~ioport-cache-gpf-2.6.9-rc1-mm5-A3 2004-09-14 01:48:34.199906544 -0700 +++ 25-akpm/arch/i386/kernel/ioport.c 2004-09-14 01:48:34.207905328 -0700 @@ -105,11 +105,11 @@ asmlinkage long sys_ioperm(unsigned long t->io_bitmap_max = bytes; - /* Update the TSS: */ - memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated); - tss->io_bitmap_max = bytes; - tss->io_bitmap_owner = ¤t->thread; - tss->io_bitmap_base = IO_BITMAP_OFFSET; + /* + * Sets the lazy trigger so that the next I/O operation will + * reload the correct bitmap. + */ + tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; put_cpu(); diff -puN arch/i386/kernel/process.c~ioport-cache-gpf-2.6.9-rc1-mm5-A3 arch/i386/kernel/process.c --- 25/arch/i386/kernel/process.c~ioport-cache-gpf-2.6.9-rc1-mm5-A3 2004-09-14 01:48:34.201906240 -0700 +++ 25-akpm/arch/i386/kernel/process.c 2004-09-14 01:48:34.207905328 -0700 @@ -496,17 +496,16 @@ handle_io_bitmap(struct thread_struct *n return; } /* - * The IO bitmap in the TSS needs updating: copy the relevant - * range of the new task's IO bitmap. Normally this is 128 bytes - * or less: + * 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. */ - memcpy(tss->io_bitmap, next->io_bitmap_ptr, - max(tss->io_bitmap_max, next->io_bitmap_max)); - tss->io_bitmap_max = next->io_bitmap_max; - tss->io_bitmap_owner = next; - tss->io_bitmap_base = IO_BITMAP_OFFSET; + tss->io_bitmap_base = INVALID_IO_BITMAP_OFFSET_LAZY; } - /* * This special macro can be used to load a debugging register */ diff -puN arch/i386/kernel/traps.c~ioport-cache-gpf-2.6.9-rc1-mm5-A3 arch/i386/kernel/traps.c --- 25/arch/i386/kernel/traps.c~ioport-cache-gpf-2.6.9-rc1-mm5-A3 2004-09-14 01:48:34.202906088 -0700 +++ 25-akpm/arch/i386/kernel/traps.c 2004-09-14 01:48:34.209905024 -0700 @@ -479,6 +479,36 @@ DO_ERROR_INFO(17, SIGBUS, "alignment che asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) { + int cpu = get_cpu(); + struct tss_struct *tss = &per_cpu(init_tss, cpu); + struct thread_struct *thread = ¤t->thread; + + /* + * 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 + * and we set the offset field correctly. Then we let the CPU to + * restart the faulting instruction. + */ + if (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->io_bitmap_base = IO_BITMAP_OFFSET; + put_cpu(); + return; + } + put_cpu(); + if (regs->eflags & VM_MASK) goto gp_in_vm86; diff -puN include/asm-i386/processor.h~ioport-cache-gpf-2.6.9-rc1-mm5-A3 include/asm-i386/processor.h --- 25/include/asm-i386/processor.h~ioport-cache-gpf-2.6.9-rc1-mm5-A3 2004-09-14 01:48:34.204905784 -0700 +++ 25-akpm/include/asm-i386/processor.h 2004-09-14 01:48:34.210904872 -0700 @@ -307,6 +307,7 @@ extern unsigned int mca_pentium_flag; #define IO_BITMAP_LONGS (IO_BITMAP_BYTES/sizeof(long)) #define IO_BITMAP_OFFSET offsetof(struct tss_struct,io_bitmap) #define INVALID_IO_BITMAP_OFFSET 0x8000 +#define INVALID_IO_BITMAP_OFFSET_LAZY 0x9000 struct i387_fsave_struct { long cwd; _