Skip site navigation (1)Skip section navigation (2)
Date:      Tue, 23 Aug 2016 21:34:36 +0000 (UTC)
From:      Nathan Whitehorn <nwhitehorn@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-projects@freebsd.org
Subject:   svn commit: r304705 - in projects/powernv/powerpc: include powernv pseries
Message-ID:  <201608232134.u7NLYaMr077167@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: nwhitehorn
Date: Tue Aug 23 21:34:36 2016
New Revision: 304705
URL: https://svnweb.freebsd.org/changeset/base/304705

Log:
  On CHRP and PowerNV, use the interrupt server number in the cpuref and pcpu
  hwref field instead of the device-tree phandle and make the CPU IDs reported
  to the scheduler dense and with the BSP at 0. There are entirely too many
  subtle bugs with non-0 BSP IDs and I'm just not going to try anymore.

Modified:
  projects/powernv/powerpc/include/spr.h
  projects/powernv/powerpc/powernv/platform_powernv.c
  projects/powernv/powerpc/pseries/platform_chrp.c
  projects/powernv/powerpc/pseries/xics.c

Modified: projects/powernv/powerpc/include/spr.h
==============================================================================
--- projects/powernv/powerpc/include/spr.h	Tue Aug 23 21:21:56 2016	(r304704)
+++ projects/powernv/powerpc/include/spr.h	Tue Aug 23 21:34:36 2016	(r304705)
@@ -194,6 +194,7 @@
 
 #define	SPR_LPCR		0x13e	/* Logical Partitioning Control */
 #define	  LPCR_LPES		0x008	/* Bit 60 */
+#define	SPR_LPID		0x13f	/* Logical Partitioning Control */
 
 #define	SPR_IBAT0U		0x210	/* .68 Instruction BAT Reg 0 Upper */
 #define	SPR_IBAT0U		0x210	/* .6. Instruction BAT Reg 0 Upper */

Modified: projects/powernv/powerpc/powernv/platform_powernv.c
==============================================================================
--- projects/powernv/powerpc/powernv/platform_powernv.c	Tue Aug 23 21:21:56 2016	(r304704)
+++ projects/powernv/powerpc/powernv/platform_powernv.c	Tue Aug 23 21:34:36 2016	(r304705)
@@ -104,6 +104,8 @@ PLATFORM_DEF(powernv_platform);
 
 static int powernv_boot_pir;
 
+#define BSP_MUST_BE_CPU_ZERO
+
 static int
 powernv_probe(platform_t plat)
 {
@@ -126,6 +128,12 @@ powernv_attach(platform_t plat)
 	/* 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);
 
@@ -219,12 +227,30 @@ powernv_mem_regions(platform_t plat, str
 static u_long
 powernv_timebase_freq(platform_t plat, struct cpuref *cpuref)
 {
-	phandle_t phandle;
+	char buf[8];
+	phandle_t cpu, dev, root;
+	int res;
 	int32_t ticks = -1;
 
-	phandle = cpuref->cr_hwref;
+	root = OF_peer(0);
 
-	OF_getencprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
+	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);
+	}
+
+	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;
+	}
+	if (cpu == 0)
+		return (512000000);
+
+	OF_getencprop(cpu, "timebase-frequency", &ticks, sizeof(ticks));
 
 	if (ticks <= 0)
 		panic("Unable to determine timebase frequency!");
@@ -233,11 +259,11 @@ powernv_timebase_freq(platform_t plat, s
 }
 
 static int
-powernv_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+powernv_cpuref_for_server(struct cpuref *cpuref, int cpu_n, int server)
 {
 	char buf[8];
 	phandle_t cpu, dev, root;
-	int res, cpuid;
+	int res, cpuid, i, j;
 
 	root = OF_peer(0);
 
@@ -248,116 +274,97 @@ powernv_smp_first_cpu(platform_t plat, s
 			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) {
+	i = 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);
-
-	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;
-
-	return (0);
-}
-
-static int
-powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
-{
-	char buf[8];
-	phandle_t cpu;
-	int i, res, cpuid;
+		if (res <= 0 || strcmp(buf, "cpu") != 0)
+			continue;
 
-	/* 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);
+		res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
+		if (res > 0) {
+			cell_t interrupt_servers[res/sizeof(cell_t)];
+			OF_getencprop(cpu, "ibm,ppc-interrupt-server#s",
+			    interrupt_servers, res);
+			for (j = 0; j < res/sizeof(cell_t); j++) {
+				cpuid = interrupt_servers[j];
+				if (server != -1 && cpuid == server)
+					break;
+				if (cpu_n != -1 && cpu_n == i)
+					break;
+				i++;
 			}
+
+			if (j != res/sizeof(cell_t))
+				break;
+		} else {
+			res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
+			if (res <= 0)
+				cpuid = 0;
+			if (server != -1 && cpuid == server)
+				break;
+			if (cpu_n != -1 && cpu_n == i)
+				break;
+			i++;
 		}
 	}
 
-	/* 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)
 		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_hwref = cpuid;
+	cpuref->cr_cpuid = i;
 
 	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;
-
-	chosen = OF_finddevice("/chosen");
-	if (chosen == 0)
-		return (ENOENT);
-
-	res = OF_getencprop(chosen, "fdtbootcpu", &cpuid, sizeof(cpuid));
-	if (res < 0)
-		return (ENOENT);
-
-	/* XXX: FDT from kexec lies sometimes. PIR seems not to. */
-	if (cpuid == 0)
-		cpuid = powernv_boot_pir;
-
-	cpuref->cr_cpuid = cpuid;
+#ifdef BSP_MUST_BE_CPU_ZERO
+	return (powernv_smp_get_bsp(plat, cpuref));
+#else
+	return (powernv_cpuref_for_server(cpuref, 0, -1));
+#endif
+}
 
