Index: arch/ia32/include/mm/asid.h
===================================================================
--- arch/ia32/include/mm/asid.h	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ arch/ia32/include/mm/asid.h	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -41,4 +41,5 @@
 
 #define asid_get()		(ASID_START+1)
+#define asid_put(asid)
 
 #endif
Index: genarch/src/mm/as_ht.c
===================================================================
--- genarch/src/mm/as_ht.c	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ genarch/src/mm/as_ht.c	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -43,4 +43,5 @@
 
 static pte_t *ht_create(int flags);
+static void ht_destroy(pte_t *page_table);
 
 static void ht_lock(as_t *as, bool lock);
@@ -49,4 +50,5 @@
 as_operations_t as_ht_operations = {
 	.page_table_create = ht_create,
+	.page_table_destroy = ht_destroy,
 	.page_table_lock = ht_lock,
 	.page_table_unlock = ht_unlock,
@@ -70,4 +72,15 @@
 	}
 	return NULL;
+}
+
+/** Destroy page table.
+ *
+ * Actually do nothing as the global page hash table is used.
+ *
+ * @param page_table This parameter is ignored.
+ */
+void ht_destroy(pte_t *page_table)
+{
+	/* No-op. */
 }
 
Index: genarch/src/mm/as_pt.c
===================================================================
--- genarch/src/mm/as_pt.c	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ genarch/src/mm/as_pt.c	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -45,4 +45,5 @@
 
 static pte_t *ptl0_create(int flags);
+static void ptl0_destroy(pte_t *page_table);
 
 static void pt_lock(as_t *as, bool lock);
@@ -51,4 +52,5 @@
 as_operations_t as_pt_operations = {
 	.page_table_create = ptl0_create,
+	.page_table_destroy = ptl0_destroy,
 	.page_table_lock = pt_lock,
 	.page_table_unlock = pt_unlock
@@ -95,4 +97,15 @@
 }
 
+/** Destroy page table.
+ *
+ * Destroy PTL0, other levels are expected to be already deallocated.
+ *
+ * @param page_table Physical address of PTL0.
+ */
+void ptl0_destroy(pte_t *page_table)
+{
+	frame_free(ADDR2PFN((__address) page_table));
+}
+
 /** Lock page tables.
  *
Index: generic/include/mm/as.h
===================================================================
--- generic/include/mm/as.h	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ generic/include/mm/as.h	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -76,4 +76,7 @@
 	mutex_t lock;
 
+	/** Number of references (i.e tasks that reference this as). */
+	count_t refcount;
+
 	/** Number of processors on wich is this address space active. */
 	count_t cpu_refcount;
@@ -91,4 +94,5 @@
 struct as_operations {
 	pte_t *(* page_table_create)(int flags);
+	void (* page_table_destroy)(pte_t *page_table);
 	void (* page_table_lock)(as_t *as, bool lock);
 	void (* page_table_unlock)(as_t *as, bool unlock);
@@ -159,16 +163,19 @@
 
 extern void as_init(void);
+
 extern as_t *as_create(int flags);
+extern void as_destroy(as_t *as);
+extern void as_switch(as_t *old, as_t *new);
+extern int as_page_fault(__address page, pf_access_t access, istate_t *istate);
+
 extern as_area_t *as_area_create(as_t *as, int flags, size_t size, __address base, int attrs,
 	mem_backend_t *backend, mem_backend_data_t *backend_data);
+extern int as_area_destroy(as_t *as, __address address);	
 extern int as_area_resize(as_t *as, __address address, size_t size, int flags);
-extern int as_area_destroy(as_t *as, __address address);
+int as_area_share(as_t *src_as, __address src_base, size_t acc_size,
+		  as_t *dst_as, __address dst_base, int dst_flags_mask);
+
 extern int as_area_get_flags(as_area_t *area);
 extern bool as_area_check_access(as_area_t *area, pf_access_t access);
-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);
-int as_area_share(as_t *src_as, __address src_base, size_t acc_size,
-		  as_t *dst_as, __address dst_base, int dst_flags_mask);
 extern size_t as_get_size(__address base);
 extern int used_space_insert(as_area_t *a, __address page, count_t count);
Index: generic/include/mm/page.h
===================================================================
--- generic/include/mm/page.h	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ generic/include/mm/page.h	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -86,4 +86,5 @@
 extern pte_t *page_mapping_find(as_t *as, __address page);
 extern pte_t *page_table_create(int flags);
+extern void page_table_destroy(pte_t *page_table);
 extern void map_structure(__address s, size_t size);
 extern __address hw_map(__address physaddr, size_t size);
Index: generic/include/proc/task.h
===================================================================
--- generic/include/proc/task.h	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ generic/include/proc/task.h	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -57,7 +57,7 @@
 	
 	/**
-	  * Serializes access to the B+tree of task's futexes. This mutex is
-	  * independent on the task spinlock.
-	  */
+	 * Serializes access to the B+tree of task's futexes. This mutex is
+	 * independent on the task spinlock.
+	 */
 	mutex_t futexes_lock;
 	btree_t futexes;	/**< B+tree of futexes referenced by this task. */
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ generic/src/mm/as.c	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -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.
  *
Index: generic/src/proc/task.c
===================================================================
--- generic/src/proc/task.c	(revision 343fc179b8db56da13456e0da507302315e0d11b)
+++ generic/src/proc/task.c	(revision 482826d75499a7a92dfbb849934f408e9ae8469b)
@@ -108,4 +108,13 @@
 	
 	ipl = interrupts_disable();
+
+	/*
+	 * Increment address space reference count.
+	 * TODO: Reconsider the locking scheme.
+	 */
+	mutex_lock(&as->lock);
+	as->refcount++;
+	mutex_unlock(&as->lock);
+
 	spinlock_lock(&tasks_lock);
 
@@ -140,5 +149,5 @@
 	rc = elf_load((elf_header_t *) program_addr, as);
 	if (rc != EE_OK) {
-		as_free(as);
+		as_destroy(as);
 		return NULL;
 	} 
