Hi Matt, FYI, starting from this commit, the kernel immediately reboots in my kvm boot tests.. Thanks, Fengguang commit a790068f4435a053fa16562eceed520f9b027c41 Author: Matt Fleming Date: Mon Mar 5 14:21:35 2012 +0000 x86, efi: Fixup efi_ioremap() breakage Don't map holes. * Is the e820 map the correct memory map to use? * Is it OK to call find_early_table_space multiple times? * Do we need add_efi_memmap anymore? Unconditionally do it? * Should we reduce freq of printk(init_memory_mapping);? * Are there parts of the memmap not in the e820 map? * Do we even need to map ACPI stuff? is it ioremap'd? * Is it save to reserve pagetables in init_memory_mapping(), are the other callers (gart_iommu) called after bootmem? Signed-off-by: Matt Fleming diff --git a/arch/x86/include/asm/page_types.h b/arch/x86/include/asm/page_types.h index bce688d..4f95f23 100644 --- a/arch/x86/include/asm/page_types.h +++ b/arch/x86/include/asm/page_types.h @@ -51,8 +51,9 @@ static inline phys_addr_t get_max_mapped(void) return (phys_addr_t)max_pfn_mapped << PAGE_SHIFT; } -extern unsigned long init_memory_mapping(unsigned long start, - unsigned long end); +extern unsigned long init_memory_mapping(void); +extern unsigned long __init_memory_mapping(unsigned long start, + unsigned long end); extern void initmem_init(void); extern void free_initmem(void); diff --git a/arch/x86/kernel/amd_gart_64.c b/arch/x86/kernel/amd_gart_64.c index b1e7c7f..f52ced2 100644 --- a/arch/x86/kernel/amd_gart_64.c +++ b/arch/x86/kernel/amd_gart_64.c @@ -769,7 +769,7 @@ int __init gart_iommu_init(void) if (end_pfn > max_low_pfn_mapped) { start_pfn = (aper_base>>PAGE_SHIFT); - init_memory_mapping(start_pfn<>PAGE_SHIFT, E820_RESERVED_EFI); - if (efi_end > end_pfn) - end_pfn = efi_end; - } -#endif - - max_low_pfn_mapped = init_memory_mapping(0, end_pfn << PAGE_SHIFT); - max_pfn_mapped = max_low_pfn_mapped; + /* max_low_pfn_mapped is updated here */ + max_pfn_mapped = init_memory_mapping(); #ifdef CONFIG_X86_64 if (max_pfn > max_low_pfn) { - max_pfn_mapped = init_memory_mapping(1UL<<32, - max_pfn<> PAGE_SHIFT; } +/* + * Traverse the E820 memory map and add RAM/ACPI/EFI regions to the + * initial memory mapping. + */ +unsigned long __init_refok init_memory_mapping(void) +{ + struct e820entry *entry; + unsigned long last_pfn_mapped = 0; + unsigned long start, end; + int i; + + /* Map the legacy region until we fix all drivers */ + __init_memory_mapping(0, 1 << 20); + + for (i = 0; i < e820.nr_map; i++) { + entry = &e820.map[i]; + start = entry->addr; + end = start + entry->size; + + /* We've already mapped below 1MB */ + if (end < (1 << 20)) + continue; + + if (start < (1 << 20)) + start = 1 << 20; +#ifdef CONFIG_X86_32 + /* + * The map is sorted, so bail once we hit a region + * that's above max_low_pfn. + */ + if (start >= max_low_pfn << PAGE_SHIFT) + break; + + if (end > max_low_pfn << PAGE_SHIFT) + end = max_low_pfn << PAGE_SHIFT; +#endif + switch (entry->type) { + case E820_RAM: + case E820_RESERVED_EFI: + case E820_ACPI: + case E820_NVS: + last_pfn_mapped = __init_memory_mapping(start, end); + break; + default: + continue; + } + + if (end <= max_low_pfn << PAGE_SHIFT) + max_low_pfn_mapped = last_pfn_mapped; + } + + return last_pfn_mapped; +} /* * devmem_is_allowed() checks to see if /dev/mem access to a certain address diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c index 436a030..e86e370 100644 --- a/arch/x86/mm/init_64.c +++ b/arch/x86/mm/init_64.c @@ -659,7 +659,7 @@ int arch_add_memory(int nid, u64 start, u64 size) unsigned long nr_pages = size >> PAGE_SHIFT; int ret; - last_mapped_pfn = init_memory_mapping(start, start + size); + last_mapped_pfn = __init_memory_mapping(start, start + size); if (last_mapped_pfn > max_pfn_mapped) max_pfn_mapped = last_mapped_pfn; diff --git a/arch/x86/platform/efi/efi.c b/arch/x86/platform/efi/efi.c index 264cc6e..ef0a725 100644 --- a/arch/x86/platform/efi/efi.c +++ b/arch/x86/platform/efi/efi.c @@ -573,8 +573,7 @@ void __init efi_init(void) printk(KERN_WARNING "Kernel-defined memdesc doesn't match the one from EFI!\n"); - if (add_efi_memmap) - do_add_efi_memmap(); + do_add_efi_memmap(); #ifdef CONFIG_X86_32 x86_platform.get_wallclock = efi_get_time;