-	if (powernv_smp_first_cpu(plat, &i) != 0)
+static int
+powernv_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+#ifdef BSP_MUST_BE_CPU_ZERO
+	int bsp, ncpus, err;
+	struct cpuref scratch;
+
+	powernv_cpuref_for_server(&scratch, -1, powernv_boot_pir);
+	bsp = scratch.cr_cpuid;
+	
+	for (ncpus = bsp; powernv_cpuref_for_server(&scratch, ncpus, -1) !=
+	    ENOENT; ncpus++) {}
+	if (cpuref->cr_cpuid + 1 == ncpus)
 		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);
+	err = powernv_cpuref_for_server(cpuref,
+	    (cpuref->cr_cpuid + bsp + 1) % ncpus, -1);
+	if (cpuref->cr_cpuid >= bsp)
+		cpuref->cr_cpuid -= bsp;
+	else 
+		cpuref->cr_cpuid = ncpus - (bsp - cpuref->cr_cpuid);
+	return (err);
+#else
+	return (powernv_cpuref_for_server(cpuref, cpuref->cr_cpuid+1, -1));
+#endif
+}
 
-	return (0);
+static int
+powernv_smp_get_bsp(platform_t plat, struct cpuref *cpuref)
+{
+#ifdef BSP_MUST_BE_CPU_ZERO
+	int err;
+	err = powernv_cpuref_for_server(cpuref, -1, powernv_boot_pir);
+	cpuref->cr_cpuid = 0;
+	return (err);
+#else
+	return (powernv_cpuref_for_server(cpuref, -1, powernv_boot_pir));
+#endif
 }
 
 #ifdef SMP
@@ -369,10 +376,10 @@ powernv_smp_start_cpu(platform_t plat, s
 	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);
+		printf("OPAL error (%d): unable to start AP %d (HW %ld)\n",
+		    result, pc->pc_cpuid, pc->pc_hwref);
 		return (ENXIO);
 	}
 
@@ -382,36 +389,47 @@ powernv_smp_start_cpu(platform_t plat, s
 static struct cpu_group *
 powernv_smp_topo(platform_t plat)
 {
-	struct pcpu *pc, *last_pc;
-	int i, ncores, ncpus;
+	char buf[8];
+	phandle_t cpu, dev, root;
+	int res, nthreads;
+
+	root = OF_peer(0);
 
-	ncores = ncpus = 0;
-	last_pc = NULL;
-	CPU_FOREACH(i) {
-		pc = pcpu_find(i);
-		if (pc == NULL)
+	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
 
@@ -427,6 +445,7 @@ powernv_smp_ap_init(platform_t platform)
 {
 
 	/* Direct interrupts to SRR instead of HSRR and reset LPCR otherwise */
+	mtspr(SPR_LPID, 0);
 	mtspr(SPR_LPCR, LPCR_LPES);
 }
 
@@ -434,3 +453,4 @@ static void
 powernv_cpu_idle(sbintime_t sbt)
 {
 }
+

Modified: projects/powernv/powerpc/pseries/platform_chrp.c
==============================================================================
--- projects/powernv/powerpc/pseries/platform_chrp.c	Tue Aug 23 21:21:56 2016	(r304704)
+++ projects/powernv/powerpc/pseries/platform_chrp.c	Tue Aug 23 21:34:36 2016	(r304705)
@@ -111,6 +111,8 @@ static platform_def_t chrp_platform = {
 
 PLATFORM_DEF(chrp_platform);
 
+#define BSP_MUST_BE_CPU_ZERO
+
 static int
 chrp_probe(platform_t plat)
 {
@@ -276,12 +278,30 @@ chrp_real_maxaddr(platform_t plat)
 static u_long
 chrp_timebase_freq(platform_t plat, struct cpuref *cpuref)
 {
-	phandle_t phandle;
+	char buf[8];
+	phandle_t cpu, dev, root;
+	int res;
 	int32_t ticks = -1;
 
-	phandle = cpuref->cr_hwref;
+	root = OF_peer(0);
 
-	OF_getencprop(phandle, "timebase-frequency", &ticks, sizeof(ticks));
+	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);
+	}
+
+	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;
+	}
+	if (cpu == 0)
+		return (512000000);
+
+	OF_getencprop(cpu, "timebase-frequency", &ticks, sizeof(ticks));
 
 	if (ticks <= 0)
 		panic("Unable to determine timebase frequency!");
@@ -290,11 +310,11 @@ chrp_timebase_freq(platform_t plat, stru
 }
 
 static int
-chrp_smp_first_cpu(platform_t plat, struct cpuref *cpuref)
+chrp_cpuref_for_server(struct cpuref *cpuref, int cpu_n, int server)
 {
 	char buf[8];
 	phandle_t cpu, dev, root;
-	int res, cpuid;
+	int res, cpuid, i, j;
 
 	root = OF_peer(0);
 
@@ -315,71 +335,84 @@ chrp_smp_first_cpu(platform_t plat, stru
 			return (ENOENT);
 	}
 
-	cpu = OF_child(dev);
-
-	while (cpu != 0) {
+	i = 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 (res <= 0 || strcmp(buf, "cpu") != 0)
+			continue;
+
+		res = OF_getproplen(cpu, "ibm,ppc-interrupt-server#s");
+		if (res > 0) {
+			cell_t interrupt_servers[res/sizeof(cell_t)];
+			OF_getencprop(cpu, "ibm,ppc-interrupt-server#s",
+			    interrupt_servers, res);
+			for (j = 0; j < res/sizeof(cell_t); j++) {
+				cpuid = interrupt_servers[j];
+				if (server != -1 && cpuid == server)
+					break;
+				if (cpu_n != -1 && cpu_n == i)
+					break;
+				i++;
+			}
+
+			if (j != res/sizeof(cell_t))
+				break;
+		} else {
+			res = OF_getencprop(cpu, "reg", &cpuid, sizeof(cpuid));
+			if (res <= 0)
+				cpuid = 0;
+			if (server != -1 && cpuid == server)
+				break;
+			if (cpu_n != -1 && cpu_n == i)
+				break;
+			i++;
+		}
 	}
+
 	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_hwref = cpuid;
+	cpuref->cr_cpuid = i;
 
 	return (0);
 }
 
 static int
-chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+chrp_smp_first_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);
-			}
-		}
-	}
+#ifdef BSP_MUST_BE_CPU_ZERO
+	return (chrp_smp_get_bsp(plat, cpuref));
+#else
+	return (chrp_cpuref_for_server(cpuref, 0, -1));
+#endif
+}
 
