Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision 76d73057b7edc9cce0605befc3483baf1085d042)
+++ generic/src/mm/as.c	(revision 982f0feaabf3d54a008808578e7106b5dfa64682)
@@ -122,4 +122,5 @@
 		as->asid = ASID_INVALID;
 	
+	as->refcount = 0;
 	as->cpu_refcount = 0;
 	as->page_table = page_table_create(flags);
@@ -128,11 +129,47 @@
 }
 
-/** Free Adress space */
-void as_free(as_t *as)
-{
-	ASSERT(as->cpu_refcount == 0);
-
-	/* TODO: free as_areas and other resources held by as */
-	/* TODO: free page table */
+/** Destroy adress space.
+ *
+ * When there are no tasks referencing this address space (i.e. its refcount is zero),
+ * the address space can be destroyed.
+ */
+void as_destroy(as_t *as)
+{
+	ipl_t ipl;
+	bool cond;
+
+	ASSERT(as->refcount == 0);
+	
+	/*
+	 * Since there is no reference to this area,
+	 * it is safe not to lock its mutex.
+	 */
+	 
+	ipl = interrupts_disable();
+	spinlock_lock(&inactive_as_with_asid_lock);
+	if (as->asid != ASID_INVALID && as->asid != ASID_KERNEL) {
+		list_remove(&as->inactive_as_with_asid_link);
+		asid_put(as->asid);
+	}
+	spinlock_unlock(&inactive_as_with_asid_lock);
+
+	/*
+	 * Destroy address space areas of the address space.
+	 */	
+	for (cond = true; cond; ) {
+		btree_node_t *node;
+		
+		ASSERT(!list_empty(&as->as_area_btree.leaf_head));
+		node = list_get_instance(&as->as_area_btree.leaf_head.next, btree_node_t, leaf_link);
+		if ((cond = node->keys)) {
+			as_area_destroy(as, node->key[0]);
+			btree_remove(&as->as_area_btree, node->key[0], node);
+		}
+	}
+	
+	page_table_destroy(as->page_table);
+
+	interrupts_restore(ipl);
+	
 	free(as);
 }
@@ -841,4 +878,18 @@
 }
 
+/** Destroy page table.
+ *
+ * Destroy page table in architecture specific way.
+ *
+ * @param page_table Physical address of PTL0.
+ */
+void page_table_destroy(pte_t *page_table)
+{
+        ASSERT(as_operations);
+        ASSERT(as_operations->page_table_destroy);
+
+        as_operations->page_table_destroy(page_table);
+}
+
 /** Lock page table.
  *
