Index: arch/i386/kernel/ioport.c
===================================================================
RCS file: /usr/src/bkcvs/linux-2.5/arch/i386/kernel/ioport.c,v
retrieving revision 1.13
diff -u -r1.13 ioport.c
--- a/arch/i386/kernel/ioport.c	23 Aug 2004 19:42:10 -0000	1.13
+++ b/arch/i386/kernel/ioport.c	3 Sep 2004 21:05:09 -0000
@@ -105,8 +105,11 @@
 
 	t->io_bitmap_max = bytes;
 
-	/* Update the TSS: */
-	memcpy(tss->io_bitmap, t->io_bitmap_ptr, bytes_updated);
+	/*
+	 * 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();
 
Index: arch/i386/kernel/process.c
===================================================================
RCS file: /usr/src/bkcvs/linux-2.5/arch/i386/kernel/process.c,v
retrieving revision 1.86
diff -u -r1.86 process.c
--- a/arch/i386/kernel/process.c	24 Aug 2004 18:27:55 -0000	1.86
+++ b/arch/i386/kernel/process.c	3 Sep 2004 21:07:56 -0000
@@ -556,20 +556,17 @@
 		loaddebug(next, 7);
 	}
 
-	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);
-	}
+	/*
+	 * 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, if true, does the real copy and restart the instruction.
+	 * This will save us for redoundant copies when the currently switched task
+	 * does not perform any I/O during its timeslice.
+	 */
+	tss->io_bitmap_base = next->io_bitmap_ptr ? INVALID_IO_BITMAP_OFFSET_LAZY:
+		INVALID_IO_BITMAP_OFFSET;
+
 	return prev_p;
 }
 
Index: arch/i386/kernel/traps.c
===================================================================
RCS file: /usr/src/bkcvs/linux-2.5/arch/i386/kernel/traps.c,v
retrieving revision 1.83
diff -u -r1.83 traps.c
--- a/arch/i386/kernel/traps.c	31 Aug 2004 17:32:21 -0000	1.83
+++ b/arch/i386/kernel/traps.c	3 Sep 2004 21:05:09 -0000
@@ -479,6 +479,35 @@
 
 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 *tsk_th = &current->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 &&
+	    tsk_th->io_bitmap_ptr) {
+		memcpy(tss->io_bitmap, tsk_th->io_bitmap_ptr,
+		       tsk_th->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 (tsk_th->io_bitmap_max < tss->map_size)
+			memset((char *) tss->io_bitmap + tsk_th->io_bitmap_max, 0xff,
+			       tss->map_size - tsk_th->io_bitmap_max);
+		tss->map_size = tsk_th->io_bitmap_max;
+		tss->io_bitmap_base = IO_BITMAP_OFFSET;
+		put_cpu();
+		return;
+	}
+	put_cpu();
+
 	if (regs->eflags & VM_MASK)
 		goto gp_in_vm86;
 
Index: include/asm-i386/processor.h
===================================================================
RCS file: /usr/src/bkcvs/linux-2.5/include/asm-i386/processor.h,v
retrieving revision 1.72
diff -u -r1.72 processor.h
--- a/include/asm-i386/processor.h	24 Aug 2004 18:11:50 -0000	1.72
+++ b/include/asm-i386/processor.h	3 Sep 2004 21:05:09 -0000
@@ -307,6 +307,7 @@
 #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;
@@ -392,9 +393,13 @@
 	 */
 	unsigned long	io_bitmap[IO_BITMAP_LONGS + 1];
 	/*
+	 * Effective size of the currently set I/O bitmap.
+	 */
+	unsigned long	map_size;
+	/*
 	 * pads the TSS to be cacheline-aligned (size is 0x100)
 	 */
-	unsigned long __cacheline_filler[37];
+	unsigned long __cacheline_filler[36];
 	/*
 	 * .. and then another 0x100 bytes for emergency kernel stack
 	 */
