From patchwork Wed Jul 6 07:52:22 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 71419 Delivered-To: patch@linaro.org Received: by 10.140.28.4 with SMTP id 4csp731041qgy; Wed, 6 Jul 2016 00:50:00 -0700 (PDT) X-Received: by 10.66.255.7 with SMTP id am7mr39828885pad.75.1467791400371; Wed, 06 Jul 2016 00:50:00 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id x133si2871217pfd.105.2016.07.06.00.50.00 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 06 Jul 2016 00:50:00 -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 1bKhZo-0006OW-T2; Wed, 06 Jul 2016 07:48:56 +0000 Received: from mail-pa0-x22f.google.com ([2607:f8b0:400e:c03::22f]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bKhZj-00062N-Kb for linux-arm-kernel@lists.infradead.org; Wed, 06 Jul 2016 07:48:53 +0000 Received: by mail-pa0-x22f.google.com with SMTP id dx3so9892365pab.2 for ; Wed, 06 Jul 2016 00:48:31 -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=kFawlYDJgLSQy3nze39lSCk2SoxAVr/z0xurwysMh+Q=; b=FkkTcA57ZLBrRB/EJEHv3DImKnhftOCTFReVfLaVzNACyGT3lrTqZ+q8dOQFzm3raX ftGTf6Kelo7Qup+VsxCj/02pMUCtzSqh82DjSWSAXciSxAXhonMkR4OIAK5FEjCJnZUl AAHrVP2K0in3+x++kYp+t0qWSrfoLtxFySW5E= 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=kFawlYDJgLSQy3nze39lSCk2SoxAVr/z0xurwysMh+Q=; b=XhvB3VC2Vw5fYLYz8gzwVIe2Vpa3LofkZH9GUwfYrM9+xbavFefylinuQotUDJcaRL 9G8vIELNII0MNXoypZhtA5FxVbf3uGWqJ61a6NmFEMRvAB7dkrgAp2HnTmgMTaTfoxOO UZHJjD8bU2izXJnSlOLIMOufPTucwrR+uZJPErDtX9sHbDz3YuFsBF9OuIGxza7wq23g 0q/AGA1A+ejZIx4+hM3GaZAiux8ZM7iOoMBT8FqqgZ0IeDY50+Pzu5lpMlKYuwDTcub/ EnwyQleB18WN92GJb2lfCC995ntmcmTtEVoGzO+f20/L62ZIX5oY0k4DdtPSReEu/oHP 8EgA== X-Gm-Message-State: ALyK8tIG4mrPjQyUS4ftoER0ECmpTe45Igv0MHTSVbkMULchmKkKXx8Wxc/M0HNE+AToX00/ X-Received: by 10.66.51.42 with SMTP id h10mr39620144pao.31.1467791310974; Wed, 06 Jul 2016 00:48:30 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id 78sm2196867pfm.43.2016.07.06.00.48.29 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Wed, 06 Jul 2016 00:48:30 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH v21 4/8] arm64: kdump: add kdump support Date: Wed, 6 Jul 2016 16:52:22 +0900 Message-Id: <20160706075226.27609-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160706075226.27609-1-takahiro.akashi@linaro.org> References: <20160706075226.27609-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160706_004851_975524_018CDEBB X-CRM114-Status: GOOD ( 25.45 ) X-Spam-Score: -2.7 (--) X-Spam-Report: SpamAssassin version 3.4.0 on bombadil.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_VALID Message has at least one valid DKIM or DK signature -0.1 DKIM_VALID_AU Message has a valid DKIM or DK signature from author's domain 0.1 DKIM_SIGNED Message has a DKIM or DK signature, not necessarily valid 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: geoff@infradead.org, kexec@lists.infradead.org, james.morse@arm.com, linux-arm-kernel@lists.infradead.org, AKASHI Takahiro 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 1b196bf..ad2c53e 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -675,6 +675,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 7700c0c..c13d3eb 100644 --- a/arch/arm64/kernel/Makefile +++ b/arch/arm64/kernel/Makefile @@ -48,6 +48,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/ 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 88fd99a..7e5844d 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -35,6 +35,7 @@ #include #include #include +#include #include #include @@ -136,6 +137,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 @@ -389,6 +441,8 @@ void __init arm64_memblock_init(void) reserve_crashkernel(); + reserve_elfcorehdr(); + early_init_fdt_scan_reserved_mem(); /* 4GB maximum for 32-bit only capable devices */