From patchwork Tue Jul 26 07:56:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 72780 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp1550102qga; Tue, 26 Jul 2016 00:58:33 -0700 (PDT) X-Received: by 10.98.198.136 with SMTP id x8mr10737467pfk.103.1469519911632; Tue, 26 Jul 2016 00:58:31 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id m187si5912490pfb.130.2016.07.26.00.58.31 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 26 Jul 2016 00:58:31 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) client-ip=2001:1868:205::9; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org designates 2001:1868:205::9 as permitted sender) smtp.mailfrom=linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org; dmarc=fail (p=NONE dis=NONE) header.from=linaro.org Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.85_2 #1 (Red Hat Linux)) id 1bRxEy-0004eO-P1; Tue, 26 Jul 2016 07:57:24 +0000 Received: from merlin.infradead.org ([2001:4978:20e::2]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bRxBP-00012j-8G for linux-arm-kernel@bombadil.infradead.org; Tue, 26 Jul 2016 07:53:43 +0000 Received: from mail-pa0-x22f.google.com ([2607:f8b0:400e:c03::22f]) by merlin.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bRxBN-0006Tg-3v for linux-arm-kernel@lists.infradead.org; Tue, 26 Jul 2016 07:53:41 +0000 Received: by mail-pa0-x22f.google.com with SMTP id fi15so69719713pac.1 for ; Tue, 26 Jul 2016 00:53:20 -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=1tvZyR6UhIH5bp+gjNnCnRRI+wcgTqm0EeZ03AIBz+s=; b=RL2753LJ5eWW4qdk6EtUyhJiurv+cSffDrHiQ/4Lnl4jQQf3xhQgvohdsYenhTdnAt O/ZxV8PjRtq7t3RtP1lqZUBQKrZPF3PkclqfrB5cIEz1z1XyrFQFc4Ols1t0Y0j2vX9T yDmnKKlHYwL98bnhGF0nzXzaIIfnzPHmpQO3E= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1tvZyR6UhIH5bp+gjNnCnRRI+wcgTqm0EeZ03AIBz+s=; b=DC/aiKbQJyjbm5DEdyamvKv6ocDOz4Of1sSb129P3T5hUqPIYvb+h2rD28rKsn+Clq 0zy0KDJP3eEaub0hT7GoiDRGfgy5EIwWxJTek54XK6StRYU1uicGo4r0CINZpW8HZctP QnuCNJ/DPRy0Mge/u1NMCMrPEEFOF3+bWcq67UEw4gJ920t76BzKaZMdZrBYuAf9WyZ+ phJRF41Q0TbfMaakUuhkoiS8nYZUHP83VHGWyGjuqT/DficLmyFFr1H5AYnHQzbdYhQO si8HZ38FCfKmHOdibJrkift7ZzjQXHiylse5donbeKtomteds20HeWKkoce2SBfdUGFJ rZXQ== X-Gm-Message-State: AEkoouvD9iQZ16SQY2aC1D3M4x/m56sVJ8+g29KJkbYQjBckYx5pPXGCDIQRQ2f0BM0QyrPV X-Received: by 10.67.7.9 with SMTP id cy9mr32418067pad.155.1469519598974; Tue, 26 Jul 2016 00:53:18 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id f3sm45343767pff.26.2016.07.26.00.53.17 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Tue, 26 Jul 2016 00:53:18 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH v23 5/9] arm64: kdump: add kdump support Date: Tue, 26 Jul 2016 16:56:56 +0900 Message-Id: <20160726075659.2290-6-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160726075659.2290-1-takahiro.akashi@linaro.org> References: <20160726075659.2290-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160726_035341_226590_2A2B3DFD X-CRM114-Status: GOOD ( 29.61 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.4.1 on merlin.infradead.org summary: Content analysis details: (-2.7 points) pts rule name description ---- ---------------------- -------------------------------------------------- -0.7 RCVD_IN_DNSWL_LOW RBL: Sender listed at http://www.dnswl.org/, low trust [2607:f8b0:400e:c03:0:0:0:22f 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] 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain -0.1 DKIM_VALID Message has at least one valid DKIM or DK signature X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.20 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: mark.rutland@arm.com, geoff@infradead.org, kexec@lists.infradead.org, AKASHI Takahiro , james.morse@arm.com, bauerman@linux.vnet.ibm.com, dyoung@redhat.com, linux-arm-kernel@lists.infradead.org MIME-Version: 1.0 Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org On crash dump kernel, all the information about primary kernel's system memory (core image) is available in elf core header. The primary kernel will set aside this header with reserve_elfcorehdr() at boot time and inform crash dump kernel of its location via a new device-tree property, "linux,elfcorehdr". Please note that all other architectures use traditional "elfcorehdr=" kernel parameter for this purpose. Then crash dump kernel will access the primary kernel's memory with copy_oldmem_page(), which reads one page by ioremap'ing it since it does not reside in linear mapping on crash dump kernel. We also need our own elfcorehdr_read() here since the header is placed within crash dump kernel's usable memory. Signed-off-by: AKASHI Takahiro --- arch/arm64/Kconfig | 11 +++++++ arch/arm64/kernel/Makefile | 1 + arch/arm64/kernel/crash_dump.c | 71 ++++++++++++++++++++++++++++++++++++++++++ arch/arm64/mm/init.c | 54 ++++++++++++++++++++++++++++++++ 4 files changed, 137 insertions(+) create mode 100644 arch/arm64/kernel/crash_dump.c -- 2.9.0 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index ac4746f..0aa521d 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -678,6 +678,17 @@ config KEXEC but it is independent of the system firmware. And like a reboot you can start any kernel with it, not just Linux. +config CRASH_DUMP + bool "Build kdump crash kernel" + help + Generate crash dump after being started by kexec. This should + be normally only set in special crash dump kernels which are + loaded in the main kernel with kexec-tools into a specially + reserved region and then later executed after a crash by + kdump/kexec. + + For more details see Documentation/kdump/kdump.txt + config XEN_DOM0 def_bool y depends on XEN diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile index 0b9e49a..9e11910 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -47,6 +47,7 @@ arm64-obj-$(CONFIG_RANDOMIZE_BASE) += kaslr.o arm64-obj-$(CONFIG_HIBERNATION) += hibernate.o hibernate-asm.o arm64-obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o \ cpu-reset.o +arm64-obj-$(CONFIG_CRASH_DUMP) += crash_dump.o obj-y += $(arm64-obj-y) vdso/ probes/ obj-m += $(arm64-obj-m) diff --git a/arch/arm64/kernel/crash_dump.c b/arch/arm64/kernel/crash_dump.c new file mode 100644 index 0000000..2dc54d1 --- /dev/null +++ b/arch/arm64/kernel/crash_dump.c @@ -0,0 +1,71 @@ +/* + * Routines for doing kexec-based kdump + * + * Copyright (C) 2014 Linaro Limited + * Author: AKASHI Takahiro + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include +#include +#include +#include +#include + +/** + * copy_oldmem_page() - copy one page from old kernel memory + * @pfn: page frame number to be copied + * @buf: buffer where the copied page is placed + * @csize: number of bytes to copy + * @offset: offset in bytes into the page + * @userbuf: if set, @buf is in a user address space + * + * This function copies one page from old kernel memory into buffer pointed by + * @buf. If @buf is in userspace, set @userbuf to %1. Returns number of bytes + * copied or negative error in case of failure. + */ +ssize_t copy_oldmem_page(unsigned long pfn, char *buf, + size_t csize, unsigned long offset, + int userbuf) +{ + void *vaddr; + + if (!csize) + return 0; + + vaddr = ioremap_cache(__pfn_to_phys(pfn), PAGE_SIZE); + if (!vaddr) + return -ENOMEM; + + if (userbuf) { + if (copy_to_user(buf, vaddr + offset, csize)) { + iounmap(vaddr); + return -EFAULT; + } + } else { + memcpy(buf, vaddr + offset, csize); + } + + iounmap(vaddr); + + return csize; +} + +/** + * elfcorehdr_read - read from ELF core header + * @buf: buffer where the data is placed + * @csize: number of bytes to read + * @ppos: address in the memory + * + * This function reads @count bytes from elf core header which exists + * on crash dump kernel's memory. + */ +ssize_t elfcorehdr_read(char *buf, size_t count, u64 *ppos) +{ + memcpy(buf, phys_to_virt((phys_addr_t)*ppos), count); + return count; +} diff --git a/arch/arm64/mm/init.c b/arch/arm64/mm/init.c index 8699a8ea..f415104 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -186,6 +187,57 @@ static void __init reserve_crashkernel(void) } #endif /* CONFIG_KEXEC_CORE */ +#ifdef CONFIG_CRASH_DUMP +static int __init early_init_dt_scan_elfcorehdr(unsigned long node, + const char *uname, int depth, void *data) +{ + const __be32 *reg; + int len; + + if (depth != 1 || strcmp(uname, "chosen") != 0) + return 0; + + reg = of_get_flat_dt_prop(node, "linux,elfcorehdr", &len); + if (!reg || (len < (dt_root_addr_cells + dt_root_size_cells))) + return 1; + + elfcorehdr_addr = dt_mem_next_cell(dt_root_addr_cells, ®); + elfcorehdr_size = dt_mem_next_cell(dt_root_size_cells, ®); + + return 1; +} + +/* + * reserve_elfcorehdr() - reserves memory for elf core header + * + * This function reserves elf core header given in "elfcorehdr=" kernel + * command line parameter. This region contains all the information about + * primary kernel's core image and is used by a dump capture kernel to + * access the system memory on primary kernel. + */ +static void __init reserve_elfcorehdr(void) +{ + of_scan_flat_dt(early_init_dt_scan_elfcorehdr, NULL); + + if (!elfcorehdr_size) + return; + + if (memblock_is_region_reserved(elfcorehdr_addr, elfcorehdr_size)) { + pr_warn("elfcorehdr is overlapped\n"); + return; + } + + memblock_reserve(elfcorehdr_addr, elfcorehdr_size); + + pr_info("Reserving %lldKB of memory at 0x%llx for elfcorehdr\n", + elfcorehdr_size >> 10, elfcorehdr_addr); +} +#else +static void __init reserve_elfcorehdr(void) +{ + ; +} +#endif /* CONFIG_CRASH_DUMP */ /* * Return the maximum physical address for ZONE_DMA (DMA_BIT_MASK(32)). It * currently assumes that for memory starting above 4G, 32-bit devices will @@ -444,6 +496,8 @@ void __init arm64_memblock_init(void) reserve_crashkernel(); + reserve_elfcorehdr(); + dma_contiguous_reserve(arm64_dma_phys_limit); memblock_allow_resize();