PERFORCE change 130780 for review
Marcel Moolenaar
marcel at FreeBSD.org
Wed Dec 12 18:01:42 PST 2007
http://perforce.freebsd.org/chv.cgi?CH=130780
Change 130780 by marcel at 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);
+ }
}
More information about the p4-projects
mailing list