Index: genarch/src/mm/page_ht.c
===================================================================
--- genarch/src/mm/page_ht.c	(revision 7e4e5323698b3059ed08f14198db2c9c1fbc746a)
+++ genarch/src/mm/page_ht.c	(revision a3eeceb63abe66d5ad2d3892d18a91ad79b185fc)
@@ -48,4 +48,5 @@
 
 static void ht_mapping_insert(as_t *as, __address page, __address frame, int flags);
+static void ht_mapping_remove(as_t *as, __address page);
 static pte_t *ht_mapping_find(as_t *as, __address page);
 
@@ -71,4 +72,5 @@
 page_mapping_operations_t ht_mapping_operations = {
 	.mapping_insert = ht_mapping_insert,
+	.mapping_remove = ht_mapping_remove,
 	.mapping_find = ht_mapping_find
 };
@@ -163,8 +165,6 @@
 {
 	pte_t *t;
-	ipl_t ipl;
 	__native key[2] = { (__address) as, page };
 	
-	ipl = interrupts_disable();
 	spinlock_lock(&page_ht_lock);
 
@@ -177,6 +177,32 @@
 	
 	spinlock_unlock(&page_ht_lock);
-	interrupts_restore(ipl);
-}
+}
+
+/** Remove mapping of page from page hash table.
+ *
+ * Remove any mapping of 'page' within address space 'as'.
+ * TLB shootdown should follow in order to make effects of
+ * this call visible.
+ *
+ * The address space must be locked and interrupts must be disabled.
+ *
+ * @param as Address space to wich page belongs.
+ * @param page Virtual address of the page to be demapped.
+ */
+void ht_mapping_remove(as_t *as, __address page)
+{
+	__native key[2] = { (__address) as, page };
+	
+	spinlock_lock(&page_ht_lock);
+
+	/*
+	 * Note that removed PTE's will be freed
+	 * by remove_callback().
+	 */
+	hash_table_remove(&page_ht, key, 2);
+
+	spinlock_unlock(&page_ht_lock);
+}
+
 
 /** Find mapping for virtual page in page hash table.
Index: genarch/src/mm/page_pt.c
===================================================================
--- genarch/src/mm/page_pt.c	(revision 7e4e5323698b3059ed08f14198db2c9c1fbc746a)
+++ genarch/src/mm/page_pt.c	(revision a3eeceb63abe66d5ad2d3892d18a91ad79b185fc)
@@ -39,8 +39,10 @@
 
 static void pt_mapping_insert(as_t *as, __address page, __address frame, int flags);
+static void pt_mapping_remove(as_t *as, __address page);
 static pte_t *pt_mapping_find(as_t *as, __address page);
 
 page_mapping_operations_t pt_mapping_operations = {
 	.mapping_insert = pt_mapping_insert,
+	.mapping_remove = pt_mapping_remove,
 	.mapping_find = pt_mapping_find
 };
@@ -96,4 +98,40 @@
 }
 
+/** Remove mapping of page from hierarchical page tables.
+ *
+ * Remove any mapping of 'page' within address space 'as'.
+ * TLB shootdown should follow in order to make effects of
+ * this call visible.
+ *
+ * The address space must be locked and interrupts must be disabled.
+ *
+ * @param as Address space to wich page belongs.
+ * @param page Virtual address of the page to be demapped.
+ */
+void pt_mapping_remove(as_t *as, __address page)
+{
+	pte_t *ptl0, *ptl1, *ptl2, *ptl3;
+
+	ptl0 = (pte_t *) PA2KA((__address) as->page_table);
+
+	if (GET_PTL1_FLAGS(ptl0, PTL0_INDEX(page)) & PAGE_NOT_PRESENT)
+		return;
+
+	ptl1 = (pte_t *) PA2KA(GET_PTL1_ADDRESS(ptl0, PTL0_INDEX(page)));
+
+	if (GET_PTL2_FLAGS(ptl1, PTL1_INDEX(page)) & PAGE_NOT_PRESENT)
+		return;
+
+	ptl2 = (pte_t *) PA2KA(GET_PTL2_ADDRESS(ptl1, PTL1_INDEX(page)));
+
+	if (GET_PTL3_FLAGS(ptl2, PTL2_INDEX(page)) & PAGE_NOT_PRESENT)
+		return;
+
+	ptl3 = (pte_t *) PA2KA(GET_PTL3_ADDRESS(ptl2, PTL2_INDEX(page)));
+
+	/* Destroy the mapping. Setting to PAGE_NOT_PRESENT is not sufficient. */
+	memsetb((__address) &ptl3[PTL3_INDEX(page)], sizeof(pte_t), 0);
+}
+
 /** Find mapping for virtual page in hierarchical page tables.
  *
