[PATCH 3/3] irqchip/riscv-imsic: Remove global nr_guest_files after KVM AIA per-HART conversion

Guo Ren guoren at kernel.org
Thu Apr 23 02:07:39 PDT 2026


On Thu, Apr 23, 2026 at 12:20 PM Inochi Amaoto <inochiama at gmail.com> wrote:
>
> On Wed, Apr 22, 2026 at 11:09:30AM +0800, Guo Ren wrote:
> > Hi all,
> >
> > This patch simply removed `nr_guest_files`, which is suboptimal. For
> > v2, I will keep `nr_guest_files` inside `struct imsic_local_config`
> > (per-HART) and compute the effective HGEI count in
> > `kvm_riscv_aia_enable()` as:
> >
> > min(hgctrl->nr_hgei, lc->nr_guest_files)
> >
> > This provides a more accurate and robust per-HART configuration.
> >
> > Here are the updated two patches for your review:
> >
> >     irqchip/riscv-imsic: Move nr_guest_files to per-HART local config
> >
> >     With the recent KVM AIA per-HART HGEI conversion, the global
> >     nr_guest_files is no longer appropriate. Different HARTs in
> >     heterogeneous SoCs may have different numbers of guest interrupt
> >     files.
> >
> >     Move `nr_guest_files` from `struct imsic_global_config` to
> >     `struct imsic_local_config`, and compute it per-CPU in
> >     imsic_setup_state() based on the actual MMIO guest file region size.
> >
> >     Update the related comment to reflect that KVM now uses the
> >     per-HART value.
> >
> >     This eliminates the last global assumption about guest files and
> >     completes the per-HART conversion series for RISC-V AIA/IMSIC.
> >
> >     Signed-off-by: Guo Ren (Alibaba DAMO Academy) <guoren at kernel.org>
> >
> > diff --git a/drivers/irqchip/irq-riscv-imsic-state.c
> > b/drivers/irqchip/irq-riscv-imsic-state.c
> > index e3ed874d89e7..3d455ef43298 100644
> > --- a/drivers/irqchip/irq-riscv-imsic-state.c
> > +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> > @@ -784,7 +784,7 @@ static int __init imsic_parse_fwnode(struct
> > fwnode_handle *fwnode,
> >
> >  int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
> >  {
> > -       u32 i, j, index, nr_parent_irqs, nr_mmios, nr_guest_files,
> > nr_handlers = 0;
> > +       u32 i, j, index, nr_parent_irqs, nr_mmios, nr_handlers = 0;
> >         struct imsic_global_config *global;
> >         struct imsic_local_config *local;
> >         void __iomem **mmios_va = NULL;
> > @@ -878,7 +878,6 @@ int __init imsic_setup_state(struct fwnode_handle
> > *fwnode, void *opaque)
> >         }
> >
> >         /* Configure handlers for target CPUs */
> > -       global->nr_guest_files = BIT(global->guest_index_bits) - 1;
> >         for (i = 0; i < nr_parent_irqs; i++) {
> >                 rc = imsic_get_parent_hartid(fwnode, i, &hartid);
> >                 if (rc) {
> > @@ -920,13 +919,13 @@ int __init imsic_setup_state(struct
> > fwnode_handle *fwnode, void *opaque)
> >                 local->msi_va = mmios_va[index] + reloff;
> >
> >                 /*
> > -                * KVM uses global->nr_guest_files to determine the
> > available guest
> > +                * KVM uses local->nr_guest_files to determine the
> > available guest
> >                  * interrupt files on each CPU. Take the minimum number of guest
> >                  * interrupt files across all CPUs to avoid KVM
> > incorrectly allocating
> >                  * an unexisted or unmapped guest interrupt file on some CPUs.
> >                  */
>
> > -               nr_guest_files = (resource_size(&mmios[index]) -
> > reloff) / IMSIC_MMIO_PAGE_SZ - 1;
> > -               global->nr_guest_files = min(global->nr_guest_files,
> > nr_guest_files);
> > +               local->nr_guest_files =
> > +                       (resource_size(&mmios[index]) - reloff) /
> > IMSIC_MMIO_PAGE_SZ - 1;
> >
>
> The min is still required, otherwise the local->nr_guest_files can be
> bigger than BIT(global->guest_index_bits) - 1, which is the max number
> of the guest interrupt files that a hart can have. This condition is
> true if the IMSIC group has more than one harts.
Yes, you are correct. Thanks for pointing it out.


>
> Regards,
> Inochi
>
> >                 nr_handlers++;
> >         }
> > diff --git a/include/linux/irqchip/riscv-imsic.h
> > b/include/linux/irqchip/riscv-imsic.h
> > index 4b348836de7a..13e8bd7ff4b4 100644
> > --- a/include/linux/irqchip/riscv-imsic.h
> > +++ b/include/linux/irqchip/riscv-imsic.h
> > @@ -40,6 +40,9 @@
> >  struct imsic_local_config {
> >         phys_addr_t                             msi_pa;
> >         void __iomem                            *msi_va;
> > +
> > +       /* Number of guest interrupt files per core */
> > +       u32                                     nr_guest_files;
> >  };
> >
> >  struct imsic_global_config {
> > @@ -68,9 +71,6 @@ struct imsic_global_config {
> >         /* Number of guest interrupt identities */
> >         u32                                     nr_guest_ids;
> >
> > -       /* Number of guest interrupt files per core */
> > -       u32                                     nr_guest_files;
> > -
> >         /* Per-CPU IMSIC addresses */
> >         struct imsic_local_config __percpu      *local;
> >  };
> >
> > ------------------------
> > The other one:
> >
> >     RISC-V: KVM: AIA: Use per-HART IMSIC guest files to compute final HGEI count
> >
> >     Now that `nr_guest_files` has been moved to `struct imsic_local_config`
> >     and is computed per-HART, KVM must respect the actual number of guest
> >     interrupt files available on each HART when setting up HGEI.
> >
> >     In `kvm_riscv_aia_enable()`:
> >
> >      - Retrieve the per-CPU IMSIC local config
> >      - Take `min(hgctrl->nr_hgei, lc->nr_guest_files)` as the final usable
> >        HGEI count for this HART
> >      - Use the result to initialize `free_bitmap`
> >
> >     This ensures correct HGEI allocation on heterogeneous RISC-V SoCs
> >     where different cores may have different IMSIC guest file counts, and
> >     completes the per-HART conversion series.
> >
> >     Signed-off-by: Guo Ren (Alibaba DAMO Academy) <guoren at kernel.org>
> >
> > diff --git a/arch/riscv/kvm/aia.c b/arch/riscv/kvm/aia.c
> > index 70ff1d25dd99..a5f4b7fe1dce 100644
> > --- a/arch/riscv/kvm/aia.c
> > +++ b/arch/riscv/kvm/aia.c
> > @@ -534,6 +534,9 @@ static void aia_hgei_exit(void)
> >  void kvm_riscv_aia_enable(void)
> >  {
> >         struct aia_hgei_control *hgctrl;
> > +       const struct imsic_global_config *gc;
> > +       const struct imsic_local_config *lc;
> > +       unsigned int nr_hgei;
> >
> >         if (!kvm_riscv_aia_available())
> >                 return;
> > @@ -547,8 +550,13 @@ void kvm_riscv_aia_enable(void)
> >         if (hgctrl->nr_hgei)
> >                 hgctrl->nr_hgei--;
> >
> > -       if (hgctrl->nr_hgei) {
> > -               hgctrl->free_bitmap = BIT(hgctrl->nr_hgei + 1) - 1;
> > +       gc = imsic_get_global_config();
> > +       lc = (gc) ? this_cpu_ptr(gc->local) : NULL;
> > +       if (lc)
> > +               nr_hgei = min(hgctrl->nr_hgei, lc->nr_guest_files);
> > +
> > +       if (nr_hgei) {
> > +               hgctrl->free_bitmap = BIT(nr_hgei + 1) - 1;
> >                 hgctrl->free_bitmap &= ~BIT(0);
> >         } else {
> >                 hgctrl->free_bitmap = 0;
> >
> >
> > On Tue, Apr 21, 2026 at 10:55 PM <guoren at kernel.org> wrote:
> > >
> > > From: "Guo Ren (Alibaba DAMO Academy)" <guoren at kernel.org>
> > >
> > > With the recent KVM AIA changes, HGEI line management is now fully
> > > per-CPU (via struct aia_hgei_control::nr_hgei) and the global
> > > kvm_riscv_aia_nr_hgei has been replaced by a simple enabled flag.
> > > The IMSIC driver no longer needs to compute and enforce a global
> > > minimum number of guest interrupt files across all HARTs.
> > >
> > > Remove:
> > >  - `u32 nr_guest_files` from `struct imsic_global_config`
> > >  - the initial `BIT(global->guest_index_bits) - 1` assignment
> > >  - the entire per-CPU MMIO-based min() calculation and its comment
> > >    (which was specifically there to protect old KVM)
> > >
> > > The per-HART guest file count is already handled locally in
> > > `imsic_local_config` during the parent IRQ loop, so this global
> > > field was redundant.
> > >
> > > This completes the cleanup series, eliminates the last global
> > > assumption about guest files, and improves support for heterogeneous
> > > (big.LITTLE / multi-vendor) RISC-V platforms.
> > >
> > > Signed-off-by: Guo Ren (Alibaba DAMO Academy) <guoren at kernel.org>
> > > ---
> > >  drivers/irqchip/irq-riscv-imsic-state.c | 12 +-----------
> > >  include/linux/irqchip/riscv-imsic.h     |  3 ---
> > >  2 files changed, 1 insertion(+), 14 deletions(-)
> > >
> > > diff --git a/drivers/irqchip/irq-riscv-imsic-state.c b/drivers/irqchip/irq-riscv-imsic-state.c
> > > index e3ed874d89e7..fef27247a34f 100644
> > > --- a/drivers/irqchip/irq-riscv-imsic-state.c
> > > +++ b/drivers/irqchip/irq-riscv-imsic-state.c
> > > @@ -784,7 +784,7 @@ static int __init imsic_parse_fwnode(struct fwnode_handle *fwnode,
> > >
> > >  int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
> > >  {
> > > -       u32 i, j, index, nr_parent_irqs, nr_mmios, nr_guest_files, nr_handlers = 0;
> > > +       u32 i, j, index, nr_parent_irqs, nr_mmios, nr_handlers = 0;
> > >         struct imsic_global_config *global;
> > >         struct imsic_local_config *local;
> > >         void __iomem **mmios_va = NULL;
> > > @@ -878,7 +878,6 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
> > >         }
> > >
> > >         /* Configure handlers for target CPUs */
> > > -       global->nr_guest_files = BIT(global->guest_index_bits) - 1;
> > >         for (i = 0; i < nr_parent_irqs; i++) {
> > >                 rc = imsic_get_parent_hartid(fwnode, i, &hartid);
> > >                 if (rc) {
> > > @@ -919,15 +918,6 @@ int __init imsic_setup_state(struct fwnode_handle *fwnode, void *opaque)
> > >                 local->msi_pa = mmios[index].start + reloff;
> > >                 local->msi_va = mmios_va[index] + reloff;
> > >
> > > -               /*
> > > -                * KVM uses global->nr_guest_files to determine the available guest
> > > -                * interrupt files on each CPU. Take the minimum number of guest
> > > -                * interrupt files across all CPUs to avoid KVM incorrectly allocating
> > > -                * an unexisted or unmapped guest interrupt file on some CPUs.
> > > -                */
> > > -               nr_guest_files = (resource_size(&mmios[index]) - reloff) / IMSIC_MMIO_PAGE_SZ - 1;
> > > -               global->nr_guest_files = min(global->nr_guest_files, nr_guest_files);
> > > -
> > >                 nr_handlers++;
> > >         }
> > >
> > > diff --git a/include/linux/irqchip/riscv-imsic.h b/include/linux/irqchip/riscv-imsic.h
> > > index 4b348836de7a..7f3ff5c5ea53 100644
> > > --- a/include/linux/irqchip/riscv-imsic.h
> > > +++ b/include/linux/irqchip/riscv-imsic.h
> > > @@ -68,9 +68,6 @@ struct imsic_global_config {
> > >         /* Number of guest interrupt identities */
> > >         u32                                     nr_guest_ids;
> > >
> > > -       /* Number of guest interrupt files per core */
> > > -       u32                                     nr_guest_files;
> > > -
> > >         /* Per-CPU IMSIC addresses */
> > >         struct imsic_local_config __percpu      *local;
> > >  };
> > > --
> > > 2.40.1
> > >
> >
> >
> > --
> > Best Regards
> >  Guo Ren
> >
> > --
> > kvm-riscv mailing list
> > kvm-riscv at lists.infradead.org
> > http://lists.infradead.org/mailman/listinfo/kvm-riscv



-- 
Best Regards
 Guo Ren



More information about the linux-riscv mailing list