[PATCH v7 3/5] irqchip/riscv-imsic: Add MSI address list
Andrew Jones
andrew.jones at linux.dev
Thu Oct 22 08:46:01 PDT 2026
From: Andrew Jones <andrew.jones at oss.qualcomm.com>
Upcoming RISC-V IOMMU interrupt remapping needs to map every possible
host IMSIC target into one contiguous MSI IOVA range. MSI message
composition then uses the target CPU's position within that range.
Build an IMSIC physical address array indexed by logical CPU.
Require every possible CPU to have an initialized IMSIC page before
publishing the array. This preserves physical address zero as a valid
target and guarantees the array has num_possible_cpus() entries.
The array size and each target's index can therefore be derived
directly, without storing duplicate count or per-CPU index metadata.
Signed-off-by: Andrew Jones <andrew.jones at oss.qualcomm.com>
Signed-off-by: Andrew Jones <andrew.jones at linux.dev>
Tested-by: Fangyu Yu <fangyu.yu at linux.alibaba.com>
Acked-by: Thomas Gleixner <tglx at kernel.org>
Reviewed-by: Nutty Liu <nutty.liu at hotmail.com>
Reviewed-by: Anup Patel <anup at brainfault.org>
Acked-by: Anup Patel <anup at brainfault.org>
---
drivers/irqchip/irq-riscv-imsic-state.c | 32 +++++++++++++++++++++++++
drivers/irqchip/irq-riscv-imsic-state.h | 3 +++
2 files changed, 35 insertions(+)
diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
index b8d1bbbf42f7..eb525c324982 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.c
+++ b/drivers/irqchip/irq-riscv-imsic-state.c
@@ -687,6 +687,31 @@ static int __init imsic_get_mmio_resource(struct fwnode_handle *fwnode,
return of_address_to_resource(to_of_node(fwnode), index, res);
}
+static int __init imsic_init_msi_pa_list(void)
+{
+ struct imsic_global_config *global = &imsic->global;
+ phys_addr_t *msi_pa_list;
+ unsigned int cpu;
+
+ msi_pa_list = kcalloc(num_possible_cpus(), sizeof(*msi_pa_list), GFP_KERNEL);
+ if (!msi_pa_list)
+ return -ENOMEM;
+
+ for_each_possible_cpu(cpu) {
+ struct imsic_local_config *local = per_cpu_ptr(global->local, cpu);
+
+ if (!local->msi_va) {
+ kfree(msi_pa_list);
+ return -ENODEV;
+ }
+
+ msi_pa_list[cpu] = local->msi_pa;
+ }
+
+ imsic->msi_pa_list = msi_pa_list;
+ return 0;
+}
+
static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
struct imsic_global_config *global,
u32 *nr_parent_irqs,
@@ -937,6 +962,12 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
goto out_local_cleanup;
}
+ rc = imsic_init_msi_pa_list();
+ if (rc) {
+ pr_err("%pfwP: failed to initialize MSI address list\n", fwnode);
+ goto out_local_cleanup;
+ }
+
/* Initialize matrix allocator */
rc = imsic_matrix_init();
if (rc) {
@@ -962,6 +993,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
out_free_local:
free_percpu(imsic->global.local);
out_free_priv:
+ kfree(imsic->msi_pa_list);
kfree(imsic);
imsic = NULL;
return rc;
diff --git a/drivers/irqchip/irq-riscv-imsic-state.h b/drivers/irqchip/irq-riscv-imsic-state.h
index c42ee180b305..e51c61dcced3 100644
--- a/drivers/irqchip/irq-riscv-imsic-state.h
+++ b/drivers/irqchip/irq-riscv-imsic-state.h
@@ -50,6 +50,9 @@ struct imsic_priv {
/* Global configuration common for all HARTs */
struct imsic_global_config global;
+ /* MSI target physical addresses indexed by logical CPU for IOMMU mapping */
+ phys_addr_t *msi_pa_list;
+
/* Per-CPU state */
struct imsic_local_priv __percpu *lpriv;
--
2.56.0
More information about the linux-riscv
mailing list