Re: [PATCH] irqchip/riscv-imsic: Fix IPI target CPU mapping for sparse hartid topology
From: Anirudh Srinivasan
Date: Mon Jun 08 2026 - 11:43:03 EST
On Mon, Jun 08, 2026 at 07:59:35PM +0800, Wenhui Fan wrote:
> When the system has sparse hartid topology (e.g., only hart0 and hart8
> are online), the current IMSIC driver incorrectly calculates the MSI
> MMIO offset for each CPU. This causes IPIs targeting hart8 to be
> misdirected to hart1.
>
> The root cause is that in imsic_setup_state(), the MMIO offset is
> calculated using the parent interrupt index 'i' rather than the actual
> hartid:
> reloff = i * BIT(global->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
>
> This assumes a contiguous hartid space, which is not guaranteed in all
> systems. When only hart0 and hart8 are online, the driver receives
> nr_parent_irqs=2, with i=0 for hart0 and i=1 for hart8.
>
> Using i=1 for hart8 results in using the wrong offset which is intended
> for hart1, and causes the MSI configured for hart8 to incorrectly access
> hart1's MSI page.
>
> Fix this by using the actual hartid for offset calculation:
> reloff = hartid * BIT(global->guest_index_bits) * IMSIC_MMIO_PAGE_SZ;
The IMSIC binding [1] says that multiple groups can be used if the IMSIC
files for different groups of harts aren't located contiguously in MMIO
space. I believe that this approach must be used here, rather than
patching the kernel like this. The same quirk exists with OpenSBI
(you'll need a patch similar to yours). So rather than patching both
linux and OpenSBI, you can try this solution below.
You'd have to change your IMSIC node in the DT from something like this
/* Assuming per HART IMSIC file size is 0x1000*/
interrupt-controller@28000000 {
compatible = "riscv,imsics";
reg = <0x28000000 0x9000>;
};
to something like this
interrupt-controller@28000000 {
compatible = "riscv,imsics";
reg = <0x28000000 0x1000>, <0x28008000 0x1000>;
};
and the existing implementation in the kernel (and opensbi) should work.
[1] https://elixir.bootlin.com/linux/v7.0/source/Documentation/devicetree/bindings/interrupt-controller/riscv,imsics.yaml#L28
>
> Fixes: 21a8f8a0eb35 ("irqchip: Add RISC-V incoming MSI controller early driver")
> Signed-off-by: Wenhui Fan <fanwenhui@xxxxxxxxxxx>
> ---
> drivers/irqchip/irq-riscv-imsic-state.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
> index e3ed874d8..5f737ec36 100644
> --- a/drivers/irqchip/irq-riscv-imsic-state.c
> +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> @@ -894,7 +894,7 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
>
> /* Find MMIO location of MSI page */
> index = nr_mmios;
> - reloff = i * BIT(global->guest_index_bits) *
> + reloff = hartid * BIT(global->guest_index_bits) *
> IMSIC_MMIO_PAGE_SZ;
> for (j = 0; nr_mmios; j++) {
> if (reloff < resource_size(&mmios[j])) {
> --
> 2.43.0
>
>
> _______________________________________________
> linux-riscv mailing list
> linux-riscv@xxxxxxxxxxxxxxxxxxx
> http://lists.infradead.org/mailman/listinfo/linux-riscv