[PATCH v1 27/27] xen/riscv: add initial dom0less infrastructure support

Oleksii Kurochko posted 27 patches 4 weeks ago
[PATCH v1 27/27] xen/riscv: add initial dom0less infrastructure support
Posted by Oleksii Kurochko 4 weeks ago
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.

Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
Open questions:
 - Move declaration of p2m_set_allocation() to xen/fdt-domain-build.h or
   xen/dom0less-build.h as it is used in common code of Dom0less and
   there is not too much sense in declaration of it for each arch which
   supports Dom0less. It could be ifdef-ed in common header as, at the
   momemnt, it is used only for Dom0less.
 - Shouldn't declaration/defintion of max_init_domid move to common code
   instead of having it for each architecture separately? If yes, then what
   would be the best place.
---
---
 xen/arch/riscv/Kconfig              |  1 +
 xen/arch/riscv/dom0less-build.c     | 18 ++++++++++++++++++
 xen/arch/riscv/domain-build.c       | 13 +++++++++++++
 xen/arch/riscv/include/asm/domain.h |  8 ++++++++
 xen/arch/riscv/include/asm/p2m.h    |  2 ++
 xen/arch/riscv/include/asm/setup.h  |  4 +++-
 xen/arch/riscv/setup.c              |  2 ++
 xen/include/public/arch-riscv.h     |  3 +++
 8 files changed, 50 insertions(+), 1 deletion(-)

diff --git a/xen/arch/riscv/Kconfig b/xen/arch/riscv/Kconfig
index 091510380949..abd579aa6a54 100644
--- a/xen/arch/riscv/Kconfig
+++ b/xen/arch/riscv/Kconfig
@@ -6,6 +6,7 @@ config RISCV
 	select GENERIC_BUG_FRAME
 	select GENERIC_UART_INIT
 	select HAS_DEVICE_TREE_DISCOVERY
+	select HAS_DOM0LESS
 	select HAS_PMAP
 	select HAS_UBSAN
 	select HAS_VMAP
diff --git a/xen/arch/riscv/dom0less-build.c b/xen/arch/riscv/dom0less-build.c
index 43c8bdc52300..865311ec7037 100644
--- a/xen/arch/riscv/dom0less-build.c
+++ b/xen/arch/riscv/dom0less-build.c
@@ -43,3 +43,21 @@ int __init make_arch_nodes(struct kernel_info *kinfo)
 
     return 0;
 }
+
+void __init set_domain_type(struct domain *d, struct kernel_info *kinfo)
+{
+    /* Nothing to do */
+}
+
+int __init arch_parse_dom0less_node(struct dt_device_node *node,
+                                    struct boot_domain *bd)
+{
+    /* Nothing to do */
+    return 0;
+}
+
+int __init arch_handle_passthrough_prop(struct kernel_info *kinfo,
+                                        struct dt_device_node *node)
+{
+    return 0;
+}
diff --git a/xen/arch/riscv/domain-build.c b/xen/arch/riscv/domain-build.c
index ae26faed09ed..20735f41d646 100644
--- a/xen/arch/riscv/domain-build.c
+++ b/xen/arch/riscv/domain-build.c
@@ -154,9 +154,22 @@ int __init make_cpus_node(const struct domain *d, void *fdt)
     return res;
 }
 
+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;
+}
diff --git a/xen/arch/riscv/include/asm/domain.h b/xen/arch/riscv/include/asm/domain.h
index 21a3e6876f36..a8342ca7c5bf 100644
--- a/xen/arch/riscv/include/asm/domain.h
+++ b/xen/arch/riscv/include/asm/domain.h
@@ -20,6 +20,14 @@ struct hvm_domain
     uint64_t              params[HVM_NR_PARAMS];
 };
 
+#ifdef CONFIG_RISCV_64
+#define is_32bit_domain(d) (0)
+#define is_64bit_domain(d) (1)
+#else
+#define is_32bit_domain(d) (1)
+#define is_64bit_domain(d) (0)
+#endif
+
 struct arch_vcpu_io {
 };
 
diff --git a/xen/arch/riscv/include/asm/p2m.h b/xen/arch/riscv/include/asm/p2m.h
index 4441c0400b83..d97c8d13ef6b 100644
--- a/xen/arch/riscv/include/asm/p2m.h
+++ b/xen/arch/riscv/include/asm/p2m.h
@@ -259,6 +259,8 @@ void p2m_ctxt_switch_from(struct vcpu *p);
 void p2m_ctxt_switch_to(struct vcpu *n);
 void p2m_handle_vmenter(void);
 
+int p2m_set_allocation(struct domain *d, unsigned long pages, bool *preempted);
+
 #endif /* ASM__RISCV__P2M_H */
 
 /*
diff --git a/xen/arch/riscv/include/asm/setup.h b/xen/arch/riscv/include/asm/setup.h
index 1c23043f409f..2e3f8931d01b 100644
--- a/xen/arch/riscv/include/asm/setup.h
+++ b/xen/arch/riscv/include/asm/setup.h
@@ -5,11 +5,13 @@
 
 #include <xen/types.h>
 
+#include <public/xen.h>
+
 struct domain;
 struct dt_device_node;
 struct rangeset;
 
-#define max_init_domid (0)
+extern domid_t max_init_domid;
 
 void setup_mm(void);
 
diff --git a/xen/arch/riscv/setup.c b/xen/arch/riscv/setup.c
index 5bc34e41fe55..513f94777f38 100644
--- a/xen/arch/riscv/setup.c
+++ b/xen/arch/riscv/setup.c
@@ -32,6 +32,8 @@
 #include <asm/traps.h>
 #include <asm/vsbi.h>
 
+domid_t max_init_domid = 0;
+
 /* Xen stack for bringing up the first CPU. */
 unsigned char __initdata cpu0_boot_stack[STACK_SIZE]
     __aligned(STACK_SIZE);
diff --git a/xen/include/public/arch-riscv.h b/xen/include/public/arch-riscv.h
index 91cee3096041..3c0c786c57ac 100644
--- a/xen/include/public/arch-riscv.h
+++ b/xen/include/public/arch-riscv.h
@@ -58,6 +58,9 @@ typedef uint64_t xen_ulong_t;
 #define GUEST_RAM_BANK_BASES   { GUEST_RAM0_BASE }
 #define GUEST_RAM_BANK_SIZES   { GUEST_RAM0_SIZE }
 
+#define GUEST_MAGIC_BASE  xen_mk_ullong(0x39000000)
+#define GUEST_MAGIC_SIZE  xen_mk_ullong(0x01000000)
+
 struct vcpu_guest_context {
 };
 typedef struct vcpu_guest_context vcpu_guest_context_t;
-- 
2.53.0
Re: [PATCH v1 27/27] xen/riscv: add initial dom0less infrastructure support
Posted by Jan Beulich 12 hours ago
On 10.03.2026 18:09, 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,

I'm wondering about the splitting among patches: There's half a dozen
(effectively stub) functions which are added here, and then there is
the single init_vuart() which was split out into the earlier patch.
What's the pattern behind this, i.e. why isn't init_vuart() also
being added here?

> including domain bitness helpers and the
> p2m_set_allocation() prototype.
> 
> Additionally define the guest magic memory region in the public
> RISC-V interface.
> 
> Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
> ---
> Open questions:
>  - Move declaration of p2m_set_allocation() to xen/fdt-domain-build.h or
>    xen/dom0less-build.h as it is used in common code of Dom0less and
>    there is not too much sense in declaration of it for each arch which
>    supports Dom0less. It could be ifdef-ed in common header as, at the
>    momemnt, it is used only for Dom0less.

Having a common declaration of p2m_set_allocation() is certainly a
sensible thing to do, but not in DT or dom0less headers. p2m-common.h
is, going from file names, the only plausible place for it to go.
Whether that (a) works and (b) makes sense are separate questions.

>  - Shouldn't declaration/defintion of max_init_domid move to common code
>    instead of having it for each architecture separately? If yes, then what
>    would be the best place.

What would you use to decide whether the declaration or #define is
needed? (Plausible headers to put it can surely be found: console.h,
domain.h, and perhaps more.)

> --- a/xen/arch/riscv/include/asm/domain.h
> +++ b/xen/arch/riscv/include/asm/domain.h
> @@ -20,6 +20,14 @@ struct hvm_domain
>      uint64_t              params[HVM_NR_PARAMS];
>  };
>  
> +#ifdef CONFIG_RISCV_64
> +#define is_32bit_domain(d) (0)
> +#define is_64bit_domain(d) (1)
> +#else
> +#define is_32bit_domain(d) (1)
> +#define is_64bit_domain(d) (0)
> +#endif

First, please use true/false. Then, while I agree with the RV32 part, 32-bit
guests surely will need to be an option on a 64-bit hypervisor. Imo you'd
better introduced a field in struct arch_domain to carry that information
(or to derive it from) right away. That wouldn't be set to non-zero for the
time being, i.e. that same constant-true/false would still result.

Otherwise I don't see why you use #ifdef; you could then have things
simpler as

#define is_32bit_domain(d) IS_ENABLED(CONFIG_RISCV_32)
#define is_64bit_domain(d) IS_ENABLED(CONFIG_RISCV_64)

(but I specifically don't recommend going this route).

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

The initializer isn't of much use, is it? Instead add __read_mostly, like
Arm has it?

> --- a/xen/include/public/arch-riscv.h
> +++ b/xen/include/public/arch-riscv.h
> @@ -58,6 +58,9 @@ typedef uint64_t xen_ulong_t;
>  #define GUEST_RAM_BANK_BASES   { GUEST_RAM0_BASE }
>  #define GUEST_RAM_BANK_SIZES   { GUEST_RAM0_SIZE }
>  
> +#define GUEST_MAGIC_BASE  xen_mk_ullong(0x39000000)
> +#define GUEST_MAGIC_SIZE  xen_mk_ullong(0x01000000)

What is this, and why does it need putting in the public interface? Plus
how come the numbers are exactly the same as what Arm uses?

Jan