* [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-27 11:12 ` Jan Beulich
2025-01-08 11:13 ` [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic Oleksii Kurochko
` (7 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Unify the API for creating DomUs and checking for Dom0less mode across
architectures, including Arm and RISC-V, with potential applicability
for PPC.
Move dom0less-build.h from the Arm-specific directory to asm-generic
as these header is expected to be the same across acrhictectures with
some updates: add the following declaration of construct_domU(),
arch_xen_domctl_createdomain() and arch_create_domus() as there are
some parts which are still architecture-specific.
Relocate the CONFIG_DOM0LESS configuration to the common with adding
"depends on Arm" to not break builds for architectures which at the
moment don't support CONFIG_DOM0LESS config, especically it would be
useful to not provide stubs for construct_domU(),
arch_xen_domctl_createdomain() and arch_create_domus() in case of
*-randconfig which may set CONFIG_DOM0LESS=y.
Move is_dom0less_mode() function to the common code, as it depends on
boot modules that are already part of the common code.
Move create_domUs() function to the common code with some updates:
- Add function arch_xen_domctl_createdomain() as structure
xen_domctl_createdomain may have some arch-spicific information and
initialization.
- Add arch_create_domus() to cover parsing of arch-specific features,
for example, SVE (Scalar Vector Extension ) exists only in Arm.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/Kconfig | 8 -
xen/arch/arm/dom0less-build.c | 270 ++++++----------------
xen/arch/arm/include/asm/Makefile | 1 +
xen/arch/arm/include/asm/dom0less-build.h | 32 ---
xen/common/Kconfig | 9 +
xen/common/device-tree/Makefile | 1 +
xen/common/device-tree/dom0less-build.c | 161 +++++++++++++
xen/include/asm-generic/dom0less-build.h | 40 ++++
8 files changed, 283 insertions(+), 239 deletions(-)
delete mode 100644 xen/arch/arm/include/asm/dom0less-build.h
create mode 100644 xen/common/device-tree/dom0less-build.c
create mode 100644 xen/include/asm-generic/dom0less-build.h
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index a26d3e1182..eff6ea6b6d 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -117,14 +117,6 @@ config GICV2
Driver for the ARM Generic Interrupt Controller v2.
If unsure, say Y
-config DOM0LESS_BOOT
- bool "Dom0less boot support" if EXPERT
- default y
- help
- Dom0less boot support enables Xen to create and start domU guests during
- Xen boot without the need of a control domain (Dom0), which could be
- present anyway.
-
config GICV3
bool "GICv3 driver"
depends on !NEW_VGIC
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 49d1f14d65..b27747c05c 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -17,38 +17,6 @@
#include <asm/static-memory.h>
#include <asm/static-shmem.h>
-bool __init is_dom0less_mode(void)
-{
- struct bootmodules *mods = &bootinfo.modules;
- struct bootmodule *mod;
- unsigned int i;
- bool dom0found = false;
- bool domUfound = false;
-
- /* Look into the bootmodules */
- for ( i = 0 ; i < mods->nr_mods ; i++ )
- {
- mod = &mods->module[i];
- /* Find if dom0 and domU kernels are present */
- if ( mod->kind == BOOTMOD_KERNEL )
- {
- if ( mod->domU == false )
- {
- dom0found = true;
- break;
- }
- else
- domUfound = true;
- }
- }
-
- /*
- * If there is no dom0 kernel but at least one domU, then we are in
- * dom0less mode
- */
- return ( !dom0found && domUfound );
-}
-
#ifdef CONFIG_VGICV2
static int __init make_gicv2_domU_node(struct kernel_info *kinfo)
{
@@ -704,8 +672,8 @@ static int __init alloc_xenstore_evtchn(struct domain *d)
return 0;
}
-static int __init construct_domU(struct domain *d,
- const struct dt_device_node *node)
+int __init construct_domU(struct domain *d,
+ const struct dt_device_node *node)
{
struct kernel_info kinfo = KERNEL_INFO_INIT;
const char *dom0less_enhanced;
@@ -810,188 +778,92 @@ static int __init construct_domU(struct domain *d,
return rc;
}
-void __init create_domUs(void)
-{
- struct dt_device_node *node;
- const char *dom0less_iommu;
- bool iommu = false;
- const struct dt_device_node *cpupool_node,
- *chosen = dt_find_node_by_path("/chosen");
- const char *llc_colors_str = NULL;
-
- BUG_ON(chosen == NULL);
- dt_for_each_child_node(chosen, node)
- {
- struct domain *d;
- struct xen_domctl_createdomain d_cfg = {
- .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
- .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap,
- /*
- * The default of 1023 should be sufficient for guests because
- * on ARM we don't bind physical interrupts to event channels.
- * The only use of the evtchn port is inter-domain communications.
- * 1023 is also the default value used in libxl.
- */
- .max_evtchn_port = 1023,
- .max_grant_frames = -1,
- .max_maptrack_frames = -1,
- .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
- };
- unsigned int flags = 0U;
- uint32_t val;
- int rc;
-
- if ( !dt_device_is_compatible(node, "xen,domain") )
- continue;
- if ( (max_init_domid + 1) >= DOMID_FIRST_RESERVED )
- panic("No more domain IDs available\n");
-
- if ( dt_find_property(node, "xen,static-mem", NULL) )
- {
- if ( llc_coloring_enabled )
- panic("LLC coloring and static memory are incompatible\n");
-
- flags |= CDF_staticmem;
- }
-
- if ( dt_property_read_bool(node, "direct-map") )
- {
- if ( !(flags & CDF_staticmem) )
- panic("direct-map is not valid for domain %s without static allocation.\n",
- dt_node_name(node));
-
- flags |= CDF_directmap;
- }
-
- if ( !dt_property_read_u32(node, "cpus", &d_cfg.max_vcpus) )
- panic("Missing property 'cpus' for domain %s\n",
- dt_node_name(node));
-
- if ( !dt_property_read_string(node, "passthrough", &dom0less_iommu) &&
- !strcmp(dom0less_iommu, "enabled") )
- iommu = true;
+struct xen_domctl_createdomain __init arch_xen_domctl_createdomain(void)
+{
+ struct xen_domctl_createdomain d_cfg = {
+ .arch.gic_version = XEN_DOMCTL_CONFIG_GIC_NATIVE,
+ .flags = XEN_DOMCTL_CDF_hvm | XEN_DOMCTL_CDF_hap,
+ /*
+ * The default of 1023 should be sufficient for guests because
+ * on ARM we don't bind physical interrupts to event channels.
+ * The only use of the evtchn port is inter-domain communications.
+ * 1023 is also the default value used in libxl.
+ */
+ .max_evtchn_port = 1023,
+ .max_grant_frames = -1,
+ .max_maptrack_frames = -1,
+ .grant_opts = XEN_DOMCTL_GRANT_version(opt_gnttab_max_version),
+ };
+
+ return d_cfg;
+}
- if ( iommu_enabled &&
- (iommu || dt_find_compatible_node(node, NULL,
- "multiboot,device-tree")) )
- d_cfg.flags |= XEN_DOMCTL_CDF_iommu;
+void __init arch_create_domus(struct dt_device_node *node,
+ struct xen_domctl_createdomain *d_cfg,
+ unsigned int flags)
+{
+ uint32_t val;
- if ( !dt_property_read_u32(node, "nr_spis", &d_cfg.arch.nr_spis) )
- {
- int vpl011_virq = GUEST_VPL011_SPI;
-
- d_cfg.arch.nr_spis = gic_number_lines() - 32;
-
- /*
- * The VPL011 virq is GUEST_VPL011_SPI, unless direct-map is
- * set, in which case it'll match the hardware.
- *
- * Since the domain is not yet created, we can't use
- * d->arch.vpl011.irq. So the logic to find the vIRQ has to
- * be hardcoded.
- * The logic here shall be consistent with the one in
- * domain_vpl011_init().
- */
- if ( flags & CDF_directmap )
- {
- vpl011_virq = serial_irq(SERHND_DTUART);
- if ( vpl011_virq < 0 )
- panic("Error getting IRQ number for this serial port %d\n",
- SERHND_DTUART);
- }
+ if ( !dt_property_read_u32(node, "nr_spis", &d_cfg->arch.nr_spis) )
+ {
+ int vpl011_virq = GUEST_VPL011_SPI;
- /*
- * vpl011 uses one emulated SPI. If vpl011 is requested, make
- * sure that we allocate enough SPIs for it.
- */
- if ( dt_property_read_bool(node, "vpl011") )
- d_cfg.arch.nr_spis = MAX(d_cfg.arch.nr_spis,
- vpl011_virq - 32 + 1);
- }
+ d_cfg->arch.nr_spis = gic_number_lines() - 32;
- /* Get the optional property domain-cpupool */
- cpupool_node = dt_parse_phandle(node, "domain-cpupool", 0);
- if ( cpupool_node )
+ /*
+ * The VPL011 virq is GUEST_VPL011_SPI, unless direct-map is
+ * set, in which case it'll match the hardware.
+ *
+ * Since the domain is not yet created, we can't use
+ * d->arch.vpl011.irq. So the logic to find the vIRQ has to
+ * be hardcoded.
+ * The logic here shall be consistent with the one in
+ * domain_vpl011_init().
+ */
+ if ( flags & CDF_directmap )
{
- int pool_id = btcpupools_get_domain_pool_id(cpupool_node);
- if ( pool_id < 0 )
- panic("Error getting cpupool id from domain-cpupool (%d)\n",
- pool_id);
- d_cfg.cpupool_id = pool_id;
+ vpl011_virq = serial_irq(SERHND_DTUART);
+ if ( vpl011_virq < 0 )
+ panic("Error getting IRQ number for this serial port %d\n",
+ SERHND_DTUART);
}
- if ( dt_property_read_u32(node, "max_grant_version", &val) )
- d_cfg.grant_opts = XEN_DOMCTL_GRANT_version(val);
+ /*
+ * vpl011 uses one emulated SPI. If vpl011 is requested, make
+ * sure that we allocate enough SPIs for it.
+ */
+ if ( dt_property_read_bool(node, "vpl011") )
+ d_cfg->arch.nr_spis = MAX(d_cfg->arch.nr_spis,
+ vpl011_virq - 32 + 1);
+ }
- if ( dt_property_read_u32(node, "max_grant_frames", &val) )
- {
- if ( val > INT32_MAX )
- panic("max_grant_frames (%"PRIu32") overflow\n", val);
- d_cfg.max_grant_frames = val;
- }
+ if ( dt_get_property(node, "sve", &val) )
+ {
+#ifdef CONFIG_ARM64_SVE
+ unsigned int sve_vl_bits;
+ bool ret = false;
- if ( dt_property_read_u32(node, "max_maptrack_frames", &val) )
+ if ( !val )
{
- if ( val > INT32_MAX )
- panic("max_maptrack_frames (%"PRIu32") overflow\n", val);
- d_cfg.max_maptrack_frames = val;
+ /* Property found with no value, means max HW VL supported */
+ ret = sve_domctl_vl_param(-1, &sve_vl_bits);
}
-
- if ( dt_get_property(node, "sve", &val) )
+ else
{
-#ifdef CONFIG_ARM64_SVE
- unsigned int sve_vl_bits;
- bool ret = false;
-
- if ( !val )
- {
- /* Property found with no value, means max HW VL supported */
- ret = sve_domctl_vl_param(-1, &sve_vl_bits);
- }
+ if ( dt_property_read_u32(node, "sve", &val) )
+ ret = sve_domctl_vl_param(val, &sve_vl_bits);
else
- {
- if ( dt_property_read_u32(node, "sve", &val) )
- ret = sve_domctl_vl_param(val, &sve_vl_bits);
- else
- panic("Error reading 'sve' property\n");
- }
+ panic("Error reading 'sve' property\n");
+ }
- if ( ret )
- d_cfg.arch.sve_vl = sve_encode_vl(sve_vl_bits);
- else
- panic("SVE vector length error\n");
+ if ( ret )
+ d_cfg->arch.sve_vl = sve_encode_vl(sve_vl_bits);
+ else
+ panic("SVE vector length error\n");
#else
- panic("'sve' property found, but CONFIG_ARM64_SVE not selected\n");
+ panic("'sve' property found, but CONFIG_ARM64_SVE not selected\n");
#endif
- }
-
- dt_property_read_string(node, "llc-colors", &llc_colors_str);
- if ( !llc_coloring_enabled && llc_colors_str )
- panic("'llc-colors' found, but LLC coloring is disabled\n");
-
- /*
- * The variable max_init_domid is initialized with zero, so here it's
- * very important to use the pre-increment operator to call
- * domain_create() with a domid > 0. (domid == 0 is reserved for Dom0)
- */
- d = domain_create(++max_init_domid, &d_cfg, flags);
- if ( IS_ERR(d) )
- panic("Error creating domain %s (rc = %ld)\n",
- dt_node_name(node), PTR_ERR(d));
-
- if ( llc_coloring_enabled &&
- (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) )
- panic("Error initializing LLC coloring for domain %s (rc = %d)\n",
- dt_node_name(node), rc);
-
- d->is_console = true;
- dt_device_set_used_by(node, d->domain_id);
-
- rc = construct_domU(d, node);
- if ( rc )
- panic("Could not set up domain %s (rc = %d)\n",
- dt_node_name(node), rc);
}
}
diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile
index 4a4036c951..831c914cce 100644
--- a/xen/arch/arm/include/asm/Makefile
+++ b/xen/arch/arm/include/asm/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
generic-y += altp2m.h
generic-y += device.h
+generic-y += dom0less-build.h
generic-y += hardirq.h
generic-y += iocap.h
generic-y += paging.h
diff --git a/xen/arch/arm/include/asm/dom0less-build.h b/xen/arch/arm/include/asm/dom0less-build.h
deleted file mode 100644
index 5864944bda..0000000000
--- a/xen/arch/arm/include/asm/dom0less-build.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_DOM0LESS_BUILD_H_
-#define __ASM_DOM0LESS_BUILD_H_
-
-#include <xen/stdbool.h>
-
-#ifdef CONFIG_DOM0LESS_BOOT
-
-void create_domUs(void);
-bool is_dom0less_mode(void);
-
-#else /* !CONFIG_DOM0LESS_BOOT */
-
-static inline void create_domUs(void) {}
-static inline bool is_dom0less_mode(void)
-{
- return false;
-}
-
-#endif /* CONFIG_DOM0LESS_BOOT */
-
-#endif /* __ASM_DOM0LESS_BUILD_H_ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 6166327f4d..099e6e72ad 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -12,6 +12,15 @@ config CORE_PARKING
bool
depends on NR_CPUS > 1
+config DOM0LESS_BOOT
+ bool "Dom0less boot support" if EXPERT
+ depends on ARM
+ default ARM
+ help
+ Dom0less boot support enables Xen to create and start domU guests during
+ Xen boot without the need of a control domain (Dom0), which could be
+ present anyway.
+
config GRANT_TABLE
bool "Grant table support" if EXPERT
default y
diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile
index 7c549be38a..f3dafc9b81 100644
--- a/xen/common/device-tree/Makefile
+++ b/xen/common/device-tree/Makefile
@@ -1,5 +1,6 @@
obj-y += bootfdt.init.o
obj-y += bootinfo.init.o
obj-y += device-tree.o
+obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o
obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o
obj-y += intc.o
diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c
new file mode 100644
index 0000000000..19bfa5e005
--- /dev/null
+++ b/xen/common/device-tree/dom0less-build.c
@@ -0,0 +1,161 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#include <xen/bootfdt.h>
+#include <xen/device_tree.h>
+#include <xen/domain.h>
+#include <xen/err.h>
+#include <xen/init.h>
+#include <xen/iommu.h>
+#include <xen/llc-coloring.h>
+#include <xen/sched.h>
+#include <xen/stdbool.h>
+#include <xen/types.h>
+
+#include <public/domctl.h>
+
+#include <asm/dom0less-build.h>
+#include <asm/setup.h>
+
+bool __init is_dom0less_mode(void)
+{
+ struct bootmodules *mods = &bootinfo.modules;
+ struct bootmodule *mod;
+ unsigned int i;
+ bool dom0found = false;
+ bool domUfound = false;
+
+ /* Look into the bootmodules */
+ for ( i = 0 ; i < mods->nr_mods ; i++ )
+ {
+ mod = &mods->module[i];
+ /* Find if dom0 and domU kernels are present */
+ if ( mod->kind == BOOTMOD_KERNEL )
+ {
+ if ( mod->domU == false )
+ {
+ dom0found = true;
+ break;
+ }
+ else
+ domUfound = true;
+ }
+ }
+
+ /*
+ * If there is no dom0 kernel but at least one domU, then we are in
+ * dom0less mode
+ */
+ return ( !dom0found && domUfound );
+}
+
+void __init create_domUs(void)
+{
+ struct dt_device_node *node;
+ const char *dom0less_iommu;
+ bool iommu = false;
+ const struct dt_device_node *cpupool_node,
+ *chosen = dt_find_node_by_path("/chosen");
+ const char *llc_colors_str = NULL;
+
+ BUG_ON(chosen == NULL);
+ dt_for_each_child_node(chosen, node)
+ {
+ struct domain *d;
+ struct xen_domctl_createdomain d_cfg = arch_xen_domctl_createdomain();
+ unsigned int flags = 0U;
+ uint32_t val;
+ int rc;
+
+ if ( !dt_device_is_compatible(node, "xen,domain") )
+ continue;
+
+ if ( (max_init_domid + 1) >= DOMID_FIRST_RESERVED )
+ panic("No more domain IDs available\n");
+
+ if ( dt_find_property(node, "xen,static-mem", NULL) )
+ {
+ if ( llc_coloring_enabled )
+ panic("LLC coloring and static memory are incompatible\n");
+
+ flags |= CDF_staticmem;
+ }
+
+ if ( dt_property_read_bool(node, "direct-map") )
+ {
+ if ( !(flags & CDF_staticmem) )
+ panic("direct-map is not valid for domain %s without static allocation.\n",
+ dt_node_name(node));
+
+ flags |= CDF_directmap;
+ }
+
+ if ( !dt_property_read_u32(node, "cpus", &d_cfg.max_vcpus) )
+ panic("Missing property 'cpus' for domain %s\n",
+ dt_node_name(node));
+
+ if ( !dt_property_read_string(node, "passthrough", &dom0less_iommu) &&
+ !strcmp(dom0less_iommu, "enabled") )
+ iommu = true;
+
+ if ( iommu_enabled &&
+ (iommu || dt_find_compatible_node(node, NULL,
+ "multiboot,device-tree")) )
+ d_cfg.flags |= XEN_DOMCTL_CDF_iommu;
+
+ /* Get the optional property domain-cpupool */
+ cpupool_node = dt_parse_phandle(node, "domain-cpupool", 0);
+ if ( cpupool_node )
+ {
+ int pool_id = btcpupools_get_domain_pool_id(cpupool_node);
+ if ( pool_id < 0 )
+ panic("Error getting cpupool id from domain-cpupool (%d)\n",
+ pool_id);
+ d_cfg.cpupool_id = pool_id;
+ }
+
+ if ( dt_property_read_u32(node, "max_grant_version", &val) )
+ d_cfg.grant_opts = XEN_DOMCTL_GRANT_version(val);
+
+ if ( dt_property_read_u32(node, "max_grant_frames", &val) )
+ {
+ if ( val > INT32_MAX )
+ panic("max_grant_frames (%"PRIu32") overflow\n", val);
+ d_cfg.max_grant_frames = val;
+ }
+
+ if ( dt_property_read_u32(node, "max_maptrack_frames", &val) )
+ {
+ if ( val > INT32_MAX )
+ panic("max_maptrack_frames (%"PRIu32") overflow\n", val);
+ d_cfg.max_maptrack_frames = val;
+ }
+
+ dt_property_read_string(node, "llc-colors", &llc_colors_str);
+ if ( !llc_coloring_enabled && llc_colors_str )
+ panic("'llc-colors' found, but LLC coloring is disabled\n");
+
+ arch_create_domus(node, &d_cfg, flags);
+
+ /*
+ * The variable max_init_domid is initialized with zero, so here it's
+ * very important to use the pre-increment operator to call
+ * domain_create() with a domid > 0. (domid == 0 is reserved for Dom0)
+ */
+ d = domain_create(++max_init_domid, &d_cfg, flags);
+ if ( IS_ERR(d) )
+ panic("Error creating domain %s (rc = %ld)\n",
+ dt_node_name(node), PTR_ERR(d));
+
+ if ( llc_coloring_enabled &&
+ (rc = domain_set_llc_colors_from_str(d, llc_colors_str)) )
+ panic("Error initializing LLC coloring for domain %s (rc = %d)\n",
+ dt_node_name(node), rc);
+
+ d->is_console = true;
+ dt_device_set_used_by(node, d->domain_id);
+
+ rc = construct_domU(d, node);
+ if ( rc )
+ panic("Could not set up domain %s (rc = %d)\n",
+ dt_node_name(node), rc);
+ }
+}
diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h
new file mode 100644
index 0000000000..a6985bc20a
--- /dev/null
+++ b/xen/include/asm-generic/dom0less-build.h
@@ -0,0 +1,40 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_GENERIC_DOM0LESS_BUILD_H__
+#define __ASM_GENERIC_DOM0LESS_BUILD_H__
+
+#include <xen/stdbool.h>
+
+#ifdef CONFIG_DOM0LESS_BOOT
+
+#include <public/domctl.h>
+
+void create_domUs(void);
+bool is_dom0less_mode(void);
+
+int construct_domU(struct domain *d, const struct dt_device_node *node);
+
+struct xen_domctl_createdomain arch_xen_domctl_createdomain(void);
+void arch_create_domus(struct dt_device_node *node,
+ struct xen_domctl_createdomain *d_cfg,
+ unsigned int flags);
+
+#else /* !CONFIG_DOM0LESS_BOOT */
+
+static inline void create_domUs(void) {}
+static inline bool is_dom0less_mode(void)
+{
+ return false;
+}
+
+#endif /* CONFIG_DOM0LESS_BOOT */
+
+#endif /* __ASM_GENERIC_DOM0LESS_BUILD_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common
2025-01-08 11:13 ` [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common Oleksii Kurochko
@ 2025-01-27 11:12 ` Jan Beulich
2025-02-03 15:18 ` Oleksii Kurochko
0 siblings, 1 reply; 20+ messages in thread
From: Jan Beulich @ 2025-01-27 11:12 UTC (permalink / raw)
To: Oleksii Kurochko
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
On 08.01.2025 12:13, Oleksii Kurochko wrote:
> Unify the API for creating DomUs and checking for Dom0less mode across
> architectures, including Arm and RISC-V, with potential applicability
> for PPC.
That is you mean to re-use it for RISC-V?
> --- a/xen/common/Kconfig
> +++ b/xen/common/Kconfig
> @@ -12,6 +12,15 @@ config CORE_PARKING
> bool
> depends on NR_CPUS > 1
>
> +config DOM0LESS_BOOT
> + bool "Dom0less boot support" if EXPERT
> + depends on ARM
> + default ARM
This then would better be converted to "depends on HAVE_DOM0LESS", which
for now only Arm would select. With a dependency on XYZ the default also
doesn't need to name XYZ again, i.e. can simply be "default y".
Jan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common
2025-01-27 11:12 ` Jan Beulich
@ 2025-02-03 15:18 ` Oleksii Kurochko
0 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-02-03 15:18 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
[-- Attachment #1: Type: text/plain, Size: 881 bytes --]
On 1/27/25 12:12 PM, Jan Beulich wrote:
> On 08.01.2025 12:13, Oleksii Kurochko wrote:
>> Unify the API for creating DomUs and checking for Dom0less mode across
>> architectures, including Arm and RISC-V, with potential applicability
>> for PPC.
> That is you mean to re-use it for RISC-V?
Yes, I will re-use it.
>
>> --- a/xen/common/Kconfig
>> +++ b/xen/common/Kconfig
>> @@ -12,6 +12,15 @@ config CORE_PARKING
>> bool
>> depends on NR_CPUS > 1
>>
>> +config DOM0LESS_BOOT
>> + bool "Dom0less boot support" if EXPERT
>> + depends on ARM
>> + default ARM
> This then would better be converted to "depends on HAVE_DOM0LESS", which
> for now only Arm would select. With a dependency on XYZ the default also
> doesn't need to name XYZ again, i.e. can simply be "default y".
"depends on HAVE_DOM0LESS" would be better. I will update correspondingly.
Thanks.
~ Oleksii
[-- Attachment #2: Type: text/html, Size: 1705 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-27 11:15 ` Jan Beulich
2025-01-08 11:13 ` [PATCH v1 3/9] arm/static-shmem.h: drop inclusion of asm/setup.h Oleksii Kurochko
` (6 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Move the following parts to asm-generic with the following changes:
- struct kernel_info:
- Create arch_kernel_info for arch specific kernel information.
At the moment, it contains domain_type for Arm.
- Rename vpl011 to vuart to have more generic name suitable for other archs.
- s/phandle_gic/phandle_intc to have more generic name suitable for other
archs.
- Make text_offset of zimage structure available for RISCV_64.
- Wrap by `#ifdef KERNEL_INFO_SHM_MEM_INIT` definition of KERNEL_SHM_MEM_INIT
and wrap by `#ifndef KERNEL_INFO_INIT` definition of KERNEL_INFO_INIT to have
ability to override KERNEL_INFO_SHM_MEM_INIT for arch in case it doesn't
want to use generic one.
- All other parts are left as is from Arm's asm/kernel.h
Because of the changes in struct kernel_info the correspondent parts of Arm's
code are updated.
As part of this patch the following clean up happens:
- Drop asm/setup.h from asm/kernel.h as nothing depends from it.
Add inclusion of asm/setup.h for a code which uses device_tree_get_reg() to
avoid compilation issues for CONFIG_STATIC_MEMORY and CONFIG_STATIC_SHM.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/dom0less-build.c | 28 +++---
xen/arch/arm/domain_build.c | 10 +-
xen/arch/arm/include/asm/kernel.h | 115 +----------------------
xen/arch/arm/kernel.c | 10 +-
xen/arch/arm/static-memory.c | 1 +
xen/arch/arm/static-shmem.c | 1 +
xen/include/asm-generic/kernel.h | 146 ++++++++++++++++++++++++++++++
7 files changed, 175 insertions(+), 136 deletions(-)
create mode 100644 xen/include/asm-generic/kernel.h
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index b27747c05c..c4badb4ade 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -57,11 +57,11 @@ static int __init make_gicv2_domU_node(struct kernel_info *kinfo)
if (res)
return res;
- res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_gic);
+ res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_intc);
if (res)
return res;
- res = fdt_property_cell(fdt, "phandle", kinfo->phandle_gic);
+ res = fdt_property_cell(fdt, "phandle", kinfo->phandle_intc);
if (res)
return res;
@@ -128,11 +128,11 @@ static int __init make_gicv3_domU_node(struct kernel_info *kinfo)
if (res)
return res;
- res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_gic);
+ res = fdt_property_cell(fdt, "linux,phandle", kinfo->phandle_intc);
if (res)
return res;
- res = fdt_property_cell(fdt, "phandle", kinfo->phandle_gic);
+ res = fdt_property_cell(fdt, "phandle", kinfo->phandle_intc);
if (res)
return res;
@@ -193,7 +193,7 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo)
return res;
res = fdt_property_cell(fdt, "interrupt-parent",
- kinfo->phandle_gic);
+ kinfo->phandle_intc);
if ( res )
return res;
@@ -479,10 +479,10 @@ static int __init domain_handle_dtb_bootmodule(struct domain *d,
*/
if ( dt_node_cmp(name, "gic") == 0 )
{
- uint32_t phandle_gic = fdt_get_phandle(pfdt, node_next);
+ uint32_t phandle_intc = fdt_get_phandle(pfdt, node_next);
- if ( phandle_gic != 0 )
- kinfo->phandle_gic = phandle_gic;
+ if ( phandle_intc != 0 )
+ kinfo->phandle_intc = phandle_intc;
continue;
}
@@ -525,7 +525,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
int addrcells, sizecells;
int ret, fdt_size = DOMU_DTB_SIZE;
- kinfo->phandle_gic = GUEST_PHANDLE_GIC;
+ kinfo->phandle_intc = GUEST_PHANDLE_GIC;
kinfo->gnttab_start = GUEST_GNTTAB_BASE;
kinfo->gnttab_size = GUEST_GNTTAB_SIZE;
@@ -587,7 +587,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
/*
* domain_handle_dtb_bootmodule has to be called before the rest of
* the device tree is generated because it depends on the value of
- * the field phandle_gic.
+ * the field phandle_intc.
*/
if ( kinfo->dtb_bootmodule )
{
@@ -604,7 +604,7 @@ static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
if ( ret )
goto err;
- if ( kinfo->vpl011 )
+ if ( kinfo->vuart )
{
ret = -EINVAL;
#ifdef CONFIG_SBSA_VUART_CONSOLE
@@ -705,7 +705,7 @@ int __init construct_domU(struct domain *d,
printk("*** LOADING DOMU cpus=%u memory=%#"PRIx64"KB ***\n",
d->max_vcpus, mem);
- kinfo.vpl011 = dt_property_read_bool(node, "vpl011");
+ kinfo.vuart = dt_property_read_bool(node, "vpl011");
rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced);
if ( rc == -EILSEQ ||
@@ -733,7 +733,7 @@ int __init construct_domU(struct domain *d,
#ifdef CONFIG_ARM_64
/* type must be set before allocate memory */
- d->arch.type = kinfo.type;
+ d->arch.type = kinfo.arch.type;
#endif
if ( !dt_find_property(node, "xen,static-mem", NULL) )
allocate_memory(d, &kinfo);
@@ -751,7 +751,7 @@ int __init construct_domU(struct domain *d,
* tree node in prepare_dtb_domU, so initialization on related variables
* shall be done first.
*/
- if ( kinfo.vpl011 )
+ if ( kinfo.vuart )
{
rc = domain_vpl011_init(d, NULL);
if ( rc < 0 )
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index b072a16249..976b03a5df 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -747,7 +747,7 @@ static int __init fdt_property_interrupts(const struct kernel_info *kinfo,
return res;
res = fdt_property_cell(kinfo->fdt, "interrupt-parent",
- kinfo->phandle_gic);
+ kinfo->phandle_intc);
return res;
}
@@ -2026,7 +2026,7 @@ static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
ASSERT(dt_host && (dt_host->sibling == NULL));
- kinfo->phandle_gic = dt_interrupt_controller->phandle;
+ kinfo->phandle_intc = dt_interrupt_controller->phandle;
fdt = device_tree_flattened;
new_size = fdt_totalsize(fdt) + DOM0_FDT_EXTRA_SIZE;
@@ -2194,13 +2194,13 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
#ifdef CONFIG_ARM_64
/* if aarch32 mode is not supported at EL1 do not allow 32-bit domain */
- if ( !(cpu_has_el1_32) && kinfo->type == DOMAIN_32BIT )
+ if ( !(cpu_has_el1_32) && kinfo->arch.type == DOMAIN_32BIT )
{
printk("Platform does not support 32-bit domain\n");
return -EINVAL;
}
- if ( is_sve_domain(d) && (kinfo->type == DOMAIN_32BIT) )
+ if ( is_sve_domain(d) && (kinfo->arch.type == DOMAIN_32BIT) )
{
printk("SVE is not available for 32-bit domain\n");
return -EINVAL;
@@ -2307,7 +2307,7 @@ static int __init construct_dom0(struct domain *d)
#ifdef CONFIG_ARM_64
/* type must be set before allocate_memory */
- d->arch.type = kinfo.type;
+ d->arch.type = kinfo.arch.type;
#endif
find_gnttab_region(d, &kinfo);
if ( is_domain_direct_mapped(d) )
diff --git a/xen/arch/arm/include/asm/kernel.h b/xen/arch/arm/include/asm/kernel.h
index 7e6e3c82a4..4d74f0bcb2 100644
--- a/xen/arch/arm/include/asm/kernel.h
+++ b/xen/arch/arm/include/asm/kernel.h
@@ -6,125 +6,16 @@
#ifndef __ARCH_ARM_KERNEL_H__
#define __ARCH_ARM_KERNEL_H__
-#include <xen/device_tree.h>
#include <asm/domain.h>
-#include <asm/setup.h>
-/*
- * List of possible features for dom0less domUs
- *
- * DOM0LESS_ENHANCED_NO_XS: Notify the OS it is running on top of Xen. All the
- * default features (excluding Xenstore) will be
- * available. Note that an OS *must* not rely on the
- * availability of Xen features if this is not set.
- * DOM0LESS_XENSTORE: Xenstore will be enabled for the VM. This feature
- * can't be enabled without the
- * DOM0LESS_ENHANCED_NO_XS.
- * DOM0LESS_ENHANCED: Notify the OS it is running on top of Xen. All the
- * default features (including Xenstore) will be
- * available. Note that an OS *must* not rely on the
- * availability of Xen features if this is not set.
- */
-#define DOM0LESS_ENHANCED_NO_XS BIT(0, U)
-#define DOM0LESS_XENSTORE BIT(1, U)
-#define DOM0LESS_ENHANCED (DOM0LESS_ENHANCED_NO_XS | DOM0LESS_XENSTORE)
-
-struct kernel_info {
+struct arch_kernel_info
+{
#ifdef CONFIG_ARM_64
enum domain_type type;
#endif
-
- struct domain *d;
-
- void *fdt; /* flat device tree */
- paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
- struct meminfo mem;
-#ifdef CONFIG_STATIC_SHM
- struct shared_meminfo shm_mem;
-#endif
-
- /* kernel entry point */
- paddr_t entry;
-
- /* grant table region */
- paddr_t gnttab_start;
- paddr_t gnttab_size;
-
- /* boot blob load addresses */
- const struct bootmodule *kernel_bootmodule, *initrd_bootmodule, *dtb_bootmodule;
- const char* cmdline;
- paddr_t dtb_paddr;
- paddr_t initrd_paddr;
-
- /* Enable pl011 emulation */
- bool vpl011;
-
- /* Enable/Disable PV drivers interfaces */
- uint16_t dom0less_feature;
-
- /* GIC phandle */
- uint32_t phandle_gic;
-
- /* loader to use for this kernel */
- void (*load)(struct kernel_info *info);
- /* loader specific state */
- union {
- struct {
- paddr_t kernel_addr;
- paddr_t len;
-#ifdef CONFIG_ARM_64
- paddr_t text_offset; /* 64-bit Image only */
-#endif
- paddr_t start; /* Must be 0 for 64-bit Image */
- } zimage;
- };
};
-static inline struct membanks *kernel_info_get_mem(struct kernel_info *kinfo)
-{
- return container_of(&kinfo->mem.common, struct membanks, common);
-}
-
-static inline const struct membanks *
-kernel_info_get_mem_const(const struct kernel_info *kinfo)
-{
- return container_of(&kinfo->mem.common, const struct membanks, common);
-}
-
-#ifdef CONFIG_STATIC_SHM
-#define KERNEL_INFO_SHM_MEM_INIT .shm_mem.common.max_banks = NR_SHMEM_BANKS,
-#else
-#define KERNEL_INFO_SHM_MEM_INIT
-#endif
-
-#define KERNEL_INFO_INIT \
-{ \
- .mem.common.max_banks = NR_MEM_BANKS, \
- KERNEL_INFO_SHM_MEM_INIT \
-}
-
-/*
- * Probe the kernel to detemine its type and select a loader.
- *
- * Sets in info:
- * ->type
- * ->load hook, and sets loader specific variables ->zimage
- */
-int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
-
-/*
- * Loads the kernel into guest RAM.
- *
- * Expects to be set in info when called:
- * ->mem
- * ->fdt
- *
- * Sets in info:
- * ->entry
- * ->dtb_paddr
- * ->initrd_paddr
- */
-void kernel_load(struct kernel_info *info);
+#include <asm-generic/kernel.h>
#endif /* #ifdef __ARCH_ARM_KERNEL_H__ */
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index 80fad8b336..b75bd6a887 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -101,7 +101,7 @@ static paddr_t __init kernel_zimage_place(struct kernel_info *info)
paddr_t load_addr;
#ifdef CONFIG_ARM_64
- if ( (info->type == DOMAIN_64BIT) && (info->zimage.start == 0) )
+ if ( (info->arch.type == DOMAIN_64BIT) && (info->zimage.start == 0) )
return mem->bank[0].start + info->zimage.text_offset;
#endif
@@ -371,10 +371,10 @@ static int __init kernel_uimage_probe(struct kernel_info *info,
switch ( uimage.arch )
{
case IH_ARCH_ARM:
- info->type = DOMAIN_32BIT;
+ info->arch.type = DOMAIN_32BIT;
break;
case IH_ARCH_ARM64:
- info->type = DOMAIN_64BIT;
+ info->arch.type = DOMAIN_64BIT;
break;
default:
printk(XENLOG_ERR "Unsupported uImage arch type %d\n", uimage.arch);
@@ -444,7 +444,7 @@ static int __init kernel_zimage64_probe(struct kernel_info *info,
info->load = kernel_zimage_load;
- info->type = DOMAIN_64BIT;
+ info->arch.type = DOMAIN_64BIT;
return 0;
}
@@ -496,7 +496,7 @@ static int __init kernel_zimage32_probe(struct kernel_info *info,
info->load = kernel_zimage_load;
#ifdef CONFIG_ARM_64
- info->type = DOMAIN_32BIT;
+ info->arch.type = DOMAIN_32BIT;
#endif
return 0;
diff --git a/xen/arch/arm/static-memory.c b/xen/arch/arm/static-memory.c
index d4585c5a06..e0f76afcd8 100644
--- a/xen/arch/arm/static-memory.c
+++ b/xen/arch/arm/static-memory.c
@@ -2,6 +2,7 @@
#include <xen/sched.h>
+#include <asm/setup.h>
#include <asm/static-memory.h>
static bool __init append_static_memory_to_bank(struct domain *d,
diff --git a/xen/arch/arm/static-shmem.c b/xen/arch/arm/static-shmem.c
index 66088a4267..aff05d24d1 100644
--- a/xen/arch/arm/static-shmem.c
+++ b/xen/arch/arm/static-shmem.c
@@ -6,6 +6,7 @@
#include <xen/sched.h>
#include <asm/domain_build.h>
+#include <asm/setup.h>
#include <asm/static-memory.h>
#include <asm/static-shmem.h>
diff --git a/xen/include/asm-generic/kernel.h b/xen/include/asm-generic/kernel.h
new file mode 100644
index 0000000000..b2bd04a185
--- /dev/null
+++ b/xen/include/asm-generic/kernel.h
@@ -0,0 +1,146 @@
+/*
+ * Kernel image loading.
+ *
+ * Copyright (C) 2011 Citrix Systems, Inc.
+ */
+#ifndef __ASM_GENERIC_KERNEL_H__
+#define __ASM_GENERIC_KERNEL_H__
+
+#include <xen/bootfdt.h>
+#include <xen/device_tree.h>
+#include <xen/sched.h>
+#include <xen/types.h>
+
+/*
+ * List of possible features for dom0less domUs
+ *
+ * DOM0LESS_ENHANCED_NO_XS: Notify the OS it is running on top of Xen. All the
+ * default features (excluding Xenstore) will be
+ * available. Note that an OS *must* not rely on the
+ * availability of Xen features if this is not set.
+ * DOM0LESS_XENSTORE: Xenstore will be enabled for the VM. This feature
+ * can't be enabled without the
+ * DOM0LESS_ENHANCED_NO_XS.
+ * DOM0LESS_ENHANCED: Notify the OS it is running on top of Xen. All the
+ * default features (including Xenstore) will be
+ * available. Note that an OS *must* not rely on the
+ * availability of Xen features if this is not set.
+ */
+#define DOM0LESS_ENHANCED_NO_XS BIT(0, U)
+#define DOM0LESS_XENSTORE BIT(1, U)
+#define DOM0LESS_ENHANCED (DOM0LESS_ENHANCED_NO_XS | DOM0LESS_XENSTORE)
+
+struct kernel_info {
+ struct domain *d;
+
+ void *fdt; /* flat device tree */
+ paddr_t unassigned_mem; /* RAM not (yet) assigned to a bank */
+ struct meminfo mem;
+#ifdef CONFIG_STATIC_SHM
+ struct shared_meminfo shm_mem;
+#endif
+
+ /* kernel entry point */
+ paddr_t entry;
+
+ /* grant table region */
+ paddr_t gnttab_start;
+ paddr_t gnttab_size;
+
+ /* boot blob load addresses */
+ const struct bootmodule *kernel_bootmodule, *initrd_bootmodule, *dtb_bootmodule;
+ const char* cmdline;
+ paddr_t dtb_paddr;
+ paddr_t initrd_paddr;
+
+ /* Enable uart emulation */
+ bool vuart;
+
+ /* Enable/Disable PV drivers interfaces */
+ uint16_t dom0less_feature;
+
+ /* Interrupt controller phandle */
+ uint32_t phandle_intc;
+
+ /* loader to use for this kernel */
+ void (*load)(struct kernel_info *info);
+
+ /* loader specific state */
+ union {
+ struct {
+ paddr_t kernel_addr;
+ paddr_t len;
+#if defined(CONFIG_ARM_64) || defined(CONFIG_RISCV_64)
+ paddr_t text_offset; /* 64-bit Image only */
+#endif
+ paddr_t start; /* Must be 0 for 64-bit Image */
+ } zimage;
+ };
+
+ struct arch_kernel_info arch;
+};
+
+static inline struct membanks *kernel_info_get_mem(struct kernel_info *kinfo)
+{
+ return container_of(&kinfo->mem.common, struct membanks, common);
+}
+
+static inline const struct membanks *
+kernel_info_get_mem_const(const struct kernel_info *kinfo)
+{
+ return container_of(&kinfo->mem.common, const struct membanks, common);
+}
+
+#ifndef KERNEL_INFO_SHM_MEM_INIT
+
+#ifdef CONFIG_STATIC_SHM
+#define KERNEL_INFO_SHM_MEM_INIT .shm_mem.common.max_banks = NR_SHMEM_BANKS,
+#else
+#define KERNEL_INFO_SHM_MEM_INIT
+#endif
+
+#endif /* KERNEL_INFO_SHM_MEM_INIT */
+
+#ifndef KERNEL_INFO_INIT
+
+#define KERNEL_INFO_INIT \
+{ \
+ .mem.common.max_banks = NR_MEM_BANKS, \
+ KERNEL_INFO_SHM_MEM_INIT \
+}
+
+#endif /* KERNEL_INFO_INIT */
+
+/*
+ * Probe the kernel to detemine its type and select a loader.
+ *
+ * Sets in info:
+ * ->type
+ * ->load hook, and sets loader specific variables ->zimage
+ */
+int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
+
+/*
+ * Loads the kernel into guest RAM.
+ *
+ * Expects to be set in info when called:
+ * ->mem
+ * ->fdt
+ *
+ * Sets in info:
+ * ->entry
+ * ->dtb_paddr
+ * ->initrd_paddr
+ */
+void kernel_load(struct kernel_info *info);
+
+#endif /*__ASM_GENERIC_KERNEL_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic
2025-01-08 11:13 ` [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic Oleksii Kurochko
@ 2025-01-27 11:15 ` Jan Beulich
2025-02-03 15:34 ` Oleksii Kurochko
0 siblings, 1 reply; 20+ messages in thread
From: Jan Beulich @ 2025-01-27 11:15 UTC (permalink / raw)
To: Oleksii Kurochko
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
On 08.01.2025 12:13, Oleksii Kurochko wrote:
> Move the following parts to asm-generic with the following changes:
> - struct kernel_info:
> - Create arch_kernel_info for arch specific kernel information.
> At the moment, it contains domain_type for Arm.
> - Rename vpl011 to vuart to have more generic name suitable for other archs.
> - s/phandle_gic/phandle_intc to have more generic name suitable for other
> archs.
> - Make text_offset of zimage structure available for RISCV_64.
> - Wrap by `#ifdef KERNEL_INFO_SHM_MEM_INIT` definition of KERNEL_SHM_MEM_INIT
> and wrap by `#ifndef KERNEL_INFO_INIT` definition of KERNEL_INFO_INIT to have
> ability to override KERNEL_INFO_SHM_MEM_INIT for arch in case it doesn't
> want to use generic one.
> - All other parts are left as is from Arm's asm/kernel.h
>
> Because of the changes in struct kernel_info the correspondent parts of Arm's
> code are updated.
>
> As part of this patch the following clean up happens:
> - Drop asm/setup.h from asm/kernel.h as nothing depends from it.
> Add inclusion of asm/setup.h for a code which uses device_tree_get_reg() to
> avoid compilation issues for CONFIG_STATIC_MEMORY and CONFIG_STATIC_SHM.
>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
I question that what is being moved qualifies for asm-generic, an in particular
for a header named kernel.h. Some of what you move may make sense to move to
dom0less-build.h instead. But everything that doesn't fit there needs to find
a different home, imo.
Jan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic
2025-01-27 11:15 ` Jan Beulich
@ 2025-02-03 15:34 ` Oleksii Kurochko
2025-02-03 16:33 ` Jan Beulich
0 siblings, 1 reply; 20+ messages in thread
From: Oleksii Kurochko @ 2025-02-03 15:34 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
[-- Attachment #1: Type: text/plain, Size: 2216 bytes --]
On 1/27/25 12:15 PM, Jan Beulich wrote:
> On 08.01.2025 12:13, Oleksii Kurochko wrote:
>> Move the following parts to asm-generic with the following changes:
>> - struct kernel_info:
>> - Create arch_kernel_info for arch specific kernel information.
>> At the moment, it contains domain_type for Arm.
>> - Rename vpl011 to vuart to have more generic name suitable for other archs.
>> - s/phandle_gic/phandle_intc to have more generic name suitable for other
>> archs.
>> - Make text_offset of zimage structure available for RISCV_64.
>> - Wrap by `#ifdef KERNEL_INFO_SHM_MEM_INIT` definition of KERNEL_SHM_MEM_INIT
>> and wrap by `#ifndef KERNEL_INFO_INIT` definition of KERNEL_INFO_INIT to have
>> ability to override KERNEL_INFO_SHM_MEM_INIT for arch in case it doesn't
>> want to use generic one.
>> - All other parts are left as is from Arm's asm/kernel.h
>>
>> Because of the changes in struct kernel_info the correspondent parts of Arm's
>> code are updated.
>>
>> As part of this patch the following clean up happens:
>> - Drop asm/setup.h from asm/kernel.h as nothing depends from it.
>> Add inclusion of asm/setup.h for a code which uses device_tree_get_reg() to
>> avoid compilation issues for CONFIG_STATIC_MEMORY and CONFIG_STATIC_SHM.
>>
>> Signed-off-by: Oleksii Kurochko<oleksii.kurochko@gmail.com>
> I question that what is being moved qualifies for asm-generic, an in particular
> for a header named kernel.h. Some of what you move may make sense to move to
> dom0less-build.h instead. But everything that doesn't fit there needs to find
> a different home, imo.
It doesn't clear what then should be in kernel.h, I did in this way to not have a problem with header inclusion
during the build of Arm.
Definitions DOM0LESSS_* could be moved to dom0less-build.h, all other doesn't really connected only to dom0less feature
and could be re-used for dom0 so it seems like it should leave in a separate header ( if kernel.h isn't good for it ).
Probably kernel.h shouldn't leave in asm-generic as nothing architecture specific is in it, but on the other hand, will it
be okay to have something in xen/include if it isn't supported by all architectures?
~ Oleksii
[-- Attachment #2: Type: text/html, Size: 2745 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic
2025-02-03 15:34 ` Oleksii Kurochko
@ 2025-02-03 16:33 ` Jan Beulich
0 siblings, 0 replies; 20+ messages in thread
From: Jan Beulich @ 2025-02-03 16:33 UTC (permalink / raw)
To: Oleksii Kurochko
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
On 03.02.2025 16:34, Oleksii Kurochko wrote:
>
> On 1/27/25 12:15 PM, Jan Beulich wrote:
>> On 08.01.2025 12:13, Oleksii Kurochko wrote:
>>> Move the following parts to asm-generic with the following changes:
>>> - struct kernel_info:
>>> - Create arch_kernel_info for arch specific kernel information.
>>> At the moment, it contains domain_type for Arm.
>>> - Rename vpl011 to vuart to have more generic name suitable for other archs.
>>> - s/phandle_gic/phandle_intc to have more generic name suitable for other
>>> archs.
>>> - Make text_offset of zimage structure available for RISCV_64.
>>> - Wrap by `#ifdef KERNEL_INFO_SHM_MEM_INIT` definition of KERNEL_SHM_MEM_INIT
>>> and wrap by `#ifndef KERNEL_INFO_INIT` definition of KERNEL_INFO_INIT to have
>>> ability to override KERNEL_INFO_SHM_MEM_INIT for arch in case it doesn't
>>> want to use generic one.
>>> - All other parts are left as is from Arm's asm/kernel.h
>>>
>>> Because of the changes in struct kernel_info the correspondent parts of Arm's
>>> code are updated.
>>>
>>> As part of this patch the following clean up happens:
>>> - Drop asm/setup.h from asm/kernel.h as nothing depends from it.
>>> Add inclusion of asm/setup.h for a code which uses device_tree_get_reg() to
>>> avoid compilation issues for CONFIG_STATIC_MEMORY and CONFIG_STATIC_SHM.
>>>
>>> Signed-off-by: Oleksii Kurochko<oleksii.kurochko@gmail.com>
>> I question that what is being moved qualifies for asm-generic, an in particular
>> for a header named kernel.h. Some of what you move may make sense to move to
>> dom0less-build.h instead. But everything that doesn't fit there needs to find
>> a different home, imo.
>
> It doesn't clear what then should be in kernel.h, I did in this way to not have a problem with header inclusion
> during the build of Arm.
>
> Definitions DOM0LESSS_* could be moved to dom0less-build.h, all other doesn't really connected only to dom0less feature
> and could be re-used for dom0 so it seems like it should leave in a separate header ( if kernel.h isn't good for it ).
>
> Probably kernel.h shouldn't leave in asm-generic as nothing architecture specific is in it,
Well, kernel.h under asm-generic/ is somewhat odd in the first place.
> but on the other hand, will it
> be okay to have something in xen/include if it isn't supported by all architectures?
It can be okay; it depends on a number of factors.
Jan
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 3/9] arm/static-shmem.h: drop inclusion of asm/setup.h
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 1/9] xen/common: dom0less: make some parts of Arm's CONFIG_DOM0LESS common Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 2/9] asm-generic: move parts of Arm's asm/kernel.h to asm-generic Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic Oleksii Kurochko
` (5 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk
Nothing is dependent from asm/setup.h in asm/static-shmem.h so inclusion of
asm/setup.h is droped.
After this drop the following compilation error related to impicit declaration
of the following functions device_tree_get_reg and map_device_irqs_to_domain,
device_tree_get_u32 occur during compilation of dom0less-build.c ( as they are
declared in asm/setup.h ).
Add inclusion of <asm/setup.h> in dt-overlay.c as it is using handle_device()
declared in <asm/setup.h>.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/dom0less-build.c | 1 +
xen/arch/arm/include/asm/static-shmem.h | 1 -
xen/common/device-tree/dt-overlay.c | 2 ++
3 files changed, 3 insertions(+), 1 deletion(-)
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index c4badb4ade..259285ddda 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -14,6 +14,7 @@
#include <asm/arm64/sve.h>
#include <asm/dom0less-build.h>
#include <asm/domain_build.h>
+#include <asm/setup.h>
#include <asm/static-memory.h>
#include <asm/static-shmem.h>
diff --git a/xen/arch/arm/include/asm/static-shmem.h b/xen/arch/arm/include/asm/static-shmem.h
index fd0867c4f2..828c8e5480 100644
--- a/xen/arch/arm/include/asm/static-shmem.h
+++ b/xen/arch/arm/include/asm/static-shmem.h
@@ -5,7 +5,6 @@
#include <xen/types.h>
#include <asm/kernel.h>
-#include <asm/setup.h>
#ifdef CONFIG_STATIC_SHM
diff --git a/xen/common/device-tree/dt-overlay.c b/xen/common/device-tree/dt-overlay.c
index 97fb99eaaa..28bb9cf0cf 100644
--- a/xen/common/device-tree/dt-overlay.c
+++ b/xen/common/device-tree/dt-overlay.c
@@ -13,6 +13,8 @@
#include <xen/libfdt/libfdt.h>
#include <xen/xmalloc.h>
+#include <asm/setup.h>
+
#define DT_OVERLAY_MAX_SIZE KB(500)
static LIST_HEAD(overlay_tracker);
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
` (2 preceding siblings ...)
2025-01-08 11:13 ` [PATCH v1 3/9] arm/static-shmem.h: drop inclusion of asm/setup.h Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-27 11:19 ` Jan Beulich
2025-01-08 11:13 ` [PATCH v1 5/9] asm-generic: move Arm's static-shmem.h " Oleksii Kurochko
` (4 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Except moving Arm's static-memory.h to asm-generic #ifdef header guard
is updated: s/__ASM_STATIC_MEMORY_H_/__ASM_GENERIC_STATIC_MEMORY_H__.
Update arm/include/asm/Makefile to use asm-generic version of
static-memory.h for Arm.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/include/asm/Makefile | 1 +
xen/arch/arm/include/asm/static-memory.h | 58 ------------------------
xen/include/asm-generic/static-memory.h | 58 ++++++++++++++++++++++++
3 files changed, 59 insertions(+), 58 deletions(-)
delete mode 100644 xen/arch/arm/include/asm/static-memory.h
create mode 100644 xen/include/asm-generic/static-memory.h
diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile
index 831c914cce..ac8208a81f 100644
--- a/xen/arch/arm/include/asm/Makefile
+++ b/xen/arch/arm/include/asm/Makefile
@@ -8,4 +8,5 @@ generic-y += paging.h
generic-y += percpu.h
generic-y += random.h
generic-y += softirq.h
+generic-y += static-memory.h
generic-y += vm_event.h
diff --git a/xen/arch/arm/include/asm/static-memory.h b/xen/arch/arm/include/asm/static-memory.h
deleted file mode 100644
index 804166e541..0000000000
--- a/xen/arch/arm/include/asm/static-memory.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_STATIC_MEMORY_H_
-#define __ASM_STATIC_MEMORY_H_
-
-#include <xen/pfn.h>
-#include <asm/kernel.h>
-
-#ifdef CONFIG_STATIC_MEMORY
-
-static inline void init_staticmem_bank(const struct membank *bank)
-{
- mfn_t bank_start = _mfn(PFN_UP(bank->start));
- unsigned long bank_pages = PFN_DOWN(bank->size);
- mfn_t bank_end = mfn_add(bank_start, bank_pages);
-
- if ( mfn_x(bank_end) <= mfn_x(bank_start) )
- return;
-
- unprepare_staticmem_pages(mfn_to_page(bank_start), bank_pages, false);
-}
-
-void allocate_static_memory(struct domain *d, struct kernel_info *kinfo,
- const struct dt_device_node *node);
-void assign_static_memory_11(struct domain *d, struct kernel_info *kinfo,
- const struct dt_device_node *node);
-void init_staticmem_pages(void);
-
-#else /* !CONFIG_STATIC_MEMORY */
-
-static inline void allocate_static_memory(struct domain *d,
- struct kernel_info *kinfo,
- const struct dt_device_node *node)
-{
- ASSERT_UNREACHABLE();
-}
-
-static inline void assign_static_memory_11(struct domain *d,
- struct kernel_info *kinfo,
- const struct dt_device_node *node)
-{
- ASSERT_UNREACHABLE();
-}
-
-static inline void init_staticmem_pages(void) {};
-
-#endif /* CONFIG_STATIC_MEMORY */
-
-#endif /* __ASM_STATIC_MEMORY_H_ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-generic/static-memory.h b/xen/include/asm-generic/static-memory.h
new file mode 100644
index 0000000000..43b8740d46
--- /dev/null
+++ b/xen/include/asm-generic/static-memory.h
@@ -0,0 +1,58 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_GENERIC_STATIC_MEMORY_H__
+#define __ASM_GENERIC_STATIC_MEMORY_H__
+
+#include <xen/pfn.h>
+#include <asm/kernel.h>
+
+#ifdef CONFIG_STATIC_MEMORY
+
+static inline void init_staticmem_bank(const struct membank *bank)
+{
+ mfn_t bank_start = _mfn(PFN_UP(bank->start));
+ unsigned long bank_pages = PFN_DOWN(bank->size);
+ mfn_t bank_end = mfn_add(bank_start, bank_pages);
+
+ if ( mfn_x(bank_end) <= mfn_x(bank_start) )
+ return;
+
+ unprepare_staticmem_pages(mfn_to_page(bank_start), bank_pages, false);
+}
+
+void allocate_static_memory(struct domain *d, struct kernel_info *kinfo,
+ const struct dt_device_node *node);
+void assign_static_memory_11(struct domain *d, struct kernel_info *kinfo,
+ const struct dt_device_node *node);
+void init_staticmem_pages(void);
+
+#else /* !CONFIG_STATIC_MEMORY */
+
+static inline void allocate_static_memory(struct domain *d,
+ struct kernel_info *kinfo,
+ const struct dt_device_node *node)
+{
+ ASSERT_UNREACHABLE();
+}
+
+static inline void assign_static_memory_11(struct domain *d,
+ struct kernel_info *kinfo,
+ const struct dt_device_node *node)
+{
+ ASSERT_UNREACHABLE();
+}
+
+static inline void init_staticmem_pages(void) {};
+
+#endif /* CONFIG_STATIC_MEMORY */
+
+#endif /* __ASM_GENERIC_STATIC_MEMORY_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic
2025-01-08 11:13 ` [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic Oleksii Kurochko
@ 2025-01-27 11:19 ` Jan Beulich
2025-02-03 15:45 ` Oleksii Kurochko
0 siblings, 1 reply; 20+ messages in thread
From: Jan Beulich @ 2025-01-27 11:19 UTC (permalink / raw)
To: Oleksii Kurochko
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
On 08.01.2025 12:13, Oleksii Kurochko wrote:
> Except moving Arm's static-memory.h to asm-generic #ifdef header guard
> is updated: s/__ASM_STATIC_MEMORY_H_/__ASM_GENERIC_STATIC_MEMORY_H__.
>
> Update arm/include/asm/Makefile to use asm-generic version of
> static-memory.h for Arm.
>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
Here as well as in patch 5 the "why" is again missing. Moving is fine, as
long as it's clear that this will actually be used by another arch (e.g.
RISC-V). Whether you have such (immediate or at least near term) plans is
unclear though, as both features look like relatively advanced ones, and
hence more basic functionality may want to appear first in RISC-V.
Jan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic
2025-01-27 11:19 ` Jan Beulich
@ 2025-02-03 15:45 ` Oleksii Kurochko
0 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-02-03 15:45 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
[-- Attachment #1: Type: text/plain, Size: 1283 bytes --]
On 1/27/25 12:19 PM, Jan Beulich wrote:
> On 08.01.2025 12:13, Oleksii Kurochko wrote:
>> Except moving Arm's static-memory.h to asm-generic #ifdef header guard
>> is updated: s/__ASM_STATIC_MEMORY_H_/__ASM_GENERIC_STATIC_MEMORY_H__.
>>
>> Update arm/include/asm/Makefile to use asm-generic version of
>> static-memory.h for Arm.
>>
>> Signed-off-by: Oleksii Kurochko<oleksii.kurochko@gmail.com>
> Here as well as in patch 5 the "why" is again missing. Moving is fine, as
> long as it's clear that this will actually be used by another arch (e.g.
> RISC-V). Whether you have such (immediate or at least near term) plans is
> unclear though, as both features look like relatively advanced ones, and
> hence more basic functionality may want to appear first in RISC-V.
The reason is that suggested generic dom0less solution is using allocate_static_memory() and
assign_static_memory_11() so I decided that it would be better to have stubs for them in
asm-generic header that wrapping by the code by "#ifdef CONFIG_STATIC_MEMORY" the places where
it is used.
But considering the status of RISC-V's Xen downstream and I still don't have cases where CONFIG_STATIC_MEMORY
is used for RISC-V, probably, it would be better just to use wrapping in generic code instead of
stubs.
~ Oleksii
[-- Attachment #2: Type: text/html, Size: 1885 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 5/9] asm-generic: move Arm's static-shmem.h to asm-generic
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
` (3 preceding siblings ...)
2025-01-08 11:13 ` [PATCH v1 4/9] asm-generic: move Arm's static-memory.h to asm-generic Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header Oleksii Kurochko
` (3 subsequent siblings)
8 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Except moving Arm's static-shmem.h to asm-generic #ifdef header guard
is updated: s/__ASM_SHMEM_MEMORY_H_/__ASM_GENERIC_SHMEM_MEMORY_H__.
Update arm/include/asm/Makefile to use asm-generic version of
static-shmem.h for Arm.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/include/asm/Makefile | 1 +
xen/arch/arm/include/asm/static-shmem.h | 117 ------------------------
xen/include/asm-generic/static-shmem.h | 117 ++++++++++++++++++++++++
3 files changed, 118 insertions(+), 117 deletions(-)
delete mode 100644 xen/arch/arm/include/asm/static-shmem.h
create mode 100644 xen/include/asm-generic/static-shmem.h
diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile
index ac8208a81f..9cec55606e 100644
--- a/xen/arch/arm/include/asm/Makefile
+++ b/xen/arch/arm/include/asm/Makefile
@@ -9,4 +9,5 @@ generic-y += percpu.h
generic-y += random.h
generic-y += softirq.h
generic-y += static-memory.h
+generic-y += static-shmem.h
generic-y += vm_event.h
diff --git a/xen/arch/arm/include/asm/static-shmem.h b/xen/arch/arm/include/asm/static-shmem.h
deleted file mode 100644
index 828c8e5480..0000000000
--- a/xen/arch/arm/include/asm/static-shmem.h
+++ /dev/null
@@ -1,117 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-
-#ifndef __ASM_STATIC_SHMEM_H_
-#define __ASM_STATIC_SHMEM_H_
-
-#include <xen/types.h>
-#include <asm/kernel.h>
-
-#ifdef CONFIG_STATIC_SHM
-
-/* Worst case /memory node reg element: (addrcells + sizecells) */
-#define DT_MEM_NODE_REG_RANGE_SIZE ((NR_MEM_BANKS + NR_SHMEM_BANKS) * 4)
-
-int make_resv_memory_node(const struct kernel_info *kinfo, int addrcells,
- int sizecells);
-
-int process_shm(struct domain *d, struct kernel_info *kinfo,
- const struct dt_device_node *node);
-
-static inline int process_shm_chosen(struct domain *d,
- struct kernel_info *kinfo)
-{
- const struct dt_device_node *node = dt_find_node_by_path("/chosen");
-
- return process_shm(d, kinfo, node);
-}
-
-int process_shm_node(const void *fdt, int node, uint32_t address_cells,
- uint32_t size_cells);
-
-void early_print_info_shmem(void);
-
-void init_sharedmem_pages(void);
-
-int remove_shm_from_rangeset(const struct kernel_info *kinfo,
- struct rangeset *rangeset);
-
-int remove_shm_holes_for_domU(const struct kernel_info *kinfo,
- struct membanks *ext_regions);
-
-int make_shm_resv_memory_node(const struct kernel_info *kinfo, int addrcells,
- int sizecells);
-
-void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, __be32 *reg,
- int *nr_cells, int addrcells, int sizecells);
-
-static inline struct membanks *
-kernel_info_get_shm_mem(struct kernel_info *kinfo)
-{
- return container_of(&kinfo->shm_mem.common, struct membanks, common);
-}
-
-static inline const struct membanks *
-kernel_info_get_shm_mem_const(const struct kernel_info *kinfo)
-{
- return container_of(&kinfo->shm_mem.common, const struct membanks, common);
-}
-
-#else /* !CONFIG_STATIC_SHM */
-
-/* Worst case /memory node reg element: (addrcells + sizecells) */
-#define DT_MEM_NODE_REG_RANGE_SIZE (NR_MEM_BANKS * 4)
-
-static inline int make_resv_memory_node(const struct kernel_info *kinfo,
- int addrcells, int sizecells)
-{
- return 0;
-}
-
-static inline int process_shm(struct domain *d, struct kernel_info *kinfo,
- const struct dt_device_node *node)
-{
- return 0;
-}
-
-static inline int process_shm_chosen(struct domain *d,
- struct kernel_info *kinfo)
-{
- return 0;
-}
-
-static inline void init_sharedmem_pages(void) {};
-
-static inline int remove_shm_from_rangeset(const struct kernel_info *kinfo,
- struct rangeset *rangeset)
-{
- return 0;
-}
-
-static inline int remove_shm_holes_for_domU(const struct kernel_info *kinfo,
- struct membanks *ext_regions)
-{
- return 0;
-}
-
-static inline int make_shm_resv_memory_node(const struct kernel_info *kinfo,
- int addrcells, int sizecells)
-{
- return 0;
-}
-
-static inline void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo,
- __be32 *reg, int *nr_cells,
- int addrcells, int sizecells) {};
-
-#endif /* CONFIG_STATIC_SHM */
-
-#endif /* __ASM_STATIC_SHMEM_H_ */
-
-/*
- * Local variables:
- * mode: C
- * c-file-style: "BSD"
- * c-basic-offset: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/include/asm-generic/static-shmem.h b/xen/include/asm-generic/static-shmem.h
new file mode 100644
index 0000000000..7c83cb6195
--- /dev/null
+++ b/xen/include/asm-generic/static-shmem.h
@@ -0,0 +1,117 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef __ASM_GENERIC_STATIC_SHMEM_H__
+#define __ASM_GENERIC_STATIC_SHMEM_H__
+
+#include <xen/types.h>
+#include <asm/kernel.h>
+
+#ifdef CONFIG_STATIC_SHM
+
+/* Worst case /memory node reg element: (addrcells + sizecells) */
+#define DT_MEM_NODE_REG_RANGE_SIZE ((NR_MEM_BANKS + NR_SHMEM_BANKS) * 4)
+
+int make_resv_memory_node(const struct kernel_info *kinfo, int addrcells,
+ int sizecells);
+
+int process_shm(struct domain *d, struct kernel_info *kinfo,
+ const struct dt_device_node *node);
+
+static inline int process_shm_chosen(struct domain *d,
+ struct kernel_info *kinfo)
+{
+ const struct dt_device_node *node = dt_find_node_by_path("/chosen");
+
+ return process_shm(d, kinfo, node);
+}
+
+int process_shm_node(const void *fdt, int node, uint32_t address_cells,
+ uint32_t size_cells);
+
+void early_print_info_shmem(void);
+
+void init_sharedmem_pages(void);
+
+int remove_shm_from_rangeset(const struct kernel_info *kinfo,
+ struct rangeset *rangeset);
+
+int remove_shm_holes_for_domU(const struct kernel_info *kinfo,
+ struct membanks *ext_regions);
+
+int make_shm_resv_memory_node(const struct kernel_info *kinfo, int addrcells,
+ int sizecells);
+
+void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo, __be32 *reg,
+ int *nr_cells, int addrcells, int sizecells);
+
+static inline struct membanks *
+kernel_info_get_shm_mem(struct kernel_info *kinfo)
+{
+ return container_of(&kinfo->shm_mem.common, struct membanks, common);
+}
+
+static inline const struct membanks *
+kernel_info_get_shm_mem_const(const struct kernel_info *kinfo)
+{
+ return container_of(&kinfo->shm_mem.common, const struct membanks, common);
+}
+
+#else /* !CONFIG_STATIC_SHM */
+
+/* Worst case /memory node reg element: (addrcells + sizecells) */
+#define DT_MEM_NODE_REG_RANGE_SIZE (NR_MEM_BANKS * 4)
+
+static inline int make_resv_memory_node(const struct kernel_info *kinfo,
+ int addrcells, int sizecells)
+{
+ return 0;
+}
+
+static inline int process_shm(struct domain *d, struct kernel_info *kinfo,
+ const struct dt_device_node *node)
+{
+ return 0;
+}
+
+static inline int process_shm_chosen(struct domain *d,
+ struct kernel_info *kinfo)
+{
+ return 0;
+}
+
+static inline void init_sharedmem_pages(void) {};
+
+static inline int remove_shm_from_rangeset(const struct kernel_info *kinfo,
+ struct rangeset *rangeset)
+{
+ return 0;
+}
+
+static inline int remove_shm_holes_for_domU(const struct kernel_info *kinfo,
+ struct membanks *ext_regions)
+{
+ return 0;
+}
+
+static inline int make_shm_resv_memory_node(const struct kernel_info *kinfo,
+ int addrcells, int sizecells)
+{
+ return 0;
+}
+
+static inline void shm_mem_node_fill_reg_range(const struct kernel_info *kinfo,
+ __be32 *reg, int *nr_cells,
+ int addrcells, int sizecells) {};
+
+#endif /* CONFIG_STATIC_SHM */
+
+#endif /* __ASM_GENERIC_STATIC_SHMEM_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
` (4 preceding siblings ...)
2025-01-08 11:13 ` [PATCH v1 5/9] asm-generic: move Arm's static-shmem.h " Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-27 11:23 ` Jan Beulich
2025-01-08 11:13 ` [PATCH v1 7/9] xen/common: dom0less: introduce common kernel.c Oleksii Kurochko
` (2 subsequent siblings)
8 siblings, 1 reply; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Nothing changed. Only some functions declaration are moved to asm-generic
header as they are expected to be used by common code of domain builing or
dom0less.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/include/asm/domain_build.h | 19 ++----------
xen/include/asm-generic/domain-build.h | 41 +++++++++++++++++++++++++
2 files changed, 43 insertions(+), 17 deletions(-)
create mode 100644 xen/include/asm-generic/domain-build.h
diff --git a/xen/arch/arm/include/asm/domain_build.h b/xen/arch/arm/include/asm/domain_build.h
index 5d77af2e8b..ad5a3ddc37 100644
--- a/xen/arch/arm/include/asm/domain_build.h
+++ b/xen/arch/arm/include/asm/domain_build.h
@@ -4,28 +4,13 @@
#include <xen/sched.h>
#include <asm/kernel.h>
+#include <asm-generic/domain-build.h>
+
typedef __be32 gic_interrupt_t[3];
-typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg,
- unsigned int order, void *extra);
-bool allocate_domheap_memory(struct domain *d, paddr_t tot_size,
- alloc_domheap_mem_cb cb, void *extra);
-bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
- paddr_t tot_size);
-void allocate_memory(struct domain *d, struct kernel_info *kinfo);
-int construct_domain(struct domain *d, struct kernel_info *kinfo);
int domain_fdt_begin_node(void *fdt, const char *name, uint64_t unit);
-int make_chosen_node(const struct kernel_info *kinfo);
-int make_cpus_node(const struct domain *d, void *fdt);
-int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo,
- int addrcells, int sizecells);
-int make_memory_node(const struct kernel_info *kinfo, int addrcells,
- int sizecells, const struct membanks *mem);
int make_psci_node(void *fdt);
-int make_timer_node(const struct kernel_info *kinfo);
void evtchn_allocate(struct domain *d);
-unsigned int get_allocation_size(paddr_t size);
-
/*
* handle_device_interrupts retrieves the interrupts configuration from
* a device tree node and maps those interrupts to the target domain.
diff --git a/xen/include/asm-generic/domain-build.h b/xen/include/asm-generic/domain-build.h
new file mode 100644
index 0000000000..237f94d0c3
--- /dev/null
+++ b/xen/include/asm-generic/domain-build.h
@@ -0,0 +1,41 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+#ifndef __ASM_GENERIC_DOMAIN_BUILD_H__
+#define __ASM_GENERIC_DOMAIN_BUILD_H__
+
+#include <xen/types.h>
+
+struct domain;
+struct page_info;
+struct kernel_info;
+struct membanks;
+
+typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg,
+ unsigned int order, void *extra);
+bool allocate_domheap_memory(struct domain *d, paddr_t tot_size,
+ alloc_domheap_mem_cb cb, void *extra);
+
+bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
+ paddr_t tot_size);
+void allocate_memory(struct domain *d, struct kernel_info *kinfo);
+int construct_domain(struct domain *d, struct kernel_info *kinfo);
+int make_chosen_node(const struct kernel_info *kinfo);
+int make_cpus_node(const struct domain *d, void *fdt);
+int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo,
+ int addrcells, int sizecells);
+int make_memory_node(const struct kernel_info *kinfo, int addrcells,
+ int sizecells, const struct membanks *mem);
+int make_timer_node(const struct kernel_info *kinfo);
+
+unsigned int get_allocation_size(paddr_t size);
+
+
+#endif /* __ASM_GENERIC_DOMAIN_BUILD_H__ */
+
+/*
+ * Local variables:
+ * mode: C
+ * c-file-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* Re: [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header
2025-01-08 11:13 ` [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header Oleksii Kurochko
@ 2025-01-27 11:23 ` Jan Beulich
2025-02-03 15:50 ` Oleksii Kurochko
0 siblings, 1 reply; 20+ messages in thread
From: Jan Beulich @ 2025-01-27 11:23 UTC (permalink / raw)
To: Oleksii Kurochko
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
On 08.01.2025 12:13, Oleksii Kurochko wrote:
> Nothing changed. Only some functions declaration are moved to asm-generic
> header as they are expected to be used by common code of domain builing or
> dom0less.
>
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
> ---
> xen/arch/arm/include/asm/domain_build.h | 19 ++----------
> xen/include/asm-generic/domain-build.h | 41 +++++++++++++++++++++++++
> 2 files changed, 43 insertions(+), 17 deletions(-)
> create mode 100644 xen/include/asm-generic/domain-build.h
Again I question this movement under this name. "Domain building" is a pretty
generic thing, yes, but what you move would e.g. be entirely inapplicable on
x86 (as it is now). For example ...
> --- /dev/null
> +++ b/xen/include/asm-generic/domain-build.h
> @@ -0,0 +1,41 @@
> +/* SPDX-License-Identifier: GPL-2.0-only */
> +#ifndef __ASM_GENERIC_DOMAIN_BUILD_H__
> +#define __ASM_GENERIC_DOMAIN_BUILD_H__
> +
> +#include <xen/types.h>
> +
> +struct domain;
> +struct page_info;
> +struct kernel_info;
> +struct membanks;
> +
> +typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg,
> + unsigned int order, void *extra);
> +bool allocate_domheap_memory(struct domain *d, paddr_t tot_size,
> + alloc_domheap_mem_cb cb, void *extra);
> +
> +bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
> + paddr_t tot_size);
... the term "bank" seems pretty closely tied to DT. Other stuff ...
> +void allocate_memory(struct domain *d, struct kernel_info *kinfo);
> +int construct_domain(struct domain *d, struct kernel_info *kinfo);
> +int make_chosen_node(const struct kernel_info *kinfo);
> +int make_cpus_node(const struct domain *d, void *fdt);
> +int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo,
> + int addrcells, int sizecells);
> +int make_memory_node(const struct kernel_info *kinfo, int addrcells,
> + int sizecells, const struct membanks *mem);
> +int make_timer_node(const struct kernel_info *kinfo);
... here also falls in this category. Stuff like this may well live
under asm-generic/, but the file name chosen then needs to reflect
constraints.
> +unsigned int get_allocation_size(paddr_t size);
> +
> +
Nit: As before - no double blank lines please.
Jan
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header
2025-01-27 11:23 ` Jan Beulich
@ 2025-02-03 15:50 ` Oleksii Kurochko
2025-02-03 16:38 ` Jan Beulich
0 siblings, 1 reply; 20+ messages in thread
From: Oleksii Kurochko @ 2025-02-03 15:50 UTC (permalink / raw)
To: Jan Beulich
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
[-- Attachment #1: Type: text/plain, Size: 2580 bytes --]
On 1/27/25 12:23 PM, Jan Beulich wrote:
> On 08.01.2025 12:13, Oleksii Kurochko wrote:
>> Nothing changed. Only some functions declaration are moved to asm-generic
>> header as they are expected to be used by common code of domain builing or
>> dom0less.
>>
>> Signed-off-by: Oleksii Kurochko<oleksii.kurochko@gmail.com>
>> ---
>> xen/arch/arm/include/asm/domain_build.h | 19 ++----------
>> xen/include/asm-generic/domain-build.h | 41 +++++++++++++++++++++++++
>> 2 files changed, 43 insertions(+), 17 deletions(-)
>> create mode 100644 xen/include/asm-generic/domain-build.h
> Again I question this movement under this name. "Domain building" is a pretty
> generic thing, yes, but what you move would e.g. be entirely inapplicable on
> x86 (as it is now). For example ...
>
>> --- /dev/null
>> +++ b/xen/include/asm-generic/domain-build.h
>> @@ -0,0 +1,41 @@
>> +/* SPDX-License-Identifier: GPL-2.0-only */
>> +#ifndef __ASM_GENERIC_DOMAIN_BUILD_H__
>> +#define __ASM_GENERIC_DOMAIN_BUILD_H__
>> +
>> +#include <xen/types.h>
>> +
>> +struct domain;
>> +struct page_info;
>> +struct kernel_info;
>> +struct membanks;
>> +
>> +typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg,
>> + unsigned int order, void *extra);
>> +bool allocate_domheap_memory(struct domain *d, paddr_t tot_size,
>> + alloc_domheap_mem_cb cb, void *extra);
>> +
>> +bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
>> + paddr_t tot_size);
> ... the term "bank" seems pretty closely tied to DT. Other stuff ...
>
>> +void allocate_memory(struct domain *d, struct kernel_info *kinfo);
>> +int construct_domain(struct domain *d, struct kernel_info *kinfo);
>> +int make_chosen_node(const struct kernel_info *kinfo);
>> +int make_cpus_node(const struct domain *d, void *fdt);
>> +int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo,
>> + int addrcells, int sizecells);
>> +int make_memory_node(const struct kernel_info *kinfo, int addrcells,
>> + int sizecells, const struct membanks *mem);
>> +int make_timer_node(const struct kernel_info *kinfo);
> ... here also falls in this category. Stuff like this may well live
> under asm-generic/, but the file name chosen then needs to reflect
> constraints.
Unfortunately, at least at the moment, this is not applicable to x86.
Partially, domain_build.h was chosen to have less changes in Arm code.
Would it be better to use domain-build-dt.h?
~ Oleksii
[-- Attachment #2: Type: text/html, Size: 3376 bytes --]
^ permalink raw reply [flat|nested] 20+ messages in thread
* Re: [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header
2025-02-03 15:50 ` Oleksii Kurochko
@ 2025-02-03 16:38 ` Jan Beulich
0 siblings, 0 replies; 20+ messages in thread
From: Jan Beulich @ 2025-02-03 16:38 UTC (permalink / raw)
To: Oleksii Kurochko
Cc: Stefano Stabellini, Julien Grall, Bertrand Marquis, Michal Orzel,
Volodymyr Babchuk, Andrew Cooper, Anthony PERARD,
Roger Pau Monné, xen-devel
On 03.02.2025 16:50, Oleksii Kurochko wrote:
> On 1/27/25 12:23 PM, Jan Beulich wrote:
>> On 08.01.2025 12:13, Oleksii Kurochko wrote:
>>> Nothing changed. Only some functions declaration are moved to asm-generic
>>> header as they are expected to be used by common code of domain builing or
>>> dom0less.
>>>
>>> Signed-off-by: Oleksii Kurochko<oleksii.kurochko@gmail.com>
>>> ---
>>> xen/arch/arm/include/asm/domain_build.h | 19 ++----------
>>> xen/include/asm-generic/domain-build.h | 41 +++++++++++++++++++++++++
>>> 2 files changed, 43 insertions(+), 17 deletions(-)
>>> create mode 100644 xen/include/asm-generic/domain-build.h
>> Again I question this movement under this name. "Domain building" is a pretty
>> generic thing, yes, but what you move would e.g. be entirely inapplicable on
>> x86 (as it is now). For example ...
>>
>>> --- /dev/null
>>> +++ b/xen/include/asm-generic/domain-build.h
>>> @@ -0,0 +1,41 @@
>>> +/* SPDX-License-Identifier: GPL-2.0-only */
>>> +#ifndef __ASM_GENERIC_DOMAIN_BUILD_H__
>>> +#define __ASM_GENERIC_DOMAIN_BUILD_H__
>>> +
>>> +#include <xen/types.h>
>>> +
>>> +struct domain;
>>> +struct page_info;
>>> +struct kernel_info;
>>> +struct membanks;
>>> +
>>> +typedef bool (*alloc_domheap_mem_cb)(struct domain *d, struct page_info *pg,
>>> + unsigned int order, void *extra);
>>> +bool allocate_domheap_memory(struct domain *d, paddr_t tot_size,
>>> + alloc_domheap_mem_cb cb, void *extra);
>>> +
>>> +bool allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
>>> + paddr_t tot_size);
>> ... the term "bank" seems pretty closely tied to DT. Other stuff ...
>>
>>> +void allocate_memory(struct domain *d, struct kernel_info *kinfo);
>>> +int construct_domain(struct domain *d, struct kernel_info *kinfo);
>>> +int make_chosen_node(const struct kernel_info *kinfo);
>>> +int make_cpus_node(const struct domain *d, void *fdt);
>>> +int make_hypervisor_node(struct domain *d, const struct kernel_info *kinfo,
>>> + int addrcells, int sizecells);
>>> +int make_memory_node(const struct kernel_info *kinfo, int addrcells,
>>> + int sizecells, const struct membanks *mem);
>>> +int make_timer_node(const struct kernel_info *kinfo);
>> ... here also falls in this category. Stuff like this may well live
>> under asm-generic/, but the file name chosen then needs to reflect
>> constraints.
>
> Unfortunately, at least at the moment, this is not applicable to x86.
>
> Partially, domain_build.h was chosen to have less changes in Arm code.
>
> Would it be better to use domain-build-dt.h?
That would at least be a more specific name. Yet then - why put such under
asm-generic/ ? This stuff isn't truly generic (as in: any arch can fall
back to using this). Personally I'd rather expect such stuff to live under
e.g. include/xen/device-tree/. That would make it clear that environments
using DT may consider using it, but other environment shouldn't.
Jan
^ permalink raw reply [flat|nested] 20+ messages in thread
* [PATCH v1 7/9] xen/common: dom0less: introduce common kernel.c
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
` (5 preceding siblings ...)
2025-01-08 11:13 ` [PATCH v1 6/9] asm-generic: move some parts of Arm's domain_build.h to asm-generic header Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 8/9] xen/common: dom0less: introduce common domain-build.c Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 9/9] xen/common: dom0less: introduce common dom0less-build.c Oleksii Kurochko
8 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
The following functions don't have arch specific things so it is moved to
common:
- kernel_prboe()
- kernel_load()
- output_length()
Functions necessary for dom0less are only moved.
The following changes are done:
- Swap __init and return type of kernel_decompress() function to be
consistent with defintions of functions in other files. The same
for output_length().
- Wrap by "ifdef CONFIG_ARM" the call of kernel_uimage_probe() in
kernel_probe() as uImage isn't really used nowadays thereby leave
kernel_uimage_probe() call here just for compatability with Arm code.
- Introduce kernel_zimage_probe() to cover the case that arch can have
different zimage header.
- Add ASSERT() for kernel_load() to check that it argument isn't NULL.
- Make kernel_uimage_probe() non-static in Arm's code as it is used in
common/kernel.c.
Introduce CONFIG_DOMAIN_BUILD_HELPERS to not provide stubs for archs
which doesn't provice enough functionality to enable it.
Select CONFIG_DOMAIN_BUILD_HELPERS for CONFIG_ARM as only Arm supports
it, at the moment.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/Kconfig | 1 +
xen/arch/arm/kernel.c | 221 +---------------------------
xen/common/Kconfig | 11 +-
xen/common/device-tree/Makefile | 1 +
xen/common/device-tree/kernel.c | 242 +++++++++++++++++++++++++++++++
xen/include/asm-generic/kernel.h | 13 ++
6 files changed, 272 insertions(+), 217 deletions(-)
create mode 100644 xen/common/device-tree/kernel.c
diff --git a/xen/arch/arm/Kconfig b/xen/arch/arm/Kconfig
index eff6ea6b6d..8a8681ef3b 100644
--- a/xen/arch/arm/Kconfig
+++ b/xen/arch/arm/Kconfig
@@ -12,6 +12,7 @@ config ARM_64
config ARM
def_bool y
+ select DOMAIN_BUILD_HELPERS
select FUNCTION_ALIGNMENT_4B
select GENERIC_UART_INIT
select HAS_ALTERNATIVE if HAS_VMAP
diff --git a/xen/arch/arm/kernel.c b/xen/arch/arm/kernel.c
index b75bd6a887..8e5fd09c75 100644
--- a/xen/arch/arm/kernel.c
+++ b/xen/arch/arm/kernel.c
@@ -160,105 +160,6 @@ static void __init kernel_zimage_load(struct kernel_info *info)
iounmap(kernel);
}
-static __init uint32_t output_length(char *image, unsigned long image_len)
-{
- return *(uint32_t *)&image[image_len - 4];
-}
-
-static __init int kernel_decompress(struct bootmodule *mod, uint32_t offset)
-{
- char *output, *input;
- char magic[2];
- int rc;
- unsigned int kernel_order_out;
- paddr_t output_size;
- struct page_info *pages;
- mfn_t mfn;
- int i;
- paddr_t addr = mod->start;
- paddr_t size = mod->size;
-
- if ( size < offset )
- return -EINVAL;
-
- /*
- * It might be that gzip header does not appear at the start address
- * (e.g. in case of compressed uImage) so take into account offset to
- * gzip header.
- */
- addr += offset;
- size -= offset;
-
- if ( size < 2 )
- return -EINVAL;
-
- copy_from_paddr(magic, addr, sizeof(magic));
-
- /* only gzip is supported */
- if ( !gzip_check(magic, size) )
- return -EINVAL;
-
- input = ioremap_cache(addr, size);
- if ( input == NULL )
- return -EFAULT;
-
- output_size = output_length(input, size);
- kernel_order_out = get_order_from_bytes(output_size);
- pages = alloc_domheap_pages(NULL, kernel_order_out, 0);
- if ( pages == NULL )
- {
- iounmap(input);
- return -ENOMEM;
- }
- mfn = page_to_mfn(pages);
- output = vmap_contig(mfn, 1 << kernel_order_out);
-
- rc = perform_gunzip(output, input, size);
- clean_dcache_va_range(output, output_size);
- iounmap(input);
- vunmap(output);
-
- if ( rc )
- {
- free_domheap_pages(pages, kernel_order_out);
- return rc;
- }
-
- mod->start = page_to_maddr(pages);
- mod->size = output_size;
-
- /*
- * Need to free pages after output_size here because they won't be
- * freed by discard_initial_modules
- */
- i = PFN_UP(output_size);
- for ( ; i < (1 << kernel_order_out); i++ )
- free_domheap_page(pages + i);
-
- /*
- * When using static heap feature, don't give bootmodules memory back to
- * the heap allocator
- */
- if ( using_static_heap )
- return 0;
-
- /*
- * When freeing the kernel, we need to pass the module start address and
- * size as they were before taking an offset to gzip header into account,
- * so that the entire region will be freed.
- */
- addr -= offset;
- size += offset;
-
- /*
- * Free the original kernel, update the pointers to the
- * decompressed kernel
- */
- fw_unreserved_regions(addr, addr + size, init_domheap_pages, 0);
-
- return 0;
-}
-
/*
* Uimage CPU Architecture Codes
*/
@@ -271,8 +172,8 @@ static __init int kernel_decompress(struct bootmodule *mod, uint32_t offset)
/*
* Check if the image is a uImage and setup kernel_info
*/
-static int __init kernel_uimage_probe(struct kernel_info *info,
- struct bootmodule *mod)
+int __init kernel_uimage_probe(struct kernel_info *info,
+ struct bootmodule *mod)
{
struct {
__be32 magic; /* Image Header Magic Number */
@@ -502,130 +403,20 @@ static int __init kernel_zimage32_probe(struct kernel_info *info,
return 0;
}
-int __init kernel_probe(struct kernel_info *info,
- const struct dt_device_node *domain)
+int __init kernel_zimage_probe(struct kernel_info *info, paddr_t addr,
+ paddr_t size)
{
- struct bootmodule *mod = NULL;
- struct bootcmdline *cmd = NULL;
- struct dt_device_node *node;
- u64 kernel_addr, initrd_addr, dtb_addr, size;
int rc;
- /*
- * We need to initialize start to 0. This field may be populated during
- * kernel_xxx_probe() if the image has a fixed entry point (for e.g.
- * uimage.ep).
- * We will use this to determine if the image has a fixed entry point or
- * the load address should be used as the start address.
- */
- info->entry = 0;
-
- /* domain is NULL only for the hardware domain */
- if ( domain == NULL )
- {
- ASSERT(is_hardware_domain(info->d));
-
- mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
-
- info->kernel_bootmodule = mod;
- info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
-
- cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
- if ( cmd )
- info->cmdline = &cmd->cmdline[0];
- }
- else
- {
- const char *name = NULL;
-
- dt_for_each_child_node(domain, node)
- {
- if ( dt_device_is_compatible(node, "multiboot,kernel") )
- {
- u32 len;
- const __be32 *val;
-
- val = dt_get_property(node, "reg", &len);
- dt_get_range(&val, node, &kernel_addr, &size);
- mod = boot_module_find_by_addr_and_kind(
- BOOTMOD_KERNEL, kernel_addr);
- info->kernel_bootmodule = mod;
- }
- else if ( dt_device_is_compatible(node, "multiboot,ramdisk") )
- {
- u32 len;
- const __be32 *val;
-
- val = dt_get_property(node, "reg", &len);
- dt_get_range(&val, node, &initrd_addr, &size);
- info->initrd_bootmodule = boot_module_find_by_addr_and_kind(
- BOOTMOD_RAMDISK, initrd_addr);
- }
- else if ( dt_device_is_compatible(node, "multiboot,device-tree") )
- {
- uint32_t len;
- const __be32 *val;
-
- val = dt_get_property(node, "reg", &len);
- if ( val == NULL )
- continue;
- dt_get_range(&val, node, &dtb_addr, &size);
- info->dtb_bootmodule = boot_module_find_by_addr_and_kind(
- BOOTMOD_GUEST_DTB, dtb_addr);
- }
- else
- continue;
- }
- name = dt_node_name(domain);
- cmd = boot_cmdline_find_by_name(name);
- if ( cmd )
- info->cmdline = &cmd->cmdline[0];
- }
- if ( !mod || !mod->size )
- {
- printk(XENLOG_ERR "Missing kernel boot module?\n");
- return -ENOENT;
- }
-
- printk("Loading %pd kernel from boot module @ %"PRIpaddr"\n",
- info->d, info->kernel_bootmodule->start);
- if ( info->initrd_bootmodule )
- printk("Loading ramdisk from boot module @ %"PRIpaddr"\n",
- info->initrd_bootmodule->start);
-
- /*
- * uImage header always appears at the top of the image (even compressed),
- * so it needs to be probed first. Note that in case of compressed uImage,
- * kernel_decompress is called from kernel_uimage_probe making the function
- * self-containing (i.e. fall through only in case of a header not found).
- */
- rc = kernel_uimage_probe(info, mod);
- if ( rc != -ENOENT )
- return rc;
-
- /*
- * If it is a gzip'ed image, 32bit or 64bit, uncompress it.
- * At this point, gzip header appears (if at all) at the top of the image,
- * so pass 0 as an offset.
- */
- rc = kernel_decompress(mod, 0);
- if ( rc && rc != -EINVAL )
- return rc;
-
#ifdef CONFIG_ARM_64
- rc = kernel_zimage64_probe(info, mod->start, mod->size);
+ rc = kernel_zimage64_probe(info, addr, size);
if (rc < 0)
#endif
- rc = kernel_zimage32_probe(info, mod->start, mod->size);
+ rc = kernel_zimage32_probe(info, addr, size);
return rc;
}
-void __init kernel_load(struct kernel_info *info)
-{
- info->load(info);
-}
-
/*
* Local variables:
* mode: C
diff --git a/xen/common/Kconfig b/xen/common/Kconfig
index 099e6e72ad..83f8a8f791 100644
--- a/xen/common/Kconfig
+++ b/xen/common/Kconfig
@@ -14,13 +14,20 @@ config CORE_PARKING
config DOM0LESS_BOOT
bool "Dom0less boot support" if EXPERT
- depends on ARM
- default ARM
+ depends on DOMAIN_BUILD_HELPERS
+ default DOMAIN_BUILD_HELPERS
help
Dom0less boot support enables Xen to create and start domU guests during
Xen boot without the need of a control domain (Dom0), which could be
present anyway.
+config DOMAIN_BUILD_HELPERS
+ bool
+ help
+ Introduce functions necessary for working with domain creation, kernel,
+ etc. As an examples, these type of functions are going to be used by
+ CONFIG_DOM0LESS_BOOT.
+
config GRANT_TABLE
bool "Grant table support" if EXPERT
default y
diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile
index f3dafc9b81..e88a4d5799 100644
--- a/xen/common/device-tree/Makefile
+++ b/xen/common/device-tree/Makefile
@@ -4,3 +4,4 @@ obj-y += device-tree.o
obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o
obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o
obj-y += intc.o
+obj-$(CONFIG_DOMAIN_BUILD_HELPERS) += kernel.o
diff --git a/xen/common/device-tree/kernel.c b/xen/common/device-tree/kernel.c
new file mode 100644
index 0000000000..bd5d968bfd
--- /dev/null
+++ b/xen/common/device-tree/kernel.c
@@ -0,0 +1,242 @@
+#include <xen/bootfdt.h>
+#include <xen/device_tree.h>
+#include <xen/errno.h>
+#include <xen/gunzip.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/mm.h>
+#include <xen/pfn.h>
+#include <xen/sched.h>
+#include <xen/types.h>
+#include <xen/vmap.h>
+
+#include <asm/kernel.h>
+#include <asm/page.h>
+#include <asm/setup.h>
+
+static uint32_t __init output_length(char *image, unsigned long image_len)
+{
+ return *(uint32_t *)&image[image_len - 4];
+}
+
+int __init kernel_decompress(struct bootmodule *mod, uint32_t offset)
+{
+ char *output, *input;
+ char magic[2];
+ int rc;
+ unsigned int kernel_order_out;
+ paddr_t output_size;
+ struct page_info *pages;
+ mfn_t mfn;
+ int i;
+ paddr_t addr = mod->start;
+ paddr_t size = mod->size;
+
+ if ( size < offset )
+ return -EINVAL;
+
+ /*
+ * It might be that gzip header does not appear at the start address
+ * (e.g. in case of compressed uImage) so take into account offset to
+ * gzip header.
+ */
+ addr += offset;
+ size -= offset;
+
+ if ( size < 2 )
+ return -EINVAL;
+
+ copy_from_paddr(magic, addr, sizeof(magic));
+
+ /* only gzip is supported */
+ if ( !gzip_check(magic, size) )
+ return -EINVAL;
+
+ input = ioremap_cache(addr, size);
+ if ( input == NULL )
+ return -EFAULT;
+
+ output_size = output_length(input, size);
+ kernel_order_out = get_order_from_bytes(output_size);
+ pages = alloc_domheap_pages(NULL, kernel_order_out, 0);
+ if ( pages == NULL )
+ {
+ iounmap(input);
+ return -ENOMEM;
+ }
+ mfn = page_to_mfn(pages);
+ output = vmap_contig(mfn, 1 << kernel_order_out);
+
+ rc = perform_gunzip(output, input, size);
+ clean_dcache_va_range(output, output_size);
+ iounmap(input);
+ vunmap(output);
+
+ if ( rc )
+ {
+ free_domheap_pages(pages, kernel_order_out);
+ return rc;
+ }
+
+ mod->start = page_to_maddr(pages);
+ mod->size = output_size;
+
+ /*
+ * Need to free pages after output_size here because they won't be
+ * freed by discard_initial_modules
+ */
+ i = PFN_UP(output_size);
+ for ( ; i < (1 << kernel_order_out); i++ )
+ free_domheap_page(pages + i);
+
+ /*
+ * When using static heap feature, don't give bootmodules memory back to
+ * the heap allocator
+ */
+ if ( using_static_heap )
+ return 0;
+
+ /*
+ * When freeing the kernel, we need to pass the module start address and
+ * size as they were before taking an offset to gzip header into account,
+ * so that the entire region will be freed.
+ */
+ addr -= offset;
+ size += offset;
+
+ /*
+ * Free the original kernel, update the pointers to the
+ * decompressed kernel
+ */
+ fw_unreserved_regions(addr, addr + size, init_domheap_pages, 0);
+
+ return 0;
+}
+
+int __init kernel_probe(struct kernel_info *info,
+ const struct dt_device_node *domain)
+{
+ struct bootmodule *mod = NULL;
+ struct bootcmdline *cmd = NULL;
+ struct dt_device_node *node;
+ u64 kernel_addr, initrd_addr, dtb_addr, size;
+ int rc;
+
+ /*
+ * We need to initialize start to 0. This field may be populated during
+ * kernel_xxx_probe() if the image has a fixed entry point (for e.g.
+ * uimage.ep).
+ * We will use this to determine if the image has a fixed entry point or
+ * the load address should be used as the start address.
+ */
+ info->entry = 0;
+
+ /* domain is NULL only for the hardware domain */
+ if ( domain == NULL )
+ {
+ ASSERT(is_hardware_domain(info->d));
+
+ mod = boot_module_find_by_kind(BOOTMOD_KERNEL);
+
+ info->kernel_bootmodule = mod;
+ info->initrd_bootmodule = boot_module_find_by_kind(BOOTMOD_RAMDISK);
+
+ cmd = boot_cmdline_find_by_kind(BOOTMOD_KERNEL);
+ if ( cmd )
+ info->cmdline = &cmd->cmdline[0];
+ }
+ else
+ {
+ const char *name = NULL;
+
+ dt_for_each_child_node(domain, node)
+ {
+ if ( dt_device_is_compatible(node, "multiboot,kernel") )
+ {
+ u32 len;
+ const __be32 *val;
+
+ val = dt_get_property(node, "reg", &len);
+ dt_get_range(&val, node, &kernel_addr, &size);
+ mod = boot_module_find_by_addr_and_kind(
+ BOOTMOD_KERNEL, kernel_addr);
+ info->kernel_bootmodule = mod;
+ }
+ else if ( dt_device_is_compatible(node, "multiboot,ramdisk") )
+ {
+ u32 len;
+ const __be32 *val;
+
+ val = dt_get_property(node, "reg", &len);
+ dt_get_range(&val, node, &initrd_addr, &size);
+ info->initrd_bootmodule = boot_module_find_by_addr_and_kind(
+ BOOTMOD_RAMDISK, initrd_addr);
+ }
+ else if ( dt_device_is_compatible(node, "multiboot,device-tree") )
+ {
+ uint32_t len;
+ const __be32 *val;
+
+ val = dt_get_property(node, "reg", &len);
+ if ( val == NULL )
+ continue;
+ dt_get_range(&val, node, &dtb_addr, &size);
+ info->dtb_bootmodule = boot_module_find_by_addr_and_kind(
+ BOOTMOD_GUEST_DTB, dtb_addr);
+ }
+ else
+ continue;
+ }
+ name = dt_node_name(domain);
+ cmd = boot_cmdline_find_by_name(name);
+ if ( cmd )
+ info->cmdline = &cmd->cmdline[0];
+ }
+ if ( !mod || !mod->size )
+ {
+ printk(XENLOG_ERR "Missing kernel boot module?\n");
+ return -ENOENT;
+ }
+
+ printk("Loading %pd kernel from boot module @ %"PRIpaddr"\n",
+ info->d, info->kernel_bootmodule->start);
+ if ( info->initrd_bootmodule )
+ printk("Loading ramdisk from boot module @ %"PRIpaddr"\n",
+ info->initrd_bootmodule->start);
+
+ /*
+ * uImage isn't really used nowadays thereby leave kernel_uimage_probe()
+ * call here just for compatability with Arm code.
+ */
+#ifdef CONFIG_ARM
+ /*
+ * uImage header always appears at the top of the image (even compressed),
+ * so it needs to be probed first. Note that in case of compressed uImage,
+ * kernel_decompress is called from kernel_uimage_probe making the function
+ * self-containing (i.e. fall through only in case of a header not found).
+ */
+ rc = kernel_uimage_probe(info, mod);
+ if ( rc != -ENOENT )
+ return rc;
+#endif
+
+ /*
+ * If it is a gzip'ed image, 32bit or 64bit, uncompress it.
+ * At this point, gzip header appears (if at all) at the top of the image,
+ * so pass 0 as an offset.
+ */
+ rc = kernel_decompress(mod, 0);
+ if ( rc && rc != -EINVAL )
+ return rc;
+
+ rc = kernel_zimage_probe(info, mod->start, mod->size);
+
+ return rc;
+}
+
+void __init kernel_load(struct kernel_info *info)
+{
+ ASSERT(info && info->load);
+
+ info->load(info);
+}
diff --git a/xen/include/asm-generic/kernel.h b/xen/include/asm-generic/kernel.h
index b2bd04a185..d668c7ef4f 100644
--- a/xen/include/asm-generic/kernel.h
+++ b/xen/include/asm-generic/kernel.h
@@ -134,6 +134,19 @@ int kernel_probe(struct kernel_info *info, const struct dt_device_node *domain);
*/
void kernel_load(struct kernel_info *info);
+int kernel_decompress(struct bootmodule *mod, uint32_t offset);
+
+int kernel_zimage_probe(struct kernel_info *info, paddr_t addr, paddr_t size);
+
+/*
+ * uImage isn't really used nowadays thereby leave kernel_uimage_probe()
+ * call here just for compatability with Arm code.
+ */
+#ifdef CONFIG_ARM
+struct bootmodule;
+int kernel_uimage_probe(struct kernel_info *info, struct bootmodule *mod);
+#endif
+
#endif /*__ASM_GENERIC_KERNEL_H__ */
/*
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 8/9] xen/common: dom0less: introduce common domain-build.c
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
` (6 preceding siblings ...)
2025-01-08 11:13 ` [PATCH v1 7/9] xen/common: dom0less: introduce common kernel.c Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
2025-01-08 11:13 ` [PATCH v1 9/9] xen/common: dom0less: introduce common dom0less-build.c Oleksii Kurochko
8 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Some functions of Arm's domain_build.c could be reused by dom0less or other
features connected to domain construction/build.
The following functions are moved to common:
- get_allocation_size().
- allocate_domheap_memory().
- guest_map_pages().
- allocate_bank_memory().
- add_hwdom_free_regions().
- find_unallocated_memory().
- allocate_memory().
- dtb_load().
- initrd_load().
Prototype of dtb_load() and initrd_load() is updated to recieve a pointer
to copy_to_guest_phys() as some archs require
copy_to_guest_phys_fluch_dcache().
Update arm/include/asm/Makefile to generate domain-build.h for Arm as it is
used by domain-build.c.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/domain_build.c | 400 +-----------------------
xen/arch/arm/include/asm/Makefile | 1 +
xen/common/device-tree/Makefile | 1 +
xen/common/device-tree/domain-build.c | 405 +++++++++++++++++++++++++
xen/include/asm-generic/domain-build.h | 33 +-
5 files changed, 441 insertions(+), 399 deletions(-)
create mode 100644 xen/common/device-tree/domain-build.c
diff --git a/xen/arch/arm/domain_build.c b/xen/arch/arm/domain_build.c
index 976b03a5df..e72da272d8 100644
--- a/xen/arch/arm/domain_build.c
+++ b/xen/arch/arm/domain_build.c
@@ -119,18 +119,6 @@ struct vcpu *__init alloc_dom0_vcpu0(struct domain *dom0)
return vcpu_create(dom0, 0);
}
-unsigned int __init get_allocation_size(paddr_t size)
-{
- /*
- * get_order_from_bytes returns the order greater than or equal to
- * the given size, but we need less than or equal. Adding one to
- * the size pushes an evenly aligned size into the next order, so
- * we can then unconditionally subtract 1 from the order which is
- * returned.
- */
- return get_order_from_bytes(size + 1) - 1;
-}
-
/*
* Insert the given pages into a memory bank, banks are ordered by address.
*
@@ -417,98 +405,6 @@ static void __init allocate_memory_11(struct domain *d,
}
}
-bool __init allocate_domheap_memory(struct domain *d, paddr_t tot_size,
- alloc_domheap_mem_cb cb, void *extra)
-{
- unsigned int max_order = UINT_MAX;
-
- while ( tot_size > 0 )
- {
- unsigned int order = get_allocation_size(tot_size);
- struct page_info *pg;
-
- order = min(max_order, order);
-
- pg = alloc_domheap_pages(d, order, 0);
- if ( !pg )
- {
- /*
- * If we can't allocate one page, then it is unlikely to
- * succeed in the next iteration. So bail out.
- */
- if ( !order )
- return false;
-
- /*
- * If we can't allocate memory with order, then it is
- * unlikely to succeed in the next iteration.
- * Record the order - 1 to avoid re-trying.
- */
- max_order = order - 1;
- continue;
- }
-
- if ( !cb(d, pg, order, extra) )
- return false;
-
- tot_size -= (1ULL << (PAGE_SHIFT + order));
- }
-
- return true;
-}
-
-static bool __init guest_map_pages(struct domain *d, struct page_info *pg,
- unsigned int order, void *extra)
-{
- gfn_t *sgfn = (gfn_t *)extra;
- int res;
-
- BUG_ON(!sgfn);
- res = guest_physmap_add_page(d, *sgfn, page_to_mfn(pg), order);
- if ( res )
- {
- dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
- return false;
- }
-
- *sgfn = gfn_add(*sgfn, 1UL << order);
-
- return true;
-}
-
-bool __init allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
- paddr_t tot_size)
-{
- struct membanks *mem = kernel_info_get_mem(kinfo);
- struct domain *d = kinfo->d;
- struct membank *bank;
-
- /*
- * allocate_bank_memory can be called with a tot_size of zero for
- * the second memory bank. It is not an error and we can safely
- * avoid creating a zero-size memory bank.
- */
- if ( tot_size == 0 )
- return true;
-
- bank = &mem->bank[mem->nr_banks];
- bank->start = gfn_to_gaddr(sgfn);
- bank->size = tot_size;
-
- /*
- * Allocate pages from the heap until tot_size is zero and map them to the
- * guest using guest_map_pages, passing the starting gfn as extra parameter
- * for the map operation.
- */
- if ( !allocate_domheap_memory(d, tot_size, guest_map_pages, &sgfn) )
- return false;
-
- mem->nr_banks++;
- kinfo->unassigned_mem -= bank->size;
-
- return true;
-}
-
/*
* When PCI passthrough is available we want to keep the
* "linux,pci-domain" in sync for every host bridge.
@@ -899,229 +795,6 @@ int __init add_ext_regions(unsigned long s_gfn, unsigned long e_gfn,
return 0;
}
-static int __init add_hwdom_free_regions(unsigned long s_gfn,
- unsigned long e_gfn, void *data)
-{
- struct membanks *free_regions = data;
- paddr_t start, size;
- paddr_t s = pfn_to_paddr(s_gfn);
- paddr_t e = pfn_to_paddr(e_gfn);
- unsigned int i, j;
-
- if ( free_regions->nr_banks >= free_regions->max_banks )
- return 0;
-
- /*
- * Both start and size of the free region should be 2MB aligned to
- * potentially allow superpage mapping.
- */
- start = (s + SZ_2M - 1) & ~(SZ_2M - 1);
- if ( start > e )
- return 0;
-
- /*
- * e is actually "end-1" because it is called by rangeset functions
- * which are inclusive of the last address.
- */
- e += 1;
- size = (e - start) & ~(SZ_2M - 1);
-
- /* Find the insert position (descending order). */
- for ( i = 0; i < free_regions->nr_banks ; i++ )
- if ( size > free_regions->bank[i].size )
- break;
-
- /* Move the other banks to make space. */
- for ( j = free_regions->nr_banks; j > i ; j-- )
- {
- free_regions->bank[j].start = free_regions->bank[j - 1].start;
- free_regions->bank[j].size = free_regions->bank[j - 1].size;
- }
-
- free_regions->bank[i].start = start;
- free_regions->bank[i].size = size;
- free_regions->nr_banks++;
-
- return 0;
-}
-
-/*
- * Find unused regions of Host address space which can be exposed to domain
- * using the host memory layout. In order to calculate regions we exclude every
- * region passed in mem_banks from the Host RAM.
- */
-static int __init find_unallocated_memory(const struct kernel_info *kinfo,
- const struct membanks *mem_banks[],
- unsigned int nr_mem_banks,
- struct membanks *free_regions,
- int (*cb)(unsigned long s_gfn,
- unsigned long e_gfn,
- void *data))
-{
- const struct membanks *mem = bootinfo_get_mem();
- struct rangeset *unalloc_mem;
- paddr_t start, end;
- unsigned int i, j;
- int res;
-
- ASSERT(domain_use_host_layout(kinfo->d));
-
- unalloc_mem = rangeset_new(NULL, NULL, 0);
- if ( !unalloc_mem )
- return -ENOMEM;
-
- /* Start with all available RAM */
- for ( i = 0; i < mem->nr_banks; i++ )
- {
- start = mem->bank[i].start;
- end = mem->bank[i].start + mem->bank[i].size;
- res = rangeset_add_range(unalloc_mem, PFN_DOWN(start),
- PFN_DOWN(end - 1));
- if ( res )
- {
- printk(XENLOG_ERR "Failed to add: %#"PRIpaddr"->%#"PRIpaddr"\n",
- start, end);
- goto out;
- }
- }
-
- /* Remove all regions listed in mem_banks */
- for ( i = 0; i < nr_mem_banks; i++ )
- for ( j = 0; j < mem_banks[i]->nr_banks; j++ )
- {
- start = mem_banks[i]->bank[j].start;
-
- /* Shared memory banks can contain INVALID_PADDR as start */
- if ( INVALID_PADDR == start )
- continue;
-
- end = mem_banks[i]->bank[j].start + mem_banks[i]->bank[j].size;
- res = rangeset_remove_range(unalloc_mem, PFN_DOWN(start),
- PFN_DOWN(end - 1));
- if ( res )
- {
- printk(XENLOG_ERR
- "Failed to add: %#"PRIpaddr"->%#"PRIpaddr", error %d\n",
- start, end, res);
- goto out;
- }
- }
-
- start = 0;
- end = (1ULL << p2m_ipa_bits) - 1;
- res = rangeset_report_ranges(unalloc_mem, PFN_DOWN(start), PFN_DOWN(end),
- cb, free_regions);
- if ( res )
- free_regions->nr_banks = 0;
- else if ( !free_regions->nr_banks )
- res = -ENOENT;
-
-out:
- rangeset_destroy(unalloc_mem);
-
- return res;
-}
-
-void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
-{
- struct membanks *mem = kernel_info_get_mem(kinfo);
- unsigned int i, nr_banks = GUEST_RAM_BANKS;
- struct membanks *hwdom_free_mem = NULL;
-
- printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
- /* Don't want format this as PRIpaddr (16 digit hex) */
- (unsigned long)(kinfo->unassigned_mem >> 20), d);
-
- mem->nr_banks = 0;
- /*
- * Use host memory layout for hwdom. Only case for this is when LLC coloring
- * is enabled.
- */
- if ( is_hardware_domain(d) )
- {
- struct membanks *gnttab = xzalloc_flex_struct(struct membanks, bank, 1);
- /*
- * Exclude the following regions:
- * 1) Remove reserved memory
- * 2) Grant table assigned to hwdom
- */
- const struct membanks *mem_banks[] = {
- bootinfo_get_reserved_mem(),
- gnttab,
- };
-
- if ( !gnttab )
- goto fail;
-
- gnttab->nr_banks = 1;
- gnttab->bank[0].start = kinfo->gnttab_start;
- gnttab->bank[0].size = kinfo->gnttab_size;
-
- hwdom_free_mem = xzalloc_flex_struct(struct membanks, bank,
- NR_MEM_BANKS);
- if ( !hwdom_free_mem )
- goto fail;
-
- hwdom_free_mem->max_banks = NR_MEM_BANKS;
-
- if ( find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks),
- hwdom_free_mem, add_hwdom_free_regions) )
- goto fail;
-
- nr_banks = hwdom_free_mem->nr_banks;
- xfree(gnttab);
- }
-
- for ( i = 0; kinfo->unassigned_mem > 0 && nr_banks > 0; i++, nr_banks-- )
- {
- paddr_t bank_start, bank_size;
-
- if ( is_hardware_domain(d) )
- {
- bank_start = hwdom_free_mem->bank[i].start;
- bank_size = hwdom_free_mem->bank[i].size;
- }
- else
- {
- const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
- const uint64_t banksize[] = GUEST_RAM_BANK_SIZES;
-
- if ( i >= GUEST_RAM_BANKS )
- goto fail;
-
- bank_start = bankbase[i];
- bank_size = banksize[i];
- }
-
- bank_size = MIN(bank_size, kinfo->unassigned_mem);
- if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(bank_start), bank_size) )
- goto fail;
- }
-
- if ( kinfo->unassigned_mem )
- goto fail;
-
- for( i = 0; i < mem->nr_banks; i++ )
- {
- printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
- d,
- i,
- mem->bank[i].start,
- mem->bank[i].start + mem->bank[i].size,
- /* Don't want format this as PRIpaddr (16 digit hex) */
- (unsigned long)(mem->bank[i].size >> 20));
- }
-
- xfree(hwdom_free_mem);
- return;
-
- fail:
- panic("Failed to allocate requested domain memory."
- /* Don't want format this as PRIpaddr (16 digit hex) */
- " %ldKB unallocated. Fix the VMs configurations.\n",
- (unsigned long)kinfo->unassigned_mem >> 10);
-}
-
static int __init handle_pci_range(const struct dt_device_node *dev,
uint64_t addr, uint64_t len, void *data)
{
@@ -2056,75 +1729,6 @@ static int __init prepare_dtb_hwdom(struct domain *d, struct kernel_info *kinfo)
return -EINVAL;
}
-static void __init dtb_load(struct kernel_info *kinfo)
-{
- unsigned long left;
-
- printk("Loading %pd DTB to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
- kinfo->d, kinfo->dtb_paddr,
- kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt));
-
- left = copy_to_guest_phys_flush_dcache(kinfo->d, kinfo->dtb_paddr,
- kinfo->fdt,
- fdt_totalsize(kinfo->fdt));
-
- if ( left != 0 )
- panic("Unable to copy the DTB to %pd memory (left = %lu bytes)\n",
- kinfo->d, left);
- xfree(kinfo->fdt);
-}
-
-static void __init initrd_load(struct kernel_info *kinfo)
-{
- const struct bootmodule *mod = kinfo->initrd_bootmodule;
- paddr_t load_addr = kinfo->initrd_paddr;
- paddr_t paddr, len;
- int node;
- int res;
- __be32 val[2];
- __be32 *cellp;
- void __iomem *initrd;
-
- if ( !mod || !mod->size )
- return;
-
- paddr = mod->start;
- len = mod->size;
-
- printk("Loading %pd initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
- kinfo->d, paddr, load_addr, load_addr + len);
-
- /* Fix up linux,initrd-start and linux,initrd-end in /chosen */
- node = fdt_path_offset(kinfo->fdt, "/chosen");
- if ( node < 0 )
- panic("Cannot find the /chosen node\n");
-
- cellp = (__be32 *)val;
- dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr);
- res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-start",
- val, sizeof(val));
- if ( res )
- panic("Cannot fix up \"linux,initrd-start\" property\n");
-
- cellp = (__be32 *)val;
- dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr + len);
- res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-end",
- val, sizeof(val));
- if ( res )
- panic("Cannot fix up \"linux,initrd-end\" property\n");
-
- initrd = ioremap_wc(paddr, len);
- if ( !initrd )
- panic("Unable to map the hwdom initrd\n");
-
- res = copy_to_guest_phys_flush_dcache(kinfo->d, load_addr,
- initrd, len);
- if ( res != 0 )
- panic("Unable to copy the initrd in the hwdom memory\n");
-
- iounmap(initrd);
-}
-
/*
* Allocate the event channel PPIs and setup the HVM_PARAM_CALLBACK_IRQ.
* The allocated IRQ will be found in d->arch.evtchn_irq.
@@ -2217,8 +1821,8 @@ int __init construct_domain(struct domain *d, struct kernel_info *kinfo)
*/
kernel_load(kinfo);
/* initrd_load will fix up the fdt, so call it before dtb_load */
- initrd_load(kinfo);
- dtb_load(kinfo);
+ initrd_load(kinfo, copy_to_guest_phys_flush_dcache);
+ dtb_load(kinfo, copy_to_guest_phys_flush_dcache);
memset(regs, 0, sizeof(*regs));
diff --git a/xen/arch/arm/include/asm/Makefile b/xen/arch/arm/include/asm/Makefile
index 9cec55606e..cda29dca6c 100644
--- a/xen/arch/arm/include/asm/Makefile
+++ b/xen/arch/arm/include/asm/Makefile
@@ -1,6 +1,7 @@
# SPDX-License-Identifier: GPL-2.0-only
generic-y += altp2m.h
generic-y += device.h
+generic-y += domain-build.h
generic-y += dom0less-build.h
generic-y += hardirq.h
generic-y += iocap.h
diff --git a/xen/common/device-tree/Makefile b/xen/common/device-tree/Makefile
index e88a4d5799..831b91399b 100644
--- a/xen/common/device-tree/Makefile
+++ b/xen/common/device-tree/Makefile
@@ -1,6 +1,7 @@
obj-y += bootfdt.init.o
obj-y += bootinfo.init.o
obj-y += device-tree.o
+obj-$(CONFIG_DOMAIN_BUILD_HELPERS) += domain-build.o
obj-$(CONFIG_DOM0LESS_BOOT) += dom0less-build.o
obj-$(CONFIG_OVERLAY_DTB) += dt-overlay.o
obj-y += intc.o
diff --git a/xen/common/device-tree/domain-build.c b/xen/common/device-tree/domain-build.c
new file mode 100644
index 0000000000..b4fb67ad9f
--- /dev/null
+++ b/xen/common/device-tree/domain-build.c
@@ -0,0 +1,405 @@
+#include <xen/bootfdt.h>
+#include <xen/init.h>
+#include <xen/lib.h>
+#include <xen/libfdt/libfdt.h>
+#include <xen/mm.h>
+#include <xen/sched.h>
+#include <xen/sizes.h>
+#include <xen/types.h>
+#include <xen/vmap.h>
+
+#include <asm/domain-build.h>
+#include <asm/kernel.h>
+#include <asm/p2m.h>
+
+bool __init allocate_domheap_memory(struct domain *d, paddr_t tot_size,
+ alloc_domheap_mem_cb cb, void *extra)
+{
+ unsigned int max_order = UINT_MAX;
+
+ while ( tot_size > 0 )
+ {
+ unsigned int order = get_allocation_size(tot_size);
+ struct page_info *pg;
+
+ order = min(max_order, order);
+
+ pg = alloc_domheap_pages(d, order, 0);
+ if ( !pg )
+ {
+ /*
+ * If we can't allocate one page, then it is unlikely to
+ * succeed in the next iteration. So bail out.
+ */
+ if ( !order )
+ return false;
+
+ /*
+ * If we can't allocate memory with order, then it is
+ * unlikely to succeed in the next iteration.
+ * Record the order - 1 to avoid re-trying.
+ */
+ max_order = order - 1;
+ continue;
+ }
+
+ if ( !cb(d, pg, order, extra) )
+ return false;
+
+ tot_size -= (1ULL << (PAGE_SHIFT + order));
+ }
+
+ return true;
+}
+
+static bool __init guest_map_pages(struct domain *d, struct page_info *pg,
+ unsigned int order, void *extra)
+{
+ gfn_t *sgfn = (gfn_t *)extra;
+ int res;
+
+ BUG_ON(!sgfn);
+ res = guest_physmap_add_page(d, *sgfn, page_to_mfn(pg), order);
+ if ( res )
+ {
+ dprintk(XENLOG_ERR, "Failed map pages to DOMU: %d", res);
+ return false;
+ }
+
+ *sgfn = gfn_add(*sgfn, 1UL << order);
+
+ return true;
+}
+
+bool __init allocate_bank_memory(struct kernel_info *kinfo, gfn_t sgfn,
+ paddr_t tot_size)
+{
+ struct membanks *mem = kernel_info_get_mem(kinfo);
+ struct domain *d = kinfo->d;
+ struct membank *bank;
+
+ /*
+ * allocate_bank_memory can be called with a tot_size of zero for
+ * the second memory bank. It is not an error and we can safely
+ * avoid creating a zero-size memory bank.
+ */
+ if ( tot_size == 0 )
+ return true;
+
+ bank = &mem->bank[mem->nr_banks];
+ bank->start = gfn_to_gaddr(sgfn);
+ bank->size = tot_size;
+
+ /*
+ * Allocate pages from the heap until tot_size is zero and map them to the
+ * guest using guest_map_pages, passing the starting gfn as extra parameter
+ * for the map operation.
+ */
+ if ( !allocate_domheap_memory(d, tot_size, guest_map_pages, &sgfn) )
+ return false;
+
+ mem->nr_banks++;
+ kinfo->unassigned_mem -= bank->size;
+
+ return true;
+}
+
+static int __init add_hwdom_free_regions(unsigned long s_gfn,
+ unsigned long e_gfn, void *data)
+{
+ struct membanks *free_regions = data;
+ paddr_t start, size;
+ paddr_t s = pfn_to_paddr(s_gfn);
+ paddr_t e = pfn_to_paddr(e_gfn);
+ unsigned int i, j;
+
+ if ( free_regions->nr_banks >= free_regions->max_banks )
+ return 0;
+
+ /*
+ * Both start and size of the free region should be 2MB aligned to
+ * potentially allow superpage mapping.
+ */
+ start = (s + SZ_2M - 1) & ~(SZ_2M - 1);
+ if ( start > e )
+ return 0;
+
+ /*
+ * e is actually "end-1" because it is called by rangeset functions
+ * which are inclusive of the last address.
+ */
+ e += 1;
+ size = (e - start) & ~(SZ_2M - 1);
+
+ /* Find the insert position (descending order). */
+ for ( i = 0; i < free_regions->nr_banks ; i++ )
+ if ( size > free_regions->bank[i].size )
+ break;
+
+ /* Move the other banks to make space. */
+ for ( j = free_regions->nr_banks; j > i ; j-- )
+ {
+ free_regions->bank[j].start = free_regions->bank[j - 1].start;
+ free_regions->bank[j].size = free_regions->bank[j - 1].size;
+ }
+
+ free_regions->bank[i].start = start;
+ free_regions->bank[i].size = size;
+ free_regions->nr_banks++;
+
+ return 0;
+}
+
+/*
+ * Find unused regions of Host address space which can be exposed to domain
+ * using the host memory layout. In order to calculate regions we exclude every
+ * region passed in mem_banks from the Host RAM.
+ */
+int __init find_unallocated_memory(const struct kernel_info *kinfo,
+ const struct membanks *mem_banks[],
+ unsigned int nr_mem_banks,
+ struct membanks *free_regions,
+ int (*cb)(unsigned long s_gfn,
+ unsigned long e_gfn,
+ void *data))
+{
+ const struct membanks *mem = bootinfo_get_mem();
+ struct rangeset *unalloc_mem;
+ paddr_t start, end;
+ unsigned int i, j;
+ int res;
+
+ ASSERT(domain_use_host_layout(kinfo->d));
+
+ unalloc_mem = rangeset_new(NULL, NULL, 0);
+ if ( !unalloc_mem )
+ return -ENOMEM;
+
+ /* Start with all available RAM */
+ for ( i = 0; i < mem->nr_banks; i++ )
+ {
+ start = mem->bank[i].start;
+ end = mem->bank[i].start + mem->bank[i].size;
+ res = rangeset_add_range(unalloc_mem, PFN_DOWN(start),
+ PFN_DOWN(end - 1));
+ if ( res )
+ {
+ printk(XENLOG_ERR "Failed to add: %#"PRIpaddr"->%#"PRIpaddr"\n",
+ start, end);
+ goto out;
+ }
+ }
+
+ /* Remove all regions listed in mem_banks */
+ for ( i = 0; i < nr_mem_banks; i++ )
+ for ( j = 0; j < mem_banks[i]->nr_banks; j++ )
+ {
+ start = mem_banks[i]->bank[j].start;
+
+ /* Shared memory banks can contain INVALID_PADDR as start */
+ if ( INVALID_PADDR == start )
+ continue;
+
+ end = mem_banks[i]->bank[j].start + mem_banks[i]->bank[j].size;
+ res = rangeset_remove_range(unalloc_mem, PFN_DOWN(start),
+ PFN_DOWN(end - 1));
+ if ( res )
+ {
+ printk(XENLOG_ERR
+ "Failed to add: %#"PRIpaddr"->%#"PRIpaddr", error %d\n",
+ start, end, res);
+ goto out;
+ }
+ }
+
+ start = 0;
+ end = (1ULL << p2m_ipa_bits) - 1;
+ res = rangeset_report_ranges(unalloc_mem, PFN_DOWN(start), PFN_DOWN(end),
+ cb, free_regions);
+ if ( res )
+ free_regions->nr_banks = 0;
+ else if ( !free_regions->nr_banks )
+ res = -ENOENT;
+
+out:
+ rangeset_destroy(unalloc_mem);
+
+ return res;
+}
+
+void __init allocate_memory(struct domain *d, struct kernel_info *kinfo)
+{
+ struct membanks *mem = kernel_info_get_mem(kinfo);
+ unsigned int i, nr_banks = GUEST_RAM_BANKS;
+ struct membanks *hwdom_free_mem = NULL;
+
+ printk(XENLOG_INFO "Allocating mappings totalling %ldMB for %pd:\n",
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ (unsigned long)(kinfo->unassigned_mem >> 20), d);
+
+ mem->nr_banks = 0;
+ /*
+ * Use host memory layout for hwdom. Only case for this is when LLC coloring
+ * is enabled.
+ */
+ if ( is_hardware_domain(d) )
+ {
+ struct membanks *gnttab = xzalloc_flex_struct(struct membanks, bank, 1);
+ /*
+ * Exclude the following regions:
+ * 1) Remove reserved memory
+ * 2) Grant table assigned to hwdom
+ */
+ const struct membanks *mem_banks[] = {
+ bootinfo_get_reserved_mem(),
+ gnttab,
+ };
+
+ if ( !gnttab )
+ goto fail;
+
+ gnttab->nr_banks = 1;
+ gnttab->bank[0].start = kinfo->gnttab_start;
+ gnttab->bank[0].size = kinfo->gnttab_size;
+
+ hwdom_free_mem = xzalloc_flex_struct(struct membanks, bank,
+ NR_MEM_BANKS);
+ if ( !hwdom_free_mem )
+ goto fail;
+
+ hwdom_free_mem->max_banks = NR_MEM_BANKS;
+
+ if ( find_unallocated_memory(kinfo, mem_banks, ARRAY_SIZE(mem_banks),
+ hwdom_free_mem, add_hwdom_free_regions) )
+ goto fail;
+
+ nr_banks = hwdom_free_mem->nr_banks;
+ xfree(gnttab);
+ }
+
+ for ( i = 0; kinfo->unassigned_mem > 0 && nr_banks > 0; i++, nr_banks-- )
+ {
+ paddr_t bank_start, bank_size;
+
+ if ( is_hardware_domain(d) )
+ {
+ bank_start = hwdom_free_mem->bank[i].start;
+ bank_size = hwdom_free_mem->bank[i].size;
+ }
+ else
+ {
+ const uint64_t bankbase[] = GUEST_RAM_BANK_BASES;
+ const uint64_t banksize[] = GUEST_RAM_BANK_SIZES;
+
+ if ( i >= GUEST_RAM_BANKS )
+ goto fail;
+
+ bank_start = bankbase[i];
+ bank_size = banksize[i];
+ }
+
+ bank_size = MIN(bank_size, kinfo->unassigned_mem);
+ if ( !allocate_bank_memory(kinfo, gaddr_to_gfn(bank_start), bank_size) )
+ goto fail;
+ }
+
+ if ( kinfo->unassigned_mem )
+ goto fail;
+
+ for( i = 0; i < mem->nr_banks; i++ )
+ {
+ printk(XENLOG_INFO "%pd BANK[%d] %#"PRIpaddr"-%#"PRIpaddr" (%ldMB)\n",
+ d,
+ i,
+ mem->bank[i].start,
+ mem->bank[i].start + mem->bank[i].size,
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ (unsigned long)(mem->bank[i].size >> 20));
+ }
+
+ xfree(hwdom_free_mem);
+ return;
+
+ fail:
+ panic("Failed to allocate requested domain memory."
+ /* Don't want format this as PRIpaddr (16 digit hex) */
+ " %ldKB unallocated. Fix the VMs configurations.\n",
+ (unsigned long)kinfo->unassigned_mem >> 10);
+}
+
+/* Copy data to guest physical address, then clean the region. */
+typedef unsigned long (*copy_to_guest_phys_cb)(struct domain *d,
+ paddr_t gpa,
+ void *buf,
+ unsigned int len);
+
+void __init dtb_load(struct kernel_info *kinfo,
+ copy_to_guest_phys_cb copy_to_guest)
+{
+ unsigned long left;
+
+ printk("Loading %pd DTB to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
+ kinfo->d, kinfo->dtb_paddr,
+ kinfo->dtb_paddr + fdt_totalsize(kinfo->fdt));
+
+ left = copy_to_guest(kinfo->d, kinfo->dtb_paddr,
+ kinfo->fdt,
+ fdt_totalsize(kinfo->fdt));
+
+ if ( left != 0 )
+ panic("Unable to copy the DTB to %pd memory (left = %lu bytes)\n",
+ kinfo->d, left);
+ xfree(kinfo->fdt);
+}
+
+void __init initrd_load(struct kernel_info *kinfo,
+ copy_to_guest_phys_cb copy_to_guest)
+{
+ const struct bootmodule *mod = kinfo->initrd_bootmodule;
+ paddr_t load_addr = kinfo->initrd_paddr;
+ paddr_t paddr, len;
+ int node;
+ int res;
+ __be32 val[2];
+ __be32 *cellp;
+ void __iomem *initrd;
+
+ if ( !mod || !mod->size )
+ return;
+
+ paddr = mod->start;
+ len = mod->size;
+
+ printk("Loading %pd initrd from %"PRIpaddr" to 0x%"PRIpaddr"-0x%"PRIpaddr"\n",
+ kinfo->d, paddr, load_addr, load_addr + len);
+
+ /* Fix up linux,initrd-start and linux,initrd-end in /chosen */
+ node = fdt_path_offset(kinfo->fdt, "/chosen");
+ if ( node < 0 )
+ panic("Cannot find the /chosen node\n");
+
+ cellp = (__be32 *)val;
+ dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr);
+ res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-start",
+ val, sizeof(val));
+ if ( res )
+ panic("Cannot fix up \"linux,initrd-start\" property\n");
+
+ cellp = (__be32 *)val;
+ dt_set_cell(&cellp, ARRAY_SIZE(val), load_addr + len);
+ res = fdt_setprop_inplace(kinfo->fdt, node, "linux,initrd-end",
+ val, sizeof(val));
+ if ( res )
+ panic("Cannot fix up \"linux,initrd-end\" property\n");
+
+ initrd = ioremap_wc(paddr, len);
+ if ( !initrd )
+ panic("Unable to map the hwdom initrd\n");
+
+ res = copy_to_guest(kinfo->d, load_addr,
+ initrd, len);
+ if ( res != 0 )
+ panic("Unable to copy the initrd in the hwdom memory\n");
+
+ iounmap(initrd);
+}
diff --git a/xen/include/asm-generic/domain-build.h b/xen/include/asm-generic/domain-build.h
index 237f94d0c3..4119d6e329 100644
--- a/xen/include/asm-generic/domain-build.h
+++ b/xen/include/asm-generic/domain-build.h
@@ -2,6 +2,7 @@
#ifndef __ASM_GENERIC_DOMAIN_BUILD_H__
#define __ASM_GENERIC_DOMAIN_BUILD_H__
+#include <xen/mm.h>
#include <xen/types.h>
struct domain;
@@ -26,7 +27,37 @@ int make_memory_node(const struct kernel_info *kinfo, int addrcells,
int sizecells, const struct membanks *mem);
int make_timer_node(const struct kernel_info *kinfo);
-unsigned int get_allocation_size(paddr_t size);
+
+static inline int get_allocation_size(paddr_t size)
+{
+ /*
+ * get_order_from_bytes returns the order greater than or equal to
+ * the given size, but we need less than or equal. Adding one to
+ * the size pushes an evenly aligned size into the next order, so
+ * we can then unconditionally subtract 1 from the order which is
+ * returned.
+ */
+ return get_order_from_bytes(size + 1) - 1;
+}
+
+typedef unsigned long (*copy_to_guest_phys_cb)(struct domain *d,
+ paddr_t gpa,
+ void *buf,
+ unsigned int len);
+
+void initrd_load(struct kernel_info *kinfo,
+ copy_to_guest_phys_cb copy_to_guest);
+
+void dtb_load(struct kernel_info *kinfo,
+ copy_to_guest_phys_cb copy_to_guest);
+
+int find_unallocated_memory(const struct kernel_info *kinfo,
+ const struct membanks *mem_banks[],
+ unsigned int nr_mem_banks,
+ struct membanks *free_regions,
+ int (*cb)(unsigned long s_gfn,
+ unsigned long e_gfn,
+ void *data));
#endif /* __ASM_GENERIC_DOMAIN_BUILD_H__ */
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread* [PATCH v1 9/9] xen/common: dom0less: introduce common dom0less-build.c
2025-01-08 11:13 [PATCH for 4.21 v1 0/9] Move parts of Arm's Dom0less to common code Oleksii Kurochko
` (7 preceding siblings ...)
2025-01-08 11:13 ` [PATCH v1 8/9] xen/common: dom0less: introduce common domain-build.c Oleksii Kurochko
@ 2025-01-08 11:13 ` Oleksii Kurochko
8 siblings, 0 replies; 20+ messages in thread
From: Oleksii Kurochko @ 2025-01-08 11:13 UTC (permalink / raw)
To: xen-devel
Cc: Oleksii Kurochko, Stefano Stabellini, Julien Grall,
Bertrand Marquis, Michal Orzel, Volodymyr Babchuk, Andrew Cooper,
Anthony PERARD, Jan Beulich, Roger Pau Monné
Part of Arm's dom0less-build.c could be common between architectures which are
using device tree files to create guest domains. Thereby move some parts of
Arm's dom0less-build.c to common code with minor changes.
As a part of theses changes the following changes are introduced:
- Introduce make_arch_nodes() to cover arch-specific nodes. For example, in
case of Arm, it is PSCI and vpl011 nodes.
- Introduce set_domain_type() to abstract a way how setting of domain type
happens. For example, RISC-V won't have this member of arch_domain structure
as vCPUs will always have the same bitness as hypervisor. In case of Arm, it
is possible that Arm64 could create 32-bit and 64-bit domains.
- Introduce init_vuart() to cover details of virtual uart initialization.
- Introduce init_intc_phandle() to cover some details of interrupt controller
phandle initialization. As an example, RISC-V could have different name for
interrupt controller node ( APLIC, PLIC, IMSIC, etc ) but the code in
domain_handle_dtb_bootmodule() could handle only one interrupt controller
node name.
- s/make_gic_domU_node/make_intc_domU_node as GIC is Arm specific naming and
add prototype of make_intc_domU_node() to dom0less-build.h
The following functions are moved to xen/common/device-tree:
- Functions which are moved as is:
- domain_p2m_pages().
- handle_passthrough_prop().
- handle_prop_pfdt().
- scan_pfdt_node().
- check_partial_fdt().
- Functions which are moved with some minor changes:
- alloc_xenstore_evtchn():
- ifdef-ing by CONFIG_HVM accesses to hvm.params.
- prepare_dtb_domU():
- ifdef-ing access to gnttab_{start,size} by CONFIG_GRANT_TABLE.
- s/make_gic_domU_node/make_intc_domU_node.
- Add call of make_arch_nodes().
- domain_handle_dtb_bootmodule():
- hide details of interrupt controller phandle initialization by calling
init_intc_phandle().
- Update the comment above init_intc_phandle(): s/gic/interrupt controller.
- construct_domU():
- ifdef-ing by CONFIG_HVM accesses to hvm.params.
- Call init_vuart() to hide Arm's vpl011_init() details there.
- Add call of set_domain_type() instead of setting kinfo->arch.type explicitly.
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
xen/arch/arm/dom0less-build.c | 569 ++---------------------
xen/common/device-tree/dom0less-build.c | 559 ++++++++++++++++++++++
xen/include/asm-generic/dom0less-build.h | 14 +
3 files changed, 608 insertions(+), 534 deletions(-)
diff --git a/xen/arch/arm/dom0less-build.c b/xen/arch/arm/dom0less-build.c
index 259285ddda..872a9437da 100644
--- a/xen/arch/arm/dom0less-build.c
+++ b/xen/arch/arm/dom0less-build.c
@@ -143,7 +143,7 @@ static int __init make_gicv3_domU_node(struct kernel_info *kinfo)
}
#endif
-static int __init make_gic_domU_node(struct kernel_info *kinfo)
+int __init make_intc_domU_node(struct kernel_info *kinfo)
{
switch ( kinfo->d->arch.vgic.version )
{
@@ -209,577 +209,62 @@ static int __init make_vpl011_uart_node(struct kernel_info *kinfo)
}
#endif
-/*
- * Scan device tree properties for passthrough specific information.
- * Returns < 0 on error
- * 0 on success
- */
-static int __init handle_passthrough_prop(struct kernel_info *kinfo,
- const struct fdt_property *xen_reg,
- const struct fdt_property *xen_path,
- bool xen_force,
- uint32_t address_cells,
- uint32_t size_cells)
-{
- const __be32 *cell;
- unsigned int i, len;
- struct dt_device_node *node;
- int res;
- paddr_t mstart, size, gstart;
-
- /* xen,reg specifies where to map the MMIO region */
- cell = (const __be32 *)xen_reg->data;
- len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) *
- sizeof(uint32_t));
-
- for ( i = 0; i < len; i++ )
- {
- device_tree_get_reg(&cell, address_cells, size_cells,
- &mstart, &size);
- gstart = dt_next_cell(address_cells, &cell);
-
- if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK )
- {
- printk(XENLOG_ERR
- "DomU passthrough config has not page aligned addresses/sizes\n");
- return -EINVAL;
- }
-
- res = iomem_permit_access(kinfo->d, paddr_to_pfn(mstart),
- paddr_to_pfn(PAGE_ALIGN(mstart + size - 1)));
- if ( res )
- {
- printk(XENLOG_ERR "Unable to permit to dom%d access to"
- " 0x%"PRIpaddr" - 0x%"PRIpaddr"\n",
- kinfo->d->domain_id,
- mstart & PAGE_MASK, PAGE_ALIGN(mstart + size) - 1);
- return res;
- }
-
- res = map_regions_p2mt(kinfo->d,
- gaddr_to_gfn(gstart),
- PFN_DOWN(size),
- maddr_to_mfn(mstart),
- p2m_mmio_direct_dev);
- if ( res < 0 )
- {
- printk(XENLOG_ERR
- "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n",
- mstart, gstart);
- return -EFAULT;
- }
- }
-
- /*
- * If xen_force, we let the user assign a MMIO region with no
- * associated path.
- */
- if ( xen_path == NULL )
- return xen_force ? 0 : -EINVAL;
-
- /*
- * xen,path specifies the corresponding node in the host DT.
- * Both interrupt mappings and IOMMU settings are based on it,
- * as they are done based on the corresponding host DT node.
- */
- node = dt_find_node_by_path(xen_path->data);
- if ( node == NULL )
- {
- printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n",
- xen_path->data);
- return -EINVAL;
- }
-
- res = map_device_irqs_to_domain(kinfo->d, node, true, NULL);
- if ( res < 0 )
- return res;
-
- res = iommu_add_dt_device(node);
- if ( res < 0 )
- return res;
-
- /* If xen_force, we allow assignment of devices without IOMMU protection. */
- if ( xen_force && !dt_device_is_protected(node) )
- return 0;
-
- return iommu_assign_dt_device(kinfo->d, node);
-}
-
-static int __init handle_prop_pfdt(struct kernel_info *kinfo,
- const void *pfdt, int nodeoff,
- uint32_t address_cells, uint32_t size_cells,
- bool scan_passthrough_prop)
-{
- void *fdt = kinfo->fdt;
- int propoff, nameoff, res;
- const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL;
- const char *name;
- bool found, xen_force = false;
-
- for ( propoff = fdt_first_property_offset(pfdt, nodeoff);
- propoff >= 0;
- propoff = fdt_next_property_offset(pfdt, propoff) )
- {
- if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) )
- return -FDT_ERR_INTERNAL;
-
- found = false;
- nameoff = fdt32_to_cpu(prop->nameoff);
- name = fdt_string(pfdt, nameoff);
-
- if ( scan_passthrough_prop )
- {
- if ( dt_prop_cmp("xen,reg", name) == 0 )
- {
- xen_reg = prop;
- found = true;
- }
- else if ( dt_prop_cmp("xen,path", name) == 0 )
- {
- xen_path = prop;
- found = true;
- }
- else if ( dt_prop_cmp("xen,force-assign-without-iommu",
- name) == 0 )
- {
- xen_force = true;
- found = true;
- }
- }
-
- /*
- * Copy properties other than the ones above: xen,reg, xen,path,
- * and xen,force-assign-without-iommu.
- */
- if ( !found )
- {
- res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len));
- if ( res )
- return res;
- }
- }
-
- /*
- * Only handle passthrough properties if both xen,reg and xen,path
- * are present, or if xen,force-assign-without-iommu is specified.
- */
- if ( xen_reg != NULL && (xen_path != NULL || xen_force) )
- {
- res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force,
- address_cells, size_cells);
- if ( res < 0 )
- {
- printk(XENLOG_ERR "Failed to assign device to %pd\n", kinfo->d);
- return res;
- }
- }
- else if ( (xen_path && !xen_reg) || (xen_reg && !xen_path && !xen_force) )
- {
- printk(XENLOG_ERR "xen,reg or xen,path missing for %pd\n",
- kinfo->d);
- return -EINVAL;
- }
-
- /* FDT_ERR_NOTFOUND => There is no more properties for this node */
- return ( propoff != -FDT_ERR_NOTFOUND ) ? propoff : 0;
-}
-
-static int __init scan_pfdt_node(struct kernel_info *kinfo, const void *pfdt,
- int nodeoff,
- uint32_t address_cells, uint32_t size_cells,
- bool scan_passthrough_prop)
-{
- int rc = 0;
- void *fdt = kinfo->fdt;
- int node_next;
-
- rc = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL));
- if ( rc )
- return rc;
-
- rc = handle_prop_pfdt(kinfo, pfdt, nodeoff, address_cells, size_cells,
- scan_passthrough_prop);
- if ( rc )
- return rc;
-
- address_cells = device_tree_get_u32(pfdt, nodeoff, "#address-cells",
- DT_ROOT_NODE_ADDR_CELLS_DEFAULT);
- size_cells = device_tree_get_u32(pfdt, nodeoff, "#size-cells",
- DT_ROOT_NODE_SIZE_CELLS_DEFAULT);
-
- node_next = fdt_first_subnode(pfdt, nodeoff);
- while ( node_next > 0 )
- {
- rc = scan_pfdt_node(kinfo, pfdt, node_next, address_cells, size_cells,
- scan_passthrough_prop);
- if ( rc )
- return rc;
-
- node_next = fdt_next_subnode(pfdt, node_next);
- }
-
- return fdt_end_node(fdt);
-}
-
-static int __init check_partial_fdt(void *pfdt, size_t size)
-{
- int res;
-
- if ( fdt_magic(pfdt) != FDT_MAGIC )
- {
- dprintk(XENLOG_ERR, "Partial FDT is not a valid Flat Device Tree");
- return -EINVAL;
- }
-
- res = fdt_check_header(pfdt);
- if ( res )
- {
- dprintk(XENLOG_ERR, "Failed to check the partial FDT (%d)", res);
- return -EINVAL;
- }
-
- if ( fdt_totalsize(pfdt) > size )
- {
- dprintk(XENLOG_ERR, "Partial FDT totalsize is too big");
- return -EINVAL;
- }
-
- return 0;
-}
-
-static int __init domain_handle_dtb_bootmodule(struct domain *d,
- struct kernel_info *kinfo)
+int __init make_arch_nodes(struct kernel_info *kinfo)
{
- void *pfdt;
- int res, node_next;
-
- pfdt = ioremap_cache(kinfo->dtb_bootmodule->start,
- kinfo->dtb_bootmodule->size);
- if ( pfdt == NULL )
- return -EFAULT;
-
- res = check_partial_fdt(pfdt, kinfo->dtb_bootmodule->size);
- if ( res < 0 )
- goto out;
-
- for ( node_next = fdt_first_subnode(pfdt, 0);
- node_next > 0;
- node_next = fdt_next_subnode(pfdt, node_next) )
- {
- const char *name = fdt_get_name(pfdt, node_next, NULL);
-
- if ( name == NULL )
- continue;
-
- /*
- * Only scan /gic /aliases /passthrough, ignore the rest.
- * They don't have to be parsed in order.
- *
- * Take the GIC phandle value from the special /gic node in the
- * DTB fragment.
- */
- if ( dt_node_cmp(name, "gic") == 0 )
- {
- uint32_t phandle_intc = fdt_get_phandle(pfdt, node_next);
-
- if ( phandle_intc != 0 )
- kinfo->phandle_intc = phandle_intc;
- continue;
- }
-
- if ( dt_node_cmp(name, "aliases") == 0 )
- {
- res = scan_pfdt_node(kinfo, pfdt, node_next,
- DT_ROOT_NODE_ADDR_CELLS_DEFAULT,
- DT_ROOT_NODE_SIZE_CELLS_DEFAULT,
- false);
- if ( res )
- goto out;
- continue;
- }
- if ( dt_node_cmp(name, "passthrough") == 0 )
- {
- res = scan_pfdt_node(kinfo, pfdt, node_next,
- DT_ROOT_NODE_ADDR_CELLS_DEFAULT,
- DT_ROOT_NODE_SIZE_CELLS_DEFAULT,
- true);
- if ( res )
- goto out;
- continue;
- }
- }
-
- out:
- iounmap(pfdt);
-
- return res;
-}
-
-/*
- * The max size for DT is 2MB. However, the generated DT is small (not including
- * domU passthrough DT nodes whose size we account separately), 4KB are enough
- * for now, but we might have to increase it in the future.
- */
-#define DOMU_DTB_SIZE 4096
-static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
-{
- int addrcells, sizecells;
- int ret, fdt_size = DOMU_DTB_SIZE;
-
- kinfo->phandle_intc = GUEST_PHANDLE_GIC;
- kinfo->gnttab_start = GUEST_GNTTAB_BASE;
- kinfo->gnttab_size = GUEST_GNTTAB_SIZE;
-
- addrcells = GUEST_ROOT_ADDRESS_CELLS;
- sizecells = GUEST_ROOT_SIZE_CELLS;
-
- /* Account for domU passthrough DT size */
- if ( kinfo->dtb_bootmodule )
- fdt_size += kinfo->dtb_bootmodule->size;
-
- /* Cap to max DT size if needed */
- fdt_size = min(fdt_size, SZ_2M);
-
- kinfo->fdt = xmalloc_bytes(fdt_size);
- if ( kinfo->fdt == NULL )
- return -ENOMEM;
-
- ret = fdt_create(kinfo->fdt, fdt_size);
- if ( ret < 0 )
- goto err;
-
- ret = fdt_finish_reservemap(kinfo->fdt);
- if ( ret < 0 )
- goto err;
-
- ret = fdt_begin_node(kinfo->fdt, "");
- if ( ret < 0 )
- goto err;
-
- ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells);
- if ( ret )
- goto err;
-
- ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells);
- if ( ret )
- goto err;
-
- ret = make_chosen_node(kinfo);
- if ( ret )
- goto err;
+ int ret;
ret = make_psci_node(kinfo->fdt);
if ( ret )
- goto err;
-
- ret = make_cpus_node(d, kinfo->fdt);
- if ( ret )
- goto err;
-
- ret = make_memory_node(kinfo, addrcells, sizecells,
- kernel_info_get_mem(kinfo));
- if ( ret )
- goto err;
-
- ret = make_resv_memory_node(kinfo, addrcells, sizecells);
- if ( ret )
- goto err;
-
- /*
- * domain_handle_dtb_bootmodule has to be called before the rest of
- * the device tree is generated because it depends on the value of
- * the field phandle_intc.
- */
- if ( kinfo->dtb_bootmodule )
- {
- ret = domain_handle_dtb_bootmodule(d, kinfo);
- if ( ret )
- goto err;
- }
-
- ret = make_gic_domU_node(kinfo);
- if ( ret )
- goto err;
-
- ret = make_timer_node(kinfo);
- if ( ret )
- goto err;
+ return -EINVAL;
if ( kinfo->vuart )
{
- ret = -EINVAL;
#ifdef CONFIG_SBSA_VUART_CONSOLE
ret = make_vpl011_uart_node(kinfo);
#endif
if ( ret )
- goto err;
- }
-
- if ( kinfo->dom0less_feature & DOM0LESS_ENHANCED_NO_XS )
- {
- ret = make_hypervisor_node(d, kinfo, addrcells, sizecells);
- if ( ret )
- goto err;
+ return -EINVAL;
}
- ret = fdt_end_node(kinfo->fdt);
- if ( ret < 0 )
- goto err;
-
- ret = fdt_finish(kinfo->fdt);
- if ( ret < 0 )
- goto err;
-
return 0;
-
- err:
- printk("Device tree generation failed (%d).\n", ret);
- xfree(kinfo->fdt);
-
- return -EINVAL;
}
-static unsigned long __init domain_p2m_pages(unsigned long maxmem_kb,
- unsigned int smp_cpus)
+/* TODO: make arch.type generic ? */
+#ifdef CONFIG_ARM_64
+void __init set_domain_type(struct domain *d, struct kernel_info *kinfo)
{
- /*
- * Keep in sync with libxl__get_required_paging_memory().
- * 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map,
- * plus 128 pages to cover extended regions.
- */
- unsigned long memkb = 4 * (256 * smp_cpus + (maxmem_kb / 1024) + 128);
-
- BUILD_BUG_ON(PAGE_SIZE != SZ_4K);
-
- return DIV_ROUND_UP(memkb, 1024) << (20 - PAGE_SHIFT);
+ /* type must be set before allocate memory */
+ d->arch.type = kinfo->arch.type;
}
-
-static int __init alloc_xenstore_evtchn(struct domain *d)
+#else
+void __init set_domain_type(struct domain *d, struct kernel_info *kinfo)
{
- evtchn_alloc_unbound_t alloc;
- int rc;
-
- alloc.dom = d->domain_id;
- alloc.remote_dom = hardware_domain->domain_id;
- rc = evtchn_alloc_unbound(&alloc, 0);
- if ( rc )
- {
- printk("Failed allocating event channel for domain\n");
- return rc;
- }
-
- d->arch.hvm.params[HVM_PARAM_STORE_EVTCHN] = alloc.port;
-
- return 0;
+ /* Nothing to do */
}
+#endif
-int __init construct_domU(struct domain *d,
- const struct dt_device_node *node)
+int __init init_vuart(struct domain *d, struct kernel_info *kinfo,
+ const struct dt_device_node *node)
{
- struct kernel_info kinfo = KERNEL_INFO_INIT;
- const char *dom0less_enhanced;
- int rc;
- u64 mem;
- u32 p2m_mem_mb;
- unsigned long p2m_pages;
-
- rc = dt_property_read_u64(node, "memory", &mem);
- if ( !rc )
- {
- printk("Error building DomU: cannot read \"memory\" property\n");
- return -EINVAL;
- }
- kinfo.unassigned_mem = (paddr_t)mem * SZ_1K;
-
- rc = dt_property_read_u32(node, "xen,domain-p2m-mem-mb", &p2m_mem_mb);
- /* If xen,domain-p2m-mem-mb is not specified, use the default value. */
- p2m_pages = rc ?
- p2m_mem_mb << (20 - PAGE_SHIFT) :
- domain_p2m_pages(mem, d->max_vcpus);
-
- spin_lock(&d->arch.paging.lock);
- rc = p2m_set_allocation(d, p2m_pages, NULL);
- spin_unlock(&d->arch.paging.lock);
- if ( rc != 0 )
- return rc;
-
- printk("*** LOADING DOMU cpus=%u memory=%#"PRIx64"KB ***\n",
- d->max_vcpus, mem);
-
- kinfo.vuart = dt_property_read_bool(node, "vpl011");
-
- rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced);
- if ( rc == -EILSEQ ||
- rc == -ENODATA ||
- (rc == 0 && !strcmp(dom0less_enhanced, "enabled")) )
- {
- if ( hardware_domain )
- kinfo.dom0less_feature = DOM0LESS_ENHANCED;
- else
- panic("At the moment, Xenstore support requires dom0 to be present\n");
- }
- else if ( rc == 0 && !strcmp(dom0less_enhanced, "no-xenstore") )
- kinfo.dom0less_feature = DOM0LESS_ENHANCED_NO_XS;
-
- if ( vcpu_create(d, 0) == NULL )
- return -ENOMEM;
-
- d->max_pages = ((paddr_t)mem * SZ_1K) >> PAGE_SHIFT;
-
- kinfo.d = d;
-
- rc = kernel_probe(&kinfo, node);
- if ( rc < 0 )
- return rc;
-
-#ifdef CONFIG_ARM_64
- /* type must be set before allocate memory */
- d->arch.type = kinfo.arch.type;
-#endif
- if ( !dt_find_property(node, "xen,static-mem", NULL) )
- allocate_memory(d, &kinfo);
- else if ( !is_domain_direct_mapped(d) )
- allocate_static_memory(d, &kinfo, node);
- else
- assign_static_memory_11(d, &kinfo, node);
+ int rc = 0;
- rc = process_shm(d, &kinfo, node);
- if ( rc < 0 )
- return rc;
+ kinfo->vuart = dt_property_read_bool(node, "vpl011");
/*
* Base address and irq number are needed when creating vpl011 device
* tree node in prepare_dtb_domU, so initialization on related variables
* shall be done first.
*/
- if ( kinfo.vuart )
+ if ( kinfo->vuart )
{
rc = domain_vpl011_init(d, NULL);
if ( rc < 0 )
return rc;
}
- rc = prepare_dtb_domU(d, &kinfo);
- if ( rc < 0 )
- return rc;
-
- rc = construct_domain(d, &kinfo);
- if ( rc < 0 )
- return rc;
-
- if ( kinfo.dom0less_feature & DOM0LESS_XENSTORE )
- {
- ASSERT(hardware_domain);
- rc = alloc_xenstore_evtchn(d);
- if ( rc < 0 )
- return rc;
- d->arch.hvm.params[HVM_PARAM_STORE_PFN] = ~0ULL;
- }
-
return rc;
}
-
struct xen_domctl_createdomain __init arch_xen_domctl_createdomain(void)
{
struct xen_domctl_createdomain d_cfg = {
@@ -868,6 +353,22 @@ void __init arch_create_domus(struct dt_device_node *node,
}
}
+int __init init_intc_phandle(struct kernel_info *kinfo, const char *name,
+ const int node_next, const void *pfdt)
+{
+ if ( dt_node_cmp(name, "gic") == 0 )
+ {
+ uint32_t phandle_intc = fdt_get_phandle(pfdt, node_next);
+
+ if ( phandle_intc != 0 )
+ kinfo->phandle_intc = phandle_intc;
+
+ return 0;
+ }
+
+ return 1;
+}
+
/*
* Local variables:
* mode: C
diff --git a/xen/common/device-tree/dom0less-build.c b/xen/common/device-tree/dom0less-build.c
index 19bfa5e005..509f825ce6 100644
--- a/xen/common/device-tree/dom0less-build.c
+++ b/xen/common/device-tree/dom0less-build.c
@@ -3,17 +3,26 @@
#include <xen/device_tree.h>
#include <xen/domain.h>
#include <xen/err.h>
+#include <xen/event.h>
#include <xen/init.h>
+#include <xen/iocap.h>
#include <xen/iommu.h>
+#include <xen/libfdt/libfdt.h>
#include <xen/llc-coloring.h>
+#include <xen/sizes.h>
#include <xen/sched.h>
#include <xen/stdbool.h>
#include <xen/types.h>
+#include <xen/vmap.h>
#include <public/domctl.h>
+#include <asm/domain-build.h>
#include <asm/dom0less-build.h>
+#include <asm/kernel.h>
#include <asm/setup.h>
+#include <asm/static-memory.h>
+#include <asm/static-shmem.h>
bool __init is_dom0less_mode(void)
{
@@ -159,3 +168,553 @@ void __init create_domUs(void)
dt_node_name(node), rc);
}
}
+
+/*
+ * Scan device tree properties for passthrough specific information.
+ * Returns < 0 on error
+ * 0 on success
+ */
+static int __init handle_passthrough_prop(struct kernel_info *kinfo,
+ const struct fdt_property *xen_reg,
+ const struct fdt_property *xen_path,
+ bool xen_force,
+ uint32_t address_cells,
+ uint32_t size_cells)
+{
+ const __be32 *cell;
+ unsigned int i, len;
+ struct dt_device_node *node;
+ int res;
+ paddr_t mstart, size, gstart;
+
+ /* xen,reg specifies where to map the MMIO region */
+ cell = (const __be32 *)xen_reg->data;
+ len = fdt32_to_cpu(xen_reg->len) / ((address_cells * 2 + size_cells) *
+ sizeof(uint32_t));
+
+ for ( i = 0; i < len; i++ )
+ {
+ device_tree_get_reg(&cell, address_cells, size_cells,
+ &mstart, &size);
+ gstart = dt_next_cell(address_cells, &cell);
+
+ if ( gstart & ~PAGE_MASK || mstart & ~PAGE_MASK || size & ~PAGE_MASK )
+ {
+ printk(XENLOG_ERR
+ "DomU passthrough config has not page aligned addresses/sizes\n");
+ return -EINVAL;
+ }
+
+ res = iomem_permit_access(kinfo->d, paddr_to_pfn(mstart),
+ paddr_to_pfn(PAGE_ALIGN(mstart + size - 1)));
+ if ( res )
+ {
+ printk(XENLOG_ERR "Unable to permit to dom%d access to"
+ " 0x%"PRIpaddr" - 0x%"PRIpaddr"\n",
+ kinfo->d->domain_id,
+ mstart & PAGE_MASK, PAGE_ALIGN(mstart + size) - 1);
+ return res;
+ }
+
+ res = map_regions_p2mt(kinfo->d,
+ gaddr_to_gfn(gstart),
+ PFN_DOWN(size),
+ maddr_to_mfn(mstart),
+ p2m_mmio_direct_dev);
+ if ( res < 0 )
+ {
+ printk(XENLOG_ERR
+ "Failed to map %"PRIpaddr" to the guest at%"PRIpaddr"\n",
+ mstart, gstart);
+ return -EFAULT;
+ }
+ }
+
+ /*
+ * If xen_force, we let the user assign a MMIO region with no
+ * associated path.
+ */
+ if ( xen_path == NULL )
+ return xen_force ? 0 : -EINVAL;
+
+ /*
+ * xen,path specifies the corresponding node in the host DT.
+ * Both interrupt mappings and IOMMU settings are based on it,
+ * as they are done based on the corresponding host DT node.
+ */
+ node = dt_find_node_by_path(xen_path->data);
+ if ( node == NULL )
+ {
+ printk(XENLOG_ERR "Couldn't find node %s in host_dt!\n",
+ xen_path->data);
+ return -EINVAL;
+ }
+
+ res = map_device_irqs_to_domain(kinfo->d, node, true, NULL);
+ if ( res < 0 )
+ return res;
+
+ res = iommu_add_dt_device(node);
+ if ( res < 0 )
+ return res;
+
+ /* If xen_force, we allow assignment of devices without IOMMU protection. */
+ if ( xen_force && !dt_device_is_protected(node) )
+ return 0;
+
+ return iommu_assign_dt_device(kinfo->d, node);
+}
+
+static int __init handle_prop_pfdt(struct kernel_info *kinfo,
+ const void *pfdt, int nodeoff,
+ uint32_t address_cells, uint32_t size_cells,
+ bool scan_passthrough_prop)
+{
+ void *fdt = kinfo->fdt;
+ int propoff, nameoff, res;
+ const struct fdt_property *prop, *xen_reg = NULL, *xen_path = NULL;
+ const char *name;
+ bool found, xen_force = false;
+
+ for ( propoff = fdt_first_property_offset(pfdt, nodeoff);
+ propoff >= 0;
+ propoff = fdt_next_property_offset(pfdt, propoff) )
+ {
+ if ( !(prop = fdt_get_property_by_offset(pfdt, propoff, NULL)) )
+ return -FDT_ERR_INTERNAL;
+
+ found = false;
+ nameoff = fdt32_to_cpu(prop->nameoff);
+ name = fdt_string(pfdt, nameoff);
+
+ if ( scan_passthrough_prop )
+ {
+ if ( dt_prop_cmp("xen,reg", name) == 0 )
+ {
+ xen_reg = prop;
+ found = true;
+ }
+ else if ( dt_prop_cmp("xen,path", name) == 0 )
+ {
+ xen_path = prop;
+ found = true;
+ }
+ else if ( dt_prop_cmp("xen,force-assign-without-iommu",
+ name) == 0 )
+ {
+ xen_force = true;
+ found = true;
+ }
+ }
+
+ /*
+ * Copy properties other than the ones above: xen,reg, xen,path,
+ * and xen,force-assign-without-iommu.
+ */
+ if ( !found )
+ {
+ res = fdt_property(fdt, name, prop->data, fdt32_to_cpu(prop->len));
+ if ( res )
+ return res;
+ }
+ }
+
+ /*
+ * Only handle passthrough properties if both xen,reg and xen,path
+ * are present, or if xen,force-assign-without-iommu is specified.
+ */
+ if ( xen_reg != NULL && (xen_path != NULL || xen_force) )
+ {
+ res = handle_passthrough_prop(kinfo, xen_reg, xen_path, xen_force,
+ address_cells, size_cells);
+ if ( res < 0 )
+ {
+ printk(XENLOG_ERR "Failed to assign device to %pd\n", kinfo->d);
+ return res;
+ }
+ }
+ else if ( (xen_path && !xen_reg) || (xen_reg && !xen_path && !xen_force) )
+ {
+ printk(XENLOG_ERR "xen,reg or xen,path missing for %pd\n",
+ kinfo->d);
+ return -EINVAL;
+ }
+
+ /* FDT_ERR_NOTFOUND => There is no more properties for this node */
+ return ( propoff != -FDT_ERR_NOTFOUND ) ? propoff : 0;
+}
+
+static int __init scan_pfdt_node(struct kernel_info *kinfo, const void *pfdt,
+ int nodeoff,
+ uint32_t address_cells, uint32_t size_cells,
+ bool scan_passthrough_prop)
+{
+ int rc = 0;
+ void *fdt = kinfo->fdt;
+ int node_next;
+
+ rc = fdt_begin_node(fdt, fdt_get_name(pfdt, nodeoff, NULL));
+ if ( rc )
+ return rc;
+
+ rc = handle_prop_pfdt(kinfo, pfdt, nodeoff, address_cells, size_cells,
+ scan_passthrough_prop);
+ if ( rc )
+ return rc;
+
+ address_cells = device_tree_get_u32(pfdt, nodeoff, "#address-cells",
+ DT_ROOT_NODE_ADDR_CELLS_DEFAULT);
+ size_cells = device_tree_get_u32(pfdt, nodeoff, "#size-cells",
+ DT_ROOT_NODE_SIZE_CELLS_DEFAULT);
+
+ node_next = fdt_first_subnode(pfdt, nodeoff);
+ while ( node_next > 0 )
+ {
+ rc = scan_pfdt_node(kinfo, pfdt, node_next, address_cells, size_cells,
+ scan_passthrough_prop);
+ if ( rc )
+ return rc;
+
+ node_next = fdt_next_subnode(pfdt, node_next);
+ }
+
+ return fdt_end_node(fdt);
+}
+
+static int __init check_partial_fdt(void *pfdt, size_t size)
+{
+ int res;
+
+ if ( fdt_magic(pfdt) != FDT_MAGIC )
+ {
+ dprintk(XENLOG_ERR, "Partial FDT is not a valid Flat Device Tree");
+ return -EINVAL;
+ }
+
+ res = fdt_check_header(pfdt);
+ if ( res )
+ {
+ dprintk(XENLOG_ERR, "Failed to check the partial FDT (%d)", res);
+ return -EINVAL;
+ }
+
+ if ( fdt_totalsize(pfdt) > size )
+ {
+ dprintk(XENLOG_ERR, "Partial FDT totalsize is too big");
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int __init domain_handle_dtb_bootmodule(struct domain *d,
+ struct kernel_info *kinfo)
+{
+ void *pfdt;
+ int res, node_next;
+
+ pfdt = ioremap_cache(kinfo->dtb_bootmodule->start,
+ kinfo->dtb_bootmodule->size);
+ if ( pfdt == NULL )
+ return -EFAULT;
+
+ res = check_partial_fdt(pfdt, kinfo->dtb_bootmodule->size);
+ if ( res < 0 )
+ goto out;
+
+ for ( node_next = fdt_first_subnode(pfdt, 0);
+ node_next > 0;
+ node_next = fdt_next_subnode(pfdt, node_next) )
+ {
+ const char *name = fdt_get_name(pfdt, node_next, NULL);
+
+ if ( name == NULL )
+ continue;
+
+ /*
+ * Only scan /$(interrupt_controller) /aliases /passthrough,
+ * ignore the rest.
+ * They don't have to be parsed in order.
+ *
+ * Take the interrupt controller phandle value from the special
+ * interrupt controller node in the DTB fragment.
+ */
+ if ( init_intc_phandle(kinfo, name, node_next, pfdt) == 0 )
+ continue;
+
+ if ( dt_node_cmp(name, "aliases") == 0 )
+ {
+ res = scan_pfdt_node(kinfo, pfdt, node_next,
+ DT_ROOT_NODE_ADDR_CELLS_DEFAULT,
+ DT_ROOT_NODE_SIZE_CELLS_DEFAULT,
+ false);
+ if ( res )
+ goto out;
+ continue;
+ }
+ if ( dt_node_cmp(name, "passthrough") == 0 )
+ {
+ res = scan_pfdt_node(kinfo, pfdt, node_next,
+ DT_ROOT_NODE_ADDR_CELLS_DEFAULT,
+ DT_ROOT_NODE_SIZE_CELLS_DEFAULT,
+ true);
+ if ( res )
+ goto out;
+ continue;
+ }
+ }
+
+ out:
+ iounmap(pfdt);
+
+ return res;
+}
+
+static unsigned long __init domain_p2m_pages(unsigned long maxmem_kb,
+ unsigned int smp_cpus)
+{
+ /*
+ * Keep in sync with libxl__get_required_paging_memory().
+ * 256 pages (1MB) per vcpu, plus 1 page per MiB of RAM for the P2M map,
+ * plus 128 pages to cover extended regions.
+ */
+ unsigned long memkb = 4 * (256 * smp_cpus + (maxmem_kb / 1024) + 128);
+
+ BUILD_BUG_ON(PAGE_SIZE != SZ_4K);
+
+ return DIV_ROUND_UP(memkb, 1024) << (20 - PAGE_SHIFT);
+}
+
+/*
+ * The max size for DT is 2MB. However, the generated DT is small (not including
+ * domU passthrough DT nodes whose size we account separately), 4KB are enough
+ * for now, but we might have to increase it in the future.
+ */
+#define DOMU_DTB_SIZE 4096
+static int __init prepare_dtb_domU(struct domain *d, struct kernel_info *kinfo)
+{
+ int addrcells, sizecells;
+ int ret, fdt_size = DOMU_DTB_SIZE;
+
+ kinfo->phandle_intc = GUEST_PHANDLE_GIC;
+
+#ifdef CONFIG_GRANT_TABLE
+ kinfo->gnttab_start = GUEST_GNTTAB_BASE;
+ kinfo->gnttab_size = GUEST_GNTTAB_SIZE;
+#endif
+
+ addrcells = GUEST_ROOT_ADDRESS_CELLS;
+ sizecells = GUEST_ROOT_SIZE_CELLS;
+
+ /* Account for domU passthrough DT size */
+ if ( kinfo->dtb_bootmodule )
+ fdt_size += kinfo->dtb_bootmodule->size;
+
+ /* Cap to max DT size if needed */
+ fdt_size = min(fdt_size, SZ_2M);
+
+ kinfo->fdt = xmalloc_bytes(fdt_size);
+ if ( kinfo->fdt == NULL )
+ return -ENOMEM;
+
+ ret = fdt_create(kinfo->fdt, fdt_size);
+ if ( ret < 0 )
+ goto err;
+
+ ret = fdt_finish_reservemap(kinfo->fdt);
+ if ( ret < 0 )
+ goto err;
+
+ ret = fdt_begin_node(kinfo->fdt, "");
+ if ( ret < 0 )
+ goto err;
+
+ ret = fdt_property_cell(kinfo->fdt, "#address-cells", addrcells);
+ if ( ret )
+ goto err;
+
+ ret = fdt_property_cell(kinfo->fdt, "#size-cells", sizecells);
+ if ( ret )
+ goto err;
+
+ ret = make_chosen_node(kinfo);
+ if ( ret )
+ goto err;
+
+ ret = make_cpus_node(d, kinfo->fdt);
+ if ( ret )
+ goto err;
+
+ ret = make_memory_node(kinfo, addrcells, sizecells,
+ kernel_info_get_mem(kinfo));
+ if ( ret )
+ goto err;
+
+ ret = make_resv_memory_node(kinfo, addrcells, sizecells);
+ if ( ret )
+ goto err;
+
+ /*
+ * domain_handle_dtb_bootmodule has to be called before the rest of
+ * the device tree is generated because it depends on the value of
+ * the field phandle_intc.
+ */
+ if ( kinfo->dtb_bootmodule )
+ {
+ ret = domain_handle_dtb_bootmodule(d, kinfo);
+ if ( ret )
+ goto err;
+ }
+
+ ret = make_intc_domU_node(kinfo);
+ if ( ret )
+ goto err;
+
+ ret = make_timer_node(kinfo);
+ if ( ret )
+ goto err;
+
+ if ( kinfo->dom0less_feature & DOM0LESS_ENHANCED_NO_XS )
+ {
+ ret = make_hypervisor_node(d, kinfo, addrcells, sizecells);
+ if ( ret )
+ goto err;
+ }
+
+ ret = make_arch_nodes(kinfo);
+ if ( ret )
+ goto err;
+
+ ret = fdt_end_node(kinfo->fdt);
+ if ( ret < 0 )
+ goto err;
+
+ ret = fdt_finish(kinfo->fdt);
+ if ( ret < 0 )
+ goto err;
+
+ return 0;
+
+ err:
+ printk("Device tree generation failed (%d).\n", ret);
+ xfree(kinfo->fdt);
+
+ return -EINVAL;
+}
+
+static int __init alloc_xenstore_evtchn(struct domain *d)
+{
+ evtchn_alloc_unbound_t alloc;
+ int rc;
+
+ alloc.dom = d->domain_id;
+ alloc.remote_dom = hardware_domain->domain_id;
+ rc = evtchn_alloc_unbound(&alloc, 0);
+ if ( rc )
+ {
+ printk("Failed allocating event channel for domain\n");
+ return rc;
+ }
+
+#ifdef CONFIG_HVM
+ d->arch.hvm.params[HVM_PARAM_STORE_EVTCHN] = alloc.port;
+#endif
+
+ return 0;
+}
+
+int __init construct_domU(struct domain *d,
+ const struct dt_device_node *node)
+{
+ struct kernel_info kinfo = KERNEL_INFO_INIT;
+ const char *dom0less_enhanced;
+ int rc;
+ u64 mem;
+ u32 p2m_mem_mb;
+ unsigned long p2m_pages;
+
+ rc = dt_property_read_u64(node, "memory", &mem);
+ if ( !rc )
+ {
+ printk("Error building DomU: cannot read \"memory\" property\n");
+ return -EINVAL;
+ }
+ kinfo.unassigned_mem = (paddr_t)mem * SZ_1K;
+
+ rc = dt_property_read_u32(node, "xen,domain-p2m-mem-mb", &p2m_mem_mb);
+ /* If xen,domain-p2m-mem-mb is not specified, use the default value. */
+ p2m_pages = rc ?
+ p2m_mem_mb << (20 - PAGE_SHIFT) :
+ domain_p2m_pages(mem, d->max_vcpus);
+
+ spin_lock(&d->arch.paging.lock);
+ rc = p2m_set_allocation(d, p2m_pages, NULL);
+ spin_unlock(&d->arch.paging.lock);
+ if ( rc != 0 )
+ return rc;
+
+ printk("*** LOADING DOMU cpus=%u memory=%#"PRIx64"KB ***\n",
+ d->max_vcpus, mem);
+
+ rc = dt_property_read_string(node, "xen,enhanced", &dom0less_enhanced);
+ if ( rc == -EILSEQ ||
+ rc == -ENODATA ||
+ (rc == 0 && !strcmp(dom0less_enhanced, "enabled")) )
+ {
+ if ( hardware_domain )
+ kinfo.dom0less_feature = DOM0LESS_ENHANCED;
+ else
+ panic("At the moment, Xenstore support requires dom0 to be present\n");
+ }
+ else if ( rc == 0 && !strcmp(dom0less_enhanced, "no-xenstore") )
+ kinfo.dom0less_feature = DOM0LESS_ENHANCED_NO_XS;
+
+ if ( vcpu_create(d, 0) == NULL )
+ return -ENOMEM;
+
+ d->max_pages = ((paddr_t)mem * SZ_1K) >> PAGE_SHIFT;
+
+ kinfo.d = d;
+
+ rc = kernel_probe(&kinfo, node);
+ if ( rc < 0 )
+ return rc;
+
+ set_domain_type(d, &kinfo);
+
+ if ( !dt_find_property(node, "xen,static-mem", NULL) )
+ allocate_memory(d, &kinfo);
+ else if ( !is_domain_direct_mapped(d) )
+ allocate_static_memory(d, &kinfo, node);
+ else
+ assign_static_memory_11(d, &kinfo, node);
+
+ rc = process_shm(d, &kinfo, node);
+ if ( rc < 0 )
+ return rc;
+
+ rc = init_vuart(d, &kinfo, node);
+ if ( rc < 0 )
+ return rc;
+
+ rc = prepare_dtb_domU(d, &kinfo);
+ if ( rc < 0 )
+ return rc;
+
+ rc = construct_domain(d, &kinfo);
+ if ( rc < 0 )
+ return rc;
+
+ if ( kinfo.dom0less_feature & DOM0LESS_XENSTORE )
+ {
+ ASSERT(hardware_domain);
+ rc = alloc_xenstore_evtchn(d);
+ if ( rc < 0 )
+ return rc;
+#ifdef CONFIG_HVM
+ d->arch.hvm.params[HVM_PARAM_STORE_PFN] = ~0ULL;
+#endif
+ }
+
+ return rc;
+}
diff --git a/xen/include/asm-generic/dom0less-build.h b/xen/include/asm-generic/dom0less-build.h
index a6985bc20a..3e4af9dcce 100644
--- a/xen/include/asm-generic/dom0less-build.h
+++ b/xen/include/asm-generic/dom0less-build.h
@@ -8,6 +8,9 @@
#include <public/domctl.h>
+struct kernel_info;
+struct dt_device_node;
+
void create_domUs(void);
bool is_dom0less_mode(void);
@@ -18,6 +21,17 @@ void arch_create_domus(struct dt_device_node *node,
struct xen_domctl_createdomain *d_cfg,
unsigned int flags);
+int init_vuart(struct domain *d, struct kernel_info *kinfo,
+ const struct dt_device_node *node);
+
+int make_intc_domU_node(struct kernel_info *kinfo);
+int make_arch_nodes(struct kernel_info *kinfo);
+
+void set_domain_type(struct domain *d, struct kernel_info *kinfo);
+
+int init_intc_phandle(struct kernel_info *kinfo, const char *name,
+ const int node_next, const void *pfdt);
+
#else /* !CONFIG_DOM0LESS_BOOT */
static inline void create_domUs(void) {}
--
2.47.1
^ permalink raw reply related [flat|nested] 20+ messages in thread