[PATCH AUTOSEL 4.9 40/60] iommu/amd: Silence warnings under memory pressure

2019-09-22 Thread Sasha Levin
From: Qian Cai 

[ Upstream commit 3d708895325b78506e8daf00ef31549476e8586a ]

When running heavy memory pressure workloads, the system is throwing
endless warnings,

smartpqi :23:00.0: AMD-Vi: IOMMU mapping error in map_sg (io-pages:
5 reason: -12)
Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40
07/10/2019
swapper/10: page allocation failure: order:0, mode:0xa20(GFP_ATOMIC),
nodemask=(null),cpuset=/,mems_allowed=0,4
Call Trace:
 
 dump_stack+0x62/0x9a
 warn_alloc.cold.43+0x8a/0x148
 __alloc_pages_nodemask+0x1a5c/0x1bb0
 get_zeroed_page+0x16/0x20
 iommu_map_page+0x477/0x540
 map_sg+0x1ce/0x2f0
 scsi_dma_map+0xc6/0x160
 pqi_raid_submit_scsi_cmd_with_io_request+0x1c3/0x470 [smartpqi]
 do_IRQ+0x81/0x170
 common_interrupt+0xf/0xf
 

because the allocation could fail from iommu_map_page(), and the volume
of this call could be huge which may generate a lot of serial console
output and cosumes all CPUs.

Fix it by silencing the warning in this call site, and there is still a
dev_err() later to notify the failure.

Signed-off-by: Qian Cai 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index c1233d0288a03..245e831fe64c3 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2589,7 +2589,9 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
 
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
phys_addr = (sg_phys(s) & PAGE_MASK) + (j << 
PAGE_SHIFT);
-   ret = iommu_map_page(domain, bus_addr, phys_addr, 
PAGE_SIZE, prot, GFP_ATOMIC);
+   ret = iommu_map_page(domain, bus_addr, phys_addr,
+PAGE_SIZE, prot,
+GFP_ATOMIC | __GFP_NOWARN);
if (ret)
goto out_unmap;
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 64/89] iommu/amd: Silence warnings under memory pressure

2019-09-22 Thread Sasha Levin
From: Qian Cai 

[ Upstream commit 3d708895325b78506e8daf00ef31549476e8586a ]

When running heavy memory pressure workloads, the system is throwing
endless warnings,

smartpqi :23:00.0: AMD-Vi: IOMMU mapping error in map_sg (io-pages:
5 reason: -12)
Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40
07/10/2019
swapper/10: page allocation failure: order:0, mode:0xa20(GFP_ATOMIC),
nodemask=(null),cpuset=/,mems_allowed=0,4
Call Trace:
 
 dump_stack+0x62/0x9a
 warn_alloc.cold.43+0x8a/0x148
 __alloc_pages_nodemask+0x1a5c/0x1bb0
 get_zeroed_page+0x16/0x20
 iommu_map_page+0x477/0x540
 map_sg+0x1ce/0x2f0
 scsi_dma_map+0xc6/0x160
 pqi_raid_submit_scsi_cmd_with_io_request+0x1c3/0x470 [smartpqi]
 do_IRQ+0x81/0x170
 common_interrupt+0xf/0xf
 

because the allocation could fail from iommu_map_page(), and the volume
of this call could be huge which may generate a lot of serial console
output and cosumes all CPUs.

Fix it by silencing the warning in this call site, and there is still a
dev_err() later to notify the failure.

Signed-off-by: Qian Cai 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 684f7cdd814b6..68eb4f1b42f44 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2538,7 +2538,9 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
 
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
phys_addr = (sg_phys(s) & PAGE_MASK) + (j << 
PAGE_SHIFT);
-   ret = iommu_map_page(domain, bus_addr, phys_addr, 
PAGE_SIZE, prot, GFP_ATOMIC);
+   ret = iommu_map_page(domain, bus_addr, phys_addr,
+PAGE_SIZE, prot,
+GFP_ATOMIC | __GFP_NOWARN);
if (ret)
goto out_unmap;
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 65/89] iommu/iova: Avoid false sharing on fq_timer_on

2019-09-22 Thread Sasha Levin
From: Eric Dumazet 

[ Upstream commit 0d87308cca2c124f9bce02383f1d9632c9be89c4 ]

In commit 14bd9a607f90 ("iommu/iova: Separate atomic variables
to improve performance") Jinyu Qi identified that the atomic_cmpxchg()
in queue_iova() was causing a performance loss and moved critical fields
so that the false sharing would not impact them.

However, avoiding the false sharing in the first place seems easy.
We should attempt the atomic_cmpxchg() no more than 100 times
per second. Adding an atomic_read() will keep the cache
line mostly shared.

This false sharing came with commit 9a005a800ae8
("iommu/iova: Add flush timer").

Signed-off-by: Eric Dumazet 
Fixes: 9a005a800ae8 ('iommu/iova: Add flush timer')
Cc: Jinyu Qi 
Cc: Joerg Roedel 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iova.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 9f35b9a0d6d86..4edf65dbbcab5 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -607,7 +607,9 @@ void queue_iova(struct iova_domain *iovad,
 
spin_unlock_irqrestore(&fq->lock, flags);
 
-   if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0)
+   /* Avoid false sharing as much as possible. */
+   if (!atomic_read(&iovad->fq_timer_on) &&
+   !atomic_cmpxchg(&iovad->fq_timer_on, 0, 1))
mod_timer(&iovad->fq_timer,
  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 127/128] iommu/amd: Override wrong IVRS IOAPIC on Raven Ridge systems

2019-09-22 Thread Sasha Levin
From: Kai-Heng Feng 

[ Upstream commit 93d051550ee02eaff9a2541d825605a7bd778027 ]

Raven Ridge systems may have malfunction touchpad or hang at boot if
incorrect IVRS IOAPIC is provided by BIOS.

Users already found correct "ivrs_ioapic=" values, let's put them inside
kernel to workaround buggy BIOS.

BugLink: https://bugs.launchpad.net/bugs/1795292
BugLink: https://bugs.launchpad.net/bugs/1837688
Reported-by: kbuild test robot 
Signed-off-by: Kai-Heng Feng 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/Makefile   |  2 +-
 drivers/iommu/amd_iommu.h| 14 +
 drivers/iommu/amd_iommu_init.c   |  5 +-
 drivers/iommu/amd_iommu_quirks.c | 92 
 4 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu.h
 create mode 100644 drivers/iommu/amd_iommu_quirks.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index ab5eba6edf82b..e13ea199f5896 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
diff --git a/drivers/iommu/amd_iommu.h b/drivers/iommu/amd_iommu.h
new file mode 100644
index 0..12d540d9b59b0
--- /dev/null
+++ b/drivers/iommu/amd_iommu.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef AMD_IOMMU_H
+#define AMD_IOMMU_H
+
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line);
+
+#ifdef CONFIG_DMI
+void amd_iommu_apply_ivrs_quirks(void);
+#else
+static void amd_iommu_apply_ivrs_quirks(void) { }
+#endif
+
+#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 66b4800bcdd8b..1e9a5da562f0d 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -39,6 +39,7 @@
 #include 
 
 #include 
+#include "amd_iommu.h"
 #include "amd_iommu_proto.h"
 #include "amd_iommu_types.h"
 #include "irq_remapping.h"
@@ -1002,7 +1003,7 @@ static void __init set_dev_entry_from_acpi(struct 
amd_iommu *iommu,
set_iommu_for_device(iommu, devid);
 }
 
-static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
 {
struct devid_map *entry;
struct list_head *list;
@@ -1153,6 +1154,8 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
if (ret)
return ret;
 
+   amd_iommu_apply_ivrs_quirks();
+
/*
 * First save the recommended feature enable bits from ACPI
 */
diff --git a/drivers/iommu/amd_iommu_quirks.c b/drivers/iommu/amd_iommu_quirks.c
new file mode 100644
index 0..c235f79b7a200
--- /dev/null
+++ b/drivers/iommu/amd_iommu_quirks.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Quirks for AMD IOMMU
+ *
+ * Copyright (C) 2019 Kai-Heng Feng 
+ */
+
+#ifdef CONFIG_DMI
+#include 
+
+#include "amd_iommu.h"
+
+#define IVHD_SPECIAL_IOAPIC1
+
+struct ivrs_quirk_entry {
+   u8 id;
+   u16 devid;
+};
+
+enum {
+   DELL_INSPIRON_7375 = 0,
+   DELL_LATITUDE_5495,
+   LENOVO_IDEAPAD_330S_15ARR,
+};
+
+static const struct ivrs_quirk_entry ivrs_ioapic_quirks[][3] __initconst = {
+   /* ivrs_ioapic[4]=00:14.0 ivrs_ioapic[5]=00:00.2 */
+   [DELL_INSPIRON_7375] = {
+   { .id = 4, .devid = 0xa0 },
+   { .id = 5, .devid = 0x2 },
+   {}
+   },
+   /* ivrs_ioapic[4]=00:14.0 */
+   [DELL_LATITUDE_5495] = {
+   { .id = 4, .devid = 0xa0 },
+   {}
+   },
+   /* ivrs_ioapic[32]=00:14.0 */
+   [LENOVO_IDEAPAD_330S_15ARR] = {
+   { .id = 32, .devid = 0xa0 },
+   {}
+   },
+   {}
+};
+
+static int __init ivrs_ioapic_quirk_cb(const struct dmi_system_id *d)
+{
+   const struct ivrs_quirk_entry *i;
+
+   for (i = d->driver_data; i->id != 0 && i->devid != 0; i++)
+   add_special_device(IVHD_SPECIAL_IOAPIC, i->id, (u16 
*)&i->devid, 0);
+
+   return 0;
+}
+
+static const struct dmi_system_id ivrs_quirks[] __initconst = {
+   {
+   .callback = ivrs_ioapic_quirk_cb,
+   .ident = "Dell Inspiron 7375",
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+   DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7375"),
+   },
+   .driver_dat

[PATCH AUTOSEL 4.19 097/128] iommu/iova: Avoid false sharing on fq_timer_on

2019-09-22 Thread Sasha Levin
From: Eric Dumazet 

[ Upstream commit 0d87308cca2c124f9bce02383f1d9632c9be89c4 ]

In commit 14bd9a607f90 ("iommu/iova: Separate atomic variables
to improve performance") Jinyu Qi identified that the atomic_cmpxchg()
in queue_iova() was causing a performance loss and moved critical fields
so that the false sharing would not impact them.

However, avoiding the false sharing in the first place seems easy.
We should attempt the atomic_cmpxchg() no more than 100 times
per second. Adding an atomic_read() will keep the cache
line mostly shared.

This false sharing came with commit 9a005a800ae8
("iommu/iova: Add flush timer").

Signed-off-by: Eric Dumazet 
Fixes: 9a005a800ae8 ('iommu/iova: Add flush timer')
Cc: Jinyu Qi 
Cc: Joerg Roedel 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iova.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 9a576ae837dcb..da4516fbf5425 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -580,7 +580,9 @@ void queue_iova(struct iova_domain *iovad,
 
spin_unlock_irqrestore(&fq->lock, flags);
 
-   if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0)
+   /* Avoid false sharing as much as possible. */
+   if (!atomic_read(&iovad->fq_timer_on) &&
+   !atomic_cmpxchg(&iovad->fq_timer_on, 0, 1))
mod_timer(&iovad->fq_timer,
  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 095/128] iommu/amd: Silence warnings under memory pressure

2019-09-22 Thread Sasha Levin
From: Qian Cai 

[ Upstream commit 3d708895325b78506e8daf00ef31549476e8586a ]

When running heavy memory pressure workloads, the system is throwing
endless warnings,

smartpqi :23:00.0: AMD-Vi: IOMMU mapping error in map_sg (io-pages:
5 reason: -12)
Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40
07/10/2019
swapper/10: page allocation failure: order:0, mode:0xa20(GFP_ATOMIC),
nodemask=(null),cpuset=/,mems_allowed=0,4
Call Trace:
 
 dump_stack+0x62/0x9a
 warn_alloc.cold.43+0x8a/0x148
 __alloc_pages_nodemask+0x1a5c/0x1bb0
 get_zeroed_page+0x16/0x20
 iommu_map_page+0x477/0x540
 map_sg+0x1ce/0x2f0
 scsi_dma_map+0xc6/0x160
 pqi_raid_submit_scsi_cmd_with_io_request+0x1c3/0x470 [smartpqi]
 do_IRQ+0x81/0x170
 common_interrupt+0xf/0xf
 

because the allocation could fail from iommu_map_page(), and the volume
of this call could be huge which may generate a lot of serial console
output and cosumes all CPUs.

Fix it by silencing the warning in this call site, and there is still a
dev_err() later to notify the failure.

Signed-off-by: Qian Cai 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 8d9920ff41344..b892637c320bc 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2533,7 +2533,9 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
 
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
phys_addr = (sg_phys(s) & PAGE_MASK) + (j << 
PAGE_SHIFT);
-   ret = iommu_map_page(domain, bus_addr, phys_addr, 
PAGE_SIZE, prot, GFP_ATOMIC);
+   ret = iommu_map_page(domain, bus_addr, phys_addr,
+PAGE_SIZE, prot,
+GFP_ATOMIC | __GFP_NOWARN);
if (ret)
goto out_unmap;
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 179/185] iommu/amd: Override wrong IVRS IOAPIC on Raven Ridge systems

2019-09-22 Thread Sasha Levin
From: Kai-Heng Feng 

[ Upstream commit 93d051550ee02eaff9a2541d825605a7bd778027 ]

Raven Ridge systems may have malfunction touchpad or hang at boot if
incorrect IVRS IOAPIC is provided by BIOS.

Users already found correct "ivrs_ioapic=" values, let's put them inside
kernel to workaround buggy BIOS.

BugLink: https://bugs.launchpad.net/bugs/1795292
BugLink: https://bugs.launchpad.net/bugs/1837688
Reported-by: kbuild test robot 
Signed-off-by: Kai-Heng Feng 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/Makefile   |  2 +-
 drivers/iommu/amd_iommu.h| 14 +
 drivers/iommu/amd_iommu_init.c   |  5 +-
 drivers/iommu/amd_iommu_quirks.c | 92 
 4 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu.h
 create mode 100644 drivers/iommu/amd_iommu_quirks.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 8c71a15e986b5..826a5bbe0d09b 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
diff --git a/drivers/iommu/amd_iommu.h b/drivers/iommu/amd_iommu.h
new file mode 100644
index 0..12d540d9b59b0
--- /dev/null
+++ b/drivers/iommu/amd_iommu.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef AMD_IOMMU_H
+#define AMD_IOMMU_H
+
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line);
+
+#ifdef CONFIG_DMI
+void amd_iommu_apply_ivrs_quirks(void);
+#else
+static void amd_iommu_apply_ivrs_quirks(void) { }
+#endif
+
+#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 07d84dbab564e..6469f51282427 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -30,6 +30,7 @@
 #include 
 
 #include 
+#include "amd_iommu.h"
 #include "amd_iommu_proto.h"
 #include "amd_iommu_types.h"
 #include "irq_remapping.h"
@@ -997,7 +998,7 @@ static void __init set_dev_entry_from_acpi(struct amd_iommu 
*iommu,
set_iommu_for_device(iommu, devid);
 }
 
-static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
 {
struct devid_map *entry;
struct list_head *list;
@@ -1148,6 +1149,8 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
if (ret)
return ret;
 
+   amd_iommu_apply_ivrs_quirks();
+
/*
 * First save the recommended feature enable bits from ACPI
 */
diff --git a/drivers/iommu/amd_iommu_quirks.c b/drivers/iommu/amd_iommu_quirks.c
new file mode 100644
index 0..c235f79b7a200
--- /dev/null
+++ b/drivers/iommu/amd_iommu_quirks.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Quirks for AMD IOMMU
+ *
+ * Copyright (C) 2019 Kai-Heng Feng 
+ */
+
+#ifdef CONFIG_DMI
+#include 
+
+#include "amd_iommu.h"
+
+#define IVHD_SPECIAL_IOAPIC1
+
+struct ivrs_quirk_entry {
+   u8 id;
+   u16 devid;
+};
+
+enum {
+   DELL_INSPIRON_7375 = 0,
+   DELL_LATITUDE_5495,
+   LENOVO_IDEAPAD_330S_15ARR,
+};
+
+static const struct ivrs_quirk_entry ivrs_ioapic_quirks[][3] __initconst = {
+   /* ivrs_ioapic[4]=00:14.0 ivrs_ioapic[5]=00:00.2 */
+   [DELL_INSPIRON_7375] = {
+   { .id = 4, .devid = 0xa0 },
+   { .id = 5, .devid = 0x2 },
+   {}
+   },
+   /* ivrs_ioapic[4]=00:14.0 */
+   [DELL_LATITUDE_5495] = {
+   { .id = 4, .devid = 0xa0 },
+   {}
+   },
+   /* ivrs_ioapic[32]=00:14.0 */
+   [LENOVO_IDEAPAD_330S_15ARR] = {
+   { .id = 32, .devid = 0xa0 },
+   {}
+   },
+   {}
+};
+
+static int __init ivrs_ioapic_quirk_cb(const struct dmi_system_id *d)
+{
+   const struct ivrs_quirk_entry *i;
+
+   for (i = d->driver_data; i->id != 0 && i->devid != 0; i++)
+   add_special_device(IVHD_SPECIAL_IOAPIC, i->id, (u16 
*)&i->devid, 0);
+
+   return 0;
+}
+
+static const struct dmi_system_id ivrs_quirks[] __initconst = {
+   {
+   .callback = ivrs_ioapic_quirk_cb,
+   .ident = "Dell Inspiron 7375",
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+   DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7375"),
+   },
+   .driver_dat

[PATCH AUTOSEL 5.2 135/185] iommu/amd: Silence warnings under memory pressure

2019-09-22 Thread Sasha Levin
From: Qian Cai 

[ Upstream commit 3d708895325b78506e8daf00ef31549476e8586a ]

When running heavy memory pressure workloads, the system is throwing
endless warnings,

smartpqi :23:00.0: AMD-Vi: IOMMU mapping error in map_sg (io-pages:
5 reason: -12)
Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40
07/10/2019
swapper/10: page allocation failure: order:0, mode:0xa20(GFP_ATOMIC),
nodemask=(null),cpuset=/,mems_allowed=0,4
Call Trace:
 
 dump_stack+0x62/0x9a
 warn_alloc.cold.43+0x8a/0x148
 __alloc_pages_nodemask+0x1a5c/0x1bb0
 get_zeroed_page+0x16/0x20
 iommu_map_page+0x477/0x540
 map_sg+0x1ce/0x2f0
 scsi_dma_map+0xc6/0x160
 pqi_raid_submit_scsi_cmd_with_io_request+0x1c3/0x470 [smartpqi]
 do_IRQ+0x81/0x170
 common_interrupt+0xf/0xf
 

because the allocation could fail from iommu_map_page(), and the volume
of this call could be huge which may generate a lot of serial console
output and cosumes all CPUs.

Fix it by silencing the warning in this call site, and there is still a
dev_err() later to notify the failure.

Signed-off-by: Qian Cai 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index dce1d8d2e8a44..2bbe931c3585e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2540,7 +2540,9 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
 
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
phys_addr = (sg_phys(s) & PAGE_MASK) + (j << 
PAGE_SHIFT);
-   ret = iommu_map_page(domain, bus_addr, phys_addr, 
PAGE_SIZE, prot, GFP_ATOMIC);
+   ret = iommu_map_page(domain, bus_addr, phys_addr,
+PAGE_SIZE, prot,
+GFP_ATOMIC | __GFP_NOWARN);
if (ret)
goto out_unmap;
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 138/185] iommu/iova: Avoid false sharing on fq_timer_on

2019-09-22 Thread Sasha Levin
From: Eric Dumazet 

[ Upstream commit 0d87308cca2c124f9bce02383f1d9632c9be89c4 ]

In commit 14bd9a607f90 ("iommu/iova: Separate atomic variables
to improve performance") Jinyu Qi identified that the atomic_cmpxchg()
in queue_iova() was causing a performance loss and moved critical fields
so that the false sharing would not impact them.

However, avoiding the false sharing in the first place seems easy.
We should attempt the atomic_cmpxchg() no more than 100 times
per second. Adding an atomic_read() will keep the cache
line mostly shared.

This false sharing came with commit 9a005a800ae8
("iommu/iova: Add flush timer").

Signed-off-by: Eric Dumazet 
Fixes: 9a005a800ae8 ('iommu/iova: Add flush timer')
Cc: Jinyu Qi 
Cc: Joerg Roedel 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iova.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 3e1a8a6755723..41c605b0058f9 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -577,7 +577,9 @@ void queue_iova(struct iova_domain *iovad,
 
spin_unlock_irqrestore(&fq->lock, flags);
 
-   if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0)
+   /* Avoid false sharing as much as possible. */
+   if (!atomic_read(&iovad->fq_timer_on) &&
+   !atomic_cmpxchg(&iovad->fq_timer_on, 0, 1))
mod_timer(&iovad->fq_timer,
  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.3 197/203] iommu/amd: Override wrong IVRS IOAPIC on Raven Ridge systems

2019-09-22 Thread Sasha Levin
From: Kai-Heng Feng 

[ Upstream commit 93d051550ee02eaff9a2541d825605a7bd778027 ]

Raven Ridge systems may have malfunction touchpad or hang at boot if
incorrect IVRS IOAPIC is provided by BIOS.

Users already found correct "ivrs_ioapic=" values, let's put them inside
kernel to workaround buggy BIOS.

BugLink: https://bugs.launchpad.net/bugs/1795292
BugLink: https://bugs.launchpad.net/bugs/1837688
Reported-by: kbuild test robot 
Signed-off-by: Kai-Heng Feng 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/Makefile   |  2 +-
 drivers/iommu/amd_iommu.h| 14 +
 drivers/iommu/amd_iommu_init.c   |  5 +-
 drivers/iommu/amd_iommu_quirks.c | 92 
 4 files changed, 111 insertions(+), 2 deletions(-)
 create mode 100644 drivers/iommu/amd_iommu.h
 create mode 100644 drivers/iommu/amd_iommu_quirks.c

diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index f13f36ae1af65..c6a277e698484 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -10,7 +10,7 @@ obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
 obj-$(CONFIG_IOMMU_IOVA) += iova.o
 obj-$(CONFIG_OF_IOMMU) += of_iommu.o
 obj-$(CONFIG_MSM_IOMMU) += msm_iommu.o
-obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o
+obj-$(CONFIG_AMD_IOMMU) += amd_iommu.o amd_iommu_init.o amd_iommu_quirks.o
 obj-$(CONFIG_AMD_IOMMU_DEBUGFS) += amd_iommu_debugfs.o
 obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
diff --git a/drivers/iommu/amd_iommu.h b/drivers/iommu/amd_iommu.h
new file mode 100644
index 0..12d540d9b59b0
--- /dev/null
+++ b/drivers/iommu/amd_iommu.h
@@ -0,0 +1,14 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+#ifndef AMD_IOMMU_H
+#define AMD_IOMMU_H
+
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line);
+
+#ifdef CONFIG_DMI
+void amd_iommu_apply_ivrs_quirks(void);
+#else
+static void amd_iommu_apply_ivrs_quirks(void) { }
+#endif
+
+#endif
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 4413aa67000e5..568c52317757c 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -32,6 +32,7 @@
 #include 
 
 #include 
+#include "amd_iommu.h"
 #include "amd_iommu_proto.h"
 #include "amd_iommu_types.h"
 #include "irq_remapping.h"
@@ -1002,7 +1003,7 @@ static void __init set_dev_entry_from_acpi(struct 
amd_iommu *iommu,
set_iommu_for_device(iommu, devid);
 }
 
-static int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
+int __init add_special_device(u8 type, u8 id, u16 *devid, bool cmd_line)
 {
struct devid_map *entry;
struct list_head *list;
@@ -1153,6 +1154,8 @@ static int __init init_iommu_from_acpi(struct amd_iommu 
*iommu,
if (ret)
return ret;
 
+   amd_iommu_apply_ivrs_quirks();
+
/*
 * First save the recommended feature enable bits from ACPI
 */
diff --git a/drivers/iommu/amd_iommu_quirks.c b/drivers/iommu/amd_iommu_quirks.c
new file mode 100644
index 0..c235f79b7a200
--- /dev/null
+++ b/drivers/iommu/amd_iommu_quirks.c
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+
+/*
+ * Quirks for AMD IOMMU
+ *
+ * Copyright (C) 2019 Kai-Heng Feng 
+ */
+
+#ifdef CONFIG_DMI
+#include 
+
+#include "amd_iommu.h"
+
+#define IVHD_SPECIAL_IOAPIC1
+
+struct ivrs_quirk_entry {
+   u8 id;
+   u16 devid;
+};
+
+enum {
+   DELL_INSPIRON_7375 = 0,
+   DELL_LATITUDE_5495,
+   LENOVO_IDEAPAD_330S_15ARR,
+};
+
+static const struct ivrs_quirk_entry ivrs_ioapic_quirks[][3] __initconst = {
+   /* ivrs_ioapic[4]=00:14.0 ivrs_ioapic[5]=00:00.2 */
+   [DELL_INSPIRON_7375] = {
+   { .id = 4, .devid = 0xa0 },
+   { .id = 5, .devid = 0x2 },
+   {}
+   },
+   /* ivrs_ioapic[4]=00:14.0 */
+   [DELL_LATITUDE_5495] = {
+   { .id = 4, .devid = 0xa0 },
+   {}
+   },
+   /* ivrs_ioapic[32]=00:14.0 */
+   [LENOVO_IDEAPAD_330S_15ARR] = {
+   { .id = 32, .devid = 0xa0 },
+   {}
+   },
+   {}
+};
+
+static int __init ivrs_ioapic_quirk_cb(const struct dmi_system_id *d)
+{
+   const struct ivrs_quirk_entry *i;
+
+   for (i = d->driver_data; i->id != 0 && i->devid != 0; i++)
+   add_special_device(IVHD_SPECIAL_IOAPIC, i->id, (u16 
*)&i->devid, 0);
+
+   return 0;
+}
+
+static const struct dmi_system_id ivrs_quirks[] __initconst = {
+   {
+   .callback = ivrs_ioapic_quirk_cb,
+   .ident = "Dell Inspiron 7375",
+   .matches = {
+   DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."),
+   DMI_MATCH(DMI_PRODUCT_NAME, "Inspiron 7375"),
+   },
+   .driver_dat

[PATCH AUTOSEL 5.3 152/203] iommu/iova: Avoid false sharing on fq_timer_on

2019-09-22 Thread Sasha Levin
From: Eric Dumazet 

[ Upstream commit 0d87308cca2c124f9bce02383f1d9632c9be89c4 ]

In commit 14bd9a607f90 ("iommu/iova: Separate atomic variables
to improve performance") Jinyu Qi identified that the atomic_cmpxchg()
in queue_iova() was causing a performance loss and moved critical fields
so that the false sharing would not impact them.

However, avoiding the false sharing in the first place seems easy.
We should attempt the atomic_cmpxchg() no more than 100 times
per second. Adding an atomic_read() will keep the cache
line mostly shared.

This false sharing came with commit 9a005a800ae8
("iommu/iova: Add flush timer").

Signed-off-by: Eric Dumazet 
Fixes: 9a005a800ae8 ('iommu/iova: Add flush timer')
Cc: Jinyu Qi 
Cc: Joerg Roedel 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iova.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 3e1a8a6755723..41c605b0058f9 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -577,7 +577,9 @@ void queue_iova(struct iova_domain *iovad,
 
spin_unlock_irqrestore(&fq->lock, flags);
 
-   if (atomic_cmpxchg(&iovad->fq_timer_on, 0, 1) == 0)
+   /* Avoid false sharing as much as possible. */
+   if (!atomic_read(&iovad->fq_timer_on) &&
+   !atomic_cmpxchg(&iovad->fq_timer_on, 0, 1))
mod_timer(&iovad->fq_timer,
  jiffies + msecs_to_jiffies(IOVA_FQ_TIMEOUT));
 }
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.3 149/203] iommu/amd: Silence warnings under memory pressure

2019-09-22 Thread Sasha Levin
From: Qian Cai 

[ Upstream commit 3d708895325b78506e8daf00ef31549476e8586a ]

When running heavy memory pressure workloads, the system is throwing
endless warnings,

smartpqi :23:00.0: AMD-Vi: IOMMU mapping error in map_sg (io-pages:
5 reason: -12)
Hardware name: HPE ProLiant DL385 Gen10/ProLiant DL385 Gen10, BIOS A40
07/10/2019
swapper/10: page allocation failure: order:0, mode:0xa20(GFP_ATOMIC),
nodemask=(null),cpuset=/,mems_allowed=0,4
Call Trace:
 
 dump_stack+0x62/0x9a
 warn_alloc.cold.43+0x8a/0x148
 __alloc_pages_nodemask+0x1a5c/0x1bb0
 get_zeroed_page+0x16/0x20
 iommu_map_page+0x477/0x540
 map_sg+0x1ce/0x2f0
 scsi_dma_map+0xc6/0x160
 pqi_raid_submit_scsi_cmd_with_io_request+0x1c3/0x470 [smartpqi]
 do_IRQ+0x81/0x170
 common_interrupt+0xf/0xf
 

because the allocation could fail from iommu_map_page(), and the volume
of this call could be huge which may generate a lot of serial console
output and cosumes all CPUs.

Fix it by silencing the warning in this call site, and there is still a
dev_err() later to notify the failure.

Signed-off-by: Qian Cai 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 61de81965c44e..e1259429ded2f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2577,7 +2577,9 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
 
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
phys_addr = (sg_phys(s) & PAGE_MASK) + (j << 
PAGE_SHIFT);
-   ret = iommu_map_page(domain, bus_addr, phys_addr, 
PAGE_SIZE, prot, GFP_ATOMIC);
+   ret = iommu_map_page(domain, bus_addr, phys_addr,
+PAGE_SIZE, prot,
+GFP_ATOMIC | __GFP_NOWARN);
if (ret)
goto out_unmap;
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 8/8] iommu/amd: Fix race in increase_address_space()

2019-09-09 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 754265bcab78a9014f0f99cd35e0d610fcd7dfa7 ]

After the conversion to lock-less dma-api call the
increase_address_space() function can be called without any
locking. Multiple CPUs could potentially race for increasing
the address space, leading to invalid domain->mode settings
and invalid page-tables. This has been happening in the wild
under high IO load and memory pressure.

Fix the race by locking this operation. The function is
called infrequently so that this does not introduce
a performance regression in the dma-api path again.

Reported-by: Qian Cai 
Fixes: 256e4621c21a ('iommu/amd: Make use of the generic IOVA allocator')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 8b79e2b32d378..69c269dc4f1bf 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1340,18 +1340,21 @@ static void domain_flush_devices(struct 
protection_domain *domain)
  * another level increases the size of the address space by 9 bits to a size up
  * to 64 bits.
  */
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
   gfp_t gfp)
 {
+   unsigned long flags;
u64 *pte;
 
-   if (domain->mode == PAGE_MODE_6_LEVEL)
+   spin_lock_irqsave(&domain->lock, flags);
+
+   if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
/* address space already 64 bit large */
-   return false;
+   goto out;
 
pte = (void *)get_zeroed_page(gfp);
if (!pte)
-   return false;
+   goto out;
 
*pte = PM_LEVEL_PDE(domain->mode,
iommu_virt_to_phys(domain->pt_root));
@@ -1359,7 +1362,10 @@ static bool increase_address_space(struct 
protection_domain *domain,
domain->mode+= 1;
domain->updated  = true;
 
-   return true;
+out:
+   spin_unlock_irqrestore(&domain->lock, flags);
+
+   return;
 }
 
 static u64 *alloc_pte(struct protection_domain *domain,
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 7/8] iommu/amd: Flush old domains in kdump kernel

2019-09-09 Thread Sasha Levin
From: Stuart Hayes 

[ Upstream commit 36b7200f67dfe75b416b5281ed4ace9927b513bc ]

When devices are attached to the amd_iommu in a kdump kernel, the old device
table entries (DTEs), which were copied from the crashed kernel, will be
overwritten with a new domain number.  When the new DTE is written, the IOMMU
is told to flush the DTE from its internal cache--but it is not told to flush
the translation cache entries for the old domain number.

Without this patch, AMD systems using the tg3 network driver fail when kdump
tries to save the vmcore to a network system, showing network timeouts and
(sometimes) IOMMU errors in the kernel log.

This patch will flush IOMMU translation cache entries for the old domain when
a DTE gets overwritten with a new domain number.

Signed-off-by: Stuart Hayes 
Fixes: 3ac3e5ee5ed5 ('iommu/amd: Copy old trans table from old kernel')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 684f7cdd814b6..822c85226a29f 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1150,6 +1150,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu 
*iommu)
iommu_completion_wait(iommu);
 }
 
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
+{
+   struct iommu_cmd cmd;
+
+   build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+ dom_id, 1);
+   iommu_queue_command(iommu, &cmd);
+
+   iommu_completion_wait(iommu);
+}
+
 static void amd_iommu_flush_all(struct amd_iommu *iommu)
 {
struct iommu_cmd cmd;
@@ -1835,6 +1846,7 @@ static void set_dte_entry(u16 devid, struct 
protection_domain *domain, bool ats)
 {
u64 pte_root = 0;
u64 flags = 0;
+   u32 old_domid;
 
if (domain->mode != PAGE_MODE_NONE)
pte_root = iommu_virt_to_phys(domain->pt_root);
@@ -1877,8 +1889,20 @@ static void set_dte_entry(u16 devid, struct 
protection_domain *domain, bool ats)
flags &= ~DEV_DOMID_MASK;
flags |= domain->id;
 
+   old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
amd_iommu_dev_table[devid].data[1]  = flags;
amd_iommu_dev_table[devid].data[0]  = pte_root;
+
+   /*
+* A kdump kernel might be replacing a domain ID that was copied from
+* the previous kernel--if so, it needs to flush the translation cache
+* entries for the old domain ID that is being overwritten
+*/
+   if (old_domid) {
+   struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+   amd_iommu_flush_tlb_domid(iommu, old_domid);
+   }
 }
 
 static void clear_dte_entry(u16 devid)
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 8/8] iommu/amd: Fix race in increase_address_space()

2019-09-09 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 754265bcab78a9014f0f99cd35e0d610fcd7dfa7 ]

