x86-64, NUMA: Fix distance table handling
NUMA distance table handling has the following problems. * numa_reset_distance() uses numa_distance * sizeof(numa_distance[0]) as the table size when it should be using the square of numa_distance. * The same size miscalculation when allocation space for phys_dist in numa_emulation(). * In numa_emulation(), phys_dist must be reserved; otherwise, the new emulated distance table may overlap it. Fix them and, while at it, take numa_distance_cnt resetting in numa_reset_distance() out of the if block to simplify the code a bit. David Rientjes reported incorrect handling of distance table during emulation. -tj: Edited out numa_alloc_distance() related changes which weren't necessary and rewrote patch description. -v2: Ingo was unhappy with 80-column limit induced linebreaks. Let lines run over 80-column. Signed-off-by: Yinghai Lu <yinghai@kernel.org> Reported-by: David Rientjes <rientjes@google.com> Signed-off-by: Tejun Heo <tj@kernel.org> Cc: Ingo Molnar <mingo@elte.hu> Acked-by: David Rientjes <rientjes@google.com>
This commit is contained in:
parent
cc28989437
commit
ce0033307f
@ -390,14 +390,12 @@ static void __init numa_nodemask_from_meminfo(nodemask_t *nodemask,
|
||||
*/
|
||||
void __init numa_reset_distance(void)
|
||||
{
|
||||
size_t size;
|
||||
size_t size = numa_distance_cnt * numa_distance_cnt * sizeof(numa_distance[0]);
|
||||
|
||||
if (numa_distance_cnt) {
|
||||
size = numa_distance_cnt * sizeof(numa_distance[0]);
|
||||
if (numa_distance_cnt)
|
||||
memblock_x86_free_range(__pa(numa_distance),
|
||||
__pa(numa_distance) + size);
|
||||
numa_distance_cnt = 0;
|
||||
}
|
||||
numa_distance_cnt = 0;
|
||||
numa_distance = NULL;
|
||||
}
|
||||
|
||||
|
@ -300,6 +300,7 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
|
||||
static struct numa_meminfo pi __initdata;
|
||||
const u64 max_addr = max_pfn << PAGE_SHIFT;
|
||||
u8 *phys_dist = NULL;
|
||||
size_t phys_size = numa_dist_cnt * numa_dist_cnt * sizeof(phys_dist[0]);
|
||||
int i, j, ret;
|
||||
|
||||
if (!emu_cmdline)
|
||||
@ -336,21 +337,18 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
|
||||
goto no_emu;
|
||||
}
|
||||
|
||||
/*
|
||||
* Copy the original distance table. It's temporary so no need to
|
||||
* reserve it.
|
||||
*/
|
||||
/* copy the physical distance table */
|
||||
if (numa_dist_cnt) {
|
||||
size_t size = numa_dist_cnt * sizeof(phys_dist[0]);
|
||||
u64 phys;
|
||||
|
||||
phys = memblock_find_in_range(0,
|
||||
(u64)max_pfn_mapped << PAGE_SHIFT,
|
||||
size, PAGE_SIZE);
|
||||
phys_size, PAGE_SIZE);
|
||||
if (phys == MEMBLOCK_ERROR) {
|
||||
pr_warning("NUMA: Warning: can't allocate copy of distance table, disabling emulation\n");
|
||||
goto no_emu;
|
||||
}
|
||||
memblock_x86_reserve_range(phys, phys + phys_size, "TMP NUMA DIST");
|
||||
phys_dist = __va(phys);
|
||||
|
||||
for (i = 0; i < numa_dist_cnt; i++)
|
||||
@ -398,6 +396,10 @@ void __init numa_emulation(struct numa_meminfo *numa_meminfo, int numa_dist_cnt)
|
||||
numa_set_distance(i, j, dist);
|
||||
}
|
||||
}
|
||||
|
||||
/* free the copied physical distance table */
|
||||
if (phys_dist)
|
||||
memblock_x86_free_range(__pa(phys_dist), __pa(phys_dist) + phys_size);
|
||||
return;
|
||||
|
||||
no_emu:
|
||||
|
Loading…
Reference in New Issue
Block a user