From owner-p4-projects@FreeBSD.ORG Thu Jun 13 22:17:50 2013 Return-Path: Delivered-To: p4-projects@freebsd.org Received: by hub.freebsd.org (Postfix, from userid 32767) id ABBB6CC6; Thu, 13 Jun 2013 22:17:50 +0000 (UTC) Delivered-To: perforce@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by hub.freebsd.org (Postfix) with ESMTP id 6D378CC4 for ; Thu, 13 Jun 2013 22:17:50 +0000 (UTC) (envelope-from brooks@freebsd.org) Received: from skunkworks.freebsd.org (skunkworks6.freebsd.org [IPv6:2001:1900:2254:2068::682:0]) by mx1.freebsd.org (Postfix) with ESMTP id 4ED8C171C for ; Thu, 13 Jun 2013 22:17:50 +0000 (UTC) Received: from skunkworks.freebsd.org ([127.0.1.74]) by skunkworks.freebsd.org (8.14.7/8.14.7) with ESMTP id r5DMHonN071993 for ; Thu, 13 Jun 2013 22:17:50 GMT (envelope-from brooks@freebsd.org) Received: (from perforce@localhost) by skunkworks.freebsd.org (8.14.7/8.14.6/Submit) id r5DMHosV071990 for perforce@freebsd.org; Thu, 13 Jun 2013 22:17:50 GMT (envelope-from brooks@freebsd.org) Date: Thu, 13 Jun 2013 22:17:50 GMT Message-Id: <201306132217.r5DMHosV071990@skunkworks.freebsd.org> X-Authentication-Warning: skunkworks.freebsd.org: perforce set sender to brooks@freebsd.org using -f From: Brooks Davis Subject: PERFORCE change 229692 for review To: Perforce Change Reviews Precedence: bulk X-BeenThere: p4-projects@freebsd.org X-Mailman-Version: 2.1.14 List-Id: p4 projects tree changes List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 13 Jun 2013 22:17:50 -0000 http://p4web.freebsd.org/@@229692?ac=10 Change 229692 by brooks@brooks_zenith on 2013/06/13 22:17:45 Checkpoint a compiling, but untested SMP implementation for BERI. In principle, the included kernel config will only find one CPU in the FDT and will boot with that. Affected files ... .. //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_ic_if.m#3 edit .. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_asm.S#2 edit .. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_mp.c#2 edit .. //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_pic.c#5 edit .. //depot/projects/ctsrd/beribsd/src/sys/mips/conf/BERI_SIM_SMP_MDROOT#1 add Differences ... ==== //depot/projects/ctsrd/beribsd/src/sys/dev/fdt/fdt_ic_if.m#3 (text+ko) ==== @@ -225,3 +225,42 @@ device_t _child; u_int _irq; }; + +/** + * @brief Enable an IPI source. + * + * @param _dev the interrupt controller + * @param _tid the thread ID (relative to the interrupt controller) + * to enable IPIs for + * @param _ipi_irq hardware IRQ to send IPIs to + */ +METHOD void setup_ipi { + device_t _dev; + u_int _tid; + u_int _irq; +}; + +/** + * @brief Send an IPI to the specified thread. + * + * @param _dev the interrupt controller + * @param _tid the thread ID (relative to the interrupt controller) + * to send IPIs to + */ +METHOD void send_ipi { + device_t _dev; + u_int _tid; +}; + +/** + * @brief Clear the IPI on the specfied thread. Only call with the + * local hardware thread or interrupts may be lost! + * + * @param _dev the interrupt controller + * @param _tid the thread ID (relative to the interrupt controller) + * to clear the IPI on + */ +METHOD void clear_ipi { + device_t _dev; + u_int _tid; +}; ==== //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_asm.S#2 (text+ko) ==== @@ -32,10 +32,11 @@ #include #ifdef SMP +/* XXXBED: Correct for multithread, needs adjustment for multicore. */ LEAF(platform_processor_id) MFC0 v0, MIPS_COP_0_PRID - srl v0, v0, 25 + srl v0, v0, 24 jr ra - and v0, v0, 7 + and v0, v0, 255 END(platform_processor_id) #endif ==== //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_mp.c#2 (text+ko) ==== @@ -36,40 +36,84 @@ #include #include +#include + +#include +#include "fdt_ic_if.h" -/* - * XXXRW: - * - * 1. It would be nice if we could read the number of hardware threads present - * on the current CPU core from a CP0 register (or similar). - */ +struct spin_entry { + uint64_t entry_addr; + uint64_t a0; + uint32_t rsvd1; + uint32_t pir; + uint64_t rsvd2; +}; -#define BERI_NUMTHREADS 8 +static phandle_t cpu_of_nodes[MAXCPU]; +static device_t picmap[MAXCPU]; void platform_cpu_mask(cpuset_t *mask) { - u_int i; + phandle_t cpus, cpu; + pcell_t reg; + + if ((cpus = OF_finddevice("/cpus")) <= 0) { + printf("%s: no \"/cpus\" device found in FDT\n", __func__); + goto error; + } + if ((cpu = OF_child(cpus)) <= 0) { + printf("%s: no children of \"/cpus\" found in FDT\n", __func__); + goto error; + } + CPU_ZERO(mask); + do { + if (OF_getprop(cpu, "reg", ®, sizeof(reg)) <= 0) { + printf("%s: cpu device with no reg property\n", + __func__); + goto error; + } + if (reg > MAXCPU) { + printf("%s: cpu ID too large (%d > %d)\n", __func__, + reg, MAXCPU); + } + cpu_of_nodes[reg] = cpu; + + CPU_SET(reg, mask); + } while ((cpu = OF_peer(cpu)) > 0); + return; +error: + /* + * If we run into any problems determining the CPU layout, + * fall back to UP. + * + * XXX: panic instead? + */ CPU_ZERO(mask); - for (i = 0; i < BERI_NUMTHREADS; i++) - CPU_SET(i, mask); + CPU_SET(1, mask); } void platform_ipi_send(int cpuid) { - panic("%s: not yet", __func__); + /* XXX: single core/pic */ + FDT_IC_SEND_IPI(picmap[cpuid], cpuid); } void platform_ipi_clear(void) { + int cpuid = platform_processor_id(); - panic("%s: not yet", __func__); + /* XXX: single core/pic */ + FDT_IC_CLEAR_IPI(picmap[cpuid], cpuid); } +/* + * XXXBED: Set via FDT? + */ int platform_ipi_intrnum(void) { @@ -77,6 +121,9 @@ return (4); } +/* + * XXXBED: Fine for MT, will need something better for multi-core. + */ struct cpu_group * platform_smp_topo(void) { @@ -88,8 +135,9 @@ platform_init_ap(int cpuid) { u_int clock_int_mask; + device_t ic; - KASSERT(cpuid != 0, ("%s: invalid CPU id %d", __func__, cpuid)); + KASSERT(cpuid < MAXCPU, ("%s: invalid CPU id %d", __func__, cpuid)); /* * Enable per-thread timer. @@ -97,18 +145,54 @@ clock_int_mask = hard_int_mask(5); set_intr_mask(clock_int_mask); -#ifdef NOTYET /* * Enable IPIs. */ - * XXXRW: Not yet. - */ -#endif + /* XXX: single core/pic */ + ic = SLIST_FIRST(&fdt_ic_list_head)->dev; + FDT_IC_SETUP_IPI(ic, cpuid, platform_ipi_intrnum()); + picmap[cpuid] = ic; } +/* + * BERI startup conforms to the spin-table start method defined in the + * ePAPR 1.0 spec. The initial spin waiting for an address is started + * by the CPU firmware. + */ int platform_start_ap(int cpuid) { + phandle_t cpu; + char prop[16]; + struct spin_entry *se; - panic("%s: not yet", __func__); + KASSERT(cpuid != 0, ("%s: can't start CPU 0!\n", __func__)); + KASSERT((cpuid > 0 && cpuid < MAXCPU), + ("%s: invalid CPU id %d", __func__, cpuid)); + + cpu = cpu_of_nodes[cpuid]; + if (OF_getprop(cpu, "status", &prop, sizeof(prop)) <= 0 && + OF_getprop(OF_parent(cpu), "status", &prop, sizeof(prop))) + panic("%s: CPU %d has no status property", __func__, cpuid); + else + if (strcmp("disabled", prop) != 0) + panic("%s: CPU %d status is '%s' not 'disabled'", + __func__, cpuid, prop); + + if (OF_getprop(cpu, "enable-method", &prop, sizeof(prop)) <= 0 && + OF_getprop(OF_parent(cpu), "enable-method", &prop, sizeof(prop))) + panic("%s: CPU %d has no enable-method property", __func__, + cpuid); + else + if (strcmp("spin-table", prop) != 0) + panic("%s: CPU %d enable-method is '%s' not " + "'spin-table'", __func__, cpuid, prop); + + if (OF_getprop(cpu, "cpu-release-addr", &se, sizeof(se)) <= 0) + panic("%s: CPU %d has missing or invalid cpu-release-addr", + __func__, cpuid); + se->pir = cpuid; + se->entry_addr = (intptr_t)mpentry; + + return (0); } ==== //depot/projects/ctsrd/beribsd/src/sys/mips/beri/beri_pic.c#5 (text+ko) ==== @@ -79,6 +79,7 @@ static void beripic_intr(void *); #define BP_MAX_HARD_IRQS 6 +#define BP_FIRST_SOFT 64 struct beripic_softc { device_t bp_dev; @@ -127,7 +128,6 @@ #ifdef __mips__ mips_intrcnt_t counter; #endif - /* XXX counter */ }; struct beripic_cookie { @@ -381,6 +381,9 @@ sc->bp_nhard = nhard; sc->bp_nsoft = nsoft; sc->bp_nsrcs = sc->bp_nhard + sc->bp_nsoft; + /* XXX: should deal with gap between hard and soft */ + KASSERT(sc->bp_nhard < BP_FIRST_SOFT, + ("too many hard sources")); KASSERT(rman_get_size(sc->bp_cfg_res) / 8 == sc->bp_nsrcs, ("config space size does not match sources")); KASSERT(sc->bp_nhard % 64 == 0, @@ -627,6 +630,45 @@ bpic->intr(bpic->arg); } +#ifdef SMP +static void +beripic_setup_ipi(device_t ic, u_int tid, u_int ipi_irq) +{ + + bp_config_source(ic, BP_FIRST_SOFT + tid, 1, tid, ipi_irq); +} + +static void +beripic_send_ipi(device_t ic, u_int tid) +{ + struct beripic_softc *sc; + uint64_t bit; + + sc = device_get_softc(ic); + + KASSERT(tid < sc->bp_nsoft, ("tid (%d) to large\n")); + + bit = 1ULL << (tid % 64); + bus_space_write_8(sc->bp_set_bst, sc->bp_set_bsh, + BP_FIRST_SOFT / 8 + (tid >> 6), bit); +} + +static void +beripic_clear_ipi(device_t ic, u_int tid) +{ + struct beripic_softc *sc; + uint64_t bit; + + sc = device_get_softc(ic); + + KASSERT(tid < sc->bp_nsoft, ("tid (%d) to large\n")); + + bit = 1ULL << (tid % 64); + bus_space_write_8(sc->bp_clear_bst, sc->bp_clear_bsh, + BP_FIRST_SOFT / 8 + (tid >> 6), bit); +} +#endif + devclass_t beripic_devclass; static device_method_t beripic_fdt_methods[] = { @@ -642,6 +684,12 @@ DEVMETHOD(fdt_ic_setup_intr, beripic_setup_intr), DEVMETHOD(fdt_ic_teardown_intr, beripic_teardown_intr), +#ifdef SMP + DEVMETHOD(fdt_ic_setup_ipi, beripic_setup_ipi), + DEVMETHOD(fdt_ic_clear_ipi, beripic_clear_ipi), + DEVMETHOD(fdt_ic_send_ipi, beripic_send_ipi), +#endif + { 0, 0 }, };