Index: kernel/arch/abs32le/include/arch/mm/page.h
===================================================================
--- kernel/arch/abs32le/include/arch/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/abs32le/include/arch/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -115,5 +115,5 @@
 /* Macros for querying the last level entries. */
 #define PTE_VALID_ARCH(p) \
-	(*((uint32_t *) (p)) != 0)
+	((p)->soft_valid != 0)
 #define PTE_PRESENT_ARCH(p) \
 	((p)->present != 0)
Index: kernel/arch/amd64/include/arch/mm/page.h
===================================================================
--- kernel/arch/amd64/include/arch/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/amd64/include/arch/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -131,5 +131,5 @@
 /* Macros for querying the last-level PTE entries. */
 #define PTE_VALID_ARCH(p) \
-	(*((uint64_t *) (p)) != 0)
+	((p)->soft_valid != 0)
 #define PTE_PRESENT_ARCH(p) \
 	((p)->present != 0)
Index: kernel/arch/arm32/include/arch/mm/page_armv4.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page_armv4.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/arm32/include/arch/mm/page_armv4.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -44,5 +44,5 @@
 /* Macros for querying the last-level PTE entries. */
 #define PTE_VALID_ARCH(pte) \
-	(*((uint32_t *) (pte)) != 0)
+	(((pte_t *) (pte))->l0.should_be_zero != 0 || PTE_PRESENT_ARCH(pte))
 #define PTE_PRESENT_ARCH(pte) \
 	(((pte_t *) (pte))->l0.descriptor_type != 0)
Index: kernel/arch/arm32/include/arch/mm/page_armv6.h
===================================================================
--- kernel/arch/arm32/include/arch/mm/page_armv6.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/arm32/include/arch/mm/page_armv6.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -44,5 +44,5 @@
 /* Macros for querying the last-level PTE entries. */
 #define PTE_VALID_ARCH(pte) \
-	(*((uint32_t *) (pte)) != 0)
+	(((pte_t *) (pte))->l0.should_be_zero_0 != 0 || PTE_PRESENT_ARCH(pte))
 #define PTE_PRESENT_ARCH(pte) \
 	(((pte_t *) (pte))->l0.descriptor_type != 0)
Index: kernel/arch/ia32/include/arch/mm/page.h
===================================================================
--- kernel/arch/ia32/include/arch/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/ia32/include/arch/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -132,5 +132,5 @@
 /* Macros for querying the last level entries. */
 #define PTE_VALID_ARCH(p) \
-	(*((uint32_t *) (p)) != 0)
+	((p)->soft_valid != 0)
 #define PTE_PRESENT_ARCH(p) \
 	((p)->present != 0)
