Index: generic/include/mm/as.h
===================================================================
--- generic/include/mm/as.h	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/include/mm/as.h	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -49,4 +49,6 @@
 #define UDATA_ADDRESS	UDATA_ADDRESS_ARCH
 
+#define AS_KERNEL	(1<<0)		/**< Kernel address space. */
+
 enum as_area_type {
 	AS_AREA_TEXT = 1, AS_AREA_DATA, AS_AREA_STACK 
@@ -62,5 +64,5 @@
 	link_t link;
 	as_area_type_t type;
-	size_t size;		/**< Size of this area. */
+	size_t size;		/**< Size of this area in multiples of PAGE_SIZE. */
 	__address base;		/**< Base address of this area. */
 	index_t *mapping;	/**< Map of physical frame numbers mapped to virtual page numbers in this area. */
@@ -75,4 +77,7 @@
  */
 struct as {
+	/** Protected by asidlock. Must be acquired before as-> lock. */
+	link_t as_with_asid_link;
+
 	SPINLOCK_DECLARE(lock);
 	link_t as_area_head;
@@ -81,5 +86,5 @@
 };
 
-extern as_t * as_create(pte_t *ptl0);
+extern as_t * as_create(pte_t *ptl0, int flags);
 extern as_area_t *as_area_create(as_t *as, as_area_type_t type, size_t size, __address base);
 extern void as_area_set_mapping(as_area_t *a, index_t vpn, index_t pfn);
@@ -87,12 +92,5 @@
 extern void as_install(as_t *m);
 
-/*
- * Each architecture should implement this function.
- * Its main purpose is to do TLB purges according
- * to architecture's requirements. Note that
- * some architectures invalidate their TLB automatically
- * on hardware address space switch (e.g. ia32 and
- * amd64).
- */
+/* Interface to be implemented by architectures. */
 #ifndef as_install_arch
 extern void as_install_arch(as_t *as);
Index: generic/include/mm/asid.h
===================================================================
--- generic/include/mm/asid.h	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/include/mm/asid.h	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -27,8 +27,34 @@
  */
 
+/*
+ * This is generic interface for managing
+ * Address Space IDentifiers (ASIDs).
+ */
+
 #ifndef __ASID_H__
 #define __ASID_H__
 
+#include <arch/mm/asid.h>
+#include <typedefs.h>
+
 #define ASID_KERNEL	0
+#define ASID_INVALID	1
+#define ASID_START	2
+#define ASID_MAX	ASID_MAX_ARCH
+
+#define ASIDS_ALLOCABLE	((ASID_MAX+1)-ASID_START)
+
+extern spinlock_t asidlock;
+extern link_t as_with_asid_head;
+
+extern asid_t asid_get(void);
+extern void asid_put(asid_t asid);
+
+#ifndef asid_install
+extern void asid_install(as_t *as);
+#endif /* !def asid_install */
+
+#define asid_find_free()	ASID_START
+#define asid_put_arch(x)
 
 #endif
Index: generic/include/mm/tlb.h
===================================================================
--- generic/include/mm/tlb.h	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/include/mm/tlb.h	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -32,16 +32,5 @@
 #include <arch/mm/asid.h>
 #include <arch/types.h>
-
-extern void tlb_init(void);
-
-#ifdef CONFIG_SMP
-extern void tlb_shootdown_start(void);
-extern void tlb_shootdown_finalize(void);
-extern void tlb_shootdown_ipi_recv(void);
-#else
-#  define tlb_shootdown_start()	;
-#  define tlb_shootdown_finalize()	;
-#  define tlb_shootdown_ipi_recv() ;
-#endif /* CONFIG_SMP */
+#include <typedefs.h>
 
 /** Type of TLB shootdown message. */
@@ -50,5 +39,5 @@
 	TLB_INVL_ALL,			/**< Invalidate all entries in TLB. */
 	TLB_INVL_ASID,			/**< Invalidate all entries belonging to one address space. */
-	TLB_INVL_PAGE			/**< Invalidate one entry for specified page. */
+	TLB_INVL_PAGES			/**< Invalidate specified page range belonging to one address space. */
 };
 
@@ -64,13 +53,24 @@
 typedef struct tlb_shootdown_msg tlb_shootdown_msg_t;
 
+extern void tlb_init(void);
+
+#ifdef CONFIG_SMP
+extern void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt);
+extern void tlb_shootdown_finalize(void);
+extern void tlb_shootdown_ipi_recv(void);
+#else
+#  define tlb_shootdown_start(w, x, y, z)
+#  define tlb_shootdown_finalize()
+#  define tlb_shootdown_ipi_recv()
+#endif /* CONFIG_SMP */
+
+
 /* Export TLB interface that each architecture must implement. */
 extern void tlb_arch_init(void);
 extern void tlb_print(void);
