x86-64, NUMA: Prepare numa_emulation() for moving NUMA emulation into a separate file

Update numa_emulation() such that, it

- takes @numa_meminfo and @numa_dist_cnt instead of directly
  referencing the global variables.

- copies the distance table by iterating each distance with
  node_distance() instead of memcpy'ing the distance table.

- tests emu_cmdline to determine whether emulation is requested and
  fills emu_nid_to_phys[] with identity mapping if emulation is not
  used.  This allows the caller to call numa_emulation()
  unconditionally and makes return value unncessary.

- defines dummy version if CONFIG_NUMA_EMU is disabled.

This patch doesn't introduce any behavior change.

Signed-off-by: Tejun Heo <tj@kernel.org>
Cc: Yinghai Lu <yinghai@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
This commit is contained in:
Tejun Heo 2011-02-22 11:10:08 +01:00
parent 69efcc6d90
commit fbe99959d1

View file

@ -789,17 +789,20 @@ 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 * Sets up the system RAM area from start_pfn to last_pfn according to the
* numa=fake command-line option. * numa=fake command-line option.
*/ */
static bool __init numa_emulation(void) static void __init numa_emulation(struct numa_meminfo *numa_meminfo,
int numa_dist_cnt)
{ {
static struct numa_meminfo ei __initdata; static struct numa_meminfo ei __initdata;
static struct numa_meminfo pi __initdata; static struct numa_meminfo pi __initdata;
const u64 max_addr = max_pfn << PAGE_SHIFT; const u64 max_addr = max_pfn << PAGE_SHIFT;
int phys_dist_cnt = numa_distance_cnt;
u8 *phys_dist = NULL; u8 *phys_dist = NULL;
int i, j, ret; int i, j, ret;
if (!emu_cmdline)
goto no_emu;
memset(&ei, 0, sizeof(ei)); memset(&ei, 0, sizeof(ei));
pi = numa_meminfo; pi = *numa_meminfo;
for (i = 0; i < MAX_NUMNODES; i++) for (i = 0; i < MAX_NUMNODES; i++)
emu_nid_to_phys[i] = NUMA_NO_NODE; emu_nid_to_phys[i] = NUMA_NO_NODE;
@ -822,19 +825,19 @@ static bool __init numa_emulation(void)
} }
if (ret < 0) if (ret < 0)
return false; goto no_emu;
if (numa_cleanup_meminfo(&ei) < 0) { if (numa_cleanup_meminfo(&ei) < 0) {
pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n"); pr_warning("NUMA: Warning: constructed meminfo invalid, disabling emulation\n");
return false; goto no_emu;
} }
/* /*
* Copy the original distance table. It's temporary so no need to * Copy the original distance table. It's temporary so no need to
* reserve it. * reserve it.
*/ */
if (phys_dist_cnt) { if (numa_dist_cnt) {
size_t size = phys_dist_cnt * sizeof(numa_distance[0]); size_t size = numa_dist_cnt * sizeof(phys_dist[0]);
u64 phys; u64 phys;
phys = memblock_find_in_range(0, phys = memblock_find_in_range(0,
@ -842,14 +845,18 @@ static bool __init numa_emulation(void)
size, PAGE_SIZE); size, PAGE_SIZE);
if (phys == MEMBLOCK_ERROR) { if (phys == MEMBLOCK_ERROR) {
pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n"); pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
return false; goto no_emu;
} }
phys_dist = __va(phys); phys_dist = __va(phys);
memcpy(phys_dist, numa_distance, size);
for (i = 0; i < numa_dist_cnt; i++)
for (j = 0; j < numa_dist_cnt; j++)
phys_dist[i * numa_dist_cnt + j] =
node_distance(i, j);
} }
/* commit */ /* commit */
numa_meminfo = ei; *numa_meminfo = ei;
/* /*
* Transform __apicid_to_node table to use emulated nids by * Transform __apicid_to_node table to use emulated nids by
@ -878,18 +885,27 @@ static bool __init numa_emulation(void)
int physj = emu_nid_to_phys[j]; int physj = emu_nid_to_phys[j];
int dist; int dist;
if (physi >= phys_dist_cnt || physj >= phys_dist_cnt) if (physi >= numa_dist_cnt || physj >= numa_dist_cnt)
dist = physi == physj ? dist = physi == physj ?
LOCAL_DISTANCE : REMOTE_DISTANCE; LOCAL_DISTANCE : REMOTE_DISTANCE;
else else
dist = phys_dist[physi * phys_dist_cnt + physj]; dist = phys_dist[physi * numa_dist_cnt + physj];
numa_set_distance(i, j, dist); numa_set_distance(i, j, dist);
} }
} }
return true; return;
no_emu:
/* No emulation. Build identity emu_nid_to_phys[] for numa_add_cpu() */
for (i = 0; i < ARRAY_SIZE(emu_nid_to_phys); i++)
emu_nid_to_phys[i] = i;
} }
#endif /* CONFIG_NUMA_EMU */ #else /* CONFIG_NUMA_EMU */
static inline void numa_emulation(struct numa_meminfo *numa_meminfo,
int numa_dist_cnt)
{ }
#endif /* CONFIG_NUMA_EMU */
static int __init dummy_numa_init(void) static int __init dummy_numa_init(void)
{ {
@ -937,15 +953,9 @@ void __init initmem_init(void)
if (numa_cleanup_meminfo(&numa_meminfo) < 0) if (numa_cleanup_meminfo(&numa_meminfo) < 0)
continue; continue;
#ifdef CONFIG_NUMA_EMU
/* numa_emulation(&numa_meminfo, numa_distance_cnt);
* If requested, try emulation. If emulation is not used,
* build identity emu_nid_to_phys[] for numa_add_cpu()
*/
if (!emu_cmdline || !numa_emulation())
for (j = 0; j < ARRAY_SIZE(emu_nid_to_phys); j++)
emu_nid_to_phys[j] = j;
#endif
if (numa_register_memblks(&numa_meminfo) < 0) if (numa_register_memblks(&numa_meminfo) < 0)
continue; continue;