From patchwork Mon Sep 10 14:16:36 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Morse X-Patchwork-Id: 10594207 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id D7FF914BD for ; Mon, 10 Sep 2018 14:17:24 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C6BB028F89 for ; Mon, 10 Sep 2018 14:17:24 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id BADC128F9A; Mon, 10 Sep 2018 14:17:24 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-2.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,MAILING_LIST_MULTI,RCVD_IN_DNSWL_NONE autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 289BD28F89 for ; Mon, 10 Sep 2018 14:17:24 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From:Reply-To:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To: References:List-Owner; bh=L4F55u5YT+GYay19QPKc1hOTTn5/3yjUHGfXciMYej4=; b=sTd H4Op9FwnmAqbpXofGulegFi9qjY7sq7WNJZB6DFQHIvuHPZ1eLP3npNJVgtMQl3bB6qBmg+Qxx1dx /kUw9m5p0YZW3tWHPACHJkCWq4DRZs4Bh4C1Dm4xzqZSRfM2wgfWw/HM6JhJLBw2shzEj7ICn6HMA KOLbLTz7xtU+zXo+bpEJvR6gE2gJWxCvslTKmilT1oeDntBZ7rGcuDTisKQZIQeHzR7QppbKYr34X PIrDrkSjWR3M7dTuS9R2ec6aq/7dWtxw8wl4Z08+Gl8+o26oUgfEzTc1+po2ox4sGiNvjp94jtCe7 yRKCTeCDaLHW1yod2MXb+cCBDnhhdwQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fzMzx-0008Bu-Bb; Mon, 10 Sep 2018 14:17:05 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1fzMzq-00081n-Ft for linux-arm-kernel@lists.infradead.org; Mon, 10 Sep 2018 14:17:01 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id E143C80D; Mon, 10 Sep 2018 07:16:44 -0700 (PDT) Received: from melchizedek.Emea.Arm.com (melchizedek.Emea.Arm.com [10.4.12.81]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id 8B6383F557; Mon, 10 Sep 2018 07:16:43 -0700 (PDT) From: James Morse To: linux-arm-kernel@lists.infradead.org Subject: [RFC/PATCH] arm64: Fix /proc/iomem for reserved but not memory regions Date: Mon, 10 Sep 2018 15:16:36 +0100 Message-Id: <20180910141636.21813-1-james.morse@arm.com> X-Mailer: git-send-email 2.18.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20180910_071658_638897_B6F5309B X-CRM114-Status: GOOD ( 15.60 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Ard Biesheuvel , Catalin Marinas , Will Deacon , Akashi Takahiro , John Stultz , James Morse MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP commit 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem") wrongly assumed that memblock_reserve() would not be used to reserve regions that aren't memory. It turns out, this is exactly what early_init_dt_reserve_memory_arch() will do if it finds a reservation that was also carved out of the memory node. reserve_memblock_reserved_regions() now needs to cope with reserved regions that aren't memory, which means we must walk two lists at once. We can't use walk_system_ram_res() and reserve_region_with_split() together, as the former hands its callback a copied resource on the stack, where as the latter expects the in-tree resource to be provided. Allocate an array of struct resources during request_standard_resources() so that we have all the 'System RAM' regions on hand. Increasing the mem_idx cursor is optional as multiple memblock_reserved() regions may exist in one System RAM region. Because adjacent memblock_reserved() regions will be merged, we also need to consider multiple System RAM regions for one span of memblock_reserved() address space. Fixes: 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem") Reported-by: John Stultz CC: Akashi Takahiro CC: Ard Biesheuvel Signed-off-by: James Morse Tested-by: John Stultz --- John, any chance you could give this a test on the platform that the warning fires on? Thanks! arch/arm64/kernel/setup.c | 50 ++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 19 deletions(-) diff --git a/arch/arm64/kernel/setup.c b/arch/arm64/kernel/setup.c index 5b4fac434c84..952c2b126882 100644 --- a/arch/arm64/kernel/setup.c +++ b/arch/arm64/kernel/setup.c @@ -64,6 +64,9 @@ #include #include +static int num_standard_resources; +static struct resource *standard_resources; + phys_addr_t __fdt_pointer __initdata; /* @@ -206,14 +209,19 @@ static void __init request_standard_resources(void) { struct memblock_region *region; struct resource *res; + unsigned long i = 0; kernel_code.start = __pa_symbol(_text); kernel_code.end = __pa_symbol(__init_begin - 1); kernel_data.start = __pa_symbol(_sdata); kernel_data.end = __pa_symbol(_end - 1); + num_standard_resources = memblock.memory.cnt; + standard_resources = alloc_bootmem_low(num_standard_resources * + sizeof(*standard_resources)); + for_each_memblock(memory, region) { - res = alloc_bootmem_low(sizeof(*res)); + res = &standard_resources[i++]; if (memblock_is_nomap(region)) { res->name = "reserved"; res->flags = IORESOURCE_MEM; @@ -244,8 +252,11 @@ static void __init request_standard_resources(void) static int __init reserve_memblock_reserved_regions(void) { phys_addr_t start, end, roundup_end = 0; - struct resource *mem, *res; - u64 i; + struct resource *mem; + u64 i, mem_idx = 0; + + if (!standard_resources) + return 0; for_each_reserved_mem_region(i, &start, &end) { if (end <= roundup_end) @@ -255,24 +266,25 @@ static int __init reserve_memblock_reserved_regions(void) end = __pfn_to_phys(PFN_UP(end)) - 1; roundup_end = end; - res = kzalloc(sizeof(*res), GFP_ATOMIC); - if (WARN_ON(!res)) - return -ENOMEM; - res->start = start; - res->end = end; - res->name = "reserved"; - res->flags = IORESOURCE_MEM; + while (start > standard_resources[mem_idx].end) { + mem_idx++; + if (mem_idx >= num_standard_resources) + return 0; /* no more 'System RAM' */ + } + do { + mem = &standard_resources[mem_idx]; - mem = request_resource_conflict(&iomem_resource, res); - /* - * We expected memblock_reserve() regions to conflict with - * memory created by request_standard_resources(). - */ - if (WARN_ON_ONCE(!mem)) - continue; - kfree(res); + if (mem->start > end) + continue; /* doesn't overlap with memory */ + + start = max(start, mem->start); + reserve_region_with_split(mem, start, + min(end, mem->end), + "reserved"); - reserve_region_with_split(mem, start, end, "reserved"); + if (mem->end < end) + mem_idx++; + } while (mem->end < end && mem_idx < num_standard_resources); } return 0;