From: Alejandro Vallejo <alejandro.garciavallejo@amd.com>
To: Nicola Vetrini <nicola.vetrini@bugseng.com>,
Oleksii Moisieiev <Oleksii_Moisieiev@epam.com>
Cc: xen-devel@lists.xenproject.org,
"Andrew Cooper" <andrew.cooper3@citrix.com>,
"Anthony PERARD" <anthony.perard@vates.tech>,
"Bertrand Marquis" <bertrand.marquis@arm.com>,
"Jan Beulich" <jbeulich@suse.com>,
"Julien Grall" <julien@xen.org>,
"Michal Orzel" <michal.orzel@amd.com>,
"Roger Pau Monné" <roger.pau@citrix.com>,
"Stefano Stabellini" <sstabellini@kernel.org>,
"Volodymyr Babchuk" <Volodymyr_Babchuk@epam.com>,
Xen-devel <xen-devel-bounces@lists.xenproject.org>
Subject: Re: [PATCH v3] xen/arm, xen/common: Add Kconfig option to control Dom0 boot
Date: Fri, 26 Sep 2025 12:53:06 +0200 [thread overview]
Message-ID: <DD2OC4H9KI4C.1F2MA94EVW435@amd.com> (raw)
In-Reply-To: <8fd7c0f5d203aa0f13cd8efe5129b6f3@bugseng.com>
On Wed Sep 24, 2025 at 6:06 PM CEST, Nicola Vetrini wrote:
> On 2025-09-24 18:00, Oleksii Moisieiev wrote:
>> This commit introduces a new Kconfig option, `CONFIG_DOM0_BOOT`, to
>> allow for building Xen without support for booting a regular domain
>> (Dom0).
>> This functionality is primarily intended for the ARM architecture.
>>
>> A new Kconfig symbol, `HAS_DOM0`, has been added and is selected by
>> default for ARM and X86 architecture. This symbol signifies that an
>> architecture has the capability to support a Dom0.
>>
>> The `DOM0_BOOT` option depends on `HAS_DOM0` and defaults to 'y'. For
>> expert users, this option can be disabled (`CONFIG_EXPERT=y` and no
>> `CONFIG_DOM0_BOOT` in the config), which will compile out the Dom0
>> creation code on ARM. This is useful for embedded or dom0less-only
>> scenarios to reduce binary size and complexity.
>>
>> The ARM boot path has been updated to panic if it detects a
>> non-dom0less
>> configuration while `CONFIG_DOM0_BOOT` is disabled, preventing an
>> invalid
>> boot.
>>
>> Signed-off-by: Oleksii Moisieiev <oleksii_moisieiev@epam.com>
>>
>> ---
>>
>> Changes in v3:
>> - rephrase error message when dom0less mode wasn't detected while dom0
>> is disabled.
>> - rephrase help message for DOM0_BOOT config option
>> - update DOM0_BOOT dependencies for X86
>>
>> Changes in v2:
>> - decided not to rename HAS_DOM0 (HAS_OPTIONAL_DOM0 was another option
>> suggested in ML) because in this case HAS_DOM0LESS should be renamed
>> either.
>> - fix order of HAS_DOM0 config parameter
>> - add HAS_DOM0 option to x86 architecture.
>>
>> CONFIG_DOM0_BOOT Kconfig option was introduced to make the Dom0
>> regular (legacy) domain an optional feature that can be compiled out
>> from the Xen hypervisor build.
>>
>> The primary motivation for this change is to enhance modularity and
>> produce a cleaner, more specialized hypervisor binary when a control
>> domain is not needed. In many embedded or dedicated systems, Xen is
>> used in a "dom0less" configuration where guests are pre-configured and
>> launched directly by the hypervisor. In these scenarios, the entire
>> subsystem for booting and managing Dom0 is unnecessary.
>>
>> This approach aligns with software quality standards like MISRA C,
>> which advocate for the removal of unreachable or unnecessary code to
>> improve safety and maintainability. Specifically, this change helps
>> adhere to:
>>
>> MISRA C:2012, Rule 2.2: "There shall be no dead code"
>>
>> In a build configured for a dom0less environment, the code responsible
>> for creating Dom0 would be considered "dead code" as it would never be
>> executed. By using the preprocessor to remove it before compilation,
>> we ensure that the final executable is free from this unreachable
>> code. This simplifies static analysis, reduces the attack surface,
>> and makes the codebase easier to verify, which is critical for
>> systems requiring high levels of safety and security.
>>
>
> Misra's definition of "dead code" is code that is executed, but can be
> removed without changing the behavior of the program, while unreachable
> code is code that is not executed, so I would cite MISRA C Rule 2.1 ("A
> project shall not contain unreachable code"), rather that R2.2.
>
>> ---
>> xen/arch/arm/Kconfig | 1 +
>> xen/arch/arm/domain_build.c | 8 ++++++++
>> xen/arch/arm/setup.c | 14 ++++++++++----
>> xen/arch/x86/Kconfig | 1 +
>> xen/common/Kconfig | 11 +++++++++++
>> 5 files changed, 31 insertions(+), 4 deletions(-)
>>
>> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
>> index cf6af68299..336b2ed242 100644
>> --- a/xen/arch/arm/Kconfig
>> +++ b/xen/arch/arm/Kconfig
>> @@ -17,6 +17,7 @@ config ARM
>> select GENERIC_UART_INIT
>> select HAS_ALTERNATIVE if HAS_VMAP
>> select HAS_DEVICE_TREE_DISCOVERY
>> + select HAS_DOM0
>> select HAS_DOM0LESS
>> select HAS_GRANT_CACHE_FLUSH if GRANT_TABLE
>> select HAS_STACK_PROTECTOR
>> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
>> index fb8fbb1650..62602afc78 100644
>> --- a/xen/arch/arm/domain_build.c
>> +++ b/xen/arch/arm/domain_build.c
>> @@ -42,8 +42,10 @@
>> #include <asm/grant_table.h>
>> #include <xen/serial.h>
>>
>> +#ifdef CONFIG_DOM0_BOOT
>> static unsigned int __initdata opt_dom0_max_vcpus;
>> integer_param("dom0_max_vcpus", opt_dom0_max_vcpus);
>> +#endif
>>
>> /*
>> * If true, the extended regions support is enabled for dom0 and
>> @@ -104,6 +106,7 @@ int __init parse_arch_dom0_param(const char *s,
>> const char *e)
>> */
>> #define DOM0_FDT_EXTRA_SIZE (128 + sizeof(struct fdt_reserve_entry))
>>
>> +#ifdef CONFIG_DOM0_BOOT
>> unsigned int __init dom0_max_vcpus(void)
>> {
>> if ( opt_dom0_max_vcpus == 0 )
>> @@ -116,6 +119,7 @@ unsigned int __init dom0_max_vcpus(void)
>>
>> return opt_dom0_max_vcpus;
>> }
>> +#endif
>>
>> /*
>> * Insert the given pages into a memory bank, banks are ordered by
>> address.
>> @@ -1962,6 +1966,7 @@ int __init construct_domain(struct domain *d,
>> struct kernel_info *kinfo)
>> return 0;
>> }
>>
>> +#ifdef CONFIG_DOM0_BOOT
>> static int __init construct_dom0(struct domain *d)
>> {
>> struct kernel_info kinfo = KERNEL_INFO_INIT;
>> @@ -1993,6 +1998,7 @@ static int __init construct_dom0(struct domain
>> *d)
>>
>> return construct_hwdom(&kinfo, NULL);
>> }
>> +#endif
>>
>> int __init construct_hwdom(struct kernel_info *kinfo,
>> const struct dt_device_node *node)
>> @@ -2046,6 +2052,7 @@ int __init construct_hwdom(struct kernel_info
>> *kinfo,
>> return construct_domain(d, kinfo);
>> }
>>
>> +#ifdef CONFIG_DOM0_BOOT
>> void __init create_dom0(void)
>> {
>> struct domain *dom0;
>> @@ -2103,6 +2110,7 @@ void __init create_dom0(void)
>>
>> set_xs_domain(dom0);
>> }
>> +#endif /* CONFIG_DOM0_BOOT */
>>
>> /*
>> * Local variables:
>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>> index 7ad870e382..fbb290df60 100644
>> --- a/xen/arch/arm/setup.c
>> +++ b/xen/arch/arm/setup.c
>> @@ -481,12 +481,18 @@ void asmlinkage __init noreturn
>> start_xen(unsigned long fdt_paddr)
>> enable_errata_workarounds();
>> enable_cpu_features();
>>
>> - /* Create initial domain 0. */
>> - if ( !is_dom0less_mode() )
>> + if ( IS_ENABLED(CONFIG_DOM0_BOOT) && !is_dom0less_mode() )
This probably wants inlining in is_dom0less_mode() so every use gets to be
resolved statically.
>> + {
>> + /* Create initial domain 0. */
>> create_dom0();
>> + }
>> else
>> - printk(XENLOG_INFO "Xen dom0less mode detected\n");
>> -
>> + {
>> + if ( is_dom0less_mode())
>> + printk(XENLOG_INFO "Xen dom0less mode detected\n");
>> + else
>> + panic("Neither dom0 nor dom0less mode was detected,
I'd rather have a static check in common code.
BUILD_BUG_ON(!CONFIG_DOM0_BOOT && !CONFIG_DOM0LESS_BOOT);
>> aborting\n");
>> + }
>> if ( acpi_disabled )
>> {
>> create_domUs();
>> diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
>> index 3f0f3a0f3a..2aeb361c63 100644
>> --- a/xen/arch/x86/Kconfig
>> +++ b/xen/arch/x86/Kconfig
>> @@ -18,6 +18,7 @@ config X86
>> select HAS_COMPAT
>> select HAS_CPUFREQ
>> select HAS_DIT
>> + select HAS_DOM0
>> select HAS_EHCI
>> select HAS_EX_TABLE
>> select HAS_FAST_MULTIPLY
>> diff --git a/xen/common/Kconfig b/xen/common/Kconfig
>> index 76f9ce705f..10a8fc8718 100644
>> --- a/xen/common/Kconfig
>> +++ b/xen/common/Kconfig
>> @@ -26,6 +26,14 @@ config DOM0LESS_BOOT
>> Xen boot without the need of a control domain (Dom0), which could
>> be
>> present anyway.
>>
>> +config DOM0_BOOT
>> + bool "Dom0 boot support" if EXPERT
>> + default y
>> + depends on (ARM && HAS_DOM0 && HAS_DEVICE_TREE_DISCOVERY &&
>> DOMAIN_BUILD_HELPERS) || (X86 && HAS_DOM0)
Why not just HAS_DOM0? And why HAS_DEVICE_DISCOVERY and DOMAIN_BUILD_HELPERS?
More importantly, why not drop HAS_DOM0 and do "DOM0LESS_BOOT && (X86 || ARM)"
instead? Or just HAS_OPTIONAL_DOM0. dom0less is always optional, while dom0 is
supported everywhere. HAS_OPTIONAL_DOM0 would signal that a port is capable of
compiling out special dom0 construction logic.
The current dependency list seems off to me.
>> + help
>> + Dom0 boot support enables Xen to boot to the all-powerful domain
>> (Dom0).
... or the pvshim, in the current x86 code.
In time we'll probably want to make it so that !DOM0_BOOT && !DOM0LESS_BOOT &&
PV_SHIM means PVSHIM_EXCLUSIVE, which would solve the Kconfig headaches we have
with it by making all options additive.
But as things are today, this includes dom0 and the PV shim.
>> + If this isn't enabled Xen is expected to boot in dom0less mode
>> only.
... or fail to compile (as per my suggestion above) when dom0less isn't
available either.
There's an annoying side effect here. randconfig will be able to create a broken
config. !DOM0_BOOT && !DOM0LESS_BOOT. CI would need adjusting to keep DOM0_BOOT
set in randconfig jobs.
I don't have a good solution for that.
Cheers,
Alejandro
next prev parent reply other threads:[~2025-09-26 11:00 UTC|newest]
Thread overview: 11+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-09-24 16:00 [PATCH v3] xen/arm, xen/common: Add Kconfig option to control Dom0 boot Oleksii Moisieiev
2025-09-24 16:06 ` Nicola Vetrini
2025-09-24 16:37 ` Oleksii Moisieiev
2025-09-26 10:53 ` Alejandro Vallejo [this message]
2025-09-26 12:03 ` Jan Beulich
2025-09-25 6:34 ` Jan Beulich
2025-09-25 8:14 ` Oleksii Moisieiev
2025-09-25 10:15 ` Jan Beulich
2025-09-25 9:22 ` Grygorii Strashko
2025-09-25 10:53 ` Oleksii Moisieiev
2025-09-25 10:58 ` Grygorii Strashko
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=DD2OC4H9KI4C.1F2MA94EVW435@amd.com \
--to=alejandro.garciavallejo@amd.com \
--cc=Oleksii_Moisieiev@epam.com \
--cc=Volodymyr_Babchuk@epam.com \
--cc=andrew.cooper3@citrix.com \
--cc=anthony.perard@vates.tech \
--cc=bertrand.marquis@arm.com \
--cc=jbeulich@suse.com \
--cc=julien@xen.org \
--cc=michal.orzel@amd.com \
--cc=nicola.vetrini@bugseng.com \
--cc=roger.pau@citrix.com \
--cc=sstabellini@kernel.org \
--cc=xen-devel-bounces@lists.xenproject.org \
--cc=xen-devel@lists.xenproject.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.