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;
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to