ARM: 6890/1: memmap: only free allocated memmap entries when using SPARSEMEM
The SPARSEMEM code allocates memmap entries only for sections which are present (i.e. those which contain some valid memory). The membank checks in free_unused_memmap do not take this into account and can incorrectly attempt to free memory which is not allocated, resulting in a BUG() in the bootmem code. However, if memory is configured as follows: |<----section---->|<----hole---->|<----section---->| +--------+--------+--------------+--------+--------+ | bank 0 | unused | | bank 1 | unused | +--------+--------+--------------+--------+--------+ where a bank only occupies part of a section, the memmap allocated for the remainder of the section *can* be freed. This patch modifies the checks in free_unused_memmap so that only valid memmap entries are considered for removal. Acked-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Will Deacon <will.deacon@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
362607df9f
commit
9af386c8dc
1 changed files with 15 additions and 1 deletions
|
@ -392,7 +392,7 @@ free_memmap(unsigned long start_pfn, unsigned long end_pfn)
|
|||
* Convert start_pfn/end_pfn to a struct page pointer.
|
||||
*/
|
||||
start_pg = pfn_to_page(start_pfn - 1) + 1;
|
||||
end_pg = pfn_to_page(end_pfn);
|
||||
end_pg = pfn_to_page(end_pfn - 1) + 1;
|
||||
|
||||
/*
|
||||
* Convert to physical addresses, and
|
||||
|
@ -426,6 +426,14 @@ static void __init free_unused_memmap(struct meminfo *mi)
|
|||
|
||||
bank_start = bank_pfn_start(bank);
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM
|
||||
/*
|
||||
* Take care not to free memmap entries that don't exist
|
||||
* due to SPARSEMEM sections which aren't present.
|
||||
*/
|
||||
bank_start = min(bank_start,
|
||||
ALIGN(prev_bank_end, PAGES_PER_SECTION));
|
||||
#endif
|
||||
/*
|
||||
* If we had a previous bank, and there is a space
|
||||
* between the current bank and the previous, free it.
|
||||
|
@ -440,6 +448,12 @@ static void __init free_unused_memmap(struct meminfo *mi)
|
|||
*/
|
||||
prev_bank_end = ALIGN(bank_pfn_end(bank), MAX_ORDER_NR_PAGES);
|
||||
}
|
||||
|
||||
#ifdef CONFIG_SPARSEMEM
|
||||
if (!IS_ALIGNED(prev_bank_end, PAGES_PER_SECTION))
|
||||
free_memmap(prev_bank_end,
|
||||
ALIGN(prev_bank_end, PAGES_PER_SECTION));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void __init free_highpages(void)
|
||||
|
|
Loading…
Reference in a new issue