After the conversion to lock-less dma-api call the
increase_address_space() function can be called without any
locking. Multiple CPUs could potentially race for increasing
the address space, leading to invalid domain->mode settings
and invalid page-tables. This has been happening in the wild
under high IO load and memory pressure.

Fix the race by locking this operation. The function is
called infrequently so that this does not introduce
a performance regression in the dma-api path again.

Reported-by: Qian Cai 
Fixes: 256e4621c21a ('iommu/amd: Make use of the generic IOVA allocator')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 822c85226a29f..a1174e61daf4e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1337,18 +1337,21 @@ static void domain_flush_devices(struct 
protection_domain *domain)
  * another level increases the size of the address space by 9 bits to a size up
  * to 64 bits.
  */
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
   gfp_t gfp)
 {
+   unsigned long flags;
u64 *pte;
 
-   if (domain->mode == PAGE_MODE_6_LEVEL)
+   spin_lock_irqsave(&domain->lock, flags);
+
+   if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
/* address space already 64 bit large */
-   return false;
+   goto out;
 
pte = (void *)get_zeroed_page(gfp);
if (!pte)
-   return false;
+   goto out;
 
*pte = PM_LEVEL_PDE(domain->mode,
iommu_virt_to_phys(domain->pt_root));
@@ -1356,7 +1359,10 @@ static bool increase_address_space(struct 
protection_domain *domain,
domain->mode+= 1;
domain->updated  = true;
 
-   return true;
+out:
+   spin_unlock_irqrestore(&domain->lock, flags);
+
+   return;
 }
 
 static u64 *alloc_pte(struct protection_domain *domain,
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 6/6] iommu/amd: Fix race in increase_address_space()

2019-09-09 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 754265bcab78a9014f0f99cd35e0d610fcd7dfa7 ]

After the conversion to lock-less dma-api call the
increase_address_space() function can be called without any
locking. Multiple CPUs could potentially race for increasing
the address space, leading to invalid domain->mode settings
and invalid page-tables. This has been happening in the wild
under high IO load and memory pressure.

Fix the race by locking this operation. The function is
called infrequently so that this does not introduce
a performance regression in the dma-api path again.

Reported-by: Qian Cai 
Fixes: 256e4621c21a ('iommu/amd: Make use of the generic IOVA allocator')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index c1233d0288a03..dd7880de7e4e9 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1321,18 +1321,21 @@ static void domain_flush_devices(struct 
protection_domain *domain)
  * another level increases the size of the address space by 9 bits to a size up
  * to 64 bits.
  */
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
   gfp_t gfp)
 {
+   unsigned long flags;
u64 *pte;
 
-   if (domain->mode == PAGE_MODE_6_LEVEL)
+   spin_lock_irqsave(&domain->lock, flags);
+
+   if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
/* address space already 64 bit large */
-   return false;
+   goto out;
 
pte = (void *)get_zeroed_page(gfp);
if (!pte)
-   return false;
+   goto out;
 
*pte = PM_LEVEL_PDE(domain->mode,
virt_to_phys(domain->pt_root));
@@ -1340,7 +1343,10 @@ static bool increase_address_space(struct 
protection_domain *domain,
domain->mode+= 1;
domain->updated  = true;
 
-   return true;
+out:
+   spin_unlock_irqrestore(&domain->lock, flags);
+
+   return;
 }
 
 static u64 *alloc_pte(struct protection_domain *domain,
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 7/8] iommu/amd: Flush old domains in kdump kernel

2019-09-09 Thread Sasha Levin
From: Stuart Hayes 

[ Upstream commit 36b7200f67dfe75b416b5281ed4ace9927b513bc ]

When devices are attached to the amd_iommu in a kdump kernel, the old device
table entries (DTEs), which were copied from the crashed kernel, will be
overwritten with a new domain number.  When the new DTE is written, the IOMMU
is told to flush the DTE from its internal cache--but it is not told to flush
the translation cache entries for the old domain number.

Without this patch, AMD systems using the tg3 network driver fail when kdump
tries to save the vmcore to a network system, showing network timeouts and
(sometimes) IOMMU errors in the kernel log.

This patch will flush IOMMU translation cache entries for the old domain when
a DTE gets overwritten with a new domain number.

Signed-off-by: Stuart Hayes 
Fixes: 3ac3e5ee5ed5 ('iommu/amd: Copy old trans table from old kernel')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 8d9920ff41344..8b79e2b32d378 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1153,6 +1153,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu 
*iommu)
iommu_completion_wait(iommu);
 }
 
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
+{
+   struct iommu_cmd cmd;
+
+   build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+ dom_id, 1);
+   iommu_queue_command(iommu, &cmd);
+
+   iommu_completion_wait(iommu);
+}
+
 static void amd_iommu_flush_all(struct amd_iommu *iommu)
 {
struct iommu_cmd cmd;
@@ -1838,6 +1849,7 @@ static void set_dte_entry(u16 devid, struct 
protection_domain *domain,
 {
u64 pte_root = 0;
u64 flags = 0;
+   u32 old_domid;
 
if (domain->mode != PAGE_MODE_NONE)
pte_root = iommu_virt_to_phys(domain->pt_root);
@@ -1887,8 +1899,20 @@ static void set_dte_entry(u16 devid, struct 
protection_domain *domain,
flags &= ~DEV_DOMID_MASK;
flags |= domain->id;
 
+   old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
amd_iommu_dev_table[devid].data[1]  = flags;
amd_iommu_dev_table[devid].data[0]  = pte_root;
+
+   /*
+* A kdump kernel might be replacing a domain ID that was copied from
+* the previous kernel--if so, it needs to flush the translation cache
+* entries for the old domain ID that is being overwritten
+*/
+   if (old_domid) {
+   struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+   amd_iommu_flush_tlb_domid(iommu, old_domid);
+   }
 }
 
 static void clear_dte_entry(u16 devid)
-- 
2.20.1



[PATCH AUTOSEL 5.2 12/12] iommu/amd: Fix race in increase_address_space()

2019-09-09 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 754265bcab78a9014f0f99cd35e0d610fcd7dfa7 ]

After the conversion to lock-less dma-api call the
increase_address_space() function can be called without any
locking. Multiple CPUs could potentially race for increasing
the address space, leading to invalid domain->mode settings
and invalid page-tables. This has been happening in the wild
under high IO load and memory pressure.

Fix the race by locking this operation. The function is
called infrequently so that this does not introduce
a performance regression in the dma-api path again.

Reported-by: Qian Cai 
Fixes: 256e4621c21a ('iommu/amd: Make use of the generic IOVA allocator')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 16 +++-
 1 file changed, 11 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b265062edf6c8..3e687f18b203a 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1425,18 +1425,21 @@ static void free_pagetable(struct protection_domain 
*domain)
  * another level increases the size of the address space by 9 bits to a size up
  * to 64 bits.
  */
-static bool increase_address_space(struct protection_domain *domain,
+static void increase_address_space(struct protection_domain *domain,
   gfp_t gfp)
 {
+   unsigned long flags;
u64 *pte;
 
-   if (domain->mode == PAGE_MODE_6_LEVEL)
+   spin_lock_irqsave(&domain->lock, flags);
+
+   if (WARN_ON_ONCE(domain->mode == PAGE_MODE_6_LEVEL))
/* address space already 64 bit large */
-   return false;
+   goto out;
 
pte = (void *)get_zeroed_page(gfp);
if (!pte)
-   return false;
+   goto out;
 
*pte = PM_LEVEL_PDE(domain->mode,
iommu_virt_to_phys(domain->pt_root));
@@ -1444,7 +1447,10 @@ static bool increase_address_space(struct 
protection_domain *domain,
domain->mode+= 1;
domain->updated  = true;
 
-   return true;
+out:
+   spin_unlock_irqrestore(&domain->lock, flags);
+
+   return;
 }
 
 static u64 *alloc_pte(struct protection_domain *domain,
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 07/12] iommu/vt-d: Remove global page flush support

2019-09-09 Thread Sasha Levin
From: Jacob Pan 

[ Upstream commit 8744daf4b0699b724ee0a56b313a6c0c4ea289e3 ]

Global pages support is removed from VT-d spec 3.0. Since global pages G
flag only affects first-level paging structures and because DMA request
with PASID are only supported by VT-d spec. 3.0 and onward, we can
safely remove global pages support.

For kernel shared virtual address IOTLB invalidation, PASID
granularity and page selective within PASID will be used. There is
no global granularity supported. Without this fix, IOTLB invalidation
will cause invalid descriptor error in the queued invalidation (QI)
interface.

Fixes: 1c4f88b7f1f9 ("iommu/vt-d: Shared virtual address in scalable mode")
Reported-by: Sanjay K Kumar 
Signed-off-by: Jacob Pan 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-svm.c   | 36 +++-
 include/linux/intel-iommu.h |  3 ---
 2 files changed, 15 insertions(+), 24 deletions(-)

diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index eceaa7e968ae8..641dc223c97b8 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -100,24 +100,19 @@ int intel_svm_finish_prq(struct intel_iommu *iommu)
 }
 
 static void intel_flush_svm_range_dev (struct intel_svm *svm, struct 
intel_svm_dev *sdev,
-  unsigned long address, unsigned long 
pages, int ih, int gl)
+   unsigned long address, unsigned long pages, int 
ih)
 {
struct qi_desc desc;
 
-   if (pages == -1) {
-   /* For global kernel pages we have to flush them in *all* PASIDs
-* because that's the only option the hardware gives us. Despite
-* the fact that they are actually only accessible through one. 
*/
-   if (gl)
-   desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
-   QI_EIOTLB_DID(sdev->did) |
-   QI_EIOTLB_GRAN(QI_GRAN_ALL_ALL) |
-   QI_EIOTLB_TYPE;
-   else
-   desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
-   QI_EIOTLB_DID(sdev->did) |
-   QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
-   QI_EIOTLB_TYPE;
+   /*
+* Do PASID granu IOTLB invalidation if page selective capability is
+* not available.
+*/
+   if (pages == -1 || !cap_pgsel_inv(svm->iommu->cap)) {
+   desc.qw0 = QI_EIOTLB_PASID(svm->pasid) |
+   QI_EIOTLB_DID(sdev->did) |
+   QI_EIOTLB_GRAN(QI_GRAN_NONG_PASID) |
+   QI_EIOTLB_TYPE;
desc.qw1 = 0;
} else {
int mask = ilog2(__roundup_pow_of_two(pages));
@@ -127,7 +122,6 @@ static void intel_flush_svm_range_dev (struct intel_svm 
*svm, struct intel_svm_d
QI_EIOTLB_GRAN(QI_GRAN_PSI_PASID) |
QI_EIOTLB_TYPE;
desc.qw1 = QI_EIOTLB_ADDR(address) |
-   QI_EIOTLB_GL(gl) |
QI_EIOTLB_IH(ih) |
QI_EIOTLB_AM(mask);
}
@@ -162,13 +156,13 @@ static void intel_flush_svm_range_dev (struct intel_svm 
*svm, struct intel_svm_d
 }
 
 static void intel_flush_svm_range(struct intel_svm *svm, unsigned long address,
- unsigned long pages, int ih, int gl)
+   unsigned long pages, int ih)
 {
struct intel_svm_dev *sdev;
 
rcu_read_lock();
list_for_each_entry_rcu(sdev, &svm->devs, list)
-   intel_flush_svm_range_dev(svm, sdev, address, pages, ih, gl);
+   intel_flush_svm_range_dev(svm, sdev, address, pages, ih);
rcu_read_unlock();
 }
 
@@ -180,7 +174,7 @@ static void intel_invalidate_range(struct mmu_notifier *mn,
struct intel_svm *svm = container_of(mn, struct intel_svm, notifier);
 
intel_flush_svm_range(svm, start,
- (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 
0, 0);
+ (end - start + PAGE_SIZE - 1) >> VTD_PAGE_SHIFT, 
0);
 }
 
 static void intel_mm_release(struct mmu_notifier *mn, struct mm_struct *mm)
@@ -203,7 +197,7 @@ static void intel_mm_release(struct mmu_notifier *mn, 
struct mm_struct *mm)
rcu_read_lock();
list_for_each_entry_rcu(sdev, &svm->devs, list) {
intel_pasid_tear_down_entry(svm->iommu, sdev->dev, svm->pasid);
-   intel_flush_svm_range_dev(svm, sdev, 0, -1, 0, !svm->mm);
+   intel_flush_svm_range_dev(svm, sdev, 0, -1, 0);
}
rcu_read_unlock();
 
@@ -410,7 +404,7 @@ int intel_svm_unbind_mm(struct device *dev, int pasid)
 

[PATCH AUTOSEL 5.2 11/12] iommu/amd: Flush old domains in kdump kernel

2019-09-09 Thread Sasha Levin
From: Stuart Hayes 

[ Upstream commit 36b7200f67dfe75b416b5281ed4ace9927b513bc ]

When devices are attached to the amd_iommu in a kdump kernel, the old device
table entries (DTEs), which were copied from the crashed kernel, will be
overwritten with a new domain number.  When the new DTE is written, the IOMMU
is told to flush the DTE from its internal cache--but it is not told to flush
the translation cache entries for the old domain number.

Without this patch, AMD systems using the tg3 network driver fail when kdump
tries to save the vmcore to a network system, showing network timeouts and
(sometimes) IOMMU errors in the kernel log.

This patch will flush IOMMU translation cache entries for the old domain when
a DTE gets overwritten with a new domain number.

Signed-off-by: Stuart Hayes 
Fixes: 3ac3e5ee5ed5 ('iommu/amd: Copy old trans table from old kernel')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 24 
 1 file changed, 24 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index dce1d8d2e8a44..b265062edf6c8 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1143,6 +1143,17 @@ static void amd_iommu_flush_tlb_all(struct amd_iommu 
*iommu)
iommu_completion_wait(iommu);
 }
 
+static void amd_iommu_flush_tlb_domid(struct amd_iommu *iommu, u32 dom_id)
+{
+   struct iommu_cmd cmd;
+
+   build_inv_iommu_pages(&cmd, 0, CMD_INV_IOMMU_ALL_PAGES_ADDRESS,
+ dom_id, 1);
+   iommu_queue_command(iommu, &cmd);
+
+   iommu_completion_wait(iommu);
+}
+
 static void amd_iommu_flush_all(struct amd_iommu *iommu)
 {
struct iommu_cmd cmd;
@@ -1863,6 +1874,7 @@ static void set_dte_entry(u16 devid, struct 
protection_domain *domain,
 {
u64 pte_root = 0;
u64 flags = 0;
+   u32 old_domid;
 
if (domain->mode != PAGE_MODE_NONE)
pte_root = iommu_virt_to_phys(domain->pt_root);
@@ -1912,8 +1924,20 @@ static void set_dte_entry(u16 devid, struct 
protection_domain *domain,
flags &= ~DEV_DOMID_MASK;
flags |= domain->id;
 
+   old_domid = amd_iommu_dev_table[devid].data[1] & DEV_DOMID_MASK;
amd_iommu_dev_table[devid].data[1]  = flags;
amd_iommu_dev_table[devid].data[0]  = pte_root;
+
+   /*
+* A kdump kernel might be replacing a domain ID that was copied from
+* the previous kernel--if so, it needs to flush the translation cache
+* entries for the old domain ID that is being overwritten
+*/
+   if (old_domid) {
+   struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+   amd_iommu_flush_tlb_domid(iommu, old_domid);
+   }
 }
 
 static void clear_dte_entry(u16 devid)
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 150/167] iommu/iova: Remove stale cached32_node

2019-09-03 Thread Sasha Levin
 buggy address belongs to the page:
[   48.484006] page:ea001c3f0600 refcount:1 mapcount:0 
mapping:181a91c0 index:0x0 compound_mapcount: 0
[   48.484045] flags: 0x80010200(slab|head)
[   48.484096] raw: 80010200 ea001c421a08 ea001c447e88 
181a91c0
[   48.484141] raw:  00120012 0001 

[   48.484188] page dumped because: kasan: bad access detected
[   48.484230]
[   48.484265] Memory state around the buggy address:
[   48.484314]  88870fc18f00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[   48.484361]  88870fc18f80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[   48.484406] >88870fc19000: fb fb fb fb fb fc fc fc fc fc fc fc fc fc fc 
fc
[   48.484451]^
[   48.484494]  88870fc19080: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc
[   48.484530]  88870fc19100: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc 
fc

Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=108602
Fixes: e60aa7b53845 ("iommu/iova: Extend rbtree node caching")
Signed-off-by: Chris Wilson 
Cc: Robin Murphy 
Cc: Joerg Roedel 
Cc: Joerg Roedel 
Cc:  # v4.15+
Reviewed-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iova.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/iova.c b/drivers/iommu/iova.c
index 60348d707b993..9a576ae837dcb 100644
--- a/drivers/iommu/iova.c
+++ b/drivers/iommu/iova.c
@@ -148,8 +148,9 @@ __cached_rbnode_delete_update(struct iova_domain *iovad, 
struct iova *free)
struct iova *cached_iova;
 
cached_iova = rb_entry(iovad->cached32_node, struct iova, node);
-   if (free->pfn_hi < iovad->dma_32bit_pfn &&
-   free->pfn_lo >= cached_iova->pfn_lo)
+   if (free == cached_iova ||
+   (free->pfn_hi < iovad->dma_32bit_pfn &&
+free->pfn_lo >= cached_iova->pfn_lo))
iovad->cached32_node = rb_next(&free->node);
 
cached_iova = rb_entry(iovad->cached_node, struct iova, node);
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 2/7] iommu/dma: Handle SG length overflow better

2019-08-20 Thread Sasha Levin
From: Robin Murphy 

[ Upstream commit ab2cbeb0ed301a9f0460078e91b09f39958212ef ]

Since scatterlist dimensions are all unsigned ints, in the relatively
rare cases where a device's max_segment_size is set to UINT_MAX, then
the "cur_len + s_length <= max_len" check in __finalise_sg() will always
return true. As a result, the corner case of such a device mapping an
excessively large scatterlist which is mergeable to or beyond a total
length of 4GB can lead to overflow and a bogus truncated dma_length in
the resulting segment.

As we already assume that any single segment must be no longer than
max_len to begin with, this can easily be addressed by reshuffling the
comparison.

Fixes: 809eac54cdd6 ("iommu/dma: Implement scatterlist segment merging")
Reported-by: Nicolin Chen 
Tested-by: Nicolin Chen 
Signed-off-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dma-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 1520e7f02c2f1..89d191b6a0e0f 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -493,7 +493,7 @@ static int __finalise_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 * - and wouldn't make the resulting output segment too long
 */
if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
-   (cur_len + s_length <= max_len)) {
+   (max_len - cur_len >= s_length)) {
/* ...then concatenate it with the previous one */
cur_len += s_length;
} else {
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 04/12] iommu/dma: Handle SG length overflow better

2019-08-20 Thread Sasha Levin
From: Robin Murphy 

[ Upstream commit ab2cbeb0ed301a9f0460078e91b09f39958212ef ]

Since scatterlist dimensions are all unsigned ints, in the relatively
rare cases where a device's max_segment_size is set to UINT_MAX, then
the "cur_len + s_length <= max_len" check in __finalise_sg() will always
return true. As a result, the corner case of such a device mapping an
excessively large scatterlist which is mergeable to or beyond a total
length of 4GB can lead to overflow and a bogus truncated dma_length in
the resulting segment.

As we already assume that any single segment must be no longer than
max_len to begin with, this can easily be addressed by reshuffling the
comparison.

Fixes: 809eac54cdd6 ("iommu/dma: Implement scatterlist segment merging")
Reported-by: Nicolin Chen 
Tested-by: Nicolin Chen 
Signed-off-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dma-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 9d1cebe7f6cbb..c87764a4e2126 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -684,7 +684,7 @@ static int __finalise_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 * - and wouldn't make the resulting output segment too long
 */
if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
-   (cur_len + s_length <= max_len)) {
+   (max_len - cur_len >= s_length)) {
/* ...then concatenate it with the previous one */
cur_len += s_length;
} else {
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 17/27] iommu/dma: Handle SG length overflow better

2019-08-20 Thread Sasha Levin
From: Robin Murphy 

[ Upstream commit ab2cbeb0ed301a9f0460078e91b09f39958212ef ]

Since scatterlist dimensions are all unsigned ints, in the relatively
rare cases where a device's max_segment_size is set to UINT_MAX, then
the "cur_len + s_length <= max_len" check in __finalise_sg() will always
return true. As a result, the corner case of such a device mapping an
excessively large scatterlist which is mergeable to or beyond a total
length of 4GB can lead to overflow and a bogus truncated dma_length in
the resulting segment.

As we already assume that any single segment must be no longer than
max_len to begin with, this can easily be addressed by reshuffling the
comparison.

Fixes: 809eac54cdd6 ("iommu/dma: Implement scatterlist segment merging")
Reported-by: Nicolin Chen 
Tested-by: Nicolin Chen 
Signed-off-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dma-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 511ff9a1d6d94..f9dbb064f9571 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -675,7 +675,7 @@ static int __finalise_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 * - and wouldn't make the resulting output segment too long
 */
if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
-   (cur_len + s_length <= max_len)) {
+   (max_len - cur_len >= s_length)) {
/* ...then concatenate it with the previous one */
cur_len += s_length;
} else {
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 27/44] dma-direct: don't truncate dma_required_mask to bus addressing capabilities

2019-08-20 Thread Sasha Levin
From: Lucas Stach 

[ Upstream commit d8ad55538abe443919e20e0bb996561bca9cad84 ]

The dma required_mask needs to reflect the actual addressing capabilities
needed to handle the whole system RAM. When truncated down to the bus
addressing capabilities dma_addressing_limited() will incorrectly signal
no limitations for devices which are restricted by the bus_dma_mask.

Fixes: b4ebe6063204 (dma-direct: implement complete bus_dma_mask handling)
Signed-off-by: Lucas Stach 
Tested-by: Atish Patra 
Signed-off-by: Christoph Hellwig 
Signed-off-by: Sasha Levin 
---
 kernel/dma/direct.c | 3 ---
 1 file changed, 3 deletions(-)

diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 2c2772e9702ab..9912be7a970de 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -55,9 +55,6 @@ u64 dma_direct_get_required_mask(struct device *dev)
 {
u64 max_dma = phys_to_dma_direct(dev, (max_pfn - 1) << PAGE_SHIFT);
 
-   if (dev->bus_dma_mask && dev->bus_dma_mask < max_dma)
-   max_dma = dev->bus_dma_mask;
-
return (1ULL << (fls64(max_dma) - 1)) * 2 - 1;
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 26/44] iommu/dma: Handle SG length overflow better

2019-08-20 Thread Sasha Levin
From: Robin Murphy 

[ Upstream commit ab2cbeb0ed301a9f0460078e91b09f39958212ef ]

Since scatterlist dimensions are all unsigned ints, in the relatively
rare cases where a device's max_segment_size is set to UINT_MAX, then
the "cur_len + s_length <= max_len" check in __finalise_sg() will always
return true. As a result, the corner case of such a device mapping an
excessively large scatterlist which is mergeable to or beyond a total
length of 4GB can lead to overflow and a bogus truncated dma_length in
the resulting segment.

As we already assume that any single segment must be no longer than
max_len to begin with, this can easily be addressed by reshuffling the
comparison.

Fixes: 809eac54cdd6 ("iommu/dma: Implement scatterlist segment merging")
Reported-by: Nicolin Chen 
Tested-by: Nicolin Chen 
Signed-off-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dma-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 379318266468c..8c02d2283d647 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -710,7 +710,7 @@ static int __finalise_sg(struct device *dev, struct 
scatterlist *sg, int nents,
 * - and wouldn't make the resulting output segment too long
 */
if (cur_len && !s_iova_off && (dma_addr & seg_mask) &&
-   (cur_len + s_length <= max_len)) {
+   (max_len - cur_len >= s_length)) {
/* ...then concatenate it with the previous one */
cur_len += s_length;
} else {
-- 
2.20.1



[PATCH AUTOSEL 5.2 06/59] dma-mapping: check pfn validity in dma_common_{mmap, get_sgtable}

2019-08-06 Thread Sasha Levin
From: Christoph Hellwig 

[ Upstream commit 66d7780f18eae0232827fcffeaded39a6a168236 ]

Check that the pfn returned from arch_dma_coherent_to_pfn refers to
a valid page and reject the mmap / get_sgtable requests otherwise.

Based on the arm implementation of the mmap and get_sgtable methods.

Signed-off-by: Christoph Hellwig 
Tested-by: Vignesh Raghavendra 
Signed-off-by: Sasha Levin 
---
 kernel/dma/mapping.c | 13 +++--
 1 file changed, 11 insertions(+), 2 deletions(-)

diff --git a/kernel/dma/mapping.c b/kernel/dma/mapping.c
index f7afdadb6770b..3401382bbca2f 100644
--- a/kernel/dma/mapping.c
+++ b/kernel/dma/mapping.c
@@ -116,11 +116,16 @@ int dma_common_get_sgtable(struct device *dev, struct 
sg_table *sgt,
int ret;
 
if (!dev_is_dma_coherent(dev)) {
+   unsigned long pfn;
+
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
return -ENXIO;
 
-   page = pfn_to_page(arch_dma_coherent_to_pfn(dev, cpu_addr,
-   dma_addr));
+   /* If the PFN is not valid, we do not have a struct page */
+   pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+   if (!pfn_valid(pfn))
+   return -ENXIO;
+   page = pfn_to_page(pfn);
} else {
page = virt_to_page(cpu_addr);
}
@@ -170,7 +175,11 @@ int dma_common_mmap(struct device *dev, struct 
vm_area_struct *vma,
if (!dev_is_dma_coherent(dev)) {
if (!IS_ENABLED(CONFIG_ARCH_HAS_DMA_COHERENT_TO_PFN))
return -ENXIO;
+
+   /* If the PFN is not valid, we do not have a struct page */
pfn = arch_dma_coherent_to_pfn(dev, cpu_addr, dma_addr);
+   if (!pfn_valid(pfn))
+   return -ENXIO;
} else {
pfn = page_to_pfn(virt_to_page(cpu_addr));
}
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 40/76] iommu/vt-d: Check if domain->pgd was allocated

2019-08-02 Thread Sasha Levin
From: Dmitry Safonov 

[ Upstream commit 3ee9eca760e7d0b68c55813243de66bbb499dc3b ]

There is a couple of places where on domain_init() failure domain_exit()
is called. While currently domain_init() can fail only if
alloc_pgtable_page() has failed.

Make domain_exit() check if domain->pgd present, before calling
domain_unmap(), as it theoretically should crash on clearing pte entries
in dma_pte_clear_level().

Cc: David Woodhouse 
Cc: Joerg Roedel 
Cc: Lu Baolu 
Cc: iommu@lists.linux-foundation.org
Signed-off-by: Dmitry Safonov 
Reviewed-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2101601adf57d..1ad24367373f4 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1900,7 +1900,6 @@ static int domain_init(struct dmar_domain *domain, struct 
intel_iommu *iommu,
 
 static void domain_exit(struct dmar_domain *domain)
 {
-   struct page *freelist;
 
/* Remove associated devices and clear attached or cached domains */
rcu_read_lock();
@@ -1910,9 +1909,12 @@ static void domain_exit(struct dmar_domain *domain)
/* destroy iovas */
put_iova_domain(&domain->iovad);
 
-   freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+   if (domain->pgd) {
+   struct page *freelist;
 
-   dma_free_pagelist(freelist);
+   freelist = domain_unmap(domain, 0, DOMAIN_MAX_PFN(domain->gaw));
+   dma_free_pagelist(freelist);
+   }
 
free_domain_mem(domain);
 }
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 84/85] dma-direct: correct the physical addr in dma_direct_sync_sg_for_cpu/device

2019-07-26 Thread Sasha Levin
From: Fugang Duan 

[ Upstream commit 449fa54d6815be8c2c1f68fa9dbbae9384a7c03e ]

dma_map_sg() may use swiotlb buffer when the kernel command line includes
"swiotlb=force" or the dma_addr is out of dev->dma_mask range.  After
DMA complete the memory moving from device to memory, then user call
dma_sync_sg_for_cpu() to sync with DMA buffer, and copy the original
virtual buffer to other space.

So dma_direct_sync_sg_for_cpu() should use swiotlb physical addr, not
the original physical addr from sg_phys(sg).

dma_direct_sync_sg_for_device() also has the same issue, correct it as
well.

Fixes: 55897af63091("dma-direct: merge swiotlb_dma_ops into the dma_direct 
code")
Signed-off-by: Fugang Duan 
Reviewed-by: Robin Murphy 
Signed-off-by: Christoph Hellwig 
Signed-off-by: Sasha Levin 
---
 kernel/dma/direct.c | 18 +++---
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index 2c2772e9702a..2c6d51a62251 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -231,12 +231,14 @@ void dma_direct_sync_sg_for_device(struct device *dev,
int i;
 
for_each_sg(sgl, sg, nents, i) {
-   if (unlikely(is_swiotlb_buffer(sg_phys(sg
-   swiotlb_tbl_sync_single(dev, sg_phys(sg), sg->length,
+   phys_addr_t paddr = dma_to_phys(dev, sg_dma_address(sg));
+
+   if (unlikely(is_swiotlb_buffer(paddr)))
+   swiotlb_tbl_sync_single(dev, paddr, sg->length,
dir, SYNC_FOR_DEVICE);
 
if (!dev_is_dma_coherent(dev))
-   arch_sync_dma_for_device(dev, sg_phys(sg), sg->length,
+   arch_sync_dma_for_device(dev, paddr, sg->length,
dir);
}
 }
@@ -268,11 +270,13 @@ void dma_direct_sync_sg_for_cpu(struct device *dev,
int i;
 
for_each_sg(sgl, sg, nents, i) {
+   phys_addr_t paddr = dma_to_phys(dev, sg_dma_address(sg));
+
if (!dev_is_dma_coherent(dev))
-   arch_sync_dma_for_cpu(dev, sg_phys(sg), sg->length, 
dir);
-   
-   if (unlikely(is_swiotlb_buffer(sg_phys(sg
-   swiotlb_tbl_sync_single(dev, sg_phys(sg), sg->length, 
dir,
+   arch_sync_dma_for_cpu(dev, paddr, sg->length, dir);
+
+   if (unlikely(is_swiotlb_buffer(paddr)))
+   swiotlb_tbl_sync_single(dev, paddr, sg->length, dir,
SYNC_FOR_CPU);
}
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 18/85] swiotlb: fix phys_addr_t overflow warning

2019-07-26 Thread Sasha Levin
From: Arnd Bergmann 

[ Upstream commit 9c106119f6538f65bdddb7948a157d90625effa7 ]

On architectures that have a larger dma_addr_t than phys_addr_t,
the swiotlb_tbl_map_single() function truncates its return code
in the failure path, making it impossible to identify the error
later, as we compare to the original value:

kernel/dma/swiotlb.c:551:9: error: implicit conversion from 'dma_addr_t' (aka 
'unsigned long long') to 'phys_addr_t' (aka 'unsigned int') changes value from 
18446744073709551615 to 4294967295 [-Werror,-Wconstant-conversion]
return DMA_MAPPING_ERROR;

Use an explicit typecast here to convert it to the narrower type,
and use the same expression in the error handling later.

Fixes: b907e20508d0 ("swiotlb: remove SWIOTLB_MAP_ERROR")
Acked-by: Stefano Stabellini 
Signed-off-by: Arnd Bergmann 
Signed-off-by: Konrad Rzeszutek Wilk 
Signed-off-by: Sasha Levin 
---
 drivers/xen/swiotlb-xen.c | 2 +-
 kernel/dma/swiotlb.c  | 4 ++--
 2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/xen/swiotlb-xen.c b/drivers/xen/swiotlb-xen.c
index d53f3493a6b9..cfbe46785a3b 100644
--- a/drivers/xen/swiotlb-xen.c
+++ b/drivers/xen/swiotlb-xen.c
@@ -402,7 +402,7 @@ static dma_addr_t xen_swiotlb_map_page(struct device *dev, 
struct page *page,
 
map = swiotlb_tbl_map_single(dev, start_dma_addr, phys, size, dir,
 attrs);
-   if (map == DMA_MAPPING_ERROR)
+   if (map == (phys_addr_t)DMA_MAPPING_ERROR)
return DMA_MAPPING_ERROR;
 
dev_addr = xen_phys_to_bus(map);
diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index 13f0cb080a4d..5f4e1b78babb 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -546,7 +546,7 @@ phys_addr_t swiotlb_tbl_map_single(struct device *hwdev,
if (!(attrs & DMA_ATTR_NO_WARN) && printk_ratelimit())
dev_warn(hwdev, "swiotlb buffer is full (sz: %zd bytes), total 
%lu (slots), used %lu (slots)\n",
 size, io_tlb_nslabs, tmp_io_tlb_used);
-   return DMA_MAPPING_ERROR;
+   return (phys_addr_t)DMA_MAPPING_ERROR;
 found:
io_tlb_used += nslots;
spin_unlock_irqrestore(&io_tlb_lock, flags);
@@ -664,7 +664,7 @@ bool swiotlb_map(struct device *dev, phys_addr_t *phys, 
dma_addr_t *dma_addr,
/* Oh well, have to allocate and map a bounce buffer. */
*phys = swiotlb_tbl_map_single(dev, __phys_to_dma(dev, io_tlb_start),
*phys, size, dir, attrs);
-   if (*phys == DMA_MAPPING_ERROR)
+   if (*phys == (phys_addr_t)DMA_MAPPING_ERROR)
return false;
 
/* Ensure that the address returned is DMA'ble */
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] iommu/iova: Remove stale cached32_node

2019-07-20 Thread Sasha Levin
Hi,

[This is an automated email]

This commit has been processed because it contains a "Fixes:" tag,
fixing commit: e60aa7b53845 iommu/iova: Extend rbtree node caching.

The bot has tested the following trees: v5.2.1, v5.1.18, v4.19.59.

v5.2.1: Build OK!
v5.1.18: Build OK!
v4.19.59: Failed to apply! Possible dependencies:
bee60e94a1e2 ("iommu/iova: Optimise attempts to allocate iova from 32bit 
address range")


NOTE: The patch will not be queued to stable trees until it is upstream.

How should we proceed with this patch?

--
Thanks,
Sasha
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.1 044/141] dma-remap: Avoid de-referencing NULL atomic_pool

2019-07-18 Thread Sasha Levin
 ffc1366cfd40 
ff80082295d4
[   13.064645] fd20: 0004 ffc136577ec0 ffc136610cc0 
21670570
[   13.072590] fd40: ffc1366cfd80 ff80081b5d10 ff80097b6000 
ffc13aae4200
[   13.080536] fd60: ffc1366cfeb0 0004 21670570 
0004
[   13.088481] fd80: ffc1366cfe30 ff80081b6b20 ffc13aae4200 

[   13.096427] fda0: 0004 21670570 ffc1366cfeb0 
ffc13a838200
[   13.104371] fdc0:  000a ff80097b6000 
00040987
[   13.112316] fde0: ffc1366cfe20 ff80081b3af0 ffc13a838200 

[   13.120261] fe00: ffc1366cfe30 ff80081b6b0c ffc13aae4200 

[   13.128206] fe20: 0004 00040987 ffc1366cfe70 
ff80081b7dd8
[   13.136151] fe40: ff80097b6000 ffc13aae4200 ffc13aae4200 
fff7
[   13.144096] fe60: 21670570 ffc13a8c63c0  
ff8008083180
[   13.152042] fe80: ff1d 21670570  
007f917ad9b8
[   13.159986] fea0: 2000 0015  
00040987
[   13.167930] fec0: 0001 21670570 0004 

[   13.175874] fee0: 0888 44011000 006d 
0003
[   13.183819] ff00: 0040 ff80ffc8  
0020
[   13.191762] ff20:   0001 

[   13.199707] ff40:  007f917553e0  
0004
[   13.207651] ff60: 21670570 007f91835480 0004 
007f91831638
[   13.215595] ff80: 0004 004b0de0 004b 

[   13.223539] ffa0:  007fc92ac8c0 007f9175d178 
007fc92ac8c0
[   13.231483] ffc0: 007f917ad9b8 2000 0001 
0040
[   13.239427] ffe0:    

[   13.247360] Call trace:
[   13.249866] Exception stack(0xffc1366cf7a0 to 0xffc1366cf8d0)
[   13.256386] f7a0: 1000 007f ffc1366cf990 
ff80083c0df8
[   13.264331] f7c0: 6145 ff80089b5001 ffc13ab08130 
0001
[   13.272275] f7e0: 0008 ffc13a8568c8  

[   13.280220] f800: ffc1366cf960 ffc1366cf960 ffc1366cf930 
ffd8
[   13.288165] f820: ff8009931ac0 4554535953425553 4544006273753d4d 
3831633d45434956
[   13.296110] f840: 003832313a39 ff800845926c ffc1366cf880 
00040987
[   13.304054] f860:  ff8009c57000 0fff 
00013a5ff000
[   13.311999] f880:  ff800809797c ff80098febb1 
6c2062756820746f
[   13.319944] f8a0: 65776f702074736f 05f5e0ff ff80098feb7f 
fffe
[   13.327884] f8c0: 0030 
[   13.332835] [] addr_in_gen_pool+0x4/0x48
[   13.338398] [] xhci_mem_cleanup+0xc8/0x51c
[   13.344137] [] xhci_resume+0x308/0x65c
[   13.349524] [] xhci_brcm_resume+0x84/0x8c
[   13.355174] [] platform_pm_resume+0x3c/0x64
[   13.360997] [] dpm_run_callback+0x5c/0x15c
[   13.366732] [] device_resume+0xc0/0x190
[   13.372205] [] dpm_resume+0x144/0x2cc
[   13.377504] [] dpm_resume_end+0x20/0x34
[   13.382980] [] suspend_devices_and_enter+0x104/0x704
[   13.389585] [] pm_suspend+0x320/0x53c
[   13.394881] [] state_store+0xbc/0xe0
[   13.400094] [] kobj_attr_store+0x14/0x24
[   13.405655] [] sysfs_kf_write+0x60/0x70
[   13.411128] [] kernfs_fop_write+0x130/0x194
[   13.416954] [] __vfs_write+0x60/0x150
[   13.422254] [] vfs_write+0xc8/0x164
[   13.427376] [] SyS_write+0x70/0xc8
[   13.432412] [] el0_svc_naked+0x34/0x38
[   13.437800] Code: 92800173 97f6fb9e 17f5 d1000442 (f8408c03)
[   13.444033] ---[ end trace 2effe12f909ce205 ]---

The call path leading to this problem is xhci_mem_cleanup() ->
dma_free_coherent() -> dma_free_from_pool() -> addr_in_gen_pool. If the
atomic_pool is NULL, we can't possibly have the address in the atomic
pool anyway, so guard against that.

Signed-off-by: Florian Fainelli 
Signed-off-by: Christoph Hellwig 
Signed-off-by: Sasha Levin 
---
 kernel/dma/remap.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index 7a723194ecbe..0207e3764d52 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -158,6 +158,9 @@ int __init dma_atomic_pool_init(gfp_t gfp, pgprot_t prot)
 
 bool dma_in_atomic_pool(void *start, size_t size)
 {
+   if (unlikely(!atomic_pool))
+   return false;
+
return addr_in_gen_pool(atomic_pool, (unsigned long)start, size);
 }
 
-- 
2.20.1



[PATCH AUTOSEL 5.2 061/171] dma-remap: Avoid de-referencing NULL atomic_pool

2019-07-18 Thread Sasha Levin
 ffc1366cfd40 
ff80082295d4
[   13.064645] fd20: 0004 ffc136577ec0 ffc136610cc0 
21670570
[   13.072590] fd40: ffc1366cfd80 ff80081b5d10 ff80097b6000 
ffc13aae4200
[   13.080536] fd60: ffc1366cfeb0 0004 21670570 
0004
[   13.088481] fd80: ffc1366cfe30 ff80081b6b20 ffc13aae4200 

[   13.096427] fda0: 0004 21670570 ffc1366cfeb0 
ffc13a838200
[   13.104371] fdc0:  000a ff80097b6000 
00040987
[   13.112316] fde0: ffc1366cfe20 ff80081b3af0 ffc13a838200 

[   13.120261] fe00: ffc1366cfe30 ff80081b6b0c ffc13aae4200 

[   13.128206] fe20: 0004 00040987 ffc1366cfe70 
ff80081b7dd8
[   13.136151] fe40: ff80097b6000 ffc13aae4200 ffc13aae4200 
fff7
[   13.144096] fe60: 21670570 ffc13a8c63c0  
ff8008083180
[   13.152042] fe80: ff1d 21670570  
007f917ad9b8
[   13.159986] fea0: 2000 0015  
00040987
[   13.167930] fec0: 0001 21670570 0004 

[   13.175874] fee0: 0888 44011000 006d 
0003
[   13.183819] ff00: 0040 ff80ffc8  
0020
[   13.191762] ff20:   0001 

[   13.199707] ff40:  007f917553e0  
0004
[   13.207651] ff60: 21670570 007f91835480 0004 
007f91831638
[   13.215595] ff80: 0004 004b0de0 004b 

[   13.223539] ffa0:  007fc92ac8c0 007f9175d178 
007fc92ac8c0
[   13.231483] ffc0: 007f917ad9b8 2000 0001 
0040
[   13.239427] ffe0:    

[   13.247360] Call trace:
[   13.249866] Exception stack(0xffc1366cf7a0 to 0xffc1366cf8d0)
[   13.256386] f7a0: 1000 007f ffc1366cf990 
ff80083c0df8
[   13.264331] f7c0: 6145 ff80089b5001 ffc13ab08130 
0001
[   13.272275] f7e0: 0008 ffc13a8568c8  

[   13.280220] f800: ffc1366cf960 ffc1366cf960 ffc1366cf930 
ffd8
[   13.288165] f820: ff8009931ac0 4554535953425553 4544006273753d4d 
3831633d45434956
[   13.296110] f840: 003832313a39 ff800845926c ffc1366cf880 
00040987
[   13.304054] f860:  ff8009c57000 0fff 
00013a5ff000
[   13.311999] f880:  ff800809797c ff80098febb1 
6c2062756820746f
[   13.319944] f8a0: 65776f702074736f 05f5e0ff ff80098feb7f 
fffe
[   13.327884] f8c0: 0030 
[   13.332835] [] addr_in_gen_pool+0x4/0x48
[   13.338398] [] xhci_mem_cleanup+0xc8/0x51c
[   13.344137] [] xhci_resume+0x308/0x65c
[   13.349524] [] xhci_brcm_resume+0x84/0x8c
[   13.355174] [] platform_pm_resume+0x3c/0x64
[   13.360997] [] dpm_run_callback+0x5c/0x15c
[   13.366732] [] device_resume+0xc0/0x190
[   13.372205] [] dpm_resume+0x144/0x2cc
[   13.377504] [] dpm_resume_end+0x20/0x34
[   13.382980] [] suspend_devices_and_enter+0x104/0x704
[   13.389585] [] pm_suspend+0x320/0x53c
[   13.394881] [] state_store+0xbc/0xe0
[   13.400094] [] kobj_attr_store+0x14/0x24
[   13.405655] [] sysfs_kf_write+0x60/0x70
[   13.411128] [] kernfs_fop_write+0x130/0x194
[   13.416954] [] __vfs_write+0x60/0x150
[   13.422254] [] vfs_write+0xc8/0x164
[   13.427376] [] SyS_write+0x70/0xc8
[   13.432412] [] el0_svc_naked+0x34/0x38
[   13.437800] Code: 92800173 97f6fb9e 17f5 d1000442 (f8408c03)
[   13.444033] ---[ end trace 2effe12f909ce205 ]---

The call path leading to this problem is xhci_mem_cleanup() ->
dma_free_coherent() -> dma_free_from_pool() -> addr_in_gen_pool. If the
atomic_pool is NULL, we can't possibly have the address in the atomic
pool anyway, so guard against that.

Signed-off-by: Florian Fainelli 
Signed-off-by: Christoph Hellwig 
Signed-off-by: Sasha Levin 
---
 kernel/dma/remap.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/kernel/dma/remap.c b/kernel/dma/remap.c
index 7a723194ecbe..0207e3764d52 100644
--- a/kernel/dma/remap.c
+++ b/kernel/dma/remap.c
@@ -158,6 +158,9 @@ int __init dma_atomic_pool_init(gfp_t gfp, pgprot_t prot)
 
 bool dma_in_atomic_pool(void *start, size_t size)
 {
+   if (unlikely(!atomic_pool))
+   return false;
+
return addr_in_gen_pool(atomic_pool, (unsigned long)start, size);
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/ma

Re: [PATCH 1/2] iommu/vt-d: Don't queue_iova() if there is no flush queue

2019-07-16 Thread Sasha Levin
Hi,

[This is an automated email]

This commit has been processed because it contains a "Fixes:" tag,
fixing commit: 13cf01744608 iommu/vt-d: Make use of iova deferred flushing.

The bot has tested the following trees: v5.2.1, v5.1.18, v4.19.59, v4.14.133.

v5.2.1: Build OK!
v5.1.18: Build OK!
v4.19.59: Failed to apply! Possible dependencies:
02b4da5f84d1 ("intel-iommu: mark intel_dma_ops static")
0bbeb01a4faf ("iommu/vt-d: Manage scalalble mode PASID tables")
524a669bdd5f ("iommu/vt-d: remove the mapping_error dma_map_ops method")
932a6523ce39 ("iommu/vt-d: Use dev_printk() when possible")
964f2311a686 ("iommu/intel: small map_page cleanup")
ef848b7e5a6a ("iommu/vt-d: Setup pasid entry for RID2PASID support")
f7b0c4ce8cb3 ("iommu/vt-d: Flush IOTLB for untrusted device in time")

v4.14.133: Failed to apply! Possible dependencies:
0bbeb01a4faf ("iommu/vt-d: Manage scalalble mode PASID tables")
2e2e35d51279 ("iommu/vt-d: Missing checks for pasid tables if allocation 
fails")
2f13eb7c580f ("iommu/vt-d: Enable 5-level paging mode in the PASID entry")
3e781fcafedb ("iommu/vt-d: Remove unnecessary WARN_ON()")
4774cc524570 ("iommu/vt-d: Apply per pci device pasid table in SVA")
4fa064b26c2e ("iommu/vt-d: Clear pasid table entry when memory unbound")
524a669bdd5f ("iommu/vt-d: remove the mapping_error dma_map_ops method")
562831747f62 ("iommu/vt-d: Global PASID name space")
7ec916f82c48 ("Revert "iommu/intel-iommu: Enable CONFIG_DMA_DIRECT_OPS=y 
and clean up intel_{alloc,free}_coherent()"")
85319dcc8955 ("iommu/vt-d: Add for_each_device_domain() helper")
932a6523ce39 ("iommu/vt-d: Use dev_printk() when possible")
964f2311a686 ("iommu/intel: small map_page cleanup")
971401015d14 ("iommu/vt-d: Use real PASID for flush in caching mode")
9ddbfb42138d ("iommu/vt-d: Move device_domain_info to header")
a7fc93fed94b ("iommu/vt-d: Allocate and free pasid table")
af39507305fb ("iommu/vt-d: Apply global PASID in SVA")
be9e6598aeb0 ("iommu/vt-d: Handle memory shortage on pasid table 
allocation")
cc580e41260d ("iommu/vt-d: Per PCI device pasid table interfaces")
d657c5c73ca9 ("iommu/intel-iommu: Enable CONFIG_DMA_DIRECT_OPS=y and clean 
up intel_{alloc,free}_coherent()")
ef848b7e5a6a ("iommu/vt-d: Setup pasid entry for RID2PASID support")
f7b0c4ce8cb3 ("iommu/vt-d: Flush IOTLB for untrusted device in time")


NOTE: The patch will not be queued to stable trees until it is upstream.

How should we proceed with this patch?

--
Thanks,
Sasha
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 043/105] iommu: Fix a leak in iommu_insert_resv_region

2019-07-15 Thread Sasha Levin
From: Eric Auger 

[ Upstream commit ad0834dedaa15c3a176f783c0373f836e44b4700 ]

In case we expand an existing region, we unlink
this latter and insert the larger one. In
that case we should free the original region after
the insertion. Also we can immediately return.

Fixes: 6c65fb318e8b ("iommu: iommu_get_group_resv_regions")

Signed-off-by: Eric Auger 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iommu.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 3de5c0bcb5cc..1620a6f49989 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -205,18 +205,21 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
pos = pos->next;
} else if ((start >= a) && (end <= b)) {
if (new->type == type)
-   goto done;
+   return 0;
else
pos = pos->next;
} else {
if (new->type == type) {
phys_addr_t new_start = min(a, start);
phys_addr_t new_end = max(b, end);
+   int ret;
 
list_del(&entry->list);
entry->start = new_start;
entry->length = new_end - new_start + 1;
-   iommu_insert_resv_region(entry, regions);
+   ret = iommu_insert_resv_region(entry, regions);
+   kfree(entry);
+   return ret;
} else {
pos = pos->next;
}
@@ -229,7 +232,6 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
return -ENOMEM;
 
list_add_tail(®ion->list, pos);
-done:
return 0;
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 058/158] iommu: Fix a leak in iommu_insert_resv_region

2019-07-15 Thread Sasha Levin
From: Eric Auger 

[ Upstream commit ad0834dedaa15c3a176f783c0373f836e44b4700 ]

In case we expand an existing region, we unlink
this latter and insert the larger one. In
that case we should free the original region after
the insertion. Also we can immediately return.

Fixes: 6c65fb318e8b ("iommu: iommu_get_group_resv_regions")

Signed-off-by: Eric Auger 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iommu.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 8c15c5980299..bc14825edc9c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -211,18 +211,21 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
pos = pos->next;
} else if ((start >= a) && (end <= b)) {
if (new->type == type)
-   goto done;
+   return 0;
else
pos = pos->next;
} else {
if (new->type == type) {
phys_addr_t new_start = min(a, start);
phys_addr_t new_end = max(b, end);
+   int ret;
 
list_del(&entry->list);
entry->start = new_start;
entry->length = new_end - new_start + 1;
-   iommu_insert_resv_region(entry, regions);
+   ret = iommu_insert_resv_region(entry, regions);
+   kfree(entry);
+   return ret;
} else {
pos = pos->next;
}
@@ -235,7 +238,6 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
return -ENOMEM;
 
list_add_tail(®ion->list, pos);
-done:
return 0;
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.1 077/219] iommu: Fix a leak in iommu_insert_resv_region

2019-07-15 Thread Sasha Levin
From: Eric Auger 

[ Upstream commit ad0834dedaa15c3a176f783c0373f836e44b4700 ]

In case we expand an existing region, we unlink
this latter and insert the larger one. In
that case we should free the original region after
the insertion. Also we can immediately return.

Fixes: 6c65fb318e8b ("iommu: iommu_get_group_resv_regions")

Signed-off-by: Eric Auger 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iommu.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 109de67d5d72..2d06c507fbed 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -241,18 +241,21 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
pos = pos->next;
} else if ((start >= a) && (end <= b)) {
if (new->type == type)
-   goto done;
+   return 0;
else
pos = pos->next;
} else {
if (new->type == type) {
phys_addr_t new_start = min(a, start);
phys_addr_t new_end = max(b, end);
+   int ret;
 
list_del(&entry->list);
entry->start = new_start;
entry->length = new_end - new_start + 1;
-   iommu_insert_resv_region(entry, regions);
+   ret = iommu_insert_resv_region(entry, regions);
+   kfree(entry);
+   return ret;
} else {
pos = pos->next;
}
@@ -265,7 +268,6 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
return -ENOMEM;
 
list_add_tail(®ion->list, pos);
-done:
return 0;
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 229/249] iommu/arm-smmu-v3: Invalidate ATC when detaching a device

2019-07-15 Thread Sasha Levin
From: Jean-Philippe Brucker 

[ Upstream commit 8dd8f005bdd45823fc153ef490239558caf6ff20 ]

We make the invalid assumption in arm_smmu_detach_dev() that the ATC is
clear after calling pci_disable_ats(). For one thing, only enabling the
PCIe ATS capability constitutes an implicit invalidation event, so the
comment was wrong. More importantly, the ATS capability isn't necessarily
disabled by pci_disable_ats() in a PF, if the associated VFs have ATS
enabled. Explicitly invalidate all ATC entries in arm_smmu_detach_dev().
The endpoint cannot form new ATC entries because STE.EATS is clear.

Fixes: 9ce27afc0830 ("iommu/arm-smmu-v3: Add support for PCI ATS")
Reported-by: Manoj Kumar 
Reported-by: Robin Murphy 
Signed-off-by: Jean-Philippe Brucker 
Acked-by: Will Deacon 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 5 -
 1 file changed, 4 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4d5a694f02c2..0fee8f7957ec 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1884,9 +1884,13 @@ static int arm_smmu_enable_ats(struct arm_smmu_master 
*master)
 
 static void arm_smmu_disable_ats(struct arm_smmu_master *master)
 {
+   struct arm_smmu_cmdq_ent cmd;
+
if (!master->ats_enabled || !dev_is_pci(master->dev))
return;
 
+   arm_smmu_atc_inv_to_cmd(0, 0, 0, &cmd);
+   arm_smmu_atc_inv_master(master, &cmd);
pci_disable_ats(to_pci_dev(master->dev));
master->ats_enabled = false;
 }
@@ -1906,7 +1910,6 @@ static void arm_smmu_detach_dev(struct arm_smmu_master 
*master)
master->domain = NULL;
arm_smmu_install_ste_for_dev(master);
 
-   /* Disabling ATS invalidates all ATC entries */
arm_smmu_disable_ats(master);
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.2 089/249] iommu: Fix a leak in iommu_insert_resv_region

2019-07-15 Thread Sasha Levin
From: Eric Auger 

[ Upstream commit ad0834dedaa15c3a176f783c0373f836e44b4700 ]

In case we expand an existing region, we unlink
this latter and insert the larger one. In
that case we should free the original region after
the insertion. Also we can immediately return.

Fixes: 6c65fb318e8b ("iommu: iommu_get_group_resv_regions")

Signed-off-by: Eric Auger 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/iommu.c | 8 +---
 1 file changed, 5 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 9f0a2844371c..30db41e9f15c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -225,18 +225,21 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
pos = pos->next;
} else if ((start >= a) && (end <= b)) {
if (new->type == type)
-   goto done;
+   return 0;
else
pos = pos->next;
} else {
if (new->type == type) {
phys_addr_t new_start = min(a, start);
phys_addr_t new_end = max(b, end);
+   int ret;
 
list_del(&entry->list);
entry->start = new_start;
entry->length = new_end - new_start + 1;
-   iommu_insert_resv_region(entry, regions);
+   ret = iommu_insert_resv_region(entry, regions);
+   kfree(entry);
+   return ret;
} else {
pos = pos->next;
}
@@ -249,7 +252,6 @@ static int iommu_insert_resv_region(struct 
iommu_resv_region *new,
return -ENOMEM;
 
list_add_tail(®ion->list, pos);
-done:
return 0;
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH AUTOSEL 5.1 09/51] iommu/vt-d: Fix lock inversion between iommu->lock and device_domain_lock

2019-06-26 Thread Sasha Levin

On Wed, Jun 26, 2019 at 08:56:06AM +0200, Joerg Roedel wrote:

Hi Sasha,

On Tue, Jun 25, 2019 at 11:40:25PM -0400, Sasha Levin wrote:

From: Dave Jiang 

[ Upstream commit 7560cc3ca7d9d11555f80c830544e463fcdb28b8 ]


This commit was reverted upstream, please drop it from your stable
queue. It caused new lockdep issues.


I've dropped it, thank you.

--
Thanks,
Sasha
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.1 09/51] iommu/vt-d: Fix lock inversion between iommu->lock and device_domain_lock

2019-06-25 Thread Sasha Levin
From: Dave Jiang 

[ Upstream commit 7560cc3ca7d9d11555f80c830544e463fcdb28b8 ]

Lockdep debug reported lock inversion related with the iommu code
caused by dmar_insert_one_dev_info() grabbing the iommu->lock and
the device_domain_lock out of order versus the code path in
iommu_flush_dev_iotlb(). Expanding the scope of the iommu->lock and
reversing the order of lock acquisition fixes the issue.

[   76.238180] dsa_bus wq0.0: dsa wq wq0.0 disabled
[   76.248706]
[   76.250486] 
[   76.257113] WARNING: possible irq lock inversion dependency detected
[   76.263736] 5.1.0-rc5+ #162 Not tainted
[   76.267854] 
[   76.274485] systemd-journal/521 just changed the state of lock:
[   76.280685] 55b330f5 (device_domain_lock){..-.}, at: 
iommu_flush_dev_iotlb.part.63+0x29/0x90
[   76.290099] but this lock took another, SOFTIRQ-unsafe lock in the past:
[   76.297093]  (&(&iommu->lock)->rlock){+.+.}
[   76.297094]
[   76.297094]
[   76.297094] and interrupts could create inverse lock ordering between them.
[   76.297094]
[   76.314257]
[   76.314257] other info that might help us debug this:
[   76.321448]  Possible interrupt unsafe locking scenario:
[   76.321448]
[   76.328907]CPU0CPU1
[   76.333777]
[   76.338642]   lock(&(&iommu->lock)->rlock);
[   76.343165]local_irq_disable();
[   76.349422]lock(device_domain_lock);
[   76.356116]lock(&(&iommu->lock)->rlock);
[   76.363154]   
[   76.366134] lock(device_domain_lock);
[   76.370548]
[   76.370548]  *** DEADLOCK ***

Fixes: 745f2586e78e ("iommu/vt-d: Simplify function get_domain_for_dev()")
Signed-off-by: Dave Jiang 
Reviewed-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 0feb3f70da16..c82d5f1bd306 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2509,6 +2509,7 @@ static struct dmar_domain 
*dmar_insert_one_dev_info(struct intel_iommu *iommu,
}
}
 
+   spin_lock(&iommu->lock);
spin_lock_irqsave(&device_domain_lock, flags);
if (dev)
found = find_domain(dev);
@@ -2524,17 +2525,16 @@ static struct dmar_domain 
*dmar_insert_one_dev_info(struct intel_iommu *iommu,
 
if (found) {
spin_unlock_irqrestore(&device_domain_lock, flags);
+   spin_unlock(&iommu->lock);
free_devinfo_mem(info);
/* Caller must free the original domain */
return found;
}
 
-   spin_lock(&iommu->lock);
ret = domain_attach_iommu(domain, iommu);
-   spin_unlock(&iommu->lock);
-
if (ret) {
spin_unlock_irqrestore(&device_domain_lock, flags);
+   spin_unlock(&iommu->lock);
free_devinfo_mem(info);
return NULL;
}
@@ -2544,6 +2544,7 @@ static struct dmar_domain 
*dmar_insert_one_dev_info(struct intel_iommu *iommu,
if (dev)
dev->archdata.iommu = info;
spin_unlock_irqrestore(&device_domain_lock, flags);
+   spin_unlock(&iommu->lock);
 
/* PASID table is mandatory for a PCI device in scalable mode. */
if (dev && dev_is_pci(dev) && sm_supported(iommu)) {
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.1 10/51] iommu/vt-d: Set the right field for Page Walk Snoop

2019-06-25 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 66d78ad316b0e1ca5ae19663468554e2c0e31c26 ]

Set the page walk snoop to the right bit, otherwise the domain
id field will be overlapped.

Reported-by: Dave Jiang 
Fixes: 6f7db75e1c469 ("iommu/vt-d: Add second level page table interface")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-pasid.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c
index 03b12d2ee213..fdf05c45d516 100644
--- a/drivers/iommu/intel-pasid.c
+++ b/drivers/iommu/intel-pasid.c
@@ -387,7 +387,7 @@ static inline void pasid_set_present(struct pasid_entry *pe)
  */
 static inline void pasid_set_page_snoop(struct pasid_entry *pe, bool value)
 {
-   pasid_set_bits(&pe->val[1], 1 << 23, value);
+   pasid_set_bits(&pe->val[1], 1 << 23, value << 23);
 }
 
 /*
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.4 34/56] iommu/tegra-smmu: Fix invalid ASID bits on Tegra30/114

2019-06-01 Thread Sasha Levin
From: Dmitry Osipenko 

[ Upstream commit 43a0541e312f7136e081e6bf58f6c8a2e9672688 ]

Both Tegra30 and Tegra114 have 4 ASID's and the corresponding bitfield of
the TLB_FLUSH register differs from later Tegra generations that have 128
ASID's.

In a result the PTE's are now flushed correctly from TLB and this fixes
problems with graphics (randomly failing tests) on Tegra30.

Cc: stable 
Signed-off-by: Dmitry Osipenko 
Acked-by: Thierry Reding 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/tegra-smmu.c | 25 ++---
 1 file changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 9305964250aca..c4eb293b15242 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -91,7 +91,6 @@ static inline u32 smmu_readl(struct tegra_smmu *smmu, 
unsigned long offset)
 #define  SMMU_TLB_FLUSH_VA_MATCH_ALL (0 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_SECTION (2 << 0)
 #define  SMMU_TLB_FLUSH_VA_MATCH_GROUP   (3 << 0)
-#define  SMMU_TLB_FLUSH_ASID(x)  (((x) & 0x7f) << 24)
 #define  SMMU_TLB_FLUSH_VA_SECTION(addr) addr) & 0xffc0) >> 12) | \
  SMMU_TLB_FLUSH_VA_MATCH_SECTION)
 #define  SMMU_TLB_FLUSH_VA_GROUP(addr)   addr) & 0xc000) >> 12) | \
@@ -194,8 +193,12 @@ static inline void smmu_flush_tlb_asid(struct tegra_smmu 
*smmu,
 {
u32 value;
 
-   value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
-   SMMU_TLB_FLUSH_VA_MATCH_ALL;
+   if (smmu->soc->num_asids == 4)
+   value = (asid & 0x3) << 29;
+   else
+   value = (asid & 0x7f) << 24;
+
+   value |= SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_VA_MATCH_ALL;
smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
@@ -205,8 +208,12 @@ static inline void smmu_flush_tlb_section(struct 
tegra_smmu *smmu,
 {
u32 value;
 
-   value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
-   SMMU_TLB_FLUSH_VA_SECTION(iova);
+   if (smmu->soc->num_asids == 4)
+   value = (asid & 0x3) << 29;
+   else
+   value = (asid & 0x7f) << 24;
+
+   value |= SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_VA_SECTION(iova);
smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
@@ -216,8 +223,12 @@ static inline void smmu_flush_tlb_group(struct tegra_smmu 
*smmu,
 {
u32 value;
 
-   value = SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_ASID(asid) |
-   SMMU_TLB_FLUSH_VA_GROUP(iova);
+   if (smmu->soc->num_asids == 4)
+   value = (asid & 0x3) << 29;
+   else
+   value = (asid & 0x7f) << 24;
+
+   value |= SMMU_TLB_FLUSH_ASID_MATCH | SMMU_TLB_FLUSH_VA_GROUP(iova);
smmu_writel(smmu, value, SMMU_TLB_FLUSH);
 }
 
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.4 19/56] iommu/vt-d: Set intel_iommu_gfx_mapped correctly

2019-06-01 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit cf1ec4539a50bdfe688caad4615ca47646884316 ]

The intel_iommu_gfx_mapped flag is exported by the Intel
IOMMU driver to indicate whether an IOMMU is used for the
graphic device. In a virtualized IOMMU environment (e.g.
QEMU), an include-all IOMMU is used for graphic device.
This flag is found to be clear even the IOMMU is used.

Cc: Ashok Raj 
Cc: Jacob Pan 
Cc: Kevin Tian 
Reported-by: Zhenyu Wang 
Fixes: c0771df8d5297 ("intel-iommu: Export a flag indicating that the IOMMU is 
used for iGFX.")
Suggested-by: Kevin Tian 
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 7 ---
 1 file changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 3e97c4b2ebed2..b965561a41627 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -3983,9 +3983,7 @@ static void __init init_no_remapping_devices(void)
 
/* This IOMMU has *only* gfx devices. Either bypass it or
   set the gfx_mapped flag, as appropriate */
-   if (dmar_map_gfx) {
-   intel_iommu_gfx_mapped = 1;
-   } else {
+   if (!dmar_map_gfx) {
drhd->ignored = 1;
for_each_active_dev_scope(drhd->devices,
  drhd->devices_cnt, i, dev)
@@ -4694,6 +4692,9 @@ int __init intel_iommu_init(void)
goto out_free_reserved_range;
}
 
+   if (dmar_map_gfx)
+   intel_iommu_gfx_mapped = 1;
+
init_no_remapping_devices();
 
ret = init_dmars();
-- 
2.20.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.4 9/9] iommu/amd: Set exclusion range correctly

2019-04-26 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 3c677d206210f53a4be972211066c0f1cd47fe12 ]

The exlcusion range limit register needs to contain the
base-address of the last page that is part of the range, as
bits 0-11 of this register are treated as 0xfff by the
hardware for comparisons.

So correctly set the exclusion range in the hardware to the
last page which is _in_ the range.

Fixes: b2026aa2dce44 ('x86, AMD IOMMU: add functions for programming IOMMU MMIO 
space')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 94f1bf772ec9..db85cc5791dc 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -295,7 +295,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 
address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
u64 start = iommu->exclusion_start & PAGE_MASK;
-   u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+   u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
u64 entry;
 
if (!iommu->exclusion_start)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 15/16] iommu/amd: Set exclusion range correctly

2019-04-26 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 3c677d206210f53a4be972211066c0f1cd47fe12 ]

The exlcusion range limit register needs to contain the
base-address of the last page that is part of the range, as
bits 0-11 of this register are treated as 0xfff by the
hardware for comparisons.

So correctly set the exclusion range in the hardware to the
last page which is _in_ the range.

Fixes: b2026aa2dce44 ('x86, AMD IOMMU: add functions for programming IOMMU MMIO 
space')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 157e93421fb8..13bbe5795e4e 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -318,7 +318,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 
address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
u64 start = iommu->exclusion_start & PAGE_MASK;
-   u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+   u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
u64 entry;
 
if (!iommu->exclusion_start)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 3.18 8/8] iommu/amd: Set exclusion range correctly

2019-04-26 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 3c677d206210f53a4be972211066c0f1cd47fe12 ]

The exlcusion range limit register needs to contain the
base-address of the last page that is part of the range, as
bits 0-11 of this register are treated as 0xfff by the
hardware for comparisons.

So correctly set the exclusion range in the hardware to the
last page which is _in_ the range.

Fixes: b2026aa2dce44 ('x86, AMD IOMMU: add functions for programming IOMMU MMIO 
space')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 2f3475247f0f..127f9cc563e9 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -294,7 +294,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 
address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
u64 start = iommu->exclusion_start & PAGE_MASK;
-   u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+   u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
u64 entry;
 
if (!iommu->exclusion_start)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 30/32] iommu/amd: Set exclusion range correctly

2019-04-26 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 3c677d206210f53a4be972211066c0f1cd47fe12 ]

The exlcusion range limit register needs to contain the
base-address of the last page that is part of the range, as
bits 0-11 of this register are treated as 0xfff by the
hardware for comparisons.

So correctly set the exclusion range in the hardware to the
last page which is _in_ the range.

Fixes: b2026aa2dce44 ('x86, AMD IOMMU: add functions for programming IOMMU MMIO 
space')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index b97984a5ddad..9b3d8fd5f7c1 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -355,7 +355,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 
address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
u64 start = iommu->exclusion_start & PAGE_MASK;
-   u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+   u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
u64 entry;
 
if (!iommu->exclusion_start)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 50/53] iommu/amd: Set exclusion range correctly

2019-04-26 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 3c677d206210f53a4be972211066c0f1cd47fe12 ]

The exlcusion range limit register needs to contain the
base-address of the last page that is part of the range, as
bits 0-11 of this register are treated as 0xfff by the
hardware for comparisons.

So correctly set the exclusion range in the hardware to the
last page which is _in_ the range.

Fixes: b2026aa2dce44 ('x86, AMD IOMMU: add functions for programming IOMMU MMIO 
space')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index e062ab9687c7..5689e07799e3 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -356,7 +356,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 
address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
u64 start = iommu->exclusion_start & PAGE_MASK;
-   u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+   u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
u64 entry;
 
if (!iommu->exclusion_start)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 75/79] iommu/amd: Set exclusion range correctly

2019-04-26 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 3c677d206210f53a4be972211066c0f1cd47fe12 ]

The exlcusion range limit register needs to contain the
base-address of the last page that is part of the range, as
bits 0-11 of this register are treated as 0xfff by the
hardware for comparisons.

So correctly set the exclusion range in the hardware to the
last page which is _in_ the range.

Fixes: b2026aa2dce44 ('x86, AMD IOMMU: add functions for programming IOMMU MMIO 
space')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu_init.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 66123b911ec8..8ae6b350e64c 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -358,7 +358,7 @@ static void iommu_write_l2(struct amd_iommu *iommu, u8 
address, u32 val)
 static void iommu_set_exclusion_range(struct amd_iommu *iommu)
 {
u64 start = iommu->exclusion_start & PAGE_MASK;
-   u64 limit = (start + iommu->exclusion_length) & PAGE_MASK;
+   u64 limit = (start + iommu->exclusion_length - 1) & PAGE_MASK;
u64 entry;
 
if (!iommu->exclusion_start)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 41/43] iommu/amd: Reserve exclusion range in iova-domain

2019-04-22 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 8aafaaf2212192012f5bae305bb31cdf7681d777 ]

If a device has an exclusion range specified in the IVRS
table, this region needs to be reserved in the iova-domain
of that device. This hasn't happened until now and can cause
data corruption on data transfered with these devices.

Treat exclusion ranges as reserved regions in the iommu-core
to fix the problem.

Fixes: be2a022c0dd0 ('x86, AMD IOMMU: add functions to parse IOMMU memory 
mapping requirements for devices')
Signed-off-by: Joerg Roedel 
Reviewed-by: Gary R Hook 
Signed-off-by: Sasha Levin (Microsoft) 
---
 drivers/iommu/amd_iommu.c   | 9 ++---
 drivers/iommu/amd_iommu_init.c  | 7 ---
 drivers/iommu/amd_iommu_types.h | 2 ++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index bd339bfe0d15..684f7cdd814b 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3127,21 +3127,24 @@ static void amd_iommu_get_resv_regions(struct device 
*dev,
return;
 
list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+   int type, prot = 0;
size_t length;
-   int prot = 0;
 
if (devid < entry->devid_start || devid > entry->devid_end)
continue;
 
+   type   = IOMMU_RESV_DIRECT;
length = entry->address_end - entry->address_start;
if (entry->prot & IOMMU_PROT_IR)
prot |= IOMMU_READ;
if (entry->prot & IOMMU_PROT_IW)
prot |= IOMMU_WRITE;
+   if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE)
+   /* Exclusion range */
+   type = IOMMU_RESV_RESERVED;
 
region = iommu_alloc_resv_region(entry->address_start,
-length, prot,
-IOMMU_RESV_DIRECT);
+length, prot, type);
if (!region) {
pr_err("Out of memory allocating dm-regions for %s\n",
dev_name(dev));
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index b97984a5ddad..91d7718625a6 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -1980,6 +1980,9 @@ static int __init init_unity_map_range(struct ivmd_header 
*m)
if (e == NULL)
return -ENOMEM;
 
+   if (m->flags & IVMD_FLAG_EXCL_RANGE)
+   init_exclusion_range(m);
+
switch (m->type) {
default:
kfree(e);
@@ -2026,9 +2029,7 @@ static int __init init_memory_definitions(struct 
acpi_table_header *table)
 
while (p < end) {
m = (struct ivmd_header *)p;
-   if (m->flags & IVMD_FLAG_EXCL_RANGE)
-   init_exclusion_range(m);
-   else if (m->flags & IVMD_FLAG_UNITY_MAP)
+   if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE))
init_unity_map_range(m);
 
p += m->length;
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index f6b24c7d8b70..3054c0971759 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -369,6 +369,8 @@
 #define IOMMU_PROT_IR 0x01
 #define IOMMU_PROT_IW 0x02
 
+#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE(1 << 2)
+
 /* IOMMU capabilities */
 #define IOMMU_CAP_IOTLB   24
 #define IOMMU_CAP_NPCACHE 26
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 65/68] iommu/amd: Reserve exclusion range in iova-domain

2019-04-22 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 8aafaaf2212192012f5bae305bb31cdf7681d777 ]

If a device has an exclusion range specified in the IVRS
table, this region needs to be reserved in the iova-domain
of that device. This hasn't happened until now and can cause
data corruption on data transfered with these devices.

Treat exclusion ranges as reserved regions in the iommu-core
to fix the problem.

Fixes: be2a022c0dd0 ('x86, AMD IOMMU: add functions to parse IOMMU memory 
mapping requirements for devices')
Signed-off-by: Joerg Roedel 
Reviewed-by: Gary R Hook 
Signed-off-by: Sasha Levin (Microsoft) 
---
 drivers/iommu/amd_iommu.c   | 9 ++---
 drivers/iommu/amd_iommu_init.c  | 7 ---
 drivers/iommu/amd_iommu_types.h | 2 ++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 0b3877681e4a..8d9920ff4134 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3119,21 +3119,24 @@ static void amd_iommu_get_resv_regions(struct device 
*dev,
return;
 
list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+   int type, prot = 0;
size_t length;
-   int prot = 0;
 
if (devid < entry->devid_start || devid > entry->devid_end)
continue;
 
+   type   = IOMMU_RESV_DIRECT;
length = entry->address_end - entry->address_start;
if (entry->prot & IOMMU_PROT_IR)
prot |= IOMMU_READ;
if (entry->prot & IOMMU_PROT_IW)
prot |= IOMMU_WRITE;
+   if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE)
+   /* Exclusion range */
+   type = IOMMU_RESV_RESERVED;
 
region = iommu_alloc_resv_region(entry->address_start,
-length, prot,
-IOMMU_RESV_DIRECT);
+length, prot, type);
if (!region) {
pr_err("Out of memory allocating dm-regions for %s\n",
dev_name(dev));
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index e062ab9687c7..be3801d43d48 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -2001,6 +2001,9 @@ static int __init init_unity_map_range(struct ivmd_header 
*m)
if (e == NULL)
return -ENOMEM;
 
+   if (m->flags & IVMD_FLAG_EXCL_RANGE)
+   init_exclusion_range(m);
+
switch (m->type) {
default:
kfree(e);
@@ -2047,9 +2050,7 @@ static int __init init_memory_definitions(struct 
acpi_table_header *table)
 
while (p < end) {
m = (struct ivmd_header *)p;
-   if (m->flags & IVMD_FLAG_EXCL_RANGE)
-   init_exclusion_range(m);
-   else if (m->flags & IVMD_FLAG_UNITY_MAP)
+   if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE))
init_unity_map_range(m);
 
p += m->length;
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index e2b342e65a7b..69f3d4c95b53 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -373,6 +373,8 @@
 #define IOMMU_PROT_IR 0x01
 #define IOMMU_PROT_IW 0x02
 
+#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE(1 << 2)
+
 /* IOMMU capabilities */
 #define IOMMU_CAP_IOTLB   24
 #define IOMMU_CAP_NPCACHE 26
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 94/98] iommu/amd: Reserve exclusion range in iova-domain

2019-04-22 Thread Sasha Levin
From: Joerg Roedel 

[ Upstream commit 8aafaaf2212192012f5bae305bb31cdf7681d777 ]

If a device has an exclusion range specified in the IVRS
table, this region needs to be reserved in the iova-domain
of that device. This hasn't happened until now and can cause
data corruption on data transfered with these devices.

Treat exclusion ranges as reserved regions in the iommu-core
to fix the problem.

Fixes: be2a022c0dd0 ('x86, AMD IOMMU: add functions to parse IOMMU memory 
mapping requirements for devices')
Signed-off-by: Joerg Roedel 
Reviewed-by: Gary R Hook 
Signed-off-by: Sasha Levin (Microsoft) 
---
 drivers/iommu/amd_iommu.c   | 9 ++---
 drivers/iommu/amd_iommu_init.c  | 7 ---
 drivers/iommu/amd_iommu_types.h | 2 ++
 3 files changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index e628ef23418f..55b3e4b9d5dc 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -3166,21 +3166,24 @@ static void amd_iommu_get_resv_regions(struct device 
*dev,
return;
 
list_for_each_entry(entry, &amd_iommu_unity_map, list) {
+   int type, prot = 0;
size_t length;
-   int prot = 0;
 
if (devid < entry->devid_start || devid > entry->devid_end)
continue;
 
+   type   = IOMMU_RESV_DIRECT;
length = entry->address_end - entry->address_start;
if (entry->prot & IOMMU_PROT_IR)
prot |= IOMMU_READ;
if (entry->prot & IOMMU_PROT_IW)
prot |= IOMMU_WRITE;
+   if (entry->prot & IOMMU_UNITY_MAP_FLAG_EXCL_RANGE)
+   /* Exclusion range */
+   type = IOMMU_RESV_RESERVED;
 
region = iommu_alloc_resv_region(entry->address_start,
-length, prot,
-IOMMU_RESV_DIRECT);
+length, prot, type);
if (!region) {
pr_err("Out of memory allocating dm-regions for %s\n",
dev_name(dev));
diff --git a/drivers/iommu/amd_iommu_init.c b/drivers/iommu/amd_iommu_init.c
index 66123b911ec8..84fa5b22371e 100644
--- a/drivers/iommu/amd_iommu_init.c
+++ b/drivers/iommu/amd_iommu_init.c
@@ -2013,6 +2013,9 @@ static int __init init_unity_map_range(struct ivmd_header 
*m)
if (e == NULL)
return -ENOMEM;
 
+   if (m->flags & IVMD_FLAG_EXCL_RANGE)
+   init_exclusion_range(m);
+
switch (m->type) {
default:
kfree(e);
@@ -2059,9 +2062,7 @@ static int __init init_memory_definitions(struct 
acpi_table_header *table)
 
while (p < end) {
m = (struct ivmd_header *)p;
-   if (m->flags & IVMD_FLAG_EXCL_RANGE)
-   init_exclusion_range(m);
-   else if (m->flags & IVMD_FLAG_UNITY_MAP)
+   if (m->flags & (IVMD_FLAG_UNITY_MAP | IVMD_FLAG_EXCL_RANGE))
init_unity_map_range(m);
 
p += m->length;
diff --git a/drivers/iommu/amd_iommu_types.h b/drivers/iommu/amd_iommu_types.h
index eae0741f72dc..87965e4d9647 100644
--- a/drivers/iommu/amd_iommu_types.h
+++ b/drivers/iommu/amd_iommu_types.h
@@ -374,6 +374,8 @@
 #define IOMMU_PROT_IR 0x01
 #define IOMMU_PROT_IW 0x02
 
+#define IOMMU_UNITY_MAP_FLAG_EXCL_RANGE(1 << 2)
+
 /* IOMMU capabilities */
 #define IOMMU_CAP_IOTLB   24
 #define IOMMU_CAP_NPCACHE 26
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH AUTOSEL 5.0 008/262] swiotlb: add checks for the return value of memblock_alloc*()

2019-04-03 Thread Sasha Levin

On Thu, Mar 28, 2019 at 07:55:20AM +0200, Mike Rapoport wrote:

Hi,

On Wed, Mar 27, 2019 at 01:57:43PM -0400, Sasha Levin wrote:

From: Mike Rapoport 

[ Upstream commit a0bf842e89a3842162aa8514b9bf4611c86fee10 ]

Add panic() calls if memblock_alloc() returns NULL.

The panic() format duplicates the one used by memblock itself and in
order to avoid explosion with long parameters list replace open coded
allocation size calculations with a local variable.


This patch is a part of a series that removes panic() calls from memblock
allocators rather than a fix.


I've dropped it, thanks!

--
Thanks,
Sasha
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 3.18 07/10] iommu/dmar: Fix buffer overflow during PCI bus notification

2019-03-29 Thread Sasha Levin
From: Julia Cartwright 

[ Upstream commit cffaaf0c816238c45cd2d06913476c83eb50f682 ]

Commit 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI
device path") changed the type of the path data, however, the change in
path type was not reflected in size calculations.  Update to use the
correct type and prevent a buffer overflow.

This bug manifests in systems with deep PCI hierarchies, and can lead to
an overflow of the static allocated buffer (dmar_pci_notify_info_buf),
or can lead to overflow of slab-allocated data.

   BUG: KASAN: global-out-of-bounds in dmar_alloc_pci_notify_info+0x1d5/0x2e0
   Write of size 1 at addr 90445d80 by task swapper/0/1
   CPU: 0 PID: 1 Comm: swapper/0 Tainted: GW   
4.14.87-rt49-02406-gd0a0e96 #1
   Call Trace:
? dump_stack+0x46/0x59
? print_address_description+0x1df/0x290
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? kasan_report+0x256/0x340
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? e820__memblock_setup+0xb0/0xb0
? dmar_dev_scope_init+0x424/0x48f
? __down_write_common+0x1ec/0x230
? dmar_dev_scope_init+0x48f/0x48f
? dmar_free_unused_resources+0x109/0x109
? cpumask_next+0x16/0x20
? __kmem_cache_create+0x392/0x430
? kmem_cache_create+0x135/0x2f0
? e820__memblock_setup+0xb0/0xb0
? intel_iommu_init+0x170/0x1848
? _raw_spin_unlock_irqrestore+0x32/0x60
? migrate_enable+0x27a/0x5b0
? sched_setattr+0x20/0x20
? migrate_disable+0x1fc/0x380
? task_rq_lock+0x170/0x170
? try_to_run_init_process+0x40/0x40
? locks_remove_file+0x85/0x2f0
? dev_prepare_static_identity_mapping+0x78/0x78
? rt_spin_unlock+0x39/0x50
? lockref_put_or_lock+0x2a/0x40
? dput+0x128/0x2f0
? __rcu_read_unlock+0x66/0x80
? __fput+0x250/0x300
? __rcu_read_lock+0x1b/0x30
? mntput_no_expire+0x38/0x290
? e820__memblock_setup+0xb0/0xb0
? pci_iommu_init+0x25/0x63
? pci_iommu_init+0x25/0x63
? do_one_initcall+0x7e/0x1c0
? initcall_blacklisted+0x120/0x120
? kernel_init_freeable+0x27b/0x307
? rest_init+0xd0/0xd0
? kernel_init+0xf/0x120
? rest_init+0xd0/0xd0
? ret_from_fork+0x1f/0x40
   The buggy address belongs to the variable:
dmar_pci_notify_info_buf+0x40/0x60

Fixes: 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI device 
path")
Signed-off-by: Julia Cartwright 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dmar.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 6b78e131f6dd..f6a42ea14ef1 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -134,7 +134,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned 
long event)
for (tmp = dev; tmp; tmp = tmp->bus->self)
level++;
 
-   size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path);
+   size = sizeof(*info) + level * sizeof(info->path[0]);
if (size <= sizeof(dmar_pci_notify_info_buf)) {
info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf;
} else {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.4 11/16] iommu/dmar: Fix buffer overflow during PCI bus notification

2019-03-29 Thread Sasha Levin
From: Julia Cartwright 

[ Upstream commit cffaaf0c816238c45cd2d06913476c83eb50f682 ]

Commit 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI
device path") changed the type of the path data, however, the change in
path type was not reflected in size calculations.  Update to use the
correct type and prevent a buffer overflow.

This bug manifests in systems with deep PCI hierarchies, and can lead to
an overflow of the static allocated buffer (dmar_pci_notify_info_buf),
or can lead to overflow of slab-allocated data.

   BUG: KASAN: global-out-of-bounds in dmar_alloc_pci_notify_info+0x1d5/0x2e0
   Write of size 1 at addr 90445d80 by task swapper/0/1
   CPU: 0 PID: 1 Comm: swapper/0 Tainted: GW   
4.14.87-rt49-02406-gd0a0e96 #1
   Call Trace:
? dump_stack+0x46/0x59
? print_address_description+0x1df/0x290
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? kasan_report+0x256/0x340
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? e820__memblock_setup+0xb0/0xb0
? dmar_dev_scope_init+0x424/0x48f
? __down_write_common+0x1ec/0x230
? dmar_dev_scope_init+0x48f/0x48f
? dmar_free_unused_resources+0x109/0x109
? cpumask_next+0x16/0x20
? __kmem_cache_create+0x392/0x430
? kmem_cache_create+0x135/0x2f0
? e820__memblock_setup+0xb0/0xb0
? intel_iommu_init+0x170/0x1848
? _raw_spin_unlock_irqrestore+0x32/0x60
? migrate_enable+0x27a/0x5b0
? sched_setattr+0x20/0x20
? migrate_disable+0x1fc/0x380
? task_rq_lock+0x170/0x170
? try_to_run_init_process+0x40/0x40
? locks_remove_file+0x85/0x2f0
? dev_prepare_static_identity_mapping+0x78/0x78
? rt_spin_unlock+0x39/0x50
? lockref_put_or_lock+0x2a/0x40
? dput+0x128/0x2f0
? __rcu_read_unlock+0x66/0x80
? __fput+0x250/0x300
? __rcu_read_lock+0x1b/0x30
? mntput_no_expire+0x38/0x290
? e820__memblock_setup+0xb0/0xb0
? pci_iommu_init+0x25/0x63
? pci_iommu_init+0x25/0x63
? do_one_initcall+0x7e/0x1c0
? initcall_blacklisted+0x120/0x120
? kernel_init_freeable+0x27b/0x307
? rest_init+0xd0/0xd0
? kernel_init+0xf/0x120
? rest_init+0xd0/0xd0
? ret_from_fork+0x1f/0x40
   The buggy address belongs to the variable:
dmar_pci_notify_info_buf+0x40/0x60

Fixes: 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI device 
path")
Signed-off-by: Julia Cartwright 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dmar.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 5a63e32a4a6b..cbad1926cec1 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -143,7 +143,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned 
long event)
for (tmp = dev; tmp; tmp = tmp->bus->self)
level++;
 
-   size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path);
+   size = sizeof(*info) + level * sizeof(info->path[0]);
if (size <= sizeof(dmar_pci_notify_info_buf)) {
info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf;
} else {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 14/21] iommu/dmar: Fix buffer overflow during PCI bus notification

2019-03-29 Thread Sasha Levin
From: Julia Cartwright 

[ Upstream commit cffaaf0c816238c45cd2d06913476c83eb50f682 ]

Commit 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI
device path") changed the type of the path data, however, the change in
path type was not reflected in size calculations.  Update to use the
correct type and prevent a buffer overflow.

This bug manifests in systems with deep PCI hierarchies, and can lead to
an overflow of the static allocated buffer (dmar_pci_notify_info_buf),
or can lead to overflow of slab-allocated data.

   BUG: KASAN: global-out-of-bounds in dmar_alloc_pci_notify_info+0x1d5/0x2e0
   Write of size 1 at addr 90445d80 by task swapper/0/1
   CPU: 0 PID: 1 Comm: swapper/0 Tainted: GW   
4.14.87-rt49-02406-gd0a0e96 #1
   Call Trace:
? dump_stack+0x46/0x59
? print_address_description+0x1df/0x290
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? kasan_report+0x256/0x340
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? e820__memblock_setup+0xb0/0xb0
? dmar_dev_scope_init+0x424/0x48f
? __down_write_common+0x1ec/0x230
? dmar_dev_scope_init+0x48f/0x48f
? dmar_free_unused_resources+0x109/0x109
? cpumask_next+0x16/0x20
? __kmem_cache_create+0x392/0x430
? kmem_cache_create+0x135/0x2f0
? e820__memblock_setup+0xb0/0xb0
? intel_iommu_init+0x170/0x1848
? _raw_spin_unlock_irqrestore+0x32/0x60
? migrate_enable+0x27a/0x5b0
? sched_setattr+0x20/0x20
? migrate_disable+0x1fc/0x380
? task_rq_lock+0x170/0x170
? try_to_run_init_process+0x40/0x40
? locks_remove_file+0x85/0x2f0
? dev_prepare_static_identity_mapping+0x78/0x78
? rt_spin_unlock+0x39/0x50
? lockref_put_or_lock+0x2a/0x40
? dput+0x128/0x2f0
? __rcu_read_unlock+0x66/0x80
? __fput+0x250/0x300
? __rcu_read_lock+0x1b/0x30
? mntput_no_expire+0x38/0x290
? e820__memblock_setup+0xb0/0xb0
? pci_iommu_init+0x25/0x63
? pci_iommu_init+0x25/0x63
? do_one_initcall+0x7e/0x1c0
? initcall_blacklisted+0x120/0x120
? kernel_init_freeable+0x27b/0x307
? rest_init+0xd0/0xd0
? kernel_init+0xf/0x120
? rest_init+0xd0/0xd0
? ret_from_fork+0x1f/0x40
   The buggy address belongs to the variable:
dmar_pci_notify_info_buf+0x40/0x60

Fixes: 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI device 
path")
Signed-off-by: Julia Cartwright 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dmar.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index 63110fbbb410..d51734e0c350 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -143,7 +143,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned 
long event)
for (tmp = dev; tmp; tmp = tmp->bus->self)
level++;
 
-   size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path);
+   size = sizeof(*info) + level * sizeof(info->path[0]);
if (size <= sizeof(dmar_pci_notify_info_buf)) {
info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf;
} else {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 22/37] iommu/dmar: Fix buffer overflow during PCI bus notification

2019-03-29 Thread Sasha Levin
From: Julia Cartwright 

[ Upstream commit cffaaf0c816238c45cd2d06913476c83eb50f682 ]

Commit 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI
device path") changed the type of the path data, however, the change in
path type was not reflected in size calculations.  Update to use the
correct type and prevent a buffer overflow.

This bug manifests in systems with deep PCI hierarchies, and can lead to
an overflow of the static allocated buffer (dmar_pci_notify_info_buf),
or can lead to overflow of slab-allocated data.

   BUG: KASAN: global-out-of-bounds in dmar_alloc_pci_notify_info+0x1d5/0x2e0
   Write of size 1 at addr 90445d80 by task swapper/0/1
   CPU: 0 PID: 1 Comm: swapper/0 Tainted: GW   
4.14.87-rt49-02406-gd0a0e96 #1
   Call Trace:
? dump_stack+0x46/0x59
? print_address_description+0x1df/0x290
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? kasan_report+0x256/0x340
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? e820__memblock_setup+0xb0/0xb0
? dmar_dev_scope_init+0x424/0x48f
? __down_write_common+0x1ec/0x230
? dmar_dev_scope_init+0x48f/0x48f
? dmar_free_unused_resources+0x109/0x109
? cpumask_next+0x16/0x20
? __kmem_cache_create+0x392/0x430
? kmem_cache_create+0x135/0x2f0
? e820__memblock_setup+0xb0/0xb0
? intel_iommu_init+0x170/0x1848
? _raw_spin_unlock_irqrestore+0x32/0x60
? migrate_enable+0x27a/0x5b0
? sched_setattr+0x20/0x20
? migrate_disable+0x1fc/0x380
? task_rq_lock+0x170/0x170
? try_to_run_init_process+0x40/0x40
? locks_remove_file+0x85/0x2f0
? dev_prepare_static_identity_mapping+0x78/0x78
? rt_spin_unlock+0x39/0x50
? lockref_put_or_lock+0x2a/0x40
? dput+0x128/0x2f0
? __rcu_read_unlock+0x66/0x80
? __fput+0x250/0x300
? __rcu_read_lock+0x1b/0x30
? mntput_no_expire+0x38/0x290
? e820__memblock_setup+0xb0/0xb0
? pci_iommu_init+0x25/0x63
? pci_iommu_init+0x25/0x63
? do_one_initcall+0x7e/0x1c0
? initcall_blacklisted+0x120/0x120
? kernel_init_freeable+0x27b/0x307
? rest_init+0xd0/0xd0
? kernel_init+0xf/0x120
? rest_init+0xd0/0xd0
? ret_from_fork+0x1f/0x40
   The buggy address belongs to the variable:
dmar_pci_notify_info_buf+0x40/0x60

Fixes: 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI device 
path")
Signed-off-by: Julia Cartwright 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dmar.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index c0d1c4db5794..38d0128b8135 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -144,7 +144,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned 
long event)
for (tmp = dev; tmp; tmp = tmp->bus->self)
level++;
 
-   size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path);
+   size = sizeof(*info) + level * sizeof(info->path[0]);
if (size <= sizeof(dmar_pci_notify_info_buf)) {
info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf;
} else {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 38/57] iommu/dmar: Fix buffer overflow during PCI bus notification

2019-03-29 Thread Sasha Levin
From: Julia Cartwright 

[ Upstream commit cffaaf0c816238c45cd2d06913476c83eb50f682 ]

Commit 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI
device path") changed the type of the path data, however, the change in
path type was not reflected in size calculations.  Update to use the
correct type and prevent a buffer overflow.

This bug manifests in systems with deep PCI hierarchies, and can lead to
an overflow of the static allocated buffer (dmar_pci_notify_info_buf),
or can lead to overflow of slab-allocated data.

   BUG: KASAN: global-out-of-bounds in dmar_alloc_pci_notify_info+0x1d5/0x2e0
   Write of size 1 at addr 90445d80 by task swapper/0/1
   CPU: 0 PID: 1 Comm: swapper/0 Tainted: GW   
4.14.87-rt49-02406-gd0a0e96 #1
   Call Trace:
? dump_stack+0x46/0x59
? print_address_description+0x1df/0x290
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? kasan_report+0x256/0x340
? dmar_alloc_pci_notify_info+0x1d5/0x2e0
? e820__memblock_setup+0xb0/0xb0
? dmar_dev_scope_init+0x424/0x48f
? __down_write_common+0x1ec/0x230
? dmar_dev_scope_init+0x48f/0x48f
? dmar_free_unused_resources+0x109/0x109
? cpumask_next+0x16/0x20
? __kmem_cache_create+0x392/0x430
? kmem_cache_create+0x135/0x2f0
? e820__memblock_setup+0xb0/0xb0
? intel_iommu_init+0x170/0x1848
? _raw_spin_unlock_irqrestore+0x32/0x60
? migrate_enable+0x27a/0x5b0
? sched_setattr+0x20/0x20
? migrate_disable+0x1fc/0x380
? task_rq_lock+0x170/0x170
? try_to_run_init_process+0x40/0x40
? locks_remove_file+0x85/0x2f0
? dev_prepare_static_identity_mapping+0x78/0x78
? rt_spin_unlock+0x39/0x50
? lockref_put_or_lock+0x2a/0x40
? dput+0x128/0x2f0
? __rcu_read_unlock+0x66/0x80
? __fput+0x250/0x300
? __rcu_read_lock+0x1b/0x30
? mntput_no_expire+0x38/0x290
? e820__memblock_setup+0xb0/0xb0
? pci_iommu_init+0x25/0x63
? pci_iommu_init+0x25/0x63
? do_one_initcall+0x7e/0x1c0
? initcall_blacklisted+0x120/0x120
? kernel_init_freeable+0x27b/0x307
? rest_init+0xd0/0xd0
? kernel_init+0xf/0x120
? rest_init+0xd0/0xd0
? ret_from_fork+0x1f/0x40
   The buggy address belongs to the variable:
dmar_pci_notify_info_buf+0x40/0x60

Fixes: 57384592c433 ("iommu/vt-d: Store bus information in RMRR PCI device 
path")
Signed-off-by: Julia Cartwright 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/dmar.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/dmar.c b/drivers/iommu/dmar.c
index d9c748b6f9e4..7f9824b0609e 100644
--- a/drivers/iommu/dmar.c
+++ b/drivers/iommu/dmar.c
@@ -144,7 +144,7 @@ dmar_alloc_pci_notify_info(struct pci_dev *dev, unsigned 
long event)
for (tmp = dev; tmp; tmp = tmp->bus->self)
level++;
 
-   size = sizeof(*info) + level * sizeof(struct acpi_dmar_pci_path);
+   size = sizeof(*info) + level * sizeof(info->path[0]);
if (size <= sizeof(dmar_pci_notify_info_buf)) {
info = (struct dmar_pci_notify_info *)dmar_pci_notify_info_buf;
} else {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 3.18 14/15] iommu/vt-d: Check capability before disabling protected memory

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 5bb71fc790a88d063507dc5d445ab8b14e845591 ]

The spec states in 10.4.16 that the Protected Memory Enable
Register should be treated as read-only for implementations
not supporting protected memory regions (PLMR and PHMR fields
reported as Clear in the Capability register).

Cc: Jacob Pan 
Cc: mark gross 
Suggested-by: Ashok Raj 
Fixes: f8bab73515ca5 ("intel-iommu: PMEN support")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2068cb59f7ed..b1966269f26a 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1402,6 +1402,9 @@ static void iommu_disable_protect_mem_regions(struct 
intel_iommu *iommu)
u32 pmen;
unsigned long flags;
 
+   if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
+   return;
+
raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.4 18/21] iommu/vt-d: Check capability before disabling protected memory

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 5bb71fc790a88d063507dc5d445ab8b14e845591 ]

The spec states in 10.4.16 that the Protected Memory Enable
Register should be treated as read-only for implementations
not supporting protected memory regions (PLMR and PHMR fields
reported as Clear in the Capability register).

Cc: Jacob Pan 
Cc: mark gross 
Suggested-by: Ashok Raj 
Fixes: f8bab73515ca5 ("intel-iommu: PMEN support")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 8b4a4d95669a..3e97c4b2ebed 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1598,6 +1598,9 @@ static void iommu_disable_protect_mem_regions(struct 
intel_iommu *iommu)
u32 pmen;
unsigned long flags;
 
+   if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
+   return;
+
raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 24/27] iommu/vt-d: Check capability before disabling protected memory

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 5bb71fc790a88d063507dc5d445ab8b14e845591 ]

