Index: sys/kern/subr_eventhandler.c
===================================================================
--- sys/kern/subr_eventhandler.c
+++ sys/kern/subr_eventhandler.c
@@ -37,6 +37,7 @@
 #include <sys/mutex.h>
 #include <sys/proc.h>
 #include <sys/systm.h>
+#include <sys/rmlock.h>
 #include <sys/eventhandler.h>
 
 static MALLOC_DEFINE(M_EVENTHANDLER, "eventhandler", "Event handler records");
@@ -317,3 +318,226 @@
 
 	return (list);
 }
+
+/*
+ * Static event handler points.
+ */
+static void
+static_eventhandler_validate(struct static_eventhandler *seh)
+{
+	int i;
+
+	for (i = 0; i < seh->count; i++) {
+		if (seh->cb[i] != NULL) {
+			switch (seh->prio[i]) {
+			case STATIC_EVENTHANDLER_PRIO_FIRST:
+			case STATIC_EVENTHANDLER_PRIO_ANY:
+			case STATIC_EVENTHANDLER_PRIO_LAST:
+				break;
+			default:
+			case STATIC_EVENTHANDLER_PRIO_INVALID:
+				panic("seh %p bad priority %d at %d\n", seh, seh->prio[i], i);
+				break;
+			}
+		}
+	}
+
+	for (i = 1; i < seh->count; i++) {
+		if (seh->prio[i] < seh->prio[i - 1]) {
+			panic("seh %p unsorted priorities (%d < %d) at %d\n", seh,
+			    seh->prio[i], seh->prio[i - 1], i);
+		}
+	}
+
+	for (i = seh->count; i < seh->size; i++) {
+		if (seh->cb[i] != NULL) {
+			panic("seh %p callback %p found past the end\n", seh,
+			    seh->cb[i]);
+		}
+		if (seh->prio[i] != STATIC_EVENTHANDLER_PRIO_INVALID) {
+			panic("seh %p prio %d found past the end\n", seh,
+			    seh->prio[i]);
+		}
+	}
+}
+
+static void
+static_eventhandler_assert_prio(struct static_eventhandler *seh,
+    enum static_eventhandler_prio prio)
+{
+
+	switch (prio) {
+		case STATIC_EVENTHANDLER_PRIO_FIRST:
+		case STATIC_EVENTHANDLER_PRIO_ANY:
+		case STATIC_EVENTHANDLER_PRIO_LAST:
+			break;
+		default:
+		case STATIC_EVENTHANDLER_PRIO_INVALID:
+			panic("invalid priority %d passed", prio);
+			break;
+	}
+}
+
+void
+static_eventhandler_init(struct static_eventhandler *seh)
+{
+
+	rms_init(&seh->lock, seh->ident);
+}
+
+void
+static_eventhandler_register(struct static_eventhandler *seh, void *pcb,
+    enum static_eventhandler_prio prio)
+{
+	static_eventhandler_cb **newcb, **tofree_cb, *cb;
+	size_t newsize;
+	enum static_eventhandler_prio *newprio, *tofree_prio;
+	int i;
+
+	static_eventhandler_assert_prio(seh, prio);
+
+	cb = (void *)pcb;
+	tofree_cb = NULL;
+	tofree_prio = NULL;
+	rms_wlock(&seh->lock);
+	MPASS(seh->count <= seh->size);
+	if (seh->cb == NULL) {
+		seh->size = 8;
+		seh->cb = malloc(sizeof(seh->cb[0]) * seh->size, M_EVENTHANDLER,
+		    M_WAITOK | M_ZERO);
+		seh->prio = malloc(sizeof(seh->prio[0]) * seh->size, M_EVENTHANDLER,
+		    M_WAITOK | M_ZERO);
+	} else if (seh->count == seh->size) {
+		newsize = seh->size * 2;
+		newcb = malloc(sizeof(seh->cb[0]) * newsize,
+		    M_EVENTHANDLER, M_WAITOK | M_ZERO);
+		newprio = malloc(sizeof(seh->prio[0]) * newsize,
+		    M_EVENTHANDLER, M_WAITOK | M_ZERO);
+		memcpy(newcb, seh->cb, sizeof(seh->cb[0]) * seh->size);
+		memcpy(newprio, seh->prio, sizeof(seh->prio[0]) * seh->size);
+
+		tofree_cb = seh->cb;
+		tofree_prio = seh->prio;
+		seh->cb = newcb;
+		seh->prio = newprio;
+		seh->size = newsize;
+	}
+
+	static_eventhandler_validate(seh);
+
+	for (i = 0; i < seh->size; i++) {
+		if (seh->cb[i] == cb)
+			panic("callback %p already registered", cb);
+	}
+
+	switch (prio) {
+	case STATIC_EVENTHANDLER_PRIO_INVALID:
+		/* appease clang */
+		panic("should not be here");
+		break;
+	case STATIC_EVENTHANDLER_PRIO_FIRST:
+		memmove(&seh->cb[1], seh->cb,
+		    sizeof(seh->cb[0]) * seh->count);
+		memmove(&seh->prio[1], seh->prio,
+		    sizeof(seh->prio[0]) * seh->count);
+		seh->cb[0] = cb;
+		seh->prio[0] = prio;
+		seh->count++;
+		break;
+	case STATIC_EVENTHANDLER_PRIO_ANY:
+		for (i = 0; i < seh->count; i++) {
+			if (seh->prio[i] != STATIC_EVENTHANDLER_PRIO_FIRST)
+				break;
+		}
+		if (i == seh->count) {
+			/*
+			 * Insert at the end.
+			 */
+			seh->cb[seh->count] = cb;
+			seh->prio[seh->count] = prio;
+			seh->count++;
+		} else {
+			/*
+			 * Move all entries to handle STATIC_EVENTHANDLER_PRIO_LAST.
+			 */
+			memmove(&seh->cb[i + 1], seh->cb,
+			    sizeof(seh->cb[0]) * (seh->count - i));
+			memmove(&seh->prio[i + 1], seh->prio,
+			    sizeof(seh->prio[0]) * (seh->count - i));
+			seh->cb[i] = cb;
+			seh->prio[i] = prio;
+			seh->count++;
+		}
+		break;
+	case STATIC_EVENTHANDLER_PRIO_LAST:
+		seh->cb[seh->count] = cb;
+		seh->prio[seh->count] = prio;
+		seh->count++;
+		break;
+	}
+	rms_wunlock(&seh->lock);
+	free(tofree_cb, M_EVENTHANDLER);
+	free(tofree_prio, M_EVENTHANDLER);
+}
+
+void
+static_eventhandler_deregister(struct static_eventhandler *seh, void *pcb)
+{
+	static_eventhandler_cb *cb;
+	int i;
+
+	cb = pcb;
+	rms_wlock(&seh->lock);
+	MPASS(seh->count <= seh->size);
+	static_eventhandler_validate(seh);
+
+	for (i = 0; i < seh->count; i++) {
+		if (seh->cb[i] == cb)
+			break;
+	}
+
+	if (i == seh->count)
+		panic("callback %p not found", cb);
+
+	switch (seh->prio[i]) {
+	case STATIC_EVENTHANDLER_PRIO_INVALID:
+		/* appease clang */
+		panic("should not be here");
+		break;
+	case STATIC_EVENTHANDLER_PRIO_FIRST:
+		memmove(seh->cb, &seh->cb[1],
+		    sizeof(seh->cb[0]) * (seh->count - 1));
+		memmove(seh->prio, &seh->prio[1],
+		    sizeof(seh->prio[0]) * (seh->count - 1));
+		break;
+	case STATIC_EVENTHANDLER_PRIO_ANY:
+		memmove(&seh->cb[i], &seh->cb[i + 1],
+		    sizeof(seh->cb[0]) * (seh->count - i));
+		memmove(&seh->prio[i], &seh->cb[i + 1],
+		    sizeof(seh->cb[0]) * (seh->count - i));
+		break;
+	case STATIC_EVENTHANDLER_PRIO_LAST:
+		seh->cb[i] = seh->cb[seh->count - 1];
+		seh->prio[i] = seh->prio[seh->count - 1];
+		break;
+	}
+	seh->cb[seh->count] = NULL;
+	seh->prio[seh->count] = STATIC_EVENTHANDLER_PRIO_INVALID;
+	seh->count--;
+	rms_wunlock(&seh->lock);
+}
+
+void
+static_eventhandler_invoke(struct static_eventhandler *seh, void *arg)
+{
+	int i;
+
+	if (seh->count == 0)
+		return;
+
+	rms_rlock(&seh->lock);
+	for (i = 0; i < seh->count; i++) {
+		(seh->cb[i])(arg);
+	}
+	rms_runlock(&seh->lock);
+}
Index: sys/sys/_eventhandler.h
===================================================================
--- sys/sys/_eventhandler.h
+++ sys/sys/_eventhandler.h
@@ -69,4 +69,52 @@
 };									\
 struct __hack
 
+/*
+ * Headers to accomodate _rmlock.h
+ */
+#include <sys/param.h>
+#include <sys/_cpuset.h>
+#include <sys/_lock.h>
+#include <sys/_mutex.h>
+#include <sys/_sx.h>
+#include <sys/_rmlock.h>
+
+typedef void static_eventhandler_cb(void *);
+
+enum static_eventhandler_prio {
+	STATIC_EVENTHANDLER_PRIO_INVALID,
+	STATIC_EVENTHANDLER_PRIO_FIRST,
+	STATIC_EVENTHANDLER_PRIO_ANY,
+	STATIC_EVENTHANDLER_PRIO_LAST
+};
+
+struct static_eventhandler {
+	const char *ident;
+	enum static_eventhandler_prio *prio;
+	struct rmslock lock;
+	u_int	count;
+	u_int	size;
+	static_eventhandler_cb **cb;
+};
+
+#define	STATIC_EVENTHANDLER_DECLARE(name)				\
+extern struct static_eventhandler static_eventhandler_ ## name
+
+#define	STATIC_EVENTHANDLER_REGISTER(name, func, prio)			\
+	static_eventhandler_register(&static_eventhandler_ ## name, func, \
+	    STATIC_EVENTHANDLER_PRIO_ ## prio)
+
+#define	STATIC_EVENTHANDLER_DEREGISTER(name, func)			\
+	static_eventhandler_deregister(&static_eventhandler_ ## name, func)
+
+#define	STATIC_EVENTHANDLER_INVOKE(name, arg)				\
+	static_eventhandler_invoke(&static_eventhandler_ ## name, arg)
+
+#define	STATIC_EVENTHANDLER_DEFINE(name)				\
+struct static_eventhandler static_eventhandler_ ## name = {		\
+	.ident = __STRING(name),					\
+};									\
+SYSINIT(_seh_init_ ## name, SI_SUB_EVENTHANDLER, SI_ORDER_ANY,		\
+    static_eventhandler_init, &static_eventhandler_ ## name);
+
 #endif
Index: sys/sys/eventhandler.h
===================================================================
--- sys/sys/eventhandler.h
+++ sys/sys/eventhandler.h
@@ -317,4 +317,13 @@
 typedef void (*rt_addrmsg_fn)(void *, struct ifaddr *, int);
 EVENTHANDLER_DECLARE(rt_addrmsg, rt_addrmsg_fn);
 
+/*
+ * Static eventhandler support.
+ */
+void static_eventhandler_init(struct static_eventhandler *seh);
+void static_eventhandler_register(struct static_eventhandler *seh, void *func,
+    enum static_eventhandler_prio prio);
+void static_eventhandler_deregister(struct static_eventhandler *seh, void *func);
+void static_eventhandler_invoke(struct static_eventhandler *seh, void *arg);
+
 #endif /* _SYS_EVENTHANDLER_H_ */