From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
To: Breno Leitao <leitao@debian.org>
Cc: Jonathan Corbet <corbet@lwn.net>,
Shuah Khan <skhan@linuxfoundation.org>,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, oss@malat.biz, paulmck@kernel.org,
rostedt@goodmis.org, kernel-team@meta.com
Subject: Re: [PATCH] bootconfig: Apply early options from embedded config
Date: Wed, 25 Mar 2026 00:38:17 +0900 [thread overview]
Message-ID: <20260325003817.c3c2aee509b4048d4c5c786e@kernel.org> (raw)
In-Reply-To: <20260324-early_bootconfig-v1-1-1c0e625aff06@debian.org>
On Tue, 24 Mar 2026 05:52:33 -0700
Breno Leitao <leitao@debian.org> wrote:
> Right not is impossible to set early parameters in bootconfig, which
> limits the usage of bootconfig to some critical parameters.
>
> Add bootconfig_apply_early_params() which walks all kernel.* keys in the
> parsed XBC tree and calls do_early_param() for each one. It is called
> from setup_boot_config() immediately after a successful xbc_init() on
> the embedded data, which happens before parse_early_param() runs in
> start_kernel().
>
> This allows early options such as:
>
> kernel.mitigations = off
> kernel.irqchip.gicv3_pseudo_nmi = 1
>
> to be placed in the embedded bootconfig and take effect, without
> requiring them to be on the kernel command line.
>
> Early options in initrd bootconfig are still silently ignored, as the
> initrd is only available after the early param window has closed.
>
> Document this behaviour in both Kconfig and the admin guide.
Thanks Breno, this makes things clearer.
This looks good to me.
Thanks,
>
> Signed-off-by: Breno Leitao <leitao@debian.org>
> ---
> Documentation/admin-guide/bootconfig.rst | 4 ++
> init/Kconfig | 6 +++
> init/main.c | 67 +++++++++++++++++++++++++++++++-
> 3 files changed, 76 insertions(+), 1 deletion(-)
>
> diff --git a/Documentation/admin-guide/bootconfig.rst b/Documentation/admin-guide/bootconfig.rst
> index f712758472d5c..e820f33d3ad16 100644
> --- a/Documentation/admin-guide/bootconfig.rst
> +++ b/Documentation/admin-guide/bootconfig.rst
> @@ -169,6 +169,10 @@ Boot Kernel With a Boot Config
> There are two options to boot the kernel with bootconfig: attaching the
> bootconfig to the initrd image or embedding it in the kernel itself.
>
> +Early options (those registered with ``early_param()``) may only be
> +specified in the embedded bootconfig, because the initrd is not yet
> +available when early parameters are processed.
> +
> Attaching a Boot Config to Initrd
> ---------------------------------
>
> diff --git a/init/Kconfig b/init/Kconfig
> index 938fbe6a91e15..5e8057e73fe06 100644
> --- a/init/Kconfig
> +++ b/init/Kconfig
> @@ -1534,6 +1534,12 @@ config BOOT_CONFIG_EMBED
> image. But if the system doesn't support initrd, this option will
> help you by embedding a bootconfig file while building the kernel.
>
> + Unlike bootconfig attached to initrd, the embedded bootconfig also
> + supports early options (those registered with early_param()). Any
> + kernel.* key in the embedded bootconfig is applied before
> + parse_early_param() runs. Early options in initrd bootconfig will
> + not be applied.
> +
> If unsure, say N.
>
> config BOOT_CONFIG_EMBED_FILE
> diff --git a/init/main.c b/init/main.c
> index 453ac9dff2da0..eba42b2351d47 100644
> --- a/init/main.c
> +++ b/init/main.c
> @@ -416,9 +416,63 @@ static int __init warn_bootconfig(char *str)
> return 0;
> }
>
> +/*
> + * do_early_param() is defined later in this file but called from
> + * bootconfig_apply_early_params() below, so we need a forward declaration.
> + */
> +static int __init do_early_param(char *param, char *val,
> + const char *unused, void *arg);
> +
> +/*
> + * bootconfig_apply_early_params - dispatch kernel.* keys from the embedded
> + * bootconfig as early_param() calls.
> + *
> + * early_param() handlers must run before most of the kernel initialises
> + * (e.g. before the GIC driver reads irqchip.gicv3_pseudo_nmi). A bootconfig
> + * attached to the initrd arrives too late for this because the initrd is not
> + * mapped yet when early params are processed. The embedded bootconfig lives
> + * in the kernel image itself (.init.data), so it is always reachable.
> + *
> + * This function is called from setup_boot_config() which runs in
> + * start_kernel() before parse_early_param(), making the timing correct.
> + */
> +static void __init bootconfig_apply_early_params(void)
> +{
> + char val_buf[COMMAND_LINE_SIZE];
> + struct xbc_node *knode, *root;
> + const char *val;
> +
> + root = xbc_find_node("kernel");
> + if (!root)
> + return;
> +
> + /*
> + * Keys that do not match any early_param() handler are silently
> + * ignored — do_early_param() always returns 0.
> + */
> + xbc_node_for_each_key_value(root, knode, val) {
> + if (xbc_node_compose_key_after(root, knode, xbc_namebuf, XBC_KEYLEN_MAX) < 0)
> + continue;
> +
> + if (!val) {
> + do_early_param(xbc_namebuf, NULL, NULL, NULL);
> + continue;
> + }
> +
> + /*
> + * We need to copy const char *val to a char pointer,
> + * which is what do_early_param() need, given it might
> + * call strsep(), strtok() later.
> + */
> + strscpy(val_buf, val, sizeof(val_buf));
> + do_early_param(xbc_namebuf, val_buf, NULL, NULL);
> + }
> +}
> +
> static void __init setup_boot_config(void)
> {
> static char tmp_cmdline[COMMAND_LINE_SIZE] __initdata;
> + bool using_embedded = false;
> const char *msg, *data;
> int pos, ret;
> size_t size;
> @@ -427,8 +481,17 @@ static void __init setup_boot_config(void)
> /* Cut out the bootconfig data even if we have no bootconfig option */
> data = get_boot_config_from_initrd(&size);
> /* If there is no bootconfig in initrd, try embedded one. */
> - if (!data)
> + if (!data) {
> data = xbc_get_embedded_bootconfig(&size);
> + /*
> + * Record that we are using the embedded config so that
> + * bootconfig_apply_early_params() is called below.
> + * When CONFIG_BOOT_CONFIG_EMBED is not set,
> + * xbc_get_embedded_bootconfig() is a stub returning NULL, so
> + * data is always NULL here and using_embedded stays false.
> + */
> + using_embedded = data;
> + }
>
> strscpy(tmp_cmdline, boot_command_line, COMMAND_LINE_SIZE);
> err = parse_args("bootconfig", tmp_cmdline, NULL, 0, 0, 0, NULL,
> @@ -466,6 +529,8 @@ static void __init setup_boot_config(void)
> } else {
> xbc_get_info(&ret, NULL);
> pr_info("Load bootconfig: %ld bytes %d nodes\n", (long)size, ret);
> + if (using_embedded)
> + bootconfig_apply_early_params();
> /* keys starting with "kernel." are passed via cmdline */
> extra_command_line = xbc_make_cmdline("kernel");
> /* Also, "init." keys are init arguments */
>
> ---
> base-commit: 785f0eb2f85decbe7c1ef9ae922931f0194ffc2e
> change-id: 20260323-early_bootconfig-2efc4509af3d
>
> Best regards,
> --
> Breno Leitao <leitao@debian.org>
>
--
Masami Hiramatsu (Google) <mhiramat@kernel.org>
prev parent reply other threads:[~2026-03-24 15:38 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-03-24 12:52 [PATCH] bootconfig: Apply early options from embedded config Breno Leitao
2026-03-24 15:38 ` Masami Hiramatsu [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260325003817.c3c2aee509b4048d4c5c786e@kernel.org \
--to=mhiramat@kernel.org \
--cc=corbet@lwn.net \
--cc=kernel-team@meta.com \
--cc=leitao@debian.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=oss@malat.biz \
--cc=paulmck@kernel.org \
--cc=rostedt@goodmis.org \
--cc=skhan@linuxfoundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox