Index: Makefile.config
===================================================================
--- Makefile.config	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ Makefile.config	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -41,2 +41,3 @@
 #TEST_DIR=print/print1/
 #TEST_DIR=thread/thread1/
+#TEST_DIR=mm/mapping1/
Index: arch/ia32/src/mm/tlb.c
===================================================================
--- arch/ia32/src/mm/tlb.c	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ arch/ia32/src/mm/tlb.c	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -28,7 +28,14 @@
 
 #include <mm/tlb.h>
+#include <arch/mm/asid.h>
 #include <arch/asm.h>
 
-void tlb_invalidate(int asid)
+/** Invalidate all TLB entries
+ *
+ * Invalidate all TLB entries.
+ *
+ * @param asid This argument is ignored.
+ */
+void tlb_invalidate(asid_t asid)
 {
 	write_cr3(read_cr3());
Index: arch/mips32/include/mm/asid.h
===================================================================
--- arch/mips32/include/mm/asid.h	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ arch/mips32/include/mm/asid.h	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -31,4 +31,9 @@
 
 #include <arch/types.h>
+#include <typedefs.h>
+
+#define ASIDS		256
+#define ASID_INVALID	0
+#define ASID_START	1
 
 typedef __u8 asid_t;
@@ -36,4 +41,5 @@
 extern asid_t asid_get(void);
 extern void asid_put(asid_t asid);
+extern bool asid_has_conflicts(asid_t asid);
 
 #endif
Index: arch/mips32/include/mm/tlb.h
===================================================================
--- arch/mips32/include/mm/tlb.h	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ arch/mips32/include/mm/tlb.h	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -42,12 +42,15 @@
 #define PAGE_CACHEABLE_EXC_WRITE	5
 
-struct entry_lo {
-	unsigned g : 1; 	/* global bit */
-	unsigned v : 1; 	/* valid bit */
-	unsigned d : 1; 	/* dirty/write-protect bit */
-	unsigned c : 3; 	/* cache coherency attribute */
-	unsigned pfn : 24;	/* frame number */
-	unsigned zero: 2;	/* zero */
-} __attribute__ ((packed));
+union entry_lo {
+	struct {
+		unsigned g : 1; 	/* global bit */
+		unsigned v : 1; 	/* valid bit */
+		unsigned d : 1; 	/* dirty/write-protect bit */
+		unsigned c : 3; 	/* cache coherency attribute */
+		unsigned pfn : 24;	/* frame number */
+		unsigned zero: 2;	/* zero */
+	} __attribute__ ((packed));
+	__u32 value;
+};
 
 struct pte {
@@ -61,21 +64,35 @@
 } __attribute__ ((packed));
 
-struct entry_hi {
-	unsigned asid : 8;
-	unsigned : 5;
-	unsigned vpn2 : 19;
-} __attribute__ ((packed));
+union entry_hi {
+	struct {
+		unsigned asid : 8;
+		unsigned : 5;
+		unsigned vpn2 : 19;
+	} __attribute__ ((packed));
+	__u32 value;
+};
 
-struct page_mask {
-	unsigned : 13;
-	unsigned mask : 12;
-	unsigned : 7;
-} __attribute__ ((packed));
+union page_mask {
+	struct {
+		unsigned : 13;
+		unsigned mask : 12;
+		unsigned : 7;
+	} __attribute__ ((packed));
+	__u32 value;
+};
 
-struct index {
-	unsigned index : 4;
-	unsigned : 27;
-	unsigned p : 1;
-} __attribute__ ((packed));
+union index {
+	struct {
+		unsigned index : 4;
+		unsigned : 27;
+		unsigned p : 1;
+	} __attribute__ ((packed));
+	__u32 value;
+};
+
+typedef union entry_lo entry_lo_t;
+typedef union entry_hi entry_hi_t;
+typedef union page_mask page_mask_t;
+typedef union index tlb_index_t;
 
 /** Probe TLB for Matching Entry
Index: arch/mips32/src/mm/asid.c
===================================================================
--- arch/mips32/src/mm/asid.c	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ arch/mips32/src/mm/asid.c	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -1,4 +1,5 @@
 /*
  * Copyright (C) 2005 Martin Decky
+ * Copyright (C) 2005 Jakub Jermar
  * All rights reserved.
  *
@@ -31,6 +32,5 @@
 #include <arch.h>
 #include <debug.h>
-
-#define ASIDS	256
+#include <typedefs.h>
 
 static spinlock_t asid_usage_lock;
@@ -54,5 +54,5 @@
 	spinlock_lock(&asid_usage_lock);
 	
-	for (i=0, j = 0; (i<ASIDS); i++) {
+	for (i = ASID_START, j = ASID_START; i < ASIDS; i++) {
 		if (asid_usage[i] < min) {
 			j = i;
@@ -63,5 +63,5 @@
 	}
 
-	asid_usage[i]++;
+	asid_usage[j]++;
 
 	spinlock_unlock(&asid_usage_lock);
@@ -84,4 +84,6 @@
 	spinlock_lock(&asid_usage_lock);
 
+	ASSERT(asid != ASID_INVALID);
+	
 	ASSERT(asid_usage[asid] > 0);
 	asid_usage[asid]--;
@@ -90,2 +92,29 @@
 	cpu_priority_restore(pri);
 }
+
+/** Find out whether ASID is used by more address spaces
+ *
+ * Find out whether ASID is used by more address spaces.
+ *
+ * @param asid ASID in question.
+ *
+ * @return True if 'asid' is used by more address spaces, false otherwise.
+ */
+bool asid_has_conflicts(asid_t asid)
+{
+	bool has_conflicts = false;
+	pri_t pri;
+
+	ASSERT(asid != ASID_INVALID);
+
+	pri = cpu_priority_high();
+	spinlock_lock(&asid_usage_lock);
+
+	if (asid_usage[asid] > 1)
+		has_conflicts = true;
+
+	spinlock_unlock(&asid_usage_lock);
+	cpu_priority_restore(pri);
+
+	return has_conflicts;
+}
Index: arch/mips32/src/mm/tlb.c
===================================================================
--- arch/mips32/src/mm/tlb.c	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ arch/mips32/src/mm/tlb.c	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -38,4 +38,5 @@
 #include <synch/spinlock.h>
 #include <print.h>
+#include <debug.h>
 
 static void tlb_refill_fail(struct exception_regdump *pstate);
@@ -44,5 +45,5 @@
 
 static pte_t *find_mapping_and_check(__address badvaddr);
-static void prepare_entry_lo(struct entry_lo *lo, bool g, bool v, bool d, int c, __address pfn);
+static void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn);
 
 /** Initialize TLB
@@ -83,5 +84,5 @@
 void tlb_refill(struct exception_regdump *pstate)
 {
-	struct entry_lo lo;
+	entry_lo_t lo;
 	__address badvaddr;
 	pte_t *pte;
@@ -105,10 +106,10 @@
 	 */
 	if ((badvaddr/PAGE_SIZE) % 2 == 0) {
-		cp0_entry_lo0_write(*((__u32 *) &lo));
+		cp0_entry_lo0_write(lo.value);
 		cp0_entry_lo1_write(0);
 	}
 	else {
 		cp0_entry_lo0_write(0);
-		cp0_entry_lo1_write(*((__u32 *) &lo));
+		cp0_entry_lo1_write(lo.value);
 	}
 	tlbwr();
