* [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
@ 2024-05-28 16:39 Vasant Hegde
2024-05-28 16:39 ` [PATCH 2/2] iommu/amd: Fix Invalid wait context issue Vasant Hegde
2024-05-28 18:06 ` [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Robin Murphy
0 siblings, 2 replies; 10+ messages in thread
From: Vasant Hegde @ 2024-05-28 16:39 UTC (permalink / raw)
To: iommu, joro
Cc: suravee.suthikulpanit, Vasant Hegde, Lianbo Jiang, Robin Murphy
Commit 3ab657291638 ("iommu: use the __iommu_attach_device() directly for deferred attach")
replaced iommu_attach_device() call with __iommu_attach_device(). But
missed to take group lock. Take lock before attaching device to domain.
Fixes: 3ab657291638 ("iommu: use the __iommu_attach_device() directly for deferred attach")
Cc: Lianbo Jiang <lijiang@redhat.com>
Cc: Robin Murphy <robin.murphy@arm.com>
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/iommu.c | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9df7cc75c1bc..1743dba023b6 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2114,10 +2114,19 @@ EXPORT_SYMBOL_GPL(iommu_attach_device);
int iommu_deferred_attach(struct device *dev, struct iommu_domain *domain)
{
- if (dev->iommu && dev->iommu->attach_deferred)
- return __iommu_attach_device(domain, dev);
+ int ret = 0;
+ struct iommu_group *group = dev->iommu_group;
- return 0;
+ if (!group)
+ return -EINVAL;
+
+ if (dev->iommu && dev->iommu->attach_deferred) {
+ mutex_lock(&group->mutex);
+ ret = __iommu_attach_device(domain, dev);
+ mutex_unlock(&group->mutex);
+ }
+
+ return ret;
}
void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH 2/2] iommu/amd: Fix Invalid wait context issue
2024-05-28 16:39 [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Vasant Hegde
@ 2024-05-28 16:39 ` Vasant Hegde
2024-05-28 20:43 ` Chris Bainbridge
2024-05-29 6:35 ` Mikhail Gavrilov
2024-05-28 18:06 ` [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Robin Murphy
1 sibling, 2 replies; 10+ messages in thread
From: Vasant Hegde @ 2024-05-28 16:39 UTC (permalink / raw)
To: iommu, joro
Cc: suravee.suthikulpanit, Vasant Hegde, Borislav Petkov,
Mikhail Gavrilov, Chris Bainbridge
With commit c4cb23111103 ("iommu/amd: Add support for enable/disable IOPF")
we are hitting below issue. This happens because in IOPF enablement path
it holds spin lock with irq disable and then tries to take mutex lock.
dmesg:
-----
[ 0.938739] =============================
[ 0.938740] [ BUG: Invalid wait context ]
[ 0.938742] 6.10.0-rc1+ #1 Not tainted
[ 0.938745] -----------------------------
[ 0.938746] swapper/0/1 is trying to lock:
[ 0.938748] ffffffff8c9f01d8 (&port_lock_key){....}-{3:3}, at: serial8250_console_write+0x78/0x4a0
[ 0.938767] other info that might help us debug this:
[ 0.938768] context-{5:5}
[ 0.938769] 7 locks held by swapper/0/1:
[ 0.938772] #0: ffff888101a91310 (&group->mutex){+.+.}-{4:4}, at: bus_iommu_probe+0x70/0x160
[ 0.938790] #1: ffff888101d1f1b8 (&domain->lock){....}-{3:3}, at: amd_iommu_attach_device+0xa5/0x700
[ 0.938799] #2: ffff888101cc3d18 (&dev_data->lock){....}-{3:3}, at: amd_iommu_attach_device+0xc5/0x700
[ 0.938806] #3: ffff888100052830 (&iommu->lock){....}-{2:2}, at: amd_iommu_iopf_add_device+0x3f/0xa0
[ 0.938813] #4: ffffffff8945a340 (console_lock){+.+.}-{0:0}, at: _printk+0x48/0x50
[ 0.938822] #5: ffffffff8945a390 (console_srcu){....}-{0:0}, at: console_flush_all+0x58/0x4e0
[ 0.938867] #6: ffffffff82459f80 (console_owner){....}-{0:0}, at: console_flush_all+0x1f0/0x4e0
[ 0.938872] stack backtrace:
[ 0.938874] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.10.0-rc1+ #1
[ 0.938877] Hardware name: HP HP EliteBook 745 G3/807E, BIOS N73 Ver. 01.39 04/16/2019
Fix above issue by re-arranging code in attach device path:
- move device PASID/IOPF enablement outside lock in AMD IOMMU driver.
This is safe as core layer holds group->mutex lock before calling
iommu_ops->attach_dev.
Reported-by: Borislav Petkov <bp@alien8.de>
Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
Reported-by: Chris Bainbridge <chris.bainbridge@gmail.com>
Fixes: c4cb23111103 ("iommu/amd: Add support for enable/disable IOPF")
Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
---
drivers/iommu/amd/iommu.c | 48 +++++++++++++++++++--------------------
drivers/iommu/amd/ppr.c | 22 ++++--------------
2 files changed, 28 insertions(+), 42 deletions(-)
diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
index 52d83730a22a..c2703599bb16 100644
--- a/drivers/iommu/amd/iommu.c
+++ b/drivers/iommu/amd/iommu.c
@@ -2032,7 +2032,6 @@ static int do_attach(struct iommu_dev_data *dev_data,
struct protection_domain *domain)
{
struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
- struct pci_dev *pdev;
int ret = 0;
/* Update data structures */
@@ -2047,30 +2046,13 @@ static int do_attach(struct iommu_dev_data *dev_data,
domain->dev_iommu[iommu->index] += 1;
domain->dev_cnt += 1;
- pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
+ /* Setup GCR3 table */
if (pdom_is_sva_capable(domain)) {
ret = init_gcr3_table(dev_data, domain);
if (ret)
return ret;
-
- if (pdev) {
- pdev_enable_caps(pdev);
-
- /*
- * Device can continue to function even if IOPF
- * enablement failed. Hence in error path just
- * disable device PRI support.
- */
- if (amd_iommu_iopf_add_device(iommu, dev_data))
- pdev_disable_cap_pri(pdev);
- }
- } else if (pdev) {
- pdev_enable_cap_ats(pdev);
}
- /* Update device table */
- amd_iommu_dev_update_dte(dev_data, true);
-
return ret;
}
@@ -2163,6 +2145,11 @@ static void detach_device(struct device *dev)
do_detach(dev_data);
+out:
+ spin_unlock(&dev_data->lock);
+
+ spin_unlock_irqrestore(&domain->lock, flags);
+
/* Remove IOPF handler */
if (ppr)
amd_iommu_iopf_remove_device(iommu, dev_data);
@@ -2170,10 +2157,6 @@ static void detach_device(struct device *dev)
if (dev_is_pci(dev))
pdev_disable_caps(to_pci_dev(dev));
-out:
- spin_unlock(&dev_data->lock);
-
- spin_unlock_irqrestore(&domain->lock, flags);
}
static struct iommu_device *amd_iommu_probe_device(struct device *dev)
@@ -2485,6 +2468,7 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
struct protection_domain *domain = to_pdomain(dom);
struct amd_iommu *iommu = get_amd_iommu_from_dev(dev);
+ struct pci_dev *pdev;
int ret;
/*
@@ -2517,7 +2501,23 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
}
#endif
- iommu_completion_wait(iommu);
+ pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
+ if (pdev && pdom_is_sva_capable(domain)) {
+ pdev_enable_caps(pdev);
+
+ /*
+ * Device can continue to function even if IOPF
+ * enablement failed. Hence in error path just
+ * disable device PRI support.
+ */
+ if (amd_iommu_iopf_add_device(iommu, dev_data))
+ pdev_disable_cap_pri(pdev);
+ } else if (pdev) {
+ pdev_enable_cap_ats(pdev);
+ }
+
+ /* Update device table */
+ amd_iommu_dev_update_dte(dev_data, true);
return ret;
}
diff --git a/drivers/iommu/amd/ppr.c b/drivers/iommu/amd/ppr.c
index 091423bb8aac..b3b690410f2a 100644
--- a/drivers/iommu/amd/ppr.c
+++ b/drivers/iommu/amd/ppr.c
@@ -249,40 +249,26 @@ void amd_iommu_page_response(struct device *dev, struct iopf_fault *evt,
int amd_iommu_iopf_add_device(struct amd_iommu *iommu,
struct iommu_dev_data *dev_data)
{
- unsigned long flags;
int ret = 0;
if (!dev_data->pri_enabled)
return ret;
- raw_spin_lock_irqsave(&iommu->lock, flags);
-
- if (!iommu->iopf_queue) {
- ret = -EINVAL;
- goto out_unlock;
- }
+ if (!iommu->iopf_queue)
+ return -EINVAL;
ret = iopf_queue_add_device(iommu->iopf_queue, dev_data->dev);
if (ret)
- goto out_unlock;
+ return ret;
dev_data->ppr = true;
-
-out_unlock:
- raw_spin_unlock_irqrestore(&iommu->lock, flags);
- return ret;
+ return 0;
}
/* Its assumed that caller has verified that device was added to iopf queue */
void amd_iommu_iopf_remove_device(struct amd_iommu *iommu,
struct iommu_dev_data *dev_data)
{
- unsigned long flags;
-
- raw_spin_lock_irqsave(&iommu->lock, flags);
-
iopf_queue_remove_device(iommu->iopf_queue, dev_data->dev);
dev_data->ppr = false;
-
- raw_spin_unlock_irqrestore(&iommu->lock, flags);
}
--
2.31.1
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
2024-05-28 16:39 [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Vasant Hegde
2024-05-28 16:39 ` [PATCH 2/2] iommu/amd: Fix Invalid wait context issue Vasant Hegde
@ 2024-05-28 18:06 ` Robin Murphy
2024-05-29 7:24 ` Vasant Hegde
1 sibling, 1 reply; 10+ messages in thread
From: Robin Murphy @ 2024-05-28 18:06 UTC (permalink / raw)
To: Vasant Hegde, iommu, joro; +Cc: suravee.suthikulpanit, Lianbo Jiang
On 2024-05-28 5:39 pm, Vasant Hegde wrote:
> Commit 3ab657291638 ("iommu: use the __iommu_attach_device() directly for deferred attach")
> replaced iommu_attach_device() call with __iommu_attach_device(). But
> missed to take group lock. Take lock before attaching device to domain.
Why? Nothing here is even touching the group. If we've reached a
deferred attach then we know the domain is the default domain already
initialised and set as the current of the device's group, and the device
is already otherwise added and holding a reference to that group, and a
driver is bound to the device in order to make the DMA API call we're
inside, so nothing should be at risk of disappearing under our feet.
Please clarify what purpose this locking actually serves.
But then there's also the fact that the initial DMA mapping operation
which triggers deferred attach could legitimately be called under a
spinlock or in an IRQ handler, so if anything it was a bug in
795bbbb9b6f8 ("iommu/dma-iommu: Handle deferred devices") to ever use
iommu_attach_device() (and thus involve the mutex) in the first place :/
Thanks,
Robin.
> Fixes: 3ab657291638 ("iommu: use the __iommu_attach_device() directly for deferred attach")
> Cc: Lianbo Jiang <lijiang@redhat.com>
> Cc: Robin Murphy <robin.murphy@arm.com>
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> ---
> drivers/iommu/iommu.c | 15 ++++++++++++---
> 1 file changed, 12 insertions(+), 3 deletions(-)
>
> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
> index 9df7cc75c1bc..1743dba023b6 100644
> --- a/drivers/iommu/iommu.c
> +++ b/drivers/iommu/iommu.c
> @@ -2114,10 +2114,19 @@ EXPORT_SYMBOL_GPL(iommu_attach_device);
>
> int iommu_deferred_attach(struct device *dev, struct iommu_domain *domain)
> {
> - if (dev->iommu && dev->iommu->attach_deferred)
> - return __iommu_attach_device(domain, dev);
> + int ret = 0;
> + struct iommu_group *group = dev->iommu_group;
>
> - return 0;
> + if (!group)
> + return -EINVAL;
> +
> + if (dev->iommu && dev->iommu->attach_deferred) {
> + mutex_lock(&group->mutex);
> + ret = __iommu_attach_device(domain, dev);
> + mutex_unlock(&group->mutex);
> + }
> +
> + return ret;
> }
>
> void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] iommu/amd: Fix Invalid wait context issue
2024-05-28 16:39 ` [PATCH 2/2] iommu/amd: Fix Invalid wait context issue Vasant Hegde
@ 2024-05-28 20:43 ` Chris Bainbridge
2024-05-29 6:35 ` Mikhail Gavrilov
1 sibling, 0 replies; 10+ messages in thread
From: Chris Bainbridge @ 2024-05-28 20:43 UTC (permalink / raw)
To: Vasant Hegde
Cc: iommu, joro, suravee.suthikulpanit, Borislav Petkov,
Mikhail Gavrilov
On Tue, 28 May 2024 at 17:40, Vasant Hegde <vasant.hegde@amd.com> wrote:
>
> With commit c4cb23111103 ("iommu/amd: Add support for enable/disable IOPF")
> we are hitting below issue. This happens because in IOPF enablement path
> it holds spin lock with irq disable and then tries to take mutex lock.
>
> dmesg:
> -----
> [ 0.938739] =============================
> [ 0.938740] [ BUG: Invalid wait context ]
> [ 0.938742] 6.10.0-rc1+ #1 Not tainted
> [ 0.938745] -----------------------------
> [ 0.938746] swapper/0/1 is trying to lock:
> [ 0.938748] ffffffff8c9f01d8 (&port_lock_key){....}-{3:3}, at: serial8250_console_write+0x78/0x4a0
> [ 0.938767] other info that might help us debug this:
> [ 0.938768] context-{5:5}
> [ 0.938769] 7 locks held by swapper/0/1:
> [ 0.938772] #0: ffff888101a91310 (&group->mutex){+.+.}-{4:4}, at: bus_iommu_probe+0x70/0x160
> [ 0.938790] #1: ffff888101d1f1b8 (&domain->lock){....}-{3:3}, at: amd_iommu_attach_device+0xa5/0x700
> [ 0.938799] #2: ffff888101cc3d18 (&dev_data->lock){....}-{3:3}, at: amd_iommu_attach_device+0xc5/0x700
> [ 0.938806] #3: ffff888100052830 (&iommu->lock){....}-{2:2}, at: amd_iommu_iopf_add_device+0x3f/0xa0
> [ 0.938813] #4: ffffffff8945a340 (console_lock){+.+.}-{0:0}, at: _printk+0x48/0x50
> [ 0.938822] #5: ffffffff8945a390 (console_srcu){....}-{0:0}, at: console_flush_all+0x58/0x4e0
> [ 0.938867] #6: ffffffff82459f80 (console_owner){....}-{0:0}, at: console_flush_all+0x1f0/0x4e0
> [ 0.938872] stack backtrace:
> [ 0.938874] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.10.0-rc1+ #1
> [ 0.938877] Hardware name: HP HP EliteBook 745 G3/807E, BIOS N73 Ver. 01.39 04/16/2019
>
> Fix above issue by re-arranging code in attach device path:
> - move device PASID/IOPF enablement outside lock in AMD IOMMU driver.
> This is safe as core layer holds group->mutex lock before calling
> iommu_ops->attach_dev.
>
> Reported-by: Borislav Petkov <bp@alien8.de>
> Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
> Reported-by: Chris Bainbridge <chris.bainbridge@gmail.com>
> Fixes: c4cb23111103 ("iommu/amd: Add support for enable/disable IOPF")
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
Patch works for me.
Tested-by: Chris Bainbridge <chris.bainbridge@gmail.com>
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 2/2] iommu/amd: Fix Invalid wait context issue
2024-05-28 16:39 ` [PATCH 2/2] iommu/amd: Fix Invalid wait context issue Vasant Hegde
2024-05-28 20:43 ` Chris Bainbridge
@ 2024-05-29 6:35 ` Mikhail Gavrilov
1 sibling, 0 replies; 10+ messages in thread
From: Mikhail Gavrilov @ 2024-05-29 6:35 UTC (permalink / raw)
To: Vasant Hegde
Cc: iommu, joro, suravee.suthikulpanit, Borislav Petkov,
Chris Bainbridge
[-- Attachment #1: Type: text/plain, Size: 7888 bytes --]
On Tue, May 28, 2024 at 9:40 PM Vasant Hegde <vasant.hegde@amd.com> wrote:
>
> With commit c4cb23111103 ("iommu/amd: Add support for enable/disable IOPF")
> we are hitting below issue. This happens because in IOPF enablement path
> it holds spin lock with irq disable and then tries to take mutex lock.
>
> dmesg:
> -----
> [ 0.938739] =============================
> [ 0.938740] [ BUG: Invalid wait context ]
> [ 0.938742] 6.10.0-rc1+ #1 Not tainted
> [ 0.938745] -----------------------------
> [ 0.938746] swapper/0/1 is trying to lock:
> [ 0.938748] ffffffff8c9f01d8 (&port_lock_key){....}-{3:3}, at: serial8250_console_write+0x78/0x4a0
> [ 0.938767] other info that might help us debug this:
> [ 0.938768] context-{5:5}
> [ 0.938769] 7 locks held by swapper/0/1:
> [ 0.938772] #0: ffff888101a91310 (&group->mutex){+.+.}-{4:4}, at: bus_iommu_probe+0x70/0x160
> [ 0.938790] #1: ffff888101d1f1b8 (&domain->lock){....}-{3:3}, at: amd_iommu_attach_device+0xa5/0x700
> [ 0.938799] #2: ffff888101cc3d18 (&dev_data->lock){....}-{3:3}, at: amd_iommu_attach_device+0xc5/0x700
> [ 0.938806] #3: ffff888100052830 (&iommu->lock){....}-{2:2}, at: amd_iommu_iopf_add_device+0x3f/0xa0
> [ 0.938813] #4: ffffffff8945a340 (console_lock){+.+.}-{0:0}, at: _printk+0x48/0x50
> [ 0.938822] #5: ffffffff8945a390 (console_srcu){....}-{0:0}, at: console_flush_all+0x58/0x4e0
> [ 0.938867] #6: ffffffff82459f80 (console_owner){....}-{0:0}, at: console_flush_all+0x1f0/0x4e0
> [ 0.938872] stack backtrace:
> [ 0.938874] CPU: 2 PID: 1 Comm: swapper/0 Not tainted 6.10.0-rc1+ #1
> [ 0.938877] Hardware name: HP HP EliteBook 745 G3/807E, BIOS N73 Ver. 01.39 04/16/2019
>
> Fix above issue by re-arranging code in attach device path:
> - move device PASID/IOPF enablement outside lock in AMD IOMMU driver.
> This is safe as core layer holds group->mutex lock before calling
> iommu_ops->attach_dev.
>
> Reported-by: Borislav Petkov <bp@alien8.de>
> Reported-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
> Reported-by: Chris Bainbridge <chris.bainbridge@gmail.com>
> Fixes: c4cb23111103 ("iommu/amd: Add support for enable/disable IOPF")
> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
> ---
> drivers/iommu/amd/iommu.c | 48 +++++++++++++++++++--------------------
> drivers/iommu/amd/ppr.c | 22 ++++--------------
> 2 files changed, 28 insertions(+), 42 deletions(-)
>
> diff --git a/drivers/iommu/amd/iommu.c b/drivers/iommu/amd/iommu.c
> index 52d83730a22a..c2703599bb16 100644
> --- a/drivers/iommu/amd/iommu.c
> +++ b/drivers/iommu/amd/iommu.c
> @@ -2032,7 +2032,6 @@ static int do_attach(struct iommu_dev_data *dev_data,
> struct protection_domain *domain)
> {
> struct amd_iommu *iommu = get_amd_iommu_from_dev_data(dev_data);
> - struct pci_dev *pdev;
> int ret = 0;
>
> /* Update data structures */
> @@ -2047,30 +2046,13 @@ static int do_attach(struct iommu_dev_data *dev_data,
> domain->dev_iommu[iommu->index] += 1;
> domain->dev_cnt += 1;
>
> - pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
> + /* Setup GCR3 table */
> if (pdom_is_sva_capable(domain)) {
> ret = init_gcr3_table(dev_data, domain);
> if (ret)
> return ret;
> -
> - if (pdev) {
> - pdev_enable_caps(pdev);
> -
> - /*
> - * Device can continue to function even if IOPF
> - * enablement failed. Hence in error path just
> - * disable device PRI support.
> - */
> - if (amd_iommu_iopf_add_device(iommu, dev_data))
> - pdev_disable_cap_pri(pdev);
> - }
> - } else if (pdev) {
> - pdev_enable_cap_ats(pdev);
> }
>
> - /* Update device table */
> - amd_iommu_dev_update_dte(dev_data, true);
> -
> return ret;
> }
>
> @@ -2163,6 +2145,11 @@ static void detach_device(struct device *dev)
>
> do_detach(dev_data);
>
> +out:
> + spin_unlock(&dev_data->lock);
> +
> + spin_unlock_irqrestore(&domain->lock, flags);
> +
> /* Remove IOPF handler */
> if (ppr)
> amd_iommu_iopf_remove_device(iommu, dev_data);
> @@ -2170,10 +2157,6 @@ static void detach_device(struct device *dev)
> if (dev_is_pci(dev))
> pdev_disable_caps(to_pci_dev(dev));
>
> -out:
> - spin_unlock(&dev_data->lock);
> -
> - spin_unlock_irqrestore(&domain->lock, flags);
> }
>
> static struct iommu_device *amd_iommu_probe_device(struct device *dev)
> @@ -2485,6 +2468,7 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
> struct iommu_dev_data *dev_data = dev_iommu_priv_get(dev);
> struct protection_domain *domain = to_pdomain(dom);
> struct amd_iommu *iommu = get_amd_iommu_from_dev(dev);
> + struct pci_dev *pdev;
> int ret;
>
> /*
> @@ -2517,7 +2501,23 @@ static int amd_iommu_attach_device(struct iommu_domain *dom,
> }
> #endif
>
> - iommu_completion_wait(iommu);
> + pdev = dev_is_pci(dev_data->dev) ? to_pci_dev(dev_data->dev) : NULL;
> + if (pdev && pdom_is_sva_capable(domain)) {
> + pdev_enable_caps(pdev);
> +
> + /*
> + * Device can continue to function even if IOPF
> + * enablement failed. Hence in error path just
> + * disable device PRI support.
> + */
> + if (amd_iommu_iopf_add_device(iommu, dev_data))
> + pdev_disable_cap_pri(pdev);
> + } else if (pdev) {
> + pdev_enable_cap_ats(pdev);
> + }
> +
> + /* Update device table */
> + amd_iommu_dev_update_dte(dev_data, true);
>
> return ret;
> }
> diff --git a/drivers/iommu/amd/ppr.c b/drivers/iommu/amd/ppr.c
> index 091423bb8aac..b3b690410f2a 100644
> --- a/drivers/iommu/amd/ppr.c
> +++ b/drivers/iommu/amd/ppr.c
> @@ -249,40 +249,26 @@ void amd_iommu_page_response(struct device *dev, struct iopf_fault *evt,
> int amd_iommu_iopf_add_device(struct amd_iommu *iommu,
> struct iommu_dev_data *dev_data)
> {
> - unsigned long flags;
> int ret = 0;
>
> if (!dev_data->pri_enabled)
> return ret;
>
> - raw_spin_lock_irqsave(&iommu->lock, flags);
> -
> - if (!iommu->iopf_queue) {
> - ret = -EINVAL;
> - goto out_unlock;
> - }
> + if (!iommu->iopf_queue)
> + return -EINVAL;
>
> ret = iopf_queue_add_device(iommu->iopf_queue, dev_data->dev);
> if (ret)
> - goto out_unlock;
> + return ret;
>
> dev_data->ppr = true;
> -
> -out_unlock:
> - raw_spin_unlock_irqrestore(&iommu->lock, flags);
> - return ret;
> + return 0;
> }
>
> /* Its assumed that caller has verified that device was added to iopf queue */
> void amd_iommu_iopf_remove_device(struct amd_iommu *iommu,
> struct iommu_dev_data *dev_data)
> {
> - unsigned long flags;
> -
> - raw_spin_lock_irqsave(&iommu->lock, flags);
> -
> iopf_queue_remove_device(iommu->iopf_queue, dev_data->dev);
> dev_data->ppr = false;
> -
> - raw_spin_unlock_irqrestore(&iommu->lock, flags);
> }
> --
> 2.31.1
>
Tested-by: Mikhail Gavrilov <mikhail.v.gavrilov@gmail.com>
--
Best Regards,
Mike Gavrilov.
[-- Attachment #2: dmesg.zip --]
[-- Type: application/zip, Size: 63104 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
2024-05-28 18:06 ` [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Robin Murphy
@ 2024-05-29 7:24 ` Vasant Hegde
2024-06-10 17:44 ` Jason Gunthorpe
0 siblings, 1 reply; 10+ messages in thread
From: Vasant Hegde @ 2024-05-29 7:24 UTC (permalink / raw)
To: Robin Murphy, iommu, joro; +Cc: suravee.suthikulpanit, Lianbo Jiang
Hi Robin,
On 5/28/2024 11:36 PM, Robin Murphy wrote:
> On 2024-05-28 5:39 pm, Vasant Hegde wrote:
>> Commit 3ab657291638 ("iommu: use the __iommu_attach_device() directly for
>> deferred attach")
>> replaced iommu_attach_device() call with __iommu_attach_device(). But
>> missed to take group lock. Take lock before attaching device to domain.
>
> Why? Nothing here is even touching the group. If we've reached a deferred attach
> then we know the domain is the default domain already initialised and set as the
> current of the device's group, and the device is already otherwise added and
> holding a reference to that group, and a driver is bound to the device in order
> to make the DMA API call we're inside, so nothing should be at risk of
> disappearing under our feet. Please clarify what purpose this locking actually
> serves.
I am sorry. I should have written better description. I was trying to see if its
safe to use iommu_group_mutex_assert() in our driver. I did audit the iommu.c
code and saw this one place it was missed. I just looked into git history and
tried to fix it. As you explained below I should have looked into the caller of
this function in detail!
>
> But then there's also the fact that the initial DMA mapping operation which
> triggers deferred attach could legitimately be called under a spinlock or in an
> IRQ handler, so if anything it was a bug in 795bbbb9b6f8 ("iommu/dma-iommu:
> Handle deferred devices") to ever use iommu_attach_device() (and thus involve
> the mutex) in the first place :/
Thanks for the detailed explanation. I will drop this patch in next version.
-Vasant
>
> Thanks,
> Robin.
>
>> Fixes: 3ab657291638 ("iommu: use the __iommu_attach_device() directly for
>> deferred attach")
>> Cc: Lianbo Jiang <lijiang@redhat.com>
>> Cc: Robin Murphy <robin.murphy@arm.com>
>> Signed-off-by: Vasant Hegde <vasant.hegde@amd.com>
>> ---
>> drivers/iommu/iommu.c | 15 ++++++++++++---
>> 1 file changed, 12 insertions(+), 3 deletions(-)
>>
>> diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
>> index 9df7cc75c1bc..1743dba023b6 100644
>> --- a/drivers/iommu/iommu.c
>> +++ b/drivers/iommu/iommu.c
>> @@ -2114,10 +2114,19 @@ EXPORT_SYMBOL_GPL(iommu_attach_device);
>> int iommu_deferred_attach(struct device *dev, struct iommu_domain *domain)
>> {
>> - if (dev->iommu && dev->iommu->attach_deferred)
>> - return __iommu_attach_device(domain, dev);
>> + int ret = 0;
>> + struct iommu_group *group = dev->iommu_group;
>> - return 0;
>> + if (!group)
>> + return -EINVAL;
>> +
>> + if (dev->iommu && dev->iommu->attach_deferred) {
>> + mutex_lock(&group->mutex);
>> + ret = __iommu_attach_device(domain, dev);
>> + mutex_unlock(&group->mutex);
>> + }
>> +
>> + return ret;
>> }
>> void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
2024-05-29 7:24 ` Vasant Hegde
@ 2024-06-10 17:44 ` Jason Gunthorpe
2024-06-24 14:20 ` Vasant Hegde
0 siblings, 1 reply; 10+ messages in thread
From: Jason Gunthorpe @ 2024-06-10 17:44 UTC (permalink / raw)
To: Vasant Hegde
Cc: Robin Murphy, iommu, joro, suravee.suthikulpanit, Lianbo Jiang
On Wed, May 29, 2024 at 12:54:14PM +0530, Vasant Hegde wrote:
> Hi Robin,
>
>
> On 5/28/2024 11:36 PM, Robin Murphy wrote:
> > On 2024-05-28 5:39 pm, Vasant Hegde wrote:
> >> Commit 3ab657291638 ("iommu: use the __iommu_attach_device() directly for
> >> deferred attach")
> >> replaced iommu_attach_device() call with __iommu_attach_device(). But
> >> missed to take group lock. Take lock before attaching device to domain.
> >
> > Why? Nothing here is even touching the group. If we've reached a deferred attach
> > then we know the domain is the default domain already initialised and set as the
> > current of the device's group, and the device is already otherwise added and
> > holding a reference to that group, and a driver is bound to the device in order
> > to make the DMA API call we're inside, so nothing should be at risk of
> > disappearing under our feet. Please clarify what purpose this locking actually
> > serves.
>
> I am sorry. I should have written better description. I was trying to see if its
> safe to use iommu_group_mutex_assert() in our driver.
The core code guarentees that the dev will not have racing
attach_dev() ops, and we added the iommu_group_mutex_assert() as a way
for drivers to document they are making use of that assumption.
I'm guessing the purpose of this patch is to allow the AMD driver to
use iommu_group_mutex_assert() as it will fail in the deferred attach
path.
> > But then there's also the fact that the initial DMA mapping operation which
> > triggers deferred attach could legitimately be called under a spinlock or in an
> > IRQ handler, so if anything it was a bug in 795bbbb9b6f8 ("iommu/dma-iommu:
> > Handle deferred devices") to ever use iommu_attach_device() (and thus involve
> > the mutex) in the first place :/
ops->attach_dev() must be called in a sleepable context, even
the Intel driver will hit a GFP_KERNEL allocation in its attach_dev()
op. It seems to be an issue in 795bbbb9b6f8 that it did not consider
this.
I suppose in practice kdump using drivers are setting up DMA during
their probe functions and don't get into this problem.
IMHO adding the mutex here is an appropriate thing, it should not be
closing any race, but it is the right locking documentation to make
iommu_group_mutex_assert() work.
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
2024-06-10 17:44 ` Jason Gunthorpe
@ 2024-06-24 14:20 ` Vasant Hegde
2024-06-24 15:25 ` Jason Gunthorpe
0 siblings, 1 reply; 10+ messages in thread
From: Vasant Hegde @ 2024-06-24 14:20 UTC (permalink / raw)
To: Jason Gunthorpe, Robin Murphy
Cc: Robin Murphy, iommu, joro, suravee.suthikulpanit, Lianbo Jiang
Jason,
On 6/10/2024 11:14 PM, Jason Gunthorpe wrote:
> On Wed, May 29, 2024 at 12:54:14PM +0530, Vasant Hegde wrote:
>> Hi Robin,
>>
>>
>> On 5/28/2024 11:36 PM, Robin Murphy wrote:
>>> On 2024-05-28 5:39 pm, Vasant Hegde wrote:
>>>> Commit 3ab657291638 ("iommu: use the __iommu_attach_device() directly for
>>>> deferred attach")
>>>> replaced iommu_attach_device() call with __iommu_attach_device(). But
>>>> missed to take group lock. Take lock before attaching device to domain.
>>>
>>> Why? Nothing here is even touching the group. If we've reached a deferred attach
>>> then we know the domain is the default domain already initialised and set as the
>>> current of the device's group, and the device is already otherwise added and
>>> holding a reference to that group, and a driver is bound to the device in order
>>> to make the DMA API call we're inside, so nothing should be at risk of
>>> disappearing under our feet. Please clarify what purpose this locking actually
>>> serves.
>>
>> I am sorry. I should have written better description. I was trying to see if its
>> safe to use iommu_group_mutex_assert() in our driver.
>
> The core code guarentees that the dev will not have racing
> attach_dev() ops, and we added the iommu_group_mutex_assert() as a way
> for drivers to document they are making use of that assumption.
>
> I'm guessing the purpose of this patch is to allow the AMD driver to
> use iommu_group_mutex_assert() as it will fail in the deferred attach
> path.
Right. That's what I was thinking.
>
>>> But then there's also the fact that the initial DMA mapping operation which
>>> triggers deferred attach could legitimately be called under a spinlock or in an
>>> IRQ handler, so if anything it was a bug in 795bbbb9b6f8 ("iommu/dma-iommu:
>>> Handle deferred devices") to ever use iommu_attach_device() (and thus involve
>>> the mutex) in the first place :/
>
> ops->attach_dev() must be called in a sleepable context, even
> the Intel driver will hit a GFP_KERNEL allocation in its attach_dev()
> op. It seems to be an issue in 795bbbb9b6f8 that it did not consider
> this.
>
> I suppose in practice kdump using drivers are setting up DMA during
> their probe functions and don't get into this problem.
Looking into code path and AMD driver code, it does look like in kdump path
deferred attach gets called.
>
> IMHO adding the mutex here is an appropriate thing, it should not be
> closing any race, but it is the right locking documentation to make
> iommu_group_mutex_assert() work.
It may be good thing to add mutex here.. But if any of the caller of these
deferred functions hold spin lock again we will hit the similar issue that I hit
with AMD driver.
-Vasant
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
2024-06-24 14:20 ` Vasant Hegde
@ 2024-06-24 15:25 ` Jason Gunthorpe
2024-06-24 16:02 ` Vasant Hegde
0 siblings, 1 reply; 10+ messages in thread
From: Jason Gunthorpe @ 2024-06-24 15:25 UTC (permalink / raw)
To: Vasant Hegde
Cc: Robin Murphy, iommu, joro, suravee.suthikulpanit, Lianbo Jiang
On Mon, Jun 24, 2024 at 07:50:46PM +0530, Vasant Hegde wrote:
> It may be good thing to add mutex here.. But if any of the caller of these
> deferred functions hold spin lock again we will hit the similar issue that I hit
> with AMD driver.
My point was that Intel doesn't support non-sleeping attach, it uses
GFP_KERNEL, that support seems to be a uniquely AMD thing of the major
drivers.
So, I don't see an issue with formalizing the lowest common
denominator in the core code - the context must be sleepable.
Presumably things work because the kdump kernels only run drivers that
reliably trigger first dma from sleepable contexts. Unless there is
something AMD only that relies on this special behavior??
Jason
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach()
2024-06-24 15:25 ` Jason Gunthorpe
@ 2024-06-24 16:02 ` Vasant Hegde
0 siblings, 0 replies; 10+ messages in thread
From: Vasant Hegde @ 2024-06-24 16:02 UTC (permalink / raw)
To: Jason Gunthorpe
Cc: Robin Murphy, iommu, joro, suravee.suthikulpanit, Lianbo Jiang
Jason,
On 6/24/2024 8:55 PM, Jason Gunthorpe wrote:
> On Mon, Jun 24, 2024 at 07:50:46PM +0530, Vasant Hegde wrote:
>
>> It may be good thing to add mutex here.. But if any of the caller of these
>> deferred functions hold spin lock again we will hit the similar issue that I hit
>> with AMD driver.
>
> My point was that Intel doesn't support non-sleeping attach, it uses
> GFP_KERNEL, that support seems to be a uniquely AMD thing of the major
> drivers.
As I understand we don't have any hard requirement. We can sleep in attach
device path. I do have a patch to replace dev_data->spinlock to mutex in AMD
driver. I need to do some more testing before sending it out.
>
> So, I don't see an issue with formalizing the lowest common
> denominator in the core code - the context must be sleepable.
>
> Presumably things work because the kdump kernels only run drivers that
> reliably trigger first dma from sleepable contexts. Unless there is
> something AMD only that relies on this special behavior??
AFAIK AMD driver doesn't have any special behaviour in kdump path. When we jump
to crashing kernel (kexec) we don't disable IOMMU and try to init IOMMU with
existing info.
Having said that I have not done exhaustive kdump test with mutex lock. I will
run some more tests and get back to you.
-Vasant
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2024-06-24 16:02 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-05-28 16:39 [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Vasant Hegde
2024-05-28 16:39 ` [PATCH 2/2] iommu/amd: Fix Invalid wait context issue Vasant Hegde
2024-05-28 20:43 ` Chris Bainbridge
2024-05-29 6:35 ` Mikhail Gavrilov
2024-05-28 18:06 ` [PATCH 1/2] iommu: Take group lock before attaching device in iommu_deferred_attach() Robin Murphy
2024-05-29 7:24 ` Vasant Hegde
2024-06-10 17:44 ` Jason Gunthorpe
2024-06-24 14:20 ` Vasant Hegde
2024-06-24 15:25 ` Jason Gunthorpe
2024-06-24 16:02 ` Vasant Hegde
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox