Module Name:    src
Committed By:   knakahara
Date:           Mon Aug 17 06:16:03 UTC 2015

Modified Files:
        src/sys/arch/x86/include: intr.h intr_distribute.h pci_machdep_common.h
        src/sys/arch/x86/pci: pci_intr_machdep.c pci_msi_machdep.c
            pci_msi_machdep.h
        src/sys/arch/x86/x86: intr.c
        src/sys/conf: files
        src/sys/dev/pci: if_wm.c pci_stub.c pcivar.h
        src/sys/dev/pci/ixgbe: ixgbe.c ixgbe.h ixv.c ixv.h
        src/sys/kern: files.kern kern_stub.c
        src/sys/secmodel/suser: secmodel_suser.c
        src/sys/sys: Makefile intr.h kauth.h
Added Files:
        src/sys/kern: subr_interrupt.c
        src/sys/sys: interrupt.h intrio.h

Log Message:
Add kernel code to support intrctl(8).


To generate a diff of this commit:
cvs rdiff -u -r1.47 -r1.48 src/sys/arch/x86/include/intr.h
cvs rdiff -u -r1.1 -r1.2 src/sys/arch/x86/include/intr_distribute.h
cvs rdiff -u -r1.20 -r1.21 src/sys/arch/x86/include/pci_machdep_common.h
cvs rdiff -u -r1.36 -r1.37 src/sys/arch/x86/pci/pci_intr_machdep.c
cvs rdiff -u -r1.8 -r1.9 src/sys/arch/x86/pci/pci_msi_machdep.c
cvs rdiff -u -r1.2 -r1.3 src/sys/arch/x86/pci/pci_msi_machdep.h
cvs rdiff -u -r1.86 -r1.87 src/sys/arch/x86/x86/intr.c
cvs rdiff -u -r1.1130 -r1.1131 src/sys/conf/files
cvs rdiff -u -r1.345 -r1.346 src/sys/dev/pci/if_wm.c
cvs rdiff -u -r1.1 -r1.2 src/sys/dev/pci/pci_stub.c
cvs rdiff -u -r1.103 -r1.104 src/sys/dev/pci/pcivar.h
cvs rdiff -u -r1.35 -r1.36 src/sys/dev/pci/ixgbe/ixgbe.c
cvs rdiff -u -r1.8 -r1.9 src/sys/dev/pci/ixgbe/ixgbe.h
cvs rdiff -u -r1.14 -r1.15 src/sys/dev/pci/ixgbe/ixv.c
cvs rdiff -u -r1.6 -r1.7 src/sys/dev/pci/ixgbe/ixv.h
cvs rdiff -u -r1.6 -r1.7 src/sys/kern/files.kern
cvs rdiff -u -r1.39 -r1.40 src/sys/kern/kern_stub.c
cvs rdiff -u -r0 -r1.1 src/sys/kern/subr_interrupt.c
cvs rdiff -u -r1.41 -r1.42 src/sys/secmodel/suser/secmodel_suser.c
cvs rdiff -u -r1.156 -r1.157 src/sys/sys/Makefile
cvs rdiff -u -r0 -r1.1 src/sys/sys/interrupt.h src/sys/sys/intrio.h
cvs rdiff -u -r1.18 -r1.19 src/sys/sys/intr.h
cvs rdiff -u -r1.71 -r1.72 src/sys/sys/kauth.h

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/arch/x86/include/intr.h
diff -u src/sys/arch/x86/include/intr.h:1.47 src/sys/arch/x86/include/intr.h:1.48
--- src/sys/arch/x86/include/intr.h:1.47	Mon Apr 27 06:51:40 2015
+++ src/sys/arch/x86/include/intr.h	Mon Aug 17 06:16:02 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.h,v 1.47 2015/04/27 06:51:40 knakahara Exp $	*/
+/*	$NetBSD: intr.h,v 1.48 2015/08/17 06:16:02 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 1998, 2001, 2006, 2007, 2008 The NetBSD Foundation, Inc.
@@ -86,13 +86,14 @@ struct intrsource {
 	void *is_recurse;		/* entry for spllower */
 	void *is_resume;		/* entry for doreti */
 	lwp_t *is_lwp;			/* for soft interrupts */
-	struct evcnt is_evcnt;		/* interrupt counter */
+	struct evcnt is_evcnt;		/* interrupt counter per cpu */
 	int is_flags;			/* see below */
 	int is_type;			/* level, edge */
 	int is_idtvec;
 	int is_minlevel;
 	char is_evname[32];		/* event counter name */
 	char is_intrid[INTRIDBUF];	/* intrid created by create_intrid() */
+	char is_xname[INTRDEVNAMEBUF];	/* device names */
 	cpuid_t is_active_cpu;		/* active cpuid */
 	struct percpu_evcnt *is_saved_evcnt;	/* interrupt count of deactivated cpus */
 	SIMPLEQ_ENTRY(intrsource) is_list;	/* link of intrsources */
@@ -185,6 +186,8 @@ typedef uint64_t intr_handle_t;
 
 void intr_default_setup(void);
 void x86_nmi(void);
+void *intr_establish_xname(int, struct pic *, int, int, int, int (*)(void *),
+			   void *, bool, const char *);
 void *intr_establish(int, struct pic *, int, int, int, int (*)(void *), void *, bool);
 void intr_disestablish(struct intrhand *);
 void intr_add_pcibus(struct pcibus_attach_args *);

Index: src/sys/arch/x86/include/intr_distribute.h
diff -u src/sys/arch/x86/include/intr_distribute.h:1.1 src/sys/arch/x86/include/intr_distribute.h:1.2
--- src/sys/arch/x86/include/intr_distribute.h:1.1	Mon Apr 27 06:42:52 2015
+++ src/sys/arch/x86/include/intr_distribute.h	Mon Aug 17 06:16:02 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr_distribute.h,v 1.1 2015/04/27 06:42:52 knakahara Exp $	*/
+/*	$NetBSD: intr_distribute.h,v 1.2 2015/08/17 06:16:02 knakahara Exp $	*/
 
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
@@ -34,6 +34,7 @@
 #include <sys/kcpuset.h>
 
 int intr_distribute(struct intrhand *, const kcpuset_t *, kcpuset_t *);
+int intr_distribute_handler(const char *, const kcpuset_t *, kcpuset_t *);
 
 #endif /* _KERNEL */
 

