xen/arch/arm/Kconfig | 1 + xen/arch/arm/domain_build.c | 8 ++++++++ xen/arch/arm/setup.c | 13 ++++++++++--- xen/arch/x86/Kconfig | 1 + xen/common/Kconfig | 12 ++++++++++++ 5 files changed, 32 insertions(+), 3 deletions(-)
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>
Acked-by: Jan Beulich <jbeulich@suse.com>
---
Changes in v5:
- rebased on top of the latest staging.
- add Ack
Changes in v4:
- change Misra rule to 2.1 from 2.2 in description
- remove extra dependencies for ARM architecture from DOM0_BOOT
- rephrase DOM0_BOOT help by adding hyperlaunch
- DOM0_BOOT is mandatory for x86 architecture
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.1: "A project shall not contain unreachable 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.
---
xen/arch/arm/Kconfig | 1 +
xen/arch/arm/domain_build.c | 8 ++++++++
xen/arch/arm/setup.c | 13 ++++++++++---
xen/arch/x86/Kconfig | 1 +
xen/common/Kconfig | 12 ++++++++++++
5 files changed, 32 insertions(+), 3 deletions(-)
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index 06289005f4..6d0936b353 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -18,6 +18,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_SHARED_INFO
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 72d5316180..cc932d7686 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -43,8 +43,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
@@ -123,6 +125,7 @@ paddr_t __init hwdom_get_fdt_alloc_size(void)
return ACPI_DOM0_FDT_MIN_SIZE;
}
+#ifdef CONFIG_DOM0_BOOT
unsigned int __init dom0_max_vcpus(void)
{
if ( opt_dom0_max_vcpus == 0 )
@@ -135,6 +138,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.
@@ -1862,6 +1866,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;
@@ -1893,6 +1898,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)
@@ -1944,6 +1950,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;
@@ -2001,6 +2008,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 16f899dff5..ea9c037fba 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -491,11 +491,18 @@ void asmlinkage __init noreturn start_xen(unsigned long fdt_paddr)
do_init_boottests();
- /* Create initial domain 0. */
- if ( !is_dom0less_mode() )
+ if ( IS_ENABLED(CONFIG_DOM0_BOOT) && !is_dom0less_mode() )
+ {
+ /* 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, aborting\n");
+ }
if ( acpi_disabled )
{
diff --git a/xen/arch/x86/Kconfig b/xen/arch/x86/Kconfig
index e5535ac484..39182f6ce4 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 5b289e444f..ca16f7d6f9 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -26,6 +26,15 @@ 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 && !X86
+ default y
+ depends on HAS_DOM0
+ help
+ Dom0 boot support enables Xen to boot to the all-powerful domain (Dom0).
+ If this isn't enabled Xen is expected to boot in dom0less/hyperlaunch
+ mode only. Note: This option is mandatory for X86 architecture.
+
config DOMAIN_BUILD_HELPERS
bool
@@ -125,6 +134,9 @@ config HAS_DEVICE_TREE_DISCOVERY
bool
select DEVICE_TREE_PARSE
+config HAS_DOM0
+ bool
+
config HAS_DOM0LESS
bool
--
2.43.0
base-commit: e4da1829737fb575133d1f79d9ad987000891649
branch: amoi_dom0_remove5
On 02-Oct-26 15:26, 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>
> Acked-by: Jan Beulich <jbeulich@suse.com>
>
> ---
>
> Changes in v5:
> - rebased on top of the latest staging.
> - add Ack
>
> Changes in v4:
> - change Misra rule to 2.1 from 2.2 in description
> - remove extra dependencies for ARM architecture from DOM0_BOOT
> - rephrase DOM0_BOOT help by adding hyperlaunch
> - DOM0_BOOT is mandatory for x86 architecture
>
> 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.1: "A project shall not contain unreachable code"
But with this patch you will introduce a lot of unreachable code anyway.
>
> 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.
>
> ---
> xen/arch/arm/Kconfig | 1 +
> xen/arch/arm/domain_build.c | 8 ++++++++
> xen/arch/arm/setup.c | 13 ++++++++++---
> xen/arch/x86/Kconfig | 1 +
> xen/common/Kconfig | 12 ++++++++++++
> 5 files changed, 32 insertions(+), 3 deletions(-)
>
> diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
> index 06289005f4..6d0936b353 100644
> --- a/xen/arch/arm/Kconfig
> +++ b/xen/arch/arm/Kconfig
> @@ -18,6 +18,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_SHARED_INFO
> diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
> index 72d5316180..cc932d7686 100644
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -43,8 +43,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
What about the other dom0-only options: dom0_mem (and CONFIG_DOM0_MEM),
dom0-llc-colors and dom0=sve?
>
> /*
> * If true, the extended regions support is enabled for dom0 and
> @@ -123,6 +125,7 @@ paddr_t __init hwdom_get_fdt_alloc_size(void)
> return ACPI_DOM0_FDT_MIN_SIZE;
> }
>
> +#ifdef CONFIG_DOM0_BOOT
> unsigned int __init dom0_max_vcpus(void)
> {
> if ( opt_dom0_max_vcpus == 0 )
> @@ -135,6 +138,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.
> @@ -1862,6 +1866,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)
This makes dom0_set_llc_colors() unreachable. The same goes for
prepare_acpi() with ACPI=y, as dom0less is DT only. ACPI should be prevented
when DOM0_BOOT=n.
> {
> struct kernel_info kinfo = KERNEL_INFO_INIT;
> @@ -1893,6 +1898,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)
> @@ -1944,6 +1950,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;
> @@ -2001,6 +2008,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 16f899dff5..ea9c037fba 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -491,11 +491,18 @@ void asmlinkage __init noreturn start_xen(unsigned long fdt_paddr)
>
> do_init_boottests();
>
> - /* Create initial domain 0. */
> - if ( !is_dom0less_mode() )
> + if ( IS_ENABLED(CONFIG_DOM0_BOOT) && !is_dom0less_mode() )
> + {
> + /* Create initial domain 0. */
> create_dom0();
> + }
> else
> - printk(XENLOG_INFO "Xen dom0less mode detected\n");
> + {
> + if ( is_dom0less_mode())
Missing space after () and before )
> + printk(XENLOG_INFO "Xen dom0less mode detected\n");
> + else
> + panic("Neither dom0 nor dom0less mode was detected, aborting\n");
> + }
To avoid calling is_dom0less_mode() twice, how about:
if ( is_dom0less_mode() )
printk(XENLOG_INFO "Xen dom0less mode detected\n");
else if ( IS_ENABLED(CONFIG_DOM0_BOOT) )
create_dom0();
else
panic("Neither dom0 nor dom0less mode was detected, aborting\n");
~Michal
On 02.10.2026 15:26, 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.
I (still) wonder why this would be, but well ...
> 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.
Oleksii - what's your take towards RISC-V here? Should it select the new
symbol right away as well?
> 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>
> Acked-by: Jan Beulich <jbeulich@suse.com>
Notwithstanding the ack, a few further comments.
> --- a/xen/arch/arm/domain_build.c
> +++ b/xen/arch/arm/domain_build.c
> @@ -43,8 +43,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
> @@ -123,6 +125,7 @@ paddr_t __init hwdom_get_fdt_alloc_size(void)
> return ACPI_DOM0_FDT_MIN_SIZE;
> }
>
> +#ifdef CONFIG_DOM0_BOOT
> unsigned int __init dom0_max_vcpus(void)
> {
> if ( opt_dom0_max_vcpus == 0 )
> @@ -135,6 +138,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.
> @@ -1862,6 +1866,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;
> @@ -1893,6 +1898,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)
> @@ -1944,6 +1950,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;
> @@ -2001,6 +2008,7 @@ void __init create_dom0(void)
>
> set_xs_domain(dom0);
> }
> +#endif /* CONFIG_DOM0_BOOT */
It's not really a lot of code which is being removed, which may suggest this
is getting too fine-grained. (Primarily, for now) Arm maintainers will need
to judge.
I further wonder how much unreachable code is newly introduced by this, when
the new option is enabled. set_xs_domain() (visible in patch context above)
is possibly only the first example.
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -491,11 +491,18 @@ void asmlinkage __init noreturn start_xen(unsigned long fdt_paddr)
>
> do_init_boottests();
>
> - /* Create initial domain 0. */
> - if ( !is_dom0less_mode() )
> + if ( IS_ENABLED(CONFIG_DOM0_BOOT) && !is_dom0less_mode() )
> + {
> + /* 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, aborting\n");
> + }
If I was maintainer of this code, I would ask for the figure braces to be
omitted - the inner if() can easily be "else if".
> --- a/xen/common/Kconfig
> +++ b/xen/common/Kconfig
> @@ -26,6 +26,15 @@ 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 && !X86
Like already indicated in reply to v3 I'm irritated by this: What use is
the select of HAS_DOM0 on x86 when then you exclude x86 here? I think it
needs to be clarified whether, as the commit message says, this is going
to be Arm-only or of broader use. In the latter case the !X86 here would
want leaving out; the description then would want to clarify that making
x86 respect the option is a TODO item (possibly part of the hyperlaunch
effort).
In the former case more questions arise, like why this wants to be a
common option in the first place. (But since from an abstract pov this is
a common choice, this case likely doesn't want pursuing anyway.)
Jan
© 2016 - 2026 Red Hat, Inc.