Re: [PATCH 23/24] iommu/amd: Assign per-vIOMMU translate device ID
From: Suthikulpanit, Suravee
Date: Tue Sep 08 2026 - 07:54:13 EST
On 8/19/2026 5:18 PM, guanghuifeng@xxxxxxxxxxxxxxxxx wrote:
在 2026/7/27 21:29, Suravee Suthikulpanit 写道:
Allocate one translate-device-id per IOMMUFD vIOMMU instance from the
per-segment pool on init. Program translation DTE and VFctrl TransDevID
after MMIO reset; clear both on init error and destroy.
Add per-vIOMMU trans_devid_lock to serialize DTE and VFctrl updates
during teardown.
Signed-off-by: Suravee Suthikulpanit <suravee.suthikulpanit@xxxxxxx>
---
drivers/iommu/amd/amd_iommu_types.h | 7 ++++++
drivers/iommu/amd/iommufd.c | 35 +++++++++++++++++++++++++++++
drivers/iommu/amd/viommu.c | 2 ++
3 files changed, 44 insertions(+)
diff --git a/drivers/iommu/amd/amd_iommu_types.h b/drivers/iommu/amd/ amd_iommu_types.h
index f288a7b384d0..39cf2c588106 100644
--- a/drivers/iommu/amd/amd_iommu_types.h
+++ b/drivers/iommu/amd/amd_iommu_types.h
@@ -559,6 +559,13 @@ struct amd_iommu_viommu {
u64 *domid_table;
u16 trans_devid;
+ /*
+ * Serializes translate-device-id hardware changes (DTE, VFctrl) and
+ * coordinates with pool relocation during PCI attach. Lock ordering:
+ * pci_seg->trans_devid_mutex, then trans_devid_lock.
+ */
+ struct mutex trans_devid_lock;
+
....
@@ -124,6 +153,12 @@ static void amd_iommufd_viommu_destroy(struct iommufd_viommu *viommu)
xa_destroy(&aviommu->gdomid_array);
iommufd_viommu_destroy_mmap(&aviommu->core, aviommu- >vfmmio_mmap_offset);
amd_viommu_uninit_one(iommu, aviommu);
+
+ mutex_lock(&aviommu->trans_devid_lock);
+ amd_iommu_update_vfctrl_mmio_translate_devid(iommu, aviommu->gid, 0);
+ amd_iommu_clear_translate_dte(iommu, aviommu->trans_devid);
+ amd_iommu_trans_devid_free(iommu->pci_seg, aviommu->trans_devid, aviommu);
+ mutex_unlock(&aviommu->trans_devid_lock);
amd_iommu_gid_free(iommu, aviommu->gid);
}
The comment states "pci_seg->trans_devid_mutex, then trans_devid_lock"
as the lock ordering. However, examining the actual code paths:
In amd_iommufd_viommu_destroy():
mutex_lock(&aviommu->trans_devid_lock); /* viommu lock first */
...
amd_iommu_trans_devid_free(...); /* takes seg_mutex inside */
mutex_unlock(&aviommu->trans_devid_lock);
In amd_iommu_trans_devid_free():
mutex_lock(&pci_seg->trans_devid_mutex); /* seg_mutex nested */
In trans_devid_relocate() (Patch 24):
mutex_lock(&aviommu->trans_devid_lock); /* viommu lock first */
mutex_lock(&pci_seg->trans_devid_mutex); /* seg_mutex second */
All paths consistently take trans_devid_lock first, then
trans_devid_mutex (nested). The actual ordering is the opposite of
what the comment describes:
Actual: trans_devid_lock -> trans_devid_mutex
Comment: trans_devid_mutex -> trans_devid_lock
The code is consistent and there is no deadlock risk, but the
comment should be corrected to avoid confusing future readers:
* Lock ordering: trans_devid_lock, then pci_seg->trans_devid_mutex.
I'll update the comment in v5.
Thanks,
Suravee