Page Menu
Home
FreeBSD
Search
Configure Global Search
Log In
Files
F175448742
D14011.id38299.diff
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
16 KB
Referenced Files
None
Subscribers
None
D14011.id38299.diff
View Options
Index: sys/powerpc/powernv/platform_powernv.c
===================================================================
--- sys/powerpc/powernv/platform_powernv.c
+++ sys/powerpc/powernv/platform_powernv.c
@@ -1,5 +1,6 @@
/*-
* Copyright (c) 2015 Nathan Whitehorn
+ * Copyright (c) 2017-2018 Semihalf
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -73,6 +74,7 @@
#endif
static void powernv_reset(platform_t);
static void powernv_cpu_idle(sbintime_t sbt);
+static int powernv_cpuref_init(void);
static platform_method_t powernv_methods[] = {
PLATFORMMETHOD(platform_probe, powernv_probe),
@@ -100,9 +102,13 @@
0
};
+static struct cpuref platform_cpuref[MAXCPU];
+static int platform_cpuref_cnt;
+static int platform_cpuref_valid;
+
PLATFORM_DEF(powernv_platform);
-static int powernv_boot_pir;
+static uint64_t powernv_boot_pir;
static int
powernv_probe(platform_t plat)
@@ -126,12 +132,20 @@
/* Ping OPAL again just to make sure */
opal_check();
+#if BYTE_ORDER == LITTLE_ENDIAN
+ opal_call(OPAL_REINIT_CPUS, 2 /* Little endian */);
+#else
+ opal_call(OPAL_REINIT_CPUS, 1 /* Big endian */);
+#endif
+
cpu_idle_hook = powernv_cpu_idle;
powernv_boot_pir = mfspr(SPR_PIR);
/* Init CPU bits */
powernv_smp_ap_init(plat);
+ powernv_cpuref_init();
+
/* Set SLB count from device tree */
cpu = OF_peer(0);
cpu = OF_child(cpu);
@@ -218,29 +232,13 @@
static u_long
powernv_timebase_freq(platform_t plat, struct cpuref *cpuref)
-{
- phandle_t phandle;
- int32_t ticks = -1;
-
- phandle = cpuref->cr_hwref;
-
- OF_getencprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
-
- if (ticks <= 0)
- panic("Unable to determine timebase frequency!");
-
- return (ticks);
-}
-
-static int
-powernv_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
{
char buf[8];
phandle_t cpu, dev, root;
- int res, cpuid;
+ int res;
+ int32_t ticks = -1;
root = OF_peer(0);
-
dev = OF_child(root);
while (dev != 0) {
res = OF_getprop(dev, "name", buf, sizeof(buf));
@@ -248,118 +246,127 @@
break;
dev = OF_peer(dev);
}
- if (dev == 0) {
- /*
- * psim doesn't have a name property on the /cpus node,
- * but it can be found directly
- */
- dev = OF_finddevice("/cpus");
- if (dev == 0)
- return (ENOENT);
- }
-
- cpu = OF_child(dev);
- while (cpu != 0) {
+ for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
if (res > 0 && strcmp(buf, "cpu") == 0)
break;
- cpu = OF_peer(cpu);
}
if (cpu == 0)
- return (ENOENT);
+ return (512000000);
- cpuref->cr_hwref = cpu;
- res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
- sizeof(cpuid));
- if (res <= 0)
- res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
- if (res <= 0)
- cpuid = 0;
- cpuref->cr_cpuid = cpuid;
+ OF_getencprop(cpu, "timebase-frequency", &ticks, sizeof(ticks));
+
+ if (ticks <= 0)
+ panic("Unable to determine timebase frequency!");
+
+ return (ticks);
- return (0);
}
static int
-powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+powernv_cpuref_init(void)
{
- char buf[8];
- phandle_t cpu;
- int i, res, cpuid;
-
- /* Check for whether it should be the next thread */
- res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s");
- if (res > 0) {
- cell_t interrupt_servers[res/sizeof(cell_t)];
- OF_getencprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
- interrupt_servers, res);
- for (i = 0; i < res/sizeof(cell_t) - 1; i++) {
- if (interrupt_servers[i] == cpuref->cr_cpuid) {
- cpuref->cr_cpuid = interrupt_servers[i+1];
- return (0);
+ phandle_t cpu, dev;
+ char buf[32];
+ int a, res, tmp_cpuref_cnt;
+ static struct cpuref tmp_cpuref[MAXCPU];
+ cell_t interrupt_servers[32];
+ uint64_t bsp;
+
+ if (platform_cpuref_valid)
+ return (0);
+
+ dev = OF_peer(0);
+ dev = OF_child(dev);
+ while (dev != 0) {
+ res = OF_getprop(dev, "name", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpus") == 0)
+ break;
+ dev = OF_peer(dev);
+ }
+
+ bsp = 0;
+ tmp_cpuref_cnt = 0;
+ for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
+ res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpu") == 0) {
+ res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
+ if (res > 0) {
+
+
+ OF_getencprop(cpu, "ibm,ppc-interrupt-server#s",
+ interrupt_servers, res);
+
+ for (a = 0; a < res/sizeof(cell_t); a++) {
+ tmp_cpuref[tmp_cpuref_cnt].cr_hwref = interrupt_servers[a];
+ tmp_cpuref[tmp_cpuref_cnt].cr_cpuid = tmp_cpuref_cnt;
+
+ if (interrupt_servers[a] == (uint32_t)powernv_boot_pir)
+ bsp = tmp_cpuref_cnt;
+
+ tmp_cpuref_cnt++;
+ }
}
}
}
- /* Next CPU core/package */
- cpu = OF_peer(cpuref->cr_hwref);
- while (cpu != 0) {
- res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
- if (res > 0 && strcmp(buf, "cpu") == 0)
- break;
- cpu = OF_peer(cpu);
+ /* Map IDs, so BSP has CPUID 0 regardless of hwref */
+ for (a = bsp; a < tmp_cpuref_cnt; a++) {
+ platform_cpuref[platform_cpuref_cnt].cr_hwref = tmp_cpuref[a].cr_hwref;
+ platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt;
+ platform_cpuref_cnt++;
+ }
+ for (a = 0; a < bsp; a++) {
+ platform_cpuref[platform_cpuref_cnt].cr_hwref = tmp_cpuref[a].cr_hwref;
+ platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt;
+ platform_cpuref_cnt++;
}
- if (cpu == 0)
- return (ENOENT);
- cpuref->cr_hwref = cpu;
- res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
- sizeof(cpuid));
- if (res <= 0)
- res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
- if (res <= 0)
- cpuid = 0;
- cpuref->cr_cpuid = cpuid;
+ platform_cpuref_valid = 1;
return (0);
}
static int
-powernv_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+powernv_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
{
- phandle_t chosen;
- int cpuid, res;
- struct cpuref i;
+ if (platform_cpuref_valid == 0)
+ return (EINVAL);
- chosen = OF_finddevice("/chosen");
- if (chosen == 0)
- return (ENOENT);
+ cpuref->cr_cpuid = 0;
+ cpuref->cr_hwref = platform_cpuref[0].cr_hwref;
- res = OF_getencprop(chosen, "fdtbootcpu", &cpuid, sizeof(cpuid));
- if (res < 0)
- return (ENOENT);
+ return (0);
+}
- /* XXX: FDT from kexec lies sometimes. PIR seems not to. */
- if (cpuid == 0)
- cpuid = powernv_boot_pir;
+static int
+powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+ int id;
- cpuref->cr_cpuid = cpuid;
+ if (platform_cpuref_valid == 0)
+ return (EINVAL);
- if (powernv_smp_first_cpu(plat, &i) != 0)
+ id = cpuref->cr_cpuid + 1;
+ if (id >= platform_cpuref_cnt)
return (ENOENT);
- cpuref->cr_hwref = i.cr_hwref;
- do {
- if (i.cr_cpuid == cpuid) {
- cpuref->cr_hwref = i.cr_hwref;
- break;
- }
- } while (powernv_smp_next_cpu(plat, &i) == 0);
+ cpuref->cr_cpuid = platform_cpuref[id].cr_cpuid;
+ cpuref->cr_hwref = platform_cpuref[id].cr_hwref;
return (0);
}
+static int
+powernv_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+
+ cpuref->cr_cpuid = platform_cpuref[0].cr_cpuid;
+ cpuref->cr_hwref = platform_cpuref[0].cr_hwref;
+ return (0);
+}
+
#ifdef SMP
static int
powernv_smp_start_cpu(platform_t plat, struct pcpu *pc)
@@ -369,10 +376,10 @@
ap_pcpu = pc;
powerpc_sync();
- result = opal_call(OPAL_START_CPU, pc->pc_cpuid, EXC_RST);
+ result = opal_call(OPAL_START_CPU, pc->pc_hwref, EXC_RST);
if (result != OPAL_SUCCESS) {
printf("OPAL error (%d): unable to start AP %d\n",
- result, pc->pc_cpuid);
+ result, (int)pc->pc_hwref);
return (ENXIO);
}
@@ -382,37 +389,49 @@
static struct cpu_group *
powernv_smp_topo(platform_t plat)
{
- struct pcpu *pc, *last_pc;
- int i, ncores, ncpus;
-
- ncores = ncpus = 0;
- last_pc = NULL;
- CPU_FOREACH(i) {
- pc = pcpu_find(i);
- if (pc == NULL)
+ char buf[8];
+ phandle_t cpu, dev, root;
+ int res, nthreads;
+
+ root = OF_peer(0);
+
+ dev = OF_child(root);
+ while (dev != 0) {
+ res = OF_getprop(dev, "name", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpus") == 0)
+ break;
+ dev = OF_peer(dev);
+ }
+
+ nthreads = 1;
+ for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
+ res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+ if (res <= 0 || strcmp(buf, "cpu") != 0)
continue;
- if (last_pc == NULL || pc->pc_hwref != last_pc->pc_hwref)
- ncores++;
- last_pc = pc;
- ncpus++;
+
+ res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
+
+ if (res >= 0)
+ nthreads = res / sizeof(cell_t);
+ else
+ nthreads = 1;
+ break;
}
- if (ncpus % ncores != 0) {
+ if (mp_ncpus % nthreads != 0) {
printf("WARNING: Irregular SMP topology. Performance may be "
- "suboptimal (%d CPUS, %d cores)\n", ncpus, ncores);
+ "suboptimal (%d threads, %d on first core)\n",
+ mp_ncpus, nthreads);
return (smp_topo_none());
}
/* Don't do anything fancier for non-threaded SMP */
- if (ncpus == ncores)
+ if (nthreads == 1)
return (smp_topo_none());
-#ifdef NOTYET /* smp_topo_1level() fails with non-consecutive CPU IDs */
- return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT));
-#else
- return (smp_topo_none());
-#endif
+ return (smp_topo_1level(CG_SHARE_L1, nthreads, CG_FLAG_SMT));
}
+
#endif
static void
Index: sys/powerpc/pseries/platform_chrp.c
===================================================================
--- sys/powerpc/pseries/platform_chrp.c
+++ sys/powerpc/pseries/platform_chrp.c
@@ -75,6 +75,7 @@
static int chrp_smp_next_cpu(platform_t, struct cpuref *cpuref);
static int chrp_smp_get_bsp(platform_t, struct cpuref *cpuref);
static void chrp_smp_ap_init(platform_t);
+static int chrp_cpuref_init(void);
#ifdef SMP
static int chrp_smp_start_cpu(platform_t, struct pcpu *cpu);
static struct cpu_group *chrp_smp_topo(platform_t plat);
@@ -85,6 +86,10 @@
static void phyp_cpu_idle(sbintime_t sbt);
#endif
+static struct cpuref platform_cpuref[MAXCPU];
+static int platform_cpuref_cnt;
+static int platform_cpuref_valid;
+
static platform_method_t chrp_methods[] = {
PLATFORMMETHOD(platform_probe, chrp_probe),
PLATFORMMETHOD(platform_attach, chrp_attach),
@@ -159,6 +164,7 @@
chrp_smp_ap_init(plat);
}
#endif
+ chrp_cpuref_init();
/* Some systems (e.g. QEMU) need Open Firmware to stand down */
ofw_quiesce();
@@ -295,48 +301,12 @@
static int
chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
{
- char buf[8];
- phandle_t cpu, dev, root;
- int res, cpuid;
-
- root = OF_peer(0);
- dev = OF_child(root);
- while (dev != 0) {
- res = OF_getprop(dev, "name", buf, sizeof(buf));
- if (res > 0 && strcmp(buf, "cpus") == 0)
- break;
- dev = OF_peer(dev);
- }
- if (dev == 0) {
- /*
- * psim doesn't have a name property on the /cpus node,
- * but it can be found directly
- */
- dev = OF_finddevice("/cpus");
- if (dev == 0)
- return (ENOENT);
- }
+ if (platform_cpuref_valid == 0)
+ return (EINVAL);
- cpu = OF_child(dev);
-
- while (cpu != 0) {
- res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
- if (res > 0 && strcmp(buf, "cpu") == 0)
- break;
- cpu = OF_peer(cpu);
- }
- if (cpu == 0)
- return (ENOENT);
-
- cpuref->cr_hwref = cpu;
- res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
- sizeof(cpuid));
- if (res <= 0)
- res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
- if (res <= 0)
- cpuid = 0;
- cpuref->cr_cpuid = cpuid;
+ cpuref->cr_cpuid = 0;
+ cpuref->cr_hwref = platform_cpuref[0].cr_hwref;
return (0);
}
@@ -344,43 +314,17 @@
static int
chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
{
- char buf[8];
- phandle_t cpu;
- int i, res, cpuid;
-
- /* Check for whether it should be the next thread */
- res = OF_getproplen(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s");
- if (res > 0) {
- cell_t interrupt_servers[res/sizeof(cell_t)];
- OF_getencprop(cpuref->cr_hwref, "ibm,ppc-interrupt-server#s",
- interrupt_servers, res);
- for (i = 0; i < res/sizeof(cell_t) - 1; i++) {
- if (interrupt_servers[i] == cpuref->cr_cpuid) {
- cpuref->cr_cpuid = interrupt_servers[i+1];
- return (0);
- }
- }
- }
+ int id;
- /* Next CPU core/package */
- cpu = OF_peer(cpuref->cr_hwref);
- while (cpu != 0) {
- res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
- if (res > 0 && strcmp(buf, "cpu") == 0)
- break;
- cpu = OF_peer(cpu);
- }
- if (cpu == 0)
+ if (platform_cpuref_valid == 0)
+ return (EINVAL);
+
+ id = cpuref->cr_cpuid + 1;
+ if (id >= platform_cpuref_cnt)
return (ENOENT);
- cpuref->cr_hwref = cpu;
- res = OF_getencprop(cpu, "ibm,ppc-interrupt-server#s", &cpuid,
- sizeof(cpuid));
- if (res <= 0)
- res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
- if (res <= 0)
- cpuid = 0;
- cpuref->cr_cpuid = cpuid;
+ cpuref->cr_cpuid = platform_cpuref[id].cr_cpuid;
+ cpuref->cr_hwref = platform_cpuref[id].cr_hwref;
return (0);
}
@@ -388,33 +332,60 @@
static int
chrp_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
{
- ihandle_t inst;
- phandle_t bsp, chosen;
- int res, cpuid;
- chosen = OF_finddevice("/chosen");
- if (chosen == 0)
- return (ENXIO);
+ cpuref->cr_cpuid = platform_cpuref[0].cr_cpuid;
+ cpuref->cr_hwref = platform_cpuref[0].cr_hwref;
+ return (0);
+}
- res = OF_getencprop(chosen, "cpu", &inst, sizeof(inst));
- if (res < 0)
- return (ENXIO);
+static int
+chrp_cpuref_init(void)
+{
+ phandle_t cpu, dev;
+ char buf[32];
+ int a, res;
+ cell_t interrupt_servers[32];
+ uint64_t bsp;
- bsp = OF_instance_to_package(inst);
+ if (platform_cpuref_valid)
+ return (0);
- /* Pick the primary thread. Can it be any other? */
- cpuref->cr_hwref = bsp;
- res = OF_getencprop(bsp, "ibm,ppc-interrupt-server#s", &cpuid,
- sizeof(cpuid));
- if (res <= 0)
- res = OF_getencprop(bsp, "reg", &cpuid, sizeof(cpuid));
- if (res <= 0)
- cpuid = 0;
- cpuref->cr_cpuid = cpuid;
+ dev = OF_peer(0);
+ dev = OF_child(dev);
+ while (dev != 0) {
+ res = OF_getprop(dev, "name", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpus") == 0)
+ break;
+ dev = OF_peer(dev);
+ }
+
+ bsp = 0;
+ for (cpu = OF_child(dev); cpu != 0; cpu = OF_peer(cpu)) {
+ res = OF_getprop(cpu, "device_type", buf, sizeof(buf));
+ if (res > 0 && strcmp(buf, "cpu") == 0) {
+ res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
+ if (res > 0) {
+
+
+ OF_getencprop(cpu, "ibm,ppc-interrupt-server#s",
+ interrupt_servers, res);
+
+ for (a = 0; a < res/sizeof(cell_t); a++) {
+ platform_cpuref[platform_cpuref_cnt].cr_hwref = interrupt_servers[a];
+ platform_cpuref[platform_cpuref_cnt].cr_cpuid = platform_cpuref_cnt;
+
+ platform_cpuref_cnt++;
+ }
+ }
+ }
+ }
+
+ platform_cpuref_valid = 1;
return (0);
}
+
#ifdef SMP
static int
chrp_smp_start_cpu(platform_t plat, struct pcpu *pc)
@@ -438,7 +409,7 @@
ap_pcpu = pc;
powerpc_sync();
- result = rtas_call_method(start_cpu, 3, 1, pc->pc_cpuid, EXC_RST, pc,
+ result = rtas_call_method(start_cpu, 3, 1, pc->pc_hwref, EXC_RST, pc,
&err);
if (result < 0 || err != 0) {
printf("RTAS error (%d/%d): unable to start AP %d\n",
@@ -514,8 +485,8 @@
{
if (!(mfmsr() & PSL_HV)) {
/* Register VPA */
- phyp_hcall(H_REGISTER_VPA, 1UL, PCPU_GET(cpuid),
- splpar_vpa[PCPU_GET(cpuid)]);
+ phyp_hcall(H_REGISTER_VPA, 1UL, PCPU_GET(hwref),
+ splpar_vpa[PCPU_GET(hwref)]);
/* Set interrupt priority */
phyp_hcall(H_CPPR, 0xff);
Index: sys/powerpc/pseries/xics.c
===================================================================
--- sys/powerpc/pseries/xics.c
+++ sys/powerpc/pseries/xics.c
@@ -263,6 +263,10 @@
cell_t status, cpu;
int ncpus, i, error;
+ /* Ignore IPIs */
+ if (irq == MAX_XICP_IRQS)
+ return;
+
/*
* This doesn't appear to actually support affinity groups, so pick a
* random CPU.
@@ -281,6 +285,8 @@
ncpus++;
}
+ cpu = pcpu_find(cpu)->pc_hwref;
+
/* XXX: super inefficient */
for (i = 0; i < sc->nintvecs; i++) {
if (sc->intvecs[i].irq == irq) {
@@ -312,9 +318,9 @@
#ifdef POWERNV
if (mfmsr() & PSL_HV) {
- regs = xicp_mem_for_cpu(PCPU_GET(cpuid));
+ regs = xicp_mem_for_cpu(PCPU_GET(hwref));
KASSERT(regs != NULL,
- ("Can't find regs for CPU %d", PCPU_GET(cpuid)));
+ ("Can't find regs for CPU %ld", (uintptr_t)PCPU_GET(hwref)));
}
#endif
@@ -343,7 +349,7 @@
if (regs)
bus_write_1(regs, 12, 0xff);
else
- phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(cpuid)),
+ phyp_hcall(H_IPI, (uint64_t)(PCPU_GET(hwref)),
0xff);
}
@@ -370,7 +376,7 @@
("Too many XICP interrupts"));
/* Bind to this CPU to start: distrib. ID is last entry in gserver# */
- cpu = PCPU_GET(cpuid);
+ cpu = PCPU_GET(hwref);
mtx_lock(&sc->sc_mtx);
sc->intvecs[sc->nintvecs].irq = irq;
@@ -411,7 +417,7 @@
#ifdef POWERNV
if (mfmsr() & PSL_HV)
- bus_write_4(xicp_mem_for_cpu(PCPU_GET(cpuid)), 4, xirr);
+ bus_write_4(xicp_mem_for_cpu(PCPU_GET(hwref)), 4, xirr);
else
#endif
phyp_hcall(H_EOI, xirr);
@@ -422,6 +428,8 @@
{
#ifdef POWERNV
+ cpu = pcpu_find(cpu)->pc_hwref;
+
if (mfmsr() & PSL_HV)
bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY);
else
File Metadata
Details
Attached
Mime Type
text/plain
Expires
Sun, Oct 11, 10:47 PM (18 h, 50 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
40632134
Default Alt Text
D14011.id38299.diff (16 KB)
Attached To
Mode
D14011: PPC64: use hwref instead of cpuid
Attached
Detach File
Event Timeline
Log In to Comment