mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-12 05:48:40 +00:00
ARM: memblock: setup lowmem mappings using memblock
Use memblock information to setup lowmem mappings rather than the membank array. This allows platforms to manipulate the memblock information during initialization to reserve (and remove) memory from the kernel's view of memory - and thus allowing platforms to setup their own private mappings for this memory without causing problems with multiple aliasing mappings: size = min(size, SZ_2M); base = memblock_alloc(size, min(align, SZ_2M)); memblock_free(base, size); memblock_remove(base, size); This is needed because multiple mappings of regions with differing attributes (sharability, type, cache) are not permitted with ARMv6 and above. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
This commit is contained in:
parent
f25b4b4c89
commit
8df6516864
1 changed files with 29 additions and 20 deletions
|
@ -744,11 +744,14 @@ static int __init early_vmalloc(char *arg)
|
|||
}
|
||||
early_param("vmalloc", early_vmalloc);
|
||||
|
||||
static phys_addr_t lowmem_limit __initdata = 0;
|
||||
|
||||
static void __init sanity_check_meminfo(void)
|
||||
{
|
||||
int i, j, highmem = 0;
|
||||
|
||||
memblock_set_current_limit(__pa(vmalloc_min - 1) + 1);
|
||||
lowmem_limit = __pa(vmalloc_min - 1) + 1;
|
||||
memblock_set_current_limit(lowmem_limit);
|
||||
|
||||
for (i = 0, j = 0; i < meminfo.nr_banks; i++) {
|
||||
struct membank *bank = &meminfo.bank[j];
|
||||
|
@ -849,6 +852,7 @@ static void __init sanity_check_meminfo(void)
|
|||
static inline void prepare_page_table(void)
|
||||
{
|
||||
unsigned long addr;
|
||||
phys_addr_t end;
|
||||
|
||||
/*
|
||||
* Clear out all the mappings below the kernel image.
|
||||
|
@ -863,11 +867,18 @@ static inline void prepare_page_table(void)
|
|||
for ( ; addr < PAGE_OFFSET; addr += PGDIR_SIZE)
|
||||
pmd_clear(pmd_off_k(addr));
|
||||
|
||||
/*
|
||||
* Find the end of the first block of lowmem.
|
||||
*/
|
||||
end = memblock.memory.regions[0].base + memblock.memory.regions[0].size;
|
||||
if (end >= lowmem_limit)
|
||||
end = lowmem_limit;
|
||||
|
||||
/*
|
||||
* Clear out all the kernel space mappings, except for the first
|
||||
* memory bank, up to the end of the vmalloc region.
|
||||
*/
|
||||
for (addr = __phys_to_virt(bank_phys_end(&meminfo.bank[0]));
|
||||
for (addr = __phys_to_virt(end);
|
||||
addr < VMALLOC_END; addr += PGDIR_SIZE)
|
||||
pmd_clear(pmd_off_k(addr));
|
||||
}
|
||||
|
@ -984,29 +995,27 @@ static void __init kmap_init(void)
|
|||
#endif
|
||||
}
|
||||
|
||||
static inline void map_memory_bank(struct membank *bank)
|
||||
{
|
||||
struct map_desc map;
|
||||
|
||||
map.pfn = bank_pfn_start(bank);
|
||||
map.virtual = __phys_to_virt(bank_phys_start(bank));
|
||||
map.length = bank_phys_size(bank);
|
||||
map.type = MT_MEMORY;
|
||||
|
||||
create_mapping(&map);
|
||||
}
|
||||
|
||||
static void __init map_lowmem(void)
|
||||
{
|
||||
struct meminfo *mi = &meminfo;
|
||||
int i;
|
||||
struct memblock_region *reg;
|
||||
|
||||
/* Map all the lowmem memory banks. */
|
||||
for (i = 0; i < mi->nr_banks; i++) {
|
||||
struct membank *bank = &mi->bank[i];
|
||||
for_each_memblock(memory, reg) {
|
||||
phys_addr_t start = reg->base;
|
||||
phys_addr_t end = start + reg->size;
|
||||
struct map_desc map;
|
||||
|
||||
if (!bank->highmem)
|
||||
map_memory_bank(bank);
|
||||
if (end > lowmem_limit)
|
||||
end = lowmem_limit;
|
||||
if (start >= end)
|
||||
break;
|
||||
|
||||
map.pfn = __phys_to_pfn(start);
|
||||
map.virtual = __phys_to_virt(start);
|
||||
map.length = end - start;
|
||||
map.type = MT_MEMORY;
|
||||
|
||||
create_mapping(&map);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue