Index: HelenOS.config
===================================================================
--- HelenOS.config	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ HelenOS.config	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -344,4 +344,7 @@
 ! [PLATFORM=sparc64] CONFIG_VIRT_IDX_DCACHE (y/n)
 
+% Simics SMP Hack
+! [PROCESSOR=sun4v] CONFIG_SIMICS_SMP_HACK (y/n)
+
 % Support for userspace debuggers
 ! CONFIG_UDEBUG (y/n)
Index: kernel/arch/sparc64/Makefile.inc
===================================================================
--- kernel/arch/sparc64/Makefile.inc	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/Makefile.inc	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -92,5 +92,6 @@
 	arch/$(KARCH)/src/drivers/sgcn.c \
 	arch/$(KARCH)/src/drivers/pci.c \
-	arch/$(KARCH)/src/drivers/fhc.c
+	arch/$(KARCH)/src/drivers/fhc.c \
+	arch/$(KARCH)/src/trap/$(USARCH)/interrupt.c
 
 ifeq ($(USARCH),sun4u)
@@ -112,6 +113,6 @@
 ifeq ($(CONFIG_SMP),y)
 	ARCH_SOURCES += \
-		arch/$(KARCH)/src/smp/ipi.c \
-		arch/$(KARCH)/src/smp/smp.c
+		arch/$(KARCH)/src/smp/$(USARCH)/smp.c \
+		arch/$(KARCH)/src/smp/$(USARCH)/ipi.c
 endif
 
Index: kernel/arch/sparc64/include/mm/sun4v/mmu.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/mmu.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/mm/sun4v/mmu.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup sparc64mm	
+/** @addtogroup sparc64mm
  * @{
  */
Index: kernel/arch/sparc64/include/mm/sun4v/tlb.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/tlb.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/mm/sun4v/tlb.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup sparc64mm	
+/** @addtogroup sparc64mm
  * @{
  */
Index: kernel/arch/sparc64/include/mm/sun4v/tsb.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/tsb.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/mm/sun4v/tsb.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -28,5 +28,5 @@
  */
 
-/** @addtogroup sparc64mm	
+/** @addtogroup sparc64mm
  * @{
  */
Index: kernel/arch/sparc64/include/mm/sun4v/tte.h
===================================================================
--- kernel/arch/sparc64/include/mm/sun4v/tte.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/mm/sun4v/tte.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -27,5 +27,5 @@
  */
 
-/** @addtogroup sparc64mm	
+/** @addtogroup sparc64mm
  * @{
  */
Index: kernel/arch/sparc64/include/smp/sun4v/smp.h
===================================================================
--- kernel/arch/sparc64/include/smp/sun4v/smp.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/include/smp/sun4v/smp.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,48 @@
+/*
+ * 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
+ * @brief	sun4v smp functions
+ */
+
+#ifndef KERN_sparc64_sun4v_SMP_H_
+#define KERN_sparc64_sun4v_SMP_H_
+
+#include <typedefs.h>
+#include <arch/sun4v/cpu.h>
+
+extern bool calculate_optimal_nrdy(exec_unit_t *);
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/sparc64/include/sun4v/cpu.h
===================================================================
--- kernel/arch/sparc64/include/sun4v/cpu.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/sun4v/cpu.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -44,7 +44,9 @@
 #ifndef __ASM__
 
+#include <atomic.h>
+#include <synch/spinlock.h>
+
 struct cpu;
 
-/*
 typedef struct {
 	uint64_t exec_unit_id;
@@ -55,5 +57,4 @@
 	SPINLOCK_DECLARE(proposed_nrdy_lock);
 } exec_unit_t;
-*/
 
 typedef struct cpu_arch {
@@ -63,7 +64,7 @@
 					     generated when the TICK register
 					     matches this value. */
-	//exec_unit_t *exec_unit;		/**< Physical core. */
-	//unsigned long proposed_nrdy;	/**< Proposed No. of ready threads
-	//				     so that cores are equally balanced. */
+	exec_unit_t *exec_unit;		/**< Physical core. */
+	unsigned long proposed_nrdy;	/**< Proposed No. of ready threads
+					     so that cores are equally balanced. */
 } cpu_arch_t;
 
Index: kernel/arch/sparc64/include/sun4v/ipi.h
===================================================================
--- kernel/arch/sparc64/include/sun4v/ipi.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/sun4v/ipi.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -38,7 +38,8 @@
 #define KERN_sparc64_sun4v_IPI_H_
 
-uint64_t ipi_brodcast_to(void (*func)(void), uint16_t cpu_list[MAX_NUM_STRANDS],
-		uint64_t list_size);
-uint64_t ipi_unicast_to(void (*func)(void), uint16_t cpu_id);
+#include <arch/types.h>
+
+extern uint64_t ipi_brodcast_to(void (*)(void), uint16_t cpu_list[], uint64_t);
+extern uint64_t ipi_unicast_to(void (*)(void), uint16_t);
 
 #endif
Index: kernel/arch/sparc64/include/trap/interrupt.h
===================================================================
--- kernel/arch/sparc64/include/trap/interrupt.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/include/trap/interrupt.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -32,66 +32,9 @@
 /** 
  * @file
- * @brief This file contains interrupt vector trap handler.
+ * @brief This file contains level N interrupt and inter-processor interrupt
+ * trap handler.
  */
-
-#ifndef KERN_sparc64_TRAP_INTERRUPT_H_
-#define KERN_sparc64_TRAP_INTERRUPT_H_
-
-#include <arch/trap/trap_table.h>
-#include <arch/stack.h>
-
-/* IMAP register bits */
-#define IGN_MASK	0x7c0
-#define INO_MASK	0x1f
-#define IMAP_V_MASK	(1ULL << 31)
-
-#define IGN_SHIFT	6
-
-
-/* Interrupt ASI registers. */
-#define ASI_INTR_W			0x77
-#define ASI_INTR_DISPATCH_STATUS	0x48
-#define ASI_INTR_R			0x7f
-#define ASI_INTR_RECEIVE		0x49
-
-/* VA's used with ASI_INTR_W register. */
-#if defined (US)
-#define ASI_UDB_INTR_W_DATA_0	0x40
-#define ASI_UDB_INTR_W_DATA_1	0x50
-#define ASI_UDB_INTR_W_DATA_2	0x60
-#elif defined (US3)
-#define VA_INTR_W_DATA_0	0x40
-#define VA_INTR_W_DATA_1	0x48
-#define VA_INTR_W_DATA_2	0x50
-#define VA_INTR_W_DATA_3	0x58
-#define VA_INTR_W_DATA_4	0x60
-#define VA_INTR_W_DATA_5	0x68
-#define VA_INTR_W_DATA_6	0x80
-#define VA_INTR_W_DATA_7	0x88
-#endif
-#define VA_INTR_W_DISPATCH	0x70
-
-/* VA's used with ASI_INTR_R register. */
-#if defined(US)
-#define ASI_UDB_INTR_R_DATA_0	0x40
-#define ASI_UDB_INTR_R_DATA_1	0x50
-#define ASI_UDB_INTR_R_DATA_2	0x60
-#elif defined (US3)
-#define VA_INTR_R_DATA_0	0x40
-#define VA_INTR_R_DATA_1	0x48
-#define VA_INTR_R_DATA_2	0x50
-#define VA_INTR_R_DATA_3	0x58
-#define VA_INTR_R_DATA_4	0x60
-#define VA_INTR_R_DATA_5	0x68
-#define VA_INTR_R_DATA_6	0x80
-#define VA_INTR_R_DATA_7	0x88
-#endif
-
-/* Shifts in the Interrupt Vector Dispatch virtual address. */
-#define INTR_VEC_DISPATCH_MID_SHIFT	14
-
-/* Bits in the Interrupt Dispatch Status register. */
-#define INTR_DISPATCH_STATUS_NACK	0x2
-#define INTR_DISPATCH_STATUS_BUSY	0x1
+#ifndef KERN_sparc64_INTERRUPT_TRAP_H_
+#define KERN_sparc64_INTERRUPT_TRAP_H_
 
 #define TT_INTERRUPT_LEVEL_1			0x41
@@ -111,8 +54,13 @@
 #define TT_INTERRUPT_LEVEL_15			0x4f
 
-#define TT_INTERRUPT_VECTOR_TRAP		0x60
+#define INTERRUPT_LEVEL_N_HANDLER_SIZE		TRAP_TABLE_ENTRY_SIZE
 
-#define INTERRUPT_LEVEL_N_HANDLER_SIZE		TRAP_TABLE_ENTRY_SIZE
-#define INTERRUPT_VECTOR_TRAP_HANDLER_SIZE	TRAP_TABLE_ENTRY_SIZE
+/* IMAP register bits */
+#define IGN_MASK	0x7c0
+#define INO_MASK	0x1f
+#define IMAP_V_MASK	(1ULL << 31)
+
+#define IGN_SHIFT	6
+
 
 #ifdef __ASM__
@@ -121,9 +69,5 @@
 	PREEMPTIBLE_HANDLER exc_dispatch
 .endm
-
-.macro INTERRUPT_VECTOR_TRAP_HANDLER
-	PREEMPTIBLE_HANDLER interrupt
-.endm
-#endif /* __ASM__ */
+#endif
 
 #ifndef __ASM__
@@ -134,4 +78,11 @@
 #endif /* !def __ASM__ */
 
+
+#if defined (SUN4U)
+#include <arch/trap/sun4u/interrupt.h>
+#elif defined (SUN4V)
+#include <arch/trap/sun4v/interrupt.h>
+#endif
+
 #endif
 