@@ -130,7 +131,7 @@
 void tlb_invalid(struct exception_regdump *pstate)
 {
-	struct index index;
+	tlb_index_t index;
 	__address badvaddr;
-	struct entry_lo lo;
+	entry_lo_t lo;
 	pte_t *pte;
 
@@ -141,5 +142,5 @@
 	 */
 	tlbp();
-	*((__u32 *) &index) = cp0_index_read();
+	index.value = cp0_index_read();
 	
 	spinlock_lock(&VM->lock);	
@@ -148,6 +149,8 @@
 	 * Fail if the entry is not in TLB.
 	 */
-	if (index.p)
-		goto fail;
+	if (index.p) {
+		printf("TLB entry not found.\n");
+		goto fail;
+	}
 
 	pte = find_mapping_and_check(badvaddr);
@@ -171,7 +174,7 @@
 	 */
 	if ((badvaddr/PAGE_SIZE) % 2 == 0)
-		cp0_entry_lo0_write(*((__u32 *) &lo));
+		cp0_entry_lo0_write(lo.value);
 	else
-		cp0_entry_lo1_write(*((__u32 *) &lo));
+		cp0_entry_lo1_write(lo.value);
 	tlbwi();
 
@@ -190,10 +193,9 @@
  * @param pstate Interrupted register context.
  */
-
 void tlb_modified(struct exception_regdump *pstate)
 {
-	struct index index;
+	tlb_index_t index;
 	__address badvaddr;
-	struct entry_lo lo;
+	entry_lo_t lo;
 	pte_t *pte;
 
@@ -204,5 +206,5 @@
 	 */
 	tlbp();
-	*((__u32 *) &index) = cp0_index_read();
+	index.value = cp0_index_read();
 	
 	spinlock_lock(&VM->lock);	
@@ -211,6 +213,8 @@
 	 * Fail if the entry is not in TLB.
 	 */
-	if (index.p)
-		goto fail;
+	if (index.p) {
+		printf("TLB entry not found.\n");
+		goto fail;
+	}
 
 	pte = find_mapping_and_check(badvaddr);
@@ -241,7 +245,7 @@
 	 */
 	if ((badvaddr/PAGE_SIZE) % 2 == 0)
-		cp0_entry_lo0_write(*((__u32 *) &lo));
+		cp0_entry_lo0_write(lo.value);
 	else
-		cp0_entry_lo1_write(*((__u32 *) &lo));
+		cp0_entry_lo1_write(lo.value);
 	tlbwi();
 
@@ -289,12 +293,33 @@
 }
 
-
-void tlb_invalidate(int asid)
-{
+/** Invalidate TLB entries with specified ASID
+ *
+ * Invalidate TLB entries with specified ASID.
+ *
+ * @param asid ASID.
+ */
+void tlb_invalidate(asid_t asid)
+{
+	entry_hi_t hi;
 	pri_t pri;
-	
+	int i;	
+	
+	ASSERT(asid != ASID_INVALID);
+
 	pri = cpu_priority_high();
 	
-	// TODO
+	for (i = 0; i < TLB_SIZE; i++) {
+		cp0_index_write(i);
+		tlbr();
+		
+		hi.value = cp0_entry_hi_read();
+		if (hi.asid == asid) {
+			cp0_pagemask_write(TLB_PAGE_MASK_16K);
+			cp0_entry_hi_write(0);
+			cp0_entry_lo0_write(0);
+			cp0_entry_lo1_write(0);
+			tlbwi();
+		}
+	}
 	
 	cpu_priority_restore(pri);
@@ -312,14 +337,16 @@
 pte_t *find_mapping_and_check(__address badvaddr)
 {
-	struct entry_hi hi;
+	entry_hi_t hi;
 	pte_t *pte;
 
-	*((__u32 *) &hi) = cp0_entry_hi_read();
+	hi.value = cp0_entry_hi_read();
 
 	/*
 	 * Handler cannot succeed if the ASIDs don't match.
 	 */
-	if (hi.asid != VM->asid)
+	if (hi.asid != VM->asid) {
+		printf("EntryHi.asid=%d, VM->asid=%d\n", hi.asid, VM->asid);
 		return NULL;
+	}
 	
 	/*
@@ -327,17 +354,21 @@
 	 */
 	pte = find_mapping(badvaddr, 0);
-	if (!pte)
+	if (!pte) {
+		printf("No such mapping.\n");
 		return NULL;
+	}
 
 	/*
 	 * Handler cannot succeed if the mapping is marked as invalid.
 	 */
-	if (!pte->v)
+	if (!pte->v) {
+		printf("Invalid mapping.\n");
 		return NULL;
+	}
 
 	return pte;
 }
 
-void prepare_entry_lo(struct entry_lo *lo, bool g, bool v, bool d, int c, __address pfn)
+void prepare_entry_lo(entry_lo_t *lo, bool g, bool v, bool d, int c, __address pfn)
 {
 	lo->g = g;
Index: arch/mips32/src/mm/vm.c
===================================================================
--- arch/mips32/src/mm/vm.c	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ arch/mips32/src/mm/vm.c	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -32,5 +32,4 @@
 #include <arch/cp0.h>
 #include <arch.h>
-#include <print.h>
 
 /** Install ASID of the current VM
@@ -42,8 +41,8 @@
 void vm_install_arch(vm_t *vm)
 {
-	struct entry_hi hi;
+	entry_hi_t hi;
 	pri_t pri;
 	
-	*((__u32 *) &hi) = cp0_entry_hi_read();
+	hi.value = cp0_entry_hi_read();
 
 	pri = cpu_priority_high();
Index: include/mm/tlb.h
===================================================================
--- include/mm/tlb.h	(revision bca1b4709513d451ac751917139b9d420745f27f)
+++ include/mm/tlb.h	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -30,4 +30,6 @@
 #define __TLB_H__
 
+#include <arch/mm/asid.h>
+
 extern void tlb_init(void);
 
@@ -44,5 +46,5 @@
 /* Export TLB interface that each architecture must implement. */
 extern void tlb_init_arch(void);
-extern void tlb_invalidate(int asid);
+extern void tlb_invalidate(asid_t asid);
 extern void tlb_shootdown_ipi_send(void);
 
Index: test/mm/mapping1/test.c
===================================================================
--- test/mm/mapping1/test.c	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
+++ test/mm/mapping1/test.c	(revision cc205f1f38b5517610765fe3a34396d52e75eca2)
@@ -0,0 +1,79 @@
+/*
+ * Copyright (C) 2005 Jakub Jermar
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * - Redistributions of source code must retain the above copyright
+ *   notice, this list of conditions and the following disclaimer.
+ * - Redistributions in binary form must reproduce the above copyright
+ *   notice, this list of conditions and the following disclaimer in the
+ *   documentation and/or other materials provided with the distribution.
+ * - The name of the author may not be used to endorse or promote products
+ *   derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <print.h>
+#include <test.h>
+#include <mm/page.h>
+#include <mm/frame.h>
+#include <arch/mm/page.h>
+#include <arch/types.h>
+#include <debug.h>
+
+#define PAGE0	0x10000000
+#define PAGE1	(PAGE0+PAGE_SIZE)
+
+#define VALUE0	0x01234567
+#define VALUE1	0x89abcdef
+
+void test(void)
+{
+	__address frame0, frame1;
+	__u32 v0, v1;
+
+	printf("Memory management test mapping #1\n");
+
+	frame0 = frame_alloc(FRAME_KA);
+	frame1 = frame_alloc(FRAME_KA);	
+	
+	*((__u32 *) frame0) = VALUE0;
+	*((__u32 *) frame1) = VALUE1;
+	
+	printf("Mapping %X to %X.\n", PAGE0, KA2PA(frame0));
+	map_page_to_frame(PAGE0, KA2PA(frame0), PAGE_PRESENT, 0);
+	printf("Mapping %X to %X.\n", PAGE1, KA2PA(frame1));	
+	map_page_to_frame(PAGE1, KA2PA(frame1), PAGE_PRESENT, 0);
+	
+	printf("Value at %X is %X.\n", PAGE0, v0 = *((__u32 *) PAGE0));
+	printf("Value at %X is %X.\n", PAGE1, v1 = *((__u32 *) PAGE1));
+	
+	ASSERT(v0 == VALUE0);
+	ASSERT(v1 == VALUE1);
+
+	printf("Writing 0 to %X.\n", PAGE0);
+	*((__u32 *) PAGE0) = 0;
+	printf("Writing 0 to %X.\n", PAGE1);
+	*((__u32 *) PAGE1) = 0;	
+	
+	printf("Value at %X is %X.\n", PAGE0, v0 = *((__u32 *) PAGE0));	
+	printf("Value at %X is %X.\n", PAGE1, v1 = *((__u32 *) PAGE1));
+
+	ASSERT(v0 == 0);
+	ASSERT(v1 == 0);
+	
+	printf("Test passed.\n");
+	
+}
