lkml.org 
[lkml]   [2008]   [Jan]   [15]   [last100]   RSS Feed
Views: [more markup]  [less markup]  [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    DateTue, 15 Jan 2008 12:39:47 +0100
    FromIngo Molnar <>
    SubjectRe: bugreport kernel panic on early stage, with HIGHMEM4G:
    * Denys Fedoryshchenko <denys@visp.net.lb> wrote:
    
    > Hi> > After physical memory upgrade from 3GB to 4GB (also it happens on 5GB) 
    > got kernel panic.> > Because it is happening on early stage and my machine doesn't contain 
    > serial port, i had to take photo. Kernel boots fine with 64GB highmem, 
    > no highmem, or highmem4G with limited memory by mem=3G. All dmesg 
    > attached. Also i attach dmidecode and lspci -vvv output, probably it 
    > will be useful.
    
    thanks for the detailed report, i think i know what's going on. Could 
    you try the patch below, does it fix your problem?
    
    this seems to be a SPARSEMEM bug which is present in v2.6.23 as well and 
    has probably been present ever since SPARSEMEM was added to 32-bit x86.
    
    There's a ~256MB hole in your e820 memory map (the pci aperture), which 
    causes the last 4 sparsemem sections (each covering 64MB of RAM) to be 
    not present - and they are thus missing from the sparsemem mem_map[] 
    too. The highmem init code on the other hand assumes that all pages are 
    in the mem_map[]:
    
     static void __init set_highmem_pages_init(int bad_ppro)
     {
            int pfn;
            for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
                    add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
    the pfn_to_page() is unconditional and dereferences to a NULL-ish 
    pointer which crashes your box. highend_pfn is what got miscalculated by 
    256 MB, so set_highmem_pages_init() tried to reference a non-existing 
    struct page - but it should still be robust enough against non-existent 
    pages.
    
    The patch below fixes this bug. Please also send a dmesg if you manage 
    to boot the box up fine, i've added a few debug printouts to confirm 
    this theory. (i'll figure out whether we need to clip highend_pfn as 
    well - but this patch alone should be good enough to fix the crash on 
    your box.)
    
    	Ingo
    
    ------------->
    Subject: x86: fix CONFIG_SPARSEMEM highmem init bug
    From: Ingo Molnar <mingo@elte.hu>
    fix CONFIG_SPARSEMEM highmem init bug.
    
    Signed-off-by: Ingo Molnar <mingo@elte.hu>
    ---
     arch/x86/mm/init_32.c |   43 ++++++++++++++++++++++++++++++++++++++++---
     mm/sparse.c           |    8 +++++++-
     2 files changed, 47 insertions(+), 4 deletions(-)
    Index: linux/arch/x86/mm/init_32.c
    ===================================================================
    --- linux.orig/arch/x86/mm/init_32.c
    +++ linux/arch/x86/mm/init_32.c
    @@ -321,11 +321,48 @@ extern void set_highmem_pages_init(int);
     static void __init set_highmem_pages_init(int bad_ppro)
     {
     	int pfn;
    -	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++)
    -		add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
    +
    +	printk("set_highmem_pages_init(bad_ppro:%d)\n", bad_ppro);
    +	printk("sizeof(struct page):        %d\n", sizeof(struct page));
    +	printk("sizeof(struct mem_section): %d\n", sizeof(struct mem_section));
    +	printk("PFN_SECTION_SHIFT:          %d\n", PFN_SECTION_SHIFT);
    +
    +	printk("mem_map: %p\n", mem_map);
    +	printk("  highstart_pfn: %9ld [page: %p]\n",
    +		highstart_pfn, pfn_to_page(highstart_pfn));
    +	printk("    highend_pfn: %9ld [page: %p]\n",
    +		highend_pfn, pfn_to_page(highend_pfn));
    +	printk("  highend_pfn-1: %9ld [page: %p]\n",
    +		highend_pfn-1, pfn_to_page(highend_pfn-1));
    +
    +	printk("NR_MEM_SECTIONS: %ld\n", NR_MEM_SECTIONS);
    +	printk("pfn_to_section_nr(highstart_pfn): %9ld\n",
    +		pfn_to_section_nr(highstart_pfn));
    +	printk("pfn_to_section_nr(highend_pfn):   %9ld\n",
    +		pfn_to_section_nr(highend_pfn));
    +	printk("pfn_to_section_nr(highend_pfn-1): %9ld\n",
    +		pfn_to_section_nr(highend_pfn-1));
    +
    +	printk("totalhigh_pages: %9ld\n", totalhigh_pages);
    +	printk(" totalram_pages: %9ld\n", totalram_pages);
    +
    +	for (pfn = highstart_pfn; pfn < highend_pfn; pfn++) {
    +		if (pfn_valid(pfn))
    +			add_one_highpage_init(pfn_to_page(pfn), pfn, bad_ppro);
    +		else {
    +			if (WARN_ON_ONCE(1)) {
    +				printk("bad pfn: %d\n", pfn);
    +				break;
    +			}
    +		}
    +	}
    +	printk("totalhigh_pages: %9ld\n", totalhigh_pages);
    +	printk(" totalram_pages: %9ld\n", totalram_pages);
    +
    +
     	totalram_pages += totalhigh_pages;
     }
    -#endif /* CONFIG_FLATMEM */
    +#endif /* CONFIG_NUMA */
     
     #else
     #define kmap_init() do { } while (0)
    Index: linux/mm/sparse.c
    ===================================================================
    --- linux.orig/mm/sparse.c
    +++ linux/mm/sparse.c
    @@ -295,9 +295,13 @@ void __init sparse_init(void)
     	struct page *map;
     	unsigned long *usemap;
     
    +	printk("sparse_init()\n");
     	for (pnum = 0; pnum < NR_MEM_SECTIONS; pnum++) {
    -		if (!present_section_nr(pnum))
    +		printk("section %2ld: ", pnum);
    +		if (!present_section_nr(pnum)) {
    +			printk("!present\n");
     			continue;
    +		}
     
     		map = sparse_early_mem_map_alloc(pnum);
     		if (!map)
    @@ -309,6 +313,8 @@ void __init sparse_init(void)
     
     		sparse_init_one_section(__nr_to_section(pnum), pnum, map,
     								usemap);
    +		printk("map: %p, usemap: %p [content: %08lx]\n",
    +			map, usemap, __nr_to_section(pnum)->section_mem_map);
     	}
     }
     
    
    
    
    \
     
     \ /
      Last update: 2008-01-15 12:43    [from the cache]
    ©2003-2008