From patchwork Mon Apr 3 02:24:34 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 9658751 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 624FD60237 for ; Mon, 3 Apr 2017 02:40:49 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 555F5283FB for ; Mon, 3 Apr 2017 02:40:49 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 49C9B28409; Mon, 3 Apr 2017 02:40:49 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 AAC7A283FB for ; Mon, 3 Apr 2017 02:40:48 +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:References: In-Reply-To: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:List-Owner; bh=6o7I5+6UVoDV60qKhYiL63c+hfKUY3/w/YcUnIax1a4=; b=WnSlgJ19jv291LnAwjOdaco8kN G+5NZdhcFr3PpmXRZVtsHTs1vAW47RBtBUVByV2M5VLiWpNQeE+sTUcfVninwKHk4+wWdCnsa5ET6 K9TaKU3yclDgho7g3CJAMC52gipjUx3hAdzUjRTmpiRQcyyojzV9K4IEcTQLXjOkt5f1T9gidF6Yg P/OT4t1+TBkG/uuCSt+pAxRRWrOUymaJ80fiwNnwtmVcLyBNGKVlXa9rj7sh5EL7DMYImqW5HpC5l BCFhr6YX5ergBdWuZ/Cl90j+/6/VQbyq05Fr5pMdujE+dWO1nIjzZi5Uw14Gz6Xdx+1Mh19GZ7MgN IM3Pni9Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1curvD-0006WV-Rd; Mon, 03 Apr 2017 02:40:47 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1curux-0006DQ-SN for linux-arm-kernel@bombadil.infradead.org; Mon, 03 Apr 2017 02:40:31 +0000 DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=infradead.org; s=merlin.20170209; h=References:In-Reply-To:Message-Id:Date: Subject:Cc:To:From:Sender:Reply-To:MIME-Version:Content-Type: Content-Transfer-Encoding:Content-ID:Content-Description:Resent-Date: Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:List-Id: List-Help:List-Unsubscribe:List-Subscribe:List-Post:List-Owner:List-Archive; bh=oFMgX6KF1hgZPf1rcFlqnBM99/VDvONMP2lZ2DIcgMI=; b=pZ3BSn47j7NMevSp9cZCnAnZA PfgEl08h5tEOkxnnbDMkMJWxUdnIDsgfd6rsQBUAdaxmZHeIc7X7hfFUI4XSPg0JgzwRzX/6Rjy5y 7v46Kew8dvEr2WglFrF4SGFJI7qJVS577bD18rZjs28Hu/AzS1bT+1JHouDm12NtuNCUblPHcaJ3Y JQorCEyZ0XM7cx88fTmnQuJo6Uu2uld5GF+fwVx+CY4r2i+r5cPunRPFTPymhuR167Yam9FVa2xLN 9hQ/EPld8qy425eXYIzyeE8i89ybCRw9hLl6KZ9SIGYu/jOViyi4OqhrwBM4rQD4rjL3u3VE0J/l2 GF+kRasJA==; Received: from mail-pg0-x22c.google.com ([2607:f8b0:400e:c05::22c]) by merlin.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1curdB-0004EA-NM for linux-arm-kernel@lists.infradead.org; Mon, 03 Apr 2017 02:22:11 +0000 Received: by mail-pg0-x22c.google.com with SMTP id x125so105479478pgb.0 for ; Sun, 02 Apr 2017 19:21:49 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=oFMgX6KF1hgZPf1rcFlqnBM99/VDvONMP2lZ2DIcgMI=; b=JRSycpry4Xc4mHGWiYDHlZOrdC1rL2Oxi9Iu16Hs6o583PwcqfIwjYeEajYJXvtlnI nH+f0UMqRF21f5gZHVLYWfof8qeDzBvEyJo8rGvcj3YiMn37umJTwLgkcGqZSXNjKBqY gXCqsb4neEpLms174MOLlcvUlnzrVA5ViDro0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=oFMgX6KF1hgZPf1rcFlqnBM99/VDvONMP2lZ2DIcgMI=; b=TTEKSSpI7m19OwbsI6AqTm1sbI5t51ZHZjx2v2Mw42rd/e7gwWRs6mLQHlWFiTpzCG MF9btx1cMDbkLqyYFJZCJcEkbNgqD/m/SKC+spdjI392wpZ53sB1BS+pxu5oGAxX5tgT hoJ7Yi1sdHP0ujcR7vy+Kfgrz0fktxq17PVAXVWdmBn6mr0+Os1yuYvwqkGRNZ3yL2/v a8EX9pDC+5fE03p4gGUwN14ZEcVjU1kluscTrjBBrfS4NVR8Ak+JoHfDlQ1GB96/k8DE oLjRupXnQu3ntachumufyBLTJMbsCgH0IM67IQCvaeCZIdOy0tUeHzeBfE06Heq2/0gC JDAw== X-Gm-Message-State: AFeK/H2glRhk1UYHTlcTx1GFu2eIGlun5vHdX3gd75VAbl8CErwT/knjpqaScO+7TodttQEh X-Received: by 10.99.219.21 with SMTP id e21mr15175912pgg.70.1491186107293; Sun, 02 Apr 2017 19:21:47 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id 140sm22105954pfa.58.2017.04.02.19.21.46 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Sun, 02 Apr 2017 19:21:46 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH v35 06/14] arm64: kdump: protect crash dump kernel memory Date: Mon, 3 Apr 2017 11:24:34 +0900 Message-Id: <20170403022440.12515-4-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.11.1 In-Reply-To: <20170403022139.12383-1-takahiro.akashi@linaro.org> References: <20170403022139.12383-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170402_222210_440670_CA3A3F9F X-CRM114-Status: GOOD ( 22.44 ) 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: mark.rutland@arm.com, panand@redhat.com, ard.biesheuvel@linaro.org, geoff@infradead.org, dwmw2@infradead.org, kexec@lists.infradead.org, Takahiro Akashi , james.morse@arm.com, bauerman@linux.vnet.ibm.com, sgoel@codeaurora.org, dyoung@redhat.com, linux-arm-kernel@lists.infradead.org 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 From: Takahiro Akashi arch_kexec_protect_crashkres() and arch_kexec_unprotect_crashkres() are meant to be called by kexec_load() in order to protect the memory allocated for crash dump kernel once the image is loaded. The protection is implemented by unmapping the relevant segments in crash dump kernel memory, rather than making it read-only as other archs do, to prevent coherency issues due to potential cache aliasing (with mismatched attributes). Page-level mappings are consistently used here so that we can change the attributes of segments in page granularity as well as shrink the region also in page granularity through /sys/kernel/kexec_crash_size, putting the freed memory back to buddy system. Signed-off-by: AKASHI Takahiro Reviewed-by: Ard Biesheuvel --- arch/arm64/kernel/machine_kexec.c | 32 +++++++++--- arch/arm64/mm/mmu.c | 103 ++++++++++++++++++++------------------ 2 files changed, 80 insertions(+), 55 deletions(-) diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c index bc96c8a7fc79..b63baa749609 100644 --- a/arch/arm64/kernel/machine_kexec.c +++ b/arch/arm64/kernel/machine_kexec.c @@ -14,7 +14,9 @@ #include #include +#include #include +#include #include "cpu-reset.h" @@ -22,8 +24,6 @@ extern const unsigned char arm64_relocate_new_kernel[]; extern const unsigned long arm64_relocate_new_kernel_size; -static unsigned long kimage_start; - /** * kexec_image_info - For debugging output. */ @@ -64,8 +64,6 @@ void machine_kexec_cleanup(struct kimage *kimage) */ int machine_kexec_prepare(struct kimage *kimage) { - kimage_start = kimage->start; - kexec_image_info(kimage); if (kimage->type != KEXEC_TYPE_CRASH && cpus_are_stuck_in_kernel()) { @@ -183,7 +181,7 @@ void machine_kexec(struct kimage *kimage) kexec_list_flush(kimage); /* Flush the new image if already in place. */ - if (kimage->head & IND_DONE) + if ((kimage != kexec_crash_image) && (kimage->head & IND_DONE)) kexec_segment_flush(kimage); pr_info("Bye!\n"); @@ -201,7 +199,7 @@ void machine_kexec(struct kimage *kimage) */ cpu_soft_restart(1, reboot_code_buffer_phys, kimage->head, - kimage_start, 0); + kimage->start, 0); BUG(); /* Should never get here. */ } @@ -210,3 +208,25 @@ void machine_crash_shutdown(struct pt_regs *regs) { /* Empty routine needed to avoid build errors. */ } + +void arch_kexec_protect_crashkres(void) +{ + int i; + + kexec_segment_flush(kexec_crash_image); + + for (i = 0; i < kexec_crash_image->nr_segments; i++) + set_memory_valid( + __phys_to_virt(kexec_crash_image->segment[i].mem), + kexec_crash_image->segment[i].memsz >> PAGE_SHIFT, 0); +} + +void arch_kexec_unprotect_crashkres(void) +{ + int i; + + for (i = 0; i < kexec_crash_image->nr_segments; i++) + set_memory_valid( + __phys_to_virt(kexec_crash_image->segment[i].mem), + kexec_crash_image->segment[i].memsz >> PAGE_SHIFT, 1); +} diff --git a/arch/arm64/mm/mmu.c b/arch/arm64/mm/mmu.c index 91502e36e6d9..0c429ec6fde8 100644 --- a/arch/arm64/mm/mmu.c +++ b/arch/arm64/mm/mmu.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -393,10 +395,28 @@ static void update_mapping_prot(phys_addr_t phys, unsigned long virt, flush_tlb_kernel_range(virt, virt + size); } -static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end) +static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, + phys_addr_t end, pgprot_t prot, int flags) +{ + __create_pgd_mapping(pgd, start, __phys_to_virt(start), end - start, + prot, early_pgtable_alloc, flags); +} + +void __init mark_linear_text_alias_ro(void) +{ + /* + * Remove the write permissions from the linear alias of .text/.rodata + */ + update_mapping_prot(__pa_symbol(_text), (unsigned long)lm_alias(_text), + (unsigned long)__init_begin - (unsigned long)_text, + PAGE_KERNEL_RO); +} + +static void __init map_mem(pgd_t *pgd) { phys_addr_t kernel_start = __pa_symbol(_text); phys_addr_t kernel_end = __pa_symbol(__init_begin); + struct memblock_region *reg; int flags = 0; if (debug_pagealloc_enabled()) @@ -405,30 +425,28 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end /* * Take care not to create a writable alias for the * read-only text and rodata sections of the kernel image. + * So temporarily mark them as NOMAP to skip mappings in + * the following for-loop */ + memblock_mark_nomap(kernel_start, kernel_end - kernel_start); +#ifdef CONFIG_KEXEC_CORE + if (crashk_res.end) + memblock_mark_nomap(crashk_res.start, + resource_size(&crashk_res)); +#endif - /* No overlap with the kernel text/rodata */ - if (end < kernel_start || start >= kernel_end) { - __create_pgd_mapping(pgd, start, __phys_to_virt(start), - end - start, PAGE_KERNEL, - early_pgtable_alloc, flags); - return; - } + /* map all the memory banks */ + for_each_memblock(memory, reg) { + phys_addr_t start = reg->base; + phys_addr_t end = start + reg->size; - /* - * This block overlaps the kernel text/rodata mappings. - * Map the portion(s) which don't overlap. - */ - if (start < kernel_start) - __create_pgd_mapping(pgd, start, - __phys_to_virt(start), - kernel_start - start, PAGE_KERNEL, - early_pgtable_alloc, flags); - if (kernel_end < end) - __create_pgd_mapping(pgd, kernel_end, - __phys_to_virt(kernel_end), - end - kernel_end, PAGE_KERNEL, - early_pgtable_alloc, flags); + if (start >= end) + break; + if (memblock_is_nomap(reg)) + continue; + + __map_memblock(pgd, start, end, PAGE_KERNEL, flags); + } /* * Map the linear alias of the [_text, __init_begin) interval @@ -440,37 +458,24 @@ static void __init __map_memblock(pgd_t *pgd, phys_addr_t start, phys_addr_t end * Note that contiguous mappings cannot be remapped in this way, * so we should avoid them here. */ - __create_pgd_mapping(pgd, kernel_start, __phys_to_virt(kernel_start), - kernel_end - kernel_start, PAGE_KERNEL, - early_pgtable_alloc, NO_CONT_MAPPINGS); -} + __map_memblock(pgd, kernel_start, kernel_end, + PAGE_KERNEL, NO_CONT_MAPPINGS); + memblock_clear_nomap(kernel_start, kernel_end - kernel_start); -void __init mark_linear_text_alias_ro(void) -{ +#ifdef CONFIG_KEXEC_CORE /* - * Remove the write permissions from the linear alias of .text/.rodata + * Use page-level mappings here so that we can shrink the region + * in page granularity and put back unused memory to buddy system + * through /sys/kernel/kexec_crash_size interface. */ - update_mapping_prot(__pa_symbol(_text), (unsigned long)lm_alias(_text), - (unsigned long)__init_begin - (unsigned long)_text, - PAGE_KERNEL_RO); -} - -static void __init map_mem(pgd_t *pgd) -{ - struct memblock_region *reg; - - /* map all the memory banks */ - for_each_memblock(memory, reg) { - phys_addr_t start = reg->base; - phys_addr_t end = start + reg->size; - - if (start >= end) - break; - if (memblock_is_nomap(reg)) - continue; - - __map_memblock(pgd, start, end); + if (crashk_res.end) { + __map_memblock(pgd, crashk_res.start, crashk_res.end + 1, + PAGE_KERNEL, + NO_BLOCK_MAPPINGS | NO_CONT_MAPPINGS); + memblock_clear_nomap(crashk_res.start, + resource_size(&crashk_res)); } +#endif } void mark_rodata_ro(void)