Hi, Recently We are testing stable kernel 3.10 on an ARM board. It failed to boot if we enabled CONFIG_SPARSEMEM config. Through the analysis, we found that mem_init() assumes the pages of different sections are continuous. But the truth is the pages of different sections are not continuous when CONFIG_SPARSEMEM is enabled. So now we have two ways to boot up when we enabled CONFIG_SPARSEMEM on an arm board. 1. In mem_init() and show_mem() compare pfn instead of page just like the patch in attachement. 2. Enable CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER when enabled CONFIG_SPARSEMEM. QUESTION: I want to know why CONFIG_SPARSEMEM_ALLOC_MEM_MAP_TOGETHER depends on x86_64 ? Whether we can enable it on an ARM board ? Or any other better solution ? Best regards!
>From c142b3157d4e0f9909076a24b6fe58c60afde0f3 Mon Sep 17 00:00:00 2001 From: Zhang Zhen <zhenzhang.zhang@xxxxxxxxxx> Date: Tue, 1 Jul 2014 14:59:19 +0800 Subject: [PATCH] sparse mem: compare pfn instead of page If CONFIG_SPARSEMEM is enabled, here the pages of different sections are not continuous. So we compare pfn instead of page. Signed-off-by: Zhang Zhen <zhenzhang.zhang@xxxxxxxxxx> --- arch/arm/mm/init.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 0ecc43f..a36caac 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -115,6 +115,9 @@ void show_mem(unsigned int filter) do { total++; +#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_MACH_HI1380) + page = pfn_to_page(pfn1); +#endif if (PageReserved(page)) reserved++; else if (PageSwapCache(page)) @@ -125,8 +128,13 @@ void show_mem(unsigned int filter) free++; else shared += page_count(page) - 1; +#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_MACH_HI1380) + pfn1++; + } while (pfn1 < pfn2); +#else page++; } while (page < end); +#endif } printk("%d pages of RAM\n", total); @@ -619,12 +627,21 @@ void __init mem_init(void) end = pfn_to_page(pfn2 - 1) + 1; do { +#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_MACH_HI1380) + page = pfn_to_page(pfn1); +#endif if (PageReserved(page)) reserved_pages++; else if (!page_count(page)) free_pages++; + +#if defined(CONFIG_SPARSEMEM) && defined(CONFIG_MACH_HI1380) + pfn1++; + } while (pfn1 < pfn2); +#else page++; } while (page < end); +#endif } /* -- 1.8.1.2