From patchwork Mon Sep 11 06:47:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Dave Young X-Patchwork-Id: 9946713 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 491F96035D for ; Mon, 11 Sep 2017 06:49:18 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 386E728B0E for ; Mon, 11 Sep 2017 06:49:18 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 2D08B28B10; Mon, 11 Sep 2017 06:49:18 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-4.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 3B0FF28B0E for ; Mon, 11 Sep 2017 06:49:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:In-Reply-To:MIME-Version:References: Message-ID:Subject:To:From:Date:Reply-To:Content-ID:Content-Description: Resent-Date:Resent-From:Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID: List-Owner; bh=mELlY328Ohpi7cha3qoltcQL0X6xMNZlcSBGIf+ypB0=; b=VCuGd18M1TXhC0 lF1C9V69Ot5h8chtDCyMTVK16apLIQkDV16gMXgcf4y+eiWlfzjZZ/QpssQF0Gi7DLQb3ESlLSDuj S7plZ0ijeOhP/Xunj0Yce9mdoMZ3nGllUrk/GlTX7xhNCH3VUzcT+szPQ4X30q9rQ/mIyJiwwabTh ePJSaf3cB6KdUE72ogXC4d3lHfF8SNK2BLJYfnSmTxMTYUU5GvgY6ruBwHGLC+qpiNsIu6FDSWxZx XmaZ6O13SjjHXt90NcSnIwKtVkaSgTKUh5nApiG15YoQc7R9vUKdwP7oBJVSfHYloN7VeBAZD7xzJ siVG69oi9uqq5KKrBZKQ==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1drIWg-0008Kt-OF; Mon, 11 Sep 2017 06:48:58 +0000 Received: from mx1.redhat.com ([209.132.183.28]) by bombadil.infradead.org with esmtps (Exim 4.87 #1 (Red Hat Linux)) id 1drIWD-00087N-Q8; Mon, 11 Sep 2017 06:48:32 +0000 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 36C1EC0BAA0A; Mon, 11 Sep 2017 06:48:06 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mx1.redhat.com 36C1EC0BAA0A Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; dmarc=none (p=none dis=none) header.from=redhat.com Authentication-Results: ext-mx07.extmail.prod.ext.phx2.redhat.com; spf=fail smtp.mailfrom=dyoung@redhat.com Received: from dhcp-128-65.nay.redhat.com (ovpn-12-101.pek2.redhat.com [10.72.12.101]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 4550F4DA29; Mon, 11 Sep 2017 06:47:58 +0000 (UTC) Date: Mon, 11 Sep 2017 14:47:54 +0800 From: Dave Young To: AKASHI Takahiro Subject: Re: [PATCH 6/9] arm64: kexec_file: load initrd, device-tree and purgatory segments Message-ID: <20170911064754.GA7332@dhcp-128-65.nay.redhat.com> References: <20170908031616.17916-1-takahiro.akashi@linaro.org> <20170908031616.17916-7-takahiro.akashi@linaro.org> MIME-Version: 1.0 Content-Disposition: inline In-Reply-To: <20170908031616.17916-7-takahiro.akashi@linaro.org> User-Agent: Mutt/1.8.3 (2017-05-23) X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Greylist: Sender IP whitelisted, not delayed by milter-greylist-4.5.16 (mx1.redhat.com [10.5.110.31]); Mon, 11 Sep 2017 06:48:06 +0000 (UTC) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170910_234829_913567_550847BC X-CRM114-Status: GOOD ( 29.54 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: herbert@gondor.apana.org.au, bhe@redhat.com, ard.biesheuvel@linaro.org, catalin.marinas@arm.com, will.deacon@arm.com, linux-kernel@vger.kernel.org, kexec@lists.infradead.org, dhowells@redhat.com, arnd@arndb.de, linux-arm-kernel@lists.infradead.org, mpe@ellerman.id.au, bauerman@linux.vnet.ibm.com, akpm@linux-foundation.org, davem@davemloft.net, vgoyal@redhat.com Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP Hi, On 09/08/17 at 12:16pm, AKASHI Takahiro wrote: > load_other_segments() sets up and adds all the memory segments necessary > other than kernel, including initrd, device-tree blob and purgatory. > Most of the code was borrowed from kexec-tools' counterpart. > > In addition, arch_kexec_image_probe(), arch_kexec_image_load() and > arch_kexec_kernel_verify_sig() are added as stubs for supporting multiple > types of kernel image formats. > > Signed-off-by: AKASHI Takahiro > Cc: Catalin Marinas > Cc: Will Deacon > --- > arch/arm64/include/asm/kexec.h | 19 +++ > arch/arm64/kernel/machine_kexec_file.c | 264 +++++++++++++++++++++++++++++++++ > 2 files changed, 283 insertions(+) > create mode 100644 arch/arm64/kernel/machine_kexec_file.c > > diff --git a/arch/arm64/include/asm/kexec.h b/arch/arm64/include/asm/kexec.h > index e17f0529a882..d74dc49670ad 100644 > --- a/arch/arm64/include/asm/kexec.h > +++ b/arch/arm64/include/asm/kexec.h > @@ -93,6 +93,25 @@ static inline void crash_prepare_suspend(void) {} > static inline void crash_post_resume(void) {} > #endif > > +#ifdef CONFIG_KEXEC_FILE > +#define ARCH_HAS_KIMAGE_ARCH > + > +struct kimage_arch { > + void *dtb_buf; > +}; > + > +struct kimage; > + > +extern int setup_dtb(struct kimage *image, > + unsigned long initrd_load_addr, unsigned long initrd_len, > + char *cmdline, unsigned long cmdline_len, > + char **dtb_buf, size_t *dtb_buf_len); > +extern int load_other_segments(struct kimage *image, > + unsigned long kernel_load_addr, > + char *initrd, unsigned long initrd_len, > + char *cmdline, unsigned long cmdline_len); > +#endif > + > #endif /* __ASSEMBLY__ */ > > #endif > diff --git a/arch/arm64/kernel/machine_kexec_file.c b/arch/arm64/kernel/machine_kexec_file.c > new file mode 100644 > index 000000000000..a6d2c006b4f7 > --- /dev/null > +++ b/arch/arm64/kernel/machine_kexec_file.c > @@ -0,0 +1,264 @@ > +/* > + * kexec_file for arm64 > + * > + * Copyright (C) 2017 Linaro Limited > + * Author: AKASHI Takahiro > + * > + * Most code is derived from arm64 port of kexec-tools > + * > + * 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. > + */ > + > +#define pr_fmt(fmt) "kexec_file: " fmt > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +static int __dt_root_addr_cells; > +static int __dt_root_size_cells; > + > +static struct kexec_file_ops *kexec_file_loaders[0]; > + > +int arch_kexec_kernel_image_probe(struct kimage *image, void *buf, > + unsigned long buf_len) > +{ > + struct kexec_file_ops *fops; > + int i, ret; > + > + for (i = 0; i < ARRAY_SIZE(kexec_file_loaders); i++) { > + fops = kexec_file_loaders[i]; > + if (!fops || !fops->probe) > + continue; > + > + ret = fops->probe(buf, buf_len); > + if (!ret) { > + image->fops = fops; > + return 0; > + } > + } > + > + return -ENOEXEC; > +} > + > +void *arch_kexec_kernel_image_load(struct kimage *image) > +{ > + if (!image->fops || !image->fops->load) > + return ERR_PTR(-ENOEXEC); > + > + return image->fops->load(image, image->kernel_buf, > + image->kernel_buf_len, image->initrd_buf, > + image->initrd_buf_len, image->cmdline_buf, > + image->cmdline_buf_len); > +} > + > +int arch_kimage_file_post_load_cleanup(struct kimage *image) > +{ > + vfree(image->arch.dtb_buf); > + image->arch.dtb_buf = NULL; > + > + vfree(image->arch.elf_headers); > + image->arch.elf_headers = NULL; > + image->arch.elf_headers_sz = 0; > + > + if (!image->fops || !image->fops->cleanup) > + return 0; > + > + return image->fops->cleanup(image->image_loader_data); > +} > + > +#ifdef CONFIG_KEXEC_VERIFY_SIG > +int arch_kexec_kernel_verify_sig(struct kimage *image, void *kernel, > + unsigned long kernel_len) > +{ > + if (!image->fops || !image->fops->verify_sig) { > + pr_debug("kernel loader does not support signature verification.\n"); > + return -EKEYREJECTED; > + } > + > + return image->fops->verify_sig(kernel, kernel_len); > +} arch_kexec_kernel_verify_sig now be duplicated so it can be put in the general function in kexec_file.c Also the probe and load function are also duplicated, they can be moved to common code as well. The x86 load function can be cleaned up with removing the vfree callback. --- arch/x86/kernel/machine_kexec_64.c | 3 --- 1 file changed, 3 deletions(-) > +#endif > + > +int arch_kexec_walk_mem(struct kexec_buf *kbuf, int (*func)(u64, u64, void *)) > +{ > + if (kbuf->image->type == KEXEC_TYPE_CRASH) > + return walk_iomem_res_desc(crashk_res.desc, > + IORESOURCE_SYSTEM_RAM | IORESOURCE_BUSY, > + crashk_res.start, crashk_res.end, > + kbuf, func); > + else if (kbuf->top_down) > + return walk_system_ram_res_rev(0, ULONG_MAX, kbuf, func); > + else > + return walk_system_ram_res(0, ULONG_MAX, kbuf, func); > +} > + > +int setup_dtb(struct kimage *image, > + unsigned long initrd_load_addr, unsigned long initrd_len, > + char *cmdline, unsigned long cmdline_len, > + char **dtb_buf, size_t *dtb_buf_len) > +{ > + char *buf = NULL; > + size_t buf_size; > + int nodeoffset; > + u64 value; > + int range_len; > + int ret; > + > + /* duplicate dt blob */ > + buf_size = fdt_totalsize(initial_boot_params); > + range_len = (__dt_root_addr_cells + __dt_root_size_cells) * sizeof(u32); > + > + if (initrd_load_addr) > + buf_size += fdt_prop_len("initrd-start", sizeof(u64)) > + + fdt_prop_len("initrd-end", sizeof(u64)); > + > + if (cmdline) > + buf_size += fdt_prop_len("bootargs", cmdline_len + 1); > + > + buf = vmalloc(buf_size); > + if (!buf) { > + ret = -ENOMEM; > + goto out_err; > + } > + > + ret = fdt_open_into(initial_boot_params, buf, buf_size); > + if (ret) > + goto out_err; > + > + nodeoffset = fdt_path_offset(buf, "/chosen"); > + if (nodeoffset < 0) > + goto out_err; > + > + /* add bootargs */ > + if (cmdline) { > + ret = fdt_setprop(buf, nodeoffset, "bootargs", > + cmdline, cmdline_len + 1); > + if (ret) > + goto out_err; > + } > + > + /* add initrd-* */ > + if (initrd_load_addr) { > + value = cpu_to_fdt64(initrd_load_addr); > + ret = fdt_setprop(buf, nodeoffset, "initrd-start", > + &value, sizeof(value)); > + if (ret) > + goto out_err; > + > + value = cpu_to_fdt64(initrd_load_addr + initrd_len); > + ret = fdt_setprop(buf, nodeoffset, "initrd-end", > + &value, sizeof(value)); > + if (ret) > + goto out_err; > + } > + > + /* trim a buffer */ > + fdt_pack(buf); > + *dtb_buf = buf; > + *dtb_buf_len = fdt_totalsize(buf); > + > + return 0; > + > +out_err: > + vfree(buf); > + return ret; > +} > + > +int load_other_segments(struct kimage *image, unsigned long kernel_load_addr, > + char *initrd, unsigned long initrd_len, > + char *cmdline, unsigned long cmdline_len) > +{ > + struct kexec_buf kbuf; > + unsigned long initrd_load_addr = 0; > + unsigned long purgatory_load_addr, dtb_load_addr; > + char *dtb = NULL; > + unsigned long dtb_len; > + int ret = 0; > + > + kbuf.image = image; > + /* not allocate anything below the kernel */ > + kbuf.buf_min = kernel_load_addr; > + > + /* Load initrd */ > + if (initrd) { > + kbuf.buffer = initrd; > + kbuf.bufsz = initrd_len; > + kbuf.memsz = initrd_len; > + kbuf.buf_align = PAGE_SIZE; > + /* within 1GB-aligned window of up to 32GB in size */ > + kbuf.buf_max = round_down(kernel_load_addr, SZ_1G) > + + (unsigned long)SZ_1G * 31; > + kbuf.top_down = 0; > + > + ret = kexec_add_buffer(&kbuf); > + if (ret) > + goto out_err; > + initrd_load_addr = kbuf.mem; > + > + pr_debug("Loaded initrd at 0x%lx bufsz=0x%lx memsz=0x%lx\n", > + initrd_load_addr, initrd_len, initrd_len); > + } > + > + /* Load dtb blob */ > + ret = setup_dtb(image, initrd_load_addr, initrd_len, > + cmdline, cmdline_len, &dtb, &dtb_len); > + if (ret) { > + pr_err("Preparing for new dtb failed\n"); > + goto out_err; > + } > + > + kbuf.buffer = dtb; > + kbuf.bufsz = dtb_len; > + kbuf.memsz = dtb_len; > + /* not across 2MB boundary */ > + kbuf.buf_align = SZ_2M; > + kbuf.buf_max = ULONG_MAX; > + kbuf.top_down = 1; > + > + ret = kexec_add_buffer(&kbuf); > + if (ret) > + goto out_err; > + dtb_load_addr = kbuf.mem; > + image->arch.dtb_buf = dtb; > + > + pr_debug("Loaded dtb at 0x%lx bufsz=0x%lx memsz=0x%lx\n", > + dtb_load_addr, dtb_len, dtb_len); > + > + /* Load purgatory */ > + ret = kexec_load_purgatory(image, kernel_load_addr, ULONG_MAX, 1, > + &purgatory_load_addr); > + if (ret) { > + pr_err("Loading purgatory failed\n"); > + goto out_err; > + } > + > + ret = kexec_purgatory_get_set_symbol(image, "kernel_entry", > + &kernel_load_addr, sizeof(kernel_load_addr), 0); > + if (ret) { > + pr_err("Setting symbol (kernel_entry) failed.\n"); > + goto out_err; > + } > + > + ret = kexec_purgatory_get_set_symbol(image, "dtb_addr", > + &dtb_load_addr, sizeof(dtb_load_addr), 0); > + if (ret) { > + pr_err("Setting symbol (dtb_addr) failed.\n"); > + goto out_err; > + } > + > + pr_debug("Loaded purgatory at 0x%lx\n", purgatory_load_addr); > + > + return 0; > + > +out_err: > + vfree(dtb); > + image->arch.dtb_buf = NULL; > + return ret; > +} > -- > 2.14.1 > > > _______________________________________________ > kexec mailing list > kexec@lists.infradead.org > http://lists.infradead.org/mailman/listinfo/kexec Thanks Dave --- linux-x86.orig/arch/x86/kernel/machine_kexec_64.c +++ linux-x86/arch/x86/kernel/machine_kexec_64.c @@ -384,9 +384,6 @@ int arch_kexec_kernel_image_probe(struct void *arch_kexec_kernel_image_load(struct kimage *image) { - vfree(image->arch.elf_headers); - image->arch.elf_headers = NULL; - if (!image->fops || !image->fops->load) return ERR_PTR(-ENOEXEC);