The spec states in 10.4.16 that the Protected Memory Enable
Register should be treated as read-only for implementations
not supporting protected memory regions (PLMR and PHMR fields
reported as Clear in the Capability register).

Cc: Jacob Pan 
Cc: mark gross 
Suggested-by: Ashok Raj 
Fixes: f8bab73515ca5 ("intel-iommu: PMEN support")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 86e349614e21..28feb1744710 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1636,6 +1636,9 @@ static void iommu_disable_protect_mem_regions(struct 
intel_iommu *iommu)
u32 pmen;
unsigned long flags;
 
+   if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
+   return;
+
raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 34/37] iommu/vt-d: Check capability before disabling protected memory

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 5bb71fc790a88d063507dc5d445ab8b14e845591 ]

The spec states in 10.4.16 that the Protected Memory Enable
Register should be treated as read-only for implementations
not supporting protected memory regions (PLMR and PHMR fields
reported as Clear in the Capability register).

Cc: Jacob Pan 
Cc: mark gross 
Suggested-by: Ashok Raj 
Fixes: f8bab73515ca5 ("intel-iommu: PMEN support")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 802ba7b16e09..fe935293fa7b 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1646,6 +1646,9 @@ static void iommu_disable_protect_mem_regions(struct 
intel_iommu *iommu)
u32 pmen;
unsigned long flags;
 
+   if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
+   return;
+
raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 48/52] iommu/vt-d: Check capability before disabling protected memory

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 5bb71fc790a88d063507dc5d445ab8b14e845591 ]

The spec states in 10.4.16 that the Protected Memory Enable
Register should be treated as read-only for implementations
not supporting protected memory regions (PLMR and PHMR fields
reported as Clear in the Capability register).

Cc: Jacob Pan 
Cc: mark gross 
Suggested-by: Ashok Raj 
Fixes: f8bab73515ca5 ("intel-iommu: PMEN support")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 2b8f5ebae821..603bf5233a99 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1624,6 +1624,9 @@ static void iommu_disable_protect_mem_regions(struct 
intel_iommu *iommu)
u32 pmen;
unsigned long flags;
 
+   if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
+   return;
+
raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 61/67] iommu/vt-d: Save the right domain ID used by hardware

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 84c11e4df5aa4955acaa441f0cf1cb2e50daf64b ]

The driver sets a default domain id (FLPT_DEFAULT_DID) in the
first level only pasid entry, but saves a different domain id
in @sdev->did. The value saved in @sdev->did will be used to
invalidate the translation caches. Hence, the driver might
result in invalidating the caches with a wrong domain id.

Cc: Ashok Raj 
Cc: Jacob Pan 
Fixes: 1c4f88b7f1f92 ("iommu/vt-d: Shared virtual address in scalable mode")
Signed-off-by: Liu Yi L 
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 63b427cc13d5..331504d8259f 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5330,7 +5330,7 @@ int intel_iommu_enable_pasid(struct intel_iommu *iommu, 
struct intel_svm_dev *sd
 
ctx_lo = context[0].lo;
 
-   sdev->did = domain->iommu_did[iommu->seq_id];
+   sdev->did = FLPT_DEFAULT_DID;
sdev->sid = PCI_DEVID(info->bus, info->devfn);
 
if (!(ctx_lo & CONTEXT_PASIDE)) {
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 60/67] iommu/vt-d: Check capability before disabling protected memory

2019-03-29 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit 5bb71fc790a88d063507dc5d445ab8b14e845591 ]

The spec states in 10.4.16 that the Protected Memory Enable
Register should be treated as read-only for implementations
not supporting protected memory regions (PLMR and PHMR fields
reported as Clear in the Capability register).

Cc: Jacob Pan 
Cc: mark gross 
Suggested-by: Ashok Raj 
Fixes: f8bab73515ca5 ("intel-iommu: PMEN support")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 78188bf7e90d..63b427cc13d5 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -1534,6 +1534,9 @@ static void iommu_disable_protect_mem_regions(struct 
intel_iommu *iommu)
u32 pmen;
unsigned long flags;
 
+   if (!cap_plmr(iommu->cap) && !cap_phmr(iommu->cap))
+   return;
+
raw_spin_lock_irqsave(&iommu->register_lock, flags);
pmen = readl(iommu->reg + DMAR_PMEN_REG);
pmen &= ~DMA_PMEN_EPM;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 30/87] iommu/io-pgtable-arm-v7s: Only kmemleak_ignore L2 tables

2019-03-27 Thread Sasha Levin
From: Nicolas Boichat 

[ Upstream commit 032ebd8548c9d05e8d2bdc7a7ec2fe29454b0ad0 ]

L1 tables are allocated with __get_dma_pages, and therefore already
ignored by kmemleak.

Without this, the kernel would print this error message on boot,
when the first L1 table is allocated:

[2.810533] kmemleak: Trying to color unknown object at 0xffd652388000 
as Black
[2.818190] CPU: 5 PID: 39 Comm: kworker/5:0 Tainted: G S
4.19.16 #8
[2.831227] Workqueue: events deferred_probe_work_func
[2.836353] Call trace:
...
[2.852532]  paint_ptr+0xa0/0xa8
[2.855750]  kmemleak_ignore+0x38/0x6c
[2.859490]  __arm_v7s_alloc_table+0x168/0x1f4
[2.863922]  arm_v7s_alloc_pgtable+0x114/0x17c
[2.868354]  alloc_io_pgtable_ops+0x3c/0x78
...

Fixes: e5fc9753b1a8314 ("iommu/io-pgtable: Add ARMv7 short descriptor support")
Signed-off-by: Nicolas Boichat 
Acked-by: Will Deacon 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/io-pgtable-arm-v7s.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
b/drivers/iommu/io-pgtable-arm-v7s.c
index d68a552cfe8d..3085b47fac1d 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -207,7 +207,8 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
if (dma != virt_to_phys(table))
goto out_unmap;
}
-   kmemleak_ignore(table);
+   if (lvl == 2)
+   kmemleak_ignore(table);
return table;
 
 out_unmap:
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 042/123] iommu/io-pgtable-arm-v7s: Only kmemleak_ignore L2 tables

2019-03-27 Thread Sasha Levin
From: Nicolas Boichat 

[ Upstream commit 032ebd8548c9d05e8d2bdc7a7ec2fe29454b0ad0 ]

L1 tables are allocated with __get_dma_pages, and therefore already
ignored by kmemleak.

Without this, the kernel would print this error message on boot,
when the first L1 table is allocated:

[2.810533] kmemleak: Trying to color unknown object at 0xffd652388000 
as Black
[2.818190] CPU: 5 PID: 39 Comm: kworker/5:0 Tainted: G S
4.19.16 #8
[2.831227] Workqueue: events deferred_probe_work_func
[2.836353] Call trace:
...
[2.852532]  paint_ptr+0xa0/0xa8
[2.855750]  kmemleak_ignore+0x38/0x6c
[2.859490]  __arm_v7s_alloc_table+0x168/0x1f4
[2.863922]  arm_v7s_alloc_pgtable+0x114/0x17c
[2.868354]  alloc_io_pgtable_ops+0x3c/0x78
...

Fixes: e5fc9753b1a8314 ("iommu/io-pgtable: Add ARMv7 short descriptor support")
Signed-off-by: Nicolas Boichat 
Acked-by: Will Deacon 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/io-pgtable-arm-v7s.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
b/drivers/iommu/io-pgtable-arm-v7s.c
index 29b7a6755fcd..56368c8bd791 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -217,7 +217,8 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
if (dma != phys)
goto out_unmap;
}
-   kmemleak_ignore(table);
+   if (lvl == 2)
+   kmemleak_ignore(table);
return table;
 
 out_unmap:
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 059/192] iommu/io-pgtable-arm-v7s: Only kmemleak_ignore L2 tables

2019-03-27 Thread Sasha Levin
From: Nicolas Boichat 

[ Upstream commit 032ebd8548c9d05e8d2bdc7a7ec2fe29454b0ad0 ]

L1 tables are allocated with __get_dma_pages, and therefore already
ignored by kmemleak.

Without this, the kernel would print this error message on boot,
when the first L1 table is allocated:

[2.810533] kmemleak: Trying to color unknown object at 0xffd652388000 
as Black
[2.818190] CPU: 5 PID: 39 Comm: kworker/5:0 Tainted: G S
4.19.16 #8
[2.831227] Workqueue: events deferred_probe_work_func
[2.836353] Call trace:
...
[2.852532]  paint_ptr+0xa0/0xa8
[2.855750]  kmemleak_ignore+0x38/0x6c
[2.859490]  __arm_v7s_alloc_table+0x168/0x1f4
[2.863922]  arm_v7s_alloc_pgtable+0x114/0x17c
[2.868354]  alloc_io_pgtable_ops+0x3c/0x78
...

Fixes: e5fc9753b1a8314 ("iommu/io-pgtable: Add ARMv7 short descriptor support")
Signed-off-by: Nicolas Boichat 
Acked-by: Will Deacon 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/io-pgtable-arm-v7s.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
b/drivers/iommu/io-pgtable-arm-v7s.c
index b5948ba6b3b3..7a3ce176f47f 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -217,7 +217,8 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
if (dma != phys)
goto out_unmap;
}
-   kmemleak_ignore(table);
+   if (lvl == 2)
+   kmemleak_ignore(table);
return table;
 
 out_unmap:
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 085/262] iommu/io-pgtable-arm-v7s: Only kmemleak_ignore L2 tables

2019-03-27 Thread Sasha Levin
From: Nicolas Boichat 

[ Upstream commit 032ebd8548c9d05e8d2bdc7a7ec2fe29454b0ad0 ]

L1 tables are allocated with __get_dma_pages, and therefore already
ignored by kmemleak.

Without this, the kernel would print this error message on boot,
when the first L1 table is allocated:

[2.810533] kmemleak: Trying to color unknown object at 0xffd652388000 
as Black
[2.818190] CPU: 5 PID: 39 Comm: kworker/5:0 Tainted: G S
4.19.16 #8
[2.831227] Workqueue: events deferred_probe_work_func
[2.836353] Call trace:
...
[2.852532]  paint_ptr+0xa0/0xa8
[2.855750]  kmemleak_ignore+0x38/0x6c
[2.859490]  __arm_v7s_alloc_table+0x168/0x1f4
[2.863922]  arm_v7s_alloc_pgtable+0x114/0x17c
[2.868354]  alloc_io_pgtable_ops+0x3c/0x78
...

Fixes: e5fc9753b1a8314 ("iommu/io-pgtable: Add ARMv7 short descriptor support")
Signed-off-by: Nicolas Boichat 
Acked-by: Will Deacon 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/io-pgtable-arm-v7s.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
b/drivers/iommu/io-pgtable-arm-v7s.c
index cec29bf45c9b..98a4a4a0dfb0 100644
--- a/drivers/iommu/io-pgtable-arm-v7s.c
+++ b/drivers/iommu/io-pgtable-arm-v7s.c
@@ -217,7 +217,8 @@ static void *__arm_v7s_alloc_table(int lvl, gfp_t gfp,
if (dma != phys)
goto out_unmap;
}
-   kmemleak_ignore(table);
+   if (lvl == 2)
+   kmemleak_ignore(table);
return table;
 
 out_unmap:
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 056/262] iommu/vt-d: Disable ATS support on untrusted devices

2019-03-27 Thread Sasha Levin
From: Lu Baolu 

