Re: use generic DMA mapping code in powerpc V4

2018-12-11 Thread Christian Zigotzky


> On 12. Dec 2018, at 01:47, Benjamin Herrenschmidt  
> wrote:
> 
>> On Tue, 2018-12-11 at 19:17 +0100, Christian Zigotzky wrote:
>> X5000 (P5020 board): U-Boot loads the kernel and the dtb file. Then the 
>> kernel starts but it doesn't find any hard disks (partitions). That 
>> means this is also the bad commit for the P5020 board.
> 
> What are the disks hanging off ? A PCIe device of some sort ?
> 
> Can you send good & bad dmesg logs ?
> 
> Ben.
> 
> 
Unfortunately not. It doesn’t detect any hard disk. That means the kernel ring 
buffer won’t save to log files. I don’t have a serial null modem cable for 
seeing all output. We use SATA disks. I will investigate more in this problem 
with rollback the files in the bad commit.

— Christian



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

[RFC PATCH 1/3] PCI: Add dma-resv window list

2018-12-11 Thread Srinath Mannam via iommu
Add a dma_resv parameter in pci host bridge structure
to hold resource entries list of memory regions for
which IOVAs has to reserve.

IOMMU framework reserve IOVA for this list of address
range while initializing IOMMU domain of corresponding
PCI EP connected to the HOST.

PCIe host driver will add resource entries to this
list based on requirements.
Few hosts can't use all inbound address, so those
address regions will be add to this list to avoid
IOMMU mapping.

Signed-off-by: Srinath Mannam 
---
 drivers/pci/probe.c | 3 +++
 include/linux/pci.h | 1 +
 2 files changed, 4 insertions(+)

diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index ec78400..bbed0e7 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -544,6 +544,7 @@ struct pci_host_bridge *pci_alloc_host_bridge(size_t priv)
return NULL;
 
INIT_LIST_HEAD(>windows);
+   INIT_LIST_HEAD(>dma_resv);
bridge->dev.release = pci_release_host_bridge_dev;
 
/*
@@ -572,6 +573,7 @@ struct pci_host_bridge *devm_pci_alloc_host_bridge(struct 
device *dev,
return NULL;
 
INIT_LIST_HEAD(>windows);
+   INIT_LIST_HEAD(>dma_resv);
bridge->dev.release = devm_pci_release_host_bridge_dev;
 
return bridge;
@@ -581,6 +583,7 @@ EXPORT_SYMBOL(devm_pci_alloc_host_bridge);
 void pci_free_host_bridge(struct pci_host_bridge *bridge)
 {
pci_free_resource_list(>windows);
+   pci_free_resource_list(>dma_resv);
 
kfree(bridge);
 }
diff --git a/include/linux/pci.h b/include/linux/pci.h
index e72ca8d..1f0a32a 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -472,6 +472,7 @@ struct pci_host_bridge {
void*sysdata;
int busnr;
struct list_head windows;   /* resource_entry */
+   struct list_head dma_resv;  /* reserv dma ranges */
u8 (*swizzle_irq)(struct pci_dev *, u8 *); /* Platform IRQ swizzler */
int (*map_irq)(const struct pci_dev *, u8, u8);
void (*release_fn)(struct pci_host_bridge *);
-- 
2.7.4

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


[RFC PATCH 2/3] iommu/dma: IOVA reserve for PCI host reserve address list

2018-12-11 Thread Srinath Mannam via iommu
PCI host has list of resource entries contain memory
address range for which IOVA address mapping has to
be reserve.
These address ranges are the address holes in
dma-ranges property.

It is similar to PCI IO resources address range
reserving in IOMMU for each EP connected to
corresponding host.

Signed-off-by: Srinath Mannam 
---
 drivers/iommu/dma-iommu.c | 8 
 1 file changed, 8 insertions(+)

diff --git a/drivers/iommu/dma-iommu.c b/drivers/iommu/dma-iommu.c
index 511ff9a..346da81 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -220,6 +220,14 @@ static void iova_reserve_pci_windows(struct pci_dev *dev,
hi = iova_pfn(iovad, window->res->end - window->offset);
reserve_iova(iovad, lo, hi);
}
+
+   /* Get reserved DMA windows from host bridge */
+   resource_list_for_each_entry(window, >dma_resv) {
+
+   lo = iova_pfn(iovad, window->res->start - window->offset);
+   hi = iova_pfn(iovad, window->res->end - window->offset);
+   reserve_iova(iovad, lo, hi);
+   }
 }
 
 static int iova_reserve_iommu_regions(struct device *dev,
-- 
2.7.4

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


[RFC PATCH 0/3] PCIe Host request to reserve IOVA

2018-12-11 Thread Srinath Mannam via iommu
Few SOCs have limitation that their PCIe host
can't allow few inbound address ranges.
Allowed inbound address ranges are listed in
dma-ranges DT property and this address ranges
are required to do IOVA mapping.
Remaining address ranges have to be reserved in
IOVA mapping.

PCIe Host driver of those SOCs has to list all
address ranges which have to reserve their IOVA
address into PCIe host bridge resource entry list.
IOMMU framework will reserve these IOVAs while
initializing IOMMU domain.

This patch set is based on Linux-4.19-rc1.

Srinath Mannam (3):
  PCI: Add dma-resv window list
  iommu/dma: IOVA reserve for PCI host reserve address list
  PCI: iproc: Add dma reserve resources to host

 drivers/iommu/dma-iommu.c   |  8 ++
 drivers/pci/controller/pcie-iproc.c | 49 +
 drivers/pci/probe.c |  3 +++
 include/linux/pci.h |  1 +
 4 files changed, 61 insertions(+)

-- 
2.7.4

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


Re: use generic DMA mapping code in powerpc V4

2018-12-11 Thread Benjamin Herrenschmidt
On Tue, 2018-12-11 at 19:17 +0100, Christian Zigotzky wrote:
> X5000 (P5020 board): U-Boot loads the kernel and the dtb file. Then the 
> kernel starts but it doesn't find any hard disks (partitions). That 
> means this is also the bad commit for the P5020 board.

What are the disks hanging off ? A PCIe device of some sort ?

Can you send good & bad dmesg logs ?

Ben.


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


Re: [PATCH v6 0/7] Add virtio-iommu driver

2018-12-11 Thread Michael S. Tsirkin
On Tue, Dec 11, 2018 at 10:31:01AM -0800, Christoph Hellwig wrote:
> On Tue, Dec 11, 2018 at 06:20:57PM +, Jean-Philippe Brucker wrote:
> > Implement the virtio-iommu driver, following specification v0.9 [1].
> > 
> > Only minor changes since v5 [2]. I fixed issues reported by Michael and
> > added tags from Eric and Bharat. Thanks!
> > 
> > You can find Linux driver and kvmtool device on v0.9 branches [3],
> > module and x86 support on virtio-iommu/devel. Also tested with Eric's
> > QEMU device [4].
> 
> Just curious, what is the use case for it?

If what I saw is any indication, it allows a very simple implementation
of page table shadowing on the host, at the cost of not being able to
accelerate with a hardware nested page tables support when available.

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


[GIT PULL] iommu/arm-smmu: Updates for 4.21

2018-12-11 Thread Will Deacon
Hi Joerg,

Please pull the following arm-smmu updates for 4.21. This includes the
clock and pm_runtime updates to the arm-smmu driver, as well as some
non-critical fixes for the arm-smmu-v3 driver.

Cheers,

Will

--->8

The following changes since commit 9ff01193a20d391e8dbce4403dd5ef87c7eaaca6:

  Linux 4.20-rc3 (2018-11-18 13:33:44 -0800)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git 
for-joerg/arm-smmu/updates

for you to fetch changes up to 89cddc563743cb1e0068867ac97013b2a5bf86aa:

  iommu/arm-smmu: Add support for qcom,smmu-v2 variant (2018-12-10 14:56:00 
+)


Robin Murphy (1):
  iommu/arm-smmu-v3: Fix big-endian CMD_SYNC writes

Sricharan R (3):
  iommu/arm-smmu: Add pm_runtime/sleep ops
  iommu/arm-smmu: Invoke pm_runtime across the driver
  iommu/arm-smmu: Add the device_link between masters and smmu

Vivek Gautam (2):
  dt-bindings: arm-smmu: Add bindings for qcom,smmu-v2
  iommu/arm-smmu: Add support for qcom,smmu-v2 variant

Will Deacon (1):
  iommu/arm-smmu-v3: Use explicit mb() when moving cons pointer

Zhen Lei (1):
  iommu/arm-smmu-v3: Avoid memory corruption from Hisilicon MSI payloads

 .../devicetree/bindings/iommu/arm,smmu.txt |  39 +
 drivers/iommu/arm-smmu-v3.c|  22 ++-
 drivers/iommu/arm-smmu.c   | 170 +++--
 3 files changed, 216 insertions(+), 15 deletions(-)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v6 0/7] Add virtio-iommu driver

2018-12-11 Thread Jean-Philippe Brucker
On 11/12/2018 18:31, Christoph Hellwig wrote:
> On Tue, Dec 11, 2018 at 06:20:57PM +, Jean-Philippe Brucker wrote:
>> Implement the virtio-iommu driver, following specification v0.9 [1].
>>
>> Only minor changes since v5 [2]. I fixed issues reported by Michael and
>> added tags from Eric and Bharat. Thanks!
>>
>> You can find Linux driver and kvmtool device on v0.9 branches [3],
>> module and x86 support on virtio-iommu/devel. Also tested with Eric's
>> QEMU device [4].
> 
> Just curious, what is the use case for it?

The main use case is assigning a device to guest userspace, using VFIO
both in the host and in the guest (the most cited example being DPDK).
There are others, and I wrote a little more about them last week:
https://www.spinics.net/lists/linux-pci/msg78529.html

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


Re: [RFC PATCH 0/6] Auxiliary IOMMU domains and Arm SMMUv3

2018-12-11 Thread Jean-Philippe Brucker
On 10/12/2018 08:57, 'j...@8bytes.org' wrote:
> Hi Kevin,
> 
> On Mon, Dec 10, 2018 at 02:06:44AM +, Tian, Kevin wrote:
>> Can I interpret above as that you agree with the aux domain concept (i.e. one
>> device can be linked to multiple domains) in general, and now we're just 
>> trying
>> to address the remaining open in API level?
> 
> Yes, I thouht about alternatives, but in the end they are all harder to
> use than the aux-domain concept. We just need to make sure that we have
> a clear definition of what the API extension do and how they impact the
> behavior of existing functions.
> 
>>> enum iommu_dev_features {
>>> /* ... */
>>> IOMMU_DEV_FEAT_AUX,
>>> IOMMU_DEV_FEAT_SVA,
>>> /* ... */
>>> };
>>>
>>
>> Does above represent whether a device implements aux/sva features,
>> or whether a device has been enabled by driver to support aux/sva 
>> features?
> 
> These represent whether the device together with the IOMMU support them,
> basically whether these features are usable via the IOMMU-API.
> 
> 
>>
>>> /* Check if a device supports a given feature of the IOMMU-API */
>>> bool iommu_dev_has_feature(struct device *dev, enum
>>> iommu_dev_features *feat);
>>
>> If the latter we also need iommu_dev_set_feature so driver can poke
>> it based on its own configuration.
> 
> Do you mean we need an explict enable-API for the features? I thought
> about that too, but some features clearly don't need it and I didn't
> want to complicate the usage. My assumption was that when the feature is
> available, it is also enabled.

The cost of enabling those features for a device does seem negligible.
For the SMMU we need to allocate about 70k of additional memory for the
initial PASID table, but enabling the PASID cap shouldn't add any
overhead otherwise. Same for PRI, shouldn't add any overhead.

As for ATS, it supposedly makes things faster, although it does mean
more invalidation requests. There currently is a global pci=noats
parameter, but maybe we need something with finer granularity to
enable/disable it per device?

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


Re: [PATCH v6 0/7] Add virtio-iommu driver

2018-12-11 Thread Christoph Hellwig
On Tue, Dec 11, 2018 at 06:20:57PM +, Jean-Philippe Brucker wrote:
> Implement the virtio-iommu driver, following specification v0.9 [1].
> 
> Only minor changes since v5 [2]. I fixed issues reported by Michael and
> added tags from Eric and Bharat. Thanks!
> 
> You can find Linux driver and kvmtool device on v0.9 branches [3],
> module and x86 support on virtio-iommu/devel. Also tested with Eric's
> QEMU device [4].

