--- /dev/null	2013-07-25 14:29:58.000000000 +0000
+++ new/usr/src/uts/common/os/intrd.c	2013-07-25 14:29:58.311959119 +0000
@@ -0,0 +1,295 @@
+/*
+ * This file and its contents are supplied under the terms of the
+ * Common Development and Distribution License ("CDDL"), version 1.0.
+ * You may only use this file in accordance with the terms of version
+ * 1.0 of the CDDL.
+ *
+ * A full copy of the text of the CDDL should have accompanied this
+ * source.  A copy of the CDDL is also available via the Internet at
+ * http://www.illumos.org/license/CDDL.
+ */
+
+/*
+ * Copyright 2013 David Hoeppner.  All rights reserved.
+ */
+
+/*
+ * Interrupt Load Balancer.
+ *
+ *
+ */
+
+/* XXX
+ *
+ * intrd_cpu_list::walk list |::print intrd_cpu_t
+ *
+ *
+ *
+ */
+#include <sys/param.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/apic.h>
+#include <sys/callb.h>
+#include <sys/cpuvar.h>
+#include <sys/proc.h>
+#include <sys/processor.h>
+#include <sys/sdt.h>
+#include <sys/sysmacros.h>
+#include <sys/time.h>
+
+extern	proc_t	*proc_intrd;
+
+#define	INTRD_NAME		"intrd"
+
+#define	IS_CPU(cpu_id)		(cpu[cpu_id] != NULL)
+
+#define	INTRD_NORMAL_SLEEPTIME	10
+#define	INTRD_IDLE_SLEEPTIME	45
+#define INTRD_ONECPU_SLEEPTIME	(60 * 15)
+
+#define	INTRD_NUMBER_SAMPLES	10
+
+
+static kmutex_t		intrd_lock;
+static kcondvar_t	intrd_cv;
+
+/*
+ * Interrupt CPU instance.
+ */
+typedef struct _intrd_cpu {
+	list_node_t	ic_next;
+	boolean_t	ic_offline;
+	hrtime_t	ic_tot[INTRD_NUMBER_SAMPLES];
+	list_t		ic_ivec_list;
+	processorid_t	ic_cpu_id;	/* XXX duplicate */
+} intrd_cpu_t;
+
+/*
+ * Interrupt vector instance.
+ */
+typedef struct _intrd_ivec {
+	list_node_t	ii_next;
+} intrd_ivec_t;
+
+static list_t	intrd_cpu_list;		/* List of all CPU's */
+
+static uint8_t	intrd_cs = 0;		/* Index of current sample  */
+static long	intrd_sleeptime = INTRD_NORMAL_SLEEPTIME;
+
+/*
+ * Function prototypes.
+ */
+static	void	intrd_update(void *);
+static	void	intrd_cpu_register(processorid_t);
+static	int	intrd_cpu_setup(cpu_setup_t, int, void *);
+static	void	intrd_stat_all(void);
+
+/*
+ * Helper macros.
+ */
+#define	FOREACH_INTRD_CPU(icpu, icpu_list)			\
+	for (icpu = list_head(&icpu_list); icpu != NULL;	\
+	    icpu = list_next(&icpu_list, icpu))
+
+#define	DTRACE_INTRD(name)	\
+	DTRACE_PROBE(__intrd_##name)
+
+#define	DEBUG	1
+#ifdef	DEBUG
+#define	INTRD_IMPLDBG(args)	cmn_err args
+#else
+#define	INTRD_IMPLDBG(args)
+#endif
+
+void
+intrd(void)
+{
+	processorid_t	cpu_id;
+	callb_cpr_t	cpr;
+	user_t		*u = PTOU(curproc);
+
+	proc_intrd = ttoproc(curthread);
+	proc_intrd->p_cstime = proc_intrd->p_stime = 0;
+	proc_intrd->p_cutime = proc_intrd->p_utime = 0;
+
+	(void) strncpy(u->u_psargs, INTRD_NAME, sizeof(u->u_psargs));
+	(void) strncpy(u->u_comm, INTRD_NAME, sizeof(u->u_comm));
+
+	/* Global mutex lock */
+	mutex_init(&intrd_lock, NULL, MUTEX_DEFAULT, NULL);
+
+	/* Initialize list for CPUs */
+	list_create(&intrd_cpu_list, sizeof (intrd_cpu_t),
+	    offsetof(intrd_cpu_t, ic_next));
+
+	/*
+	 * Build a list of all CPUs able for interrupt handling.
+	 */
+	mutex_enter(&cpu_lock);
+	for (cpu_id = 0; cpu_id <= max_cpu_seqid_ever; cpu_id++) {
+		if (IS_CPU(cpu_id))
+			intrd_cpu_register(cpu_id);
+	}
+
+	/*
+	 * Register a callback if a CPU goes offline or comes online.
+	 */
+	register_cpu_setup_func(intrd_cpu_setup, NULL);
+	mutex_exit(&cpu_lock);
+
+	/* We should have at least one CPU */
+	// ASSERT(!list_is_empty(&intrd_cpu_list));
+	// ASSERT(intrd_number_cpus >= 1);
+
+	CALLB_CPR_INIT(&cpr, &intrd_lock, callb_generic_cpr, INTRD_NAME);
+
+	mutex_enter(&intrd_lock);
+	for (;;) {
+
+		DTRACE_INTRD(stat_all);
+		intrd_stat_all();
+
+		CALLB_CPR_SAFE_BEGIN(&cpr);
+		cv_timedwait(&intrd_cv, &intrd_lock, ddi_get_lbolt() +
+		    SEC_TO_TICK(intrd_sleeptime));
+		CALLB_CPR_SAFE_END(&cpr, &intrd_lock);
+	}
+
+	CALLB_CPR_EXIT(&cpr);
+
+	/*
+	 * Unregister CPU callback.
+	 */
+	mutex_enter(&cpu_lock);
+	unregister_cpu_setup_func(intrd_cpu_setup, NULL);
+	mutex_exit(&cpu_lock);
+}
+
+/*
+ * Allocate a new intrd CPU structure and add CPU
+ * to the global list of CPUs.
+ */
+static void
+intrd_cpu_register(processorid_t cpu_id)
+{
+	cpu_t		*cp = cpu[cpu_id];
+	intrd_cpu_t	*new_cpu;
+
+	new_cpu = kmem_alloc(sizeof (intrd_cpu_t), KM_SLEEP);
+	new_cpu->ic_cpu_id = cpu_id;
+
+	/* Initialize list for interrupt vectors */
+	list_create(&new_cpu->ic_ivec_list, sizeof (intrd_ivec_t),
+	    offsetof(intrd_ivec_t, ii_next));
+
+	list_link_init(&new_cpu->ic_next);
+
+	/* Check if this CPU can handle interrupts */
+	mutex_enter(&cpu_lock);
+	if (cpu_is_nointr(cp))
+		new_cpu->ic_offline = B_TRUE;
+	mutex_exit(&cpu_lock);
+
+	/* Add new CPU to the list of all CPU's */
+	list_insert_tail(&intrd_cpu_list, new_cpu);
+
+	INTRD_IMPLDBG((CE_CONT, "intrd_cpu_register: cpu=0x%x", cpu_id));
+}
+
+/*
+ * Remove a CPU from the global list of CPUs.
+ */
+static void
+intrd_cpu_unregister(processorid_t cpu_id)
+{
+	intrd_cpu_t	*icpu;
+
+	mutex_enter(&intrd_lock);
+	FOREACH_INTRD_CPU(icpu, intrd_cpu_list) {
+		if (icpu->ic_cpu_id == cpu_id) {
+			list_remove(&intrd_cpu_list, icpu);
+			/* XXX or just offline CPU; statistics? */
+			break;
+		}
+	}
+	mutex_exit(&intrd_lock);
+
+	INTRD_IMPLDBG((CE_CONT, "intrd_cpu_unregister: cpu=0x%x",
+	    cpu_id));
+}
+
+/*
+ * Hook for CPU changes.
+ */
+static int
+intrd_cpu_setup(cpu_setup_t what, int cpu_id, void *arg)
+{
+
+	switch (what) {
+	/* XXX */
+	case CPU_OFF:
+		intrd_cpu_unregister(cpu_id);
+		cv_signal(&intrd_cv);
+		break;
+
+	case CPU_INTR_ON:
+		intrd_cpu_register(cpu_id);
+		cv_signal(&intrd_cv);
+		break;
+
+	default:
+		break;
+	}
+
+	return (0);
+}
+
+static void
+intrd_cpu_stat(intrd_cpu_t *icpu)
+{
+	cpu_t		*cp;
+	hrtime_t	msnsecs[NCMSTATES];
+
+	cp = cpu[icpu->ic_cpu_id];
+	get_cpu_mstate(cp, msnsecs);
+
+	icpu->ic_tot[intrd_cs] = msnsecs[CMS_IDLE] + msnsecs[CMS_USER] +
+	    msnsecs[CMS_SYSTEM];
+}
+
+static void
+intrd_irq_stat(intrd_cpu_t *icpu)
+{
+	apic_irq_t	*irqp;
+	int		irq_id;
+
+	/* XXX: Do better then APIC_MAX_VECTOR */
+	for (irq_id = APIC_FIRST_FREE_IRQ; irq_id < APIC_MAX_VECTOR;
+	    irq_id++) {
+/*
+		irqp = apic_irq_table[irq_id];
+		if (icpu->ic_cpu_id == (processorid_t)irqp->airq_cpu) {
+			INTRD_IMPLDBG((CE_CONT, "intrd_irq_stat: irq:0x%x",
+			    irqp->airq_cpu));
+		}
+*/
+	}
+}
+
+static void
+intrd_stat_all(void)
+{
+	intrd_cpu_t	*icpu;
+
+	FOREACH_INTRD_CPU(icpu, intrd_cpu_list) {
+		intrd_cpu_stat(icpu);
+		intrd_irq_stat(icpu);
+	}
+}
+
+static void
+intrd_interrupt_move(void)
+{
+	/* XXX: pcitool_set_intr(dip, arg, mode); */
+}