Index: kernel/arch/ia64/src/mm/tlb.c
===================================================================
--- kernel/arch/ia64/src/mm/tlb.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/ia64/src/mm/tlb.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -484,5 +484,5 @@
 {
 	uintptr_t va;
-	pte_t *t;
+	pte_t t;
 	
 	va = istate->cr_ifa; /* faulting address */
@@ -490,11 +490,11 @@
 	ASSERT(!is_kernel_fault(va));
 
-	t = page_mapping_find(AS, va, true);
-	if (t) {
+	bool found = page_mapping_find(AS, va, true, &t);
+	if (found) {
 		/*
 		 * The mapping was found in software page hash table.
 		 * Insert it into data translation cache.
 		 */
-		itc_pte_copy(t);
+		itc_pte_copy(&t);
 	} else {
 		/*
@@ -600,11 +600,12 @@
 	
 	
-	pte_t *entry = page_mapping_find(as, va, true);
-	if (entry) {
+	pte_t t;
+	bool found = page_mapping_find(as, va, true, &t);
+	if (found) {
 		/*
 		 * The mapping was found in the software page hash table.
 		 * Insert it into data translation cache.
 		 */
-		dtc_pte_copy(entry);
+		dtc_pte_copy(&t);
 	} else {
 		if (try_memmap_io_insertion(va, istate))
@@ -641,5 +642,5 @@
 {
 	uintptr_t va;
-	pte_t *t;
+	pte_t t;
 	as_t *as = AS;
 	
@@ -649,13 +650,17 @@
 		as = AS_KERNEL;
 
-	t = page_mapping_find(as, va, true);
-	ASSERT((t) && (t->p));
-	if ((t) && (t->p) && (t->w)) {
+	bool found = page_mapping_find(as, va, true, &t);
+
+	ASSERT(found);
+	ASSERT(t.p);
+
+	if (found && t.p && t.w) {
 		/*
 		 * Update the Dirty bit in page tables and reinsert
 		 * the mapping into DTC.
 		 */
-		t->d = true;
-		dtc_pte_copy(t);
+		t.d = true;
+		dtc_pte_copy(&t);
+		page_mapping_update(as, va, true, &t);
 	} else {
 		as_page_fault(va, PF_ACCESS_WRITE, istate);
@@ -672,5 +677,5 @@
 {
 	uintptr_t va;
-	pte_t *t;
+	pte_t t;
 	
 	va = istate->cr_ifa;  /* faulting address */
@@ -678,13 +683,17 @@
 	ASSERT(!is_kernel_fault(va));
 	
-	t = page_mapping_find(AS, va, true);
-	ASSERT((t) && (t->p));
-	if ((t) && (t->p) && (t->x)) {
+	bool found = page_mapping_find(AS, va, true, &t);
+
+	ASSERT(found);
+	ASSERT(t.p);
+
+	if (found && t.p && t.x) {
 		/*
 		 * Update the Accessed bit in page tables and reinsert
 		 * the mapping into ITC.
 		 */
-		t->a = true;
-		itc_pte_copy(t);
+		t.a = true;
+		itc_pte_copy(&t);
+		page_mapping_update(AS, va, true, &t);
 	} else {
 		as_page_fault(va, PF_ACCESS_EXEC, istate);
@@ -701,5 +710,5 @@
 {
 	uintptr_t va;
-	pte_t *t;
+	pte_t t;
 	as_t *as = AS;
 	
@@ -709,13 +718,17 @@
 		as = AS_KERNEL;
 
-	t = page_mapping_find(as, va, true);
-	ASSERT((t) && (t->p));
-	if ((t) && (t->p)) {
+	bool found = page_mapping_find(as, va, true, &t);
+
+	ASSERT(found);
+	ASSERT(t.p);
+
+	if (found && t.p) {
 		/*
 		 * Update the Accessed bit in page tables and reinsert
 		 * the mapping into DTC.
 		 */
-		t->a = true;
-		dtc_pte_copy(t);
+		t.a = true;
+		dtc_pte_copy(&t);
+		page_mapping_update(as, va, true, &t);
 	} else {
 		if (as_page_fault(va, PF_ACCESS_READ, istate) == AS_PF_FAULT) {
@@ -736,5 +749,5 @@
 {
 	uintptr_t va;
-	pte_t *t;
+	pte_t t;
 	
 	va = istate->cr_ifa;  /* faulting address */
@@ -745,7 +758,10 @@
 	 * Assume a write to a read-only page.
 	 */
-	t = page_mapping_find(AS, va, true);
-	ASSERT((t) && (t->p));
-	ASSERT(!t->w);
+	bool found = page_mapping_find(AS, va, true, &t);
+
+	ASSERT(found);
+	ASSERT(t.p);
+	ASSERT(!t.w);
+
 	as_page_fault(va, PF_ACCESS_WRITE, istate);
 }
@@ -760,5 +776,5 @@
 {
 	uintptr_t va;
-	pte_t *t;
+	pte_t t;
 	
 	va = istate->cr_ifa;  /* faulting address */
@@ -766,16 +782,17 @@
 	ASSERT(!is_kernel_fault(va));
 
-	t = page_mapping_find(AS, va, true);
-	ASSERT(t);
-	
-	if (t->p) {
+	bool found = page_mapping_find(AS, va, true, &t);
+
+	ASSERT(found);
+	
+	if (t.p) {
 		/*
 		 * If the Present bit is set in page hash table, just copy it
 		 * and update ITC/DTC.
 		 */
-		if (t->x)
-			itc_pte_copy(t);
+		if (t.x)
+			itc_pte_copy(&t);
 		else
-			dtc_pte_copy(t);
+			dtc_pte_copy(&t);
 	} else {
 		as_page_fault(va, PF_ACCESS_READ, istate);
Index: kernel/arch/mips32/include/arch/mm/page.h
===================================================================
--- kernel/arch/mips32/include/arch/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/mips32/include/arch/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -137,9 +137,9 @@
 
 /* Last-level info macros. */
-#define PTE_VALID_ARCH(pte)			(*((uint32_t *) (pte)) != 0)
-#define PTE_PRESENT_ARCH(pte)			((pte)->p != 0)
-#define PTE_GET_FRAME_ARCH(pte)			((pte)->pfn << 12)
-#define PTE_WRITABLE_ARCH(pte)			((pte)->w != 0)
-#define PTE_EXECUTABLE_ARCH(pte)		1
+#define PTE_VALID_ARCH(pte)		((pte)->soft_valid != 0)
+#define PTE_PRESENT_ARCH(pte)		((pte)->p != 0)
+#define PTE_GET_FRAME_ARCH(pte)		((pte)->pfn << 12)
+#define PTE_WRITABLE_ARCH(pte)		((pte)->w != 0)
+#define PTE_EXECUTABLE_ARCH(pte)	1
 
 #ifndef __ASM__
Index: kernel/arch/mips32/src/mm/tlb.c
===================================================================
--- kernel/arch/mips32/src/mm/tlb.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/mips32/src/mm/tlb.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -97,17 +97,19 @@
 	entry_lo_t lo;
 	uintptr_t badvaddr;
-	pte_t *pte;
+	pte_t pte;
 	
 	badvaddr = cp0_badvaddr_read();
 
-	pte = page_mapping_find(AS, badvaddr, true);
-	if (pte && pte->p) {
+	bool found = page_mapping_find(AS, badvaddr, true, &pte);
+	if (found && pte.p) {
 		/*
 		 * Record access to PTE.
 		 */
-		pte->a = 1;
-
-		tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d,
-		    pte->cacheable, pte->pfn);
+		pte.a = 1;
+
+		tlb_prepare_entry_lo(&lo, pte.g, pte.p, pte.d,
+		    pte.cacheable, pte.pfn);
+
+		page_mapping_update(AS, badvaddr, true, &pte);
 
 		/*
@@ -138,5 +140,5 @@
 	tlb_index_t index;
 	uintptr_t badvaddr;
-	pte_t *pte;
+	pte_t pte;
 
 	/*
@@ -162,6 +164,6 @@
 	badvaddr = cp0_badvaddr_read();
 
-	pte = page_mapping_find(AS, badvaddr, true);
-	if (pte && pte->p) {
+	bool found = page_mapping_find(AS, badvaddr, true, &pte);
+	if (found && pte.p) {
 		/*
 		 * Read the faulting TLB entry.
@@ -172,8 +174,10 @@
 		 * Record access to PTE.
 		 */
-		pte->a = 1;
-
-		tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->d,
-		    pte->cacheable, pte->pfn);
+		pte.a = 1;
+
+		tlb_prepare_entry_lo(&lo, pte.g, pte.p, pte.d,
+		    pte.cacheable, pte.pfn);
+
+		page_mapping_update(AS, badvaddr, true, &pte);
 
 		/*
@@ -200,5 +204,5 @@
 	tlb_index_t index;
 	uintptr_t badvaddr;
-	pte_t *pte;
+	pte_t pte;
 
 	badvaddr = cp0_badvaddr_read();
@@ -224,6 +228,6 @@
 	}
 
-	pte = page_mapping_find(AS, badvaddr, true);
-	if (pte && pte->p && pte->w) {
+	bool found = page_mapping_find(AS, badvaddr, true, &pte);
+	if (found && pte.p && pte.w) {
 		/*
 		 * Read the faulting TLB entry.
@@ -234,9 +238,11 @@
 		 * Record access and write to PTE.
 		 */
-		pte->a = 1;
-		pte->d = 1;
-
-		tlb_prepare_entry_lo(&lo, pte->g, pte->p, pte->w,
-		    pte->cacheable, pte->pfn);
+		pte.a = 1;
+		pte.d = 1;
+
+		tlb_prepare_entry_lo(&lo, pte.g, pte.p, pte.w,
+		    pte.cacheable, pte.pfn);
+
+		page_mapping_update(AS, badvaddr, true, &pte);
 
 		/*
Index: kernel/arch/ppc32/include/arch/mm/page.h
===================================================================
--- kernel/arch/ppc32/include/arch/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/ppc32/include/arch/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -140,5 +140,5 @@
 
 /* Macros for querying the last-level PTEs. */
-#define PTE_VALID_ARCH(pte)       (*((uint32_t *) (pte)) != 0)
+#define PTE_VALID_ARCH(pte)       ((pte)->valid != 0)
 #define PTE_PRESENT_ARCH(pte)     ((pte)->present != 0)
 #define PTE_GET_FRAME_ARCH(pte)   ((pte)->pfn << 12)
Index: kernel/arch/ppc32/src/mm/pht.c
===================================================================
--- kernel/arch/ppc32/src/mm/pht.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/ppc32/src/mm/pht.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -49,21 +49,22 @@
  * @param access   Access mode that caused the fault.
  * @param istate   Pointer to interrupted state.
- *
- * @return PTE on success, NULL otherwise.
- *
- */
-static pte_t *find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
-    istate_t *istate)
+ * @param[out] pte Structure that will receive a copy of the found PTE.
+ *
+ * @return True if the mapping was found, false otherwise.
+ *
+ */
+static bool find_mapping_and_check(as_t *as, uintptr_t badvaddr, int access,
+    istate_t *istate, pte_t *pte)
 {
 	/*
 	 * Check if the mapping exists in page tables.
 	 */
-	pte_t *pte = page_mapping_find(as, badvaddr, true);
-	if ((pte) && (pte->present)) {
+	bool found = page_mapping_find(as, badvaddr, true, pte);
+	if (found && pte->present) {
 		/*
 		 * Mapping found in page tables.
 		 * Immediately succeed.
 		 */
-		return pte;
+		return true;
 	}
 	/*
@@ -76,10 +77,13 @@
 		 * The mapping ought to be in place.
 		 */
-		pte = page_mapping_find(as, badvaddr, true);
-		ASSERT((pte) && (pte->present));
-		return pte;
-	}
-
-	return NULL;
+		found = page_mapping_find(as, badvaddr, true, pte);
+
+		ASSERT(found);
+		ASSERT(pte->present);
+
+		return found;
+	}
+
+	return false;
 }
 
@@ -182,11 +186,12 @@
 		badvaddr = istate->pc;
 	
-	pte_t *pte = find_mapping_and_check(AS, badvaddr,
-	    PF_ACCESS_READ /* FIXME */, istate);
-	
-	if (pte) {
+	pte_t pte;
+	bool found = find_mapping_and_check(AS, badvaddr,
+	    PF_ACCESS_READ /* FIXME */, istate, &pte);
+	
+	if (found) {
 		/* Record access to PTE */
-		pte->accessed = 1;
-		pht_insert(badvaddr, pte);
+		pte.accessed = 1;
+		pht_insert(badvaddr, &pte);
 	}
 }
Index: kernel/arch/sparc32/include/arch/mm/page.h
===================================================================
--- kernel/arch/sparc32/include/arch/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/sparc32/include/arch/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -129,5 +129,5 @@
 /* Macros for querying the last level entries. */
 #define PTE_VALID_ARCH(p) \
-	(*((uint32_t *) (p)) != 0)
+	((p)->et != PTE_ET_INVALID)
 #define PTE_PRESENT_ARCH(p) \
 	((p)->et != 0)
Index: kernel/arch/sparc64/src/mm/sun4u/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4u/tlb.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/sparc64/src/mm/sun4u/tlb.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -197,17 +197,18 @@
 {
 	size_t index = (istate->tpc >> MMU_PAGE_WIDTH) % MMU_PAGES_PER_PAGE;
-	pte_t *t;
-
-	t = page_mapping_find(AS, istate->tpc, true);
-	if (t && PTE_EXECUTABLE(t)) {
+	pte_t t;
+
+	bool found = page_mapping_find(AS, istate->tpc, true, &t);
+	if (found && PTE_EXECUTABLE(&t)) {
 		/*
 		 * The mapping was found in the software page hash table.
 		 * Insert it into ITLB.
 		 */
-		t->a = true;
-		itlb_pte_copy(t, index);
+		t.a = true;
+		itlb_pte_copy(&t, index);
 #ifdef CONFIG_TSB
-		itsb_pte_copy(t, index);
-#endif
+		itsb_pte_copy(&t, index);
+#endif
+		page_mapping_update(AS, istate->tpc, true, &t);
 	} else {
 		/*
@@ -233,5 +234,5 @@
 	uintptr_t page_16k;
 	size_t index;
-	pte_t *t;
+	pte_t t;
 	as_t *as = AS;
 
@@ -253,15 +254,16 @@
 	}
 
-	t = page_mapping_find(as, page_16k, true);
-	if (t) {
+	bool found = page_mapping_find(as, page_16k, true, &t);
+	if (found) {
 		/*
 		 * The mapping was found in the software page hash table.
 		 * Insert it into DTLB.
 		 */
-		t->a = true;
-		dtlb_pte_copy(t, index, true);
+		t.a = true;
+		dtlb_pte_copy(&t, index, true);
 #ifdef CONFIG_TSB
-		dtsb_pte_copy(t, index, true);
-#endif
+		dtsb_pte_copy(&t, index, true);
+#endif
+		page_mapping_update(as, page_16k, true, &t);
 	} else {
 		/*
@@ -283,5 +285,5 @@
 	uintptr_t page_16k;
 	size_t index;
-	pte_t *t;
+	pte_t t;
 	as_t *as = AS;
 
@@ -293,6 +295,6 @@
 		as = AS_KERNEL;
 
-	t = page_mapping_find(as, page_16k, true);
-	if (t && PTE_WRITABLE(t)) {
+	bool found = page_mapping_find(as, page_16k, true, &t);
+	if (found && PTE_WRITABLE(&t)) {
 		/*
 		 * The mapping was found in the software page hash table and is
@@ -300,12 +302,13 @@
 		 * into DTLB.
 		 */
-		t->a = true;
-		t->d = true;
+		t.a = true;
+		t.d = true;
 		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_SECONDARY,
 		    page_16k + index * MMU_PAGE_SIZE);
-		dtlb_pte_copy(t, index, false);
+		dtlb_pte_copy(&t, index, false);
 #ifdef CONFIG_TSB
-		dtsb_pte_copy(t, index, false);
-#endif
+		dtsb_pte_copy(&t, index, false);
+#endif
+		page_mapping_update(as, page_16k, true, &t);
 	} else {
 		/*
Index: kernel/arch/sparc64/src/mm/sun4v/tlb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/tlb.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/arch/sparc64/src/mm/sun4v/tlb.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -211,18 +211,18 @@
 {
 	uintptr_t va = ALIGN_DOWN(istate->tpc, PAGE_SIZE);
-	pte_t *t;
-
-	t = page_mapping_find(AS, va, true);
-
-	if (t && PTE_EXECUTABLE(t)) {
+	pte_t t;
+
+	bool found = page_mapping_find(AS, va, true, &t);
+	if (found && PTE_EXECUTABLE(&t)) {
 		/*
 		 * The mapping was found in the software page hash table.
 		 * Insert it into ITLB.
 		 */
-		t->a = true;
-		itlb_pte_copy(t);
+		t.a = true;
+		itlb_pte_copy(&t);
 #ifdef CONFIG_TSB
-		itsb_pte_copy(t);
-#endif
+		itsb_pte_copy(&t);
+#endif
+		page_mapping_update(AS, va, true, &t);
 	} else {
 		/*
@@ -244,5 +244,5 @@
 void fast_data_access_mmu_miss(unsigned int tt, istate_t *istate)
 {
-	pte_t *t;
+	pte_t t;
 	uintptr_t va = DMISS_ADDRESS(istate->tlb_tag_access);
 	uint16_t ctx = DMISS_CONTEXT(istate->tlb_tag_access);
@@ -261,15 +261,16 @@
 	}
 
-	t = page_mapping_find(as, va, true);
-	if (t) {
+	bool found = page_mapping_find(as, va, true, &t);
+	if (found) {
 		/*
 		 * The mapping was found in the software page hash table.
 		 * Insert it into DTLB.
 		 */
-		t->a = true;
-		dtlb_pte_copy(t, true);
+		t.a = true;
+		dtlb_pte_copy(&t, true);
 #ifdef CONFIG_TSB
-		dtsb_pte_copy(t, true);
-#endif
+		dtsb_pte_copy(&t, true);
+#endif
+		page_mapping_update(as, va, true, &t);
 	} else {
 		/*
@@ -288,5 +289,5 @@
 void fast_data_access_protection(unsigned int tt, istate_t *istate)
 {
-	pte_t *t;
+	pte_t t;
 	uintptr_t va = DMISS_ADDRESS(istate->tlb_tag_access);
 	uint16_t ctx = DMISS_CONTEXT(istate->tlb_tag_access);
@@ -296,6 +297,6 @@
 		as = AS_KERNEL;
 
-	t = page_mapping_find(as, va, true);
-	if (t && PTE_WRITABLE(t)) {
+	bool found = page_mapping_find(as, va, true, &t);
+	if (found && PTE_WRITABLE(&t)) {
 		/*
 		 * The mapping was found in the software page hash table and is
@@ -303,11 +304,12 @@
 		 * into DTLB.
 		 */
-		t->a = true;
-		t->d = true;
+		t.a = true;
+		t.d = true;
 		mmu_demap_page(va, ctx, MMU_FLAG_DTLB);
-		dtlb_pte_copy(t, false);
+		dtlb_pte_copy(&t, false);
 #ifdef CONFIG_TSB
-		dtsb_pte_copy(t, false);
-#endif
+		dtsb_pte_copy(&t, false);
+#endif
+		page_mapping_update(as, va, true, &t);
 	} else {
 		/*
Index: kernel/genarch/include/genarch/mm/page_ht.h
===================================================================
--- kernel/genarch/include/genarch/mm/page_ht.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/genarch/include/genarch/mm/page_ht.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -44,5 +44,4 @@
 #include <mm/page.h>
 #include <mm/slab.h>
-#include <synch/mutex.h>
 #include <adt/hash_table.h>
 
@@ -55,5 +54,5 @@
 
 /* Macros for querying page hash table PTEs. */
-#define PTE_VALID(pte)       ((pte) != NULL)
+#define PTE_VALID(pte)       ((void *) (pte) != NULL)
 #define PTE_PRESENT(pte)     ((pte)->p != 0)
 #define PTE_GET_FRAME(pte)   ((pte)->frame)
@@ -66,5 +65,4 @@
 
 extern slab_cache_t *pte_cache;
-extern mutex_t page_ht_lock;
 extern hash_table_t page_ht;
 extern hash_table_operations_t ht_operations;
Index: kernel/genarch/src/mm/as_ht.c
===================================================================
--- kernel/genarch/src/mm/as_ht.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/genarch/src/mm/as_ht.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -77,5 +77,4 @@
 	if (flags & FLAG_AS_KERNEL) {
 		hash_table_create(&page_ht, PAGE_HT_ENTRIES, 2, &ht_operations);
-		mutex_initialize(&page_ht_lock, MUTEX_PASSIVE);
 		pte_cache = slab_cache_create("pte_t", sizeof(pte_t), 0,
 		    NULL, NULL, SLAB_CACHE_MAGDEFERRED);
@@ -99,5 +98,5 @@
 /** Lock page table.
  *
- * Lock address space and page hash table.
+ * Lock address space.
  * Interrupts must be disabled.
  *
@@ -110,11 +109,9 @@
 	if (lock)
 		mutex_lock(&as->lock);
-	
-	mutex_lock(&page_ht_lock);
 }
 
 /** Unlock page table.
  *
- * Unlock address space and page hash table.
+ * Unlock address space.
  * Interrupts must be disabled.
  *
@@ -125,6 +122,4 @@
 void ht_unlock(as_t *as, bool unlock)
 {
-	mutex_unlock(&page_ht_lock);
-	
 	if (unlock)
 		mutex_unlock(&as->lock);
@@ -140,5 +135,5 @@
 bool ht_locked(as_t *as)
 {
-	return (mutex_locked(&page_ht_lock) && mutex_locked(&as->lock));
+	return mutex_locked(&as->lock);
 }
 
Index: kernel/genarch/src/mm/page_ht.c
===================================================================
--- kernel/genarch/src/mm/page_ht.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/genarch/src/mm/page_ht.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -59,5 +59,6 @@
 static void ht_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
 static void ht_mapping_remove(as_t *, uintptr_t);
-static pte_t *ht_mapping_find(as_t *, uintptr_t, bool);
+static bool ht_mapping_find(as_t *, uintptr_t, bool, pte_t *);
+static void ht_mapping_update(as_t *, uintptr_t, bool, pte_t *);
 static void ht_mapping_make_global(uintptr_t, size_t);
 
@@ -70,5 +71,5 @@
  *
  */
-mutex_t page_ht_lock;
+IRQ_SPINLOCK_STATIC_INITIALIZE(page_ht_lock);
 
 /** Page hash table.
@@ -91,4 +92,5 @@
 	.mapping_remove = ht_mapping_remove,
 	.mapping_find = ht_mapping_find,
+	.mapping_update = ht_mapping_update,
 	.mapping_make_global = ht_mapping_make_global
 };
@@ -191,4 +193,6 @@
 
 	ASSERT(page_table_locked(as));
+
+	irq_spinlock_lock(&page_ht_lock, true);
 	
 	if (!hash_table_find(&page_ht, key)) {
@@ -217,4 +221,6 @@
 		hash_table_insert(&page_ht, key, &pte->link);
 	}
+
+	irq_spinlock_unlock(&page_ht_lock, true);
 }
 
@@ -238,4 +244,6 @@
 	ASSERT(page_table_locked(as));
 	
+	irq_spinlock_lock(&page_ht_lock, true);
+
 	/*
 	 * Note that removed PTE's will be freed
@@ -243,17 +251,9 @@
 	 */
 	hash_table_remove(&page_ht, key, 2);
-}
-
-
-/** Find mapping for virtual page in page hash table.
- *
- * @param as     Address space to which page belongs.
- * @param page   Virtual page.
- * @param nolock True if the page tables need not be locked.
- *
- * @return NULL if there is no such mapping; requested mapping otherwise.
- *
- */
-pte_t *ht_mapping_find(as_t *as, uintptr_t page, bool nolock)
+
+	irq_spinlock_unlock(&page_ht_lock, true);
+}
+
+static pte_t *ht_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
 {
 	sysarg_t key[2] = {
@@ -263,5 +263,5 @@
 
 	ASSERT(nolock || page_table_locked(as));
-	
+
 	link_t *cur = hash_table_find(&page_ht, key);
 	if (cur)
@@ -271,4 +271,57 @@
 }
 
+/** Find mapping for virtual page in page hash table.
+ *
+ * @param as       Address space to which page belongs.
+ * @param page     Virtual page.
+ * @param nolock   True if the page tables need not be locked.
+ * @param[out] pte Structure that will receive a copy of the found PTE.
+ *
+ * @return True if the mapping was found, false otherwise.
+ */
+bool ht_mapping_find(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
+{
+	irq_spinlock_lock(&page_ht_lock, true);
+
+	pte_t *t = ht_mapping_find_internal(as, page, nolock);
+	if (t)
+		*pte = *t;
+
+	irq_spinlock_unlock(&page_ht_lock, true);
+	
+	return t != NULL;
+}
+
+/** Update mapping for virtual page in page hash table.
+ *
+ * @param as       Address space to which page belongs.
+ * @param page     Virtual page.
+ * @param nolock   True if the page tables need not be locked.
+ * @param pte      New PTE.
+ */
+void ht_mapping_update(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
+{
+	irq_spinlock_lock(&page_ht_lock, true);
+
+	pte_t *t = ht_mapping_find_internal(as, page, nolock);
+	if (!t)
+		panic("Updating non-existent PTE");
+	
+	ASSERT(pte->as == t->as);
+	ASSERT(pte->page == t->page);
+	ASSERT(pte->frame == t->frame);
+	ASSERT(pte->g == t->g);
+	ASSERT(pte->x == t->x);
+	ASSERT(pte->w == t->w);
+	ASSERT(pte->k == t->k);
+	ASSERT(pte->c == t->c);
+	ASSERT(pte->p == t->p);
+
+	t->a = pte->a;
+	t->d = pte->d;
+
+	irq_spinlock_unlock(&page_ht_lock, true);
+}
+
 void ht_mapping_make_global(uintptr_t base, size_t size)
 {
Index: kernel/genarch/src/mm/page_pt.c
===================================================================
--- kernel/genarch/src/mm/page_pt.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/genarch/src/mm/page_pt.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -53,5 +53,6 @@
 static void pt_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
 static void pt_mapping_remove(as_t *, uintptr_t);
-static pte_t *pt_mapping_find(as_t *, uintptr_t, bool);
+static bool pt_mapping_find(as_t *, uintptr_t, bool, pte_t *pte);
+static void pt_mapping_update(as_t *, uintptr_t, bool, pte_t *pte);
 static void pt_mapping_make_global(uintptr_t, size_t);
 
@@ -60,4 +61,5 @@
 	.mapping_remove = pt_mapping_remove,
 	.mapping_find = pt_mapping_find,
+	.mapping_update = pt_mapping_update,
 	.mapping_make_global = pt_mapping_make_global
 };
@@ -289,15 +291,5 @@
 }
 
-/** Find mapping for virtual page in hierarchical page tables.
- *
- * @param as     Address space to which page belongs.
- * @param page   Virtual page.
- * @param nolock True if the page tables need not be locked.
- *
- * @return NULL if there is no such mapping; entry from PTL3 describing
- *         the mapping otherwise.
- *
- */
-pte_t *pt_mapping_find(as_t *as, uintptr_t page, bool nolock)
+static pte_t *pt_mapping_find_internal(as_t *as, uintptr_t page, bool nolock)
 {
 	ASSERT(nolock || page_table_locked(as));
@@ -334,4 +326,43 @@
 	
 	return &ptl3[PTL3_INDEX(page)];
+}
+
+/** Find mapping for virtual page in hierarchical page tables.
+ *
+ * @param as       Address space to which page belongs.
+ * @param page     Virtual page.
+ * @param nolock   True if the page tables need not be locked.
+ * @param[out] pte Structure that will receive a copy of the found PTE.
+ *
+ * @return True if the mapping was found, false otherwise.
+ */
+bool pt_mapping_find(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
+{
+	pte_t *t = pt_mapping_find_internal(as, page, nolock);
+	if (t)
+		*pte = *t;
+	return t != NULL;
+}
+
+/** Update mapping for virtual page in hierarchical page tables.
+ *
+ * @param as       Address space to which page belongs.
+ * @param page     Virtual page.
+ * @param nolock   True if the page tables need not be locked.
+ * @param[in] pte  New PTE.
+ */
+void pt_mapping_update(as_t *as, uintptr_t page, bool nolock, pte_t *pte)
+{
+	pte_t *t = pt_mapping_find_internal(as, page, nolock);
+	if (!t)
+		panic("Updating non-existent PTE");	
+
+	ASSERT(PTE_VALID(t) == PTE_VALID(pte));
+	ASSERT(PTE_PRESENT(t) == PTE_PRESENT(pte));
+	ASSERT(PTE_GET_FRAME(t) == PTE_GET_FRAME(pte));
+	ASSERT(PTE_WRITABLE(t) == PTE_WRITABLE(pte));
+	ASSERT(PTE_EXECUTABLE(t) == PTE_EXECUTABLE(pte));
+
+	*t = *pte;
 }
 
Index: kernel/generic/include/mm/page.h
===================================================================
--- kernel/generic/include/mm/page.h	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/include/mm/page.h	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -48,5 +48,6 @@
 	void (* mapping_insert)(as_t *, uintptr_t, uintptr_t, unsigned int);
 	void (* mapping_remove)(as_t *, uintptr_t);
-	pte_t *(* mapping_find)(as_t *, uintptr_t, bool);
+	bool (* mapping_find)(as_t *, uintptr_t, bool, pte_t *);
+	void (* mapping_update)(as_t *, uintptr_t, bool, pte_t *);
 	void (* mapping_make_global)(uintptr_t, size_t);
 } page_mapping_operations_t;
@@ -60,5 +61,6 @@
 extern void page_mapping_insert(as_t *, uintptr_t, uintptr_t, unsigned int);
 extern void page_mapping_remove(as_t *, uintptr_t);
-extern pte_t *page_mapping_find(as_t *, uintptr_t, bool);
+extern bool page_mapping_find(as_t *, uintptr_t, bool, pte_t *);
+extern void page_mapping_update(as_t *, uintptr_t, bool, pte_t *);
 extern void page_mapping_make_global(uintptr_t, size_t);
 extern pte_t *page_table_create(unsigned int);
Index: kernel/generic/src/ipc/ops/pagein.c
===================================================================
--- kernel/generic/src/ipc/ops/pagein.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/src/ipc/ops/pagein.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -47,11 +47,12 @@
 {
 	if (!IPC_GET_RETVAL(answer->data)) {
-		pte_t *pte;
+		pte_t pte;
 		uintptr_t frame;
 
 		page_table_lock(AS, true);
-		pte = page_mapping_find(AS, IPC_GET_ARG1(answer->data), false);
-		if (pte) {
-			frame = PTE_GET_FRAME(pte);
+		bool found = page_mapping_find(AS, IPC_GET_ARG1(answer->data),
+		    false, &pte);
+		if (found) {
+			frame = PTE_GET_FRAME(&pte);
 			pfn_t pfn = ADDR2PFN(frame);
 			if (find_zone(pfn, 1, 0) != (size_t) -1) {
Index: kernel/generic/src/mm/as.c
===================================================================
--- kernel/generic/src/mm/as.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/src/mm/as.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -889,10 +889,11 @@
 		
 				for (; i < node_size; i++) {
-					pte_t *pte = page_mapping_find(as,
-					    ptr + P2SZ(i), false);
+					pte_t pte;
+					bool found = page_mapping_find(as,
+					    ptr + P2SZ(i), false, &pte);
 					
-					ASSERT(pte);
-					ASSERT(PTE_VALID(pte));
-					ASSERT(PTE_PRESENT(pte));
+					ASSERT(found);
+					ASSERT(PTE_VALID(&pte));
+					ASSERT(PTE_PRESENT(&pte));
 					
 					if ((area->backend) &&
@@ -900,5 +901,5 @@
 						area->backend->frame_free(area,
 						    ptr + P2SZ(i),
-						    PTE_GET_FRAME(pte));
+						    PTE_GET_FRAME(&pte));
 					}
 					
@@ -1003,10 +1004,11 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as,
-				     ptr + P2SZ(size), false);
+				pte_t pte;
+				bool found = page_mapping_find(as,
+				     ptr + P2SZ(size), false, &pte);
 				
-				ASSERT(pte);
-				ASSERT(PTE_VALID(pte));
-				ASSERT(PTE_PRESENT(pte));
+				ASSERT(found);
+				ASSERT(PTE_VALID(&pte));
+				ASSERT(PTE_PRESENT(&pte));
 				
 				if ((area->backend) &&
@@ -1014,5 +1016,5 @@
 					area->backend->frame_free(area,
 					    ptr + P2SZ(size),
-					    PTE_GET_FRAME(pte));
+					    PTE_GET_FRAME(&pte));
 				}
 				
@@ -1315,12 +1317,13 @@
 			
 			for (size = 0; size < (size_t) node->value[i]; size++) {
-				pte_t *pte = page_mapping_find(as,
-				    ptr + P2SZ(size), false);
+				pte_t pte;
+				bool found = page_mapping_find(as,
+				    ptr + P2SZ(size), false, &pte);
 				
-				ASSERT(pte);
-				ASSERT(PTE_VALID(pte));
-				ASSERT(PTE_PRESENT(pte));
+				ASSERT(found);
+				ASSERT(PTE_VALID(&pte));
+				ASSERT(PTE_PRESENT(&pte));
 				
-				old_frame[frame_idx++] = PTE_GET_FRAME(pte);
+				old_frame[frame_idx++] = PTE_GET_FRAME(&pte);
 				
 				/* Remove old mapping */
@@ -1452,10 +1455,11 @@
 	 * we need to make sure the mapping has not been already inserted.
 	 */
-	pte_t *pte;
-	if ((pte = page_mapping_find(AS, page, false))) {
-		if (PTE_PRESENT(pte)) {
-			if (((access == PF_ACCESS_READ) && PTE_READABLE(pte)) ||
-			    (access == PF_ACCESS_WRITE && PTE_WRITABLE(pte)) ||
-			    (access == PF_ACCESS_EXEC && PTE_EXECUTABLE(pte))) {
+	pte_t pte;
+	bool found = page_mapping_find(AS, page, false, &pte);
+	if (found) {
+		if (PTE_PRESENT(&pte)) {
+			if (((access == PF_ACCESS_READ) && PTE_READABLE(&pte)) ||
+			    (access == PF_ACCESS_WRITE && PTE_WRITABLE(&pte)) ||
+			    (access == PF_ACCESS_EXEC && PTE_EXECUTABLE(&pte))) {
 				page_table_unlock(AS, false);
 				mutex_unlock(&area->lock);
Index: kernel/generic/src/mm/backend_anon.c
===================================================================
--- kernel/generic/src/mm/backend_anon.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/src/mm/backend_anon.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -131,17 +131,21 @@
 			
 			for (j = 0; j < count; j++) {
-				pte_t *pte;
+				pte_t pte;
+				bool found;
 			
 				page_table_lock(area->as, false);
-				pte = page_mapping_find(area->as,
-				    base + P2SZ(j), false);
-				ASSERT(pte && PTE_VALID(pte) &&
-				    PTE_PRESENT(pte));
+				found = page_mapping_find(area->as,
+				    base + P2SZ(j), false, &pte);
+
+				ASSERT(found);
+				ASSERT(PTE_VALID(&pte));
+				ASSERT(PTE_PRESENT(&pte));
+
 				btree_insert(&area->sh_info->pagemap,
 				    (base + P2SZ(j)) - area->base,
-				    (void *) PTE_GET_FRAME(pte), NULL);
+				    (void *) PTE_GET_FRAME(&pte), NULL);
 				page_table_unlock(area->as, false);
 
-				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
+				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(&pte));
 				frame_reference_add(pfn);
 			}
Index: kernel/generic/src/mm/backend_elf.c
===================================================================
--- kernel/generic/src/mm/backend_elf.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/src/mm/backend_elf.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -184,5 +184,6 @@
 			
 			for (j = 0; j < count; j++) {
-				pte_t *pte;
+				pte_t pte;
+				bool found;
 			
 				/*
@@ -196,14 +197,17 @@
 				
 				page_table_lock(area->as, false);
-				pte = page_mapping_find(area->as,
-				    base + P2SZ(j), false);
-				ASSERT(pte && PTE_VALID(pte) &&
-				    PTE_PRESENT(pte));
+				found = page_mapping_find(area->as,
+				    base + P2SZ(j), false, &pte);
+
+				ASSERT(found);
+				ASSERT(PTE_VALID(&pte));
+				ASSERT(PTE_PRESENT(&pte));
+
 				btree_insert(&area->sh_info->pagemap,
 				    (base + P2SZ(j)) - area->base,
-				    (void *) PTE_GET_FRAME(pte), NULL);
+				    (void *) PTE_GET_FRAME(&pte), NULL);
 				page_table_unlock(area->as, false);
 
-				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(pte));
+				pfn_t pfn = ADDR2PFN(PTE_GET_FRAME(&pte));
 				frame_reference_add(pfn);
 			}
@@ -335,11 +339,14 @@
 			dirty = true;
 		} else {
-			pte_t *pte = page_mapping_find(AS_KERNEL,
-			    base + i * FRAME_SIZE, true);
-
-			ASSERT(pte);
-			ASSERT(PTE_PRESENT(pte));
-
-			frame = PTE_GET_FRAME(pte);
+			pte_t pte;
+			bool found;
+
+			found = page_mapping_find(AS_KERNEL,
+			    base + i * FRAME_SIZE, true, &pte);
+
+			ASSERT(found);
+			ASSERT(PTE_PRESENT(&pte));
+
+			frame = PTE_GET_FRAME(&pte);
 		}	
 	} else if (upage >= start_anon) {
Index: kernel/generic/src/mm/page.c
===================================================================
--- kernel/generic/src/mm/page.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/src/mm/page.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -137,13 +137,13 @@
 /** Find mapping for virtual page.
  *
- * @param as     Address space to which page belongs.
- * @param page   Virtual page.
- * @param nolock True if the page tables need not be locked.
- *
- * @return NULL if there is no such mapping; requested mapping
- *         otherwise.
- *
- */
-NO_TRACE pte_t *page_mapping_find(as_t *as, uintptr_t page, bool nolock)
+ * @param as       Address space to which page belongs.
+ * @param page     Virtual page.
+ * @param nolock   True if the page tables need not be locked.
+ * @param[out] pte Structure that will receive a copy of the found PTE.
+ *
+ * @return True if the mapping was found, false otherwise.
+ */
+NO_TRACE bool page_mapping_find(as_t *as, uintptr_t page, bool nolock,
+    pte_t *pte)
 {
 	ASSERT(nolock || page_table_locked(as));
@@ -153,5 +153,26 @@
 	
 	return page_mapping_operations->mapping_find(as,
-	    ALIGN_DOWN(page, PAGE_SIZE), nolock);
+	    ALIGN_DOWN(page, PAGE_SIZE), nolock, pte);
+}
+
+/** Update mapping for virtual page.
+ *
+ * Use only to update accessed and modified/dirty bits.
+ *
+ * @param as       Address space to which page belongs.
+ * @param page     Virtual page.
+ * @param nolock   True if the page tables need not be locked.
+ * @param pte      New PTE.
+ */
+NO_TRACE void page_mapping_update(as_t *as, uintptr_t page, bool nolock,
+    pte_t *pte)
+{
+	ASSERT(nolock || page_table_locked(as));
+	
+	ASSERT(page_mapping_operations);
+	ASSERT(page_mapping_operations->mapping_find);
+	
+	page_mapping_operations->mapping_update(as,
+	    ALIGN_DOWN(page, PAGE_SIZE), nolock, pte);
 }
 
@@ -173,11 +194,12 @@
 	page_table_lock(AS, true);
 	
-	pte_t *pte = page_mapping_find(AS, virt, false);
-	if ((!PTE_VALID(pte)) || (!PTE_PRESENT(pte))) {
+	pte_t pte;
+	bool found = page_mapping_find(AS, virt, false, &pte);
+	if (!found || !PTE_VALID(&pte) || !PTE_PRESENT(&pte)) {
 		page_table_unlock(AS, true);
 		return ENOENT;
 	}
 	
-	*phys = PTE_GET_FRAME(pte) +
+	*phys = PTE_GET_FRAME(&pte) +
 	    (virt - ALIGN_DOWN(virt, PAGE_SIZE));
 	
Index: kernel/generic/src/synch/futex.c
===================================================================
--- kernel/generic/src/synch/futex.c	(revision f126c876616f5bbece442f6a35e0434e74d4c869)
+++ kernel/generic/src/synch/futex.c	(revision 2a2fbc84d3b2a2ff06b9bb236ff8e813c17ce223)
@@ -291,10 +291,14 @@
 	spinlock_lock(&futex_ht_lock);
 
-	bool found = false;
-	pte_t *t = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE), true);
-	
-	if (t && PTE_VALID(t) && PTE_PRESENT(t)) {
-		found = true;
-		*paddr = PTE_GET_FRAME(t) + (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
+	bool success = false;
+
+	pte_t t;
+	bool found;
+
+	found = page_mapping_find(AS, ALIGN_DOWN(uaddr, PAGE_SIZE), true, &t);
+	if (found && PTE_VALID(&t) && PTE_PRESENT(&t)) {
+		success = true;
+		*paddr = PTE_GET_FRAME(&t) +
+		    (uaddr - ALIGN_DOWN(uaddr, PAGE_SIZE));
 	}
 	
@@ -302,5 +306,5 @@
 	page_table_unlock(AS, false);
 	
-	return found;
+	return success;
 }
 
