From patchwork Tue Jul 12 05:05:10 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 71784 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp276043qga; Mon, 11 Jul 2016 22:02:14 -0700 (PDT) X-Received: by 10.98.77.65 with SMTP id a62mr41206967pfb.128.1468299734488; Mon, 11 Jul 2016 22:02:14 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id gw3si633056pac.42.2016.07.11.22.02.14 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 11 Jul 2016 22:02:14 -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 1bMpol-0004kx-Nk; Tue, 12 Jul 2016 05:01:11 +0000 Received: from mail-pa0-x236.google.com ([2607:f8b0:400e:c03::236]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bMpoe-0004SO-Mz for linux-arm-kernel@lists.infradead.org; Tue, 12 Jul 2016 05:01:06 +0000 Received: by mail-pa0-x236.google.com with SMTP id hu1so2456666pad.3 for ; Mon, 11 Jul 2016 22:00:43 -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=TKoWTajL/Fu/wFwYrzty/Iyuhp7dR/d3w50bZqycoLM=; b=NCtm0yduF3M4snBG7IXfcfDJ/ZcJs0WdHnbQbrKZbAFQP89jFw1q0i4OFSoRrhKP3y cmA+o2YG6IA/9SROzrigmSc/IiIwfNdFUeBmlP3bmMlpNXFlQGauzJodiOxCUP4jZTFE jxuq1DhJN8t+FE3HOIe8ch7frQ6Q7qoHLIEWA= 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=TKoWTajL/Fu/wFwYrzty/Iyuhp7dR/d3w50bZqycoLM=; b=lIc8S8Kq7uNPksMdnL0rj1eEaSSo5+daKWdVhpru+tICjYrKjzNbgQ/icwgI+15Org upESudZedE7WZgUix5VO8owJx1Cwev0QcgiBRz+G36rjcI4dHGDC0tRJPQcynxqChNDd tIZEV5LrOKHyMqoS01xUPy9OINSpF5XjID7aba44zzm1Sz2jb7COLYhQuCoLeDh2dyHK vfH71ow73ShDp3bqCV8MWMvfpaV8yFQ7mjL2cpOvhtSSWoKTL+X7mC06wAdpyaZS5Y0q EGQY3Mk9Tq7Dcy36Uy4ezGgr5FzgE7pg3orAkMeXAqERKCvXUekmNhtrLigX8W0q/Q5x UsDA== X-Gm-Message-State: ALyK8tIxGZ4QesHh4N11MJERlzpQl6mYW4fFs8nYC2jZoanCS2yx/gdYH0iUwt7yaN910eny X-Received: by 10.66.161.132 with SMTP id xs4mr511467pab.140.1468299643357; Mon, 11 Jul 2016 22:00:43 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id b186sm6049036pfa.61.2016.07.11.22.00.42 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 11 Jul 2016 22:00:42 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH v22 4/8] arm64: kdump: add kdump support Date: Tue, 12 Jul 2016 14:05:10 +0900 Message-Id: <20160712050514.22307-5-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160712050514.22307-1-takahiro.akashi@linaro.org> References: <20160712050514.22307-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160711_220104_940119_05D39C17 X-CRM114-Status: GOOD ( 25.54 ) 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:236 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: mark.rutland@arm.com, geoff@infradead.org, kexec@lists.infradead.org, AKASHI Takahiro , robh+dt@kernel.org, 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 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 d8b296f..ad38b93 100644 --- a/arch/arm64/mm/init.c +++ b/arch/arm64/mm/init.c @@ -36,6 +36,7 @@ #include #include #include +#include #include #include @@ -189,6 +190,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 @@ -442,6 +494,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 */