Index: arch/amd64/include/mm/page.h
===================================================================
--- arch/amd64/include/mm/page.h	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/amd64/include/mm/page.h	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -107,4 +107,21 @@
 #ifndef __ASM__
 
+/* Page fault error codes. */
+
+/** When bit on this position is 0, the page fault was caused by a not-present page. */
+#define PFERR_CODE_P            (1<<0)  
+
+/** When bit on this position is 1, the page fault was caused by a write. */
+#define PFERR_CODE_RW           (1<<1)
+
+/** When bit on this position is 1, the page fault was caused in user mode. */
+#define PFERR_CODE_US           (1<<2)
+
+/** When bit on this position is 1, a reserved bit was set in page directory. */
+#define PFERR_CODE_RSVD         (1<<3)
+
+/** When bit on this position os 1, the page fault was caused during instruction fecth. */
+#define PFERR_CODE_ID		(1<<4)
+
 /** Page Table Entry. */
 struct page_specifier {
Index: arch/amd64/src/mm/page.c
===================================================================
--- arch/amd64/src/mm/page.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/amd64/src/mm/page.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -169,7 +169,19 @@
 {
 	__address page;
+	pf_access_t access;
 	
 	page = read_cr2();
-	if (as_page_fault(page, istate) == AS_PF_FAULT) {
+	
+	if (istate->error_word & PFERR_CODE_RSVD)
+		panic("Reserved bit set in page table entry.\n");
+	
+	if (istate->error_word & PFERR_CODE_RW)
+		access = PF_ACCESS_WRITE;
+	else if (istate->error_word & PFERR_CODE_ID)
+		access = PF_ACCESS_EXEC;
+	else
+		access = PF_ACCESS_READ;
+	
+	if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
 		print_info_errcode(n, istate);
 		printf("Page fault address: %llX\n", page);
Index: arch/ia32/include/interrupt.h
===================================================================
--- arch/ia32/include/interrupt.h	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ia32/include/interrupt.h	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -93,4 +93,5 @@
 extern void (* eoi_function)(void);
 
+extern void PRINT_INFO_ERRCODE(istate_t *istate);
 extern void null_interrupt(int n, istate_t *istate);
 extern void gp_fault(int n, istate_t *istate);
@@ -98,5 +99,4 @@
 extern void ss_fault(int n, istate_t *istate);
 extern void simd_fp_exception(int n, istate_t *istate);
-extern void page_fault(int n, istate_t *istate);
 extern void syscall(int n, istate_t *istate);
 extern void tlb_shootdown_ipi(int n, istate_t *istate);
Index: arch/ia32/include/mm/page.h
===================================================================
--- arch/ia32/include/mm/page.h	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ia32/include/mm/page.h	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -91,4 +91,18 @@
 #include <typedefs.h>
 
+/* Page fault error codes. */
+
+/** When bit on this position is 0, the page fault was caused by a not-present page. */
+#define PFERR_CODE_P		(1<<0)
+
+/** When bit on this position is 1, the page fault was caused by a write. */
+#define PFERR_CODE_RW		(1<<1)
+
+/** When bit on this position is 1, the page fault was caused in user mode. */
+#define PFERR_CODE_US		(1<<2)
+
+/** When bit on this position is 1, a reserved bit was set in page directory. */ 
+#define PFERR_CODE_RSVD		(1<<3)	
+
 /** Page Table Entry. */
 struct page_specifier {
@@ -139,4 +153,5 @@
 
 extern void page_arch_init(void);
+extern void page_fault(int n, istate_t *istate);
 
 #endif /* __ASM__ */
Index: arch/ia32/src/interrupt.c
===================================================================
--- arch/ia32/src/interrupt.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ia32/src/interrupt.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -55,5 +55,5 @@
 void (* eoi_function)(void) = NULL;
 
-static void PRINT_INFO_ERRCODE(istate_t *istate)
+void PRINT_INFO_ERRCODE(istate_t *istate)
 {
 	char *symbol = get_symtab_entry(istate->eip);
@@ -140,16 +140,4 @@
 }
 
-void page_fault(int n, istate_t *istate)
-{
-	__address page;
-
-	page = read_cr2();
-	if (as_page_fault(page, istate) == AS_PF_FAULT) {
-		PRINT_INFO_ERRCODE(istate);
-		printf("page fault address: %#x\n", page);
-		panic("page fault\n");
-	}
-}
-
 void syscall(int n, istate_t *istate)
 {
Index: arch/ia32/src/mm/page.c
===================================================================
--- arch/ia32/src/mm/page.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ia32/src/mm/page.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -44,5 +44,4 @@
 #include <interrupt.h>
 
-
 void page_arch_init(void)
 {
@@ -88,2 +87,24 @@
 	return virtaddr;
 }
+
+void page_fault(int n, istate_t *istate)
+{
+        __address page;
+	pf_access_t access;
+	
+        page = read_cr2();
+		
+        if (istate->error_word & PFERR_CODE_RSVD)
+		panic("Reserved bit set in page directory.\n");
+
+	if (istate->error_word & PFERR_CODE_RW)
+		access = PF_ACCESS_WRITE;
+	else
+		access = PF_ACCESS_READ;
+
+        if (as_page_fault(page, access, istate) == AS_PF_FAULT) {
+                PRINT_INFO_ERRCODE(istate);
+                printf("page fault address: %#x\n", page);
+                panic("page fault\n");
+        }
+}
Index: arch/ia64/src/mm/tlb.c
===================================================================
--- arch/ia64/src/mm/tlb.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ia64/src/mm/tlb.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -430,8 +430,12 @@
 {
 	region_register rr;
+	rid_t rid;
 	__address va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
 	page_table_lock(AS, true);
 	t = page_mapping_find(AS, va);
@@ -448,6 +452,6 @@
 		 */
 		page_table_unlock(AS, true);
-		if (as_page_fault(va, istate) == AS_PF_FAULT) {
-			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, istate->cr_ifa, rr.map.rid, istate->cr_iip);
+		if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
 		}
 	}
@@ -494,5 +498,5 @@
 		 */
 		page_table_unlock(AS, true);
-		if (as_page_fault(va, istate) == AS_PF_FAULT) {
+		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
 			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
 		}
@@ -519,78 +523,121 @@
 void data_dirty_bit_fault(__u64 vector, istate_t *istate)
 {
+	region_register rr;
+	rid_t rid;
+	__address va;
 	pte_t *t;
+	
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
 
 	page_table_lock(AS, true);
-	t = page_mapping_find(AS, istate->cr_ifa);
+	t = page_mapping_find(AS, va);
+	ASSERT(t && t->p);
+	if (t && t->p && t->w) {
+		/*
+		 * Update the Dirty bit in page tables and reinsert
+		 * the mapping into DTC.
+		 */
+		t->d = true;
+		dtc_pte_copy(t);
+	} else {
+		if (as_page_fault(va, PF_ACCESS_WRITE, istate) == AS_PF_FAULT) {
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+			t->d = true;
+			dtc_pte_copy(t);
+		}
+	}
+	page_table_unlock(AS, true);
+}
+
+/** Instruction access bit fault handler.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void instruction_access_bit_fault(__u64 vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	__address va;
+	pte_t *t;	
+
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
+	ASSERT(t && t->p);
+	if (t && t->p && t->x) {
+		/*
+		 * Update the Accessed bit in page tables and reinsert
+		 * the mapping into ITC.
+		 */
+		t->a = true;
+		itc_pte_copy(t);
+	} else {
+		if (as_page_fault(va, PF_ACCESS_EXEC, istate) == AS_PF_FAULT) {
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+			t->a = true;
+			itc_pte_copy(t);
+		}
+	}
+	page_table_unlock(AS, true);
+}
+
+/** Data access bit fault handler.
+ *
+ * @param vector Interruption vector.
+ * @param istate Structure with saved interruption state.
+ */
+void data_access_bit_fault(__u64 vector, istate_t *istate)
+{
+	region_register rr;
+	rid_t rid;
+	__address va;
+	pte_t *t;
+
+	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
+	page_table_lock(AS, true);
+	t = page_mapping_find(AS, va);
 	ASSERT(t && t->p);
 	if (t && t->p) {
 		/*
-		 * Update the Dirty bit in page tables and reinsert
+		 * Update the Accessed bit in page tables and reinsert
 		 * the mapping into DTC.
 		 */
-		t->d = true;
+		t->a = true;
 		dtc_pte_copy(t);
+	} else {
+		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
+			panic("%s: va=%p, rid=%d, iip=%p\n", __FUNCTION__, va, rid, istate->cr_iip);
+			t->a = true;
+			itc_pte_copy(t);
+		}
 	}
 	page_table_unlock(AS, true);
 }
 
-/** Instruction access bit fault handler.
+/** Page not present fault handler.
  *
  * @param vector Interruption vector.
  * @param istate Structure with saved interruption state.
  */
-void instruction_access_bit_fault(__u64 vector, istate_t *istate)
-{
-	pte_t *t;
-
-	page_table_lock(AS, true);
-	t = page_mapping_find(AS, istate->cr_ifa);
-	ASSERT(t && t->p);
-	if (t && t->p) {
-		/*
-		 * Update the Accessed bit in page tables and reinsert
-		 * the mapping into ITC.
-		 */
-		t->a = true;
-		itc_pte_copy(t);
-	}
-	page_table_unlock(AS, true);
-}
-
-/** Data access bit fault handler.
- *
- * @param vector Interruption vector.
- * @param istate Structure with saved interruption state.
- */
-void data_access_bit_fault(__u64 vector, istate_t *istate)
-{
-	pte_t *t;
-
-	page_table_lock(AS, true);
-	t = page_mapping_find(AS, istate->cr_ifa);
-	ASSERT(t && t->p);
-	if (t && t->p) {
-		/*
-		 * Update the Accessed bit in page tables and reinsert
-		 * the mapping into DTC.
-		 */
-		t->a = true;
-		dtc_pte_copy(t);
-	}
-	page_table_unlock(AS, true);
-}
-
-/** Page not present fault handler.
- *
- * @param vector Interruption vector.
- * @param istate Structure with saved interruption state.
- */
 void page_not_present(__u64 vector, istate_t *istate)
 {
 	region_register rr;
+	rid_t rid;
 	__address va;
 	pte_t *t;
 	
 	va = istate->cr_ifa;	/* faulting address */
+	rr.word = rr_read(VA2VRN(va));
+	rid = rr.map.rid;
+
 	page_table_lock(AS, true);
 	t = page_mapping_find(AS, va);
@@ -609,7 +656,7 @@
 	} else {
 		page_table_unlock(AS, true);
-		if (as_page_fault(va, istate) == AS_PF_FAULT) {
-			panic("%s: va=%p, rid=%d\n", __FUNCTION__, va, rr.map.rid);
-		}
-	}
-}
+		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
+			panic("%s: va=%p, rid=%d\n", __FUNCTION__, va, rid);
+		}
+	}
+}
Index: arch/mips32/src/mm/tlb.c
===================================================================
--- arch/mips32/src/mm/tlb.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/mips32/src/mm/tlb.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -45,5 +45,5 @@
 static void tlb_modified_fail(istate_t *istate);
 