[ Upstream commit d8b8591054575f33237556c32762d54e30774d28 ]

Commit fb58fdcd295b9 ("iommu/vt-d: Do not enable ATS for untrusted
devices") disables ATS support on the devices which have been marked
as untrusted. Unfortunately this is not enough to fix the DMA attack
vulnerabiltiies because IOMMU driver allows translated requests as
long as a device advertises the ATS capability. Hence a malicious
peripheral device could use this to bypass IOMMU.

This disables the ATS support on untrusted devices by clearing the
internal per-device ATS mark. As the result, IOMMU driver will block
any translated requests from any device marked as untrusted.

Cc: Jacob Pan 
Cc: Mika Westerberg 
Suggested-by: Kevin Tian 
Suggested-by: Ashok Raj 
Fixes: fb58fdcd295b9 ("iommu/vt-d: Do not enable ATS for untrusted devices")
Signed-off-by: Lu Baolu 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/intel-iommu.c | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 78188bf7e90d..dbd6824dfffa 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -2485,7 +2485,8 @@ static struct dmar_domain 
*dmar_insert_one_dev_info(struct intel_iommu *iommu,
if (dev && dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(info->dev);
 
-   if (!pci_ats_disabled() &&
+   if (!pdev->untrusted &&
+   !pci_ats_disabled() &&
ecap_dev_iotlb_support(iommu->ecap) &&
pci_find_ext_capability(pdev, PCI_EXT_CAP_ID_ATS) &&
dmar_find_matched_atsr_unit(pdev))
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 5.0 008/262] swiotlb: add checks for the return value of memblock_alloc*()

2019-03-27 Thread Sasha Levin
From: Mike Rapoport 

[ Upstream commit a0bf842e89a3842162aa8514b9bf4611c86fee10 ]

Add panic() calls if memblock_alloc() returns NULL.

The panic() format duplicates the one used by memblock itself and in
order to avoid explosion with long parameters list replace open coded
allocation size calculations with a local variable.

Link: 
http://lkml.kernel.org/r/1548057848-15136-19-git-send-email-r...@linux.ibm.com
Signed-off-by: Mike Rapoport 
Cc: Catalin Marinas 
Cc: Christophe Leroy 
Cc: Christoph Hellwig 
Cc: "David S. Miller" 
Cc: Dennis Zhou 
Cc: Geert Uytterhoeven 
Cc: Greentime Hu 
Cc: Greg Kroah-Hartman 
Cc: Guan Xuetao 
Cc: Guo Ren 
Cc: Guo Ren  [c-sky]
Cc: Heiko Carstens 
Cc: Juergen Gross  [Xen]
Cc: Mark Salter 
Cc: Matt Turner 
Cc: Max Filippov 
Cc: Michael Ellerman 
Cc: Michal Simek 
Cc: Paul Burton 
Cc: Petr Mladek 
Cc: Richard Weinberger 
Cc: Rich Felker 
Cc: Rob Herring 
Cc: Rob Herring 
Cc: Russell King 
Cc: Stafford Horne 
Cc: Tony Luck 
Cc: Vineet Gupta 
Cc: Yoshinori Sato 
Signed-off-by: Andrew Morton 
Signed-off-by: Linus Torvalds 
Signed-off-by: Sasha Levin 
---
 kernel/dma/swiotlb.c | 19 +--
 1 file changed, 13 insertions(+), 6 deletions(-)

diff --git a/kernel/dma/swiotlb.c b/kernel/dma/swiotlb.c
index c873f9cc2146..41224f0ec40e 100644
--- a/kernel/dma/swiotlb.c
+++ b/kernel/dma/swiotlb.c
@@ -191,6 +191,7 @@ void __init swiotlb_update_mem_attributes(void)
 int __init swiotlb_init_with_tbl(char *tlb, unsigned long nslabs, int verbose)
 {
unsigned long i, bytes;
+   size_t alloc_size;
 
bytes = nslabs << IO_TLB_SHIFT;
 
@@ -203,12 +204,18 @@ int __init swiotlb_init_with_tbl(char *tlb, unsigned long 
nslabs, int verbose)
 * to find contiguous free memory regions of size up to IO_TLB_SEGSIZE
 * between io_tlb_start and io_tlb_end.
 */
-   io_tlb_list = memblock_alloc(
-   PAGE_ALIGN(io_tlb_nslabs * sizeof(int)),
-   PAGE_SIZE);
-   io_tlb_orig_addr = memblock_alloc(
-   PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t)),
-   PAGE_SIZE);
+   alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(int));
+   io_tlb_list = memblock_alloc(alloc_size, PAGE_SIZE);
+   if (!io_tlb_list)
+   panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+ __func__, alloc_size, PAGE_SIZE);
+
+   alloc_size = PAGE_ALIGN(io_tlb_nslabs * sizeof(phys_addr_t));
+   io_tlb_orig_addr = memblock_alloc(alloc_size, PAGE_SIZE);
+   if (!io_tlb_orig_addr)
+   panic("%s: Failed to allocate %lu bytes align=0x%lx\n",
+ __func__, alloc_size, PAGE_SIZE);
+
for (i = 0; i < io_tlb_nslabs; i++) {
io_tlb_list[i] = IO_TLB_SEGSIZE - OFFSET(i, IO_TLB_SEGSIZE);
io_tlb_orig_addr[i] = INVALID_PHYS_ADDR;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 06/32] iommu/amd: Call free_iova_fast with pfn in map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit 51d8838d66d3249508940d8f59b07701f2129723 ]

In the error path of map_sg, free_iova_fast is being called with
address instead of the pfn. This results in a bad value getting into
the rcache, and can result in hitting a BUG_ON when
iova_magazine_free_pfns is called.

Cc: Joerg Roedel 
Cc: Suravee Suthikulpanit 
Signed-off-by: Jerry Snitselaar 
Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index bba1b9f2f782b..4209aa1c09f9c 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2610,7 +2610,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
}
 
 out_free_iova:
-   free_iova_fast(&dma_dom->iovad, address, npages);
+   free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
return 0;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 3.18 05/18] iommu/amd: Fix IOMMU page flush when detach device from a domain

2019-02-23 Thread Sasha Levin
From: Suravee Suthikulpanit 

[ Upstream commit 9825bd94e3a2baae1f4874767ae3a7d4c049720e ]

When a VM is terminated, the VFIO driver detaches all pass-through
devices from VFIO domain by clearing domain id and page table root
pointer from each device table entry (DTE), and then invalidates
the DTE. Then, the VFIO driver unmap pages and invalidate IOMMU pages.

Currently, the IOMMU driver keeps track of which IOMMU and how many
devices are attached to the domain. When invalidate IOMMU pages,
the driver checks if the IOMMU is still attached to the domain before
issuing the invalidate page command.

However, since VFIO has already detached all devices from the domain,
the subsequent INVALIDATE_IOMMU_PAGES commands are being skipped as
there is no IOMMU attached to the domain. This results in data
corruption and could cause the PCI device to end up in indeterministic
state.

Fix this by invalidate IOMMU pages when detach a device, and
before decrementing the per-domain device reference counts.

Cc: Boris Ostrovsky 
Suggested-by: Joerg Roedel 
Co-developed-by: Brijesh Singh 
Signed-off-by: Brijesh Singh 
Signed-off-by: Suravee Suthikulpanit 
Fixes: 6de8ad9b9ee0 ('x86/amd-iommu: Make iommu_flush_pages aware of multiple 
IOMMUs')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 5cf388ad1555d..48a73c48876b9 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2132,14 +2132,11 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+   struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
 
iommu = amd_iommu_rlookup_table[dev_data->devid];
 
-   /* decrease reference counters */
-   dev_data->domain->dev_iommu[iommu->index] -= 1;
-   dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -2147,6 +2144,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+   /* Flush IOTLB */
+   domain_flush_tlb_pde(domain);
+
+   /* Wait for the flushes to finish */
+   domain_flush_complete(domain);
+
+   /* decrease reference counters - needs to happen after the flushes */
+   domain->dev_iommu[iommu->index] -= 1;
+   domain->dev_cnt -= 1;
 }
 
 /*
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.4 06/26] iommu/amd: Fix IOMMU page flush when detach device from a domain

2019-02-23 Thread Sasha Levin
From: Suravee Suthikulpanit 

[ Upstream commit 9825bd94e3a2baae1f4874767ae3a7d4c049720e ]

When a VM is terminated, the VFIO driver detaches all pass-through
devices from VFIO domain by clearing domain id and page table root
pointer from each device table entry (DTE), and then invalidates
the DTE. Then, the VFIO driver unmap pages and invalidate IOMMU pages.

Currently, the IOMMU driver keeps track of which IOMMU and how many
devices are attached to the domain. When invalidate IOMMU pages,
the driver checks if the IOMMU is still attached to the domain before
issuing the invalidate page command.

However, since VFIO has already detached all devices from the domain,
the subsequent INVALIDATE_IOMMU_PAGES commands are being skipped as
there is no IOMMU attached to the domain. This results in data
corruption and could cause the PCI device to end up in indeterministic
state.

Fix this by invalidate IOMMU pages when detach a device, and
before decrementing the per-domain device reference counts.

Cc: Boris Ostrovsky 
Suggested-by: Joerg Roedel 
Co-developed-by: Brijesh Singh 
Signed-off-by: Brijesh Singh 
Signed-off-by: Suravee Suthikulpanit 
Fixes: 6de8ad9b9ee0 ('x86/amd-iommu: Make iommu_flush_pages aware of multiple 
IOMMUs')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 52c36394dba50..0ad8b7c78a438 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1982,6 +1982,7 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+   struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
u16 alias;
 
@@ -1997,10 +1998,6 @@ static void do_detach(struct iommu_dev_data *dev_data)
iommu = amd_iommu_rlookup_table[dev_data->devid];
alias = dev_data->alias;
 
-   /* decrease reference counters */
-   dev_data->domain->dev_iommu[iommu->index] -= 1;
-   dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+   /* Flush IOTLB */
+   domain_flush_tlb_pde(domain);
+
+   /* Wait for the flushes to finish */
+   domain_flush_complete(domain);
+
+   /* decrease reference counters - needs to happen after the flushes */
+   domain->dev_iommu[iommu->index] -= 1;
+   domain->dev_cnt -= 1;
 }
 
 /*
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 07/32] iommu/amd: Unmap all mapped pages in error path of map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit f1724c0883bb0ce93b8dcb94b53dcca3b75ac9a7 ]

In the error path of map_sg there is an incorrect if condition
for breaking out of the loop that searches the scatterlist
for mapped pages to unmap. Instead of breaking out of the
loop once all the pages that were mapped have been unmapped,
it will break out of the loop after it has unmapped 1 page.
Fix the condition, so it breaks out of the loop only after
all the mapped pages have been unmapped.

Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Cc: Joerg Roedel 
Signed-off-by: Jerry Snitselaar 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 4209aa1c09f9c..80fb16c8c05e9 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2604,7 +2604,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-   if (--mapped_pages)
+   if (--mapped_pages == 0)
goto out_free_iova;
}
}
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 09/32] iommu/amd: Fix IOMMU page flush when detach device from a domain

2019-02-23 Thread Sasha Levin
From: Suravee Suthikulpanit 

[ Upstream commit 9825bd94e3a2baae1f4874767ae3a7d4c049720e ]

When a VM is terminated, the VFIO driver detaches all pass-through
devices from VFIO domain by clearing domain id and page table root
pointer from each device table entry (DTE), and then invalidates
the DTE. Then, the VFIO driver unmap pages and invalidate IOMMU pages.

Currently, the IOMMU driver keeps track of which IOMMU and how many
devices are attached to the domain. When invalidate IOMMU pages,
the driver checks if the IOMMU is still attached to the domain before
issuing the invalidate page command.

However, since VFIO has already detached all devices from the domain,
the subsequent INVALIDATE_IOMMU_PAGES commands are being skipped as
there is no IOMMU attached to the domain. This results in data
corruption and could cause the PCI device to end up in indeterministic
state.

Fix this by invalidate IOMMU pages when detach a device, and
before decrementing the per-domain device reference counts.

Cc: Boris Ostrovsky 
Suggested-by: Joerg Roedel 
Co-developed-by: Brijesh Singh 
Signed-off-by: Brijesh Singh 
Signed-off-by: Suravee Suthikulpanit 
Fixes: 6de8ad9b9ee0 ('x86/amd-iommu: Make iommu_flush_pages aware of multiple 
IOMMUs')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 80fb16c8c05e9..7766f07ab9b45 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1889,6 +1889,7 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+   struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
u16 alias;
 
@@ -1904,10 +1905,6 @@ static void do_detach(struct iommu_dev_data *dev_data)
iommu = amd_iommu_rlookup_table[dev_data->devid];
alias = dev_data->alias;
 
-   /* decrease reference counters */
-   dev_data->domain->dev_iommu[iommu->index] -= 1;
-   dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -1917,6 +1914,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+   /* Flush IOTLB */
+   domain_flush_tlb_pde(domain);
+
+   /* Wait for the flushes to finish */
+   domain_flush_complete(domain);
+
+   /* decrease reference counters - needs to happen after the flushes */
+   domain->dev_iommu[iommu->index] -= 1;
+   domain->dev_cnt -= 1;
 }
 
 /*
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 11/65] iommu/amd: Call free_iova_fast with pfn in map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit 51d8838d66d3249508940d8f59b07701f2129723 ]

In the error path of map_sg, free_iova_fast is being called with
address instead of the pfn. This results in a bad value getting into
the rcache, and can result in hitting a BUG_ON when
iova_magazine_free_pfns is called.

Cc: Joerg Roedel 
Cc: Suravee Suthikulpanit 
Signed-off-by: Jerry Snitselaar 
Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index bee0dfb7b93b1..5edc8e6f27114 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2554,7 +2554,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
}
 
 out_free_iova:
-   free_iova_fast(&dma_dom->iovad, address, npages);
+   free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
return 0;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 06/45] iommu/amd: Call free_iova_fast with pfn in map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit 51d8838d66d3249508940d8f59b07701f2129723 ]

In the error path of map_sg, free_iova_fast is being called with
address instead of the pfn. This results in a bad value getting into
the rcache, and can result in hitting a BUG_ON when
iova_magazine_free_pfns is called.

Cc: Joerg Roedel 
Cc: Suravee Suthikulpanit 
Signed-off-by: Jerry Snitselaar 
Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index efa6cd2500b93..2dc9a71cb54f8 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2559,7 +2559,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
}
 
 out_free_iova:
-   free_iova_fast(&dma_dom->iovad, address, npages);
+   free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
return 0;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 15/65] iommu/amd: Fix IOMMU page flush when detach device from a domain

2019-02-23 Thread Sasha Levin
From: Suravee Suthikulpanit 

[ Upstream commit 9825bd94e3a2baae1f4874767ae3a7d4c049720e ]

When a VM is terminated, the VFIO driver detaches all pass-through
devices from VFIO domain by clearing domain id and page table root
pointer from each device table entry (DTE), and then invalidates
the DTE. Then, the VFIO driver unmap pages and invalidate IOMMU pages.

Currently, the IOMMU driver keeps track of which IOMMU and how many
devices are attached to the domain. When invalidate IOMMU pages,
the driver checks if the IOMMU is still attached to the domain before
issuing the invalidate page command.

However, since VFIO has already detached all devices from the domain,
the subsequent INVALIDATE_IOMMU_PAGES commands are being skipped as
there is no IOMMU attached to the domain. This results in data
corruption and could cause the PCI device to end up in indeterministic
state.

Fix this by invalidate IOMMU pages when detach a device, and
before decrementing the per-domain device reference counts.

Cc: Boris Ostrovsky 
Suggested-by: Joerg Roedel 
Co-developed-by: Brijesh Singh 
Signed-off-by: Brijesh Singh 
Signed-off-by: Suravee Suthikulpanit 
Fixes: 6de8ad9b9ee0 ('x86/amd-iommu: Make iommu_flush_pages aware of multiple 
IOMMUs')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 6459f4f621314..7b6d1a74ba3e4 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1922,16 +1922,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+   struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
u16 alias;
 
iommu = amd_iommu_rlookup_table[dev_data->devid];
alias = dev_data->alias;
 
-   /* decrease reference counters */
-   dev_data->domain->dev_iommu[iommu->index] -= 1;
-   dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -1941,6 +1938,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+   /* Flush IOTLB */
+   domain_flush_tlb_pde(domain);
+
+   /* Wait for the flushes to finish */
+   domain_flush_complete(domain);
+
+   /* decrease reference counters - needs to happen after the flushes */
+   domain->dev_iommu[iommu->index] -= 1;
+   domain->dev_cnt -= 1;
 }
 
 /*
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 09/45] iommu/amd: Fix IOMMU page flush when detach device from a domain

2019-02-23 Thread Sasha Levin
From: Suravee Suthikulpanit 

[ Upstream commit 9825bd94e3a2baae1f4874767ae3a7d4c049720e ]

When a VM is terminated, the VFIO driver detaches all pass-through
devices from VFIO domain by clearing domain id and page table root
pointer from each device table entry (DTE), and then invalidates
the DTE. Then, the VFIO driver unmap pages and invalidate IOMMU pages.

Currently, the IOMMU driver keeps track of which IOMMU and how many
devices are attached to the domain. When invalidate IOMMU pages,
the driver checks if the IOMMU is still attached to the domain before
issuing the invalidate page command.

However, since VFIO has already detached all devices from the domain,
the subsequent INVALIDATE_IOMMU_PAGES commands are being skipped as
there is no IOMMU attached to the domain. This results in data
corruption and could cause the PCI device to end up in indeterministic
state.

Fix this by invalidate IOMMU pages when detach a device, and
before decrementing the per-domain device reference counts.

Cc: Boris Ostrovsky 
Suggested-by: Joerg Roedel 
Co-developed-by: Brijesh Singh 
Signed-off-by: Brijesh Singh 
Signed-off-by: Suravee Suthikulpanit 
Fixes: 6de8ad9b9ee0 ('x86/amd-iommu: Make iommu_flush_pages aware of multiple 
IOMMUs')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index b418a859577ff..6f7587ef832e6 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1912,6 +1912,7 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+   struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
u16 alias;
 
@@ -1927,10 +1928,6 @@ static void do_detach(struct iommu_dev_data *dev_data)
iommu = amd_iommu_rlookup_table[dev_data->devid];
alias = dev_data->alias;
 
-   /* decrease reference counters */
-   dev_data->domain->dev_iommu[iommu->index] -= 1;
-   dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -1940,6 +1937,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+   /* Flush IOTLB */
+   domain_flush_tlb_pde(domain);
+
+   /* Wait for the flushes to finish */
+   domain_flush_complete(domain);
+
+   /* decrease reference counters - needs to happen after the flushes */
+   domain->dev_iommu[iommu->index] -= 1;
+   domain->dev_cnt -= 1;
 }
 
 /*
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 07/45] iommu/amd: Unmap all mapped pages in error path of map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit f1724c0883bb0ce93b8dcb94b53dcca3b75ac9a7 ]

In the error path of map_sg there is an incorrect if condition
for breaking out of the loop that searches the scatterlist
for mapped pages to unmap. Instead of breaking out of the
loop once all the pages that were mapped have been unmapped,
it will break out of the loop after it has unmapped 1 page.
Fix the condition, so it breaks out of the loop only after
all the mapped pages have been unmapped.

Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Cc: Joerg Roedel 
Signed-off-by: Jerry Snitselaar 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 2dc9a71cb54f8..b418a859577ff 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2553,7 +2553,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-   if (--mapped_pages)
+   if (--mapped_pages == 0)
goto out_free_iova;
}
}
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 12/65] iommu/amd: Unmap all mapped pages in error path of map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit f1724c0883bb0ce93b8dcb94b53dcca3b75ac9a7 ]

In the error path of map_sg there is an incorrect if condition
for breaking out of the loop that searches the scatterlist
for mapped pages to unmap. Instead of breaking out of the
loop once all the pages that were mapped have been unmapped,
it will break out of the loop after it has unmapped 1 page.
Fix the condition, so it breaks out of the loop only after
all the mapped pages have been unmapped.

Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Cc: Joerg Roedel 
Signed-off-by: Jerry Snitselaar 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 5edc8e6f27114..6459f4f621314 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2548,7 +2548,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-   if (--mapped_pages)
+   if (--mapped_pages == 0)
goto out_free_iova;
}
}
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.20 18/72] iommu/amd: Fix IOMMU page flush when detach device from a domain

2019-02-23 Thread Sasha Levin
From: Suravee Suthikulpanit 

[ Upstream commit 9825bd94e3a2baae1f4874767ae3a7d4c049720e ]

When a VM is terminated, the VFIO driver detaches all pass-through
devices from VFIO domain by clearing domain id and page table root
pointer from each device table entry (DTE), and then invalidates
the DTE. Then, the VFIO driver unmap pages and invalidate IOMMU pages.

Currently, the IOMMU driver keeps track of which IOMMU and how many
devices are attached to the domain. When invalidate IOMMU pages,
the driver checks if the IOMMU is still attached to the domain before
issuing the invalidate page command.

However, since VFIO has already detached all devices from the domain,
the subsequent INVALIDATE_IOMMU_PAGES commands are being skipped as
there is no IOMMU attached to the domain. This results in data
corruption and could cause the PCI device to end up in indeterministic
state.

Fix this by invalidate IOMMU pages when detach a device, and
before decrementing the per-domain device reference counts.

Cc: Boris Ostrovsky 
Suggested-by: Joerg Roedel 
Co-developed-by: Brijesh Singh 
Signed-off-by: Brijesh Singh 
Signed-off-by: Suravee Suthikulpanit 
Fixes: 6de8ad9b9ee0 ('x86/amd-iommu: Make iommu_flush_pages aware of multiple 
IOMMUs')
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 15 +++
 1 file changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 9d06bc36a2c19..862cf8c27dd27 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1922,16 +1922,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+   struct protection_domain *domain = dev_data->domain;
struct amd_iommu *iommu;
u16 alias;
 
iommu = amd_iommu_rlookup_table[dev_data->devid];
alias = dev_data->alias;
 
-   /* decrease reference counters */
-   dev_data->domain->dev_iommu[iommu->index] -= 1;
-   dev_data->domain->dev_cnt -= 1;
-
/* Update data structures */
dev_data->domain = NULL;
list_del(&dev_data->list);
@@ -1941,6 +1938,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
/* Flush the DTE entry */
device_flush_dte(dev_data);
+
+   /* Flush IOTLB */
+   domain_flush_tlb_pde(domain);
+
+   /* Wait for the flushes to finish */
+   domain_flush_complete(domain);
+
+   /* decrease reference counters - needs to happen after the flushes */
+   domain->dev_iommu[iommu->index] -= 1;
+   domain->dev_cnt -= 1;
 }
 
 /*
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.20 15/72] iommu/amd: Unmap all mapped pages in error path of map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit f1724c0883bb0ce93b8dcb94b53dcca3b75ac9a7 ]

In the error path of map_sg there is an incorrect if condition
for breaking out of the loop that searches the scatterlist
for mapped pages to unmap. Instead of breaking out of the
loop once all the pages that were mapped have been unmapped,
it will break out of the loop after it has unmapped 1 page.
Fix the condition, so it breaks out of the loop only after
all the mapped pages have been unmapped.

Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Cc: Joerg Roedel 
Signed-off-by: Jerry Snitselaar 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index ce543ecbb4158..9d06bc36a2c19 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2548,7 +2548,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
bus_addr  = address + s->dma_address + (j << 
PAGE_SHIFT);
iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-   if (--mapped_pages)
+   if (--mapped_pages == 0)
goto out_free_iova;
}
}
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.20 14/72] iommu/amd: Call free_iova_fast with pfn in map_sg

2019-02-23 Thread Sasha Levin
From: Jerry Snitselaar 

[ Upstream commit 51d8838d66d3249508940d8f59b07701f2129723 ]

In the error path of map_sg, free_iova_fast is being called with
address instead of the pfn. This results in a bad value getting into
the rcache, and can result in hitting a BUG_ON when
iova_magazine_free_pfns is called.

Cc: Joerg Roedel 
Cc: Suravee Suthikulpanit 
Signed-off-by: Jerry Snitselaar 
Fixes: 80187fd39dcb ("iommu/amd: Optimize map_sg and unmap_sg")
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 1167ff0416cf7..ce543ecbb4158 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -2554,7 +2554,7 @@ static int map_sg(struct device *dev, struct scatterlist 
*sglist,
}
 
 out_free_iova:
-   free_iova_fast(&dma_dom->iovad, address, npages);
+   free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
return 0;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 2/3] HYPERV/IOMMU: Add Hyper-V stub IOMMU driver

2019-02-01 Thread Sasha Levin

Hi Tianyu,

Few comments below.

On Thu, Jan 31, 2019 at 06:17:32PM +0800, lantianyu1...@gmail.com wrote:

From: Lan Tianyu 

On the bare metal, enabling X2APIC mode requires interrupt remapping
function which helps to deliver irq to cpu with 32-bit APIC ID.
Hyper-V doesn't provide interrupt remapping function so far and Hyper-V
MSI protocol already supports to deliver interrupt to the CPU whose
virtual processor index is more than 255. IO-APIC interrupt still has
8-bit APIC ID limitation.

This patch is to add Hyper-V stub IOMMU driver in order to enable
X2APIC mode successfully in Hyper-V Linux guest. The driver returns X2APIC
interrupt remapping capability when X2APIC mode is available. Otherwise,
it creates a Hyper-V irq domain to limit IO-APIC interrupts' affinity
and make sure cpus assigned with IO-APIC interrupt have 8-bit APIC ID.

Signed-off-by: Lan Tianyu 
---
drivers/iommu/Kconfig |   7 ++
drivers/iommu/Makefile|   1 +
drivers/iommu/hyperv-iommu.c  | 189 ++
drivers/iommu/irq_remapping.c |   3 +
drivers/iommu/irq_remapping.h |   1 +
5 files changed, 201 insertions(+)
create mode 100644 drivers/iommu/hyperv-iommu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index 45d7021..5c397c0 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -437,4 +437,11 @@ config QCOM_IOMMU
help
  Support for IOMMU on certain Qualcomm SoCs.

+config HYPERV_IOMMU
+   bool "Hyper-V stub IOMMU support"
+   depends on HYPERV


select IOMMU_API ?


+   help
+   Hyper-V stub IOMMU driver provides capability to run
+   Linux guest with X2APIC mode enabled.
+
endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index a158a68..8c71a15 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -32,3 +32,4 @@ obj-$(CONFIG_EXYNOS_IOMMU) += exynos-iommu.o
obj-$(CONFIG_FSL_PAMU) += fsl_pamu.o fsl_pamu_domain.o
obj-$(CONFIG_S390_IOMMU) += s390-iommu.o
obj-$(CONFIG_QCOM_IOMMU) += qcom_iommu.o
+obj-$(CONFIG_HYPERV_IOMMU) += hyperv-iommu.o
diff --git a/drivers/iommu/hyperv-iommu.c b/drivers/iommu/hyperv-iommu.c
new file mode 100644
index 000..a64b747
--- /dev/null
+++ b/drivers/iommu/hyperv-iommu.c
@@ -0,0 +1,189 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define pr_fmt(fmt) "HYPERV-IR: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+#include 
+#include 
+#include 
+
+#include "irq_remapping.h"
+
+/*
+ * According IO-APIC spec, IO APIC has a 24-entry Interrupt
+ * Redirection Table.


Can the spec be linked somewhere? In the commit message, or here?


+ */
+#define IOAPIC_REMAPPING_ENTRY 24
+
+static cpumask_t ioapic_max_cpumask = { CPU_BITS_NONE };
+struct irq_domain *ioapic_ir_domain;
+
+static int hyperv_ir_set_affinity(struct irq_data *data,
+   const struct cpumask *mask, bool force)
+{
+   struct irq_data *parent = data->parent_data;
+   struct irq_cfg *cfg = irqd_cfg(data);
+   struct IO_APIC_route_entry *entry;
+   cpumask_t cpumask;
+   int ret;
+
+   cpumask_andnot(&cpumask, mask, &ioapic_max_cpumask);
+
+   /* Return error If new irq affinity is out of ioapic_max_cpumask. */
+   if (!cpumask_empty(&cpumask))
+   return -EINVAL;
+
+   ret = parent->chip->irq_set_affinity(parent, mask, force);
+   if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE)
+   return ret;
+
+   entry = data->chip_data;
+   entry->dest = cfg->dest_apicid;
+   entry->vector = cfg->vector;
+   send_cleanup_vector(cfg);
+
+   return 0;
+}
+
+static struct irq_chip hyperv_ir_chip = {
+   .name   = "HYPERV-IR",
+   .irq_ack= apic_ack_irq,
+   .irq_set_affinity   = hyperv_ir_set_affinity,
+};
+
+static int hyperv_irq_remapping_alloc(struct irq_domain *domain,
+unsigned int virq, unsigned int nr_irqs,
+void *arg)
+{
+   struct irq_alloc_info *info = arg;
+   struct IO_APIC_route_entry *entry;


What's the role of this variable? We set it, once, later on in the
function but that's all?


+   struct irq_data *irq_data;
+   struct irq_desc *desc;
+   struct irq_cfg *cfg;
+   int ret = 0;
+
+   if (!info || info->type != X86_IRQ_ALLOC_TYPE_IOAPIC || nr_irqs > 1)
+   return -EINVAL;
+
+   ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg);
+   if (ret < 0)
+   goto fail;
+
+   irq_data = irq_domain_get_irq_data(domain, virq);
+   cfg = irqd_cfg(irq_data);


