Received: by 2002:a05:6a10:8c0a:0:0:0:0 with SMTP id go10csp1488853pxb; Wed, 10 Feb 2021 09:26:05 -0800 (PST) X-Google-Smtp-Source: ABdhPJwt+4geepmCnR7jsdJskHgtQ6+kdD4EhMXbFJ7GQ5Vr83r0z11OYWOi7TIGbpyBSfW19EYg X-Received: by 2002:a17:906:d0c3:: with SMTP id bq3mr3888013ejb.424.1612977965635; Wed, 10 Feb 2021 09:26:05 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1612977965; cv=none; d=google.com; s=arc-20160816; b=0uanBUfZu6jb2T1j0HfFlQnKW/tCUrUDvx6nN+MOxwAZp6goiN6KPUHRcSF2CKJsPw FvBv7ODZabf8sG8eerSousyuXsRiRuqcxmQUmCn0HrEOq1WUZcus70qBl4gadRszY9tQ rmduhgKr8L1pn6ZuCWVexnOFdHJD+WYrmmgi4lvYucb7RgD39hanFzUXbXd5YP+WgC8h +MTmdT1nrs4yavBQP3Y0ctRQ72q2IcV1w/Kaas+xIgLWXpbdxeb+MY4ySnuXkRsBMmfQ zhRo+PIRHi/UXVfDIj1ayfEt9Jpcj1dhDuPnSl4tg4Vtlkg2JTBIqBZI1Q2J9ht4hpO6 7M4g== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:in-reply-to:content-disposition:mime-version :references:message-id:subject:cc:to:from:date; bh=ysC2kY6lw48OjNmEWfhszlohQCXKkxkhQTUpID2nTYg=; b=vQTbECmq1jfjdNAr0mE7IEmZwEZVmnS9Q4wE8YDafO4R8mr9kz85vDx6kLuTsZTp6y t2qcG84YXxYwQ2xclFWxlVRoCZTmtAnFpUNvpiKUHZSILZNrt1Fum9KtMAlSA79I8duC n1qDvueBm0KC34BA/CAKoEEQVdR0h/gRX5vmYAG1uAyh8S7UGy6zSW8Oaf6Vd0Gsd5CR 4edLmCSesq9GHgAxYStDJgOvfGvpxobmsuRl6P7QCpBOklK1GTbYgM/3Hd8NNiLjjK+A 36O0usjKTxpSYl8wZXzic85+vezoJb33XlhCS1OhVG4OcJQK6Jzgeo5JhdeykJlNKzrX 1U+Q== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id a3si1958985ejd.66.2021.02.10.09.25.41; Wed, 10 Feb 2021 09:26:05 -0800 (PST) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S232511AbhBJRYC (ORCPT + 99 others); Wed, 10 Feb 2021 12:24:02 -0500 Received: from mail-ot1-f47.google.com ([209.85.210.47]:44430 "EHLO mail-ot1-f47.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S232037AbhBJRXw (ORCPT ); Wed, 10 Feb 2021 12:23:52 -0500 Received: by mail-ot1-f47.google.com with SMTP id e5so2484028otb.11; Wed, 10 Feb 2021 09:23:35 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:date:from:to:cc:subject:message-id:references :mime-version:content-disposition:in-reply-to; bh=ysC2kY6lw48OjNmEWfhszlohQCXKkxkhQTUpID2nTYg=; b=PsEBKkbzb5r9n/Y0jIi9mwjxjcnthViNyQjwcN1ybfaDtAEeao98i4iJVvAmpIE0hf 2CXRiRF34O5tEiW1OwdtNBfS9MGElxhOHY7cBqoY3T1ncz5vWoZ4JMFl4a1AujwuIECx DI8N8lexaAvsFBWrJAACvdTrde378RZqfOhqaVYPthOAeSNbo3g/6hEYypLQ17Lj3ja/ kl3AUKOKiLYZWAG5t2dY3hYcu3W6nbvWFQ0o1+k9aLOiAzswyyV36E5hvndWrtwhL/zd zJqyvvYLdoBVeNvupxzYtK3x24nPAPcQ3cugm1WrxqvhqJlUNgKFOHfOd0+vjALX3DqD NzgQ== X-Gm-Message-State: AOAM532BChbGMJEPG/4dZdv1pHwBU6bdjSUGEQWpuDKuCD7NE+S3i5J5 VYbj+nkfYe+udhOa7gBzIw== X-Received: by 2002:a05:6830:1c6c:: with SMTP id s12mr2957430otg.125.1612977790317; Wed, 10 Feb 2021 09:23:10 -0800 (PST) Received: from robh.at.kernel.org (24-155-109-49.dyn.grandenetworks.net. [24.155.109.49]) by smtp.gmail.com with ESMTPSA id 203sm566875oie.14.2021.02.10.09.23.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 10 Feb 2021 09:23:09 -0800 (PST) Received: (nullmailer pid 2375394 invoked by uid 1000); Wed, 10 Feb 2021 17:23:07 -0000 Date: Wed, 10 Feb 2021 11:23:07 -0600 From: Rob Herring To: Lakshmi Ramasubramanian Cc: zohar@linux.ibm.com, bauerman@linux.ibm.com, takahiro.akashi@linaro.org, gregkh@linuxfoundation.org, will@kernel.org, joe@perches.com, catalin.marinas@arm.com, mpe@ellerman.id.au, james.morse@arm.com, sashal@kernel.org, benh@kernel.crashing.org, paulus@samba.org, frowand.list@gmail.com, vincenzo.frascino@arm.com, mark.rutland@arm.com, dmitry.kasatkin@gmail.com, jmorris@namei.org, serge@hallyn.com, pasha.tatashin@soleen.com, allison@lohutok.net, masahiroy@kernel.org, mbrugger@suse.com, hsinyi@chromium.org, tao.li@vivo.com, christophe.leroy@c-s.fr, prsriva@linux.microsoft.com, balajib@linux.microsoft.com, linux-integrity@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, linuxppc-dev@lists.ozlabs.org Subject: Re: [PATCH v17 02/10] of: Add a common kexec FDT setup function Message-ID: <20210210172307.GB2361245@robh.at.kernel.org> References: <20210209182200.30606-1-nramas@linux.microsoft.com> <20210209182200.30606-3-nramas@linux.microsoft.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20210209182200.30606-3-nramas@linux.microsoft.com> Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Tue, Feb 09, 2021 at 10:21:52AM -0800, Lakshmi Ramasubramanian wrote: > From: Rob Herring > > Both arm64 and powerpc do essentially the same FDT /chosen setup for > kexec. The differences are either omissions that arm64 should have > or additional properties that will be ignored. The setup code can be > combined and shared by both powerpc and arm64. > > The differences relative to the arm64 version: > - If /chosen doesn't exist, it will be created (should never happen). > - Any old dtb and initrd reserved memory will be released. > - The new initrd and elfcorehdr are marked reserved. > - "linux,booted-from-kexec" is set. > > The differences relative to the powerpc version: > - "kaslr-seed" and "rng-seed" may be set. > - "linux,elfcorehdr" is set. > - Any existing "linux,usable-memory-range" is removed. > > Combine the code for setting up the /chosen node in the FDT and updating > the memory reservation for kexec, for powerpc and arm64, in > of_kexec_alloc_and_setup_fdt() and move it to "drivers/of/kexec.c". > > Signed-off-by: Rob Herring > Signed-off-by: Lakshmi Ramasubramanian > --- > drivers/of/Makefile | 6 ++ > drivers/of/kexec.c | 258 ++++++++++++++++++++++++++++++++++++++++++++ > include/linux/of.h | 13 +++ > 3 files changed, 277 insertions(+) > create mode 100644 drivers/of/kexec.c > > diff --git a/drivers/of/Makefile b/drivers/of/Makefile > index 6e1e5212f058..c13b982084a3 100644 > --- a/drivers/of/Makefile > +++ b/drivers/of/Makefile > @@ -14,4 +14,10 @@ obj-$(CONFIG_OF_RESOLVE) += resolver.o > obj-$(CONFIG_OF_OVERLAY) += overlay.o > obj-$(CONFIG_OF_NUMA) += of_numa.o > > +ifdef CONFIG_KEXEC_FILE > +ifdef CONFIG_OF_FLATTREE > +obj-y += kexec.o > +endif > +endif > + > obj-$(CONFIG_OF_UNITTEST) += unittest-data/ > diff --git a/drivers/of/kexec.c b/drivers/of/kexec.c > new file mode 100644 > index 000000000000..469e09613cdd > --- /dev/null > +++ b/drivers/of/kexec.c > @@ -0,0 +1,258 @@ > +// SPDX-License-Identifier: GPL-2.0-only > +/* > + * Copyright (C) 2020 Arm Limited > + * > + * Based on arch/arm64/kernel/machine_kexec_file.c: > + * Copyright (C) 2018 Linaro Limited > + * > + * And arch/powerpc/kexec/file_load.c: > + * Copyright (C) 2016 IBM Corporation > + */ > + > +#include > +#include > +#include > +#include > +#include > +#include > +#include > + > +/* relevant device tree properties */ > +#define FDT_PROP_KEXEC_ELFHDR "linux,elfcorehdr" > +#define FDT_PROP_MEM_RANGE "linux,usable-memory-range" > +#define FDT_PROP_INITRD_START "linux,initrd-start" > +#define FDT_PROP_INITRD_END "linux,initrd-end" > +#define FDT_PROP_BOOTARGS "bootargs" > +#define FDT_PROP_KASLR_SEED "kaslr-seed" > +#define FDT_PROP_RNG_SEED "rng-seed" > +#define RNG_SEED_SIZE 128 > + > +/** > + * fdt_find_and_del_mem_rsv - delete memory reservation with given address and size > + * > + * @fdt: Flattened device tree for the current kernel. > + * @start: Starting address of the reserved memory. > + * @size: Size of the reserved memory. > + * > + * Return: 0 on success, or negative errno on error. > + */ > +static int fdt_find_and_del_mem_rsv(void *fdt, unsigned long start, unsigned long size) > +{ > + int i, ret, num_rsvs = fdt_num_mem_rsv(fdt); > + > + for (i = 0; i < num_rsvs; i++) { > + u64 rsv_start, rsv_size; > + > + ret = fdt_get_mem_rsv(fdt, i, &rsv_start, &rsv_size); > + if (ret) { > + pr_err("Malformed device tree.\n"); > + return -EINVAL; > + } > + > + if (rsv_start == start && rsv_size == size) { > + ret = fdt_del_mem_rsv(fdt, i); > + if (ret) { > + pr_err("Error deleting device tree reservation.\n"); > + return -EINVAL; > + } > + > + return 0; > + } > + } > + > + return -ENOENT; > +} > + > +/* > + * of_kexec_alloc_and_setup_fdt - Alloc and setup a new Flattened Device Tree > + * > + * @image: kexec image being loaded. > + * @initrd_load_addr: Address where the next initrd will be loaded. > + * @initrd_len: Size of the next initrd, or 0 if there will be none. > + * @cmdline: Command line for the next kernel, or NULL if there will > + * be none. > + * > + * Return: fdt on success, or NULL errno on error. > + */ > +void *of_kexec_alloc_and_setup_fdt(const struct kimage *image, > + unsigned long initrd_load_addr, > + unsigned long initrd_len, > + const char *cmdline) > +{ > + void *fdt; > + int ret, chosen_node; > + const void *prop; > + unsigned long fdt_size; > + > + fdt_size = fdt_totalsize(initial_boot_params) + > + (cmdline ? strlen(cmdline) : 0) + > + FDT_EXTRA_SPACE; > + > + fdt = kvmalloc(fdt_size, GFP_KERNEL); > + if (!fdt) > + return NULL; > + > + ret = fdt_open_into(initial_boot_params, fdt, fdt_size); > + if (ret < 0) { > + pr_err("Error %d setting up the new device tree.\n", ret); > + goto out; > + } > + > + /* Remove memory reservation for the current device tree. */ > + ret = fdt_find_and_del_mem_rsv(fdt, __pa(initial_boot_params), > + fdt_totalsize(initial_boot_params)); > + if (ret == -EINVAL) { > + pr_err("Error removing memory reservation.\n"); > + goto out; > + } > + > + chosen_node = fdt_path_offset(fdt, "/chosen"); > + if (chosen_node == -FDT_ERR_NOTFOUND) > + chosen_node = fdt_add_subnode(fdt, fdt_path_offset(fdt, "/"), > + "chosen"); > + if (chosen_node < 0) { > + ret = chosen_node; > + goto out; > + } > + > + ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KEXEC_ELFHDR); > + if (ret && ret != -FDT_ERR_NOTFOUND) > + goto out; > + ret = fdt_delprop(fdt, chosen_node, FDT_PROP_MEM_RANGE); > + if (ret && ret != -FDT_ERR_NOTFOUND) > + goto out; > + > + /* Did we boot using an initrd? */ > + prop = fdt_getprop(fdt, chosen_node, "linux,initrd-start", NULL); > + if (prop) { > + u64 tmp_start, tmp_end, tmp_size; > + > + tmp_start = fdt64_to_cpu(*((const fdt64_t *) prop)); > + > + prop = fdt_getprop(fdt, chosen_node, "linux,initrd-end", NULL); > + if (!prop) { > + ret = -EINVAL; > + goto out; > + } > + > + tmp_end = fdt64_to_cpu(*((const fdt64_t *) prop)); > + > + /* > + * kexec reserves exact initrd size, while firmware may > + * reserve a multiple of PAGE_SIZE, so check for both. > + */ > + tmp_size = tmp_end - tmp_start; > + ret = fdt_find_and_del_mem_rsv(fdt, tmp_start, tmp_size); > + if (ret == -ENOENT) > + ret = fdt_find_and_del_mem_rsv(fdt, tmp_start, > + round_up(tmp_size, PAGE_SIZE)); > + if (ret == -EINVAL) > + goto out; > + } > + > + /* add initrd-* */ > + if (initrd_load_addr) { > + ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_START, > + initrd_load_addr); > + if (ret) > + goto out; > + > + ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_INITRD_END, > + initrd_load_addr + initrd_len); > + if (ret) > + goto out; > + > + ret = fdt_add_mem_rsv(fdt, initrd_load_addr, initrd_len); > + if (ret) > + goto out; > + > + } else { > + ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_START); > + if (ret && (ret != -FDT_ERR_NOTFOUND)) > + goto out; > + > + ret = fdt_delprop(fdt, chosen_node, FDT_PROP_INITRD_END); > + if (ret && (ret != -FDT_ERR_NOTFOUND)) > + goto out; > + } > + > + if (image->type == KEXEC_TYPE_CRASH) { > + /* add linux,elfcorehdr */ > + ret = fdt_appendprop_addrrange(fdt, 0, chosen_node, > + FDT_PROP_KEXEC_ELFHDR, > + image->arch.elf_headers_mem, > + image->arch.elf_headers_sz); > + if (ret) > + goto out; > + > + /* > + * Avoid elfcorehdr from being stomped on in kdump kernel by > + * setting up memory reserve map. > + */ > + ret = fdt_add_mem_rsv(fdt, image->arch.elf_headers_mem, > + image->arch.elf_headers_sz); > + if (ret) > + goto out; > + > + /* add linux,usable-memory-range */ > + ret = fdt_appendprop_addrrange(fdt, 0, chosen_node, > + FDT_PROP_MEM_RANGE, > + crashk_res.start, > + crashk_res.end - crashk_res.start + 1); > + if (ret) > + goto out; > + } > + > + /* add bootargs */ > + if (cmdline) { > + ret = fdt_setprop_string(fdt, chosen_node, FDT_PROP_BOOTARGS, cmdline); > + if (ret) > + goto out; > + } else { > + ret = fdt_delprop(fdt, chosen_node, FDT_PROP_BOOTARGS); > + if (ret && (ret != -FDT_ERR_NOTFOUND)) > + goto out; > + } > + > + /* add kaslr-seed */ > + ret = fdt_delprop(fdt, chosen_node, FDT_PROP_KASLR_SEED); > + if (ret == -FDT_ERR_NOTFOUND) > + ret = 0; > + else if (ret) > + goto out; > + > + if (rng_is_initialized()) { > + u64 seed = get_random_u64(); > + > + ret = fdt_setprop_u64(fdt, chosen_node, FDT_PROP_KASLR_SEED, seed); > + if (ret) > + goto out; > + } else { > + pr_notice("RNG is not initialised: omitting \"%s\" property\n", > + FDT_PROP_KASLR_SEED); > + } > + > + /* add rng-seed */ > + if (rng_is_initialized()) { > + void *rng_seed; > + > + ret = fdt_setprop_placeholder(fdt, chosen_node, FDT_PROP_RNG_SEED, > + RNG_SEED_SIZE, &rng_seed); > + if (ret) > + goto out; > + get_random_bytes(rng_seed, RNG_SEED_SIZE); > + } else { > + pr_notice("RNG is not initialised: omitting \"%s\" property\n", > + FDT_PROP_RNG_SEED); > + } > + > + ret = fdt_setprop(fdt, chosen_node, "linux,booted-from-kexec", NULL, 0); > + > +out: > + if (ret) { > + kvfree(fdt); > + fdt = NULL; > + } > + > + return fdt; > +} > diff --git a/include/linux/of.h b/include/linux/of.h > index 4b27c9a27df3..f0eff5e84353 100644 > --- a/include/linux/of.h > +++ b/include/linux/of.h > @@ -560,6 +560,19 @@ int of_map_id(struct device_node *np, u32 id, > > phys_addr_t of_dma_get_max_cpu_address(struct device_node *np); > > +/* > + * Additional space needed for the buffer to build the new FDT > + * so that we can add initrd, bootargs, kaslr-seed, rng-seed, > + * userable-memory-range and elfcorehdr. > + */ > +#define FDT_EXTRA_SPACE 0x1000 No need for this to be public now. Move it to of/kexec.c. Rob