Hi Russell, By reading the code of show_mem(), I found that there is an assumption that the page structs must be continuous for each bank:
for_each_bank (i, mi) { ... page = pfn_to_page(pfn1); end = pfn_to_page(pfn2 - 1) + 1; do { ... page++; <-- pageframe must be continuous ... } while (page < end); ... } Therefore, a bank must be fully contained in a section in sparse memory mode, because page frames are allocated section by section (in sparse_init()). However, I didn't find other code which enforces this assumption. Instead, in arm_memory_present (arch/arm/mm/init.c), it seems that a bank may contain more than one section: arm_memory_present: ... for_each_memblock(memory, reg) memory_present(0, memblock_region_memory_base_pfn(reg), memblock_region_memory_end_pfn(reg)); ... memory_present: ... for (pfn = start; pfn < end; pfn += PAGES_PER_SECTION) { ... } ... Therefore, would you please consider the following patch, which removes the assumption that a bank must be fully contained in one section? =========================== >From b2c4bb5807c755d92274e11bb00cc548fea62242 Mon Sep 17 00:00:00 2001 From: Wang Nan <wangn...@huawei.com> Date: Thu, 2 Jan 2014 13:20:02 +0800 Subject: [PATCH] use pfn_to_page in show_mem If a bank spans into different sections, the page structures of the bank may not continous. This patch uses pfn_to_page to recompute the address of struct page in show_mem from pfn, makes it to collect correct information even if a bank spans into different sections. Signed-off-by: Wang Nan <wangn...@huawei.com> --- arch/arm/mm/init.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index 1f7b19a..3078e5a 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -97,16 +97,14 @@ void show_mem(unsigned int filter) for_each_bank (i, mi) { struct membank *bank = &mi->bank[i]; - unsigned int pfn1, pfn2; - struct page *page, *end; + unsigned int pfn, pfn_end; + struct page *page; - pfn1 = bank_pfn_start(bank); - pfn2 = bank_pfn_end(bank); - - page = pfn_to_page(pfn1); - end = pfn_to_page(pfn2 - 1) + 1; + pfn = bank_pfn_start(bank); + pfn_end = bank_pfn_end(bank); do { + page = pfn_to_page(pfn); total++; if (PageReserved(page)) reserved++; @@ -118,8 +116,8 @@ void show_mem(unsigned int filter) free++; else shared += page_count(page) - 1; - page++; - } while (page < end); + pfn++; + } while (pfn < pfn_end); } printk("%d pages of RAM\n", total); -- 1.8.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/