[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v3 23/23] xen/riscv: add initial dom0less infrastructure support





On 6/23/26 10:36 AM, Jan Beulich wrote:
On 17.06.2026 13:17, Oleksii Kurochko wrote:
Enable dom0less support for RISC-V by selecting HAS_DOM0LESS and
providing the minimal architecture hooks required by the common
dom0less infrastructure.

Add stub implementations for architecture-specific helpers used when
building domains from the device tree. These currently perform no
additional work but allow the generic dom0less code to build and run
on RISC-V.

Introduce max_init_domid as a runtime variable rather than a constant
so that it can be updated during dom0less domain creation.

Provide missing helpers and definitions required by the domain
construction code, including domain bitness helpers and the
p2m_set_allocation() prototype.

Additionally define the guest magic memory region in the public
RISC-V interface. GUEST_MAGIC_BASE is placed at 0x79000000 to avoid
overlapping with the QEMU RISC-V virt machine address space.

No qemu comes into play so far (and likely such also isn't planned).
Then why would such an overlap be problematic? Plus as before, the
constraints on such arbitrarily chosen numbers want putting down in
a code comment next to the respective #define-s.

You're right QEMU isn't used directly, so my wording was misleading.
I used QEMU's RISC-V virt machine memory layout [1] as a reference when
laying out the guest's physical address map, but the value itself is
arbitrary. The only real constraint is that the GUEST_MAGIC_SIZE region
must not overlap guest RAM or the emulated device regions; since the RAM
bank sizes are known, it could equally be placed in a hole after a RAM
bank rather than below GUEST_RAM0_BASE. I'll drop the QEMU mention from
the commit message and document this constraint in a comment next to the
#define-s instead.

/*
 * The guest magic region holds Xen-reserved pages mapped into the guest's
 * physical address space (shared info, grant table, etc.). The only real
 * constraint is that the GUEST_MAGIC_SIZE-byte region must not overlap
 * guest RAM (the GUEST_RAMx banks) or the emulated device regions defined
 * above; the exact base is otherwise arbitrary. Here it is placed in the
 * unused gap below GUEST_RAM0_BASE (0x80000000), but a hole after a RAM
 * bank would work equally well.
 */
#define GUEST_MAGIC_BASE  _ULL(0x79000000)
#define GUEST_MAGIC_SIZE  _ULL(0x01000000)

[1] https://elixir.bootlin.com/qemu/v11.0.1/source/hw/riscv/virt.c#L82


--- a/xen/arch/riscv/domain-build.c
+++ b/xen/arch/riscv/domain-build.c
@@ -156,9 +156,22 @@ int __init make_cpus_node(const struct domain *d, struct 
kernel_info *kinfo)
      return fdt_end_node(fdt);
  }
+int __init construct_hwdom(struct kernel_info *kinfo,
+                           const struct dt_device_node *node)
+{
+    return -EOPNOTSUPP;
+}
+
  int __init make_timer_node(const struct kernel_info *kinfo)
  {
      /* There is no need for timer node for RISC-V. */
return 0;
  }
+
+int __init make_hypervisor_node(struct domain *d,
+                                const struct kernel_info *kinfo,
+                                int addrcells, int sizecells)
+{
+    return -EOPNOTSUPP;
+}

In the description you say "to build and run". How come "run" is actually
true when these two new stubs return an error? For construct_hwdom() this
may be explained by you not aiming at supporting Dom0 / hwdom (but that
then still is a limitation to mention, perhaps in a TODO comment), but
with DOM0LESS_ENHANCED_NO_XS set make_hypervisor_node() failing is going
to break DomU building as well, afaics.

You're right. I've dropped "run" from the description, since some other stuff should be introduced to make dom0less guest domain to be runnable.

Regarding make_hypervisor_node(): it's true that returning an error breaks DomU building too, not only Dom0. As you mentioned it's acceptable for the moment only because no RISC-V domain currently sets DOM0LESS_ENHANCED_NO_XS, so the failing path is never taken in practice. I'll add a TODO comment to make this limitation explicit:

    /*
* TODO: Generating the hypervisor node isn't implemented yet. Returning
     * an error here breaks building of any domain (DomU included) whose
* dom0less_feature has DOM0LESS_ENHANCED_NO_XS set. This is harmless for
     * now because Dom0/hwdom construction isn't supported on RISC-V yet
* either, and no RISC-V DomU sets that flag, so this path is never taken.
     * It must be implemented before DOM0LESS_ENHANCED_NO_XS is used.
     */


--- a/xen/arch/riscv/include/asm/setup.h
+++ b/xen/arch/riscv/include/asm/setup.h
@@ -5,7 +5,9 @@
#include <xen/types.h> -#define max_init_domid (0)
+#include <public/xen.h>
+
+extern domid_t max_init_domid;

Shouldn't this be generalized, seeing that dom0less code requires it this
way on every arch? Same ...

--- a/xen/arch/riscv/setup.c
+++ b/xen/arch/riscv/setup.c
@@ -33,6 +33,8 @@
  #include <asm/traps.h>
  #include <asm/vsbi.h>
+domid_t __initdata max_init_domid;

... for the placement of this then, obviously.

I tried here to introduce less changes.

Also considering that max_init_domid is used in console.c code after init is freed it seems like it is incorrect to use __initdata here. So what Arm is using better suites (__read_mostly).

