[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <aInKb8qr689ytM41@darkstar.users.ipa.redhat.com>
Date: Wed, 30 Jul 2025 15:31:59 +0800
From: Dave Young <dyoung@...hat.com>
To: Brian Mak <makb@...iper.net>
Cc: Thomas Gleixner <tglx@...utronix.de>, Ingo Molnar <mingo@...hat.com>,
Borislav Petkov <bp@...en8.de>,
Dave Hansen <dave.hansen@...ux.intel.com>,
"H. Peter Anvin" <hpa@...or.com>,
Andrew Morton <akpm@...ux-foundation.org>,
Baoquan He <bhe@...hat.com>, Rob Herring <robh@...nel.org>,
Saravana Kannan <saravanak@...gle.com>, x86@...nel.org,
kexec@...ts.infradead.org, devicetree@...r.kernel.org,
linux-kernel@...r.kernel.org
Subject: Re: [PATCH RESEND] x86/kexec: Carry forward the boot DTB on kexec
On Tue, Jul 29, 2025 at 11:21:42AM -0700, Brian Mak wrote:
> The kexec_file_load syscall on x86 currently does not support passing
> a device tree blob to the new kernel.
>
> To add support for this, we copy the behavior of ARM64 and PowerPC and
> copy the current boot's device tree blob for use in the new kernel. We
> do this on x86 by passing the device tree blob as a setup_data entry in
> accordance with the x86 boot protocol.
>
> Signed-off-by: Brian Mak <makb@...iper.net>
> ---
> arch/x86/kernel/kexec-bzimage64.c | 46 +++++++++++++++++++++++++++++--
> 1 file changed, 43 insertions(+), 3 deletions(-)
>
> diff --git a/arch/x86/kernel/kexec-bzimage64.c b/arch/x86/kernel/kexec-bzimage64.c
> index 24a41f0e0cf1..c24536c25f98 100644
> --- a/arch/x86/kernel/kexec-bzimage64.c
> +++ b/arch/x86/kernel/kexec-bzimage64.c
> @@ -16,6 +16,8 @@
> #include <linux/kexec.h>
> #include <linux/kernel.h>
> #include <linux/mm.h>
> +#include <linux/libfdt.h>
> +#include <linux/of_fdt.h>
> #include <linux/efi.h>
> #include <linux/random.h>
>
> @@ -212,6 +214,28 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
> }
> #endif /* CONFIG_EFI */
>
> +#ifdef CONFIG_OF_FLATTREE
> +static void setup_dtb(struct boot_params *params,
> + unsigned long params_load_addr,
> + unsigned int dtb_setup_data_offset)
> +{
> + struct setup_data *sd = (void *)params + dtb_setup_data_offset;
> + unsigned long setup_data_phys, dtb_len;
> +
> + dtb_len = fdt_totalsize(initial_boot_params);
> + sd->type = SETUP_DTB;
> + sd->len = dtb_len;
> +
> + /* Carry over current boot DTB with setup_data */
> + memcpy(sd->data, initial_boot_params, dtb_len);
> +
> + /* Add setup data */
> + setup_data_phys = params_load_addr + dtb_setup_data_offset;
> + sd->next = params->hdr.setup_data;
> + params->hdr.setup_data = setup_data_phys;
> +}
> +#endif /* CONFIG_OF_FLATTREE */
> +
> static void
> setup_ima_state(const struct kimage *image, struct boot_params *params,
> unsigned long params_load_addr,
> @@ -336,6 +360,16 @@ setup_boot_parameters(struct kimage *image, struct boot_params *params,
> sizeof(struct efi_setup_data);
> #endif
>
> +#ifdef CONFIG_OF_FLATTREE
> + if (initial_boot_params) {
> + setup_dtb(params, params_load_addr, setup_data_offset);
> + setup_data_offset += sizeof(struct setup_data) +
> + fdt_totalsize(initial_boot_params);
I suppose current boot dtb should be valid for the current runnning
kernel, if you use kexec to load another kernel the next kexec reboot
could fail due to unmatching dtb.
Make this unconditionally could break the previous working kexec?
> + } else {
> + pr_info("No DTB\n");
pr_debug sounds better.
> + }
> +#endif
> +
> if (IS_ENABLED(CONFIG_IMA_KEXEC)) {
> /* Setup IMA log buffer state */
> setup_ima_state(image, params, params_load_addr,
> @@ -529,6 +563,12 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
> sizeof(struct setup_data) +
> RNG_SEED_LENGTH;
>
> +#ifdef CONFIG_OF_FLATTREE
> + if (initial_boot_params)
> + kbuf.bufsz += sizeof(struct setup_data) +
> + fdt_totalsize(initial_boot_params);
> +#endif
> +
> if (IS_ENABLED(CONFIG_IMA_KEXEC))
> kbuf.bufsz += sizeof(struct setup_data) +
> sizeof(struct ima_setup_data);
> @@ -537,7 +577,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
> kbuf.bufsz += sizeof(struct setup_data) +
> sizeof(struct kho_data);
>
> - params = kzalloc(kbuf.bufsz, GFP_KERNEL);
> + params = kvzalloc(kbuf.bufsz, GFP_KERNEL);
> if (!params)
> return ERR_PTR(-ENOMEM);
> efi_map_offset = params_cmdline_sz;
> @@ -647,7 +687,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
> return ldata;
>
> out_free_params:
> - kfree(params);
> + kvfree(params);
> return ERR_PTR(ret);
> }
>
> @@ -659,7 +699,7 @@ static int bzImage64_cleanup(void *loader_data)
> if (!ldata)
> return 0;
>
> - kfree(ldata->bootparams_buf);
> + kvfree(ldata->bootparams_buf);
> ldata->bootparams_buf = NULL;
>
> return 0;
>
> base-commit: d7b8f8e20813f0179d8ef519541a3527e7661d3a
> --
> 2.25.1
>
Thanks
Dave
Powered by blists - more mailing lists