Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ce003330 authored by Yinghai Lu's avatar Yinghai Lu Committed by Tejun Heo
Browse files

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: default avatarYinghai Lu <yinghai@kernel.org>
Reported-by: default avatarDavid Rientjes <rientjes@google.com>
Signed-off-by: default avatarTejun Heo <tj@kernel.org>
Cc: Ingo Molnar <mingo@elte.hu>
Acked-by: default avatarDavid Rientjes <rientjes@google.com>
parent cc289894
Loading
Loading
Loading
Loading
+3 −5
Original line number Diff line number Diff line
@@ -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 = NULL;
}

+8 −6
Original line number Diff line number Diff line
@@ -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: