[PATCH v1 11/27] xen/riscv: create APLIC DT node for guest domains

Oleksii Kurochko posted 27 patches 4 weeks ago
[PATCH v1 11/27] xen/riscv: create APLIC DT node for guest domains
Posted by Oleksii Kurochko 4 weeks ago
Guests require a Device Tree description of the interrupt controller
topology. Add support for creating an APLIC node when building the
guest DT.

The node is derived from the host DT and linked to the guest IMSIC
via the msi-parent property, allowing guests to discover and use the
APLIC interrupt controller.

Co-developed-by: Romain Caritey <Romain.Caritey@microchip.com>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@gmail.com>
---
 xen/arch/riscv/aplic.c | 82 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 82 insertions(+)

diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c
index 739e8dab3498..e139946a05a0 100644
--- a/xen/arch/riscv/aplic.c
+++ b/xen/arch/riscv/aplic.c
@@ -12,8 +12,10 @@
 #include <xen/const.h>
 #include <xen/device_tree.h>
 #include <xen/errno.h>
+#include <xen/fdt-kernel.h>
 #include <xen/init.h>
 #include <xen/irq.h>
+#include <xen/libfdt/libfdt.h>
 #include <xen/mm.h>
 #include <xen/sections.h>
 #include <xen/spinlock.h>
@@ -295,6 +297,85 @@ static void cf_check aplic_set_irq_type(struct irq_desc *desc,
     spin_unlock(&aplic.lock);
 }
 
+static int __init cf_check aplic_make_dom_dt_node(
+                                    const struct kernel_info *kinfo,
+                                    const struct dt_device_node *aplic_node)
+{
+    uint32_t len;
+    const __be32 *regs;
+    const void *data = NULL;
+    int res = 0;
+    void *fdt = kinfo->fdt;
+
+    res = imsic_make_dt_node(kinfo);
+    if ( res )
+        return res;
+
+    res = fdt_begin_node(fdt, aplic_node->full_name);
+    if (res)
+        return res;
+
+    data = dt_get_property(aplic_node, "#interrupt-cells", &len);
+    if ( !data )
+    {
+        printk("%s: Can't find '#interrupt-cells' property\n",
+               aplic_node->full_name);
+        return -FDT_ERR_XEN(ENOENT);
+    }
+
+    res = fdt_property(fdt, "#interrupt-cells", data, len);
+    if ( res )
+        return res;
+
+    regs = dt_get_property(aplic_node, "reg", &len);
+    if ( !regs )
+    {
+        printk("%s: Can't find 'reg' property\n", aplic_node->full_name);
+        return -FDT_ERR_XEN(ENOENT);
+    }
+
+    res = fdt_property(fdt, "reg", regs, len);
+    if ( res )
+        return res;
+
+    data = dt_get_property(aplic_node, "riscv,num-sources", &len);
+    if ( !data )
+    {
+        printk("%s: Can't find 'riscv,num-sources' property\n",
+                aplic_node->full_name);
+        return -FDT_ERR_XEN(ENOENT);
+    }
+
+    res = fdt_property(fdt, "riscv,num-sources", data, len);
+    if ( res )
+        return res;
+
+    res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+    if ( res )
+        return res;
+
+    data = dt_get_property(aplic_node, "compatible", &len);
+    if ( !data )
+    {
+        printk("%s: Can't find 'compatible' property\n", aplic_node->full_name);
+        return -FDT_ERR_XEN(ENOENT);
+    }
+
+    res = fdt_property(fdt, "compatible", data, len);
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "msi-parent", aplic.imsic_cfg->phandle);
+    if ( res )
+        return res;
+
+    res = fdt_property_cell(fdt, "phandle", kinfo->phandle_intc);
+    if ( res )
+        return res;
+
+    return fdt_end_node(fdt);
+}
+
 static const hw_irq_controller aplic_xen_irq_type = {
     .typename     = "aplic",
     .startup      = aplic_irq_startup,
@@ -310,6 +391,7 @@ static const struct intc_hw_operations aplic_ops = {
     .host_irq_type       = &aplic_xen_irq_type,
     .handle_interrupt    = aplic_handle_interrupt,
     .set_irq_type        = aplic_set_irq_type,
+    .make_dom_dt_node    = aplic_make_dom_dt_node,
 };
 
 static int cf_check aplic_irq_xlate(const uint32_t *intspec,
-- 
2.53.0
Re: [PATCH v1 11/27] xen/riscv: create APLIC DT node for guest domains
Posted by Jan Beulich 6 days, 11 hours ago
On 10.03.2026 18:08, Oleksii Kurochko wrote:
> @@ -295,6 +297,85 @@ static void cf_check aplic_set_irq_type(struct irq_desc *desc,
>      spin_unlock(&aplic.lock);
>  }
>  
> +static int __init cf_check aplic_make_dom_dt_node(
> +                                    const struct kernel_info *kinfo,
> +                                    const struct dt_device_node *aplic_node)

Nit: Entirely bogus indentation.

> +{
> +    uint32_t len;
> +    const __be32 *regs;
> +    const void *data = NULL;

Again, why the initializer?

> +    int res = 0;
> +    void *fdt = kinfo->fdt;
> +
> +    res = imsic_make_dt_node(kinfo);
> +    if ( res )
> +        return res;
> +
> +    res = fdt_begin_node(fdt, aplic_node->full_name);
> +    if (res)

Nit: Style.

> +        return res;
> +
> +    data = dt_get_property(aplic_node, "#interrupt-cells", &len);
> +    if ( !data )
> +    {
> +        printk("%s: Can't find '#interrupt-cells' property\n",
> +               aplic_node->full_name);
> +        return -FDT_ERR_XEN(ENOENT);
> +    }

Again, pull this up to be first in the function?

> +    res = fdt_property(fdt, "#interrupt-cells", data, len);
> +    if ( res )
> +        return res;

So host properties are again directly handed through to the guest?
Shouldn't the number of interrupts (aiui that's the "number of cells"
here) a guest gets be independent from the host it runs one?

> +    regs = dt_get_property(aplic_node, "reg", &len);
> +    if ( !regs )
> +    {
> +        printk("%s: Can't find 'reg' property\n", aplic_node->full_name);
> +        return -FDT_ERR_XEN(ENOENT);
> +    }
> +
> +    res = fdt_property(fdt, "reg", regs, len);
> +    if ( res )
> +        return res;
> +
> +    data = dt_get_property(aplic_node, "riscv,num-sources", &len);
> +    if ( !data )
> +    {
> +        printk("%s: Can't find 'riscv,num-sources' property\n",
> +                aplic_node->full_name);
> +        return -FDT_ERR_XEN(ENOENT);
> +    }
> +
> +    res = fdt_property(fdt, "riscv,num-sources", data, len);
> +    if ( res )
> +        return res;

Or maybe this is the number of interrupts?

Jan