-	/* 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)
+static int
+chrp_smp_next_cpu(platform_t plat, struct cpuref *cpuref)
+{
+#ifdef BSP_MUST_BE_CPU_ZERO
+	int bsp, ncpus, err;
+	struct cpuref scratch;
+
+	chrp_smp_get_bsp(plat, &scratch);
+	chrp_cpuref_for_server(&scratch, -1, scratch.cr_hwref);
+	bsp = scratch.cr_cpuid;
+
+	for (ncpus = bsp; chrp_cpuref_for_server(&scratch, ncpus, -1) !=
+	    ENOENT; ncpus++) {}
+	if (cpuref->cr_cpuid + 1 == ncpus)
 		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;
-
-	return (0);
+	err = chrp_cpuref_for_server(cpuref,
+	    (cpuref->cr_cpuid + bsp + 1) % ncpus, -1);
+	if (cpuref->cr_cpuid >= bsp)
+		cpuref->cr_cpuid -= bsp;
+	else
+		cpuref->cr_cpuid = ncpus - (bsp - cpuref->cr_cpuid);
+	return (err);
+#else
+	return (chrp_cpuref_for_server(cpuref, cpuref->cr_cpuid+1, -1));
+#endif
 }
 
 static int
@@ -400,14 +433,17 @@ chrp_smp_get_bsp(platform_t plat, struct
 	bsp = OF_instance_to_package(inst);
 
 	/* 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;
+
+	chrp_cpuref_for_server(cpuref, -1, cpuid);
+#ifdef BSP_MUST_BE_CPU_ZERO
 	cpuref->cr_cpuid = cpuid;
+#endif
 
 	return (0);
 }
@@ -435,7 +471,7 @@ chrp_smp_start_cpu(platform_t plat, stru
 	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",
@@ -453,39 +489,62 @@ chrp_smp_start_cpu(platform_t plat, stru
 static struct cpu_group *
 chrp_smp_topo(platform_t plat)
 {
-	struct pcpu *pc, *last_pc;
-	int i, ncores, ncpus;
+	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);
+	}
 
-	ncores = ncpus = 0;
-	last_pc = NULL;
-	CPU_FOREACH(i) {
-		pc = pcpu_find(i);
-		if (pc == NULL)
+	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());
 
-	return (smp_topo_1level(CG_SHARE_L1, ncpus / ncores, CG_FLAG_SMT));
+	return (smp_topo_1level(CG_SHARE_L1, nthreads, CG_FLAG_SMT));
 }
 #endif
 
 static void
 chrp_reset(platform_t platform)
 {
-	OF_reboot();
+	cell_t token, status;
+
+	if (rtas_exists()) {
+		token = rtas_token_lookup("system-reboot");
+		if (token != -1)
+			rtas_call_method(token, 0, 1, &status);
+	} else {
+		OF_reboot();
+	}
 }
 
 #ifdef __powerpc64__

Modified: projects/powernv/powerpc/pseries/xics.c
==============================================================================
--- projects/powernv/powerpc/pseries/xics.c	Tue Aug 23 21:21:56 2016	(r304704)
+++ projects/powernv/powerpc/pseries/xics.c	Tue Aug 23 21:34:36 2016	(r304705)
@@ -267,6 +267,8 @@ xicp_bind(device_t dev, u_int irq, cpuse
 			break;
 		ncpus++;
 	}
+
+	cpu = pcpu_find(cpu)->pc_hwref;
 	
 	/* XXX: super inefficient */
 	for (i = 0; i < sc->nintvecs; i++) {
@@ -284,7 +286,8 @@ xicp_bind(device_t dev, u_int irq, cpuse
 		error = opal_call(OPAL_SET_XIVE, irq, cpu << 2, XICP_PRIORITY);
 
 	if (error < 0)
-		panic("Cannot bind interrupt %d to CPU %d", irq, cpu);
+		panic("Cannot bind interrupt %d to CPU %d: %d", irq, cpu,
+		    error);
 }
 
 static void
@@ -296,9 +299,9 @@ xicp_dispatch(device_t dev, struct trapf
 	int i;
 
 	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", PCPU_GET(hwref)));
 	}
 
 	sc = device_get_softc(dev);
@@ -325,7 +328,7 @@ xicp_dispatch(device_t dev, struct trapf
 			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);
 		}
 
@@ -335,6 +338,7 @@ xicp_dispatch(device_t dev, struct trapf
 				break;
 		}
 
+//printf("Interrupt %ld\n", xirr);
 		KASSERT(i < sc->nintvecs, ("Unmapped XIRR"));
 		powerpc_dispatch_intr(sc->intvecs[i].vector, tf);
 	}
@@ -352,7 +356,7 @@ xicp_enable(device_t dev, u_int irq, u_i
 		("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;
@@ -390,7 +394,7 @@ xicp_eoi(device_t dev, u_int irq)
 	xirr = irq | (XICP_PRIORITY << 24);
 
 	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
 		phyp_hcall(H_EOI, xirr);
 }
@@ -399,6 +403,8 @@ static void
 xicp_ipi(device_t dev, u_int cpu)
 {
 
+	cpu = pcpu_find(cpu)->pc_hwref;
+
 	if (mfmsr() & PSL_HV)
 		bus_write_1(xicp_mem_for_cpu(cpu), 12, XICP_PRIORITY);
 	else



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201608232134.u7NLYaMr077167>