Index: genarch/src/mm/page_ht.c
===================================================================
--- genarch/src/mm/page_ht.c	(revision bfb87dfa5a2db236f9520a16f8ba1d59d1d9c11c)
+++ genarch/src/mm/page_ht.c	(revision 8f00329caf7098cf41c86ae4e096edda0a3858a9)
@@ -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 bfb87dfa5a2db236f9520a16f8ba1d59d1d9c11c)
+++ genarch/src/mm/page_pt.c	(revision 8f00329caf7098cf41c86ae4e096edda0a3858a9)
@@ -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.
  *
Index: generic/include/mm/page.h
===================================================================
--- generic/include/mm/page.h	(revision bfb87dfa5a2db236f9520a16f8ba1d59d1d9c11c)
+++ generic/include/mm/page.h	(revision 8f00329caf7098cf41c86ae4e096edda0a3858a9)
@@ -63,4 +63,5 @@
 struct page_mapping_operations {
 	void (* mapping_insert)(as_t *as, __address page, __address frame, int flags);
+	void (* mapping_remove)(as_t *as, __address page);
 	pte_t *(* mapping_find)(as_t *as, __address page);
 };
@@ -71,4 +72,5 @@
 extern void page_init(void);
 extern void page_mapping_insert(as_t *as, __address page, __address frame, int flags);
+extern void page_mapping_remove(as_t *as, __address page);
 extern pte_t *page_mapping_find(as_t *as, __address page);
 extern pte_t *page_table_create(int flags);
Index: generic/src/mm/page.c
===================================================================
--- generic/src/mm/page.c	(revision bfb87dfa5a2db236f9520a16f8ba1d59d1d9c11c)
+++ generic/src/mm/page.c	(revision 8f00329caf7098cf41c86ae4e096edda0a3858a9)
@@ -72,5 +72,5 @@
 }
 
-/** Map page to frame
+/** Insert mapping of page to frame.
  *
  * Map virtual address 'page' to physical address 'frame'
@@ -79,5 +79,5 @@
  * The address space must be locked and interrupts must be disabled.
  *
- * @param as Address space to wich page belongs..
+ * @param as Address space to wich page belongs.
  * @param page Virtual address of the page to be mapped.
  * @param frame Physical address of memory frame to which the mapping is done.
@@ -90,4 +90,23 @@
 	
 	page_mapping_operations->mapping_insert(as, page, frame, flags);
+}
+
+/** Remove mapping of page.
+ *
+ * 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 page_mapping_remove(as_t *as, __address page)
+{
+	ASSERT(page_mapping_operations);
+	ASSERT(page_mapping_operations->mapping_remove);
+	
+	page_mapping_operations->mapping_remove(as, page);
 }
 