Index: kernel/arch/sparc64/include/trap/sun4u/interrupt.h
===================================================================
--- kernel/arch/sparc64/include/trap/sun4u/interrupt.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/include/trap/sun4u/interrupt.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -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 sparc64interrupt
+ * @{
+ */
+/** 
+ * @file
+ * @brief This file contains interrupt vector trap handler.
+ */
+
+#ifndef KERN_sparc64_TRAP_SUN4U_INTERRUPT_H_
+#define KERN_sparc64_TRAP_SUN4U_INTERRUPT_H_
+
+#include <arch/trap/trap_table.h>
+#include <arch/stack.h>
+
+
+/* Interrupt ASI registers. */
+#define ASI_INTR_W			0x77
+#define ASI_INTR_DISPATCH_STATUS	0x48
+#define ASI_INTR_R			0x7f
+#define ASI_INTR_RECEIVE		0x49
+
+/* VA's used with ASI_INTR_W register. */
+#if defined (US)
+#define ASI_UDB_INTR_W_DATA_0	0x40
+#define ASI_UDB_INTR_W_DATA_1	0x50
+#define ASI_UDB_INTR_W_DATA_2	0x60
+#elif defined (US3)
+#define VA_INTR_W_DATA_0	0x40
+#define VA_INTR_W_DATA_1	0x48
+#define VA_INTR_W_DATA_2	0x50
+#define VA_INTR_W_DATA_3	0x58
+#define VA_INTR_W_DATA_4	0x60
+#define VA_INTR_W_DATA_5	0x68
+#define VA_INTR_W_DATA_6	0x80
+#define VA_INTR_W_DATA_7	0x88
+#endif
+#define VA_INTR_W_DISPATCH	0x70
+
+/* VA's used with ASI_INTR_R register. */
+#if defined(US)
+#define ASI_UDB_INTR_R_DATA_0	0x40
+#define ASI_UDB_INTR_R_DATA_1	0x50
+#define ASI_UDB_INTR_R_DATA_2	0x60
+#elif defined (US3)
+#define VA_INTR_R_DATA_0	0x40
+#define VA_INTR_R_DATA_1	0x48
+#define VA_INTR_R_DATA_2	0x50
+#define VA_INTR_R_DATA_3	0x58
+#define VA_INTR_R_DATA_4	0x60
+#define VA_INTR_R_DATA_5	0x68
+#define VA_INTR_R_DATA_6	0x80
+#define VA_INTR_R_DATA_7	0x88
+#endif
+
+/* Shifts in the Interrupt Vector Dispatch virtual address. */
+#define INTR_VEC_DISPATCH_MID_SHIFT	14
+
+/* Bits in the Interrupt Dispatch Status register. */
+#define INTR_DISPATCH_STATUS_NACK	0x2
+#define INTR_DISPATCH_STATUS_BUSY	0x1
+
+#define TT_INTERRUPT_VECTOR_TRAP		0x60
+
+#define INTERRUPT_VECTOR_TRAP_HANDLER_SIZE	TRAP_TABLE_ENTRY_SIZE
+
+#ifdef __ASM__
+.macro INTERRUPT_VECTOR_TRAP_HANDLER
+	PREEMPTIBLE_HANDLER interrupt
+.endm
+#endif /* __ASM__ */
+
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/sparc64/include/trap/sun4v/interrupt.h
===================================================================
--- kernel/arch/sparc64/include/trap/sun4v/interrupt.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/include/trap/sun4v/interrupt.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,50 @@
+/*
+ * 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 sparc64interrupt
+ * @{
+ */
+/** 
+ * @file
+ * @brief This file contains interrupt vector trap handler.
+ */
+
+#ifndef KERN_sparc64_TRAP_SUN4V_INTERRUPT_H_
+#define KERN_sparc64_TRAP_SUN4V_INTERRUPT_H_
+
+#ifndef __ASM__
+
+extern void sun4v_ipi_init(void);
+extern void cpu_mondo(void);
+
+#endif
+
+#endif
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/cpu/sun4v/cpu.c
===================================================================
--- kernel/arch/sparc64/src/cpu/sun4v/cpu.c	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/src/cpu/sun4v/cpu.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -41,6 +41,5 @@
 #include <arch/sun4v/md.h>
 #include <arch/sun4v/hypercall.h>
-
-//#include <arch/trap/sun4v/interrupt.h>
+#include <arch/trap/sun4v/interrupt.h>
 
 /** Perform sparc64 specific initialization of the processor structure for the
@@ -74,6 +73,6 @@
 		
 	tick_init();
-    	//MH - uncomment later
-	//sun4v_ipi_init();
+
+	sun4v_ipi_init();
 }
 
@@ -96,5 +95,5 @@
 {
 	printf("cpu%d: Niagara (%d MHz)\n", m->id,
-		m->arch.clock_frequency / 1000000);
+	    m->arch.clock_frequency / 1000000);
 }
 
Index: rnel/arch/sparc64/src/smp/ipi.c
===================================================================
--- kernel/arch/sparc64/src/smp/ipi.c	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ 	(revision )
@@ -1,174 +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 sparc64	
- * @{
- */
-/** @file
- */
-
-#include <smp/ipi.h>
-#include <cpu.h>
-#include <arch.h>
-#include <arch/cpu.h>
-#include <arch/asm.h>
-#include <config.h>
-#include <mm/tlb.h>
-#include <arch/interrupt.h>
-#include <arch/trap/interrupt.h>
-#include <arch/barrier.h>
-#include <preemption.h>
-#include <time/delay.h>
-#include <panic.h>
-
-/** Set the contents of the outgoing interrupt vector data.
- *
- * The first data item (data 0) will be set to the value of func, the
- * rest of the vector will contain zeros.
- *
- * This is a helper function used from within the cross_call function.
- *
- * @param func value the first data item of the vector will be set to
- */
-static inline void set_intr_w_data(void (* func)(void))
-{
-#if defined (US)
-	asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
-	asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
-	asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
-#elif defined (US3)
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t)	func);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
-	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
-#endif
-}
-
-/** Invoke function on another processor.
- *
- * Currently, only functions without arguments are supported.
- * Supporting more arguments in the future should be no big deal.
- *
- * Interrupts must be disabled prior to this call.
- *
- * @param mid MID of the target processor.
- * @param func Function to be invoked.
- */
-static void cross_call(int mid, void (* func)(void))
-{
-	uint64_t status;
-	bool done;
-
-	/*
-	 * This function might enable interrupts for a while.
-	 * In order to prevent migration to another processor,
-	 * we explicitly disable preemption.
-	 */
-	
-	preemption_disable();
-	
-	status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
-	if (status & INTR_DISPATCH_STATUS_BUSY)
-		panic("Interrupt Dispatch Status busy bit set.");
-	
-	ASSERT(!(pstate_read() & PSTATE_IE_BIT));
-	
-	do {
-		set_intr_w_data(func);
-		asi_u64_write(ASI_INTR_W,
-		    (mid << INTR_VEC_DISPATCH_MID_SHIFT) |
-		    VA_INTR_W_DISPATCH, 0);
-	
-		membar();
-		
-		do {
-			status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
-		} while (status & INTR_DISPATCH_STATUS_BUSY);
-		
-		done = !(status & INTR_DISPATCH_STATUS_NACK);
-		if (!done) {
-			/*
-			 * Prevent deadlock.
-			 */			
-			(void) interrupts_enable();
-			delay(20 + (tick_read() & 0xff));
-			(void) interrupts_disable();
-		}
-	} while (done);
-	
-	preemption_enable();
-}
-
-/*
- * Deliver IPI to all processors except the current one.
- *
- * The sparc64 architecture does not support any group addressing
- * which is found, for instance, on ia32 and amd64. Therefore we
- * need to simulate the broadcast by sending the message to
- * all target processors step by step.
- *
- * We assume that interrupts are disabled.
- *
- * @param ipi IPI number.
- */
-void ipi_broadcast_arch(int ipi)
-{
-	unsigned int i;
-	
-	void (* func)(void);
-	
-	switch (ipi) {
-	case IPI_TLB_SHOOTDOWN:
-		func = tlb_shootdown_ipi_recv;
-		break;
-	default:
-		panic("Unknown IPI (%d).", ipi);
-		break;
-	}
-	
-	/*
-	 * As long as we don't support hot-plugging
-	 * or hot-unplugging of CPUs, we can walk
-	 * the cpus array and read processor's MID
-	 * without locking.
-	 */
-	
-	for (i = 0; i < config.cpu_active; i++) {
-		if (&cpus[i] == CPU)
-			continue;		/* skip the current CPU */
-
-		cross_call(cpus[i].arch.mid, func);
-	}
-}
-
-/** @}
- */
Index: rnel/arch/sparc64/src/smp/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/smp.c	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ 	(revision )
@@ -1,137 +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 sparc64	
- * @{
- */
-/** @file
- */
-
-#include <smp/smp.h>
-#include <genarch/ofw/ofw_tree.h>
-#include <cpu.h>
-#include <arch/cpu_family.h>
-#include <arch/cpu.h>
-#include <arch.h>
-#include <config.h>
-#include <macros.h>
-#include <arch/types.h>
-#include <synch/synch.h>
-#include <synch/waitq.h>
-#include <print.h>
-#include <arch/cpu_node.h>
-
-/**
- * This global variable is used to pick-up application processors
- * from their active loop in start.S. When a processor looping in
- * start.S sees that this variable contains its MID, it can
- * proceed with its initialization.
- *
- * This variable is modified only by the bootstrap processor.
- * Other processors access it read-only.
- */
-volatile uint64_t waking_up_mid = (uint64_t) -1;
-
-/** Determine number of processors. */
-void smp_init(void)
-{
-	ofw_tree_node_t *node;
-	size_t cnt = 0;
-	
-	if (is_us() || is_us_iii()) {
-		node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
-		while (node) {
-			cnt++;
-			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) {
-			cnt += 2;
-			node = ofw_tree_find_peer_by_name(node, "cmp");
-		}
-	}
-	
-	config.cpu_count = max(1, cnt);
-}
-
-/**
- * Wakes up the CPU which is represented by the "node" OFW tree node.
- * If "node" represents the current CPU, calling the function has
- * no effect. 
- */
-static void wakeup_cpu(ofw_tree_node_t *node)
-{
-	uint32_t mid;
-	ofw_tree_property_t *prop;
-		
-	/* '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 == NULL)
-		return;
-		
-	mid = *((uint32_t *) prop->value);
-	if (CPU->arch.mid == mid)
-		return;
-
-	waking_up_mid = mid;
-		
-	if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) ==
-	    ESYNCH_TIMEOUT)
-		printf("%s: waiting for processor (mid = %" PRIu32
-		    ") timed out\n", __func__, mid);
-}
-
-/** Wake application processors up. */
-void kmp(void *arg)
-{
-	ofw_tree_node_t *node;
-	int i;
-	
-	if (is_us() || is_us_iii()) {
-		node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
-		for (i = 0; node;
-                     node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++)
-			wakeup_cpu(node);
-	} else if (is_us_iv()) {
-		node = ofw_tree_find_child(cpus_parent(), "cmp");
-		while (node) {
-			wakeup_cpu(ofw_tree_find_child(node, "cpu@0"));
-			wakeup_cpu(ofw_tree_find_child(node, "cpu@1"));
-			node = ofw_tree_find_peer_by_name(node, "cmp");
-		}
-	}
-}
-
-/** @}
- */
Index: kernel/arch/sparc64/src/smp/sun4u/ipi.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4u/ipi.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/src/smp/sun4u/ipi.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,174 @@
+/*
+ * 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 sparc64	
+ * @{
+ */
+/** @file
+ */
+
+#include <smp/ipi.h>
+#include <cpu.h>
+#include <arch.h>
+#include <arch/cpu.h>
+#include <arch/asm.h>
+#include <config.h>
+#include <mm/tlb.h>
+#include <arch/interrupt.h>
+#include <arch/trap/interrupt.h>
+#include <arch/barrier.h>
+#include <preemption.h>
+#include <time/delay.h>
+#include <panic.h>
+
+/** Set the contents of the outgoing interrupt vector data.
+ *
+ * The first data item (data 0) will be set to the value of func, the
+ * rest of the vector will contain zeros.
+ *
+ * This is a helper function used from within the cross_call function.
+ *
+ * @param func value the first data item of the vector will be set to
+ */
+static inline void set_intr_w_data(void (* func)(void))
+{
+#if defined (US)
+	asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_0, (uintptr_t) func);
+	asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_1, 0);
+	asi_u64_write(ASI_INTR_W, ASI_UDB_INTR_W_DATA_2, 0);
+#elif defined (US3)
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_0, (uintptr_t)	func);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_1, 0);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_2, 0);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_3, 0);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_4, 0);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_5, 0);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_6, 0);
+	asi_u64_write(ASI_INTR_W, VA_INTR_W_DATA_7, 0);
+#endif
+}
+
+/** Invoke function on another processor.
+ *
+ * Currently, only functions without arguments are supported.
+ * Supporting more arguments in the future should be no big deal.
+ *
+ * Interrupts must be disabled prior to this call.
+ *
+ * @param mid MID of the target processor.
+ * @param func Function to be invoked.
+ */
+static void cross_call(int mid, void (* func)(void))
+{
+	uint64_t status;
+	bool done;
+
+	/*
+	 * This function might enable interrupts for a while.
+	 * In order to prevent migration to another processor,
+	 * we explicitly disable preemption.
+	 */
+	
+	preemption_disable();
+	
+	status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
+	if (status & INTR_DISPATCH_STATUS_BUSY)
+		panic("Interrupt Dispatch Status busy bit set\n");
+	
+	ASSERT(!(pstate_read() & PSTATE_IE_BIT));
+	
+	do {
+		set_intr_w_data(func);
+		asi_u64_write(ASI_INTR_W,
+		    (mid << INTR_VEC_DISPATCH_MID_SHIFT) |
+		    VA_INTR_W_DISPATCH, 0);
+	
+		membar();
+		
+		do {
+			status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
+		} while (status & INTR_DISPATCH_STATUS_BUSY);
+		
+		done = !(status & INTR_DISPATCH_STATUS_NACK);
+		if (!done) {
+			/*
+			 * Prevent deadlock.
+			 */			
+			(void) interrupts_enable();
+			delay(20 + (tick_read() & 0xff));
+			(void) interrupts_disable();
+		}
+	} while (done);
+	
+	preemption_enable();
+}
+
+/*
+ * Deliver IPI to all processors except the current one.
+ *
+ * The sparc64 architecture does not support any group addressing
+ * which is found, for instance, on ia32 and amd64. Therefore we
+ * need to simulate the broadcast by sending the message to
+ * all target processors step by step.
+ *
+ * We assume that interrupts are disabled.
+ *
+ * @param ipi IPI number.
+ */
+void ipi_broadcast_arch(int ipi)
+{
+	unsigned int i;
+	
+	void (* func)(void);
+	
+	switch (ipi) {
+	case IPI_TLB_SHOOTDOWN:
+		func = tlb_shootdown_ipi_recv;
+		break;
+	default:
+		panic("Unknown IPI (%d).\n", ipi);
+		break;
+	}
+	
+	/*
+	 * As long as we don't support hot-plugging
+	 * or hot-unplugging of CPUs, we can walk
+	 * the cpus array and read processor's MID
+	 * without locking.
+	 */
+	
+	for (i = 0; i < config.cpu_active; i++) {
+		if (&cpus[i] == CPU)
+			continue;		/* skip the current CPU */
+
+		cross_call(cpus[i].arch.mid, func);
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/smp/sun4u/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/src/smp/sun4u/smp.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,137 @@
+/*
+ * 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 sparc64	
+ * @{
+ */
+/** @file
+ */
+
+#include <smp/smp.h>
+#include <genarch/ofw/ofw_tree.h>
+#include <cpu.h>
+#include <arch/cpu_family.h>
+#include <arch/cpu.h>
+#include <arch.h>
+#include <config.h>
+#include <macros.h>
+#include <arch/types.h>
+#include <synch/synch.h>
+#include <synch/waitq.h>
+#include <print.h>
+#include <arch/cpu_node.h>
+
+/**
+ * This global variable is used to pick-up application processors
+ * from their active loop in start.S. When a processor looping in
+ * start.S sees that this variable contains its MID, it can
+ * proceed with its initialization.
+ *
+ * This variable is modified only by the bootstrap processor.
+ * Other processors access it read-only.
+ */
+volatile uint64_t waking_up_mid = (uint64_t) -1;
+
+/** Determine number of processors. */
+void smp_init(void)
+{
+	ofw_tree_node_t *node;
+	unsigned int cnt = 0;
+	
+	if (is_us() || is_us_iii()) {
+		node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
+		while (node) {
+			cnt++;
+			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) {
+			cnt += 2;
+			node = ofw_tree_find_peer_by_name(node, "cmp");
+		}
+	}
+	
+	config.cpu_count = max(1, cnt);
+}
+
+/**
+ * Wakes up the CPU which is represented by the "node" OFW tree node.
+ * If "node" represents the current CPU, calling the function has
+ * no effect. 
+ */
+static void wakeup_cpu(ofw_tree_node_t *node)
+{
+	uint32_t mid;
+	ofw_tree_property_t *prop;
+		
+	/* '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 == NULL)
+		return;
+		
+	mid = *((uint32_t *) prop->value);
+	if (CPU->arch.mid == mid)
+		return;
+
+	waking_up_mid = mid;
+		
+	if (waitq_sleep_timeout(&ap_completion_wq, 1000000, SYNCH_FLAGS_NONE) ==
+	    ESYNCH_TIMEOUT)
+		printf("%s: waiting for processor (mid = %" PRIu32
+		    ") timed out\n", __func__, mid);
+}
+
+/** Wake application processors up. */
+void kmp(void *arg)
+{
+	ofw_tree_node_t *node;
+	int i;
+	
+	if (is_us() || is_us_iii()) {
+		node = ofw_tree_find_child_by_device_type(cpus_parent(), "cpu");
+		for (i = 0; node;
+                     node = ofw_tree_find_peer_by_device_type(node, "cpu"), i++)
+			wakeup_cpu(node);
+	} else if (is_us_iv()) {
+		node = ofw_tree_find_child(cpus_parent(), "cmp");
+		while (node) {
+			wakeup_cpu(ofw_tree_find_child(node, "cpu@0"));
+			wakeup_cpu(ofw_tree_find_child(node, "cpu@1"));
+			node = ofw_tree_find_peer_by_name(node, "cmp");
+		}
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/smp/sun4v/ipi.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4v/ipi.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/src/smp/sun4v/ipi.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,123 @@
+/*
+ * 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 sparc64	
+ * @{
+ */
+/** @file
+ */
+
+#include <smp/ipi.h>
+#include <cpu.h>
+#include <config.h>
+#include <interrupt.h>
+#include <arch/asm.h>
+#include <arch/cpu.h>
+#include <arch/sun4v/hypercall.h>
+#include <arch/sun4v/ipi.h>
+
+#define IPI_MESSAGE_SIZE	8
+
+static uint64_t data[MAX_NUM_STRANDS][IPI_MESSAGE_SIZE]
+	__attribute__ ((aligned (64)));
+
+static uint16_t ipi_cpu_list[MAX_NUM_STRANDS][MAX_NUM_STRANDS];
+
+/**
+ * Sends an inter-processor interrupt to all virtual processors whose IDs are
+ * listed in the list.
+ *
+ * @param func		address of the function to be invoked on the recipient
+ * @param cpu_list	list of CPU IDs (16-bit identifiers) of the recipients
+ * @param list_size	number of recipients (number of valid cpu_list entries)
+ *
+ * @return		error code returned by the CPU_MONDO_SEND hypercall
+ */
+uint64_t ipi_brodcast_to(void (*func)(void), uint16_t cpu_list[MAX_NUM_STRANDS],
+		uint64_t list_size) {
+
+	data[CPU->arch.id][0] = (uint64_t) func;
+
+	unsigned int i;
+	for (i = 0; i < list_size; i++) {
+		ipi_cpu_list[CPU->arch.id][i] = cpu_list[i];
+	}
+
+	return __hypercall_fast3(CPU_MONDO_SEND, list_size,
+		KA2PA(ipi_cpu_list[CPU->arch.id]), KA2PA(data[CPU->arch.id]));
+}
+
+/**
+ * Send an inter-processor interrupt to a particular CPU.
+ *
+ * @param func		address of the function to be invoked on the recipient
+ * @param cpu_is	CPU ID (16-bit identifier) of the recipient
+ *
+ * @return		error code returned by the CPU_MONDO_SEND hypercall
+ */
+uint64_t ipi_unicast_to(void (*func)(void), uint16_t cpu_id) {
+	ipi_cpu_list[CPU->arch.id][0] = cpu_id;
+	return ipi_brodcast_to(func, ipi_cpu_list[CPU->arch.id], 1);
+}
+
+/*
+ * Deliver IPI to all processors except the current one.
+ *
+ * We assume that interrupts are disabled.
+ *
+ * @param ipi IPI number.
+ */
+void ipi_broadcast_arch(int ipi)
+{
+	void (* func)(void);
+	
+	switch (ipi) {
+	case IPI_TLB_SHOOTDOWN:
+		func = tlb_shootdown_ipi_recv;
+		break;
+	default:
+		panic("Unknown IPI (%d).\n", ipi);
+		break;
+	}
+
+	unsigned int i;
+	unsigned idx = 0;
+	for (i = 0; i < config.cpu_active; i++) {
+		if (&cpus[i] == CPU) {
+			continue;
+		}
+
+		ipi_cpu_list[CPU->id][idx] = (uint16_t) cpus[i].id;
+		idx++;
+	}
+
+	ipi_brodcast_to(func, ipi_cpu_list[CPU->arch.id], idx);
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/smp/sun4v/smp.c
===================================================================
--- kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/src/smp/sun4v/smp.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,465 @@
+/*
+ * Copyright (c) 2006 Jakub Jermar
+ * 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 <smp/smp.h>
+#include <smp/ipi.h>
+#include <genarch/ofw/ofw_tree.h>
+#include <cpu.h>
+#include <arch/cpu.h>
+#include <arch/boot/boot.h>
+#include <arch.h>
+#include <config.h>
+#include <macros.h>
+#include <func.h>
+#include <arch/types.h>
+#include <synch/synch.h>
+#include <synch/waitq.h>
+#include <print.h>
+#include <arch/sun4v/hypercall.h>
+#include <arch/sun4v/md.h>
+#include <arch/sun4v/ipi.h>
+#include <time/delay.h>
+#include <arch/smp/sun4v/smp.h>
+#include <string.h>
+
+/** hypervisor code of the "running" state of the CPU */
+#define CPU_STATE_RUNNING	2
+
+/** maximum possible number of processor cores */
+#define MAX_NUM_CORES		8
+
+/** needed in the CPU_START hypercall */
+extern void kernel_image_start(void);
+
+/** needed in the CPU_START hypercall */
+extern void *trap_table;
+
+/** number of execution units detected */
+uint8_t exec_unit_count = 0;
+
+/** execution units (processor cores) */
+exec_unit_t exec_units[MAX_NUM_CORES];
+
+/** CPU structures */
+extern cpu_t *cpus;
+
+/** maximum number of strands per a physical core detected */
+unsigned int max_core_strands = 0;
+
+#ifdef CONFIG_SIMICS_SMP_HACK
+/**
+ * Copies a piece of HelenOS code to the place where OBP had its IPI handler.
+ * By sending an IPI by the BSP to the AP the code will be executed.
+ * The code will jump to the first instruction of the kernel. This is
+ * a workaround how to make APs execute HelenOS code on Simics.
+ */
+static void simics_smp_hack_init(void) {
+	asm volatile (
+		"setx temp_cpu_mondo_handler, %g4, %g6 \n"
+		"setx 0x80200f80, %g4, %g7 \n"
+
+		"ldx [%g6], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x8], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x10], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x18], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x20], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x28], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x30], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x38], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"add %g7, 0x8, %g7 \n"
+		"ldx [%g6 + 0x40], %g4 \n"
+		"stxa %g4, [%g7] 0x14 \n"
+		"membar #Sync \n"
+
+		"flush %i7"
+
+		);
+}
+#endif
+
+#if 0
+/**
+ * Proposes the optimal number of ready threads for each virtual processor
+ * in the given processor core so that the processor core is as busy as the
+ * average processor core. The proposed number of ready threads will be
+ * stored to the proposed_nrdy variable of the cpu_arch_t struture.
+ */
+bool calculate_optimal_nrdy(exec_unit_t *exec_unit) {
+
+	/* calculate the number of threads the core will steal */
+	int avg = atomic_get(&nrdy) / exec_unit_count;
+	int to_steal = avg - atomic_get(&(exec_units->nrdy));
+	if (to_steal < 0) {
+		return true;
+	} else if (to_steal == 0) {
+		return false;
+	}
+
+	/* initialize the proposals with the real numbers of ready threads */
+	unsigned int k;
+	for (k = 0; k < exec_unit->strand_count; k++) {
+		exec_units->cpus[k]->arch.proposed_nrdy =
+			atomic_get(&(exec_unit->cpus[k]->nrdy));
+	}
+
+	/* distribute the threads to be stolen to the core's CPUs */
+	int j;
+	for (j = to_steal; j > 0; j--) {
+		unsigned int k;
+		unsigned int least_busy = 0;
+		unsigned int least_busy_nrdy =
+			exec_unit->cpus[0]->arch.proposed_nrdy;
+
+		/* for each stolen thread, give it to the least busy CPU */
+		for (k = 0; k < exec_unit->strand_count; k++) {
+			if (exec_unit->cpus[k]->arch.proposed_nrdy
+					< least_busy_nrdy) {
+				least_busy = k;
+				least_busy_nrdy =
+					exec_unit->cpus[k]->arch.proposed_nrdy;
+			}
+		}
+		exec_unit->cpus[least_busy]->arch.proposed_nrdy++;
+	}
+
+	return false;
+}
+#endif
+
+/**
+ * Finds out which execution units belong to particular CPUs. By execution unit
+ * we mean the physical core the logical processor is backed by. Since each
+ * Niagara physical core has just one integer execution unit and we will
+ * ignore other execution units than the integer ones, we will use the terms
+ * "integer execution unit", "execution unit" and "physical core"
+ * interchangeably.
+ *
+ * The physical cores are detected by browsing the children of the CPU node
+ * in the machine description and looking for a node representing an integer
+ * execution unit. Once the integer execution unit of a particular CPU is
+ * known, the ID of the CPU is added to the list of cpuids of the corresponding
+ * execution unit structure (exec_unit_t). If an execution unit is encountered
+ * for the first time, a new execution unit structure (exec_unit_t) must be
+ * created first and added to the execution units array (exec_units).
+ *
+ * If the function fails to find an execution unit for a CPU (this may happen
+ * on machines with older firmware or on Simics), it performs a fallback code
+ * which pretends there exists just one execution unit and all CPUs belong to
+ * it.
+ *
+ * Finally, the array of all execution units is reordered such that its element
+ * which represents the physical core of the the bootstrap CPU is at index 0.
+ * Moreover, the array of CPU IDs within the BSP's physical core structure is
+ * reordered such that the element which represents the ID of the BSP is at
+ * index 0. This is done because we would like the CPUs to be woken up
+ * such that the 0-index CPU of the 0-index execution unit is
+ * woken up first. And since the BSP is already woken up, we would like it to be
+ * at 0-th position of the 0-th execution unit structure.
+ *
+ * Apart from that, the code also counts the total number of CPUs and stores
+ * it to the global config.cpu_count variable.
+ */
+static void detect_execution_units(void)
+{
+	/* ID of the bootstrap processor */
+	uint64_t myid;
+
+	/* total number of CPUs detected */
+	size_t cpu_count = 0;
+
+	/* will be set to 1 if detecting the physical cores fails */
+	bool exec_unit_assign_error = 0;
+
+	/* index of the bootstrap physical core in the array of cores */
+	unsigned int bsp_exec_unit_index = 0;
+
+	/* index of the BSP ID inside the array of bootstrap core's cpuids */
+	unsigned int bsp_core_strand_index = 0;
+
+	__hypercall_fast_ret1(0, 0, 0, 0, 0, CPU_MYID, &myid);
+	md_node_t node = md_get_root();
+
+	/* walk through all the CPU nodes in the MD*/
+	while (md_next_node(&node, "cpu")) {
+
+		uint64_t cpuid;
+		md_get_integer_property(node, "id", &cpuid);
+		cpu_count++;
+
+		/*
+ 		 * if failed in previous CPUs, don't try
+ 		 * to detect physical cores any more
+ 		 */
+		if (exec_unit_assign_error)
+			continue;
+
+		/* detect exec. unit for the CPU represented by current node */
+		uint64_t exec_unit_id = 0;
+		md_child_iter_t it = md_get_child_iterator(node);
+
+		while (md_next_child(&it)) {
+			md_node_t child = md_get_child_node(it);
+			const char *exec_unit_type;
+			md_get_string_property(child, "type", &exec_unit_type);
+
+			/* each physical core has just 1 integer exec. unit */
+			if (str_cmp(exec_unit_type, "integer") == 0) {
+				exec_unit_id = child;
+				break;
+			}
+		}
+
+		/* execution unit detected successfully */
+		if (exec_unit_id != 0) {
+
+			/* find the exec. unit in array of existing units */
+			unsigned int i = 0;
+			for (i = 0; i < exec_unit_count; i++) {
+				if (exec_units[i].exec_unit_id == exec_unit_id)
+					break;
+			}
+
+			/*
+			 * execution unit just met has not been met before, so
+			 * create a new entry in array of all execution units
+			 */
+			if (i == exec_unit_count) {
+				exec_units[i].exec_unit_id = exec_unit_id;
+				exec_units[i].strand_count = 0;
+				atomic_set(&(exec_units[i].nrdy), 0);
+				spinlock_initialize(&(exec_units[i].proposed_nrdy_lock), "proposed nrdy lock");
+				exec_unit_count++;
+			}
+
+			/*
+			 * remember the exec. unit and strand of the BSP
+			 */
+			if (cpuid == myid) {
+				bsp_exec_unit_index = i;
+				bsp_core_strand_index = exec_units[i].strand_count;
+			}
+
+			/* add the CPU just met to the exec. unit's list */
+			exec_units[i].cpuids[exec_units[i].strand_count] = cpuid;
+			exec_units[i].strand_count++;
+			max_core_strands =
+				exec_units[i].strand_count > max_core_strands ?
+				exec_units[i].strand_count : max_core_strands;
+
+		/* detecting execution unit failed */
+		} else {
+			exec_unit_assign_error = 1;
+		}
+	}		
+
+	/* save the number of CPUs to a globally accessible variable */
+	config.cpu_count = cpu_count;
+
+	/*
+ 	 * A fallback code which will be executed if finding out which
+ 	 * execution units belong to particular CPUs fails. Pretend there
+ 	 * exists just one execution unit and all CPUs belong to it.
+ 	 */
+	if (exec_unit_assign_error) {
+		bsp_exec_unit_index = 0;
+		exec_unit_count = 1;
+		exec_units[0].strand_count = cpu_count;
+		exec_units[0].exec_unit_id = 1;
+		spinlock_initialize(&(exec_units[0].proposed_nrdy_lock), "proposed nrdy lock");
+		atomic_set(&(exec_units[0].nrdy), 0);
+		max_core_strands = cpu_count;
+
+		/* browse CPUs again, assign them the fictional exec. unit */
+		node = md_get_root();
+		unsigned int i = 0;
+
+		while (md_next_node(&node, "cpu")) {
+			uint64_t cpuid;
+			md_get_integer_property(node, "id", &cpuid);
+			if (cpuid == myid) {
+				bsp_core_strand_index = i;
+			}
+			exec_units[0].cpuids[i++] = cpuid;
+		}
+	}
+
+	/*
+ 	 * Reorder the execution units array elements and the cpuid array
+ 	 * elements so that the BSP will always be the very first CPU of
+ 	 * the very first execution unit.
+ 	 */
+	exec_unit_t temp_exec_unit = exec_units[0];
+	exec_units[0] = exec_units[bsp_exec_unit_index];
+	exec_units[bsp_exec_unit_index] = temp_exec_unit;
+
+	uint64_t temp_cpuid = exec_units[0].cpuids[0];
+	exec_units[0].cpuids[0] = exec_units[0].cpuids[bsp_exec_unit_index];
+	exec_units[0].cpuids[bsp_core_strand_index] = temp_cpuid;
+
+}
+
+/**
+ * Determine number of processors and detect physical cores. On Simics
+ * copy the code which will be executed by the AP when the BSP sends an
+ * IPI to it in order to make it execute HelenOS code.
+ */
+void smp_init(void)
+{
+	detect_execution_units();
+#ifdef CONFIG_SIMICS_SMP_HACK
+	simics_smp_hack_init();
+#endif
+}
+
+/**
+ * For each CPU sets the value of cpus[i].arch.id, where i is the
+ * index of the CPU in the cpus variable, to the cpuid of the i-th processor
+ * to be run. The CPUs are run such that the CPU represented by cpus[0]
+ * is run first, cpus[1] is run after it, and cpus[cpu_count - 1] is run as the
+ * last one.
+ *
+ * The CPU IDs are set such that during waking the CPUs up the
+ * processor cores will be alternated, i.e. first one CPU from the first core
+ * will be run, after that one CPU from the second CPU core will be run,...
+ * then one CPU from the last core will be run, after that another CPU
+ * from the first core will be run, then another CPU from the second core
+ * will be run,... then another CPU from the last core will be run, and so on.
+ */
+static void init_cpuids(void)
+{
+	unsigned int cur_core_strand;
+	unsigned int cur_core;
+	unsigned int cur_cpu = 0;
+
+	for (cur_core_strand = 0; cur_core_strand < max_core_strands; cur_core_strand++) {
+		for (cur_core = 0; cur_core < exec_unit_count; cur_core++) {
+			if (cur_core_strand > exec_units[cur_core].strand_count)
+				continue;
+
+			cpus[cur_cpu].arch.exec_unit = &(exec_units[cur_core]);
+			atomic_add(&(exec_units[cur_core].nrdy), atomic_get(&(cpus[cur_cpu].nrdy)));
+			cpus[cur_cpu].arch.id = exec_units[cur_core].cpuids[cur_core_strand];
+			exec_units[cur_core].cpus[cur_core_strand] = &(cpus[cur_cpu]);
+			cur_cpu++;
+		}
+	}
+}
+
+/**
+ * Wakes up a single CPU.
+ *
+ * @param cpuid	ID of the CPU to be woken up
+ */
+static bool wake_cpu(uint64_t cpuid)
+{
+
+#ifdef CONFIG_SIMICS_SMP_HACK
+	ipi_unicast_to((void (*)(void)) 1234, cpuid);
+#else
+	/* stop the CPU before making it execute our code */
+	if (__hypercall_fast1(CPU_STOP, cpuid) != EOK)
+		return false;
+
+	/* wait for the CPU to stop */
+	uint64_t state;
+	__hypercall_fast_ret1(cpuid, 0, 0, 0, 0,
+		CPU_STATE, &state);
+	while (state == CPU_STATE_RUNNING) {
+		__hypercall_fast_ret1(cpuid, 0, 0, 0, 0,
+			CPU_STATE, &state);
+	}
+
+	/* make the CPU run again and execute HelenOS code */
+	if (__hypercall_fast4(
+		CPU_START, cpuid,
+		(uint64_t) KA2PA(kernel_image_start),
+		KA2PA(trap_table), bootinfo.physmem_start			
+		) != EOK)
+			return false;
+#endif
+
+	if (waitq_sleep_timeout(&ap_completion_wq, 10000000, SYNCH_FLAGS_NONE) ==
+			ESYNCH_TIMEOUT)
+		printf("%s: waiting for processor (cpuid = %" PRIu32
+		") timed out\n", __func__, cpuid);
+
+	return true;
+}
+
+/** Wake application processors up. */
+void kmp(void *arg)
+{
+	init_cpuids();
+
+	unsigned int i;
+
+	for (i = 1; i < config.cpu_count; i++) {
+		wake_cpu(cpus[i].arch.id);
+	}
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/trap/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/interrupt.c	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/src/trap/interrupt.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -1,4 +1,5 @@
 /*
  * Copyright (c) 2005 Jakub Jermar
+ * Copyright (c) 2009 Pavel Rimsky
  * All rights reserved.
  *
@@ -34,6 +35,6 @@
 
 #include <arch/interrupt.h>
+#include <arch/trap/interrupt.h>
 #include <arch/sparc64.h>
-#include <arch/trap/interrupt.h>
 #include <interrupt.h>
 #include <ddi/irq.h>
@@ -60,65 +61,4 @@
 	exc_register(n - 1, name, f);
 }
-
-/** Process hardware interrupt.
- *
- * @param n Ignored.
- * @param istate Ignored.
- */
-void interrupt(int n, istate_t *istate)
-{
-	uint64_t status;
-	uint64_t intrcv;
-	uint64_t data0;
-	status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
-	if (status & (!INTR_DISPATCH_STATUS_BUSY))
-		panic("Interrupt Dispatch Status busy bit not set.");
-
-	intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
-#if defined (US)
-	data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
-#elif defined (US3)
-	data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
-#endif
-
-	irq_t *irq = irq_dispatch_and_lock(data0);
-	if (irq) {
-		/*
-		 * The IRQ handler was found.
-		 */
-		irq->handler(irq);
-		/*
-		 * See if there is a clear-interrupt-routine and call it.
-		 */
-		if (irq->cir) {
-			irq->cir(irq->cir_arg, irq->inr);
-		}
-		spinlock_unlock(&irq->lock);
-	} else if (data0 > config.base) {
-		/*
-		 * This is a cross-call.
-		 * data0 contains address of the kernel function.
-		 * We call the function only after we verify
-		 * it is one of the supported ones.
-		 */
-#ifdef CONFIG_SMP
-		if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
-			tlb_shootdown_ipi_recv();
-		}
-#endif
-	} else {
-		/*
-		 * Spurious interrupt.
-		 */
-#ifdef CONFIG_DEBUG
-		printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
-		    ", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
-#endif
-	}
-
-	membar();
-	asi_u64_write(ASI_INTR_RECEIVE, 0, 0);
-}
-
 /** @}
  */
Index: kernel/arch/sparc64/src/trap/sun4u/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/sun4u/interrupt.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/src/trap/sun4u/interrupt.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,111 @@
+/*
+ * 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 sparc64interrupt
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/interrupt.h>
+#include <arch/sparc64.h>
+#include <arch/trap/interrupt.h>
+#include <interrupt.h>
+#include <ddi/irq.h>
+#include <arch/types.h>
+#include <debug.h>
+#include <arch/asm.h>
+#include <arch/barrier.h>
+#include <print.h>
+#include <arch.h>
+#include <mm/tlb.h>
+#include <config.h>
+#include <synch/spinlock.h>
+
+/** Process hardware interrupt.
+ *
+ * @param n Ignored.
+ * @param istate Ignored.
+ */
+void interrupt(int n, istate_t *istate)
+{
+	uint64_t status;
+	uint64_t intrcv;
+	uint64_t data0;
+	status = asi_u64_read(ASI_INTR_DISPATCH_STATUS, 0);
+	if (status & (!INTR_DISPATCH_STATUS_BUSY))
+		panic("Interrupt Dispatch Status busy bit not set\n");
+
+	intrcv = asi_u64_read(ASI_INTR_RECEIVE, 0);
+#if defined (US)
+	data0 = asi_u64_read(ASI_INTR_R, ASI_UDB_INTR_R_DATA_0);
+#elif defined (US3)
+	data0 = asi_u64_read(ASI_INTR_R, VA_INTR_R_DATA_0);
+#endif
+
+	irq_t *irq = irq_dispatch_and_lock(data0);
+	if (irq) {
+		/*
+		 * The IRQ handler was found.
+		 */
+		irq->handler(irq);
+		/*
+		 * See if there is a clear-interrupt-routine and call it.
+		 */
+		if (irq->cir) {
+			irq->cir(irq->cir_arg, irq->inr);
+		}
+		spinlock_unlock(&irq->lock);
+	} else if (data0 > config.base) {
+		/*
+		 * This is a cross-call.
+		 * data0 contains address of the kernel function.
+		 * We call the function only after we verify
+		 * it is one of the supported ones.
+		 */
+#ifdef CONFIG_SMP
+		if (data0 == (uintptr_t) tlb_shootdown_ipi_recv) {
+			tlb_shootdown_ipi_recv();
+		}
+#endif
+	} else {
+		/*
+		 * Spurious interrupt.
+		 */
+#ifdef CONFIG_DEBUG
+		printf("cpu%u: spurious interrupt (intrcv=%#" PRIx64
+		    ", data0=%#" PRIx64 ")\n", CPU->id, intrcv, data0);
+#endif
+	}
+
+	membar();
+	asi_u64_write(ASI_INTR_RECEIVE, 0, 0);
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/trap/sun4v/interrupt.c
===================================================================
--- kernel/arch/sparc64/src/trap/sun4v/interrupt.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
+++ kernel/arch/sparc64/src/trap/sun4v/interrupt.c	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -0,0 +1,121 @@
+/*
+ * 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 sparc64interrupt
+ * @{
+ */
+/** @file
+ */
+
+#include <arch/interrupt.h>
+#include <arch/trap/interrupt.h>
+#include <arch/sparc64.h>
+#include <interrupt.h>
+#include <ddi/irq.h>
+#include <arch/types.h>
+#include <debug.h>
+#include <arch/asm.h>
+#include <arch/barrier.h>
+#include <print.h>
+#include <arch.h>
+#include <mm/tlb.h>
+#include <config.h>
+#include <synch/spinlock.h>
+#include <arch/sun4v/hypercall.h>
+
+/** number of uint64_t-s in one CPU mondo message */
+#define CPU_MONDO_ENTRY_SIZE	8
+
+/** number of entries (messages) in the CPU mondo queue */
+#define CPU_MONDO_NENTRIES	8
+
+/** number of uint64_t-s in the CPU mondo queue */
+#define CPU_MONDO_QUEUE_SIZE	((CPU_MONDO_NENTRIES) * (CPU_MONDO_ENTRY_SIZE))
+
+/** used to identify CPU mondo queue in the hypercall */
+#define CPU_MONDO_QUEUE_ID	0x3c
+
+/** ASI for reading/writing CPU mondo head/tail registers */
+#define ASI_QUEUE		0x25
+
+/** VA for reading the CPU mondo tail */
+#define VA_CPU_MONDO_QUEUE_TAIL	0x3c8
+
+/** VA for reading/writing the CPU mondo head */
+#define VA_CPU_MONDO_QUEUE_HEAD	0x3c0
+
+/**
+ * array which contains CPU mondo queue for every CPU
+ */
+uint64_t cpu_mondo_queues[MAX_NUM_STRANDS][CPU_MONDO_QUEUE_SIZE]
+	__attribute__((aligned(
+	CPU_MONDO_QUEUE_SIZE * sizeof(uint64_t))));
+
+/**
+ * Initializes CPU mondo queue for the current CPU.
+ */
+void sun4v_ipi_init(void)
+{
+	if (__hypercall_fast3(
+		CPU_QCONF,
+		CPU_MONDO_QUEUE_ID,
+		KA2PA(cpu_mondo_queues[CPU->id]),
+		CPU_MONDO_NENTRIES) != EOK)
+			panic("Initializing mondo queue failed on CPU %d.\n",
+			    CPU->arch.id);
+}
+
+/**
+ * Handler of the CPU Mondo trap. Reads the message queue, updates the head
+ * register and processes the message (invokes a function call).
+ */
+void cpu_mondo(void)
+{
+#ifdef CONFIG_SMP
+	unsigned int tail = asi_u64_read(ASI_QUEUE, VA_CPU_MONDO_QUEUE_TAIL);
+	unsigned int head = asi_u64_read(ASI_QUEUE, VA_CPU_MONDO_QUEUE_HEAD);
+
+	while (head != tail) {
+		uint64_t data1 = cpu_mondo_queues[CPU->id][0];
+
+		head = (head + CPU_MONDO_ENTRY_SIZE * sizeof(uint64_t)) %
+		    (CPU_MONDO_QUEUE_SIZE * sizeof(uint64_t));
+		asi_u64_write(ASI_QUEUE, VA_CPU_MONDO_QUEUE_HEAD, head);
+
+		if (data1 == (uintptr_t) tlb_shootdown_ipi_recv) {
+			((void (*)(void)) data1)();
+		} else {
+			printf("Spurious interrupt on %d, data = %lx.\n",
+			    CPU->arch.id, data1);
+		}
+	}
+#endif
+}
+
+/** @}
+ */
Index: kernel/arch/sparc64/src/trap/sun4v/trap_table.S
===================================================================
--- kernel/arch/sparc64/src/trap/sun4v/trap_table.S	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/arch/sparc64/src/trap/sun4v/trap_table.S	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -344,5 +344,5 @@
 .global cpu_mondo_handler_tl0
 cpu_mondo_handler_tl0:
-/* PREEMPTIBLE_HANDLER cpu_mondo */
+PREEMPTIBLE_HANDLER cpu_mondo
 
 /* TT = 0x80, TL = 0, spill_0_normal handler */
@@ -533,5 +533,5 @@
 cpu_mondo_handler_tl1:
 	wrpr %g0, %tl
-/*	PREEMPTIBLE_HANDLER cpu_mondo */
+	PREEMPTIBLE_HANDLER cpu_mondo
 
 /* TT = 0x80, TL > 0, spill_0_normal handler */
Index: kernel/generic/include/cpu.h
===================================================================
--- kernel/generic/include/cpu.h	(revision 61001a9defa8a06128475b5d909949241e85057e)
+++ kernel/generic/include/cpu.h	(revision 72bf0d24c385bb60c29d5035914d6402640fc6d2)
@@ -48,5 +48,5 @@
  * There is one structure like this for every processor.
  */
-typedef struct {
+typedef struct cpu {
 	SPINLOCK_DECLARE(lock);
 
