From patchwork Wed Dec 12 17:40:00 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Steve Capper X-Patchwork-Id: 1869121 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from merlin.infradead.org (merlin.infradead.org [205.233.59.134]) by patchwork1.kernel.org (Postfix) with ESMTP id D8AD33FC81 for ; Wed, 12 Dec 2012 17:43:54 +0000 (UTC) Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TiqI4-00021l-G2; Wed, 12 Dec 2012 17:40:16 +0000 Received: from service87.mimecast.com ([91.220.42.44]) by merlin.infradead.org with esmtp (Exim 4.76 #1 (Red Hat Linux)) id 1TiqI0-00021T-5V for linux-arm-kernel@lists.infradead.org; Wed, 12 Dec 2012 17:40:13 +0000 Received: from cam-owa2.Emea.Arm.com (fw-tnat.cambridge.arm.com [217.140.96.21]) by service87.mimecast.com; Wed, 12 Dec 2012 17:40:09 +0000 Received: from e103986-lin.cambridge.arm.com ([10.1.255.212]) by cam-owa2.Emea.Arm.com with Microsoft SMTPSVC(6.0.3790.3959); Wed, 12 Dec 2012 17:40:09 +0000 From: Steve Capper To: linux-arm-kernel@lists.infradead.org Subject: [RFC PATCH] ARM: Consider memblocks in mem_init and show_mem. Date: Wed, 12 Dec 2012 17:40:00 +0000 Message-Id: <1355334000-10198-1-git-send-email-steve.capper@arm.com> X-Mailer: git-send-email 1.7.9.5 X-OriginalArrivalTime: 12 Dec 2012 17:40:09.0608 (UTC) FILETIME=[BB30E880:01CDD88F] X-MC-Unique: 112121217400901701 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20121212_124012_547633_71049FA6 X-CRM114-Status: GOOD ( 13.85 ) X-Spam-Score: -2.6 (--) X-Spam-Report: SpamAssassin version 3.3.2 on merlin.infradead.org summary: Content analysis details: (-2.6 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [91.220.42.44 listed in list.dnswl.org] -0.0 SPF_PASS SPF: sender matches SPF record -1.9 BAYES_00 BODY: Bayes spam probability is 0 to 1% [score: 0.0000] Cc: Steve Capper , Michael Spang X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Sender: linux-arm-kernel-bounces@lists.infradead.org Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org This is based on Michael Spang's patch [1]; and is my attempt at applying the feedback from Russell [2]. With discontiguous memory (a requirement for running NUMA on some systems), membanks may not necessarily be representable as contiguous blocks of struct page *s. This patch updates the page scanning code in mem_init and show_mem to consider pages in the intersection of membanks and memblocks instead. We can't consider memblocks solely as under sparse memory configurations, contiguous physical membanks won't necessarily have a contiguous memory map (but may be merged into the same memblock). Only memory blocks in the "memory" region were considered as the "reserved" region was found to always overlap "memory"; all the memory banks are added with memblock_add (which adds to "memory") and no instances were found where memory was added to "reserved" then removed from "memory". In mem_init we are running on one CPU, and I can't see the memblocks changing whilst being enumerated. In show_mem, we can be running on multiple CPUs; whilst the memblock manipulation functions are annotated as __init, this doesn't stop memblocks being manipulated during bootup. I can't see any place where memblocks are removed or merged other than driver initialisation (memblock_steal) or boot memory initialisation. One consequence of using memblocks in show_mem, is that we are unable to define ARCH_DISCARD_MEMBLOCK. Any feedback would be welcome. Thanks, diff --git a/arch/arm/mm/init.c b/arch/arm/mm/init.c index ad722f1..abe4eae 100644 --- a/arch/arm/mm/init.c +++ b/arch/arm/mm/init.c @@ -94,36 +94,56 @@ void show_mem(unsigned int filter) { int free = 0, total = 0, reserved = 0; int shared = 0, cached = 0, slab = 0, i; - struct meminfo * mi = &meminfo; + struct meminfo *mi = &meminfo; + struct memblock_region *reg; printk("Mem-info:\n"); show_free_areas(filter); for_each_bank (i, mi) { struct membank *bank = &mi->bank[i]; - unsigned int pfn1, pfn2; - struct page *page, *end; - - pfn1 = bank_pfn_start(bank); - pfn2 = bank_pfn_end(bank); - - page = pfn_to_page(pfn1); - end = pfn_to_page(pfn2 - 1) + 1; - - do { - total++; - if (PageReserved(page)) - reserved++; - else if (PageSwapCache(page)) - cached++; - else if (PageSlab(page)) - slab++; - else if (!page_count(page)) - free++; - else - shared += page_count(page) - 1; - page++; - } while (page < end); + unsigned int sbank, ebank; + + sbank = bank_pfn_start(bank); + ebank = bank_pfn_end(bank); + + /* consider every memory block that intersects our memory bank */ + for_each_memblock(memory, reg) { + struct page *page, *end; + unsigned int pfn1, pfn2; + unsigned int sblock = memblock_region_memory_base_pfn(reg); + unsigned int eblock = memblock_region_memory_end_pfn(reg); + + /* we're beyond the membank */ + if (sblock >= ebank) + break; + + /* we're not yet at the membank */ + if (eblock <= sbank) + continue; + + /* take the intersection between bank and block */ + pfn1 = max(sblock, sbank); + pfn2 = min(eblock, ebank); + + page = pfn_to_page(pfn1); + end = pfn_to_page(pfn2 - 1) + 1; + + do { + total++; + if (PageReserved(page)) + reserved++; + else if (PageSwapCache(page)) + cached++; + else if (PageSlab(page)) + slab++; + else if (!page_count(page)) + free++; + else + shared += page_count(page) - 1; + page++; + } while (page < end); + } } printk("%d pages of RAM\n", total); @@ -619,22 +639,41 @@ void __init mem_init(void) for_each_bank(i, &meminfo) { struct membank *bank = &meminfo.bank[i]; - unsigned int pfn1, pfn2; - struct page *page, *end; - - pfn1 = bank_pfn_start(bank); - pfn2 = bank_pfn_end(bank); - - page = pfn_to_page(pfn1); - end = pfn_to_page(pfn2 - 1) + 1; - - do { - if (PageReserved(page)) - reserved_pages++; - else if (!page_count(page)) - free_pages++; - page++; - } while (page < end); + unsigned int sbank, ebank; + + sbank = bank_pfn_start(bank); + ebank = bank_pfn_end(bank); + + /* consider every memory block that intersects our memory bank */ + for_each_memblock(memory, reg) { + struct page *page, *end; + unsigned int pfn1, pfn2; + unsigned int sblock = memblock_region_memory_base_pfn(reg); + unsigned int eblock = memblock_region_memory_end_pfn(reg); + + /* we're beyond the membank */ + if (sblock >= ebank) + break; + + /* we're not yet at the membank */ + if (eblock <= sbank) + continue; + + /* take the intersection between bank and block */ + pfn1 = max(sblock, sbank); + pfn2 = min(eblock, ebank); + + page = pfn_to_page(pfn1); + end = pfn_to_page(pfn2 - 1) + 1; + + do { + if (PageReserved(page)) + reserved_pages++; + else if (!page_count(page)) + free_pages++; + page++; + } while (page < end); + } } /*