From patchwork Thu Apr 14 11:57:17 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Leizhen (ThunderTown)" X-Patchwork-Id: 12813389 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id 21504C433EF for ; Thu, 14 Apr 2022 12:01:56 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20210309; h=Sender: Content-Transfer-Encoding:Content-Type:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:References:In-Reply-To: Message-ID:Date:Subject:CC:To:From:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=lMKswkSVxRFY+nEaO2VdSZJOY3MOa2llK689tcy+HHg=; b=QoPJf7MhUxTv+w FI3mM0HMxOCUG6ugRMseOieapqC0SIKZdGNOJxq9mGQVLNyjoRi7vc9pwz8kVpGgFHcgWFf4xY6Sj Dz/P6BgrOfFj1kYcXP0sHdvZN9BU8bsrqIcyQ6nCXNEWD/NYdZh7K/39jB33aby53V/EAWmYwQfqc 8hJDPg9fAQpYmYIeEsLLC6EPdfb63DTgY0bK6ihVZhnZkdUQTVvMVxoW8+s4dXk97jfSHqr7BTYAc xXKBAAnpD6F1UrRoq1XbxPez4KNRyiKr8Ospyr8YDAPqPIEMxU5M1dyZT4z3S3t0KH+oRqMgzVWJt rJPSkPNjblgY69hYgibw==; Received: from localhost ([::1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.94.2 #2 (Red Hat Linux)) id 1ney9U-005NNI-GQ; Thu, 14 Apr 2022 12:00:44 +0000 Received: from szxga02-in.huawei.com ([45.249.212.188]) by bombadil.infradead.org with esmtps (Exim 4.94.2 #2 (Red Hat Linux)) id 1ney7S-005MEN-3O; Thu, 14 Apr 2022 11:58:47 +0000 Received: from dggpemm500021.china.huawei.com (unknown [172.30.72.54]) by szxga02-in.huawei.com (SkyGuard) with ESMTP id 4KfHxR4tmvzgYmL; Thu, 14 Apr 2022 19:56:43 +0800 (CST) Received: from dggpemm500006.china.huawei.com (7.185.36.236) by dggpemm500021.china.huawei.com (7.185.36.109) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Thu, 14 Apr 2022 19:58:34 +0800 Received: from thunder-town.china.huawei.com (10.174.178.55) by dggpemm500006.china.huawei.com (7.185.36.236) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256) id 15.1.2375.24; Thu, 14 Apr 2022 19:58:33 +0800 From: Zhen Lei To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , , "H . Peter Anvin" , , Dave Young , Baoquan He , Vivek Goyal , Eric Biederman , , Catalin Marinas , "Will Deacon" , , Rob Herring , Frank Rowand , , Jonathan Corbet , CC: Zhen Lei , Randy Dunlap , Feng Zhou , Kefeng Wang , Chen Zhou , "John Donnelly" , Dave Kleikamp Subject: [PATCH v22 6/9] arm64: kdump: Use page-level mapping for the high memory of crashkernel Date: Thu, 14 Apr 2022 19:57:17 +0800 Message-ID: <20220414115720.1887-7-thunder.leizhen@huawei.com> X-Mailer: git-send-email 2.26.0.windows.1 In-Reply-To: <20220414115720.1887-1-thunder.leizhen@huawei.com> References: <20220414115720.1887-1-thunder.leizhen@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.174.178.55] X-ClientProxiedBy: dggems701-chm.china.huawei.com (10.3.19.178) To dggpemm500006.china.huawei.com (7.185.36.236) X-CFilter-Loop: Reflected X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20220414_045838_522647_69091F25 X-CRM114-Status: GOOD ( 21.24 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=archiver.kernel.org@lists.infradead.org If the crashkernel has both high memory above 4G and low memory under 4G, kexec always loads the content such as Imge and dtb to the high memory instead of the low memory. This means that only high memory requires write protection based on page-level mapping. The allocation of high memory does not depend on the DMA boundary. So we can reserve the high memory first even if the crashkernel reservation is deferred. Signed-off-by: Zhen Lei --- arch/arm64/mm/init.c | 84 ++++++++++++++++++++++++++++++++++++++++++++ arch/arm64/mm/mmu.c | 3 +- 2 files changed, 86 insertions(+), 1 deletion(-) diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 99d5539c13de3b1..b1b40b900fae170 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -90,6 +90,9 @@ phys_addr_t __ro_after_init arm64_dma_phys_limit; phys_addr_t __ro_after_init arm64_dma_phys_limit = PHYS_MASK + 1; #endif +static bool crash_high_mem_reserved __initdata; +static struct resource crashk_res_high; + /* Current arm64 boot protocol requires 2MB alignment */ #define CRASH_ALIGN SZ_2M @@ -128,6 +131,66 @@ static int __init reserve_crashkernel_low(unsigned long long low_size) return 0; } +static void __init reserve_crashkernel_high(void) +{ + unsigned long long crash_base, crash_size; + char *cmdline = boot_command_line; + int ret; + + if (!IS_ENABLED(CONFIG_KEXEC_CORE)) + return; + + /* crashkernel=X[@offset] */ + ret = parse_crashkernel(cmdline, memblock_phys_mem_size(), + &crash_size, &crash_base); + if (ret || !crash_size) { + ret = parse_crashkernel_high(cmdline, 0, &crash_size, &crash_base); + if (ret || !crash_size) + return; + } + + crash_size = PAGE_ALIGN(crash_size); + + /* + * For the case crashkernel=X, may fall back to reserve memory above + * 4G, make reservations here in advance. It will be released later if + * the region is successfully reserved under 4G. + */ + if (!crash_base) { + crash_base = memblock_phys_alloc_range(crash_size, CRASH_ALIGN, + crash_base, CRASH_ADDR_HIGH_MAX); + if (!crash_base) + return; + + crash_high_mem_reserved = true; + } + + /* Mark the memory range that requires page-level mappings */ + crashk_res.start = crash_base; + crashk_res.end = crash_base + crash_size - 1; +} + +static void __init hand_over_reserved_high_mem(void) +{ + crashk_res_high.start = crashk_res.start; + crashk_res_high.end = crashk_res.end; + + crashk_res.start = 0; + crashk_res.end = 0; +} + +static void __init take_reserved_high_mem(unsigned long long *crash_base, + unsigned long long *crash_size) +{ + *crash_base = crashk_res_high.start; + *crash_size = resource_size(&crashk_res_high); +} + +static void __init free_reserved_high_mem(void) +{ + memblock_phys_free(crashk_res_high.start, resource_size(&crashk_res_high)); +} + /* * reserve_crashkernel() - reserves memory for crash kernel * @@ -159,6 +222,8 @@ static void __init reserve_crashkernel(void) if (!IS_ENABLED(CONFIG_KEXEC_CORE)) return; + hand_over_reserved_high_mem(); + /* crashkernel=X[@offset] */ ret = parse_crashkernel(cmdline, memblock_phys_mem_size(), &crash_size, &crash_base); @@ -177,6 +242,11 @@ static void __init reserve_crashkernel(void) high = true; crash_max = CRASH_ADDR_HIGH_MAX; + + if (crash_high_mem_reserved) { + take_reserved_high_mem(&crash_base, &crash_size); + goto reserve_low; + } } fixed_base = !!crash_base; @@ -195,6 +265,11 @@ static void __init reserve_crashkernel(void) * reserved later. */ if (!fixed_base && (crash_max == CRASH_ADDR_LOW_MAX)) { + if (crash_high_mem_reserved) { + take_reserved_high_mem(&crash_base, &crash_size); + goto reserve_low; + } + crash_max = CRASH_ADDR_HIGH_MAX; goto retry; } @@ -212,6 +287,7 @@ static void __init reserve_crashkernel(void) * condition to make sure the crash low memory will be reserved. */ if ((crash_base >= CRASH_ADDR_LOW_MAX) || high) { +reserve_low: /* case #3 of crashkernel,low reservation */ if (!high) crash_low_size = DEFAULT_CRASH_KERNEL_LOW_SIZE; @@ -220,6 +296,12 @@ static void __init reserve_crashkernel(void) memblock_phys_free(crash_base, crash_size); return; } + } else if (crash_high_mem_reserved) { + /* + * The crash memory is successfully allocated under 4G, and the + * previously reserved high memory is no longer required. + */ + free_reserved_high_mem(); } pr_info("crashkernel reserved: 0x%016llx - 0x%016llx (%lld MB)\n", @@ -437,6 +519,8 @@ void __init arm64_memblock_init(void) if (!IS_ENABLED(CONFIG_ZONE_DMA) && !IS_ENABLED(CONFIG_ZONE_DMA32)) reserve_crashkernel(); + else + reserve_crashkernel_high(); high_memory = __va(memblock_end_of_DRAM() - 1) + 1; } diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 8c6666cbc7f2216..f84eca55b103d0c 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -531,7 +531,8 @@ static void __init map_mem(pgd_t *pgdp) if (crash_mem_map && (IS_ENABLED(CONFIG_ZONE_DMA) || IS_ENABLED(CONFIG_ZONE_DMA32))) eflags = NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS; - else if (crashk_res.end) + + if (crashk_res.end) memblock_mark_nomap(crashk_res.start, resource_size(&crashk_res)); #endif