Index: src/sys/arch/x86/include/pci_machdep_common.h
diff -u src/sys/arch/x86/include/pci_machdep_common.h:1.20 src/sys/arch/x86/include/pci_machdep_common.h:1.21
--- src/sys/arch/x86/include/pci_machdep_common.h:1.20	Thu Aug 13 04:39:33 2015
+++ src/sys/arch/x86/include/pci_machdep_common.h	Mon Aug 17 06:16:02 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_machdep_common.h,v 1.20 2015/08/13 04:39:33 msaitoh Exp $	*/
+/*	$NetBSD: pci_machdep_common.h,v 1.21 2015/08/17 06:16:02 knakahara Exp $	*/
 
 /*
  * Copyright (c) 1996 Christopher G. Demetriou.  All rights reserved.
@@ -118,7 +118,6 @@ const struct evcnt *pci_intr_evcnt(pci_c
 void		*pci_intr_establish(pci_chipset_tag_t, pci_intr_handle_t,
 		    int, int (*)(void *), void *);
 void		pci_intr_disestablish(pci_chipset_tag_t, void *);
-int		pci_intr_distribute(void *, const kcpuset_t *, kcpuset_t *);
 
 typedef enum {
 	PCI_INTR_TYPE_INTX = 0,

Index: src/sys/arch/x86/pci/pci_intr_machdep.c
diff -u src/sys/arch/x86/pci/pci_intr_machdep.c:1.36 src/sys/arch/x86/pci/pci_intr_machdep.c:1.37
--- src/sys/arch/x86/pci/pci_intr_machdep.c:1.36	Thu Aug 13 04:39:33 2015
+++ src/sys/arch/x86/pci/pci_intr_machdep.c	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_intr_machdep.c,v 1.36 2015/08/13 04:39:33 msaitoh Exp $	*/
+/*	$NetBSD: pci_intr_machdep.c,v 1.37 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 1997, 1998, 2009 The NetBSD Foundation, Inc.
@@ -73,7 +73,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.36 2015/08/13 04:39:33 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_intr_machdep.c,v 1.37 2015/08/17 06:16:03 knakahara Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -275,8 +275,8 @@ pci_intr_setattr(pci_chipset_tag_t pc, p
 }
 
 void *
-pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
-    int level, int (*func)(void *), void *arg)
+pci_intr_establish_xname(pci_chipset_tag_t pc, pci_intr_handle_t ih,
+    int level, int (*func)(void *), void *arg, const char *xname)
 {
 	int pin, irq;
 	struct pic *pic;
@@ -295,9 +295,11 @@ pci_intr_establish(pci_chipset_tag_t pc,
 
 	if (INT_VIA_MSI(ih)) {
 		if (MSI_INT_IS_MSIX(ih))
-			return x86_pci_msix_establish(pc, ih, level, func, arg);
+			return x86_pci_msix_establish(pc, ih, level, func, arg,
+			    xname);
 		else
-			return x86_pci_msi_establish(pc, ih, level, func, arg);
+			return x86_pci_msi_establish(pc, ih, level, func, arg,
+			    xname);
 	}
 
 	pic = &i8259_pic;
@@ -320,8 +322,16 @@ pci_intr_establish(pci_chipset_tag_t pc,
 	}
 #endif
 
-	return intr_establish(irq, pic, pin, IST_LEVEL, level, func, arg,
-	    mpsafe);
+	return intr_establish_xname(irq, pic, pin, IST_LEVEL, level, func, arg,
+	    mpsafe, xname);
+}
+
+void *
+pci_intr_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
+    int level, int (*func)(void *), void *arg)
+{
+
+	return pci_intr_establish_xname(pc, ih, level, func, arg, "unknown");
 }
 
 void
@@ -340,15 +350,6 @@ pci_intr_disestablish(pci_chipset_tag_t 
 	intr_disestablish(cookie);
 }
 
-int
-pci_intr_distribute(void *cookie, const kcpuset_t *newset, kcpuset_t *oldset)
-{
-
-	/* XXX Is pc_ov->ov_intr_distribute required? */
-
-	return intr_distribute(cookie, newset, oldset);
-}
-
 #if NIOAPIC > 0
 pci_intr_type_t
 pci_intr_type(pci_intr_handle_t ih)

Index: src/sys/arch/x86/pci/pci_msi_machdep.c
diff -u src/sys/arch/x86/pci/pci_msi_machdep.c:1.8 src/sys/arch/x86/pci/pci_msi_machdep.c:1.9
--- src/sys/arch/x86/pci/pci_msi_machdep.c:1.8	Thu Aug 13 04:39:33 2015
+++ src/sys/arch/x86/pci/pci_msi_machdep.c	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_msi_machdep.c,v 1.8 2015/08/13 04:39:33 msaitoh Exp $	*/
+/*	$NetBSD: pci_msi_machdep.c,v 1.9 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
@@ -34,7 +34,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_msi_machdep.c,v 1.8 2015/08/13 04:39:33 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_msi_machdep.c,v 1.9 2015/08/17 06:16:03 knakahara Exp $");
 
 #include "opt_intrdebug.h"
 
@@ -208,7 +208,8 @@ pci_msi_alloc_common(pci_intr_handle_t *
 
 static void *
 pci_msi_common_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
-    int level, int (*func)(void *), void *arg, struct pic *pic)
+    int level, int (*func)(void *), void *arg, struct pic *pic,
+    const char *xname)
 {
 	int irq, pin;
 	bool mpsafe;
@@ -219,8 +220,8 @@ pci_msi_common_establish(pci_chipset_tag
 	pin = MSI_INT_VEC(ih);
 	mpsafe = ((ih & MPSAFE_MASK) != 0);
 
-	return intr_establish(irq, pic, pin, IST_EDGE, level, func, arg,
-	    mpsafe);
+	return intr_establish_xname(irq, pic, pin, IST_EDGE, level, func, arg,
+	    mpsafe, xname);
 }
 
 static void
@@ -396,7 +397,7 @@ x86_pci_msi_release(pci_chipset_tag_t pc
  */
 void *
 x86_pci_msi_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
-    int level, int (*func)(void *), void *arg)
+    int level, int (*func)(void *), void *arg, const char *xname)
 {
 	struct pic *pic;
 
@@ -406,7 +407,7 @@ x86_pci_msi_establish(pci_chipset_tag_t 
 		return NULL;
 	}
 
-	return pci_msi_common_establish(pc, ih, level, func, arg, pic);
+	return pci_msi_common_establish(pc, ih, level, func, arg, pic, xname);
 }
 
 /*
@@ -441,7 +442,7 @@ x86_pci_msix_release(pci_chipset_tag_t p
  */
 void *
 x86_pci_msix_establish(pci_chipset_tag_t pc, pci_intr_handle_t ih,
-    int level, int (*func)(void *), void *arg)
+    int level, int (*func)(void *), void *arg, const char *xname)
 {
 	struct pic *pic;
 
@@ -451,7 +452,7 @@ x86_pci_msix_establish(pci_chipset_tag_t
 		return NULL;
 	}
 
-	return pci_msi_common_establish(pc, ih, level, func, arg, pic);
+	return pci_msi_common_establish(pc, ih, level, func, arg, pic, xname);
 }
 
 /*

Index: src/sys/arch/x86/pci/pci_msi_machdep.h
diff -u src/sys/arch/x86/pci/pci_msi_machdep.h:1.2 src/sys/arch/x86/pci/pci_msi_machdep.h:1.3
--- src/sys/arch/x86/pci/pci_msi_machdep.h:1.2	Fri May 15 08:36:41 2015
+++ src/sys/arch/x86/pci/pci_msi_machdep.h	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pci_msi_machdep.h,v 1.2 2015/05/15 08:36:41 knakahara Exp $	*/
+/*	$NetBSD: pci_msi_machdep.h,v 1.3 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*
  * Copyright (c) 2015 Internet Initiative Japan Inc.
@@ -34,13 +34,13 @@ const char	*x86_pci_msi_string(pci_chips
 void		x86_pci_msi_release(pci_chipset_tag_t, pci_intr_handle_t *,
 		    int);
 void		*x86_pci_msi_establish(pci_chipset_tag_t, pci_intr_handle_t,
-		    int, int (*)(void *), void *);
+		    int, int (*)(void *), void *, const char *);
 void		x86_pci_msi_disestablish(pci_chipset_tag_t, void *);
 
 void		x86_pci_msix_release(pci_chipset_tag_t, pci_intr_handle_t *,
 		    int);
 void		*x86_pci_msix_establish(pci_chipset_tag_t, pci_intr_handle_t,
-		    int, int (*)(void *), void *);
+		    int, int (*)(void *), void *, const char *xname);
 void		x86_pci_msix_disestablish(pci_chipset_tag_t, void *);
 
 #endif /* _X86_PCI_PCI_MSI_MACHDEP_H_ */

Index: src/sys/arch/x86/x86/intr.c
diff -u src/sys/arch/x86/x86/intr.c:1.86 src/sys/arch/x86/x86/intr.c:1.87
--- src/sys/arch/x86/x86/intr.c:1.86	Tue Jun 23 10:00:13 2015
+++ src/sys/arch/x86/x86/intr.c	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.c,v 1.86 2015/06/23 10:00:13 msaitoh Exp $	*/
+/*	$NetBSD: intr.c,v 1.87 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008, 2009 The NetBSD Foundation, Inc.
@@ -133,7 +133,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.86 2015/06/23 10:00:13 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.87 2015/08/17 06:16:03 knakahara Exp $");
 
 #include "opt_intrdebug.h"
 #include "opt_multiprocessor.h"
@@ -151,6 +151,10 @@ __KERNEL_RCSID(0, "$NetBSD: intr.c,v 1.8
 #include <sys/cpu.h>
 #include <sys/atomic.h>
 #include <sys/xcall.h>
+#include <sys/interrupt.h>
+
+#include <sys/kauth.h>
+#include <sys/conf.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -224,6 +228,8 @@ static void intr_source_free(struct cpu_
 static void intr_establish_xcall(void *, void *);
 static void intr_disestablish_xcall(void *, void *);
 
+static const char *legacy_intr_string(int, char *, size_t, struct pic *);
+
 static inline bool redzone_const_or_false(bool);
 static inline int redzone_const_or_zero(int);
 
@@ -829,6 +835,19 @@ intr_findpic(int num)
 }
 
 /*
+ * Append device name to intrsource. If device A and device B share IRQ number,
+ * the device name of the interrupt id is "device A, device B".
+ */
+static void
+intr_append_intrsource_xname(struct intrsource *isp, const char *xname)
+{
+
+	if (isp->is_xname[0] != '\0')
+		strlcat(isp->is_xname, ", ", sizeof(isp->is_xname));
+	strlcat(isp->is_xname, xname, sizeof(isp->is_xname));
+}
+
+/*
  * Handle per-CPU component of interrupt establish.
  *
  * => caller (on initiating CPU) holds cpu_lock on our behalf
@@ -882,8 +901,9 @@ intr_establish_xcall(void *arg1, void *a
 }
 
 void *
-intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level,
-	       int (*handler)(void *), void *arg, bool known_mpsafe)
+intr_establish_xname(int legacy_irq, struct pic *pic, int pin, int type,
+		     int level, int (*handler)(void *), void *arg,
+		     bool known_mpsafe, const char *xname)
 {
 	struct intrhand **p, *q, *ih;
 	struct cpu_info *ci;
@@ -958,7 +978,7 @@ intr_establish(int legacy_irq, struct pi
 
 	source->is_pin = pin;
 	source->is_pic = pic;
-
+	intr_append_intrsource_xname(source, xname);
 	switch (source->is_type) {
 	case IST_NONE:
 		source->is_type = type;
@@ -1047,6 +1067,15 @@ intr_establish(int legacy_irq, struct pi
 	return (ih);
 }
 
+void *
+intr_establish(int legacy_irq, struct pic *pic, int pin, int type, int level,
+	       int (*handler)(void *), void *arg, bool known_mpsafe)
+{
+
+	return intr_establish_xname(legacy_irq, pic, pin, type,
+	    level, handler, arg, known_mpsafe, "unknown");
+}
+
 /*
  * Called on bound CPU to handle intr_disestablish().
  *
@@ -1918,17 +1947,159 @@ intr_set_affinity(struct intrsource *isp
 	return err;
 }
 
-int
-intr_distribute(struct intrhand *ih, const kcpuset_t *newset, kcpuset_t *oldset)
+static bool
+intr_is_affinity_intrsource(struct intrsource *isp, const kcpuset_t *cpuset)
 {
+	struct cpu_info *ci;
+
+	KASSERT(mutex_owned(&cpu_lock));
+
+	ci = isp->is_handlers->ih_cpu;
+	KASSERT(ci != NULL);
+
+	return kcpuset_isset(cpuset, cpu_index(ci));
+}
+
+static struct intrhand *
+intr_get_handler(const char *intrid)
+{
+	struct intrsource *isp;
+
+	KASSERT(mutex_owned(&cpu_lock));
+
+	isp = intr_get_io_intrsource(intrid);
+	if (isp == NULL)
+		return NULL;
+
+	return isp->is_handlers;
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+uint64_t
+interrupt_get_count(const char *intrid, u_int cpu_idx)
+{
+	struct cpu_info *ci;
 	struct intrsource *isp;
-	int ret, slot;
+	struct intrhand *ih;
+	struct percpu_evcnt pep;
+	cpuid_t cpuid;
+	int i, slot;
+	uint64_t count = 0;
 
+	ci = cpu_lookup(cpu_idx);
+	cpuid = ci->ci_cpuid;
+
+	mutex_enter(&cpu_lock);
+
+	ih = intr_get_handler(intrid);
+	if (ih == NULL) {
+		count = 0;
+		goto out;
+	}
+	slot = ih->ih_slot;
+	isp = ih->ih_cpu->ci_isources[slot];
+
+	for (i = 0; i < ncpu; i++) {
+		pep = isp->is_saved_evcnt[i];
+		if (cpuid == pep.cpuid) {
+			if (isp->is_active_cpu == pep.cpuid) {
+				count = isp->is_evcnt.ev_count;
+				goto out;
+			} else {
+				count = pep.count;
+				goto out;
+			}
+		}
+	}
+
+ out:
+	mutex_exit(&cpu_lock);
+	return count;
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+void
+interrupt_get_assigned(const char *intrid, kcpuset_t *cpuset)
+{
+	struct cpu_info *ci;
+	struct intrhand *ih;
+
+	kcpuset_zero(cpuset);
+
+	mutex_enter(&cpu_lock);
+
+	ih = intr_get_handler(intrid);
 	if (ih == NULL)
-		return EINVAL;
+		goto out;
+
+	ci = ih->ih_cpu;
+	kcpuset_set(cpuset, cpu_index(ci));
+
+ out:
+	mutex_exit(&cpu_lock);
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+void
+interrupt_get_available(kcpuset_t *cpuset)
+{
+	CPU_INFO_ITERATOR cii;
+	struct cpu_info *ci;
+
+	kcpuset_zero(cpuset);
+
+	mutex_enter(&cpu_lock);
+	for (CPU_INFO_FOREACH(cii, ci)) {
+		if ((ci->ci_schedstate.spc_flags & SPCF_NOINTR) == 0) {
+			kcpuset_set(cpuset, cpu_index(ci));
+		}
+	}
+	mutex_exit(&cpu_lock);
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+void
+interrupt_get_devname(const char *intrid, char *buf, size_t len)
+{
+	struct intrsource *isp;
+	struct intrhand *ih;
+	int slot;
 
 	mutex_enter(&cpu_lock);
 
+	ih = intr_get_handler(intrid);
+	if (ih == NULL) {
+		buf[0] = '\0';
+		goto out;
+	}
+	slot = ih->ih_slot;
+	isp = ih->ih_cpu->ci_isources[slot];
+	strncpy(buf, isp->is_xname, INTRDEVNAMEBUF);
+
+ out:
+	mutex_exit(&cpu_lock);
+}
+
+static int
+intr_distribute_locked(struct intrhand *ih, const kcpuset_t *newset,
+    kcpuset_t *oldset)
+{
+	struct intrsource *isp;
+	int slot;
+
+	KASSERT(mutex_owned(&cpu_lock));
+
+	if (ih == NULL)
+		return EINVAL;
+
 	slot = ih->ih_slot;
 	isp = ih->ih_cpu->ci_isources[slot];
 	KASSERT(isp != NULL);
@@ -1936,9 +2107,114 @@ intr_distribute(struct intrhand *ih, con
 	if (oldset != NULL)
 		intr_get_affinity(isp, oldset);
 
-	ret = intr_set_affinity(isp, newset);
+	return intr_set_affinity(isp, newset);
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+int
+interrupt_distribute(void *cookie, const kcpuset_t *newset, kcpuset_t *oldset)
+{
+	int error;
+	struct intrhand *ih = cookie;
 
+	mutex_enter(&cpu_lock);
+	error = intr_distribute_locked(ih, newset, oldset);
 	mutex_exit(&cpu_lock);
 
-	return ret;
+	return error;
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+int
+interrupt_distribute_handler(const char *intrid, const kcpuset_t *newset,
+    kcpuset_t *oldset)
+{
+	int error;
+	struct intrhand *ih;
+
+	mutex_enter(&cpu_lock);
+
+	ih = intr_get_handler(intrid);
+	if (ih == NULL) {
+		error = ENOENT;
+		goto out;
+	}
+	error = intr_distribute_locked(ih, newset, oldset);
+
+ out:
+	mutex_exit(&cpu_lock);
+	return error;
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+struct intrids_handler *
+interrupt_construct_intrids(const kcpuset_t *cpuset)
+{
+	struct intrsource *isp;
+	struct intrids_handler *ii_handler;
+	intrid_t *ids;
+	int i, count;
+
+	if (kcpuset_iszero(cpuset))
+		return 0;
+
+	/*
+	 * Count the number of interrupts which affinity to any cpu of "cpuset".
+	 */
+	count = 0;
+	mutex_enter(&cpu_lock);
+	SIMPLEQ_FOREACH(isp, &io_interrupt_sources, is_list) {
+		if (intr_is_affinity_intrsource(isp, cpuset))
+			count++;
+	}
+	mutex_exit(&cpu_lock);
+
+	ii_handler = kmem_zalloc(sizeof(int) + sizeof(intrid_t) * count,
+	    KM_SLEEP);
+	if (ii_handler == NULL)
+		return NULL;
+	ii_handler->iih_nids = count;
+	if (count == 0)
+		return ii_handler;
+
+	ids = ii_handler->iih_intrids;
+	i = 0;
+	mutex_enter(&cpu_lock);
+	SIMPLEQ_FOREACH(isp, &io_interrupt_sources, is_list) {
+		/* Ignore devices attached after counting "count". */
+		if (i >= count) {
+			DPRINTF(("New devices are attached after counting.\n"));
+			break;
+		}
+
+		if (!intr_is_affinity_intrsource(isp, cpuset))
+			continue;
+
+		strncpy(ids[i], isp->is_intrid, sizeof(intrid_t));
+		i++;
+	}
+	mutex_exit(&cpu_lock);
+
+	return ii_handler;
+}
+
+/*
+ * MI interface for subr_interrupt.c
+ */
+void
+interrupt_destruct_intrids(struct intrids_handler *ii_handler)
+{
+	size_t iih_size;
+
+	if (ii_handler == NULL)
+		return;
+
+	iih_size = sizeof(int) + sizeof(intrid_t) * ii_handler->iih_nids;
+	kmem_free(ii_handler, iih_size);
 }

Index: src/sys/conf/files
diff -u src/sys/conf/files:1.1130 src/sys/conf/files:1.1131
--- src/sys/conf/files:1.1130	Sat Aug  1 21:19:24 2015
+++ src/sys/conf/files	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files,v 1.1130 2015/08/01 21:19:24 jmcneill Exp $
+#	$NetBSD: files,v 1.1131 2015/08/17 06:16:03 knakahara Exp $
 #	@(#)files.newconf	7.5 (Berkeley) 5/10/93
 
 version 	20141030
@@ -1443,6 +1443,9 @@ file	kern/kern_drvctl.c		drvctl		needs-f
 defpseudo cpuctl
 defflag				CPU_UCODE: firmload
 
+# interrupt control
+defpseudo intrctl
+
 # pass-to-userspace transporter
 defpseudo putter
 file	dev/putter/putter.c		putter

Index: src/sys/dev/pci/if_wm.c
diff -u src/sys/dev/pci/if_wm.c:1.345 src/sys/dev/pci/if_wm.c:1.346
--- src/sys/dev/pci/if_wm.c:1.345	Tue Jul 28 07:15:03 2015
+++ src/sys/dev/pci/if_wm.c	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: if_wm.c,v 1.345 2015/07/28 07:15:03 msaitoh Exp $	*/
+/*	$NetBSD: if_wm.c,v 1.346 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*
  * Copyright (c) 2001, 2002, 2003, 2004 Wasabi Systems, Inc.
@@ -81,7 +81,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.345 2015/07/28 07:15:03 msaitoh Exp $");
+__KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.346 2015/08/17 06:16:03 knakahara Exp $");
 
 #ifdef _KERNEL_OPT
 #include "opt_net_mpsafe.h"
@@ -99,6 +99,7 @@ __KERNEL_RCSID(0, "$NetBSD: if_wm.c,v 1.
 #include <sys/device.h>
 #include <sys/queue.h>
 #include <sys/syslog.h>
+#include <sys/interrupt.h>
 
 #include <sys/rndsource.h>
 
@@ -1601,7 +1602,8 @@ wm_attach(device_t parent, device_t self
 #ifdef WM_MPSAFE
 	pci_intr_setattr(pc, &ih, PCI_INTR_MPSAFE, true);
 #endif
-	sc->sc_ihs[0] = pci_intr_establish(pc, ih, IPL_NET, wm_intr_legacy,sc);
+	sc->sc_ihs[0] = pci_intr_establish_xname(pc, ih, IPL_NET,
+	    wm_intr_legacy, sc, device_xname(sc->sc_dev));
 	if (sc->sc_ihs[0] == NULL) {
 		aprint_error_dev(sc->sc_dev, "unable to establish interrupt");
 		if (intrstr != NULL)
@@ -1627,6 +1629,7 @@ alloc_retry:
 	if (pci_intr_type(sc->sc_intrs[0]) == PCI_INTR_TYPE_MSIX) {
 		void *vih;
 		kcpuset_t *affinity;
+		char intr_xname[INTRDEVNAMEBUF];
 
 		kcpuset_create(&affinity, false);
 
@@ -1639,9 +1642,14 @@ alloc_retry:
 			    &sc->sc_intrs[msix_matrix[i].intridx],
 			    PCI_INTR_MPSAFE, true);
 #endif
-			vih = pci_intr_establish(pc,
+			memset(intr_xname, 0, sizeof(intr_xname));
+			strlcat(intr_xname, device_xname(sc->sc_dev),
+			    sizeof(intr_xname));
+			strlcat(intr_xname, msix_matrix[i].intrname,
+			    sizeof(intr_xname));
+			vih = pci_intr_establish_xname(pc,
 			    sc->sc_intrs[msix_matrix[i].intridx], IPL_NET,
-			    msix_matrix[i].func, sc);
+			    msix_matrix[i].func, sc, intr_xname);
 			if (vih == NULL) {
 				aprint_error_dev(sc->sc_dev,
 				    "unable to establish MSI-X(for %s)%s%s\n",
@@ -1661,7 +1669,7 @@ alloc_retry:
 			kcpuset_zero(affinity);
 			/* Round-robin affinity */
 			kcpuset_set(affinity, msix_matrix[i].cpuid % ncpu);
-			error = pci_intr_distribute(vih, affinity, NULL);
+			error = interrupt_distribute(vih, affinity, NULL);
 			if (error == 0) {
 				aprint_normal_dev(sc->sc_dev,
 				    "for %s interrupting at %s affinity to %u\n",
@@ -1684,8 +1692,8 @@ alloc_retry:
 #ifdef WM_MPSAFE
 		pci_intr_setattr(pc, &sc->sc_intrs[0], PCI_INTR_MPSAFE, true);
 #endif
-		sc->sc_ihs[0] = pci_intr_establish(pc, sc->sc_intrs[0],
-		    IPL_NET, wm_intr_legacy, sc);
+		sc->sc_ihs[0] = pci_intr_establish_xname(pc, sc->sc_intrs[0],
+		    IPL_NET, wm_intr_legacy, sc, device_xname(sc->sc_dev));
 		if (sc->sc_ihs[0] == NULL) {
 			aprint_error_dev(sc->sc_dev,"unable to establish %s\n",
 			    (pci_intr_type(sc->sc_intrs[0])

Index: src/sys/dev/pci/pci_stub.c
diff -u src/sys/dev/pci/pci_stub.c:1.1 src/sys/dev/pci/pci_stub.c:1.2
--- src/sys/dev/pci/pci_stub.c:1.1	Wed Aug 24 20:27:35 2011
+++ src/sys/dev/pci/pci_stub.c	Mon Aug 17 06:16:03 2015
@@ -1,5 +1,5 @@
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pci_stub.c,v 1.1 2011/08/24 20:27:35 dyoung Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pci_stub.c,v 1.2 2015/08/17 06:16:03 knakahara Exp $");
 
 #include "opt_pci.h"
 
@@ -14,11 +14,15 @@ int default_pci_bus_devorder(pci_chipset
 int default_pci_chipset_tag_create(pci_chipset_tag_t, uint64_t,
     const struct pci_overrides *, void *, pci_chipset_tag_t *);
 void default_pci_chipset_tag_destroy(pci_chipset_tag_t);
+void *default_pci_intr_establish_xname(pci_chipset_tag_t, pci_intr_handle_t,
+    int, int (*)(void *), void *, const char *);
 
 __strict_weak_alias(pci_bus_devorder, default_pci_bus_devorder);
 __strict_weak_alias(pci_chipset_tag_create, default_pci_chipset_tag_create);
 __strict_weak_alias(pci_chipset_tag_destroy, default_pci_chipset_tag_destroy);
 
+__strict_weak_alias(pci_intr_establish_xname, default_pci_intr_establish_xname);
+
 int
 default_pci_bus_devorder(pci_chipset_tag_t pc, int bus, uint8_t *devs,
     int maxdevs)
@@ -43,3 +47,11 @@ default_pci_chipset_tag_create(pci_chips
 {
 	return EOPNOTSUPP;
 }
+
+void *
+default_pci_intr_establish_xname(pci_chipset_tag_t pc, pci_intr_handle_t ih,
+    int level, int (*func)(void *), void *arg, const char *__nouse)
+{
+
+	return pci_intr_establish(pc, ih, level, func, arg);
+}

Index: src/sys/dev/pci/pcivar.h
diff -u src/sys/dev/pci/pcivar.h:1.103 src/sys/dev/pci/pcivar.h:1.104
--- src/sys/dev/pci/pcivar.h:1.103	Thu Aug 13 04:39:33 2015
+++ src/sys/dev/pci/pcivar.h	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pcivar.h,v 1.103 2015/08/13 04:39:33 msaitoh Exp $	*/
+/*	$NetBSD: pcivar.h,v 1.104 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*
  * Copyright (c) 1996, 1997 Christopher G. Demetriou.  All rights reserved.
@@ -340,6 +340,8 @@ int	pci_chipset_tag_create(pci_chipset_t
 	                       void *, pci_chipset_tag_t *);
 void	pci_chipset_tag_destroy(pci_chipset_tag_t);
 int	pci_bus_devorder(pci_chipset_tag_t, int, uint8_t *, int);
+void	*pci_intr_establish_xname(pci_chipset_tag_t, pci_intr_handle_t,
+				  int, int (*)(void *), void *, const char *);
 
 /*
  * Device abstraction for inheritance by elanpci(4), for example.

Index: src/sys/dev/pci/ixgbe/ixgbe.c
diff -u src/sys/dev/pci/ixgbe/ixgbe.c:1.35 src/sys/dev/pci/ixgbe/ixgbe.c:1.36
--- src/sys/dev/pci/ixgbe/ixgbe.c:1.35	Thu Aug 13 10:03:37 2015
+++ src/sys/dev/pci/ixgbe/ixgbe.c	Mon Aug 17 06:16:03 2015
@@ -59,7 +59,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe.c 279805 2015-03-09 10:29:15Z araujo $*/
-/*$NetBSD: ixgbe.c,v 1.35 2015/08/13 10:03:37 msaitoh Exp $*/
+/*$NetBSD: ixgbe.c,v 1.36 2015/08/17 06:16:03 knakahara Exp $*/
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -2689,7 +2689,7 @@ ixgbe_allocate_msix(struct adapter *adap
 		/* Round-robin affinity */
 		kcpuset_zero(affinity);
 		kcpuset_set(affinity, cpu_id % ncpu);
-		error = pci_intr_distribute(adapter->osdep.ihs[i], affinity,
+		error = interrupt_distribute(adapter->osdep.ihs[i], affinity,
 		    NULL);
 		aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
 		    intrstr);
@@ -2736,7 +2736,7 @@ ixgbe_allocate_msix(struct adapter *adap
 	/* Round-robin affinity */
 	kcpuset_zero(affinity);
 	kcpuset_set(affinity, cpu_id % ncpu);
-	error = pci_intr_distribute(adapter->osdep.ihs[vector], affinity,NULL);
+	error = interrupt_distribute(adapter->osdep.ihs[vector], affinity,NULL);
 
 	aprint_normal_dev(dev,
 	    "for link, interrupting at %s", intrstr);

Index: src/sys/dev/pci/ixgbe/ixgbe.h
diff -u src/sys/dev/pci/ixgbe/ixgbe.h:1.8 src/sys/dev/pci/ixgbe/ixgbe.h:1.9
--- src/sys/dev/pci/ixgbe/ixgbe.h:1.8	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixgbe.h	Mon Aug 17 06:16:03 2015
@@ -59,7 +59,7 @@
  * POSSIBILITY OF SUCH DAMAGE.
  */
 /*$FreeBSD: head/sys/dev/ixgbe/ixgbe.h 279393 2015-02-28 14:57:57Z ngie $*/
-/*$NetBSD: ixgbe.h,v 1.8 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixgbe.h,v 1.9 2015/08/17 06:16:03 knakahara Exp $*/
 
 
 #ifndef _IXGBE_H_
@@ -107,6 +107,7 @@
 #include <sys/endian.h>
 #include <sys/workqueue.h>
 #include <sys/cpu.h>
+#include <sys/interrupt.h>
 
 #include "ixgbe_netbsd.h"
 #include "ixgbe_api.h"

Index: src/sys/dev/pci/ixgbe/ixv.c
diff -u src/sys/dev/pci/ixgbe/ixv.c:1.14 src/sys/dev/pci/ixgbe/ixv.c:1.15
--- src/sys/dev/pci/ixgbe/ixv.c:1.14	Fri Aug 14 15:27:28 2015
+++ src/sys/dev/pci/ixgbe/ixv.c	Mon Aug 17 06:16:03 2015
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixv.c 275358 2014-12-01 11:45:24Z hselasky $*/
-/*$NetBSD: ixv.c,v 1.14 2015/08/14 15:27:28 martin Exp $*/
+/*$NetBSD: ixv.c,v 1.15 2015/08/17 06:16:03 knakahara Exp $*/
 
 #include "opt_inet.h"
 #include "opt_inet6.h"
@@ -1713,7 +1713,7 @@ ixv_allocate_msix(struct adapter *adapte
 		/* Round-robin affinity */
 		kcpuset_zero(affinity);
 		kcpuset_set(affinity, cpu_id % ncpu);
-		error = pci_intr_distribute(adapter->osdep.ihs[i], affinity,
+		error = interrupt_distribute(adapter->osdep.ihs[i], affinity,
 		    NULL);
 		aprint_normal_dev(dev, "for TX/RX, interrupting at %s",
 		    intrstr);
@@ -1750,7 +1750,7 @@ ixv_allocate_msix(struct adapter *adapte
 	/* Round-robin affinity */
 	kcpuset_zero(affinity);
 	kcpuset_set(affinity, cpu_id % ncpu);
-	error = pci_intr_distribute(adapter->osdep.ihs[vector], affinity,NULL);
+	error = interrupt_distribute(adapter->osdep.ihs[vector], affinity,NULL);
 
 	aprint_normal_dev(dev,
 	    "for link, interrupting at %s, ", intrstr);

Index: src/sys/dev/pci/ixgbe/ixv.h
diff -u src/sys/dev/pci/ixgbe/ixv.h:1.6 src/sys/dev/pci/ixgbe/ixv.h:1.7
--- src/sys/dev/pci/ixgbe/ixv.h:1.6	Wed Aug  5 04:08:44 2015
+++ src/sys/dev/pci/ixgbe/ixv.h	Mon Aug 17 06:16:03 2015
@@ -31,7 +31,7 @@
 
 ******************************************************************************/
 /*$FreeBSD: head/sys/dev/ixgbe/ixv.h 257176 2013-10-26 17:58:36Z glebius $*/
-/*$NetBSD: ixv.h,v 1.6 2015/08/05 04:08:44 msaitoh Exp $*/
+/*$NetBSD: ixv.h,v 1.7 2015/08/17 06:16:03 knakahara Exp $*/
 
 
 #ifndef _IXV_H_
@@ -75,6 +75,7 @@
 #include <sys/proc.h>
 #include <sys/sysctl.h>
 #include <sys/endian.h>
+#include <sys/interrupt.h>
 
 #include "ixgbe_netbsd.h"
 #include "ixgbe_api.h"

Index: src/sys/kern/files.kern
diff -u src/sys/kern/files.kern:1.6 src/sys/kern/files.kern:1.7
--- src/sys/kern/files.kern:1.6	Sun May 10 07:41:15 2015
+++ src/sys/kern/files.kern	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: files.kern,v 1.6 2015/05/10 07:41:15 pgoyette Exp $
+#	$NetBSD: files.kern,v 1.7 2015/08/17 06:16:03 knakahara Exp $
 
 #
 # kernel sources
@@ -131,6 +131,7 @@ file	kern/subr_exec_fd.c		kern
 file	kern/subr_extent.c		kern
 file	kern/subr_hash.c		kern
 file	kern/subr_humanize.c		kern
+file	kern/subr_interrupt.c		kern
 file	kern/subr_iostat.c		kern
 file	kern/subr_ipi.c			kern
 file	kern/subr_kcpuset.c		kern

Index: src/sys/kern/kern_stub.c
diff -u src/sys/kern/kern_stub.c:1.39 src/sys/kern/kern_stub.c:1.40
--- src/sys/kern/kern_stub.c:1.39	Mon Apr 27 06:42:53 2015
+++ src/sys/kern/kern_stub.c	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: kern_stub.c,v 1.39 2015/04/27 06:42:53 knakahara Exp $	*/
+/*	$NetBSD: kern_stub.c,v 1.40 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 2007, 2008 The NetBSD Foundation, Inc.
@@ -62,7 +62,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: kern_stub.c,v 1.39 2015/04/27 06:42:53 knakahara Exp $");
+__KERNEL_RCSID(0, "$NetBSD: kern_stub.c,v 1.40 2015/08/17 06:16:03 knakahara Exp $");
 
 #include "opt_ptrace.h"
 #include "opt_ktrace.h"
@@ -147,7 +147,14 @@ __weak_alias(userconf_prompt, voidop);
 
 __weak_alias(kobj_renamespace, nullop);
 
-__weak_alias(pci_intr_distribute, eopnotsupp);
+__weak_alias(interrupt_get_count, eopnotsupp);
+__weak_alias(interrupt_get_assigned, eopnotsupp);
+__weak_alias(interrupt_get_available, eopnotsupp);
+__weak_alias(interrupt_get_devname, eopnotsupp);
+__weak_alias(interrupt_construct_intrids, eopnotsupp);
+__weak_alias(interrupt_destruct_intrids, eopnotsupp);
+__weak_alias(interrupt_distribute, eopnotsupp);
+__weak_alias(interrupt_distribute_handler, eopnotsupp);
 
 /*
  * Scheduler activations system calls.  These need to remain until libc's

Index: src/sys/secmodel/suser/secmodel_suser.c
diff -u src/sys/secmodel/suser/secmodel_suser.c:1.41 src/sys/secmodel/suser/secmodel_suser.c:1.42
--- src/sys/secmodel/suser/secmodel_suser.c:1.41	Tue Feb 25 18:30:13 2014
+++ src/sys/secmodel/suser/secmodel_suser.c	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: secmodel_suser.c,v 1.41 2014/02/25 18:30:13 pooka Exp $ */
+/* $NetBSD: secmodel_suser.c,v 1.42 2015/08/17 06:16:03 knakahara Exp $ */
 /*-
  * Copyright (c) 2006 Elad Efrat <e...@netbsd.org>
  * All rights reserved.
@@ -38,7 +38,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.41 2014/02/25 18:30:13 pooka Exp $");
+__KERNEL_RCSID(0, "$NetBSD: secmodel_suser.c,v 1.42 2015/08/17 06:16:03 knakahara Exp $");
 
 #include <sys/types.h>
 #include <sys/param.h>
@@ -443,6 +443,20 @@ secmodel_suser_system_cb(kauth_cred_t cr
 
 		break;
 
+	case KAUTH_SYSTEM_INTR:
+		switch (req) {
+		case KAUTH_REQ_SYSTEM_INTR_AFFINITY:
+			if (isroot)
+				result = KAUTH_RESULT_ALLOW;
+
+			break;
+
+		default:
+			break;
+		}
+
+		break;
+
 	default:
 		break;
 	}

Index: src/sys/sys/Makefile
diff -u src/sys/sys/Makefile:1.156 src/sys/sys/Makefile:1.157
--- src/sys/sys/Makefile:1.156	Fri Jul 31 12:51:32 2015
+++ src/sys/sys/Makefile	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-#	$NetBSD: Makefile,v 1.156 2015/07/31 12:51:32 kamil Exp $
+#	$NetBSD: Makefile,v 1.157 2015/08/17 06:16:03 knakahara Exp $
 
 .include <bsd.own.mk>
 
@@ -21,7 +21,7 @@ INCS=	acct.h agpio.h aio.h ansi.h aout_m
 	exec_coff.h exec_ecoff.h exec_elf.h exec_script.h extattr.h extent.h \
 	fcntl.h fd_set.h fdio.h featuretest.h file.h filedesc.h filio.h \
 	flashio.h float_ieee754.h fstypes.h gcq.h gmon.h gpio.h hash.h \
-	ieee754.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
+	ieee754.h intr.h intrio.h inttypes.h ioccom.h ioctl.h ioctl_compat.h iostat.h ipc.h \
 	joystick.h \
 	kcore.h kcpuset.h kgdb.h kmem.h ksem.h ksyms.h ktrace.h \
 	localedef.h lock.h lockf.h lua.h lwp.h lwpctl.h \

Index: src/sys/sys/intr.h
diff -u src/sys/sys/intr.h:1.18 src/sys/sys/intr.h:1.19
--- src/sys/sys/intr.h:1.18	Mon Apr 27 06:42:53 2015
+++ src/sys/sys/intr.h	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: intr.h,v 1.18 2015/04/27 06:42:53 knakahara Exp $	*/
+/*	$NetBSD: intr.h,v 1.19 2015/08/17 06:16:03 knakahara Exp $	*/
 
 /*-
  * Copyright (c) 2007 The NetBSD Foundation, Inc.
@@ -33,6 +33,7 @@
 #define	_SYS_INTR_H_
 
 #define INTRIDBUF 64
+#define INTRDEVNAMEBUF 256
 
 #ifdef _KERNEL
 

Index: src/sys/sys/kauth.h
diff -u src/sys/sys/kauth.h:1.71 src/sys/sys/kauth.h:1.72
--- src/sys/sys/kauth.h:1.71	Mon Mar 18 19:35:46 2013
+++ src/sys/sys/kauth.h	Mon Aug 17 06:16:03 2015
@@ -1,4 +1,4 @@
-/* $NetBSD: kauth.h,v 1.71 2013/03/18 19:35:46 plunky Exp $ */
+/* $NetBSD: kauth.h,v 1.72 2015/08/17 06:16:03 knakahara Exp $ */
 
 /*-
  * Copyright (c) 2005, 2006 Elad Efrat <e...@netbsd.org>  
@@ -111,6 +111,7 @@ enum {
 	KAUTH_SYSTEM_LFS,
 	KAUTH_SYSTEM_FS_EXTATTR,
 	KAUTH_SYSTEM_FS_SNAPSHOT,
+	KAUTH_SYSTEM_INTR,
 };
 
 /*
@@ -156,6 +157,7 @@ enum kauth_system_req {
 	KAUTH_REQ_SYSTEM_LFS_FCNTL,
 	KAUTH_REQ_SYSTEM_MOUNT_UMAP,
 	KAUTH_REQ_SYSTEM_MOUNT_DEVICE,
+	KAUTH_REQ_SYSTEM_INTR_AFFINITY,
 };
 
 /*

Added files:

Index: src/sys/kern/subr_interrupt.c
diff -u /dev/null src/sys/kern/subr_interrupt.c:1.1
--- /dev/null	Mon Aug 17 06:16:03 2015
+++ src/sys/kern/subr_interrupt.c	Mon Aug 17 06:16:03 2015
@@ -0,0 +1,513 @@
+/*	$NetBSD: subr_interrupt.c,v 1.1 2015/08/17 06:16:03 knakahara Exp $	*/
+
+/*
+ * Copyright (c) 2015 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__KERNEL_RCSID(0, "$NetBSD: subr_interrupt.c,v 1.1 2015/08/17 06:16:03 knakahara Exp $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/errno.h>
+#include <sys/cpu.h>
+#include <sys/interrupt.h>
+#include <sys/intr.h>
+#include <sys/kcpuset.h>
+#include <sys/kmem.h>
+#include <sys/proc.h>
+#include <sys/xcall.h>
+#include <sys/sysctl.h>
+
+#include <sys/conf.h>
+#include <sys/intrio.h>
+#include <sys/kauth.h>
+
+#include <machine/limits.h>
+
+#ifdef INTR_DEBUG
+#define DPRINTF(msg) printf msg
+#else
+#define DPRINTF(msg)
+#endif
+
+static struct intrio_set kintrio_set = { "\0", NULL, 0 };
+
+#define UNSET_NOINTR_SHIELD	0
+#define SET_NOINTR_SHIELD	1
+
+static void
+interrupt_shield_xcall(void *arg1, void *arg2)
+{
+	struct cpu_info *ci;
+	struct schedstate_percpu *spc;
+	int s, shield;
+
+	ci = arg1;
+	shield = (int)(intptr_t)arg2;
+	spc = &ci->ci_schedstate;
+
+	s = splsched();
+	if (shield == UNSET_NOINTR_SHIELD)
+		spc->spc_flags &= ~SPCF_NOINTR;
+	else if (shield == SET_NOINTR_SHIELD)
+		spc->spc_flags |= SPCF_NOINTR;
+	splx(s);
+}
+
+/*
+ * Change SPCF_NOINTR flag of schedstate_percpu->spc_flags.
+ */
+static int
+interrupt_shield(u_int cpu_idx, int shield)
+{
+	struct cpu_info *ci;
+	struct schedstate_percpu *spc;
+
+	KASSERT(mutex_owned(&cpu_lock));
+
+	ci = cpu_lookup(cpu_idx);
+	if (ci == NULL)
+		return EINVAL;
+
+	spc = &ci->ci_schedstate;
+	if (shield == UNSET_NOINTR_SHIELD) {
+		if ((spc->spc_flags & SPCF_NOINTR) == 0)
+			return 0;
+	} else if (shield == SET_NOINTR_SHIELD) {
+		if ((spc->spc_flags & SPCF_NOINTR) != 0)
+			return 0;
+	}
+
+	if (ci == curcpu() || !mp_online) {
+		interrupt_shield_xcall(ci, (void *)(intptr_t)shield);
+	} else {
+		uint64_t where;
+		where = xc_unicast(0, interrupt_shield_xcall, ci,
+			(void *)(intptr_t)shield, ci);
+		xc_wait(where);
+	}
+
+	spc->spc_lastmod = time_second;
+	return 0;
+}
+
+/*
+ * Move all assigned interrupts from "cpu_idx" to the other cpu as possible.
+ * The destination cpu is the lowest cpuid of available cpus.
+ * If there are no available cpus, give up to move interrupts.
+ */
+static int
+interrupt_avert_intr(u_int cpu_idx)
+{
+	kcpuset_t *cpuset;
+	struct intrids_handler *ii_handler;
+	intrid_t *ids;
+	int error, i, nids;
+
+	kcpuset_create(&cpuset, true);
+	kcpuset_set(cpuset, cpu_idx);
+
+	ii_handler = interrupt_construct_intrids(cpuset);
+	if (ii_handler == NULL) {
+		error = ENOMEM;
+		goto out;
+	}
+	nids = ii_handler->iih_nids;
+	if (nids == 0) {
+		error = 0;
+		goto destruct_out;
+	}
+
+	interrupt_get_available(cpuset);
+	kcpuset_clear(cpuset, cpu_idx);
+	if (kcpuset_iszero(cpuset)) {
+		DPRINTF(("%s: no available cpu\n", __func__));
+		error = ENOENT;
+		goto destruct_out;
+	}
+
+	ids = ii_handler->iih_intrids;
+	for (i = 0; i < nids; i++) {
+		error = interrupt_distribute_handler(ids[i], cpuset, NULL);
+		if (error)
+			break;
+	}
+
+ destruct_out:
+	interrupt_destruct_intrids(ii_handler);
+ out:
+	kcpuset_destroy(cpuset);
+	return error;
+}
+
+/*
+ * Return actual intrio_list_line size.
+ * intrio_list_line size is variable by ncpu.
+ */
+static size_t
+interrupt_intrio_list_line_size(void)
+{
+
+	return sizeof(struct intrio_list_line) +
+		sizeof(struct intrio_list_line_cpu) * (ncpu - 1);
+}
+
+/*
+ * Return the size of interrupts list data on success.
+ * Reterun 0 on failed.
+ */
+static size_t
+interrupt_intrio_list_size(void)
+{
+	struct intrids_handler *ii_handler;
+	size_t ilsize;
+
+	ilsize = 0;
+
+	/* buffer header */
+	ilsize += sizeof(struct intrio_list);
+
+	/* il_line body */
+	ii_handler = interrupt_construct_intrids(kcpuset_running);
+	if (ii_handler == NULL)
+		return 0;
+	ilsize += interrupt_intrio_list_line_size() * (ii_handler->iih_nids);
+
+	interrupt_destruct_intrids(ii_handler);
+	return ilsize;
+}
+
+/*
+ * Set intrctl list data to "il", and return list structure bytes.
+ * If error occured, return <0.
+ * If "data" == NULL, simply return list structure bytes.
+ */
+static int
+interrupt_intrio_list(struct intrio_list *il, int length)
+{
+	struct intrio_list_line *illine;
+	kcpuset_t *assigned, *avail;
+	struct intrids_handler *ii_handler;
+	intrid_t *ids;
+	size_t ilsize;
+	u_int cpu_idx;
+	int nids, intr_idx, ret, line_size;
+
+	ilsize = interrupt_intrio_list_size();
+	if (ilsize == 0)
+		return -ENOMEM;
+
+	if (il == NULL)
+		return ilsize;
+
+	if (length < ilsize)
+		return -ENOMEM;
+
+	illine = (struct intrio_list_line *)
+		((char *)il + sizeof(struct intrio_list));
+	il->il_lineoffset = (off_t)((uintptr_t)illine - (uintptr_t)il);
+
+	kcpuset_create(&avail, true);
+	interrupt_get_available(avail);
+	kcpuset_create(&assigned, true);
+
+	ii_handler = interrupt_construct_intrids(kcpuset_running);
+	if (ii_handler == NULL) {
+		DPRINTF(("%s: interrupt_construct_intrids() failed\n",
+			__func__));
+		ret = -ENOMEM;
+		goto out;
+	}
+
+	line_size = interrupt_intrio_list_line_size();
+	/* ensure interrupts are not added after interrupt_intrio_list_size(). */
+	nids = ii_handler->iih_nids;
+	ids = ii_handler->iih_intrids;
+	if (ilsize < sizeof(struct intrio_list) + line_size * nids) {
+		DPRINTF(("%s: interrupts are added during execution.\n",
+			__func__));
+		ret = -ENOMEM;
+		goto destruct_out;
+	}
+
+	for (intr_idx = 0; intr_idx < nids; intr_idx++) {
+		char devname[INTRDEVNAMEBUF];
+
+		strncpy(illine->ill_intrid, ids[intr_idx], INTRIDBUF);
+		interrupt_get_devname(ids[intr_idx], devname, sizeof(devname));
+		strncpy(illine->ill_xname, devname, INTRDEVNAMEBUF);
+
+		interrupt_get_assigned(ids[intr_idx], assigned);
+		for (cpu_idx = 0; cpu_idx < ncpu; cpu_idx++) {
+			struct intrio_list_line_cpu *illcpu =
+				&illine->ill_cpu[cpu_idx];
+
+			illcpu->illc_assigned =
+				kcpuset_isset(assigned, cpu_idx) ? true : false;
+			illcpu->illc_count =
+				interrupt_get_count(ids[intr_idx], cpu_idx);
+		}
+
+		illine = (struct intrio_list_line *)
+			((char *)illine + line_size);
+	}
+
+	ret = ilsize;
+	il->il_version = INTRIO_LIST_VERSION;
+	il->il_ncpus = ncpu;
+	il->il_nintrs = nids;
+	il->il_linesize = line_size;
+	il->il_bufsize = ilsize;
+
+ destruct_out:
+	interrupt_destruct_intrids(ii_handler);
+ out:
+	kcpuset_destroy(assigned);
+	kcpuset_destroy(avail);
+
+	return ret;
+}
+
+/*
+ * "intrctl list" entry
+ */
+static int
+interrupt_intrio_list_sysctl(SYSCTLFN_ARGS)
+{
+	int ret, error;
+	void *buf;
+
+	if (oldlenp == NULL)
+		return EINVAL;
+
+	/*
+	 * If oldp == NULL, the sysctl(8) caller process want to get the size of
+	 * intrctl list data only.
+	 */
+	if (oldp == NULL) {
+		ret = interrupt_intrio_list(NULL, 0);
+		if (ret < 0)
+			return -ret;
+
+		*oldlenp = ret;
+		return 0;
+	}
+
+	/*
+	 * If oldp != NULL, the sysctl(8) caller process want to get both the size
+	 * and the contents of intrctl list data.
+	 */
+	if (*oldlenp == 0)
+		return ENOMEM;
+
+	buf = kmem_zalloc(*oldlenp, KM_SLEEP);
+	if (buf == NULL)
+		return ENOMEM;
+
+	ret = interrupt_intrio_list(buf, *oldlenp);
+	if (ret < 0) {
+		error = -ret;
+		goto out;
+	}
+	error = copyout(buf, oldp, *oldlenp);
+
+ out:
+	kmem_free(buf, *oldlenp);
+	return error;
+}
+
+/*
+ * "intrctl affinity" entry
+ */
+static int
+interrupt_set_affinity_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	struct intrio_set *iset;
+	cpuset_t *ucpuset;
+	kcpuset_t *kcpuset;
+	int error;
+
+	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_INTR,
+	    KAUTH_REQ_SYSTEM_INTR_AFFINITY, NULL, NULL, NULL);
+	if (error)
+		return EPERM;
+
+	node = *rnode;
+	iset = (struct intrio_set *)node.sysctl_data;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error != 0 || newp == NULL)
+		return error;
+
+	ucpuset = iset->cpuset;
+	kcpuset_create(&kcpuset, true);
+	error = kcpuset_copyin(ucpuset, kcpuset, iset->cpuset_size);
+	if (error)
+		goto out;
+	if (kcpuset_iszero(kcpuset)) {
+		error = EINVAL;
+		goto out;
+	}
+
+	error = interrupt_distribute_handler(iset->intrid, kcpuset, NULL);
+
+ out:
+	kcpuset_destroy(kcpuset);
+	return error;
+}
+
+/*
+ * "intrctl intr" entry
+ */
+static int
+interrupt_intr_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	struct intrio_set *iset;
+	cpuset_t *ucpuset;
+	kcpuset_t *kcpuset;
+	int error;
+	u_int cpu_idx;
+
+	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CPU,
+	    KAUTH_REQ_SYSTEM_CPU_SETSTATE, NULL, NULL, NULL);
+	if (error)
+		return EPERM;
+
+	node = *rnode;
+	iset = (struct intrio_set *)node.sysctl_data;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error != 0 || newp == NULL)
+		return error;
+
+	ucpuset = iset->cpuset;
+	kcpuset_create(&kcpuset, true);
+	error = kcpuset_copyin(ucpuset, kcpuset, iset->cpuset_size);
+	if (error)
+		goto out;
+	if (kcpuset_iszero(kcpuset)) {
+		error = EINVAL;
+		goto out;
+	}
+
+	cpu_idx = kcpuset_ffs(kcpuset) - 1; /* support one CPU only */
+
+	mutex_enter(&cpu_lock);
+	error = interrupt_shield(cpu_idx, UNSET_NOINTR_SHIELD);
+	mutex_exit(&cpu_lock);
+
+ out:
+	kcpuset_destroy(kcpuset);
+	return error;
+}
+
+/*
+ * "intrctl nointr" entry
+ */
+static int
+interrupt_nointr_sysctl(SYSCTLFN_ARGS)
+{
+	struct sysctlnode node;
+	struct intrio_set *iset;
+	cpuset_t *ucpuset;
+	kcpuset_t *kcpuset;
+	int error;
+	u_int cpu_idx;
+
+	error = kauth_authorize_system(l->l_cred, KAUTH_SYSTEM_CPU,
+	    KAUTH_REQ_SYSTEM_CPU_SETSTATE, NULL, NULL, NULL);
+	if (error)
+		return EPERM;
+
+	node = *rnode;
+	iset = (struct intrio_set *)node.sysctl_data;
+
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error != 0 || newp == NULL)
+		return error;
+
+	ucpuset = iset->cpuset;
+	kcpuset_create(&kcpuset, true);
+	error = kcpuset_copyin(ucpuset, kcpuset, iset->cpuset_size);
+	if (error)
+		goto out;
+	if (kcpuset_iszero(kcpuset)) {
+		error = EINVAL;
+		goto out;
+	}
+
+	cpu_idx = kcpuset_ffs(kcpuset) - 1; /* support one CPU only */
+
+	mutex_enter(&cpu_lock);
+	error = interrupt_shield(cpu_idx, SET_NOINTR_SHIELD);
+	mutex_exit(&cpu_lock);
+	if (error)
+		goto out;
+
+	error = interrupt_avert_intr(cpu_idx);
+
+ out:
+	kcpuset_destroy(kcpuset);
+	return error;
+}
+
+SYSCTL_SETUP(sysctl_interrupt_setup, "sysctl interrupt setup")
+{
+	const struct sysctlnode *node = NULL;
+
+	sysctl_createv(clog, 0, NULL, &node,
+		       CTLFLAG_PERMANENT, CTLTYPE_NODE,
+		       "intr", SYSCTL_DESCR("Interrupt options"),
+		       NULL, 0, NULL, 0,
+		       CTL_KERN, CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &node, NULL,
+		       CTLFLAG_PERMANENT, CTLTYPE_STRUCT,
+		       "list", SYSCTL_DESCR("intrctl list"),
+		       interrupt_intrio_list_sysctl, 0, NULL,
+		        0, CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &node, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRUCT,
+		       "affinity", SYSCTL_DESCR("set affinity"),
+		       interrupt_set_affinity_sysctl, 0, &kintrio_set,
+		       sizeof(kintrio_set), CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &node, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRUCT,
+		       "intr", SYSCTL_DESCR("set intr"),
+		       interrupt_intr_sysctl, 0, &kintrio_set,
+		       sizeof(kintrio_set), CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &node, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE, CTLTYPE_STRUCT,
+		       "nointr", SYSCTL_DESCR("set nointr"),
+		       interrupt_nointr_sysctl, 0, &kintrio_set,
+		       sizeof(kintrio_set), CTL_CREATE, CTL_EOL);
+}

Index: src/sys/sys/interrupt.h
diff -u /dev/null src/sys/sys/interrupt.h:1.1
--- /dev/null	Mon Aug 17 06:16:03 2015
+++ src/sys/sys/interrupt.h	Mon Aug 17 06:16:03 2015
@@ -0,0 +1,56 @@
+/*	$NetBSD: interrupt.h,v 1.1 2015/08/17 06:16:03 knakahara Exp $	*/
+
+/*
+ * Copyright (c) 2015 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#ifndef _SYS_INTERRUPT_H_
+#define _SYS_INTERUPT_H_
+
+#include <sys/types.h>
+#include <sys/intr.h>
+#include <sys/kcpuset.h>
+
+typedef char intrid_t[INTRIDBUF];
+struct intrids_handler {
+	int iih_nids;
+	intrid_t iih_intrids[1];
+	/*
+	 * The number of the "iih_intrids" array will be overwritten by
+	 * "iih_nids" after intr_construct_intrids().
+	 */
+};
+
+uint64_t	interrupt_get_count(const char *, u_int);
+void		interrupt_get_assigned(const char *, kcpuset_t *);
+void		interrupt_get_available(kcpuset_t *);
+void		interrupt_get_devname(const char *, char *, size_t);
+struct intrids_handler	*interrupt_construct_intrids(const kcpuset_t *);
+void		interrupt_destruct_intrids(struct intrids_handler *);
+int		interrupt_distribute(void *, const kcpuset_t *, kcpuset_t *);
+int		interrupt_distribute_handler(const char *, const kcpuset_t *,
+		    kcpuset_t *);
+
+#endif /* !_SYS_INTERRUPT_H_ */
Index: src/sys/sys/intrio.h
diff -u /dev/null src/sys/sys/intrio.h:1.1
--- /dev/null	Mon Aug 17 06:16:03 2015
+++ src/sys/sys/intrio.h	Mon Aug 17 06:16:03 2015
@@ -0,0 +1,68 @@
+/*	$NetBSD: intrio.h,v 1.1 2015/08/17 06:16:03 knakahara Exp $	*/
+
+/*
+ * Copyright (c) 2015 Internet Initiative Japan Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
+ * ``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 FOUNDATION OR CONTRIBUTORS
+ * 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.
+ */
+
+#ifndef _SYS_INTRIO_H_
+#define _SYS_INTRIO_H_
+
+#include <sys/types.h>
+#include <sys/intr.h>
+#include <sys/sched.h>
+
+#define INTRIO_LIST_VERSION 1
+
+struct intrio_set {
+	char intrid[INTRIDBUF];
+	cpuset_t *cpuset;
+	size_t cpuset_size;
+};
+
+struct intrio_list_line_cpu {
+	bool illc_assigned;
+	uint64_t illc_count;
+};
+
+struct intrio_list_line {
+	char ill_intrid[INTRIDBUF];
+	char ill_xname[INTRDEVNAMEBUF];
+	struct intrio_list_line_cpu ill_cpu[1]; /* Array size is overwritten to ncpu. */
+};
+
+struct intrio_list {
+	int il_version; /* Version number of this struct. */
+	int il_ncpus;
+	int il_nintrs;
+	size_t il_bufsize;
+
+	size_t il_linesize;
+	off_t il_lineoffset;
+/*
+ * struct intrio_list_line il_lines[interrupt_num] must be followed here.
+ */
+};
+
+#endif /* !_SYS_INTRIO_H_ */

Reply via email to