arm64: Fix mapping of memory banks not ending on a PMD_SIZE boundary
The map_mem() function limits the current memblock limit to PGDIR_SIZE (the initial swapper_pg_dir mapping) to avoid create_mapping() allocating memory from unmapped areas. However, if the first block is within PGDIR_SIZE and not ending on a PMD_SIZE boundary, when 4K page configuration is enabled, create_mapping() will try to allocate a pte page. Such page may be returned by memblock_alloc() from the end of such bank (or any subsequent bank within PGDIR_SIZE) which is not mapped yet. The patch limits the current memblock limit to the aligned end of the first bank and gradually increases it as more memory is mapped. It also ensures that the start of the first bank is aligned to PMD_SIZE to avoid pte page allocation for this mapping. Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Reported-by: "Leizhen (ThunderTown, Euler)" <thunder.leizhen@huawei.com> Tested-by: "Leizhen (ThunderTown, Euler)" <thunder.leizhen@huawei.com>
This commit is contained in:
Родитель
c80b7ee852
Коммит
e25208f77c
|
@ -296,6 +296,7 @@ void __iomem * __init early_io_map(phys_addr_t phys, unsigned long virt)
|
|||
static void __init map_mem(void)
|
||||
{
|
||||
struct memblock_region *reg;
|
||||
phys_addr_t limit;
|
||||
|
||||
/*
|
||||
* Temporarily limit the memblock range. We need to do this as
|
||||
|
@ -303,9 +304,11 @@ static void __init map_mem(void)
|
|||
* memory addressable from the initial direct kernel mapping.
|
||||
*
|
||||
* The initial direct kernel mapping, located at swapper_pg_dir,
|
||||
* gives us PGDIR_SIZE memory starting from PHYS_OFFSET (aligned).
|
||||
* gives us PGDIR_SIZE memory starting from PHYS_OFFSET (which must be
|
||||
* aligned to 2MB as per Documentation/arm64/booting.txt).
|
||||
*/
|
||||
memblock_set_current_limit((PHYS_OFFSET & PGDIR_MASK) + PGDIR_SIZE);
|
||||
limit = PHYS_OFFSET + PGDIR_SIZE;
|
||||
memblock_set_current_limit(limit);
|
||||
|
||||
/* map all the memory banks */
|
||||
for_each_memblock(memory, reg) {
|
||||
|
@ -315,6 +318,22 @@ static void __init map_mem(void)
|
|||
if (start >= end)
|
||||
break;
|
||||
|
||||
#ifndef CONFIG_ARM64_64K_PAGES
|
||||
/*
|
||||
* For the first memory bank align the start address and
|
||||
* current memblock limit to prevent create_mapping() from
|
||||
* allocating pte page tables from unmapped memory.
|
||||
* When 64K pages are enabled, the pte page table for the
|
||||
* first PGDIR_SIZE is already present in swapper_pg_dir.
|
||||
*/
|
||||
if (start < limit)
|
||||
start = ALIGN(start, PMD_SIZE);
|
||||
if (end < limit) {
|
||||
limit = end & PMD_MASK;
|
||||
memblock_set_current_limit(limit);
|
||||
}
|
||||
#endif
|
||||
|
||||
create_mapping(start, __phys_to_virt(start), end - start);
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче