mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-11 12:28:41 +08:00
x86/numa: Fix the address overlap check in numa_fill_memblks()
[ Upstream commit9b99c17f75
] numa_fill_memblks() fills in the gaps in numa_meminfo memblks over a physical address range. To do so, it first creates a list of existing memblks that overlap that address range. The issue is that it is off by one when comparing to the end of the address range, so memblks that do not overlap are selected. The impact of selecting a memblk that does not actually overlap is that an existing memblk may be filled when the expected action is to do nothing and return NUMA_NO_MEMBLK to the caller. The caller can then add a new NUMA node and memblk. Replace the broken open-coded search for address overlap with the memblock helper memblock_addrs_overlap(). Update the kernel doc and in code comments. Suggested by: "Huang, Ying" <ying.huang@intel.com> Fixes:8f012db27c
("x86/numa: Introduce numa_fill_memblks()") Signed-off-by: Alison Schofield <alison.schofield@intel.com> Acked-by: Mike Rapoport (IBM) <rppt@kernel.org> Acked-by: Dave Hansen <dave.hansen@linux.intel.com> Reviewed-by: Dan Williams <dan.j.williams@intel.com> Link: https://lore.kernel.org/r/10a3e6109c34c21a8dd4c513cf63df63481a2b07.1705085543.git.alison.schofield@intel.com Signed-off-by: Dan Williams <dan.j.williams@intel.com> Signed-off-by: Sasha Levin <sashal@kernel.org>
This commit is contained in:
parent
bf21b0b98a
commit
6b725eab09
@ -974,14 +974,12 @@ static struct numa_memblk *numa_memblk_list[NR_NODE_MEMBLKS] __initdata;
|
|||||||
* @start: address to begin fill
|
* @start: address to begin fill
|
||||||
* @end: address to end fill
|
* @end: address to end fill
|
||||||
*
|
*
|
||||||
* Find and extend numa_meminfo memblks to cover the @start-@end
|
* Find and extend numa_meminfo memblks to cover the physical
|
||||||
* physical address range, such that the first memblk includes
|
* address range @start-@end
|
||||||
* @start, the last memblk includes @end, and any gaps in between
|
|
||||||
* are filled.
|
|
||||||
*
|
*
|
||||||
* RETURNS:
|
* RETURNS:
|
||||||
* 0 : Success
|
* 0 : Success
|
||||||
* NUMA_NO_MEMBLK : No memblk exists in @start-@end range
|
* NUMA_NO_MEMBLK : No memblks exist in address range @start-@end
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int __init numa_fill_memblks(u64 start, u64 end)
|
int __init numa_fill_memblks(u64 start, u64 end)
|
||||||
@ -993,17 +991,14 @@ int __init numa_fill_memblks(u64 start, u64 end)
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* Create a list of pointers to numa_meminfo memblks that
|
* Create a list of pointers to numa_meminfo memblks that
|
||||||
* overlap start, end. Exclude (start == bi->end) since
|
* overlap start, end. The list is used to make in-place
|
||||||
* end addresses in both a CFMWS range and a memblk range
|
* changes that fill out the numa_meminfo memblks.
|
||||||
* are exclusive.
|
|
||||||
*
|
|
||||||
* This list of pointers is used to make in-place changes
|
|
||||||
* that fill out the numa_meminfo memblks.
|
|
||||||
*/
|
*/
|
||||||
for (int i = 0; i < mi->nr_blks; i++) {
|
for (int i = 0; i < mi->nr_blks; i++) {
|
||||||
struct numa_memblk *bi = &mi->blk[i];
|
struct numa_memblk *bi = &mi->blk[i];
|
||||||
|
|
||||||
if (start < bi->end && end >= bi->start) {
|
if (memblock_addrs_overlap(start, end - start, bi->start,
|
||||||
|
bi->end - bi->start)) {
|
||||||
blk[count] = &mi->blk[i];
|
blk[count] = &mi->blk[i];
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -121,6 +121,8 @@ int memblock_reserve(phys_addr_t base, phys_addr_t size);
|
|||||||
int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
|
int memblock_physmem_add(phys_addr_t base, phys_addr_t size);
|
||||||
#endif
|
#endif
|
||||||
void memblock_trim_memory(phys_addr_t align);
|
void memblock_trim_memory(phys_addr_t align);
|
||||||
|
unsigned long memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
|
||||||
|
phys_addr_t base2, phys_addr_t size2);
|
||||||
bool memblock_overlaps_region(struct memblock_type *type,
|
bool memblock_overlaps_region(struct memblock_type *type,
|
||||||
phys_addr_t base, phys_addr_t size);
|
phys_addr_t base, phys_addr_t size);
|
||||||
int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
|
int memblock_mark_hotplug(phys_addr_t base, phys_addr_t size);
|
||||||
|
@ -180,8 +180,9 @@ static inline phys_addr_t memblock_cap_size(phys_addr_t base, phys_addr_t *size)
|
|||||||
/*
|
/*
|
||||||
* Address comparison utilities
|
* Address comparison utilities
|
||||||
*/
|
*/
|
||||||
static unsigned long __init_memblock memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1,
|
unsigned long __init_memblock
|
||||||
phys_addr_t base2, phys_addr_t size2)
|
memblock_addrs_overlap(phys_addr_t base1, phys_addr_t size1, phys_addr_t base2,
|
||||||
|
phys_addr_t size2)
|
||||||
{
|
{
|
||||||
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
|
return ((base1 < (base2 + size2)) && (base2 < (base1 + size1)));
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user