Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 13 Dec 2007 02:01:40 GMT
From:      Marcel Moolenaar <marcel@FreeBSD.org>
To:        Perforce Change Reviews <perforce@freebsd.org>
Subject:   PERFORCE change 130780 for review
Message-ID:  <200712130201.lBD21eun023676@repoman.freebsd.org>

next in thread | raw e-mail | index | archive | help
http://perforce.freebsd.org/chv.cgi?CH=130780

Change 130780 by marcel@marcel_jnpr on 2007/12/13 02:00:45

	o  Have the PIC tell MD code which IRQ to use for setting up
	   an IPI handler.
	o  Setup a fast handler for the IPI IRQ just prior to enabling
	   all interrupts.
	o  Send a test IPI to the BSP after all interrupts (including
	   the IPI) are enabled.
	o  Implement the IPI handler as a regular interrupt filter.
	
	The upshot is that an IPI is no different from any other HW
	interrupt and as such, vmstat -i will list it:
	
		# vmstat -i
		interrupt                          total       rate
		irq22: scc0                          442         26
		irq19: ata0                           60          3
		irq27: ohci0                           1          0
		irq28: ohci1                           1          0
		irq58: atapci0                       136          8
		irq63: atapci1                        27          1
		irq40: fwohci0                         2          0
		irq64: IPI                             1          0
		Total                                670         39

Affected files ...

.. //depot/projects/powerpc/sys/powerpc/include/intr_machdep.h#4 edit
.. //depot/projects/powerpc/sys/powerpc/include/openpicreg.h#6 edit
.. //depot/projects/powerpc/sys/powerpc/include/smp.h#4 edit
.. //depot/projects/powerpc/sys/powerpc/powermac/hrowpic.c#4 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/intr_machdep.c#6 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/mp_machdep.c#13 edit
.. //depot/projects/powerpc/sys/powerpc/powerpc/openpic.c#6 edit

Differences ...

==== //depot/projects/powerpc/sys/powerpc/include/intr_machdep.h#4 (text+ko) ====

@@ -34,7 +34,9 @@
 
 struct trapframe;
 
-void	powerpc_register_pic(device_t);
+driver_filter_t powerpc_ipi_handler;
+
+void	powerpc_register_pic(device_t, u_int);
 
 void	powerpc_dispatch_intr(u_int, struct trapframe *);
 int	powerpc_enable_intr(void);

==== //depot/projects/powerpc/sys/powerpc/include/openpicreg.h#6 (text+ko) ====

@@ -40,7 +40,7 @@
 #define	OPENPIC_IPI_DISPATCH(ipi)	(0x40 + (ipi) * 0x10)
 
 /* current task priority reg */
-#define	OPENPIC_TPR		0x80
+#define	OPENPIC_TPR			0x80
 #define  OPENPIC_TPR_MASK			0x0000000f
 
 #define	OPENPIC_WHOAMI			0x90
@@ -129,6 +129,9 @@
 #define	OPENPIC_PCPU_TPR(cpu)		\
 	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_TPR)
 
+#define	OPENPIC_PCPU_WHOAMI(cpu)		\
+	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_WHOAMI)
+
 #define OPENPIC_PCPU_IACK(cpu)			\
 	(OPENPIC_PCPU_BASE(cpu) + OPENPIC_IACK)
 

==== //depot/projects/powerpc/sys/powerpc/include/smp.h#4 (text+ko) ====

@@ -32,9 +32,11 @@
 #ifdef _KERNEL
 
 #define	IPI_AST			0
-#define	IPI_RENDEZVOUS		1
-#define	IPI_STOP		2
-#define	IPI_PREEMPT		3
+#define	IPI_PREEMPT		1
+#define	IPI_RENDEZVOUS		2
+#define	IPI_STOP		3
+
+#define	IPI_PPC_TEST		4
 
 #ifndef LOCORE
 

==== //depot/projects/powerpc/sys/powerpc/powermac/hrowpic.c#4 (text+ko) ====

@@ -68,6 +68,7 @@
 static void	hrowpic_dispatch(device_t, struct trapframe *);
 static void	hrowpic_enable(device_t, u_int, u_int);
 static void	hrowpic_eoi(device_t, u_int);
+static void	hrowpic_ipi(device_t, u_int);
 static void	hrowpic_mask(device_t, u_int);
 static void	hrowpic_unmask(device_t, u_int);
 
@@ -80,6 +81,7 @@
 	DEVMETHOD(pic_dispatch,		hrowpic_dispatch),
 	DEVMETHOD(pic_enable,		hrowpic_enable),
 	DEVMETHOD(pic_eoi,		hrowpic_eoi),
+	DEVMETHOD(pic_ipi,		hrowpic_ipi),
 	DEVMETHOD(pic_mask,		hrowpic_mask),
 	DEVMETHOD(pic_unmask,		hrowpic_unmask),
 
@@ -167,7 +169,7 @@
 	hrowpic_write_reg(sc, HPIC_ENABLE, HPIC_SECONDARY, 0);
 	hrowpic_write_reg(sc, HPIC_CLEAR,  HPIC_SECONDARY, 0xffffffff);
 
-	powerpc_register_pic(dev);
+	powerpc_register_pic(dev, 64);
 	return (0);
 }
 
@@ -250,6 +252,12 @@
 }
 
 static void
+hrowpic_ipi(device_t dev, u_int irq)
+{
+	/* No SMP support. */
+}
+
+static void
 hrowpic_mask(device_t dev, u_int irq)
 {
 	struct hrowpic_softc *sc;

==== //depot/projects/powerpc/sys/powerpc/powerpc/intr_machdep.c#6 (text+ko) ====

@@ -78,6 +78,7 @@
 #include <machine/frame.h>
 #include <machine/intr_machdep.h>
 #include <machine/md_var.h>
+#include <machine/smp.h>
 #include <machine/trap.h>
 
 #include "pic_if.h"
@@ -96,6 +97,9 @@
 static u_int nvectors;		/* Allocated vectors */
 static u_int stray_count;
 
+static void *ipi_cookie;
+static u_int ipi_irq;
+
 device_t pic;
 
 static void
@@ -132,17 +136,31 @@
 }
 
 void
-powerpc_register_pic(device_t dev)
+powerpc_register_pic(device_t dev, u_int ipi)
 {
 
 	pic = dev;
+	ipi_irq = ipi;
 }
 
 int
 powerpc_enable_intr(void)
 {
 	struct powerpc_intr *i;
-	int vector;
+	int error, vector;
+
+	if (pic == NULL)
+		panic("no PIC detected\n");
+
+#ifdef SMP
+	/* Install an IPI handler. */
+	error = powerpc_setup_intr("IPI", ipi_irq, powerpc_ipi_handler,
+	    NULL, NULL, INTR_TYPE_MISC | INTR_EXCL | INTR_FAST, &ipi_cookie);
+	if (error) {
+		printf("unable to setup IPI handler\n");
+		return (error);
+	}
+#endif
 
 	for (vector = 0; vector < nvectors; vector++) {
 		i = powerpc_intrs[vector];
@@ -152,6 +170,11 @@
 		PIC_ENABLE(pic, i->irq, vector);
 	}
 
+#ifdef SMP
+	/* Send ourself a test IPI message. */
+	ipi_self(IPI_PPC_TEST);
+#endif
+
 	return (0);
 }
 

==== //depot/projects/powerpc/sys/powerpc/powerpc/mp_machdep.c#13 (text+ko) ====

@@ -35,6 +35,7 @@
 #include <sys/smp.h>
 
 #include <machine/bus.h>
+#include <machine/cpu.h>
 #include <machine/intr_machdep.h>
 #include <machine/smp.h>
 
@@ -212,6 +213,50 @@
 
 SYSINIT(start_aps, SI_SUB_SMP, SI_ORDER_FIRST, cpu_mp_unleash, NULL);
 
+static u_int ipi_msg_cnt[32];
+
+int
+powerpc_ipi_handler(void *arg)
+{
+	cpumask_t self;
+	uint32_t ipimask;
+	int msg;
+
+	ipimask = atomic_readandclear_32(&(pcpup->pc_ipimask));
+	if (ipimask == 0)
+		return (FILTER_STRAY);
+	while ((msg = ffs(ipimask) - 1) != -1) {
+		ipimask &= ~(1u << msg);
+		ipi_msg_cnt[msg]++;
+		switch (msg) {
+		case IPI_AST:
+			break;
+		case IPI_PREEMPT:
+			/* TBD */
+			break;
+		case IPI_RENDEZVOUS:
+			smp_rendezvous_action();
+			break;
+		case IPI_STOP:
+			self = PCPU_GET(cpumask);
+#if 0
+			savectx(PCPU_PTR(pcb));
+#endif
+			atomic_set_int(&stopped_cpus, self);
+			while ((started_cpus & self) == 0)
+				cpu_spinwait();
+			atomic_clear_int(&started_cpus, self);
+			atomic_clear_int(&stopped_cpus, self);
+			break;
+		case IPI_PPC_TEST:
+			mp_ipi_test++;
+			break;
+		}
+	}
+
+	return (FILTER_HANDLED);
+}
+
 static void
 ipi_send(struct pcpu *pc, int ipi)
 {

==== //depot/projects/powerpc/sys/powerpc/powerpc/openpic.c#6 (text+ko) ====

@@ -82,7 +82,7 @@
 openpic_attach(device_t dev)
 {
 	struct openpic_softc *sc;
-	u_int     irq;
+	u_int     ipi, irq;
 	u_int32_t x;
 
 	sc = device_get_softc(dev);
@@ -132,9 +132,23 @@
 		    "Version %s, supports %d CPUs and %d irqs\n",
 		    sc->sc_version, sc->sc_ncpu, sc->sc_nirq);
 
-	/* disable all interrupts */
-	for (irq = 0; irq < sc->sc_nirq; irq++)
-		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), OPENPIC_IMASK);
+	/* Reset and disable all interrupts. */
+	for (irq = 0; irq < sc->sc_nirq; irq++) {
+		x = irq;                /* irq == vector. */
+		x |= OPENPIC_IMASK;
+		x |= OPENPIC_POLARITY_POSITIVE;
+		x |= OPENPIC_SENSE_LEVEL;
+		x |= 8 << OPENPIC_PRIORITY_SHIFT;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	}
+
+	/* Reset and disable all IPIs. */
+	for (ipi = 0; ipi < 4; ipi++) {
+		x = sc->sc_nirq + ipi;
+		x |= OPENPIC_IMASK;
+		x |= 15 << OPENPIC_PRIORITY_SHIFT;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(ipi), x);
+	}
 
 	openpic_set_priority(sc, 15);
 
@@ -147,16 +161,6 @@
 	for (irq = 0; irq < sc->sc_nirq; irq++)
 		openpic_write(sc, OPENPIC_IDEST(irq), 1 << 0);
 
-	for (irq = 0; irq < sc->sc_nirq; irq++) {
-		x = irq;		/* irq == vector. */
-		x |= OPENPIC_IMASK;
-		x |= OPENPIC_POLARITY_POSITIVE;
-		x |= OPENPIC_SENSE_LEVEL;
-		x |= 8 << OPENPIC_PRIORITY_SHIFT;
-		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
-	}
-
-	/* XXX IPI */
 	/* XXX set spurious intr vector */
 
 	openpic_set_priority(sc, 0);
@@ -167,7 +171,7 @@
 		openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
 	}
 
-	powerpc_register_pic(dev);
+	powerpc_register_pic(dev, sc->sc_nirq);
 
 	return (0);
 }
@@ -199,10 +203,17 @@
 	uint32_t x;
 
 	sc = device_get_softc(dev);
-	x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
-	x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
-	x |= vector;
-	openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	if (irq < sc->sc_nirq) {
+		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
+		x |= vector;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	} else {
+		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
+		x &= ~(OPENPIC_IMASK | OPENPIC_VECTOR_MASK);
+		x |= vector;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
+	}
 }
 
 void
@@ -220,7 +231,8 @@
 	struct openpic_softc *sc;
 
 	sc = device_get_softc(dev);
-	openpic_write(sc, OPENPIC_IPI_DISPATCH(0), 1u << cpu);
+	openpic_write(sc, OPENPIC_PCPU_IPI_DISPATCH(PCPU_GET(cpuid), 0),
+	    1u << cpu);
 }
 
 void
@@ -230,9 +242,15 @@
 	uint32_t x;
 
 	sc = device_get_softc(dev);
-	x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
-	x |= OPENPIC_IMASK;
-	openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	if (irq < sc->sc_nirq) {
+		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+		x |= OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	} else {
+		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
+		x |= OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
+	}
 	openpic_write(sc, OPENPIC_PCPU_EOI(PCPU_GET(cpuid)), 0);
 }
 
@@ -243,7 +261,13 @@
 	uint32_t x;
 
 	sc = device_get_softc(dev);
-	x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
-	x &= ~OPENPIC_IMASK;
-	openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	if (irq < sc->sc_nirq) {
+		x = openpic_read(sc, OPENPIC_SRC_VECTOR(irq));
+		x &= ~OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_SRC_VECTOR(irq), x);
+	} else {
+		x = openpic_read(sc, OPENPIC_IPI_VECTOR(0));
+		x &= ~OPENPIC_IMASK;
+		openpic_write(sc, OPENPIC_IPI_VECTOR(0), x);
+	}
 }



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?200712130201.lBD21eun023676>