|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [xen master] xen/riscv: create APLIC DT node for guest domains
commit 3ecc6da8d633d393d1e07b1c5971560ad62dd405
Author: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
AuthorDate: Wed Sep 9 17:07:33 2026 +0200
Commit: Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Mon Sep 21 10:09:06 2026 +0200
xen/riscv: create APLIC DT node for guest domains
Guests require a Device Tree description of the interrupt controller
topology. Add support for creating an APLIC node when building the
guest DT.
Provide stub for imsic_make_dt_node() it will be introduced properly
in follow-up patch.
The value chosen for GUEST_APLIC_S_BASE is based on QEMU one.
DT-building functions are marked __init because domain creation happens at
boot time, before the init sections are freed. In a typical deployment
libxl creates the interrupt controller node in userspace and hands the
complete FDT to Xen, so these functions are only called during early
domain construction.
Co-developed-by: Romain Caritey <Romain.Caritey@xxxxxxxxxxxxx>
Signed-off-by: Oleksii Kurochko <oleksii.kurochko@xxxxxxxxx>
Acked-by: Jan Beulich <jbeulich@xxxxxxxx>
---
xen/arch/riscv/aplic-priv.h | 13 ++++++
xen/arch/riscv/aplic.c | 2 +
xen/arch/riscv/include/asm/aplic.h | 8 ++++
xen/arch/riscv/include/asm/guest-layout.h | 6 +++
xen/arch/riscv/vaplic.c | 77 +++++++++++++++++++++++++++++++
5 files changed, 106 insertions(+)
diff --git a/xen/arch/riscv/aplic-priv.h b/xen/arch/riscv/aplic-priv.h
index 85e0d028d1..35100d3a64 100644
--- a/xen/arch/riscv/aplic-priv.h
+++ b/xen/arch/riscv/aplic-priv.h
@@ -34,4 +34,17 @@ struct aplic_priv {
const struct imsic_config *imsic_cfg;
};
+/*
+ * Value is inspired by what QEMU is using for riscv,num-sources property for
+ * APLIC node.
+ */
+#define GUEST_APLIC_MAX_SOURCES 96U
+
+/*
+ * Specifies the number of interrupt sources supported by guest APLIC domain.
+ * Could be limited by host interrupt controller and is identical for every
+ * domain for now.
+ */
+extern unsigned int guest_aplic_num_sources;
+
#endif /* ASM_RISCV_APLIC_PRIV_H */
diff --git a/xen/arch/riscv/aplic.c b/xen/arch/riscv/aplic.c
index d08401db46..c2d7183e18 100644
--- a/xen/arch/riscv/aplic.c
+++ b/xen/arch/riscv/aplic.c
@@ -92,6 +92,8 @@ static int __init cf_check aplic_init(void)
panic("%s: failed to get number of interrupt sources\n",
node->full_name);
+ guest_aplic_num_sources = min(GUEST_APLIC_MAX_SOURCES,
aplic_info.num_irqs);
+
if ( aplic_info.num_irqs > ARRAY_SIZE(aplic.regs->sourcecfg) )
aplic_info.num_irqs = ARRAY_SIZE(aplic.regs->sourcecfg);
diff --git a/xen/arch/riscv/include/asm/aplic.h
b/xen/arch/riscv/include/asm/aplic.h
index 5a7fcb6ec4..07318aaac2 100644
--- a/xen/arch/riscv/include/asm/aplic.h
+++ b/xen/arch/riscv/include/asm/aplic.h
@@ -34,6 +34,14 @@
#define APLIC_TARGET_HART_IDX_SHIFT 18
+#define APLIC_IDC_SIZE 32
+
+#define APLIC_MIN_SIZE 0x4000
+#define APLIC_SIZE_ALIGN(x) ROUNDUP(x, APLIC_MIN_SIZE)
+
+#define APLIC_SIZE(nr_cpus) (APLIC_MIN_SIZE + \
+ APLIC_SIZE_ALIGN(APLIC_IDC_SIZE * (nr_cpus)))
+
struct aplic_regs {
uint32_t domaincfg; /* 0x0000 */
uint32_t sourcecfg[1023]; /* 0x0004 */
diff --git a/xen/arch/riscv/include/asm/guest-layout.h
b/xen/arch/riscv/include/asm/guest-layout.h
index 5e566450bd..90603f06bb 100644
--- a/xen/arch/riscv/include/asm/guest-layout.h
+++ b/xen/arch/riscv/include/asm/guest-layout.h
@@ -3,6 +3,12 @@
#include <public/xen.h>
+/*
+ * Base address of the guest's supervisor-mode APLIC. The value is the address
+ * typically used for APLIC by QEMU.
+ */
+#define GUEST_APLIC_S_BASE _UL(0xd000000)
+
/*
* Base address of the guest's supervisor-mode IMSIC. The value is the address
* typically used for IMSIC by QEMU.
diff --git a/xen/arch/riscv/vaplic.c b/xen/arch/riscv/vaplic.c
index c9f188b989..a529a5b1dc 100644
--- a/xen/arch/riscv/vaplic.c
+++ b/xen/arch/riscv/vaplic.c
@@ -9,6 +9,8 @@
*/
#include <xen/errno.h>
+#include <xen/fdt-kernel.h>
+#include <xen/libfdt/libfdt.h>
#include <xen/sched.h>
#include <xen/xvmalloc.h>
@@ -19,6 +21,80 @@
#include "aplic-priv.h"
+unsigned int __ro_after_init guest_aplic_num_sources;
+
+#define VAPLIC_COMPATIBLE "riscv,aplic"
+
+#define FDT_VAPLIC_INT_CELLS 2
+
+static int __init cf_check vaplic_make_domu_dt_node(struct kernel_info *kinfo)
+{
+ struct domain *d = kinfo->bd.d;
+ int res;
+ void *fdt = kinfo->fdt;
+ unsigned int msi_parent_phandle;
+ char vaplic_name[32];
+ unsigned int aplic_size = APLIC_SIZE(d->max_vcpus);
+ const __be32 reg[] = {
+ cpu_to_be32(GUEST_APLIC_S_BASE >> 32),
+ cpu_to_be32(GUEST_APLIC_S_BASE),
+ cpu_to_be32(0),
+ cpu_to_be32(aplic_size),
+ };
+
+ BUILD_BUG_ON(APLIC_SIZE(MAX_VIRT_CPUS) > UINT_MAX);
+
+ res = snprintf(vaplic_name, ARRAY_SIZE(vaplic_name), "/soc/aplic@%lx",
+ GUEST_APLIC_S_BASE);
+ if ( res >= sizeof(vaplic_name) )
+ {
+ dprintk(XENLOG_DEBUG, "vaplic name is truncated\n");
+ return -ENOBUFS;
+ }
+
+ res = vimsic_make_domu_dt_node(kinfo, &msi_parent_phandle);
+ if ( res )
+ return res;
+
+ res = fdt_begin_node(fdt, vaplic_name);
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "#interrupt-cells", FDT_VAPLIC_INT_CELLS);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "reg", reg, sizeof(reg));
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "riscv,num-sources", guest_aplic_num_sources);
+ if ( res )
+ return res;
+
+ res = fdt_property(fdt, "interrupt-controller", NULL, 0);
+ if ( res )
+ return res;
+
+ res = fdt_property_string(fdt, "compatible", VAPLIC_COMPATIBLE);
+ if ( res )
+ return res;
+
+ res = fdt_property_cell(fdt, "msi-parent", msi_parent_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 struct vintc_init_ops __initconstrel init_ops = {
+ .make_domu_dt_node = vaplic_make_domu_dt_node,
+};
+
static const struct vintc_ops vintc_ops = {
.vcpu_init = vcpu_imsic_init,
.vcpu_deinit = vcpu_imsic_deinit,
@@ -33,6 +109,7 @@ int domain_vaplic_init(struct domain *d)
d->arch.vintc = &vaplic->vintc;
d->arch.vintc->ops = &vintc_ops;
+ d->arch.vintc->init_ops = &init_ops;
vaplic->regs.domaincfg = APLIC_DOMAINCFG_RO;
--
generated by git-patchbot for /home/xen/git/xen.git#master
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |