From owner-svn-src-user@FreeBSD.ORG Thu Sep 2 16:09:47 2010 Return-Path: Delivered-To: svn-src-user@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id 21F4B10656F5; Thu, 2 Sep 2010 16:09:47 +0000 (UTC) (envelope-from nwhitehorn@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id 0FB1B8FC16; Thu, 2 Sep 2010 16:09:47 +0000 (UTC) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id o82G9ltI010464; Thu, 2 Sep 2010 16:09:47 GMT (envelope-from nwhitehorn@svn.freebsd.org) Received: (from nwhitehorn@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id o82G9kJ1010454; Thu, 2 Sep 2010 16:09:46 GMT (envelope-from nwhitehorn@svn.freebsd.org) Message-Id: <201009021609.o82G9kJ1010454@svn.freebsd.org> From: Nathan Whitehorn Date: Thu, 2 Sep 2010 16:09:46 +0000 (UTC) To: src-committers@freebsd.org, svn-src-user@freebsd.org X-SVN-Group: user MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r212151 - in user/nwhitehorn/ps3: powerpc/aim powerpc/booke powerpc/powerpc powerpc/ps3 sys X-BeenThere: svn-src-user@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: "SVN commit messages for the experimental " user" src tree" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 02 Sep 2010 16:09:47 -0000 Author: nwhitehorn Date: Thu Sep 2 16:09:46 2010 New Revision: 212151 URL: http://svn.freebsd.org/changeset/base/212151 Log: Bring up both threads on Cell in a useful way. This consists of several changes: - Provide a new method (based on the one on i386) to provide MD idle routines. These can be overridden by the hypervisor module if required. - Introduce a new mechanism to the platform KOBJ to report CPU topology. - Extend the PS3 hypervisor module to use the above. - Add IPI support to ps3pic. Modified: user/nwhitehorn/ps3/powerpc/aim/machdep.c user/nwhitehorn/ps3/powerpc/booke/machdep.c user/nwhitehorn/ps3/powerpc/powerpc/cpu.c user/nwhitehorn/ps3/powerpc/powerpc/mp_machdep.c user/nwhitehorn/ps3/powerpc/powerpc/platform.c user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c user/nwhitehorn/ps3/sys/smp.h Modified: user/nwhitehorn/ps3/powerpc/aim/machdep.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/aim/machdep.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/aim/machdep.c Thu Sep 2 16:09:46 2010 (r212151) @@ -623,52 +623,6 @@ cpu_halt(void) OF_exit(); } -void -cpu_idle(int busy) -{ - register_t msr; - uint16_t vers; - - msr = mfmsr(); - vers = mfpvr() >> 16; - -#ifdef INVARIANTS - if ((msr & PSL_EE) != PSL_EE) { - struct thread *td = curthread; - printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr); - panic("ints disabled in idleproc!"); - } -#endif - if (powerpc_pow_enabled) { - switch (vers) { - case IBM970: - case IBM970FX: - case IBM970MP: - case MPC7447A: - case MPC7448: - case MPC7450: - case MPC7455: - case MPC7457: - __asm __volatile("\ - dssall; sync; mtmsr %0; isync" - :: "r"(msr | PSL_POW)); - break; - default: - powerpc_sync(); - mtmsr(msr | PSL_POW); - isync(); - break; - } - } -} - -int -cpu_idle_wakeup(int cpu) -{ - - return (0); -} - int ptrace_set_pc(struct thread *td, unsigned long addr) { Modified: user/nwhitehorn/ps3/powerpc/booke/machdep.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/booke/machdep.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/booke/machdep.c Thu Sep 2 16:09:46 2010 (r212151) @@ -468,38 +468,6 @@ cpu_flush_dcache(void *ptr, size_t len) /* TBD */ } -/* - * cpu_idle - * - * Set Wait state enable. - */ -void -cpu_idle (int busy) -{ - register_t msr; - - msr = mfmsr(); - -#ifdef INVARIANTS - if ((msr & PSL_EE) != PSL_EE) { - struct thread *td = curthread; - printf("td msr %x\n", td->td_md.md_saved_msr); - panic("ints disabled in idleproc!"); - } -#endif - - /* Freescale E500 core RM section 6.4.1. */ - msr = msr | PSL_WE; - __asm __volatile("msync; mtmsr %0; isync" :: "r" (msr)); -} - -int -cpu_idle_wakeup(int cpu) -{ - - return (0); -} - void spinlock_enter(void) { Modified: user/nwhitehorn/ps3/powerpc/powerpc/cpu.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/powerpc/cpu.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/powerpc/cpu.c Thu Sep 2 16:09:46 2010 (r212151) @@ -64,6 +64,7 @@ #include #include #include +#include #include #include @@ -73,12 +74,15 @@ #include #include -int powerpc_pow_enabled; - static void cpu_6xx_setup(int cpuid, uint16_t vers); static void cpu_e500_setup(int cpuid, uint16_t vers); static void cpu_970_setup(int cpuid, uint16_t vers); +int powerpc_pow_enabled; +void (*cpu_idle_hook)(void) = NULL; +static void cpu_idle_60x(void); +static void cpu_idle_e500(void); + struct cputab { const char *name; uint16_t version; @@ -377,6 +381,9 @@ cpu_6xx_setup(int cpuid, uint16_t vers) } printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, bitmask); + + if (cpu_idle_hook == NULL) + cpu_idle_hook = cpu_idle_60x; } @@ -444,6 +451,9 @@ cpu_e500_setup(int cpuid, uint16_t vers) mtspr(SPR_HID0, hid0); printf("cpu%d: HID0 %b\n", cpuid, (int)hid0, HID0_E500_BITMASK); + + if (cpu_idle_hook == NULL) + cpu_idle_hook = cpu_idle_e500; } static void @@ -481,6 +491,8 @@ cpu_970_setup(int cpuid, uint16_t vers) : "=r" (hid0_hi) : "K" (SPR_HID0)); printf("cpu%d: HID0 %b\n", cpuid, (int)(hid0_hi), HID0_970_BITMASK); #endif + + cpu_idle_hook = cpu_idle_60x; } static int @@ -493,3 +505,74 @@ cpu_feature_bit(SYSCTL_HANDLER_ARGS) return (sysctl_handle_int(oidp, &result, 0, req)); } +void +cpu_idle(int busy) +{ + +#ifdef INVARIANTS + if ((mfmsr() & PSL_EE) != PSL_EE) { + struct thread *td = curthread; + printf("td msr %#lx\n", (u_long)td->td_md.md_saved_msr); + panic("ints disabled in idleproc!"); + } +#endif + + if (cpu_idle_hook != NULL) + cpu_idle_hook(); +} + +int +cpu_idle_wakeup(int cpu) +{ + return (0); +} + +static void +cpu_idle_60x(void) +{ + register_t msr; + uint16_t vers; + + if (!powerpc_pow_enabled) + return; + + msr = mfmsr(); + vers = mfpvr() >> 16; + +#ifdef AIM + switch (vers) { + case IBM970: + case IBM970FX: + case IBM970MP: + case MPC7447A: + case MPC7448: + case MPC7450: + case MPC7455: + case MPC7457: + __asm __volatile("\ + dssall; sync; mtmsr %0; isync" + :: "r"(msr | PSL_POW)); + break; + default: + powerpc_sync(); + mtmsr(msr | PSL_POW); + isync(); + break; + } +#endif +} + +static void +cpu_idle_e500(void) +{ + register_t msr; + + msr = mfmsr(); + +#ifdef E500 + /* Freescale E500 core RM section 6.4.1. */ + __asm __volatile("msync; mtmsr %0; isync" :: + "r" (msr | PSL_WE)); +#endif +} + Modified: user/nwhitehorn/ps3/powerpc/powerpc/mp_machdep.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/powerpc/mp_machdep.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/powerpc/mp_machdep.c Thu Sep 2 16:09:46 2010 (r212151) @@ -100,13 +100,6 @@ machdep_ap_bootstrap(void) sched_throw(NULL); } -struct cpu_group * -cpu_topo(void) -{ - - return (smp_topo_none()); -} - void cpu_mp_setmaxid(void) { Modified: user/nwhitehorn/ps3/powerpc/powerpc/platform.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/powerpc/platform.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/powerpc/platform.c Thu Sep 2 16:09:46 2010 (r212151) @@ -40,6 +40,7 @@ __FBSDID("$FreeBSD$"); #include #include #include +#include #include #include @@ -111,6 +112,14 @@ platform_smp_start_cpu(struct pcpu *cpu) return (PLATFORM_SMP_START_CPU(plat_obj, cpu)); } +#ifdef SMP +struct cpu_group * +cpu_topo(void) +{ + return (PLATFORM_SMP_TOPO(plat_obj)); +} +#endif + /* * Reset back to firmware. */ Modified: user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m ============================================================================== --- user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/powerpc/platform_if.m Thu Sep 2 16:09:46 2010 (r212151) @@ -30,6 +30,7 @@ #include #include #include +#include #include #include @@ -67,6 +68,14 @@ CODE { { return (ENOENT); } + static struct cpu_group *platform_null_smp_topo(platform_t plat) + { +#ifdef SMP + return (smp_topo_none()); +#else + return (NULL); +#endif + } static vm_offset_t platform_null_real_maxaddr(platform_t plat) { return (VM_MAX_ADDRESS); @@ -176,6 +185,13 @@ METHOD int smp_start_cpu { }; /** + * @brief Return SMP topology + */ +METHOD cpu_group_t smp_topo { + platform_t _plat; +} DEFAULT platform_null_smp_topo; + +/** * @brief Reset system */ METHOD void reset { Modified: user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/ps3/platform_ps3.c Thu Sep 2 16:09:46 2010 (r212151) @@ -64,11 +64,15 @@ static void ps3_mem_regions(platform_t, struct mem_region **avail, int *availsz); static vm_offset_t ps3_real_maxaddr(platform_t); static u_long ps3_timebase_freq(platform_t, struct cpuref *cpuref); +#ifdef SMP static int ps3_smp_first_cpu(platform_t, struct cpuref *cpuref); static int ps3_smp_next_cpu(platform_t, struct cpuref *cpuref); static int ps3_smp_get_bsp(platform_t, struct cpuref *cpuref); static int ps3_smp_start_cpu(platform_t, struct pcpu *cpu); +static struct cpu_group *ps3_smp_topo(platform_t); +#endif static void ps3_reset(platform_t); +static void ps3_cpu_idle(void); static platform_method_t ps3_methods[] = { PLATFORMMETHOD(platform_probe, ps3_probe), @@ -77,10 +81,13 @@ static platform_method_t ps3_methods[] = PLATFORMMETHOD(platform_real_maxaddr, ps3_real_maxaddr), PLATFORMMETHOD(platform_timebase_freq, ps3_timebase_freq), +#ifdef SMP PLATFORMMETHOD(platform_smp_first_cpu, ps3_smp_first_cpu), PLATFORMMETHOD(platform_smp_next_cpu, ps3_smp_next_cpu), PLATFORMMETHOD(platform_smp_get_bsp, ps3_smp_get_bsp), PLATFORMMETHOD(platform_smp_start_cpu, ps3_smp_start_cpu), + PLATFORMMETHOD(platform_smp_topo, ps3_smp_topo), +#endif PLATFORMMETHOD(platform_reset, ps3_reset), @@ -147,6 +154,7 @@ ps3_attach(platform_t plat) 0, 0x04 /* any address */, &avail_regions[1].mr_start, &junk); pmap_mmu_install("mmu_ps3", BUS_PROBE_SPECIFIC); + cpu_idle_hook = ps3_cpu_idle; return (0); } @@ -174,6 +182,7 @@ ps3_timebase_freq(platform_t plat, struc return (ticks); } +#ifdef SMP static int ps3_smp_first_cpu(platform_t plat, struct cpuref *cpuref) { @@ -210,7 +219,6 @@ ps3_smp_get_bsp(platform_t plat, struct static int ps3_smp_start_cpu(platform_t plat, struct pcpu *pc) { -#ifdef SMP /* loader(8) is spinning on 0x40 == 0 right now */ uint32_t *secondary_spin_sem = (uint32_t *)(0x40); int timeout; @@ -228,12 +236,15 @@ ps3_smp_start_cpu(platform_t plat, struc DELAY(100); return ((pc->pc_awake) ? 0 : EBUSY); -#else - /* No SMP support */ - return (ENXIO); -#endif } +static struct cpu_group * +ps3_smp_topo(platform_t plat) +{ + return (smp_topo_1level(CG_SHARE_L1, 2, CG_FLAG_SMT)); +} +#endif + static void ps3_reset(platform_t plat) { @@ -246,3 +257,19 @@ ps3_real_maxaddr(platform_t plat) return (avail_regions[0].mr_start + avail_regions[0].mr_size); } +static void +ps3_cpu_idle(void) +{ + static volatile int pausing = 0; + + /* + * XXX: It appears that the PS3 can livelock if both threads + * call lv1_pause(0) simultaneously. + */ + if (!atomic_cmpset_int(&pausing, 0, 1)) + return; + + lv1_pause(0); + pausing = 0; +} + Modified: user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c ============================================================================== --- user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/powerpc/ps3/ps3pic.c Thu Sep 2 16:09:46 2010 (r212151) @@ -62,6 +62,7 @@ struct ps3pic_softc { uint64_t *bitmap_thread1; uint64_t *mask_thread1; + uint64_t sc_ipi_outlet[2]; int sc_vector[64]; }; @@ -119,9 +120,6 @@ ps3pic_attach(device_t dev) uint64_t ppe; int thread; - powerpc_register_pic(dev, 64); - root_pic = dev; /* PS3s have only one PIC */ - sc = device_get_softc(dev); sc->bitmap_thread0 = contigmalloc(128 /* 512 bits * 2 */, M_PS3PIC, @@ -138,8 +136,19 @@ ps3pic_attach(device_t dev) #ifdef SMP lv1_configure_irq_state_bitmap(ppe, !thread, vtophys(sc->bitmap_thread1)); + + /* Map both IPIs to the same VIRQ to avoid changes in intr_machdep */ + lv1_construct_event_receive_port(&sc->sc_ipi_outlet[0]); + lv1_connect_irq_plug_ext(ppe, thread, sc->sc_ipi_outlet[0], + sc->sc_ipi_outlet[0], 0); + lv1_construct_event_receive_port(&sc->sc_ipi_outlet[1]); + lv1_connect_irq_plug_ext(ppe, !thread, sc->sc_ipi_outlet[0], + sc->sc_ipi_outlet[1], 0); #endif + powerpc_register_pic(dev, sc->sc_ipi_outlet[0]); + root_pic = dev; /* PS3s have only one PIC */ + return (0); } @@ -175,9 +184,6 @@ ps3pic_enable(device_t dev, u_int irq, u { struct ps3pic_softc *sc; - if (irq > 63) /* IPI */ - return; - sc = device_get_softc(dev); sc->sc_vector[irq] = vector; @@ -197,8 +203,12 @@ ps3pic_eoi(device_t dev, u_int irq) } static void -ps3pic_ipi(device_t dev, u_int irq) +ps3pic_ipi(device_t dev, u_int cpu) { + struct ps3pic_softc *sc; + sc = device_get_softc(dev); + + lv1_send_event_locally(sc->sc_ipi_outlet[cpu]); } static void @@ -208,6 +218,11 @@ ps3pic_mask(device_t dev, u_int irq) uint64_t ppe; sc = device_get_softc(dev); + + /* Do not mask IPIs! */ + if (irq == sc->sc_ipi_outlet[0]) + return; + sc->mask_thread0[0] &= ~(1UL << (63 - irq)); sc->mask_thread1[0] &= ~(1UL << (63 - irq)); Modified: user/nwhitehorn/ps3/sys/smp.h ============================================================================== --- user/nwhitehorn/ps3/sys/smp.h Thu Sep 2 16:09:09 2010 (r212150) +++ user/nwhitehorn/ps3/sys/smp.h Thu Sep 2 16:09:46 2010 (r212151) @@ -16,8 +16,6 @@ #ifndef LOCORE -#ifdef SMP - /* * Topology of a NUMA or HTT system. * @@ -41,6 +39,8 @@ struct cpu_group { int8_t cg_flags; /* Traversal modifiers. */ }; +typedef struct cpu_group *cpu_group_t; + /* * Defines common resources for CPUs in the group. The highest level * resource should be used when multiple are shared. @@ -60,6 +60,7 @@ struct cpu_group { /* * Convenience routines for building topologies. */ +#ifdef SMP struct cpu_group *smp_topo(void); struct cpu_group *smp_topo_none(void); struct cpu_group *smp_topo_1level(int l1share, int l1count, int l1flags);