Re: [PATCH v4 02/21] iommufd: Add iommufd_sw_map_msi()

Andrew Jones <[email protected]>
Newsgroups org.infradead.lists.linux-riscv,dev.linux.lists.iommu,org.kernel.vger.linux-kernel
Message-ID <gr2h3ktgacozyo7rdggkxsg5mbdtzcnimaawd24c37hnf2tun3@hqivsenaq5wd>
Hi Jason,

On Thu, Aug 20, 2026 at 07:09:08PM -0300, Jason Gunthorpe wrote:
> On Thu, Aug 20, 2026 at 11:41:31PM +0200, Andrew Jones wrote:
> > Add a descriptor-free counterpart to iommufd_sw_msi(). The existing
> > function is tied to a struct msi_desc and stores the result in the
> > descriptor. This variant returns the IOVA directly so callers can
> > pre-map MSI targets before any descriptor has been allocated.
> 
> I haven't grasped why it is like this?
> 
> The cover letter says:
> 
>   ARM can map a fixed doorbell PA per ITS and cache its IOVA on the
>   descriptor because affinity changes only hardware routing, not the
>   composed address. An IMSIC target PA changes with affinity, and MSI
>   composition may run in atomic context, so mapping the selected target on
>   demand is not an option. This series pre-maps the supervisor IMSIC page
>   for every possible CPU into a domain-local PA-to-IOVA table when remapped
>   IRQs are first allocated, allowing composition to select the target with
>   an O(1) lookup. If iommufd replaces a paging domain while IRQs remain
>   allocated, the incoming domain's table is rebuilt before it is attached.
> 
> There are a few confusiong things with this statement:
>  1) Okay the IMSIC PA changes dynamically but since it can be
>     premapped the PAs required is fixed and known. ARM doesn't change
>     the PA dynamically?

ARM's PA is fixed. On affinity change it uses MOVI to instruct the ITS to
change the routing.

>  2) Why do you say mapping on demand is not possible? ARM's
>     iommu_dma_prepare_msi() is not called in an atomic context and
>     does do the iommu mapping.

By "on demand" I mean after IRQ allocation, when selecting a new MSI
target may occur in atomic context. Mapping then is not possible. Like ARM,
this riscv implementation performs all mappings at alloc-irqs time.

> 
> What I rather expected was for riscv to have a PA window that is very
> big and not just one page, eg adjust iommu_dma_prepare_msi() so you
> can pass in the entire PA space that you need for the affinity
> changes. Maybe this is a list of phys_addr_t ?

That's more or less what this series does. There's no big PA window
because the IMSIC PAs aren't generally contiguous. iommu_dma_map_msi()
factors the mapping operation out of iommu_dma_prepare_msi() and returns
each IOVA directly. A batched list API would be possible, but it would
only move the loop.

> 
> Then keep with the ARM flow where everything happens at the same
> times as today. Instead of just mapping one page you map the entire
> list.

The goal of this approach was to match ARM's flow as much as possible
despite the quite different architecture. Here's a table showing how
they match up now.

.------------------------------------------------------------------------------.
| IRQ lifecycle phase | ARM IR / ITS              | RISC-V IR / IMSIC          |
|---------------------|---------------------------|----------------------------|
| IRQ allocation      | ITS allocates an event/   | IMSIC allocates a vector   |
|                     | LPI. The MSI target PA is | on a CPU. The MSI target   |
|                     | the fixed GITS_TRANSLATER | PA is that CPU's IMSIC     |
|                     | address.                  | page.                      |
|                     |                           |                            |
|                     | iommu_dma_prepare_msi()   | iommu_dma_map_msi()        |
|                     | is called from the IR     | is called from the IR      |
|                     | irqdomain .alloc          | irqdomain .alloc           |
|                     | callback. It calls        | callback. It's called once |
|                     | iommu_dma_map_msi() once  | for each possible IMSIC    |
|                     | for the fixed ITS PA.     | PA.                        |
|---------------------|---------------------------|----------------------------|
| MSI mapping setup   | iommu_dma_map_msi()       | iommu_dma_map_msi()        |
|                     | dispatches to             | dispatches to              |
|                     | iommu_dma_sw_map_msi()    | iommu_dma_sw_map_msi()     |
|                     | or iommufd_sw_map_msi().  | or iommufd_sw_map_msi().   |
|                     | One IOVA is cached in the | One IOVA per IMSIC PA is   |
|                     | MSI descriptor.           | cached in the IOMMU domain |
|                     |                           | table.                     |
|---------------------|---------------------------|----------------------------|
| Initial composition | Compose the fixed target  | Compose the selected CPU's |
|                     | IOVA plus the event ID.   | IMSIC PA and local ID,     |
|                     |                           | then substitute its IOVA.  |
|---------------------|---------------------------|----------------------------|
| Affinity change     | Send MOVI to change ITS-  | Allocate a vector on the   |
|                     | internal routing. The     | new CPU. The device's MSI  |
|                     | device MSI address does   | address changes to the new |
|                     | not change.               | CPU's IMSIC IOVA.          |
|                     |                           |                            |
|                     |                           | The parent IMSIC irqdomain |
|                     |                           | irq_set_affinity() selects |
|                     |                           | the new vector and         |
|                     |                           | recomposes from the top of |
|                     |                           | the hierarchy. The IR      |
|                     |                           | irqdomain's                |
|                     |                           | irq_compose_msi_msg()      |
|                     |                           | translates the new IMSIC   |
|                     |                           | PA to its IOVA.            |
|---------------------|---------------------------|----------------------------|
| Message update      | No new device MSI message | Recompose and rewrite the  |
|                     | is required.              | device MSI message through |
|                     |                           | the IRQ hierarchy.         |
|---------------------|---------------------------|----------------------------|
| Composition context | No IOMMU mapping or       | Composition may occur in   |
|                     | lookup is required during | atomic context, so all     |
|                     | an affinity change.       | IMSIC PAs must already be  |
|                     |                           | mapped and lookup cannot   |
|                     |                           | sleep.                     |
|---------------------|---------------------------|----------------------------|
| Domain replacement  | iommufd_group_setup_msi() | iommufd_group_setup_msi()  |
|                     | installs the one required | installs all required MSI  |
|                     | MSI mapping before attach.| mappings before attach.    |
|                     | The descriptor's cached   | riscv_iommu_ir_attach_     |
|                     | IOVA stays valid.         | paging_domain() builds the |
|                     |                           | new domain's PA-to-IOVA    |
|                     |                           | lookup table.              |
|---------------------|---------------------------|----------------------------|
| Domain destruction  | The ITS MSI mapping is    | The IMSIC mappings and     |
|                     | released with the domain. | PA-to-IOVA table are       |
|                     |                           | released with the domain.  |
.------------------------------------------------------------------------------.

Hopefully that helps describe the design better.

Thanks,
drew

_______________________________________________
linux-riscv mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/linux-riscv
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.