-extern void tlb_invalidate(asid_t asid);
 extern void tlb_shootdown_ipi_send(void);
 
 extern void tlb_invalidate_all(void);
 extern void tlb_invalidate_asid(asid_t asid);
-extern void tlb_invalidate_page(asid_t asid, __address page);
-
+extern void tlb_invalidate_pages(asid_t asid, __address page, count_t cnt);
 #endif
Index: generic/src/main/kinit.c
===================================================================
--- generic/src/main/kinit.c	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/src/main/kinit.c	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -147,5 +147,5 @@
 			panic("config.init_addr is not frame aligned");
 		
-		as = as_create(NULL);
+		as = as_create(NULL, 0);
 		if (!as)
 			panic("as_create\n");
Index: generic/src/main/main.c
===================================================================
--- generic/src/main/main.c	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/src/main/main.c	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -186,5 +186,5 @@
 	 * Create kernel address space.
 	 */
-	as = as_create(GET_PTL0_ADDRESS());
+	as = as_create(GET_PTL0_ADDRESS(), AS_KERNEL);
 	if (!as)
 		panic("can't create kernel address space\n");
Index: generic/src/mm/as.c
===================================================================
--- generic/src/mm/as.c	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/src/mm/as.c	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -34,4 +34,5 @@
 
 #include <mm/as.h>
+#include <mm/asid.h>
 #include <mm/page.h>
 #include <mm/frame.h>
@@ -40,4 +41,5 @@
 #include <arch/mm/page.h>
 #include <genarch/mm/page_pt.h>
+#include <mm/asid.h>
 #include <arch/mm/asid.h>
 #include <arch/mm/as.h>
@@ -71,5 +73,5 @@
  * 	  (Virtual Address Translation) mechanisms.
  */
-as_t *as_create(pte_t *ptl0)
+as_t *as_create(pte_t *ptl0, int flags)
 {
 	as_t *as;
@@ -77,8 +79,12 @@
 	as = (as_t *) malloc(sizeof(as_t));
 	if (as) {
+		list_initialize(&as->as_with_asid_link);
 		spinlock_initialize(&as->lock, "as_lock");
 		list_initialize(&as->as_area_head);
 
-		as->asid = asid_get();
+		if (flags & AS_KERNEL)
+			as->asid = ASID_KERNEL;
+		else
+			as->asid = ASID_INVALID;
 
 		as->ptl0 = ptl0;
@@ -290,4 +296,6 @@
 	ipl_t ipl;
 	
+	asid_install(as);
+	
 	ipl = interrupts_disable();
 	spinlock_lock(&as->lock);
@@ -299,5 +307,5 @@
 	/*
 	 * Perform architecture-specific steps.
-	 * (e.g. invalidate TLB, install ASID etc.)
+	 * (e.g. write ASID to hardware register etc.)
 	 */
 	as_install_arch(as);
Index: generic/src/mm/tlb.c
===================================================================
--- generic/src/mm/tlb.c	(revision 5d2ab231a2e6c513f459e864da1c59750cce6db7)
+++ generic/src/mm/tlb.c	(revision 4512d7e1af168899c6317084648322e9f8381026)
@@ -47,5 +47,5 @@
 #ifdef CONFIG_SMP
 /* must be called with interrupts disabled */
-void tlb_shootdown_start(void)
+void tlb_shootdown_start(tlb_invalidate_type_t type, asid_t asid, __address page, count_t cnt)
 {
 	int i;
@@ -53,6 +53,24 @@
 	CPU->tlb_active = 0;
 	spinlock_lock(&tlblock);
+	
+	/*
+	 * TODO: assemble shootdown message.
+	 */
 	tlb_shootdown_ipi_send();
-	tlb_invalidate(0); /* TODO: use valid ASID */
+
+	switch (type) {
+	    case TLB_INVL_ALL:
+		tlb_invalidate_all();
+		break;
+	    case TLB_INVL_ASID:
+		tlb_invalidate_asid(asid);
+		break;
+	    case TLB_INVL_PAGES:
+		tlb_invalidate_pages(asid, page, cnt);
+		break;
+	    default:
+		panic("unknown tlb_invalidate_type_t value: %d\n", type);
+		break;
+	}
 	
 busy_wait:	
@@ -78,5 +96,5 @@
 	spinlock_lock(&tlblock);
 	spinlock_unlock(&tlblock);
-	tlb_invalidate(0);	/* TODO: use valid ASID */
+	tlb_invalidate_all();	/* TODO: use valid ASID */
 	CPU->tlb_active = 1;
 }
