Commit 8df65168 authored by Russell King's avatar Russell King

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: default avatarRussell King <rmk+kernel@arm.linux.org.uk>
parent f25b4b4c
......@@ -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 (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;
if (!bank->highmem)
map_memory_bank(bank);
create_mapping(&map);
}
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment