|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH v2 17/26] xen/riscv: generate IMSIC DT node for guest domains
Guests using the IMSIC interrupt controller require a corresponding
Device Tree description.
Add support for generating an IMSIC node when building the guest DT.
This allows guests to discover and use the IMSIC interrupt controller.
Co-developed-by: Romain Caritey <Romain.Caritey@xxxxxxxxxxxxx>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
---
Changes in v2:
- s/imsic_make_reg_property/guest_imsic_make_reg_property.
- s/imsic_set_interrupt_extended_prop/guest_imsic_set_interrupt_extended_prop.
- Use initalizer for regs[] array in imsic_make_reg_property().
- Move buf[] insde the for() loop.
- Correct check of returned phandle.
- Drop local variable len.
- /s/XVFREE/xvfree in imsic_set_interrupt_extended_prop().
- Drop initializer for local variable data.
- s/uint32_t/unsinged int for pos and cpu in
imsic_set_interrupt_extended_prop().
- Drop next_phandle as it is now in common code.
- Introduce vcpu_imsic_deinit.
- Refactor vimsic_make_domu_dt_node() to avoid usage of host IMSIC dt node.
---
xen/arch/riscv/imsic.c | 127 +++++++++++++++++++++-
xen/arch/riscv/include/asm/guest-layout.h | 2 +
2 files changed, 128 insertions(+), 1 deletion(-)
diff --git a/xen/arch/riscv/imsic.c b/xen/arch/riscv/imsic.c
index ceea6778d9dc..19cbacdf96e1 100644
--- a/xen/arch/riscv/imsic.c
+++ b/xen/arch/riscv/imsic.c
@@ -13,9 +13,12 @@
#include <xen/const.h>
#include <xen/cpumask.h>
#include <xen/device_tree.h>
+#include <xen/domain.h>
#include <xen/errno.h>
+#include <xen/fdt-domain-build.h>
#include <xen/fdt-kernel.h>
#include <xen/init.h>
+#include <xen/libfdt/libfdt.h>
#include <xen/macros.h>
#include <xen/sched.h>
#include <xen/smp.h>
@@ -35,6 +38,11 @@ static struct imsic_config imsic_cfg = {
.lock = SPIN_LOCK_UNLOCKED,
};
+static unsigned int __ro_after_init guest_num_msis;
+
+#define GUEST_IMSIC_COMPATIBLE "riscv,imsics"
+#define GUEST_IMSIC_NUM_MSIS 255
+
#define IMSIC_DISABLE_EIDELIVERY 0
#define IMSIC_ENABLE_EIDELIVERY 1
#define IMSIC_DISABLE_EITHRESHOLD 1
@@ -291,6 +299,11 @@ static int imsic_parse_node(const struct dt_device_node
*node,
return -ENOENT;
}
+ if ( dt_property_read_u32(node, "riscv,num-guest-ids", &tmp) )
+ guest_num_msis = tmp;
+ else
+ guest_num_msis = imsic_cfg.nr_ids;
+
if ( (imsic_cfg.nr_ids < IMSIC_MIN_ID) ||
(imsic_cfg.nr_ids > IMSIC_MAX_ID) )
{
@@ -524,8 +537,120 @@ int __init imsic_init(const struct dt_device_node *node)
return rc;
}
+static int __init guest_imsic_make_reg_property(struct domain *d, void *fdt)
+{
+ paddr_t base_addr = GUEST_IMSIC_S_BASE;
+ __be32 regs[4] = {
+ cpu_to_be32(base_addr >> 32),
+ cpu_to_be32(base_addr),
+ cpu_to_be32((IMSIC_MMIO_PAGE_SZ * d->max_vcpus) >> 32),
+ cpu_to_be32(IMSIC_MMIO_PAGE_SZ * d->max_vcpus),
+ };
+
+ return fdt_property(fdt, "reg", regs, sizeof(regs));
+}
+
+static int __init guest_imsic_set_interrupt_extended_prop(struct domain *d,
+ void *fdt)
+{
+ unsigned int cpu, pos = 0;
+ uint32_t phandle;
+ uint32_t *irq_ext;
+ int res;
+
+ irq_ext = xvzalloc_array(uint32_t, d->max_vcpus * 2);
+ if ( !irq_ext )
+ return -ENOMEM;
+
+ for ( cpu = 0; cpu < d->max_vcpus; cpu++ )
+ {
+ char buf[64];
+
+ snprintf(buf, sizeof(buf), "/cpus/cpu@%u/interrupt-controller", cpu);
+ phandle = fdt_get_phandle(fdt, fdt_path_offset(fdt, buf));
+
+ if ( !phandle )
+ {
+ res = -ENODEV;
+ goto out;
+ }
+
+ irq_ext[pos++] = cpu_to_be32(phandle);
+ irq_ext[pos++] = cpu_to_be32(IRQ_S_EXT);
+ }
+
+ res = fdt_property(fdt, "interrupts-extended", irq_ext,
+ d->max_vcpus * 2 * sizeof(*irq_ext));
+
+ out:
+ xvfree(irq_ext);
+
+ return res;
+}
+
int __init vimsic_make_domu_dt_node(struct kernel_info *kinfo,
unsigned int *phandle)
{
- return -EOPNOTSUPP;
+ int res;
+ void *fdt = kinfo->fdt;
+ char vimsic_name[128];
+ unsigned int vimsic_phandle;
+ unsigned int num_msis = min(GUEST_IMSIC_NUM_MSIS + 0U, guest_num_msis);
+
+ res = snprintf(vimsic_name, sizeof(vimsic_name), "/soc/imsic@%x",
+ GUEST_IMSIC_S_BASE);
+ if ( res >= sizeof(vimsic_name) )
+ {
+ dprintk(XENLOG_DEBUG, "vimsic name is truncated\n");
+ return -ENOBUFS;
+ }
+
+ res = fdt_begin_node(fdt, vimsic_name);
+ if ( res )
+ return res;
+
+ res = fdt_property_string(fdt, "compatible", GUEST_IMSIC_COMPATIBLE);
+ if ( res )
+ return res;
+
+ res = guest_imsic_make_reg_property(kinfo->bd.d, fdt);
+ if ( res )
+ return res;
+
+ res = guest_imsic_set_interrupt_extended_prop(kinfo->bd.d, fdt);
+ if ( res )
+ return res;
+
+ res = fdt_property_u32(fdt, "riscv,num-ids", num_msis);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "msi-controller", NULL, 0);
+ if ( res )
+ return res;
+
+ res = fdt_property_u32(fdt, "#msi-cells", 0);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+ if ( res )
+ return res;
+
+ res = fdt_property_u32(fdt, "#interrupt-cells", 0);
+ if ( res )
+ return res;
+
+ vimsic_phandle = alloc_phandle(kinfo);
+ if ( !vimsic_phandle )
+ return -EOVERFLOW;
+
+ res = fdt_property_cell(fdt, "phandle", vimsic_phandle);
+ if ( res )
+ return res;
+
+ if ( phandle )
+ *phandle = vimsic_phandle;
+
+ return fdt_end_node(fdt);
}
diff --git a/xen/arch/riscv/include/asm/guest-layout.h
b/xen/arch/riscv/include/asm/guest-layout.h
index 9fc990c057f2..b16ec79c3786 100644
--- a/xen/arch/riscv/include/asm/guest-layout.h
+++ b/xen/arch/riscv/include/asm/guest-layout.h
@@ -5,6 +5,8 @@
#define GUEST_APLIC_S_BASE 0xd000000
+#define GUEST_IMSIC_S_BASE 0x28000000
+
#define GUEST_RAM_BANKS 2
/*
--
2.54.0
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |