All of lore.kernel.org
 help / color / mirror / Atom feed
From: Chaitanya Kulkarni <chaitanyak@nvidia.com>
To: Sebastian Ott <sebott@redhat.com>
Cc: "linux-nvme@lists.infradead.org" <linux-nvme@lists.infradead.org>,
	"iommu@lists.linux.dev" <iommu@lists.linux.dev>,
	Robin Murphy <robin.murphy@arm.com>,
	"linux-block@vger.kernel.org" <linux-block@vger.kernel.org>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"linux-xfs@vger.kernel.org" <linux-xfs@vger.kernel.org>,
	Jens Axboe <axboe@fb.com>, Christoph Hellwig <hch@lst.de>,
	Will Deacon <will@kernel.org>, Carlos Maiolino <cem@kernel.org>
Subject: Re: WARNING: drivers/iommu/io-pgtable-arm.c:639
Date: Wed, 10 Dec 2025 02:30:50 +0000	[thread overview]
Message-ID: <30ae8fc4-94ff-4467-835e-28b4a4dfcd8f@nvidia.com> (raw)
In-Reply-To: <99e12a04-d23f-f9e7-b02e-770e0012a794@redhat.com>

Sebastian,

On 12/9/25 13:05, Sebastian Ott wrote:
> On Tue, 9 Dec 2025, Robin Murphy wrote:
>> On 2025-12-09 11:43 am, Sebastian Ott wrote:
>>>  Hi,
>>>
>>>  got the following warning after a kernel update on Thurstday, 
>>> leading to a
>>>  panic and fs corruption. I didn't capture the first warning but I'm 
>>> pretty
>>>  sure it was the same. It's reproducible but I didn't bisect since it
>>>  borked my fs. The only hint I can give is that v6.18 worked. Is this a
>>>  known issue? Anything I should try?
>>
>> nvme_unmap_data() is attempting to unmap an IOVA that was never 
>> mapped, or has already been unmapped by someone else. That's a usage 
>> bug.
>
> OK, that's what I suspected - thanks for the confirmation!
>
> I did another repro and tried:
>
> good: 44fc84337b6e Merge tag 'arm64-upstream' of 
> git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux
> bad:  cc25df3e2e22 Merge tag 'for-6.19/block-20251201' of 
> git://git.kernel.org/pub/scm/linux/kernel/git/axboe/linux
>
> I'll start bisecting between these 2 - hoping it doesn't fork up my root
> fs again...
>
> Thanks,
> Sebastian
>
>
Can you see if this fixes your problem ?


==========
WARNING/DISCLOSURE:

These patches may cause system instability or crashes during testing.
Test only on non-production systems with proper backups in place.
==========


 From 0d180e8055e98d91174ba8fdd47ab934a7a88bef Mon Sep 17 00:00:00 2001
From: Chaitanya Kulkarni <ckulkarnilinux@gmail.com>
Date: Tue, 9 Dec 2025 01:23:51 -0800
Subject: [PATCH 1/2 COMPILE TESTED ONLY] iommu/io-pgtable-arm: fix size_t signedness bug in
  unmap path

__arm_lpae_unmap() returns size_t but was returning -ENOENT (negative
error code) when encountering an unmapped PTE. Since size_t is unsigned,
-ENOENT (typically -2) becomes a huge positive value (0xFFFFFFFFFFFFFFFE
on 64-bit systems).

This corrupted value propagates through the call chain:
   __arm_lpae_unmap() returns -ENOENT as size_t
   -> arm_lpae_unmap_pages() returns it
   -> __iommu_unmap() adds it to iova address
   -> iommu_pgsize() triggers BUG_ON due to corrupted iova

The corruption causes:
1. IOVA address overflow in __iommu_unmap() loop
2. BUG_ON in iommu_pgsize() from invalid address alignment
3. Kernel panic on ARM64 systems with SMMU

Fix by returning 0 instead of -ENOENT. The WARN_ON already signals
the error condition, and returning 0 (meaning "nothing unmapped")
is the correct semantic for size_t return type. This matches the
behavior of other io-pgtable implementations (io-pgtable-arm-v7s,
io-pgtable-dart) which return 0 on error conditions.

Kernel splat observed:

  ------------[ cut here ]------------
  kernel BUG at drivers/iommu/iommu.c:2464!
  Internal error: Oops - BUG: 00000000f2000800 [#1] SMP
  Modules linked in: xt_CHECKSUM xt_MASQUERADE xt_conntrack ipt_REJECT
   nf_reject_ipv4 xt_tcpudp nft_compat x_tables nft_chain_nat nf_nat
   nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 nf_tables nfnetlink bridge
   stp llc nvme_fabrics binfmt_misc nls_iso8859_1 ipmi_ssif arm_smmuv3_pmu
   cdc_subset arm_spe_pmu spi_nor acpi_power_meter acpi_ipmi ipmi_devintf
   cppc_cpufreq ipmi_msghandler sch_fq_codel dm_multipath scsi_dh_rdac
   scsi_dh_emc scsi_dh_alua arm_cspmu_module efi_pstore autofs4 btrfs
   blake2b libblake2b raid10 raid456 async_raid6_recov async_memcpy
   async_pq async_xor async_tx xor xor_neon raid6_pq raid1 raid0 mlx5_ib
   ib_uverbs ib_core cdc_ether usbnet mlx5_core ghash_ce dax_hmem sm4_ce_gcm
   ast cxl_acpi sm4_ce_ccm drm_shmem_helper sm4_ce cxl_port drm_client_lib
   i2c_smbus sm4_ce_cipher mlxfw drm_kms_helper cxl_core sm4 nvme psample
   igb sm3_ce arm_smccc_trng einj drm nvme_core i2c_algo_bit xhci_pci_renesas
   tls i2c_tegra aes_neon_bs aes_neon_blk aes_ce_blk aes_ce_cipher
  CPU: 26 UID: 0 PID: 0 Comm: swapper/26 Tainted: G        W          6.19.0+ #98
  Tainted: [W]=WARN
  Hardware name: NVIDIA GB200 NVL/P3809-BMC, BIOS 02.05.10 20251010
  pstate: 234000c9 (nzCv daIF +PAN -UAO +TCO +DIT -SSBS BTYPE=--)
  pc : iommu_pgsize.isra.0+0xe8/0xf8
  lr : __iommu_unmap+0xe0/0x308
  sp : ffff80008034fca0
  x29: ffff80008034fca0 x28: 000000000000fffe x27: ffffc6e7950e60b0
  x26: 00000000f9740000 x25: ffffc6e794b2cde8 x24: ffffc6e7967916a8
  x23: ffff80008034fdb8 x22: 0000000000030000 x21: ffff000030949220
  x20: 00000000f974fffe x19: fffffffffffffffe x18: 0000000000000000
  x17: 0000000000000000 x16: 0000000000000000 x15: 0000000000000000
  x14: 0000000000000000 x13: 0000000000000000 x12: 0000000000000000
  x11: 000000000000003f x10: 0000000020010000 x9 : 00000000f974fffe
  x8 : 000000000000003f x7 : 0000000000000000 x6 : ffffffffffffffff
  x5 : 0000000000000000 x4 : ffff80008034fd00 x3 : 0000000000020002
  x2 : 00000000f974fffe x1 : 00000000f974fffe x0 : 0000000020010000
  Call trace:
   iommu_pgsize.isra.0+0xe8/0xf8 (P)
   iommu_unmap_fast+0x18/0x40
   __iommu_dma_iova_unlink+0xec/0x2e8
   dma_iova_destroy+0x30/0xa0
   nvme_unmap_data+0x200/0x2e8 [nvme]
   nvme_pci_complete_batch+0x58/0xa8 [nvme]
   nvme_irq+0x98/0xa8 [nvme]
   __handle_irq_event_percpu+0xbc/0x498
   handle_irq_event+0x54/0xe0
   handle_fasteoi_irq+0x12c/0x1c8
   handle_irq_desc+0x54/0x90
   generic_handle_domain_irq+0x24/0x48
   gic_handle_irq+0x200/0x410
   call_on_irq_stack+0x30/0x48
   do_interrupt_handler+0xa8/0xb8
   el1_interrupt+0x4c/0xd0
   el1h_64_irq_handler+0x18/0x38
   el1h_64_irq+0x84/0x88
   cpuidle_enter_state+0x110/0x6a8 (P)
   cpuidle_enter+0x40/0x70
   do_idle+0x264/0x310
   cpu_startup_entry+0x3c/0x50
   secondary_start_kernel+0x13c/0x180
   __secondary_switched+0xc0/0xc8
  Code: d2800009 d280000a d280000b d65f03c0 (d4210000)
  ---[ end trace 0000000000000000 ]---

Fixes: 3318f7b5cefb ("iommu/io-pgtable-arm: Add quirk to quiet WARN_ON()")
Cc: stable@vger.kernel.org
Reported-by: Ankit Agrawal <ankita@nvidia.com>
Reported-by: Sebastian Ott <sebott@redhat.com>
Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com>
---

=======================================================================
DISCLOSURE: DUE TO LACK OF H/W THIS PATCH IS COMPLETELY UNTESTED AND
BASED SOLELY ON THEORETICAL ANALYSIS. PLEASE REVIEW CAREFULLY.
=======================================================================

---
  drivers/iommu/io-pgtable-arm.c | 2 +-
  1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index e6626004b323..05d63fe92e43 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -637,7 +637,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable *data,
  	pte = READ_ONCE(*ptep);
  	if (!pte) {
  		WARN_ON(!(data->iop.cfg.quirks & IO_PGTABLE_QUIRK_NO_WARN));
-		return -ENOENT;
+		return 0;
  	}
  
  	/* If the size matches this level, we're in the right place */
-- 
2.40.0

######################################################################


 From aa540bb77f7d4460c87b0a317df264de748a3b3c Mon Sep 17 00:00:00 2001
From: Chaitanya Kulkarni <ckulkarnilinux@gmail.com>
Date: Tue, 9 Dec 2025 17:01:15 -0800
Subject: [PATCH 2/2 COMPILE TESTED ONLY] block: fix partial IOVA mapping cleanup in
  blk_rq_dma_map_iova

When dma_iova_link() fails partway through mapping a request's
scatter-gather list, the function would break out of the loop without
cleaning up the already-mapped portions. This leads to a map/unmap
size mismatch when the request is later completed.

The completion path (via dma_iova_destroy or nvme_unmap_data) attempts
to unmap the full expected size, but only a partial size was actually
mapped. This triggers "unmapped PTE" warnings in the ARM LPAE io-pgtable
code and can cause IOVA address corruption.

Fix by adding an out_unlink error path that calls dma_iova_unlink()
to clean up any partial mapping before returning failure. This ensures
that when an error occurs:
1. All partially-mapped IOVA ranges are properly unmapped
2. The completion path won't attempt to unmap non-existent mappings
3. No map/unmap size mismatch occurs

Fixes: 858299dc6160 ("block: add scatterlist-less DMA mapping helpers")
Signed-off-by: Chaitanya Kulkarni <kch@nvidia.com>
---

=======================================================================
DISCLOSURE: DUE TO LACK OF H/W THIS PATCH IS COMPLETELY UNTESTED AND
BASED SOLELY ON THEORETICAL ANALYSIS. PLEASE REVIEW CAREFULLY.
=======================================================================

---
  block/blk-mq-dma.c | 19 ++++++++++++++-----
  1 file changed, 14 insertions(+), 5 deletions(-)

diff --git a/block/blk-mq-dma.c b/block/blk-mq-dma.c
index b6dbc9767596..eb8b5b6b595c 100644
--- a/block/blk-mq-dma.c
+++ b/block/blk-mq-dma.c
@@ -126,17 +126,26 @@ static bool blk_rq_dma_map_iova(struct request *req, struct device *dma_dev,
  		error = dma_iova_link(dma_dev, state, vec->paddr, mapped,
  				vec->len, dir, attrs);
  		if (error)
-			break;
+			goto out_unlink;
  		mapped += vec->len;
  	} while (blk_map_iter_next(req, &iter->iter, vec));
  
  	error = dma_iova_sync(dma_dev, state, 0, mapped);
-	if (error) {
-		iter->status = errno_to_blk_status(error);
-		return false;
-	}
+	if (error)
+		goto out_unlink;
  
  	return true;
+
+out_unlink:
+	/*
+	 * Unlink any partial mapping to avoid unmap mismatch later.
+	 * If we mapped some bytes but not all, we must clean up now
+	 * to prevent attempting to unmap more than was actually mapped.
+	 */
+	if (mapped)
+		dma_iova_unlink(dma_dev, state, 0, mapped, dir, attrs);
+	iter->status = errno_to_blk_status(error);
+	return false;
  }
  
  static inline void blk_rq_map_iter_init(struct request *rq,
-- 
2.40.0


-ck



  reply	other threads:[~2025-12-10  2:30 UTC|newest]

Thread overview: 16+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-12-09 11:43 WARNING: drivers/iommu/io-pgtable-arm.c:639 Sebastian Ott
2025-12-09 11:50 ` Robin Murphy
2025-12-09 17:29   ` Chaitanya Kulkarni
2025-12-09 17:34     ` Robin Murphy
2025-12-09 17:59       ` Chaitanya Kulkarni
2025-12-09 21:05   ` Sebastian Ott
2025-12-10  2:30     ` Chaitanya Kulkarni [this message]
2025-12-10  4:05       ` Keith Busch
2025-12-10  4:59         ` Chaitanya Kulkarni
2025-12-10 17:12           ` Sebastian Ott
2025-12-10 21:12             ` Chaitanya Kulkarni
2025-12-10  5:02 ` Keith Busch
2025-12-10  5:33   ` Keith Busch
2025-12-10 11:08   ` Sebastian Ott
2025-12-10 11:21     ` Keith Busch
2025-12-10 16:57       ` Sebastian Ott

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=30ae8fc4-94ff-4467-835e-28b4a4dfcd8f@nvidia.com \
    --to=chaitanyak@nvidia.com \
    --cc=axboe@fb.com \
    --cc=cem@kernel.org \
    --cc=hch@lst.de \
    --cc=iommu@lists.linux.dev \
    --cc=linux-block@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-nvme@lists.infradead.org \
    --cc=linux-xfs@vger.kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=sebott@redhat.com \
    --cc=will@kernel.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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.