Re: [RFC PATCH v5 0/3] vfio: platform: return device properties for a platform device

2015-10-05 Thread Baptiste Reynal
On Mon, Oct 5, 2015 at 11:53 AM, Christoffer Dall
 wrote:
> [why are you top-posting?]
>
> On Mon, Oct 05, 2015 at 11:42:38AM +0200, Baptiste Reynal wrote:
>> In this patch series we want to wrap an already available kernel
>> interface to expose a device property to userspace,
>
> which 'already available kernel interface' is that exactly?

We use the unified device property interface.

>
>> in order to keep
>> the code lighter on the userspace. We need those properties in VFIO as
>
> I'm not sure I agree with your 'need those properties in VFIO' statement
> here, can you elaborate?
>

For device assignment, we need to transfer those properties to the
guest in order to fully exploit the device (and not simply transfer
generic properties for a given device).

The example I have in mind is the PL330 which can have optionnal
properties, as described in
Documentation/devicetree/bindings/dma/arm-pl330.txt

>> VFIO grants the possibility to develop userspace drivers.
>>
>> The sysfs doesn't seems to be ready for this kind of usage. We can
>> only find raw data that require heavy parsing. Here we retrieve
>> directly usable data and it can be extended later according to new
>> needs (as it is already done with ACPI).
>
> Why couldn't you expose this kind of data through sysfs instead of VFIO
> and independently of VFIO?  Would that be more wrong/difficult/whatever?
>

This has been bound to VFIO as we needed it for VFIO, but I don't see
any reasons not to expose it somewhere else if it may be reused.

>>
>> This interface has been developed for VFIO and is currently bound to
>> it, though there is no special dependencies with it. We could make it
>> more generic, but I can only think of VFIO to use it.
>
> Thanks,
> -Christoffer
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v5 0/3] vfio: platform: return device properties for a platform device

2015-10-05 Thread Baptiste Reynal
In this patch series we want to wrap an already available kernel
interface to expose a device property to userspace, in order to keep
the code lighter on the userspace. We need those properties in VFIO as
VFIO grants the possibility to develop userspace drivers.

The sysfs doesn't seems to be ready for this kind of usage. We can
only find raw data that require heavy parsing. Here we retrieve
directly usable data and it can be extended later according to new
needs (as it is already done with ACPI).

This interface has been developed for VFIO and is currently bound to
it, though there is no special dependencies with it. We could make it
more generic, but I can only think of VFIO to use it.

