Re: 2.6.39.1 immediately reboots/resets on EFI system

From: Yinghai Lu
Date: Tue Jun 07 2011 - 18:25:38 EST


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
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/