Module Name:    src
Committed By:   martin
Date:           Thu Jul 30 09:37:37 UTC 2015

Modified Files:
        src/sys/arch/arm/broadcom [netbsd-7]: bcm2835_intr.c bcm2835_intr.h
            bcm2835_obio.c bcm2835reg.h
        src/sys/arch/arm/cortex [netbsd-7]: gic.c
        src/sys/arch/arm/marvell [netbsd-7]: mvsoc_intr.h
        src/sys/arch/arm/omap [netbsd-7]: omap4430_intr.h omap5430_intr.h
        src/sys/arch/arm/pic [netbsd-7]: pic.c picvar.h
        src/sys/arch/evbarm/rpi [netbsd-7]: rpi_machdep.c

Log Message:
Pull up following revision(s) (requested by skrll in ticket #890):
        sys/arch/arm/pic/pic.c: revision 1.27-1.32
        sys/arch/arm/omap/omap5430_intr.h: revision 1.3
        sys/arch/arm/broadcom/bcm2835_obio.c: revision 1.25
        sys/arch/arm/cortex/gic.c: revision 1.18
        sys/arch/arm/broadcom/bcm2835reg.h: revision 1.15
        sys/arch/evbarm/rpi/rpi_machdep.c: revision 1.61
        sys/arch/arm/broadcom/bcm2835_intr.h: revision 1.2
        sys/arch/arm/marvell/mvsoc_intr.h: revision 1.5
        sys/arch/arm/broadcom/bcm2835_intr.c: revision 1.8-1.10
        sys/arch/arm/pic/picvar.h: revision 1.12-1.14
        sys/arch/arm/omap/omap4430_intr.h: revision 1.3

Don't clear CI_ASTPENDING in exception return, do it in ast() instead.
Add basic support for __HAVE_PREEMPTION.
Use atomic ops for ci_astpending if __HAVE_PREEMPTION is defined.
Use kpreempt_disable/kpreempt_enable
Add __HAVE_PIC_HAVE_PENDING_INTRS and define it if __HAVE_PIC_SET_PRIORITY
is undefined (also define in mvsoc_intr.h since their use of the latter is
peculiar).  This new define controls whether the pending interrupt logic is
compiled.  The GIC doesn't use pending interrupts since it uses the priority
level on the GIC to control delivery of interrupts, thus there can never
be a pending interrupt.  The kernel shrinks about 4KB with the removal of
the pending interupt support,
Only if we __HAVE_PIC_PENDING_INTRS do we need the variables to track them.
Add #define __HAVE_PIC_PENDING_INTRS for the non-GIC PICs.
Add a pic_cpus to the softc which specifies which cpus the pic can send
IPIs to.  For GIC, initialize pic_cpus to kcpuset_running since it can handle
all the cpus.
Adapt pic to deal with the BCM2836 interrupts.
Move pic_pending_pics, pic_pending_ipls, and pic_blocked_irqs into a
structure and make then per-cpu.  There is no global interrupt state anymore.
Use right kcpuset call.
Don't need pic_ipi_sender anymore.
Don't send IPIs to ourselves if sending to everyone.
RPI2 MP support.
Thanks to Matt Thomas for making this possible with his changes to pic.c
Use a bit per IPI type in local mailbox 0 registers. Ok matt@
IPIs should be IPL_HIGH according to rmind@
Fix bcm2836mp_pic_{un,}block_irqs to handle timer AND mailbox interrupts
if they're both passed.  Thanks to nat@ for finding this.
Sprinkle some KASSERTs


To generate a diff of this commit:
cvs rdiff -u -r1.3.12.2 -r1.3.12.3 src/sys/arch/arm/broadcom/bcm2835_intr.c
cvs rdiff -u -r1.1 -r1.1.18.1 src/sys/arch/arm/broadcom/bcm2835_intr.h
cvs rdiff -u -r1.20.2.2 -r1.20.2.3 src/sys/arch/arm/broadcom/bcm2835_obio.c
cvs rdiff -u -r1.10.12.3 -r1.10.12.4 src/sys/arch/arm/broadcom/bcm2835reg.h
cvs rdiff -u -r1.10.2.4 -r1.10.2.5 src/sys/arch/arm/cortex/gic.c
cvs rdiff -u -r1.4 -r1.4.4.1 src/sys/arch/arm/marvell/mvsoc_intr.h
cvs rdiff -u -r1.2 -r1.2.18.1 src/sys/arch/arm/omap/omap4430_intr.h
cvs rdiff -u -r1.2 -r1.2.4.1 src/sys/arch/arm/omap/omap5430_intr.h
cvs rdiff -u -r1.22.2.2 -r1.22.2.3 src/sys/arch/arm/pic/pic.c
cvs rdiff -u -r1.10.2.1 -r1.10.2.2 src/sys/arch/arm/pic/picvar.h
cvs rdiff -u -r1.43.2.4 -r1.43.2.5 src/sys/arch/evbarm/rpi/rpi_machdep.c

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/arm/broadcom/bcm2835_intr.c
diff -u src/sys/arch/arm/broadcom/bcm2835_intr.c:1.3.12.2 src/sys/arch/arm/broadcom/bcm2835_intr.c:1.3.12.3
--- src/sys/arch/arm/broadcom/bcm2835_intr.c:1.3.12.2	Wed Mar 11 20:22:55 2015
+++ src/sys/arch/arm/broadcom/bcm2835_intr.c	Thu Jul 30 09:37:37 2015
@@ -1,7 +1,7 @@
-/*	$NetBSD: bcm2835_intr.c,v 1.3.12.2 2015/03/11 20:22:55 snj Exp $	*/
+/*	$NetBSD: bcm2835_intr.c,v 1.3.12.3 2015/07/30 09:37:37 martin Exp $	*/
 
 /*-
- * Copyright (c) 2012 The NetBSD Foundation, Inc.
+ * Copyright (c) 2012, 2015 The NetBSD Foundation, Inc.
  * All rights reserved.
  *
  * This code is derived from software contributed to The NetBSD Foundation
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.3.12.2 2015/03/11 20:22:55 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_intr.c,v 1.3.12.3 2015/07/30 09:37:37 martin Exp $");
 
 #define _INTR_PRIVATE
 
@@ -67,21 +67,12 @@ static int bcm2836mp_pic_find_pending_ir
 static void bcm2836mp_pic_establish_irq(struct pic_softc *, struct intrsource *);
 static void bcm2836mp_pic_source_name(struct pic_softc *, int, char *,
     size_t);
-#if 0
 #ifdef MULTIPROCESSOR
 int bcm2836mp_ipi_handler(void *);
 static void bcm2836mp_cpu_init(struct pic_softc *, struct cpu_info *);
 static void bcm2836mp_send_ipi(struct pic_softc *, const kcpuset_t *, u_long);
 #endif
 #endif
-#endif
-
-#ifdef MULTIPROCESSOR
-static void
-bcm2835_dummy(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi)
-{
-}
-#endif
 
 static int  bcm2835_icu_match(device_t, cfdata_t, void *);
 static void bcm2835_icu_attach(device_t, device_t, void *);
@@ -92,9 +83,6 @@ static struct pic_ops bcm2835_picops = {
 	.pic_find_pending_irqs = bcm2835_pic_find_pending_irqs,
 	.pic_establish_irq = bcm2835_pic_establish_irq,
 	.pic_source_name = bcm2835_pic_source_name,
-#if defined(MULTIPROCESSOR)
-	.pic_ipi_send = bcm2835_dummy,
-#endif
 };
 
 struct pic_softc bcm2835_pic = {
@@ -110,16 +98,33 @@ static struct pic_ops bcm2836mp_picops =
 	.pic_find_pending_irqs = bcm2836mp_pic_find_pending_irqs,
 	.pic_establish_irq = bcm2836mp_pic_establish_irq,
 	.pic_source_name = bcm2836mp_pic_source_name,
-#if 0 && defined(MULTIPROCESSOR)
+#if defined(MULTIPROCESSOR)
 	.pic_cpu_init = bcm2836mp_cpu_init,
 	.pic_ipi_send = bcm2836mp_send_ipi,
 #endif
 };
 
-struct pic_softc bcm2836mp_pic = {
-	.pic_ops = &bcm2836mp_picops,
-	.pic_maxsources = BCM2836MP_NIRQ,
-	.pic_name = "bcm2836 mp pic",
+struct pic_softc bcm2836mp_pic[BCM2836_NCPUS] = {
+	[0] = {
+		.pic_ops = &bcm2836mp_picops,
+		.pic_maxsources = BCM2836_NIRQPERCPU,
+		.pic_name = "bcm2836 pic",
+	},
+	[1] = {
+		.pic_ops = &bcm2836mp_picops,
+		.pic_maxsources = BCM2836_NIRQPERCPU,
+		.pic_name = "bcm2836 pic",
+	},
+	[2] = {
+		.pic_ops = &bcm2836mp_picops,
+		.pic_maxsources = BCM2836_NIRQPERCPU,
+		.pic_name = "bcm2836 pic",
+	},
+	[3] = {
+		.pic_ops = &bcm2836mp_picops,
+		.pic_maxsources = BCM2836_NIRQPERCPU,
+		.pic_name = "bcm2836 pic",
+	},
 };
 #endif
 
@@ -165,7 +170,7 @@ static const char * const bcm2835_source
 };
 
 #if defined(BCM2836)
-static const char * const bcm2836mp_sources[BCM2836MP_NIRQ] = {
+static const char * const bcm2836mp_sources[BCM2836_NIRQPERCPU] = {
 	"cntpsirq",	"cntpnsirq",	"cnthpirq",	"cntvirq",
 	"mailbox0",	"mailbox1",	"mailbox2",	"mailbox3",
 };
@@ -211,14 +216,14 @@ bcm2835_icu_attach(device_t parent, devi
 
 	bcmicu_sc = sc;
 
-	pic_add(sc->sc_pic, 0);
-
 #if defined(BCM2836)
-#if 0 && defined(MULTIPROCESSOR)
+#if defined(MULTIPROCESSOR)
 	aprint_normal(": Multiprocessor");
 #endif
-	pic_add(&bcm2836mp_pic, BCM2836_INT_LOCALBASE);
+
+	bcm2836mp_intr_init(curcpu());
 #endif
+	pic_add(sc->sc_pic, BCM2835_INT_BASE);
 
 	aprint_normal("\n");
 }
@@ -228,15 +233,18 @@ bcm2835_irq_handler(void *frame)
 {
 	struct cpu_info * const ci = curcpu();
 	const int oldipl = ci->ci_cpl;
+	const cpuid_t cpuid = ci->ci_cpuid;
 	const uint32_t oldipl_mask = __BIT(oldipl);
 	int ipl_mask = 0;
 
 	ci->ci_data.cpu_nintr++;
 
 	bcm2835_barrier();
-	ipl_mask = bcm2835_pic_find_pending_irqs(&bcm2835_pic);
+	if (cpuid == 0) {
+		ipl_mask = bcm2835_pic_find_pending_irqs(&bcm2835_pic);
+	}
 #if defined(BCM2836)
-	ipl_mask |= bcm2836mp_pic_find_pending_irqs(&bcm2836mp_pic);
+	ipl_mask |= bcm2836mp_pic_find_pending_irqs(&bcm2836mp_pic[cpuid]);
 #endif
 
 	/*
@@ -283,8 +291,8 @@ bcm2835_pic_find_pending_irqs(struct pic
 	gpu1irq = bpending & BCM2835_INTBIT_GPU1;
 
 	if (armirq) {
-		ipl |= pic_mark_pending_sources(pic, BCM2835_INT_BASICBASE,
-		    armirq);
+		ipl |= pic_mark_pending_sources(pic,
+		    BCM2835_INT_BASICBASE - BCM2835_INT_BASE, armirq);
 
 	}
 
@@ -292,15 +300,15 @@ bcm2835_pic_find_pending_irqs(struct pic
 		uint32_t pending1;
 
 		pending1 = read_bcm2835reg(BCM2835_INTC_IRQ1PENDING);
-		ipl |= pic_mark_pending_sources(pic, BCM2835_INT_GPU0BASE,
-		    pending1);
+		ipl |= pic_mark_pending_sources(pic,
+		    BCM2835_INT_GPU0BASE - BCM2835_INT_BASE, pending1);
 	}
 	if (gpu1irq || (bpending & BCM2835_INTBIT_PENDING2)) {
 		uint32_t pending2;
 
 		pending2 = read_bcm2835reg(BCM2835_INTC_IRQ2PENDING);
-		ipl |= pic_mark_pending_sources(pic, BCM2835_INT_GPU1BASE,
-		    pending2);
+		ipl |= pic_mark_pending_sources(pic,
+		    BCM2835_INT_GPU1BASE - BCM2835_INT_BASE, pending2);
 	}
 
 	return ipl;
@@ -329,15 +337,17 @@ bcm2835_pic_source_name(struct pic_softc
 #define	BCM2836MP_MAILBOX_IRQS	__BITS(4,4)
 
 #define	BCM2836MP_ALL_IRQS	\
-     (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS)
+    (BCM2836MP_TIMER_IRQS | BCM2836MP_MAILBOX_IRQS)
 
 static void
 bcm2836mp_pic_unblock_irqs(struct pic_softc *pic, size_t irqbase,
     uint32_t irq_mask)
 {
-	const int cpuid = 0;
+	struct cpu_info * const ci = curcpu();
+	const cpuid_t cpuid = ci->ci_cpuid;
 
-//printf("%s: irqbase %zu irq_mask %08x\n", __func__, irqbase, irq_mask);
+	KASSERT(pic == &bcm2836mp_pic[cpuid]);
+	KASSERT(irqbase == 0);
 
 	if (irq_mask & BCM2836MP_TIMER_IRQS) {
 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_TIMER_IRQS);
@@ -351,8 +361,8 @@ bcm2836mp_pic_unblock_irqs(struct pic_so
 		    BCM2836_LOCAL_TIMER_IRQ_CONTROL_BASE,
 		    BCM2836_LOCAL_TIMER_IRQ_CONTROL_SIZE,
 		    BUS_SPACE_BARRIER_READ|BUS_SPACE_BARRIER_WRITE);
-//printf("%s: val %08x\n", __func__, val);
-	} else if (irq_mask & BCM2836MP_MAILBOX_IRQS) {
+	}
+	if (irq_mask & BCM2836MP_MAILBOX_IRQS) {
 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_MAILBOX_IRQS);
 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid));
@@ -373,9 +383,12 @@ static void
 bcm2836mp_pic_block_irqs(struct pic_softc *pic, size_t irqbase,
     uint32_t irq_mask)
 {
-	const int cpuid = 0;
+	struct cpu_info * const ci = curcpu();
+	const cpuid_t cpuid = ci->ci_cpuid;
+
+	KASSERT(pic == &bcm2836mp_pic[cpuid]);
+	KASSERT(irqbase == 0);
 
-//printf("%s: irqbase %zu irq_mask %08x\n", __func__, irqbase, irq_mask);
 	if (irq_mask & BCM2836MP_TIMER_IRQS) {
 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_TIMER_IRQS);
 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
@@ -384,8 +397,8 @@ bcm2836mp_pic_block_irqs(struct pic_soft
 		bus_space_write_4(al_iot, al_ioh,
 		    BCM2836_LOCAL_TIMER_IRQ_CONTROLN(cpuid),
 		    val);
-//printf("%s: val %08x\n", __func__, val);
-	} else if (irq_mask & BCM2836MP_MAILBOX_IRQS) {
+	}
+	if (irq_mask & BCM2836MP_MAILBOX_IRQS) {
 		uint32_t mask = __SHIFTOUT(irq_mask, BCM2836MP_MAILBOX_IRQS);
 		uint32_t val = bus_space_read_4(al_iot, al_ioh,
 		    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(cpuid));
@@ -399,14 +412,16 @@ bcm2836mp_pic_block_irqs(struct pic_soft
 	return;
 }
 
-
 static int
 bcm2836mp_pic_find_pending_irqs(struct pic_softc *pic)
 {
-	const int cpuid = 0;
+	struct cpu_info * const ci = curcpu();
+	const cpuid_t cpuid = ci->ci_cpuid;
 	uint32_t lpending;
 	int ipl = 0;
 
+	KASSERT(pic == &bcm2836mp_pic[cpuid]);
+
 	bcm2835_barrier();
 
 	lpending = bus_space_read_4(al_iot, al_ioh,
@@ -424,19 +439,106 @@ bcm2836mp_pic_find_pending_irqs(struct p
 static void
 bcm2836mp_pic_establish_irq(struct pic_softc *pic, struct intrsource *is)
 {
-
 	/* Nothing really*/
 	KASSERT(is->is_irq >= 0);
-	KASSERT(is->is_irq < BCM2836MP_NIRQ);
-//	KASSERT(is->is_type == IST_LEVEL);
-
-
+	KASSERT(is->is_irq < BCM2836_NIRQPERCPU);
 }
 
 static void
 bcm2836mp_pic_source_name(struct pic_softc *pic, int irq, char *buf, size_t len)
 {
-	irq %= 32;
+
+	irq %= BCM2836_NIRQPERCPU;
 	strlcpy(buf, bcm2836mp_sources[irq], len);
 }
+
+
+#ifdef MULTIPROCESSOR
+static void bcm2836mp_cpu_init(struct pic_softc *pic, struct cpu_info *ci)
+{
+
+	/* Enable IRQ and not FIQ */
+	bus_space_write_4(al_iot, al_ioh,
+	    BCM2836_LOCAL_MAILBOX_IRQ_CONTROLN(ci->ci_cpuid), 1);
+}
+
+
+static void
+bcm2836mp_send_ipi(struct pic_softc *pic, const kcpuset_t *kcp, u_long ipi)
+{
+	KASSERT(pic != NULL);
+	KASSERT(pic != &bcm2835_pic);
+	KASSERT(pic->pic_cpus != NULL);
+
+	const cpuid_t cpuid = pic - &bcm2836mp_pic[0];
+
+	bus_space_write_4(al_iot, al_ioh,
+	    BCM2836_LOCAL_MAILBOX0_SETN(cpuid), __BIT(ipi));
+}
+
+int
+bcm2836mp_ipi_handler(void *priv)
+{
+	const struct cpu_info *ci = curcpu();
+	const cpuid_t cpuid = ci->ci_cpuid;
+	uint32_t ipimask, bit;
+
+	ipimask = bus_space_read_4(al_iot, al_ioh,
+	    BCM2836_LOCAL_MAILBOX0_CLRN(cpuid));
+	bus_space_write_4(al_iot, al_ioh, BCM2836_LOCAL_MAILBOX0_CLRN(cpuid),
+	    ipimask);
+
+	while ((bit = ffs(ipimask)) > 0) {
+		const u_int ipi = bit - 1;
+		switch (ipi) {
+		case IPI_AST:
+		case IPI_NOP:
+#ifdef __HAVE_PREEMPTION
+		case IPI_KPREEMPT:
+#endif
+			pic_ipi_nop(priv);
+			break;
+		case IPI_XCALL:
+			pic_ipi_xcall(priv);
+			break;
+		case IPI_GENERIC:
+			pic_ipi_generic(priv);
+			break;
+		case IPI_SHOOTDOWN:
+			pic_ipi_shootdown(priv);
+			break;
+#ifdef DDB
+		case IPI_DDB:
+			pic_ipi_ddb(priv);
+			break;
+#endif
+		}
+		ipimask &= ~__BIT(ipi);
+	}
+
+	return 1;
+}
+
+void
+bcm2836mp_intr_init(struct cpu_info *ci)
+{
+	const cpuid_t cpuid = ci->ci_cpuid;
+	struct pic_softc * const pic = &bcm2836mp_pic[cpuid];
+
+	pic->pic_cpus = ci->ci_kcpuset;
+	pic_add(pic, BCM2836_INT_BASECPUN(cpuid));
+
+	intr_establish(BCM2836_INT_MAILBOX0_CPUN(cpuid), IPL_HIGH,
+	    IST_LEVEL | IST_MPSAFE, bcm2836mp_ipi_handler, NULL);
+
+	/* clock interrupt will attach with gtmr */
+	if (cpuid == 0)
+		return;
+
+	intr_establish(BCM2836_INT_CNTVIRQ_CPUN(cpuid), IPL_CLOCK,
+	    IST_LEVEL | IST_MPSAFE, gtmr_intr, NULL);
+
+}
+#endif
+
 #endif

Index: src/sys/arch/arm/broadcom/bcm2835_intr.h
diff -u src/sys/arch/arm/broadcom/bcm2835_intr.h:1.1 src/sys/arch/arm/broadcom/bcm2835_intr.h:1.1.18.1
--- src/sys/arch/arm/broadcom/bcm2835_intr.h:1.1	Thu Jul 26 06:21:57 2012
+++ src/sys/arch/arm/broadcom/bcm2835_intr.h	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_intr.h,v 1.1 2012/07/26 06:21:57 skrll Exp $	*/
+/*	$NetBSD: bcm2835_intr.h,v 1.1.18.1 2015/07/30 09:37:37 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -38,8 +38,8 @@
 
 void bcm2835_irq_handler(void *);
 
-#define PIC_MAXSOURCES 96
-#define PIC_MAXMAXSOURCES 128
+#define PIC_MAXSOURCES 96 + (4*32)
+#define PIC_MAXMAXSOURCES 96 + (4*32) + 32
 
 #include <arm/pic/picvar.h>
 
@@ -50,6 +50,8 @@ bcm2835_intr_establish(int irq, int ipl,
 	return intr_establish(irq, ipl, IST_LEVEL, func, arg);
 }
 
+void bcm2836mp_intr_init(struct cpu_info *);
+
 #endif	/* _LOCORE */
 
 #endif /* _BCM2835_INTR_H_ */

Index: src/sys/arch/arm/broadcom/bcm2835_obio.c
diff -u src/sys/arch/arm/broadcom/bcm2835_obio.c:1.20.2.2 src/sys/arch/arm/broadcom/bcm2835_obio.c:1.20.2.3
--- src/sys/arch/arm/broadcom/bcm2835_obio.c:1.20.2.2	Wed Mar 11 20:22:55 2015
+++ src/sys/arch/arm/broadcom/bcm2835_obio.c	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835_obio.c,v 1.20.2.2 2015/03/11 20:22:55 snj Exp $	*/
+/*	$NetBSD: bcm2835_obio.c,v 1.20.2.3 2015/07/30 09:37:37 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012, 2014 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: bcm2835_obio.c,v 1.20.2.2 2015/03/11 20:22:55 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: bcm2835_obio.c,v 1.20.2.3 2015/07/30 09:37:37 martin Exp $");
 
 #include "locators.h"
 #include "obio.h"
@@ -38,10 +38,10 @@ __KERNEL_RCSID(0, "$NetBSD: bcm2835_obio
 #include "opt_bcm283x.h"
 
 #include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/device.h>
-
 #include <sys/bus.h>
+#include <sys/cpu.h>
+#include <sys/device.h>
+#include <sys/systm.h>
 
 #include <arm/broadcom/bcm2835reg.h>
 #include <arm/broadcom/bcm2835var.h>
@@ -262,7 +262,6 @@ obio_attach(device_t parent, device_t se
 				.mpcaa_irq = ad->ad_intr,
 			};
 
-
 			config_found(self, &mpcaa, NULL);
 			continue;
 		}
@@ -314,5 +313,9 @@ obio_print(void *aux, const char *name)
 void
 bcm2836_cpu_hatch(struct cpu_info *ci)
 {
+
+	bcm2836mp_intr_init(ci);
+
+	gtmr_init_cpu_clock(ci);
 }
 #endif

Index: src/sys/arch/arm/broadcom/bcm2835reg.h
diff -u src/sys/arch/arm/broadcom/bcm2835reg.h:1.10.12.3 src/sys/arch/arm/broadcom/bcm2835reg.h:1.10.12.4
--- src/sys/arch/arm/broadcom/bcm2835reg.h:1.10.12.3	Wed Mar 11 20:22:55 2015
+++ src/sys/arch/arm/broadcom/bcm2835reg.h	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: bcm2835reg.h,v 1.10.12.3 2015/03/11 20:22:55 snj Exp $	*/
+/*	$NetBSD: bcm2835reg.h,v 1.10.12.4 2015/07/30 09:37:37 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -83,7 +83,7 @@
 #define	BCM2835_USB_SIZE	0x20000
 #define	BCM2835_DMA15_SIZE	0x100
 
-#define BCM2835_IOPHYSTOVIRT(a) \
+#define	BCM2835_IOPHYSTOVIRT(a) \
     ((0xf0000000 | (((a) & 0xf0000000) >> 4)) + ((a) & ~0xff000000))
 
 #define	BCM2835_BUSADDR_CACHE_MASK	0xc0000000
@@ -127,8 +127,40 @@
 #define	BCM2835_INTC_ENABLEBASE		(BCM2835_INTC_BASE + 0x10)
 #define	BCM2835_INTC_DISABLEBASE	(BCM2835_INTC_BASE + 0x1c)
 
-/* Interrupt source */
-#define	BCM2835_INT_GPU0BASE		0
+#if defined(BCM2836)
+#define	BCM2836_NCPUS			4
+#define	BCM2836_NIRQPERCPU		32
+
+#define	BCM2836_INT_LOCALBASE		0
+#define	BCM2836_INT_BASECPUN(n)		(BCM2836_INT_LOCALBASE + ((n) * BCM2836_NIRQPERCPU))
+#define	BCM2836_NIRQ			(BCM2836_NIRQPERCPU * BCM2836_NCPUS)
+
+#define	BCM2835_INT_BASE		BCM2836_NIRQ
+
+#define	BCM2836_INT_CNTPSIRQ		0
+#define	BCM2836_INT_CNTPNSIRQ		1
+#define	BCM2836_INT_CNTHPIRQ		2
+#define	BCM2836_INT_CNTVIRQ		3
+#define	BCM2836_INT_MAILBOX0		4
+#define	BCM2836_INT_MAILBOX1		5
+#define	BCM2836_INT_MAILBOX2		6
+#define	BCM2836_INT_MAILBOX3		7
+#define	BCM2836_INT_GPU_FAST		8
+#define	BCM2836_INT_PMU_FAST		9
+#define	BCM2836_INT_ZERO		10
+#define	BCM2836_INT_TIMER		11
+#define	BCM2836_INT_NLOCAL		12
+
+#define	BCM2836_INT_CNTVIRQ_CPUN(n)	(BCM2836_INT_BASECPUN(n) + BCM2836_INT_CNTVIRQ)
+#define	BCM2836_INT_MAILBOX0_CPUN(n)	(BCM2836_INT_BASECPUN(n) + BCM2836_INT_MAILBOX0)
+#else
+#define	BCM2835_INT_BASE		0
+#endif /* !BCM2836 */
+
+/* Periperal Interrupt sources */
+#define	BCM2835_NIRQ			96
+
+#define	BCM2835_INT_GPU0BASE		(BCM2835_INT_BASE + 0)
 #define	BCM2835_INT_TIMER0		(BCM2835_INT_GPU0BASE + 0)
 #define	BCM2835_INT_TIMER1		(BCM2835_INT_GPU0BASE + 1)
 #define	BCM2835_INT_TIMER2		(BCM2835_INT_GPU0BASE + 2)
@@ -140,7 +172,7 @@
 #define	BCM2835_INT_AUX			(BCM2835_INT_GPU0BASE + 29)
 #define	BCM2835_INT_ARM			(BCM2835_INT_GPU0BASE + 30)
 
-#define	BCM2835_INT_GPU1BASE		32
+#define	BCM2835_INT_GPU1BASE		(BCM2835_INT_BASE + 32)
 #define	BCM2835_INT_GPIO0		(BCM2835_INT_GPU1BASE + 17)
 #define	BCM2835_INT_GPIO1		(BCM2835_INT_GPU1BASE + 18)
 #define	BCM2835_INT_GPIO2		(BCM2835_INT_GPU1BASE + 19)
@@ -151,7 +183,7 @@
 #define	BCM2835_INT_UART0		(BCM2835_INT_GPU1BASE + 25)
 #define	BCM2835_INT_EMMC		(BCM2835_INT_GPU1BASE + 30)
 
-#define	BCM2835_INT_BASICBASE		64
+#define	BCM2835_INT_BASICBASE		(BCM2835_INT_BASE + 64)
 #define	BCM2835_INT_ARMTIMER		(BCM2835_INT_BASICBASE + 0)
 #define	BCM2835_INT_ARMMAILBOX		(BCM2835_INT_BASICBASE + 1)
 #define	BCM2835_INT_ARMDOORBELL0	(BCM2835_INT_BASICBASE + 2)
@@ -161,31 +193,8 @@
 #define	BCM2835_INT_ILLEGALTYPE0	(BCM2835_INT_BASICBASE + 6)
 #define	BCM2835_INT_ILLEGALTYPE1	(BCM2835_INT_BASICBASE + 7)
 
-#define	BCM2836_NCPUS			4
-
-#define	BCM2836_INT_LOCALBASE		96
-
-#define	BCM2836_INT_CNTPSIRQ		0
-#define	BCM2836_INT_CNTPNSIRQ		1
-#define	BCM2836_INT_CNTHPIRQ		2
-#define	BCM2836_INT_CNTVIRQ		3
-#define	BCM2836_INT_MAILBOX0		4
-#define	BCM2836_INT_MAILBOX1		5
-#define	BCM2836_INT_MAILBOX2		6
-#define	BCM2836_INT_MAILBOX3		7
-#define	BCM2836_INT_GPU_FAST		8
-#define	BCM2836_INT_PMU_FAST		9
-#define	BCM2836_INT_ZERO		10
-#define	BCM2836_INT_TIMER		11
-#define	BCM2836_INT_NLOCAL		12
-
-#define	BCM2836_INT_CNTVIRQ_CPUN(n)	(BCM2836_INT_LOCALBASE + ((n) * 32) + BCM2836_INT_CNTVIRQ)
-#define	BCM2836_INT_MAILBOX0_CPUN(n)	(BCM2836_INT_LOCALBASE + ((n) * 32) + BCM2836_INT_MAILBOX0)
-
-#define	BCM2835_NIRQ			96
-#define	BCM2836MP_NIRQ			32
 
-#define	BCM2835_UART0_CLK	3000000
+#define	BCM2835_UART0_CLK		3000000
 
 #define	BCM2836_ARM_LOCAL_VBASE \
 	BCM2835_IOPHYSTOVIRT(BCM2836_ARM_LOCAL_BASE)

Index: src/sys/arch/arm/cortex/gic.c
diff -u src/sys/arch/arm/cortex/gic.c:1.10.2.4 src/sys/arch/arm/cortex/gic.c:1.10.2.5
--- src/sys/arch/arm/cortex/gic.c:1.10.2.4	Sat Mar 21 17:24:19 2015
+++ src/sys/arch/arm/cortex/gic.c	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: gic.c,v 1.10.2.4 2015/03/21 17:24:19 snj Exp $	*/
+/*	$NetBSD: gic.c,v 1.10.2.5 2015/07/30 09:37:37 martin Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -34,7 +34,7 @@
 #define _INTR_PRIVATE
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.10.2.4 2015/03/21 17:24:19 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: gic.c,v 1.10.2.5 2015/07/30 09:37:37 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/bus.h>
@@ -569,6 +569,9 @@ armgic_attach(device_t parent, device_t 
 	    "%zu sources (%zu valid)\n",
 	    sc->sc_pic.pic_maxsources, sc->sc_gic_lines);
 
+#ifdef MULTIPROCESSOR
+	sc->sc_pic.pic_cpus = kcpuset_running;
+#endif
 	pic_add(&sc->sc_pic, 0);
 
 	/*

Index: src/sys/arch/arm/marvell/mvsoc_intr.h
diff -u src/sys/arch/arm/marvell/mvsoc_intr.h:1.4 src/sys/arch/arm/marvell/mvsoc_intr.h:1.4.4.1
--- src/sys/arch/arm/marvell/mvsoc_intr.h:1.4	Tue Mar 18 06:46:14 2014
+++ src/sys/arch/arm/marvell/mvsoc_intr.h	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: mvsoc_intr.h,v 1.4 2014/03/18 06:46:14 matt Exp $	*/
+/*	$NetBSD: mvsoc_intr.h,v 1.4.4.1 2015/07/30 09:37:37 martin Exp $	*/
 /*
  * Copyright (c) 2010 KIYOHARA Takashi
  * All rights reserved.
@@ -33,6 +33,7 @@
 
 #if defined(ARMADAXP)
 #define __HAVE_PIC_SET_PRIORITY
+#define __HAVE_PIC_PENDING_INTRS
 #endif
 #endif
 

Index: src/sys/arch/arm/omap/omap4430_intr.h
diff -u src/sys/arch/arm/omap/omap4430_intr.h:1.2 src/sys/arch/arm/omap/omap4430_intr.h:1.2.18.1
--- src/sys/arch/arm/omap/omap4430_intr.h:1.2	Sat Sep  1 00:05:36 2012
+++ src/sys/arch/arm/omap/omap4430_intr.h	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: omap4430_intr.h,v 1.2 2012/09/01 00:05:36 matt Exp $	*/
+/*	$NetBSD: omap4430_intr.h,v 1.2.18.1 2015/07/30 09:37:37 martin Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -44,8 +44,9 @@
 #define	PIC_MAXMAXSOURCES	(PIC_MAXSOURCES+6*32)
 
 /*
- * The BCM53xx uses a generic interrupt controller so pull that stuff.
+ * The OMAP4 uses a generic interrupt controller so pull in that stuff.
  */
+#define __HAVE_PIC_PENDING_INTRS
 #include <arm/cortex/gic_intr.h>
 #include <arm/cortex/a9tmr_intr.h>      /* A9 Timer PPIs */
 

Index: src/sys/arch/arm/omap/omap5430_intr.h
diff -u src/sys/arch/arm/omap/omap5430_intr.h:1.2 src/sys/arch/arm/omap/omap5430_intr.h:1.2.4.1
--- src/sys/arch/arm/omap/omap5430_intr.h:1.2	Wed Apr  9 19:50:01 2014
+++ src/sys/arch/arm/omap/omap5430_intr.h	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: omap5430_intr.h,v 1.2 2014/04/09 19:50:01 matt Exp $	*/
+/*	$NetBSD: omap5430_intr.h,v 1.2.4.1 2015/07/30 09:37:37 martin Exp $	*/
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -40,8 +40,9 @@
 #define PIC_MAXMAXSOURCES	(PIC_MAXSOURCES+8*32)
 
 /*
- * The BCM53xx uses a generic interrupt controller so pull that stuff.
+ * The OMAP5 uses a generic interrupt controller so pull in that stuff.
  */
+#define __HAVE_PIC_PENDING_INTRS
 #include <arm/cortex/gic_intr.h>
 #include <arm/cortex/gtmr_intr.h>      /* Generic Timer PPIs */
 

Index: src/sys/arch/arm/pic/pic.c
diff -u src/sys/arch/arm/pic/pic.c:1.22.2.2 src/sys/arch/arm/pic/pic.c:1.22.2.3
--- src/sys/arch/arm/pic/pic.c:1.22.2.2	Mon Nov 10 19:57:26 2014
+++ src/sys/arch/arm/pic/pic.c	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: pic.c,v 1.22.2.2 2014/11/10 19:57:26 martin Exp $	*/
+/*	$NetBSD: pic.c,v 1.22.2.3 2015/07/30 09:37:37 martin Exp $	*/
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -33,7 +33,7 @@
 #include "opt_multiprocessor.h"
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.22.2.2 2014/11/10 19:57:26 martin Exp $");
+__KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.22.2.3 2015/07/30 09:37:37 martin Exp $");
 
 #include <sys/param.h>
 #include <sys/atomic.h>
@@ -54,22 +54,38 @@ __KERNEL_RCSID(0, "$NetBSD: pic.c,v 1.22
 
 #include <arm/pic/picvar.h>
 
+#if defined(__HAVE_PIC_PENDING_INTRS)
+/*
+ * This implementation of pending interrupts on a MULTIPROCESSOR system makes
+ * the assumption that a PIC (pic_softc) shall only have all its interrupts
+ * come from the same CPU.  In other words, interrupts from a single PIC will
+ * not be distributed among multiple CPUs.
+ */
+struct pic_pending {
+	volatile uint32_t blocked_pics;
+	volatile uint32_t pending_pics;
+	volatile uint32_t pending_ipls;
+};
 static uint32_t
 	pic_find_pending_irqs_by_ipl(struct pic_softc *, size_t, uint32_t, int);
 static struct pic_softc *
-	pic_list_find_pic_by_pending_ipl(uint32_t);
+	pic_list_find_pic_by_pending_ipl(struct pic_pending *, uint32_t);
 static void
-	pic_deliver_irqs(struct pic_softc *, int, void *);
+	pic_deliver_irqs(struct pic_pending *, struct pic_softc *, int, void *);
 static void
-	pic_list_deliver_irqs(register_t, int, void *);
+	pic_list_deliver_irqs(struct pic_pending *, register_t, int, void *);
+
+#ifdef MULTIPROCESSOR
+percpu_t *pic_pending_percpu;
+#else
+struct pic_pending pic_pending;
+#endif /* MULTIPROCESSOR */
+#endif /* __HAVE_PIC_PENDING_INTRS */
 
 struct pic_softc *pic_list[PIC_MAXPICS];
 #if PIC_MAXPICS > 32
 #error PIC_MAXPICS > 32 not supported
 #endif
-volatile uint32_t pic_blocked_pics;
-volatile uint32_t pic_pending_pics;
-volatile uint32_t pic_pending_ipls;
 struct intrsource *pic_sources[PIC_MAXMAXSOURCES];
 struct intrsource *pic__iplsources[PIC_MAXMAXSOURCES];
 struct intrsource **pic_iplsource[NIPL] = {
@@ -139,27 +155,30 @@ intr_cpu_init(struct cpu_info *ci)
 
 typedef void (*pic_ipi_send_func_t)(struct pic_softc *, u_long);
 
-static struct pic_softc *
-pic_ipi_sender(void)
+void
+intr_ipi_send(const kcpuset_t *kcp, u_long ipi)
 {
+	struct cpu_info * const ci = curcpu();
+	KASSERT(ipi < NIPI);
+	bool __diagused sent_p = false;
 	for (size_t slot = 0; slot < PIC_MAXPICS; slot++) {
 		struct pic_softc * const pic = pic_list[slot];
-		if (pic != NULL && pic->pic_ops->pic_ipi_send != NULL) {
-			return pic;
+		if (pic == NULL || pic->pic_cpus == NULL)
+			continue;
+		if (kcp == NULL || kcpuset_intersecting_p(kcp, pic->pic_cpus)) {
+			// never send to ourself
+			if (pic->pic_cpus == ci->ci_kcpuset)
+				continue;
+
+			(*pic->pic_ops->pic_ipi_send)(pic, kcp, ipi);
+			// If we were targeting a single CPU or this pic
+			// handles all cpus, we're done.
+			if (kcp != NULL || pic->pic_cpus == kcpuset_running)
+				return;
+			sent_p = true;
 		}
 	}
-	return NULL;
-}
-
-void
-intr_ipi_send(const kcpuset_t *kcp, u_long ipi)
-{
-	struct pic_softc * const pic = pic_ipi_sender();
-	KASSERT(ipi < NIPI);
-	if (cold && pic == NULL)
-		return;
-	KASSERT(pic != NULL);
-	(*pic->pic_ops->pic_ipi_send)(pic, kcp, ipi);
+	KASSERT(cold || sent_p);
 }
 #endif /* MULTIPROCESSOR */
 
@@ -190,6 +209,7 @@ pic_handle_intr(void *arg)
 	return rv > 0;
 }
 
+#if defined(__HAVE_PIC_PENDING_INTRS)
 void
 pic_mark_pending_source(struct pic_softc *pic, struct intrsource *is)
 {
@@ -199,8 +219,16 @@ pic_mark_pending_source(struct pic_softc
 	    __BIT(is->is_irq & 0x1f));
 
 	atomic_or_32(&pic->pic_pending_ipls, ipl_mask);
-	atomic_or_32(&pic_pending_ipls, ipl_mask);
-	atomic_or_32(&pic_pending_pics, __BIT(pic->pic_id));
+#ifdef MULTIPROCESSOR
+	struct pic_pending *pend = percpu_getref(pic_pending_percpu);
+#else
+	struct pic_pending *pend = &pic_pending;
+#endif
+	atomic_or_32(&pend->pending_ipls, ipl_mask);
+	atomic_or_32(&pend->pending_pics, __BIT(pic->pic_id));
+#ifdef MULTIPROCESSOR
+	percpu_putref(pic_pending_percpu);
+#endif
 }
 
 void
@@ -243,9 +271,16 @@ pic_mark_pending_sources(struct pic_soft
 	}
 
 	atomic_or_32(&pic->pic_pending_ipls, ipl_mask);
-	atomic_or_32(&pic_pending_ipls, ipl_mask);
-	atomic_or_32(&pic_pending_pics, __BIT(pic->pic_id));
-
+#ifdef MULTIPROCESSOR
+	struct pic_pending *pend = percpu_getref(pic_pending_percpu);
+#else
+	struct pic_pending *pend = &pic_pending;
+#endif
+	atomic_or_32(&pend->pending_ipls, ipl_mask);
+	atomic_or_32(&pend->pending_pics, __BIT(pic->pic_id));
+#ifdef MULTIPROCESSOR
+	percpu_putref(pic_pending_percpu);
+#endif
 	return ipl_mask;
 }
 
@@ -277,6 +312,7 @@ pic_find_pending_irqs_by_ipl(struct pic_
 		pending &= ~irq_mask;
 	}
 }
+#endif /* __HAVE_PIC_PENDING_INTRS */
 
 void
 pic_dispatch(struct intrsource *is, void *frame)
@@ -312,8 +348,10 @@ pic_dispatch(struct intrsource *is, void
 	percpu_putref(is->is_pic->pic_percpu);
 }
 
+#if defined(__HAVE_PIC_PENDING_INTRS)
 void
-pic_deliver_irqs(struct pic_softc *pic, int ipl, void *frame)
+pic_deliver_irqs(struct pic_pending *pend, struct pic_softc *pic, int ipl,
+    void *frame)
 {
 	const uint32_t ipl_mask = __BIT(ipl);
 	struct intrsource *is;
@@ -328,7 +366,7 @@ pic_deliver_irqs(struct pic_softc *pic, 
 	uint32_t blocked_irqs;
 	int irq;
 	bool progress __diagused = false;
-	
+
 	KASSERT(pic->pic_pending_ipls & ipl_mask);
 
 	irq_base = 0;
@@ -392,7 +430,7 @@ pic_deliver_irqs(struct pic_softc *pic, 
 		} while (pending_irqs);
 		if (blocked_irqs) {
 			atomic_or_32(iblocked, blocked_irqs);
-			atomic_or_32(&pic_blocked_pics, __BIT(pic->pic_id));
+			atomic_or_32(&pend->blocked_pics, __BIT(pic->pic_id));
 		}
 	}
 
@@ -402,15 +440,16 @@ pic_deliver_irqs(struct pic_softc *pic, 
 	 * about these.
 	 */
 	if (atomic_and_32_nv(&pic->pic_pending_ipls, ~ipl_mask) == 0)
-		atomic_and_32(&pic_pending_pics, ~__BIT(pic->pic_id));
+		atomic_and_32(&pend->pending_pics, ~__BIT(pic->pic_id));
 }
 
 static void
-pic_list_unblock_irqs(void)
+pic_list_unblock_irqs(struct pic_pending *pend)
 {
-	uint32_t blocked_pics = pic_blocked_pics;
+	uint32_t blocked_pics = pend->blocked_pics;
+
+	pend->blocked_pics = 0;
 
-	pic_blocked_pics = 0;
 	for (;;) {
 		struct pic_softc *pic;
 #if PIC_MAXSOURCES > 32
@@ -447,9 +486,9 @@ pic_list_unblock_irqs(void)
 
 
 struct pic_softc *
-pic_list_find_pic_by_pending_ipl(uint32_t ipl_mask)
+pic_list_find_pic_by_pending_ipl(struct pic_pending *pend, uint32_t ipl_mask)
 {
-	uint32_t pending_pics = pic_pending_pics;
+	uint32_t pending_pics = pend->pending_pics;
 	struct pic_softc *pic;
 
 	for (;;) {
@@ -466,17 +505,19 @@ pic_list_find_pic_by_pending_ipl(uint32_
 }
 
 void
-pic_list_deliver_irqs(register_t psw, int ipl, void *frame)
+pic_list_deliver_irqs(struct pic_pending *pend, register_t psw, int ipl,
+    void *frame)
 {
 	const uint32_t ipl_mask = __BIT(ipl);
 	struct pic_softc *pic;
 
-	while ((pic = pic_list_find_pic_by_pending_ipl(ipl_mask)) != NULL) {
-		pic_deliver_irqs(pic, ipl, frame);
+	while ((pic = pic_list_find_pic_by_pending_ipl(pend, ipl_mask)) != NULL) {
+		pic_deliver_irqs(pend, pic, ipl, frame);
 		KASSERT((pic->pic_pending_ipls & ipl_mask) == 0);
 	}
-	atomic_and_32(&pic_pending_ipls, ~ipl_mask);
+	atomic_and_32(&pend->pending_ipls, ~ipl_mask);
 }
+#endif /* __HAVE_PIC_PENDING_INTRS */
 
 void
 pic_do_pending_ints(register_t psw, int newipl, void *frame)
@@ -486,19 +527,35 @@ pic_do_pending_ints(register_t psw, int 
 		KASSERTMSG(ci->ci_cpl == IPL_HIGH, "cpl %d", ci->ci_cpl);
 		return;
 	}
-	while ((pic_pending_ipls & ~__BIT(newipl)) > __BIT(newipl)) {
-		KASSERT(pic_pending_ipls < __BIT(NIPL));
+#if defined(__HAVE_PIC_PENDING_INTRS)
+#ifdef MULTIPROCESSOR
+	struct pic_pending *pend = percpu_getref(pic_pending_percpu);
+#else
+	struct pic_pending *pend = &pic_pending;
+#endif
+	while ((pend->pending_ipls & ~__BIT(newipl)) > __BIT(newipl)) {
+		KASSERT(pend->pending_ipls < __BIT(NIPL));
 		for (;;) {
-			int ipl = 31 - __builtin_clz(pic_pending_ipls);
+			int ipl = 31 - __builtin_clz(pend->pending_ipls);
 			KASSERT(ipl < NIPL);
 			if (ipl <= newipl)
 				break;
 
 			pic_set_priority(ci, ipl);
-			pic_list_deliver_irqs(psw, ipl, frame);
-			pic_list_unblock_irqs();
+			pic_list_deliver_irqs(pend, psw, ipl, frame);
+			pic_list_unblock_irqs(pend);
 		}
 	}
+#ifdef MULTIPROCESSOR
+	percpu_putref(pic_pending_percpu);
+#endif
+#endif /* __HAVE_PIC_PENDING_INTRS */
+#ifdef __HAVE_PREEEMPTION
+	if (newipl == IPL_NONE && (ci->ci_astpending & __BIT(1))) {
+		pic_set_priority(ci, IPL_SCHED);
+		kpreempt(0);
+	}
+#endif
 	if (ci->ci_cpl != newipl)
 		pic_set_priority(ci, newipl);
 }
@@ -534,6 +591,15 @@ pic_percpu_allocate(void *v0, void *v1, 
 #endif
 }
 
+#if defined(__HAVE_PIC_PENDING_INTRS) && defined(MULTIPROCESSOR)
+static void
+pic_pending_zero(void *v0, void *v1, struct cpu_info *ci)
+{
+	struct pic_pending * const p = v0;
+	memset(p, 0, sizeof(*p));
+}
+#endif /* __HAVE_PIC_PENDING_INTRS && MULTIPROCESSOR */
+
 void
 pic_add(struct pic_softc *pic, int irqbase)
 {
@@ -541,6 +607,18 @@ pic_add(struct pic_softc *pic, int irqba
 
 	KASSERT(strlen(pic->pic_name) > 0);
 
+#if defined(__HAVE_PIC_PENDING_INTRS) && defined(MULTIPROCESSOR)
+	if (__predict_false(pic_pending_percpu == NULL)) {
+		pic_pending_percpu = percpu_alloc(sizeof(struct pic_pending));
+		KASSERT(pic_pending_percpu != NULL);
+
+		/*
+		 * Now zero the per-cpu pending data.
+		 */
+		percpu_foreach(pic_pending_percpu, pic_pending_zero, NULL);
+	}
+#endif /* __HAVE_PIC_PENDING_INTRS && MULTIPROCESSOR */
+
 	for (slot = 0; slot < PIC_MAXPICS; slot++) {
 		struct pic_softc * const xpic = pic_list[slot];
 		if (xpic == NULL) {
@@ -594,7 +672,7 @@ pic_add(struct pic_softc *pic, int irqba
 	KASSERT((slot == 0) == (pic->pic_ops->pic_set_priority != NULL));
 #endif
 #ifdef MULTIPROCESSOR
-	KASSERT((slot == 0) == (pic->pic_ops->pic_ipi_send != NULL));
+	KASSERT((pic->pic_cpus != NULL) == (pic->pic_ops->pic_ipi_send != NULL));
 #endif
 	pic_list[slot] = pic;
 }

Index: src/sys/arch/arm/pic/picvar.h
diff -u src/sys/arch/arm/pic/picvar.h:1.10.2.1 src/sys/arch/arm/pic/picvar.h:1.10.2.2
--- src/sys/arch/arm/pic/picvar.h:1.10.2.1	Sun Nov  9 16:05:25 2014
+++ src/sys/arch/arm/pic/picvar.h	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: picvar.h,v 1.10.2.1 2014/11/09 16:05:25 martin Exp $	*/
+/*	$NetBSD: picvar.h,v 1.10.2.2 2015/07/30 09:37:37 martin Exp $	*/
 /*-
  * Copyright (c) 2008 The NetBSD Foundation, Inc.
  * All rights reserved.
@@ -59,11 +59,17 @@ struct cpu_info;
 #define	NIPI			6
 #endif
 
+#if !defined(__HAVE_PIC_SET_PRIORITY)
+#define __HAVE_PIC_PENDING_INTRS
+#endif
+
 int	pic_handle_intr(void *);
+#if defined(__HAVE_PIC_PENDING_INTRS)
 void	pic_mark_pending(struct pic_softc *pic, int irq);
 void	pic_mark_pending_source(struct pic_softc *pic, struct intrsource *is);
 uint32_t pic_mark_pending_sources(struct pic_softc *pic, size_t irq_base,
 	    uint32_t pending);
+#endif /* __HAVE_PIC_PENDING_INTRS */
 void	*pic_establish_intr(struct pic_softc *pic, int irq, int ipl, int type,
 	    int (*func)(void *), void *arg);
 int	pic_alloc_irq(struct pic_softc *pic);
@@ -119,9 +125,14 @@ struct pic_percpu {
 struct pic_softc {
 	const struct pic_ops *pic_ops;
 	struct intrsource **pic_sources;
+#ifdef __HAVE_PIC_PENDING_INTRS
 	volatile uint32_t pic_pending_irqs[(PIC_MAXSOURCES + 31) / 32];
 	volatile uint32_t pic_blocked_irqs[(PIC_MAXSOURCES + 31) / 32];
 	volatile uint32_t pic_pending_ipls;
+#endif
+#ifdef MULTIPROCESSOR
+	kcpuset_t *pic_cpus;
+#endif
 	size_t pic_maxsources;
 	percpu_t *pic_percpu;
 	uint8_t pic_id;
@@ -161,7 +172,7 @@ void	pic_set_priority(struct cpu_info *,
 void	pic_add(struct pic_softc *, int);
 void	pic_do_pending_int(void);
 #ifdef MULTIPROCESSOR
-int	pic_ipi_nop(void *);
+int	pic_ipi_nop(void *);		// IPI_KPREEMPT tto
 int	pic_ipi_xcall(void *);
 int	pic_ipi_generic(void *);
 int	pic_ipi_shootdown(void *);

Index: src/sys/arch/evbarm/rpi/rpi_machdep.c
diff -u src/sys/arch/evbarm/rpi/rpi_machdep.c:1.43.2.4 src/sys/arch/evbarm/rpi/rpi_machdep.c:1.43.2.5
--- src/sys/arch/evbarm/rpi/rpi_machdep.c:1.43.2.4	Wed Mar 11 20:22:56 2015
+++ src/sys/arch/evbarm/rpi/rpi_machdep.c	Thu Jul 30 09:37:37 2015
@@ -1,4 +1,4 @@
-/*	$NetBSD: rpi_machdep.c,v 1.43.2.4 2015/03/11 20:22:56 snj Exp $	*/
+/*	$NetBSD: rpi_machdep.c,v 1.43.2.5 2015/07/30 09:37:37 martin Exp $	*/
 
 /*-
  * Copyright (c) 2012 The NetBSD Foundation, Inc.
@@ -30,7 +30,7 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.43.2.4 2015/03/11 20:22:56 snj Exp $");
+__KERNEL_RCSID(0, "$NetBSD: rpi_machdep.c,v 1.43.2.5 2015/07/30 09:37:37 martin Exp $");
 
 #include "opt_arm_debug.h"
 #include "opt_bcm283x.h"
@@ -518,11 +518,6 @@ rpi_bootstrap(void)
 			    __func__, i);
 		}
 	}
-
-	/*
-	 * XXXNH: Disable non-boot CPUs for now
-	 */
-	arm_cpu_hatched = 0;
 #endif
 }
 

Reply via email to