From: Joerg Roedel <joro-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
To: Mark Hounschell <markh-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
Cc: iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org
Subject: Re: Can't boot new 4.4 kernel with IOMMU enabled
Date: Mon, 11 Apr 2016 15:54:51 +0200 [thread overview]
Message-ID: <20160411135451.GO17838@8bytes.org> (raw)
In-Reply-To: <56EC39CB.2010909-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
Hi Mark,
On Fri, Mar 18, 2016 at 01:24:27PM -0400, Mark Hounschell wrote:
> Should I submit a kernel bug report on this?
I just fixed a regression in v4.4. Can you please try the attached patch
and report if it fixes your problem too? The patch is against v4.6-rc2.
Thanks,
Joerg
>From e76e8764c9265b5dec31e6a8e5be61f028866d93 Mon Sep 17 00:00:00 2001
From: Joerg Roedel <jroedel-l3A5Bk7waGM@public.gmane.org>
Date: Fri, 8 Apr 2016 15:12:24 +0200
Subject: [PATCH] iommu/amd: Fix checking of pci dma aliases
Commit 61289cb ('iommu/amd: Remove old alias handling code')
removed the old alias handling code from the AMD IOMMU
driver because this is now handled by the IOMMU core code.
But this also removed the handling of PCI aliases, which is
not handled by the core code. This caused issues with PCI
devices that have hidden PCIe-to-PCI bridges that rewrite
the request-id.
Fix this bug by re-introducing some of the removed functions
from commit 61289cbaf6c8 and add a alias field
'struct iommu_dev_data'. This field carrys the return value
of the get_alias() function and uses that instead of the
amd_iommu_alias_table[] array in the code.
Fixes: 61289cbaf6c8 ('iommu/amd: Remove old alias handling code')
Cc: stable-u79uwXL29TY76Z2rM5mHXA@public.gmane.org # v4.4+
Signed-off-by: Joerg Roedel <jroedel-l3A5Bk7waGM@public.gmane.org>
---
drivers/iommu/amd_iommu.c | 87 +++++++++++++++++++++++++++++++++++++++++------
1 file changed, 76 insertions(+), 11 deletions(-)
diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 374c129..5efadad 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -92,6 +92,7 @@ struct iommu_dev_data {
struct list_head dev_data_list; /* For global dev_data_list */
struct protection_domain *domain; /* Domain the device is bound to */
u16 devid; /* PCI Device ID */
+ u16 alias; /* Alias Device ID */
bool iommu_v2; /* Device can make use of IOMMUv2 */
bool passthrough; /* Device is identity mapped */
struct {
@@ -166,6 +167,13 @@ static struct protection_domain *to_pdomain(struct iommu_domain *dom)
return container_of(dom, struct protection_domain, domain);
}
+static inline u16 get_device_id(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+
+ return PCI_DEVID(pdev->bus->number, pdev->devfn);
+}
+
static struct iommu_dev_data *alloc_dev_data(u16 devid)
{
struct iommu_dev_data *dev_data;
@@ -203,6 +211,68 @@ out_unlock:
return dev_data;
}
+static int __last_alias(struct pci_dev *pdev, u16 alias, void *data)
+{
+ *(u16 *)data = alias;
+ return 0;
+}
+
+static u16 get_alias(struct device *dev)
+{
+ struct pci_dev *pdev = to_pci_dev(dev);
+ u16 devid, ivrs_alias, pci_alias;
+
+ devid = get_device_id(dev);
+ ivrs_alias = amd_iommu_alias_table[devid];
+ pci_for_each_dma_alias(pdev, __last_alias, &pci_alias);
+
+ if (ivrs_alias == pci_alias)
+ return ivrs_alias;
+
+ /*
+ * DMA alias showdown
+ *
+ * The IVRS is fairly reliable in telling us about aliases, but it
+ * can't know about every screwy device. If we don't have an IVRS
+ * reported alias, use the PCI reported alias. In that case we may
+ * still need to initialize the rlookup and dev_table entries if the
+ * alias is to a non-existent device.
+ */
+ if (ivrs_alias == devid) {
+ if (!amd_iommu_rlookup_table[pci_alias]) {
+ amd_iommu_rlookup_table[pci_alias] =
+ amd_iommu_rlookup_table[devid];
+ memcpy(amd_iommu_dev_table[pci_alias].data,
+ amd_iommu_dev_table[devid].data,
+ sizeof(amd_iommu_dev_table[pci_alias].data));
+ }
+
+ return pci_alias;
+ }
+
+ pr_info("AMD-Vi: Using IVRS reported alias %02x:%02x.%d "
+ "for device %s[%04x:%04x], kernel reported alias "
+ "%02x:%02x.%d\n", PCI_BUS_NUM(ivrs_alias), PCI_SLOT(ivrs_alias),
+ PCI_FUNC(ivrs_alias), dev_name(dev), pdev->vendor, pdev->device,
+ PCI_BUS_NUM(pci_alias), PCI_SLOT(pci_alias),
+ PCI_FUNC(pci_alias));
+
+ /*
+ * If we don't have a PCI DMA alias and the IVRS alias is on the same
+ * bus, then the IVRS table may know about a quirk that we don't.
+ */
+ if (pci_alias == devid &&
+ PCI_BUS_NUM(ivrs_alias) == pdev->bus->number) {
+ pdev->dev_flags |= PCI_DEV_FLAGS_DMA_ALIAS_DEVFN;
+ pdev->dma_alias_devfn = ivrs_alias & 0xff;
+ pr_info("AMD-Vi: Added PCI DMA alias %02x.%d for %s\n",
+ PCI_SLOT(ivrs_alias), PCI_FUNC(ivrs_alias),
+ dev_name(dev));
+ }
+
+ return ivrs_alias;
+}
+
static struct iommu_dev_data *find_dev_data(u16 devid)
{
struct iommu_dev_data *dev_data;
@@ -215,13 +285,6 @@ static struct iommu_dev_data *find_dev_data(u16 devid)
return dev_data;
}
-static inline u16 get_device_id(struct device *dev)
-{
- struct pci_dev *pdev = to_pci_dev(dev);
-
- return PCI_DEVID(pdev->bus->number, pdev->devfn);
-}
-
static struct iommu_dev_data *get_dev_data(struct device *dev)
{
return dev->archdata.iommu;
@@ -349,6 +412,8 @@ static int iommu_init_device(struct device *dev)
if (!dev_data)
return -ENOMEM;
+ dev_data->alias = get_alias(dev);
+
if (pci_iommuv2_capable(pdev)) {
struct amd_iommu *iommu;
@@ -369,7 +434,7 @@ static void iommu_ignore_device(struct device *dev)
u16 devid, alias;
devid = get_device_id(dev);
- alias = amd_iommu_alias_table[devid];
+ alias = get_alias(dev);
memset(&amd_iommu_dev_table[devid], 0, sizeof(struct dev_table_entry));
memset(&amd_iommu_dev_table[alias], 0, sizeof(struct dev_table_entry));
@@ -1061,7 +1126,7 @@ static int device_flush_dte(struct iommu_dev_data *dev_data)
int ret;
iommu = amd_iommu_rlookup_table[dev_data->devid];
- alias = amd_iommu_alias_table[dev_data->devid];
+ alias = dev_data->alias;
ret = iommu_flush_dte(iommu, dev_data->devid);
if (!ret && alias != dev_data->devid)
@@ -2039,7 +2104,7 @@ static void do_attach(struct iommu_dev_data *dev_data,
bool ats;
iommu = amd_iommu_rlookup_table[dev_data->devid];
- alias = amd_iommu_alias_table[dev_data->devid];
+ alias = dev_data->alias;
ats = dev_data->ats.enabled;
/* Update data structures */
@@ -2073,7 +2138,7 @@ static void do_detach(struct iommu_dev_data *dev_data)
return;
iommu = amd_iommu_rlookup_table[dev_data->devid];
- alias = amd_iommu_alias_table[dev_data->devid];
+ alias = dev_data->alias;
/* decrease reference counters */
dev_data->domain->dev_iommu[iommu->index] -= 1;
--
1.8.4.5
next prev parent reply other threads:[~2016-04-11 13:54 UTC|newest]
Thread overview: 32+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-01-12 21:37 Can't boot new 4.4 kernel with IOMMU enabled Mark Hounschell
[not found] ` <56957209.1080202-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-13 3:09 ` Baoquan He
[not found] ` <20160113030950.GB11902-0VdLhd/A9PlfpSRLqpFUpR/sF2h8X+2i0E9HWUfgJXw@public.gmane.org>
2016-01-13 14:42 ` Mark Hounschell
[not found] ` <56966244.80700-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-14 0:05 ` Baoquan He
[not found] ` <20160114000520.GA2449-ejN7fcUYdH/by3iVrkZq2A@public.gmane.org>
2016-01-14 14:04 ` Mark Hounschell
[not found] ` <5697AAD8.1000105-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-20 15:38 ` Joerg Roedel
[not found] ` <20160120153823.GG18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-01-20 15:46 ` Joerg Roedel
[not found] ` <20160120154658.GH18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-01-20 16:04 ` Mark Hounschell
[not found] ` <569FB013.4050709-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-20 16:19 ` Joerg Roedel
[not found] ` <20160120161904.GI18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-01-20 18:19 ` Mark Hounschell
[not found] ` <569FCFC8.2000606-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-20 18:26 ` Joerg Roedel
[not found] ` <20160120182602.GJ18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-01-20 19:32 ` Mark Hounschell
[not found] ` <569FE0B0.4030902-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-20 20:30 ` Joerg Roedel
2016-01-21 14:50 ` Mark Hounschell
[not found] ` <56A0F03C.8010109-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-21 14:58 ` Mark Hounschell
[not found] ` <56A0F221.10502-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-21 22:39 ` Joerg Roedel
[not found] ` <20160121223958.GL18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-02-02 15:49 ` Mark Hounschell
[not found] ` <56B0CFF7.80907-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-02-16 16:24 ` Joerg Roedel
[not found] ` <20160216162455.GX18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-02-16 17:32 ` Mark Hounschell
[not found] ` <56C35D1A.9080307-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-02-26 16:23 ` Joerg Roedel
[not found] ` <20160226162319.GH22747-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-02-26 19:20 ` Mark Hounschell
[not found] ` <56D0A565.8080406-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-02-29 17:42 ` Joerg Roedel
[not found] ` <20160229174252.GN22747-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-02-29 17:52 ` Mark Hounschell
[not found] ` <56D48560.4010904-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-03-18 17:24 ` Mark Hounschell
[not found] ` <56EC39CB.2010909-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-04-11 13:54 ` Joerg Roedel [this message]
[not found] ` <20160411135451.GO17838-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-04-11 14:59 ` Mark Hounschell
[not found] ` <570BBBE4.9040307-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-04-11 15:43 ` Joerg Roedel
2016-01-20 15:56 ` Mark Hounschell
2016-01-20 12:31 ` Joerg Roedel
[not found] ` <20160120123116.GF18805-zLv9SwRftAIdnm+yROfE0A@public.gmane.org>
2016-01-20 13:03 ` Mark Hounschell
[not found] ` <569F858E.4060701-n2QNKt385d+sTnJN9+BGXg@public.gmane.org>
2016-01-20 13:18 ` Baoquan He
2016-01-20 13:03 ` Baoquan He
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=20160411135451.GO17838@8bytes.org \
--to=joro-zlv9swrftaidnm+yrofe0a@public.gmane.org \
--cc=iommu-cunTk1MwBs9QetFLy7KEm3xJsTq8ys+cHZ5vskTnxNA@public.gmane.org \
--cc=markh-n2QNKt385d+sTnJN9+BGXg@public.gmane.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;
as well as URLs for NNTP newsgroup(s).