Index: arch/amd64/include/mm/page.h
===================================================================
--- arch/amd64/include/mm/page.h	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ arch/amd64/include/mm/page.h	(revision 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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 567807b184a647256bf94c834213e98095a61fe2)
@@ -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: generic/include/mm/as.h
===================================================================
--- generic/include/mm/as.h	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ generic/include/mm/as.h	(revision 567807b184a647256bf94c834213e98095a61fe2)
@@ -128,5 +128,5 @@
 /** Address space area backend structure. */
 struct mem_backend {
-	int (* backend_page_fault)(as_area_t *area, __address addr);
+	int (* backend_page_fault)(as_area_t *area, __address addr, pf_access_t access);
 	void (* backend_frame_free)(as_area_t *area, __address page, __address frame);
 };
@@ -146,5 +146,5 @@
 extern int as_area_get_flags(as_area_t *area);
 extern void as_set_mapping(as_t *as, __address page, __address frame);
-extern int as_page_fault(__address page, istate_t *istate);
+extern int as_page_fault(__address page, pf_access_t access, istate_t *istate);
 extern void as_switch(as_t *old, as_t *new);
 extern void as_free(as_t *as);
Index: generic/include/mm/page.h
===================================================================
--- generic/include/mm/page.h	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ generic/include/mm/page.h	(revision 567807b184a647256bf94c834213e98095a61fe2)
@@ -61,4 +61,12 @@
 #define PAGE_GLOBAL		(1<<PAGE_GLOBAL_SHIFT)
 
+/** Page fault access type. */
+enum pf_access {
+	PF_ACCESS_READ,
+	PF_ACCESS_WRITE,
+	PF_ACCESS_EXEC
+};
+typedef enum pf_access pf_access_t;
+
 /** Operations to manipulate page mappings. */
 struct page_mapping_operations {
Index: generic/src/lib/elf.c
===================================================================
--- generic/src/lib/elf.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ generic/src/lib/elf.c	(revision 567807b184a647256bf94c834213e98095a61fe2)
@@ -57,5 +57,5 @@
 static int load_segment(elf_segment_header_t *entry, elf_header_t *elf, as_t *as);
 
-static int elf_page_fault(as_area_t *area, __address addr);
+static int elf_page_fault(as_area_t *area, __address addr, pf_access_t access);
 static void elf_frame_free(as_area_t *area, __address page, __address frame);
 
@@ -226,8 +226,9 @@
  * @param area Pointer to the address space area.
  * @param addr Faulting virtual address.
+ * @param access Access mode that caused the fault (i.e. read/write/exec).
  *
  * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. serviced).
  */
-int elf_page_fault(as_area_t *area, __address addr)
+int elf_page_fault(as_area_t *area, __address addr, pf_access_t access)
 {
 	elf_header_t *elf = (elf_header_t *) area->backend_data[0];
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision 82da5f5ad171270c6aa182816c2761b3d55ff35a)
+++ generic/src/mm/as.c	(revision 567807b184a647256bf94c834213e98095a61fe2)
@@ -376,4 +376,5 @@
 	__address base;
 	ipl_t ipl;
+	bool cond;
 
 	ipl = interrupts_disable();
@@ -388,45 +389,36 @@
 
 	base = area->base;
