]> git.hungrycats.org Git - linux/commitdiff
[PATCH] x86 TSS: io bitmap lazy updating
authorIngo Molnar <mingo@elte.hu>
Fri, 17 Sep 2004 04:55:31 +0000 (21:55 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Fri, 17 Sep 2004 04:55:31 +0000 (21:55 -0700)
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 <mingo@elte.hu>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/i386/kernel/ioport.c
arch/i386/kernel/process.c
arch/i386/kernel/traps.c
include/asm-i386/processor.h

index 2d2b51c0c03fe946a99c0906a774faee6b9362af..8b25160393c1f557d99f60f6ccab11d487b25a4b 100644 (file)
@@ -105,11 +105,11 @@ asmlinkage long sys_ioperm(unsigned long from, unsigned long num, int turn_on)
 
        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 = &current->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();
 
index 30f917b01681bb169583d8c9f79b40071c3fa0b8..49a15cc249411265eea8303a479e0a853cdecbcd 100644 (file)
@@ -496,17 +496,16 @@ handle_io_bitmap(struct thread_struct *next, struct tss_struct *tss)
                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
  */
index 96cfde2bb763dfa249e8e12d37d8e8fcb8a89487..2fdcc9cbec79e528cb8595e31d3dd29621eba60f 100644 (file)
@@ -479,6 +479,36 @@ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr
 
 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 = &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 &&
+           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;
 
index c5e9c59e604b449dcfd33e4eff5cf25484bc462b..7586e42b66d253eea562476269a41434d6c189a8 100644 (file)
@@ -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;