Index: kernel/arch/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision b4655da89eb65d1571b8afdfdbbb34449add2ef7)
+++ kernel/arch/sparc64/Makefile.inc	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -71,5 +71,5 @@
 	arch/$(KARCH)/src/fpu_context.c \
 	arch/$(KARCH)/src/dummy.s \
-	arch/$(KARCH)/src/mm/as.c \
+	arch/$(KARCH)/src/mm/$(USARCH)/as.c \
 	arch/$(KARCH)/src/mm/cache.S \
 	arch/$(KARCH)/src/mm/$(USARCH)/frame.c \
@@ -81,5 +81,5 @@
 	arch/$(KARCH)/src/proc/thread.c \
 	arch/$(KARCH)/src/trap/mmu.S \
-	arch/$(KARCH)/src/trap/trap_table.S \
+	arch/$(KARCH)/src/trap/$(USARCH)/trap_table.S \
 	arch/$(KARCH)/src/trap/trap.c \
 	arch/$(KARCH)/src/trap/exception.c \
Index: kernel/arch/sparc64/include/mm/sun4u/tte.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4u/tte.h	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/include/mm/sun4u/tte.h	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,104 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup sparc64mm	
+ * @{
+ */
+/** @file
+ */
+
+#ifndef KERN_sparc64_sun4u_TTE_H_
+#define KERN_sparc64_sun4u_TTE_H_
+
+#define TTE_G		(1 << 0)
+#define TTE_W		(1 << 1)
+#define TTE_P		(1 << 2)
+#define TTE_E		(1 << 3)
+#define TTE_CV		(1 << 4)
+#define TTE_CP		(1 << 5)
+#define TTE_L		(1 << 6)
+
+#define TTE_V_SHIFT	63
+#define TTE_SIZE_SHIFT	61
+
+#ifndef __ASM__
+
+#include <arch/types.h>
+
+/* TTE tag's VA_tag field contains bits <63:VA_TAG_PAGE_SHIFT> of the VA */
+#define VA_TAG_PAGE_SHIFT	22
+
+/** Translation Table Entry - Tag. */
+union tte_tag {
+	uint64_t value;
+	struct {
+		unsigned g : 1;		/**< Global. */
+		unsigned : 2;		/**< Reserved. */
+		unsigned context : 13;	/**< Context identifier. */
+		unsigned : 6;		/**< Reserved. */
+		uint64_t va_tag : 42;	/**< Virtual Address Tag, bits 63:22. */
+	} __attribute__ ((packed));
+};
+
+typedef union tte_tag tte_tag_t;
+
+/** Translation Table Entry - Data. */
+union tte_data {
+	uint64_t value;
+	struct {
+		unsigned v : 1;		/**< Valid. */
+		unsigned size : 2;	/**< Page size of this entry. */
+		unsigned nfo : 1;	/**< No-Fault-Only. */
+		unsigned ie : 1;	/**< Invert Endianness. */
+		unsigned soft2 : 9;	/**< Software defined field. */
+#if defined (US)
+		unsigned diag : 9;	/**< Diagnostic data. */
+		unsigned pfn : 28;	/**< Physical Address bits, bits 40:13. */
+#elif defined (US3)
+		unsigned : 7;		/**< Reserved. */
+		unsigned pfn : 30;	/**< Physical Address bits, bits 42:13 */
+#endif
+		unsigned soft : 6;	/**< Software defined field. */
+		unsigned l : 1;		/**< Lock. */
+		unsigned cp : 1;	/**< Cacheable in physically indexed cache. */
+		unsigned cv : 1;	/**< Cacheable in virtually indexed cache. */
+		unsigned e : 1;		/**< Side-effect. */
+		unsigned p : 1;		/**< Privileged. */
+		unsigned w : 1;		/**< Writable. */
+		unsigned g : 1;		/**< Global. */
+	} __attribute__ ((packed));
+};
+
+typedef union tte_data tte_data_t;
+
+#endif /* !def __ASM__ */
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/cpu/sun4u/cpu.c
===================================================================
--- kernel/arch/sparc64/src/cpu/sun4u/cpu.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/cpu/sun4u/cpu.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,189 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup sparc64
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/cpu_family.h>
+#include <cpu.h>
+#include <arch.h>
+#include <genarch/ofw/ofw_tree.h>
+#include <arch/drivers/tick.h>
+#include <print.h>
+#include <arch/cpu_node.h>
+
+/**
+ * Finds out the clock frequency of the current CPU.
+ *
+ * @param node	node representing the current CPU in the OFW tree
+ * @return 	clock frequency if "node" is the current CPU and no error
+ *		occurs,	-1 if "node" is not the current CPU or on error
+ */
+static int find_cpu_frequency(ofw_tree_node_t *node)
+{
+	ofw_tree_property_t *prop;
+	uint32_t mid;
+
+	/* 'upa-portid' for US, 'portid' for US-III, 'cpuid' for US-IV */
+	prop = ofw_tree_getprop(node, "upa-portid");
+	if ((!prop) || (!prop->value))
+		prop = ofw_tree_getprop(node, "portid");
+	if ((!prop) || (!prop->value))
+		prop = ofw_tree_getprop(node, "cpuid");
+	
+	if (prop && prop->value) {
+		mid = *((uint32_t *) prop->value);
+		if (mid == CPU->arch.mid) {
+			prop = ofw_tree_getprop(node, "clock-frequency");
+			if (prop && prop->value) {
+				return *((uint32_t *) prop->value);
+			}
+		}
+	}
+	
+	return -1;
+}
+
+/** Perform sparc64 specific initialization of the processor structure for the
+ * current processor.
+ */
+void cpu_arch_init(void)
+{
+	ofw_tree_node_t *node;
+	uint32_t clock_frequency = 0;
+	
+	CPU->arch.mid = read_mid();
+	
+	/*
+	 * Detect processor frequency.
+	 */
+	if (is_us() || is_us_iii()) { 
+		node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
+		while (node) {
+			int f = find_cpu_frequency(node);
+			if (f != -1) 
+				clock_frequency = (uint32_t) f;
+			node = ofw_tree_find_peer_by_device_type(node, "cpu");
+		}
+	} else if (is_us_iv()) {
+		node = ofw_tree_find_child(cpus_parent(), "cmp");
+		while (node) {
+			int f;
+			f = find_cpu_frequency(
+				ofw_tree_find_child(node, "cpu@0"));
+			if (f != -1) 
+				clock_frequency = (uint32_t) f;
+			f = find_cpu_frequency(
+				ofw_tree_find_child(node, "cpu@1"));
+			if (f != -1) 
+				clock_frequency = (uint32_t) f;
+			node = ofw_tree_find_peer_by_name(node, "cmp");
+		}
+	}
+		
+	CPU->arch.clock_frequency = clock_frequency;
+	tick_init();
+}
+
+/** Read version information from the current processor. */
+void cpu_identify(void)
+{
+	CPU->arch.ver.value = ver_read();
+}
+
+/** Print version information for a processor.
+ *
+ * This function is called by the bootstrap processor.
+ *
+ * @param m Processor structure of the CPU for which version information is to
+ * 	be printed.
+ */
+void cpu_print_report(cpu_t *m)
+{
+	char *manuf, *impl;
+
+	switch (m->arch.ver.manuf) {
+	case MANUF_FUJITSU:
+		manuf = "Fujitsu";
+		break;
+	case MANUF_ULTRASPARC:
+		manuf = "UltraSPARC";
+		break;
+	case MANUF_SUN:
+	    	manuf = "Sun";
+		break;
+	default:
+		manuf = "Unknown";
+		break;
+	}
+	
+	switch (CPU->arch.ver.impl) {
+	case IMPL_ULTRASPARCI:
+		impl = "UltraSPARC I";
+		break;
+	case IMPL_ULTRASPARCII:
+		impl = "UltraSPARC II";
+		break;
+	case IMPL_ULTRASPARCII_I:
+		impl = "UltraSPARC IIi";
+		break;
+	case IMPL_ULTRASPARCII_E:
+		impl = "UltraSPARC IIe";
+		break;
+	case IMPL_ULTRASPARCIII:
+		impl = "UltraSPARC III";
+		break;
+	case IMPL_ULTRASPARCIII_PLUS:
+		impl = "UltraSPARC III+";
+		break;
+	case IMPL_ULTRASPARCIII_I:
+		impl = "UltraSPARC IIIi";
+		break;
+	case IMPL_ULTRASPARCIV:
+		impl = "UltraSPARC IV";
+		break;
+	case IMPL_ULTRASPARCIV_PLUS:
+		impl = "UltraSPARC IV+";
+		break;
+	case IMPL_SPARC64V:
+		impl = "SPARC 64V";
+		break;
+	default:
+		impl = "Unknown";
+		break;
+	}
+
+	printf("cpu%d: manuf=%s, impl=%s, mask=%d (%d MHz)\n", m->id, manuf,
+		impl, m->arch.ver.mask, m->arch.clock_frequency / 1000000);
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/cpu/sun4v/cpu.c
===================================================================
--- kernel/arch/sparc64/src/cpu/sun4v/cpu.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/cpu/sun4v/cpu.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,102 @@
+/*
+ * 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.
+ */
+
+/** @addtogroup sparc64
+ * @{
+ */
+/** @file
+ */
+
+#include <cpu.h>
+#include <arch.h>
+#include <genarch/ofw/ofw_tree.h>
+#include <arch/drivers/tick.h>
+#include <print.h>
+#include <arch/sun4v/md.h>
+#include <arch/sun4v/hypercall.h>
+
+//#include <arch/trap/sun4v/interrupt.h>
+
+/** Perform sparc64 specific initialization of the processor structure for the
+ * current processor.
+ */
+void cpu_arch_init(void)
+{
+	uint64_t myid;
+	__hypercall_fast_ret1(0, 0, 0, 0, 0, CPU_MYID, &myid);
+
+	//MH
+	//CPU->arch.id = myid;
+
+	md_node_t node = md_get_root();
+
+	/* walk through MD, find the current CPU node & its clock-frequency */
+	while (true) {
+		if (!md_next_node(&node, "cpu")) {
+			panic("Could not determine CPU frequency.");
+		}
+		uint64_t id = 0;
+		md_get_integer_property(node, "id", &id);
+
+		if (id == myid) {
+			uint64_t clock_frequency = 0;
+			md_get_integer_property(node, "clock-frequency",
+				&clock_frequency);
+			CPU->arch.clock_frequency = clock_frequency;
+			break;
+		}
+	}
+		
+	tick_init();
+    	//MH - uncomment later
+	//sun4v_ipi_init();
+}
+
+/**
+ * Implemented as an empty function as accessing the VER register is
+ * a hyperprivileged operation on sun4v.
+ */
+void cpu_identify(void)
+{
+}
+
+/** Print version information for a processor.
+ *
+ * This function is called by the bootstrap processor.
+ *
+ * @param m Processor structure of the CPU for which version information is to
+ * 	be printed.
+ */
+void cpu_print_report(cpu_t *m)
+{
+	printf("cpu%d: Niagara (%d MHz)\n", m->id,
+		m->arch.clock_frequency / 1000000);
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/mm/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/as.c	(revision b4655da89eb65d1571b8afdfdbbb34449add2ef7)
+++ 	(revision )
@@ -1,224 +1,0 @@
-/*
- * Copyright (c) 2006 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.
- */
-
-/** @addtogroup sparc64mm
- * @{
- */
-/** @file
- */
-
-#include <arch/mm/as.h>
-#include <arch/mm/tlb.h>
-#include <genarch/mm/page_ht.h>
-#include <genarch/mm/asid_fifo.h>
-#include <debug.h>
-#include <config.h>
-
-#ifdef CONFIG_TSB
-#include <arch/mm/tsb.h>
-#include <arch/memstr.h>
-#include <arch/asm.h>
-#include <mm/frame.h>
-#include <bitops.h>
-#include <macros.h>
-#endif /* CONFIG_TSB */
-
-/** Architecture dependent address space init. */
-void as_arch_init(void)
-{
-	if (config.cpu_active == 1) {
-		as_operations = &as_ht_operations;
-		asid_fifo_init();
-	}
-}
-
-int as_constructor_arch(as_t *as, int flags)
-{
-#ifdef CONFIG_TSB
-	/*
-	 * The order must be calculated with respect to the emulated
-	 * 16K page size.
-	 */
-	int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
-	    sizeof(tsb_entry_t)) >> FRAME_WIDTH);
-
-	uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
-
-	if (!tsb)
-		return -1;
-
-	as->arch.itsb = (tsb_entry_t *) tsb;
-	as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
-	    sizeof(tsb_entry_t));
-
-	memsetb(as->arch.itsb,
-	    (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
-#endif
-	return 0;
-}
-
-int as_destructor_arch(as_t *as)
-{
-#ifdef CONFIG_TSB
-	/*
-	 * The count must be calculated with respect to the emualted 16K page
-	 * size.
-	 */
-	size_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
-	    sizeof(tsb_entry_t)) >> FRAME_WIDTH;
-	frame_free(KA2PA((uintptr_t) as->arch.itsb));
-	return cnt;
-#else
-	return 0;
-#endif
-}
-
-int as_create_arch(as_t *as, int flags)
-{
-#ifdef CONFIG_TSB
-	tsb_invalidate(as, 0, (size_t) -1);
-#endif
-	return 0;
-}
-
-/** Perform sparc64-specific tasks when an address space becomes active on the
- * processor.
- *
- * Install ASID and map TSBs.
- *
- * @param as Address space.
- */
-void as_install_arch(as_t *as)
-{
-	tlb_context_reg_t ctx;
-	
-	/*
-	 * Note that we don't and may not lock the address space. That's ok
-	 * since we only read members that are currently read-only.
-	 *
-	 * Moreover, the as->asid is protected by asidlock, which is being held.
-	 */
-	
-	/*
-	 * Write ASID to secondary context register. The primary context
-	 * register has to be set from TL>0 so it will be filled from the
-	 * secondary context register from the TL=1 code just before switch to
-	 * userspace.
-	 */
-	ctx.v = 0;
-	ctx.context = as->asid;
-	mmu_secondary_context_write(ctx.v);
-
-#ifdef CONFIG_TSB	
-	uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
-
-	ASSERT(as->arch.itsb && as->arch.dtsb);
-
-	uintptr_t tsb = (uintptr_t) as->arch.itsb;
-		
-	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
-		/*
-		 * TSBs were allocated from memory not covered
-		 * by the locked 4M kernel DTLB entry. We need
-		 * to map both TSBs explicitly.
-		 */
-		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
-		dtlb_insert_mapping(tsb, KA2PA(tsb), PAGESIZE_64K, true, true);
-	}
-		
-	/*
-	 * Setup TSB Base registers.
-	 */
-	tsb_base_reg_t tsb_base;
-		
-	tsb_base.value = 0;
-	tsb_base.size = TSB_SIZE;
-	tsb_base.split = 0;
-
-	tsb_base.base = ((uintptr_t) as->arch.itsb) >> MMU_PAGE_WIDTH;
-	itsb_base_write(tsb_base.value);
-	tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
-	dtsb_base_write(tsb_base.value);
-	
-#if defined (US3)
-	/*
-	 * Clear the extension registers.
-	 * In HelenOS, primary and secondary context registers contain
-	 * equal values and kernel misses (context 0, ie. the nucleus context)
-	 * are excluded from the TSB miss handler, so it makes no sense
-	 * to have separate TSBs for primary, secondary and nucleus contexts.
-	 * Clearing the extension registers will ensure that the value of the
-	 * TSB Base register will be used as an address of TSB, making the code
-	 * compatible with the US port. 
-	 */
-	itsb_primary_extension_write(0);
-	itsb_nucleus_extension_write(0);
-	dtsb_primary_extension_write(0);
-	dtsb_secondary_extension_write(0);
-	dtsb_nucleus_extension_write(0);
-#endif
-#endif
-}
-
-/** Perform sparc64-specific tasks when an address space is removed from the
- * processor.
- *
- * Demap TSBs.
- *
- * @param as Address space.
- */
-void as_deinstall_arch(as_t *as)
-{
-
-	/*
-	 * Note that we don't and may not lock the address space. That's ok
-	 * since we only read members that are currently read-only.
-	 *
-	 * Moreover, the as->asid is protected by asidlock, which is being held.
-	 */
-
-#ifdef CONFIG_TSB
-	uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
-
-	ASSERT(as->arch.itsb && as->arch.dtsb);
-
-	uintptr_t tsb = (uintptr_t) as->arch.itsb;
-		
-	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
-		/*
-		 * TSBs were allocated from memory not covered
-		 * by the locked 4M kernel DTLB entry. We need
-		 * to demap the entry installed by as_install_arch().
-		 */
-		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
-	}
-#endif
-}
-
-/** @}
- */
Index: kernel/arch/sparc64/src/mm/sun4u/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4u/as.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/mm/sun4u/as.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,224 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup sparc64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/as.h>
+#include <arch/mm/tlb.h>
+#include <genarch/mm/page_ht.h>
+#include <genarch/mm/asid_fifo.h>
+#include <debug.h>
+#include <config.h>
+
+#ifdef CONFIG_TSB
+#include <arch/mm/tsb.h>
+#include <arch/memstr.h>
+#include <arch/asm.h>
+#include <mm/frame.h>
+#include <bitops.h>
+#include <macros.h>
+#endif /* CONFIG_TSB */
+
+/** Architecture dependent address space init. */
+void as_arch_init(void)
+{
+	if (config.cpu_active == 1) {
+		as_operations = &as_ht_operations;
+		asid_fifo_init();
+	}
+}
+
+int as_constructor_arch(as_t *as, int flags)
+{
+#ifdef CONFIG_TSB
+	/*
+	 * The order must be calculated with respect to the emulated
+	 * 16K page size.
+	 */
+	int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
+	    sizeof(tsb_entry_t)) >> FRAME_WIDTH);
+
+	uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
+
+	if (!tsb)
+		return -1;
+
+	as->arch.itsb = (tsb_entry_t *) tsb;
+	as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
+	    sizeof(tsb_entry_t));
+
+	memsetb(as->arch.itsb,
+	    (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
+#endif
+	return 0;
+}
+
+int as_destructor_arch(as_t *as)
+{
+#ifdef CONFIG_TSB
+	/*
+	 * The count must be calculated with respect to the emualted 16K page
+	 * size.
+	 */
+	size_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
+	    sizeof(tsb_entry_t)) >> FRAME_WIDTH;
+	frame_free(KA2PA((uintptr_t) as->arch.itsb));
+	return cnt;
+#else
+	return 0;
+#endif
+}
+
+int as_create_arch(as_t *as, int flags)
+{
+#ifdef CONFIG_TSB
+	tsb_invalidate(as, 0, (size_t) -1);
+#endif
+	return 0;
+}
+
+/** Perform sparc64-specific tasks when an address space becomes active on the
+ * processor.
+ *
+ * Install ASID and map TSBs.
+ *
+ * @param as Address space.
+ */
+void as_install_arch(as_t *as)
+{
+	tlb_context_reg_t ctx;
+	
+	/*
+	 * Note that we don't and may not lock the address space. That's ok
+	 * since we only read members that are currently read-only.
+	 *
+	 * Moreover, the as->asid is protected by asidlock, which is being held.
+	 */
+	
+	/*
+	 * Write ASID to secondary context register. The primary context
+	 * register has to be set from TL>0 so it will be filled from the
+	 * secondary context register from the TL=1 code just before switch to
+	 * userspace.
+	 */
+	ctx.v = 0;
+	ctx.context = as->asid;
+	mmu_secondary_context_write(ctx.v);
+
+#ifdef CONFIG_TSB	
+	uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
+
+	ASSERT(as->arch.itsb && as->arch.dtsb);
+
+	uintptr_t tsb = (uintptr_t) as->arch.itsb;
+		
+	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+		/*
+		 * TSBs were allocated from memory not covered
+		 * by the locked 4M kernel DTLB entry. We need
+		 * to map both TSBs explicitly.
+		 */
+		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
+		dtlb_insert_mapping(tsb, KA2PA(tsb), PAGESIZE_64K, true, true);
+	}
+		
+	/*
+	 * Setup TSB Base registers.
+	 */
+	tsb_base_reg_t tsb_base;
+		
+	tsb_base.value = 0;
+	tsb_base.size = TSB_SIZE;
+	tsb_base.split = 0;
+
+	tsb_base.base = ((uintptr_t) as->arch.itsb) >> MMU_PAGE_WIDTH;
+	itsb_base_write(tsb_base.value);
+	tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
+	dtsb_base_write(tsb_base.value);
+	
+#if defined (US3)
+	/*
+	 * Clear the extension registers.
+	 * In HelenOS, primary and secondary context registers contain
+	 * equal values and kernel misses (context 0, ie. the nucleus context)
+	 * are excluded from the TSB miss handler, so it makes no sense
+	 * to have separate TSBs for primary, secondary and nucleus contexts.
+	 * Clearing the extension registers will ensure that the value of the
+	 * TSB Base register will be used as an address of TSB, making the code
+	 * compatible with the US port. 
+	 */
+	itsb_primary_extension_write(0);
+	itsb_nucleus_extension_write(0);
+	dtsb_primary_extension_write(0);
+	dtsb_secondary_extension_write(0);
+	dtsb_nucleus_extension_write(0);
+#endif
+#endif
+}
+
+/** Perform sparc64-specific tasks when an address space is removed from the
+ * processor.
+ *
+ * Demap TSBs.
+ *
+ * @param as Address space.
+ */
+void as_deinstall_arch(as_t *as)
+{
+
+	/*
+	 * Note that we don't and may not lock the address space. That's ok
+	 * since we only read members that are currently read-only.
+	 *
+	 * Moreover, the as->asid is protected by asidlock, which is being held.
+	 */
+
+#ifdef CONFIG_TSB
+	uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
+
+	ASSERT(as->arch.itsb && as->arch.dtsb);
+
+	uintptr_t tsb = (uintptr_t) as->arch.itsb;
+		
+	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+		/*
+		 * TSBs were allocated from memory not covered
+		 * by the locked 4M kernel DTLB entry. We need
+		 * to demap the entry installed by as_install_arch().
+		 */
+		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
+	}
+#endif
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/mm/sun4u/tsb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4u/tsb.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/mm/sun4u/tsb.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,177 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup sparc64mm	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/tsb.h>
+#include <arch/mm/tlb.h>
+#include <arch/mm/page.h>
+#include <arch/barrier.h>
+#include <mm/as.h>
+#include <arch/types.h>
+#include <macros.h>
+#include <debug.h>
+
+#define TSB_INDEX_MASK	((1 << (21 + 1 + TSB_SIZE - MMU_PAGE_WIDTH)) - 1)
+
+/** Invalidate portion of TSB.
+ *
+ * We assume that the address space is already locked. Note that respective
+ * portions of both TSBs are invalidated at a time.
+ *
+ * @param as Address space.
+ * @param page First page to invalidate in TSB.
+ * @param pages Number of pages to invalidate. Value of (size_t) -1 means the
+ * 	whole TSB.
+ */
+void tsb_invalidate(as_t *as, uintptr_t page, size_t pages)
+{
+	size_t i0;
+	size_t i;
+	size_t cnt;
+	
+	ASSERT(as->arch.itsb && as->arch.dtsb);
+	
+	i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK;
+	ASSERT(i0 < ITSB_ENTRY_COUNT && i0 < DTSB_ENTRY_COUNT);
+
+	if (pages == (size_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT)
+		cnt = ITSB_ENTRY_COUNT;
+	else
+		cnt = pages * 2;
+	
+	for (i = 0; i < cnt; i++) {
+		as->arch.itsb[(i0 + i) & (ITSB_ENTRY_COUNT - 1)].tag.invalid =
+		    true;
+		as->arch.dtsb[(i0 + i) & (DTSB_ENTRY_COUNT - 1)].tag.invalid =
+		    true;
+	}
+}
+
+/** Copy software PTE to ITSB.
+ *
+ * @param t 	Software PTE.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K subpage.
+ */
+void itsb_pte_copy(pte_t *t, size_t index)
+{
+	as_t *as;
+	tsb_entry_t *tsb;
+	size_t entry;
+
+	ASSERT(index <= 1);
+	
+	as = t->as;
+	entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; 
+	ASSERT(entry < ITSB_ENTRY_COUNT);
+	tsb = &as->arch.itsb[entry];
+
+	/*
+	 * We use write barriers to make sure that the TSB load
+	 * won't use inconsistent data or that the fault will
+	 * be repeated.
+	 */
+
+	tsb->tag.invalid = true;	/* invalidate the entry
+					 * (tag target has this
+					 * set to 0) */
+
+	write_barrier();
+
+	tsb->tag.context = as->asid;
+	/* the shift is bigger than PAGE_WIDTH, do not bother with index  */
+	tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT;
+	tsb->data.value = 0;
+	tsb->data.size = PAGESIZE_8K;
+	tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
+	tsb->data.cp = t->c;	/* cp as cache in phys.-idxed, c as cacheable */
+	tsb->data.p = t->k;	/* p as privileged, k as kernel */
+	tsb->data.v = t->p;	/* v as valid, p as present */
+	
+	write_barrier();
+	
+	tsb->tag.invalid = false;	/* mark the entry as valid */
+}
+
+/** Copy software PTE to DTSB.
+ *
+ * @param t	Software PTE.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K-subpage.
+ * @param ro	If true, the mapping is copied read-only.
+ */
+void dtsb_pte_copy(pte_t *t, size_t index, bool ro)
+{
+	as_t *as;
+	tsb_entry_t *tsb;
+	size_t entry;
+	
+	ASSERT(index <= 1);
+
+	as = t->as;
+	entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK;
+	ASSERT(entry < DTSB_ENTRY_COUNT);
+	tsb = &as->arch.dtsb[entry];
+
+	/*
+	 * We use write barriers to make sure that the TSB load
+	 * won't use inconsistent data or that the fault will
+	 * be repeated.
+	 */
+
+	tsb->tag.invalid = true;	/* invalidate the entry
+					 * (tag target has this
+					 * set to 0) */
+
+	write_barrier();
+
+	tsb->tag.context = as->asid;
+	/* the shift is bigger than PAGE_WIDTH, do not bother with index */
+	tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT;
+	tsb->data.value = 0;
+	tsb->data.size = PAGESIZE_8K;
+	tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
+	tsb->data.cp = t->c;
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	tsb->data.cv = t->c;
+#endif /* CONFIG_VIRT_IDX_DCACHE */
+	tsb->data.p = t->k;		/* p as privileged */
+	tsb->data.w = ro ? false : t->w;
+	tsb->data.v = t->p;
+	
+	write_barrier();
+	
+	tsb->tag.invalid = false;	/* mark the entry as valid */
+}
+
+/** @}
+ */
+
Index: kernel/arch/sparc64/src/mm/sun4v/as.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/as.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/mm/sun4v/as.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,226 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup sparc64mm
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/as.h>
+#include <arch/mm/tlb.h>
+#include <genarch/mm/page_ht.h>
+#include <genarch/mm/asid_fifo.h>
+#include <debug.h>
+#include <config.h>
+
+#ifdef CONFIG_TSB
+#include <arch/mm/tsb.h>
+#include <arch/memstr.h>
+#include <arch/asm.h>
+#include <mm/frame.h>
+#include <bitops.h>
+#include <macros.h>
+#endif /* CONFIG_TSB */
+
+/** Architecture dependent address space init. */
+void as_arch_init(void)
+{
+	if (config.cpu_active == 1) {
+		as_operations = &as_ht_operations;
+		asid_fifo_init();
+	}
+}
+
+int as_constructor_arch(as_t *as, int flags)
+{
+#ifdef CONFIG_TSB
+	/*
+	 * The order must be calculated with respect to the emulated
+	 * 16K page size.
+	 */
+	int order = fnzb32(((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
+	    sizeof(tsb_entry_t)) >> FRAME_WIDTH);
+
+	uintptr_t tsb = (uintptr_t) frame_alloc(order, flags | FRAME_KA);
+
+	if (!tsb)
+		return -1;
+
+	as->arch.itsb = (tsb_entry_t *) tsb;
+	as->arch.dtsb = (tsb_entry_t *) (tsb + ITSB_ENTRY_COUNT *
+	    sizeof(tsb_entry_t));
+
+	memsetb(as->arch.itsb,
+	    (ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) * sizeof(tsb_entry_t), 0);
+#endif
+	return 0;
+}
+
+int as_destructor_arch(as_t *as)
+{
+#ifdef CONFIG_TSB
+	/*
+	 * The count must be calculated with respect to the emualted 16K page
+	 * size.
+	 */
+	size_t cnt = ((ITSB_ENTRY_COUNT + DTSB_ENTRY_COUNT) *
+	    sizeof(tsb_entry_t)) >> FRAME_WIDTH;
+	frame_free(KA2PA((uintptr_t) as->arch.itsb));
+	return cnt;
+#else
+	return 0;
+#endif
+}
+
+int as_create_arch(as_t *as, int flags)
+{
+#ifdef CONFIG_TSB
+	tsb_invalidate(as, 0, (size_t) -1);
+#endif
+	return 0;
+}
+
+/** Perform sparc64-specific tasks when an address space becomes active on the
+ * processor.
+ *
+ * Install ASID and map TSBs.
+ *
+ * @param as Address space.
+ */
+void as_install_arch(as_t *as)
+{
+#if 0
+	tlb_context_reg_t ctx;
+	
+	/*
+	 * Note that we don't and may not lock the address space. That's ok
+	 * since we only read members that are currently read-only.
+	 *
+	 * Moreover, the as->asid is protected by asidlock, which is being held.
+	 */
+	
+	/*
+	 * Write ASID to secondary context register. The primary context
+	 * register has to be set from TL>0 so it will be filled from the
+	 * secondary context register from the TL=1 code just before switch to
+	 * userspace.
+	 */
+	ctx.v = 0;
+	ctx.context = as->asid;
+	mmu_secondary_context_write(ctx.v);
+
+#ifdef CONFIG_TSB	
+	uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
+
+	ASSERT(as->arch.itsb && as->arch.dtsb);
+
+	uintptr_t tsb = (uintptr_t) as->arch.itsb;
+		
+	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+		/*
+		 * TSBs were allocated from memory not covered
+		 * by the locked 4M kernel DTLB entry. We need
+		 * to map both TSBs explicitly.
+		 */
+		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
+		dtlb_insert_mapping(tsb, KA2PA(tsb), PAGESIZE_64K, true, true);
+	}
+		
+	/*
+	 * Setup TSB Base registers.
+	 */
+	tsb_base_reg_t tsb_base;
+		
+	tsb_base.value = 0;
+	tsb_base.size = TSB_SIZE;
+	tsb_base.split = 0;
+
+	tsb_base.base = ((uintptr_t) as->arch.itsb) >> MMU_PAGE_WIDTH;
+	itsb_base_write(tsb_base.value);
+	tsb_base.base = ((uintptr_t) as->arch.dtsb) >> MMU_PAGE_WIDTH;
+	dtsb_base_write(tsb_base.value);
+	
+#if defined (US3)
+	/*
+	 * Clear the extension registers.
+	 * In HelenOS, primary and secondary context registers contain
+	 * equal values and kernel misses (context 0, ie. the nucleus context)
+	 * are excluded from the TSB miss handler, so it makes no sense
+	 * to have separate TSBs for primary, secondary and nucleus contexts.
+	 * Clearing the extension registers will ensure that the value of the
+	 * TSB Base register will be used as an address of TSB, making the code
+	 * compatible with the US port. 
+	 */
+	itsb_primary_extension_write(0);
+	itsb_nucleus_extension_write(0);
+	dtsb_primary_extension_write(0);
+	dtsb_secondary_extension_write(0);
+	dtsb_nucleus_extension_write(0);
+#endif
+#endif
+#endif
+}
+
+/** Perform sparc64-specific tasks when an address space is removed from the
+ * processor.
+ *
+ * Demap TSBs.
+ *
+ * @param as Address space.
+ */
+void as_deinstall_arch(as_t *as)
+{
+
+	/*
+	 * Note that we don't and may not lock the address space. That's ok
+	 * since we only read members that are currently read-only.
+	 *
+	 * Moreover, the as->asid is protected by asidlock, which is being held.
+	 */
+
+#ifdef CONFIG_TSB
+	uintptr_t base = ALIGN_DOWN(config.base, 1 << KERNEL_PAGE_WIDTH);
+
+	ASSERT(as->arch.itsb && as->arch.dtsb);
+
+	uintptr_t tsb = (uintptr_t) as->arch.itsb;
+		
+	if (!overlaps(tsb, 8 * MMU_PAGE_SIZE, base, 1 << KERNEL_PAGE_WIDTH)) {
+		/*
+		 * TSBs were allocated from memory not covered
+		 * by the locked 4M kernel DTLB entry. We need
+		 * to demap the entry installed by as_install_arch().
+		 */
+		dtlb_demap(TLB_DEMAP_PAGE, TLB_DEMAP_NUCLEUS, tsb);
+	}
+#endif
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/mm/sun4v/tsb.c
===================================================================
--- kernel/arch/sparc64/src/mm/sun4v/tsb.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/mm/sun4v/tsb.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,181 @@
+/*
+ * Copyright (c) 2006 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.
+ */
+
+/** @addtogroup sparc64mm	
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/mm/tsb.h>
+#include <arch/mm/tlb.h>
+#include <arch/mm/page.h>
+#include <arch/barrier.h>
+#include <mm/as.h>
+#include <arch/types.h>
+#include <macros.h>
+#include <debug.h>
+
+#define TSB_INDEX_MASK	((1 << (21 + 1 + TSB_SIZE - MMU_PAGE_WIDTH)) - 1)
+
+/** Invalidate portion of TSB.
+ *
+ * We assume that the address space is already locked. Note that respective
+ * portions of both TSBs are invalidated at a time.
+ *
+ * @param as Address space.
+ * @param page First page to invalidate in TSB.
+ * @param pages Number of pages to invalidate. Value of (size_t) -1 means the
+ * 	whole TSB.
+ */
+void tsb_invalidate(as_t *as, uintptr_t page, size_t pages)
+{
+	size_t i0;
+	size_t i;
+	size_t cnt;
+	
+	ASSERT(as->arch.itsb && as->arch.dtsb);
+	
+	i0 = (page >> MMU_PAGE_WIDTH) & TSB_INDEX_MASK;
+	ASSERT(i0 < ITSB_ENTRY_COUNT && i0 < DTSB_ENTRY_COUNT);
+
+	if (pages == (size_t) -1 || (pages * 2) > ITSB_ENTRY_COUNT)
+		cnt = ITSB_ENTRY_COUNT;
+	else
+		cnt = pages * 2;
+	
+	for (i = 0; i < cnt; i++) {
+		as->arch.itsb[(i0 + i) & (ITSB_ENTRY_COUNT - 1)].tag.invalid =
+		    true;
+		as->arch.dtsb[(i0 + i) & (DTSB_ENTRY_COUNT - 1)].tag.invalid =
+		    true;
+	}
+}
+
+/** Copy software PTE to ITSB.
+ *
+ * @param t 	Software PTE.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K subpage.
+ */
+void itsb_pte_copy(pte_t *t, size_t index)
+{
+#if 0
+	as_t *as;
+	tsb_entry_t *tsb;
+	size_t entry;
+
+	ASSERT(index <= 1);
+	
+	as = t->as;
+	entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK; 
+	ASSERT(entry < ITSB_ENTRY_COUNT);
+	tsb = &as->arch.itsb[entry];
+
+	/*
+	 * We use write barriers to make sure that the TSB load
+	 * won't use inconsistent data or that the fault will
+	 * be repeated.
+	 */
+
+	tsb->tag.invalid = true;	/* invalidate the entry
+					 * (tag target has this
+					 * set to 0) */
+
+	write_barrier();
+
+	tsb->tag.context = as->asid;
+	/* the shift is bigger than PAGE_WIDTH, do not bother with index  */
+	tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT;
+	tsb->data.value = 0;
+	tsb->data.size = PAGESIZE_8K;
+	tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
+	tsb->data.cp = t->c;	/* cp as cache in phys.-idxed, c as cacheable */
+	tsb->data.p = t->k;	/* p as privileged, k as kernel */
+	tsb->data.v = t->p;	/* v as valid, p as present */
+	
+	write_barrier();
+	
+	tsb->tag.invalid = false;	/* mark the entry as valid */
+#endif
+}
+
+/** Copy software PTE to DTSB.
+ *
+ * @param t	Software PTE.
+ * @param index	Zero if lower 8K-subpage, one if higher 8K-subpage.
+ * @param ro	If true, the mapping is copied read-only.
+ */
+void dtsb_pte_copy(pte_t *t, size_t index, bool ro)
+{
+#if 0
+	as_t *as;
+	tsb_entry_t *tsb;
+	size_t entry;
+	
+	ASSERT(index <= 1);
+
+	as = t->as;
+	entry = ((t->page >> MMU_PAGE_WIDTH) + index) & TSB_INDEX_MASK;
+	ASSERT(entry < DTSB_ENTRY_COUNT);
+	tsb = &as->arch.dtsb[entry];
+
+	/*
+	 * We use write barriers to make sure that the TSB load
+	 * won't use inconsistent data or that the fault will
+	 * be repeated.
+	 */
+
+	tsb->tag.invalid = true;	/* invalidate the entry
+					 * (tag target has this
+					 * set to 0) */
+
+	write_barrier();
+
+	tsb->tag.context = as->asid;
+	/* the shift is bigger than PAGE_WIDTH, do not bother with index */
+	tsb->tag.va_tag = t->page >> VA_TAG_PAGE_SHIFT;
+	tsb->data.value = 0;
+	tsb->data.size = PAGESIZE_8K;
+	tsb->data.pfn = (t->frame >> MMU_FRAME_WIDTH) + index;
+	tsb->data.cp = t->c;
+#ifdef CONFIG_VIRT_IDX_DCACHE
+	tsb->data.cv = t->c;
+#endif /* CONFIG_VIRT_IDX_DCACHE */
+	tsb->data.p = t->k;		/* p as privileged */
+	tsb->data.w = ro ? false : t->w;
+	tsb->data.v = t->p;
+	
+	write_barrier();
+	
+	tsb->tag.invalid = false;	/* mark the entry as valid */
+#endif
+}
+
+/** @}
+ */
+
Index: kernel/arch/sparc64/src/sun4v/md.c
===================================================================
--- kernel/arch/sparc64/src/sun4v/md.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/sun4v/md.c	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,318 @@
+/*
+ * Copyright (c) 2009 Pavel Rimsky
+ * 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.
+ */
+
+/** @addtogroup sparc64
+ * @{
+ */
+/** @file
+ */
+
+#include <debug.h>
+#include <panic.h>
+#include <func.h>
+#include <print.h>
+#include <string.h>
+#include <arch/sun4v/md.h>
+#include <arch/sun4v/hypercall.h>
+#include <arch/mm/page.h>
+
+/* maximum MD size estimate (in bytes) */
+#define MD_MAX_SIZE	(64 * 1024)
+
+/** element types (element tag values) */
+#define LIST_END	0x0	/**< End of element list */
+#define NODE		0x4e	/**< Start of node definition */
+#define NODE_END	0x45	/**< End of node definition */
+#define NOOP		0x20	/**< NOOP list element - to be ignored */
+#define PROP_ARC	0x61	/**< Node property arc'ing to another node */
+#define PROP_VAL	0x76	/**< Node property with an integer value */
+#define PROP_STR	0x73	/**< Node property with a string value */
+#define PROP_DATA	0x64	/**< Node property with a block of data */
+
+
+/** machine description header */
+typedef struct {
+	uint32_t transport_version;	/**< Transport version number */
+	uint32_t node_blk_sz;		/**< Size in bytes of node block */
+	uint32_t name_blk_sz;		/**< Size in bytes of name block */
+	uint32_t data_blk_sz;		/**< Size in bytes of data block */
+} __attribute__ ((packed)) md_header_t;
+
+/** machine description element (in the node block) */
+typedef struct {
+	uint8_t tag;			/**< Type of element */
+	uint8_t name_len;		/**< Length in bytes of element name */
+	uint16_t _reserved_field;	/**< reserved field (zeros) */
+	uint32_t name_offset;		/**< Location offset of name associated
+					     with this element relative to
+					     start of name block */
+	union {
+		/** for elements of type “PROP_STR” and of type “PROP_DATA” */
+		struct {
+			/** Length in bytes of data in data block */
+			uint32_t data_len;
+
+			/**
+			 * Location offset of data associated with this
+			 * element relative to start of data block
+			 */
+			uint32_t data_offset;
+		} y;
+
+		/**
+		 *  64 bit value for elements of tag type “NODE”, “PROP_VAL”
+		 *  or “PROP_ARC”
+		 */
+		uint64_t val;
+	} d;
+} __attribute__ ((packed)) md_element_t;
+
+/** index of the element within the node block */
+typedef unsigned int element_idx_t;
+
+/** buffer to which the machine description will be saved */
+static uint8_t mach_desc[MD_MAX_SIZE]
+	 __attribute__ ((aligned (16)));
+
+
+/** returns pointer to the element at the given index */
+static md_element_t *get_element(element_idx_t idx)
+{
+	return (md_element_t *) (
+		mach_desc + sizeof(md_header_t) + idx * sizeof(md_element_t));
+}
+
+/** returns the name of the element represented by the index */
+static const char *get_element_name(element_idx_t idx)
+{
+	md_header_t *md_header = (md_header_t *) mach_desc;
+	uintptr_t name_offset = get_element(idx)->name_offset;
+	return (char *) mach_desc + sizeof(md_header_t) +
+		md_header->node_blk_sz + name_offset;
+}
+
+/** finds the name of the node represented by "node" */
+const char *md_get_node_name(md_node_t node)
+{
+	return get_element_name(node);
+}
+
+/**
+ * Returns the value of the integer property of the given node.
+ *
+ * @param 
+ */
+bool md_get_integer_property(md_node_t node, const char *key,
+	uint64_t *result)
+{
+	element_idx_t idx = node;	
+
+	while (get_element(idx)->tag != NODE_END) {
+		idx++;
+		md_element_t *element = get_element(idx);
+		if (element->tag == PROP_VAL &&
+				str_cmp(key, get_element_name(idx)) == 0) {
+			*result = element->d.val;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * Returns the value of the string property of the given node.
+ *
+ * @param 
+ */
+bool md_get_string_property(md_node_t node, const char *key,
+	const char **result)
+{
+	md_header_t *md_header = (md_header_t *) mach_desc;
+	element_idx_t idx = node;
+
+	while (get_element(idx)->tag != NODE_END) {
+		idx++;
+		md_element_t *element = get_element(idx);
+		if (element->tag == PROP_DATA &&
+				str_cmp(key, get_element_name(idx)) == 0) {
+			*result = (char *) mach_desc + sizeof(md_header_t) +
+				md_header->node_blk_sz + md_header->name_blk_sz +
+				element->d.y.data_offset;
+			return true;
+		}
+	}
+
+	return false;
+}
+
+/**
+ * Moves the child oterator to the next child (following sibling of the node
+ * the oterator currently points to).
+ *
+ * @param it	pointer to the iterator to be moved
+ */
+bool md_next_child(md_child_iter_t *it)
+{
+	element_idx_t backup = *it;
+
+	while (get_element(*it)->tag != NODE_END) {
+		(*it)++;
+		md_element_t *element = get_element(*it);
+		if (element->tag == PROP_ARC &&
+				str_cmp("fwd", get_element_name(*it)) == 0) {
+			return true;
+		}
+	}
+
+	*it = backup;
+	return false;
+}
+
+/**
+ * Returns the node the iterator point to.
+ */
+md_node_t md_get_child_node(md_child_iter_t it)
+{
+	return get_element(it)->d.val;
+}
+
+/**
+ * Helper function used to split a string to a part before the first
+ * slash sign and a part after the slash sign.
+ *
+ * @param str	pointer to the string to be split; when the function finishes,
+ * 		it will	contain only the part following the first slash sign of
+ * 		the original string
+ * @param head	pointer to the string which will be set to the part before the
+ * 		first slash sign
+ */
+static bool str_parse_head(char **str, char **head)
+{
+	*head = *str;
+
+	char *cur = *str;
+	while (*cur != '\0') {
+		if (*cur == '/') {
+			*cur = '\0';
+			*str = cur + 1;
+			return true;
+		}
+		cur++;
+	}
+
+	return false;
+}
+
+/**
+ * Returns the descendant of the given node. The descendant is identified
+ * by a path where the node names are separated by a slash.
+ *
+ * Ex.: Let there be a node N with path "a/b/c/x/y/z" and let P represent the
+ * node with path "a/b/c". Then md_get_child(P, "x/y/z") will return N.
+ */
+md_node_t md_get_child(md_node_t node, char *name)
+{
+	bool more;
+
+	do {
+		char *head;
+		more = str_parse_head(&name, &head);
+		
+		while (md_next_child(&node)) {
+			element_idx_t child = md_get_child_node(node);
+			if (str_cmp(head, get_element_name(child)) == 0) {
+				node = child;
+				break;
+			}
+		}
+
+	} while (more);
+
+	return node;
+}
+
+/** returns the root node of MD */
+md_node_t md_get_root(void)
+{
+	return 0;
+}
+
+/**
+ * Returns the child iterator - a token to be passed to functions iterating
+ * through all the children of a node.
+ *
+ * @param node	a node whose children the iterator will be used
+ * 		to iterate through
+ */
+md_child_iter_t md_get_child_iterator(md_node_t node)
+{
+	return node;
+}
+
+/**
+ * Moves "node" to the node following "node" in the list of all the existing
+ * nodes of the MD whose name is "name". 
+ */
+bool md_next_node(md_node_t *node, const char *name)
+{
+	md_element_t *element;
+	(*node)++;
+
+	do {
+		element = get_element(*node);
+
+		if (element->tag == NODE &&
+				str_cmp(name, get_element_name(*node)) == 0) {
+			return true;
+		}
+		
+		(*node)++;
+	} while (element->tag != LIST_END);
+
+	return false;
+}
+
+/**
+ * Retrieves the machine description from the hypervisor and saves it to
+ * a kernel buffer.
+ */
+void md_init(void)
+{
+	uint64_t retval = __hypercall_fast2(MACH_DESC, KA2PA(mach_desc),
+		MD_MAX_SIZE);
+
+	retval = retval;
+	if (retval != EOK) {
+		printf("Could not retrieve machine description, error = %d.\n",
+			retval);
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/trap/sun4u/trap_table.S
===================================================================
--- kernel/arch/sparc64/src/trap/sun4u/trap_table.S	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/trap/sun4u/trap_table.S	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,851 @@
+#
+# 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.
+#
+
+/**
+ * @file
+ * @brief This file contains kernel trap table.
+ */
+
+.register %g2, #scratch
+.register %g3, #scratch
+
+.text
+
+#include <arch/trap/trap_table.h>
+#include <arch/trap/regwin.h>
+#include <arch/trap/interrupt.h>
+#include <arch/trap/exception.h>
+#include <arch/trap/syscall.h>
+#include <arch/trap/mmu.h>
+#include <arch/mm/mmu.h>
+#include <arch/mm/page.h>
+#include <arch/stack.h>
+#include <arch/regdef.h>
+
+#define TABLE_SIZE	TRAP_TABLE_SIZE
+#define ENTRY_SIZE	TRAP_TABLE_ENTRY_SIZE
+
+/*
+ * Kernel trap table.
+ */
+.align TABLE_SIZE
+.global trap_table
+trap_table:
+
+/* TT = 0x08, TL = 0, instruction_access_exception */
+.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
+.global instruction_access_exception_tl0
+instruction_access_exception_tl0:
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER instruction_access_exception
+
+/* TT = 0x0a, TL = 0, instruction_access_error */
+.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
+.global instruction_access_error_tl0
+instruction_access_error_tl0:
+	PREEMPTIBLE_HANDLER instruction_access_error
+
+/* TT = 0x10, TL = 0, illegal_instruction */
+.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
+.global illegal_instruction_tl0
+illegal_instruction_tl0:
+	PREEMPTIBLE_HANDLER illegal_instruction
+
+/* TT = 0x11, TL = 0, privileged_opcode */
+.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
+.global privileged_opcode_tl0
+privileged_opcode_tl0:
+	PREEMPTIBLE_HANDLER privileged_opcode
+
+/* TT = 0x12, TL = 0, unimplemented_LDD */
+.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
+.global unimplemented_LDD_tl0
+unimplemented_LDD_tl0:
+	PREEMPTIBLE_HANDLER unimplemented_LDD
+
+/* TT = 0x13, TL = 0, unimplemented_STD */
+.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
+.global unimplemented_STD_tl0
+unimplemented_STD_tl0:
+	PREEMPTIBLE_HANDLER unimplemented_STD
+
+/* TT = 0x20, TL = 0, fb_disabled handler */
+.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
+.global fb_disabled_tl0
+fp_disabled_tl0:
+	PREEMPTIBLE_HANDLER fp_disabled
+
+/* TT = 0x21, TL = 0, fb_exception_ieee_754 handler */
+.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
+.global fb_exception_ieee_754_tl0
+fp_exception_ieee_754_tl0:
+	PREEMPTIBLE_HANDLER fp_exception_ieee_754
+
+/* TT = 0x22, TL = 0, fb_exception_other handler */
+.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
+.global fb_exception_other_tl0
+fp_exception_other_tl0:
+	PREEMPTIBLE_HANDLER fp_exception_other
+
+/* TT = 0x23, TL = 0, tag_overflow */
+.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
+.global tag_overflow_tl0
+tag_overflow_tl0:
+	PREEMPTIBLE_HANDLER tag_overflow
+
+/* TT = 0x24, TL = 0, clean_window handler */
+.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
+.global clean_window_tl0
+clean_window_tl0:
+	CLEAN_WINDOW_HANDLER
+
+/* TT = 0x28, TL = 0, division_by_zero */
+.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
+.global division_by_zero_tl0
+division_by_zero_tl0:
+	PREEMPTIBLE_HANDLER division_by_zero
+
+/* TT = 0x30, TL = 0, data_access_exception */
+.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
+.global data_access_exception_tl0
+data_access_exception_tl0:
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER data_access_exception
+
+/* TT = 0x32, TL = 0, data_access_error */
+.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
+.global data_access_error_tl0
+data_access_error_tl0:
+	PREEMPTIBLE_HANDLER data_access_error
+
+/* TT = 0x34, TL = 0, mem_address_not_aligned */
+.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global mem_address_not_aligned_tl0
+mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER mem_address_not_aligned
+
+/* TT = 0x35, TL = 0, LDDF_mem_address_not_aligned */
+.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global LDDF_mem_address_not_aligned_tl0
+LDDF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER LDDF_mem_address_not_aligned
+
+/* TT = 0x36, TL = 0, STDF_mem_address_not_aligned */
+.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global STDF_mem_address_not_aligned_tl0
+STDF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER STDF_mem_address_not_aligned
+
+/* TT = 0x37, TL = 0, privileged_action */
+.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
+.global privileged_action_tl0
+privileged_action_tl0:
+	PREEMPTIBLE_HANDLER privileged_action
+
+/* TT = 0x38, TL = 0, LDQF_mem_address_not_aligned */
+.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global LDQF_mem_address_not_aligned_tl0
+LDQF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER LDQF_mem_address_not_aligned
+
+/* TT = 0x39, TL = 0, STQF_mem_address_not_aligned */
+.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global STQF_mem_address_not_aligned_tl0
+STQF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER STQF_mem_address_not_aligned
+
+/* TT = 0x41, TL = 0, interrupt_level_1 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
+.global interrupt_level_1_handler_tl0
+interrupt_level_1_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 1
+
+/* TT = 0x42, TL = 0, interrupt_level_2 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
+.global interrupt_level_2_handler_tl0
+interrupt_level_2_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 2
+
+/* TT = 0x43, TL = 0, interrupt_level_3 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
+.global interrupt_level_3_handler_tl0
+interrupt_level_3_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 3
+
+/* TT = 0x44, TL = 0, interrupt_level_4 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
+.global interrupt_level_4_handler_tl0
+interrupt_level_4_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 4
+
+/* TT = 0x45, TL = 0, interrupt_level_5 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
+.global interrupt_level_5_handler_tl0
+interrupt_level_5_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 5
+
+/* TT = 0x46, TL = 0, interrupt_level_6 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
+.global interrupt_level_6_handler_tl0
+interrupt_level_6_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 6
+
+/* TT = 0x47, TL = 0, interrupt_level_7 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
+.global interrupt_level_7_handler_tl0
+interrupt_level_7_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 7
+
+/* TT = 0x48, TL = 0, interrupt_level_8 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
+.global interrupt_level_8_handler_tl0
+interrupt_level_8_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 8
+
+/* TT = 0x49, TL = 0, interrupt_level_9 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
+.global interrupt_level_9_handler_tl0
+interrupt_level_9_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 9
+
+/* TT = 0x4a, TL = 0, interrupt_level_10 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
+.global interrupt_level_10_handler_tl0
+interrupt_level_10_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 10
+
+/* TT = 0x4b, TL = 0, interrupt_level_11 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
+.global interrupt_level_11_handler_tl0
+interrupt_level_11_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 11
+
+/* TT = 0x4c, TL = 0, interrupt_level_12 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
+.global interrupt_level_12_handler_tl0
+interrupt_level_12_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 12
+
+/* TT = 0x4d, TL = 0, interrupt_level_13 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
+.global interrupt_level_13_handler_tl0
+interrupt_level_13_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 13
+
+/* TT = 0x4e, TL = 0, interrupt_level_14 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
+.global interrupt_level_14_handler_tl0
+interrupt_level_14_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 14
+
+/* TT = 0x4f, TL = 0, interrupt_level_15 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
+.global interrupt_level_15_handler_tl0
+interrupt_level_15_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 15
+
+/* TT = 0x60, TL = 0, interrupt_vector_trap handler */
+.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
+.global interrupt_vector_trap_handler_tl0
+interrupt_vector_trap_handler_tl0:
+	INTERRUPT_VECTOR_TRAP_HANDLER
+
+/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
+.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
+.global fast_instruction_access_mmu_miss_handler_tl0
+fast_instruction_access_mmu_miss_handler_tl0:
+	FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
+
+/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
+.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
+.global fast_data_access_mmu_miss_handler_tl0
+fast_data_access_mmu_miss_handler_tl0:
+	FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
+
+/* TT = 0x6c, TL = 0, fast_data_access_protection */
+.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
+.global fast_data_access_protection_handler_tl0
+fast_data_access_protection_handler_tl0:
+	FAST_DATA_ACCESS_PROTECTION_HANDLER 0
+
+/* TT = 0x80, TL = 0, spill_0_normal handler */
+.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
+.global spill_0_normal_tl0
+spill_0_normal_tl0:
+	SPILL_NORMAL_HANDLER_KERNEL
+
+/* TT = 0x84, TL = 0, spill_1_normal handler */
+.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
+.global spill_1_normal_tl0
+spill_1_normal_tl0:
+	SPILL_NORMAL_HANDLER_USERSPACE
+
+/* TT = 0x88, TL = 0, spill_2_normal handler */
+.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
+.global spill_2_normal_tl0
+spill_2_normal_tl0:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xa0, TL = 0, spill_0_other handler */
+.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
+.global spill_0_other_tl0
+spill_0_other_tl0:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xc0, TL = 0, fill_0_normal handler */
+.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
+.global fill_0_normal_tl0
+fill_0_normal_tl0:
+	FILL_NORMAL_HANDLER_KERNEL
+
+/* TT = 0xc4, TL = 0, fill_1_normal handler */
+.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
+.global fill_1_normal_tl0
+fill_1_normal_tl0:
+	FILL_NORMAL_HANDLER_USERSPACE
+
+/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
+.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
+    20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
+    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
+    58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
+    77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
+    96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
+    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
+    127
+.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
+.global trap_instruction_\cur\()_tl0
+trap_instruction_\cur\()_tl0:
+	ba %xcc, trap_instruction_handler
+	mov \cur, %g2
+.endr
+
+/*
+ * Handlers for TL>0.
+ */
+
+/* TT = 0x08, TL > 0, instruction_access_exception */
+.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
+.global instruction_access_exception_tl1
+instruction_access_exception_tl1:
+	wrpr %g0, 1, %tl
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER instruction_access_exception
+
+/* TT = 0x0a, TL > 0, instruction_access_error */
+.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
+.global instruction_access_error_tl1
+instruction_access_error_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER instruction_access_error
+
+/* TT = 0x10, TL > 0, illegal_instruction */
+.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
+.global illegal_instruction_tl1
+illegal_instruction_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER illegal_instruction
+
+/* TT = 0x24, TL > 0, clean_window handler */
+.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
+.global clean_window_tl1
+clean_window_tl1:
+	CLEAN_WINDOW_HANDLER
+
+/* TT = 0x28, TL > 0, division_by_zero */
+.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
+.global division_by_zero_tl1
+division_by_zero_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER division_by_zero
+
+/* TT = 0x30, TL > 0, data_access_exception */
+.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
+.global data_access_exception_tl1
+data_access_exception_tl1:
+	wrpr %g0, 1, %tl
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER data_access_exception
+
+/* TT = 0x32, TL > 0, data_access_error */
+.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
+.global data_access_error_tl1
+data_access_error_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER data_access_error
+
+/* TT = 0x34, TL > 0, mem_address_not_aligned */
+.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
+.global mem_address_not_aligned_tl1
+mem_address_not_aligned_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER mem_address_not_aligned
+
+/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
+.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
+.global fast_data_access_mmu_miss_handler_tl1
+fast_data_access_mmu_miss_handler_tl1:
+	FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
+
+/* TT = 0x6c, TL > 0, fast_data_access_protection */
+.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
+.global fast_data_access_protection_handler_tl1
+fast_data_access_protection_handler_tl1:
+	FAST_DATA_ACCESS_PROTECTION_HANDLER 1
+
+/* TT = 0x80, TL > 0, spill_0_normal handler */
+.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
+.global spill_0_normal_tl1
+spill_0_normal_tl1:
+	SPILL_NORMAL_HANDLER_KERNEL
+
+/* TT = 0x88, TL > 0, spill_2_normal handler */
+.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
+.global spill_2_normal_tl1
+spill_2_normal_tl1:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xa0, TL > 0, spill_0_other handler */
+.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
+.global spill_0_other_tl1
+spill_0_other_tl1:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xc0, TL > 0, fill_0_normal handler */
+.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
+.global fill_0_normal_tl1
+fill_0_normal_tl1:
+	FILL_NORMAL_HANDLER_KERNEL
+
+.align TABLE_SIZE
+
+
+#define NOT(x)	((x) == 0)
+
+/* Preemptible trap handler for TL=1.
+ *
+ * This trap handler makes arrangements to make calling of scheduler() from
+ * within a trap context possible. It is called from several other trap
+ * handlers.
+ *
+ * This function can be entered either with interrupt globals or alternate
+ * globals. Memory management trap handlers are obliged to switch to one of
+ * those global sets prior to calling this function. Register window management
+ * functions are not allowed to modify the alternate global registers.
+ *
+ * The kernel is designed to work on trap levels 0 - 4. For instance, the
+ * following can happen:
+ * TL0: kernel thread runs (CANSAVE=0, kernel stack not in DTLB)
+ * TL1: preemptible trap handler started after a tick interrupt
+ * TL2: preemptible trap handler did SAVE
+ * TL3: spill handler touched the kernel stack  
+ * TL4: hardware or software failure
+ *
+ * Input registers:
+ *	%g1		Address of function to call if this is not a syscall.
+ * 	%g2	 	First argument for the function.
+ *	%g6		Pre-set as kernel stack base if trap from userspace.
+ *	%g7		Pre-set as address of the userspace window buffer.
+ */
+.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
+	/*
+	 * ASSERT(%tl == 1)
+	 */
+	rdpr %tl, %g3
+	cmp %g3, 1
+	be %xcc, 1f
+	nop
+0:	ba %xcc, 0b				! this is for debugging, if we ever get here
+	nop					! it will be easy to find
+
+1:
+.if NOT(\is_syscall)
+	rdpr %tstate, %g3
+	
+	/*
+	 * One of the ways this handler can be invoked is after a nested MMU trap from
+	 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
+	 * the CWP register. We deal with the situation by simulating the MMU trap
+	 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
+	 * trap is resolved. However, because we are in the wrong window from the
+	 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
+	 */ 
+	and %g3, TSTATE_CWP_MASK, %g4
+	wrpr %g4, 0, %cwp			! resynchronize CWP
+
+	andcc %g3, TSTATE_PRIV_BIT, %g0		! if this trap came from the privileged mode...
+	bnz %xcc, 0f				! ...skip setting of kernel stack and primary context
+	nop
+	
+.endif
+	/*
+	 * Normal window spills will go to the userspace window buffer.
+	 */
+	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
+
+	wrpr %g0, NWINDOWS - 1, %cleanwin	! prevent unnecessary clean_window exceptions
+
+	/*
+	 * Switch to kernel stack. The old stack is
+	 * automatically saved in the old window's %sp
+	 * and the new window's %fp.
+	 */
+	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
+
+.if \is_syscall
+	/*
+	 * Copy arguments for the syscall to the new window.
+	 */
+	mov %i0, %o0
+	mov %i1, %o1
+	mov %i2, %o2
+	mov %i3, %o3
+	mov %i4, %o4
+	mov %i5, %o5
+.endif
+
+	/*
+	 * Mark the CANRESTORE windows as OTHER windows.
+	 */
+	rdpr %canrestore, %l0
+	wrpr %l0, %otherwin
+	wrpr %g0, %canrestore
+
+	/*
+	 * Switch to primary context 0.
+	 */
+	mov VA_PRIMARY_CONTEXT_REG, %l0
+	stxa %g0, [%l0] ASI_DMMU
+	rd %pc, %l0
+	flush %l0
+
+.if NOT(\is_syscall)
+	ba %xcc, 1f
+	nop
+0:
+	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
+
+	/*
+	 * At this moment, we are using the kernel stack 
+	 * and have successfully allocated a register window.
+	 */
+1:
+.endif
+	/*
+	 * Other window spills will go to the userspace window buffer
+	 * and normal spills will go to the kernel stack.
+	 */
+	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
+	
+	/*
+	 * Copy arguments.
+	 */
+	mov %g1, %l0
+.if NOT(\is_syscall)
+	mov %g2, %o0
+.else
+	! store the syscall number on the stack as 7th argument
+	stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6] 
+.endif
+
+	/*
+	 * Save TSTATE, TPC and TNPC aside.
+	 */
+	rdpr %tstate, %g1
+	rdpr %tpc, %g2
+	rdpr %tnpc, %g3
+	rd %y, %g4
+
+	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
+	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
+	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
+
+	/*
+	 * Save the Y register.
+	 * This register is deprecated according to SPARC V9 specification
+	 * and is only present for backward compatibility with previous
+	 * versions of the SPARC architecture.
+	 * Surprisingly, gcc makes use of this register without a notice.
+	 */
+	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
+	
+	wrpr %g0, 0, %tl
+	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
+	SAVE_GLOBALS
+	
+.if NOT(\is_syscall)
+	/*
+	 * Call the higher-level handler and pass istate as second parameter.
+	 */
+	call %l0
+	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
+.else
+	/*
+	 * Call the higher-level syscall handler and enable interrupts.
+	 */
+	call syscall_handler
+	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
+	mov %o0, %i0				! copy the value returned by the syscall
+.endif
+
+	RESTORE_GLOBALS
+	rdpr %pstate, %l1			! we must preserve the PEF bit
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	wrpr %g0, 1, %tl
+	
+	/*
+	 * Read TSTATE, TPC and TNPC from saved copy.
+	 */
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
+
+	/*
+	 * Copy PSTATE.PEF to the in-register copy of TSTATE.
+	 */
+	and %l1, PSTATE_PEF_BIT, %l1
+	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
+	sethi %hi(TSTATE_PEF_BIT), %g4
+	andn %g1, %g4, %g1
+	or %g1, %l1, %g1
+
+	/*
+	 * Restore TSTATE, TPC and TNPC from saved copies.
+	 */
+	wrpr %g1, 0, %tstate
+	wrpr %g2, 0, %tpc
+	wrpr %g3, 0, %tnpc
+
+	/*
+	 * Restore Y.
+	 */
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
+	wr %g4, %y
+
+	/*
+	 * If OTHERWIN is zero, then all the userspace windows have been
+	 * spilled to kernel memory (i.e. register window buffer). Moreover,
+	 * if the scheduler was called in the meantime, all valid windows
+	 * belonging to other threads were spilled by context_restore().
+	 * If OTHERWIN is non-zero, then some userspace windows are still
+	 * valid. Others might have been spilled. However, the CWP pointer
+	 * needs no fixing because the scheduler had not been called.
+	 */
+	rdpr %otherwin, %l0
+	brnz %l0, 0f
+	nop
+
+	/*
+	 * OTHERWIN == 0
+	 */
+
+	/*
+	 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
+	 */
+	and %g1, TSTATE_CWP_MASK, %l0
+	inc %l0
+	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
+	rdpr %cwp, %l1
+	cmp %l0, %l1
+	bz %xcc, 0f			! CWP is ok
+	nop
+
+	/*
+	 * Fix CWP.
+	 * In order to recapitulate, the input registers in the current
+	 * window are the output registers of the window to which we want
+	 * to restore. Because the fill trap fills only input and local
+	 * registers of a window, we need to preserve those output
+	 * registers manually.
+	 */
+	mov %sp, %g2
+	stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
+	stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
+	stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
+	stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
+	stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
+	stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
+	stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
+	stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
+	wrpr %l0, 0, %cwp
+	mov %g2, %sp
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
+
+	/*
+	 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
+	 * The CWP has already been restored to the value it had after the SAVE
+	 * at the beginning of this function.
+	 */
+0:
+.if NOT(\is_syscall)
+	rdpr %tstate, %g1
+	andcc %g1, TSTATE_PRIV_BIT, %g0		! if we are not returning to userspace...,
+	bnz %xcc, 1f				! ...skip restoring userspace windows
+	nop
+.endif
+
+	/*
+	 * Spills and fills will be processed by the {spill,fill}_1_normal
+	 * handlers.
+	 */
+	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
+
+	/*
+	 * Set primary context according to secondary context.
+	 */
+	wr %g0, ASI_DMMU, %asi
+	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
+	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
+	rd %pc, %g1
+	flush %g1
+	
+	rdpr %cwp, %g1
+	rdpr %otherwin, %g2
+
+	/*
+	 * Skip all OTHERWIN windows and descend to the first window
+	 * in the userspace window buffer.
+	 */
+	sub %g1, %g2, %g3
+	dec %g3
+	and %g3, NWINDOWS - 1, %g3
+	wrpr %g3, 0, %cwp
+
+	/*
+	 * CWP is now in the window last saved in the userspace window buffer.
+	 * Fill all windows stored in the buffer.
+	 */
+	clr %g4
+0:	andcc %g7, UWB_ALIGNMENT - 1, %g0	! alignment check
+	bz %xcc, 0f				! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
+	nop
+
+	add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
+	ldx [%g7 + L0_OFFSET], %l0
+	ldx [%g7 + L1_OFFSET], %l1
+	ldx [%g7 + L2_OFFSET], %l2
+	ldx [%g7 + L3_OFFSET], %l3
+	ldx [%g7 + L4_OFFSET], %l4
+	ldx [%g7 + L5_OFFSET], %l5
+	ldx [%g7 + L6_OFFSET], %l6
+	ldx [%g7 + L7_OFFSET], %l7
+	ldx [%g7 + I0_OFFSET], %i0
+	ldx [%g7 + I1_OFFSET], %i1
+	ldx [%g7 + I2_OFFSET], %i2
+	ldx [%g7 + I3_OFFSET], %i3
+	ldx [%g7 + I4_OFFSET], %i4
+	ldx [%g7 + I5_OFFSET], %i5
+	ldx [%g7 + I6_OFFSET], %i6
+	ldx [%g7 + I7_OFFSET], %i7
+
+	dec %g3
+	and %g3, NWINDOWS - 1, %g3
+	wrpr %g3, 0, %cwp			! switch to the preceeding window
+
+	ba %xcc, 0b
+	inc %g4
+
+0:
+	/*
+	 * Switch back to the proper current window and adjust
+	 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
+	 */
+	wrpr %g1, 0, %cwp
+	add %g4, %g2, %g2
+	cmp %g2, NWINDOWS - 2
+	bg %xcc, 2f				! fix the CANRESTORE=NWINDOWS-1 anomaly
+	mov NWINDOWS - 2, %g1			! use dealy slot for both cases
+	sub %g1, %g2, %g1
+	
+	wrpr %g0, 0, %otherwin
+	wrpr %g1, 0, %cansave			! NWINDOWS - 2 - CANRESTORE
+	wrpr %g2, 0, %canrestore		! OTHERWIN + windows in the buffer
+	wrpr %g2, 0, %cleanwin			! avoid information leak
+
+1:
+	restore
+
+.if \is_syscall
+	done
+.else
+	retry
+.endif
+
+	/*
+	 * We got here in order to avoid inconsistency of the window state registers.
+	 * If the:
+	 *
+	 * 	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
+	 *
+	 * instruction trapped and spilled a register window into the userspace
+	 * window buffer, we have just restored NWINDOWS - 1 register windows.
+	 * However, CANRESTORE can be only NWINDOW - 2 at most.
+	 *
+	 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
+	 * and set the window state registers so that:
+	 *
+	 * 	CANRESTORE 	= NWINDOWS - 2
+	 *	CLEANWIN	= NWINDOWS - 2
+	 *	CANSAVE 	= 0
+	 *	OTHERWIN	= 0
+	 *
+	 * The RESTORE instruction is therfore to be skipped.
+	 */
+2:
+	wrpr %g0, 0, %otherwin
+	wrpr %g0, 0, %cansave
+	wrpr %g1, 0, %canrestore
+	wrpr %g1, 0, %cleanwin
+
+	rdpr %cwp, %g1
+	dec %g1
+	and %g1, NWINDOWS - 1, %g1
+	wrpr %g1, 0, %cwp			! CWP--
+	
+.if \is_syscall
+	done
+.else
+	retry
+.endif
+
+.endm
+
+.global preemptible_handler
+preemptible_handler:
+	PREEMPTIBLE_HANDLER_TEMPLATE 0
+
+.global trap_instruction_handler
+trap_instruction_handler:
+	PREEMPTIBLE_HANDLER_TEMPLATE 1
Index: kernel/arch/sparc64/src/trap/sun4v/trap_table.S
===================================================================
--- kernel/arch/sparc64/src/trap/sun4v/trap_table.S	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
+++ kernel/arch/sparc64/src/trap/sun4v/trap_table.S	(revision 74cbac7d1784d49086f1f07794c3f33e0d9ccc1c)
@@ -0,0 +1,704 @@
+#
+# Copyright (c) 2005 Jakub Jermar
+# Copyright (c) 2008 Pavel Rimsky
+# 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.
+#
+
+/**
+ * @file
+ * @brief This file contains kernel trap table.
+ */
+
+.register %g2, #scratch
+.register %g3, #scratch
+
+.text
+
+#include <arch/trap/trap_table.h>
+#include <arch/trap/regwin.h>
+#include <arch/trap/interrupt.h>
+#include <arch/trap/exception.h>
+#include <arch/trap/syscall.h>
+#include <arch/trap/sun4v/mmu.h>
+#include <arch/mm/sun4v/mmu.h>
+#include <arch/mm/page.h>
+#include <arch/stack.h>
+#include <arch/sun4v/regdef.h>
+
+#define TABLE_SIZE	TRAP_TABLE_SIZE
+#define ENTRY_SIZE	TRAP_TABLE_ENTRY_SIZE
+
+/*
+ * Kernel trap table.
+ */
+.align TABLE_SIZE
+.global trap_table
+trap_table:
+
+/* TT = 0x08, TL = 0, instruction_access_exception */
+.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
+.global instruction_access_exception_tl0
+instruction_access_exception_tl0:
+	/*wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER instruction_access_exception*/
+
+/* TT = 0x0a, TL = 0, instruction_access_error */
+.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
+.global instruction_access_error_tl0
+instruction_access_error_tl0:
+	PREEMPTIBLE_HANDLER instruction_access_error
+
+/* TT = 0x10, TL = 0, illegal_instruction */
+.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
+.global illegal_instruction_tl0
+illegal_instruction_tl0:
+	PREEMPTIBLE_HANDLER illegal_instruction
+
+/* TT = 0x11, TL = 0, privileged_opcode */
+.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
+.global privileged_opcode_tl0
+privileged_opcode_tl0:
+	PREEMPTIBLE_HANDLER privileged_opcode
+
+/* TT = 0x12, TL = 0, unimplemented_LDD */
+.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
+.global unimplemented_LDD_tl0
+unimplemented_LDD_tl0:
+	PREEMPTIBLE_HANDLER unimplemented_LDD
+
+/* TT = 0x13, TL = 0, unimplemented_STD */
+.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
+.global unimplemented_STD_tl0
+unimplemented_STD_tl0:
+	PREEMPTIBLE_HANDLER unimplemented_STD
+
+/* TT = 0x20, TL = 0, fb_disabled handler */
+.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
+.global fb_disabled_tl0
+fp_disabled_tl0:
+	PREEMPTIBLE_HANDLER fp_disabled
+
+/* TT = 0x21, TL = 0, fb_exception_ieee_754 handler */
+.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
+.global fb_exception_ieee_754_tl0
+fp_exception_ieee_754_tl0:
+	PREEMPTIBLE_HANDLER fp_exception_ieee_754
+
+/* TT = 0x22, TL = 0, fb_exception_other handler */
+.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
+.global fb_exception_other_tl0
+fp_exception_other_tl0:
+	PREEMPTIBLE_HANDLER fp_exception_other
+
+/* TT = 0x23, TL = 0, tag_overflow */
+.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
+.global tag_overflow_tl0
+tag_overflow_tl0:
+	PREEMPTIBLE_HANDLER tag_overflow
+
+/* TT = 0x24, TL = 0, clean_window handler */
+.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
+.global clean_window_tl0
+clean_window_tl0:
+	CLEAN_WINDOW_HANDLER
+
+/* TT = 0x28, TL = 0, division_by_zero */
+.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
+.global division_by_zero_tl0
+division_by_zero_tl0:
+	PREEMPTIBLE_HANDLER division_by_zero
+
+/* TT = 0x30, TL = 0, data_access_exception */
+.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
+.global data_access_exception_tl0
+data_access_exception_tl0:
+	/*wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER data_access_exception*/
+
+/* TT = 0x32, TL = 0, data_access_error */
+.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
+.global data_access_error_tl0
+data_access_error_tl0:
+	PREEMPTIBLE_HANDLER data_access_error
+
+/* TT = 0x34, TL = 0, mem_address_not_aligned */
+.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global mem_address_not_aligned_tl0
+mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER mem_address_not_aligned
+
+/* TT = 0x35, TL = 0, LDDF_mem_address_not_aligned */
+.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global LDDF_mem_address_not_aligned_tl0
+LDDF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER LDDF_mem_address_not_aligned
+
+/* TT = 0x36, TL = 0, STDF_mem_address_not_aligned */
+.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global STDF_mem_address_not_aligned_tl0
+STDF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER STDF_mem_address_not_aligned
+
+/* TT = 0x37, TL = 0, privileged_action */
+.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
+.global privileged_action_tl0
+privileged_action_tl0:
+	PREEMPTIBLE_HANDLER privileged_action
+
+/* TT = 0x38, TL = 0, LDQF_mem_address_not_aligned */
+.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global LDQF_mem_address_not_aligned_tl0
+LDQF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER LDQF_mem_address_not_aligned
+
+/* TT = 0x39, TL = 0, STQF_mem_address_not_aligned */
+.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
+.global STQF_mem_address_not_aligned_tl0
+STQF_mem_address_not_aligned_tl0:
+	PREEMPTIBLE_HANDLER STQF_mem_address_not_aligned
+
+/* TT = 0x41, TL = 0, interrupt_level_1 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
+.global interrupt_level_1_handler_tl0
+interrupt_level_1_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 1
+
+/* TT = 0x42, TL = 0, interrupt_level_2 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
+.global interrupt_level_2_handler_tl0
+interrupt_level_2_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 2
+
+/* TT = 0x43, TL = 0, interrupt_level_3 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
+.global interrupt_level_3_handler_tl0
+interrupt_level_3_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 3
+
+/* TT = 0x44, TL = 0, interrupt_level_4 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
+.global interrupt_level_4_handler_tl0
+interrupt_level_4_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 4
+
+/* TT = 0x45, TL = 0, interrupt_level_5 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
+.global interrupt_level_5_handler_tl0
+interrupt_level_5_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 5
+
+/* TT = 0x46, TL = 0, interrupt_level_6 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
+.global interrupt_level_6_handler_tl0
+interrupt_level_6_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 6
+
+/* TT = 0x47, TL = 0, interrupt_level_7 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
+.global interrupt_level_7_handler_tl0
+interrupt_level_7_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 7
+
+/* TT = 0x48, TL = 0, interrupt_level_8 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
+.global interrupt_level_8_handler_tl0
+interrupt_level_8_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 8
+
+/* TT = 0x49, TL = 0, interrupt_level_9 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
+.global interrupt_level_9_handler_tl0
+interrupt_level_9_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 9
+
+/* TT = 0x4a, TL = 0, interrupt_level_10 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
+.global interrupt_level_10_handler_tl0
+interrupt_level_10_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 10
+
+/* TT = 0x4b, TL = 0, interrupt_level_11 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
+.global interrupt_level_11_handler_tl0
+interrupt_level_11_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 11
+
+/* TT = 0x4c, TL = 0, interrupt_level_12 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
+.global interrupt_level_12_handler_tl0
+interrupt_level_12_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 12
+
+/* TT = 0x4d, TL = 0, interrupt_level_13 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
+.global interrupt_level_13_handler_tl0
+interrupt_level_13_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 13
+
+/* TT = 0x4e, TL = 0, interrupt_level_14 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
+.global interrupt_level_14_handler_tl0
+interrupt_level_14_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 14
+
+/* TT = 0x4f, TL = 0, interrupt_level_15 handler */
+.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
+.global interrupt_level_15_handler_tl0
+interrupt_level_15_handler_tl0:
+	INTERRUPT_LEVEL_N_HANDLER 15
+
+/* TT = 0x60, TL = 0, interrupt_vector_trap handler */
+.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
+.global interrupt_vector_trap_handler_tl0
+interrupt_vector_trap_handler_tl0:
+	INTERRUPT_VECTOR_TRAP_HANDLER
+
+/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
+.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
+.global fast_instruction_access_mmu_miss_handler_tl0
+fast_instruction_access_mmu_miss_handler_tl0:
+	/*FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER*/
+
+/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
+.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
+.global fast_data_access_mmu_miss_handler_tl0
+fast_data_access_mmu_miss_handler_tl0:
+	FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
+
+/* TT = 0x6c, TL = 0, fast_data_access_protection */
+.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
+.global fast_data_access_protection_handler_tl0
+fast_data_access_protection_handler_tl0:
+	/*FAST_DATA_ACCESS_PROTECTION_HANDLER 0*/
+
+/* TT = 0x80, TL = 0, spill_0_normal handler */
+.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
+.global spill_0_normal_tl0
+spill_0_normal_tl0:
+	SPILL_NORMAL_HANDLER_KERNEL
+
+/* TT = 0x84, TL = 0, spill_1_normal handler */
+.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
+.global spill_1_normal_tl0
+spill_1_normal_tl0:
+	SPILL_NORMAL_HANDLER_USERSPACE
+
+/* TT = 0x88, TL = 0, spill_2_normal handler */
+.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
+.global spill_2_normal_tl0
+spill_2_normal_tl0:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xa0, TL = 0, spill_0_other handler */
+.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
+.global spill_0_other_tl0
+spill_0_other_tl0:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xc0, TL = 0, fill_0_normal handler */
+.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
+.global fill_0_normal_tl0
+fill_0_normal_tl0:
+	FILL_NORMAL_HANDLER_KERNEL
+
+/* TT = 0xc4, TL = 0, fill_1_normal handler */
+.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
+.global fill_1_normal_tl0
+fill_1_normal_tl0:
+	FILL_NORMAL_HANDLER_USERSPACE
+
+/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
+.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
+    20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
+    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
+    58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
+    77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
+    96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
+    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
+    127
+.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
+.global trap_instruction_\cur\()_tl0
+trap_instruction_\cur\()_tl0:
+	ba trap_instruction_handler
+	mov \cur, %g2
+.endr
+
+/*
+ * Handlers for TL>0.
+ */
+
+/* TT = 0x08, TL > 0, instruction_access_exception */
+.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
+.global instruction_access_exception_tl1
+instruction_access_exception_tl1:
+	/*wrpr %g0, 1, %tl
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER instruction_access_exception*/
+
+/* TT = 0x0a, TL > 0, instruction_access_error */
+.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
+.global instruction_access_error_tl1
+instruction_access_error_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER instruction_access_error
+
+/* TT = 0x10, TL > 0, illegal_instruction */
+.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
+.global illegal_instruction_tl1
+illegal_instruction_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER illegal_instruction
+
+/* TT = 0x24, TL > 0, clean_window handler */
+.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
+.global clean_window_tl1
+clean_window_tl1:
+	CLEAN_WINDOW_HANDLER
+
+/* TT = 0x28, TL > 0, division_by_zero */
+.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
+.global division_by_zero_tl1
+division_by_zero_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER division_by_zero
+
+/* TT = 0x30, TL > 0, data_access_exception */
+.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
+.global data_access_exception_tl1
+data_access_exception_tl1:
+	/*wrpr %g0, 1, %tl
+	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
+	PREEMPTIBLE_HANDLER data_access_exception*/
+
+/* TT = 0x32, TL > 0, data_access_error */
+.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
+.global data_access_error_tl1
+data_access_error_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER data_access_error
+
+/* TT = 0x34, TL > 0, mem_address_not_aligned */
+.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
+.global mem_address_not_aligned_tl1
+mem_address_not_aligned_tl1:
+	wrpr %g0, 1, %tl
+	PREEMPTIBLE_HANDLER mem_address_not_aligned
+
+/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
+.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
+.global fast_data_access_mmu_miss_handler_tl1
+fast_data_access_mmu_miss_handler_tl1:
+	FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
+
+/* TT = 0x6c, TL > 0, fast_data_access_protection */
+.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
+.global fast_data_access_protection_handler_tl1
+fast_data_access_protection_handler_tl1:
+	/*FAST_DATA_ACCESS_PROTECTION_HANDLER 1*/
+
+/* TT = 0x80, TL > 0, spill_0_normal handler */
+.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
+.global spill_0_normal_tl1
+spill_0_normal_tl1:
+	SPILL_NORMAL_HANDLER_KERNEL
+
+/* TT = 0x88, TL > 0, spill_2_normal handler */
+.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
+.global spill_2_normal_tl1
+spill_2_normal_tl1:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xa0, TL > 0, spill_0_other handler */
+.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
+.global spill_0_other_tl1
+spill_0_other_tl1:
+	SPILL_TO_USPACE_WINDOW_BUFFER
+
+/* TT = 0xc0, TL > 0, fill_0_normal handler */
+.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
+.global fill_0_normal_tl1
+fill_0_normal_tl1:
+	FILL_NORMAL_HANDLER_KERNEL
+
+.align TABLE_SIZE
+
+
+/*
+ * Spills the window at CWP + 2 to the kernel stack. This macro is to be
+ * used before doing SAVE when the spill trap is undesirable.
+ * 
+ * Parameters:
+ * 	tmpreg1		global register to be used for scratching purposes
+ * 	tmpreg2		global register to be used for scratching purposes
+ */
+.macro INLINE_SPILL tmpreg1, tmpreg2
+	! CWP := CWP + 2
+	rdpr %cwp, \tmpreg2
+	add \tmpreg2, 2, \tmpreg1
+	and \tmpreg1, NWINDOWS - 1, \tmpreg1		! modulo NWINDOWS
+	wrpr \tmpreg1, %cwp
+	
+	! spill to kernel stack
+	stx %l0, [%sp + STACK_BIAS + L0_OFFSET]	
+	stx %l1, [%sp + STACK_BIAS + L1_OFFSET]
+	stx %l2, [%sp + STACK_BIAS + L2_OFFSET]
+	stx %l3, [%sp + STACK_BIAS + L3_OFFSET]
+	stx %l4, [%sp + STACK_BIAS + L4_OFFSET]
+	stx %l5, [%sp + STACK_BIAS + L5_OFFSET]
+	stx %l6, [%sp + STACK_BIAS + L6_OFFSET]
+	stx %l7, [%sp + STACK_BIAS + L7_OFFSET]
+	stx %i0, [%sp + STACK_BIAS + I0_OFFSET]
+	stx %i1, [%sp + STACK_BIAS + I1_OFFSET]
+	stx %i2, [%sp + STACK_BIAS + I2_OFFSET]
+	stx %i3, [%sp + STACK_BIAS + I3_OFFSET]
+	stx %i4, [%sp + STACK_BIAS + I4_OFFSET]
+	stx %i5, [%sp + STACK_BIAS + I5_OFFSET]
+	stx %i6, [%sp + STACK_BIAS + I6_OFFSET]
+	stx %i7, [%sp + STACK_BIAS + I7_OFFSET]
+
+	! CWP := CWP - 2
+	wrpr \tmpreg2, %cwp
+
+	saved
+.endm
+
+/*
+ * Fill the window at CWP - 1 from the kernel stack. This macro is to be
+ * used before doing RESTORE when the fill trap is undesirable.
+ * 
+ * Parameters:
+ * 	tmpreg1		global register to be used for scratching purposes
+ * 	tmpreg2		global register to be used for scratching purposes
+ */
+.macro INLINE_FILL tmpreg1, tmpreg2
+	! CWP := CWP - 1
+	rdpr %cwp, \tmpreg2
+	add \tmpreg2, NWINDOWS - 1, \tmpreg1
+	and \tmpreg1, NWINDOWS - 1, \tmpreg1
+	wrpr \tmpreg1, %cwp
+
+	! fill from kernel stack
+	ldx [%sp + STACK_BIAS + L0_OFFSET], %l0
+	ldx [%sp + STACK_BIAS + L1_OFFSET], %l1
+	ldx [%sp + STACK_BIAS + L2_OFFSET], %l2
+	ldx [%sp + STACK_BIAS + L3_OFFSET], %l3
+	ldx [%sp + STACK_BIAS + L4_OFFSET], %l4
+	ldx [%sp + STACK_BIAS + L5_OFFSET], %l5
+	ldx [%sp + STACK_BIAS + L6_OFFSET], %l6
+	ldx [%sp + STACK_BIAS + L7_OFFSET], %l7
+	ldx [%sp + STACK_BIAS + I0_OFFSET], %i0
+	ldx [%sp + STACK_BIAS + I1_OFFSET], %i1
+	ldx [%sp + STACK_BIAS + I2_OFFSET], %i2
+	ldx [%sp + STACK_BIAS + I3_OFFSET], %i3
+	ldx [%sp + STACK_BIAS + I4_OFFSET], %i4
+	ldx [%sp + STACK_BIAS + I5_OFFSET], %i5
+	ldx [%sp + STACK_BIAS + I6_OFFSET], %i6
+	ldx [%sp + STACK_BIAS + I7_OFFSET], %i7
+
+	! CWP := CWP + 1
+	wrpr \tmpreg2, %cwp
+
+	restored
+.endm
+
+/*
+ * Preemptible trap handler for handling traps from kernel.
+ */
+.macro PREEMPTIBLE_HANDLER_KERNEL
+
+	/*
+	 * ASSERT(%tl == 1)
+	 */
+	rdpr %tl, %g3
+	cmp %g3, 1
+	be 1f
+	nop
+0:	ba 0b					! this is for debugging, if we ever get here
+	nop					! it will be easy to find
+
+	/* prevent unnecessary CLEANWIN exceptions */
+	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
+1:
+	/*
+	 * Prevent SAVE instruction from causing a spill exception. If the
+	 * CANSAVE register is zero, explicitly spill register window
+	 * at CWP + 2.
+	 */
+
+	rdpr %cansave, %g3
+	brnz %g3, 2f
+	nop
+	INLINE_SPILL %g3, %g4
+
+2:
+	/* ask for new register window */
+	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
+
+	/* copy higher level routine's address and its argument */
+	mov %g1, %l0
+	mov %g2, %o0
+
+	/*
+	 * Save TSTATE, TPC and TNPC aside.
+	 */
+	rdpr %tstate, %g1
+	rdpr %tpc, %g2
+	rdpr %tnpc, %g3
+
+	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
+	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
+	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
+
+	/*
+	 * Save the Y register.
+	 * This register is deprecated according to SPARC V9 specification
+	 * and is only present for backward compatibility with previous
+	 * versions of the SPARC architecture.
+	 * Surprisingly, gcc makes use of this register without a notice.
+	 */
+	rd %y, %g4
+	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
+
+	/* switch to TL = 0, explicitly enable FPU */
+	wrpr %g0, 0, %tl
+	wrpr %g0, 0, %gl
+	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
+
+	/* g1 -> l1, ..., g7 -> l7 */
+	SAVE_GLOBALS
+
+	/* call higher-level service routine, pass istate as its 2nd parameter */
+	call %l0
+	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
+
+	/* l1 -> g1, ..., l7 -> g7 */
+	RESTORE_GLOBALS
+
+	/* we must prserve the PEF bit */
+	rdpr %pstate, %l1
+
+	/* TL := 1, GL := 1 */
+	wrpr %g0, PSTATE_PRIV_BIT, %pstate
+	wrpr %g0, 1, %tl
+	wrpr %g0, 1, %gl
+
+	/* Read TSTATE, TPC and TNPC from saved copy. */
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
+
+	/* Copy PSTATE.PEF to the in-register copy of TSTATE. */
+	and %l1, PSTATE_PEF_BIT, %l1
+	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
+	sethi %hi(TSTATE_PEF_BIT), %g4		! reset the PEF bit to 0 ...
+	andn %g1, %g4, %g1
+	or %g1, %l1, %g1			! ... "or" it with saved PEF
+
+	/* Restore TSTATE, TPC and TNPC from saved copies. */
+	wrpr %g1, 0, %tstate
+	wrpr %g2, 0, %tpc
+	wrpr %g3, 0, %tnpc
+
+	/* Restore Y. */
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
+	wr %g4, %y
+	
+	/* If TSTATE.CWP + 1 == CWP, then we do not have to fix CWP. */
+	and %g1, TSTATE_CWP_MASK, %l0
+	inc %l0
+	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
+	rdpr %cwp, %l1
+	cmp %l0, %l1
+	bz 4f				! CWP is ok
+	nop
+
+3:
+	/*
+	 * Fix CWP.
+	 * In order to recapitulate, the input registers in the current
+	 * window are the output registers of the window to which we want
+	 * to restore. Because the fill trap fills only input and local
+	 * registers of a window, we need to preserve those output
+	 * registers manually.
+	 */
+	mov %sp, %g2
+	stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
+	stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
+	stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
+	stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
+	stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
+	stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
+	stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
+	stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
+	wrpr %l0, 0, %cwp
+	mov %g2, %sp
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
+	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
+
+4:
+	/*
+	 * Prevent RESTORE instruction from causing a fill exception. If the
+	 * CANRESTORE register is zero, explicitly fill register window
+	 * at CWP - 1.
+	 */
+	rdpr %canrestore, %g1
+	brnz %g1, 5f
+	nop
+	INLINE_FILL %g3, %g4
+
+5:
+	restore
+
+	retry
+.endm
+
+
+#define NOT(x)	((x) == 0)
+
+/* Preemptible trap handler for TL=1.
+ *
+ * This trap handler makes arrangements to make calling of scheduler() from
+ * within a trap context possible. It is called from several other trap
+ * handlers.
+ */
+.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
+	PREEMPTIBLE_HANDLER_KERNEL
+.endm
+
+.global preemptible_handler
+preemptible_handler:
+	PREEMPTIBLE_HANDLER_TEMPLATE 0
+
+.global trap_instruction_handler
+trap_instruction_handler:
+	PREEMPTIBLE_HANDLER_TEMPLATE 1
+
Index: kernel/arch/sparc64/src/trap/trap_table.S
===================================================================
--- kernel/arch/sparc64/src/trap/trap_table.S	(revision b4655da89eb65d1571b8afdfdbbb34449add2ef7)
+++ 	(revision )
@@ -1,851 +1,0 @@
-#
-# 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.
-#
-
-/**
- * @file
- * @brief This file contains kernel trap table.
- */
-
-.register %g2, #scratch
-.register %g3, #scratch
-
-.text
-
-#include <arch/trap/trap_table.h>
-#include <arch/trap/regwin.h>
-#include <arch/trap/interrupt.h>
-#include <arch/trap/exception.h>
-#include <arch/trap/syscall.h>
-#include <arch/trap/mmu.h>
-#include <arch/mm/mmu.h>
-#include <arch/mm/page.h>
-#include <arch/stack.h>
-#include <arch/regdef.h>
-
-#define TABLE_SIZE	TRAP_TABLE_SIZE
-#define ENTRY_SIZE	TRAP_TABLE_ENTRY_SIZE
-
-/*
- * Kernel trap table.
- */
-.align TABLE_SIZE
-.global trap_table
-trap_table:
-
-/* TT = 0x08, TL = 0, instruction_access_exception */
-.org trap_table + TT_INSTRUCTION_ACCESS_EXCEPTION*ENTRY_SIZE
-.global instruction_access_exception_tl0
-instruction_access_exception_tl0:
-	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
-	PREEMPTIBLE_HANDLER instruction_access_exception
-
-/* TT = 0x0a, TL = 0, instruction_access_error */
-.org trap_table + TT_INSTRUCTION_ACCESS_ERROR*ENTRY_SIZE
-.global instruction_access_error_tl0
-instruction_access_error_tl0:
-	PREEMPTIBLE_HANDLER instruction_access_error
-
-/* TT = 0x10, TL = 0, illegal_instruction */
-.org trap_table + TT_ILLEGAL_INSTRUCTION*ENTRY_SIZE
-.global illegal_instruction_tl0
-illegal_instruction_tl0:
-	PREEMPTIBLE_HANDLER illegal_instruction
-
-/* TT = 0x11, TL = 0, privileged_opcode */
-.org trap_table + TT_PRIVILEGED_OPCODE*ENTRY_SIZE
-.global privileged_opcode_tl0
-privileged_opcode_tl0:
-	PREEMPTIBLE_HANDLER privileged_opcode
-
-/* TT = 0x12, TL = 0, unimplemented_LDD */
-.org trap_table + TT_UNIMPLEMENTED_LDD*ENTRY_SIZE
-.global unimplemented_LDD_tl0
-unimplemented_LDD_tl0:
-	PREEMPTIBLE_HANDLER unimplemented_LDD
-
-/* TT = 0x13, TL = 0, unimplemented_STD */
-.org trap_table + TT_UNIMPLEMENTED_STD*ENTRY_SIZE
-.global unimplemented_STD_tl0
-unimplemented_STD_tl0:
-	PREEMPTIBLE_HANDLER unimplemented_STD
-
-/* TT = 0x20, TL = 0, fb_disabled handler */
-.org trap_table + TT_FP_DISABLED*ENTRY_SIZE
-.global fb_disabled_tl0
-fp_disabled_tl0:
-	PREEMPTIBLE_HANDLER fp_disabled
-
-/* TT = 0x21, TL = 0, fb_exception_ieee_754 handler */
-.org trap_table + TT_FP_EXCEPTION_IEEE_754*ENTRY_SIZE
-.global fb_exception_ieee_754_tl0
-fp_exception_ieee_754_tl0:
-	PREEMPTIBLE_HANDLER fp_exception_ieee_754
-
-/* TT = 0x22, TL = 0, fb_exception_other handler */
-.org trap_table + TT_FP_EXCEPTION_OTHER*ENTRY_SIZE
-.global fb_exception_other_tl0
-fp_exception_other_tl0:
-	PREEMPTIBLE_HANDLER fp_exception_other
-
-/* TT = 0x23, TL = 0, tag_overflow */
-.org trap_table + TT_TAG_OVERFLOW*ENTRY_SIZE
-.global tag_overflow_tl0
-tag_overflow_tl0:
-	PREEMPTIBLE_HANDLER tag_overflow
-
-/* TT = 0x24, TL = 0, clean_window handler */
-.org trap_table + TT_CLEAN_WINDOW*ENTRY_SIZE
-.global clean_window_tl0
-clean_window_tl0:
-	CLEAN_WINDOW_HANDLER
-
-/* TT = 0x28, TL = 0, division_by_zero */
-.org trap_table + TT_DIVISION_BY_ZERO*ENTRY_SIZE
-.global division_by_zero_tl0
-division_by_zero_tl0:
-	PREEMPTIBLE_HANDLER division_by_zero
-
-/* TT = 0x30, TL = 0, data_access_exception */
-.org trap_table + TT_DATA_ACCESS_EXCEPTION*ENTRY_SIZE
-.global data_access_exception_tl0
-data_access_exception_tl0:
-	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
-	PREEMPTIBLE_HANDLER data_access_exception
-
-/* TT = 0x32, TL = 0, data_access_error */
-.org trap_table + TT_DATA_ACCESS_ERROR*ENTRY_SIZE
-.global data_access_error_tl0
-data_access_error_tl0:
-	PREEMPTIBLE_HANDLER data_access_error
-
-/* TT = 0x34, TL = 0, mem_address_not_aligned */
-.org trap_table + TT_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
-.global mem_address_not_aligned_tl0
-mem_address_not_aligned_tl0:
-	PREEMPTIBLE_HANDLER mem_address_not_aligned
-
-/* TT = 0x35, TL = 0, LDDF_mem_address_not_aligned */
-.org trap_table + TT_LDDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
-.global LDDF_mem_address_not_aligned_tl0
-LDDF_mem_address_not_aligned_tl0:
-	PREEMPTIBLE_HANDLER LDDF_mem_address_not_aligned
-
-/* TT = 0x36, TL = 0, STDF_mem_address_not_aligned */
-.org trap_table + TT_STDF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
-.global STDF_mem_address_not_aligned_tl0
-STDF_mem_address_not_aligned_tl0:
-	PREEMPTIBLE_HANDLER STDF_mem_address_not_aligned
-
-/* TT = 0x37, TL = 0, privileged_action */
-.org trap_table + TT_PRIVILEGED_ACTION*ENTRY_SIZE
-.global privileged_action_tl0
-privileged_action_tl0:
-	PREEMPTIBLE_HANDLER privileged_action
-
-/* TT = 0x38, TL = 0, LDQF_mem_address_not_aligned */
-.org trap_table + TT_LDQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
-.global LDQF_mem_address_not_aligned_tl0
-LDQF_mem_address_not_aligned_tl0:
-	PREEMPTIBLE_HANDLER LDQF_mem_address_not_aligned
-
-/* TT = 0x39, TL = 0, STQF_mem_address_not_aligned */
-.org trap_table + TT_STQF_MEM_ADDRESS_NOT_ALIGNED*ENTRY_SIZE
-.global STQF_mem_address_not_aligned_tl0
-STQF_mem_address_not_aligned_tl0:
-	PREEMPTIBLE_HANDLER STQF_mem_address_not_aligned
-
-/* TT = 0x41, TL = 0, interrupt_level_1 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_1*ENTRY_SIZE
-.global interrupt_level_1_handler_tl0
-interrupt_level_1_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 1
-
-/* TT = 0x42, TL = 0, interrupt_level_2 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_2*ENTRY_SIZE
-.global interrupt_level_2_handler_tl0
-interrupt_level_2_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 2
-
-/* TT = 0x43, TL = 0, interrupt_level_3 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_3*ENTRY_SIZE
-.global interrupt_level_3_handler_tl0
-interrupt_level_3_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 3
-
-/* TT = 0x44, TL = 0, interrupt_level_4 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_4*ENTRY_SIZE
-.global interrupt_level_4_handler_tl0
-interrupt_level_4_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 4
-
-/* TT = 0x45, TL = 0, interrupt_level_5 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_5*ENTRY_SIZE
-.global interrupt_level_5_handler_tl0
-interrupt_level_5_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 5
-
-/* TT = 0x46, TL = 0, interrupt_level_6 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_6*ENTRY_SIZE
-.global interrupt_level_6_handler_tl0
-interrupt_level_6_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 6
-
-/* TT = 0x47, TL = 0, interrupt_level_7 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_7*ENTRY_SIZE
-.global interrupt_level_7_handler_tl0
-interrupt_level_7_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 7
-
-/* TT = 0x48, TL = 0, interrupt_level_8 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_8*ENTRY_SIZE
-.global interrupt_level_8_handler_tl0
-interrupt_level_8_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 8
-
-/* TT = 0x49, TL = 0, interrupt_level_9 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_9*ENTRY_SIZE
-.global interrupt_level_9_handler_tl0
-interrupt_level_9_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 9
-
-/* TT = 0x4a, TL = 0, interrupt_level_10 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_10*ENTRY_SIZE
-.global interrupt_level_10_handler_tl0
-interrupt_level_10_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 10
-
-/* TT = 0x4b, TL = 0, interrupt_level_11 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_11*ENTRY_SIZE
-.global interrupt_level_11_handler_tl0
-interrupt_level_11_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 11
-
-/* TT = 0x4c, TL = 0, interrupt_level_12 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_12*ENTRY_SIZE
-.global interrupt_level_12_handler_tl0
-interrupt_level_12_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 12
-
-/* TT = 0x4d, TL = 0, interrupt_level_13 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_13*ENTRY_SIZE
-.global interrupt_level_13_handler_tl0
-interrupt_level_13_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 13
-
-/* TT = 0x4e, TL = 0, interrupt_level_14 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_14*ENTRY_SIZE
-.global interrupt_level_14_handler_tl0
-interrupt_level_14_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 14
-
-/* TT = 0x4f, TL = 0, interrupt_level_15 handler */
-.org trap_table + TT_INTERRUPT_LEVEL_15*ENTRY_SIZE
-.global interrupt_level_15_handler_tl0
-interrupt_level_15_handler_tl0:
-	INTERRUPT_LEVEL_N_HANDLER 15
-
-/* TT = 0x60, TL = 0, interrupt_vector_trap handler */
-.org trap_table + TT_INTERRUPT_VECTOR_TRAP*ENTRY_SIZE
-.global interrupt_vector_trap_handler_tl0
-interrupt_vector_trap_handler_tl0:
-	INTERRUPT_VECTOR_TRAP_HANDLER
-
-/* TT = 0x64, TL = 0, fast_instruction_access_MMU_miss */
-.org trap_table + TT_FAST_INSTRUCTION_ACCESS_MMU_MISS*ENTRY_SIZE
-.global fast_instruction_access_mmu_miss_handler_tl0
-fast_instruction_access_mmu_miss_handler_tl0:
-	FAST_INSTRUCTION_ACCESS_MMU_MISS_HANDLER
-
-/* TT = 0x68, TL = 0, fast_data_access_MMU_miss */
-.org trap_table + TT_FAST_DATA_ACCESS_MMU_MISS*ENTRY_SIZE
-.global fast_data_access_mmu_miss_handler_tl0
-fast_data_access_mmu_miss_handler_tl0:
-	FAST_DATA_ACCESS_MMU_MISS_HANDLER 0
-
-/* TT = 0x6c, TL = 0, fast_data_access_protection */
-.org trap_table + TT_FAST_DATA_ACCESS_PROTECTION*ENTRY_SIZE
-.global fast_data_access_protection_handler_tl0
-fast_data_access_protection_handler_tl0:
-	FAST_DATA_ACCESS_PROTECTION_HANDLER 0
-
-/* TT = 0x80, TL = 0, spill_0_normal handler */
-.org trap_table + TT_SPILL_0_NORMAL*ENTRY_SIZE
-.global spill_0_normal_tl0
-spill_0_normal_tl0:
-	SPILL_NORMAL_HANDLER_KERNEL
-
-/* TT = 0x84, TL = 0, spill_1_normal handler */
-.org trap_table + TT_SPILL_1_NORMAL*ENTRY_SIZE
-.global spill_1_normal_tl0
-spill_1_normal_tl0:
-	SPILL_NORMAL_HANDLER_USERSPACE
-
-/* TT = 0x88, TL = 0, spill_2_normal handler */
-.org trap_table + TT_SPILL_2_NORMAL*ENTRY_SIZE
-.global spill_2_normal_tl0
-spill_2_normal_tl0:
-	SPILL_TO_USPACE_WINDOW_BUFFER
-
-/* TT = 0xa0, TL = 0, spill_0_other handler */
-.org trap_table + TT_SPILL_0_OTHER*ENTRY_SIZE
-.global spill_0_other_tl0
-spill_0_other_tl0:
-	SPILL_TO_USPACE_WINDOW_BUFFER
-
-/* TT = 0xc0, TL = 0, fill_0_normal handler */
-.org trap_table + TT_FILL_0_NORMAL*ENTRY_SIZE
-.global fill_0_normal_tl0
-fill_0_normal_tl0:
-	FILL_NORMAL_HANDLER_KERNEL
-
-/* TT = 0xc4, TL = 0, fill_1_normal handler */
-.org trap_table + TT_FILL_1_NORMAL*ENTRY_SIZE
-.global fill_1_normal_tl0
-fill_1_normal_tl0:
-	FILL_NORMAL_HANDLER_USERSPACE
-
-/* TT = 0x100 - 0x17f, TL = 0, trap_instruction_0 - trap_instruction_7f */
-.irp cur, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,\
-    20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38,\
-    39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,\
-    58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76,\
-    77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,\
-    96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,\
-    112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126,\
-    127
-.org trap_table + (TT_TRAP_INSTRUCTION_0+\cur)*ENTRY_SIZE
-.global trap_instruction_\cur\()_tl0
-trap_instruction_\cur\()_tl0:
-	ba %xcc, trap_instruction_handler
-	mov \cur, %g2
-.endr
-
-/*
- * Handlers for TL>0.
- */
-
-/* TT = 0x08, TL > 0, instruction_access_exception */
-.org trap_table + (TT_INSTRUCTION_ACCESS_EXCEPTION+512)*ENTRY_SIZE
-.global instruction_access_exception_tl1
-instruction_access_exception_tl1:
-	wrpr %g0, 1, %tl
-	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
-	PREEMPTIBLE_HANDLER instruction_access_exception
-
-/* TT = 0x0a, TL > 0, instruction_access_error */
-.org trap_table + (TT_INSTRUCTION_ACCESS_ERROR+512)*ENTRY_SIZE
-.global instruction_access_error_tl1
-instruction_access_error_tl1:
-	wrpr %g0, 1, %tl
-	PREEMPTIBLE_HANDLER instruction_access_error
-
-/* TT = 0x10, TL > 0, illegal_instruction */
-.org trap_table + (TT_ILLEGAL_INSTRUCTION+512)*ENTRY_SIZE
-.global illegal_instruction_tl1
-illegal_instruction_tl1:
-	wrpr %g0, 1, %tl
-	PREEMPTIBLE_HANDLER illegal_instruction
-
-/* TT = 0x24, TL > 0, clean_window handler */
-.org trap_table + (TT_CLEAN_WINDOW+512)*ENTRY_SIZE
-.global clean_window_tl1
-clean_window_tl1:
-	CLEAN_WINDOW_HANDLER
-
-/* TT = 0x28, TL > 0, division_by_zero */
-.org trap_table + (TT_DIVISION_BY_ZERO+512)*ENTRY_SIZE
-.global division_by_zero_tl1
-division_by_zero_tl1:
-	wrpr %g0, 1, %tl
-	PREEMPTIBLE_HANDLER division_by_zero
-
-/* TT = 0x30, TL > 0, data_access_exception */
-.org trap_table + (TT_DATA_ACCESS_EXCEPTION+512)*ENTRY_SIZE
-.global data_access_exception_tl1
-data_access_exception_tl1:
-	wrpr %g0, 1, %tl
-	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
-	PREEMPTIBLE_HANDLER data_access_exception
-
-/* TT = 0x32, TL > 0, data_access_error */
-.org trap_table + (TT_DATA_ACCESS_ERROR+512)*ENTRY_SIZE
-.global data_access_error_tl1
-data_access_error_tl1:
-	wrpr %g0, 1, %tl
-	PREEMPTIBLE_HANDLER data_access_error
-
-/* TT = 0x34, TL > 0, mem_address_not_aligned */
-.org trap_table + (TT_MEM_ADDRESS_NOT_ALIGNED+512)*ENTRY_SIZE
-.global mem_address_not_aligned_tl1
-mem_address_not_aligned_tl1:
-	wrpr %g0, 1, %tl
-	PREEMPTIBLE_HANDLER mem_address_not_aligned
-
-/* TT = 0x68, TL > 0, fast_data_access_MMU_miss */
-.org trap_table + (TT_FAST_DATA_ACCESS_MMU_MISS+512)*ENTRY_SIZE
-.global fast_data_access_mmu_miss_handler_tl1
-fast_data_access_mmu_miss_handler_tl1:
-	FAST_DATA_ACCESS_MMU_MISS_HANDLER 1
-
-/* TT = 0x6c, TL > 0, fast_data_access_protection */
-.org trap_table + (TT_FAST_DATA_ACCESS_PROTECTION+512)*ENTRY_SIZE
-.global fast_data_access_protection_handler_tl1
-fast_data_access_protection_handler_tl1:
-	FAST_DATA_ACCESS_PROTECTION_HANDLER 1
-
-/* TT = 0x80, TL > 0, spill_0_normal handler */
-.org trap_table + (TT_SPILL_0_NORMAL+512)*ENTRY_SIZE
-.global spill_0_normal_tl1
-spill_0_normal_tl1:
-	SPILL_NORMAL_HANDLER_KERNEL
-
-/* TT = 0x88, TL > 0, spill_2_normal handler */
-.org trap_table + (TT_SPILL_2_NORMAL+512)*ENTRY_SIZE
-.global spill_2_normal_tl1
-spill_2_normal_tl1:
-	SPILL_TO_USPACE_WINDOW_BUFFER
-
-/* TT = 0xa0, TL > 0, spill_0_other handler */
-.org trap_table + (TT_SPILL_0_OTHER+512)*ENTRY_SIZE
-.global spill_0_other_tl1
-spill_0_other_tl1:
-	SPILL_TO_USPACE_WINDOW_BUFFER
-
-/* TT = 0xc0, TL > 0, fill_0_normal handler */
-.org trap_table + (TT_FILL_0_NORMAL+512)*ENTRY_SIZE
-.global fill_0_normal_tl1
-fill_0_normal_tl1:
-	FILL_NORMAL_HANDLER_KERNEL
-
-.align TABLE_SIZE
-
-
-#define NOT(x)	((x) == 0)
-
-/* Preemptible trap handler for TL=1.
- *
- * This trap handler makes arrangements to make calling of scheduler() from
- * within a trap context possible. It is called from several other trap
- * handlers.
- *
- * This function can be entered either with interrupt globals or alternate
- * globals. Memory management trap handlers are obliged to switch to one of
- * those global sets prior to calling this function. Register window management
- * functions are not allowed to modify the alternate global registers.
- *
- * The kernel is designed to work on trap levels 0 - 4. For instance, the
- * following can happen:
- * TL0: kernel thread runs (CANSAVE=0, kernel stack not in DTLB)
- * TL1: preemptible trap handler started after a tick interrupt
- * TL2: preemptible trap handler did SAVE
- * TL3: spill handler touched the kernel stack  
- * TL4: hardware or software failure
- *
- * Input registers:
- *	%g1		Address of function to call if this is not a syscall.
- * 	%g2	 	First argument for the function.
- *	%g6		Pre-set as kernel stack base if trap from userspace.
- *	%g7		Pre-set as address of the userspace window buffer.
- */
-.macro PREEMPTIBLE_HANDLER_TEMPLATE is_syscall
-	/*
-	 * ASSERT(%tl == 1)
-	 */
-	rdpr %tl, %g3
-	cmp %g3, 1
-	be %xcc, 1f
-	nop
-0:	ba %xcc, 0b				! this is for debugging, if we ever get here
-	nop					! it will be easy to find
-
-1:
-.if NOT(\is_syscall)
-	rdpr %tstate, %g3
-	
-	/*
-	 * One of the ways this handler can be invoked is after a nested MMU trap from
-	 * either spill_1_normal or fill_1_normal traps. Both of these traps manipulate
-	 * the CWP register. We deal with the situation by simulating the MMU trap
-	 * on TL=1 and restart the respective SAVE or RESTORE instruction once the MMU
-	 * trap is resolved. However, because we are in the wrong window from the
-	 * perspective of the MMU trap, we need to synchronize CWP with CWP from TL=0.
-	 */ 
-	and %g3, TSTATE_CWP_MASK, %g4
-	wrpr %g4, 0, %cwp			! resynchronize CWP
-
-	andcc %g3, TSTATE_PRIV_BIT, %g0		! if this trap came from the privileged mode...
-	bnz %xcc, 0f				! ...skip setting of kernel stack and primary context
-	nop
-	
-.endif
-	/*
-	 * Normal window spills will go to the userspace window buffer.
-	 */
-	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(2), %wstate
-
-	wrpr %g0, NWINDOWS - 1, %cleanwin	! prevent unnecessary clean_window exceptions
-
-	/*
-	 * Switch to kernel stack. The old stack is
-	 * automatically saved in the old window's %sp
-	 * and the new window's %fp.
-	 */
-	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
-.if \is_syscall
-	/*
-	 * Copy arguments for the syscall to the new window.
-	 */
-	mov %i0, %o0
-	mov %i1, %o1
-	mov %i2, %o2
-	mov %i3, %o3
-	mov %i4, %o4
-	mov %i5, %o5
-.endif
-
-	/*
-	 * Mark the CANRESTORE windows as OTHER windows.
-	 */
-	rdpr %canrestore, %l0
-	wrpr %l0, %otherwin
-	wrpr %g0, %canrestore
-
-	/*
-	 * Switch to primary context 0.
-	 */
-	mov VA_PRIMARY_CONTEXT_REG, %l0
-	stxa %g0, [%l0] ASI_DMMU
-	rd %pc, %l0
-	flush %l0
-
-.if NOT(\is_syscall)
-	ba %xcc, 1f
-	nop
-0:
-	save %sp, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-
-	/*
-	 * At this moment, we are using the kernel stack 
-	 * and have successfully allocated a register window.
-	 */
-1:
-.endif
-	/*
-	 * Other window spills will go to the userspace window buffer
-	 * and normal spills will go to the kernel stack.
-	 */
-	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(0), %wstate
-	
-	/*
-	 * Copy arguments.
-	 */
-	mov %g1, %l0
-.if NOT(\is_syscall)
-	mov %g2, %o0
-.else
-	! store the syscall number on the stack as 7th argument
-	stx %g2, [%sp + STACK_WINDOW_SAVE_AREA_SIZE + STACK_BIAS + STACK_ARG6] 
-.endif
-
-	/*
-	 * Save TSTATE, TPC and TNPC aside.
-	 */
-	rdpr %tstate, %g1
-	rdpr %tpc, %g2
-	rdpr %tnpc, %g3
-	rd %y, %g4
-
-	stx %g1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE]
-	stx %g2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC]
-	stx %g3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC]
-
-	/*
-	 * Save the Y register.
-	 * This register is deprecated according to SPARC V9 specification
-	 * and is only present for backward compatibility with previous
-	 * versions of the SPARC architecture.
-	 * Surprisingly, gcc makes use of this register without a notice.
-	 */
-	stx %g4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y]
-	
-	wrpr %g0, 0, %tl
-	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT, %pstate
-	SAVE_GLOBALS
-	
-.if NOT(\is_syscall)
-	/*
-	 * Call the higher-level handler and pass istate as second parameter.
-	 */
-	call %l0
-	add %sp, PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC, %o1
-.else
-	/*
-	 * Call the higher-level syscall handler and enable interrupts.
-	 */
-	call syscall_handler
-	wrpr %g0, PSTATE_PRIV_BIT | PSTATE_PEF_BIT | PSTATE_IE_BIT, %pstate
-	mov %o0, %i0				! copy the value returned by the syscall
-.endif
-
-	RESTORE_GLOBALS
-	rdpr %pstate, %l1			! we must preserve the PEF bit
-	wrpr %g0, PSTATE_AG_BIT | PSTATE_PRIV_BIT, %pstate
-	wrpr %g0, 1, %tl
-	
-	/*
-	 * Read TSTATE, TPC and TNPC from saved copy.
-	 */
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TSTATE], %g1
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TPC], %g2
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_TNPC], %g3
-
-	/*
-	 * Copy PSTATE.PEF to the in-register copy of TSTATE.
-	 */
-	and %l1, PSTATE_PEF_BIT, %l1
-	sllx %l1, TSTATE_PSTATE_SHIFT, %l1
-	sethi %hi(TSTATE_PEF_BIT), %g4
-	andn %g1, %g4, %g1
-	or %g1, %l1, %g1
-
-	/*
-	 * Restore TSTATE, TPC and TNPC from saved copies.
-	 */
-	wrpr %g1, 0, %tstate
-	wrpr %g2, 0, %tpc
-	wrpr %g3, 0, %tnpc
-
-	/*
-	 * Restore Y.
-	 */
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_Y], %g4
-	wr %g4, %y
-
-	/*
-	 * If OTHERWIN is zero, then all the userspace windows have been
-	 * spilled to kernel memory (i.e. register window buffer). Moreover,
-	 * if the scheduler was called in the meantime, all valid windows
-	 * belonging to other threads were spilled by context_restore().
-	 * If OTHERWIN is non-zero, then some userspace windows are still
-	 * valid. Others might have been spilled. However, the CWP pointer
-	 * needs no fixing because the scheduler had not been called.
-	 */
-	rdpr %otherwin, %l0
-	brnz %l0, 0f
-	nop
-
-	/*
-	 * OTHERWIN == 0
-	 */
-
-	/*
-	 * If TSTATE.CWP + 1 == CWP, then we still do not have to fix CWP.
-	 */
-	and %g1, TSTATE_CWP_MASK, %l0
-	inc %l0
-	and %l0, NWINDOWS - 1, %l0	! %l0 mod NWINDOWS
-	rdpr %cwp, %l1
-	cmp %l0, %l1
-	bz %xcc, 0f			! CWP is ok
-	nop
-
-	/*
-	 * Fix CWP.
-	 * In order to recapitulate, the input registers in the current
-	 * window are the output registers of the window to which we want
-	 * to restore. Because the fill trap fills only input and local
-	 * registers of a window, we need to preserve those output
-	 * registers manually.
-	 */
-	mov %sp, %g2
-	stx %i0, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0]
-	stx %i1, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1]
-	stx %i2, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2]
-	stx %i3, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3]
-	stx %i4, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4]
-	stx %i5, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5]
-	stx %i6, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6]
-	stx %i7, [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7]
-	wrpr %l0, 0, %cwp
-	mov %g2, %sp
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I0], %i0
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I1], %i1
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I2], %i2
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I3], %i3
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I4], %i4
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I5], %i5
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I6], %i6
-	ldx [%sp + PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE + STACK_BIAS + SAVED_I7], %i7
-
-	/*
-	 * OTHERWIN != 0 or fall-through from the OTHERWIN == 0 case.
-	 * The CWP has already been restored to the value it had after the SAVE
-	 * at the beginning of this function.
-	 */
-0:
-.if NOT(\is_syscall)
-	rdpr %tstate, %g1
-	andcc %g1, TSTATE_PRIV_BIT, %g0		! if we are not returning to userspace...,
-	bnz %xcc, 1f				! ...skip restoring userspace windows
-	nop
-.endif
-
-	/*
-	 * Spills and fills will be processed by the {spill,fill}_1_normal
-	 * handlers.
-	 */
-	wrpr %g0, WSTATE_OTHER(0) | WSTATE_NORMAL(1), %wstate
-
-	/*
-	 * Set primary context according to secondary context.
-	 */
-	wr %g0, ASI_DMMU, %asi
-	ldxa [VA_SECONDARY_CONTEXT_REG] %asi, %g1
-	stxa %g1, [VA_PRIMARY_CONTEXT_REG] %asi
-	rd %pc, %g1
-	flush %g1
-	
-	rdpr %cwp, %g1
-	rdpr %otherwin, %g2
-
-	/*
-	 * Skip all OTHERWIN windows and descend to the first window
-	 * in the userspace window buffer.
-	 */
-	sub %g1, %g2, %g3
-	dec %g3
-	and %g3, NWINDOWS - 1, %g3
-	wrpr %g3, 0, %cwp
-
-	/*
-	 * CWP is now in the window last saved in the userspace window buffer.
-	 * Fill all windows stored in the buffer.
-	 */
-	clr %g4
-0:	andcc %g7, UWB_ALIGNMENT - 1, %g0	! alignment check
-	bz %xcc, 0f				! %g7 is UWB_ALIGNMENT-aligned, no more windows to refill
-	nop
-
-	add %g7, -STACK_WINDOW_SAVE_AREA_SIZE, %g7
-	ldx [%g7 + L0_OFFSET], %l0
-	ldx [%g7 + L1_OFFSET], %l1
-	ldx [%g7 + L2_OFFSET], %l2
-	ldx [%g7 + L3_OFFSET], %l3
-	ldx [%g7 + L4_OFFSET], %l4
-	ldx [%g7 + L5_OFFSET], %l5
-	ldx [%g7 + L6_OFFSET], %l6
-	ldx [%g7 + L7_OFFSET], %l7
-	ldx [%g7 + I0_OFFSET], %i0
-	ldx [%g7 + I1_OFFSET], %i1
-	ldx [%g7 + I2_OFFSET], %i2
-	ldx [%g7 + I3_OFFSET], %i3
-	ldx [%g7 + I4_OFFSET], %i4
-	ldx [%g7 + I5_OFFSET], %i5
-	ldx [%g7 + I6_OFFSET], %i6
-	ldx [%g7 + I7_OFFSET], %i7
-
-	dec %g3
-	and %g3, NWINDOWS - 1, %g3
-	wrpr %g3, 0, %cwp			! switch to the preceeding window
-
-	ba %xcc, 0b
-	inc %g4
-
-0:
-	/*
-	 * Switch back to the proper current window and adjust
-	 * OTHERWIN, CANRESTORE, CANSAVE and CLEANWIN.
-	 */
-	wrpr %g1, 0, %cwp
-	add %g4, %g2, %g2
-	cmp %g2, NWINDOWS - 2
-	bg %xcc, 2f				! fix the CANRESTORE=NWINDOWS-1 anomaly
-	mov NWINDOWS - 2, %g1			! use dealy slot for both cases
-	sub %g1, %g2, %g1
-	
-	wrpr %g0, 0, %otherwin
-	wrpr %g1, 0, %cansave			! NWINDOWS - 2 - CANRESTORE
-	wrpr %g2, 0, %canrestore		! OTHERWIN + windows in the buffer
-	wrpr %g2, 0, %cleanwin			! avoid information leak
-
-1:
-	restore
-
-.if \is_syscall
-	done
-.else
-	retry
-.endif
-
-	/*
-	 * We got here in order to avoid inconsistency of the window state registers.
-	 * If the:
-	 *
-	 * 	save %g6, -PREEMPTIBLE_HANDLER_STACK_FRAME_SIZE, %sp
-	 *
-	 * instruction trapped and spilled a register window into the userspace
-	 * window buffer, we have just restored NWINDOWS - 1 register windows.
-	 * However, CANRESTORE can be only NWINDOW - 2 at most.
-	 *
-	 * The solution is to manually switch to (CWP - 1) mod NWINDOWS
-	 * and set the window state registers so that:
-	 *
-	 * 	CANRESTORE 	= NWINDOWS - 2
-	 *	CLEANWIN	= NWINDOWS - 2
-	 *	CANSAVE 	= 0
-	 *	OTHERWIN	= 0
-	 *
-	 * The RESTORE instruction is therfore to be skipped.
-	 */
-2:
-	wrpr %g0, 0, %otherwin
-	wrpr %g0, 0, %cansave
-	wrpr %g1, 0, %canrestore
-	wrpr %g1, 0, %cleanwin
-
-	rdpr %cwp, %g1
-	dec %g1
-	and %g1, NWINDOWS - 1, %g1
-	wrpr %g1, 0, %cwp			! CWP--
-	
-.if \is_syscall
-	done
-.else
-	retry
-.endif
-
-.endm
-
-.global preemptible_handler
-preemptible_handler:
-	PREEMPTIBLE_HANDLER_TEMPLATE 0
-
-.global trap_instruction_handler
-trap_instruction_handler:
-	PREEMPTIBLE_HANDLER_TEMPLATE 1
