Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Jan 2020 01:26:54 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r356858 - in head/sys/powerpc: include ofw powernv powerpc
Message-ID:  <202001180126.00I1QsjE060194@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Sat Jan 18 01:26:54 2020
New Revision: 356858
URL: https://svnweb.freebsd.org/changeset/base/356858

Log:
  powerpc: Fix the NUMA domain list on powernv
  
  Summary:
  Consolidate the NUMA associativity handling into a platform function.
  Non-NUMA platforms will just fall back to the default (0).  Currently
  only implemented for powernv, which uses a lookup table to map the
  device tree associativity into a system NUMA domain.
  
  Fixes hangs on powernv after r356534, and corrects a fairly longstanding
  bug in powernv's NUMA handling, which ended up using domains 1 and 2 for
  devices and memory on power9, while CPUs were bound to domains 0 and 1.
  
  Reviewed by:	bdragon, luporl
  Differential Revision:	https://reviews.freebsd.org/D23220

Modified:
  head/sys/powerpc/include/ofw_machdep.h
  head/sys/powerpc/include/platform.h
  head/sys/powerpc/ofw/ofw_machdep.c
  head/sys/powerpc/ofw/ofw_pcibus.c
  head/sys/powerpc/powernv/platform_powernv.c
  head/sys/powerpc/powerpc/platform.c
  head/sys/powerpc/powerpc/platform_if.m

Modified: head/sys/powerpc/include/ofw_machdep.h
==============================================================================
--- head/sys/powerpc/include/ofw_machdep.h	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/include/ofw_machdep.h	Sat Jan 18 01:26:54 2020	(r356858)
@@ -37,6 +37,9 @@
 #include <dev/ofw/openfirm.h>
 #include <machine/platform.h>
 
+struct mem_region;
+struct numa_mem_region;
+
 typedef	uint32_t	cell_t;
 
 void OF_getetheraddr(device_t dev, u_char *addr);

Modified: head/sys/powerpc/include/platform.h
==============================================================================
--- head/sys/powerpc/include/platform.h	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/include/platform.h	Sat Jan 18 01:26:54 2020	(r356858)
@@ -37,6 +37,7 @@
 #ifndef	_MACHINE_PLATFORM_H_
 #define	_MACHINE_PLATFORM_H_
   
+#include <machine/ofw_machdep.h>
 #include <machine/smp.h>
 #include <machine/pcpu.h>
 
@@ -66,6 +67,7 @@ int	platform_smp_start_cpu(struct pcpu *);
 void	platform_smp_timebase_sync(u_long tb, int ap);
 void	platform_smp_ap_init(void);
 void	platform_smp_probe_threads(void);
+int	platform_node_numa_domain(phandle_t);
   
 const char *installed_platform(void);
 void platform_probe_and_attach(void);

Modified: head/sys/powerpc/ofw/ofw_machdep.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_machdep.c	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/ofw/ofw_machdep.c	Sat Jan 18 01:26:54 2020	(r356858)
@@ -466,9 +466,8 @@ void
 ofw_numa_mem_regions(struct numa_mem_region *memp, int *memsz)
 {
 	phandle_t phandle;
-	int res, count, msz;
+	int count, msz;
 	char name[31];
-	cell_t associativity[5];
 	struct numa_mem_region *curmemp;
 
 	msz = 0;
@@ -486,13 +485,8 @@ ofw_numa_mem_regions(struct numa_mem_region *memp, int
 		if (count == 0)
 			continue;
 		curmemp = &memp[msz];
-		res = OF_getproplen(phandle, "ibm,associativity");
-		if (res <= 0)
-			continue;
 		MPASS(count == 1);
-		OF_getencprop(phandle, "ibm,associativity",
-			associativity, res);
-		curmemp->mr_domain = associativity[3];
+		curmemp->mr_domain = platform_node_numa_domain(phandle);
 		if (bootverbose)
 			printf("%s %#jx-%#jx domain(%ju)\n",
 			    name, (uintmax_t)curmemp->mr_start,

Modified: head/sys/powerpc/ofw/ofw_pcibus.c
==============================================================================
--- head/sys/powerpc/ofw/ofw_pcibus.c	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/ofw/ofw_pcibus.c	Sat Jan 18 01:26:54 2020	(r356858)
@@ -385,39 +385,13 @@ ofw_pcibus_get_devinfo(device_t bus, device_t dev)
 	return (&dinfo->opd_obdinfo);
 }
 
-static int
-ofw_pcibus_parse_associativity(device_t dev, int *domain)
-{
-	phandle_t node;
-	cell_t associativity[5];
-	int res;
-
-	if ((node = ofw_bus_get_node(dev)) == -1) {
-		if (bootverbose)
-			device_printf(dev, "no ofw node found\n");
-		return (ENXIO);
-	}
-	res = OF_getproplen(node, "ibm,associativity");
-	if (res <= 0)
-		return (ENXIO);
-	OF_getencprop(node, "ibm,associativity",
-		associativity, res);
-
-	*domain = associativity[3];
-	if (bootverbose)
-		device_printf(dev, "domain(%d)\n", *domain);
-	return (0);
-}
-
 int
 ofw_pcibus_get_cpus(device_t dev, device_t child, enum cpu_sets op, size_t setsize,
     cpuset_t *cpuset)
 {
 	int d, error;
 
-	error = ofw_pcibus_parse_associativity(child, &d);
-	if (error)
-		return (bus_generic_get_cpus(dev, child, op, setsize, cpuset));
+	d = platform_node_numa_domain(ofw_bus_get_node(dev));
 
 	switch (op) {
 	case LOCAL_CPUS:
@@ -450,12 +424,7 @@ ofw_pcibus_get_cpus(device_t dev, device_t child, enum
 int
 ofw_pcibus_get_domain(device_t dev, device_t child, int *domain)
 {
-	int d, error;
+	*domain = platform_node_numa_domain(ofw_bus_get_node(child));
 
-	error = ofw_pcibus_parse_associativity(child, &d);
-	/* No ofw node; go up a level */
-	if (error)
-		return (bus_generic_get_domain(dev, child, domain));
-	*domain = d;
 	return (0);
 }

Modified: head/sys/powerpc/powernv/platform_powernv.c
==============================================================================
--- head/sys/powerpc/powernv/platform_powernv.c	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/powernv/platform_powernv.c	Sat Jan 18 01:26:54 2020	(r356858)
@@ -79,6 +79,7 @@ static struct cpu_group *powernv_smp_topo(platform_t p
 static void powernv_reset(platform_t);
 static void powernv_cpu_idle(sbintime_t sbt);
 static int powernv_cpuref_init(void);
+static int powernv_node_numa_domain(platform_t platform, phandle_t node);
 
 static platform_method_t powernv_methods[] = {
 	PLATFORMMETHOD(platform_probe, 		powernv_probe),
@@ -96,6 +97,7 @@ static platform_method_t powernv_methods[] = {
 	PLATFORMMETHOD(platform_smp_probe_threads,	powernv_smp_probe_threads),
 	PLATFORMMETHOD(platform_smp_topo,	powernv_smp_topo),
 #endif
+	PLATFORMMETHOD(platform_node_numa_domain,	powernv_node_numa_domain),
 
 	PLATFORMMETHOD(platform_reset,		powernv_reset),
 
@@ -111,6 +113,7 @@ static platform_def_t powernv_platform = {
 static struct cpuref platform_cpuref[MAXCPU];
 static int platform_cpuref_cnt;
 static int platform_cpuref_valid;
+static int platform_associativity;
 
 PLATFORM_DEF(powernv_platform);
 
@@ -131,8 +134,10 @@ powernv_attach(platform_t plat)
 	uint32_t nptlp, shift = 0, slb_encoding = 0;
 	int32_t lp_size, lp_encoding;
 	char buf[255];
+	pcell_t refpoints[3];
 	pcell_t prop;
 	phandle_t cpu;
+	phandle_t opal;
 	int res, len, idx;
 	register_t msr;
 
@@ -144,7 +149,14 @@ powernv_attach(platform_t plat)
 #else
 	opal_call(OPAL_REINIT_CPUS, 1 /* Big endian */);
 #endif
+	opal = OF_finddevice("/ibm,opal");
 
+	platform_associativity = 4; /* Skiboot default. */
+	if (OF_getencprop(opal, "ibm,associativity-reference-points", refpoints,
+	    sizeof(refpoints)) > 0) {
+		platform_associativity = refpoints[0];
+	}
+
        if (cpu_idle_hook == NULL)
                 cpu_idle_hook = powernv_cpu_idle;
 
@@ -328,7 +340,8 @@ powernv_cpuref_init(void)
 				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;
-					tmp_cpuref[tmp_cpuref_cnt].cr_domain = interrupt_servers[a] >> 11;
+					tmp_cpuref[tmp_cpuref_cnt].cr_domain =
+					    powernv_node_numa_domain(NULL, cpu);
 					if (interrupt_servers[a] == (uint32_t)powernv_boot_pir)
 						bsp = tmp_cpuref_cnt;
 
@@ -493,6 +506,40 @@ powernv_smp_ap_init(platform_t platform)
 static void
 powernv_cpu_idle(sbintime_t sbt)
 {
+}
+
+static int
+powernv_node_numa_domain(platform_t platform, phandle_t node)
+{
+	/* XXX: Is locking necessary in here? */
+	static int numa_domains[MAXMEMDOM];
+	static int numa_max_domain;
+	cell_t associativity[5];
+	int i, res;
+
+	res = OF_getproplen(node, "ibm,associativity");
+
+	/* If already at the root, use default domain. */
+	if (res == 0)
+		return (0);
+	else if (res < 0)
+		/* If this node doesn't have associativity, check its parent. */
+		return (powernv_node_numa_domain(platform, OF_parent(node)));
+
+	OF_getencprop(node, "ibm,associativity",
+		associativity, res);
+
+	for (i = 0; i < numa_max_domain; i++) {
+		if (numa_domains[i] == associativity[platform_associativity])
+			return (i);
+	}
+	if (i < MAXMEMDOM)
+		numa_domains[numa_max_domain++] =
+		    associativity[platform_associativity];
+	else
+		i = 0;
+
+	return (i);
 }
 
 /* Set up the Nest MMU on POWER9 relatively early, but after pmap is setup. */

Modified: head/sys/powerpc/powerpc/platform.c
==============================================================================
--- head/sys/powerpc/powerpc/platform.c	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/powerpc/platform.c	Sat Jan 18 01:26:54 2020	(r356858)
@@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
 
 #include <machine/cpu.h>
 #include <machine/md_var.h>
+#include <machine/ofw_machdep.h>
 #include <machine/platform.h>
 #include <machine/platformvar.h>
 #include <machine/smp.h>
@@ -309,6 +310,12 @@ cpu_topo(void)
 	return (PLATFORM_SMP_TOPO(plat_obj));
 }
 #endif
+
+int
+platform_node_numa_domain(phandle_t node)
+{
+	return (PLATFORM_NODE_NUMA_DOMAIN(plat_obj, node));
+}
 
 /*
  * Reset back to firmware.

Modified: head/sys/powerpc/powerpc/platform_if.m
==============================================================================
--- head/sys/powerpc/powerpc/platform_if.m	Sat Jan 18 01:22:54 2020	(r356857)
+++ head/sys/powerpc/powerpc/platform_if.m	Sat Jan 18 01:26:54 2020	(r356858)
@@ -32,6 +32,7 @@
 #include <sys/systm.h>
 #include <sys/smp.h>
 
+#include <machine/ofw_machdep.h>
 #include <machine/platform.h>
 #include <machine/platformvar.h>
 #include <machine/smp.h>
@@ -88,6 +89,11 @@ CODE {
 	{
 		return;
 	}
+	static int platform_null_node_numa_domain(platform_t plat,
+	    phandle_t node)
+	{
+		return (0);
+	}
 };
 
 /**
@@ -255,3 +261,12 @@ METHOD void smp_timebase_sync {
 	int		_ap;
 };
 
+/**
+ * @brief Return the NUMA domain for the given device tree node.  Always returns
+ * a valid domain.
+ *
+ */
+METHOD int node_numa_domain {
+	platform_t	_plat;
+	phandle_t	_node;
+} DEFAULT platform_null_node_numa_domain;



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