Is this actually being used anywhere, or do we only need it for the
check below? It's not clear from the code why we're calling irqd_cfg()
and ignoring the result.


+   if (!irq_data || !cfg) {


You just dereferenced irq_data in the line above this one, it's a bit
late to check that it's not NULL.


+  

[PATCH AUTOSEL 4.4 35/80] iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer

2019-01-28 Thread Sasha Levin
From: Will Deacon 

[ Upstream commit a868e8530441286342f90c1fd9c5f24de3aa2880 ]

After removing an entry from a queue (e.g. reading an event in
arm_smmu_evtq_thread()) it is necessary to advance the MMIO consumer
pointer to free the queue slot back to the SMMU. A memory barrier is
required here so that all reads targetting the queue entry have
completed before the consumer pointer is updated.

The implementation of queue_inc_cons() relies on a writel() to complete
the previous reads, but this is incorrect because writel() is only
guaranteed to complete prior writes. This patch replaces the call to
writel() with an mb(); writel_relaxed() sequence, which gives us the
read->write ordering which we require.

Cc: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index fc6eb752ab35..eb9937225d64 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -683,7 +683,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
 
q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-   writel(q->cons, q->cons_reg);
+
+   /*
+* Ensure that all CPU accesses (reads and writes) to the queue
+* are complete before we update the cons pointer.
+*/
+   mb();
+   writel_relaxed(q->cons, q->cons_reg);
 }
 
 static int queue_sync_prod(struct arm_smmu_queue *q)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 049/107] iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer

2019-01-28 Thread Sasha Levin
From: Will Deacon 

[ Upstream commit a868e8530441286342f90c1fd9c5f24de3aa2880 ]

After removing an entry from a queue (e.g. reading an event in
arm_smmu_evtq_thread()) it is necessary to advance the MMIO consumer
pointer to free the queue slot back to the SMMU. A memory barrier is
required here so that all reads targetting the queue entry have
completed before the consumer pointer is updated.

The implementation of queue_inc_cons() relies on a writel() to complete
the previous reads, but this is incorrect because writel() is only
guaranteed to complete prior writes. This patch replaces the call to
writel() with an mb(); writel_relaxed() sequence, which gives us the
read->write ordering which we require.

Cc: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index ff4be1174ff0..7bd98585d78d 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -697,7 +697,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
 
q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-   writel(q->cons, q->cons_reg);
+
+   /*
+* Ensure that all CPU accesses (reads and writes) to the queue
+* are complete before we update the cons pointer.
+*/
+   mb();
+   writel_relaxed(q->cons, q->cons_reg);
 }
 
 static int queue_sync_prod(struct arm_smmu_queue *q)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 043/107] iommu/amd: Fix amd_iommu=force_isolation

2019-01-28 Thread Sasha Levin
From: Yu Zhao 

[ Upstream commit c12b08ebbe16f0d3a96a116d86709b04c1ee8e74 ]

The parameter is still there but it's ignored. We need to check its
value before deciding to go into passthrough mode for AMD IOMMU v2
capable device.

We occasionally use this parameter to force v2 capable device into
translation mode to debug memory corruption that we suspect is
caused by DMA writes.

To address the following comment from Joerg Roedel on the first
version, v2 capability of device is completely ignored.
> This breaks the iommu_v2 use-case, as it needs a direct mapping for the
> devices that support it.

And from Documentation/admin-guide/kernel-parameters.txt:
  This option does not override iommu=pt

Fixes: aafd8ba0ca74 ("iommu/amd: Implement add_device and remove_device")

Signed-off-by: Yu Zhao 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index bba1b9f2f782..e984418ffa2a 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -464,7 +464,14 @@ static int iommu_init_device(struct device *dev)
 
dev_data->alias = get_alias(dev);
 
-   if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
+   /*
+* By default we use passthrough mode for IOMMUv2 capable device.
+* But if amd_iommu=force_isolation is set (e.g. to debug DMA to
+* invalid address), we ignore the capability for the device so
+* it'll be forced to go into translation mode.
+*/
+   if ((iommu_pass_through || !amd_iommu_force_isolation) &&
+   dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
struct amd_iommu *iommu;
 
iommu = amd_iommu_rlookup_table[dev_data->devid];
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.9 048/107] iommu/arm-smmu: Add support for qcom, smmu-v2 variant

2019-01-28 Thread Sasha Levin
From: Vivek Gautam 

[ Upstream commit 89cddc563743cb1e0068867ac97013b2a5bf86aa ]

qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
clock and power requirements.
On msm8996, multiple cores, viz. mdss, video, etc. use this
smmu. On sdm845, this smmu is used with gpu.
Add bindings for the same.

Signed-off-by: Vivek Gautam 
Reviewed-by: Rob Herring 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 5a9a4416f467..f7ecb30a0bac 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -297,6 +297,7 @@ enum arm_smmu_implementation {
GENERIC_SMMU,
ARM_MMU500,
CAVIUM_SMMUV2,
+   QCOM_SMMUV2,
 };
 
 struct arm_smmu_s2cr {
@@ -1894,6 +1895,7 @@ ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, 
GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
 ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
+ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2);
 
 static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
@@ -1902,6 +1904,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,mmu-401", .data = &arm_mmu401 },
{ .compatible = "arm,mmu-500", .data = &arm_mmu500 },
{ .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },
+   { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 },
{ },
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 085/170] iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer

2019-01-28 Thread Sasha Levin
From: Will Deacon 

[ Upstream commit a868e8530441286342f90c1fd9c5f24de3aa2880 ]

After removing an entry from a queue (e.g. reading an event in
arm_smmu_evtq_thread()) it is necessary to advance the MMIO consumer
pointer to free the queue slot back to the SMMU. A memory barrier is
required here so that all reads targetting the queue entry have
completed before the consumer pointer is updated.

The implementation of queue_inc_cons() relies on a writel() to complete
the previous reads, but this is incorrect because writel() is only
guaranteed to complete prior writes. This patch replaces the call to
writel() with an mb(); writel_relaxed() sequence, which gives us the
read->write ordering which we require.

Cc: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 26e99c03390f..09eb258a9a7d 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -730,7 +730,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
 
q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-   writel(q->cons, q->cons_reg);
+
+   /*
+* Ensure that all CPU accesses (reads and writes) to the queue
+* are complete before we update the cons pointer.
+*/
+   mb();
+   writel_relaxed(q->cons, q->cons_reg);
 }
 
 static int queue_sync_prod(struct arm_smmu_queue *q)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 084/170] iommu/arm-smmu: Add support for qcom, smmu-v2 variant

2019-01-28 Thread Sasha Levin
From: Vivek Gautam 

[ Upstream commit 89cddc563743cb1e0068867ac97013b2a5bf86aa ]

qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
clock and power requirements.
On msm8996, multiple cores, viz. mdss, video, etc. use this
smmu. On sdm845, this smmu is used with gpu.
Add bindings for the same.

Signed-off-by: Vivek Gautam 
Reviewed-by: Rob Herring 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 15b5856475fc..01a6a0ea2a4f 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -117,6 +117,7 @@ enum arm_smmu_implementation {
GENERIC_SMMU,
ARM_MMU500,
CAVIUM_SMMUV2,
+   QCOM_SMMUV2,
 };
 
 /* Until ACPICA headers cover IORT rev. C */
@@ -1910,6 +1911,7 @@ ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, 
GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
 ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
+ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2);
 
 static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
@@ -1918,6 +1920,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,mmu-401", .data = &arm_mmu401 },
{ .compatible = "arm,mmu-500", .data = &arm_mmu500 },
{ .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },
+   { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 },
{ },
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.14 075/170] iommu/amd: Fix amd_iommu=force_isolation

2019-01-28 Thread Sasha Levin
From: Yu Zhao 

[ Upstream commit c12b08ebbe16f0d3a96a116d86709b04c1ee8e74 ]

The parameter is still there but it's ignored. We need to check its
value before deciding to go into passthrough mode for AMD IOMMU v2
capable device.

We occasionally use this parameter to force v2 capable device into
translation mode to debug memory corruption that we suspect is
caused by DMA writes.

To address the following comment from Joerg Roedel on the first
version, v2 capability of device is completely ignored.
> This breaks the iommu_v2 use-case, as it needs a direct mapping for the
> devices that support it.

And from Documentation/admin-guide/kernel-parameters.txt:
  This option does not override iommu=pt

Fixes: aafd8ba0ca74 ("iommu/amd: Implement add_device and remove_device")

Signed-off-by: Yu Zhao 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index efa6cd2500b9..766103ea237e 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -442,7 +442,14 @@ static int iommu_init_device(struct device *dev)
 
dev_data->alias = get_alias(dev);
 
-   if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
+   /*
+* By default we use passthrough mode for IOMMUv2 capable device.
+* But if amd_iommu=force_isolation is set (e.g. to debug DMA to
+* invalid address), we ignore the capability for the device so
+* it'll be forced to go into translation mode.
+*/
+   if ((iommu_pass_through || !amd_iommu_force_isolation) &&
+   dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
struct amd_iommu *iommu;
 
iommu = amd_iommu_rlookup_table[dev_data->devid];
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 130/258] iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer

2019-01-28 Thread Sasha Levin
From: Will Deacon 

[ Upstream commit a868e8530441286342f90c1fd9c5f24de3aa2880 ]

After removing an entry from a queue (e.g. reading an event in
arm_smmu_evtq_thread()) it is necessary to advance the MMIO consumer
pointer to free the queue slot back to the SMMU. A memory barrier is
required here so that all reads targetting the queue entry have
completed before the consumer pointer is updated.

The implementation of queue_inc_cons() relies on a writel() to complete
the previous reads, but this is incorrect because writel() is only
guaranteed to complete prior writes. This patch replaces the call to
writel() with an mb(); writel_relaxed() sequence, which gives us the
read->write ordering which we require.

Cc: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4afb9cb99ea3..9ae3678844eb 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -688,7 +688,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
 
q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-   writel(q->cons, q->cons_reg);
+
+   /*
+* Ensure that all CPU accesses (reads and writes) to the queue
+* are complete before we update the cons pointer.
+*/
+   mb();
+   writel_relaxed(q->cons, q->cons_reg);
 }
 
 static int queue_sync_prod(struct arm_smmu_queue *q)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 128/258] iommu/arm-smmu-v3: Avoid memory corruption from Hisilicon MSI payloads

2019-01-28 Thread Sasha Levin
From: Zhen Lei 

[ Upstream commit 84a9a75774961612d0c7dd34a1777e8f98a65abd ]

The GITS_TRANSLATER MMIO doorbell register in the ITS hardware is
architected to be 4 bytes in size, yet on hi1620 and earlier, Hisilicon
have allocated the adjacent 4 bytes to carry some IMPDEF sideband
information which results in an 8-byte MSI payload being delivered when
signalling an interrupt:

MSIAddr:
 |4bytes|4bytes|
 |MSIData   |IMPDEF|

This poses no problem for the ITS hardware because the adjacent 4 bytes
are reserved in the memory map. However, when delivering MSIs to memory,
as we do in the SMMUv3 driver for signalling the completion of a SYNC
command, the extended payload will corrupt the 4 bytes adjacent to the
"sync_count" member in struct arm_smmu_device. Fortunately, the current
layout allocates these bytes to padding, but this is fragile and we
should make this explicit.

Reviewed-by: Robin Murphy 
Signed-off-by: Zhen Lei 
[will: Rewrote commit message and comment]
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 6 +-
 1 file changed, 5 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 3e02aace38b1..4afb9cb99ea3 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -586,7 +586,11 @@ struct arm_smmu_device {
 
struct arm_smmu_strtab_cfg  strtab_cfg;
 
-   u32 sync_count;
+   /* Hi16xx adds an extra 32 bits of goodness to its MSI payload */
+   union {
+   u32 sync_count;
+   u64 padding;
+   };
 
/* IOMMU core code handle */
struct iommu_device iommu;
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 118/258] iommu/amd: Fix amd_iommu=force_isolation

2019-01-28 Thread Sasha Levin
From: Yu Zhao 

[ Upstream commit c12b08ebbe16f0d3a96a116d86709b04c1ee8e74 ]

The parameter is still there but it's ignored. We need to check its
value before deciding to go into passthrough mode for AMD IOMMU v2
capable device.

We occasionally use this parameter to force v2 capable device into
translation mode to debug memory corruption that we suspect is
caused by DMA writes.

To address the following comment from Joerg Roedel on the first
version, v2 capability of device is completely ignored.
> This breaks the iommu_v2 use-case, as it needs a direct mapping for the
> devices that support it.

And from Documentation/admin-guide/kernel-parameters.txt:
  This option does not override iommu=pt

Fixes: aafd8ba0ca74 ("iommu/amd: Implement add_device and remove_device")

Signed-off-by: Yu Zhao 
Signed-off-by: Joerg Roedel 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/amd_iommu.c | 9 -
 1 file changed, 8 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index bee0dfb7b93b..34c9aa76a7bd 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -438,7 +438,14 @@ static int iommu_init_device(struct device *dev)
 
dev_data->alias = get_alias(dev);
 
-   if (dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
+   /*
+* By default we use passthrough mode for IOMMUv2 capable device.
+* But if amd_iommu=force_isolation is set (e.g. to debug DMA to
+* invalid address), we ignore the capability for the device so
+* it'll be forced to go into translation mode.
+*/
+   if ((iommu_pass_through || !amd_iommu_force_isolation) &&
+   dev_is_pci(dev) && pci_iommuv2_capable(to_pci_dev(dev))) {
struct amd_iommu *iommu;
 
iommu = amd_iommu_rlookup_table[dev_data->devid];
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.19 129/258] iommu/arm-smmu: Add support for qcom, smmu-v2 variant

2019-01-28 Thread Sasha Levin
From: Vivek Gautam 

[ Upstream commit 89cddc563743cb1e0068867ac97013b2a5bf86aa ]

qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
clock and power requirements.
On msm8996, multiple cores, viz. mdss, video, etc. use this
smmu. On sdm845, this smmu is used with gpu.
Add bindings for the same.

Signed-off-by: Vivek Gautam 
Reviewed-by: Rob Herring 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index e7cbf4fcf61d..ce119cb279c3 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -118,6 +118,7 @@ enum arm_smmu_implementation {
GENERIC_SMMU,
ARM_MMU500,
CAVIUM_SMMUV2,
+   QCOM_SMMUV2,
 };
 
 struct arm_smmu_s2cr {
@@ -1912,6 +1913,7 @@ ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, 
GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
 ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
+ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2);
 
 static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
@@ -1920,6 +1922,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,mmu-401", .data = &arm_mmu401 },
{ .compatible = "arm,mmu-500", .data = &arm_mmu500 },
{ .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },
+   { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 },
{ },
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.20 154/304] iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer

2019-01-28 Thread Sasha Levin
From: Will Deacon 

[ Upstream commit a868e8530441286342f90c1fd9c5f24de3aa2880 ]

After removing an entry from a queue (e.g. reading an event in
arm_smmu_evtq_thread()) it is necessary to advance the MMIO consumer
pointer to free the queue slot back to the SMMU. A memory barrier is
required here so that all reads targetting the queue entry have
completed before the consumer pointer is updated.

The implementation of queue_inc_cons() relies on a writel() to complete
the previous reads, but this is incorrect because writel() is only
guaranteed to complete prior writes. This patch replaces the call to
writel() with an mb(); writel_relaxed() sequence, which gives us the
read->write ordering which we require.

Cc: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu-v3.c | 8 +++-
 1 file changed, 7 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 62ef4afc9ee5..11f528e727a1 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -679,7 +679,13 @@ static void queue_inc_cons(struct arm_smmu_queue *q)
u32 cons = (Q_WRP(q, q->cons) | Q_IDX(q, q->cons)) + 1;
 
q->cons = Q_OVF(q, q->cons) | Q_WRP(q, cons) | Q_IDX(q, cons);
-   writel(q->cons, q->cons_reg);
+
+   /*
+* Ensure that all CPU accesses (reads and writes) to the queue
+* are complete before we update the cons pointer.
+*/
+   mb();
+   writel_relaxed(q->cons, q->cons_reg);
 }
 
 static int queue_sync_prod(struct arm_smmu_queue *q)
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH AUTOSEL 4.20 153/304] iommu/arm-smmu: Add support for qcom, smmu-v2 variant

2019-01-28 Thread Sasha Levin
From: Vivek Gautam 

[ Upstream commit 89cddc563743cb1e0068867ac97013b2a5bf86aa ]

qcom,smmu-v2 is an arm,smmu-v2 implementation with specific
clock and power requirements.
On msm8996, multiple cores, viz. mdss, video, etc. use this
smmu. On sdm845, this smmu is used with gpu.
Add bindings for the same.

Signed-off-by: Vivek Gautam 
Reviewed-by: Rob Herring 
Reviewed-by: Tomasz Figa 
Tested-by: Srinivas Kandagatla 
Reviewed-by: Robin Murphy 
Signed-off-by: Will Deacon 
Signed-off-by: Sasha Levin 
---
 drivers/iommu/arm-smmu.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 5a28ae892504..e23aa7f6c4ad 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -119,6 +119,7 @@ enum arm_smmu_implementation {
GENERIC_SMMU,
ARM_MMU500,
CAVIUM_SMMUV2,
+   QCOM_SMMUV2,
 };
 
 struct arm_smmu_s2cr {
@@ -1954,6 +1955,7 @@ ARM_SMMU_MATCH_DATA(smmu_generic_v2, ARM_SMMU_V2, 
GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu401, ARM_SMMU_V1_64K, GENERIC_SMMU);
 ARM_SMMU_MATCH_DATA(arm_mmu500, ARM_SMMU_V2, ARM_MMU500);
 ARM_SMMU_MATCH_DATA(cavium_smmuv2, ARM_SMMU_V2, CAVIUM_SMMUV2);
+ARM_SMMU_MATCH_DATA(qcom_smmuv2, ARM_SMMU_V2, QCOM_SMMUV2);
 
 static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,smmu-v1", .data = &smmu_generic_v1 },
@@ -1962,6 +1964,7 @@ static const struct of_device_id arm_smmu_of_match[] = {
{ .compatible = "arm,mmu-401", .data = &arm_mmu401 },
{ .compatible = "arm,mmu-500", .data = &arm_mmu500 },
{ .compatible = "cavium,smmu-v2", .data = &cavium_smmuv2 },
+   { .compatible = "qcom,smmu-v2", .data = &qcom_smmuv2 },
{ },
 };
 MODULE_DEVICE_TABLE(of, arm_smmu_of_match);
-- 
2.19.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


<    1   2   3   4   5   >