On 06/08/2011 12:25 AM, Yinghai Lu wrote: > On 06/07/2011 05:22 AM, Maarten Lankhorst wrote: >> It seems the error still occurs when calling free_bootmem_late >> even if I only reserve blocks that haven't been reserved yet. > > please check this one. > > --- > arch/x86/platform/efi/efi.c | 2 +- > include/linux/mm.h | 2 ++ > mm/page_alloc.c | 32 ++++++++++++++++++++++++++++++++ > 3 files changed, 35 insertions(+), 1 deletion(-) > > Index: linux-2.6/arch/x86/platform/efi/efi.c > =================================================================== > --- linux-2.6.orig/arch/x86/platform/efi/efi.c > +++ linux-2.6/arch/x86/platform/efi/efi.c > @@ -368,7 +368,7 @@ static void __init efi_free_boot_service > md->type != EFI_BOOT_SERVICES_DATA) > continue; > > - free_bootmem_late(start, size); > + free_bootmem_late_with_active_regions(start, size); > } > } > > Index: linux-2.6/include/linux/mm.h > =================================================================== > --- linux-2.6.orig/include/linux/mm.h > +++ linux-2.6/include/linux/mm.h > @@ -1322,6 +1322,8 @@ extern void get_pfn_range_for_nid(unsign > extern unsigned long find_min_pfn_with_active_regions(void); > extern void free_bootmem_with_active_regions(int nid, > unsigned long max_low_pfn); > +void free_bootmem_late_with_active_regions(unsigned long addr, > + unsigned long size); > int add_from_early_node_map(struct range *range, int az, > int nr_range, int nid); > u64 __init find_memory_core_early(int nid, u64 size, u64 align, > Index: linux-2.6/mm/page_alloc.c > =================================================================== > --- linux-2.6.orig/mm/page_alloc.c > +++ linux-2.6/mm/page_alloc.c > @@ -3828,6 +3828,38 @@ void __init free_bootmem_with_active_reg > } > } > > +/** > + * free_bootmem_late_with_active_regions - Call free_bootmem_late for each active range > + * @addr: starting address of the range > + * @size: size of the range in bytes > + * > + * this function make sure on active regions only > + */ > +void __init free_bootmem_late_with_active_regions(unsigned long addr, > + unsigned long size) > +{ > + int i; > + int nid = MAX_NUMNODES; > + unsigned long start_pfn = PFN_UP(addr); > + unsigned long end_pfn = PFN_DOWN(addr + size); > + > + if (start_pfn >= end_pfn) > + return; > + > + for_each_active_range_index_in_nid(i, nid) { > + unsigned long common_start, common_end; > + > + common_start = max(start_pfn, early_node_map[i].start_pfn); > + common_end = min(end_pfn, early_node_map[i].end_pfn); > + > + if (common_start >= common_end) > + continue; > + > + free_bootmem_late(common_start << PAGE_SHIFT, > + (common_end - common_start) << PAGE_SHIFT); > + } > +} > + > #ifdef CONFIG_HAVE_MEMBLOCK > /* > * Basic iterator support. Return the last range of PFNs for a node > I applied this on top of 3.0-rc1 (with offsets), kernels boots but see now in dmesg output a new 'BUG: Bad page state in process swapper pfn:01800' see attached dmesg output. Jim