From patchwork Tue Aug 9 01:56:12 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 73507 Delivered-To: patch@linaro.org Received: by 10.140.29.52 with SMTP id a49csp247671qga; Mon, 8 Aug 2016 18:53:02 -0700 (PDT) X-Received: by 10.66.159.170 with SMTP id xd10mr34116271pab.41.1470707582711; Mon, 08 Aug 2016 18:53:02 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id er10si39869194pac.38.2016.08.08.18.53.02 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Mon, 08 Aug 2016 18:53:02 -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 1bWwCw-0004BG-Mu; Tue, 09 Aug 2016 01:51:54 +0000 Received: from mail-pa0-x22c.google.com ([2607:f8b0:400e:c03::22c]) by bombadil.infradead.org with esmtps (Exim 4.85_2 #1 (Red Hat Linux)) id 1bWwCP-0003fd-H3 for linux-arm-kernel@lists.infradead.org; Tue, 09 Aug 2016 01:51:26 +0000 Received: by mail-pa0-x22c.google.com with SMTP id iw10so136585pac.2 for ; Mon, 08 Aug 2016 18:51:01 -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=jABP0fM1/t9RNx0r+BrxqJZM1QmkHTO0HpMjmviKKXA=; b=LwU6Qli44uluqiEC05eRlfmwBMcEO6uTBbN364at0lW38+3TsBM9lQXasV+UIDMoST CPyeKt7rlWM2A2Z4pBs/t5/9iztOX4jBZ1dAyKvnyFXD5ttj+Dqh7sJqRQob6WT75cV1 hwKEwYV3e8/ucOE5bBlRrdm+K1ieUHcM5Vpfo= 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=jABP0fM1/t9RNx0r+BrxqJZM1QmkHTO0HpMjmviKKXA=; b=GUDo6k/5s0lwx1NzRkiJ+iJIrHoAJunkXxk3YnNw0WHcCjL1gnVmOaW+qKSOJ81Wfn UpCuGGVjkxzN8I56cwflpDQ4+vZeU1Hb/yjuik4q5tD2/ELBUZUM/7FB12/jzdIVQVwz AVeZbeAEPWUIEpGeI5iahoDPnGoVVFSL3u2ASsfporR36cAgXSkT1iD532O+z4cky/Yt 9Yd82gzdZ/0qcxYeooOsdjPmnWvbzkssILG9CGoueI1tNPYMwxIGhXcjr+omzE+gGhaM VMp6n99E+A/q1UwVI6JeqpN2bzhnVtSVVrfzWOGQ11rhZtOT0Rad11af05/yfOasiuqF ieqg== X-Gm-Message-State: AEkoouv69dKLaEjj4s7ME/fxKoD2jOHQo73RltsBcs1hAEVVN/uv2rs9nJK5KncjdSRQP15J X-Received: by 10.67.15.8 with SMTP id fk8mr38277844pad.19.1470707460601; Mon, 08 Aug 2016 18:51:00 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id m24sm50991665pfi.34.2016.08.08.18.50.59 (version=TLS1_2 cipher=AES128-SHA bits=128/128); Mon, 08 Aug 2016 18:50:59 -0700 (PDT) From: AKASHI Takahiro To: catalin.marinas@arm.com, will.deacon@arm.com Subject: [PATCH v24 5/9] arm64: kdump: add kdump support Date: Tue, 9 Aug 2016 10:56:12 +0900 Message-Id: <20160809015615.28527-3-takahiro.akashi@linaro.org> X-Mailer: git-send-email 2.9.0 In-Reply-To: <20160809015615.28527-1-takahiro.akashi@linaro.org> References: <20160809015248.28414-2-takahiro.akashi@linaro.org> <20160809015615.28527-1-takahiro.akashi@linaro.org> X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160808_185121_962495_500DA830 X-CRM114-Status: GOOD ( 25.92 ) 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:22c 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 , 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 69c8787..9ede54b 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -682,6 +682,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 14f7b65..f1cbfc8 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/ 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 e3771c4..bba1e39 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();