-static pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc);
+static pte_t *find_mapping_and_check(__address badvaddr, int access, istate_t *istate, int *pfrc);
 
 static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, bool cacheable, __address pfn);
@@ -102,5 +102,5 @@
 	page_table_lock(AS, true);
 
-	pte = find_mapping_and_check(badvaddr, istate, &pfrc);
+	pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
 	if (!pte) {
 		switch (pfrc) {
@@ -187,5 +187,5 @@
 	}
 
-	pte = find_mapping_and_check(badvaddr, istate, &pfrc);
+	pte = find_mapping_and_check(badvaddr, PF_ACCESS_READ, istate, &pfrc);
 	if (!pte) {
 		switch (pfrc) {
@@ -271,5 +271,5 @@
 	}
 
-	pte = find_mapping_and_check(badvaddr, istate, &pfrc);
+	pte = find_mapping_and_check(badvaddr, PF_ACCESS_WRITE, istate, &pfrc);
 	if (!pte) {
 		switch (pfrc) {
@@ -367,4 +367,5 @@
  *
  * @param badvaddr Faulting virtual address.
+ * @param access Access mode that caused the fault.
  * @param istate Pointer to interrupted state.
  * @param pfrc Pointer to variable where as_page_fault() return code will be stored.
@@ -372,5 +373,5 @@
  * @return PTE on success, NULL otherwise.
  */
-pte_t *find_mapping_and_check(__address badvaddr, istate_t *istate, int *pfrc)
+pte_t *find_mapping_and_check(__address badvaddr, int access, istate_t *istate, int *pfrc)
 {
 	entry_hi_t hi;
@@ -405,5 +406,5 @@
 		 */
 		page_table_unlock(AS, true);
-		switch (rc = as_page_fault(badvaddr, istate)) {
+		switch (rc = as_page_fault(badvaddr, access, istate)) {
 		case AS_PF_OK:
 			/*
Index: arch/ppc32/src/mm/page.c
===================================================================
--- arch/ppc32/src/mm/page.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ppc32/src/mm/page.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -54,4 +54,5 @@
  * @param lock     Lock/unlock the address space.
  * @param badvaddr Faulting virtual address.
+ * @param access   Access mode that caused the fault.
  * @param istate   Pointer to interrupted state.
  * @param pfrc     Pointer to variable where as_page_fault() return code will be stored.
@@ -59,5 +60,6 @@
  *
  */
-static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, istate_t *istate, int *pfcr)
+static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, int access,
+				     istate_t *istate, int *pfcr)
 {
 	/*
@@ -79,5 +81,5 @@
 		 */
 		page_table_unlock(as, lock);
-		switch (rc = as_page_fault(badvaddr, istate)) {
+		switch (rc = as_page_fault(badvaddr, access, istate)) {
 			case AS_PF_OK:
 				/*
@@ -212,5 +214,5 @@
 	page_table_lock(as, lock);
 	
-	pte = find_mapping_and_check(as, lock, badvaddr, istate, &pfcr);
+	pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfcr);
 	if (!pte) {
 		switch (pfcr) {
Index: arch/ppc64/src/mm/page.c
===================================================================
--- arch/ppc64/src/mm/page.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/ppc64/src/mm/page.c	(revision b31d18860feb425f02434cc29cf3afa379e0ef8f)
@@ -54,4 +54,5 @@
  * @param lock     Lock/unlock the address space.
  * @param badvaddr Faulting virtual address.
+ * @param access   Access mode that caused the fault.
  * @param istate   Pointer to interrupted state.
  * @param pfrc     Pointer to variable where as_page_fault() return code will be stored.
@@ -59,5 +60,6 @@
  *
  */
-static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, istate_t *istate, int *pfcr)
+static pte_t *find_mapping_and_check(as_t *as, bool lock, __address badvaddr, int access,
+				     istate_t *istate, int *pfcr)
 {
 	/*
@@ -79,5 +81,5 @@
 		 */
 		page_table_unlock(as, lock);
-		switch (rc = as_page_fault(badvaddr, istate)) {
+		switch (rc = as_page_fault(badvaddr, access, istate)) {
 			case AS_PF_OK:
 				/*
@@ -212,5 +214,5 @@
 	page_table_lock(as, lock);
 	
-	pte = find_mapping_and_check(as, lock, badvaddr, istate, &pfcr);
+	pte = find_mapping_and_check(as, lock, badvaddr, PF_ACCESS_READ /* FIXME */, istate, &pfcr);
 	if (!pte) {
 		switch (pfcr) {