On Sat, Oct 3, 2015 at 12:53 AM, Peter Maydell  wrote:
> On 2 October 2015 at 21:28, Christoffer Dall
>  wrote:
>> We discussed this for the purposes of ARM during SFO15 last week, and
>> basically arrived at the conclusion that the resonable thing to do is to
>> rely on sysfs device tree parsing in userspace.  We don't have a great
>> solution for ACPI yet, but we also don't know of any ACPI-only devices
>> that want platform device passthrough yet.
>
> I wasn't hugely happy with that approach though:
>  * it's DT specific and just won't work on ACPI platforms; implementing
>features with a "needs DT" dependency seems like it will come back to
>bite us later
>  * I don't really want to build in a lot of infrastructure into
>QEMU to either build the DTC compiler into it or else introduce
>a runtime dependency on the dtc binary, if this is just going
>to be a stopgap solution until somebody says "has to work on
>ACPI" and we need to do it some other way
>
> On the other hand I don't exactly have a better approach to suggest
> (except "don't do device passthrough for platform devices, insist
> on a real bus like PCI"...)
>
> thanks
> -- PMM
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[RFC PATCH v5 1/3] vfio: platform: add device properties skeleton and user API

2015-09-30 Thread Baptiste Reynal
From: Antonios Motakis 

This patch introduces an API that allows to return device properties (OF
or ACPI) of a device bound to the vfio-platform/vfio-amba driver and the
skeleton of the implementation for VFIO_PLATFORM. Information about any
device node bound by VFIO_PLATFORM should be queried via the introduced
ioctl VFIO_DEVICE_GET_DEV_PROPERTY.

The user needs to know the name and the data type of the property he is
accessing.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 

---
v4 -> v5:
 - add a limit size to namesz (128)
 - remove flags propagation
 - replace E2BIG with ENOSPC when the buffer size is too small
 - remove useless affectation

v3 -> v4:
 - added flags placeholder in vfio_dev_properties
 - ioctl returns -E2BIG if the buffer is too small
 - details VFIO_DEVICE_GET_DEV_PROPERTY documentation
---
 drivers/vfio/platform/Makefile|  3 +-
 drivers/vfio/platform/properties.c| 77 +++
 drivers/vfio/platform/vfio_platform_common.c  | 34 
 drivers/vfio/platform/vfio_platform_private.h |  9 
 include/uapi/linux/vfio.h | 31 +++
 5 files changed, 153 insertions(+), 1 deletion(-)
 create mode 100644 drivers/vfio/platform/properties.c

diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 9ce8afe..37cf5ed 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,5 +1,6 @@
 
-vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o \
+  properties.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
 obj-$(CONFIG_VFIO_PLATFORM) += reset/
diff --git a/drivers/vfio/platform/properties.c 
b/drivers/vfio/platform/properties.c
new file mode 100644
index 000..48c90c5
--- /dev/null
+++ b/drivers/vfio/platform/properties.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 - Virtual Open Systems
+ * Authors: Antonios Motakis 
+ *  Baptiste Reynal 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include "vfio_platform_private.h"
+
+static int dev_property_get_strings(struct device *dev,
+   char *name, unsigned *lenp,
+   void __user *datap, unsigned long datasz)
+{
+   return -EINVAL;
+}
+
+static int dev_property_get_uint(struct device *dev,
+char *name, uint32_t type, unsigned *lenp,
+void __user *datap, unsigned long datasz)
+{
+   return -EINVAL;
+}
+
+int vfio_platform_dev_properties(struct device *dev,
+uint32_t type, unsigned *lenp,
+void __user *datap, unsigned long datasz)
+{
+   char *name;
+   long namesz;
+   int ret;
+
+   namesz = strnlen_user(datap, datasz);
+   if (!namesz)
+   return -EFAULT;
+   if (namesz > datasz || namesz > VFIO_PLATFORM_NAMESZ_LIMIT)
+   return -EINVAL;
+
+   name = kzalloc(namesz, GFP_KERNEL);
+   if (!name)
+   return -ENOMEM;
+   if (strncpy_from_user(name, datap, namesz) <= 0) {
+   kfree(name);
+   return -EFAULT;
+   }
+
+   switch (type) {
+   case VFIO_DEV_PROPERTY_TYPE_STRINGS:
+   ret = dev_property_get_strings(dev, name, lenp,
+   datap, datasz);
+   break;
+
+   case VFIO_DEV_PROPERTY_TYPE_U64:
+   case VFIO_DEV_PROPERTY_TYPE_U32:
+   case VFIO_DEV_PROPERTY_TYPE_U16:
+   case VFIO_DEV_PROPERTY_TYPE_U8:
+   ret = dev_property_get_uint(dev, name, type, lenp,
+   datap, datasz);
+   break;
+
+   default:
+   ret = -EINVAL;
+   }
+
+   kfree(name);
+   return ret;
+}
diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index e43efb5..cb1bbb4 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "vfio_platform_private.h"
 
@@ -302,6 +303,34 @@ static long vfio_platform_ioctl(void *device_data,
return vdev->reset(vdev);
else
return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_GET_DEV_PROPERTY) {
+  

[RFC PATCH v5 2/3] vfio: platform: access device property as a list of strings

2015-09-30 Thread Baptiste Reynal
From: Antonios Motakis 

Certain device properties (e.g. the device node name, the compatible
string), are available as a list of strings (separated by the null
terminating character). Let the VFIO user query this type of properties.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 

---
v4 -> v5:
 - return ENOSPC when the buffer size is too small
 - remove strlen call

v3 -> v4:
 - The list length is computed before strings copy. If the entire list
   doesn't fit, no strings are copied to the user.
---
 drivers/vfio/platform/properties.c | 43 +-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/properties.c 
b/drivers/vfio/platform/properties.c
index 48c90c5..212755f 100644
--- a/drivers/vfio/platform/properties.c
+++ b/drivers/vfio/platform/properties.c
@@ -22,7 +22,48 @@ static int dev_property_get_strings(struct device *dev,
char *name, unsigned *lenp,
void __user *datap, unsigned long datasz)
 {
-   return -EINVAL;
+   const char **val;
+   int n, i, ret;
+
+   if (lenp == NULL)
+   return -EFAULT;
+
+   *lenp = 0;
+
+   n = device_property_read_string_array(dev, name, NULL, 0);
+   if (n < 0)
+   return n;
+
+   val = kcalloc(n, sizeof(char *), GFP_KERNEL);
+   if (!val)
+   return -ENOMEM;
+
+   ret = device_property_read_string_array(dev, name, val, n);
+   if (ret < 0)
+   goto out;
+
+   for (i = 0; i < n; i++)
+   *lenp += strlen(val[i]) + 1;
+
+   if (datasz < *lenp) {
+   ret = -ENOSPC;
+   goto out;
+   }
+
+   for (i = 0; i < n; i++) {
+   size_t len = strlen(val[i]) + 1;
+
+   if (copy_to_user(datap, val[i], len)) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   datap += len;
+   }
+
+out:
+   kfree(val);
+   return ret;
 }
 
 static int dev_property_get_uint(struct device *dev,
-- 
2.6.0

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


[RFC PATCH v5 3/3] vfio: platform: return device properties as arrays of unsigned integers

2015-09-30 Thread Baptiste Reynal
From: Antonios Motakis 

Certain properties of a device are accessible as an array of unsigned
integers, either u64, u32, u16, or u8. Let the VFIO user query this
type of device properties.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 

---
v4 -> v5:
 - fix return error when the buffer size is too small
---
 drivers/vfio/platform/properties.c | 62 +-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/properties.c 
b/drivers/vfio/platform/properties.c
index 212755f..a4b6955 100644
--- a/drivers/vfio/platform/properties.c
+++ b/drivers/vfio/platform/properties.c
@@ -70,7 +70,67 @@ static int dev_property_get_uint(struct device *dev,
 char *name, uint32_t type, unsigned *lenp,
 void __user *datap, unsigned long datasz)
 {
-   return -EINVAL;
+   int ret, n;
+   u8 *out;
+   size_t sz;
+   int (*func)(const struct device *, const char *, void *, size_t)
+   = NULL;
+
+   switch (type) {
+   case VFIO_DEV_PROPERTY_TYPE_U64:
+   sz = sizeof(u64);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u64_array;
+   break;
+   case VFIO_DEV_PROPERTY_TYPE_U32:
+   sz = sizeof(u32);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u32_array;
+   break;
+   case VFIO_DEV_PROPERTY_TYPE_U16:
+   sz = sizeof(u16);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u16_array;
+   break;
+   case VFIO_DEV_PROPERTY_TYPE_U8:
+   sz = sizeof(u8);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u8_array;
+   break;
+
+   default:
+   return -EINVAL;
+   }
+
+   /* get size of array */
+   n = func(dev, name, NULL, 0);
+   if (n < 0)
+   return n;
+
+   if (lenp)
+   *lenp = n * sz;
+
+   if (n * sz > datasz)
+   return -ENOSPC;
+
+   out = kcalloc(n, sz, GFP_KERNEL);
+   if (!out)
+   return -ENOMEM;
+
+   ret = func(dev, name, out, n);
+   if (ret)
+   goto out;
+
+   if (copy_to_user(datap, out, n * sz))
+   ret = -EFAULT;
+
+out:
+   kfree(out);
+   return ret;
 }
 
 int vfio_platform_dev_properties(struct device *dev,
-- 
2.6.0

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


[RFC PATCH v5 0/3] vfio: platform: return device properties for a platform device

2015-09-30 Thread Baptiste Reynal
This RFC's intention is to show what an interface to access device
properties for the VFIO platform driver can look like. These properties
can be retrieved from the device tree node describing the device, or ACPI
properties.

If a device property corresponding to a platform device bound to VFIO PLATFORM
or VFIO AMBA is available, this patch series will allow the user to query
for this information. This can be useful for userspace drivers to automatically
query parameters related to the device.

Specifically for QEMU, reading the "compatible" property of the device tree
node could be of use to find out what device is being assigned to the guest and
handle appropriately a wider range of devices in the future, and to generate an
appropriate device tree for the guest.

Older versions of this series were specifically targeted at device tree
properties. The v3 has been reworked on top of Rafael J. Wysocki's
uniform device properties API for device tree and ACPI devices. This will allow
us to use the API in the future with devices described via ACPI.

The API to get the list of available properties and the device tree full_name
have been removed. These probably don't serve an useful purpose, as the user
of this API need to know anyway what properties are specific to the device he
wants to access with VFIO. If we decide to reintroduce the list of properties
in the future, the generic device properties API in the kernel will have to
be extended accordingly.

A kernel with this series and all the dependencies applied can be pulled from
branch vfio-device-properties-v5 from the repository:
https://git.virtualopensystems.com/dev/linux.git

Changes since v4:
 - Rework code according to Alex Williamson's comments
Changes since v3:
 - Rebased on top on v4.2
 - Rework VFIO_DEVICE_GET_DEV_PROPERTY ioctl
 - Rework code according to Eric Auger's comments
Changes since v2:
 - Reworked on top of Rafael J. Wysocki's uniform device properties API for
   device tree and ACPI
 - Support for u64 array properties
 - Removed API to get list of available properties and device tree full_name
Changes since v1:
 - Updated for VFIO platform patch series v8:
   VFIO AMBA devices now supported in addition to VFIO PLATFORM devices
 - Refactored and cleaned up the code

Antonios Motakis (3):
  vfio: platform: add device properties skeleton and user API
  vfio: platform: access device property as a list of strings
  vfio: platform: return device properties as arrays of unsigned
integers

 drivers/vfio/platform/Makefile|   3 +-
 drivers/vfio/platform/properties.c| 178 ++
 drivers/vfio/platform/vfio_platform_common.c  |  34 +
 drivers/vfio/platform/vfio_platform_private.h |   9 ++
 include/uapi/linux/vfio.h |  31 +
 5 files changed, 254 insertions(+), 1 deletion(-)
 create mode 100644 drivers/vfio/platform/properties.c

-- 
2.6.0

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


Re: [RFC PATCH v4 3/3] vfio: platform: return device properties as arrays of unsigned integers

2015-09-09 Thread Baptiste Reynal
On Wed, Sep 9, 2015 at 10:48 PM, Alex Williamson  wrote:

> On Wed, 2015-09-09 at 11:17 +0200, Baptiste Reynal wrote:
> > From: Antonios Motakis 
> >
> > Certain properties of a device are accessible as an array of unsigned
> > integers, either u64, u32, u16, or u8. Let the VFIO user query this
> > type of device properties.
> >
> > Signed-off-by: Antonios Motakis 
> > Signed-off-by: Baptiste Reynal 
> > ---
> >  drivers/vfio/platform/properties.c | 62
> +-
> >  1 file changed, 61 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/vfio/platform/properties.c
> b/drivers/vfio/platform/properties.c
> > index 8bf9c8f..625e2d3 100644
> > --- a/drivers/vfio/platform/properties.c
> > +++ b/drivers/vfio/platform/properties.c
> > @@ -70,7 +70,67 @@ static int dev_property_get_uint(struct device *dev,
> uint32_t *flags,
> >char *name, uint32_t type, unsigned *lenp,
> >void __user *datap, unsigned long datasz)
> >  {
> > - return -EINVAL;
> > + int ret, n;
> > + u8 *out;
> > + size_t sz;
> > + int (*func)(const struct device *, const char *, void *, size_t)
> > + = NULL;
> > +
> > + switch (type) {
> > + case VFIO_DEV_PROPERTY_TYPE_U64:
> > + sz = sizeof(u64);
> > + func = (int (*)(const struct device *,
> > + const char *, void *, size_t))
> > + device_property_read_u64_array;
> > + break;
> > + case VFIO_DEV_PROPERTY_TYPE_U32:
> > + sz = sizeof(u32);
> > + func = (int (*)(const struct device *,
> > + const char *, void *, size_t))
> > + device_property_read_u32_array;
> > + break;
> > + case VFIO_DEV_PROPERTY_TYPE_U16:
> > + sz = sizeof(u16);
> > + func = (int (*)(const struct device *,
> > + const char *, void *, size_t))
> > + device_property_read_u16_array;
> > + break;
> > + case VFIO_DEV_PROPERTY_TYPE_U8:
> > + sz = sizeof(u8);
> > + func = (int (*)(const struct device *,
> > + const char *, void *, size_t))
> > + device_property_read_u8_array;
> > + break;
> > +
> > + default:
> > + return -EINVAL;
> > + }
> > +
> > + /* get size of array */
> > + n = func(dev, name, NULL, 0);
> > + if (n < 0)
> > + return n;
> > +
> > + if (lenp)
> > + *lenp = n * sz;
>
> Why is this conditional?
>

Same paranoia as before. If lenp is not allocated, the function behaviour
is the same.


>
> > +
> > + if (n * sz > datasz)
> > + return -EOVERFLOW;
>
> Ugh, this isn't E2BIG or ENOSPC...
>

Ok, will be changed to ENOSPC.


>
> > +
> > + out = kcalloc(n, sz, GFP_KERNEL);
> > + if (!out)
> > + return -ENOMEM;
> > +
> > + ret = func(dev, name, out, n);
> > + if (ret)
> > + goto out;
> > +
> > + if (copy_to_user(datap, out, n * sz))
> > + ret = -EFAULT;
> > +
> > +out:
> > + kfree(out);
> > + return ret;
> >  }
> >
> >  int vfio_platform_dev_properties(struct device *dev, uint32_t *flags,
>
>
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [RFC PATCH v4 2/3] vfio: platform: access device property as a list of strings

2015-09-09 Thread Baptiste Reynal
On Wed, Sep 9, 2015 at 10:48 PM, Alex Williamson  wrote:

> On Wed, 2015-09-09 at 11:17 +0200, Baptiste Reynal wrote:
> > From: Antonios Motakis 
> >
> > Certain device properties (e.g. the device node name, the compatible
> > string), are available as a list of strings (separated by the null
> > terminating character). Let the VFIO user query this type of properties.
> >
> > Signed-off-by: Antonios Motakis 
> > Signed-off-by: Baptiste Reynal 
> >
> > ---
> > v3 -> v4:
> >  - The list length is computed before strings copy. If the entire list
> >doesn't fit, no strings are copied to the user.
> > ---
> >  drivers/vfio/platform/properties.c | 43
> +-
> >  1 file changed, 42 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/vfio/platform/properties.c
> b/drivers/vfio/platform/properties.c
> > index 98754c2..8bf9c8f 100644
> > --- a/drivers/vfio/platform/properties.c
> > +++ b/drivers/vfio/platform/properties.c
> > @@ -22,7 +22,48 @@ static int dev_property_get_strings(struct device
> *dev, uint32_t *flags,
> >   char *name, unsigned *lenp,
> >   void __user *datap, unsigned long
> datasz)
> >  {
> > - return -EINVAL;
> > + const char **val;
> > + int n, i, ret;
> > +
> > + if (lenp == NULL)
> > + return -EFAULT;
>
> Paranoia?
>

Kind of, automatic reflex.


>
> > +
> > + *lenp = 0;
> > +
> > + n = device_property_read_string_array(dev, name, NULL, 0);
> > + if (n < 0)
> > + return n;
> > +
> > + val = kcalloc(n, sizeof(char *), GFP_KERNEL);
> > + if (!val)
> > + return -ENOMEM;
> > +
> > + ret = device_property_read_string_array(dev, name, val, n);
> > + if (ret < 0)
> > + goto out;
> > +
> > + for (i = 0; i < n; i++)
> > + *lenp += strlen(val[i]) + 1;
> > +
> > + if (datasz < *lenp) {
> > + ret = -E2BIG;
> > + goto out;
> > + }
> > +
> > + for (i = 0; i < n; i++) {
> > + size_t len = strlen(val[i]) + 1;
> > +
> > + if (copy_to_user(datap, val[i], strlen(val[i]) + 1)) {
>
> No need to call strlen() again here
>

Thanks, will be fixed.


>
> > + ret = -EFAULT;
> > + goto out;
> > + }
> > +
> > + datap += len;
> > + }
> > +
> > +out:
> > + kfree(val);
> > + return ret;
> >  }
> >
> >  static int dev_property_get_uint(struct device *dev, uint32_t *flags,
>
>
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [RFC PATCH v4 1/3] vfio: platform: add device properties skeleton and user API

2015-09-09 Thread Baptiste Reynal
On Wed, Sep 9, 2015 at 10:48 PM, Alex Williamson  wrote:

> On Wed, 2015-09-09 at 11:17 +0200, Baptiste Reynal wrote:
> > From: Antonios Motakis 
> >
> > This patch introduces an API that allows to return device properties (OF
> > or ACPI) of a device bound to the vfio-platform/vfio-amba driver and the
> > skeleton of the implementation for VFIO_PLATFORM. Information about any
> > device node bound by VFIO_PLATFORM should be queried via the introduced
> > ioctl VFIO_DEVICE_GET_DEV_PROPERTY.
> >
> > The user needs to know the name and the data type of the property he is
> > accessing.
> >
> > Signed-off-by: Antonios Motakis 
> > Signed-off-by: Baptiste Reynal 
> >
> > ---
> > v3 -> v4:
> >  - added flags placeholder in vfio_dev_properties
> >  - ioctl returns -E2BIG if the buffer is too small
> >  - details VFIO_DEVICE_GET_DEV_PROPERTY documentation
> > ---
> >  drivers/vfio/platform/Makefile|  3 +-
> >  drivers/vfio/platform/properties.c| 77
> +++
> >  drivers/vfio/platform/vfio_platform_common.c  | 35 
> >  drivers/vfio/platform/vfio_platform_private.h |  7 +++
> >  include/uapi/linux/vfio.h | 31 +++
> >  5 files changed, 152 insertions(+), 1 deletion(-)
> >  create mode 100644 drivers/vfio/platform/properties.c
> >
> > diff --git a/drivers/vfio/platform/Makefile
> b/drivers/vfio/platform/Makefile
> > index 9ce8afe..37cf5ed 100644
> > --- a/drivers/vfio/platform/Makefile
> > +++ b/drivers/vfio/platform/Makefile
> > @@ -1,5 +1,6 @@
> >
> > -vfio-platform-y := vfio_platform.o vfio_platform_common.o
> vfio_platform_irq.o
> > +vfio-platform-y := vfio_platform.o vfio_platform_common.o
> vfio_platform_irq.o \
> > +properties.o
> >
> >  obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
> >  obj-$(CONFIG_VFIO_PLATFORM) += reset/
> > diff --git a/drivers/vfio/platform/properties.c
> b/drivers/vfio/platform/properties.c
> > new file mode 100644
> > index 000..98754c2
> > --- /dev/null
> > +++ b/drivers/vfio/platform/properties.c
> > @@ -0,0 +1,77 @@
> > +/*
> > + * Copyright (C) 2015 - Virtual Open Systems
> > + * Authors: Antonios Motakis 
> > + *  Baptiste Reynal 
> > + *
> > + * This program is free software; you can redistribute it and/or modify
> > + * it under the terms of the GNU General Public License, version 2, as
> > + * published by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + */
> > +
> > +#include 
> > +#include 
> > +#include 
> > +#include "vfio_platform_private.h"
> > +
> > +static int dev_property_get_strings(struct device *dev, uint32_t *flags,
> > + char *name, unsigned *lenp,
> > + void __user *datap, unsigned long
> datasz)
> > +{
> > + return -EINVAL;
> > +}
> > +
> > +static int dev_property_get_uint(struct device *dev, uint32_t *flags,
> > +  char *name, uint32_t type, unsigned *lenp,
> > +  void __user *datap, unsigned long datasz)
> > +{
> > + return -EINVAL;
> > +}
> > +
> > +int vfio_platform_dev_properties(struct device *dev, uint32_t *flags,
> > +  uint32_t type, unsigned *lenp,
> > +  void __user *datap, unsigned long datasz)
> > +{
> > + char *name;
> > + long namesz;
> > + int ret;
> > +
> > + namesz = strnlen_user(datap, datasz);
> > + if (!namesz)
> > + return -EFAULT;
> > + if (namesz > datasz)
> > + return -EINVAL;
> > +
> > + name = kzalloc(namesz, GFP_KERNEL);
>
> What prevents the user from passing an arbitrarily large string here?
>

Nothing, should I put an arbitrary limit ?


>
> > + if (!name)
> > + return -ENOMEM;
> > + if (strncpy_from_user(name, datap, namesz) <= 0) {
> > + kfree(name);
> > + return -EFAULT;
> > + }
> > +
> > + switch (type) {
> > + case VFIO_DEV_PROPERTY_TYPE_STRINGS:
> > + ret = dev_property_get_str

[RFC PATCH v4 0/3] vfio: platform: return device properties for a platform device

2015-09-09 Thread Baptiste Reynal
This RFC's intention is to show what an interface to access device
properties for the VFIO platform driver can look like. These properties
can be retrieved from the device tree node describing the device, or ACPI 
properties.

If a device property corresponding to a platform device bound to VFIO PLATFORM
or VFIO AMBA is available, this patch series will allow the user to query
for this information. This can be useful for userspace drivers to automatically
query parameters related to the device.

Specifically for QEMU, reading the "compatible" property of the device tree
node could be of use to find out what device is being assigned to the guest and
handle appropriately a wider range of devices in the future, and to generate an
appropriate device tree for the guest.

Older versions of this series were specifically targeted at device tree
properties. The v3 has been reworked on top of Rafael J. Wysocki's
uniform device properties API for device tree and ACPI devices. This will allow
us to use the API in the future with devices described via ACPI.

The API to get the list of available properties and the device tree full_name
have been removed. These probably don't serve an useful purpose, as the user
of this API need to know anyway what properties are specific to the device he
wants to access with VFIO. If we decide to reintroduce the list of properties
in the future, the generic device properties API in the kernel will have to
be extended accordingly.

A kernel with this series and all the dependencies applied can be pulled from
branch vfio-device-properties-v4 from the repository:
https://git.virtualopensystems.com/dev/linux.git

Changes since v3:
 - Rebased on top on v4.2
 - Rework VFIO_DEVICE_GET_DEV_PROPERTY ioctl
 - Rework code according to Eric Auger's comments
Changes since v2:
 - Reworked on top of Rafael J. Wysocki's uniform device properties API for
   device tree and ACPI
 - Support for u64 array properties
 - Removed API to get list of available properties and device tree full_name
Changes since v1:
 - Updated for VFIO platform patch series v8:
   VFIO AMBA devices now supported in addition to VFIO PLATFORM devices
 - Refactored and cleaned up the code

Antonios Motakis (3):
  vfio: platform: add device properties skeleton and user API
  vfio: platform: access device property as a list of strings
  vfio: platform: return device properties as arrays of unsigned
integers

 drivers/vfio/platform/Makefile|   3 +-
 drivers/vfio/platform/properties.c| 178 ++
 drivers/vfio/platform/vfio_platform_common.c  |  35 +
 drivers/vfio/platform/vfio_platform_private.h |   7 +
 include/uapi/linux/vfio.h |  31 +
 5 files changed, 253 insertions(+), 1 deletion(-)
 create mode 100644 drivers/vfio/platform/properties.c

-- 
2.5.1

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


[RFC PATCH v4 1/3] vfio: platform: add device properties skeleton and user API

2015-09-09 Thread Baptiste Reynal
From: Antonios Motakis 

This patch introduces an API that allows to return device properties (OF
or ACPI) of a device bound to the vfio-platform/vfio-amba driver and the
skeleton of the implementation for VFIO_PLATFORM. Information about any
device node bound by VFIO_PLATFORM should be queried via the introduced
ioctl VFIO_DEVICE_GET_DEV_PROPERTY.

The user needs to know the name and the data type of the property he is
accessing.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 

---
v3 -> v4:
 - added flags placeholder in vfio_dev_properties
 - ioctl returns -E2BIG if the buffer is too small
 - details VFIO_DEVICE_GET_DEV_PROPERTY documentation
---
 drivers/vfio/platform/Makefile|  3 +-
 drivers/vfio/platform/properties.c| 77 +++
 drivers/vfio/platform/vfio_platform_common.c  | 35 
 drivers/vfio/platform/vfio_platform_private.h |  7 +++
 include/uapi/linux/vfio.h | 31 +++
 5 files changed, 152 insertions(+), 1 deletion(-)
 create mode 100644 drivers/vfio/platform/properties.c

diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 9ce8afe..37cf5ed 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,5 +1,6 @@
 
-vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o \
+  properties.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
 obj-$(CONFIG_VFIO_PLATFORM) += reset/
diff --git a/drivers/vfio/platform/properties.c 
b/drivers/vfio/platform/properties.c
new file mode 100644
index 000..98754c2
--- /dev/null
+++ b/drivers/vfio/platform/properties.c
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2015 - Virtual Open Systems
+ * Authors: Antonios Motakis 
+ *      Baptiste Reynal 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include "vfio_platform_private.h"
+
+static int dev_property_get_strings(struct device *dev, uint32_t *flags,
+   char *name, unsigned *lenp,
+   void __user *datap, unsigned long datasz)
+{
+   return -EINVAL;
+}
+
+static int dev_property_get_uint(struct device *dev, uint32_t *flags,
+char *name, uint32_t type, unsigned *lenp,
+void __user *datap, unsigned long datasz)
+{
+   return -EINVAL;
+}
+
+int vfio_platform_dev_properties(struct device *dev, uint32_t *flags,
+uint32_t type, unsigned *lenp,
+void __user *datap, unsigned long datasz)
+{
+   char *name;
+   long namesz;
+   int ret;
+
+   namesz = strnlen_user(datap, datasz);
+   if (!namesz)
+   return -EFAULT;
+   if (namesz > datasz)
+   return -EINVAL;
+
+   name = kzalloc(namesz, GFP_KERNEL);
+   if (!name)
+   return -ENOMEM;
+   if (strncpy_from_user(name, datap, namesz) <= 0) {
+   kfree(name);
+   return -EFAULT;
+   }
+
+   switch (type) {
+   case VFIO_DEV_PROPERTY_TYPE_STRINGS:
+   ret = dev_property_get_strings(dev, flags, name, lenp,
+   datap, datasz);
+   break;
+
+   case VFIO_DEV_PROPERTY_TYPE_U64:
+   case VFIO_DEV_PROPERTY_TYPE_U32:
+   case VFIO_DEV_PROPERTY_TYPE_U16:
+   case VFIO_DEV_PROPERTY_TYPE_U8:
+   ret = dev_property_get_uint(dev, flags, name, type, lenp,
+   datap, datasz);
+   break;
+
+   default:
+   ret = -EINVAL;
+   }
+
+   kfree(name);
+   return ret;
+}
diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index e43efb5..44ba22c 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -20,6 +20,7 @@
 #include 
 #include 
 #include 
+#include 
 
 #include "vfio_platform_private.h"
 
@@ -302,6 +303,34 @@ static long vfio_platform_ioctl(void *device_data,
return vdev->reset(vdev);
else
return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_GET_DEV_PROPERTY) {
+   struct vfio_dev_property info;
+   void __user *datap;
+   unsigned long datasz;
+   int ret;

[RFC PATCH v4 3/3] vfio: platform: return device properties as arrays of unsigned integers

2015-09-09 Thread Baptiste Reynal
From: Antonios Motakis 

Certain properties of a device are accessible as an array of unsigned
integers, either u64, u32, u16, or u8. Let the VFIO user query this
type of device properties.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/properties.c | 62 +-
 1 file changed, 61 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/properties.c 
b/drivers/vfio/platform/properties.c
index 8bf9c8f..625e2d3 100644
--- a/drivers/vfio/platform/properties.c
+++ b/drivers/vfio/platform/properties.c
@@ -70,7 +70,67 @@ static int dev_property_get_uint(struct device *dev, 
uint32_t *flags,
 char *name, uint32_t type, unsigned *lenp,
 void __user *datap, unsigned long datasz)
 {
-   return -EINVAL;
+   int ret, n;
+   u8 *out;
+   size_t sz;
+   int (*func)(const struct device *, const char *, void *, size_t)
+   = NULL;
+
+   switch (type) {
+   case VFIO_DEV_PROPERTY_TYPE_U64:
+   sz = sizeof(u64);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u64_array;
+   break;
+   case VFIO_DEV_PROPERTY_TYPE_U32:
+   sz = sizeof(u32);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u32_array;
+   break;
+   case VFIO_DEV_PROPERTY_TYPE_U16:
+   sz = sizeof(u16);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u16_array;
+   break;
+   case VFIO_DEV_PROPERTY_TYPE_U8:
+   sz = sizeof(u8);
+   func = (int (*)(const struct device *,
+   const char *, void *, size_t))
+   device_property_read_u8_array;
+   break;
+
+   default:
+   return -EINVAL;
+   }
+
+   /* get size of array */
+   n = func(dev, name, NULL, 0);
+   if (n < 0)
+   return n;
+
+   if (lenp)
+   *lenp = n * sz;
+
+   if (n * sz > datasz)
+   return -EOVERFLOW;
+
+   out = kcalloc(n, sz, GFP_KERNEL);
+   if (!out)
+   return -ENOMEM;
+
+   ret = func(dev, name, out, n);
+   if (ret)
+   goto out;
+
+   if (copy_to_user(datap, out, n * sz))
+   ret = -EFAULT;
+
+out:
+   kfree(out);
+   return ret;
 }
 
 int vfio_platform_dev_properties(struct device *dev, uint32_t *flags,
-- 
2.5.1

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


[RFC PATCH v4 2/3] vfio: platform: access device property as a list of strings

2015-09-09 Thread Baptiste Reynal
From: Antonios Motakis 

Certain device properties (e.g. the device node name, the compatible
string), are available as a list of strings (separated by the null
terminating character). Let the VFIO user query this type of properties.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 

---
v3 -> v4:
 - The list length is computed before strings copy. If the entire list
   doesn't fit, no strings are copied to the user.
---
 drivers/vfio/platform/properties.c | 43 +-
 1 file changed, 42 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/platform/properties.c 
b/drivers/vfio/platform/properties.c
index 98754c2..8bf9c8f 100644
--- a/drivers/vfio/platform/properties.c
+++ b/drivers/vfio/platform/properties.c
@@ -22,7 +22,48 @@ static int dev_property_get_strings(struct device *dev, 
uint32_t *flags,
char *name, unsigned *lenp,
void __user *datap, unsigned long datasz)
 {
-   return -EINVAL;
+   const char **val;
+   int n, i, ret;
+
+   if (lenp == NULL)
+   return -EFAULT;
+
+   *lenp = 0;
+
+   n = device_property_read_string_array(dev, name, NULL, 0);
+   if (n < 0)
+   return n;
+
+   val = kcalloc(n, sizeof(char *), GFP_KERNEL);
+   if (!val)
+   return -ENOMEM;
+
+   ret = device_property_read_string_array(dev, name, val, n);
+   if (ret < 0)
+   goto out;
+
+   for (i = 0; i < n; i++)
+   *lenp += strlen(val[i]) + 1;
+
+   if (datasz < *lenp) {
+   ret = -E2BIG;
+   goto out;
+   }
+
+   for (i = 0; i < n; i++) {
+   size_t len = strlen(val[i]) + 1;
+
+   if (copy_to_user(datap, val[i], strlen(val[i]) + 1)) {
+   ret = -EFAULT;
+   goto out;
+   }
+
+   datap += len;
+   }
+
+out:
+   kfree(val);
+   return ret;
 }
 
 static int dev_property_get_uint(struct device *dev, uint32_t *flags,
-- 
2.5.1

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


Re: [RFC PATCH v3 0/3] vfio: platform: return device properties for a platform device

2015-09-03 Thread Baptiste Reynal
On Wed, Sep 2, 2015 at 6:52 PM, Alex Williamson
 wrote:
> On Wed, 2015-09-02 at 11:49 +0200, Baptiste Reynal wrote:
>> On Wed, Sep 2, 2015 at 11:21 AM, Christoffer Dall
>>  wrote:
>> > On Wed, Sep 02, 2015 at 09:21:26AM +0200, Baptiste Reynal wrote:
>> >> On Tue, Sep 1, 2015 at 5:52 PM, Christoffer Dall
>> >>  wrote:
>> >> > On Tue, Sep 01, 2015 at 05:32:21PM +0200, Baptiste Reynal wrote:
>> >> >> Hi everyone,
>> >> >>
>> >> >> The usefullness of this patch has already been discussed during the
>> >> >> first releases 
>> >> >> (http://lists.linuxfoundation.org/pipermail/iommu/2014-August/009586.html).
>> >> >> I underline the fact that it avoids implementing the logic on the
>> >> >> userspace program, as VFIO can be used for many usage (userspace
>> >> >> drivers and device assignment).
>> >> >>
>> >> >> If you're interested in the implementation on the userspace side, an
>> >> >> RFC has been suggested for QEMU:
>> >> >> http://lists.gnu.org/archive/html/qemu-devel/2015-01/msg01211.html
>> >> >
>> >> > This one-year-old discussion is hardly exhaustive.
>> >> >
>> >> > I think you missed the gist of the question for Eric a bit as well.
>> >> >
>> >> > One important question for me is whether seeing the host DT is always
>> >> > sufficient or if the kernel and physical device driver can have more
>> >> > information about the device and its configuration which userspace may
>> >> > need, which cannot be directly read in the DT (for example because the
>> >> > driver has initialized the device in a specific way).  My point is, it's
>> >> > really not about DT-specific things (what if you used ACPI?), but it's
>> >> > about retrieving properties of a device and its configuration from
>> >> > userspace.
>> >> >
>> >> > Have we thought about the possible ways to achieve this and weight one
>> >> > option against the other?
>> >>
>> >> Problem is that now we only have a very few platform devices behind an
>> >> IOMMU, so we don't have the visibility to know if such a case will
>> >> occur. With the current use cases, the interface seems to be
>> >> sufficient.
>> >
>> > Ideally we can think about future use cases based on the experience of
>> > people in the community and come up with a solution considering future
>> > use cases.
>> >
>> >> By using IOCTL, we can always change the implementation
>> >> later without any change on the userspace.
>> >
>> > Can you be more concrete with what you mean here?
>> >
>>
>> By using an IOCTL, we define an API that allows to retrieve device
>> properties from userspace. The way it is retrieved is handled by the
>> kernel (For example for now if OF is unavailable, the kernel will
>> retrieve the property using ACPI) and is totally transparent from the
>> userspace point of view.
>>
>> My point is that we can go with the current naive implementation for
>> now, and we might extend it later according to the needs of future
>> devices, without changing anything from the userspace point of view.
>
> I don't really like "ioctl" and "naive implementation" in the same
> thought.  The ioctl itself needs to be well thought out for current and
> future needs, including independence from the source data type
> (OF/DT/ACPI/etc), proven that it's necessary, it's not redundant to
> existing interfaces, and vfio should be the one hosting it.  Thanks,
>

The word we used, naive, does not mean a bad implementation of the
IOCTL interface but rather it was referring to the fact that at this
moment we export 1-to-1 the information available in the device tree
via sys or proc file system. So one could obtain the same result
without such interface, however our implementation is aready
independent from the source of such information, since OF and ACPI are
supported already, and there will be no problem in extending the
interface to support more.

The next release will take into account your comments about argsz and flags.

Regards,
Baptiste

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


Re: [RFC PATCH v3 0/3] vfio: platform: return device properties for a platform device

2015-09-02 Thread Baptiste Reynal
On Wed, Sep 2, 2015 at 12:32 PM, Christoffer Dall
 wrote:
> On Wed, Sep 02, 2015 at 11:49:12AM +0200, Baptiste Reynal wrote:
>> On Wed, Sep 2, 2015 at 11:21 AM, Christoffer Dall
>>  wrote:
>> > On Wed, Sep 02, 2015 at 09:21:26AM +0200, Baptiste Reynal wrote:
>> >> On Tue, Sep 1, 2015 at 5:52 PM, Christoffer Dall
>> >>  wrote:
>> >> > On Tue, Sep 01, 2015 at 05:32:21PM +0200, Baptiste Reynal wrote:
>> >> >> Hi everyone,
>> >> >>
>> >> >> The usefullness of this patch has already been discussed during the
>> >> >> first releases 
>> >> >> (http://lists.linuxfoundation.org/pipermail/iommu/2014-August/009586.html).
>> >> >> I underline the fact that it avoids implementing the logic on the
>> >> >> userspace program, as VFIO can be used for many usage (userspace
>> >> >> drivers and device assignment).
>> >> >>
>> >> >> If you're interested in the implementation on the userspace side, an
>> >> >> RFC has been suggested for QEMU:
>> >> >> http://lists.gnu.org/archive/html/qemu-devel/2015-01/msg01211.html
>> >> >
>> >> > This one-year-old discussion is hardly exhaustive.
>> >> >
>> >> > I think you missed the gist of the question for Eric a bit as well.
>> >> >
>> >> > One important question for me is whether seeing the host DT is always
>> >> > sufficient or if the kernel and physical device driver can have more
>> >> > information about the device and its configuration which userspace may
>> >> > need, which cannot be directly read in the DT (for example because the
>> >> > driver has initialized the device in a specific way).  My point is, it's
>> >> > really not about DT-specific things (what if you used ACPI?), but it's
>> >> > about retrieving properties of a device and its configuration from
>> >> > userspace.
>> >> >
>> >> > Have we thought about the possible ways to achieve this and weight one
>> >> > option against the other?
>> >>
>> >> Problem is that now we only have a very few platform devices behind an
>> >> IOMMU, so we don't have the visibility to know if such a case will
>> >> occur. With the current use cases, the interface seems to be
>> >> sufficient.
>> >
>> > Ideally we can think about future use cases based on the experience of
>> > people in the community and come up with a solution considering future
>> > use cases.
>> >
>> >> By using IOCTL, we can always change the implementation
>> >> later without any change on the userspace.
>> >
>> > Can you be more concrete with what you mean here?
>> >
>>
>> By using an IOCTL, we define an API that allows to retrieve device
>> properties from userspace. The way it is retrieved is handled by the
>> kernel (For example for now if OF is unavailable, the kernel will
>> retrieve the property using ACPI) and is totally transparent from the
>> userspace point of view.
>
> ok, I thought that this series was targeting device tree specifically,
> but I see that you changed this approach in v3.
>
>>
>> My point is that we can go with the current naive implementation for
>> now, and we might extend it later according to the needs of future
>> devices, without changing anything from the userspace point of view.
>>
> fair enough.
>
> Is this series exporting properties not already exported through sysfs?

Currently not, only OF and ACPI properties are read.

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


Re: [RFC PATCH v3 0/3] vfio: platform: return device properties for a platform device

2015-09-02 Thread Baptiste Reynal
On Wed, Sep 2, 2015 at 11:21 AM, Christoffer Dall
 wrote:
> On Wed, Sep 02, 2015 at 09:21:26AM +0200, Baptiste Reynal wrote:
>> On Tue, Sep 1, 2015 at 5:52 PM, Christoffer Dall
>>  wrote:
>> > On Tue, Sep 01, 2015 at 05:32:21PM +0200, Baptiste Reynal wrote:
>> >> Hi everyone,
>> >>
>> >> The usefullness of this patch has already been discussed during the
>> >> first releases 
>> >> (http://lists.linuxfoundation.org/pipermail/iommu/2014-August/009586.html).
>> >> I underline the fact that it avoids implementing the logic on the
>> >> userspace program, as VFIO can be used for many usage (userspace
>> >> drivers and device assignment).
>> >>
>> >> If you're interested in the implementation on the userspace side, an
>> >> RFC has been suggested for QEMU:
>> >> http://lists.gnu.org/archive/html/qemu-devel/2015-01/msg01211.html
>> >
>> > This one-year-old discussion is hardly exhaustive.
>> >
>> > I think you missed the gist of the question for Eric a bit as well.
>> >
>> > One important question for me is whether seeing the host DT is always
>> > sufficient or if the kernel and physical device driver can have more
>> > information about the device and its configuration which userspace may
>> > need, which cannot be directly read in the DT (for example because the
>> > driver has initialized the device in a specific way).  My point is, it's
>> > really not about DT-specific things (what if you used ACPI?), but it's
>> > about retrieving properties of a device and its configuration from
>> > userspace.
>> >
>> > Have we thought about the possible ways to achieve this and weight one
>> > option against the other?
>>
>> Problem is that now we only have a very few platform devices behind an
>> IOMMU, so we don't have the visibility to know if such a case will
>> occur. With the current use cases, the interface seems to be
>> sufficient.
>
> Ideally we can think about future use cases based on the experience of
> people in the community and come up with a solution considering future
> use cases.
>
>> By using IOCTL, we can always change the implementation
>> later without any change on the userspace.
>
> Can you be more concrete with what you mean here?
>

By using an IOCTL, we define an API that allows to retrieve device
properties from userspace. The way it is retrieved is handled by the
kernel (For example for now if OF is unavailable, the kernel will
retrieve the property using ACPI) and is totally transparent from the
userspace point of view.

My point is that we can go with the current naive implementation for
now, and we might extend it later according to the needs of future
devices, without changing anything from the userspace point of view.

>>
>> Do you think we can valid the API, then if such a case occurs (when
>> the device informations changes between the device tree and the
>> running state) we can change the kernel implementation ?
>>
>
> Sorry, I don't understand this paragraph.
>
> -Christoffer
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 0/3] vfio: platform: return device properties for a platform device

2015-09-02 Thread Baptiste Reynal
On Tue, Sep 1, 2015 at 5:52 PM, Christoffer Dall
 wrote:
> On Tue, Sep 01, 2015 at 05:32:21PM +0200, Baptiste Reynal wrote:
>> Hi everyone,
>>
>> The usefullness of this patch has already been discussed during the
>> first releases 
>> (http://lists.linuxfoundation.org/pipermail/iommu/2014-August/009586.html).
>> I underline the fact that it avoids implementing the logic on the
>> userspace program, as VFIO can be used for many usage (userspace
>> drivers and device assignment).
>>
>> If you're interested in the implementation on the userspace side, an
>> RFC has been suggested for QEMU:
>> http://lists.gnu.org/archive/html/qemu-devel/2015-01/msg01211.html
>
> This one-year-old discussion is hardly exhaustive.
>
> I think you missed the gist of the question for Eric a bit as well.
>
> One important question for me is whether seeing the host DT is always
> sufficient or if the kernel and physical device driver can have more
> information about the device and its configuration which userspace may
> need, which cannot be directly read in the DT (for example because the
> driver has initialized the device in a specific way).  My point is, it's
> really not about DT-specific things (what if you used ACPI?), but it's
> about retrieving properties of a device and its configuration from
> userspace.
>
> Have we thought about the possible ways to achieve this and weight one
> option against the other?

Problem is that now we only have a very few platform devices behind an
IOMMU, so we don't have the visibility to know if such a case will
occur. With the current use cases, the interface seems to be
sufficient. By using IOCTL, we can always change the implementation
later without any change on the userspace.

Do you think we can valid the API, then if such a case occurs (when
the device informations changes between the device tree and the
running state) we can change the kernel implementation ?

>
> -Christoffer
>
>>
>> On Tue, Sep 1, 2015 at 11:28 AM, Christoffer Dall
>>  wrote:
>> > Hi Eric,
>> >
>> > On Tue, Sep 01, 2015 at 09:31:56AM +0200, Eric Auger wrote:
>> >
>> > [...]
>> >
>> >> >>> Can you reiterate why QEMU and VFIO don't already have the information
>> >> >>> necessary to setup resources and present a DT to the guest that the
>> >> >>> guest can use?
>> >> >> A vfio-platform driver was bound to the passthrough'ed device. QEMU
>> >> >> current knows the compat string of the device and the node's name and
>> >> >> that's it.
>> >> >>
>> >> >> The VFIO platform driver currently does not allow to return device
>> >> >> specific information. It just returns generic info such as resource
>> >> >> info. The driver is HW agnostic.
>> >> >>
>> >> >>
>> >> >> The QEMU VFIO device should be able to check some characteristics of 
>> >> >> the
>> >> >> host device tree. Typically if the host node does not comply with some
>> >> >> constraints it may not be possible to assign the device.
>> >> >>
>> >> >> We do not want the QEMU end-user to have in-depth knowledge of the HW 
>> >> >> so
>> >> >> passing the info in the QEMU command line does not sound to be the good
>> >> >> solution.
>> >> >>
>> >> >>
>> >> >> As you mentioned /proc/device-tree depends on kernel option. I am able
>> >> >> to find the properties in sysfs too but can we systematically rely on
>> >> >> sysfs (CONFIG_SYSFS)? Also I would have expected the values to be human
>> >> >> readable but they are not. Currently investigating open/read from qemu
>> >> >> but is better than an ioctl API? ...
>> >> >>
>> >> > Yeah it does, but I thought we originally planned that the driver for a
>> >> > specific platform device in QEMU should know these details,
>> >> Yes that's the objective to put this intelligence in the QEMU VFIO
>> >> device or more precisely in the associated function that builds its
>> >> guest dt node.
>> >>
>> >> Let's take an example. Assuming an xgmac supports different speeds, you
>> >> need to set those on guest. Either you put arbitrary values or you reuse
>> >> the values that were set on host. Typically some values may not be
>> >> supported by the HW.
>> >>
>> >
>> > I see.  I'm no expert here, but I could imagine that drivers could
>> > overwrite some things in the DT or do some advanced probing of the
>> > hardware which is then only exported in the sysfs and not the DT, so I
>> > would go the sysfs approach myself.
>> >
>> >> Idea of genericity was ruled out indeed meaning each device needs to
>> >> have a specialized QEMU VFIO device and an associated dt node creation
>> >> function. Now this does not prevent from exploiting host dt information.
>> >> Does that make sense?
>> >>
>> > Yes, thanks for the explanation.
>> >
>> > -Christoffer
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v3 0/3] vfio: platform: return device properties for a platform device

2015-09-01 Thread Baptiste Reynal
Hi everyone,

The usefullness of this patch has already been discussed during the
first releases 
(http://lists.linuxfoundation.org/pipermail/iommu/2014-August/009586.html).
I underline the fact that it avoids implementing the logic on the
userspace program, as VFIO can be used for many usage (userspace
drivers and device assignment).

If you're interested in the implementation on the userspace side, an
RFC has been suggested for QEMU:
http://lists.gnu.org/archive/html/qemu-devel/2015-01/msg01211.html

We are willing to put some efforts on this patch serie, so a new
version will be released according to your comments by the end of the
week.

Best regards,
Baptiste

On Tue, Sep 1, 2015 at 11:28 AM, Christoffer Dall
 wrote:
> Hi Eric,
>
> On Tue, Sep 01, 2015 at 09:31:56AM +0200, Eric Auger wrote:
>
> [...]
>
>> >>> Can you reiterate why QEMU and VFIO don't already have the information
>> >>> necessary to setup resources and present a DT to the guest that the
>> >>> guest can use?
>> >> A vfio-platform driver was bound to the passthrough'ed device. QEMU
>> >> current knows the compat string of the device and the node's name and
>> >> that's it.
>> >>
>> >> The VFIO platform driver currently does not allow to return device
>> >> specific information. It just returns generic info such as resource
>> >> info. The driver is HW agnostic.
>> >>
>> >>
>> >> The QEMU VFIO device should be able to check some characteristics of the
>> >> host device tree. Typically if the host node does not comply with some
>> >> constraints it may not be possible to assign the device.
>> >>
>> >> We do not want the QEMU end-user to have in-depth knowledge of the HW so
>> >> passing the info in the QEMU command line does not sound to be the good
>> >> solution.
>> >>
>> >>
>> >> As you mentioned /proc/device-tree depends on kernel option. I am able
>> >> to find the properties in sysfs too but can we systematically rely on
>> >> sysfs (CONFIG_SYSFS)? Also I would have expected the values to be human
>> >> readable but they are not. Currently investigating open/read from qemu
>> >> but is better than an ioctl API? ...
>> >>
>> > Yeah it does, but I thought we originally planned that the driver for a
>> > specific platform device in QEMU should know these details,
>> Yes that's the objective to put this intelligence in the QEMU VFIO
>> device or more precisely in the associated function that builds its
>> guest dt node.
>>
>> Let's take an example. Assuming an xgmac supports different speeds, you
>> need to set those on guest. Either you put arbitrary values or you reuse
>> the values that were set on host. Typically some values may not be
>> supported by the HW.
>>
>
> I see.  I'm no expert here, but I could imagine that drivers could
> overwrite some things in the DT or do some advanced probing of the
> hardware which is then only exported in the sysfs and not the DT, so I
> would go the sysfs approach myself.
>
>> Idea of genericity was ruled out indeed meaning each device needs to
>> have a specialized QEMU VFIO device and an associated dt node creation
>> function. Now this does not prevent from exploiting host dt information.
>> Does that make sense?
>>
> Yes, thanks for the explanation.
>
> -Christoffer
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC 0/6] vSMMU initialization

2015-07-15 Thread Baptiste Reynal
On Tue, Jul 14, 2015 at 1:04 PM, Will Deacon  wrote:
> On Tue, Jul 14, 2015 at 03:21:03AM +0100, Varun Sethi wrote:
>> Hi Will,
>
> Hi Varun,
>
>> > On Fri, Jun 12, 2015 at 03:20:04PM +0100, Baptiste Reynal wrote:
>> > > The ARM SMMU has support for 2-stages address translations, allowing a
>> > > virtual address to be translated at two levels:
>> > > - Stage 1 translates a virtual address (VA) into an intermediate
>> > > physical address (IPA)
>> > > - Stage 2 translates an IPA into a physical address (PA)
>> > >
>> > > Will Deacon introduced a virtual SMMU interface for KVM, which gives a
>> > > virtual machine the possibility to use an IOMMU with native drivers.
>> > > While the VM will program the first stage of translation (stage 1),
>> > > the interface will program the second (stage 2) on the physical SMMU.
>> >
>> > Please note that I have no plans to merge the kernel-side of this at the
>> > moment. It was merely an exploratory tool to see what a non-PV vSMMU
>> > implementation might look like and certainly not intended to be used in
>> > anger.
>> How do you see the context fault reporting work for the PV interface?
>
> We could have an interrupt, for the PV IOMMU and have the hypervisor
> inject that, no?
>
>> Currently the vSMMU interface does seem quiet restrictive and it may
>> simplify things by having PV iommu interface. But, do you see this even
>> true in case of SMMUv3?

Varun, may I know what do you mean by "more restrictive" ? Do you have
in mind any use case which should apply to the PV interface and not
the vSMMU ?

>
> I think SMMUv3 is *far* more amenable to the vSMMU approach, largely
> because it moves many of the data structures into memory, but also because
> it has support for things like ATS and PRI, so sharing page tables with
> the CPU becomes a real possibility (and is something that doesn't work
> well with a PV model).
>
>> Just wondering if we can give more control with respect memory transaction
>> attributes to the guest. Also, would it make sense to give guest control
>> of the fault handling attributes i.e. fault/terminate model.
>
> I'd like to see the basics prototyped before we start trying to design
> for these more advanced use-cases. I'm confident there are plenty of things
> we haven't even considered at the moment.

Hi Will,

>From my current understanding, vSMMU and PV interface seems
complementary and have different target. While the PV interface
targets broad compatibility with hardware and page table abstraction,
the vSMMU relies on specific hardware capabilities for better
performances (with dual-stage support and future ATS/PRI). As no PV
interface exists for now, we decided to focus our effort on the vSMMU.
Unless PV interface is strictly needed, we'd like to continue with the
implementation of the vSMMU.

In my opinion, both solutions are complementary and can co-exist once
someone shows interest for the PV.
>
> Will

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


Re: [PATCH] iommu/arm-smmu: Fix bug in ARM_SMMU_FEAT_TRANS_OPS condition check

2015-06-23 Thread Baptiste Reynal
This issue has already been fixed here :
http://www.spinics.net/lists/arm-kernel/msg424824.html

Regards,
Baptiste

On Tue, Jun 23, 2015 at 2:07 PM, Sricharan R  wrote:
> Patch 'fix ARM_SMMU_FEAT_TRANS_OPS condition' changed the check
> for ARM_SMMU_FEAT_TRANS_OPS to be based on presence of stage1 check,
> but used (id & ID0_ATOSNS) instead of !(id & ID0_ATOSNS).
> Fix it here.
>
> Signed-off-by: Sricharan R 
> ---
>  drivers/iommu/arm-smmu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index 09091e9..fbf4af6 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -1866,7 +1866,7 @@ static int arm_smmu_device_cfg_probe(struct 
> arm_smmu_device *smmu)
> return -ENODEV;
> }
>
> -   if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) {
> +   if ((id & ID0_S1TS) && ((smmu->version == 1) || !(id & ID0_ATOSNS))) {
> smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
> dev_notice(smmu->dev, "\taddress translation ops\n");
> }
> --
> QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member of 
> Code Aurora Forum, hosted by The Linux Foundation
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[RFC 6/6] hw/arm/sysbus-fdt: add smmu masters in device tree

2015-06-12 Thread Baptiste Reynal
This patch adds a function to bind a device as an SMMU master in the
device tree. Currently, only one device is supported.

A device can be set as SMMU master by using the "x-iommu" argument on
the command line:

-device pl330,x-iommu=true

Signed-off-by: Baptiste Reynal 
---
 hw/arm/sysbus-fdt.c | 35 +++
 hw/vfio/platform.c  |  1 +
 include/hw/vfio/vfio-platform.h |  1 +
 3 files changed, 37 insertions(+)

diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
index 67f4425..356f644 100644
--- a/hw/arm/sysbus-fdt.c
+++ b/hw/arm/sysbus-fdt.c
@@ -101,6 +101,38 @@ static const NodeCreationPair add_fdt_node_functions[] = {
 {"", NULL}, /* last element */
 };
 
+static int add_smmu_master(SysBusDevice *sbdev, void *opaque)
+{
+if (object_dynamic_cast(OBJECT(sbdev), TYPE_VFIO_PLATFORM) &&
+   VFIO_PLATFORM_DEVICE(sbdev)->iommu_master) {
+int master[2];
+char *smmu_nodename, *master_nodename;
+uint64_t mmio_base;
+PlatformBusFDTData *data = opaque;
+PlatformBusDevice *pbus = data->pbus;
+void *fdt = data->fdt;
+VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
+VFIODevice *vbasedev = &vdev->vbasedev;
+const char *parent_node = data->pbus_node_name;
+
+smmu_nodename = g_strdup_printf("/smmu@%" PRIx64, vsmmu->base);
+mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+
+master_nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
+vbasedev->name,
+mmio_base);
+
+master[0] = cpu_to_be32(qemu_fdt_get_phandle(fdt, master_nodename));
+master[1] = cpu_to_be32(vbasedev->group->groupid);
+
+qemu_fdt_setprop(fdt, smmu_nodename, "mmu-masters",
+master, 2*sizeof(int));
+
+}
+
+return 0;
+}
+
 /**
  * add_fdt_node - add the device tree node of a dynamic sysbus device
  *
@@ -193,6 +225,9 @@ static void 
add_all_platform_bus_fdt_nodes(ARMPlatformBusFDTParams *fdt_params)
 
 /* Loop through all dynamic sysbus devices and create their node */
 foreach_dynamic_sysbus_device(add_fdt_node, &data);
+if (vsmmu) {
+foreach_dynamic_sysbus_device(add_smmu_master, &data);
+}
 
 g_free(node);
 }
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index 6192458..d4ea297 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -585,6 +585,7 @@ static Property vfio_platform_dev_properties[] = {
 DEFINE_PROP_BOOL("x-mmap", VFIOPlatformDevice, vbasedev.allow_mmap, true),
 DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
mmap_timeout, 1100),
+DEFINE_PROP_BOOL("x-iommu", VFIOPlatformDevice, iommu_master, false),
 DEFINE_PROP_END_OF_LIST(),
 };
 
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
index 26b2ad6..8f5d980 100644
--- a/include/hw/vfio/vfio-platform.h
+++ b/include/hw/vfio/vfio-platform.h
@@ -57,6 +57,7 @@ typedef struct VFIOPlatformDevice {
 uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
 QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
 QemuMutex intp_mutex; /* protect the intp_list IRQ state */
+bool iommu_master; /* is the device a master to the vSMMU ? */
 } VFIOPlatformDevice;
 
 typedef struct VFIOPlatformDeviceClass {
-- 
2.4.3

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


[RFC 5/6] hw/arm/sysbus-fdt: enable vsmmu dynamic instantiation

2015-06-12 Thread Baptiste Reynal
This patch adds the device tree node creation for the vSMMU.

Signed-off-by: Baptiste Reynal 
---
 hw/arm/sysbus-fdt.c | 43 +++
 1 file changed, 43 insertions(+)

diff --git a/hw/arm/sysbus-fdt.c b/hw/arm/sysbus-fdt.c
index 3038b94..67f4425 100644
--- a/hw/arm/sysbus-fdt.c
+++ b/hw/arm/sysbus-fdt.c
@@ -26,6 +26,10 @@
 #include "sysemu/device_tree.h"
 #include "hw/platform-bus.h"
 #include "sysemu/sysemu.h"
+#include "hw/vfio/vfio-platform.h"
+#include "hw/vfio/vfio-smmu.h"
+
+#include 
 
 /*
  * internal struct that contains the information to create dynamic
@@ -53,8 +57,47 @@ typedef struct NodeCreationPair {
 int (*add_fdt_node_fn)(SysBusDevice *sbdev, void *opaque);
 } NodeCreationPair;
 
+VFIOSmmuDevice *vsmmu = NULL;
+
+static int add_arm_smmu_fdt_node(SysBusDevice *sbdev, void *opaque)
+{
+PlatformBusFDTData *data = opaque;
+vsmmu = VFIO_SMMU_DEVICE(sbdev);
+void *fdt = data->fdt;
+const char *nodename;
+uint32_t reg_attr[4], irq_attr[3];
+uint32_t gint = 0;
+
+nodename = g_strdup_printf("/smmu@%" PRIx64, vsmmu->base);
+
+qemu_fdt_add_subnode(fdt, nodename);
+qemu_fdt_setprop(fdt, nodename, "compatible", "arm,smmu-v2", 12);
+
+reg_attr[0] = 0;
+reg_attr[1] = cpu_to_be32(vsmmu->base);
+reg_attr[2] = 0;
+reg_attr[3] = cpu_to_be32(vsmmu->size);
+
+qemu_fdt_setprop(fdt, nodename, "reg",
+reg_attr, 4*sizeof(uint32_t));
+
+/* Add dummy interrupt */
+irq_attr[0] = 0;
+irq_attr[1] = 0;
+irq_attr[2] = 0;
+
+qemu_fdt_setprop(fdt, nodename, "interrupts",
+irq_attr, 3*sizeof(uint32_t));
+
+qemu_fdt_setprop(fdt, nodename, "#global-interrupts", &gint,
+sizeof(uint32_t));
+
+return 0;
+}
+
 /* list of supported dynamic sysbus devices */
 static const NodeCreationPair add_fdt_node_functions[] = {
+{TYPE_VFIO_SMMU, add_arm_smmu_fdt_node},
 {"", NULL}, /* last element */
 };
 
-- 
2.4.3

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


[RFC 1/6] headers sync

2015-06-12 Thread Baptiste Reynal
Signed-off-by: Baptiste Reynal 
---
 linux-headers/linux/kvm.h | 15 +++
 1 file changed, 15 insertions(+)

diff --git a/linux-headers/linux/kvm.h b/linux-headers/linux/kvm.h
index fad9e5c..d48d7b1 100644
--- a/linux-headers/linux/kvm.h
+++ b/linux-headers/linux/kvm.h
@@ -1003,6 +1003,19 @@ struct kvm_device_attr {
 #define   KVM_DEV_VFIO_GROUP_ADD   1
 #define   KVM_DEV_VFIO_GROUP_DEL   2
 
+#define  KVM_DEV_ARM_SMMU_V2_CFG   1
+#define   KVM_DEV_ARM_SMMU_V2_CFG_INIT 1
+#define   KVM_DEV_ARM_SMMU_V2_CFG_IRQ  2
+#define   KVM_DEV_ARM_SMMU_V2_CFG_SIZE 3
+#define  KVM_DEV_ARM_SMMU_V2_VFIO  2
+#define   KVM_DEV_ARM_SMMU_V2_VFIO_GROUP_ADD   1
+#define   KVM_DEV_ARM_SMMU_V2_VFIO_GROUP_DEL   2
+
+struct arm_smmu_v2_vfio_group_sid {
+   __u32   fd; /* file descriptor of the VFIO group */
+   __u16   sid;
+};
+
 enum kvm_device_type {
KVM_DEV_TYPE_FSL_MPIC_20= 1,
 #define KVM_DEV_TYPE_FSL_MPIC_20   KVM_DEV_TYPE_FSL_MPIC_20
@@ -1018,6 +1031,8 @@ enum kvm_device_type {
 #define KVM_DEV_TYPE_FLIC  KVM_DEV_TYPE_FLIC
KVM_DEV_TYPE_ARM_VGIC_V3,
 #define KVM_DEV_TYPE_ARM_VGIC_V3   KVM_DEV_TYPE_ARM_VGIC_V3
+   KVM_DEV_TYPE_ARM_SMMU_V2,
+#define KVM_DEV_TYPE_ARM_SMMU_V2   KVM_DEV_TYPE_ARM_SMMU_V2
KVM_DEV_TYPE_MAX,
 };
 
-- 
2.4.3

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


[RFC 2/6] hw/core/platform-bus: initialization notifier

2015-06-12 Thread Baptiste Reynal
Add a platform_bus_link_done_notifier for devices to be notified once
the platform bus is initialized. Address and IRQs for platform devices
are unknown at device realization, we need to notify the device once
the platform bus gathered all devices, i.e. when those resources are
ready. This is required for some device initialization
(e.g. the vSMMU base address needs to be set on the KVM device).

Signed-off-by: Baptiste Reynal 
---
 hw/core/platform-bus.c| 13 +
 include/hw/platform-bus.h |  1 +
 2 files changed, 14 insertions(+)

diff --git a/hw/core/platform-bus.c b/hw/core/platform-bus.c
index 0f052b3..8642dfc 100644
--- a/hw/core/platform-bus.c
+++ b/hw/core/platform-bus.c
@@ -24,6 +24,18 @@
 #include "exec/address-spaces.h"
 #include "sysemu/sysemu.h"
 
+static NotifierList platform_bus_link_done_notifiers =
+NOTIFIER_LIST_INITIALIZER(platform_bus_link_done_notifiers);
+
+void qemu_add_platform_bus_link_done_notifier(Notifier *notify)
+{
+notifier_list_add(&platform_bus_link_done_notifiers, notify);
+}
+
+static void qemu_run_platform_bus_link_done_notifiers(void)
+{
+notifier_list_notify(&platform_bus_link_done_notifiers, NULL);
+}
 
 /*
  * Returns the PlatformBus IRQ number for a SysBusDevice irq number or -1 if
@@ -196,6 +208,7 @@ static void platform_bus_init_notify(Notifier *notifier, 
void *data)
 plaform_bus_refresh_irqs(pb);
 
 foreach_dynamic_sysbus_device(link_sysbus_device, pb);
+qemu_run_platform_bus_link_done_notifiers();
 }
 
 static void platform_bus_realize(DeviceState *dev, Error **errp)
diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h
index bd42b83..3c3f96b 100644
--- a/include/hw/platform-bus.h
+++ b/include/hw/platform-bus.h
@@ -53,5 +53,6 @@ int platform_bus_get_irqn(PlatformBusDevice *platform_bus, 
SysBusDevice *sbdev,
   int n);
 hwaddr platform_bus_get_mmio_addr(PlatformBusDevice *pbus, SysBusDevice *sbdev,
   int n);
+void qemu_add_platform_bus_link_done_notifier(Notifier *notify);
 
 #endif /* !HW_PLATFORM_BUS_H */
-- 
2.4.3

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


[RFC 3/6] hw/core/platform-bus: add base_address field

2015-06-12 Thread Baptiste Reynal
Add base_address field to platform_bus structure and initialize it.

As the platform devices addresses are relative to the platform bus, we
need it to get the absolute address of a device.

Signed-off-by: Baptiste Reynal 
---
 hw/arm/virt.c | 4 
 include/hw/platform-bus.h | 2 ++
 2 files changed, 6 insertions(+)

diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index 1b1cc71..33361c5 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -740,6 +740,7 @@ static void create_platform_bus(VirtBoardInfo *vbi, 
qemu_irq *pic)
 {
 DeviceState *dev;
 SysBusDevice *s;
+PlatformBusDevice *pbus;
 int i;
 ARMPlatformBusFDTParams *fdt_params = g_new(ARMPlatformBusFDTParams, 1);
 MemoryRegion *sysmem = get_system_memory();
@@ -766,6 +767,9 @@ static void create_platform_bus(VirtBoardInfo *vbi, 
qemu_irq *pic)
 platform_bus_params.platform_bus_size);
 qdev_init_nofail(dev);
 s = SYS_BUS_DEVICE(dev);
+pbus = PLATFORM_BUS_DEVICE(dev);
+
+pbus->base_address = vbi->memmap[VIRT_PLATFORM_BUS].base;
 
 for (i = 0; i < platform_bus_params.platform_bus_num_irqs; i++) {
 int irqn = platform_bus_params.platform_bus_first_irq + i;
diff --git a/include/hw/platform-bus.h b/include/hw/platform-bus.h
index 3c3f96b..13efc82 100644
--- a/include/hw/platform-bus.h
+++ b/include/hw/platform-bus.h
@@ -41,6 +41,8 @@ struct PlatformBusDevice {
 bool done_gathering;
 
 /*< public >*/
+hwaddr base_address;
+
 uint32_t mmio_size;
 MemoryRegion mmio;
 
-- 
2.4.3

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


[RFC 4/6] hw/vfio: vsmmu device

2015-06-12 Thread Baptiste Reynal
This patches introduces support for ARM virtual SMMU, enabling two stages
address translation.

The vSMMU device can be instantiated from the command line using following
option:

-device vsmmu,x-group=1

Signed-off-by: Baptiste Reynal 
---
 hw/vfio/Makefile.objs   |   1 +
 hw/vfio/common.c|   8 ++-
 hw/vfio/platform.c  |   1 +
 hw/vfio/smmu.c  | 157 
 include/hw/vfio/vfio-smmu.h |  50 ++
 5 files changed, 215 insertions(+), 2 deletions(-)
 create mode 100644 hw/vfio/smmu.c
 create mode 100644 include/hw/vfio/vfio-smmu.h

diff --git a/hw/vfio/Makefile.objs b/hw/vfio/Makefile.objs
index d540c9d..4b91901 100644
--- a/hw/vfio/Makefile.objs
+++ b/hw/vfio/Makefile.objs
@@ -3,4 +3,5 @@ obj-$(CONFIG_SOFTMMU) += common.o
 obj-$(CONFIG_PCI) += pci.o
 obj-$(CONFIG_SOFTMMU) += platform.o
 obj-$(CONFIG_SOFTMMU) += calxeda-xgmac.o
+obj-$(CONFIG_SOFTMMU) += smmu.o
 endif
diff --git a/hw/vfio/common.c b/hw/vfio/common.c
index b1045da..a3ee72f 100644
--- a/hw/vfio/common.c
+++ b/hw/vfio/common.c
@@ -676,8 +676,12 @@ static int vfio_connect_container(VFIOGroup *group, 
AddressSpace *as)
 goto free_container_exit;
 }
 
-ret = ioctl(fd, VFIO_SET_IOMMU,
-v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU);
+if (ioctl(fd, VFIO_CHECK_EXTENSION, VFIO_TYPE1_NESTING_IOMMU)) {
+ret = ioctl(fd, VFIO_SET_IOMMU, VFIO_TYPE1_NESTING_IOMMU);
+} else {
+ret = ioctl(fd, VFIO_SET_IOMMU,
+   v2 ? VFIO_TYPE1v2_IOMMU : VFIO_TYPE1_IOMMU);
+}
 if (ret) {
 error_report("vfio: failed to set iommu for container: %m");
 ret = -errno;
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
index 9382bb7..6192458 100644
--- a/hw/vfio/platform.c
+++ b/hw/vfio/platform.c
@@ -475,6 +475,7 @@ static int vfio_base_device_init(VFIODevice *vbasedev)
 error_report("vfio: failed to get group %d", groupid);
 return -ENOENT;
 }
+vbasedev->group = group;
 
 g_snprintf(path, sizeof(path), "%s", vbasedev->name);
 
diff --git a/hw/vfio/smmu.c b/hw/vfio/smmu.c
new file mode 100644
index 000..467abbe
--- /dev/null
+++ b/hw/vfio/smmu.c
@@ -0,0 +1,157 @@
+/*
+ * support for vsmmu interface to use it with vfio devices
+ *
+ * Copyright (C) 2015 - Virtual Open Systems
+ *
+ * Author: Baptiste Reynal 
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2.  See
+ * the COPYING file in the top-level directory.
+ */
+
+#include 
+
+#include "hw/vfio/vfio-smmu.h"
+#include "sysemu/kvm.h"
+#include "sysemu/sysemu.h"
+#include "qemu/error-report.h"
+#include "hw/platform-bus.h"
+#include "hw/vfio/vfio.h"
+#include "hw/vfio/vfio-common.h"
+
+static void vsmmu_notify(Notifier *notifier, void *data)
+{
+SmmuNotifierParams *p = DO_UPCAST(SmmuNotifierParams,
+notifier, notifier);
+
+DeviceState *dev;
+PlatformBusDevice *pbus;
+SysBusDevice *sbdev = SYS_BUS_DEVICE(p->vsmmu);
+
+dev = qdev_find_recursive(sysbus_get_default(), TYPE_PLATFORM_BUS_DEVICE);
+pbus = PLATFORM_BUS_DEVICE(dev);
+assert(pbus->done_gathering);
+
+hwaddr base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
+base += pbus->base_address;
+
+struct kvm_device_attr attr = {
+.group = KVM_DEV_ARM_SMMU_V2_CFG,
+.attr = KVM_DEV_ARM_SMMU_V2_CFG_INIT,
+.addr = (uint64_t)(unsigned long) &base,
+};
+
+if (ioctl(p->vsmmu->kvm_device, KVM_SET_DEVICE_ATTR, &attr)) {
+error_report("Error during vSMMU initialization: %m.\n");
+} else {
+p->vsmmu->base = base;
+}
+}
+
+static void smmu_realize(DeviceState *dev, Error **errp)
+{
+VFIOSmmuDevice *vsmmu = VFIO_SMMU_DEVICE(dev);
+SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
+VFIOGroup *group;
+int ret;
+const char *name = "smmu memory";
+
+group = vfio_get_group(vsmmu->group, &address_space_memory);
+if (!group) {
+error_report("vfio: failed to get group %d", vsmmu->group);
+goto fail;
+}
+
+/* Create ARM_SMMU_V2 */
+struct kvm_create_device cd = {
+.type = KVM_DEV_TYPE_ARM_SMMU_V2,
+};
+
+ret = kvm_vm_ioctl(kvm_state, KVM_CREATE_DEVICE, &cd);
+if (ret < 0) {
+error_report("vfio: error creating vSMMU: %m");
+goto fail;
+};
+vsmmu->kvm_device = cd.fd;
+
+/* Add group */
+struct arm_smmu_v2_vfio_group_sid group_sid = {
+.fd = group->fd,
+.sid = group->groupid,
+};
+
+struct kvm_device_attr attr = {
+.group = KVM_DEV_ARM_SMMU_V2_VFIO,
+.attr = KVM_DEV_ARM_SMMU_V2_VFIO_GROUP_ADD,
+.addr = (uint64_t)(uns

[RFC 0/6] vSMMU initialization

2015-06-12 Thread Baptiste Reynal
The ARM SMMU has support for 2-stages address translations, allowing a virtual
address to be translated at two levels:
- Stage 1 translates a virtual address (VA) into an intermediate physical
address (IPA)
- Stage 2 translates an IPA into a physical address (PA)

Will Deacon introduced a virtual SMMU interface for KVM, which gives a virtual
machine the possibility to use an IOMMU with native drivers. While the VM will
program the first stage of translation (stage 1), the interface will program
the second (stage 2) on the physical SMMU.

This RFC brings support for the vSMMU on QEMU-side, introducing the code for
vSMMU initialization and the device tree operations needed to attach devices
to it.

The main purpose of such vSMMU device is to allow VFIO devices to benefit
from an IOMMU on the guest side, for userspace drivers or nested VFIO.

It is an early state of development so:
- Interrupts are not handled for now
- Only one device can be bound to the vSMMU

I'm open to any comments or suggestions.

Baptiste Reynal (6):
  headers sync
  hw/core/platform-bus: initialization notifier
  hw/core/platform-bus: add base_address field
  hw/vfio: vsmmu device
  hw/arm/sysbus-fdt: enable vsmmu dynamic instantiation
  hw/arm/sysbus-fdt: add smmu masters in device tree

 hw/arm/sysbus-fdt.c |  78 
 hw/arm/virt.c   |   4 +
 hw/core/platform-bus.c  |  13 
 hw/vfio/Makefile.objs   |   1 +
 hw/vfio/common.c|   8 +-
 hw/vfio/platform.c  |   2 +
 hw/vfio/smmu.c  | 157 
 include/hw/platform-bus.h   |   3 +
 include/hw/vfio/vfio-platform.h |   1 +
 include/hw/vfio/vfio-smmu.h |  50 +
 linux-headers/linux/kvm.h   |  15 
 11 files changed, 330 insertions(+), 2 deletions(-)
 create mode 100644 hw/vfio/smmu.c
 create mode 100644 include/hw/vfio/vfio-smmu.h

-- 
2.4.3

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


Re: SMMU 2-stage support

2015-04-03 Thread Baptiste Reynal
Hello,

We are eventually working on the vSMMU implementation. Relying on the talk
Will Deacon gave at the Linux Plumbers IOMMU Microconference on October
2014 (http://linuxplumbersconf.org/2014/ocw/proposals/2019), I tried the
vSMMU initialization.

I have a question about the KVM_DEV_ARM_SMMU_V2_CFG_INIT call. What is
exactly expected as parameters ?
My guess is, as it is the base address of the vSMMU, it should be the
address expected to be the "physical address" of the vSMMU on the guest
side. Am I right ?

Thanks,
Baptiste

On Wed, Feb 18, 2015 at 7:56 PM, Will Deacon  wrote:

> On Wed, Feb 18, 2015 at 05:04:21PM +0000, Baptiste Reynal wrote:
> > We are currently working on the ARM SMMU 2-stage support in order to
> > expose SMMU capabilities to a guest OS.
> > By doing some research, we noticed some work has already be done by Will
> > Deacon on exposing virtual IOMMU interface to KVM guest. After going
> > through slides and code (on
> > git://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git<
> http://git.kernel.org/pub/scm/linux/kernel/git/will/linux.git>,
> > branch: iommu/vsmmu), we have some questions :
> >
> > - What is the status of this work ? Is Alex still working on it ?
>
> I got a reasonable way through implementing something, but ran into a
> wall for a few reasons:
>
>   (1) I don't have anything where I can test this (yet)
>
>   (2) Nobody's actually asking for it...
>
> > - Are there any test case about the current vsmmu implementation ?
>
> No.
>
> > - What is exposed to the guest in the current implementation ?
>
> An emulation of a stage-1 only SMMU.
>
> > - How do the guest program the stage-1 translation ?
>
> Just like it would for a physical SMMU.
> It's probably easiest if you look at the (incomplete, WIP) code:
>
>
> https://git.kernel.org/cgit/linux/kernel/git/will/linux.git/commit/?h=iommu/vsmmu&id=539dbcb964e5c730791a6a31a4f58ceff4b945c2
>
> Anyway, until somebody actually wants this feature I've put it on ice as
> it adds a whole bunch of complication to the ARM SMMU driver, as well as
> new user ABI extensions that I don't really want to maintain for fun.
>
> The only murmurs I've heard about IOMMU usage from a guest relate to a
> paravirtualised interface, which abstracts the details of the host IOMMU
> altogether and allows the translation to be collapsed (which can be
> better for TLB utilisation).
>
> Will
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v14 19/20] vfio: initialize the virqfd workqueue in VFIO generic code

2015-03-18 Thread Baptiste Reynal
Hello Alex,

The module solution seems fine for me, I have no argument against it.
I used your patch on my tests, they are running ok.

Regards,
Baptiste

On Wed, Mar 18, 2015 at 12:04 AM, Alex Williamson
 wrote:
> On Tue, 2015-03-17 at 16:29 -0600, Alex Williamson wrote:
>> On Mon, 2015-03-02 at 17:59 +0100, Baptiste Reynal wrote:
>> > From: Antonios Motakis 
>> >
>> > Now we have finally completely decoupled virqfd from VFIO_PCI. We can
>> > initialize it from the VFIO generic code, in order to safely use it from
>> > multiple independent VFIO bus drivers.
>> >
>> > Signed-off-by: Antonios Motakis 
>> > Signed-off-by: Baptiste Reynal 
>> > ---
>> >  drivers/vfio/Makefile   | 4 +++-
>> >  drivers/vfio/pci/Makefile   | 3 +--
>> >  drivers/vfio/pci/vfio_pci.c | 8 
>> >  drivers/vfio/vfio.c | 8 
>> >  4 files changed, 12 insertions(+), 11 deletions(-)
>> >
>> > diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
>> > index dadf0ca..d798b09 100644
>> > --- a/drivers/vfio/Makefile
>> > +++ b/drivers/vfio/Makefile
>> > @@ -1,4 +1,6 @@
>> > -obj-$(CONFIG_VFIO) += vfio.o
>> > +vfio_core-y := vfio.o virqfd.o
>> > +
>> > +obj-$(CONFIG_VFIO) += vfio_core.o
>> >  obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
>> >  obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
>> >  obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
>>
>> This inadvertently (I assume) renames the main vfio module to vfio_core.
>> That potentially breaks numerous userspace scripts that might try to
>> load the "vfio" module.  I don't think that's acceptable.  A brute force
>> way to fix this would be to rename vfio.c to vfio_core.c and change the
>> Makefile to:
>>
>> vfio-y := vfio_core.o virqfd.o
>> obj-$(CONFIG_VFIO) += vfio.o
>>
>> Is there any other trickery available to us that could include virqfd.o
>> in vfio.o w/o source file renaming?  Thanks,
>
> Maybe a better option, we could let virqfd be it's own support module
> for bus drivers that need it.  Then we keep it out of vfio "core".
> Something like this:
>
> commit f4d91ec4b72ce11e9dba861d6bf2dba93b72f0ba
> Author: Alex Williamson 
> Date:   Tue Mar 17 08:33:38 2015 -0600
>
> vfio: Split virqfd into a separate module for vfio bus drivers
>
> An unintended consequence of splittng virqfd support to be shared
> by bus drivers is renaming the core vfio module to vfio_core.  This
> is not very friendly to user scripts that may try to load the vfio
> module.  To resolve that and to make it clear that virqfd is a bus
> driver service and not a dependency of vfio core, move this to a
> separate module on which the bus drivers will depend.
>
> Signed-off-by: Alex Williamson 
>
> diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
> index d5322a4..7d092dd 100644
> --- a/drivers/vfio/Kconfig
> +++ b/drivers/vfio/Kconfig
> @@ -13,6 +13,11 @@ config VFIO_SPAPR_EEH
> depends on EEH && VFIO_IOMMU_SPAPR_TCE
> default n
>
> +config VFIO_VIRQFD
> +   tristate
> +   depends on VFIO && EVENTFD
> +   default n
> +
>  menuconfig VFIO
> tristate "VFIO Non-Privileged userspace driver framework"
> depends on IOMMU_API
> diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
> index d798b09..7b8a31f 100644
> --- a/drivers/vfio/Makefile
> +++ b/drivers/vfio/Makefile
> @@ -1,6 +1,7 @@
> -vfio_core-y := vfio.o virqfd.o
> +vfio_virqfd-y := virqfd.o
>
> -obj-$(CONFIG_VFIO) += vfio_core.o
> +obj-$(CONFIG_VFIO) += vfio.o
> +obj-$(CONFIG_VFIO_VIRQFD) += vfio_virqfd.o
>  obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
>  obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
>  obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
> diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig
> index c6bb5da..579d83b 100644
> --- a/drivers/vfio/pci/Kconfig
> +++ b/drivers/vfio/pci/Kconfig
> @@ -1,6 +1,7 @@
>  config VFIO_PCI
> tristate "VFIO support for PCI devices"
> depends on VFIO && PCI && EVENTFD
> +   select VFIO_VIRQFD
> help
>   Support for the PCI VFIO bus driver.  This is required to make
>   use of PCI drivers using the VFIO framework.
> diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
> index c0a3bff..4ec14af 100644
> --- a/drivers/vfio/platform/Kconfig
> +++ b/drivers/vfio/platform/Kconfig
> 

Re: [PATCH v14 00/20] VFIO support for platform devices

2015-03-11 Thread Baptiste Reynal
Ok, from what I've seen :

> - nit: interrupt.h not needed at early stage in vfio_platform_private.h,
> until irq introduction
This cannot be fixed by a follow-on patch as it is just the order in
the patch series.
> - version of the driver: 0.10?
Let's just keep it like that, moreover I didn't add any functionnality
since v10.

Which leaves only the wait.h in vfio_pci_intrs.c as an issue. Do we
really need a patch only to remove an include ? (And it seems that
this is already included by eventfd.h, so we don't need to move it to
vfio.h).

Finally everything seems ready for upstream, thanks everyone.

Best regards,
Baptiste

On Wed, Mar 11, 2015 at 4:52 PM, Eric Auger  wrote:
> On 03/11/2015 11:08 AM, Baptiste Reynal wrote:
>> Thanks Eric and Alex for your reviews.
>>
>> I can confirm we can drop the dependency, as I re-tested without it.
>> Do you need a fix for the headers issue underlined by Eric ?
>
> Hi Baptiste,
>
> As far as I am concerned I do not have such request ;-)
>
> Best Regards
>
> Eric
>>
>> Best regards,
>> Baptiste
>>
>> On Wed, Mar 11, 2015 at 9:40 AM, Eric Auger  wrote:
>>> On 03/10/2015 07:04 PM, Alex Williamson wrote:
>>>> On Tue, 2015-03-10 at 18:42 +0100, Eric Auger wrote:
>>>>> Hi Baptiste,
>>>>>
>>>>> Please add:
>>>>> Reviewed-by: Eric Auger  on the whole series
>>>>> Tested-by: Eric Auger  on the whole series except
>>>>> AMBA specific patches.
>>>>>
>>>>> I currently exercise the following functionalities on Calxeda Midway HW:
>>>>> - MMIO read/write/mmap,
>>>>> - automasked IRQ + mask/unmask (NONE flag),
>>>>> - virqfd (unmask handler only).
>>>>>
>>>>> Despite a new thorough review I failed in pointing out any new
>>>>> interesting issues in this series.
>>>>>
>>>>> just minor points below:
>>>>>
>>>>> - PIO regions: currently read/write/mmap is not supported. I can't
>>>>> figure out how much this is a problem at this point?
>>>>
>>>> AIUI, nobody has any way to test this, which is why it's not
>>>> implemented.  I think we've done due diligence in accommodating PIO into
>>>> the vfio-platform framework though and hopefully it will be a simple
>>>> matter to add when someone has a use case for it.
>>>>
>>>>> - nit: vfio_pci_intrs.c: may not need wait.h anymore after removal of
>>>>> virqfd code. may be added in vfio.h
>>>>> - nit: interrupt.h not needed at early stage in vfio_platform_private.h,
>>>>> until irq introduction
>>>>> - version of the driver: 0.10?
>>>>
>>>> None of these seem like blockers, I'd be willing to accept header
>>>> cleanups as follow-on and driver versions are mostly arbitrary anyway.
>>>>
>>>>> Since there is no real dependency on "[PATCH v4 0/6] vfio: type1:
>>>>> support for ARM SMMUS with VFIO_IOMMU_TYPE1" I hope we can get this
>>>>> upstreamed soon.
>>>>
>>>> Me too, I also re-reviewed the series yesterday.  If Baptiste agrees
>>>> that there's no dependency on the other series, I can add your R-b/T-b,
>>>> do some additional testing, and queue the series for linux-next.
>>>> Thanks,
>>>
>>> Hi Alex,
>>>
>>> I let Baptiste answer. If he agrees please do as proposed. I am looking
>>> forward to seeing the series in linux-next!
>>>
>>> Best Regards
>>>
>>> Eric
>>>>
>>>> Alex
>>>>
>>>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v14 00/20] VFIO support for platform devices

2015-03-11 Thread Baptiste Reynal
Thanks Eric and Alex for your reviews.

I can confirm we can drop the dependency, as I re-tested without it.
Do you need a fix for the headers issue underlined by Eric ?

Best regards,
Baptiste

On Wed, Mar 11, 2015 at 9:40 AM, Eric Auger  wrote:
> On 03/10/2015 07:04 PM, Alex Williamson wrote:
>> On Tue, 2015-03-10 at 18:42 +0100, Eric Auger wrote:
>>> Hi Baptiste,
>>>
>>> Please add:
>>> Reviewed-by: Eric Auger  on the whole series
>>> Tested-by: Eric Auger  on the whole series except
>>> AMBA specific patches.
>>>
>>> I currently exercise the following functionalities on Calxeda Midway HW:
>>> - MMIO read/write/mmap,
>>> - automasked IRQ + mask/unmask (NONE flag),
>>> - virqfd (unmask handler only).
>>>
>>> Despite a new thorough review I failed in pointing out any new
>>> interesting issues in this series.
>>>
>>> just minor points below:
>>>
>>> - PIO regions: currently read/write/mmap is not supported. I can't
>>> figure out how much this is a problem at this point?
>>
>> AIUI, nobody has any way to test this, which is why it's not
>> implemented.  I think we've done due diligence in accommodating PIO into
>> the vfio-platform framework though and hopefully it will be a simple
>> matter to add when someone has a use case for it.
>>
>>> - nit: vfio_pci_intrs.c: may not need wait.h anymore after removal of
>>> virqfd code. may be added in vfio.h
>>> - nit: interrupt.h not needed at early stage in vfio_platform_private.h,
>>> until irq introduction
>>> - version of the driver: 0.10?
>>
>> None of these seem like blockers, I'd be willing to accept header
>> cleanups as follow-on and driver versions are mostly arbitrary anyway.
>>
>>> Since there is no real dependency on "[PATCH v4 0/6] vfio: type1:
>>> support for ARM SMMUS with VFIO_IOMMU_TYPE1" I hope we can get this
>>> upstreamed soon.
>>
>> Me too, I also re-reviewed the series yesterday.  If Baptiste agrees
>> that there's no dependency on the other series, I can add your R-b/T-b,
>> do some additional testing, and queue the series for linux-next.
>> Thanks,
>
> Hi Alex,
>
> I let Baptiste answer. If he agrees please do as proposed. I am looking
> forward to seeing the series in linux-next!
>
> Best Regards
>
> Eric
>>
>> Alex
>>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 0/4] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-06 Thread Baptiste Reynal
Good news Eric !

Here are more information about the NOEXEC flag. This flag is used to
set the XN flag on the PTE, which make the page non-executable (XN is
set if NOEXEC is set).

As it used to be an EXEC flag (XN was set by default, unset if EXEC
was set), this patch serie was mandatory for PL330 test, since it
executes some code from memory. Now that it has been reversed to
NOEXEC (XN is not set by default), every page is executable, so it
works but there may be a security issue.

I think it is better to have it if it is working, but for
simplification we can add it later (as the requirement dropped when
the flag has been reversed).

Best regards,
Baptiste


On Fri, Mar 6, 2015 at 2:17 PM, Eric Auger  wrote:
> On 03/06/2015 12:27 PM, Baptiste Reynal wrote:
>> Hi everyone,
>>
>> Indeed, the NOEXEC flag is needed for our tests and VFIO should work
>> without it for some other devices (including xgmac). I think it is
>> reasonable to drop this patch serie for now.
>>
>> Still we have the IOMMU_CACHE issue. To answer Will, the SMMU page
>> tables are installed at stage-2. Currently, the dma-coherent flag is
>> not preserved to the guest, that may be the issue (As we don't have it
>> in the host in our case). "[RFC PATCH v3 0/3] vfio: platform: return
>> device properties for a platform device"
>> (http://lists.celinuxforum.org/pipermail/iommu/2014-December/011425.html)
>> may be a solution to figure out if the device is coherent or not.
>
> I confirm the problem is fixed with proper guest device-tree. Sorry for
> the noise and thanks for your support. indeed in the future the above
> series will help in getting the info dynamically.
>
> Best Regards
>
> Eric
>>
>>
>> On Fri, Mar 6, 2015 at 11:41 AM, Will Deacon  wrote:
>>> Hi Eric,
>>>
>>> On Fri, Mar 06, 2015 at 09:04:22AM +, Eric Auger wrote:
>>>> Yes to me "vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1" is
>>>> not a direct dependency of vfio-platform driver although I understand
>>>> Baptiste needs it to test with PL330 device. On my side I can test
>>>> vfio-platform driver without it, assigning the Midway Calxeda xgmac.
>>>
>>> Realistically, I don't expect anybody using device passthrough for
>>> practical applications to be using a PL330. Your xgmac example is far
>>> more compelling.
>>>
>>>> Also if I am not wrong the title of the series now does not really
>>>> reflect anymore what the series aims at. since "[PATCH v3 2/6] vfio:
>>>> type1: support for ARM SMMUs"  withdrawal, the series now "only" aims at
>>>> supporting the VFIO_DMA_MAP_FLAG_NOEXEC flag.
>>>>
>>>> However with this issue of IOMMU_CACHE always set along with arm-smmu,
>>>> there is a need for an adaptation of either vfio_iommu_type1 or arm-smmu
>>>> since the integrated pieces are not functional.
>>>
>>> Well, I'm still trying to understand exactly what is happening in your case:
>>>
>>>   - Is the xgmac coherent or not? Does it have a "dma-coherent" property?
>>>   - Are you installing the SMMU page tables at stage-1 or stage-2?
>>>   - If it *is* coherent, then we should use IOMMU_CACHE mappings for the
>>> DMA buffers and ensure that the guest knows it is coherent (by
>>> preserving the "dma-coherent" flag).
>>>   - If it is *not* coherent, then the behaviour of IOMMU_CACHE depends
>>> on the stage of translation:
>>>
>>> * Stage-1: we will make the transactions cacheable, and you'll need
>>>   to tell the guest that the device is actually cache coherent
>>> * Stage-2: IOMMU_CACHE won't actually have any effect, so everything
>>>   should work as non-coherent.
>>>
>>> In other words, I think you're probably just telling the guest the wrong
>>> thing.
>>>
>>>> On top of the dma-coherent property of the *master*, should not we also
>>>> query the cache-coherent property of the interconnect downstream to the
>>>> smmu?
>>>
>>> I don't think so... "dma-coherent" should only be set on a master if the
>>> interconnect is properly configured. It's supposed to be a "If you DMA now,
>>> it will snoop the CPU caches" flag as opposed to "If you write a random
>>> selection of MMIO registers in the SoC, then this device will be coherent".
>>>
>>>> How can we progress quickly on this topic? is it acceptable to return

Re: [PATCH v5 0/4] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-06 Thread Baptiste Reynal
Hi everyone,

Indeed, the NOEXEC flag is needed for our tests and VFIO should work
without it for some other devices (including xgmac). I think it is
reasonable to drop this patch serie for now.

Still we have the IOMMU_CACHE issue. To answer Will, the SMMU page
tables are installed at stage-2. Currently, the dma-coherent flag is
not preserved to the guest, that may be the issue (As we don't have it
in the host in our case). "[RFC PATCH v3 0/3] vfio: platform: return
device properties for a platform device"
(http://lists.celinuxforum.org/pipermail/iommu/2014-December/011425.html)
may be a solution to figure out if the device is coherent or not.


On Fri, Mar 6, 2015 at 11:41 AM, Will Deacon  wrote:
> Hi Eric,
>
> On Fri, Mar 06, 2015 at 09:04:22AM +, Eric Auger wrote:
>> Yes to me "vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1" is
>> not a direct dependency of vfio-platform driver although I understand
>> Baptiste needs it to test with PL330 device. On my side I can test
>> vfio-platform driver without it, assigning the Midway Calxeda xgmac.
>
> Realistically, I don't expect anybody using device passthrough for
> practical applications to be using a PL330. Your xgmac example is far
> more compelling.
>
>> Also if I am not wrong the title of the series now does not really
>> reflect anymore what the series aims at. since "[PATCH v3 2/6] vfio:
>> type1: support for ARM SMMUs"  withdrawal, the series now "only" aims at
>> supporting the VFIO_DMA_MAP_FLAG_NOEXEC flag.
>>
>> However with this issue of IOMMU_CACHE always set along with arm-smmu,
>> there is a need for an adaptation of either vfio_iommu_type1 or arm-smmu
>> since the integrated pieces are not functional.
>
> Well, I'm still trying to understand exactly what is happening in your case:
>
>   - Is the xgmac coherent or not? Does it have a "dma-coherent" property?
>   - Are you installing the SMMU page tables at stage-1 or stage-2?
>   - If it *is* coherent, then we should use IOMMU_CACHE mappings for the
> DMA buffers and ensure that the guest knows it is coherent (by
> preserving the "dma-coherent" flag).
>   - If it is *not* coherent, then the behaviour of IOMMU_CACHE depends
> on the stage of translation:
>
> * Stage-1: we will make the transactions cacheable, and you'll need
>   to tell the guest that the device is actually cache coherent
> * Stage-2: IOMMU_CACHE won't actually have any effect, so everything
>   should work as non-coherent.
>
> In other words, I think you're probably just telling the guest the wrong
> thing.
>
>> On top of the dma-coherent property of the *master*, should not we also
>> query the cache-coherent property of the interconnect downstream to the
>> smmu?
>
> I don't think so... "dma-coherent" should only be set on a master if the
> interconnect is properly configured. It's supposed to be a "If you DMA now,
> it will snoop the CPU caches" flag as opposed to "If you write a random
> selection of MMIO registers in the SoC, then this device will be coherent".
>
>> How can we progress quickly on this topic? is it acceptable to return
>> false on arm_smmu_capable(IOMMU_CAP_CACHE_COHERENCY) as a quick hack?
>
> No; pretending that a device is not coherent when it actually is can lead
> to corruption of DMA buffers due to unnecessary cache invalidation.
>
>> As a longer term solution, would it make sense to add a user flag at VFIO
>> user API level to turn the IOMMU_CACHE on?
>
> I think userspace certainly needs a way to figure out if a device is
> coherent or not, otherwise it can't generate the correct device-tree
> properties for something like a KVM guest but the IOMMU_* setting should
> remain in the kernel IMO. Similarly for things like MSI pages, which would
> need to be mapped as device memory on ARM -- that should be exposed as a
> higher level "please map my MSI page here" ioctl as opposed to requiring
> userspace to supply the correct memory attributes.
>
> Will
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v5 0/4] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-05 Thread Baptiste Reynal
On Wed, Mar 4, 2015 at 6:45 PM, Alex Williamson
 wrote:
> On Wed, 2015-03-04 at 17:07 +0100, Baptiste Reynal wrote:
>> This patch series makes the VFIO_IOMMU_TYPE1 driver buildable on ARM, so it
>> may be used with ARM SMMUs. It also adds support for the IOMMU_NOEXEC flag
>> supported by SMMUs adhering to the ARM SMMU specification so the VFIO user 
>> can
>> specify whether the target memory can be executed by the device behind the
>> SMMU.
>
> Ok, so the differences between IOMMU_CACHE and IOMMU_NOEXEC are twofold.
> First is that when the IOMMU is IOMMU_CAP_CACHE_COHERENCY we always use
> IOMMU_CACHE for all mappings within the domain.  This is not a user
> provided mapping flag.  Second, if a device is added behind an IOMMU
> that is not IOMMU_CAP_CACHE_COHERENCY capable, this simply means that it
> needs to be managed as a separate domain within the same container.
> vfio_domains_have_iommu_cache() reports true only if all domains within
> the container support, and are therefore using, IOMMU_CACHE.
>
> On the other hand, IOMMU_NOEXEC is a feature, but not a global mapping
> flag for a domain.  There are potentially some mappings with it within a
> domain and some without, just like the IOMMU_READ/IOMMU_WRITE.  It's
> therefore a per-DMA mapping flag as you've implemented in patch 4.
> Second, as a user specified flag, support for it is mandatory.  If a
> device is added behind an IOMMU that does not support NOEXEC and NOEXEC
> mappings are in use, the device must be rejected from addition to the
> container.

Thanks for taking time to explain. That is also my understanding on those flags.

>
> Hopefully that's correct, because I think that's what the code does.
> The problem I have with the code is that I don't think it's acceptable
> to call iommu_ops.capable() directly.  This is breaking an abstraction
> of the IOMMU API.  The obvious problem with that is:
>
> bool iommu_capable(struct bus_type *bus, enum iommu_cap cap)
>
> I assume you're calling the op directly because of bus_type, but that's
> no excuse to misuse the API.  Our choice is either to try to extend the
> API, maybe create:
>
> bool iommu_domain_capable(struct iommu_domain *domain, enum iommu_cap cap)
>
> Or to use the available function by either caching the value when we do
> have a bus_type available to us, or storing or discovering bus_type.  It
> doesn't seem that terrible to cache it on the domain.  Be careful though
> that if a device imposing lack of NOEXEC on a domain is removed, the
> ability to do NOEXEC mappings should be reinstated.  That would be easy
> if we use separate vfio_domains to manage NOEXEC capable vs NOEXEC
> in-capable devices (like we do CACHE vs no-CACHE), but there's some
> additional overhead to do that since it implies a separate iommu_domain.
> Thanks,
>
> Alex
>

I understand the issue on the API here. I will go for extending the
iommu API with iommu_domain_capable, except if you have any reason to
push for the second solution.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v4 0/5] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-04 Thread Baptiste Reynal
Actually the mapping flags are still cached on the domain, except for
IOMMU_NOEXEC (As it is used at user request).
I don't think the abstraction is ignored, since every abstraction
should implement capable.

The problem here is that IOMMU_NOEXEC can not be cached, but
IOMMU_CAP_NOEXEC has to be. Another solution could be a boolean in
vfio_domain ?

Thanks,
Baptiste

On Wed, Mar 4, 2015 at 5:10 PM, Alex Williamson
 wrote:
> On Wed, 2015-03-04 at 16:21 +0100, Baptiste Reynal wrote:
>> Thanks for your comments. A v5 is ongoing, with the removal of
>> domain->caps, instead domain->domain->ops->capable(cap) is tested.
>
> Doesn't that defeat the whole purpose of caching a subset of the mapping
> flags on the domain?  I also hope we're not ignoring the abstraction of
> the iommu api by following iommu_ops pointers directly.  Thanks,
>
> Alex
>
>> On Tue, Mar 3, 2015 at 7:01 PM, Alex Williamson 
>> wrote:
>>
>> > On Tue, 2015-03-03 at 18:46 +0100, Eric Auger wrote:
>> > > Hi Baptiste,
>> > >
>> > > In "vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag" you still
>> > > kept domain->caps |= IOMMU_CAP_NOEXEC so potentially overwriting 1<<
>> > > IOMMU_CAP_CACHE_COHERENCY I guess.
>> > >
>> > > Sorry I do not have this 4th patch file in my mailbox.
>> > >
>> > > Best Regards
>> > >
>> > > Eric
>> > >
>> > >   if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
>> > >   domain->caps |= (1 << IOMMU_CAP_CACHE_COHERENCY);
>> > >
>> > >   if (iommu_capable(bus, IOMMU_CAP_NOEXEC))
>> > >   domain->caps |= IOMMU_CAP_NOEXEC;
>> >
>> >
>> > Patch 4/5 has problems too, vfio_domains_have_iommu_cap() is called with
>> > IOMMU_CAP_CACHE_COHERENCY, but nobody is shifting that into a bitmap
>> > before doing the comparison.
>> >
>> > TBH, I don't see the point of creating this artificial bitmap out of the
>> > capabilities.  Why can't we keep everything in the domain of actual
>> > flags passed to iommu_ops functions?  It's just silly to test for cached
>> > capability and re-invent the mapping flags on every mapping call and
>> > it's just as easy to generalize a test using the actual flags as to use
>> > the capabilities, perhaps easier.  Thanks,
>> >
>> > Alex
>> >
>> >
>> >
>> > > On 03/02/2015 05:58 PM, Baptiste Reynal wrote:
>> > > > This patch series makes the VFIO_IOMMU_TYPE1 driver buildable on ARM,
>> > so it
>> > > > may be used with ARM SMMUs. It also adds support for the IOMMU_NOEXEC
>> > flag
>> > > > supported by SMMUs adhering to the ARM SMMU specification so the VFIO
>> > user can
>> > > > specify whether the target memory can be executed by the device behind
>> > the
>> > > > SMMU.
>> > > >
>> > > > Changes from v3:
>> > > >  - Rebased on linux v4.0-rc1
>> > > >  - Use bit shifting for domain->caps
>> > > >  - Baptiste Reynal is the new maintainer of this serie
>> > > > Changes from v2:
>> > > >  - Rebased on latest iommu/next branch by Joerg Roedel
>> > > > Changes from v1:
>> > > >  - Bugfixes and corrected some typos
>> > > >  - Use enum for VFIO IOMMU driver capabilities
>> > > >
>> > > > Antonios Motakis (5):
>> > > >   vfio: implement iommu driver capabilities with an enum
>> > > >   vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag
>> > > >   vfio: type1: replace domain wide protection flags with supported
>> > > > capabilities
>> > > >   vfio: type1: replace vfio_domains_have_iommu_cache with generic
>> > > > function
>> > > >   vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag
>> > > >
>> > > >  drivers/vfio/vfio_iommu_type1.c | 91
>> > +
>> > > >  include/uapi/linux/vfio.h   | 30 --
>> > > >  2 files changed, 81 insertions(+), 40 deletions(-)
>> > > >
>> > >
>> > > ___
>> > > iommu mailing list
>> > > iommu@lists.linux-foundation.org
>> > > https://lists.linuxfoundation.org/mailman/listinfo/iommu
>> >
>> >
>> >
>> >
>
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v5 0/4] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-04 Thread Baptiste Reynal
This patch series makes the VFIO_IOMMU_TYPE1 driver buildable on ARM, so it
may be used with ARM SMMUs. It also adds support for the IOMMU_NOEXEC flag
supported by SMMUs adhering to the ARM SMMU specification so the VFIO user can
specify whether the target memory can be executed by the device behind the
SMMU.

Changes from v4:
 - Remove domain->caps, use iommu capacity flags instead
Changes from v3:
 - Rebased on linux v4.0-rc1
 - Use bit shifting for domain->caps
 - Baptiste Reynal is the new maintainer of this serie
Changes from v2:
 - Rebased on latest iommu/next branch by Joerg Roedel
Changes from v1:
 - Bugfixes and corrected some typos
 - Use enum for VFIO IOMMU driver capabilities

Antonios Motakis (4):
  vfio: implement iommu driver capabilities with an enum
  vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag
  vfio: type1: replace vfio_domains_have_iommu_cache with generic
function
  vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag

 drivers/vfio/vfio_iommu_type1.c | 60 -
 include/uapi/linux/vfio.h   | 30 -
 2 files changed, 58 insertions(+), 32 deletions(-)

-- 
2.3.1

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


[PATCH v5 1/4] vfio: implement iommu driver capabilities with an enum

2015-03-04 Thread Baptiste Reynal
From: Antonios Motakis 

Currently a VFIO driver's IOMMU capabilities are encoded as a series of
numerical defines. Replace this with an enum for future maintainability.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 include/uapi/linux/vfio.h | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 82889c3..5fb3d46 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -19,22 +19,20 @@
 
 /* Kernel & User level defines for VFIO IOCTLs. */
 
-/* Extensions */
-
-#define VFIO_TYPE1_IOMMU   1
-#define VFIO_SPAPR_TCE_IOMMU   2
-#define VFIO_TYPE1v2_IOMMU 3
 /*
- * IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping).  This
- * capability is subject to change as groups are added or removed.
+ * Capabilities exposed by the VFIO IOMMU driver. Some capabilities are subject
+ * to change as groups are added or removed.
  */
-#define VFIO_DMA_CC_IOMMU  4
-
-/* Check if EEH is supported */
-#define VFIO_EEH   5
+enum vfio_iommu_cap {
+   VFIO_TYPE1_IOMMU = 1,
+   VFIO_SPAPR_TCE_IOMMU = 2,
+   VFIO_TYPE1v2_IOMMU = 3,
+   VFIO_DMA_CC_IOMMU = 4,  /* IOMMU enforces DMA cache coherence
+  (ex. PCIe NoSnoop stripping) */
+   VFIO_EEH = 5,   /* Check if EEH is supported */
+   VFIO_TYPE1_NESTING_IOMMU = 6,   /* Two-stage IOMMU, implies v2  */
+};
 
-/* Two-stage IOMMU */
-#define VFIO_TYPE1_NESTING_IOMMU   6   /* Implies v2 */
 
 /*
  * The IOCTL interface is designed for extensibility by embedding the
-- 
2.3.1

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


[PATCH v5 4/4] vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag

2015-03-04 Thread Baptiste Reynal
From: Antonios Motakis 

Some IOMMU drivers, such as the ARM SMMU driver, make available the
IOMMU_NOEXEC flag to set the page tables for a device as XN (execute never).
This affects devices such as the ARM PL330 DMA Controller, which respects
this flag and will refuse to fetch DMA instructions from memory where the
XN flag has been set.

The flag can be used only if all IOMMU domains behind the container support
the IOMMU_NOEXEC flag. Also, if any mappings are created with the flag, any
new domains with devices will have to support it as well.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/vfio_iommu_type1.c | 23 ++-
 1 file changed, 22 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index a5847e8..ec313e5 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -591,6 +591,12 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
if (!prot || !size || (size | iova | vaddr) & mask)
return -EINVAL;
 
+   if (map->flags & VFIO_DMA_MAP_FLAG_NOEXEC) {
+   if (!vfio_domains_have_iommu_cap(iommu, IOMMU_CAP_NOEXEC))
+   return -EINVAL;
+   prot |= IOMMU_NOEXEC;
+   }
+
/* Don't allow IOVA or virtual address wrap */
if (iova + size - 1 < iova || vaddr + size - 1 < vaddr)
return -EINVAL;
@@ -672,11 +678,20 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
 
for (; n; n = rb_next(n)) {
struct vfio_dma *dma;
+   const struct iommu_ops *ops = domain->domain->ops;
dma_addr_t iova;
 
dma = rb_entry(n, struct vfio_dma, node);
iova = dma->iova;
 
+   /*
+* if any of the mappings to be replayed has the NOEXEC flag
+* set, then the new iommu domain must support it
+*/
+   if ((dma->prot & IOMMU_NOEXEC) &&
+   !(ops->capable(IOMMU_CAP_NOEXEC)))
+   return -EINVAL;
+
while (iova < dma->iova + dma->size) {
phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
size_t size;
@@ -969,6 +984,11 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
return 0;
return vfio_domains_have_iommu_cap(iommu,
  IOMMU_CAP_CACHE_COHERENCY);
+   case VFIO_DMA_NOEXEC_IOMMU:
+   if (!iommu)
+   return 0;
+   return vfio_domains_have_iommu_cap(iommu,
+  IOMMU_CAP_NOEXEC);
default:
return 0;
}
@@ -992,7 +1012,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
} else if (cmd == VFIO_IOMMU_MAP_DMA) {
struct vfio_iommu_type1_dma_map map;
uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
-   VFIO_DMA_MAP_FLAG_WRITE;
+   VFIO_DMA_MAP_FLAG_WRITE |
+   VFIO_DMA_MAP_FLAG_NOEXEC;
 
minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
 
-- 
2.3.1

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


[PATCH v5 2/4] vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag

2015-03-04 Thread Baptiste Reynal
From: Antonios Motakis 

We introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag to the VFIO dma map call,
and expose its availability via the capability VFIO_DMA_NOEXEC_IOMMU.
This way the user can control whether the XN flag will be set on the
requested mappings. The IOMMU_NOEXEC flag needs to be available for all
the IOMMUs of the container used.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 include/uapi/linux/vfio.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 5fb3d46..30801a7 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -31,6 +31,7 @@ enum vfio_iommu_cap {
   (ex. PCIe NoSnoop stripping) */
VFIO_EEH = 5,   /* Check if EEH is supported */
VFIO_TYPE1_NESTING_IOMMU = 6,   /* Two-stage IOMMU, implies v2  */
+   VFIO_DMA_NOEXEC_IOMMU = 7,
 };
 
 
@@ -397,12 +398,17 @@ struct vfio_iommu_type1_info {
  *
  * Map process virtual addresses to IO virtual addresses using the
  * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
+ *
+ * To use the VFIO_DMA_MAP_FLAG_NOEXEC flag, the container must support the
+ * VFIO_DMA_NOEXEC_IOMMU capability. If mappings are created using this flag,
+ * any groups subsequently added to the container must support this capability.
  */
 struct vfio_iommu_type1_dma_map {
__u32   argsz;
__u32   flags;
 #define VFIO_DMA_MAP_FLAG_READ (1 << 0)/* readable from device 
*/
 #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)   /* writable from device */
+#define VFIO_DMA_MAP_FLAG_NOEXEC (1 << 2)  /* not executable from device */
__u64   vaddr;  /* Process virtual address */
__u64   iova;   /* IO virtual address */
__u64   size;   /* Size of mapping (bytes) */
-- 
2.3.1

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


[PATCH v5 3/4] vfio: type1: replace vfio_domains_have_iommu_cache with generic function

2015-03-04 Thread Baptiste Reynal
From: Antonios Motakis 

Replace the function vfio_domains_have_iommu_cache() with a more generic
function vfio_domains_have_iommu_cap() which allows to check all domains
of an vfio_iommu structure for a given cached capability.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/vfio_iommu_type1.c | 37 +++--
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 57d8c37..a5847e8 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -82,6 +82,23 @@ struct vfio_group {
struct list_headnext;
 };
 
+static int vfio_domains_have_iommu_cap(struct vfio_iommu *iommu, int cap)
+{
+   struct vfio_domain *domain;
+   int ret = 1;
+
+   mutex_lock(&iommu->lock);
+   list_for_each_entry(domain, &iommu->domain_list, next) {
+   if (!(domain->domain->ops->capable(cap))) {
+   ret = 0;
+   break;
+   }
+   }
+   mutex_unlock(&iommu->lock);
+
+   return ret;
+}
+
 /*
  * This code handles mapping and unmapping of user data buffers
  * into DMA'ble space using the IOMMU
@@ -935,23 +952,6 @@ static void vfio_iommu_type1_release(void *iommu_data)
kfree(iommu);
 }
 
-static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
-{
-   struct vfio_domain *domain;
-   int ret = 1;
-
-   mutex_lock(&iommu->lock);
-   list_for_each_entry(domain, &iommu->domain_list, next) {
-   if (!(domain->prot & IOMMU_CACHE)) {
-   ret = 0;
-   break;
-   }
-   }
-   mutex_unlock(&iommu->lock);
-
-   return ret;
-}
-
 static long vfio_iommu_type1_ioctl(void *iommu_data,
   unsigned int cmd, unsigned long arg)
 {
@@ -967,7 +967,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
case VFIO_DMA_CC_IOMMU:
if (!iommu)
return 0;
-   return vfio_domains_have_iommu_cache(iommu);
+   return vfio_domains_have_iommu_cap(iommu,
+ IOMMU_CAP_CACHE_COHERENCY);
default:
return 0;
}
-- 
2.3.1

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


[PATCH v2 1/1] iommu/arm-smmu: fix ARM_SMMU_FEAT_TRANS_OPS condition

2015-03-04 Thread Baptiste Reynal
This patch is a fix to "iommu/arm-smmu: add support for iova_to_phys
through ATS1PR".
According to ARM documentation, translation registers are optional even
in SMMUv1, so ID0_S1TS needs to be checked to verify their presence.
Also, we check that the domain is a stage-1 domain.

Signed-off-by: Baptiste Reynal 

---
v1 -> v2:
Add domain stage test (Thanks to Will Deacon)

---
 drivers/iommu/arm-smmu.c | 9 ++---
 1 file changed, 6 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index fc13dd5..a3adde6 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1288,10 +1288,13 @@ static phys_addr_t arm_smmu_iova_to_phys(struct 
iommu_domain *domain,
return 0;
 
spin_lock_irqsave(&smmu_domain->pgtbl_lock, flags);
-   if (smmu_domain->smmu->features & ARM_SMMU_FEAT_TRANS_OPS)
+   if (smmu_domain->smmu->features & ARM_SMMU_FEAT_TRANS_OPS &&
+   smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
ret = arm_smmu_iova_to_phys_hard(domain, iova);
-   else
+   } else {
ret = ops->iova_to_phys(ops, iova);
+   }
+
spin_unlock_irqrestore(&smmu_domain->pgtbl_lock, flags);
 
return ret;
@@ -1556,7 +1559,7 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
return -ENODEV;
}
 
-   if (smmu->version == 1 || (!(id & ID0_ATOSNS) && (id & ID0_S1TS))) {
+   if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) {
smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
dev_notice(smmu->dev, "\taddress translation ops\n");
}
-- 
2.3.1

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


Re: [PATCH v4 0/5] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-04 Thread Baptiste Reynal
Thanks for your comments. A v5 is ongoing, with the removal of
domain->caps, instead domain->domain->ops->capable(cap) is tested.

Regards,
Baptiste

On Tue, Mar 3, 2015 at 7:01 PM, Alex Williamson 
wrote:

> On Tue, 2015-03-03 at 18:46 +0100, Eric Auger wrote:
> > Hi Baptiste,
> >
> > In "vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag" you still
> > kept domain->caps |= IOMMU_CAP_NOEXEC so potentially overwriting 1<<
> > IOMMU_CAP_CACHE_COHERENCY I guess.
> >
> > Sorry I do not have this 4th patch file in my mailbox.
> >
> > Best Regards
> >
> > Eric
> >
> >   if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
> >   domain->caps |= (1 << IOMMU_CAP_CACHE_COHERENCY);
> >
> >   if (iommu_capable(bus, IOMMU_CAP_NOEXEC))
> >   domain->caps |= IOMMU_CAP_NOEXEC;
>
>
> Patch 4/5 has problems too, vfio_domains_have_iommu_cap() is called with
> IOMMU_CAP_CACHE_COHERENCY, but nobody is shifting that into a bitmap
> before doing the comparison.
>
> TBH, I don't see the point of creating this artificial bitmap out of the
> capabilities.  Why can't we keep everything in the domain of actual
> flags passed to iommu_ops functions?  It's just silly to test for cached
> capability and re-invent the mapping flags on every mapping call and
> it's just as easy to generalize a test using the actual flags as to use
> the capabilities, perhaps easier.  Thanks,
>
> Alex
>
>
>
> > On 03/02/2015 05:58 PM, Baptiste Reynal wrote:
> > > This patch series makes the VFIO_IOMMU_TYPE1 driver buildable on ARM,
> so it
> > > may be used with ARM SMMUs. It also adds support for the IOMMU_NOEXEC
> flag
> > > supported by SMMUs adhering to the ARM SMMU specification so the VFIO
> user can
> > > specify whether the target memory can be executed by the device behind
> the
> > > SMMU.
> > >
> > > Changes from v3:
> > >  - Rebased on linux v4.0-rc1
> > >  - Use bit shifting for domain->caps
> > >  - Baptiste Reynal is the new maintainer of this serie
> > > Changes from v2:
> > >  - Rebased on latest iommu/next branch by Joerg Roedel
> > > Changes from v1:
> > >  - Bugfixes and corrected some typos
> > >  - Use enum for VFIO IOMMU driver capabilities
> > >
> > > Antonios Motakis (5):
> > >   vfio: implement iommu driver capabilities with an enum
> > >   vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag
> > >   vfio: type1: replace domain wide protection flags with supported
> > > capabilities
> > >   vfio: type1: replace vfio_domains_have_iommu_cache with generic
> > > function
> > >   vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag
> > >
> > >  drivers/vfio/vfio_iommu_type1.c | 91
> +
> > >  include/uapi/linux/vfio.h   | 30 --
> > >  2 files changed, 81 insertions(+), 40 deletions(-)
> > >
> >
> > ___
> > iommu mailing list
> > iommu@lists.linux-foundation.org
> > https://lists.linuxfoundation.org/mailman/listinfo/iommu
>
>
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v14 00/20] VFIO support for platform devices

2015-03-03 Thread Baptiste Reynal
Added Eric Auger for comments.

On Mon, Mar 2, 2015 at 5:59 PM, Baptiste Reynal <
b.rey...@virtualopensystems.com> wrote:

> This patch series aims to implement VFIO support for platform devices that
> reside behind an IOMMU. Examples of such devices are devices behind an ARM
> SMMU, or behind a Samsung Exynos System MMU.
>
> The API used is based on the existing VFIO API that is also used with PCI
> devices. Only devices that include a basic set of IRQs and memory regions
> are
> targeted; devices with complex relationships with other devices on a device
> tree are not taken into account at this stage.
>
> This patch series may be applied on the following series/patches:
>  - [PATCH 1/1] iommu/arm-smmu: fix ARM_SMMU_FEAT_TRANS_OPS condition
>  - [PATCH v4 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1
>
> A copy can be cloned from the branch vfio-platform-v14 at:
> https://github.com/virtualopensystems/linux-kvm-arm.git
>
> This serie has been tested on a DMA PL330 with ARM FastModels.
>
> Changes since v13:
>  - Rebased on linux v4.0-rc1
>  - Re-added support for ARM AMBA devices
>  - Baptiste Reynal is the new maintainer of this serie
> Changes since v12:
>  - Reorder chunks to be bisect-able
> Changes since v11:
>  - Drop support for ARM AMBA devices
>  - vfio_platform_private.h is now self-contained
>  - Fix masked IRQ initialization
> Changes since v10:
>  - Check if interrupt is already masked when setting a new trigger
>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> Changes since v9:
>  - Reworked the splitting of the patches that decouple virqfd from PCI
>  - Some styling issues and typos
>  - Removed superfluous includes
>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
>  - Several other cleanups and fixes
> Changes since v8:
>  - Separate irq handler for edge and level triggered interrupts
>  - Mutex based lock for VFIO fd open/release
>  - Fixed bug where the first region of a platform device wasn't exposed
>  - Read only regions can be MMAPed only read only
>  - Code cleanups
> Changes since v7:
>  - Some initial placeholder functionality for PIO resources
>  - Cleaned up code for IRQ triggering, masking and unmasking
>  - Some functionality has been removed from this series and posted
> separately:
>- VFIO_IOMMU_TYPE1 support for ARM SMMUs
>- IOMMU NOEXEC patches
>- driver_override functionality for AMBA devices
>  - Several fixes
> Changes since v6:
>  - Integrated support for AMBA devices
>  - Numerous cleanups and fixes
> Changes since v5:
>  - Full eventfd support for IRQ masking and unmasking.
>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
>  - Other fixes based on reviewer comments.
> Changes since v4:
>  - Use static offsets for each region in the VFIO device fd
>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>availability via IOMMU_CAP_DMA_EXEC
>  - Rebased on VFIO multi domain support:
>- IOMMU_EXEC is now available if at least one IOMMU in the container
>  supports it
>- Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
>  - Some bug fixes
> Changes since v3:
>  - Use Kim Phillips' driver_probe_device()
> Changes since v2:
>  - Fixed Read/Write and MMAP on device regions
>  - Removed dependency on Device Tree
>  - Interrupts support
>  - Interrupt masking/unmasking
>  - Automask level sensitive interrupts
>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>  - Code clean ups
>
> Antonios Motakis (20):
>   vfio/platform: initial skeleton of VFIO support for platform devices
>   vfio: platform: probe to devices on the platform bus
>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>   vfio: amba: VFIO support for AMBA devices
>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
>   vfio/platform: return info for bound device
>   vfio/platform: return info for device memory mapped IO regions
>   vfio/platform: read and write support for the device fd
>   vfio/platform: support MMAP of MMIO regions
>   vfio/platform: return IRQ info
>   vfio/platform: initial interrupts support code
>   vfio/platform: trigger an interrupt via eventfd
>   vfio/platform: support for level sensitive interrupts
>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
> export
>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>   vfio: pass an opaque pointer on virqfd initialization
>   vfio: move eventfd support code for VFIO_PCI to a separate file
>   vfio: initialize the virqfd workqueue in VFIO generic code
>   v

Re: [PATCH v4 0/5] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-03 Thread Baptiste Reynal
Added Eric Auger for comments.

On Mon, Mar 2, 2015 at 5:58 PM, Baptiste Reynal <
b.rey...@virtualopensystems.com> wrote:

> This patch series makes the VFIO_IOMMU_TYPE1 driver buildable on ARM, so it
> may be used with ARM SMMUs. It also adds support for the IOMMU_NOEXEC flag
> supported by SMMUs adhering to the ARM SMMU specification so the VFIO user
> can
> specify whether the target memory can be executed by the device behind the
> SMMU.
>
> Changes from v3:
>  - Rebased on linux v4.0-rc1
>  - Use bit shifting for domain->caps
>  - Baptiste Reynal is the new maintainer of this serie
> Changes from v2:
>  - Rebased on latest iommu/next branch by Joerg Roedel
> Changes from v1:
>  - Bugfixes and corrected some typos
>  - Use enum for VFIO IOMMU driver capabilities
>
> Antonios Motakis (5):
>   vfio: implement iommu driver capabilities with an enum
>   vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag
>   vfio: type1: replace domain wide protection flags with supported
> capabilities
>   vfio: type1: replace vfio_domains_have_iommu_cache with generic
> function
>   vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag
>
>  drivers/vfio/vfio_iommu_type1.c | 91
> +
>  include/uapi/linux/vfio.h   | 30 --
>  2 files changed, 81 insertions(+), 40 deletions(-)
>
> --
> 2.3.1
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH 1/1] iommu/arm-smmu: fix ARM_SMMU_FEAT_TRANS_OPS condition

2015-03-03 Thread Baptiste Reynal
Good point, I didn't thought about it. I will publish a new version with
your modifications.

Thanks

On Mon, Mar 2, 2015 at 6:24 PM, Will Deacon  wrote:

> On Mon, Mar 02, 2015 at 04:57:22PM +, Baptiste Reynal wrote:
> > This patch is a fix to "iommu/arm-smmu: add support for iova_to_phys
> > through ATS1PR".
> > According to ARM documentation, translation registers are optional even
> > in SMMUv1, so ID0_S1TS needs to be checked to verify their presence.
> >
> > Signed-off-by: Baptiste Reynal 
> > ---
> >  drivers/iommu/arm-smmu.c | 2 +-
> >  1 file changed, 1 insertion(+), 1 deletion(-)
> >
> > diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> > index fc13dd5..d4beca4 100644
> > --- a/drivers/iommu/arm-smmu.c
> > +++ b/drivers/iommu/arm-smmu.c
> > @@ -1556,7 +1556,7 @@ static int arm_smmu_device_cfg_probe(struct
> arm_smmu_device *smmu)
> >   return -ENODEV;
> >   }
> >
> > - if (smmu->version == 1 || (!(id & ID0_ATOSNS) && (id & ID0_S1TS)))
> {
> > + if ((id & ID0_S1TS) && ((smmu->version == 1) || (id &
> ID0_ATOSNS))) {
> >   smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
> >   dev_notice(smmu->dev, "\taddress translation ops\n");
>
> I'm not sure this is a complete fix. Shouldn't we also check that the
> domain
> is a stage-1 domain in arm_smmu_iova_to_phys? (potential fixup below).
>
> Will
>
> --->8
>
> diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
> index fc13dd56953e..107163295cbc 100644
> --- a/drivers/iommu/arm-smmu.c
> +++ b/drivers/iommu/arm-smmu.c
> @@ -1288,12 +1288,15 @@ static phys_addr_t arm_smmu_iova_to_phys(struct
> iommu_domain *domain,
> return 0;
>
> spin_lock_irqsave(&smmu_domain->pgtbl_lock, flags);
> -   if (smmu_domain->smmu->features & ARM_SMMU_FEAT_TRANS_OPS)
> +
> +   if (smmu_domain->smmu->features & ARM_SMMU_FEAT_TRANS_OPS &&
> +   smmu_domain->stage == ARM_SMMU_DOMAIN_S1) {
> ret = arm_smmu_iova_to_phys_hard(domain, iova);
> -   else
> +   } else {
> ret = ops->iova_to_phys(ops, iova);
> -   spin_unlock_irqrestore(&smmu_domain->pgtbl_lock, flags);
> +   }
>
> +   spin_unlock_irqrestore(&smmu_domain->pgtbl_lock, flags);
> return ret;
>  }
>
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v14 11/20] vfio/platform: initial interrupts support code

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

This patch is a skeleton for the VFIO_DEVICE_SET_IRQS IOCTL, around which
most IRQ functionality is implemented in VFIO.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c  | 52 +--
 drivers/vfio/platform/vfio_platform_irq.c | 59 +++
 drivers/vfio/platform/vfio_platform_private.h |  7 
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 908d510..abcff7a 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -205,10 +205,54 @@ static long vfio_platform_ioctl(void *device_data,
 
return copy_to_user((void __user *)arg, &info, minsz);
 
-   } else if (cmd == VFIO_DEVICE_SET_IRQS)
-   return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+   struct vfio_irq_set hdr;
+   u8 *data = NULL;
+   int ret = 0;
+
+   minsz = offsetofend(struct vfio_irq_set, count);
+
+   if (copy_from_user(&hdr, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (hdr.argsz < minsz)
+   return -EINVAL;
+
+   if (hdr.index >= vdev->num_irqs)
+   return -EINVAL;
+
+   if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+ VFIO_IRQ_SET_ACTION_TYPE_MASK))
+   return -EINVAL;
 
-   else if (cmd == VFIO_DEVICE_RESET)
+   if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+   size_t size;
+
+   if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
+   size = sizeof(uint8_t);
+   else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
+   size = sizeof(int32_t);
+   else
+   return -EINVAL;
+
+   if (hdr.argsz - minsz < size)
+   return -EINVAL;
+
+   data = memdup_user((void __user *)(arg + minsz), size);
+   if (IS_ERR(data))
+   return PTR_ERR(data);
+   }
+
+   mutex_lock(&vdev->igate);
+
+   ret = vfio_platform_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
+  hdr.start, hdr.count, data);
+   mutex_unlock(&vdev->igate);
+   kfree(data);
+
+   return ret;
+
+   } else if (cmd == VFIO_DEVICE_RESET)
return -EINVAL;
 
return -ENOTTY;
@@ -458,6 +502,8 @@ int vfio_platform_probe_common(struct vfio_platform_device 
*vdev,
return ret;
}
 
+   mutex_init(&vdev->igate);
+
return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index c6c3ec1..df5c919 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,6 +23,56 @@
 
 #include "vfio_platform_private.h"
 
+static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
+ unsigned index, unsigned start,
+ unsigned count, uint32_t flags,
+ void *data)
+{
+   return -EINVAL;
+}
+
+static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
+   unsigned index, unsigned start,
+   unsigned count, uint32_t flags,
+   void *data)
+{
+   return -EINVAL;
+}
+
+static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+unsigned index, unsigned start,
+unsigned count, uint32_t flags,
+void *data)
+{
+   return -EINVAL;
+}
+
+int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+uint32_t flags, unsigned index, unsigned start,
+unsigned count, void *data)
+{
+   int (*func)(struct vfio_platform_device *vdev, unsigned index,
+   unsigned start, unsigned count, uint32_t flags,
+   void *data) = NULL;
+
+   switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+   case VFIO_IRQ_SET_ACTION_MASK:
+   func = vfio_platform_set_irq_mask;
+   break;
+   case VFIO_IRQ_SET_ACTION_UNMASK:
+   func = vfio_platform_set_irq_unmask;
+ 

[PATCH v14 18/20] vfio: move eventfd support code for VFIO_PCI to a separate file

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

The virqfd functionality that is used by VFIO_PCI to implement interrupt
masking and unmasking via an eventfd, is generic enough and can be reused
by another driver. Move it to a separate file in order to allow the code
to be shared.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/pci/Makefile   |   3 +-
 drivers/vfio/pci/vfio_pci_intrs.c   | 215 
 drivers/vfio/pci/vfio_pci_private.h |   3 -
 drivers/vfio/virqfd.c   | 213 +++
 include/linux/vfio.h|  27 +
 5 files changed, 242 insertions(+), 219 deletions(-)
 create mode 100644 drivers/vfio/virqfd.c

diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 1310792..c7c8644 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,4 +1,5 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
+ ../virqfd.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index 1a16da3..da6616e 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -19,228 +19,13 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
-#include 
 #include 
 
 #include "vfio_pci_private.h"
 
 /*
- * IRQfd - generic
- */
-struct virqfd {
-   void*opaque;
-   struct eventfd_ctx  *eventfd;
-   int (*handler)(void *, void *);
-   void(*thread)(void *, void *);
-   void*data;
-   struct work_struct  inject;
-   wait_queue_twait;
-   poll_table  pt;
-   struct work_struct  shutdown;
-   struct virqfd   **pvirqfd;
-};
-
-static struct workqueue_struct *vfio_irqfd_cleanup_wq;
-DEFINE_SPINLOCK(virqfd_lock);
-
-int __init vfio_virqfd_init(void)
-{
-   vfio_irqfd_cleanup_wq =
-   create_singlethread_workqueue("vfio-irqfd-cleanup");
-   if (!vfio_irqfd_cleanup_wq)
-   return -ENOMEM;
-
-   return 0;
-}
-
-void vfio_virqfd_exit(void)
-{
-   destroy_workqueue(vfio_irqfd_cleanup_wq);
-}
-
-static void virqfd_deactivate(struct virqfd *virqfd)
-{
-   queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
-}
-
-static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void 
*key)
-{
-   struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
-   unsigned long flags = (unsigned long)key;
-
-   if (flags & POLLIN) {
-   /* An event has been signaled, call function */
-   if ((!virqfd->handler ||
-virqfd->handler(virqfd->opaque, virqfd->data)) &&
-   virqfd->thread)
-   schedule_work(&virqfd->inject);
-   }
-
-   if (flags & POLLHUP) {
-   unsigned long flags;
-   spin_lock_irqsave(&virqfd_lock, flags);
-
-   /*
-* The eventfd is closing, if the virqfd has not yet been
-* queued for release, as determined by testing whether the
-* virqfd pointer to it is still valid, queue it now.  As
-* with kvm irqfds, we know we won't race against the virqfd
-* going away because we hold the lock to get here.
-*/
-   if (*(virqfd->pvirqfd) == virqfd) {
-   *(virqfd->pvirqfd) = NULL;
-   virqfd_deactivate(virqfd);
-   }
-
-   spin_unlock_irqrestore(&virqfd_lock, flags);
-   }
-
-   return 0;
-}
-
-static void virqfd_ptable_queue_proc(struct file *file,
-wait_queue_head_t *wqh, poll_table *pt)
-{
-   struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
-   add_wait_queue(wqh, &virqfd->wait);
-}
-
-static void virqfd_shutdown(struct work_struct *work)
-{
-   struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
-   u64 cnt;
-
-   eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
-   flush_work(&virqfd->inject);
-   eventfd_ctx_put(virqfd->eventfd);
-
-   kfree(virqfd);
-}
-
-static void virqfd_inject(struct work_struct *work)
-{
-   struct virqfd *virqfd = container_of(work, struct virqfd, inject);
-   if (virqfd->thread)
-   virqfd->thread(virqfd->opaque, virqfd->data);
-}
-
-int vfio_virqfd_enable(void *opaque,
-  int (*handler)(void *, void *),
-  void (*thread)(void *, void *),
-  void *data, struct virqfd **pvirqfd, int fd)
-{
-   st

[PATCH v14 17/20] vfio: pass an opaque pointer on virqfd initialization

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

VFIO_PCI passes the VFIO device structure *vdev via eventfd to the handler
that implements masking/unmasking of IRQs via an eventfd. We can replace
it in the virqfd infrastructure with an opaque type so we can make use
of the mechanism from other VFIO bus drivers.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/pci/vfio_pci_intrs.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index 7d3c135..1a16da3 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -31,10 +31,10 @@
  * IRQfd - generic
  */
 struct virqfd {
-   struct vfio_pci_device  *vdev;
+   void*opaque;
struct eventfd_ctx  *eventfd;
-   int (*handler)(struct vfio_pci_device *, void *);
-   void(*thread)(struct vfio_pci_device *, void *);
+   int (*handler)(void *, void *);
+   void(*thread)(void *, void *);
void*data;
struct work_struct  inject;
wait_queue_twait;
@@ -74,7 +74,7 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, 
int sync, void *key)
if (flags & POLLIN) {
/* An event has been signaled, call function */
if ((!virqfd->handler ||
-virqfd->handler(virqfd->vdev, virqfd->data)) &&
+virqfd->handler(virqfd->opaque, virqfd->data)) &&
virqfd->thread)
schedule_work(&virqfd->inject);
}
@@ -124,12 +124,12 @@ static void virqfd_inject(struct work_struct *work)
 {
struct virqfd *virqfd = container_of(work, struct virqfd, inject);
if (virqfd->thread)
-   virqfd->thread(virqfd->vdev, virqfd->data);
+   virqfd->thread(virqfd->opaque, virqfd->data);
 }
 
-int vfio_virqfd_enable(struct vfio_pci_device *vdev,
-  int (*handler)(struct vfio_pci_device *, void *),
-  void (*thread)(struct vfio_pci_device *, void *),
+int vfio_virqfd_enable(void *opaque,
+  int (*handler)(void *, void *),
+  void (*thread)(void *, void *),
   void *data, struct virqfd **pvirqfd, int fd)
 {
struct fd irqfd;
@@ -143,7 +143,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
return -ENOMEM;
 
virqfd->pvirqfd = pvirqfd;
-   virqfd->vdev = vdev;
+   virqfd->opaque = opaque;
virqfd->handler = handler;
virqfd->thread = thread;
virqfd->data = data;
@@ -196,7 +196,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 * before we registered and trigger it as if we didn't miss it.
 */
if (events & POLLIN) {
-   if ((!handler || handler(vdev, data)) && thread)
+   if ((!handler || handler(opaque, data)) && thread)
schedule_work(&virqfd->inject);
}
 
@@ -243,8 +243,10 @@ EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 /*
  * INTx
  */
-static void vfio_send_intx_eventfd(struct vfio_pci_device *vdev, void *unused)
+static void vfio_send_intx_eventfd(void *opaque, void *unused)
 {
+   struct vfio_pci_device *vdev = opaque;
+
if (likely(is_intx(vdev) && !vdev->virq_disabled))
eventfd_signal(vdev->ctx[0].trigger, 1);
 }
@@ -287,9 +289,9 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
  * a signal is necessary, which can then be handled via a work queue
  * or directly depending on the caller.
  */
-static int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev,
-   void *unused)
+static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
 {
+   struct vfio_pci_device *vdev = opaque;
struct pci_dev *pdev = vdev->pdev;
unsigned long flags;
int ret = 0;
@@ -641,7 +643,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device 
*vdev,
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
int32_t fd = *(int32_t *)data;
if (fd >= 0)
-   return vfio_virqfd_enable(vdev,
+   return vfio_virqfd_enable((void *) vdev,
  vfio_pci_intx_unmask_handler,
  vfio_send_intx_eventfd, NULL,
  &vdev->ctx[0].unmask, fd);
-- 
2.3.1

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


[PATCH v14 02/20] vfio: platform: probe to devices on the platform bus

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Driver to bind to Linux platform devices, and callbacks to discover their
resources to be used by the main VFIO PLATFORM code.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform.c | 103 ++
 include/uapi/linux/vfio.h |   1 +
 2 files changed, 104 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform.c

diff --git a/drivers/vfio/platform/vfio_platform.c 
b/drivers/vfio/platform/vfio_platform.c
new file mode 100644
index 000..cef645c
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis "
+#define DRIVER_DESC "VFIO for platform devices - User Level meta-driver"
+
+/* probing devices from the linux platform bus */
+
+static struct resource *get_platform_resource(struct vfio_platform_device 
*vdev,
+ int num)
+{
+   struct platform_device *dev = (struct platform_device *) vdev->opaque;
+   int i;
+
+   for (i = 0; i < dev->num_resources; i++) {
+   struct resource *r = &dev->resource[i];
+
+   if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
+   if (!num)
+   return r;
+
+   num--;
+   }
+   }
+   return NULL;
+}
+
+static int get_platform_irq(struct vfio_platform_device *vdev, int i)
+{
+   struct platform_device *pdev = (struct platform_device *) vdev->opaque;
+
+   return platform_get_irq(pdev, i);
+}
+
+static int vfio_platform_probe(struct platform_device *pdev)
+{
+   struct vfio_platform_device *vdev;
+   int ret;
+
+   vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+   if (!vdev)
+   return -ENOMEM;
+
+   vdev->opaque = (void *) pdev;
+   vdev->name = pdev->name;
+   vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
+   vdev->get_resource = get_platform_resource;
+   vdev->get_irq = get_platform_irq;
+
+   ret = vfio_platform_probe_common(vdev, &pdev->dev);
+   if (ret)
+   kfree(vdev);
+
+   return ret;
+}
+
+static int vfio_platform_remove(struct platform_device *pdev)
+{
+   struct vfio_platform_device *vdev;
+
+   vdev = vfio_platform_remove_common(&pdev->dev);
+   if (vdev) {
+   kfree(vdev);
+   return 0;
+   }
+
+   return -EINVAL;
+}
+
+static struct platform_driver vfio_platform_driver = {
+   .probe  = vfio_platform_probe,
+   .remove = vfio_platform_remove,
+   .driver = {
+   .name   = "vfio-platform",
+   .owner  = THIS_MODULE,
+   },
+};
+
+module_platform_driver(vfio_platform_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 30801a7..e33b04b 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -159,6 +159,7 @@ struct vfio_device_info {
__u32   flags;
 #define VFIO_DEVICE_FLAGS_RESET(1 << 0)/* Device supports 
reset */
 #define VFIO_DEVICE_FLAGS_PCI  (1 << 1)/* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)/* vfio-platform device */
__u32   num_regions;/* Max region index + 1 */
__u32   num_irqs;   /* Max IRQ index + 1 */
 };
-- 
2.3.1

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


[PATCH v14 07/20] vfio/platform: return info for device memory mapped IO regions

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

This patch enables the IOCTLs VFIO_DEVICE_GET_REGION_INFO ioctl call,
which allows the user to learn about the available MMIO resources of
a device.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c  | 106 +-
 drivers/vfio/platform/vfio_platform_private.h |  22 ++
 2 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index c2f853a..47f6309 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -23,17 +23,97 @@
 
 #include "vfio_platform_private.h"
 
+static DEFINE_MUTEX(driver_lock);
+
+static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
+{
+   int cnt = 0, i;
+
+   while (vdev->get_resource(vdev, cnt))
+   cnt++;
+
+   vdev->regions = kcalloc(cnt, sizeof(struct vfio_platform_region),
+   GFP_KERNEL);
+   if (!vdev->regions)
+   return -ENOMEM;
+
+   for (i = 0; i < cnt;  i++) {
+   struct resource *res =
+   vdev->get_resource(vdev, i);
+
+   if (!res)
+   goto err;
+
+   vdev->regions[i].addr = res->start;
+   vdev->regions[i].size = resource_size(res);
+   vdev->regions[i].flags = 0;
+
+   switch (resource_type(res)) {
+   case IORESOURCE_MEM:
+   vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+   break;
+   case IORESOURCE_IO:
+   vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
+   break;
+   default:
+   goto err;
+   }
+   }
+
+   vdev->num_regions = cnt;
+
+   return 0;
+err:
+   kfree(vdev->regions);
+   return -EINVAL;
+}
+
+static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
+{
+   vdev->num_regions = 0;
+   kfree(vdev->regions);
+}
+
 static void vfio_platform_release(void *device_data)
 {
+   struct vfio_platform_device *vdev = device_data;
+
+   mutex_lock(&driver_lock);
+
+   if (!(--vdev->refcnt)) {
+   vfio_platform_regions_cleanup(vdev);
+   }
+
+   mutex_unlock(&driver_lock);
+
module_put(THIS_MODULE);
 }
 
 static int vfio_platform_open(void *device_data)
 {
+   struct vfio_platform_device *vdev = device_data;
+   int ret;
+
if (!try_module_get(THIS_MODULE))
return -ENODEV;
 
+   mutex_lock(&driver_lock);
+
+   if (!vdev->refcnt) {
+   ret = vfio_platform_regions_init(vdev);
+   if (ret)
+   goto err_reg;
+   }
+
+   vdev->refcnt++;
+
+   mutex_unlock(&driver_lock);
return 0;
+
+err_reg:
+   mutex_unlock(&driver_lock);
+   module_put(THIS_MODULE);
+   return ret;
 }
 
 static long vfio_platform_ioctl(void *device_data,
@@ -54,15 +134,33 @@ static long vfio_platform_ioctl(void *device_data,
return -EINVAL;
 
info.flags = vdev->flags;
-   info.num_regions = 0;
+   info.num_regions = vdev->num_regions;
info.num_irqs = 0;
 
return copy_to_user((void __user *)arg, &info, minsz);
 
-   } else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
-   return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+   struct vfio_region_info info;
+
+   minsz = offsetofend(struct vfio_region_info, offset);
+
+   if (copy_from_user(&info, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (info.argsz < minsz)
+   return -EINVAL;
+
+   if (info.index >= vdev->num_regions)
+   return -EINVAL;
+
+   /* map offset to the physical address  */
+   info.offset = VFIO_PLATFORM_INDEX_TO_OFFSET(info.index);
+   info.size = vdev->regions[info.index].size;
+   info.flags = vdev->regions[info.index].flags;
+
+   return copy_to_user((void __user *)arg, &info, minsz);
 
-   else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+   } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
return -EINVAL;
 
else if (cmd == VFIO_DEVICE_SET_IRQS)
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
index c046988..3551f6d 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -18,7 +18,29 @@
 #include 
 #include 
 
+#define VFIO_PLA

[PATCH v14 03/20] vfio: platform: add the VFIO PLATFORM module to Kconfig

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Enable building the VFIO PLATFORM driver that allows to use Linux platform
devices with VFIO.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/Kconfig   | 1 +
 drivers/vfio/Makefile  | 1 +
 drivers/vfio/platform/Kconfig  | 9 +
 drivers/vfio/platform/Makefile | 4 
 4 files changed, 15 insertions(+)
 create mode 100644 drivers/vfio/platform/Kconfig
 create mode 100644 drivers/vfio/platform/Makefile

diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index 14e27ab..d5322a4 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -27,3 +27,4 @@ menuconfig VFIO
  If you don't know what to do here, say N.
 
 source "drivers/vfio/pci/Kconfig"
+source "drivers/vfio/platform/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 0b035b1..dadf0ca 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
 obj-$(CONFIG_VFIO_PCI) += pci/
+obj-$(CONFIG_VFIO_PLATFORM) += platform/
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
new file mode 100644
index 000..c51af17
--- /dev/null
+++ b/drivers/vfio/platform/Kconfig
@@ -0,0 +1,9 @@
+config VFIO_PLATFORM
+   tristate "VFIO support for platform devices"
+   depends on VFIO && EVENTFD && ARM
+   help
+ Support for platform devices with VFIO. This is required to make
+ use of platform devices present on the system using the VFIO
+ framework.
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
new file mode 100644
index 000..279862b
--- /dev/null
+++ b/drivers/vfio/platform/Makefile
@@ -0,0 +1,4 @@
+
+vfio-platform-y := vfio_platform.o vfio_platform_common.o
+
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
-- 
2.3.1

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


[PATCH v14 05/20] vfio: amba: add the VFIO for AMBA devices module to Kconfig

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Enable building the VFIO AMBA driver. VFIO_AMBA depends on VFIO_PLATFORM,
since it is sharing a portion of the code, and it is essentially implemented
as a platform device whose resources are discovered via AMBA specific APIs
in the kernel.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/Kconfig  | 10 ++
 drivers/vfio/platform/Makefile |  4 
 2 files changed, 14 insertions(+)

diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
index c51af17..c0a3bff 100644
--- a/drivers/vfio/platform/Kconfig
+++ b/drivers/vfio/platform/Kconfig
@@ -7,3 +7,13 @@ config VFIO_PLATFORM
  framework.
 
  If you don't know what to do here, say N.
+
+config VFIO_AMBA
+   tristate "VFIO support for AMBA devices"
+   depends on VFIO_PLATFORM && ARM_AMBA
+   help
+ Support for ARM AMBA devices with VFIO. This is required to make
+ use of ARM AMBA devices present on the system using the VFIO
+ framework.
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 279862b..1957170 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -2,3 +2,7 @@
 vfio-platform-y := vfio_platform.o vfio_platform_common.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
+
+vfio-amba-y := vfio_amba.o
+
+obj-$(CONFIG_VFIO_AMBA) += vfio-amba.o
-- 
2.3.1

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


[PATCH v14 20/20] vfio/platform: implement IRQ masking/unmasking via an eventfd

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

With this patch the VFIO user will be able to set an eventfd that can be
used in order to mask and unmask IRQs of platform devices.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_irq.c | 47 ---
 drivers/vfio/platform/vfio_platform_private.h |  2 ++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index e0e6388..88bba57 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -37,6 +37,15 @@ static void vfio_platform_mask(struct vfio_platform_irq 
*irq_ctx)
spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_mask_handler(void *opaque, void *unused)
+{
+   struct vfio_platform_irq *irq_ctx = opaque;
+
+   vfio_platform_mask(irq_ctx);
+
+   return 0;
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
  unsigned index, unsigned start,
  unsigned count, uint32_t flags,
@@ -48,8 +57,18 @@ static int vfio_platform_set_irq_mask(struct 
vfio_platform_device *vdev,
if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
return -EINVAL;
 
-   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-   return -EINVAL; /* not implemented yet */
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+   int32_t fd = *(int32_t *)data;
+
+   if (fd >= 0)
+   return vfio_virqfd_enable((void *) &vdev->irqs[index],
+ vfio_platform_mask_handler,
+ NULL, NULL,
+ &vdev->irqs[index].mask, fd);
+
+   vfio_virqfd_disable(&vdev->irqs[index].mask);
+   return 0;
+   }
 
if (flags & VFIO_IRQ_SET_DATA_NONE) {
vfio_platform_mask(&vdev->irqs[index]);
@@ -78,6 +97,15 @@ static void vfio_platform_unmask(struct vfio_platform_irq 
*irq_ctx)
spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_unmask_handler(void *opaque, void *unused)
+{
+   struct vfio_platform_irq *irq_ctx = opaque;
+
+   vfio_platform_unmask(irq_ctx);
+
+   return 0;
+}
+
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags,
@@ -89,8 +117,19 @@ static int vfio_platform_set_irq_unmask(struct 
vfio_platform_device *vdev,
if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
return -EINVAL;
 
-   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-   return -EINVAL; /* not implemented yet */
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+   int32_t fd = *(int32_t *)data;
+
+   if (fd >= 0)
+   return vfio_virqfd_enable((void *) &vdev->irqs[index],
+ vfio_platform_unmask_handler,
+ NULL, NULL,
+ &vdev->irqs[index].unmask,
+ fd);
+
+   vfio_virqfd_disable(&vdev->irqs[index].unmask);
+   return 0;
+   }
 
if (flags & VFIO_IRQ_SET_DATA_NONE) {
vfio_platform_unmask(&vdev->irqs[index]);
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
index ff2db1d..5d31e04 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -35,6 +35,8 @@ struct vfio_platform_irq {
struct eventfd_ctx  *trigger;
boolmasked;
spinlock_t  lock;
+   struct virqfd   *unmask;
+   struct virqfd   *mask;
 };
 
 struct vfio_platform_region {
-- 
2.3.1

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


[PATCH v14 14/20] vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

We want to reuse virqfd functionality in multiple VFIO drivers; before
moving these functions to core VFIO, add the vfio_ prefix to the
virqfd_enable and virqfd_disable functions, and export them so they can
be used from other modules.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/pci/vfio_pci_intrs.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index f88bfdf..4d38c93 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -126,10 +126,10 @@ static void virqfd_inject(struct work_struct *work)
virqfd->thread(virqfd->vdev, virqfd->data);
 }
 
-static int virqfd_enable(struct vfio_pci_device *vdev,
-int (*handler)(struct vfio_pci_device *, void *),
-void (*thread)(struct vfio_pci_device *, void *),
-void *data, struct virqfd **pvirqfd, int fd)
+int vfio_virqfd_enable(struct vfio_pci_device *vdev,
+  int (*handler)(struct vfio_pci_device *, void *),
+  void (*thread)(struct vfio_pci_device *, void *),
+  void *data, struct virqfd **pvirqfd, int fd)
 {
struct fd irqfd;
struct eventfd_ctx *ctx;
@@ -215,9 +215,9 @@ err_fd:
 
return ret;
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-static void virqfd_disable(struct vfio_pci_device *vdev,
-  struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
 {
unsigned long flags;
 
@@ -237,6 +237,7 @@ static void virqfd_disable(struct vfio_pci_device *vdev,
 */
flush_workqueue(vfio_irqfd_cleanup_wq);
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 
 /*
  * INTx
@@ -440,8 +441,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device 
*vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
vfio_intx_set_signal(vdev, -1);
-   virqfd_disable(vdev, &vdev->ctx[0].unmask);
-   virqfd_disable(vdev, &vdev->ctx[0].mask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
vdev->num_ctx = 0;
kfree(vdev->ctx);
@@ -605,8 +606,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, 
bool msix)
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
for (i = 0; i < vdev->num_ctx; i++) {
-   virqfd_disable(vdev, &vdev->ctx[i].unmask);
-   virqfd_disable(vdev, &vdev->ctx[i].mask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
}
 
if (msix) {
@@ -639,11 +640,12 @@ static int vfio_pci_set_intx_unmask(struct 
vfio_pci_device *vdev,
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
int32_t fd = *(int32_t *)data;
if (fd >= 0)
-   return virqfd_enable(vdev, vfio_pci_intx_unmask_handler,
-vfio_send_intx_eventfd, NULL,
-&vdev->ctx[0].unmask, fd);
+   return vfio_virqfd_enable(vdev,
+ vfio_pci_intx_unmask_handler,
+ vfio_send_intx_eventfd, NULL,
+ &vdev->ctx[0].unmask, fd);
 
-   virqfd_disable(vdev, &vdev->ctx[0].unmask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
}
 
return 0;
-- 
2.3.1

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


[PATCH v14 19/20] vfio: initialize the virqfd workqueue in VFIO generic code

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Now we have finally completely decoupled virqfd from VFIO_PCI. We can
initialize it from the VFIO generic code, in order to safely use it from
multiple independent VFIO bus drivers.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/Makefile   | 4 +++-
 drivers/vfio/pci/Makefile   | 3 +--
 drivers/vfio/pci/vfio_pci.c | 8 
 drivers/vfio/vfio.c | 8 
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index dadf0ca..d798b09 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -1,4 +1,6 @@
-obj-$(CONFIG_VFIO) += vfio.o
+vfio_core-y := vfio.o virqfd.o
+
+obj-$(CONFIG_VFIO) += vfio_core.o
 obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index c7c8644..1310792 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,5 +1,4 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
- ../virqfd.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 668d37c..2f865d07 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1030,7 +1030,6 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
pci_unregister_driver(&vfio_pci_driver);
-   vfio_virqfd_exit();
vfio_pci_uninit_perm_bits();
 }
 
@@ -1043,11 +1042,6 @@ static int __init vfio_pci_init(void)
if (ret)
return ret;
 
-   /* Start the virqfd cleanup handler */
-   ret = vfio_virqfd_init();
-   if (ret)
-   goto out_virqfd;
-
/* Register and scan for devices */
ret = pci_register_driver(&vfio_pci_driver);
if (ret)
@@ -1056,8 +1050,6 @@ static int __init vfio_pci_init(void)
return 0;
 
 out_driver:
-   vfio_virqfd_exit();
-out_virqfd:
vfio_pci_uninit_perm_bits();
return ret;
 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index 4cde855..23ba12a 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1553,6 +1553,11 @@ static int __init vfio_init(void)
if (ret)
goto err_cdev_add;
 
+   /* Start the virqfd cleanup handler used by some VFIO bus drivers */
+   ret = vfio_virqfd_init();
+   if (ret)
+   goto err_virqfd;
+
pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
/*
@@ -1565,6 +1570,8 @@ static int __init vfio_init(void)
 
return 0;
 
+err_virqfd:
+   cdev_del(&vfio.group_cdev);
 err_cdev_add:
unregister_chrdev_region(vfio.group_devt, MINORMASK);
 err_alloc_chrdev:
@@ -1579,6 +1586,7 @@ static void __exit vfio_cleanup(void)
 {
WARN_ON(!list_empty(&vfio.group_list));
 
+   vfio_virqfd_exit();
idr_destroy(&vfio.group_idr);
cdev_del(&vfio.group_cdev);
unregister_chrdev_region(vfio.group_devt, MINORMASK);
-- 
2.3.1

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


[PATCH v14 16/20] vfio: add local lock for virqfd instead of depending on VFIO PCI

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

The Virqfd code needs to keep accesses to any struct *virqfd safe, but
this comes into play only when creating or destroying eventfds, so sharing
the same spinlock with the VFIO bus driver is not necessary.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/pci/vfio_pci_intrs.c | 31 ---
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index d96ffe0..7d3c135 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -44,6 +44,7 @@ struct virqfd {
 };
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+DEFINE_SPINLOCK(virqfd_lock);
 
 int __init vfio_virqfd_init(void)
 {
@@ -80,21 +81,21 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, 
int sync, void *key)
 
if (flags & POLLHUP) {
unsigned long flags;
-   spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
+   spin_lock_irqsave(&virqfd_lock, flags);
 
/*
 * The eventfd is closing, if the virqfd has not yet been
 * queued for release, as determined by testing whether the
-* vdev pointer to it is still valid, queue it now.  As
+* virqfd pointer to it is still valid, queue it now.  As
 * with kvm irqfds, we know we won't race against the virqfd
-* going away because we hold wqh->lock to get here.
+* going away because we hold the lock to get here.
 */
if (*(virqfd->pvirqfd) == virqfd) {
*(virqfd->pvirqfd) = NULL;
virqfd_deactivate(virqfd);
}
 
-   spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
+   spin_unlock_irqrestore(&virqfd_lock, flags);
}
 
return 0;
@@ -170,16 +171,16 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 * we update the pointer to the virqfd under lock to avoid
 * pushing multiple jobs to release the same virqfd.
 */
-   spin_lock_irq(&vdev->irqlock);
+   spin_lock_irq(&virqfd_lock);
 
if (*pvirqfd) {
-   spin_unlock_irq(&vdev->irqlock);
+   spin_unlock_irq(&virqfd_lock);
ret = -EBUSY;
goto err_busy;
}
*pvirqfd = virqfd;
 
-   spin_unlock_irq(&vdev->irqlock);
+   spin_unlock_irq(&virqfd_lock);
 
/*
 * Install our own custom wake-up handling so we are notified via
@@ -217,18 +218,18 @@ err_fd:
 }
 EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
 {
unsigned long flags;
 
-   spin_lock_irqsave(&vdev->irqlock, flags);
+   spin_lock_irqsave(&virqfd_lock, flags);
 
if (*pvirqfd) {
virqfd_deactivate(*pvirqfd);
*pvirqfd = NULL;
}
 
-   spin_unlock_irqrestore(&vdev->irqlock, flags);
+   spin_unlock_irqrestore(&virqfd_lock, flags);
 
/*
 * Block until we know all outstanding shutdown jobs have completed.
@@ -441,8 +442,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device 
*vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
vfio_intx_set_signal(vdev, -1);
-   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
-   vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
+   vfio_virqfd_disable(&vdev->ctx[0].unmask);
+   vfio_virqfd_disable(&vdev->ctx[0].mask);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
vdev->num_ctx = 0;
kfree(vdev->ctx);
@@ -606,8 +607,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, 
bool msix)
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
for (i = 0; i < vdev->num_ctx; i++) {
-   vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
-   vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
+   vfio_virqfd_disable(&vdev->ctx[i].unmask);
+   vfio_virqfd_disable(&vdev->ctx[i].mask);
}
 
if (msix) {
@@ -645,7 +646,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device 
*vdev,
  vfio_send_intx_eventfd, NULL,
  &vdev->ctx[0].unmask, fd);
 
-   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+   vfio_virqfd_disable(&vdev->ctx[0].unmask);
}
 
return 0;
-- 
2.3.1

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


[PATCH v14 15/20] vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

The functions vfio_pci_virqfd_init and vfio_pci_virqfd_exit are not really
PCI specific, since we plan to reuse the virqfd code with more VFIO drivers
in addition to VFIO_PCI.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: Move rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
from "vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export"]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/pci/vfio_pci.c | 6 +++---
 drivers/vfio/pci/vfio_pci_intrs.c   | 4 ++--
 drivers/vfio/pci/vfio_pci_private.h | 4 ++--
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index f8a1863..668d37c 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1030,7 +1030,7 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
pci_unregister_driver(&vfio_pci_driver);
-   vfio_pci_virqfd_exit();
+   vfio_virqfd_exit();
vfio_pci_uninit_perm_bits();
 }
 
@@ -1044,7 +1044,7 @@ static int __init vfio_pci_init(void)
return ret;
 
/* Start the virqfd cleanup handler */
-   ret = vfio_pci_virqfd_init();
+   ret = vfio_virqfd_init();
if (ret)
goto out_virqfd;
 
@@ -1056,7 +1056,7 @@ static int __init vfio_pci_init(void)
return 0;
 
 out_driver:
-   vfio_pci_virqfd_exit();
+   vfio_virqfd_exit();
 out_virqfd:
vfio_pci_uninit_perm_bits();
return ret;
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index 4d38c93..d96ffe0 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -45,7 +45,7 @@ struct virqfd {
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
 
-int __init vfio_pci_virqfd_init(void)
+int __init vfio_virqfd_init(void)
 {
vfio_irqfd_cleanup_wq =
create_singlethread_workqueue("vfio-irqfd-cleanup");
@@ -55,7 +55,7 @@ int __init vfio_pci_virqfd_init(void)
return 0;
 }
 
-void vfio_pci_virqfd_exit(void)
+void vfio_virqfd_exit(void)
 {
destroy_workqueue(vfio_irqfd_cleanup_wq);
 }
diff --git a/drivers/vfio/pci/vfio_pci_private.h 
b/drivers/vfio/pci/vfio_pci_private.h
index c9f9b32..0253965 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -87,8 +87,8 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, 
char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_pci_virqfd_init(void);
-extern void vfio_pci_virqfd_exit(void);
+extern int vfio_virqfd_init(void);
+extern void vfio_virqfd_exit(void);
 
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
-- 
2.3.1

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


[PATCH v14 13/20] vfio/platform: support for level sensitive interrupts

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Level sensitive interrupts are exposed as maskable and automasked
interrupts and are masked and disabled automatically when they fire.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: Move masked interrupt initialization from "vfio/platform:
trigger an interrupt via eventfd"]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_irq.c | 103 +-
 drivers/vfio/platform/vfio_platform_private.h |   2 +
 2 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index 611ec80..e0e6388 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,12 +23,59 @@
 
 #include "vfio_platform_private.h"
 
+static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&irq_ctx->lock, flags);
+
+   if (!irq_ctx->masked) {
+   disable_irq_nosync(irq_ctx->hwirq);
+   irq_ctx->masked = true;
+   }
+
+   spin_unlock_irqrestore(&irq_ctx->lock, flags);
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
  unsigned index, unsigned start,
  unsigned count, uint32_t flags,
  void *data)
 {
-   return -EINVAL;
+   if (start != 0 || count != 1)
+   return -EINVAL;
+
+   if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+   return -EINVAL;
+
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+   return -EINVAL; /* not implemented yet */
+
+   if (flags & VFIO_IRQ_SET_DATA_NONE) {
+   vfio_platform_mask(&vdev->irqs[index]);
+
+   } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+   uint8_t mask = *(uint8_t *)data;
+
+   if (mask)
+   vfio_platform_mask(&vdev->irqs[index]);
+   }
+
+   return 0;
+}
+
+static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&irq_ctx->lock, flags);
+
+   if (irq_ctx->masked) {
+   enable_irq(irq_ctx->hwirq);
+   irq_ctx->masked = false;
+   }
+
+   spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
@@ -36,7 +83,50 @@ static int vfio_platform_set_irq_unmask(struct 
vfio_platform_device *vdev,
unsigned count, uint32_t flags,
void *data)
 {
-   return -EINVAL;
+   if (start != 0 || count != 1)
+   return -EINVAL;
+
+   if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+   return -EINVAL;
+
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+   return -EINVAL; /* not implemented yet */
+
+   if (flags & VFIO_IRQ_SET_DATA_NONE) {
+   vfio_platform_unmask(&vdev->irqs[index]);
+
+   } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+   uint8_t unmask = *(uint8_t *)data;
+
+   if (unmask)
+   vfio_platform_unmask(&vdev->irqs[index]);
+   }
+
+   return 0;
+}
+
+static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+{
+   struct vfio_platform_irq *irq_ctx = dev_id;
+   unsigned long flags;
+   int ret = IRQ_NONE;
+
+   spin_lock_irqsave(&irq_ctx->lock, flags);
+
+   if (!irq_ctx->masked) {
+   ret = IRQ_HANDLED;
+
+   /* automask maskable interrupts */
+   disable_irq_nosync(irq_ctx->hwirq);
+   irq_ctx->masked = true;
+   }
+
+   spin_unlock_irqrestore(&irq_ctx->lock, flags);
+
+   if (ret == IRQ_HANDLED)
+   eventfd_signal(irq_ctx->trigger, 1);
+
+   return ret;
 }
 
 static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
@@ -78,6 +168,7 @@ static int vfio_set_trigger(struct vfio_platform_device 
*vdev, int index,
 
irq->trigger = trigger;
 
+   irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
if (ret) {
kfree(irq->name);
@@ -86,6 +177,9 @@ static int vfio_set_trigger(struct vfio_platform_device 
*vdev, int index,
return ret;
}
 
+   if (!irq->masked)
+   enable_irq(irq->hwirq);
+
return 0;
 }
 
@@ -98,7 +192,7 @@ static int vfio_platform_set_irq_trigger(struct 
vfio_platform_device *vdev,
irq_handler_t handler;
 
if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
-   return -EINVAL; /* 

[PATCH v14 00/20] VFIO support for platform devices

2015-03-02 Thread Baptiste Reynal
This patch series aims to implement VFIO support for platform devices that
reside behind an IOMMU. Examples of such devices are devices behind an ARM
SMMU, or behind a Samsung Exynos System MMU.

The API used is based on the existing VFIO API that is also used with PCI
devices. Only devices that include a basic set of IRQs and memory regions are
targeted; devices with complex relationships with other devices on a device
tree are not taken into account at this stage.

This patch series may be applied on the following series/patches:
 - [PATCH 1/1] iommu/arm-smmu: fix ARM_SMMU_FEAT_TRANS_OPS condition
 - [PATCH v4 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

A copy can be cloned from the branch vfio-platform-v14 at:
https://github.com/virtualopensystems/linux-kvm-arm.git

This serie has been tested on a DMA PL330 with ARM FastModels.

Changes since v13:
 - Rebased on linux v4.0-rc1
 - Re-added support for ARM AMBA devices
 - Baptiste Reynal is the new maintainer of this serie
Changes since v12:
 - Reorder chunks to be bisect-able
Changes since v11:
 - Drop support for ARM AMBA devices
 - vfio_platform_private.h is now self-contained
 - Fix masked IRQ initialization
Changes since v10:
 - Check if interrupt is already masked when setting a new trigger
 - Fixed kasprintf with unchecked return value in VFIO AMBA driver
Changes since v9:
 - Reworked the splitting of the patches that decouple virqfd from PCI
 - Some styling issues and typos
 - Removed superfluous includes
 - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
 - Several other cleanups and fixes
Changes since v8:
 - Separate irq handler for edge and level triggered interrupts
 - Mutex based lock for VFIO fd open/release
 - Fixed bug where the first region of a platform device wasn't exposed
 - Read only regions can be MMAPed only read only
 - Code cleanups
Changes since v7:
 - Some initial placeholder functionality for PIO resources
 - Cleaned up code for IRQ triggering, masking and unmasking
 - Some functionality has been removed from this series and posted separately:
   - VFIO_IOMMU_TYPE1 support for ARM SMMUs
   - IOMMU NOEXEC patches
   - driver_override functionality for AMBA devices
 - Several fixes
Changes since v6:
 - Integrated support for AMBA devices
 - Numerous cleanups and fixes
Changes since v5:
 - Full eventfd support for IRQ masking and unmasking.
 - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
 - Other fixes based on reviewer comments.
Changes since v4:
 - Use static offsets for each region in the VFIO device fd
 - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
   availability via IOMMU_CAP_DMA_EXEC
 - Rebased on VFIO multi domain support:
   - IOMMU_EXEC is now available if at least one IOMMU in the container
 supports it
   - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
 - Some bug fixes
Changes since v3:
 - Use Kim Phillips' driver_probe_device()
Changes since v2:
 - Fixed Read/Write and MMAP on device regions
 - Removed dependency on Device Tree
 - Interrupts support
 - Interrupt masking/unmasking
 - Automask level sensitive interrupts
 - Introduced VFIO_DMA_MAP_FLAG_EXEC
 - Code clean ups

Antonios Motakis (20):
  vfio/platform: initial skeleton of VFIO support for platform devices
  vfio: platform: probe to devices on the platform bus
  vfio: platform: add the VFIO PLATFORM module to Kconfig
  vfio: amba: VFIO support for AMBA devices
  vfio: amba: add the VFIO for AMBA devices module to Kconfig
  vfio/platform: return info for bound device
  vfio/platform: return info for device memory mapped IO regions
  vfio/platform: read and write support for the device fd
  vfio/platform: support MMAP of MMIO regions
  vfio/platform: return IRQ info
  vfio/platform: initial interrupts support code
  vfio/platform: trigger an interrupt via eventfd
  vfio/platform: support for level sensitive interrupts
  vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
export
  vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
  vfio: add local lock for virqfd instead of depending on VFIO PCI
  vfio: pass an opaque pointer on virqfd initialization
  vfio: move eventfd support code for VFIO_PCI to a separate file
  vfio: initialize the virqfd workqueue in VFIO generic code
  vfio/platform: implement IRQ masking/unmasking via an eventfd

 drivers/vfio/Kconfig  |   1 +
 drivers/vfio/Makefile |   5 +-
 drivers/vfio/pci/vfio_pci.c   |   8 -
 drivers/vfio/pci/vfio_pci_intrs.c | 238 +---
 drivers/vfio/pci/vfio_pci_private.h   |   3 -
 drivers/vfio/platform/Kconfig |  19 +
 drivers/vfio/platform/Makefile|   8 +
 drivers/vfio/platform/vfio_amba.c | 115 ++
 drivers/vfio/platform/vfio_platform.c | 103 +
 drivers/vfio/platform/vfio_platform_commo

[PATCH v14 10/20] vfio/platform: return IRQ info

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Return information for the interrupts exposed by the device.
This patch extends VFIO_DEVICE_GET_INFO with the number of IRQs
and enables VFIO_DEVICE_GET_IRQ_INFO.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/Makefile|  2 +-
 drivers/vfio/platform/vfio_platform_common.c  | 31 +---
 drivers/vfio/platform/vfio_platform_irq.c | 51 +++
 drivers/vfio/platform/vfio_platform_private.h | 10 ++
 4 files changed, 89 insertions(+), 5 deletions(-)
 create mode 100644 drivers/vfio/platform/vfio_platform_irq.c

diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 1957170..81de144 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,5 +1,5 @@
 
-vfio-platform-y := vfio_platform.o vfio_platform_common.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
 
diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index d7fe2c7..908d510 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -101,6 +101,7 @@ static void vfio_platform_release(void *device_data)
 
if (!(--vdev->refcnt)) {
vfio_platform_regions_cleanup(vdev);
+   vfio_platform_irq_cleanup(vdev);
}
 
mutex_unlock(&driver_lock);
@@ -122,6 +123,10 @@ static int vfio_platform_open(void *device_data)
ret = vfio_platform_regions_init(vdev);
if (ret)
goto err_reg;
+
+   ret = vfio_platform_irq_init(vdev);
+   if (ret)
+   goto err_irq;
}
 
vdev->refcnt++;
@@ -129,6 +134,8 @@ static int vfio_platform_open(void *device_data)
mutex_unlock(&driver_lock);
return 0;
 
+err_irq:
+   vfio_platform_regions_cleanup(vdev);
 err_reg:
mutex_unlock(&driver_lock);
module_put(THIS_MODULE);
@@ -154,7 +161,7 @@ static long vfio_platform_ioctl(void *device_data,
 
info.flags = vdev->flags;
info.num_regions = vdev->num_regions;
-   info.num_irqs = 0;
+   info.num_irqs = vdev->num_irqs;
 
return copy_to_user((void __user *)arg, &info, minsz);
 
@@ -179,10 +186,26 @@ static long vfio_platform_ioctl(void *device_data,
 
return copy_to_user((void __user *)arg, &info, minsz);
 
-   } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-   return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+   struct vfio_irq_info info;
+
+   minsz = offsetofend(struct vfio_irq_info, count);
+
+   if (copy_from_user(&info, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (info.argsz < minsz)
+   return -EINVAL;
+
+   if (info.index >= vdev->num_irqs)
+   return -EINVAL;
+
+   info.flags = vdev->irqs[info.index].flags;
+   info.count = vdev->irqs[info.index].count;
+
+   return copy_to_user((void __user *)arg, &info, minsz);
 
-   else if (cmd == VFIO_DEVICE_SET_IRQS)
+   } else if (cmd == VFIO_DEVICE_SET_IRQS)
return -EINVAL;
 
else if (cmd == VFIO_DEVICE_RESET)
diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
new file mode 100644
index 000..c6c3ec1
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -0,0 +1,51 @@
+/*
+ * VFIO platform devices interrupt handling
+ *
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+{
+   int cnt = 0, i;
+
+   while (vdev->get_irq(vdev, cnt) >= 0)
+   cnt++;
+
+   vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL);
+   if (!vdev->irqs)
+   return -ENOMEM;
+
+   for (i = 0; i < cnt; i++) {
+   vdev->irqs[i].flags = 0;
+   vdev->irqs[i].count = 1;
+   }
+
+   vdev->num_irqs = cnt;
+
+   return 0;
+}
+
+voi

[PATCH v4 4/5] vfio: type1: replace vfio_domains_have_iommu_cache with generic function

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Replace the function vfio_domains_have_iommu_cache() with a more generic
function vfio_domains_have_iommu_cap() which allows to check all domains
of an vfio_iommu structure for a given cached capability.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/vfio_iommu_type1.c | 37 +++--
 1 file changed, 19 insertions(+), 18 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 998619b..0ea371b 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -82,6 +82,23 @@ struct vfio_group {
struct list_headnext;
 };
 
+static int vfio_domains_have_iommu_cap(struct vfio_iommu *iommu, int cap)
+{
+   struct vfio_domain *domain;
+   int ret = 1;
+
+   mutex_lock(&iommu->lock);
+   list_for_each_entry(domain, &iommu->domain_list, next) {
+   if (!(domain->caps & cap)) {
+   ret = 0;
+   break;
+   }
+   }
+   mutex_unlock(&iommu->lock);
+
+   return ret;
+}
+
 /*
  * This code handles mapping and unmapping of user data buffers
  * into DMA'ble space using the IOMMU
@@ -948,23 +965,6 @@ static void vfio_iommu_type1_release(void *iommu_data)
kfree(iommu);
 }
 
-static int vfio_domains_have_iommu_cache(struct vfio_iommu *iommu)
-{
-   struct vfio_domain *domain;
-   int ret = 1;
-
-   mutex_lock(&iommu->lock);
-   list_for_each_entry(domain, &iommu->domain_list, next) {
-   if (!(domain->caps & IOMMU_CAP_CACHE_COHERENCY)) {
-   ret = 0;
-   break;
-   }
-   }
-   mutex_unlock(&iommu->lock);
-
-   return ret;
-}
-
 static long vfio_iommu_type1_ioctl(void *iommu_data,
   unsigned int cmd, unsigned long arg)
 {
@@ -980,7 +980,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
case VFIO_DMA_CC_IOMMU:
if (!iommu)
return 0;
-   return vfio_domains_have_iommu_cache(iommu);
+   return vfio_domains_have_iommu_cap(iommu,
+ IOMMU_CAP_CACHE_COHERENCY);
default:
return 0;
}
-- 
2.3.1

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


[PATCH v14 12/20] vfio/platform: trigger an interrupt via eventfd

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

This patch allows to set an eventfd for a platform device's interrupt,
and also to trigger the interrupt eventfd from userspace for testing.
Level sensitive interrupts are marked as maskable and are handled in
a later patch. Edge triggered interrupts are not advertised as maskable
and are implemented here using a simple and efficient IRQ handler.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: fix masked interrupt initialization]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_irq.c | 94 ++-
 drivers/vfio/platform/vfio_platform_private.h |  2 +
 2 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index df5c919..611ec80 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -39,12 +39,92 @@ static int vfio_platform_set_irq_unmask(struct 
vfio_platform_device *vdev,
return -EINVAL;
 }
 
+static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
+{
+   struct vfio_platform_irq *irq_ctx = dev_id;
+
+   eventfd_signal(irq_ctx->trigger, 1);
+
+   return IRQ_HANDLED;
+}
+
+static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
+   int fd, irq_handler_t handler)
+{
+   struct vfio_platform_irq *irq = &vdev->irqs[index];
+   struct eventfd_ctx *trigger;
+   int ret;
+
+   if (irq->trigger) {
+   free_irq(irq->hwirq, irq);
+   kfree(irq->name);
+   eventfd_ctx_put(irq->trigger);
+   irq->trigger = NULL;
+   }
+
+   if (fd < 0) /* Disable only */
+   return 0;
+
+   irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
+   irq->hwirq, vdev->name);
+   if (!irq->name)
+   return -ENOMEM;
+
+   trigger = eventfd_ctx_fdget(fd);
+   if (IS_ERR(trigger)) {
+   kfree(irq->name);
+   return PTR_ERR(trigger);
+   }
+
+   irq->trigger = trigger;
+
+   ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
+   if (ret) {
+   kfree(irq->name);
+   eventfd_ctx_put(trigger);
+   irq->trigger = NULL;
+   return ret;
+   }
+
+   return 0;
+}
+
 static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
 unsigned index, unsigned start,
 unsigned count, uint32_t flags,
 void *data)
 {
-   return -EINVAL;
+   struct vfio_platform_irq *irq = &vdev->irqs[index];
+   irq_handler_t handler;
+
+   if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
+   return -EINVAL; /* not implemented */
+   else
+   handler = vfio_irq_handler;
+
+   if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
+   return vfio_set_trigger(vdev, index, -1, handler);
+
+   if (start != 0 || count != 1)
+   return -EINVAL;
+
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+   int32_t fd = *(int32_t *)data;
+
+   return vfio_set_trigger(vdev, index, fd, handler);
+   }
+
+   if (flags & VFIO_IRQ_SET_DATA_NONE) {
+   handler(irq->hwirq, irq);
+
+   } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+   uint8_t trigger = *(uint8_t *)data;
+
+   if (trigger)
+   handler(irq->hwirq, irq);
+   }
+
+   return 0;
 }
 
 int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
@@ -90,7 +170,12 @@ int vfio_platform_irq_init(struct vfio_platform_device 
*vdev)
if (hwirq < 0)
goto err;
 
-   vdev->irqs[i].flags = 0;
+   vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
+
+   if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
+   vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
+   | VFIO_IRQ_INFO_AUTOMASKED;
+
vdev->irqs[i].count = 1;
vdev->irqs[i].hwirq = hwirq;
}
@@ -105,6 +190,11 @@ err:
 
 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
 {
+   int i;
+
+   for (i = 0; i < vdev->num_irqs; i++)
+   vfio_set_trigger(vdev, i, -1, NULL);
+
vdev->num_irqs = 0;
kfree(vdev->irqs);
 }
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
index b119a6c..aa01cc3 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -31,6 +31,8 @@ struc

[PATCH v14 08/20] vfio/platform: read and write support for the device fd

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

VFIO returns a file descriptor which we can use to manipulate the memory
regions of the device. Usually, the user will mmap memory regions that are
addressable on page boundaries, however for memory regions where this is
not the case we cannot provide mmap functionality due to security concerns.
For this reason we also allow to use read and write functions to the file
descriptor pointing to the memory regions.

We implement this functionality only for MMIO regions of platform devices;
PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c  | 150 ++
 drivers/vfio/platform/vfio_platform_private.h |   1 +
 2 files changed, 151 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 47f6309..4df66f5 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -51,6 +51,10 @@ static int vfio_platform_regions_init(struct 
vfio_platform_device *vdev)
switch (resource_type(res)) {
case IORESOURCE_MEM:
vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+   vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+   if (!(res->flags & IORESOURCE_READONLY))
+   vdev->regions[i].flags |=
+   VFIO_REGION_INFO_FLAG_WRITE;
break;
case IORESOURCE_IO:
vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -70,6 +74,11 @@ err:
 
 static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 {
+   int i;
+
+   for (i = 0; i < vdev->num_regions; i++)
+   iounmap(vdev->regions[i].ioaddr);
+
vdev->num_regions = 0;
kfree(vdev->regions);
 }
@@ -172,15 +181,156 @@ static long vfio_platform_ioctl(void *device_data,
return -ENOTTY;
 }
 
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+  char __user *buf, size_t count,
+  loff_t off)
+{
+   unsigned int done = 0;
+
+   if (!reg.ioaddr) {
+   reg.ioaddr =
+   ioremap_nocache(reg.addr, reg.size);
+
+   if (!reg.ioaddr)
+   return -ENOMEM;
+   }
+
+   while (count) {
+   size_t filled;
+
+   if (count >= 4 && !(off % 4)) {
+   u32 val;
+
+   val = ioread32(reg.ioaddr + off);
+   if (copy_to_user(buf, &val, 4))
+   goto err;
+
+   filled = 4;
+   } else if (count >= 2 && !(off % 2)) {
+   u16 val;
+
+   val = ioread16(reg.ioaddr + off);
+   if (copy_to_user(buf, &val, 2))
+   goto err;
+
+   filled = 2;
+   } else {
+   u8 val;
+
+   val = ioread8(reg.ioaddr + off);
+   if (copy_to_user(buf, &val, 1))
+   goto err;
+
+   filled = 1;
+   }
+
+
+   count -= filled;
+   done += filled;
+   off += filled;
+   buf += filled;
+   }
+
+   return done;
+err:
+   return -EFAULT;
+}
+
 static ssize_t vfio_platform_read(void *device_data, char __user *buf,
  size_t count, loff_t *ppos)
 {
+   struct vfio_platform_device *vdev = device_data;
+   unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+   loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+   if (index >= vdev->num_regions)
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ))
+   return -EINVAL;
+
+   if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+   return vfio_platform_read_mmio(vdev->regions[index],
+   buf, count, off);
+   else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+   return -EINVAL; /* not implemented */
+
return -EINVAL;
 }
 
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+   const char __user *buf, size_t count,
+   loff_t off)
+{
+   unsigned int done = 0;
+
+   if (!reg.ioaddr) {
+   reg.ioaddr =
+   ioremap_nocache(reg.addr, reg.size);
+
+   if (!reg.ioad

[PATCH v14 09/20] vfio/platform: support MMAP of MMIO regions

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Allow to memory map the MMIO regions of the device so userspace can
directly access them. PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c | 65 
 1 file changed, 65 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 4df66f5..d7fe2c7 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -55,6 +55,16 @@ static int vfio_platform_regions_init(struct 
vfio_platform_device *vdev)
if (!(res->flags & IORESOURCE_READONLY))
vdev->regions[i].flags |=
VFIO_REGION_INFO_FLAG_WRITE;
+
+   /*
+* Only regions addressed with PAGE granularity may be
+* MMAPed securely.
+*/
+   if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+   !(vdev->regions[i].size & ~PAGE_MASK))
+   vdev->regions[i].flags |=
+   VFIO_REGION_INFO_FLAG_MMAP;
+
break;
case IORESOURCE_IO:
vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -334,8 +344,63 @@ static ssize_t vfio_platform_write(void *device_data, 
const char __user *buf,
return -EINVAL;
 }
 
+static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
+  struct vm_area_struct *vma)
+{
+   u64 req_len, pgoff, req_start;
+
+   req_len = vma->vm_end - vma->vm_start;
+   pgoff = vma->vm_pgoff &
+   ((1U << (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+   req_start = pgoff << PAGE_SHIFT;
+
+   if (region.size < PAGE_SIZE || req_start + req_len > region.size)
+   return -EINVAL;
+
+   vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+   vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+
+   return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+  req_len, vma->vm_page_prot);
+}
+
 static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
 {
+   struct vfio_platform_device *vdev = device_data;
+   unsigned int index;
+
+   index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
+
+   if (vma->vm_end < vma->vm_start)
+   return -EINVAL;
+   if (!(vma->vm_flags & VM_SHARED))
+   return -EINVAL;
+   if (index >= vdev->num_regions)
+   return -EINVAL;
+   if (vma->vm_start & ~PAGE_MASK)
+   return -EINVAL;
+   if (vma->vm_end & ~PAGE_MASK)
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
+   && (vma->vm_flags & VM_READ))
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
+   && (vma->vm_flags & VM_WRITE))
+   return -EINVAL;
+
+   vma->vm_private_data = vdev;
+
+   if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+   return vfio_platform_mmap_mmio(vdev->regions[index], vma);
+
+   else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+   return -EINVAL; /* not implemented */
+
return -EINVAL;
 }
 
-- 
2.3.1

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


[PATCH v4 3/5] vfio: type1: replace domain wide protection flags with supported capabilities

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

VFIO_IOMMU_TYPE1 keeps track for each domain it knows a list of protection
flags it always applies to all mappings in the domain. This is used for
domains that support IOMMU_CAP_CACHE_COHERENCY.

Refactor this slightly, by keeping track instead that a given domain
supports the capability, and applying the IOMMU_CACHE protection flag when
doing the actual DMA mappings.

This will allow us to reuse the behavior for IOMMU_CAP_NOEXEC, which we
also want to keep track of, but without applying it to all domains that
support it unless the user explicitly requests it.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: Use bit shifting for domain->caps]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/vfio_iommu_type1.c | 31 ++-
 1 file changed, 22 insertions(+), 9 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 57d8c37..998619b 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -65,7 +65,7 @@ struct vfio_domain {
struct iommu_domain *domain;
struct list_headnext;
struct list_headgroup_list;
-   int prot;   /* IOMMU_CACHE */
+   int caps;
boolfgsp;   /* Fine-grained super pages */
 };
 
@@ -507,7 +507,7 @@ static int map_try_harder(struct vfio_domain *domain, 
dma_addr_t iova,
for (i = 0; i < npage; i++, pfn++, iova += PAGE_SIZE) {
ret = iommu_map(domain->domain, iova,
(phys_addr_t)pfn << PAGE_SHIFT,
-   PAGE_SIZE, prot | domain->prot);
+   PAGE_SIZE, prot);
if (ret)
break;
}
@@ -525,11 +525,16 @@ static int vfio_iommu_map(struct vfio_iommu *iommu, 
dma_addr_t iova,
int ret;
 
list_for_each_entry(d, &iommu->domain_list, next) {
+   int dprot = prot;
+
+   if (d->caps & (1 << IOMMU_CAP_CACHE_COHERENCY))
+   dprot |= IOMMU_CACHE;
+
ret = iommu_map(d->domain, iova, (phys_addr_t)pfn << PAGE_SHIFT,
-   npage << PAGE_SHIFT, prot | d->prot);
+   npage << PAGE_SHIFT, dprot);
if (ret) {
if (ret != -EBUSY ||
-   map_try_harder(d, iova, pfn, npage, prot))
+   map_try_harder(d, iova, pfn, npage, dprot))
goto unwind;
}
 
@@ -644,6 +649,10 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
struct vfio_domain *d;
struct rb_node *n;
int ret;
+   int dprot = 0;
+
+   if (domain->caps & (1 << IOMMU_CAP_CACHE_COHERENCY))
+   dprot |= IOMMU_CACHE;
 
/* Arbitrarily pick the first domain in the list for lookups */
d = list_first_entry(&iommu->domain_list, struct vfio_domain, next);
@@ -677,7 +686,7 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
size += PAGE_SIZE;
 
ret = iommu_map(domain->domain, iova, phys,
-   size, dma->prot | domain->prot);
+   size, dma->prot | dprot);
if (ret)
return ret;
 
@@ -702,13 +711,17 @@ static void vfio_test_domain_fgsp(struct vfio_domain 
*domain)
 {
struct page *pages;
int ret, order = get_order(PAGE_SIZE * 2);
+   int dprot = 0;
+
+   if (domain->caps & (1 << IOMMU_CAP_CACHE_COHERENCY))
+   dprot |= IOMMU_CACHE;
 
pages = alloc_pages(GFP_KERNEL | __GFP_ZERO, order);
if (!pages)
return;
 
ret = iommu_map(domain->domain, 0, page_to_phys(pages), PAGE_SIZE * 2,
-   IOMMU_READ | IOMMU_WRITE | domain->prot);
+   IOMMU_READ | IOMMU_WRITE | dprot);
if (!ret) {
size_t unmapped = iommu_unmap(domain->domain, 0, PAGE_SIZE);
 
@@ -787,7 +800,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
}
 
if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
-   domain->prot |= IOMMU_CACHE;
+   domain->caps |= (1 << IOMMU_CAP_CACHE_COHERENCY);
 
/*
 * Try to match an existing compatible domain.  We don't want to
@@ -798,7 +811,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
 */
list_for_each_entry(d, &iommu->domain_list, next) {
if (d->domain->ops == domain->domain->ops &&
-   d->prot == domain->prot) {
+   d-&g

[PATCH v4 2/5] vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

We introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag to the VFIO dma map call,
and expose its availability via the capability VFIO_DMA_NOEXEC_IOMMU.
This way the user can control whether the XN flag will be set on the
requested mappings. The IOMMU_NOEXEC flag needs to be available for all
the IOMMUs of the container used.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 include/uapi/linux/vfio.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 5fb3d46..30801a7 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -31,6 +31,7 @@ enum vfio_iommu_cap {
   (ex. PCIe NoSnoop stripping) */
VFIO_EEH = 5,   /* Check if EEH is supported */
VFIO_TYPE1_NESTING_IOMMU = 6,   /* Two-stage IOMMU, implies v2  */
+   VFIO_DMA_NOEXEC_IOMMU = 7,
 };
 
 
@@ -397,12 +398,17 @@ struct vfio_iommu_type1_info {
  *
  * Map process virtual addresses to IO virtual addresses using the
  * provided struct vfio_dma_map. Caller sets argsz. READ &/ WRITE required.
+ *
+ * To use the VFIO_DMA_MAP_FLAG_NOEXEC flag, the container must support the
+ * VFIO_DMA_NOEXEC_IOMMU capability. If mappings are created using this flag,
+ * any groups subsequently added to the container must support this capability.
  */
 struct vfio_iommu_type1_dma_map {
__u32   argsz;
__u32   flags;
 #define VFIO_DMA_MAP_FLAG_READ (1 << 0)/* readable from device 
*/
 #define VFIO_DMA_MAP_FLAG_WRITE (1 << 1)   /* writable from device */
+#define VFIO_DMA_MAP_FLAG_NOEXEC (1 << 2)  /* not executable from device */
__u64   vaddr;  /* Process virtual address */
__u64   iova;   /* IO virtual address */
__u64   size;   /* Size of mapping (bytes) */
-- 
2.3.1

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


[PATCH v4 0/5] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

2015-03-02 Thread Baptiste Reynal
This patch series makes the VFIO_IOMMU_TYPE1 driver buildable on ARM, so it
may be used with ARM SMMUs. It also adds support for the IOMMU_NOEXEC flag
supported by SMMUs adhering to the ARM SMMU specification so the VFIO user can
specify whether the target memory can be executed by the device behind the
SMMU.

Changes from v3:
 - Rebased on linux v4.0-rc1
 - Use bit shifting for domain->caps
 - Baptiste Reynal is the new maintainer of this serie
Changes from v2:
 - Rebased on latest iommu/next branch by Joerg Roedel
Changes from v1:
 - Bugfixes and corrected some typos
 - Use enum for VFIO IOMMU driver capabilities

Antonios Motakis (5):
  vfio: implement iommu driver capabilities with an enum
  vfio: introduce the VFIO_DMA_MAP_FLAG_NOEXEC flag
  vfio: type1: replace domain wide protection flags with supported
capabilities
  vfio: type1: replace vfio_domains_have_iommu_cache with generic
function
  vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag

 drivers/vfio/vfio_iommu_type1.c | 91 +
 include/uapi/linux/vfio.h   | 30 --
 2 files changed, 81 insertions(+), 40 deletions(-)

-- 
2.3.1

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


[PATCH v4 5/5] vfio: type1: implement the VFIO_DMA_MAP_FLAG_NOEXEC flag

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Some IOMMU drivers, such as the ARM SMMU driver, make available the
IOMMU_NOEXEC flag to set the page tables for a device as XN (execute never).
This affects devices such as the ARM PL330 DMA Controller, which respects
this flag and will refuse to fetch DMA instructions from memory where the
XN flag has been set.

The flag can be used only if all IOMMU domains behind the container support
the IOMMU_NOEXEC flag. Also, if any mappings are created with the flag, any
new domains with devices will have to support it as well.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/vfio_iommu_type1.c | 25 -
 1 file changed, 24 insertions(+), 1 deletion(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 0ea371b..2bbd311 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -596,6 +596,12 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
if (!prot || !size || (size | iova | vaddr) & mask)
return -EINVAL;
 
+   if (map->flags & VFIO_DMA_MAP_FLAG_NOEXEC) {
+   if (!vfio_domains_have_iommu_cap(iommu, IOMMU_CAP_NOEXEC))
+   return -EINVAL;
+   prot |= IOMMU_NOEXEC;
+   }
+
/* Don't allow IOVA or virtual address wrap */
if (iova + size - 1 < iova || vaddr + size - 1 < vaddr)
return -EINVAL;
@@ -686,6 +692,14 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
dma = rb_entry(n, struct vfio_dma, node);
iova = dma->iova;
 
+   /*
+* if any of the mappings to be replayed has the NOEXEC flag
+* set, then the new iommu domain must support it
+*/
+   if ((dma->prot & IOMMU_NOEXEC) &&
+   !(domain->caps & IOMMU_CAP_NOEXEC))
+   return -EINVAL;
+
while (iova < dma->iova + dma->size) {
phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
size_t size;
@@ -819,6 +833,9 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
domain->caps |= (1 << IOMMU_CAP_CACHE_COHERENCY);
 
+   if (iommu_capable(bus, IOMMU_CAP_NOEXEC))
+   domain->caps |= IOMMU_CAP_NOEXEC;
+
/*
 * Try to match an existing compatible domain.  We don't want to
 * preclude an IOMMU driver supporting multiple bus_types and being
@@ -982,6 +999,11 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
return 0;
return vfio_domains_have_iommu_cap(iommu,
  IOMMU_CAP_CACHE_COHERENCY);
+   case VFIO_DMA_NOEXEC_IOMMU:
+   if (!iommu)
+   return 0;
+   return vfio_domains_have_iommu_cap(iommu,
+  IOMMU_CAP_NOEXEC);
default:
return 0;
}
@@ -1005,7 +1027,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
} else if (cmd == VFIO_IOMMU_MAP_DMA) {
struct vfio_iommu_type1_dma_map map;
uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
-   VFIO_DMA_MAP_FLAG_WRITE;
+   VFIO_DMA_MAP_FLAG_WRITE |
+   VFIO_DMA_MAP_FLAG_NOEXEC;
 
minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
 
-- 
2.3.1

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


[PATCH v14 04/20] vfio: amba: VFIO support for AMBA devices

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Add support for discovering AMBA devices with VFIO and handle them
similarly to Linux platform devices.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_amba.c | 115 ++
 include/uapi/linux/vfio.h |   1 +
 2 files changed, 116 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_amba.c

diff --git a/drivers/vfio/platform/vfio_amba.c 
b/drivers/vfio/platform/vfio_amba.c
new file mode 100644
index 000..ff0331f
--- /dev/null
+++ b/drivers/vfio/platform/vfio_amba.c
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis "
+#define DRIVER_DESC "VFIO for AMBA devices - User Level meta-driver"
+
+/* probing devices from the AMBA bus */
+
+static struct resource *get_amba_resource(struct vfio_platform_device *vdev,
+ int i)
+{
+   struct amba_device *adev = (struct amba_device *) vdev->opaque;
+
+   if (i == 0)
+   return &adev->res;
+
+   return NULL;
+}
+
+static int get_amba_irq(struct vfio_platform_device *vdev, int i)
+{
+   struct amba_device *adev = (struct amba_device *) vdev->opaque;
+   int ret = 0;
+
+   if (i < AMBA_NR_IRQS)
+   ret = adev->irq[i];
+
+   /* zero is an unset IRQ for AMBA devices */
+   return ret ? ret : -ENXIO;
+}
+
+static int vfio_amba_probe(struct amba_device *adev, const struct amba_id *id)
+{
+   struct vfio_platform_device *vdev;
+   int ret;
+
+   vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+   if (!vdev)
+   return -ENOMEM;
+
+   vdev->name = kasprintf(GFP_KERNEL, "vfio-amba-%08x", adev->periphid);
+   if (!vdev->name) {
+   kfree(vdev);
+   return -ENOMEM;
+   }
+
+   vdev->opaque = (void *) adev;
+   vdev->flags = VFIO_DEVICE_FLAGS_AMBA;
+   vdev->get_resource = get_amba_resource;
+   vdev->get_irq = get_amba_irq;
+
+   ret = vfio_platform_probe_common(vdev, &adev->dev);
+   if (ret) {
+   kfree(vdev->name);
+   kfree(vdev);
+   }
+
+   return ret;
+}
+
+static int vfio_amba_remove(struct amba_device *adev)
+{
+   struct vfio_platform_device *vdev;
+
+   vdev = vfio_platform_remove_common(&adev->dev);
+   if (vdev) {
+   kfree(vdev->name);
+   kfree(vdev);
+   return 0;
+   }
+
+   return -EINVAL;
+}
+
+static struct amba_id pl330_ids[] = {
+   { 0, 0 },
+};
+
+MODULE_DEVICE_TABLE(amba, pl330_ids);
+
+static struct amba_driver vfio_amba_driver = {
+   .probe = vfio_amba_probe,
+   .remove = vfio_amba_remove,
+   .id_table = pl330_ids,
+   .drv = {
+   .name = "vfio-amba",
+   .owner = THIS_MODULE,
+   },
+};
+
+module_amba_driver(vfio_amba_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index e33b04b..da07c1a 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -160,6 +160,7 @@ struct vfio_device_info {
 #define VFIO_DEVICE_FLAGS_RESET(1 << 0)/* Device supports 
reset */
 #define VFIO_DEVICE_FLAGS_PCI  (1 << 1)/* vfio-pci device */
 #define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)/* vfio-platform device */
+#define VFIO_DEVICE_FLAGS_AMBA  (1 << 3)   /* vfio-amba device */
__u32   num_regions;/* Max region index + 1 */
__u32   num_irqs;   /* Max IRQ index + 1 */
 };
-- 
2.3.1

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


[PATCH v14 06/20] vfio/platform: return info for bound device

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

A VFIO userspace driver will start by opening the VFIO device
that corresponds to an IOMMU group, and will use the ioctl interface
to get the basic device info, such as number of memory regions and
interrupts, and their properties. This patch enables the
VFIO_DEVICE_GET_INFO ioctl call.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: added include in vfio_platform_common.c]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 34d023b..c2f853a 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "vfio_platform_private.h"
@@ -38,10 +39,27 @@ static int vfio_platform_open(void *device_data)
 static long vfio_platform_ioctl(void *device_data,
unsigned int cmd, unsigned long arg)
 {
-   if (cmd == VFIO_DEVICE_GET_INFO)
-   return -EINVAL;
+   struct vfio_platform_device *vdev = device_data;
+   unsigned long minsz;
+
+   if (cmd == VFIO_DEVICE_GET_INFO) {
+   struct vfio_device_info info;
+
+   minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+   if (copy_from_user(&info, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (info.argsz < minsz)
+   return -EINVAL;
+
+   info.flags = vdev->flags;
+   info.num_regions = 0;
+   info.num_irqs = 0;
+
+   return copy_to_user((void __user *)arg, &info, minsz);
 
-   else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+   } else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
return -EINVAL;
 
else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-- 
2.3.1

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


[PATCH v14 01/20] vfio/platform: initial skeleton of VFIO support for platform devices

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

This patch forms the common skeleton code for platform devices support
with VFIO. This will include the core functionality of VFIO_PLATFORM,
however binding to the device and discovering the device resources will
be done with the help of a separate file where any Linux platform bus
specific code will reside.

This will allow us to implement support for also discovering AMBA devices
and their resources, but still reuse a large part of the VFIO_PLATFORM
implementation.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: added includes in vfio_platform_private.h]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c  | 121 ++
 drivers/vfio/platform/vfio_platform_private.h |  39 +
 2 files changed, 160 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform_common.c
 create mode 100644 drivers/vfio/platform/vfio_platform_private.h

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
new file mode 100644
index 000..34d023b
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+static void vfio_platform_release(void *device_data)
+{
+   module_put(THIS_MODULE);
+}
+
+static int vfio_platform_open(void *device_data)
+{
+   if (!try_module_get(THIS_MODULE))
+   return -ENODEV;
+
+   return 0;
+}
+
+static long vfio_platform_ioctl(void *device_data,
+   unsigned int cmd, unsigned long arg)
+{
+   if (cmd == VFIO_DEVICE_GET_INFO)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_SET_IRQS)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_RESET)
+   return -EINVAL;
+
+   return -ENOTTY;
+}
+
+static ssize_t vfio_platform_read(void *device_data, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+   return -EINVAL;
+}
+
+static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
+  size_t count, loff_t *ppos)
+{
+   return -EINVAL;
+}
+
+static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+{
+   return -EINVAL;
+}
+
+static const struct vfio_device_ops vfio_platform_ops = {
+   .name   = "vfio-platform",
+   .open   = vfio_platform_open,
+   .release= vfio_platform_release,
+   .ioctl  = vfio_platform_ioctl,
+   .read   = vfio_platform_read,
+   .write  = vfio_platform_write,
+   .mmap   = vfio_platform_mmap,
+};
+
+int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+  struct device *dev)
+{
+   struct iommu_group *group;
+   int ret;
+
+   if (!vdev)
+   return -EINVAL;
+
+   group = iommu_group_get(dev);
+   if (!group) {
+   pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
+   return -EINVAL;
+   }
+
+   ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
+   if (ret) {
+   iommu_group_put(group);
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
+
+struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
+{
+   struct vfio_platform_device *vdev;
+
+   vdev = vfio_del_group_dev(dev);
+   if (vdev)
+   iommu_group_put(dev->iommu_group);
+
+   return vdev;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
new file mode 100644
index 000..c046988
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is

[PATCH v4 1/5] vfio: implement iommu driver capabilities with an enum

2015-03-02 Thread Baptiste Reynal
From: Antonios Motakis 

Currently a VFIO driver's IOMMU capabilities are encoded as a series of
numerical defines. Replace this with an enum for future maintainability.

Signed-off-by: Antonios Motakis 
Signed-off-by: Baptiste Reynal 
---
 include/uapi/linux/vfio.h | 24 +++-
 1 file changed, 11 insertions(+), 13 deletions(-)

diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 82889c3..5fb3d46 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -19,22 +19,20 @@
 
 /* Kernel & User level defines for VFIO IOCTLs. */
 
-/* Extensions */
-
-#define VFIO_TYPE1_IOMMU   1
-#define VFIO_SPAPR_TCE_IOMMU   2
-#define VFIO_TYPE1v2_IOMMU 3
 /*
- * IOMMU enforces DMA cache coherence (ex. PCIe NoSnoop stripping).  This
- * capability is subject to change as groups are added or removed.
+ * Capabilities exposed by the VFIO IOMMU driver. Some capabilities are subject
+ * to change as groups are added or removed.
  */
-#define VFIO_DMA_CC_IOMMU  4
-
-/* Check if EEH is supported */
-#define VFIO_EEH   5
+enum vfio_iommu_cap {
+   VFIO_TYPE1_IOMMU = 1,
+   VFIO_SPAPR_TCE_IOMMU = 2,
+   VFIO_TYPE1v2_IOMMU = 3,
+   VFIO_DMA_CC_IOMMU = 4,  /* IOMMU enforces DMA cache coherence
+  (ex. PCIe NoSnoop stripping) */
+   VFIO_EEH = 5,   /* Check if EEH is supported */
+   VFIO_TYPE1_NESTING_IOMMU = 6,   /* Two-stage IOMMU, implies v2  */
+};
 
-/* Two-stage IOMMU */
-#define VFIO_TYPE1_NESTING_IOMMU   6   /* Implies v2 */
 
 /*
  * The IOCTL interface is designed for extensibility by embedding the
-- 
2.3.1

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


[PATCH 1/1] iommu/arm-smmu: fix ARM_SMMU_FEAT_TRANS_OPS condition

2015-03-02 Thread Baptiste Reynal
This patch is a fix to "iommu/arm-smmu: add support for iova_to_phys
through ATS1PR".
According to ARM documentation, translation registers are optional even
in SMMUv1, so ID0_S1TS needs to be checked to verify their presence.

Signed-off-by: Baptiste Reynal 
---
 drivers/iommu/arm-smmu.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index fc13dd5..d4beca4 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1556,7 +1556,7 @@ static int arm_smmu_device_cfg_probe(struct 
arm_smmu_device *smmu)
return -ENODEV;
}
 
-   if (smmu->version == 1 || (!(id & ID0_ATOSNS) && (id & ID0_S1TS))) {
+   if ((id & ID0_S1TS) && ((smmu->version == 1) || (id & ID0_ATOSNS))) {
smmu->features |= ARM_SMMU_FEAT_TRANS_OPS;
dev_notice(smmu->dev, "\taddress translation ops\n");
}
-- 
2.3.1

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


Re: [PATCH v13 00/18] VFIO support for platform devices

2015-02-27 Thread Baptiste Reynal
Thanks for your answers.

I am now the sub-maintainer of vfio-platform. I will handle the rebase of
these serie and fix "[PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
VFIO_IOMMU_TYPE1". New versions are coming soon.

Regards,
Baptiste

On Thu, Feb 26, 2015 at 6:32 PM, Marc Zyngier  wrote:

> Hi Baptiste,
>
> On 26/02/15 17:02, Baptiste Reynal wrote:
> > Hi everyone,
> >
> > Are there any comments on this patch series? If not, Is there
> > anything keeping this series from getting merged upstream?
>
> For a start, it looks like the dependency mentioned below is still not
> in, which is a bit of a problem.
>
> Also, trying to merge your branch below (after fixing the URL), I get
> some conflicts with the current mainline, so that's a bit of a show
> stopper too.
>
> Can you start by rebasing on top of 4.0-rc1 with all the dependencies,
> reposting the series, and cc-ing the original author of the patches (as
> I cannot see Antonios on the CC list)?
>
> Thanks,
>
>     M.
>
> > Thanks,
> > Baptiste
> >
> > On Fri, Jan 30, 2015 at 2:46 PM, Baptiste Reynal <
> b.rey...@virtualopensystems.com<mailto:b.rey...@virtualopensystems.com>>
> wrote:
> > This patch series aims to implement VFIO support for platform devices
> that
> > reside behind an IOMMU. Examples of such devices are devices behind an
> ARM
> > SMMU, or behind a Samsung Exynos System MMU.
> >
> > The API used is based on the existing VFIO API that is also used with PCI
> > devices. Only devices that include a basic set of IRQs and memory
> regions are
> > targeted; devices with complex relationships with other devices on a
> device
> > tree are not taken into account at this stage.
> >
> > This patch series may be applied on the following series/patches:
> >  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
> VFIO_IOMMU_TYPE1
> >
> > A copy can be cloned from the branch vfio-platform-v13 at:
> > g...@github.com:virtualopensystems/linux-kvm-arm.git
> >
> > Changes since v12:
> >  - Reorder chunks to be bisect-able
> > Changes since v11:
> >  - Drop support for ARM AMBA devices
> >  - vfio_platform_private.h is now self-contained
> >  - Fix masked IRQ initialization
> > Changes since v10:
> >  - Check if interrupt is already masked when setting a new trigger
> >  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> > Changes since v9:
> >  - Reworked the splitting of the patches that decouple virqfd from PCI
> >  - Some styling issues and typos
> >  - Removed superfluous includes
> >  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
> >  - Several other cleanups and fixes
> > Changes since v8:
> >  - Separate irq handler for edge and level triggered interrupts
> >  - Mutex based lock for VFIO fd open/release
> >  - Fixed bug where the first region of a platform device wasn't exposed
> >  - Read only regions can be MMAPed only read only
> >  - Code cleanups
> > Changes since v7:
> >  - Some initial placeholder functionality for PIO resources
> >  - Cleaned up code for IRQ triggering, masking and unmasking
> >  - Some functionality has been removed from this series and posted
> separately:
> >- VFIO_IOMMU_TYPE1 support for ARM SMMUs
> >- IOMMU NOEXEC patches
> >- driver_override functionality for AMBA devices
> >  - Several fixes
> > Changes since v6:
> >  - Integrated support for AMBA devices
> >  - Numerous cleanups and fixes
> > Changes since v5:
> >  - Full eventfd support for IRQ masking and unmasking.
> >  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
> >  - Other fixes based on reviewer comments.
> > Changes since v4:
> >  - Use static offsets for each region in the VFIO device fd
> >  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
> >availability via IOMMU_CAP_DMA_EXEC
> >  - Rebased on VFIO multi domain support:
> >- IOMMU_EXEC is now available if at least one IOMMU in the container
> >  supports it
> >- Expose IOMMU_EXEC if available via the capability
> VFIO_IOMMU_PROT_EXEC
> >  - Some bug fixes
> > Changes since v3:
> >  - Use Kim Phillips' driver_probe_device()
> > Changes since v2:
> >  - Fixed Read/Write and MMAP on device regions
> >  - Removed dependency on Device Tree
> >  - Interrupts support
> >  - Interrupt masking/unmasking
> >  - Automask level sensitive interrupts
> >  - Introduced VFIO_DMA_MAP_FLAG_EXEC
> >  - Code 

Re: [PATCH v13 00/18] VFIO support for platform devices

2015-02-26 Thread Baptiste Reynal
Hi everyone,

Are there any comments on this patch series? If not, Is there anything
keeping this series from getting merged upstream?

Thanks,
Baptiste

On Fri, Jan 30, 2015 at 2:46 PM, Baptiste Reynal <
b.rey...@virtualopensystems.com> wrote:

> This patch series aims to implement VFIO support for platform devices that
> reside behind an IOMMU. Examples of such devices are devices behind an ARM
> SMMU, or behind a Samsung Exynos System MMU.
>
> The API used is based on the existing VFIO API that is also used with PCI
> devices. Only devices that include a basic set of IRQs and memory regions
> are
> targeted; devices with complex relationships with other devices on a device
> tree are not taken into account at this stage.
>
> This patch series may be applied on the following series/patches:
>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1
>
> A copy can be cloned from the branch vfio-platform-v13 at:
> g...@github.com:virtualopensystems/linux-kvm-arm.git
>
> Changes since v12:
>  - Reorder chunks to be bisect-able
> Changes since v11:
>  - Drop support for ARM AMBA devices
>  - vfio_platform_private.h is now self-contained
>  - Fix masked IRQ initialization
> Changes since v10:
>  - Check if interrupt is already masked when setting a new trigger
>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> Changes since v9:
>  - Reworked the splitting of the patches that decouple virqfd from PCI
>  - Some styling issues and typos
>  - Removed superfluous includes
>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
>  - Several other cleanups and fixes
> Changes since v8:
>  - Separate irq handler for edge and level triggered interrupts
>  - Mutex based lock for VFIO fd open/release
>  - Fixed bug where the first region of a platform device wasn't exposed
>  - Read only regions can be MMAPed only read only
>  - Code cleanups
> Changes since v7:
>  - Some initial placeholder functionality for PIO resources
>  - Cleaned up code for IRQ triggering, masking and unmasking
>  - Some functionality has been removed from this series and posted
> separately:
>- VFIO_IOMMU_TYPE1 support for ARM SMMUs
>- IOMMU NOEXEC patches
>- driver_override functionality for AMBA devices
>  - Several fixes
> Changes since v6:
>  - Integrated support for AMBA devices
>  - Numerous cleanups and fixes
> Changes since v5:
>  - Full eventfd support for IRQ masking and unmasking.
>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
>  - Other fixes based on reviewer comments.
> Changes since v4:
>  - Use static offsets for each region in the VFIO device fd
>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
>availability via IOMMU_CAP_DMA_EXEC
>  - Rebased on VFIO multi domain support:
>- IOMMU_EXEC is now available if at least one IOMMU in the container
>  supports it
>- Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
>  - Some bug fixes
> Changes since v3:
>  - Use Kim Phillips' driver_probe_device()
> Changes since v2:
>  - Fixed Read/Write and MMAP on device regions
>  - Removed dependency on Device Tree
>  - Interrupts support
>  - Interrupt masking/unmasking
>  - Automask level sensitive interrupts
>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
>  - Code clean ups
>
> Antonios Motakis (18):
>   vfio/platform: initial skeleton of VFIO support for platform devices
>   vfio: platform: probe to devices on the platform bus
>   vfio: platform: add the VFIO PLATFORM module to Kconfig
>   vfio/platform: return info for bound device
>   vfio/platform: return info for device memory mapped IO regions
>   vfio/platform: read and write support for the device fd
>   vfio/platform: support MMAP of MMIO regions
>   vfio/platform: return IRQ info
>   vfio/platform: initial interrupts support code
>   vfio/platform: trigger an interrupt via eventfd
>   vfio/platform: support for level sensitive interrupts
>   vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
> export
>   vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
>   vfio: add local lock for virqfd instead of depending on VFIO PCI
>   vfio: pass an opaque pointer on virqfd initialization
>   vfio: move eventfd support code for VFIO_PCI to a separate file
>   vfio: initialize the virqfd workqueue in VFIO generic code
>   vfio/platform: implement IRQ masking/unmasking via an eventfd
>
>  drivers/vfio/Kconfig  |   1 +
>  drivers/vfio/Makefile |   5 +-
>  drivers/vfio/pci/vfio_pci.c   |   8 -
>  drivers/vfio/pci/vfio_pci_intrs.c

SMMU 2-stage support

2015-02-18 Thread Baptiste Reynal
We are currently working on the ARM SMMU 2-stage support in order to expose
SMMU capabilities to a guest OS.
By doing some research, we noticed some work has already be done by Will
Deacon on exposing virtual IOMMU interface to KVM guest. After going
through slides and code (on git://
git.kernel.org/pub/scm/linux/kernel/git/will/linux.git, branch:
iommu/vsmmu), we have some questions :

- What is the status of this work ? Is Alex still working on it ?
- Are there any test case about the current vsmmu implementation ?

- What is exposed to the guest in the current implementation ?
- How do the guest program the stage-1 translation ?

Thanks for your consideration,
Baptiste
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

[PATCH v13 03/18] vfio: platform: add the VFIO PLATFORM module to Kconfig

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

Enable building the VFIO PLATFORM driver that allows to use Linux platform
devices with VFIO.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/Kconfig   | 1 +
 drivers/vfio/Makefile  | 1 +
 drivers/vfio/platform/Kconfig  | 9 +
 drivers/vfio/platform/Makefile | 4 
 4 files changed, 15 insertions(+)
 create mode 100644 drivers/vfio/platform/Kconfig
 create mode 100644 drivers/vfio/platform/Makefile

diff --git a/drivers/vfio/Kconfig b/drivers/vfio/Kconfig
index a0abe04..962fb80 100644
--- a/drivers/vfio/Kconfig
+++ b/drivers/vfio/Kconfig
@@ -27,3 +27,4 @@ menuconfig VFIO
  If you don't know what to do here, say N.
 
 source "drivers/vfio/pci/Kconfig"
+source "drivers/vfio/platform/Kconfig"
diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index 0b035b1..dadf0ca 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -3,3 +3,4 @@ obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
 obj-$(CONFIG_VFIO_PCI) += pci/
+obj-$(CONFIG_VFIO_PLATFORM) += platform/
diff --git a/drivers/vfio/platform/Kconfig b/drivers/vfio/platform/Kconfig
new file mode 100644
index 000..c51af17
--- /dev/null
+++ b/drivers/vfio/platform/Kconfig
@@ -0,0 +1,9 @@
+config VFIO_PLATFORM
+   tristate "VFIO support for platform devices"
+   depends on VFIO && EVENTFD && ARM
+   help
+ Support for platform devices with VFIO. This is required to make
+ use of platform devices present on the system using the VFIO
+ framework.
+
+ If you don't know what to do here, say N.
diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
new file mode 100644
index 000..279862b
--- /dev/null
+++ b/drivers/vfio/platform/Makefile
@@ -0,0 +1,4 @@
+
+vfio-platform-y := vfio_platform.o vfio_platform_common.o
+
+obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
-- 
2.2.2

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


[PATCH v13 18/18] vfio/platform: implement IRQ masking/unmasking via an eventfd

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

With this patch the VFIO user will be able to set an eventfd that can be
used in order to mask and unmask IRQs of platform devices.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/vfio_platform_irq.c | 47 ---
 drivers/vfio/platform/vfio_platform_private.h |  2 ++
 2 files changed, 45 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index e0e6388..88bba57 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -37,6 +37,15 @@ static void vfio_platform_mask(struct vfio_platform_irq 
*irq_ctx)
spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_mask_handler(void *opaque, void *unused)
+{
+   struct vfio_platform_irq *irq_ctx = opaque;
+
+   vfio_platform_mask(irq_ctx);
+
+   return 0;
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
  unsigned index, unsigned start,
  unsigned count, uint32_t flags,
@@ -48,8 +57,18 @@ static int vfio_platform_set_irq_mask(struct 
vfio_platform_device *vdev,
if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
return -EINVAL;
 
-   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-   return -EINVAL; /* not implemented yet */
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+   int32_t fd = *(int32_t *)data;
+
+   if (fd >= 0)
+   return vfio_virqfd_enable((void *) &vdev->irqs[index],
+ vfio_platform_mask_handler,
+ NULL, NULL,
+ &vdev->irqs[index].mask, fd);
+
+   vfio_virqfd_disable(&vdev->irqs[index].mask);
+   return 0;
+   }
 
if (flags & VFIO_IRQ_SET_DATA_NONE) {
vfio_platform_mask(&vdev->irqs[index]);
@@ -78,6 +97,15 @@ static void vfio_platform_unmask(struct vfio_platform_irq 
*irq_ctx)
spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
+static int vfio_platform_unmask_handler(void *opaque, void *unused)
+{
+   struct vfio_platform_irq *irq_ctx = opaque;
+
+   vfio_platform_unmask(irq_ctx);
+
+   return 0;
+}
+
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
unsigned index, unsigned start,
unsigned count, uint32_t flags,
@@ -89,8 +117,19 @@ static int vfio_platform_set_irq_unmask(struct 
vfio_platform_device *vdev,
if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
return -EINVAL;
 
-   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
-   return -EINVAL; /* not implemented yet */
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+   int32_t fd = *(int32_t *)data;
+
+   if (fd >= 0)
+   return vfio_virqfd_enable((void *) &vdev->irqs[index],
+ vfio_platform_unmask_handler,
+ NULL, NULL,
+ &vdev->irqs[index].unmask,
+ fd);
+
+   vfio_virqfd_disable(&vdev->irqs[index].unmask);
+   return 0;
+   }
 
if (flags & VFIO_IRQ_SET_DATA_NONE) {
vfio_platform_unmask(&vdev->irqs[index]);
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
index ff2db1d..5d31e04 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -35,6 +35,8 @@ struct vfio_platform_irq {
struct eventfd_ctx  *trigger;
boolmasked;
spinlock_t  lock;
+   struct virqfd   *unmask;
+   struct virqfd   *mask;
 };
 
 struct vfio_platform_region {
-- 
2.2.2

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


[PATCH v13 17/18] vfio: initialize the virqfd workqueue in VFIO generic code

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

Now we have finally completely decoupled virqfd from VFIO_PCI. We can
initialize it from the VFIO generic code, in order to safely use it from
multiple independent VFIO bus drivers.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/Makefile   | 4 +++-
 drivers/vfio/pci/Makefile   | 3 +--
 drivers/vfio/pci/vfio_pci.c | 8 
 drivers/vfio/vfio.c | 8 
 4 files changed, 12 insertions(+), 11 deletions(-)

diff --git a/drivers/vfio/Makefile b/drivers/vfio/Makefile
index dadf0ca..d798b09 100644
--- a/drivers/vfio/Makefile
+++ b/drivers/vfio/Makefile
@@ -1,4 +1,6 @@
-obj-$(CONFIG_VFIO) += vfio.o
+vfio_core-y := vfio.o virqfd.o
+
+obj-$(CONFIG_VFIO) += vfio_core.o
 obj-$(CONFIG_VFIO_IOMMU_TYPE1) += vfio_iommu_type1.o
 obj-$(CONFIG_VFIO_IOMMU_SPAPR_TCE) += vfio_iommu_spapr_tce.o
 obj-$(CONFIG_VFIO_SPAPR_EEH) += vfio_spapr_eeh.o
diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index c7c8644..1310792 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,5 +1,4 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
- ../virqfd.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index fc4308c..8d156d7 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1012,7 +1012,6 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
pci_unregister_driver(&vfio_pci_driver);
-   vfio_virqfd_exit();
vfio_pci_uninit_perm_bits();
 }
 
@@ -1025,11 +1024,6 @@ static int __init vfio_pci_init(void)
if (ret)
return ret;
 
-   /* Start the virqfd cleanup handler */
-   ret = vfio_virqfd_init();
-   if (ret)
-   goto out_virqfd;
-
/* Register and scan for devices */
ret = pci_register_driver(&vfio_pci_driver);
if (ret)
@@ -1038,8 +1032,6 @@ static int __init vfio_pci_init(void)
return 0;
 
 out_driver:
-   vfio_virqfd_exit();
-out_virqfd:
vfio_pci_uninit_perm_bits();
return ret;
 }
diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index f018d8d..8e84471 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -1464,6 +1464,11 @@ static int __init vfio_init(void)
if (ret)
goto err_cdev_add;
 
+   /* Start the virqfd cleanup handler used by some VFIO bus drivers */
+   ret = vfio_virqfd_init();
+   if (ret)
+   goto err_virqfd;
+
pr_info(DRIVER_DESC " version: " DRIVER_VERSION "\n");
 
/*
@@ -1476,6 +1481,8 @@ static int __init vfio_init(void)
 
return 0;
 
+err_virqfd:
+   cdev_del(&vfio.group_cdev);
 err_cdev_add:
unregister_chrdev_region(vfio.group_devt, MINORMASK);
 err_alloc_chrdev:
@@ -1490,6 +1497,7 @@ static void __exit vfio_cleanup(void)
 {
WARN_ON(!list_empty(&vfio.group_list));
 
+   vfio_virqfd_exit();
idr_destroy(&vfio.group_idr);
cdev_del(&vfio.group_cdev);
unregister_chrdev_region(vfio.group_devt, MINORMASK);
-- 
2.2.2

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


[PATCH v13 16/18] vfio: move eventfd support code for VFIO_PCI to a separate file

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

The virqfd functionality that is used by VFIO_PCI to implement interrupt
masking and unmasking via an eventfd, is generic enough and can be reused
by another driver. Move it to a separate file in order to allow the code
to be shared.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/pci/Makefile   |   3 +-
 drivers/vfio/pci/vfio_pci_intrs.c   | 215 
 drivers/vfio/pci/vfio_pci_private.h |   3 -
 drivers/vfio/virqfd.c   | 213 +++
 include/linux/vfio.h|  27 +
 5 files changed, 242 insertions(+), 219 deletions(-)
 create mode 100644 drivers/vfio/virqfd.c

diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile
index 1310792..c7c8644 100644
--- a/drivers/vfio/pci/Makefile
+++ b/drivers/vfio/pci/Makefile
@@ -1,4 +1,5 @@
 
-vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o
+vfio-pci-y := vfio_pci.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o \
+ ../virqfd.o
 
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index 5b5fc23..de4befc 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -19,228 +19,13 @@
 #include 
 #include 
 #include 
-#include 
 #include 
 #include 
-#include 
 #include 
 
 #include "vfio_pci_private.h"
 
 /*
- * IRQfd - generic
- */
-struct virqfd {
-   void*opaque;
-   struct eventfd_ctx  *eventfd;
-   int (*handler)(void *, void *);
-   void(*thread)(void *, void *);
-   void*data;
-   struct work_struct  inject;
-   wait_queue_twait;
-   poll_table  pt;
-   struct work_struct  shutdown;
-   struct virqfd   **pvirqfd;
-};
-
-static struct workqueue_struct *vfio_irqfd_cleanup_wq;
-DEFINE_SPINLOCK(virqfd_lock);
-
-int __init vfio_virqfd_init(void)
-{
-   vfio_irqfd_cleanup_wq =
-   create_singlethread_workqueue("vfio-irqfd-cleanup");
-   if (!vfio_irqfd_cleanup_wq)
-   return -ENOMEM;
-
-   return 0;
-}
-
-void vfio_virqfd_exit(void)
-{
-   destroy_workqueue(vfio_irqfd_cleanup_wq);
-}
-
-static void virqfd_deactivate(struct virqfd *virqfd)
-{
-   queue_work(vfio_irqfd_cleanup_wq, &virqfd->shutdown);
-}
-
-static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, int sync, void 
*key)
-{
-   struct virqfd *virqfd = container_of(wait, struct virqfd, wait);
-   unsigned long flags = (unsigned long)key;
-
-   if (flags & POLLIN) {
-   /* An event has been signaled, call function */
-   if ((!virqfd->handler ||
-virqfd->handler(virqfd->opaque, virqfd->data)) &&
-   virqfd->thread)
-   schedule_work(&virqfd->inject);
-   }
-
-   if (flags & POLLHUP) {
-   unsigned long flags;
-   spin_lock_irqsave(&virqfd_lock, flags);
-
-   /*
-* The eventfd is closing, if the virqfd has not yet been
-* queued for release, as determined by testing whether the
-* virqfd pointer to it is still valid, queue it now.  As
-* with kvm irqfds, we know we won't race against the virqfd
-* going away because we hold the lock to get here.
-*/
-   if (*(virqfd->pvirqfd) == virqfd) {
-   *(virqfd->pvirqfd) = NULL;
-   virqfd_deactivate(virqfd);
-   }
-
-   spin_unlock_irqrestore(&virqfd_lock, flags);
-   }
-
-   return 0;
-}
-
-static void virqfd_ptable_queue_proc(struct file *file,
-wait_queue_head_t *wqh, poll_table *pt)
-{
-   struct virqfd *virqfd = container_of(pt, struct virqfd, pt);
-   add_wait_queue(wqh, &virqfd->wait);
-}
-
-static void virqfd_shutdown(struct work_struct *work)
-{
-   struct virqfd *virqfd = container_of(work, struct virqfd, shutdown);
-   u64 cnt;
-
-   eventfd_ctx_remove_wait_queue(virqfd->eventfd, &virqfd->wait, &cnt);
-   flush_work(&virqfd->inject);
-   eventfd_ctx_put(virqfd->eventfd);
-
-   kfree(virqfd);
-}
-
-static void virqfd_inject(struct work_struct *work)
-{
-   struct virqfd *virqfd = container_of(work, struct virqfd, inject);
-   if (virqfd->thread)
-   virqfd->thread(virqfd->opaque, virqfd->data);
-}
-
-int vfio_virqfd_enable(void *opaque,
-  int (*handler)(void *, void *),
-  void (*thread)(void *, void *),
-  void *data, struct virqfd **pvirqfd, int fd)
-{
-   struct fd irqfd;
-   struct eventfd_ctx *ctx;
-   struct virqfd *virqfd;
-   int ret = 0;
-   unsigned int events;
-
-   virqfd = kzalloc(sizeof(*virq

[PATCH v13 15/18] vfio: pass an opaque pointer on virqfd initialization

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

VFIO_PCI passes the VFIO device structure *vdev via eventfd to the handler
that implements masking/unmasking of IRQs via an eventfd. We can replace
it in the virqfd infrastructure with an opaque type so we can make use
of the mechanism from other VFIO bus drivers.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/pci/vfio_pci_intrs.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index b35bc16..5b5fc23 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -31,10 +31,10 @@
  * IRQfd - generic
  */
 struct virqfd {
-   struct vfio_pci_device  *vdev;
+   void*opaque;
struct eventfd_ctx  *eventfd;
-   int (*handler)(struct vfio_pci_device *, void *);
-   void(*thread)(struct vfio_pci_device *, void *);
+   int (*handler)(void *, void *);
+   void(*thread)(void *, void *);
void*data;
struct work_struct  inject;
wait_queue_twait;
@@ -74,7 +74,7 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, 
int sync, void *key)
if (flags & POLLIN) {
/* An event has been signaled, call function */
if ((!virqfd->handler ||
-virqfd->handler(virqfd->vdev, virqfd->data)) &&
+virqfd->handler(virqfd->opaque, virqfd->data)) &&
virqfd->thread)
schedule_work(&virqfd->inject);
}
@@ -124,12 +124,12 @@ static void virqfd_inject(struct work_struct *work)
 {
struct virqfd *virqfd = container_of(work, struct virqfd, inject);
if (virqfd->thread)
-   virqfd->thread(virqfd->vdev, virqfd->data);
+   virqfd->thread(virqfd->opaque, virqfd->data);
 }
 
-int vfio_virqfd_enable(struct vfio_pci_device *vdev,
-  int (*handler)(struct vfio_pci_device *, void *),
-  void (*thread)(struct vfio_pci_device *, void *),
+int vfio_virqfd_enable(void *opaque,
+  int (*handler)(void *, void *),
+  void (*thread)(void *, void *),
   void *data, struct virqfd **pvirqfd, int fd)
 {
struct fd irqfd;
@@ -143,7 +143,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
return -ENOMEM;
 
virqfd->pvirqfd = pvirqfd;
-   virqfd->vdev = vdev;
+   virqfd->opaque = opaque;
virqfd->handler = handler;
virqfd->thread = thread;
virqfd->data = data;
@@ -196,7 +196,7 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 * before we registered and trigger it as if we didn't miss it.
 */
if (events & POLLIN) {
-   if ((!handler || handler(vdev, data)) && thread)
+   if ((!handler || handler(opaque, data)) && thread)
schedule_work(&virqfd->inject);
}
 
@@ -243,8 +243,10 @@ EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 /*
  * INTx
  */
-static void vfio_send_intx_eventfd(struct vfio_pci_device *vdev, void *unused)
+static void vfio_send_intx_eventfd(void *opaque, void *unused)
 {
+   struct vfio_pci_device *vdev = opaque;
+
if (likely(is_intx(vdev) && !vdev->virq_disabled))
eventfd_signal(vdev->ctx[0].trigger, 1);
 }
@@ -287,9 +289,9 @@ void vfio_pci_intx_mask(struct vfio_pci_device *vdev)
  * a signal is necessary, which can then be handled via a work queue
  * or directly depending on the caller.
  */
-static int vfio_pci_intx_unmask_handler(struct vfio_pci_device *vdev,
-   void *unused)
+static int vfio_pci_intx_unmask_handler(void *opaque, void *unused)
 {
+   struct vfio_pci_device *vdev = opaque;
struct pci_dev *pdev = vdev->pdev;
unsigned long flags;
int ret = 0;
@@ -641,7 +643,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device 
*vdev,
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
int32_t fd = *(int32_t *)data;
if (fd >= 0)
-   return vfio_virqfd_enable(vdev,
+   return vfio_virqfd_enable((void *) vdev,
  vfio_pci_intx_unmask_handler,
  vfio_send_intx_eventfd, NULL,
  &vdev->ctx[0].unmask, fd);
-- 
2.2.2

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


[PATCH v13 14/18] vfio: add local lock for virqfd instead of depending on VFIO PCI

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

The Virqfd code needs to keep accesses to any struct *virqfd safe, but
this comes into play only when creating or destroying eventfds, so sharing
the same spinlock with the VFIO bus driver is not necessary.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/pci/vfio_pci_intrs.c | 31 ---
 1 file changed, 16 insertions(+), 15 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index a5378d5..b35bc16 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -44,6 +44,7 @@ struct virqfd {
 };
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
+DEFINE_SPINLOCK(virqfd_lock);
 
 int __init vfio_virqfd_init(void)
 {
@@ -80,21 +81,21 @@ static int virqfd_wakeup(wait_queue_t *wait, unsigned mode, 
int sync, void *key)
 
if (flags & POLLHUP) {
unsigned long flags;
-   spin_lock_irqsave(&virqfd->vdev->irqlock, flags);
+   spin_lock_irqsave(&virqfd_lock, flags);
 
/*
 * The eventfd is closing, if the virqfd has not yet been
 * queued for release, as determined by testing whether the
-* vdev pointer to it is still valid, queue it now.  As
+* virqfd pointer to it is still valid, queue it now.  As
 * with kvm irqfds, we know we won't race against the virqfd
-* going away because we hold wqh->lock to get here.
+* going away because we hold the lock to get here.
 */
if (*(virqfd->pvirqfd) == virqfd) {
*(virqfd->pvirqfd) = NULL;
virqfd_deactivate(virqfd);
}
 
-   spin_unlock_irqrestore(&virqfd->vdev->irqlock, flags);
+   spin_unlock_irqrestore(&virqfd_lock, flags);
}
 
return 0;
@@ -170,16 +171,16 @@ int vfio_virqfd_enable(struct vfio_pci_device *vdev,
 * we update the pointer to the virqfd under lock to avoid
 * pushing multiple jobs to release the same virqfd.
 */
-   spin_lock_irq(&vdev->irqlock);
+   spin_lock_irq(&virqfd_lock);
 
if (*pvirqfd) {
-   spin_unlock_irq(&vdev->irqlock);
+   spin_unlock_irq(&virqfd_lock);
ret = -EBUSY;
goto err_busy;
}
*pvirqfd = virqfd;
 
-   spin_unlock_irq(&vdev->irqlock);
+   spin_unlock_irq(&virqfd_lock);
 
/*
 * Install our own custom wake-up handling so we are notified via
@@ -217,18 +218,18 @@ err_fd:
 }
 EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct virqfd **pvirqfd)
 {
unsigned long flags;
 
-   spin_lock_irqsave(&vdev->irqlock, flags);
+   spin_lock_irqsave(&virqfd_lock, flags);
 
if (*pvirqfd) {
virqfd_deactivate(*pvirqfd);
*pvirqfd = NULL;
}
 
-   spin_unlock_irqrestore(&vdev->irqlock, flags);
+   spin_unlock_irqrestore(&virqfd_lock, flags);
 
/*
 * Block until we know all outstanding shutdown jobs have completed.
@@ -441,8 +442,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device 
*vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
vfio_intx_set_signal(vdev, -1);
-   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
-   vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
+   vfio_virqfd_disable(&vdev->ctx[0].unmask);
+   vfio_virqfd_disable(&vdev->ctx[0].mask);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
vdev->num_ctx = 0;
kfree(vdev->ctx);
@@ -606,8 +607,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, 
bool msix)
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
for (i = 0; i < vdev->num_ctx; i++) {
-   vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
-   vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
+   vfio_virqfd_disable(&vdev->ctx[i].unmask);
+   vfio_virqfd_disable(&vdev->ctx[i].mask);
}
 
if (msix) {
@@ -645,7 +646,7 @@ static int vfio_pci_set_intx_unmask(struct vfio_pci_device 
*vdev,
  vfio_send_intx_eventfd, NULL,
  &vdev->ctx[0].unmask, fd);
 
-   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+   vfio_virqfd_disable(&vdev->ctx[0].unmask);
}
 
return 0;
-- 
2.2.2

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


[PATCH v13 12/18] vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

We want to reuse virqfd functionality in multiple VFIO drivers; before
moving these functions to core VFIO, add the vfio_ prefix to the
virqfd_enable and virqfd_disable functions, and export them so they can
be used from other modules.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/pci/vfio_pci_intrs.c | 30 --
 1 file changed, 16 insertions(+), 14 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index e8d695b..0a41833d 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -126,10 +126,10 @@ static void virqfd_inject(struct work_struct *work)
virqfd->thread(virqfd->vdev, virqfd->data);
 }
 
-static int virqfd_enable(struct vfio_pci_device *vdev,
-int (*handler)(struct vfio_pci_device *, void *),
-void (*thread)(struct vfio_pci_device *, void *),
-void *data, struct virqfd **pvirqfd, int fd)
+int vfio_virqfd_enable(struct vfio_pci_device *vdev,
+  int (*handler)(struct vfio_pci_device *, void *),
+  void (*thread)(struct vfio_pci_device *, void *),
+  void *data, struct virqfd **pvirqfd, int fd)
 {
struct fd irqfd;
struct eventfd_ctx *ctx;
@@ -215,9 +215,9 @@ err_fd:
 
return ret;
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_enable);
 
-static void virqfd_disable(struct vfio_pci_device *vdev,
-  struct virqfd **pvirqfd)
+void vfio_virqfd_disable(struct vfio_pci_device *vdev, struct virqfd **pvirqfd)
 {
unsigned long flags;
 
@@ -237,6 +237,7 @@ static void virqfd_disable(struct vfio_pci_device *vdev,
 */
flush_workqueue(vfio_irqfd_cleanup_wq);
 }
+EXPORT_SYMBOL_GPL(vfio_virqfd_disable);
 
 /*
  * INTx
@@ -440,8 +441,8 @@ static int vfio_intx_set_signal(struct vfio_pci_device 
*vdev, int fd)
 static void vfio_intx_disable(struct vfio_pci_device *vdev)
 {
vfio_intx_set_signal(vdev, -1);
-   virqfd_disable(vdev, &vdev->ctx[0].unmask);
-   virqfd_disable(vdev, &vdev->ctx[0].mask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[0].mask);
vdev->irq_type = VFIO_PCI_NUM_IRQS;
vdev->num_ctx = 0;
kfree(vdev->ctx);
@@ -605,8 +606,8 @@ static void vfio_msi_disable(struct vfio_pci_device *vdev, 
bool msix)
vfio_msi_set_block(vdev, 0, vdev->num_ctx, NULL, msix);
 
for (i = 0; i < vdev->num_ctx; i++) {
-   virqfd_disable(vdev, &vdev->ctx[i].unmask);
-   virqfd_disable(vdev, &vdev->ctx[i].mask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[i].unmask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[i].mask);
}
 
if (msix) {
@@ -639,11 +640,12 @@ static int vfio_pci_set_intx_unmask(struct 
vfio_pci_device *vdev,
} else if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
int32_t fd = *(int32_t *)data;
if (fd >= 0)
-   return virqfd_enable(vdev, vfio_pci_intx_unmask_handler,
-vfio_send_intx_eventfd, NULL,
-&vdev->ctx[0].unmask, fd);
+   return vfio_virqfd_enable(vdev,
+ vfio_pci_intx_unmask_handler,
+ vfio_send_intx_eventfd, NULL,
+ &vdev->ctx[0].unmask, fd);
 
-   virqfd_disable(vdev, &vdev->ctx[0].unmask);
+   vfio_virqfd_disable(vdev, &vdev->ctx[0].unmask);
}
 
return 0;
-- 
2.2.2

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


[PATCH v13 13/18] vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

The functions vfio_pci_virqfd_init and vfio_pci_virqfd_exit are not really
PCI specific, since we plan to reuse the virqfd code with more VFIO drivers
in addition to VFIO_PCI.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: Move rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
from "vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and export"]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/pci/vfio_pci.c | 6 +++---
 drivers/vfio/pci/vfio_pci_intrs.c   | 4 ++--
 drivers/vfio/pci/vfio_pci_private.h | 4 ++--
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c
index 9558da3..fc4308c 100644
--- a/drivers/vfio/pci/vfio_pci.c
+++ b/drivers/vfio/pci/vfio_pci.c
@@ -1012,7 +1012,7 @@ put_devs:
 static void __exit vfio_pci_cleanup(void)
 {
pci_unregister_driver(&vfio_pci_driver);
-   vfio_pci_virqfd_exit();
+   vfio_virqfd_exit();
vfio_pci_uninit_perm_bits();
 }
 
@@ -1026,7 +1026,7 @@ static int __init vfio_pci_init(void)
return ret;
 
/* Start the virqfd cleanup handler */
-   ret = vfio_pci_virqfd_init();
+   ret = vfio_virqfd_init();
if (ret)
goto out_virqfd;
 
@@ -1038,7 +1038,7 @@ static int __init vfio_pci_init(void)
return 0;
 
 out_driver:
-   vfio_pci_virqfd_exit();
+   vfio_virqfd_exit();
 out_virqfd:
vfio_pci_uninit_perm_bits();
return ret;
diff --git a/drivers/vfio/pci/vfio_pci_intrs.c 
b/drivers/vfio/pci/vfio_pci_intrs.c
index 0a41833d..a5378d5 100644
--- a/drivers/vfio/pci/vfio_pci_intrs.c
+++ b/drivers/vfio/pci/vfio_pci_intrs.c
@@ -45,7 +45,7 @@ struct virqfd {
 
 static struct workqueue_struct *vfio_irqfd_cleanup_wq;
 
-int __init vfio_pci_virqfd_init(void)
+int __init vfio_virqfd_init(void)
 {
vfio_irqfd_cleanup_wq =
create_singlethread_workqueue("vfio-irqfd-cleanup");
@@ -55,7 +55,7 @@ int __init vfio_pci_virqfd_init(void)
return 0;
 }
 
-void vfio_pci_virqfd_exit(void)
+void vfio_virqfd_exit(void)
 {
destroy_workqueue(vfio_irqfd_cleanup_wq);
 }
diff --git a/drivers/vfio/pci/vfio_pci_private.h 
b/drivers/vfio/pci/vfio_pci_private.h
index 671c17a..2e2f0ea 100644
--- a/drivers/vfio/pci/vfio_pci_private.h
+++ b/drivers/vfio/pci/vfio_pci_private.h
@@ -86,8 +86,8 @@ extern ssize_t vfio_pci_vga_rw(struct vfio_pci_device *vdev, 
char __user *buf,
 extern int vfio_pci_init_perm_bits(void);
 extern void vfio_pci_uninit_perm_bits(void);
 
-extern int vfio_pci_virqfd_init(void);
-extern void vfio_pci_virqfd_exit(void);
+extern int vfio_virqfd_init(void);
+extern void vfio_virqfd_exit(void);
 
 extern int vfio_config_init(struct vfio_pci_device *vdev);
 extern void vfio_config_free(struct vfio_pci_device *vdev);
-- 
2.2.2

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


[PATCH v13 10/18] vfio/platform: trigger an interrupt via eventfd

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

This patch allows to set an eventfd for a platform device's interrupt,
and also to trigger the interrupt eventfd from userspace for testing.
Level sensitive interrupts are marked as maskable and are handled in
a later patch. Edge triggered interrupts are not advertised as maskable
and are implemented here using a simple and efficient IRQ handler.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: fix masked interrupt initialization]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_irq.c | 94 ++-
 drivers/vfio/platform/vfio_platform_private.h |  2 +
 2 files changed, 94 insertions(+), 2 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index df5c919..611ec80 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -39,12 +39,92 @@ static int vfio_platform_set_irq_unmask(struct 
vfio_platform_device *vdev,
return -EINVAL;
 }
 
+static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
+{
+   struct vfio_platform_irq *irq_ctx = dev_id;
+
+   eventfd_signal(irq_ctx->trigger, 1);
+
+   return IRQ_HANDLED;
+}
+
+static int vfio_set_trigger(struct vfio_platform_device *vdev, int index,
+   int fd, irq_handler_t handler)
+{
+   struct vfio_platform_irq *irq = &vdev->irqs[index];
+   struct eventfd_ctx *trigger;
+   int ret;
+
+   if (irq->trigger) {
+   free_irq(irq->hwirq, irq);
+   kfree(irq->name);
+   eventfd_ctx_put(irq->trigger);
+   irq->trigger = NULL;
+   }
+
+   if (fd < 0) /* Disable only */
+   return 0;
+
+   irq->name = kasprintf(GFP_KERNEL, "vfio-irq[%d](%s)",
+   irq->hwirq, vdev->name);
+   if (!irq->name)
+   return -ENOMEM;
+
+   trigger = eventfd_ctx_fdget(fd);
+   if (IS_ERR(trigger)) {
+   kfree(irq->name);
+   return PTR_ERR(trigger);
+   }
+
+   irq->trigger = trigger;
+
+   ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
+   if (ret) {
+   kfree(irq->name);
+   eventfd_ctx_put(trigger);
+   irq->trigger = NULL;
+   return ret;
+   }
+
+   return 0;
+}
+
 static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
 unsigned index, unsigned start,
 unsigned count, uint32_t flags,
 void *data)
 {
-   return -EINVAL;
+   struct vfio_platform_irq *irq = &vdev->irqs[index];
+   irq_handler_t handler;
+
+   if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
+   return -EINVAL; /* not implemented */
+   else
+   handler = vfio_irq_handler;
+
+   if (!count && (flags & VFIO_IRQ_SET_DATA_NONE))
+   return vfio_set_trigger(vdev, index, -1, handler);
+
+   if (start != 0 || count != 1)
+   return -EINVAL;
+
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD) {
+   int32_t fd = *(int32_t *)data;
+
+   return vfio_set_trigger(vdev, index, fd, handler);
+   }
+
+   if (flags & VFIO_IRQ_SET_DATA_NONE) {
+   handler(irq->hwirq, irq);
+
+   } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+   uint8_t trigger = *(uint8_t *)data;
+
+   if (trigger)
+   handler(irq->hwirq, irq);
+   }
+
+   return 0;
 }
 
 int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
@@ -90,7 +170,12 @@ int vfio_platform_irq_init(struct vfio_platform_device 
*vdev)
if (hwirq < 0)
goto err;
 
-   vdev->irqs[i].flags = 0;
+   vdev->irqs[i].flags = VFIO_IRQ_INFO_EVENTFD;
+
+   if (irq_get_trigger_type(hwirq) & IRQ_TYPE_LEVEL_MASK)
+   vdev->irqs[i].flags |= VFIO_IRQ_INFO_MASKABLE
+   | VFIO_IRQ_INFO_AUTOMASKED;
+
vdev->irqs[i].count = 1;
vdev->irqs[i].hwirq = hwirq;
}
@@ -105,6 +190,11 @@ err:
 
 void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
 {
+   int i;
+
+   for (i = 0; i < vdev->num_irqs; i++)
+   vfio_set_trigger(vdev, i, -1, NULL);
+
vdev->num_irqs = 0;
kfree(vdev->irqs);
 }
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
index b119a6c..aa01cc3 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -31,6 +31,8 @@ struc

[PATCH v13 11/18] vfio/platform: support for level sensitive interrupts

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

Level sensitive interrupts are exposed as maskable and automasked
interrupts and are masked and disabled automatically when they fire.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: Move masked interrupt initialization from "vfio/platform:
trigger an interrupt via eventfd"]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_irq.c | 103 +-
 drivers/vfio/platform/vfio_platform_private.h |   2 +
 2 files changed, 102 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index 611ec80..e0e6388 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,12 +23,59 @@
 
 #include "vfio_platform_private.h"
 
+static void vfio_platform_mask(struct vfio_platform_irq *irq_ctx)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&irq_ctx->lock, flags);
+
+   if (!irq_ctx->masked) {
+   disable_irq_nosync(irq_ctx->hwirq);
+   irq_ctx->masked = true;
+   }
+
+   spin_unlock_irqrestore(&irq_ctx->lock, flags);
+}
+
 static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
  unsigned index, unsigned start,
  unsigned count, uint32_t flags,
  void *data)
 {
-   return -EINVAL;
+   if (start != 0 || count != 1)
+   return -EINVAL;
+
+   if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+   return -EINVAL;
+
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+   return -EINVAL; /* not implemented yet */
+
+   if (flags & VFIO_IRQ_SET_DATA_NONE) {
+   vfio_platform_mask(&vdev->irqs[index]);
+
+   } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+   uint8_t mask = *(uint8_t *)data;
+
+   if (mask)
+   vfio_platform_mask(&vdev->irqs[index]);
+   }
+
+   return 0;
+}
+
+static void vfio_platform_unmask(struct vfio_platform_irq *irq_ctx)
+{
+   unsigned long flags;
+
+   spin_lock_irqsave(&irq_ctx->lock, flags);
+
+   if (irq_ctx->masked) {
+   enable_irq(irq_ctx->hwirq);
+   irq_ctx->masked = false;
+   }
+
+   spin_unlock_irqrestore(&irq_ctx->lock, flags);
 }
 
 static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
@@ -36,7 +83,50 @@ static int vfio_platform_set_irq_unmask(struct 
vfio_platform_device *vdev,
unsigned count, uint32_t flags,
void *data)
 {
-   return -EINVAL;
+   if (start != 0 || count != 1)
+   return -EINVAL;
+
+   if (!(vdev->irqs[index].flags & VFIO_IRQ_INFO_MASKABLE))
+   return -EINVAL;
+
+   if (flags & VFIO_IRQ_SET_DATA_EVENTFD)
+   return -EINVAL; /* not implemented yet */
+
+   if (flags & VFIO_IRQ_SET_DATA_NONE) {
+   vfio_platform_unmask(&vdev->irqs[index]);
+
+   } else if (flags & VFIO_IRQ_SET_DATA_BOOL) {
+   uint8_t unmask = *(uint8_t *)data;
+
+   if (unmask)
+   vfio_platform_unmask(&vdev->irqs[index]);
+   }
+
+   return 0;
+}
+
+static irqreturn_t vfio_automasked_irq_handler(int irq, void *dev_id)
+{
+   struct vfio_platform_irq *irq_ctx = dev_id;
+   unsigned long flags;
+   int ret = IRQ_NONE;
+
+   spin_lock_irqsave(&irq_ctx->lock, flags);
+
+   if (!irq_ctx->masked) {
+   ret = IRQ_HANDLED;
+
+   /* automask maskable interrupts */
+   disable_irq_nosync(irq_ctx->hwirq);
+   irq_ctx->masked = true;
+   }
+
+   spin_unlock_irqrestore(&irq_ctx->lock, flags);
+
+   if (ret == IRQ_HANDLED)
+   eventfd_signal(irq_ctx->trigger, 1);
+
+   return ret;
 }
 
 static irqreturn_t vfio_irq_handler(int irq, void *dev_id)
@@ -78,6 +168,7 @@ static int vfio_set_trigger(struct vfio_platform_device 
*vdev, int index,
 
irq->trigger = trigger;
 
+   irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
if (ret) {
kfree(irq->name);
@@ -86,6 +177,9 @@ static int vfio_set_trigger(struct vfio_platform_device 
*vdev, int index,
return ret;
}
 
+   if (!irq->masked)
+   enable_irq(irq->hwirq);
+
return 0;
 }
 
@@ -98,7 +192,7 @@ static int vfio_platform_set_irq_trigger(struct 
vfio_platform_device *vdev,
irq_handler_t handler;
 
if (vdev->irqs[index].flags & VFIO_IRQ_INFO_AUTOMASKED)
-   return -EINVAL; /* 

[PATCH v13 09/18] vfio/platform: initial interrupts support code

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

This patch is a skeleton for the VFIO_DEVICE_SET_IRQS IOCTL, around which
most IRQ functionality is implemented in VFIO.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/vfio_platform_common.c  | 52 +--
 drivers/vfio/platform/vfio_platform_irq.c | 59 +++
 drivers/vfio/platform/vfio_platform_private.h |  7 
 3 files changed, 115 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 908d510..abcff7a 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -205,10 +205,54 @@ static long vfio_platform_ioctl(void *device_data,
 
return copy_to_user((void __user *)arg, &info, minsz);
 
-   } else if (cmd == VFIO_DEVICE_SET_IRQS)
-   return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_SET_IRQS) {
+   struct vfio_irq_set hdr;
+   u8 *data = NULL;
+   int ret = 0;
+
+   minsz = offsetofend(struct vfio_irq_set, count);
+
+   if (copy_from_user(&hdr, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (hdr.argsz < minsz)
+   return -EINVAL;
+
+   if (hdr.index >= vdev->num_irqs)
+   return -EINVAL;
+
+   if (hdr.flags & ~(VFIO_IRQ_SET_DATA_TYPE_MASK |
+ VFIO_IRQ_SET_ACTION_TYPE_MASK))
+   return -EINVAL;
 
-   else if (cmd == VFIO_DEVICE_RESET)
+   if (!(hdr.flags & VFIO_IRQ_SET_DATA_NONE)) {
+   size_t size;
+
+   if (hdr.flags & VFIO_IRQ_SET_DATA_BOOL)
+   size = sizeof(uint8_t);
+   else if (hdr.flags & VFIO_IRQ_SET_DATA_EVENTFD)
+   size = sizeof(int32_t);
+   else
+   return -EINVAL;
+
+   if (hdr.argsz - minsz < size)
+   return -EINVAL;
+
+   data = memdup_user((void __user *)(arg + minsz), size);
+   if (IS_ERR(data))
+   return PTR_ERR(data);
+   }
+
+   mutex_lock(&vdev->igate);
+
+   ret = vfio_platform_set_irqs_ioctl(vdev, hdr.flags, hdr.index,
+  hdr.start, hdr.count, data);
+   mutex_unlock(&vdev->igate);
+   kfree(data);
+
+   return ret;
+
+   } else if (cmd == VFIO_DEVICE_RESET)
return -EINVAL;
 
return -ENOTTY;
@@ -458,6 +502,8 @@ int vfio_platform_probe_common(struct vfio_platform_device 
*vdev,
return ret;
}
 
+   mutex_init(&vdev->igate);
+
return 0;
 }
 EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
index c6c3ec1..df5c919 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -23,6 +23,56 @@
 
 #include "vfio_platform_private.h"
 
+static int vfio_platform_set_irq_mask(struct vfio_platform_device *vdev,
+ unsigned index, unsigned start,
+ unsigned count, uint32_t flags,
+ void *data)
+{
+   return -EINVAL;
+}
+
+static int vfio_platform_set_irq_unmask(struct vfio_platform_device *vdev,
+   unsigned index, unsigned start,
+   unsigned count, uint32_t flags,
+   void *data)
+{
+   return -EINVAL;
+}
+
+static int vfio_platform_set_irq_trigger(struct vfio_platform_device *vdev,
+unsigned index, unsigned start,
+unsigned count, uint32_t flags,
+void *data)
+{
+   return -EINVAL;
+}
+
+int vfio_platform_set_irqs_ioctl(struct vfio_platform_device *vdev,
+uint32_t flags, unsigned index, unsigned start,
+unsigned count, void *data)
+{
+   int (*func)(struct vfio_platform_device *vdev, unsigned index,
+   unsigned start, unsigned count, uint32_t flags,
+   void *data) = NULL;
+
+   switch (flags & VFIO_IRQ_SET_ACTION_TYPE_MASK) {
+   case VFIO_IRQ_SET_ACTION_MASK:
+   func = vfio_platform_set_irq_mask;
+   break;
+   case VFIO_IRQ_SET_ACTION_UNMASK:
+   func = vfio_platform_set_irq_unmask;
+   break;
+   case VFIO_IRQ_SET_ACTION_TRIGGER:
+   func = vfio_platform_set_irq_trigger;
+   break;

[PATCH v13 08/18] vfio/platform: return IRQ info

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

Return information for the interrupts exposed by the device.
This patch extends VFIO_DEVICE_GET_INFO with the number of IRQs
and enables VFIO_DEVICE_GET_IRQ_INFO.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/Makefile|  2 +-
 drivers/vfio/platform/vfio_platform_common.c  | 31 +---
 drivers/vfio/platform/vfio_platform_irq.c | 51 +++
 drivers/vfio/platform/vfio_platform_private.h | 10 ++
 4 files changed, 89 insertions(+), 5 deletions(-)
 create mode 100644 drivers/vfio/platform/vfio_platform_irq.c

diff --git a/drivers/vfio/platform/Makefile b/drivers/vfio/platform/Makefile
index 279862b..c6316cc 100644
--- a/drivers/vfio/platform/Makefile
+++ b/drivers/vfio/platform/Makefile
@@ -1,4 +1,4 @@
 
-vfio-platform-y := vfio_platform.o vfio_platform_common.o
+vfio-platform-y := vfio_platform.o vfio_platform_common.o vfio_platform_irq.o
 
 obj-$(CONFIG_VFIO_PLATFORM) += vfio-platform.o
diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index d7fe2c7..908d510 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -101,6 +101,7 @@ static void vfio_platform_release(void *device_data)
 
if (!(--vdev->refcnt)) {
vfio_platform_regions_cleanup(vdev);
+   vfio_platform_irq_cleanup(vdev);
}
 
mutex_unlock(&driver_lock);
@@ -122,6 +123,10 @@ static int vfio_platform_open(void *device_data)
ret = vfio_platform_regions_init(vdev);
if (ret)
goto err_reg;
+
+   ret = vfio_platform_irq_init(vdev);
+   if (ret)
+   goto err_irq;
}
 
vdev->refcnt++;
@@ -129,6 +134,8 @@ static int vfio_platform_open(void *device_data)
mutex_unlock(&driver_lock);
return 0;
 
+err_irq:
+   vfio_platform_regions_cleanup(vdev);
 err_reg:
mutex_unlock(&driver_lock);
module_put(THIS_MODULE);
@@ -154,7 +161,7 @@ static long vfio_platform_ioctl(void *device_data,
 
info.flags = vdev->flags;
info.num_regions = vdev->num_regions;
-   info.num_irqs = 0;
+   info.num_irqs = vdev->num_irqs;
 
return copy_to_user((void __user *)arg, &info, minsz);
 
@@ -179,10 +186,26 @@ static long vfio_platform_ioctl(void *device_data,
 
return copy_to_user((void __user *)arg, &info, minsz);
 
-   } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-   return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO) {
+   struct vfio_irq_info info;
+
+   minsz = offsetofend(struct vfio_irq_info, count);
+
+   if (copy_from_user(&info, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (info.argsz < minsz)
+   return -EINVAL;
+
+   if (info.index >= vdev->num_irqs)
+   return -EINVAL;
+
+   info.flags = vdev->irqs[info.index].flags;
+   info.count = vdev->irqs[info.index].count;
+
+   return copy_to_user((void __user *)arg, &info, minsz);
 
-   else if (cmd == VFIO_DEVICE_SET_IRQS)
+   } else if (cmd == VFIO_DEVICE_SET_IRQS)
return -EINVAL;
 
else if (cmd == VFIO_DEVICE_RESET)
diff --git a/drivers/vfio/platform/vfio_platform_irq.c 
b/drivers/vfio/platform/vfio_platform_irq.c
new file mode 100644
index 000..c6c3ec1
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -0,0 +1,51 @@
+/*
+ * VFIO platform devices interrupt handling
+ *
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+int vfio_platform_irq_init(struct vfio_platform_device *vdev)
+{
+   int cnt = 0, i;
+
+   while (vdev->get_irq(vdev, cnt) >= 0)
+   cnt++;
+
+   vdev->irqs = kcalloc(cnt, sizeof(struct vfio_platform_irq), GFP_KERNEL);
+   if (!vdev->irqs)
+   return -ENOMEM;
+
+   for (i = 0; i < cnt; i++) {
+   vdev->irqs[i].flags = 0;
+   vdev->irqs[i].count = 1;
+   }
+
+   vdev->num_irqs = cnt;
+
+   return 0;
+}
+
+void vfio_platform_irq_cleanup(struct vfio_platform_device *vdev)
+{
+   vdev->num_irqs = 0;
+   kfree(vdev->irqs);
+}
diff 

[PATCH v13 07/18] vfio/platform: support MMAP of MMIO regions

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

Allow to memory map the MMIO regions of the device so userspace can
directly access them. PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/vfio_platform_common.c | 65 
 1 file changed, 65 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 4df66f5..d7fe2c7 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -55,6 +55,16 @@ static int vfio_platform_regions_init(struct 
vfio_platform_device *vdev)
if (!(res->flags & IORESOURCE_READONLY))
vdev->regions[i].flags |=
VFIO_REGION_INFO_FLAG_WRITE;
+
+   /*
+* Only regions addressed with PAGE granularity may be
+* MMAPed securely.
+*/
+   if (!(vdev->regions[i].addr & ~PAGE_MASK) &&
+   !(vdev->regions[i].size & ~PAGE_MASK))
+   vdev->regions[i].flags |=
+   VFIO_REGION_INFO_FLAG_MMAP;
+
break;
case IORESOURCE_IO:
vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -334,8 +344,63 @@ static ssize_t vfio_platform_write(void *device_data, 
const char __user *buf,
return -EINVAL;
 }
 
+static int vfio_platform_mmap_mmio(struct vfio_platform_region region,
+  struct vm_area_struct *vma)
+{
+   u64 req_len, pgoff, req_start;
+
+   req_len = vma->vm_end - vma->vm_start;
+   pgoff = vma->vm_pgoff &
+   ((1U << (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+   req_start = pgoff << PAGE_SHIFT;
+
+   if (region.size < PAGE_SIZE || req_start + req_len > region.size)
+   return -EINVAL;
+
+   vma->vm_page_prot = pgprot_noncached(vma->vm_page_prot);
+   vma->vm_pgoff = (region.addr >> PAGE_SHIFT) + pgoff;
+
+   return remap_pfn_range(vma, vma->vm_start, vma->vm_pgoff,
+  req_len, vma->vm_page_prot);
+}
+
 static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
 {
+   struct vfio_platform_device *vdev = device_data;
+   unsigned int index;
+
+   index = vma->vm_pgoff >> (VFIO_PLATFORM_OFFSET_SHIFT - PAGE_SHIFT);
+
+   if (vma->vm_end < vma->vm_start)
+   return -EINVAL;
+   if (!(vma->vm_flags & VM_SHARED))
+   return -EINVAL;
+   if (index >= vdev->num_regions)
+   return -EINVAL;
+   if (vma->vm_start & ~PAGE_MASK)
+   return -EINVAL;
+   if (vma->vm_end & ~PAGE_MASK)
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_MMAP))
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ)
+   && (vma->vm_flags & VM_READ))
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_WRITE)
+   && (vma->vm_flags & VM_WRITE))
+   return -EINVAL;
+
+   vma->vm_private_data = vdev;
+
+   if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+   return vfio_platform_mmap_mmio(vdev->regions[index], vma);
+
+   else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+   return -EINVAL; /* not implemented */
+
return -EINVAL;
 }
 
-- 
2.2.2

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


[PATCH v13 06/18] vfio/platform: read and write support for the device fd

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

VFIO returns a file descriptor which we can use to manipulate the memory
regions of the device. Usually, the user will mmap memory regions that are
addressable on page boundaries, however for memory regions where this is
not the case we cannot provide mmap functionality due to security concerns.
For this reason we also allow to use read and write functions to the file
descriptor pointing to the memory regions.

We implement this functionality only for MMIO regions of platform devices;
PIO regions are not being handled at this point.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/vfio_platform_common.c  | 150 ++
 drivers/vfio/platform/vfio_platform_private.h |   1 +
 2 files changed, 151 insertions(+)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 47f6309..4df66f5 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -51,6 +51,10 @@ static int vfio_platform_regions_init(struct 
vfio_platform_device *vdev)
switch (resource_type(res)) {
case IORESOURCE_MEM:
vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+   vdev->regions[i].flags |= VFIO_REGION_INFO_FLAG_READ;
+   if (!(res->flags & IORESOURCE_READONLY))
+   vdev->regions[i].flags |=
+   VFIO_REGION_INFO_FLAG_WRITE;
break;
case IORESOURCE_IO:
vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
@@ -70,6 +74,11 @@ err:
 
 static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
 {
+   int i;
+
+   for (i = 0; i < vdev->num_regions; i++)
+   iounmap(vdev->regions[i].ioaddr);
+
vdev->num_regions = 0;
kfree(vdev->regions);
 }
@@ -172,15 +181,156 @@ static long vfio_platform_ioctl(void *device_data,
return -ENOTTY;
 }
 
+static ssize_t vfio_platform_read_mmio(struct vfio_platform_region reg,
+  char __user *buf, size_t count,
+  loff_t off)
+{
+   unsigned int done = 0;
+
+   if (!reg.ioaddr) {
+   reg.ioaddr =
+   ioremap_nocache(reg.addr, reg.size);
+
+   if (!reg.ioaddr)
+   return -ENOMEM;
+   }
+
+   while (count) {
+   size_t filled;
+
+   if (count >= 4 && !(off % 4)) {
+   u32 val;
+
+   val = ioread32(reg.ioaddr + off);
+   if (copy_to_user(buf, &val, 4))
+   goto err;
+
+   filled = 4;
+   } else if (count >= 2 && !(off % 2)) {
+   u16 val;
+
+   val = ioread16(reg.ioaddr + off);
+   if (copy_to_user(buf, &val, 2))
+   goto err;
+
+   filled = 2;
+   } else {
+   u8 val;
+
+   val = ioread8(reg.ioaddr + off);
+   if (copy_to_user(buf, &val, 1))
+   goto err;
+
+   filled = 1;
+   }
+
+
+   count -= filled;
+   done += filled;
+   off += filled;
+   buf += filled;
+   }
+
+   return done;
+err:
+   return -EFAULT;
+}
+
 static ssize_t vfio_platform_read(void *device_data, char __user *buf,
  size_t count, loff_t *ppos)
 {
+   struct vfio_platform_device *vdev = device_data;
+   unsigned int index = VFIO_PLATFORM_OFFSET_TO_INDEX(*ppos);
+   loff_t off = *ppos & VFIO_PLATFORM_OFFSET_MASK;
+
+   if (index >= vdev->num_regions)
+   return -EINVAL;
+
+   if (!(vdev->regions[index].flags & VFIO_REGION_INFO_FLAG_READ))
+   return -EINVAL;
+
+   if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_MMIO)
+   return vfio_platform_read_mmio(vdev->regions[index],
+   buf, count, off);
+   else if (vdev->regions[index].type & VFIO_PLATFORM_REGION_TYPE_PIO)
+   return -EINVAL; /* not implemented */
+
return -EINVAL;
 }
 
+static ssize_t vfio_platform_write_mmio(struct vfio_platform_region reg,
+   const char __user *buf, size_t count,
+   loff_t off)
+{
+   unsigned int done = 0;
+
+   if (!reg.ioaddr) {
+   reg.ioaddr =
+   ioremap_nocache(reg.addr, reg.size);
+
+   if (!reg.ioaddr)
+   return -ENOMEM;
+   }
+
+   while (count) {
+   size_t filled;
+
+   if (count 

[PATCH v13 05/18] vfio/platform: return info for device memory mapped IO regions

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

This patch enables the IOCTLs VFIO_DEVICE_GET_REGION_INFO ioctl call,
which allows the user to learn about the available MMIO resources of
a device.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/vfio_platform_common.c  | 106 +-
 drivers/vfio/platform/vfio_platform_private.h |  22 ++
 2 files changed, 124 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index c2f853a..47f6309 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -23,17 +23,97 @@
 
 #include "vfio_platform_private.h"
 
+static DEFINE_MUTEX(driver_lock);
+
+static int vfio_platform_regions_init(struct vfio_platform_device *vdev)
+{
+   int cnt = 0, i;
+
+   while (vdev->get_resource(vdev, cnt))
+   cnt++;
+
+   vdev->regions = kcalloc(cnt, sizeof(struct vfio_platform_region),
+   GFP_KERNEL);
+   if (!vdev->regions)
+   return -ENOMEM;
+
+   for (i = 0; i < cnt;  i++) {
+   struct resource *res =
+   vdev->get_resource(vdev, i);
+
+   if (!res)
+   goto err;
+
+   vdev->regions[i].addr = res->start;
+   vdev->regions[i].size = resource_size(res);
+   vdev->regions[i].flags = 0;
+
+   switch (resource_type(res)) {
+   case IORESOURCE_MEM:
+   vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_MMIO;
+   break;
+   case IORESOURCE_IO:
+   vdev->regions[i].type = VFIO_PLATFORM_REGION_TYPE_PIO;
+   break;
+   default:
+   goto err;
+   }
+   }
+
+   vdev->num_regions = cnt;
+
+   return 0;
+err:
+   kfree(vdev->regions);
+   return -EINVAL;
+}
+
+static void vfio_platform_regions_cleanup(struct vfio_platform_device *vdev)
+{
+   vdev->num_regions = 0;
+   kfree(vdev->regions);
+}
+
 static void vfio_platform_release(void *device_data)
 {
+   struct vfio_platform_device *vdev = device_data;
+
+   mutex_lock(&driver_lock);
+
+   if (!(--vdev->refcnt)) {
+   vfio_platform_regions_cleanup(vdev);
+   }
+
+   mutex_unlock(&driver_lock);
+
module_put(THIS_MODULE);
 }
 
 static int vfio_platform_open(void *device_data)
 {
+   struct vfio_platform_device *vdev = device_data;
+   int ret;
+
if (!try_module_get(THIS_MODULE))
return -ENODEV;
 
+   mutex_lock(&driver_lock);
+
+   if (!vdev->refcnt) {
+   ret = vfio_platform_regions_init(vdev);
+   if (ret)
+   goto err_reg;
+   }
+
+   vdev->refcnt++;
+
+   mutex_unlock(&driver_lock);
return 0;
+
+err_reg:
+   mutex_unlock(&driver_lock);
+   module_put(THIS_MODULE);
+   return ret;
 }
 
 static long vfio_platform_ioctl(void *device_data,
@@ -54,15 +134,33 @@ static long vfio_platform_ioctl(void *device_data,
return -EINVAL;
 
info.flags = vdev->flags;
-   info.num_regions = 0;
+   info.num_regions = vdev->num_regions;
info.num_irqs = 0;
 
return copy_to_user((void __user *)arg, &info, minsz);
 
-   } else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
-   return -EINVAL;
+   } else if (cmd == VFIO_DEVICE_GET_REGION_INFO) {
+   struct vfio_region_info info;
+
+   minsz = offsetofend(struct vfio_region_info, offset);
+
+   if (copy_from_user(&info, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (info.argsz < minsz)
+   return -EINVAL;
+
+   if (info.index >= vdev->num_regions)
+   return -EINVAL;
+
+   /* map offset to the physical address  */
+   info.offset = VFIO_PLATFORM_INDEX_TO_OFFSET(info.index);
+   info.size = vdev->regions[info.index].size;
+   info.flags = vdev->regions[info.index].flags;
+
+   return copy_to_user((void __user *)arg, &info, minsz);
 
-   else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+   } else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
return -EINVAL;
 
else if (cmd == VFIO_DEVICE_SET_IRQS)
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
index c046988..3551f6d 100644
--- a/drivers/vfio/platform/vfio_platform_private.h
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -18,7 +18,29 @@
 #include 
 #include 
 
+#define VFIO_PLATFORM_OFFSET_SHIFT   40
+#define VFIO_PLATFORM_OFFSET_MASK (((u64)(1) << VFIO_PLATFORM_OFFSET_SHIFT) - 
1)
+
+#define VFIO_PLATFORM_OFFSET_TO_INDEX(off) \
+   (off

[PATCH v13 04/18] vfio/platform: return info for bound device

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

A VFIO userspace driver will start by opening the VFIO device
that corresponds to an IOMMU group, and will use the ioctl interface
to get the basic device info, such as number of memory regions and
interrupts, and their properties. This patch enables the
VFIO_DEVICE_GET_INFO ioctl call.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: added include in vfio_platform_common.c]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c | 24 +---
 1 file changed, 21 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
index 34d023b..c2f853a 100644
--- a/drivers/vfio/platform/vfio_platform_common.c
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -18,6 +18,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 
 #include "vfio_platform_private.h"
@@ -38,10 +39,27 @@ static int vfio_platform_open(void *device_data)
 static long vfio_platform_ioctl(void *device_data,
unsigned int cmd, unsigned long arg)
 {
-   if (cmd == VFIO_DEVICE_GET_INFO)
-   return -EINVAL;
+   struct vfio_platform_device *vdev = device_data;
+   unsigned long minsz;
+
+   if (cmd == VFIO_DEVICE_GET_INFO) {
+   struct vfio_device_info info;
+
+   minsz = offsetofend(struct vfio_device_info, num_irqs);
+
+   if (copy_from_user(&info, (void __user *)arg, minsz))
+   return -EFAULT;
+
+   if (info.argsz < minsz)
+   return -EINVAL;
+
+   info.flags = vdev->flags;
+   info.num_regions = 0;
+   info.num_irqs = 0;
+
+   return copy_to_user((void __user *)arg, &info, minsz);
 
-   else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+   } else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
return -EINVAL;
 
else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
-- 
2.2.2

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


[PATCH v13 02/18] vfio: platform: probe to devices on the platform bus

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

Driver to bind to Linux platform devices, and callbacks to discover their
resources to be used by the main VFIO PLATFORM code.

Signed-off-by: Antonios Motakis 
---
 drivers/vfio/platform/vfio_platform.c | 103 ++
 include/uapi/linux/vfio.h |   1 +
 2 files changed, 104 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform.c

diff --git a/drivers/vfio/platform/vfio_platform.c 
b/drivers/vfio/platform/vfio_platform.c
new file mode 100644
index 000..cef645c
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform.c
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+#define DRIVER_VERSION  "0.10"
+#define DRIVER_AUTHOR   "Antonios Motakis "
+#define DRIVER_DESC "VFIO for platform devices - User Level meta-driver"
+
+/* probing devices from the linux platform bus */
+
+static struct resource *get_platform_resource(struct vfio_platform_device 
*vdev,
+ int num)
+{
+   struct platform_device *dev = (struct platform_device *) vdev->opaque;
+   int i;
+
+   for (i = 0; i < dev->num_resources; i++) {
+   struct resource *r = &dev->resource[i];
+
+   if (resource_type(r) & (IORESOURCE_MEM|IORESOURCE_IO)) {
+   if (!num)
+   return r;
+
+   num--;
+   }
+   }
+   return NULL;
+}
+
+static int get_platform_irq(struct vfio_platform_device *vdev, int i)
+{
+   struct platform_device *pdev = (struct platform_device *) vdev->opaque;
+
+   return platform_get_irq(pdev, i);
+}
+
+static int vfio_platform_probe(struct platform_device *pdev)
+{
+   struct vfio_platform_device *vdev;
+   int ret;
+
+   vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
+   if (!vdev)
+   return -ENOMEM;
+
+   vdev->opaque = (void *) pdev;
+   vdev->name = pdev->name;
+   vdev->flags = VFIO_DEVICE_FLAGS_PLATFORM;
+   vdev->get_resource = get_platform_resource;
+   vdev->get_irq = get_platform_irq;
+
+   ret = vfio_platform_probe_common(vdev, &pdev->dev);
+   if (ret)
+   kfree(vdev);
+
+   return ret;
+}
+
+static int vfio_platform_remove(struct platform_device *pdev)
+{
+   struct vfio_platform_device *vdev;
+
+   vdev = vfio_platform_remove_common(&pdev->dev);
+   if (vdev) {
+   kfree(vdev);
+   return 0;
+   }
+
+   return -EINVAL;
+}
+
+static struct platform_driver vfio_platform_driver = {
+   .probe  = vfio_platform_probe,
+   .remove = vfio_platform_remove,
+   .driver = {
+   .name   = "vfio-platform",
+   .owner  = THIS_MODULE,
+   },
+};
+
+module_platform_driver(vfio_platform_driver);
+
+MODULE_VERSION(DRIVER_VERSION);
+MODULE_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 9ade02b..4e93a97 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -159,6 +159,7 @@ struct vfio_device_info {
__u32   flags;
 #define VFIO_DEVICE_FLAGS_RESET(1 << 0)/* Device supports 
reset */
 #define VFIO_DEVICE_FLAGS_PCI  (1 << 1)/* vfio-pci device */
+#define VFIO_DEVICE_FLAGS_PLATFORM (1 << 2)/* vfio-platform device */
__u32   num_regions;/* Max region index + 1 */
__u32   num_irqs;   /* Max IRQ index + 1 */
 };
-- 
2.2.2

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


[PATCH v13 01/18] vfio/platform: initial skeleton of VFIO support for platform devices

2015-01-30 Thread Baptiste Reynal
From: Antonios Motakis 

This patch forms the common skeleton code for platform devices support
with VFIO. This will include the core functionality of VFIO_PLATFORM,
however binding to the device and discovering the device resources will
be done with the help of a separate file where any Linux platform bus
specific code will reside.

This will allow us to implement support for also discovering AMBA devices
and their resources, but still reuse a large part of the VFIO_PLATFORM
implementation.

Signed-off-by: Antonios Motakis 
[Baptiste Reynal: added includes in vfio_platform_private.h]
Signed-off-by: Baptiste Reynal 
---
 drivers/vfio/platform/vfio_platform_common.c  | 121 ++
 drivers/vfio/platform/vfio_platform_private.h |  39 +
 2 files changed, 160 insertions(+)
 create mode 100644 drivers/vfio/platform/vfio_platform_common.c
 create mode 100644 drivers/vfio/platform/vfio_platform_private.h

diff --git a/drivers/vfio/platform/vfio_platform_common.c 
b/drivers/vfio/platform/vfio_platform_common.c
new file mode 100644
index 000..34d023b
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_common.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "vfio_platform_private.h"
+
+static void vfio_platform_release(void *device_data)
+{
+   module_put(THIS_MODULE);
+}
+
+static int vfio_platform_open(void *device_data)
+{
+   if (!try_module_get(THIS_MODULE))
+   return -ENODEV;
+
+   return 0;
+}
+
+static long vfio_platform_ioctl(void *device_data,
+   unsigned int cmd, unsigned long arg)
+{
+   if (cmd == VFIO_DEVICE_GET_INFO)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_GET_REGION_INFO)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_GET_IRQ_INFO)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_SET_IRQS)
+   return -EINVAL;
+
+   else if (cmd == VFIO_DEVICE_RESET)
+   return -EINVAL;
+
+   return -ENOTTY;
+}
+
+static ssize_t vfio_platform_read(void *device_data, char __user *buf,
+ size_t count, loff_t *ppos)
+{
+   return -EINVAL;
+}
+
+static ssize_t vfio_platform_write(void *device_data, const char __user *buf,
+  size_t count, loff_t *ppos)
+{
+   return -EINVAL;
+}
+
+static int vfio_platform_mmap(void *device_data, struct vm_area_struct *vma)
+{
+   return -EINVAL;
+}
+
+static const struct vfio_device_ops vfio_platform_ops = {
+   .name   = "vfio-platform",
+   .open   = vfio_platform_open,
+   .release= vfio_platform_release,
+   .ioctl  = vfio_platform_ioctl,
+   .read   = vfio_platform_read,
+   .write  = vfio_platform_write,
+   .mmap   = vfio_platform_mmap,
+};
+
+int vfio_platform_probe_common(struct vfio_platform_device *vdev,
+  struct device *dev)
+{
+   struct iommu_group *group;
+   int ret;
+
+   if (!vdev)
+   return -EINVAL;
+
+   group = iommu_group_get(dev);
+   if (!group) {
+   pr_err("VFIO: No IOMMU group for device %s\n", vdev->name);
+   return -EINVAL;
+   }
+
+   ret = vfio_add_group_dev(dev, &vfio_platform_ops, vdev);
+   if (ret) {
+   iommu_group_put(group);
+   return ret;
+   }
+
+   return 0;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_probe_common);
+
+struct vfio_platform_device *vfio_platform_remove_common(struct device *dev)
+{
+   struct vfio_platform_device *vdev;
+
+   vdev = vfio_del_group_dev(dev);
+   if (vdev)
+   iommu_group_put(dev->iommu_group);
+
+   return vdev;
+}
+EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
diff --git a/drivers/vfio/platform/vfio_platform_private.h 
b/drivers/vfio/platform/vfio_platform_private.h
new file mode 100644
index 000..c046988
--- /dev/null
+++ b/drivers/vfio/platform/vfio_platform_private.h
@@ -0,0 +1,39 @@
+/*
+ * Copyright (C) 2013 - Virtual Open Systems
+ * Author: Antonios Motakis 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License, version 2, as
+ * published by the Free Software Foundation.
+ *
+ * This program is

[PATCH v13 00/18] VFIO support for platform devices

2015-01-30 Thread Baptiste Reynal
This patch series aims to implement VFIO support for platform devices that
reside behind an IOMMU. Examples of such devices are devices behind an ARM
SMMU, or behind a Samsung Exynos System MMU.

The API used is based on the existing VFIO API that is also used with PCI
devices. Only devices that include a basic set of IRQs and memory regions are
targeted; devices with complex relationships with other devices on a device
tree are not taken into account at this stage.

This patch series may be applied on the following series/patches:
 - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with VFIO_IOMMU_TYPE1

A copy can be cloned from the branch vfio-platform-v13 at:
g...@github.com:virtualopensystems/linux-kvm-arm.git

Changes since v12:
 - Reorder chunks to be bisect-able
Changes since v11:
 - Drop support for ARM AMBA devices
 - vfio_platform_private.h is now self-contained
 - Fix masked IRQ initialization
Changes since v10:
 - Check if interrupt is already masked when setting a new trigger
 - Fixed kasprintf with unchecked return value in VFIO AMBA driver
Changes since v9:
 - Reworked the splitting of the patches that decouple virqfd from PCI
 - Some styling issues and typos
 - Removed superfluous includes
 - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
 - Several other cleanups and fixes
Changes since v8:
 - Separate irq handler for edge and level triggered interrupts
 - Mutex based lock for VFIO fd open/release
 - Fixed bug where the first region of a platform device wasn't exposed
 - Read only regions can be MMAPed only read only
 - Code cleanups
Changes since v7:
 - Some initial placeholder functionality for PIO resources
 - Cleaned up code for IRQ triggering, masking and unmasking
 - Some functionality has been removed from this series and posted separately:
   - VFIO_IOMMU_TYPE1 support for ARM SMMUs
   - IOMMU NOEXEC patches
   - driver_override functionality for AMBA devices
 - Several fixes
Changes since v6:
 - Integrated support for AMBA devices
 - Numerous cleanups and fixes
Changes since v5:
 - Full eventfd support for IRQ masking and unmasking.
 - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
 - Other fixes based on reviewer comments.
Changes since v4:
 - Use static offsets for each region in the VFIO device fd
 - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
   availability via IOMMU_CAP_DMA_EXEC
 - Rebased on VFIO multi domain support:
   - IOMMU_EXEC is now available if at least one IOMMU in the container
 supports it
   - Expose IOMMU_EXEC if available via the capability VFIO_IOMMU_PROT_EXEC
 - Some bug fixes
Changes since v3:
 - Use Kim Phillips' driver_probe_device()
Changes since v2:
 - Fixed Read/Write and MMAP on device regions
 - Removed dependency on Device Tree
 - Interrupts support
 - Interrupt masking/unmasking
 - Automask level sensitive interrupts
 - Introduced VFIO_DMA_MAP_FLAG_EXEC
 - Code clean ups

Antonios Motakis (18):
  vfio/platform: initial skeleton of VFIO support for platform devices
  vfio: platform: probe to devices on the platform bus
  vfio: platform: add the VFIO PLATFORM module to Kconfig
  vfio/platform: return info for bound device
  vfio/platform: return info for device memory mapped IO regions
  vfio/platform: read and write support for the device fd
  vfio/platform: support MMAP of MMIO regions
  vfio/platform: return IRQ info
  vfio/platform: initial interrupts support code
  vfio/platform: trigger an interrupt via eventfd
  vfio/platform: support for level sensitive interrupts
  vfio: add a vfio_ prefix to virqfd_enable and virqfd_disable and
export
  vfio: virqfd: rename vfio_pci_virqfd_init and vfio_pci_virqfd_exit
  vfio: add local lock for virqfd instead of depending on VFIO PCI
  vfio: pass an opaque pointer on virqfd initialization
  vfio: move eventfd support code for VFIO_PCI to a separate file
  vfio: initialize the virqfd workqueue in VFIO generic code
  vfio/platform: implement IRQ masking/unmasking via an eventfd

 drivers/vfio/Kconfig  |   1 +
 drivers/vfio/Makefile |   5 +-
 drivers/vfio/pci/vfio_pci.c   |   8 -
 drivers/vfio/pci/vfio_pci_intrs.c | 238 +---
 drivers/vfio/pci/vfio_pci_private.h   |   3 -
 drivers/vfio/platform/Kconfig |   9 +
 drivers/vfio/platform/Makefile|   4 +
 drivers/vfio/platform/vfio_platform.c | 103 +
 drivers/vfio/platform/vfio_platform_common.c  | 521 ++
 drivers/vfio/platform/vfio_platform_irq.c | 336 +
 drivers/vfio/platform/vfio_platform_private.h |  85 +
 drivers/vfio/vfio.c   |   8 +
 drivers/vfio/virqfd.c | 213 +++
 include/linux/vfio.h  |  27 ++
 include/uapi/linux/vfio.h |   1 +
 15 files changed, 1326 insertions(+), 236 deletions(-)
 create mode 10064

Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices

2015-01-20 Thread Baptiste Reynal
This fix should work, in a more elegant way. Could you confirm ?

I'm sorry I don't have any means to reproduce the bug on my side ...

Thanks,
Baptiste

diff --git a/drivers/vfio/platform/vfio_platform_irq.c
b/drivers/vfio/platform/vfio_platform_irq.c
index 6ade36b..f5f3de0 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -208,6 +208,7 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,

irq->trigger = trigger;

+   irq_set_status_flags(irq->hwirq, IRQ_NOAUTOEN);
ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
if (ret) {
kfree(irq->name);
@@ -216,12 +217,8 @@ static int vfio_set_trigger(struct
vfio_platform_device *vdev, int index,
return ret;
}

-   /* if the IRQ has been masked by the user before setting an eventfd,
-* then we need to make sure it is properly disabled */
-   spin_lock_irqsave(&irq->lock, flags);
-   if (irq->masked)
-   disable_irq_nosync(irq->hwirq);
-   spin_unlock_irqrestore(&irq->lock, flags);
+   if (!irq->masked)
+   enable_irq(irq->hwirq);

return 0;
 }

On Mon, Jan 19, 2015 at 7:09 PM, Eric Auger  wrote:

> Hi Baptiste,
>
> yes it fixes the issue in my use case.
>
> Best Regards
>
> Eric
>
> On 01/19/2015 06:00 PM, Baptiste Reynal wrote:
> > Hi Eric,
> >
> > Thanks for taking time about this issue. I agree with you, there is a
> > problem here. While I think on a better fix and to be sure the problem
> > is here, may you try this patch and tell me if the problem is solved ?
> > (This should work as the automasked_irq_handler doesn't do anything if
> > the IRQ is masked).
> >
> > If you have a suggestion on a fix, you're welcome :)
> >
> > diff --git a/drivers/vfio/platform/vfio_platform_irq.c
> > b/drivers/vfio/platform/vfio_platform_irq.c
> > index 6ade36b..c9bac80 100644
> > --- a/drivers/vfio/platform/vfio_platform_irq.c
> > +++ b/drivers/vfio/platform/vfio_platform_irq.c
> > @@ -184,6 +184,7 @@ static int vfio_set_trigger(struct
> > vfio_platform_device *vdev, int index,
> > struct eventfd_ctx *trigger;
> > unsigned long flags;
> > int ret;
> > +   bool masked;
> >
> > if (irq->trigger) {
> > free_irq(irq->hwirq, irq);
> > @@ -208,6 +209,8 @@ static int vfio_set_trigger(struct
> > vfio_platform_device *vdev, int index,
> >
> > irq->trigger = trigger;
> >
> > +   masked = irq->masked;
> > +
> > ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
> > if (ret) {
> > kfree(irq->name);
> > @@ -219,7 +222,7 @@ static int vfio_set_trigger(struct
> > vfio_platform_device *vdev, int index,
> > /* if the IRQ has been masked by the user before setting an
> eventfd,
> >  * then we need to make sure it is properly disabled */
> > spin_lock_irqsave(&irq->lock, flags);
> > -   if (irq->masked)
> > +   if (masked)
> > disable_irq_nosync(irq->hwirq);
> > spin_unlock_irqrestore(&irq->lock, flags);
> >
> > On Mon, Jan 19, 2015 at 1:27 PM, Eric Auger  > <mailto:eric.au...@linaro.org>> wrote:
> >
> > Hi Baptiste,
> >
> > I think what happens on the second qemu run is:
> >
> > an IRQ hits immediatly after request_irq
> > automasked handler sets masked = true
> > in vfio_set_trigger following condition becomes true
> > if (irq->masked)
> > disable_irq_nosync(irq->hwirq);
> > IRQ is disabled twice, in handler and in vfio_set_trigger while
> there is
> > a single enable in resamplefd handler.
> > To me you should prevent from entering ISR between request_irq and
> > disable_irq.
> >
> > It does not happen on the first run because no IRQ hit.
> >
> > Please let me know if you share this understanding.
> >
> > Best Regards
> >
> > Eric
> >
> > On 01/19/2015 11:17 AM, Eric Auger wrote:
> > > Hi Baptiste,
> > >
> > > sorry I was off on Friday. you're right I missed the masked field
> was
> > > reset on init. Nethertheless with current QEMU VFIO code, IRQ runs
> on
> > > the first run and not on the second one. I investigate on my side
> ...
> > >
> > > Best Regards
> &

Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices

2015-01-19 Thread Baptiste Reynal
Hi Eric,

Thanks for taking time about this issue. I agree with you, there is a
problem here. While I think on a better fix and to be sure the problem is
here, may you try this patch and tell me if the problem is solved ? (This
should work as the automasked_irq_handler doesn't do anything if the IRQ is
masked).

If you have a suggestion on a fix, you're welcome :)

diff --git a/drivers/vfio/platform/vfio_platform_irq.c
b/drivers/vfio/platform/vfio_platform_irq.c
index 6ade36b..c9bac80 100644
--- a/drivers/vfio/platform/vfio_platform_irq.c
+++ b/drivers/vfio/platform/vfio_platform_irq.c
@@ -184,6 +184,7 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,
struct eventfd_ctx *trigger;
unsigned long flags;
int ret;
+   bool masked;

if (irq->trigger) {
free_irq(irq->hwirq, irq);
@@ -208,6 +209,8 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,

irq->trigger = trigger;

+   masked = irq->masked;
+
ret = request_irq(irq->hwirq, handler, 0, irq->name, irq);
if (ret) {
kfree(irq->name);
@@ -219,7 +222,7 @@ static int vfio_set_trigger(struct vfio_platform_device
*vdev, int index,
/* if the IRQ has been masked by the user before setting an eventfd,
 * then we need to make sure it is properly disabled */
spin_lock_irqsave(&irq->lock, flags);
-   if (irq->masked)
+   if (masked)
disable_irq_nosync(irq->hwirq);
spin_unlock_irqrestore(&irq->lock, flags);

On Mon, Jan 19, 2015 at 1:27 PM, Eric Auger  wrote:

> Hi Baptiste,
>
> I think what happens on the second qemu run is:
>
> an IRQ hits immediatly after request_irq
> automasked handler sets masked = true
> in vfio_set_trigger following condition becomes true
> if (irq->masked)
> disable_irq_nosync(irq->hwirq);
> IRQ is disabled twice, in handler and in vfio_set_trigger while there is
> a single enable in resamplefd handler.
> To me you should prevent from entering ISR between request_irq and
> disable_irq.
>
> It does not happen on the first run because no IRQ hit.
>
> Please let me know if you share this understanding.
>
> Best Regards
>
> Eric
>
> On 01/19/2015 11:17 AM, Eric Auger wrote:
> > Hi Baptiste,
> >
> > sorry I was off on Friday. you're right I missed the masked field was
> > reset on init. Nethertheless with current QEMU VFIO code, IRQ runs on
> > the first run and not on the second one. I investigate on my side ...
> >
> > Best Regards
> >
> > Eric
> >
> >
> >
> >
> > On 01/16/2015 02:25 PM, Baptiste Reynal wrote:
> >> Hello Eric,
> >>
> >> I'm not sure I understand the issue here. I tried to reproduce the bug
> >> by triggering an interrupt without unmasking it, but the interrupt is
> >> unmasked when the program access to the device (vfio_platform_open
> >> reinit IRQs).
> >>
> >> May I have more details on the bug ?
> >>
> >> Thanks
> >>
> >> On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis
> >>  >> <mailto:a.mota...@virtualopensystems.com>> wrote:
> >>
> >> On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger  >> <mailto:eric.au...@linaro.org>> wrote:
> >> > Hi Antonios,
> >> >
> >> > when moving to 3.19rc3 I observe a regression with my xgmac use
> case
> >> > (real-time change?).
> >> >
> >> > I guess what happens is when I kill a first qemu session, guest
> does not
> >> > have time to complete the virtual IRQ and the unmask is not
> performed by
> >> > the virqfd handler. When starting a new QEMU session, the irqfd
> >> > signalling is put in place again but since the masked field is
> set, the
> >> > IRQ is left unmasked (v11 modification in vfio_set_trigger).
> >> >
> >> > The problem is that we don't discriminate between user mask
> action and
> >> > automasked handler action. In case the user did not mask, I think
> we
> >> > should reset the masked field when doing the free_irq. What do
> you think?
> >>
> >> Hello Eric,
> >>
> >> I agree, we should reset the masked field for future users.
> >>
> >> Best regards
> >> Antonios
> >>
> >> >
> >> > Best Regards
> >> >
> >> > Eric
> >> >
> >> > On 01/06/2015 11:48 AM, 

Re: [PATCH v11 00/20] VFIO support for platform and ARM AMBA devices

2015-01-16 Thread Baptiste Reynal
Hello Eric,

I'm not sure I understand the issue here. I tried to reproduce the bug by
triggering an interrupt without unmasking it, but the interrupt is unmasked
when the program access to the device (vfio_platform_open reinit IRQs).

May I have more details on the bug ?

Thanks

On Fri, Jan 9, 2015 at 12:33 PM, Antonios Motakis <
a.mota...@virtualopensystems.com> wrote:

> On Fri, Jan 9, 2015 at 9:39 AM, Eric Auger  wrote:
> > Hi Antonios,
> >
> > when moving to 3.19rc3 I observe a regression with my xgmac use case
> > (real-time change?).
> >
> > I guess what happens is when I kill a first qemu session, guest does not
> > have time to complete the virtual IRQ and the unmask is not performed by
> > the virqfd handler. When starting a new QEMU session, the irqfd
> > signalling is put in place again but since the masked field is set, the
> > IRQ is left unmasked (v11 modification in vfio_set_trigger).
> >
> > The problem is that we don't discriminate between user mask action and
> > automasked handler action. In case the user did not mask, I think we
> > should reset the masked field when doing the free_irq. What do you think?
>
> Hello Eric,
>
> I agree, we should reset the masked field for future users.
>
> Best regards
> Antonios
>
> >
> > Best Regards
> >
> > Eric
> >
> > On 01/06/2015 11:48 AM, Antonios Motakis wrote:
> >> This patch series aims to implement VFIO support for platform devices
> that
> >> reside behind an IOMMU. Examples of such devices are devices behind an
> ARM
> >> SMMU, or behind a Samsung Exynos System MMU.
> >>
> >> The API used is based on the existing VFIO API that is also used with
> PCI
> >> devices. Only devices that include a basic set of IRQs and memory
> regions are
> >> targeted; devices with complex relationships with other devices on a
> device
> >> tree are not taken into account at this stage.
> >>
> >> This patch series may be applied on the following series/patches:
> >>  - [PATCH] driver core: amba: add device binding path 'driver_override'
> >>  - [PATCH v3 0/6] vfio: type1: support for ARM SMMUS with
> VFIO_IOMMU_TYPE1
> >>
> >> A copy can be cloned from the branch vfio-platform-v11 at:
> >> g...@github.com:virtualopensystems/linux-kvm-arm.git
> >>
> >> Changes since v10:
> >>  - Check if interrupt is already masked when setting a new trigger
> >>  - Fixed kasprintf with unchecked return value in VFIO AMBA driver
> >> Changes since v9:
> >>  - Reworked the splitting of the patches that decouple virqfd from PCI
> >>  - Some styling issues and typos
> >>  - Removed superfluous includes
> >>  - AMBA devices are now named vfio-amba- suffixed by the AMBA device id
> >>  - Several other cleanups and fixes
> >> Changes since v8:
> >>  - Separate irq handler for edge and level triggered interrupts
> >>  - Mutex based lock for VFIO fd open/release
> >>  - Fixed bug where the first region of a platform device wasn't exposed
> >>  - Read only regions can be MMAPed only read only
> >>  - Code cleanups
> >> Changes since v7:
> >>  - Some initial placeholder functionality for PIO resources
> >>  - Cleaned up code for IRQ triggering, masking and unmasking
> >>  - Some functionality has been removed from this series and posted
> separately:
> >>- VFIO_IOMMU_TYPE1 support for ARM SMMUs
> >>- IOMMU NOEXEC patches
> >>- driver_override functionality for AMBA devices
> >>  - Several fixes
> >> Changes since v6:
> >>  - Integrated support for AMBA devices
> >>  - Numerous cleanups and fixes
> >> Changes since v5:
> >>  - Full eventfd support for IRQ masking and unmasking.
> >>  - Changed IOMMU_EXEC to IOMMU_NOEXEC, along with related flags in VFIO.
> >>  - Other fixes based on reviewer comments.
> >> Changes since v4:
> >>  - Use static offsets for each region in the VFIO device fd
> >>  - Include patch in the series for the ARM SMMU to expose IOMMU_EXEC
> >>availability via IOMMU_CAP_DMA_EXEC
> >>  - Rebased on VFIO multi domain support:
> >>- IOMMU_EXEC is now available if at least one IOMMU in the container
> >>  supports it
> >>- Expose IOMMU_EXEC if available via the capability
> VFIO_IOMMU_PROT_EXEC
> >>  - Some bug fixes
> >> Changes since v3:
> >>  - Use Kim Phillips' driver_probe_device()
> >> Changes since v2:
> >>  - Fixed Read/Write and MMAP on device regions
> >>  - Removed dependency on Device Tree
> >>  - Interrupts support
> >>  - Interrupt masking/unmasking
> >>  - Automask level sensitive interrupts
> >>  - Introduced VFIO_DMA_MAP_FLAG_EXEC
> >>  - Code clean ups
> >>
> >> Antonios Motakis (20):
> >>   vfio/platform: initial skeleton of VFIO support for platform devices
> >>   vfio: platform: probe to devices on the platform bus
> >>   vfio: platform: add the VFIO PLATFORM module to Kconfig
> >>   vfio: amba: VFIO support for AMBA devices
> >>   vfio: amba: add the VFIO for AMBA devices module to Kconfig
> >>   vfio/platform: return info for bound device
> >>   vfio/platform: return info for device memory mapped IO regions
> >>   vfio/pl