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

Commit c7fc2de0 authored by Yinghai Lu's avatar Yinghai Lu Committed by H. Peter Anvin
Browse files

memblock, bootmem: Round pfn properly for memory and reserved regions



We need to round memory regions correctly -- specifically, we need to
round reserved region in the more expansive direction (lower limit
down, upper limit up) whereas usable memory regions need to be rounded
in the more restrictive direction (lower limit up, upper limit down).

This introduces two set of inlines:

	memblock_region_memory_base_pfn()
	memblock_region_memory_end_pfn()
	memblock_region_reserved_base_pfn()
	memblock_region_reserved_end_pfn()

Although they are antisymmetric (and therefore are technically
duplicates) the use of the different inlines explicitly documents the
programmer's intention.

The lack of proper rounding caused a bug on ARM, which was then found
to also affect other architectures.

Reported-by: default avatarRussell King <rmk@arm.linux.org.uk>
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
LKML-Reference: <4CB4CDFD.4020105@kernel.org>
Cc: Jeremy Fitzhardinge <jeremy@goop.org>
Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
parent 8e4029ee
Loading
Loading
Loading
Loading
+4 −4
Original line number Original line Diff line number Diff line
@@ -182,8 +182,8 @@ static void __init arm_bootmem_init(struct meminfo *mi,
	 * Reserve the memblock reserved regions in bootmem.
	 * Reserve the memblock reserved regions in bootmem.
	 */
	 */
	for_each_memblock(reserved, reg) {
	for_each_memblock(reserved, reg) {
		phys_addr_t start = memblock_region_base_pfn(reg);
		phys_addr_t start = memblock_region_reserved_base_pfn(reg);
		phys_addr_t end = memblock_region_end_pfn(reg);
		phys_addr_t end = memblock_region_reserved_end_pfn(reg);
		if (start >= start_pfn && end <= end_pfn)
		if (start >= start_pfn && end <= end_pfn)
			reserve_bootmem_node(pgdat, __pfn_to_phys(start),
			reserve_bootmem_node(pgdat, __pfn_to_phys(start),
					     (end - start) << PAGE_SHIFT,
					     (end - start) << PAGE_SHIFT,
@@ -251,8 +251,8 @@ static void arm_memory_present(void)
	struct memblock_region *reg;
	struct memblock_region *reg;


	for_each_memblock(memory, reg)
	for_each_memblock(memory, reg)
		memory_present(0, memblock_region_base_pfn(reg),
		memory_present(0, memblock_region_memory_base_pfn(reg),
			       memblock_region_end_pfn(reg));
			       memblock_region_memory_end_pfn(reg));
}
}
#endif
#endif


+7 −7
Original line number Original line Diff line number Diff line
@@ -148,8 +148,8 @@ walk_system_ram_range(unsigned long start_pfn, unsigned long nr_pages,
	int ret = -1;
	int ret = -1;


	for_each_memblock(memory, reg) {
	for_each_memblock(memory, reg) {
		tstart = max(start_pfn, memblock_region_base_pfn(reg));
		tstart = max(start_pfn, memblock_region_memory_base_pfn(reg));
		tend = min(end_pfn, memblock_region_end_pfn(reg));
		tend = min(end_pfn, memblock_region_memory_end_pfn(reg));
		if (tstart >= tend)
		if (tstart >= tend)
			continue;
			continue;
		ret = (*func)(tstart, tend - tstart, arg);
		ret = (*func)(tstart, tend - tstart, arg);
@@ -195,8 +195,8 @@ void __init do_init_bootmem(void)
	/* Add active regions with valid PFNs */
	/* Add active regions with valid PFNs */
	for_each_memblock(memory, reg) {
	for_each_memblock(memory, reg) {
		unsigned long start_pfn, end_pfn;
		unsigned long start_pfn, end_pfn;
		start_pfn = memblock_region_base_pfn(reg);
		start_pfn = memblock_region_memory_base_pfn(reg);
		end_pfn = memblock_region_end_pfn(reg);
		end_pfn = memblock_region_memory_end_pfn(reg);
		add_active_range(0, start_pfn, end_pfn);
		add_active_range(0, start_pfn, end_pfn);
	}
	}


@@ -236,9 +236,9 @@ static int __init mark_nonram_nosave(void)


	for_each_memblock(memory, reg) {
	for_each_memblock(memory, reg) {
		if (prev &&
		if (prev &&
		    memblock_region_end_pfn(prev) < memblock_region_base_pfn(reg))
		    memblock_region_memory_end_pfn(prev) < memblock_region_memory_base_pfn(reg))
			register_nosave_region(memblock_region_end_pfn(prev),
			register_nosave_region(memblock_region_memory_end_pfn(prev),
					       memblock_region_base_pfn(reg));
					       memblock_region_memory_base_pfn(reg));
		prev = reg;
		prev = reg;
	}
	}
	return 0;
	return 0;
+2 −2
Original line number Original line Diff line number Diff line
@@ -811,8 +811,8 @@ static void __init setup_nonnuma(void)
	       (top_of_ram - total_ram) >> 20);
	       (top_of_ram - total_ram) >> 20);


	for_each_memblock(memory, reg) {
	for_each_memblock(memory, reg) {
		start_pfn = memblock_region_base_pfn(reg);
		start_pfn = memblock_region_memory_base_pfn(reg);
		end_pfn = memblock_region_end_pfn(reg);
		end_pfn = memblock_region_memory_end_pfn(reg);


		fake_numa_create_new_node(end_pfn, &nid);
		fake_numa_create_new_node(end_pfn, &nid);
		add_active_range(nid, start_pfn, end_pfn);
		add_active_range(nid, start_pfn, end_pfn);
+2 −2
Original line number Original line Diff line number Diff line
@@ -244,8 +244,8 @@ static void __init do_init_bootmem(void)
	/* Add active regions with valid PFNs. */
	/* Add active regions with valid PFNs. */
	for_each_memblock(memory, reg) {
	for_each_memblock(memory, reg) {
		unsigned long start_pfn, end_pfn;
		unsigned long start_pfn, end_pfn;
		start_pfn = memblock_region_base_pfn(reg);
		start_pfn = memblock_region_memory_base_pfn(reg);
		end_pfn = memblock_region_end_pfn(reg);
		end_pfn = memblock_region_memory_end_pfn(reg);
		__add_active_range(0, start_pfn, end_pfn);
		__add_active_range(0, start_pfn, end_pfn);
	}
	}


+2 −2
Original line number Original line Diff line number Diff line
@@ -1294,8 +1294,8 @@ static void __init bootmem_init_nonnuma(void)
		if (!reg->size)
		if (!reg->size)
			continue;
			continue;


		start_pfn = memblock_region_base_pfn(reg);
		start_pfn = memblock_region_memory_base_pfn(reg);
		end_pfn = memblock_region_end_pfn(reg);
		end_pfn = memblock_region_memory_end_pfn(reg);
		add_active_range(0, start_pfn, end_pfn);
		add_active_range(0, start_pfn, end_pfn);
	}
	}


Loading