Subject: [PATCH] x86, mm: First mapped area need to be 2M aligned and big enough Henrik reported that his MacAir 3.1 would not boot with | commit 8d57470d8f859635deffe3919d7d4867b488b85a | Date: Fri Nov 16 19:38:58 2012 -0800 | | x86, mm: setup page table in top-down It turns out that we do not calculate the real_end properly: We try to get 2M size with 4K alignment, and later will round down to 2M, so we will get less then 2M for first mapping, in extreme case could be only 4K only. In Henrik's system it has (1M-32K) as last usable rage is [mem 0x7f9db000-0x7fef8fff]. The problem is exposed when EFI booting have several holes and it will force mapping to use PTE instead as we only map usable areas. To fix it, just make it be 2M aligned. As Linus said his MacAir 4.1 has 251 memmap entries, it could have more holes in memmap. To make it more robust, try to push down real_end a bit, to make sure we have 8M continuous usable area for page tables, that will let us skip those UEFI holes. Reported-by: Henrik Rydberg Bisected-by: Henrik Rydberg Tested-by: Henrik Rydberg Signed-off-by: Yinghai Lu --- arch/x86/mm/init.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) Index: linux-2.6/arch/x86/mm/init.c =================================================================== --- linux-2.6.orig/arch/x86/mm/init.c +++ linux-2.6/arch/x86/mm/init.c @@ -362,10 +362,16 @@ void __init init_mem_mapping(void) /* the ISA range is always mapped regardless of memory holes */ init_memory_mapping(0, ISA_END_ADDRESS); - /* xen has big range in reserved near end of ram, skip it at first */ - addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE, - PAGE_SIZE); - real_end = addr + PMD_SIZE; + /* + * xen has big range in reserved near end of ram, skip it at first. + * UEFI booting could have bunch of holes in memory map, try to + * skip usable range in those area, so could have pages for page + * table together, just make sure usable ranges blow real_end is + * 8MiB continuous at least. + */ + addr = memblock_find_in_range(ISA_END_ADDRESS, end, PMD_SIZE<<2, + PMD_SIZE); + real_end = addr + (PMD_SIZE<<2); /* step_size need to be small so pgt_buf from BRK could cover it */ step_size = PMD_SIZE;