From patchwork Tue Oct 9 11:08:30 2018 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: James Morse X-Patchwork-Id: 10632245 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 C4E1C17E3 for ; Tue, 9 Oct 2018 11:09:04 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A3DD5289F4 for ; Tue, 9 Oct 2018 11:09:04 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 96109289FC; Tue, 9 Oct 2018 11:09:04 +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 D1A4C289F4 for ; Tue, 9 Oct 2018 11:09:03 +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:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version: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=DXG1xP/GPKZNZ8VBFLmtTimxTLisle4h+2TJ7bPSaUc=; b=k3QclPK5++rVvu wOtbROnNXk08D9oC9rtD8xq5J5Q3Wlq42+NNlQUNgx7ETPGixnuqMXpkqJYfY/jJY3kKgqWi4wSu9 +70R8adwLHFVN2H8k2DNMpv0+UvUF6Ne63N9gWDhkEaIGn/uJaFDQ5MwPALun3CUg4uHMZCNps1Hl f6jp1evKk5IqkT23Na4krP46R5mdWu1zwTxIdWAZYn48nZsgwQ86XocCSS5SQ9AGoAsNINz+d0N4o qOWyEp4dMhtcT9QkVw5MdKJDFsf541OttKucs/j0yvi5O4LYG4juqvZgJLdhVf23mKo7S4qXcetvp f0rayW3KkVPBXHZM7N+Q==; 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 1g9psm-0004M4-N3; Tue, 09 Oct 2018 11:08:56 +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 1g9psi-0004Jo-RR for linux-arm-kernel@lists.infradead.org; Tue, 09 Oct 2018 11:08:54 +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 0E655ED1; Tue, 9 Oct 2018 04:08:40 -0700 (PDT) Received: from melchizedek.cambridge.arm.com (melchizedek.cambridge.arm.com [10.1.196.46]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8902E3F5D3; Tue, 9 Oct 2018 04:08:38 -0700 (PDT) From: James Morse To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] arm64: Fix /proc/iomem for reserved but not memory regions Date: Tue, 9 Oct 2018 12:08:30 +0100 Message-Id: <20181009110830.13331-1-james.morse@arm.com> X-Mailer: git-send-email 2.19.0 MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20181009_040852_930868_93922CAD X-CRM114-Status: GOOD ( 17.56 ) 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 , Paolo Pisati , James Morse 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 We describe ranges of 'reserved' memory to userspace via /proc/iomem. commit 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem") updated the logic to export regions that were reserved because their contents should be preserved. This allowed kexec-tools to tell the difference between 'reserved' memory that must be preserved and not overwritten, (e.g. the ACPI tables), and 'nomap' memory that must not be touched without knowing the memory-attributes (e.g. RAS CPER regions). Because kexec-tools generates the kdump /proc/vmcore elf headers from this file, the difference matters for 'reserved' memory, which should be included in the /proc/vmcore, while 'nomap' should not. (previously we only described 'nomap', which meant kexec could overwrite 'reserved' memory by accident). The above commit 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 DT reserved-memory that was also carved out of the memory node. The ramoops description on hikey and dragonboard-410c both do this. This surprises reserve_memblock_reserved_regions() which finds a reserved-memory range wasn't previously described as memory. It generates a warning and describes the region as reserved. (adding this entry was expected to fail and return the conflicting memory resource) To work around this on systems with shipped DT files that do this, reserve_memblock_reserved_regions() 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. We walk the reserved_mem_region, using mem_idx as a cursor in the array of 'System RAM'. Adjacent memblock_reserved() regions will be merged, so we consider multiple System RAM regions for one span of memblock_reserved(). We don't always move the cursor as multiple memblock_reserved() regions may exist in one System RAM region. Fixes: 50d7ba36b916 ("arm64: export memblock_reserve()d regions via /proc/iomem") Reported-by: John Stultz Reported-by: Paolo Pisati CC: Akashi Takahiro CC: Ard Biesheuvel Signed-off-by: James Morse Tested-by: John Stultz Reviewed-by: James Morse Reported-by: John Stultz Reported-by: Paolo Pisati Reviewed-by: James Morse Signed-off-by: Will Deacon --- Changes since RFC: vastly improved commit message. 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;