Index: arch/amd64/include/cpu.h
===================================================================
--- arch/amd64/include/cpu.h	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/amd64/include/cpu.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -58,4 +58,6 @@
 	int stepping;
 	struct tss *tss;
+	
+	count_t iomapver_copy;	/** Copy of TASK's I/O Permission bitmap generation count. */
 };
 
Index: arch/amd64/include/ddi/ddi.h
===================================================================
--- arch/amd64/include/ddi/ddi.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
+++ arch/amd64/include/ddi/ddi.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file	ddi.h
+ * @brief	amd64 specific DDI declarations and macros.
+ */
+
+#ifndef __amd64_DDI_H__
+#define __amd64_DDI_H__
+
+extern void io_perm_bitmap_install(void);
+
+#endif
Index: arch/amd64/include/proc/task.h
===================================================================
--- arch/amd64/include/proc/task.h	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/amd64/include/proc/task.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -35,5 +35,6 @@
 
 typedef struct {
-	bitmap_t iomap;
+	count_t iomapver;	/**< I/O Permission bitmap Generation counter. */
+	bitmap_t iomap;		/**< I/O Permission bitmap. */
 } task_arch_t;
 
Index: arch/amd64/src/ddi/ddi.c
===================================================================
--- arch/amd64/src/ddi/ddi.c	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/amd64/src/ddi/ddi.c	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -28,4 +28,5 @@
 
 #include <ddi/ddi.h>
+#include <arch/ddi/ddi.h>
 #include <proc/task.h>
 #include <arch/types.h>
@@ -36,4 +37,5 @@
 #include <errno.h>
 #include <arch/cpu.h>
+#include <arch.h>
 
 /** Enable I/O space range for task.
@@ -90,4 +92,9 @@
 	bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
 
+	/*
+	 * Increment I/O Permission bitmap generation counter.
+	 */
+	task->arch.iomapver++;
+
 	return 0;
 }
@@ -106,2 +113,55 @@
 	return 0;
 }
+
+/** Install I/O Permission bitmap.
+ *
+ * Current task's I/O permission bitmap, if any, is installed
+ * in the current CPU's TSS.
+ *
+ * Interrupts must be disabled prior this call.
+ */
+void io_perm_bitmap_install(void)
+{
+	count_t bits;
+	ptr_16_64_t cpugdtr;
+	descriptor_t *gdt_p;
+	tss_descriptor_t *tss_desc;
+	count_t ver;
+
+	/* First, copy the I/O Permission Bitmap. */
+	spinlock_lock(&TASK->lock);
+	ver = TASK->arch.iomapver;
+	if ((bits = TASK->arch.iomap.bits)) {
+		bitmap_t iomap;
+	
+		ASSERT(TASK->arch.iomap.map);
+		bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
+		bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
+		/*
+		 * It is safe to set the trailing eight bits because of the extra
+		 * convenience byte in TSS_IOMAP_SIZE.
+		 */
+		bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
+	}
+	spinlock_unlock(&TASK->lock);
+
+	/* Second, adjust TSS segment limit. */
+	gdtr_store(&cpugdtr);
+	gdt_p = (descriptor_t *) cpugdtr.base;
+	gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
+	gdtr_load(&cpugdtr);
+	
+	/*
+         * Before we load new TSS limit, the current TSS descriptor
+         * type must be changed to describe inactive TSS.
+         */
+	tss_desc = (tss_descriptor_t *)	&gdt_p[TSS_DES];
+	tss_desc->type = AR_TSS;
+	tr_load(gdtselector(TSS_DES));
+	
+	/*
+	 * Update the generation count so that faults caused by
+	 * early accesses can be serviced.
+	 */
+	CPU->arch.iomapver_copy = ver;
+}
Index: arch/amd64/src/interrupt.c
===================================================================
--- arch/amd64/src/interrupt.c	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/amd64/src/interrupt.c	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -42,4 +42,7 @@
 #include <proc/scheduler.h>
 #include <proc/thread.h>
+#include <proc/task.h>
+#include <synch/spinlock.h>
+#include <arch/ddi/ddi.h>
 
 void print_info_errcode(int n, istate_t *istate)
@@ -79,6 +82,27 @@
 }
 
+/** General Protection Fault. */
 void gp_fault(int n, istate_t *istate)
 {
+	if (TASK) {
+		count_t ver;
+
+		spinlock_lock(&TASK->lock);
+		ver = TASK->arch.iomapver;
+		spinlock_unlock(&TASK->lock);
+
+		if (CPU->arch.iomapver_copy != ver) {
+			/*
+			 * This fault can be caused by an early access
+			 * to I/O port because of an out-dated
+			 * I/O Permission bitmap installed on CPU.
+			 * Install the fresh copy and restart
+			 * the instruction.
+			 */
+			io_perm_bitmap_install();
+			return;
+		}
+	}
+
 	print_info_errcode(n, istate);
 	panic("general protection fault\n");
Index: arch/amd64/src/proc/scheduler.c
===================================================================
--- arch/amd64/src/proc/scheduler.c	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/amd64/src/proc/scheduler.c	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -37,5 +37,5 @@
 #include <print.h>
 #include <arch/pm.h>
-#include <adt/bitmap.h>
+#include <arch/ddi/ddi.h>
 
 /** Perform amd64 specific tasks needed before the new task is run.
@@ -45,42 +45,5 @@
 void before_task_runs_arch(void)
 {
-	count_t bits;
-	ptr_16_64_t cpugdtr;
-	descriptor_t *gdt_p;
-	tss_descriptor_t *tss_desc;
-
-	/*
-	 * Switch the I/O Permission Bitmap, if necessary.
-	 */
-	 
-	/* First, copy the I/O Permission Bitmap. */
-	spinlock_lock(&TASK->lock);
-	if ((bits = TASK->arch.iomap.bits)) {
-		bitmap_t iomap;
-	
-		ASSERT(TASK->arch.iomap.map);
-		bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
-		bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
-		/*
-		 * It is safe to set the trailing eight bits because of the extra
-		 * convenience byte in TSS_IOMAP_SIZE.
-		 */
-		bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
-	}
-	spinlock_unlock(&TASK->lock);
-
-	/* Second, adjust TSS segment limit. */
-	gdtr_store(&cpugdtr);
-	gdt_p = (descriptor_t *) cpugdtr.base;
-	gdt_tss_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
-	gdtr_load(&cpugdtr);
-	
-	/*
-         * Before we load new TSS limit, the current TSS descriptor
-         * type must be changed to describe inactive TSS.
-         */
-	tss_desc = (tss_descriptor_t *)	&gdt_p[TSS_DES];
-	tss_desc->type = AR_TSS;
-	tr_load(gdtselector(TSS_DES));
+	io_perm_bitmap_install();
 }
 
Index: arch/ia32/include/cpu.h
===================================================================
--- arch/ia32/include/cpu.h	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/ia32/include/cpu.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -43,4 +43,6 @@
 	int stepping;
 	struct tss *tss;
+	
+	count_t iomapver_copy;  /** Copy of TASK's I/O Permission bitmap generation count. */
 };
 
Index: arch/ia32/include/ddi/ddi.h
===================================================================
--- arch/ia32/include/ddi/ddi.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
+++ arch/ia32/include/ddi/ddi.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2006 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/**
+ * @file	ddi.h
+ * @brief	ia32 specific DDI declarations and macros.
+ */
+
+#ifndef __ia32_DDI_H__
+#define __ia32_DDI_H__
+
+extern void io_perm_bitmap_install(void);
+
+#endif
Index: arch/ia32/include/proc/task.h
===================================================================
--- arch/ia32/include/proc/task.h	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/ia32/include/proc/task.h	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -35,5 +35,6 @@
 
 typedef struct {
-	bitmap_t iomap;
+	count_t iomapver;	/**< I/O Permission bitmap Generation counter. */
+	bitmap_t iomap;		/**< I/O Permission bitmap. */
 } task_arch_t;
 
Index: arch/ia32/src/ddi/ddi.c
===================================================================
--- arch/ia32/src/ddi/ddi.c	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/ia32/src/ddi/ddi.c	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -28,4 +28,5 @@
 
 #include <ddi/ddi.h>
+#include <arch/ddi/ddi.h>
 #include <proc/task.h>
 #include <arch/types.h>
@@ -36,4 +37,6 @@
 #include <errno.h>
 #include <arch/cpu.h>
+#include <cpu.h>
+#include <arch.h>
 
 /** Enable I/O space range for task.
@@ -90,4 +93,9 @@
 	bitmap_clear_range(&task->arch.iomap, (index_t) ioaddr, (count_t) size);
 
+	/*
+	 * Increment I/O Permission bitmap generation counter.
+	 */
+	task->arch.iomapver++;
+
 	return 0;
 }
@@ -106,2 +114,53 @@
 	return 0;
 }
+
+/** Install I/O Permission bitmap.
+ *
+ * Current task's I/O permission bitmap, if any, is installed
+ * in the current CPU's TSS.
+ *
+ * Interrupts must be disabled prior this call.
+ */
+void io_perm_bitmap_install(void)
+{
+	count_t bits;
+	ptr_16_32_t cpugdtr;
+	descriptor_t *gdt_p;
+	count_t ver;
+
+	/* First, copy the I/O Permission Bitmap. */
+	spinlock_lock(&TASK->lock);
+	ver = TASK->arch.iomapver;
+	if ((bits = TASK->arch.iomap.bits)) {
+		bitmap_t iomap;
+	
+		ASSERT(TASK->arch.iomap.map);
+		bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
+		bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
+		/*
+		 * It is safe to set the trailing eight bits because of the extra
+		 * convenience byte in TSS_IOMAP_SIZE.
+		 */
+		bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
+	}
+	spinlock_unlock(&TASK->lock);
+
+	/* Second, adjust TSS segment limit. */
+	gdtr_store(&cpugdtr);
+	gdt_p = (descriptor_t *) cpugdtr.base;
+	gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
+	gdtr_load(&cpugdtr);
+
+	/*
+	 * Before we load new TSS limit, the current TSS descriptor
+	 * type must be changed to describe inactive TSS.
+	 */
+	gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
+	tr_load(selector(TSS_DES));
+	
+	/*
+	 * Update the generation count so that faults caused by
+	 * early accesses can be serviced.
+	 */
+	CPU->arch.iomapver_copy = ver;
+}
Index: arch/ia32/src/interrupt.c
===================================================================
--- arch/ia32/src/interrupt.c	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/ia32/src/interrupt.c	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -41,4 +41,7 @@
 #include <symtab.h>
 #include <proc/thread.h>
+#include <proc/task.h>
+#include <synch/spinlock.h>
+#include <arch/ddi/ddi.h>
 
 /*
@@ -79,6 +82,27 @@
 }
 
+/** General Protection Fault. */
 void gp_fault(int n, istate_t *istate)
 {
+	if (TASK) {
+		count_t ver;
+		
+		spinlock_lock(&TASK->lock);
+		ver = TASK->arch.iomapver;
+		spinlock_unlock(&TASK->lock);
+	
+		if (CPU->arch.iomapver_copy != ver) {
+			/*
+			 * This fault can be caused by an early access
+			 * to I/O port because of an out-dated
+			 * I/O Permission bitmap installed on CPU.
+			 * Install the fresh copy and restart
+			 * the instruction.
+			 */
+			io_perm_bitmap_install();
+			return;
+		}
+	}
+
 	PRINT_INFO_ERRCODE(istate);
 	panic("general protection fault\n");
Index: arch/ia32/src/proc/scheduler.c
===================================================================
--- arch/ia32/src/proc/scheduler.c	(revision 69a5600600477ae968b08bfe68aa8032066bb55f)
+++ arch/ia32/src/proc/scheduler.c	(revision 2382d090e11b14167745fbf57d52ca43189ef508)
@@ -36,6 +36,5 @@
 #include <arch/pm.h>
 #include <arch/asm.h>
-#include <adt/bitmap.h>
-#include <print.h>
+#include <arch/ddi/ddi.h>
 
 /** Perform ia32 specific tasks needed before the new task is run.
@@ -45,40 +44,5 @@
 void before_task_runs_arch(void)
 {
-	count_t bits;
-	ptr_16_32_t cpugdtr;
-	descriptor_t *gdt_p;
-
-	/*
-	 * Switch the I/O Permission Bitmap, if necessary.
-	 */
-
-	/* First, copy the I/O Permission Bitmap. */
-	spinlock_lock(&TASK->lock);
-	if ((bits = TASK->arch.iomap.bits)) {
-		bitmap_t iomap;
-	
-		ASSERT(TASK->arch.iomap.map);
-		bitmap_initialize(&iomap, CPU->arch.tss->iomap, TSS_IOMAP_SIZE * 8);
-		bitmap_copy(&iomap, &TASK->arch.iomap, TASK->arch.iomap.bits);
-		/*
-		 * It is safe to set the trailing eight bits because of the extra
-		 * convenience byte in TSS_IOMAP_SIZE.
-		 */
-		bitmap_set_range(&iomap, TASK->arch.iomap.bits, 8);
-	}
-	spinlock_unlock(&TASK->lock);
-
-	/* Second, adjust TSS segment limit. */
-	gdtr_store(&cpugdtr);
-	gdt_p = (descriptor_t *) cpugdtr.base;
-	gdt_setlimit(&gdt_p[TSS_DES], TSS_BASIC_SIZE + BITS2BYTES(bits) - 1);
-	gdtr_load(&cpugdtr);
-
-	/*
-	 * Before we load new TSS limit, the current TSS descriptor
-	 * type must be changed to describe inactive TSS.
-	 */
-	gdt_p[TSS_DES].access = AR_PRESENT | AR_TSS | DPL_KERNEL;
-	tr_load(selector(TSS_DES));
+	io_perm_bitmap_install();
 }
 