If you think it would be better to do just now instead of later then I would suggest something like this:diff --git a/xen/arch/arm/include/asm/setup.h b/xen/arch/arm/include/asm/setup.h
index 0adfa4993a8f..2af780512540 100644
--- a/xen/arch/arm/include/asm/setup.h
+++ b/xen/arch/arm/include/asm/setup.h
@@ -25,8 +25,6 @@ struct map_range_data
     struct rangeset *irq_ranges;
 };

-extern domid_t max_init_domid;
-
 void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);

 size_t estimate_efi_size(unsigned int mem_nr_banks);
diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
index 6310a47d68b6..86532d0a35b6 100644
--- a/xen/arch/arm/setup.c
+++ b/xen/arch/arm/setup.c
@@ -62,8 +62,6 @@ struct cpuinfo_arm __read_mostly system_cpuinfo;
 bool __read_mostly acpi_disabled;
 #endif

-domid_t __read_mostly max_init_domid;
-
 static __used void noreturn init_done(void)
 {
     /* Must be done past setting system_state. */
diff --git a/xen/arch/ppc/include/asm/setup.h b/xen/arch/ppc/include/asm/setup.h
index e4f64879b68c..956fa6985adb 100644
--- a/xen/arch/ppc/include/asm/setup.h
+++ b/xen/arch/ppc/include/asm/setup.h
@@ -1,6 +1,4 @@
 #ifndef __ASM_PPC_SETUP_H__
 #define __ASM_PPC_SETUP_H__

-#define max_init_domid (0)
-
 #endif /* __ASM_PPC_SETUP_H__ */
diff --git a/xen/arch/riscv/include/asm/setup.h b/xen/arch/riscv/include/asm/setup.h
index 678b65ac1e54..73ce2f293348 100644
--- a/xen/arch/riscv/include/asm/setup.h
+++ b/xen/arch/riscv/include/asm/setup.h
@@ -5,10 +5,6 @@

 #include <xen/types.h>

-#include <public/xen.h>
-
-extern domid_t max_init_domid;
-
 void setup_mm(void);

 void copy_from_paddr(void *dst, paddr_t paddr, unsigned long len);
diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c
index 05708039ab54..e30e4624f882 100644
--- a/xen/arch/riscv/setup.c
+++ b/xen/arch/riscv/setup.c
@@ -39,8 +39,6 @@
 #include <asm/traps.h>
 #include <asm/vsbi.h>

-domid_t __initdata max_init_domid;
-
 /* Xen stack for bringing up the first CPU. */
 unsigned char __initdata cpu0_boot_stack[STACK_SIZE]
     __aligned(STACK_SIZE);
diff --git a/xen/arch/x86/include/asm/setup.h b/xen/arch/x86/include/asm/setup.h
index b01e83a8ed9f..5925c5f39cff 100644
--- a/xen/arch/x86/include/asm/setup.h
+++ b/xen/arch/x86/include/asm/setup.h
@@ -68,6 +68,4 @@ extern bool opt_dom0_verbose;
 extern bool opt_dom0_cpuid_faulting;
 extern bool opt_dom0_msr_relaxed;

-#define max_init_domid (0)
-
 #endif
diff --git a/xen/common/domid.c b/xen/common/domid.c
index b0258e477c1a..cc5f468a30de 100644
--- a/xen/common/domid.c
+++ b/xen/common/domid.c
@@ -9,6 +9,15 @@
  */

 #include <xen/domain.h>
+#include <xen/dom0less-build.h>
+
+#ifdef CONFIG_DOM0LESS_BOOT
+/*
+ * Highest domain ID assigned to a boot-time (dom0less) domain. Read at runtime
+ * by the console serial-input switcher, so it must not be __initdata.
+ */
+domid_t __read_mostly max_init_domid;
+#endif

 static DEFINE_SPINLOCK(domid_lock);
 static DECLARE_BITMAP(domid_bitmap, DOMID_FIRST_RESERVED);
diff --git a/xen/drivers/char/console.c b/xen/drivers/char/console.c
index bcd6d261491b..4c09f4c7a984 100644
--- a/xen/drivers/char/console.c
+++ b/xen/drivers/char/console.c
@@ -31,6 +31,7 @@
 #include <xen/warning.h>
 #include <xen/pv_console.h>
 #include <asm/setup.h>
+#include <xen/dom0less-build.h>
 #include <xen/sections.h>
 #include <xen/consoled.h>

diff --git a/xen/include/xen/dom0less-build.h b/xen/include/xen/dom0less-build.h
index 4118dec76c0a..8d4da16d1f0a 100644
--- a/xen/include/xen/dom0less-build.h
+++ b/xen/include/xen/dom0less-build.h
@@ -5,6 +5,8 @@

 #include <xen/stdbool.h>

+#include <public/xen.h>
+
 struct domain;

 #ifdef CONFIG_DOM0LESS_BOOT
@@ -13,6 +15,9 @@ struct boot_domain;
 struct dt_device_node;
 struct kernel_info;

+/* Highest domain ID assigned to a boot-time (dom0less) domain. */
+extern domid_t max_init_domid;
+
 /*
  * List of possible features for dom0less domUs
  *
@@ -72,6 +77,8 @@ static inline bool is_dom0less_mode(void)
 }
 static inline void set_xs_domain(struct domain *d) {}

+#define max_init_domid 0
+
 #endif /* CONFIG_DOM0LESS_BOOT */

 #endif /* __ASM_GENERIC_DOM0LESS_BUILD_H__ */

Thanks.

~ Oleksii



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.