All of lore.kernel.org
 help / color / mirror / Atom feed
From: Vipin Sharma <vipinsh@google.com>
To: Alex Williamson <alex@shazbot.org>,
	Joerg Roedel <joro@8bytes.org>,
	 Bjorn Helgaas <bhelgaas@google.com>,
	Nicolin Chen <nicolinc@nvidia.com>,
	 Jason Gunthorpe <jgg@ziepe.ca>,
	Kevin Tian <kevin.tian@intel.com>,
	Robin Murphy <robin.murphy@arm.com>
Cc: jrhilke@google.com, skhawaja@google.com, tatashin@google.com,
	 Will Deacon <will@kernel.org>,
	David Matlack <dmatlack@google.com>,
	kvm@vger.kernel.org,  iommu@lists.linux.dev,
	linux-pci@vger.kernel.org,  linux-kernel@vger.kernel.org,
	Vipin Sharma <vipinsh@google.com>
Subject: [RFC PATCH 0/1] vfio: circular locking dependency in pci_dev_reset_iommu_prepare()
Date: Fri, 21 Aug 2026 12:35:00 -0700	[thread overview]
Message-ID: <20260821193502.92431-1-vipinsh@google.com> (raw)

Hello,

I have encountered a reproducible circular locking dependency (lockdep)
warning when performing a device reset via VFIO (e.g. VFIO_DEVICE_RESET ioctl
or kexec live update) on a device whose BARs have been mmapped and faulted.

This issue was introduced in commit f5b16b802174 ("PCI: Suspend iommu function
prior to resetting a device"), which added calls to
pci_dev_reset_iommu_prepare() / pci_dev_reset_iommu_done() inside core PCI
reset routines (pcie_flr(), pci_pm_reset(), etc.).

Patch 1 adds a new selftest in tools/testing/selftests/vfio/ that triggers
this warning reliably on systems with ATS and reset support.

I used Intel DSA device 8086:0b25 with the test in Patch 1.

This issue was identified in the VFIO Live Update series
  https://lore.kernel.org/kvm/20260723181436.GB260824.vipinsh@google.com/

Since issue is independent of Live Update, I am sending this out
separately to not mix two things.

I have uploaded the patch to github also:
  https://github.com/shvipin/linux vfio/lockdep-mmap-fault-device-reset

================================================================================
Lock Hierarchy Analysis (Helped by AI)
================================================================================

1. In VFIO, handling VFIO_DEVICE_RESET (vfio_pci_ioctl_reset()) or bus/hot reset
   acquires down_write(&vdev->memory_lock) to zap active MMIO BAR mappings
   and prevent concurrent MMIO faults during reset.
   Inside memory_lock, it calls pci_try_reset_function() / pcie_flr().

2. Commit f5b16b802174 added pci_dev_reset_iommu_prepare() into pcie_flr().
   pci_dev_reset_iommu_prepare() acquires guard(mutex)(&group->mutex).
   This establishes:
       &vdev->memory_lock --> &group->mutex

3. Meanwhile, during kernel boot or device discovery (iommu_probe_device() /
   bus_iommu_probe()), iommu.c holds &group->mutex while calling
   iommu_setup_dma_ops(), which calls iova_domain_init_rcaches().
   iova_domain_init_rcaches() registers a multi-instance cpuhp handler via
   cpuhp_state_add_instance_nocalls(), acquiring cpus_read_lock().
   This establishes:
       &group->mutex --> cpu_hotplug_lock

4. cpu_hotplug_lock is an outer lock for various kernel subsystems that
   execute callbacks or sysfs/firmware/perf interactions, which eventually
   perform copy_to_user(), copy_from_user(), or filldir() (which can trigger
   a page fault in user memory under mmap_lock).
   This establishes:
       cpu_hotplug_lock --> (kernfs_rwsem / inode->i_rwsem / cpuctx_mutex)
                        --> &mm->mmap_lock

5. When userspace touches an mmapped VFIO BAR, the page fault handler
   (vfio_pci_mmap_huge_fault() / vfio_pci_mmap_page_fault()) executes under
   &mm->mmap_lock and acquires down_read(&vdev->memory_lock).
   This establishes:
       &mm->mmap_lock --> &vdev->memory_lock

Combining (1) through (5) yields the circular dependency cycle:

    &group->mutex
      --> cpu_hotplug_lock
        --> [kernfs_rwsem | i_mutex_dir_key | cpuctx_mutex]
          --> &mm->mmap_lock
            --> &vdev->memory_lock
              --> &group->mutex  <== DEADLOCK DETECTED


================================================================================
Reproductions / Lockdep Traces
================================================================================

I observed this lockdep warning closing via multiple distinct paths:

--- Trace 1: via sysfs / kernfs readdir ---

[  438.457974] WARNING: possible circular locking dependency detected
[  438.477952] vfio_cdev_lockd/17678 is trying to acquire lock:
[  438.484320] (&group->mutex){+.+.}-{4:4}, at: pci_dev_reset_iommu_prepare+0x6e/0x200
[  438.494169] but task is already holding lock:
[  438.501401] (&vdev->memory_lock){++++}-{4:4}, at: vfio_pci_core_ioctl+0x460/0xb20
[  438.511064] which lock already depends on the new lock.
...
[  438.919866] Chain exists of:
[  438.919866]   &group->mutex --> &mm->mmap_lock --> &vdev->memory_lock
...
[  438.999115]  __mutex_lock+0x8c/0xd80
[  438.999122]  pci_dev_reset_iommu_prepare+0x6e/0x200
[  438.999123]  pcie_flr+0x32/0xc0
[  438.999125]  __pci_reset_function_locked+0x84/0x120
[  438.999126]  pci_try_reset_function+0x51/0xe0
[  438.999128]  vfio_pci_core_ioctl+0x72b/0xb20

--- Trace 2: via VFS lookup / microcode loading during kexec ---

[  584.552264] WARNING: possible circular locking dependency detected
[  584.572247] kexec/14239 is trying to acquire lock:
[  584.577754] (&group->mutex){+.+.}-{4:4}, at: pci_dev_reset_iommu_prepare+0x6e/0x1a0
[  584.587602] but task is already holding lock:
[  584.594838] (&vdev->memory_lock){++++}-{4:4}, at: vfio_pci_liveupdate_freeze+0x51/0x100
...
[  584.751130] -> #2 (&type->i_mutex_dir_key#4):
[  584.760319]        lookup_slow+0x26/0x50
[  584.786970]        _request_firmware+0x4ab/0x8c0
[  584.797979]        request_microcode_fw+0xf2/0x510
[  584.834601] -> #1 (cpu_hotplug_lock):
[  584.842183]        cpus_read_lock+0x3b/0xd0
[  584.858957]        iommu_setup_dma_ops+0x175/0x540

--- Trace 3: via perf read / watchdog cpuhp callback ---

[  233.859740] WARNING: possible circular locking dependency detected
[  233.879725] vfio_cdev_lockd/14999 is trying to acquire lock:
[  233.886094] (&group->mutex){+.+.}-{4:4}, at: pci_dev_reset_iommu_prepare+0x6e/0x200
[  233.895948] but task is already holding lock:
[  233.903183] (&vdev->memory_lock){++++}-{4:4}, at: vfio_pci_core_ioctl+0x460/0xb20
...
[  234.030037] -> #3 (&cpuctx_mutex):
[  234.040960]        perf_event_enable+0x18/0xa0
[  234.046126]        lockup_detector_online_cpu+0x22/0x30
[  234.057658]        cpuhp_thread_fun+0x164/0x1e0
[  234.115402] -> #1 (cpu_hotplug_lock):
[  234.122985]        cpus_read_lock+0x3b/0xd0
[  234.139757]        iommu_setup_dma_ops+0x18a/0x560


================================================================================
Potential Solutions Suggested by AI
================================================================================

1. Decouple iommu_setup_dma_ops() from group->mutex in drivers/iommu/iommu.c:
   iommu_setup_dma_ops() only requires struct device * and the domain pointer
   (group->default_domain); it does not mutate any fields in struct iommu_group.
   Moving the iommu_setup_dma_ops() calls after mutex_unlock(&group->mutex) in
   iommu_probe_device(), bus_iommu_probe(), and iommu_group_store_type() breaks
   the initial &group->mutex -> cpu_hotplug_lock dependency.

2. Avoid holding down_write(&vdev->memory_lock) across pci_try_reset_function()
   in VFIO:
   vfio-pci could zap active BAR mappings under memory_lock and set a state
   flag / disable memory decoding, drop memory_lock before calling
   pci_try_reset_function(), and then re-acquire memory_lock to re-enable
   memory. While resetting, any concurrent user fault will see the memory
   disabled condition and return VM_FAULT_SIGBUS safely.

3. Refine synchronization in pci_dev_reset_iommu_prepare():
   Evaluate if attaching to the blocking domain and pausing ATS during device
   reset can be protected using more fine-grained locking or atomic state
   flags without holding the coarse &group->mutex.

Feedback and suggestions on the preferred direction to resolve this would be
greatly appreciated.

Thanks,
Vipin Sharma

Vipin Sharma (1):
  selftests: vfio: Add mmap fault and device reset test

 tools/testing/selftests/vfio/Makefile         |  1 +
 .../selftests/vfio/vfio_pci_mmap_reset_test.c | 60 +++++++++++++++++++
 2 files changed, 61 insertions(+)
 create mode 100644 tools/testing/selftests/vfio/vfio_pci_mmap_reset_test.c

-- 
2.55.0.766.g2966f0265a-goog

             reply	other threads:[~2026-08-21 19:35 UTC|newest]

Thread overview: 7+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-08-21 19:35 Vipin Sharma [this message]
2026-08-21 19:35 ` [RFC PATCH 1/1] selftests: vfio: Add mmap fault and device reset test Vipin Sharma
2026-08-21 19:46   ` sashiko-bot
2026-08-25 19:06 ` [RFC PATCH 0/1] vfio: circular locking dependency in pci_dev_reset_iommu_prepare() David Matlack
2026-08-26 20:27   ` David Matlack
2026-08-27 17:36     ` David Matlack
2026-08-27 18:03     ` Samiullah Khawaja

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=20260821193502.92431-1-vipinsh@google.com \
    --to=vipinsh@google.com \
    --cc=alex@shazbot.org \
    --cc=bhelgaas@google.com \
    --cc=dmatlack@google.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@ziepe.ca \
    --cc=joro@8bytes.org \
    --cc=jrhilke@google.com \
    --cc=kevin.tian@intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pci@vger.kernel.org \
    --cc=nicolinc@nvidia.com \
    --cc=robin.murphy@arm.com \
    --cc=skhawaja@google.com \
    --cc=tatashin@google.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.