x86-64, NUMA: Unify emulated distance mapping
[deliverable/linux.git] / arch / x86 / mm / numa_64.c
index 722039e0948fb4e204dccfa70e97f1273319b841..8ce6177359008223c1777635a9395e62c93de483 100644 (file)
@@ -48,10 +48,6 @@ static struct numa_meminfo numa_meminfo __initdata;
 static int numa_distance_cnt;
 static u8 *numa_distance;
 
-#ifdef CONFIG_NUMA_EMU
-static bool numa_emu_dist;
-#endif
-
 /*
  * Given a shift value, try to populate memnodemap[]
  * Returns :
@@ -443,10 +439,6 @@ void __init numa_set_distance(int from, int to, int distance)
 
 int __node_distance(int from, int to)
 {
-#if defined(CONFIG_ACPI_NUMA) && defined(CONFIG_NUMA_EMU)
-       if (numa_emu_dist)
-               return acpi_emu_node_distance(from, to);
-#endif
        if (from >= numa_distance_cnt || to >= numa_distance_cnt)
                return from == to ? LOCAL_DISTANCE : REMOTE_DISTANCE;
        return numa_distance[from * numa_distance_cnt + to];
@@ -559,56 +551,6 @@ static int __init emu_find_memblk_by_nid(int nid, const struct numa_meminfo *mi)
        return -ENOENT;
 }
 
-int __init find_node_by_addr(unsigned long addr)
-{
-       const struct numa_meminfo *mi = &numa_meminfo;
-       int i;
-
-       for (i = 0; i < mi->nr_blks; i++) {
-               /*
-                * Find the real node that this emulated node appears on.  For
-                * the sake of simplicity, we only use a real node's starting
-                * address to determine which emulated node it appears on.
-                */
-               if (addr >= mi->blk[i].start && addr < mi->blk[i].end)
-                       return mi->blk[i].nid;
-       }
-       return NUMA_NO_NODE;
-}
-
-static void __init fake_physnodes(int acpi, int amd,
-                                 const struct numa_meminfo *ei)
-{
-       static struct bootnode nodes[MAX_NUMNODES] __initdata;
-       int i, nr_nodes = 0;
-
-       for (i = 0; i < ei->nr_blks; i++) {
-               int nid = ei->blk[i].nid;
-
-               if (nodes[nid].start == nodes[nid].end) {
-                       nodes[nid].start = ei->blk[i].start;
-                       nodes[nid].end = ei->blk[i].end;
-                       nr_nodes++;
-               } else {
-                       nodes[nid].start = min(ei->blk[i].start, nodes[nid].start);
-                       nodes[nid].end = max(ei->blk[i].end, nodes[nid].end);
-               }
-       }
-
-       BUG_ON(acpi && amd);
-#ifdef CONFIG_ACPI_NUMA
-       if (acpi)
-               acpi_fake_nodes(nodes, nr_nodes);
-#endif
-#ifdef CONFIG_AMD_NUMA
-       if (amd)
-               amd_fake_nodes(nodes, nr_nodes);
-#endif
-       if (!acpi && !amd)
-               for (i = 0; i < nr_cpu_ids; i++)
-                       numa_set_node(i, 0);
-}
-
 /*
  * Sets up nid to range from @start to @end.  The return value is -errno if
  * something went wrong, 0 otherwise.
@@ -853,11 +795,13 @@ static int __init split_nodes_size_interleave(struct numa_meminfo *ei,
  * Sets up the system RAM area from start_pfn to last_pfn according to the
  * numa=fake command-line option.
  */
-static bool __init numa_emulation(int acpi, int amd)
+static bool __init numa_emulation(void)
 {
        static struct numa_meminfo ei __initdata;
        static struct numa_meminfo pi __initdata;
        const u64 max_addr = max_pfn << PAGE_SHIFT;
+       int phys_dist_cnt = numa_distance_cnt;
+       u8 *phys_dist = NULL;
        int i, j, ret;
 
        memset(&ei, 0, sizeof(ei));
@@ -891,6 +835,25 @@ static bool __init numa_emulation(int acpi, int amd)
                return false;
        }
 
+       /*
+        * Copy the original distance table.  It's temporary so no need to
+        * reserve it.
+        */
+       if (phys_dist_cnt) {
+               size_t size = phys_dist_cnt * sizeof(numa_distance[0]);
+               u64 phys;
+
+               phys = memblock_find_in_range(0,
+                                             (u64)max_pfn_mapped << PAGE_SHIFT,
+                                             size, PAGE_SIZE);
+               if (phys == MEMBLOCK_ERROR) {
+                       pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
+                       return false;
+               }
+               phys_dist = __va(phys);
+               memcpy(phys_dist, numa_distance, size);
+       }
+
        /* commit */
        numa_meminfo = ei;
 
@@ -913,8 +876,23 @@ static bool __init numa_emulation(int acpi, int amd)
                if (emu_nid_to_phys[i] == NUMA_NO_NODE)
                        emu_nid_to_phys[i] = 0;
 
-       fake_physnodes(acpi, amd, &ei);
-       numa_emu_dist = true;
+       /* transform distance table */
+       numa_reset_distance();
+       for (i = 0; i < MAX_NUMNODES; i++) {
+               for (j = 0; j < MAX_NUMNODES; j++) {
+                       int physi = emu_nid_to_phys[i];
+                       int physj = emu_nid_to_phys[j];
+                       int dist;
+
+                       if (physi >= phys_dist_cnt || physj >= phys_dist_cnt)
+                               dist = physi == physj ?
+                                       LOCAL_DISTANCE : REMOTE_DISTANCE;
+                       else
+                               dist = phys_dist[physi * phys_dist_cnt + physj];
+
+                       numa_set_distance(i, j, dist);
+               }
+       }
        return true;
 }
 #endif /* CONFIG_NUMA_EMU */
@@ -970,7 +948,7 @@ void __init initmem_init(void)
                 * If requested, try emulation.  If emulation is not used,
                 * build identity emu_nid_to_phys[] for numa_add_cpu()
                 */
-               if (!emu_cmdline || !numa_emulation(i == 0, i == 1))
+               if (!emu_cmdline || !numa_emulation())
                        for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
                                emu_nid_to_phys[j] = j;
 #endif
This page took 0.027526 seconds and 5 git commands to generate.