Just curious, what is the use case for it?
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v6 6/7] iommu/virtio: Add probe request

2018-12-11 Thread Jean-Philippe Brucker
When the device offers the probe feature, send a probe request for each
device managed by the IOMMU. Extract RESV_MEM information. When we
encounter a MSI doorbell region, set it up as a IOMMU_RESV_MSI region.
This will tell other subsystems that there is no need to map the MSI
doorbell in the virtio-iommu, because MSIs bypass it.

Tested-by: Bharat Bhushan 
Tested-by: Eric Auger 
Reviewed-by: Eric Auger 
Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/virtio-iommu.c  | 156 --
 include/uapi/linux/virtio_iommu.h |  36 +++
 2 files changed, 186 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 7540dab9c8dc..0c7a7fa2628d 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -46,6 +46,7 @@ struct viommu_dev {
struct iommu_domain_geometrygeometry;
u64 pgsize_bitmap;
u8  domain_bits;
+   u32 probe_size;
 };
 
 struct viommu_mapping {
@@ -67,8 +68,10 @@ struct viommu_domain {
 };
 
 struct viommu_endpoint {
+   struct device   *dev;
struct viommu_dev   *viommu;
struct viommu_domain*vdomain;
+   struct list_headresv_regions;
 };
 
 struct viommu_request {
@@ -119,6 +122,9 @@ static off_t viommu_get_write_desc_offset(struct viommu_dev 
*viommu,
 {
size_t tail_size = sizeof(struct virtio_iommu_req_tail);
 
+   if (req->type == VIRTIO_IOMMU_T_PROBE)
+   return len - viommu->probe_size - tail_size;
+
return len - tail_size;
 }
 
@@ -393,6 +399,110 @@ static int viommu_replay_mappings(struct viommu_domain 
*vdomain)
return ret;
 }
 
+static int viommu_add_resv_mem(struct viommu_endpoint *vdev,
+  struct virtio_iommu_probe_resv_mem *mem,
+  size_t len)
+{
+   size_t size;
+   u64 start64, end64;
+   phys_addr_t start, end;
+   struct iommu_resv_region *region = NULL;
+   unsigned long prot = IOMMU_WRITE | IOMMU_NOEXEC | IOMMU_MMIO;
+
+   start = start64 = le64_to_cpu(mem->start);
+   end = end64 = le64_to_cpu(mem->end);
+   size = end64 - start64 + 1;
+
+   /* Catch any overflow, including the unlikely end64 - start64 + 1 = 0 */
+   if (start != start64 || end != end64 || size < end64 - start64)
+   return -EOVERFLOW;
+
+   if (len < sizeof(*mem))
+   return -EINVAL;
+
+   switch (mem->subtype) {
+   default:
+   dev_warn(vdev->dev, "unknown resv mem subtype 0x%x\n",
+mem->subtype);
+   /* Fall-through */
+   case VIRTIO_IOMMU_RESV_MEM_T_RESERVED:
+   region = iommu_alloc_resv_region(start, size, 0,
+IOMMU_RESV_RESERVED);
+   break;
+   case VIRTIO_IOMMU_RESV_MEM_T_MSI:
+   region = iommu_alloc_resv_region(start, size, prot,
+IOMMU_RESV_MSI);
+   break;
+   }
+   if (!region)
+   return -ENOMEM;
+
+   list_add(>resv_regions, >list);
+   return 0;
+}
+
+static int viommu_probe_endpoint(struct viommu_dev *viommu, struct device *dev)
+{
+   int ret;
+   u16 type, len;
+   size_t cur = 0;
+   size_t probe_len;
+   struct virtio_iommu_req_probe *probe;
+   struct virtio_iommu_probe_property *prop;
+   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct viommu_endpoint *vdev = fwspec->iommu_priv;
+
+   if (!fwspec->num_ids)
+   return -EINVAL;
+
+   probe_len = sizeof(*probe) + viommu->probe_size +
+   sizeof(struct virtio_iommu_req_tail);
+   probe = kzalloc(probe_len, GFP_KERNEL);
+   if (!probe)
+   return -ENOMEM;
+
+   probe->head.type = VIRTIO_IOMMU_T_PROBE;
+   /*
+* For now, assume that properties of an endpoint that outputs multiple
+* IDs are consistent. Only probe the first one.
+*/
+   probe->endpoint = cpu_to_le32(fwspec->ids[0]);
+
+   ret = viommu_send_req_sync(viommu, probe, probe_len);
+   if (ret)
+   goto out_free;
+
+   prop = (void *)probe->properties;
+   type = le16_to_cpu(prop->type) & VIRTIO_IOMMU_PROBE_T_MASK;
+
+   while (type != VIRTIO_IOMMU_PROBE_T_NONE &&
+  cur < viommu->probe_size) {
+   len = le16_to_cpu(prop->length) + sizeof(*prop);
+
+   switch (type) {
+   case VIRTIO_IOMMU_PROBE_T_RESV_MEM:
+   ret = viommu_add_resv_mem(vdev, (void *)prop, len);
+   break;
+   default:
+   dev_err(dev, "unknown viommu prop 0x%x\n", type);
+   }
+
+   if (ret)
+   

[PATCH v6 5/7] iommu: Add virtio-iommu driver

2018-12-11 Thread Jean-Philippe Brucker
The virtio IOMMU is a para-virtualized device, allowing to send IOMMU
requests such as map/unmap over virtio transport without emulating page
tables. This implementation handles ATTACH, DETACH, MAP and UNMAP
requests.

The bulk of the code transforms calls coming from the IOMMU API into
corresponding virtio requests. Mappings are kept in an interval tree
instead of page tables. A little more work is required for modular and x86
support, so for the moment the driver depends on CONFIG_VIRTIO=y and
CONFIG_ARM64.

Tested-by: Bharat Bhushan 
Tested-by: Eric Auger 
Reviewed-by: Eric Auger 
Signed-off-by: Jean-Philippe Brucker 
---
 MAINTAINERS   |   7 +
 drivers/iommu/Kconfig |  11 +
 drivers/iommu/Makefile|   1 +
 drivers/iommu/virtio-iommu.c  | 916 ++
 include/uapi/linux/virtio_ids.h   |   1 +
 include/uapi/linux/virtio_iommu.h | 106 
 6 files changed, 1042 insertions(+)
 create mode 100644 drivers/iommu/virtio-iommu.c
 create mode 100644 include/uapi/linux/virtio_iommu.h

diff --git a/MAINTAINERS b/MAINTAINERS
index 8119141a926f..6d250bc7a4ae 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -16041,6 +16041,13 @@ S: Maintained
 F: drivers/virtio/virtio_input.c
 F: include/uapi/linux/virtio_input.h
 
+VIRTIO IOMMU DRIVER
+M: Jean-Philippe Brucker 
+L: virtualizat...@lists.linux-foundation.org
+S: Maintained
+F: drivers/iommu/virtio-iommu.c
+F: include/uapi/linux/virtio_iommu.h
+
 VIRTUAL BOX GUEST DEVICE DRIVER
 M: Hans de Goede 
 M: Arnd Bergmann 
diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index d9a25715650e..d507fd754214 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -435,4 +435,15 @@ config QCOM_IOMMU
help
  Support for IOMMU on certain Qualcomm SoCs.
 
+config VIRTIO_IOMMU
+   bool "Virtio IOMMU driver"
+   depends on VIRTIO=y
+   depends on ARM64
+   select IOMMU_API
+   select INTERVAL_TREE
+   help
+ Para-virtualised IOMMU driver with virtio.
+
+ Say Y here if you intend to run this kernel as a guest.
+
 endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index a158a68c8ea8..48d831a39281 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_VIRTIO_IOMMU) += virtio-iommu.o
diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
new file mode 100644
index ..7540dab9c8dc
--- /dev/null
+++ b/drivers/iommu/virtio-iommu.c
@@ -0,0 +1,916 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Virtio driver for the paravirtualized IOMMU
+ *
+ * Copyright (C) 2018 Arm Limited
+ */
+
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include 
+
+#define MSI_IOVA_BASE  0x800
+#define MSI_IOVA_LENGTH0x10
+
+#define VIOMMU_REQUEST_VQ  0
+#define VIOMMU_NR_VQS  1
+
+struct viommu_dev {
+   struct iommu_device iommu;
+   struct device   *dev;
+   struct virtio_device*vdev;
+
+   struct ida  domain_ids;
+
+   struct virtqueue*vqs[VIOMMU_NR_VQS];
+   spinlock_t  request_lock;
+   struct list_headrequests;
+
+   /* Device configuration */
+   struct iommu_domain_geometrygeometry;
+   u64 pgsize_bitmap;
+   u8  domain_bits;
+};
+
+struct viommu_mapping {
+   phys_addr_t paddr;
+   struct interval_tree_node   iova;
+   u32 flags;
+};
+
+struct viommu_domain {
+   struct iommu_domain domain;
+   struct viommu_dev   *viommu;
+   struct mutexmutex; /* protects viommu pointer */
+   unsigned intid;
+
+   spinlock_t  mappings_lock;
+   struct rb_root_cached   mappings;
+
+   unsigned long   nr_endpoints;
+};
+
+struct viommu_endpoint {
+   struct viommu_dev   *viommu;
+   struct viommu_domain*vdomain;
+};
+
+struct viommu_request {
+   struct list_headlist;
+   void*writeback;
+   unsigned intwrite_offset;
+   unsigned intlen;
+   charbuf[];
+};
+
+#define to_viommu_domain(domain)   \
+   container_of(domain, struct viommu_domain, 

[PATCH v6 7/7] iommu/virtio: Add event queue

2018-12-11 Thread Jean-Philippe Brucker
The event queue offers a way for the device to report access faults from
endpoints. It is implemented on virtqueue #1. Whenever the host needs to
signal a fault, it fills one of the buffers offered by the guest and
interrupts it.

Tested-by: Bharat Bhushan 
Tested-by: Eric Auger 
Reviewed-by: Eric Auger 
Signed-off-by: Jean-Philippe Brucker 
---
 drivers/iommu/virtio-iommu.c  | 115 +++---
 include/uapi/linux/virtio_iommu.h |  19 +
 2 files changed, 125 insertions(+), 9 deletions(-)

diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
index 0c7a7fa2628d..e6ff515d41c0 100644
--- a/drivers/iommu/virtio-iommu.c
+++ b/drivers/iommu/virtio-iommu.c
@@ -29,7 +29,8 @@
 #define MSI_IOVA_LENGTH0x10
 
 #define VIOMMU_REQUEST_VQ  0
-#define VIOMMU_NR_VQS  1
+#define VIOMMU_EVENT_VQ1
+#define VIOMMU_NR_VQS  2
 
 struct viommu_dev {
struct iommu_device iommu;
@@ -41,6 +42,7 @@ struct viommu_dev {
struct virtqueue*vqs[VIOMMU_NR_VQS];
spinlock_t  request_lock;
struct list_headrequests;
+   void*evts;
 
/* Device configuration */
struct iommu_domain_geometrygeometry;
@@ -82,6 +84,15 @@ struct viommu_request {
charbuf[];
 };
 
+#define VIOMMU_FAULT_RESV_MASK 0xff00
+
+struct viommu_event {
+   union {
+   u32 head;
+   struct virtio_iommu_fault fault;
+   };
+};
+
 #define to_viommu_domain(domain)   \
container_of(domain, struct viommu_domain, domain)
 
@@ -503,6 +514,68 @@ static int viommu_probe_endpoint(struct viommu_dev 
*viommu, struct device *dev)
return ret;
 }
 
+static int viommu_fault_handler(struct viommu_dev *viommu,
+   struct virtio_iommu_fault *fault)
+{
+   char *reason_str;
+
+   u8 reason   = fault->reason;
+   u32 flags   = le32_to_cpu(fault->flags);
+   u32 endpoint= le32_to_cpu(fault->endpoint);
+   u64 address = le64_to_cpu(fault->address);
+
+   switch (reason) {
+   case VIRTIO_IOMMU_FAULT_R_DOMAIN:
+   reason_str = "domain";
+   break;
+   case VIRTIO_IOMMU_FAULT_R_MAPPING:
+   reason_str = "page";
+   break;
+   case VIRTIO_IOMMU_FAULT_R_UNKNOWN:
+   default:
+   reason_str = "unknown";
+   break;
+   }
+
+   /* TODO: find EP by ID and report_iommu_fault */
+   if (flags & VIRTIO_IOMMU_FAULT_F_ADDRESS)
+   dev_err_ratelimited(viommu->dev, "%s fault from EP %u at %#llx 
[%s%s%s]\n",
+   reason_str, endpoint, address,
+   flags & VIRTIO_IOMMU_FAULT_F_READ ? "R" : 
"",
+   flags & VIRTIO_IOMMU_FAULT_F_WRITE ? "W" : 
"",
+   flags & VIRTIO_IOMMU_FAULT_F_EXEC ? "X" : 
"");
+   else
+   dev_err_ratelimited(viommu->dev, "%s fault from EP %u\n",
+   reason_str, endpoint);
+   return 0;
+}
+
+static void viommu_event_handler(struct virtqueue *vq)
+{
+   int ret;
+   unsigned int len;
+   struct scatterlist sg[1];
+   struct viommu_event *evt;
+   struct viommu_dev *viommu = vq->vdev->priv;
+
+   while ((evt = virtqueue_get_buf(vq, )) != NULL) {
+   if (len > sizeof(*evt)) {
+   dev_err(viommu->dev,
+   "invalid event buffer (len %u != %zu)\n",
+   len, sizeof(*evt));
+   } else if (!(evt->head & VIOMMU_FAULT_RESV_MASK)) {
+   viommu_fault_handler(viommu, >fault);
+   }
+
+   sg_init_one(sg, evt, sizeof(*evt));
+   ret = virtqueue_add_inbuf(vq, sg, 1, evt, GFP_ATOMIC);
+   if (ret)
+   dev_err(viommu->dev, "could not add event buffer\n");
+   }
+
+   virtqueue_kick(vq);
+}
+
 /* IOMMU API */
 
 static struct iommu_domain *viommu_domain_alloc(unsigned type)
@@ -885,16 +958,35 @@ static struct iommu_ops viommu_ops = {
 static int viommu_init_vqs(struct viommu_dev *viommu)
 {
struct virtio_device *vdev = dev_to_virtio(viommu->dev);
-   const char *name = "request";
-   void *ret;
+   const char *names[] = { "request", "event" };
+   vq_callback_t *callbacks[] = {
+   NULL, /* No async requests */
+   viommu_event_handler,
+   };
 
-   ret = virtio_find_single_vq(vdev, NULL, name);
-   if (IS_ERR(ret)) {
-   dev_err(viommu->dev, "cannot find VQ\n");
-   return PTR_ERR(ret);
-   }
+   return virtio_find_vqs(vdev, VIOMMU_NR_VQS, viommu->vqs, 

[PATCH v6 4/7] PCI: OF: Initialize dev->fwnode appropriately

2018-12-11 Thread Jean-Philippe Brucker
For PCI devices that have an OF node, set the fwnode as well. This way
drivers that rely on fwnode don't need the special case described by
commit f94277af03ea ("of/platform: Initialise dev->fwnode appropriately").

Acked-by: Bjorn Helgaas 
Signed-off-by: Jean-Philippe Brucker 
---
 drivers/pci/of.c | 7 +++
 1 file changed, 7 insertions(+)

diff --git a/drivers/pci/of.c b/drivers/pci/of.c
index 4c4217d0c3f1..c272ecfcd038 100644
--- a/drivers/pci/of.c
+++ b/drivers/pci/of.c
@@ -21,12 +21,15 @@ void pci_set_of_node(struct pci_dev *dev)
return;
dev->dev.of_node = of_pci_find_child_device(dev->bus->dev.of_node,
dev->devfn);
+   if (dev->dev.of_node)
+   dev->dev.fwnode = >dev.of_node->fwnode;
 }
 
 void pci_release_of_node(struct pci_dev *dev)
 {
of_node_put(dev->dev.of_node);
dev->dev.of_node = NULL;
+   dev->dev.fwnode = NULL;
 }
 
 void pci_set_bus_of_node(struct pci_bus *bus)
@@ -35,12 +38,16 @@ void pci_set_bus_of_node(struct pci_bus *bus)
bus->dev.of_node = pcibios_get_phb_of_node(bus);
else
bus->dev.of_node = of_node_get(bus->self->dev.of_node);
+
+   if (bus->dev.of_node)
+   bus->dev.fwnode = >dev.of_node->fwnode;
 }
 
 void pci_release_bus_of_node(struct pci_bus *bus)
 {
of_node_put(bus->dev.of_node);
bus->dev.of_node = NULL;
+   bus->dev.fwnode = NULL;
 }
 
 struct device_node * __weak pcibios_get_phb_of_node(struct pci_bus *bus)
-- 
2.19.1

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


[PATCH v6 1/7] dt-bindings: virtio-mmio: Add IOMMU description

2018-12-11 Thread Jean-Philippe Brucker
The nature of a virtio-mmio node is discovered by the virtio driver at
probe time. However the DMA relation between devices must be described
statically. When a virtio-mmio node is a virtio-iommu device, it needs an
"#iommu-cells" property as specified by bindings/iommu/iommu.txt.

Otherwise, the virtio-mmio device may perform DMA through an IOMMU, which
requires an "iommus" property. Describe these requirements in the
device-tree bindings documentation.

Reviewed-by: Rob Herring 
Reviewed-by: Eric Auger 
Signed-off-by: Jean-Philippe Brucker 
---
 .../devicetree/bindings/virtio/mmio.txt   | 30 +++
 1 file changed, 30 insertions(+)

diff --git a/Documentation/devicetree/bindings/virtio/mmio.txt 
b/Documentation/devicetree/bindings/virtio/mmio.txt
index 5069c1b8e193..21af30fbb81f 100644
--- a/Documentation/devicetree/bindings/virtio/mmio.txt
+++ b/Documentation/devicetree/bindings/virtio/mmio.txt
@@ -8,10 +8,40 @@ Required properties:
 - reg: control registers base address and size including configuration 
space
 - interrupts:  interrupt generated by the device
 
+Required properties for virtio-iommu:
+
+- #iommu-cells:When the node corresponds to a virtio-iommu device, it 
is
+   linked to DMA masters using the "iommus" or "iommu-map"
+   properties [1][2]. #iommu-cells specifies the size of the
+   "iommus" property. For virtio-iommu #iommu-cells must be
+   1, each cell describing a single endpoint ID.
+
+Optional properties:
+
+- iommus:  If the device accesses memory through an IOMMU, it should
+   have an "iommus" property [1]. Since virtio-iommu itself
+   does not access memory through an IOMMU, the "virtio,mmio"
+   node cannot have both an "#iommu-cells" and an "iommus"
+   property.
+
 Example:
 
virtio_block@3000 {
compatible = "virtio,mmio";
reg = <0x3000 0x100>;
interrupts = <41>;
+
+   /* Device has endpoint ID 23 */
+   iommus = < 23>
}
+
+   viommu: iommu@3100 {
+   compatible = "virtio,mmio";
+   reg = <0x3100 0x100>;
+   interrupts = <42>;
+
+   #iommu-cells = <1>
+   }
+
+[1] Documentation/devicetree/bindings/iommu/iommu.txt
+[2] Documentation/devicetree/bindings/pci/pci-iommu.txt
-- 
2.19.1

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


[PATCH v6 0/7] Add virtio-iommu driver

2018-12-11 Thread Jean-Philippe Brucker
Implement the virtio-iommu driver, following specification v0.9 [1].

Only minor changes since v5 [2]. I fixed issues reported by Michael and
added tags from Eric and Bharat. Thanks!

You can find Linux driver and kvmtool device on v0.9 branches [3],
module and x86 support on virtio-iommu/devel. Also tested with Eric's
QEMU device [4].

[1] Virtio-iommu specification v0.9, sources and pdf
git://linux-arm.org/virtio-iommu.git virtio-iommu/v0.9
http://jpbrucker.net/virtio-iommu/spec/v0.9/virtio-iommu-v0.9.pdf

[2] [PATCH v5 0/7] Add virtio-iommu driver
https://www.spinics.net/lists/linux-pci/msg78158.html

[3] git://linux-arm.org/linux-jpb.git virtio-iommu/v0.9.1
git://linux-arm.org/kvmtool-jpb.git virtio-iommu/v0.9

[4] [RFC v9 00/17] VIRTIO-IOMMU device
https://www.mail-archive.com/qemu-devel@nongnu.org/msg575578.html

Jean-Philippe Brucker (7):
  dt-bindings: virtio-mmio: Add IOMMU description
  dt-bindings: virtio: Add virtio-pci-iommu node
  of: Allow the iommu-map property to omit untranslated devices
  PCI: OF: Initialize dev->fwnode appropriately
  iommu: Add virtio-iommu driver
  iommu/virtio: Add probe request
  iommu/virtio: Add event queue

 .../devicetree/bindings/virtio/iommu.txt  |   66 +
 .../devicetree/bindings/virtio/mmio.txt   |   30 +
 MAINTAINERS   |7 +
 drivers/iommu/Kconfig |   11 +
 drivers/iommu/Makefile|1 +
 drivers/iommu/virtio-iommu.c  | 1157 +
 drivers/of/base.c |   10 +-
 drivers/pci/of.c  |7 +
 include/uapi/linux/virtio_ids.h   |1 +
 include/uapi/linux/virtio_iommu.h |  161 +++
 10 files changed, 1448 insertions(+), 3 deletions(-)
 create mode 100644 Documentation/devicetree/bindings/virtio/iommu.txt
 create mode 100644 drivers/iommu/virtio-iommu.c
 create mode 100644 include/uapi/linux/virtio_iommu.h

-- 
2.19.1

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


[PATCH v6 2/7] dt-bindings: virtio: Add virtio-pci-iommu node

2018-12-11 Thread Jean-Philippe Brucker
Some systems implement virtio-iommu as a PCI endpoint. The operating
system needs to discover the relationship between IOMMU and masters long
before the PCI endpoint gets probed. Add a PCI child node to describe the
virtio-iommu device.

The virtio-pci-iommu is conceptually split between a PCI programming
interface and a translation component on the parent bus. The latter
doesn't have a node in the device tree. The virtio-pci-iommu node
describes both, by linking the PCI endpoint to "iommus" property of DMA
master nodes and to "iommu-map" properties of bus nodes.

Reviewed-by: Rob Herring 
Reviewed-by: Eric Auger 
Signed-off-by: Jean-Philippe Brucker 
---
 .../devicetree/bindings/virtio/iommu.txt  | 66 +++
 1 file changed, 66 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/virtio/iommu.txt

diff --git a/Documentation/devicetree/bindings/virtio/iommu.txt 
b/Documentation/devicetree/bindings/virtio/iommu.txt
new file mode 100644
index ..2407fea0651c
--- /dev/null
+++ b/Documentation/devicetree/bindings/virtio/iommu.txt
@@ -0,0 +1,66 @@
+* virtio IOMMU PCI device
+
+When virtio-iommu uses the PCI transport, its programming interface is
+discovered dynamically by the PCI probing infrastructure. However the
+device tree statically describes the relation between IOMMU and DMA
+masters. Therefore, the PCI root complex that hosts the virtio-iommu
+contains a child node representing the IOMMU device explicitly.
+
+Required properties:
+
+- compatible:  Should be "virtio,pci-iommu"
+- reg: PCI address of the IOMMU. As defined in the PCI Bus
+   Binding reference [1], the reg property is a five-cell
+   address encoded as (phys.hi phys.mid phys.lo size.hi
+   size.lo). phys.hi should contain the device's BDF as
+   0b  dfff . The other cells
+   should be zero.
+- #iommu-cells:Each platform DMA master managed by the IOMMU is 
assigned
+   an endpoint ID, described by the "iommus" property [2].
+   For virtio-iommu, #iommu-cells must be 1.
+
+Notes:
+
+- DMA from the IOMMU device isn't managed by another IOMMU. Therefore the
+  virtio-iommu node doesn't have an "iommus" property, and is omitted from
+  the iommu-map property of the root complex.
+
+Example:
+
+pcie@1000 {
+   compatible = "pci-host-ecam-generic";
+   ...
+
+   /* The IOMMU programming interface uses slot 00:01.0 */
+   iommu0: iommu@0008 {
+   compatible = "virtio,pci-iommu";
+   reg = <0x0800 0 0 0 0>;
+   #iommu-cells = <1>;
+   };
+
+   /*
+* The IOMMU manages all functions in this PCI domain except
+* itself. Omit BDF 00:01.0.
+*/
+   iommu-map = <0x0  0x0 0x8>
+   <0x9  0x9 0xfff7>;
+};
+
+pcie@2000 {
+   compatible = "pci-host-ecam-generic";
+   ...
+   /*
+* The IOMMU also manages all functions from this domain,
+* with endpoint IDs 0x1 - 0x1
+*/
+   iommu-map = <0x0  0x1 0x1>;
+};
+
+ethernet@fe001000 {
+   ...
+   /* The IOMMU manages this platform device with endpoint ID 0x2 */
+   iommus = < 0x2>;
+};
+
+[1] Documentation/devicetree/bindings/pci/pci.txt
+[2] Documentation/devicetree/bindings/iommu/iommu.txt
-- 
2.19.1

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


Re: [RFC] avoid indirect calls for DMA direct mappings v2

2018-12-11 Thread Christoph Hellwig
On Tue, Dec 11, 2018 at 05:13:30PM +, Luck, Tony wrote:
> > But that might not be your fault. My ancient system is getting flaky. A 
> > v4.19 build that
> > has booted before is also resetting :-(
> 
> After a power-cycle (and some time to let the machine cool off). System now 
> boots
> with your patch series plus the __phys_to_pfn() #define
> 
> So if you can figure the right way to fix that, you are good to go.
> 
> Tested-by: Tony Luck 

Thanks.  I'll just replace the __phys_to_pfn with PHYS_PFN for now,
and see if I can find time to get the whole kernel to agree to
one version of this macro eventually..
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [RFC] avoid indirect calls for DMA direct mappings v2

2018-12-11 Thread Luck, Tony
> But that might not be your fault. My ancient system is getting flaky. A v4.19 
> build that
> has booted before is also resetting :-(

After a power-cycle (and some time to let the machine cool off). System now 
boots
with your patch series plus the __phys_to_pfn() #define

So if you can figure the right way to fix that, you are good to go.

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


RE: [RFC] avoid indirect calls for DMA direct mappings v2

2018-12-11 Thread Luck, Tony
> This should fix it:
...
> +#include 

Not quite. Still have an issue with __phys_to_pfn(paddr)

Trying ti #include  gave we a raft of redefined
macros. So I just added

#define  __phys_to_pfn(paddr)PHYS_PFN(paddr)

to arch/ia64/mm/init.c

That made the build work. But boot spontaneously resets after:

mptsas: ioc1: attaching ssp device: fw_channel 0, fw_id 6, phy 6, sas_addr 
0x5000c5000ecada69
scsi 5:0:0:0: Direct-Access SEAGATE  ST9146802SS  0003 PQ: 0 ANSI: 5
EFI Variables Facility v0.08 2004-May-17
sd 5:0:0:0: [sdb] 286749488 512-byte logical blocks: (147 GB/137 GiB)
sd 5:0:0:0: [sdb] Write Protect is off
sd 5:0:0:0: [sdb] Write cache: enabled, read cache: enabled, supports DPO and 
FUA
 sdb: sdb1 sdb2
sd 5:0:0:0: [sdb] Attached SCSI disk

But that might not be your fault. My ancient system is getting flaky. A v4.19 
build that
has booted before is also resetting :-(

-Tony


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


Re: [PATCH v5 5/7] iommu: Add virtio-iommu driver

2018-12-11 Thread Jean-Philippe Brucker
On 10/12/2018 22:53, Michael S. Tsirkin wrote:
> On Mon, Dec 10, 2018 at 03:06:47PM +, Jean-Philippe Brucker wrote:
>> On 27/11/2018 18:53, Michael S. Tsirkin wrote:
>>> On Tue, Nov 27, 2018 at 06:10:46PM +, Jean-Philippe Brucker wrote:
 On 27/11/2018 18:04, Michael S. Tsirkin wrote:
> On Tue, Nov 27, 2018 at 05:50:50PM +, Jean-Philippe Brucker wrote:
>> On 23/11/2018 22:02, Michael S. Tsirkin wrote:
 +/*
 + * __viommu_sync_req - Complete all in-flight requests
 + *
 + * Wait for all added requests to complete. When this function 
 returns, all
 + * requests that were in-flight at the time of the call have 
 completed.
 + */
 +static int __viommu_sync_req(struct viommu_dev *viommu)
 +{
 +  int ret = 0;
 +  unsigned int len;
 +  size_t write_len;
 +  struct viommu_request *req;
 +  struct virtqueue *vq = viommu->vqs[VIOMMU_REQUEST_VQ];
 +
 +  assert_spin_locked(>request_lock);
 +
 +  virtqueue_kick(vq);
 +
 +  while (!list_empty(>requests)) {
 +  len = 0;
 +  req = virtqueue_get_buf(vq, );
 +  if (!req)
 +  continue;
 +
 +  if (!len)
 +  viommu_set_req_status(req->buf, req->len,
 +VIRTIO_IOMMU_S_IOERR);
 +
 +  write_len = req->len - req->write_offset;
 +  if (req->writeback && len == write_len)
 +  memcpy(req->writeback, req->buf + 
 req->write_offset,
 + write_len);
 +
 +  list_del(>list);
 +  kfree(req);
 +  }
>>>
>>> I didn't notice this in the past but it seems this will spin
>>> with interrupts disabled until host handles the request.
>>> Please do not do this - host execution can be another
>>> task that needs the same host CPU. This will then disable
>>> interrupts for a very very long time.
>>
>> In the guest yes, but that doesn't prevent the host from running another
>> task right?
>
> Doesn't prevent it but it will delay it significantly
> until scheduler decides to kick the VCPU task out.
>
>> My tests run fine when QEMU is bound to a single CPU, even
>> though vcpu and viommu run in different threads
>>
>>> What to do then? Queue in software and wake up task.
>>
>> Unfortunately I can't do anything here, because IOMMU drivers can't
>> sleep in the iommu_map() or iommu_unmap() path.
>>
>> The problem is the same
>> for all IOMMU drivers. That's because the DMA API allows drivers to call
>> some functions with interrupts disabled. For example
>> Documentation/DMA-API-HOWTO.txt allows dma_alloc_coherent() and
>> dma_unmap_single() to be called in interrupt context.
>
> In fact I don't really understand how it's supposed to
> work at all: you only sync when ring is full.
> So host may not have seen your map request if ring
> is not full.
> Why is it safe to use the address with a device then?

 viommu_map() calls viommu_send_req_sync(), which does the sync
 immediately after adding the MAP request.

 Thanks,
 Jean
>>>
>>> I see. So it happens on every request. Maybe you should clear
>>> event index then. This way if exits are disabled you know that
>>> host is processing the ring. Event index is good for when
>>> you don't care when it will be processed, you just want
>>> to reduce number of exits as much as possible.
>>>
>>
>> I think that's already the case: since we don't attach a callback to the
>> request queue, VRING_AVAIL_F_NO_INTERRUPT is set in avail_flags_shadow,
>> which causes the used event index to stay clear.
>>
>> Thanks,
>> Jean
> 
> VRING_AVAIL_F_NO_INTERRUPT has no effect when the event index
> feature has been negotiated. In any case, it also does not
> affect kick notifications from guest - it affects
> device interrupts.

Ok, I thought we were talking about the used event. Then this is a
device-side optimization right?

In QEMU, disabling notifications while processing the queue didn't show
any difference in netperf. Kvmtool already masks events when processing
the ring - if the host is still handling requests while the guest adds
more, then the avail event is at least one behind the new avail index,
and the guest doesn't kick the host.

Anyway I think we can look at optimizations later, since I don't think
there is any trivial one that we can squash into the initial driver.
I'll resend this series with the Kconfig and header change.

Thanks,
Jean
___
iommu mailing list

Re: [PATCH 1/6] driver core: Introduce device_iommu_mapped() function

2018-12-11 Thread Joerg Roedel
On Tue, Dec 11, 2018 at 05:59:33PM +0300, Sergei Shtylyov wrote:
> > +static inline bool device_iommu_mapped(struct device *dev)
> > +{
> > +   return (dev->iommu_group != NULL);
> 
>You know that parens are unnecessary here, right? :-)

Yes, I know, but it feels incomplete to me without them :-)

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


[PATCH 2/4] iommu: Consolitate ->add/remove_device() calls

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Put them into separate functions and call those where the
plain ops have been called before.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/iommu.c | 51 +--
 include/linux/iommu.h |  3 +++
 2 files changed, 28 insertions(+), 26 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index edbdf5d6962c..1e8f4e0c9198 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -110,6 +110,23 @@ void iommu_device_unregister(struct iommu_device *iommu)
spin_unlock(_device_lock);
 }
 
+int iommu_probe_device(struct device *dev)
+{
+   const struct iommu_ops *ops = dev->bus->iommu_ops;
+
+   WARN_ON(dev->iommu_group);
+
+   return ops->add_device(dev);
+}
+
+void iommu_release_device(struct device *dev)
+{
+   const struct iommu_ops *ops = dev->bus->iommu_ops;
+
+   if (dev->iommu_group)
+   ops->remove_device(dev);
+}
+
 static struct iommu_domain *__iommu_domain_alloc(struct bus_type *bus,
 unsigned type);
 static int __iommu_attach_device(struct iommu_domain *domain,
@@ -1117,16 +1134,7 @@ struct iommu_domain *iommu_group_default_domain(struct 
iommu_group *group)
 
 static int add_iommu_group(struct device *dev, void *data)
 {
-   struct iommu_callback_data *cb = data;
-   const struct iommu_ops *ops = cb->ops;
-   int ret;
-
-   if (!ops->add_device)
-   return 0;
-
-   WARN_ON(dev->iommu_group);
-
-   ret = ops->add_device(dev);
+   int ret = iommu_probe_device(dev);
 
/*
 * We ignore -ENODEV errors for now, as they just mean that the
@@ -1141,11 +1149,7 @@ static int add_iommu_group(struct device *dev, void 
*data)
 
 static int remove_iommu_group(struct device *dev, void *data)
 {
-   struct iommu_callback_data *cb = data;
-   const struct iommu_ops *ops = cb->ops;
-
-   if (ops->remove_device && dev->iommu_group)
-   ops->remove_device(dev);
+   iommu_release_device(dev);
 
return 0;
 }
@@ -1153,27 +1157,22 @@ static int remove_iommu_group(struct device *dev, void 
*data)
 static int iommu_bus_notifier(struct notifier_block *nb,
  unsigned long action, void *data)
 {
+   unsigned long group_action = 0;
struct device *dev = data;
-   const struct iommu_ops *ops = dev->bus->iommu_ops;
struct iommu_group *group;
-   unsigned long group_action = 0;
 
/*
 * ADD/DEL call into iommu driver ops if provided, which may
 * result in ADD/DEL notifiers to group->notifier
 */
if (action == BUS_NOTIFY_ADD_DEVICE) {
-   if (ops->add_device) {
-   int ret;
+   int ret;
 
-   ret = ops->add_device(dev);
-   return (ret) ? NOTIFY_DONE : NOTIFY_OK;
-   }
+   ret = iommu_probe_device(dev);
+   return (ret) ? NOTIFY_DONE : NOTIFY_OK;
} else if (action == BUS_NOTIFY_REMOVED_DEVICE) {
-   if (ops->remove_device && dev->iommu_group) {
-   ops->remove_device(dev);
-   return 0;
-   }
+   iommu_release_device(dev);
+   return NOTIFY_OK;
}
 
/*
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a1d28f42cb77..cb36f32cd3c2 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -398,6 +398,9 @@ void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
 const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);
 
+int iommu_probe_device(struct device *dev);
+void iommu_release_device(struct device *dev);
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
-- 
2.17.1

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


[PATCH 3/4] iommu/of: Don't call iommu_ops->add_device directly

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Make sure to invoke this call-back through the proper
function of the IOMMU-API.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/of_iommu.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index c5dd63072529..4d4847de727e 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -218,10 +218,10 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
ops = dev->iommu_fwspec->ops;
/*
 * If we have reason to believe the IOMMU driver missed the initial
-* add_device callback for dev, replay it to get things in order.
+* probe for dev, replay it to get things in order.
 */
-   if (ops && ops->add_device && dev->bus && !dev->iommu_group)
-   err = ops->add_device(dev);
+   if (dev->bus && !dev->iommu_group)
+   err = iommu_probe_device(dev);
 
/* Ignore all other errors apart from EPROBE_DEFER */
if (err == -EPROBE_DEFER) {
-- 
2.17.1

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


[PATCH 1/4] iommu/sysfs: Rename iommu_release_device()

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Remove the iommu_ prefix from the function and a few other
static data structures so that the iommu_release_device name
can be re-used in iommu core code.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/iommu-sysfs.c | 12 ++--
 1 file changed, 6 insertions(+), 6 deletions(-)

diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index 36d1a7ce7fc4..71c2249d3260 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -22,25 +22,25 @@ static struct attribute *devices_attr[] = {
NULL,
 };
 
-static const struct attribute_group iommu_devices_attr_group = {
+static const struct attribute_group devices_attr_group = {
.name = "devices",
.attrs = devices_attr,
 };
 
-static const struct attribute_group *iommu_dev_groups[] = {
-   _devices_attr_group,
+static const struct attribute_group *dev_groups[] = {
+   _attr_group,
NULL,
 };
 
-static void iommu_release_device(struct device *dev)
+static void release_device(struct device *dev)
 {
kfree(dev);
 }
 
 static struct class iommu_class = {
.name = "iommu",
-   .dev_release = iommu_release_device,
-   .dev_groups = iommu_dev_groups,
+   .dev_release = release_device,
+   .dev_groups = dev_groups,
 };
 
 static int __init iommu_dev_init(void)
-- 
2.17.1

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


[PATCH 4/4] ACPI/IORT: Don't call iommu_ops->add_device directly

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Make sure to invoke this call-back through the proper
function of the IOMMU-API.

Signed-off-by: Joerg Roedel 
---
 drivers/acpi/arm64/iort.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 70f4e80b9246..d4f7c1adc048 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -805,8 +805,8 @@ static inline int iort_add_device_replay(const struct 
iommu_ops *ops,
 {
int err = 0;
 
-   if (ops->add_device && dev->bus && !dev->iommu_group)
-   err = ops->add_device(dev);
+   if (dev->bus && !dev->iommu_group)
+   err = iommu_probe_device(dev);
 
return err;
 }
-- 
2.17.1

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


[PATCH 0/4 v2] Consolidate iommu_ops->add/remove_device() calls

2018-12-11 Thread Joerg Roedel
Hi,

here is the second version of the patch-set to wrap the
invocation of iommu_ops->add/remove_device() into functions.
The functions will do more setup stuff later when the the
iommu-related pointers in 'struct device' are consolidated.

Since version one this patch-set was rebased to v4.20-rc6
and I removed the pointer checks for the function pointers,
as suggested by Robin. I checked all 16 drivers and all of
them implement the add/remove_device call-backs.

Please review, if there are no objections I plan to queue
these patches in the IOMMU tree.

Thanks,

Joerg

Joerg Roedel (4):
  iommu/sysfs: Rename iommu_release_device()
  iommu: Consolitate ->add/remove_device() calls
  iommu/of: Don't call iommu_ops->add_device directly
  ACPI/IORT: Don't call iommu_ops->add_device directly

 drivers/acpi/arm64/iort.c   |  4 +--
 drivers/iommu/iommu-sysfs.c | 12 -
 drivers/iommu/iommu.c   | 51 ++---
 drivers/iommu/of_iommu.c|  6 ++---
 include/linux/iommu.h   |  3 +++
 5 files changed, 39 insertions(+), 37 deletions(-)

-- 
2.17.1

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


Re: [PATCH 1/6] driver core: Introduce device_iommu_mapped() function

2018-12-11 Thread Sergei Shtylyov
Hello!

On 12/11/2018 04:43 PM, Joerg Roedel wrote:

> From: Joerg Roedel 
> 
> Some places in the kernel check the iommu_group pointer in
> 'struct device' in order to find ot whether a device is
> mapped by an IOMMU.
> 
> This is not good way to make this check, as the pointer will
> be moved to 'struct dev_iommu_data'. This way to make the
> check is also not very readable.
> 
> Introduce an explicit function to perform this check.
> 
> Cc: Greg Kroah-Hartman 
> Acked-by: Greg Kroah-Hartman 
> Acked-by: Robin Murphy 
> Signed-off-by: Joerg Roedel 
> ---
>  include/linux/device.h | 10 ++
>  1 file changed, 10 insertions(+)
> 
> diff --git a/include/linux/device.h b/include/linux/device.h
> index 1b25c7a43f4c..6cb4640b6160 100644
> --- a/include/linux/device.h
> +++ b/include/linux/device.h
> @@ -1058,6 +1058,16 @@ static inline struct device *kobj_to_dev(struct 
> kobject *kobj)
>   return container_of(kobj, struct device, kobj);
>  }
>  
> +/**
> + * device_iommu_mapped - Returns true when the device DMA is translated
> + *by an IOMMU
> + * @dev: Device to perform the check on
> + */
> +static inline bool device_iommu_mapped(struct device *dev)
> +{
> + return (dev->iommu_group != NULL);

   You know that parens are unnecessary here, right? :-)

> +}
> +
>  /* Get the wakeup routines, which depend on struct device */
>  #include 
>  

MBR, Sergei

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


Re: use generic DMA mapping code in powerpc V4

2018-12-11 Thread Christian Zigotzky
Next step: 977706f9755d2d697aa6f45b4f9f0e07516efeda (powerpc/dma: remove 
dma_nommu_mmap_coherent)


Result: The P5020 board boots and the PASEMI onboard ethernet works.

-- Christian


On 10 December 2018 at 4:54PM, Christian Zigotzky wrote:
Next step: 64ecd2c160bbef31465c4d34efc0f076a2aad4df (powerpc/dma: use 
phys_to_dma instead of get_dma_offset)


The P5020 board boots and the PASEMI onboard ethernet works.

-- Christian


On 09 December 2018 at 7:26PM, Christian Zigotzky wrote:
Next step: c1bfcad4b0cf38ce5b00f7ad880d3a13484c123a (dma-mapping, 
powerpc: simplify the arch dma_set_mask override)


Result: No problems with the PASEMI onboard ethernet and with booting 
the X5000 (P5020 board).


-- Christian


On 09 December 2018 at 3:20PM, Christian Zigotzky wrote:
Next step: 602307b034734ce77a05da4b99333a2eaf6b6482 
(powerpc/fsl_pci: simplify fsl_pci_dma_set_mask)


git checkout 602307b034734ce77a05da4b99333a2eaf6b6482

The PASEMI onboard ethernet works and the X5000 boots.

-- Christian


On 08 December 2018 at 2:47PM, Christian Zigotzky wrote:
Next step: e15cd8173ef85e9cc3e2a9c7cc2982f5c1355615 (powerpc/dma: 
fix an off-by-one in dma_capable)


git checkout e15cd8173ef85e9cc3e2a9c7cc2982f5c1355615

The PASEMI onboard ethernet also works with this commit and the 
X5000 boots without any problems.


-- Christian


On 08 December 2018 at 11:29AM, Christian Zigotzky wrote:
Next step: 7ebc44c535f6bd726d553756d38b137acc718443 (powerpc/dma: 
remove max_direct_dma_addr)


git checkout 7ebc44c535f6bd726d553756d38b137acc718443

OK, the PASEMI onboard ethernet works and the P5020 board boots.

-- Christian


On 07 December 2018 at 7:33PM, Christian Zigotzky wrote:
Next step: 13c1fdec5682b6e13257277fa16aa31f342d167d (powerpc/dma: 
move pci_dma_dev_setup_swiotlb to fsl_pci.c)


git checkout 13c1fdec5682b6e13257277fa16aa31f342d167d

Result: The PASEMI onboard ethernet works and the P5020 board boots.

— Christian


















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

Re: [PATCH 6/6] sparc: merge 32-bit and 64-bit version of pci.h

2018-12-11 Thread Christoph Hellwig
I've pulled this into the dma-mapping for-next tree now.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 5/6] xhci: Use device_iommu_mapped()

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Replace the dev->iommu_group check with a proper function
call that better reprensents its purpose.

Cc: Mathias Nyman 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
---
 drivers/usb/host/xhci.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/usb/host/xhci.c b/drivers/usb/host/xhci.c
index dae3be1b9c8f..8eacd2ed412b 100644
--- a/drivers/usb/host/xhci.c
+++ b/drivers/usb/host/xhci.c
@@ -244,7 +244,7 @@ static void xhci_zero_64b_regs(struct xhci_hcd *xhci)
 * an iommu. Doing anything when there is no iommu is definitely
 * unsafe...
 */
-   if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !dev->iommu_group)
+   if (!(xhci->quirks & XHCI_ZERO_64B_REGS) || !device_iommu_mapped(dev))
return;
 
xhci_info(xhci, "Zeroing 64bit base registers, expecting fault\n");
-- 
2.17.1

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


[PATCH 4/6] powerpc/iommu: Use device_iommu_mapped()

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new function to replace the open-coded iommu check.

Cc: Benjamin Herrenschmidt 
Cc: Paul Mackerras 
Cc: Russell Currey 
Cc: Sam Bobroff 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
---
 arch/powerpc/kernel/eeh.c   | 2 +-
 arch/powerpc/kernel/iommu.c | 6 +++---
 2 files changed, 4 insertions(+), 4 deletions(-)

diff --git a/arch/powerpc/kernel/eeh.c b/arch/powerpc/kernel/eeh.c
index 6cae6b56ffd6..23fe62f11486 100644
--- a/arch/powerpc/kernel/eeh.c
+++ b/arch/powerpc/kernel/eeh.c
@@ -1472,7 +1472,7 @@ static int dev_has_iommu_table(struct device *dev, void 
*data)
if (!dev)
return 0;
 
-   if (dev->iommu_group) {
+   if (device_iommu_mapped(dev)) {
*ppdev = pdev;
return 1;
}
diff --git a/arch/powerpc/kernel/iommu.c b/arch/powerpc/kernel/iommu.c
index f0dc680e659a..48d58d1dcac2 100644
--- a/arch/powerpc/kernel/iommu.c
+++ b/arch/powerpc/kernel/iommu.c
@@ -1086,7 +1086,7 @@ int iommu_add_device(struct device *dev)
if (!device_is_registered(dev))
return -ENOENT;
 
-   if (dev->iommu_group) {
+   if (device_iommu_mapped(dev)) {
pr_debug("%s: Skipping device %s with iommu group %d\n",
 __func__, dev_name(dev),
 iommu_group_id(dev->iommu_group));
@@ -1129,7 +1129,7 @@ void iommu_del_device(struct device *dev)
 * and we needn't detach them from the associated
 * IOMMU groups
 */
-   if (!dev->iommu_group) {
+   if (!device_iommu_mapped(dev)) {
pr_debug("iommu_tce: skipping device %s with no tbl\n",
 dev_name(dev));
return;
@@ -1148,7 +1148,7 @@ static int tce_iommu_bus_notifier(struct notifier_block 
*nb,
 case BUS_NOTIFY_ADD_DEVICE:
 return iommu_add_device(dev);
 case BUS_NOTIFY_DEL_DEVICE:
-if (dev->iommu_group)
+if (device_iommu_mapped(dev))
 iommu_del_device(dev);
 return 0;
 default:
-- 
2.17.1

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


[PATCH 1/6] driver core: Introduce device_iommu_mapped() function

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Some places in the kernel check the iommu_group pointer in
'struct device' in order to find ot whether a device is
mapped by an IOMMU.

This is not good way to make this check, as the pointer will
be moved to 'struct dev_iommu_data'. This way to make the
check is also not very readable.

Introduce an explicit function to perform this check.

Cc: Greg Kroah-Hartman 
Acked-by: Greg Kroah-Hartman 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
---
 include/linux/device.h | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/include/linux/device.h b/include/linux/device.h
index 1b25c7a43f4c..6cb4640b6160 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1058,6 +1058,16 @@ static inline struct device *kobj_to_dev(struct kobject 
*kobj)
return container_of(kobj, struct device, kobj);
 }
 
+/**
+ * device_iommu_mapped - Returns true when the device DMA is translated
+ *  by an IOMMU
+ * @dev: Device to perform the check on
+ */
+static inline bool device_iommu_mapped(struct device *dev)
+{
+   return (dev->iommu_group != NULL);
+}
+
 /* Get the wakeup routines, which depend on struct device */
 #include 
 
-- 
2.17.1

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


[PATCH 2/6] iommu/of: Use device_iommu_mapped()

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use Use device_iommu_mapped() to check if the device is
already mapped by an IOMMU.

Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/of_iommu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index c5dd63072529..bfcf139503f0 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -220,7 +220,7 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
 * If we have reason to believe the IOMMU driver missed the initial
 * add_device callback for dev, replay it to get things in order.
 */
-   if (ops && ops->add_device && dev->bus && !dev->iommu_group)
+   if (ops && ops->add_device && dev->bus && !device_iommu_mapped(dev))
err = ops->add_device(dev);
 
/* Ignore all other errors apart from EPROBE_DEFER */
-- 
2.17.1

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


Re: [PATCH v3 0/7] dma-debug cleanup and dynamic allocation

2018-12-11 Thread Christoph Hellwig
Thanks, applied to dma-mapping for-next.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH 3/6] ACPI/IORT: Use device_iommu_mapped()

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Replace the iommu-check with a proper and readable function
call.

Cc: Lorenzo Pieralisi 
Acked-by: Robin Murphy 
Signed-off-by: Joerg Roedel 
---
 drivers/acpi/arm64/iort.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 70f4e80b9246..0125c8eb9e81 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -805,7 +805,7 @@ static inline int iort_add_device_replay(const struct 
iommu_ops *ops,
 {
int err = 0;
 
-   if (ops->add_device && dev->bus && !dev->iommu_group)
+   if (ops->add_device && dev->bus && !device_iommu_mapped(dev))
err = ops->add_device(dev);
 
return err;
-- 
2.17.1

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


[PATCH 0/6 v2] Introduce device_iommu_mapped() function

2018-12-11 Thread Joerg Roedel
Hi,

here is the second version of this patch-set. It replaces
the various (dev->iommu_group) checks with a function call
which better expresses their intend.

Changes to the first version are the added patch for
rcar-dmac, a driver I missed before. I also added all
Acked-By's I received on the first version.

Please review and provide Acks, if there are no objections.
I have some iommu patches that depend on these, so I'd like
to carry this patch-set in the IOMMU tree.

Regards,

Joerg

Joerg Roedel (6):
  driver core: Introduce device_iommu_mapped() function
  iommu/of: Use device_iommu_mapped()
  ACPI/IORT: Use device_iommu_mapped()
  powerpc/iommu: Use device_iommu_mapped()
  xhci: Use device_iommu_mapped()
  dmaengine: sh: rcar-dmac: Use device_iommu_mapped()

 arch/powerpc/kernel/eeh.c   |  2 +-
 arch/powerpc/kernel/iommu.c |  6 +++---
 drivers/acpi/arm64/iort.c   |  2 +-
 drivers/dma/sh/rcar-dmac.c  |  2 +-
 drivers/iommu/of_iommu.c|  2 +-
 drivers/usb/host/xhci.c |  2 +-
 include/linux/device.h  | 10 ++
 7 files changed, 18 insertions(+), 8 deletions(-)

-- 
2.17.1

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


Re: [RFC PATCH 0/6] Auxiliary IOMMU domains and Arm SMMUv3

2018-12-11 Thread Jean-Philippe Brucker
On 07/12/2018 10:29, 'j...@8bytes.org' wrote:
> Hi,
> 
> On Mon, Nov 26, 2018 at 07:29:45AM +, Tian, Kevin wrote:
>> btw Baolu just reminded me one thing which is worthy of noting here.
>> 'primary' vs. 'aux' concept makes sense only when we look from a device
>> p.o.v. That binding relationship is not (*should not be*) carry-and-forwarded
>> cross devices. every domain must be explicitly attached to other devices
>> (instead of implicitly attached being above example), and new primary/aux
>> attribute on another device will be decided at attach time.
> 
> Okay, so after all the discussions we had I learned a few more things
> about the scalable mode feature and thought a bit longer about how to
> best support it in the IOMMU-API.
> 
> The concept of sub-domains I initially proposed certainly makes no
> sense, but scalable-mode specific attach/detach functions do. So instead
> of a sub-domain mode, I'd like to propose device-feature sets.
> 
> The posted patch-set already includes this as device-attributes, but I
> don't like this naming as we are really talking about additional
> feature sets of a device. So how about we introduce this:
> 
>   enum iommu_dev_features {
>   /* ... */
>   IOMMU_DEV_FEAT_AUX,
>   IOMMU_DEV_FEAT_SVA,
>   /* ... */
>   };
> 
>   /* Check if a device supports a given feature of the IOMMU-API */
>   bool iommu_dev_has_feature(struct device *dev, enum iommu_dev_features 
> *feat);
> 
>   /*
>* Only works if iommu_dev_has_feature(dev, IOMMU_DEV_FEAT_AUX)
>* returns true
>*
>* Also, as long as domains are attached to a device through
>* this interface, any trys to call iommu_attach_device() should
>* fail (iommu_detach_device() can't fail, so we fail on the
>* tryint to re-attach). This should make us safe against a
>* device being attached to a guest as a whole while there are
>* still pasid users on it (aux and sva).
>*/
>   int iommu_aux_attach_device(struct iommu_domain *domain,
>   struct device *dev);
> 
>   int iommu_aux_detach_device(struct iommu_domain *domain,
>   struct device *dev);
>   /*
>* I know we are targeting a system-wide pasid-space, so that
>* the pasid would be the same for one domain on all devices,
>* let's just keep the option open to have different
>* pasid-spaces in one system. Also this way we can use it to
>* check whether the domain is attached to this device at all.
>*
>* returns pasid or <0 if domain has no pasid on that device.
>*/
>   int iommu_aux_get_pasid(struct iommu_domain *domain,
>   struct device *dev);>
>   /* So we need a iommu_aux_detach_all()? */

This could be useful for device drivers that want to do bulk cleanup on
device removal. If they rely on Function Level Reset to disable PASID
states for example, they could also cleanup with a detach_all(). But
most will probably need to clean up individual PASID states (for example
free all mdevs) and therefore don't need detach_all()

> This concept can also be easily extended for supporting SVA in parallel
> on the same device, with the same constraints regarding the behavior of
> iommu_attach_device()/iommu_detach_device().

So this would be without the initial step of attaching an "ext" domain
to the device in order to enable SVA/PASID?

If I understood it correctly, I agree with the
iommu_attach/detach_device() behavior for SVA as well. If a device is
bound to an mm, then the device cannot be attached to another domain
with iommu_attach_device(). This prevents leaks and forces the device
driver to clean up PASID states when switching to a different driver
(e.g. vfio-pci)

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


[PATCH 9/9] iommu/tegra: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Cc: Thierry Reding 
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/tegra-smmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/tegra-smmu.c b/drivers/iommu/tegra-smmu.c
index 0d03341317c4..0d026cb2dfff 100644
--- a/drivers/iommu/tegra-smmu.c
+++ b/drivers/iommu/tegra-smmu.c
@@ -846,7 +846,7 @@ static struct iommu_group *tegra_smmu_group_get(struct 
tegra_smmu *smmu,
 
 static struct iommu_group *tegra_smmu_device_group(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct tegra_smmu *smmu = dev->archdata.iommu;
struct iommu_group *group;
 
-- 
2.17.1

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


[PATCH 4/9] iommu/dma: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Signed-off-by: Joerg Roedel 
---
 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 d1b04753b204..2b1c6912fbcc 100644
--- a/drivers/iommu/dma-iommu.c
+++ b/drivers/iommu/dma-iommu.c
@@ -177,7 +177,7 @@ EXPORT_SYMBOL(iommu_put_dma_cookie);
 void iommu_dma_get_resv_regions(struct device *dev, struct list_head *list)
 {
 
-   if (!is_of_node(dev->iommu_fwspec->iommu_fwnode))
+   if (!is_of_node(dev_iommu_fwspec_get(dev)->iommu_fwnode))
iort_iommu_msi_get_resv_regions(dev, list);
 
 }
-- 
2.17.1

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


[PATCH 2/9] ACPI/IORT: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Cc: Lorenzo Pieralisi 
Signed-off-by: Joerg Roedel 
---
 drivers/acpi/arm64/iort.c | 19 ++-
 1 file changed, 10 insertions(+), 9 deletions(-)

diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index 70f4e80b9246..736381673638 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -779,7 +779,7 @@ static inline bool iort_iommu_driver_enabled(u8 type)
 static struct acpi_iort_node *iort_get_msi_resv_iommu(struct device *dev)
 {
struct acpi_iort_node *iommu;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 
iommu = iort_get_iort_node(fwspec->iommu_fwnode);
 
@@ -794,9 +794,10 @@ static struct acpi_iort_node 
*iort_get_msi_resv_iommu(struct device *dev)
return NULL;
 }
 
-static inline const struct iommu_ops *iort_fwspec_iommu_ops(
-   struct iommu_fwspec *fwspec)
+static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev)
 {
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
return (fwspec && fwspec->ops) ? fwspec->ops : NULL;
 }
 
@@ -824,6 +825,7 @@ static inline int iort_add_device_replay(const struct 
iommu_ops *ops,
  */
 int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
 {
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct acpi_iort_its_group *its;
struct acpi_iort_node *iommu_node, *its_node = NULL;
int i, resv = 0;
@@ -841,9 +843,9 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
struct list_head *head)
 * a given PCI or named component may map IDs to.
 */
 
-   for (i = 0; i < dev->iommu_fwspec->num_ids; i++) {
+   for (i = 0; i < fwspec->num_ids; i++) {
its_node = iort_node_map_id(iommu_node,
-   dev->iommu_fwspec->ids[i],
+   fwspec->ids[i],
NULL, IORT_MSI_TYPE);
if (its_node)
break;
@@ -874,8 +876,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, 
struct list_head *head)
return (resv == its->its_count) ? resv : -ENODEV;
 }
 #else
-static inline const struct iommu_ops *iort_fwspec_iommu_ops(
-   struct iommu_fwspec *fwspec)
+static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device 
*dev);
 { return NULL; }
 static inline int iort_add_device_replay(const struct iommu_ops *ops,
 struct device *dev)
@@ -1045,7 +1046,7 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
 * If we already translated the fwspec there
 * is nothing left to do, return the iommu_ops.
 */
-   ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+   ops = iort_fwspec_iommu_ops(dev);
if (ops)
return ops;
 
@@ -1084,7 +1085,7 @@ const struct iommu_ops *iort_iommu_configure(struct 
device *dev)
 * add_device callback for dev, replay it to get things in order.
 */
if (!err) {
-   ops = iort_fwspec_iommu_ops(dev->iommu_fwspec);
+   ops = iort_fwspec_iommu_ops(dev);
err = iort_add_device_replay(ops, dev);
}
 
-- 
2.17.1

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


[PATCH 5/9] iommu/ipmmu-vmsa: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/ipmmu-vmsa.c | 12 
 1 file changed, 8 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/ipmmu-vmsa.c b/drivers/iommu/ipmmu-vmsa.c
index ddf3a492e1d5..679f18bf0634 100644
--- a/drivers/iommu/ipmmu-vmsa.c
+++ b/drivers/iommu/ipmmu-vmsa.c
@@ -81,7 +81,9 @@ static struct ipmmu_vmsa_domain *to_vmsa_domain(struct 
iommu_domain *dom)
 
 static struct ipmmu_vmsa_device *to_ipmmu(struct device *dev)
 {
-   return dev->iommu_fwspec ? dev->iommu_fwspec->iommu_priv : NULL;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+
+   return fwspec ? fwspec->iommu_priv : NULL;
 }
 
 #define TLB_LOOP_TIMEOUT   100 /* 100us */
@@ -643,7 +645,7 @@ static void ipmmu_domain_free(struct iommu_domain 
*io_domain)
 static int ipmmu_attach_device(struct iommu_domain *io_domain,
   struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct ipmmu_vmsa_device *mmu = to_ipmmu(dev);
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
@@ -692,7 +694,7 @@ static int ipmmu_attach_device(struct iommu_domain 
*io_domain,
 static void ipmmu_detach_device(struct iommu_domain *io_domain,
struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct ipmmu_vmsa_domain *domain = to_vmsa_domain(io_domain);
unsigned int i;
 
@@ -744,13 +746,15 @@ static phys_addr_t ipmmu_iova_to_phys(struct iommu_domain 
*io_domain,
 static int ipmmu_init_platform_device(struct device *dev,
  struct of_phandle_args *args)
 {
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct platform_device *ipmmu_pdev;
 
ipmmu_pdev = of_find_device_by_node(args->np);
if (!ipmmu_pdev)
return -ENODEV;
 
-   dev->iommu_fwspec->iommu_priv = platform_get_drvdata(ipmmu_pdev);
+   fwspec->iommu_priv = platform_get_drvdata(ipmmu_pdev);
+
return 0;
 }
 
-- 
2.17.1

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


[PATCH 0/9 v2] Access dev->iommu_fwspec through functions

2018-12-11 Thread Joerg Roedel
Hi,

here is the second patch-set to wrap accesses to
dev->iommu_fwspec into functions so that the pointer
location can be changed more easily later on.

This version is rebased to v4.20-rc6 and addresses Robin's
comments. The Ack from will is also added.

If there are no objections I'd like to queue these patches
soon.

Regards,

Joerg

Joerg Roedel (9):
  iommu: Introduce wrappers around dev->iommu_fwspec
  ACPI/IORT: Use helper functions to access dev->iommu_fwspec
  iommu/arm-smmu: Use helper functions to access dev->iommu_fwspec
  iommu/dma: Use helper functions to access dev->iommu_fwspec
  iommu/ipmmu-vmsa: Use helper functions to access dev->iommu_fwspec
  iommu/mediatek: Use helper functions to access dev->iommu_fwspec
  iommu/of: Use helper functions to access dev->iommu_fwspec
  iommu/qcom: Use helper functions to access dev->iommu_fwspec
  iommu/tegra: Use helper functions to access dev->iommu_fwspec

 drivers/acpi/arm64/iort.c| 19 ++-
 drivers/iommu/arm-smmu-v3.c  | 16 +---
 drivers/iommu/arm-smmu.c | 12 ++--
 drivers/iommu/dma-iommu.c|  2 +-
 drivers/iommu/iommu.c| 14 +++---
 drivers/iommu/ipmmu-vmsa.c   | 12 
 drivers/iommu/mtk_iommu.c| 21 -
 drivers/iommu/mtk_iommu_v1.c | 28 
 drivers/iommu/of_iommu.c | 10 +++---
 drivers/iommu/qcom_iommu.c   | 18 ++
 drivers/iommu/tegra-smmu.c   |  2 +-
 include/linux/iommu.h| 11 +++
 12 files changed, 98 insertions(+), 67 deletions(-)

-- 
2.17.1

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


[PATCH 6/9] iommu/mediatek: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Cc: Matthias Brugger 
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/mtk_iommu.c| 21 -
 drivers/iommu/mtk_iommu_v1.c | 28 
 2 files changed, 28 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 44bd5b9166bb..0783fba05d19 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -244,7 +244,7 @@ static void mtk_iommu_config(struct mtk_iommu_data *data,
 {
struct mtk_smi_larb_iommu*larb_mmu;
unsigned int larbid, portid;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
int i;
 
for (i = 0; i < fwspec->num_ids; ++i) {
@@ -336,7 +336,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
   struct device *dev)
 {
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
-   struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
+   struct mtk_iommu_data *data = dev_iommu_fwspec_get(dev)->iommu_priv;
 
if (!data)
return -ENODEV;
@@ -355,7 +355,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
 static void mtk_iommu_detach_device(struct iommu_domain *domain,
struct device *dev)
 {
-   struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
+   struct mtk_iommu_data *data = dev_iommu_fwspec_get(dev)->iommu_priv;
 
if (!data)
return;
@@ -417,13 +417,14 @@ static phys_addr_t mtk_iommu_iova_to_phys(struct 
iommu_domain *domain,
 
 static int mtk_iommu_add_device(struct device *dev)
 {
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct mtk_iommu_data *data;
struct iommu_group *group;
 
-   if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != _iommu_ops)
+   if (!fwspec || fwspec->ops != _iommu_ops)
return -ENODEV; /* Not a iommu client device */
 
-   data = dev->iommu_fwspec->iommu_priv;
+   data = fwspec->iommu_priv;
iommu_device_link(>iommu, dev);
 
group = iommu_group_get_for_dev(dev);
@@ -436,12 +437,13 @@ static int mtk_iommu_add_device(struct device *dev)
 
 static void mtk_iommu_remove_device(struct device *dev)
 {
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct mtk_iommu_data *data;
 
-   if (!dev->iommu_fwspec || dev->iommu_fwspec->ops != _iommu_ops)
+   if (!fwspec || fwspec->ops != _iommu_ops)
return;
 
-   data = dev->iommu_fwspec->iommu_priv;
+   data = fwspec->iommu_priv;
iommu_device_unlink(>iommu, dev);
 
iommu_group_remove_device(dev);
@@ -468,6 +470,7 @@ static struct iommu_group *mtk_iommu_device_group(struct 
device *dev)
 
 static int mtk_iommu_of_xlate(struct device *dev, struct of_phandle_args *args)
 {
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct platform_device *m4updev;
 
if (args->args_count != 1) {
@@ -476,13 +479,13 @@ static int mtk_iommu_of_xlate(struct device *dev, struct 
of_phandle_args *args)
return -EINVAL;
}
 
-   if (!dev->iommu_fwspec->iommu_priv) {
+   if (!fwspec->iommu_priv) {
/* Get the m4u device */
m4updev = of_find_device_by_node(args->np);
if (WARN_ON(!m4updev))
return -EINVAL;
 
-   dev->iommu_fwspec->iommu_priv = platform_get_drvdata(m4updev);
+   fwspec->iommu_priv = platform_get_drvdata(m4updev);
}
 
return iommu_fwspec_add_ids(dev, args->args, 1);
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
index 0e780848f59b..d22a2a145bd2 100644
--- a/drivers/iommu/mtk_iommu_v1.c
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -206,7 +206,7 @@ static void mtk_iommu_config(struct mtk_iommu_data *data,
 {
struct mtk_smi_larb_iommu*larb_mmu;
unsigned int larbid, portid;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
int i;
 
for (i = 0; i < fwspec->num_ids; ++i) {
@@ -271,7 +271,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
   struct device *dev)
 {
struct mtk_iommu_domain *dom = to_mtk_domain(domain);
-   struct mtk_iommu_data *data = dev->iommu_fwspec->iommu_priv;
+   struct mtk_iommu_data *data = dev_iommu_fwspec_get(dev)->iommu_priv;
int ret;
 
if (!data)
@@ -293,7 +293,7 @@ static int mtk_iommu_attach_device(struct iommu_domain 
*domain,
 static void mtk_iommu_detach_device(struct iommu_domain *domain,
   

[PATCH 1/9] iommu: Introduce wrappers around dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

These wrappers will be used to easily change the location of
the field later when all users are converted.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/iommu.c | 14 +++---
 include/linux/iommu.h | 11 +++
 2 files changed, 18 insertions(+), 7 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index edbdf5d6962c..4cfd407b972c 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1976,7 +1976,7 @@ const struct iommu_ops *iommu_ops_from_fwnode(struct 
fwnode_handle *fwnode)
 int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
  const struct iommu_ops *ops)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 
if (fwspec)
return ops == fwspec->ops ? 0 : -EINVAL;
@@ -1988,26 +1988,26 @@ int iommu_fwspec_init(struct device *dev, struct 
fwnode_handle *iommu_fwnode,
of_node_get(to_of_node(iommu_fwnode));
fwspec->iommu_fwnode = iommu_fwnode;
fwspec->ops = ops;
-   dev->iommu_fwspec = fwspec;
+   dev_iommu_fwspec_set(dev, fwspec);
return 0;
 }
 EXPORT_SYMBOL_GPL(iommu_fwspec_init);
 
 void iommu_fwspec_free(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
 
if (fwspec) {
fwnode_handle_put(fwspec->iommu_fwnode);
kfree(fwspec);
-   dev->iommu_fwspec = NULL;
+   dev_iommu_fwspec_set(dev, NULL);
}
 }
 EXPORT_SYMBOL_GPL(iommu_fwspec_free);
 
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
size_t size;
int i;
 
@@ -2016,11 +2016,11 @@ int iommu_fwspec_add_ids(struct device *dev, u32 *ids, 
int num_ids)
 
size = offsetof(struct iommu_fwspec, ids[fwspec->num_ids + num_ids]);
if (size > sizeof(*fwspec)) {
-   fwspec = krealloc(dev->iommu_fwspec, size, GFP_KERNEL);
+   fwspec = krealloc(fwspec, size, GFP_KERNEL);
if (!fwspec)
return -ENOMEM;
 
-   dev->iommu_fwspec = fwspec;
+   dev_iommu_fwspec_set(dev, fwspec);
}
 
for (i = 0; i < num_ids; i++)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index a1d28f42cb77..f93fdcf7d130 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -398,6 +398,17 @@ void iommu_fwspec_free(struct device *dev);
 int iommu_fwspec_add_ids(struct device *dev, u32 *ids, int num_ids);
 const struct iommu_ops *iommu_ops_from_fwnode(struct fwnode_handle *fwnode);
 
+static inline struct iommu_fwspec *dev_iommu_fwspec_get(struct device *dev)
+{
+   return dev->iommu_fwspec;
+}
+
+static inline void dev_iommu_fwspec_set(struct device *dev,
+   struct iommu_fwspec *fwspec)
+{
+   dev->iommu_fwspec = fwspec;
+}
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
-- 
2.17.1

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


[PATCH 3/9] iommu/arm-smmu: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Cc: Will Deacon 
Cc: Robin Murphy 
Acked-by: Will Deacon 
Signed-off-by: Joerg Roedel 
---
 drivers/iommu/arm-smmu-v3.c | 16 +---
 drivers/iommu/arm-smmu.c| 12 ++--
 2 files changed, 15 insertions(+), 13 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 6947ccf26512..8f2d3a30d090 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1691,24 +1691,26 @@ static void arm_smmu_install_ste_for_dev(struct 
iommu_fwspec *fwspec)
 
 static void arm_smmu_detach_dev(struct device *dev)
 {
-   struct arm_smmu_master_data *master = dev->iommu_fwspec->iommu_priv;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
+   struct arm_smmu_master_data *master = fwspec->iommu_priv;
 
master->ste.assigned = false;
-   arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
+   arm_smmu_install_ste_for_dev(fwspec);
 }
 
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
int ret = 0;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_device *smmu;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
struct arm_smmu_master_data *master;
struct arm_smmu_strtab_ent *ste;
 
-   if (!dev->iommu_fwspec)
+   if (!fwspec)
return -ENOENT;
 
-   master = dev->iommu_fwspec->iommu_priv;
+   master = fwspec->iommu_priv;
smmu = master->smmu;
ste = >ste;
 
@@ -1748,7 +1750,7 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
ste->s2_cfg = _domain->s2_cfg;
}
 
-   arm_smmu_install_ste_for_dev(dev->iommu_fwspec);
+   arm_smmu_install_ste_for_dev(fwspec);
 out_unlock:
mutex_unlock(_domain->init_mutex);
return ret;
@@ -1839,7 +1841,7 @@ static int arm_smmu_add_device(struct device *dev)
int i, ret;
struct arm_smmu_device *smmu;
struct arm_smmu_master_data *master;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct iommu_group *group;
 
if (!fwspec || fwspec->ops != _smmu_ops)
@@ -1890,7 +1892,7 @@ static int arm_smmu_add_device(struct device *dev)
 
 static void arm_smmu_remove_device(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_master_data *master;
struct arm_smmu_device *smmu;
 
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 5a28ae892504..988d0362cd03 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1103,7 +1103,7 @@ static bool arm_smmu_free_sme(struct arm_smmu_device 
*smmu, int idx)
 
 static int arm_smmu_master_alloc_smes(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_master_cfg *cfg = fwspec->iommu_priv;
struct arm_smmu_device *smmu = cfg->smmu;
struct arm_smmu_smr *smrs = smmu->smrs;
@@ -1206,7 +1206,7 @@ static int arm_smmu_domain_add_master(struct 
arm_smmu_domain *smmu_domain,
 static int arm_smmu_attach_dev(struct iommu_domain *domain, struct device *dev)
 {
int ret;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_device *smmu;
struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
 
@@ -1380,7 +1380,7 @@ static int arm_smmu_add_device(struct device *dev)
 {
struct arm_smmu_device *smmu;
struct arm_smmu_master_cfg *cfg;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
int i, ret;
 
if (using_legacy_binding) {
@@ -1391,7 +1391,7 @@ static int arm_smmu_add_device(struct device *dev)
 * will allocate/initialise a new one. Thus we need to update 
fwspec for
 * later use.
 */
-   fwspec = dev->iommu_fwspec;
+   fwspec = dev_iommu_fwspec_get(dev);
if (ret)
goto out_free;
} else if (fwspec && fwspec->ops == _smmu_ops) {
@@ -1445,7 +1445,7 @@ static int arm_smmu_add_device(struct device *dev)
 
 static void arm_smmu_remove_device(struct device *dev)
 {
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct arm_smmu_master_cfg *cfg;
struct arm_smmu_device *smmu;
 
@@ -1465,7 +1465,7 @@ static void arm_smmu_remove_device(struct device *dev)
 
 static struct 

[PATCH 7/9] iommu/of: Use helper functions to access dev->iommu_fwspec

2018-12-11 Thread Joerg Roedel
From: Joerg Roedel 

Use the new helpers dev_iommu_fwspec_get()/set() to access
the dev->iommu_fwspec pointer. This makes it easier to move
that pointer later into another struct.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/of_iommu.c | 10 +++---
 1 file changed, 7 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/of_iommu.c b/drivers/iommu/of_iommu.c
index c5dd63072529..8b071f3dcf9e 100644
--- a/drivers/iommu/of_iommu.c
+++ b/drivers/iommu/of_iommu.c
@@ -164,7 +164,7 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
   struct device_node *master_np)
 {
const struct iommu_ops *ops = NULL;
-   struct iommu_fwspec *fwspec = dev->iommu_fwspec;
+   struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
int err = NO_IOMMU;
 
if (!master_np)
@@ -208,14 +208,18 @@ const struct iommu_ops *of_iommu_configure(struct device 
*dev,
}
}
 
+
/*
 * Two success conditions can be represented by non-negative err here:
 * >0 : there is no IOMMU, or one was unavailable for non-fatal reasons
 *  0 : we found an IOMMU, and dev->fwspec is initialised appropriately
 * <0 : any actual error
 */
-   if (!err)
-   ops = dev->iommu_fwspec->ops;
+   if (!err) {
+   /* The fwspec pointer changed, read it again */
+   fwspec = dev_iommu_fwspec_get(dev);
+   ops= fwspec->ops;
+   }
/*
 * If we have reason to believe the IOMMU driver missed the initial
 * add_device callback for dev, replay it to get things in order.
-- 
2.17.1

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


Re: [PATCH] dma-debug: fix soft lockup when a lot of debug are enabled

2018-12-11 Thread Robin Murphy

Hi Anders,

On 11/12/2018 10:36, Anders Roxell wrote:

When running a kernel in qemu with enough debugging options (slub-debug,
ftrace, kcov, kasan, ubsan, ...) enabled together, that results in a
slow initcall. So a 'watchdog: BUG: soft lockup' happens:

[   44.105619] Call trace:
[   44.106709]  __slab_alloc+0x70/0x88
[   44.107757]  kmem_cache_alloc_trace+0x13c/0x590
[   44.108764]  prealloc_memory+0xb8/0x240
[   44.109768]  dma_debug_init+0x174/0x1f0
[   44.110725]  do_one_initcall+0x430/0x8b0
[   44.111719]  do_initcall_level+0x548/0x5b4
[   44.112672]  do_initcalls+0x28/0x4c
[   44.113628]  do_basic_setup+0x34/0x3c
[   44.114559]  kernel_init_freeable+0x194/0x24c
[   44.115570]  kernel_init+0x24/0x18c
[   44.116498]  ret_from_fork+0x10/0x18

Rework to call cond_resched(), in the function prealloc_memory()'s
for-loop.


Funnily enough I've just done a bit of work in this area which should 
make allocation a lot more efficient - would you mind giving this series 
a spin on the same setup to see how much it helps the performance?


https://lore.kernel.org/lkml/cover.157601.git.robin.mur...@arm.com/

Thanks,
Robin.



Signed-off-by: Anders Roxell 
---
  kernel/dma/debug.c | 1 +
  1 file changed, 1 insertion(+)

diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 231ca4628062..2abdc265aec4 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -767,6 +767,7 @@ static int prealloc_memory(u32 num_entries)
int i;
  
  	for (i = 0; i < num_entries; ++i) {

+   cond_resched();
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
goto out_err;


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


[PATCH] dma-debug: fix soft lockup when a lot of debug are enabled

2018-12-11 Thread Anders Roxell
When running a kernel in qemu with enough debugging options (slub-debug,
ftrace, kcov, kasan, ubsan, ...) enabled together, that results in a
slow initcall. So a 'watchdog: BUG: soft lockup' happens:

[   44.105619] Call trace:
[   44.106709]  __slab_alloc+0x70/0x88
[   44.107757]  kmem_cache_alloc_trace+0x13c/0x590
[   44.108764]  prealloc_memory+0xb8/0x240
[   44.109768]  dma_debug_init+0x174/0x1f0
[   44.110725]  do_one_initcall+0x430/0x8b0
[   44.111719]  do_initcall_level+0x548/0x5b4
[   44.112672]  do_initcalls+0x28/0x4c
[   44.113628]  do_basic_setup+0x34/0x3c
[   44.114559]  kernel_init_freeable+0x194/0x24c
[   44.115570]  kernel_init+0x24/0x18c
[   44.116498]  ret_from_fork+0x10/0x18

Rework to call cond_resched(), in the function prealloc_memory()'s
for-loop.

Signed-off-by: Anders Roxell 
---
 kernel/dma/debug.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/kernel/dma/debug.c b/kernel/dma/debug.c
index 231ca4628062..2abdc265aec4 100644
--- a/kernel/dma/debug.c
+++ b/kernel/dma/debug.c
@@ -767,6 +767,7 @@ static int prealloc_memory(u32 num_entries)
int i;
 
for (i = 0; i < num_entries; ++i) {
+   cond_resched();
entry = kzalloc(sizeof(*entry), GFP_KERNEL);
if (!entry)
goto out_err;
-- 
2.19.2

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


Re: [PATCH 2/2] ACPI / scan: Refactor _CCA enforcement

2018-12-11 Thread Rafael J. Wysocki
On Fri, Dec 7, 2018 at 5:31 PM Robin Murphy  wrote:
>
> Rather than checking the DMA attribute at each callsite, just pass it
> through for acpi_dma_configure() to handle directly. That can then deal
> with the relatively exceptional DEV_DMA_NOT_SUPPORTED case by explicitly
> installing dummy DMA ops instead of just skipping setup entirely. This
> will then free up the dev->dma_ops == NULL case for some valuable
> fastpath optimisations.
>
> CC: Rafael J. Wysocki 
> CC: Len Brown 
> CC: Greg Kroah-Hartman 
> CC: Bjorn Helgaas 
> Signed-off-by: Robin Murphy 

The changes in this patch are fine by me:

Reviewed-by: Rafael J. Wysocki 

> ---
>  drivers/acpi/scan.c  | 5 +
>  drivers/base/platform.c  | 3 +--
>  drivers/pci/pci-driver.c | 3 +--
>  3 files changed, 7 insertions(+), 4 deletions(-)
>
> diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
> index bd1c59fb0e17..b75ae34ed188 100644
> --- a/drivers/acpi/scan.c
> +++ b/drivers/acpi/scan.c
> @@ -1456,6 +1456,11 @@ int acpi_dma_configure(struct device *dev, enum 
> dev_dma_attr attr)
> const struct iommu_ops *iommu;
> u64 dma_addr = 0, size = 0;
>
> +   if (attr == DEV_DMA_NOT_SUPPORTED) {
> +   set_dma_ops(dev, _dummy_ops);
> +   return 0;
> +   }
> +
> iort_dma_setup(dev, _addr, );
>
> iommu = iort_iommu_configure(dev);
> diff --git a/drivers/base/platform.c b/drivers/base/platform.c
> index 41b91af95afb..c6daca875c17 100644
> --- a/drivers/base/platform.c
> +++ b/drivers/base/platform.c
> @@ -1138,8 +1138,7 @@ int platform_dma_configure(struct device *dev)
> ret = of_dma_configure(dev, dev->of_node, true);
> } else if (has_acpi_companion(dev)) {
> attr = acpi_get_dma_attr(to_acpi_device_node(dev->fwnode));
> -   if (attr != DEV_DMA_NOT_SUPPORTED)
> -   ret = acpi_dma_configure(dev, attr);
> +   ret = acpi_dma_configure(dev, attr);
> }
>
> return ret;
> diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
> index bef17c3fca67..f899a28b90f8 100644
> --- a/drivers/pci/pci-driver.c
> +++ b/drivers/pci/pci-driver.c
> @@ -1602,8 +1602,7 @@ static int pci_dma_configure(struct device *dev)
> struct acpi_device *adev = 
> to_acpi_device_node(bridge->fwnode);
> enum dev_dma_attr attr = acpi_get_dma_attr(adev);
>
> -   if (attr != DEV_DMA_NOT_SUPPORTED)
> -   ret = acpi_dma_configure(dev, attr);
> +   ret = acpi_dma_configure(dev, attr);
> }
>
> pci_put_host_bridge_device(bridge);
> --
> 2.19.1.dirty
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 00/18] MT8183 IOMMU SUPPORT

2018-12-11 Thread Joerg Roedel
On Sat, Dec 08, 2018 at 04:39:13PM +0800, Yong Wu wrote:
> Arvind Yadav (1):
>   iommu/mediatek: Constify iommu_ops
> 
> Yong Wu (17):
>   dt-bindings: mediatek: Add binding for mt8183 IOMMU and SMI
>   iommu/mediatek: Use a struct as the platform data
>   memory: mtk-smi: Use a general config_port interface
>   memory: mtk-smi: Use a struct for the platform data for smi-common
>   iommu/io-pgtable-arm-v7s: Add paddr_to_iopte and iopte_to_paddr
> helpers
>   iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode
>   iommu/mediatek: Add bclk can be supported optionally
>   iommu/mediatek: Add larb-id remapped support
>   memory: mtk-smi: Add gals support
>   iommu/mediatek: Add mt8183 IOMMU support
>   iommu/mediatek: Add mmu1 support
>   memory: mtk-smi: Invoke pm runtime_callback to enable clocks
>   memory: mtk-smi: Add bus_sel for mt8183
>   iommu/mediatek: Fix VLD_PA_RANGE register backup when suspend
>   iommu/mediatek: Add shutdown callback
>   memory: mtk-smi: Get rid of need_larbid
>   iommu/mediatek: Switch to SPDX license identifier

If Matthias is okay with these patches, I'll queue them for v4.21.


Regards,

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


Re: [PATCH v6 00/12] iommu/vt-d: Add scalable mode support

2018-12-11 Thread Joerg Roedel
On Mon, Dec 10, 2018 at 09:58:54AM +0800, Lu Baolu wrote:
> Lu Baolu (12):
>   iommu/vt-d: Enumerate the scalable mode capability
>   iommu/vt-d: Manage scalalble mode PASID tables
>   iommu/vt-d: Move page table helpers into header
>   iommu/vt-d: Add 256-bit invalidation descriptor support
>   iommu/vt-d: Reserve a domain id for FL and PT modes
>   iommu/vt-d: Add second level page table interface
>   iommu/vt-d: Setup pasid entry for RID2PASID support
>   iommu/vt-d: Pass pasid table to context mapping
>   iommu/vt-d: Setup context and enable RID2PASID support
>   iommu/vt-d: Add first level page table interface
>   iommu/vt-d: Shared virtual address in scalable mode
>   iommu/vt-d: Remove deferred invalidation

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