From patchwork Wed Jun 15 08:14:02 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: AKASHI Takahiro X-Patchwork-Id: 70090 Delivered-To: patch@linaro.org Received: by 10.140.106.246 with SMTP id e109csp2443647qgf; Wed, 15 Jun 2016 01:11:23 -0700 (PDT) X-Received: by 10.66.168.13 with SMTP id zs13mr2501653pab.68.1465978283331; Wed, 15 Jun 2016 01:11:23 -0700 (PDT) Return-Path: Received: from bombadil.infradead.org (bombadil.infradead.org. [2001:1868:205::9]) by mx.google.com with ESMTPS id xa6si324326pab.117.2016.06.15.01.11.23 for (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 15 Jun 2016 01:11:23 -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.80.1 #2 (Red Hat Linux)) id 1bD5tT-0005kx-92; Wed, 15 Jun 2016 08:09:47 +0000 Received: from mail-pf0-x235.google.com ([2607:f8b0:400e:c00::235]) by bombadil.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1bD5tO-0005dT-9H for linux-arm-kernel@lists.infradead.org; Wed, 15 Jun 2016 08:09:44 +0000 Received: by mail-pf0-x235.google.com with SMTP id i123so2744618pfg.0 for ; Wed, 15 Jun 2016 01:09:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=date:from:to:cc:subject:message-id:mail-followup-to:references :mime-version:content-disposition:in-reply-to:user-agent; bh=jbadMP7tJu2K8wKsofoNM2l/QOv6Avw4X5IT+qZccsM=; b=bBdqTuB40OLSdSACj9w2fDOL7pTLTkZHBKJKfo1GW8NBX4+t1jP65NgmHF0qCAo0cC uhE2GOKFkWKVa6I31b1XabMMrbHEZigTtqYrjA9qJ/D9OyVZD1Ul5HwDBxkimT0OvZnL kvW7zyM9ZeOs2asOq6WLW+DZK6fmax19u0GRY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:date:from:to:cc:subject:message-id :mail-followup-to:references:mime-version:content-disposition :in-reply-to:user-agent; bh=jbadMP7tJu2K8wKsofoNM2l/QOv6Avw4X5IT+qZccsM=; b=G9J9wdb3eZApLhZXXNU5gXi8y0LrE29mLSRQ6lPWu069op3ltWBtu8bhE+ZS5bOD6t pla5/6/fwWiFWZjXIRYCzOD8/C138QK+Nj/WNvEMExvA2h5CLDzkuaSjK1R7PLtfz6Xn cZyaEFYIVOYQvb3o9QudUwZ426nizkuyUCMmIVQMsGVFkQBR6sxI+LGDQud6cV8OB0KN HitfllEaHxD2zW8kqDX/B95nVO7NajqysmHC83e90X8AtmrGLSn1ydAoNMxJe2W0Ya5H My+OraXeVZxsZMGdF2kmiKWPuvqk8t11B1inn8DrlkzOrTHPJlHZExYjknJr+irHTcRB Ssnw== X-Gm-Message-State: ALyK8tIDgl94TpH8FLDy8s/OMrecH8mDvXbQH/UjBjT1hJdVPFEpiFcS6NZnfcF9ec2Z+fOQ X-Received: by 10.98.32.65 with SMTP id g62mr2558769pfg.12.1465978161178; Wed, 15 Jun 2016 01:09:21 -0700 (PDT) Received: from linaro.org ([121.95.100.191]) by smtp.googlemail.com with ESMTPSA id t10sm22489017pan.34.2016.06.15.01.09.18 (version=TLSv1/SSLv3 cipher=OTHER); Wed, 15 Jun 2016 01:09:20 -0700 (PDT) Date: Wed, 15 Jun 2016 17:14:02 +0900 From: AKASHI Takahiro To: Geoff Levand Subject: Re: [PATCH v18 03/13] arm64/kexec: Add core kexec support Message-ID: <20160615081401.GO20774@linaro.org> Mail-Followup-To: AKASHI Takahiro , Geoff Levand , Catalin Marinas , Will Deacon , marc.zyngier@arm.com, Mark Rutland , James Morse , kexec@lists.infradead.org, linux-arm-kernel@lists.infradead.org References: <84e50e4043a2061e0f5d9273f55e158c59754af0.1465502767.git.geoff@infradead.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <84e50e4043a2061e0f5d9273f55e158c59754af0.1465502767.git.geoff@infradead.org> User-Agent: Mutt/1.5.21 (2010-09-15) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20160615_010942_605848_CD4A377E X-CRM114-Status: GOOD ( 36.07 ) 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:c00:0:0:0:235 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 , marc.zyngier@arm.com, Catalin Marinas , Will Deacon , James Morse , kexec@lists.infradead.org, linux-arm-kernel@lists.infradead.org Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patch=linaro.org@lists.infradead.org Geoff, On Thu, Jun 09, 2016 at 08:08:44PM +0000, Geoff Levand wrote: > Add three new files, kexec.h, machine_kexec.c and relocate_kernel.S to the > arm64 architecture that add support for the kexec re-boot mechanism > (CONFIG_KEXEC) on arm64 platforms. > > Signed-off-by: Geoff Levand > --- > arch/arm64/Kconfig | 10 ++ > arch/arm64/include/asm/kexec.h | 48 ++++++++++ > arch/arm64/kernel/Makefile | 2 + > arch/arm64/kernel/machine_kexec.c | 185 ++++++++++++++++++++++++++++++++++++ > arch/arm64/kernel/relocate_kernel.S | 131 +++++++++++++++++++++++++ > include/uapi/linux/kexec.h | 1 + > 6 files changed, 377 insertions(+) > create mode 100644 arch/arm64/include/asm/kexec.h > create mode 100644 arch/arm64/kernel/machine_kexec.c > create mode 100644 arch/arm64/kernel/relocate_kernel.S > > diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig > index 5a0a691..330786d 100644 > --- a/arch/arm64/Kconfig > +++ b/arch/arm64/Kconfig > @@ -664,6 +664,16 @@ config PARAVIRT_TIME_ACCOUNTING > > If in doubt, say N here. > > +config KEXEC > + depends on PM_SLEEP_SMP > + select KEXEC_CORE > + bool "kexec system call" > + ---help--- > + kexec is a system call that implements the ability to shutdown your > + current kernel, and to start another kernel. It is like a reboot > + but it is independent of the system firmware. And like a reboot > + you can start any kernel with it, not just Linux. > + > config XEN_DOM0 > def_bool y > depends on XEN > diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h > new file mode 100644 > index 0000000..04744dc > --- /dev/null > +++ b/arch/arm64/include/asm/kexec.h > @@ -0,0 +1,48 @@ > +/* > + * kexec for arm64 > + * > + * Copyright (C) Linaro. > + * Copyright (C) Huawei Futurewei Technologies. > + * > + * 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. > + */ > + > +#ifndef _ARM64_KEXEC_H > +#define _ARM64_KEXEC_H > + > +/* Maximum physical address we can use pages from */ > + > +#define KEXEC_SOURCE_MEMORY_LIMIT (-1UL) > + > +/* Maximum address we can reach in physical address mode */ > + > +#define KEXEC_DESTINATION_MEMORY_LIMIT (-1UL) > + > +/* Maximum address we can use for the control code buffer */ > + > +#define KEXEC_CONTROL_MEMORY_LIMIT (-1UL) > + > +#define KEXEC_CONTROL_PAGE_SIZE 4096 > + > +#define KEXEC_ARCH KEXEC_ARCH_AARCH64 > + > +#ifndef __ASSEMBLY__ > + > +/** > + * crash_setup_regs() - save registers for the panic kernel > + * > + * @newregs: registers are saved here > + * @oldregs: registers to be saved (may be %NULL) > + */ > + > +static inline void crash_setup_regs(struct pt_regs *newregs, > + struct pt_regs *oldregs) > +{ > + /* Empty routine needed to avoid build errors. */ > +} > + > +#endif /* __ASSEMBLY__ */ > + > +#endif > diff --git a/arch/arm64/kernel/Makefile b/arch/arm64/kernel/Makefile > index 2173149..7700c0c 100644 > --- a/arch/arm64/kernel/Makefile > +++ b/arch/arm64/kernel/Makefile > @@ -46,6 +46,8 @@ arm64-obj-$(CONFIG_ARM64_ACPI_PARKING_PROTOCOL) += acpi_parking_protocol.o > arm64-obj-$(CONFIG_PARAVIRT) += paravirt.o > 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 > > obj-y += $(arm64-obj-y) vdso/ > obj-m += $(arm64-obj-m) > diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c > new file mode 100644 > index 0000000..05f7c21 > --- /dev/null > +++ b/arch/arm64/kernel/machine_kexec.c > @@ -0,0 +1,185 @@ > +/* > + * kexec for arm64 > + * > + * Copyright (C) Linaro. > + * Copyright (C) Huawei Futurewei Technologies. > + * > + * 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 > + > +#include > +#include > +#include > +#include > + > +#include "cpu-reset.h" > + > +/* Global variables for the arm64_relocate_new_kernel routine. */ > +extern const unsigned char arm64_relocate_new_kernel[]; > +extern const unsigned long arm64_relocate_new_kernel_size; > + > +static unsigned long kimage_start; > + > +void machine_kexec_cleanup(struct kimage *kimage) > +{ > + /* Empty routine needed to avoid build errors. */ > +} > + > +/** > + * machine_kexec_prepare - Prepare for a kexec reboot. > + * > + * Called from the core kexec code when a kernel image is loaded. > + * Forbid loading a kexec kernel if we have no way of hotplugging cpus or cpus > + * are stuck in the kernel. This avoids a panic once we hit machine_kexec(). > + */ > +int machine_kexec_prepare(struct kimage *kimage) > +{ > + kimage_start = kimage->start; > + > + if (kimage->type != KEXEC_TYPE_CRASH) { > + if (cpus_are_stuck_in_kernel()) { > + pr_err("Can't kexec: failed CPUs are stuck in the kernel.\n"); > + return -EBUSY; > + } > + > + if (num_online_cpus() > 1) { > +#ifdef CONFIG_HOTPLUG_CPU > + /* any_cpu as we don't mind being preempted */ > + int any_cpu = raw_smp_processor_id(); > + > + if (cpu_ops[any_cpu]->cpu_die) > + return 0; > +#endif /* CONFIG_HOTPLUG_CPU */ > + > + pr_err("Can't kexec: no mechanism to offline secondary CPUs.\n"); > + return -EBUSY; > + } > + } > + > + return 0; > +} > + > +/** > + * kexec_list_flush - Helper to flush the kimage list to PoC. > + */ > +static void kexec_list_flush(struct kimage *kimage) > +{ > + kimage_entry_t *entry; > + unsigned int flag; > + > + for (entry = &kimage->head, flag = 0; flag != IND_DONE; entry++) { > + void *addr = kmap(phys_to_page(*entry & PAGE_MASK)); > + > + flag = *entry & IND_FLAGS; I found a bug here when I tested the kernel *without* CONFIG_SPARSEMEM_VMEMMAP. We need to check 'flag == IND_DONE' first before calculating phys_to_page(*entry & PAGE_MASK), otherwise we will see a kernel page fault (around the address 0x0) in case of IND_DONE. This bug was harmless with CONFIG_SPARSEMEM_VMEMMAP because phys_to_page() macro doesn't contain any memory access and 'addr' can be bogus but never used in IND_DONE. See my fix. (As James mentioned before, we may use phys_to_virt() instead of kmap() here.) Thanks, -Takahiro AKASHI -- 2.8.1 _______________________________________________ linux-arm-kernel mailing list linux-arm-kernel@lists.infradead.org http://lists.infradead.org/mailman/listinfo/linux-arm-kernel ===8<=== >From b814922d74bcd1746265fa0fcdb7fc6f4cb1515e Mon Sep 17 00:00:00 2001 From: AKASHI Takahiro Date: Wed, 15 Jun 2016 16:32:21 +0900 Subject: [PATCH] arm64: kexec: bugfix --- arch/arm64/kernel/machine_kexec.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kernel/machine_kexec.c b/arch/arm64/kernel/machine_kexec.c index 0d99fde..ea8e5fe 100644 --- a/arch/arm64/kernel/machine_kexec.c +++ b/arch/arm64/kernel/machine_kexec.c @@ -124,23 +124,22 @@ static void kexec_list_flush(struct kimage *kimage) { kimage_entry_t *entry; unsigned int flag; + void *addr; - for (entry = &kimage->head, flag = 0; flag != IND_DONE; entry++) { - void *addr = kmap(phys_to_page(*entry & PAGE_MASK)); - + for (entry = &kimage->head; ; entry++) { flag = *entry & IND_FLAGS; + if (flag == IND_DONE) + break; + + addr = kmap(phys_to_page(*entry & PAGE_MASK)); switch (flag) { case IND_INDIRECTION: entry = (kimage_entry_t *)addr - 1; - __flush_dcache_area(addr, PAGE_SIZE); - break; - case IND_DESTINATION: - break; case IND_SOURCE: __flush_dcache_area(addr, PAGE_SIZE); break; - case IND_DONE: + case IND_DESTINATION: break; default: BUG();