Linux-mm Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Luigi Rizzo" <lrizzo@google.com>,
	"Luigi Rizzo" <rizzo.unipi@gmail.com>,
	"Joerg Roedel" <joro@8bytes.org>, "Will Deacon" <will@kernel.org>,
	"Robin Murphy" <robin.murphy@arm.com>,
	"Christoph Hellwig" <hch@lst.de>,
	"Marek Szyprowski" <m.szyprowski@samsung.com>,
	"Andrew Morton" <akpm@linux-foundation.org>,
	"Vlastimil Babka" <vbabka@kernel.org>,
	"David Hildenbrand" <david@kernel.org>,
	"Jens Axboe" <axboe@kernel.dk>,
	"David S . Miller" <davem@davemloft.net>,
	"Eric Dumazet" <edumazet@kernel.org>,
	"Jakub Kicinski" <kuba@kernel.org>,
	"Paolo Abeni" <pabeni@redhat.com>
Cc: "Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
	"Rafael J . Wysocki" <rafael@kernel.org>,
	"Danilo Krummrich" <dakr@kernel.org>,
	"Jonathan Corbet" <corbet@lwn.net>,
	"Matthew Wilcox" <willy@infradead.org>,
	"Lorenzo Stoakes" <ljs@kernel.org>,
	"Jesper Dangaard Brouer" <hawk@kernel.org>,
	"Ilias Apalodimas" <ilias.apalodimas@linaro.org>,
	"Willem de Bruijn" <willemb@google.com>,
	"Kuniyuki Iwashima" <kuniyu@google.com>,
	"Joshua Washington" <joshwash@google.com>,
	"Harshitha Ramamurthy" <hramamurthy@google.com>,
	"Alexander Lobakin" <aleksander.lobakin@intel.com>,
	linux-mm@kvack.org
Subject: Re: [RFC PATCH v2 07/25] iommu/dma: Release PISA domain mappings on domain teardown
Date: Tue, 10 Nov 2026 23:12:09 +0000	[thread overview]
Message-ID: <sashiko-outbox-207862@kernel.org> (raw)
In-Reply-To: <20261109182533.3594984-8-lrizzo@google.com>

Thank you for your contribution! Sashiko AI review found 4 potential
issues to consider:
- [Medium] iommu/dma: list and RCU corruption in pisa_domain_quiesce()
  on quarantine
- [Medium] iommu/dma: data race on meta->flags in pisa_quarantine_meta()
  and release
- [Medium] iommu/dma: build failure in pisa_domain_quiesce() due to
  static symbols
- [Medium] iommu/dma: missing struct pisa_meta declaration in
  pisa-priv.h stubs
--

commit 72b9f4d8d1b40452a8315c8a6e6bdaec17fbdb98
Author: Luigi Rizzo <lrizzo@google.com>

iommu/dma: Release PISA domain mappings on domain teardown

This commit adds pisa_domain_release() and pisa_domain_quiesce() to unmap
active PISA pages and release or quiesce domain mappings when an IOMMU
domain is torn down or its last DMA API user detaches, quarantining and
leaking any 2MB page whose iommu_unmap() fails.

> diff --git a/drivers/iommu/pisa-map.c b/drivers/iommu/pisa-map.c
> index 2e8d635dec34c..2ba977bb68734 100644
> --- a/drivers/iommu/pisa-map.c
> +++ b/drivers/iommu/pisa-map.c

[ ... ]

> +/* Report a short IOMMU unmap and mark @meta quarantined so it is never reused. */
> +static void pisa_quarantine_meta(struct pisa_meta *meta, struct iommu_domain *domain,
> +				 int idx, dma_addr_t iova, size_t unmapped)
> +{
> +	pr_err_ratelimited("pisa: unmap of IOVA %pad in domain %p (index %d) returned %zu, quarantining PISA page\n",
> +			   &iova, domain, idx, unmapped);
> +	WRITE_ONCE(meta->flags, meta->flags | PISA_QUARANTINED);
> +}

[ ... ]

> +static unsigned int pisa_unmap_domain_locked(struct pisa_meta *meta,
> +					     struct iommu_domain *domain,
> +					     int idx, dma_addr_t base,
> +					     struct iommu_iotlb_gather *gather)
> +{
> +	dma_addr_t iova = base + pisa_meta_win_offset(meta);
> +	size_t unmapped;
> +
> +	if (!test_and_clear_bit(idx, meta->domains_mapped))
> +		return 0;
> +
> +	unmapped = iommu_unmap_fast(domain, iova, PISA_SIZE, gather);
> +	if (unlikely(unmapped != PISA_SIZE))
> +		pisa_quarantine_meta(meta, domain, idx, iova, unmapped);
> +	return 1;
> +}

[Severity: Medium]
Can concurrent updates to meta->flags in pisa_quarantine_meta() and
pisa_release_page() clobber each other?

pisa_unmap_domain_locked() clears idx in meta->domains_mapped before
calling iommu_unmap_fast() and pisa_quarantine_meta(), so a concurrent
pisa_release_page() -> pisa_unmap_all() can see bit idx already cleared
and proceed to update meta->flags without synchronization:

CPU0                                  CPU1
pisa_domain_quiesce()                 pisa_release_page()
  pisa_unmap_domain_locked()
    test_and_clear_bit(idx, ...)
                                        pisa_unmap_all()
                                        flags = meta->flags
    iommu_unmap_fast() [short unmap]
    pisa_quarantine_meta()
      meta->flags |= PISA_QUARANTINED
                                        meta->flags = flags & ~PISA_ACTIVE
                                          <-- drops PISA_QUARANTINED

When PISA_QUARANTINED is lost, pisa_release_page_rcu() frees the IOVA slot
and returns the still-mapped 2MB page to the buddy allocator.  With the
opposite interleaving, pisa_quarantine_meta() restores PISA_ACTIVE on the
retired page.

> +/*
> + * Unmap all PISA leaf PTEs from a domain whose last DMA API user detached,
> + * keeping its window and domain index so mappings are re-installed on demand.
> + */
> +void pisa_domain_quiesce(struct iommu_domain *domain)
> +{
> +	struct iommu_iotlb_gather gather;
> +	struct pisa_window *win;
> +	unsigned int slot, done = 0;
> +	bool release = false;
> +	dma_addr_t base;
> +	int idx;
> +
> +	if (!static_branch_unlikely(&pisa_key))
> +		return;
> +	win = pisa_dma_window(domain);
> +	/* Pairs with smp_store_release() in pisa_window_assign(). */
> +	base = win ? smp_load_acquire(&win->base) : 0;
> +	if (!base)
> +		return;
> +	idx = win->domain_idx - PISA_IDX_FIRST;
> +
> +	iommu_iotlb_gather_init(&gather);
> +	/* Keep call_rcu()-freed pages from reaching the buddy allocator before IOTLB sync. */
> +	rcu_read_lock();
> +	for_each_set_bit(slot, pisa_slot_bitmap, pisa_nr_slots) {
> +		struct pisa_meta *meta = READ_ONCE(pisa_slot2meta[slot]);
> +		struct pisa_alloc *pa;
> +		unsigned long flags;
> +
> +		if (!meta || !test_bit(idx, meta->domains_mapped))
> +			continue;
> +		done += pisa_unmap_domain_locked(meta, domain, idx, base, &gather);
> +		if (likely(!(meta->flags & PISA_QUARANTINED)))
> +			continue;
> +		pa = READ_ONCE(meta->pa);
> +		if (!pa)
> +			continue;
> +		spin_lock_irqsave(&pa->lock, flags);
> +		if (meta->pa == pa) {
> +			if (meta->on_list == PISA_LIST_IDLE_CLEAN ||
> +			    meta->on_list == PISA_LIST_IDLE_DIRTY)
> +				pa->num_idle_pages--;
> +			release |= pisa_place_meta(meta);
> +		}
> +		spin_unlock_irqrestore(&pa->lock, flags);
> +	}
> +
> +	if (done)
> +		iommu_iotlb_sync(domain, &gather);
> +	rcu_read_unlock();
> +	if (release)
> +		pisa_schedule_reclaim();

[Severity: Medium]
Does pisa-map.o fail to build at this commit because PISA_LIST_IDLE_CLEAN,
PISA_LIST_IDLE_DIRTY, pisa_place_meta(), and pisa_schedule_reclaim() are
still static or local to drivers/iommu/pisa-alloc.c?

Those declarations are only moved to drivers/iommu/pisa-priv.h in a later
patch in the series, commit "block, mm, iommu/dma: Support PISA for disk
I/O and scrub migration", which breaks bisection when CONFIG_PISA and
CONFIG_IOMMU_DMA are enabled.

[Severity: Medium]
Can pisa_domain_quiesce() call pisa_place_meta() on an idle page that has
already been detached from pa for release, corrupting pisa_free_list or
meta->rcu?

When an idle page (avail == bpp) is detached onto pisa_free_list or
queued with call_rcu(), meta->pa remains non-NULL until
pisa_release_page_rcu() runs after the grace period, and its slot stays
set in pisa_slot_bitmap.  If pisa_domain_quiesce() sees PISA_QUARANTINED
on that page, meta->pa == pa is still true and pisa_place_meta() runs
llist_add(&meta->llnode, &pisa_free_list) on it:

CPU0                                  CPU1
pisa_reclaim_work_fn()                pisa_domain_quiesce()
  ...                                   rcu_read_lock()
  pisa_release_page(meta)
    call_rcu(&meta->rcu, ...)
                                        pisa_unmap_domain_locked()
                                          pisa_quarantine_meta()
                                        spin_lock_irqsave(&pa->lock, ...)
                                        if (meta->pa == pa)
                                          pisa_place_meta(meta)
                                            llist_add(&meta->llnode,
                                                      &pisa_free_list)
                                              <-- overwrites live meta->rcu

Because meta->llnode and meta->rcu share an anonymous union, adding
meta->llnode to pisa_free_list overwrites the active RCU head (or creates
a cycle in pisa_free_list if pisa_reclaim_work_fn() has not popped it
yet), and a second pisa_release_page() after meta->pa is cleared to NULL
hits the !meta->pa branch and frees the quarantined 2MB page to the buddy
allocator.

In addition, pisa_shrink_list() moves idle pages onto pisa_shrink_scan()'s
local release_list and decrements pa->num_idle_pages without setting
meta->on_list to PISA_LIST_NONE, so pisa_domain_quiesce() will also
decrement pa->num_idle_pages a second time and run list_del_init() on
meta->list while pisa_shrink_scan() walks release_list unlocked.

> diff --git a/drivers/iommu/pisa-priv.h b/drivers/iommu/pisa-priv.h
> index 3ef6e51402ceb..f97f69a13d1a9 100644
> --- a/drivers/iommu/pisa-priv.h
> +++ b/drivers/iommu/pisa-priv.h

[ ... ]

>  #define pisa_nr_slots 0U
>  static inline void pisa_slots_init(void) {}
>  static inline int pisa_slot_alloc(struct pisa_meta *meta) { return 0; }
>  static inline void pisa_slot_free(unsigned int slot) {}
> +static inline int pisa_unmap_all(struct pisa_meta *meta) { return 0; }

[Severity: Medium]
Does including pisa-priv.h in drivers/iommu/iommu.c trigger a
-Wvisibility warning on struct pisa_meta when CONFIG_PISA is disabled?

struct pisa_meta is only declared inside #ifdef CONFIG_PISA, so when
CONFIG_PISA=n the parameter lists of pisa_slot_alloc() and
pisa_unmap_all() declare a local struct pisa_meta type, failing the build
under CONFIG_WERROR=y.

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20261109182533.3594984-1-lrizzo@google.com?part=7


  reply	other threads:[~2026-11-10 23:12 UTC|newest]

Thread overview: 107+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-03 21:22 [RFC: DMA_PMD 00/22] DMA_PMD: PMD_SIZE-backed IO buffer pools Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 01/22] iommu/dma: introduce CONFIG_DMA_PMD and metadata table Luigi Rizzo
2026-10-03 21:44   ` Randy Dunlap
2026-10-04  9:14     ` Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 02/22] iommu/dma: add DMA_PMD pool lifecycle and page recycle hook Luigi Rizzo
2026-10-10  2:59   ` kernel test robot
2026-10-03 21:22 ` [RFC: DMA_PMD 03/22] mm: Add split_page_compound() Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 04/22] iommu/dma: add DMA_PMD pool block allocation Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 05/22] iommu/dma: Global cap and shrinker for DMA_PMD pool memory Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 06/22] iommu/dma: reserve a per-domain IOVA window for DMA_PMD pages Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 07/22] iommu/dma: release DMA_PMD domain mappings on domain teardown Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 08/22] iommu/dma: use per-domain IOVA window to map DMA_PMD memory Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 09/22] iommu/dma: Add DMA_PMD arena allocator Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 10/22] driver core: Add per-device dma_pmd_* sysfs attributes Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 11/22] dma-mapping: Use DMA_PMD arena for dma_alloc_attrs() Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 12/22] net/core: Use per-CPU DMA_PMD pools for skb_page_frag_refill() Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 13/22] net/core: Use DMA_PMD for page_pool memory Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 14/22] iommu/dma: Support decrypted and pinned DMA_PMD pages Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 15/22] iommu/dma: Add background page scrubber for DMA_PMD pools Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 16/22] iommu/dma: Add per-NUMA-node PMD page reservoir Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 17/22] net/gve: Use DMA_PMD memory for RX buffers Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 18/22] net/gve: Use DMA_PMD memory for tx header bounce buffers Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 19/22] net/mlx5e: " Luigi Rizzo
2026-10-14 17:22   ` Dragos Tatulea
2026-10-14 17:50     ` Dragos Tatulea
2026-10-14 18:28       ` Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 20/22] net/idpf: " Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 21/22] net/bnxt: " Luigi Rizzo
2026-10-03 21:22 ` [RFC: DMA_PMD 22/22] iommu/dma: Add DMA_PMD statistics and debugfs Luigi Rizzo
2026-10-11  9:02 ` [RFC: DMA_PMD 00/22] DMA_PMD: PMD_SIZE-backed IO buffer pools Pranjal Shrivastava
2026-10-12 13:51 ` David Hildenbrand (Arm)
2026-10-12 14:45   ` Luigi Rizzo
2026-10-12 19:43     ` David Hildenbrand (Arm)
2026-10-13 10:42       ` Robin Murphy
2026-10-14 10:47         ` David Hildenbrand (Arm)
2026-10-14 11:05           ` Luigi Rizzo
2026-10-17 17:11       ` Luigi Rizzo
2026-10-22 20:12         ` Jason Gunthorpe
2026-10-22 21:51           ` Luigi Rizzo
2026-10-23 14:01             ` Jason Gunthorpe
2026-10-23 14:30               ` Luigi Rizzo
2026-10-23 14:50                 ` Jason Gunthorpe
2026-10-23 15:12                   ` Luigi Rizzo
2026-10-23 17:27                   ` Jakub Kicinski
2026-10-23 20:22                     ` Luigi Rizzo
2026-11-03  8:09                   ` Christoph Hellwig
2026-11-03  9:13                     ` Luigi Rizzo
2026-11-03 15:10                     ` Jason Gunthorpe
2026-11-06 17:21                       ` Naman Gulati
2026-11-06 17:30                         ` Jason Gunthorpe
2026-11-06 18:00                           ` Naman Gulati
2026-11-06 18:07                             ` Jason Gunthorpe
2026-11-06 18:17                               ` Naman Gulati
2026-11-06 18:43                                 ` Jason Gunthorpe
2026-11-06 19:01                                   ` Luigi Rizzo
2026-11-06 19:11                                   ` Naman Gulati
2026-10-12 14:49   ` Mostafa Saleh
2026-10-12 15:02     ` Luigi Rizzo
2026-10-14 17:28 ` Dragos Tatulea
2026-10-14 18:14   ` Luigi Rizzo
2026-11-09 18:25 ` [RFC PATCH v2 00/25] PISA: Pre-mapped IOVA Superpage Allocator for DMA and CoCo Luigi Rizzo
2026-11-09 18:25 ` [RFC PATCH v2 01/25] iommu/dma: Introduce CONFIG_PISA and metadata table Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 02/25] iommu/dma: Add PISA allocator lifecycle and page recycle hook Luigi Rizzo
2026-11-09 18:25 ` [RFC PATCH v2 03/25] iommu/dma: Add per-NUMA-node PISA page reservoir Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 04/25] iommu/dma: Add PISA block allocation Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 05/25] iommu/dma: Add global cap and shrinker for PISA pages Luigi Rizzo
2026-11-09 18:25 ` [RFC PATCH v2 06/25] iommu/dma: Reserve a per-domain IOVA window " Luigi Rizzo
2026-11-09 18:25 ` [RFC PATCH v2 07/25] iommu/dma: Release PISA domain mappings on domain teardown Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot [this message]
2026-11-09 18:25 ` [RFC PATCH v2 08/25] iommu/dma: Use per-domain IOVA window to map PISA memory Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 09/25] driver core: Add per-device pisa_* sysfs attributes for PISA optin Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 10/25] iommu/dma: Use PISA for coherent DMA allocations Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 11/25] iommu/dma: Add per-CPU block caches to PISA allocators Luigi Rizzo
2026-11-10 23:12   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 12/25] net/core: Use per-node PISA allocators for skb_page_frag_refill() Luigi Rizzo
2026-11-10 23:50   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 13/25] net/core: Use PISA for page_pool memory Luigi Rizzo
2026-11-09 18:25 ` [RFC PATCH v2 14/25] iommu/dma: Support decrypted PISA pages Luigi Rizzo
2026-11-11  0:19   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 15/25] iommu/dma: Add background page scrubber for PISA allocators Luigi Rizzo
2026-11-11  0:37   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 16/25] mm/slub: Add SLAB_CACHE_PISA_RO for PISA-backed slab caches Luigi Rizzo
2026-11-11  1:03   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 17/25] net: Allocate small skb heads from PISA Luigi Rizzo
2026-11-11  1:33   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 18/25] iommu/dma: Migrate user pages into PISA for TX zerocopy Luigi Rizzo
2026-11-11  2:41   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 19/25] iommu/dma: Stop recycling old PISA pages when allocator waste is high Luigi Rizzo
2026-11-11  2:57   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 20/25] net/libeth: Use GFP_KERNEL when pre-filling RX rings Luigi Rizzo
2026-11-11  3:13   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 21/25] net/gve: " Luigi Rizzo
2026-11-11  3:22   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 22/25] net/gve: Use PISA memory for RX buffers Luigi Rizzo
2026-11-11  3:43   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 23/25] block, mm, iommu/dma: Support PISA for disk I/O and scrub migration Luigi Rizzo
2026-11-11  4:16   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 24/25] Documentation: Add PISA architecture documentation Luigi Rizzo
2026-11-11  4:24   ` sashiko-bot
2026-11-09 18:25 ` [RFC PATCH v2 25/25] iommu/dma: Add PISA statistics and debugfs Luigi Rizzo
2026-11-11  4:37   ` sashiko-bot

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=sashiko-outbox-207862@kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=akpm@linux-foundation.org \
    --cc=aleksander.lobakin@intel.com \
    --cc=axboe@kernel.dk \
    --cc=corbet@lwn.net \
    --cc=dakr@kernel.org \
    --cc=davem@davemloft.net \
    --cc=david@kernel.org \
    --cc=edumazet@kernel.org \
    --cc=gregkh@linuxfoundation.org \
    --cc=hawk@kernel.org \
    --cc=hch@lst.de \
    --cc=hramamurthy@google.com \
    --cc=ilias.apalodimas@linaro.org \
    --cc=joro@8bytes.org \
    --cc=joshwash@google.com \
    --cc=kuba@kernel.org \
    --cc=kuniyu@google.com \
    --cc=linux-mm@kvack.org \
    --cc=ljs@kernel.org \
    --cc=lrizzo@google.com \
    --cc=m.szyprowski@samsung.com \
    --cc=pabeni@redhat.com \
    --cc=rafael@kernel.org \
    --cc=rizzo.unipi@gmail.com \
    --cc=robin.murphy@arm.com \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vbabka@kernel.org \
    --cc=will@kernel.org \
    --cc=willemb@google.com \
    --cc=willy@infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox