From owner-p4-projects@FreeBSD.ORG Thu Dec 13 02:01:41 2007 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id BDD0116A41B; Thu, 13 Dec 2007 02:01:41 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 4762A16A417 for ; Thu, 13 Dec 2007 02:01:41 +0000 (UTC) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (repoman.freebsd.org [IPv6:2001:4f8:fff6::29]) by mx1.freebsd.org (Postfix) with ESMTP id 3CE9713C4E1 for ; Thu, 13 Dec 2007 02:01:41 +0000 (UTC) (envelope-from marcel@freebsd.org) Received: from repoman.freebsd.org (localhost [127.0.0.1]) by repoman.freebsd.org (8.14.1/8.14.1) with ESMTP id lBD21e6l023679 for ; Thu, 13 Dec 2007 02:01:41 GMT (envelope-from marcel@freebsd.org) Received: (from perforce@localhost) by repoman.freebsd.org (8.14.1/8.14.1/Submit) id lBD21eun023676 for perforce@freebsd.org; Thu, 13 Dec 2007 02:01:40 GMT (envelope-from marcel@freebsd.org) Date: Thu, 13 Dec 2007 02:01:40 GMT Message-Id: <200712130201.lBD21eun023676@repoman.freebsd.org> X-Authentication-Warning: repoman.freebsd.org: perforce set sender to marcel@freebsd.org using -f From: Marcel Moolenaar To: Perforce Change Reviews Cc: Subject: PERFORCE change 130780 for review X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Dec 2007 02:01:42 -0000 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 #include #include +#include #include #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 #include +#include #include #include @@ -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); + } }