svn commit: r212151 - in user/nwhitehorn/ps3: powerpc/aim
powerpc/booke powerpc/powerpc powerpc/ps3 sys
Nathan Whitehorn
nwhitehorn at FreeBSD.org
Thu Sep 2 16:09:47 UTC 2010
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 <sys/conf.h>
#include <sys/cpu.h>
#include <sys/kernel.h>
+#include <sys/proc.h>
#include <sys/sysctl.h>
#include <machine/bus.h>
@@ -73,12 +74,15 @@
#include <machine/smp.h>
#include <machine/spr.h>
-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 <sys/ktr.h>
#include <sys/mutex.h>
#include <sys/systm.h>
+#include <sys/smp.h>
#include <sys/sysctl.h>
#include <sys/types.h>
@@ -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 <sys/lock.h>
#include <sys/mutex.h>
#include <sys/systm.h>
+#include <sys/smp.h>
#include <machine/platform.h>
#include <machine/platformvar.h>
@@ -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);
More information about the svn-src-user
mailing list