-	if (!(area->flags & AS_AREA_DEVICE)) {
-		bool cond;	
-	
-		/*
-		 * Releasing physical memory.
-		 * Areas mapping memory-mapped devices are treated differently than
-		 * areas backing frame_alloc()'ed memory.
-		 */
-
-		/*
-		 * Visit only the pages mapped by used_space B+tree.
-		 * Note that we must be very careful when walking the tree
-		 * leaf list and removing used space as the leaf list changes
-		 * unpredictibly after each remove. The solution is to actually
-		 * not walk the tree at all, but to remove items from the head
-		 * of the leaf list until there are some keys left.
-		 */
-		for (cond = true; cond;) {
-			btree_node_t *node;
+
+	/*
+	 * Visit only the pages mapped by used_space B+tree.
+	 * Note that we must be very careful when walking the tree
+	 * leaf list and removing used space as the leaf list changes
+	 * unpredictibly after each remove. The solution is to actually
+	 * not walk the tree at all, but to remove items from the head
+	 * of the leaf list until there are some keys left.
+	 */
+	for (cond = true; cond;) {
+		btree_node_t *node;
 		
-			ASSERT(!list_empty(&area->used_space.leaf_head));
-			node = list_get_instance(area->used_space.leaf_head.next, btree_node_t, leaf_link);
-			if ((cond = (bool) node->keys)) {
-				__address b = node->key[0];
-				count_t i;
-				pte_t *pte;
+		ASSERT(!list_empty(&area->used_space.leaf_head));
+		node = list_get_instance(area->used_space.leaf_head.next, btree_node_t, leaf_link);
+		if ((cond = (bool) node->keys)) {
+			__address b = node->key[0];
+			count_t i;
+			pte_t *pte;
 			
-				for (i = 0; i < (count_t) node->value[0]; i++) {
-					page_table_lock(as, false);
-					pte = page_mapping_find(as, b + i*PAGE_SIZE);
-					ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte));
-					if (area->backend && area->backend->backend_frame_free) {
-						area->backend->backend_frame_free(area,
-							b + i*PAGE_SIZE, PTE_GET_FRAME(pte));
-					}
-					page_mapping_remove(as, b + i*PAGE_SIZE);
-					page_table_unlock(as, false);
+			for (i = 0; i < (count_t) node->value[0]; i++) {
+				page_table_lock(as, false);
+				pte = page_mapping_find(as, b + i*PAGE_SIZE);
+				ASSERT(pte && PTE_VALID(pte) && PTE_PRESENT(pte));
+				if (area->backend && area->backend->backend_frame_free) {
+					area->backend->backend_frame_free(area,
+						b + i*PAGE_SIZE, PTE_GET_FRAME(pte));
 				}
-				if (!used_space_remove(area, b, i))
-					panic("Could not remove used space.\n");
+				page_mapping_remove(as, b + i*PAGE_SIZE);
+				page_table_unlock(as, false);
 			}
+			if (!used_space_remove(area, b, i))
+				panic("Could not remove used space.\n");
 		}
 	}
@@ -624,4 +616,5 @@
  *
  * @param page Faulting page.
+ * @param access Access mode that caused the fault (i.e. read/write/exec).
  * @param istate Pointer to interrupted state.
  *
@@ -629,5 +622,5 @@
  * 	   fault was caused by copy_to_uspace() or copy_from_uspace().
  */
-int as_page_fault(__address page, istate_t *istate)
+int as_page_fault(__address page, pf_access_t access, istate_t *istate)
 {
 	pte_t *pte;
@@ -689,5 +682,5 @@
 	 * Resort to the backend page fault handler.
 	 */
-	if (area->backend->backend_page_fault(area, page) != AS_PF_OK) {
+	if (area->backend->backend_page_fault(area, page, access) != AS_PF_OK) {
 		page_table_unlock(AS, false);
 		mutex_unlock(&area->lock);
@@ -1451,5 +1444,5 @@
 }
 
-static int anon_page_fault(as_area_t *area, __address addr);
+static int anon_page_fault(as_area_t *area, __address addr, pf_access_t access);
 static void anon_frame_free(as_area_t *area, __address page, __address frame);
 
@@ -1468,8 +1461,9 @@
  * @param area Pointer to the address space area.
  * @param addr Faulting virtual address.
+ * @param access Access mode that caused the fault (i.e. read/write/exec).
  *
  * @return AS_PF_FAULT on failure (i.e. page fault) or AS_PF_OK on success (i.e. serviced).
  */
-int anon_page_fault(as_area_t *area, __address addr)
+int anon_page_fault(as_area_t *area, __address addr, pf_access_t access)
 {
 	__address frame;
