IOMMU Archive on lore.kernel.org
 help / color / Atom feed
* [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs
@ 2020-03-22 12:31 Liu, Yi L
  2020-03-22 12:31 ` [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free) Liu, Yi L
                   ` (8 more replies)
  0 siblings, 9 replies; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:31 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

Shared Virtual Addressing (SVA), a.k.a, Shared Virtual Memory (SVM) on
Intel platforms allows address space sharing between device DMA and
applications. SVA can reduce programming complexity and enhance security.

This VFIO series is intended to expose SVA usage to VMs. i.e. Sharing
guest application address space with passthru devices. This is called
vSVA in this series. The whole vSVA enabling requires QEMU/VFIO/IOMMU
changes. For IOMMU and QEMU changes, they are in separate series (listed
in the "Related series").

The high-level architecture for SVA virtualization is as below, the key
design of vSVA support is to utilize the dual-stage IOMMU translation (
also known as IOMMU nesting translation) capability in host IOMMU.


    .-------------.  .---------------------------.
    |   vIOMMU    |  | Guest process CR3, FL only|
    |             |  '---------------------------'
    .----------------/
    | PASID Entry |--- PASID cache flush -
    '-------------'                       |
    |             |                       V
    |             |                CR3 in GPA
    '-------------'
Guest
------| Shadow |--------------------------|--------
      v        v                          v
Host
    .-------------.  .----------------------.
    |   pIOMMU    |  | Bind FL for GVA-GPA  |
    |             |  '----------------------'
    .----------------/  |
    | PASID Entry |     V (Nested xlate)
    '----------------\.------------------------------.
    |             |   |SL for GPA-HPA, default domain|
    |             |   '------------------------------'
    '-------------'
Where:
 - FL = First level/stage one page tables
 - SL = Second level/stage two page tables

There are roughly four parts in this patchset which are
corresponding to the basic vSVA support for PCI device
assignment
 1. vfio support for PASID allocation and free for VMs
 2. vfio support for guest page table binding request from VMs
 3. vfio support for IOMMU cache invalidation from VMs
 4. vfio support for vSVA usage on IOMMU-backed mdevs

The complete vSVA kernel upstream patches are divided into three phases:
    1. Common APIs and PCI device direct assignment
    2. IOMMU-backed Mediated Device assignment
    3. Page Request Services (PRS) support

This patchset is aiming for the phase 1 and phase 2, and based on Jacob's
below series.
[PATCH V10 00/11] Nested Shared Virtual Address (SVA) VT-d support:
https://lkml.org/lkml/2020/3/20/1172

Complete set for current vSVA can be found in below branch.
https://github.com/luxis1999/linux-vsva.git: vsva-linux-5.6-rc6

The corresponding QEMU patch series is as below, complete QEMU set can be
found in below branch.
[PATCH v1 00/22] intel_iommu: expose Shared Virtual Addressing to VMs
complete QEMU set can be found in below link:
https://github.com/luxis1999/qemu.git: sva_vtd_v10_v1

Regards,
Yi Liu

Changelog:
	- RFC v1 -> Patch v1:
	  a) Address comments to the PASID request(alloc/free) path
	  b) Report PASID alloc/free availabitiy to user-space
	  c) Add a vfio_iommu_type1 parameter to support pasid quota tuning
	  d) Adjusted to latest ioasid code implementation. e.g. remove the
	     code for tracking the allocated PASIDs as latest ioasid code
	     will track it, VFIO could use ioasid_free_set() to free all
	     PASIDs.

	- RFC v2 -> v3:
	  a) Refine the whole patchset to fit the roughly parts in this series
	  b) Adds complete vfio PASID management framework. e.g. pasid alloc,
	  free, reclaim in VM crash/down and per-VM PASID quota to prevent
	  PASID abuse.
	  c) Adds IOMMU uAPI version check and page table format check to ensure
	  version compatibility and hardware compatibility.
	  d) Adds vSVA vfio support for IOMMU-backed mdevs.

	- RFC v1 -> v2:
	  Dropped vfio: VFIO_IOMMU_ATTACH/DETACH_PASID_TABLE.

Liu Yi L (8):
  vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free)
  vfio/type1: Add vfio_iommu_type1 parameter for quota tuning
  vfio/type1: Report PASID alloc/free support to userspace
  vfio: Check nesting iommu uAPI version
  vfio/type1: Report 1st-level/stage-1 format to userspace
  vfio/type1: Bind guest page tables to host
  vfio/type1: Add VFIO_IOMMU_CACHE_INVALIDATE
  vfio/type1: Add vSVA support for IOMMU-backed mdevs

 drivers/vfio/vfio.c             | 136 +++++++++++++
 drivers/vfio/vfio_iommu_type1.c | 419 ++++++++++++++++++++++++++++++++++++++++
 include/linux/vfio.h            |  21 ++
 include/uapi/linux/vfio.h       | 127 ++++++++++++
 4 files changed, 703 insertions(+)

-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free)
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
@ 2020-03-22 12:31 ` Liu, Yi L
  2020-03-22 16:21   ` kbuild test robot
  2020-03-22 12:31 ` [PATCH v1 2/8] vfio/type1: Add vfio_iommu_type1 parameter for quota tuning Liu, Yi L
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:31 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

For a long time, devices have only one DMA address space from platform
IOMMU's point of view. This is true for both bare metal and directed-
access in virtualization environment. Reason is the source ID of DMA in
PCIe are BDF (bus/dev/fnc ID), which results in only device granularity
DMA isolation. However, this is changing with the latest advancement in
I/O technology area. More and more platform vendors are utilizing the PCIe
PASID TLP prefix in DMA requests, thus to give devices with multiple DMA
address spaces as identified by their individual PASIDs. For example,
Shared Virtual Addressing (SVA, a.k.a Shared Virtual Memory) is able to
let device access multiple process virtual address space by binding the
virtual address space with a PASID. Wherein the PASID is allocated in
software and programmed to device per device specific manner. Devices
which support PASID capability are called PASID-capable devices. If such
devices are passed through to VMs, guest software are also able to bind
guest process virtual address space on such devices. Therefore, the guest
software could reuse the bare metal software programming model, which
means guest software will also allocate PASID and program it to device
directly. This is a dangerous situation since it has potential PASID
conflicts and unauthorized address space access. It would be safer to
let host intercept in the guest software's PASID allocation. Thus PASID
are managed system-wide.

This patch adds VFIO_IOMMU_PASID_REQUEST ioctl which aims to passdown
PASID allocation/free request from the virtual IOMMU. Additionally, such
requests are intended to be invoked by QEMU or other applications which
are running in userspace, it is necessary to have a mechanism to prevent
single application from abusing available PASIDs in system. With such
consideration, this patch tracks the VFIO PASID allocation per-VM. There
was a discussion to make quota to be per assigned devices. e.g. if a VM
has many assigned devices, then it should have more quota. However, it
is not sure how many PASIDs an assigned devices will use. e.g. it is
possible that a VM with multiples assigned devices but requests less
PASIDs. Therefore per-VM quota would be better.

This patch uses struct mm pointer as a per-VM token. We also considered
using task structure pointer and vfio_iommu structure pointer. However,
task structure is per-thread, which means it cannot achieve per-VM PASID
alloc tracking purpose. While for vfio_iommu structure, it is visible
only within vfio. Therefore, structure mm pointer is selected. This patch
adds a structure vfio_mm. A vfio_mm is created when the first vfio
container is opened by a VM. On the reverse order, vfio_mm is free when
the last vfio container is released. Each VM is assigned with a PASID
quota, so that it is not able to request PASID beyond its quota. This
patch adds a default quota of 1000. This quota could be tuned by
administrator. Making PASID quota tunable will be added in another patch
in this series.

Previous discussions:
https://patchwork.kernel.org/patch/11209429/

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
Signed-off-by: Yi Sun <yi.y.sun@linux.intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 drivers/vfio/vfio.c             | 130 ++++++++++++++++++++++++++++++++++++++++
 drivers/vfio/vfio_iommu_type1.c | 104 ++++++++++++++++++++++++++++++++
 include/linux/vfio.h            |  20 +++++++
 include/uapi/linux/vfio.h       |  41 +++++++++++++
 4 files changed, 295 insertions(+)

diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index c848262..d13b483 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -32,6 +32,7 @@
 #include <linux/vfio.h>
 #include <linux/wait.h>
 #include <linux/sched/signal.h>
+#include <linux/sched/mm.h>
 
 #define DRIVER_VERSION	"0.3"
 #define DRIVER_AUTHOR	"Alex Williamson <alex.williamson@redhat.com>"
@@ -46,6 +47,8 @@ static struct vfio {
 	struct mutex			group_lock;
 	struct cdev			group_cdev;
 	dev_t				group_devt;
+	struct list_head		vfio_mm_list;
+	struct mutex			vfio_mm_lock;
 	wait_queue_head_t		release_q;
 } vfio;
 
@@ -2129,6 +2132,131 @@ int vfio_unregister_notifier(struct device *dev, enum vfio_notify_type type,
 EXPORT_SYMBOL(vfio_unregister_notifier);
 
 /**
+ * VFIO_MM objects - create, release, get, put, search
+ * Caller of the function should have held vfio.vfio_mm_lock.
+ */
+static struct vfio_mm *vfio_create_mm(struct mm_struct *mm)
+{
+	struct vfio_mm *vmm;
+	struct vfio_mm_token *token;
+	int ret = 0;
+
+	vmm = kzalloc(sizeof(*vmm), GFP_KERNEL);
+	if (!vmm)
+		return ERR_PTR(-ENOMEM);
+
+	/* Per mm IOASID set used for quota control and group operations */
+	ret = ioasid_alloc_set((struct ioasid_set *) mm,
+			       VFIO_DEFAULT_PASID_QUOTA, &vmm->ioasid_sid);
+	if (ret) {
+		kfree(vmm);
+		return ERR_PTR(ret);
+	}
+
+	kref_init(&vmm->kref);
+	token = &vmm->token;
+	token->val = mm;
+	vmm->pasid_quota = VFIO_DEFAULT_PASID_QUOTA;
+	mutex_init(&vmm->pasid_lock);
+
+	list_add(&vmm->vfio_next, &vfio.vfio_mm_list);
+
+	return vmm;
+}
+
+static void vfio_mm_unlock_and_free(struct vfio_mm *vmm)
+{
+	/* destroy the ioasid set */
+	ioasid_free_set(vmm->ioasid_sid, true);
+	mutex_unlock(&vfio.vfio_mm_lock);
+	kfree(vmm);
+}
+
+/* called with vfio.vfio_mm_lock held */
+static void vfio_mm_release(struct kref *kref)
+{
+	struct vfio_mm *vmm = container_of(kref, struct vfio_mm, kref);
+
+	list_del(&vmm->vfio_next);
+	vfio_mm_unlock_and_free(vmm);
+}
+
+void vfio_mm_put(struct vfio_mm *vmm)
+{
+	kref_put_mutex(&vmm->kref, vfio_mm_release, &vfio.vfio_mm_lock);
+}
+EXPORT_SYMBOL_GPL(vfio_mm_put);
+
+/* Assume vfio_mm_lock or vfio_mm reference is held */
+static void vfio_mm_get(struct vfio_mm *vmm)
+{
+	kref_get(&vmm->kref);
+}
+
+struct vfio_mm *vfio_mm_get_from_task(struct task_struct *task)
+{
+	struct mm_struct *mm = get_task_mm(task);
+	struct vfio_mm *vmm;
+	unsigned long long val = (unsigned long long) mm;
+
+	mutex_lock(&vfio.vfio_mm_lock);
+	list_for_each_entry(vmm, &vfio.vfio_mm_list, vfio_next) {
+		if (vmm->token.val == val) {
+			vfio_mm_get(vmm);
+			goto out;
+		}
+	}
+
+	vmm = vfio_create_mm(mm);
+	if (IS_ERR(vmm))
+		vmm = NULL;
+out:
+	mutex_unlock(&vfio.vfio_mm_lock);
+	mmput(mm);
+	return vmm;
+}
+EXPORT_SYMBOL_GPL(vfio_mm_get_from_task);
+
+int vfio_mm_pasid_alloc(struct vfio_mm *vmm, int min, int max)
+{
+	ioasid_t pasid;
+	int ret = -ENOSPC;
+
+	mutex_lock(&vmm->pasid_lock);
+
+	pasid = ioasid_alloc(vmm->ioasid_sid, min, max, NULL);
+	if (pasid == INVALID_IOASID) {
+		ret = -ENOSPC;
+		goto out_unlock;
+	}
+
+	ret = pasid;
+out_unlock:
+	mutex_unlock(&vmm->pasid_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_mm_pasid_alloc);
+
+int vfio_mm_pasid_free(struct vfio_mm *vmm, ioasid_t pasid)
+{
+	void *pdata;
+	int ret = 0;
+
+	mutex_lock(&vmm->pasid_lock);
+	pdata = ioasid_find(vmm->ioasid_sid, pasid, NULL);
+	if (IS_ERR(pdata)) {
+		ret = PTR_ERR(pdata);
+		goto out_unlock;
+	}
+	ioasid_free(pasid);
+
+out_unlock:
+	mutex_unlock(&vmm->pasid_lock);
+	return ret;
+}
+EXPORT_SYMBOL_GPL(vfio_mm_pasid_free);
+
+/**
  * Module/class support
  */
 static char *vfio_devnode(struct device *dev, umode_t *mode)
@@ -2151,8 +2279,10 @@ static int __init vfio_init(void)
 	idr_init(&vfio.group_idr);
 	mutex_init(&vfio.group_lock);
 	mutex_init(&vfio.iommu_drivers_lock);
+	mutex_init(&vfio.vfio_mm_lock);
 	INIT_LIST_HEAD(&vfio.group_list);
 	INIT_LIST_HEAD(&vfio.iommu_drivers_list);
+	INIT_LIST_HEAD(&vfio.vfio_mm_list);
 	init_waitqueue_head(&vfio.release_q);
 
 	ret = misc_register(&vfio_dev);
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index a177bf2..331ceee 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -70,6 +70,7 @@ struct vfio_iommu {
 	unsigned int		dma_avail;
 	bool			v2;
 	bool			nesting;
+	struct vfio_mm		*vmm;
 };
 
 struct vfio_domain {
@@ -2018,6 +2019,7 @@ static void vfio_iommu_type1_detach_group(void *iommu_data,
 static void *vfio_iommu_type1_open(unsigned long arg)
 {
 	struct vfio_iommu *iommu;
+	struct vfio_mm *vmm = NULL;
 
 	iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
 	if (!iommu)
@@ -2043,6 +2045,10 @@ static void *vfio_iommu_type1_open(unsigned long arg)
 	iommu->dma_avail = dma_entry_limit;
 	mutex_init(&iommu->lock);
 	BLOCKING_INIT_NOTIFIER_HEAD(&iommu->notifier);
+	vmm = vfio_mm_get_from_task(current);
+	if (!vmm)
+		pr_err("Failed to get vfio_mm track\n");
+	iommu->vmm = vmm;
 
 	return iommu;
 }
@@ -2084,6 +2090,8 @@ static void vfio_iommu_type1_release(void *iommu_data)
 	}
 
 	vfio_iommu_iova_free(&iommu->iova_list);
+	if (iommu->vmm)
+		vfio_mm_put(iommu->vmm);
 
 	kfree(iommu);
 }
@@ -2172,6 +2180,55 @@ static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu,
 	return ret;
 }
 
+static bool vfio_iommu_type1_pasid_req_valid(u32 flags)
+{
+	return !((flags & ~VFIO_PASID_REQUEST_MASK) ||
+		 (flags & VFIO_IOMMU_PASID_ALLOC &&
+		  flags & VFIO_IOMMU_PASID_FREE));
+}
+
+static int vfio_iommu_type1_pasid_alloc(struct vfio_iommu *iommu,
+					 int min,
+					 int max)
+{
+	struct vfio_mm *vmm = iommu->vmm;
+	int ret = 0;
+
+	mutex_lock(&iommu->lock);
+	if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) {
+		ret = -EFAULT;
+		goto out_unlock;
+	}
+	if (vmm)
+		ret = vfio_mm_pasid_alloc(vmm, min, max);
+	else
+		ret = -EINVAL;
+out_unlock:
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
+static int vfio_iommu_type1_pasid_free(struct vfio_iommu *iommu,
+				       unsigned int pasid)
+{
+	struct vfio_mm *vmm = iommu->vmm;
+	int ret = 0;
+
+	mutex_lock(&iommu->lock);
+	if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) {
+		ret = -EFAULT;
+		goto out_unlock;
+	}
+
+	if (vmm)
+		ret = vfio_mm_pasid_free(vmm, pasid);
+	else
+		ret = -EINVAL;
+out_unlock:
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
 static long vfio_iommu_type1_ioctl(void *iommu_data,
 				   unsigned int cmd, unsigned long arg)
 {
@@ -2276,6 +2333,53 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 
 		return copy_to_user((void __user *)arg, &unmap, minsz) ?
 			-EFAULT : 0;
+
+	} else if (cmd == VFIO_IOMMU_PASID_REQUEST) {
+		struct vfio_iommu_type1_pasid_request req;
+		unsigned long offset;
+
+		minsz = offsetofend(struct vfio_iommu_type1_pasid_request,
+				    flags);
+
+		if (copy_from_user(&req, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (req.argsz < minsz ||
+		    !vfio_iommu_type1_pasid_req_valid(req.flags))
+			return -EINVAL;
+
+		if (copy_from_user((void *)&req + minsz,
+				   (void __user *)arg + minsz,
+				   sizeof(req) - minsz))
+			return -EFAULT;
+
+		switch (req.flags & VFIO_PASID_REQUEST_MASK) {
+		case VFIO_IOMMU_PASID_ALLOC:
+		{
+			int ret = 0, result;
+
+			result = vfio_iommu_type1_pasid_alloc(iommu,
+							req.alloc_pasid.min,
+							req.alloc_pasid.max);
+			if (result > 0) {
+				offset = offsetof(
+					struct vfio_iommu_type1_pasid_request,
+					alloc_pasid.result);
+				ret = copy_to_user(
+					      (void __user *) (arg + offset),
+					      &result, sizeof(result));
+			} else {
+				pr_debug("%s: PASID alloc failed\n", __func__);
+				ret = -EFAULT;
+			}
+			return ret;
+		}
+		case VFIO_IOMMU_PASID_FREE:
+			return vfio_iommu_type1_pasid_free(iommu,
+							   req.free_pasid);
+		default:
+			return -EINVAL;
+		}
 	}
 
 	return -ENOTTY;
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index e42a711..75f9f7f1 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -89,6 +89,26 @@ extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops);
 extern void vfio_unregister_iommu_driver(
 				const struct vfio_iommu_driver_ops *ops);
 
+#define VFIO_DEFAULT_PASID_QUOTA	1000
+struct vfio_mm_token {
+	unsigned long long val;
+};
+
+struct vfio_mm {
+	struct kref			kref;
+	struct vfio_mm_token		token;
+	int				ioasid_sid;
+	/* protect @pasid_quota field and pasid allocation/free */
+	struct mutex			pasid_lock;
+	int				pasid_quota;
+	struct list_head		vfio_next;
+};
+
+extern struct vfio_mm *vfio_mm_get_from_task(struct task_struct *task);
+extern void vfio_mm_put(struct vfio_mm *vmm);
+extern int vfio_mm_pasid_alloc(struct vfio_mm *vmm, int min, int max);
+extern int vfio_mm_pasid_free(struct vfio_mm *vmm, ioasid_t pasid);
+
 /*
  * External user API
  */
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 9e843a1..298ac80 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -794,6 +794,47 @@ struct vfio_iommu_type1_dma_unmap {
 #define VFIO_IOMMU_ENABLE	_IO(VFIO_TYPE, VFIO_BASE + 15)
 #define VFIO_IOMMU_DISABLE	_IO(VFIO_TYPE, VFIO_BASE + 16)
 
+/*
+ * PASID (Process Address Space ID) is a PCIe concept which
+ * has been extended to support DMA isolation in fine-grain.
+ * With device assigned to user space (e.g. VMs), PASID alloc
+ * and free need to be system wide. This structure defines
+ * the info for pasid alloc/free between user space and kernel
+ * space.
+ *
+ * @flag=VFIO_IOMMU_PASID_ALLOC, refer to the @alloc_pasid
+ * @flag=VFIO_IOMMU_PASID_FREE, refer to @free_pasid
+ */
+struct vfio_iommu_type1_pasid_request {
+	__u32	argsz;
+#define VFIO_IOMMU_PASID_ALLOC	(1 << 0)
+#define VFIO_IOMMU_PASID_FREE	(1 << 1)
+	__u32	flags;
+	union {
+		struct {
+			__u32 min;
+			__u32 max;
+			__u32 result;
+		} alloc_pasid;
+		__u32 free_pasid;
+	};
+};
+
+#define VFIO_PASID_REQUEST_MASK	(VFIO_IOMMU_PASID_ALLOC | \
+					 VFIO_IOMMU_PASID_FREE)
+
+/**
+ * VFIO_IOMMU_PASID_REQUEST - _IOWR(VFIO_TYPE, VFIO_BASE + 22,
+ *				struct vfio_iommu_type1_pasid_request)
+ *
+ * Availability of this feature depends on PASID support in the device,
+ * its bus, the underlying IOMMU and the CPU architecture. In VFIO, it
+ * is available after VFIO_SET_IOMMU.
+ *
+ * returns: 0 on success, -errno on failure.
+ */
+#define VFIO_IOMMU_PASID_REQUEST	_IO(VFIO_TYPE, VFIO_BASE + 22)
+
 /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */
 
 /*
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 2/8] vfio/type1: Add vfio_iommu_type1 parameter for quota tuning
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
  2020-03-22 12:31 ` [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free) Liu, Yi L
@ 2020-03-22 12:31 ` Liu, Yi L
  2020-03-22 17:20   ` kbuild test robot
  2020-03-22 12:32 ` [PATCH v1 3/8] vfio/type1: Report PASID alloc/free support to userspace Liu, Yi L
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:31 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

This patch adds a module option to make the PASID quota tunable by
administrator.

TODO: needs to think more on how to  make the tuning to be per-process.

Previous discussions:
https://patchwork.kernel.org/patch/11209429/

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 drivers/vfio/vfio.c             | 8 +++++++-
 drivers/vfio/vfio_iommu_type1.c | 7 ++++++-
 include/linux/vfio.h            | 3 ++-
 3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c
index d13b483..020a792 100644
--- a/drivers/vfio/vfio.c
+++ b/drivers/vfio/vfio.c
@@ -2217,13 +2217,19 @@ struct vfio_mm *vfio_mm_get_from_task(struct task_struct *task)
 }
 EXPORT_SYMBOL_GPL(vfio_mm_get_from_task);
 
-int vfio_mm_pasid_alloc(struct vfio_mm *vmm, int min, int max)
+int vfio_mm_pasid_alloc(struct vfio_mm *vmm, int quota, int min, int max)
 {
 	ioasid_t pasid;
 	int ret = -ENOSPC;
 
 	mutex_lock(&vmm->pasid_lock);
 
+	/* update quota as it is tunable by admin */
+	if (vmm->pasid_quota != quota) {
+		vmm->pasid_quota = quota;
+		ioasid_adjust_set(vmm->ioasid_sid, quota);
+	}
+
 	pasid = ioasid_alloc(vmm->ioasid_sid, min, max, NULL);
 	if (pasid == INVALID_IOASID) {
 		ret = -ENOSPC;
diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 331ceee..e40afc0 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -60,6 +60,11 @@ module_param_named(dma_entry_limit, dma_entry_limit, uint, 0644);
 MODULE_PARM_DESC(dma_entry_limit,
 		 "Maximum number of user DMA mappings per container (65535).");
 
+static int pasid_quota = VFIO_DEFAULT_PASID_QUOTA;
+module_param_named(pasid_quota, pasid_quota, uint, 0644);
+MODULE_PARM_DESC(pasid_quota,
+		 "Quota of user owned PASIDs per vfio-based application (1000).");
+
 struct vfio_iommu {
 	struct list_head	domain_list;
 	struct list_head	iova_list;
@@ -2200,7 +2205,7 @@ static int vfio_iommu_type1_pasid_alloc(struct vfio_iommu *iommu,
 		goto out_unlock;
 	}
 	if (vmm)
-		ret = vfio_mm_pasid_alloc(vmm, min, max);
+		ret = vfio_mm_pasid_alloc(vmm, pasid_quota, min, max);
 	else
 		ret = -EINVAL;
 out_unlock:
diff --git a/include/linux/vfio.h b/include/linux/vfio.h
index 75f9f7f1..af2ef78 100644
--- a/include/linux/vfio.h
+++ b/include/linux/vfio.h
@@ -106,7 +106,8 @@ struct vfio_mm {
 
 extern struct vfio_mm *vfio_mm_get_from_task(struct task_struct *task);
 extern void vfio_mm_put(struct vfio_mm *vmm);
-extern int vfio_mm_pasid_alloc(struct vfio_mm *vmm, int min, int max);
+extern int vfio_mm_pasid_alloc(struct vfio_mm *vmm,
+				int quota, int min, int max);
 extern int vfio_mm_pasid_free(struct vfio_mm *vmm, ioasid_t pasid);
 
 /*
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 3/8] vfio/type1: Report PASID alloc/free support to userspace
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
  2020-03-22 12:31 ` [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free) Liu, Yi L
  2020-03-22 12:31 ` [PATCH v1 2/8] vfio/type1: Add vfio_iommu_type1 parameter for quota tuning Liu, Yi L
@ 2020-03-22 12:32 ` Liu, Yi L
  2020-03-22 12:32 ` [PATCH v1 4/8] vfio: Check nesting iommu uAPI version Liu, Yi L
                   ` (5 subsequent siblings)
  8 siblings, 0 replies; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:32 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

This patch reports PASID alloc/free availability to userspace (e.g. QEMU)
thus userspace could do a pre-check before utilizing this feature.

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 28 ++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h       |  8 ++++++++
 2 files changed, 36 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index e40afc0..ddd1ffe 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2234,6 +2234,30 @@ static int vfio_iommu_type1_pasid_free(struct vfio_iommu *iommu,
 	return ret;
 }
 
+static int vfio_iommu_info_add_nesting_cap(struct vfio_iommu *iommu,
+					 struct vfio_info_cap *caps)
+{
+	struct vfio_info_cap_header *header;
+	struct vfio_iommu_type1_info_cap_nesting *nesting_cap;
+
+	header = vfio_info_cap_add(caps, sizeof(*nesting_cap),
+				   VFIO_IOMMU_TYPE1_INFO_CAP_NESTING, 1);
+	if (IS_ERR(header))
+		return PTR_ERR(header);
+
+	nesting_cap = container_of(header,
+				struct vfio_iommu_type1_info_cap_nesting,
+				header);
+
+	nesting_cap->nesting_capabilities = 0;
+	if (iommu->nesting) {
+		/* nesting iommu type supports PASID requests (alloc/free) */
+		nesting_cap->nesting_capabilities |= VFIO_IOMMU_PASID_REQS;
+	}
+
+	return 0;
+}
+
 static long vfio_iommu_type1_ioctl(void *iommu_data,
 				   unsigned int cmd, unsigned long arg)
 {
@@ -2283,6 +2307,10 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 		if (ret)
 			return ret;
 
+		ret = vfio_iommu_info_add_nesting_cap(iommu, &caps);
+		if (ret)
+			return ret;
+
 		if (caps.size) {
 			info.flags |= VFIO_IOMMU_INFO_CAPS;
 
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 298ac80..8837219 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -748,6 +748,14 @@ struct vfio_iommu_type1_info_cap_iova_range {
 	struct	vfio_iova_range iova_ranges[];
 };
 
+#define VFIO_IOMMU_TYPE1_INFO_CAP_NESTING  2
+
+struct vfio_iommu_type1_info_cap_nesting {
+	struct	vfio_info_cap_header header;
+#define VFIO_IOMMU_PASID_REQS	(1 << 0)
+	__u32	nesting_capabilities;
+};
+
 #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
 
 /**
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 4/8] vfio: Check nesting iommu uAPI version
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
                   ` (2 preceding siblings ...)
  2020-03-22 12:32 ` [PATCH v1 3/8] vfio/type1: Report PASID alloc/free support to userspace Liu, Yi L
@ 2020-03-22 12:32 ` Liu, Yi L
  2020-03-22 18:30   ` kbuild test robot
  2020-03-22 12:32 ` [PATCH v1 5/8] vfio/type1: Report 1st-level/stage-1 format to userspace Liu, Yi L
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:32 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

In Linux Kernel, the IOMMU nesting translation (a.k.a dual stage address
translation) capability is abstracted in uapi/iommu.h, in which the uAPIs
like bind_gpasid/iommu_cache_invalidate/fault_report/pgreq_resp are defined.

VFIO_TYPE1_NESTING_IOMMU stands for the vfio iommu type which is backed by
hardware IOMMU w/ dual stage translation capability. For such vfio iommu
type, userspace is able to setup dual stage DMA translation in host side
via VFIO's ABI. However, such VFIO ABIs rely on the uAPIs defined in uapi/
iommu.h. So VFIO needs to provide an API to userspace for the uapi/iommu.h
version check to ensure the iommu uAPI compatibility.

This patch reports the iommu uAPI version to userspace in VFIO_CHECK_EXTENSION
IOCTL. Applications could do version check before further setup dual stage
translation in host IOMMU.

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 2 ++
 include/uapi/linux/vfio.h       | 9 +++++++++
 2 files changed, 11 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index ddd1ffe..9aa2a67 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2274,6 +2274,8 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 			if (!iommu)
 				return 0;
 			return vfio_domains_have_iommu_cache(iommu);
+		case VFIO_NESTING_IOMMU_UAPI:
+			return iommu_get_uapi_version();
 		default:
 			return 0;
 		}
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 8837219..ed9881d 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -47,6 +47,15 @@
 #define VFIO_NOIOMMU_IOMMU		8
 
 /*
+ * Hardware IOMMUs with two-stage translation capability give userspace
+ * the ownership of stage-1 translation structures (e.g. page tables).
+ * VFIO exposes the two-stage IOMMU programming capability to userspace
+ * based on the IOMMU UAPIs. Therefore user of VFIO_TYPE1_NESTING should
+ * check the IOMMU UAPI version compatibility.
+ */
+#define VFIO_NESTING_IOMMU_UAPI		9
+
+/*
  * The IOCTL interface is designed for extensibility by embedding the
  * structure length (argsz) and flags into structures passed between
  * kernel and userspace.  We therefore use the _IO() macro for these
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 5/8] vfio/type1: Report 1st-level/stage-1 format to userspace
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
                   ` (3 preceding siblings ...)
  2020-03-22 12:32 ` [PATCH v1 4/8] vfio: Check nesting iommu uAPI version Liu, Yi L
@ 2020-03-22 12:32 ` Liu, Yi L
  2020-03-22 16:44   ` kbuild test robot
  2020-03-22 12:32 ` [PATCH v1 6/8] vfio/type1: Bind guest page tables to host Liu, Yi L
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:32 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

VFIO exposes IOMMU nesting translation (a.k.a dual stage translation)
capability to userspace. Thus applications like QEMU could support
vIOMMU with hardware's nesting translation capability for pass-through
devices. Before setting up nesting translation for pass-through devices,
QEMU and other applications need to learn the supported 1st-lvl/stage-1
translation structure format like page table format.

Take vSVA (virtual Shared Virtual Addressing) as an example, to support
vSVA for pass-through devices, QEMU setup nesting translation for pass-
through devices. The guest page table are configured to host as 1st-lvl/
stage-1 page table. Therefore, guest format should be compatible with
host side.

This patch reports the supported 1st-lvl/stage-1 page table format on the
current platform to userspace. QEMU and other alike applications should
use this format info when trying to setup IOMMU nesting translation on
host IOMMU.

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 56 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h       |  1 +
 2 files changed, 57 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 9aa2a67..82a9e0b 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2234,11 +2234,66 @@ static int vfio_iommu_type1_pasid_free(struct vfio_iommu *iommu,
 	return ret;
 }
 
+static int vfio_iommu_get_stage1_format(struct vfio_iommu *iommu,
+					 u32 *stage1_format)
+{
+	struct vfio_domain *domain;
+	u32 format = 0, tmp_format = 0;
+	int ret;
+
+	mutex_lock(&iommu->lock);
+	if (list_empty(&iommu->domain_list)) {
+		mutex_unlock(&iommu->lock);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(domain, &iommu->domain_list, next) {
+		if (iommu_domain_get_attr(domain->domain,
+			DOMAIN_ATTR_PASID_FORMAT, &format)) {
+			ret = -EINVAL;
+			format = 0;
+			goto out_unlock;
+		}
+		/*
+		 * format is always non-zero (the first format is
+		 * IOMMU_PASID_FORMAT_INTEL_VTD which is 1). For
+		 * the reason of potential different backed IOMMU
+		 * formats, here we expect to have identical formats
+		 * in the domain list, no mixed formats support.
+		 * return -EINVAL to fail the attempt of setup
+		 * VFIO_TYPE1_NESTING_IOMMU if non-identical formats
+		 * are detected.
+		 */
+		if (tmp_format && tmp_format != format) {
+			ret = -EINVAL;
+			format = 0;
+			goto out_unlock;
+		}
+
+		tmp_format = format;
+	}
+	ret = 0;
+
+out_unlock:
+	if (format)
+		*stage1_format = format;
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
 static int vfio_iommu_info_add_nesting_cap(struct vfio_iommu *iommu,
 					 struct vfio_info_cap *caps)
 {
 	struct vfio_info_cap_header *header;
 	struct vfio_iommu_type1_info_cap_nesting *nesting_cap;
+	u32 formats = 0;
+	int ret;
+
+	ret = vfio_iommu_get_stage1_format(iommu, &formats);
+	if (ret) {
+		pr_warn("Failed to get stage-1 format\n");
+		return ret;
+	}
 
 	header = vfio_info_cap_add(caps, sizeof(*nesting_cap),
 				   VFIO_IOMMU_TYPE1_INFO_CAP_NESTING, 1);
@@ -2254,6 +2309,7 @@ static int vfio_iommu_info_add_nesting_cap(struct vfio_iommu *iommu,
 		/* nesting iommu type supports PASID requests (alloc/free) */
 		nesting_cap->nesting_capabilities |= VFIO_IOMMU_PASID_REQS;
 	}
+	nesting_cap->stage1_formats = formats;
 
 	return 0;
 }
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index ed9881d..ebeaf3e 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -763,6 +763,7 @@ struct vfio_iommu_type1_info_cap_nesting {
 	struct	vfio_info_cap_header header;
 #define VFIO_IOMMU_PASID_REQS	(1 << 0)
 	__u32	nesting_capabilities;
+	__u32	stage1_formats;
 };
 
 #define VFIO_IOMMU_GET_INFO _IO(VFIO_TYPE, VFIO_BASE + 12)
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 6/8] vfio/type1: Bind guest page tables to host
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
                   ` (4 preceding siblings ...)
  2020-03-22 12:32 ` [PATCH v1 5/8] vfio/type1: Report 1st-level/stage-1 format to userspace Liu, Yi L
@ 2020-03-22 12:32 ` Liu, Yi L
  2020-03-22 18:10   ` kbuild test robot
  2020-03-22 12:32 ` [PATCH v1 7/8] vfio/type1: Add VFIO_IOMMU_CACHE_INVALIDATE Liu, Yi L
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:32 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

VFIO_TYPE1_NESTING_IOMMU is an IOMMU type which is backed by hardware
IOMMUs that have nesting DMA translation (a.k.a dual stage address
translation). For such hardware IOMMUs, there are two stages/levels of
address translation, and software may let userspace/VM to own the first-
level/stage-1 translation structures. Example of such usage is vSVA (
virtual Shared Virtual Addressing). VM owns the first-level/stage-1
translation structures and bind the structures to host, then hardware
IOMMU would utilize nesting translation when doing DMA translation fo
the devices behind such hardware IOMMU.

This patch adds vfio support for binding guest translation (a.k.a stage 1)
structure to host iommu. And for VFIO_TYPE1_NESTING_IOMMU, not only bind
guest page table is needed, it also requires to expose interface to guest
for iommu cache invalidation when guest modified the first-level/stage-1
translation structures since hardware needs to be notified to flush stale
iotlbs. This would be introduced in next patch.

In this patch, guest page table bind and unbind are done by using flags
VFIO_IOMMU_BIND_GUEST_PGTBL and VFIO_IOMMU_UNBIND_GUEST_PGTBL under IOCTL
VFIO_IOMMU_BIND, the bind/unbind data are conveyed by
struct iommu_gpasid_bind_data. Before binding guest page table to host,
VM should have got a PASID allocated by host via VFIO_IOMMU_PASID_REQUEST.

Bind guest translation structures (here is guest page table) to host
are the first step to setup vSVA (Virtual Shared Virtual Addressing).

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Jean-Philippe Brucker <jean-philippe@linaro.com>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 158 ++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h       |  46 ++++++++++++
 2 files changed, 204 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 82a9e0b..a877747 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -130,6 +130,33 @@ struct vfio_regions {
 #define IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)	\
 					(!list_empty(&iommu->domain_list))
 
+struct domain_capsule {
+	struct iommu_domain *domain;
+	void *data;
+};
+
+/* iommu->lock must be held */
+static int vfio_iommu_for_each_dev(struct vfio_iommu *iommu,
+		      int (*fn)(struct device *dev, void *data),
+		      void *data)
+{
+	struct domain_capsule dc = {.data = data};
+	struct vfio_domain *d;
+	struct vfio_group *g;
+	int ret = 0;
+
+	list_for_each_entry(d, &iommu->domain_list, next) {
+		dc.domain = d->domain;
+		list_for_each_entry(g, &d->group_list, next) {
+			ret = iommu_group_for_each_dev(g->iommu_group,
+						       &dc, fn);
+			if (ret)
+				break;
+		}
+	}
+	return ret;
+}
+
 static int put_pfn(unsigned long pfn, int prot);
 
 /*
@@ -2314,6 +2341,88 @@ static int vfio_iommu_info_add_nesting_cap(struct vfio_iommu *iommu,
 	return 0;
 }
 
+static int vfio_bind_gpasid_fn(struct device *dev, void *data)
+{
+	struct domain_capsule *dc = (struct domain_capsule *)data;
+	struct iommu_gpasid_bind_data *gbind_data =
+		(struct iommu_gpasid_bind_data *) dc->data;
+
+	return iommu_sva_bind_gpasid(dc->domain, dev, gbind_data);
+}
+
+static int vfio_unbind_gpasid_fn(struct device *dev, void *data)
+{
+	struct domain_capsule *dc = (struct domain_capsule *)data;
+	struct iommu_gpasid_bind_data *gbind_data =
+		(struct iommu_gpasid_bind_data *) dc->data;
+
+	return iommu_sva_unbind_gpasid(dc->domain, dev,
+					gbind_data->hpasid);
+}
+
+/**
+ * Unbind specific gpasid, caller of this function requires hold
+ * vfio_iommu->lock
+ */
+static long vfio_iommu_type1_do_guest_unbind(struct vfio_iommu *iommu,
+				struct iommu_gpasid_bind_data *gbind_data)
+{
+	return vfio_iommu_for_each_dev(iommu,
+				vfio_unbind_gpasid_fn, gbind_data);
+}
+
+static long vfio_iommu_type1_bind_gpasid(struct vfio_iommu *iommu,
+				struct iommu_gpasid_bind_data *gbind_data)
+{
+	int ret = 0;
+
+	mutex_lock(&iommu->lock);
+	if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = vfio_iommu_for_each_dev(iommu,
+			vfio_bind_gpasid_fn, gbind_data);
+	/*
+	 * If bind failed, it may not be a total failure. Some devices
+	 * within the iommu group may have bind successfully. Although
+	 * we don't enable pasid capability for non-singletion iommu
+	 * groups, a unbind operation would be helpful to ensure no
+	 * partial binding for an iommu group.
+	 */
+	if (ret)
+		/*
+		 * Undo all binds that already succeeded, no need to
+		 * check the return value here since some device within
+		 * the group has no successful bind when coming to this
+		 * place switch.
+		 */
+		vfio_iommu_type1_do_guest_unbind(iommu, gbind_data);
+
+out_unlock:
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
+static long vfio_iommu_type1_unbind_gpasid(struct vfio_iommu *iommu,
+				struct iommu_gpasid_bind_data *gbind_data)
+{
+	int ret = 0;
+
+	mutex_lock(&iommu->lock);
+	if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) {
+		ret = -EINVAL;
+		goto out_unlock;
+	}
+
+	ret = vfio_iommu_type1_do_guest_unbind(iommu, gbind_data);
+
+out_unlock:
+	mutex_unlock(&iommu->lock);
+	return ret;
+}
+
 static long vfio_iommu_type1_ioctl(void *iommu_data,
 				   unsigned int cmd, unsigned long arg)
 {
@@ -2471,6 +2580,55 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 		default:
 			return -EINVAL;
 		}
+
+	} else if (cmd == VFIO_IOMMU_BIND) {
+		struct vfio_iommu_type1_bind bind;
+		u32 version;
+		int data_size;
+		void *gbind_data;
+		int ret;
+
+		minsz = offsetofend(struct vfio_iommu_type1_bind, flags);
+
+		if (copy_from_user(&bind, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (bind.argsz < minsz)
+			return -EINVAL;
+
+		/* Get the version of struct iommu_gpasid_bind_data */
+		if (copy_from_user(&version,
+			(void __user *) (arg + minsz),
+					sizeof(version)))
+			return -EFAULT;
+
+		data_size = iommu_uapi_get_data_size(
+				IOMMU_UAPI_BIND_GPASID, version);
+		gbind_data = kzalloc(data_size, GFP_KERNEL);
+		if (!gbind_data)
+			return -ENOMEM;
+
+		if (copy_from_user(gbind_data,
+			 (void __user *) (arg + minsz), data_size)) {
+			kfree(gbind_data);
+			return -EFAULT;
+		}
+
+		switch (bind.flags & VFIO_IOMMU_BIND_MASK) {
+		case VFIO_IOMMU_BIND_GUEST_PGTBL:
+			ret = vfio_iommu_type1_bind_gpasid(iommu,
+							   gbind_data);
+			break;
+		case VFIO_IOMMU_UNBIND_GUEST_PGTBL:
+			ret = vfio_iommu_type1_unbind_gpasid(iommu,
+							     gbind_data);
+			break;
+		default:
+			ret = -EINVAL;
+			break;
+		}
+		kfree(gbind_data);
+		return ret;
 	}
 
 	return -ENOTTY;
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index ebeaf3e..2235bc6 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -14,6 +14,7 @@
 
 #include <linux/types.h>
 #include <linux/ioctl.h>
+#include <linux/iommu.h>
 
 #define VFIO_API_VERSION	0
 
@@ -853,6 +854,51 @@ struct vfio_iommu_type1_pasid_request {
  */
 #define VFIO_IOMMU_PASID_REQUEST	_IO(VFIO_TYPE, VFIO_BASE + 22)
 
+/**
+ * Supported flags:
+ *	- VFIO_IOMMU_BIND_GUEST_PGTBL: bind guest page tables to host for
+ *			nesting type IOMMUs. In @data field It takes struct
+ *			iommu_gpasid_bind_data.
+ *	- VFIO_IOMMU_UNBIND_GUEST_PGTBL: undo a bind guest page table operation
+ *			invoked by VFIO_IOMMU_BIND_GUEST_PGTBL.
+ *
+ */
+struct vfio_iommu_type1_bind {
+	__u32		argsz;
+	__u32		flags;
+#define VFIO_IOMMU_BIND_GUEST_PGTBL	(1 << 0)
+#define VFIO_IOMMU_UNBIND_GUEST_PGTBL	(1 << 1)
+	__u8		data[];
+};
+
+#define VFIO_IOMMU_BIND_MASK	(VFIO_IOMMU_BIND_GUEST_PGTBL | \
+					VFIO_IOMMU_UNBIND_GUEST_PGTBL)
+
+/**
+ * VFIO_IOMMU_BIND - _IOW(VFIO_TYPE, VFIO_BASE + 23,
+ *				struct vfio_iommu_type1_bind)
+ *
+ * Manage address spaces of devices in this container. Initially a TYPE1
+ * container can only have one address space, managed with
+ * VFIO_IOMMU_MAP/UNMAP_DMA.
+ *
+ * An IOMMU of type VFIO_TYPE1_NESTING_IOMMU can be managed by both MAP/UNMAP
+ * and BIND ioctls at the same time. MAP/UNMAP acts on the stage-2 (host) page
+ * tables, and BIND manages the stage-1 (guest) page tables. Other types of
+ * IOMMU may allow MAP/UNMAP and BIND to coexist, where MAP/UNMAP controls
+ * the traffics only require single stage translation while BIND controls the
+ * traffics require nesting translation. But this depends on the underlying
+ * IOMMU architecture and isn't guaranteed. Example of this is the guest SVA
+ * traffics, such traffics need nesting translation to gain gVA->gPA and then
+ * gPA->hPA translation.
+ *
+ * Availability of this feature depends on the device, its bus, the underlying
+ * IOMMU and the CPU architecture.
+ *
+ * returns: 0 on success, -errno on failure.
+ */
+#define VFIO_IOMMU_BIND		_IO(VFIO_TYPE, VFIO_BASE + 23)
+
 /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */
 
 /*
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 7/8] vfio/type1: Add VFIO_IOMMU_CACHE_INVALIDATE
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
                   ` (5 preceding siblings ...)
  2020-03-22 12:32 ` [PATCH v1 6/8] vfio/type1: Bind guest page tables to host Liu, Yi L
@ 2020-03-22 12:32 ` Liu, Yi L
  2020-03-22 12:32 ` [PATCH v1 8/8] vfio/type1: Add vSVA support for IOMMU-backed mdevs Liu, Yi L
  2020-03-26 12:56 ` [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
  8 siblings, 0 replies; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:32 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@linux.intel.com>

For VFIO IOMMUs with the type VFIO_TYPE1_NESTING_IOMMU, guest "owns" the
first-level/stage-1 translation structures, the host IOMMU driver has no
knowledge of first-level/stage-1 structure cache updates unless the guest
invalidation requests are trapped and propagated to the host.

This patch adds a new IOCTL VFIO_IOMMU_CACHE_INVALIDATE to propagate guest
first-level/stage-1 IOMMU cache invalidations to host to ensure IOMMU cache
correctness.

With this patch, vSVA (Virtual Shared Virtual Addressing) can be used safely
as the host IOMMU iotlb correctness are ensured.

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@linux.intel.com>
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Jacob Pan <jacob.jun.pan@linux.intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 49 +++++++++++++++++++++++++++++++++++++++++
 include/uapi/linux/vfio.h       | 22 ++++++++++++++++++
 2 files changed, 71 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index a877747..937ec3f 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2423,6 +2423,15 @@ static long vfio_iommu_type1_unbind_gpasid(struct vfio_iommu *iommu,
 	return ret;
 }
 
+static int vfio_cache_inv_fn(struct device *dev, void *data)
+{
+	struct domain_capsule *dc = (struct domain_capsule *)data;
+	struct iommu_cache_invalidate_info *cache_inv_info =
+		(struct iommu_cache_invalidate_info *) dc->data;
+
+	return iommu_cache_invalidate(dc->domain, dev, cache_inv_info);
+}
+
 static long vfio_iommu_type1_ioctl(void *iommu_data,
 				   unsigned int cmd, unsigned long arg)
 {
@@ -2629,6 +2638,46 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
 		}
 		kfree(gbind_data);
 		return ret;
+	} else if (cmd == VFIO_IOMMU_CACHE_INVALIDATE) {
+		struct vfio_iommu_type1_cache_invalidate cache_inv;
+		u32 version;
+		int info_size;
+		void *cache_info;
+		int ret;
+
+		minsz = offsetofend(struct vfio_iommu_type1_cache_invalidate,
+				    flags);
+
+		if (copy_from_user(&cache_inv, (void __user *)arg, minsz))
+			return -EFAULT;
+
+		if (cache_inv.argsz < minsz || cache_inv.flags)
+			return -EINVAL;
+
+		/* Get the version of struct iommu_cache_invalidate_info */
+		if (copy_from_user(&version,
+			(void __user *) (arg + minsz), sizeof(version)))
+			return -EFAULT;
+
+		info_size = iommu_uapi_get_data_size(
+					IOMMU_UAPI_CACHE_INVAL, version);
+
+		cache_info = kzalloc(info_size, GFP_KERNEL);
+		if (!cache_info)
+			return -ENOMEM;
+
+		if (copy_from_user(cache_info,
+			(void __user *) (arg + minsz), info_size)) {
+			kfree(cache_info);
+			return -EFAULT;
+		}
+
+		mutex_lock(&iommu->lock);
+		ret = vfio_iommu_for_each_dev(iommu, vfio_cache_inv_fn,
+					    cache_info);
+		mutex_unlock(&iommu->lock);
+		kfree(cache_info);
+		return ret;
 	}
 
 	return -ENOTTY;
diff --git a/include/uapi/linux/vfio.h b/include/uapi/linux/vfio.h
index 2235bc6..62ca791 100644
--- a/include/uapi/linux/vfio.h
+++ b/include/uapi/linux/vfio.h
@@ -899,6 +899,28 @@ struct vfio_iommu_type1_bind {
  */
 #define VFIO_IOMMU_BIND		_IO(VFIO_TYPE, VFIO_BASE + 23)
 
+/**
+ * VFIO_IOMMU_CACHE_INVALIDATE - _IOW(VFIO_TYPE, VFIO_BASE + 24,
+ *			struct vfio_iommu_type1_cache_invalidate)
+ *
+ * Propagate guest IOMMU cache invalidation to the host. The cache
+ * invalidation information is conveyed by @cache_info, the content
+ * format would be structures defined in uapi/linux/iommu.h. User
+ * should be aware of that the struct  iommu_cache_invalidate_info
+ * has a @version field, vfio needs to parse this field before getting
+ * data from userspace.
+ *
+ * Availability of this IOCTL is after VFIO_SET_IOMMU.
+ *
+ * returns: 0 on success, -errno on failure.
+ */
+struct vfio_iommu_type1_cache_invalidate {
+	__u32   argsz;
+	__u32   flags;
+	struct	iommu_cache_invalidate_info cache_info;
+};
+#define VFIO_IOMMU_CACHE_INVALIDATE      _IO(VFIO_TYPE, VFIO_BASE + 24)
+
 /* -------- Additional API for SPAPR TCE (Server POWERPC) IOMMU -------- */
 
 /*
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* [PATCH v1 8/8] vfio/type1: Add vSVA support for IOMMU-backed mdevs
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
                   ` (6 preceding siblings ...)
  2020-03-22 12:32 ` [PATCH v1 7/8] vfio/type1: Add VFIO_IOMMU_CACHE_INVALIDATE Liu, Yi L
@ 2020-03-22 12:32 ` Liu, Yi L
  2020-03-26 12:56 ` [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
  8 siblings, 0 replies; 15+ messages in thread
From: Liu, Yi L @ 2020-03-22 12:32 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, kevin.tian, ashok.raj, kvm, jun.j.tian, iommu,
	linux-kernel, yi.y.sun, hao.wu

From: Liu Yi L <yi.l.liu@intel.com>

Recent years, mediated device pass-through framework (e.g. vfio-mdev)
are used to achieve flexible device sharing across domains (e.g. VMs).
Also there are hardware assisted mediated pass-through solutions from
platform vendors. e.g. Intel VT-d scalable mode which supports Intel
Scalable I/O Virtualization technology. Such mdevs are called IOMMU-
backed mdevs as there are IOMMU enforced DMA isolation for such mdevs.
In kernel, IOMMU-backed mdevs are exposed to IOMMU layer by aux-domain
concept, which means mdevs are protected by an iommu domain which is
aux-domain of its physical device. Details can be found in the KVM
presentation from Kevin Tian. IOMMU-backed equals to IOMMU-capable.

https://events19.linuxfoundation.org/wp-content/uploads/2017/12/\
Hardware-Assisted-Mediated-Pass-Through-with-VFIO-Kevin-Tian-Intel.pdf

This patch supports NESTING IOMMU for IOMMU-backed mdevs by figuring
out the physical device of an IOMMU-backed mdev and then invoking IOMMU
requests to IOMMU layer with the physical device and the mdev's aux
domain info.

With this patch, vSVA (Virtual Shared Virtual Addressing) can be used
on IOMMU-backed mdevs.

Cc: Kevin Tian <kevin.tian@intel.com>
CC: Jacob Pan <jacob.jun.pan@linux.intel.com>
CC: Jun Tian <jun.j.tian@intel.com>
Cc: Alex Williamson <alex.williamson@redhat.com>
Cc: Eric Auger <eric.auger@redhat.com>
Cc: Jean-Philippe Brucker <jean-philippe@linaro.org>
Signed-off-by: Liu Yi L <yi.l.liu@intel.com>
---
 drivers/vfio/vfio_iommu_type1.c | 23 ++++++++++++++++++++---
 1 file changed, 20 insertions(+), 3 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 937ec3f..d473665 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -132,6 +132,7 @@ struct vfio_regions {
 
 struct domain_capsule {
 	struct iommu_domain *domain;
+	struct vfio_group *group;
 	void *data;
 };
 
@@ -148,6 +149,7 @@ static int vfio_iommu_for_each_dev(struct vfio_iommu *iommu,
 	list_for_each_entry(d, &iommu->domain_list, next) {
 		dc.domain = d->domain;
 		list_for_each_entry(g, &d->group_list, next) {
+			dc.group = g;
 			ret = iommu_group_for_each_dev(g->iommu_group,
 						       &dc, fn);
 			if (ret)
@@ -2347,7 +2349,12 @@ static int vfio_bind_gpasid_fn(struct device *dev, void *data)
 	struct iommu_gpasid_bind_data *gbind_data =
 		(struct iommu_gpasid_bind_data *) dc->data;
 
-	return iommu_sva_bind_gpasid(dc->domain, dev, gbind_data);
+	if (dc->group->mdev_group)
+		return iommu_sva_bind_gpasid(dc->domain,
+			vfio_mdev_get_iommu_device(dev), gbind_data);
+	else
+		return iommu_sva_bind_gpasid(dc->domain,
+						dev, gbind_data);
 }
 
 static int vfio_unbind_gpasid_fn(struct device *dev, void *data)
@@ -2356,8 +2363,13 @@ static int vfio_unbind_gpasid_fn(struct device *dev, void *data)
 	struct iommu_gpasid_bind_data *gbind_data =
 		(struct iommu_gpasid_bind_data *) dc->data;
 
-	return iommu_sva_unbind_gpasid(dc->domain, dev,
+	if (dc->group->mdev_group)
+		return iommu_sva_unbind_gpasid(dc->domain,
+					vfio_mdev_get_iommu_device(dev),
 					gbind_data->hpasid);
+	else
+		return iommu_sva_unbind_gpasid(dc->domain, dev,
+						gbind_data->hpasid);
 }
 
 /**
@@ -2429,7 +2441,12 @@ static int vfio_cache_inv_fn(struct device *dev, void *data)
 	struct iommu_cache_invalidate_info *cache_inv_info =
 		(struct iommu_cache_invalidate_info *) dc->data;
 
-	return iommu_cache_invalidate(dc->domain, dev, cache_inv_info);
+	if (dc->group->mdev_group)
+		return iommu_cache_invalidate(dc->domain,
+			vfio_mdev_get_iommu_device(dev), cache_inv_info);
+	else
+		return iommu_cache_invalidate(dc->domain,
+						dev, cache_inv_info);
 }
 
 static long vfio_iommu_type1_ioctl(void *iommu_data,
-- 
2.7.4

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free)
  2020-03-22 12:31 ` [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free) Liu, Yi L
@ 2020-03-22 16:21   ` kbuild test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kbuild test robot @ 2020-03-22 16:21 UTC (permalink / raw)
  To: Liu, Yi L
  Cc: jean-philippe, kevin.tian, kbuild-all, ashok.raj, kvm, iommu,
	yi.y.sun, linux-kernel, alex.williamson, jun.j.tian, hao.wu

[-- Attachment #1: Type: text/plain, Size: 4623 bytes --]

Hi Yi,

Thank you for the patch! Perhaps something to improve:

[auto build test WARNING on vfio/next]
[also build test WARNING on v5.6-rc6 next-20200320]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Liu-Yi-L/vfio-expose-virtual-Shared-Virtual-Addressing-to-VMs/20200322-213259
base:   https://github.com/awilliam/linux-vfio.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=9.2.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All warnings (new ones prefixed by >>):

   drivers/vfio/vfio.c: In function 'vfio_create_mm':
   drivers/vfio/vfio.c:2149:8: error: implicit declaration of function 'ioasid_alloc_set'; did you mean 'ioasid_alloc'? [-Werror=implicit-function-declaration]
    2149 |  ret = ioasid_alloc_set((struct ioasid_set *) mm,
         |        ^~~~~~~~~~~~~~~~
         |        ioasid_alloc
>> drivers/vfio/vfio.c:2158:13: warning: assignment to 'long long unsigned int' from 'struct mm_struct *' makes integer from pointer without a cast [-Wint-conversion]
    2158 |  token->val = mm;
         |             ^
   drivers/vfio/vfio.c: In function 'vfio_mm_unlock_and_free':
   drivers/vfio/vfio.c:2170:2: error: implicit declaration of function 'ioasid_free_set'; did you mean 'ioasid_free'? [-Werror=implicit-function-declaration]
    2170 |  ioasid_free_set(vmm->ioasid_sid, true);
         |  ^~~~~~~~~~~~~~~
         |  ioasid_free
   drivers/vfio/vfio.c: In function 'vfio_mm_pasid_alloc':
   drivers/vfio/vfio.c:2227:26: warning: passing argument 1 of 'ioasid_alloc' makes pointer from integer without a cast [-Wint-conversion]
    2227 |  pasid = ioasid_alloc(vmm->ioasid_sid, min, max, NULL);
         |                       ~~~^~~~~~~~~~~~
         |                          |
         |                          int
   In file included from include/linux/iommu.h:16,
                    from drivers/vfio/vfio.c:20:
   include/linux/ioasid.h:45:56: note: expected 'struct ioasid_set *' but argument is of type 'int'
      45 | static inline ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min,
         |                                     ~~~~~~~~~~~~~~~~~~~^~~
   drivers/vfio/vfio.c: In function 'vfio_mm_pasid_free':
   drivers/vfio/vfio.c:2246:25: warning: passing argument 1 of 'ioasid_find' makes pointer from integer without a cast [-Wint-conversion]
    2246 |  pdata = ioasid_find(vmm->ioasid_sid, pasid, NULL);
         |                      ~~~^~~~~~~~~~~~
         |                         |
         |                         int
   In file included from include/linux/iommu.h:16,
                    from drivers/vfio/vfio.c:20:
   include/linux/ioasid.h:55:52: note: expected 'struct ioasid_set *' but argument is of type 'int'
      55 | static inline void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid,
         |                                 ~~~~~~~~~~~~~~~~~~~^~~
   cc1: some warnings being treated as errors

vim +2158 drivers/vfio/vfio.c

  2133	
  2134	/**
  2135	 * VFIO_MM objects - create, release, get, put, search
  2136	 * Caller of the function should have held vfio.vfio_mm_lock.
  2137	 */
  2138	static struct vfio_mm *vfio_create_mm(struct mm_struct *mm)
  2139	{
  2140		struct vfio_mm *vmm;
  2141		struct vfio_mm_token *token;
  2142		int ret = 0;
  2143	
  2144		vmm = kzalloc(sizeof(*vmm), GFP_KERNEL);
  2145		if (!vmm)
  2146			return ERR_PTR(-ENOMEM);
  2147	
  2148		/* Per mm IOASID set used for quota control and group operations */
  2149		ret = ioasid_alloc_set((struct ioasid_set *) mm,
  2150				       VFIO_DEFAULT_PASID_QUOTA, &vmm->ioasid_sid);
  2151		if (ret) {
  2152			kfree(vmm);
  2153			return ERR_PTR(ret);
  2154		}
  2155	
  2156		kref_init(&vmm->kref);
  2157		token = &vmm->token;
> 2158		token->val = mm;
  2159		vmm->pasid_quota = VFIO_DEFAULT_PASID_QUOTA;
  2160		mutex_init(&vmm->pasid_lock);
  2161	
  2162		list_add(&vmm->vfio_next, &vfio.vfio_mm_list);
  2163	
  2164		return vmm;
  2165	}
  2166	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46471 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 5/8] vfio/type1: Report 1st-level/stage-1 format to userspace
  2020-03-22 12:32 ` [PATCH v1 5/8] vfio/type1: Report 1st-level/stage-1 format to userspace Liu, Yi L
@ 2020-03-22 16:44   ` kbuild test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kbuild test robot @ 2020-03-22 16:44 UTC (permalink / raw)
  To: Liu, Yi L
  Cc: jean-philippe, kevin.tian, kbuild-all, ashok.raj, kvm, iommu,
	yi.y.sun, linux-kernel, alex.williamson, jun.j.tian, hao.wu

[-- Attachment #1: Type: text/plain, Size: 3463 bytes --]

Hi Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on vfio/next]
[also build test ERROR on v5.6-rc6 next-20200320]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Liu-Yi-L/vfio-expose-virtual-Shared-Virtual-Addressing-to-VMs/20200322-213259
base:   https://github.com/awilliam/linux-vfio.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=9.2.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/vfio/vfio_iommu_type1.c: In function 'vfio_iommu_get_stage1_format':
>> drivers/vfio/vfio_iommu_type1.c:2273:4: error: 'DOMAIN_ATTR_PASID_FORMAT' undeclared (first use in this function)
    2273 |    DOMAIN_ATTR_PASID_FORMAT, &format)) {
         |    ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/vfio/vfio_iommu_type1.c:2273:4: note: each undeclared identifier is reported only once for each function it appears in
   drivers/vfio/vfio_iommu_type1.c: In function 'vfio_iommu_type1_ioctl':
   drivers/vfio/vfio_iommu_type1.c:2355:11: error: implicit declaration of function 'iommu_get_uapi_version' [-Werror=implicit-function-declaration]
    2355 |    return iommu_get_uapi_version();
         |           ^~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/DOMAIN_ATTR_PASID_FORMAT +2273 drivers/vfio/vfio_iommu_type1.c

  2257	
  2258	static int vfio_iommu_get_stage1_format(struct vfio_iommu *iommu,
  2259						 u32 *stage1_format)
  2260	{
  2261		struct vfio_domain *domain;
  2262		u32 format = 0, tmp_format = 0;
  2263		int ret;
  2264	
  2265		mutex_lock(&iommu->lock);
  2266		if (list_empty(&iommu->domain_list)) {
  2267			mutex_unlock(&iommu->lock);
  2268			return -EINVAL;
  2269		}
  2270	
  2271		list_for_each_entry(domain, &iommu->domain_list, next) {
  2272			if (iommu_domain_get_attr(domain->domain,
> 2273				DOMAIN_ATTR_PASID_FORMAT, &format)) {
  2274				ret = -EINVAL;
  2275				format = 0;
  2276				goto out_unlock;
  2277			}
  2278			/*
  2279			 * format is always non-zero (the first format is
  2280			 * IOMMU_PASID_FORMAT_INTEL_VTD which is 1). For
  2281			 * the reason of potential different backed IOMMU
  2282			 * formats, here we expect to have identical formats
  2283			 * in the domain list, no mixed formats support.
  2284			 * return -EINVAL to fail the attempt of setup
  2285			 * VFIO_TYPE1_NESTING_IOMMU if non-identical formats
  2286			 * are detected.
  2287			 */
  2288			if (tmp_format && tmp_format != format) {
  2289				ret = -EINVAL;
  2290				format = 0;
  2291				goto out_unlock;
  2292			}
  2293	
  2294			tmp_format = format;
  2295		}
  2296		ret = 0;
  2297	
  2298	out_unlock:
  2299		if (format)
  2300			*stage1_format = format;
  2301		mutex_unlock(&iommu->lock);
  2302		return ret;
  2303	}
  2304	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46471 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 2/8] vfio/type1: Add vfio_iommu_type1 parameter for quota tuning
  2020-03-22 12:31 ` [PATCH v1 2/8] vfio/type1: Add vfio_iommu_type1 parameter for quota tuning Liu, Yi L
@ 2020-03-22 17:20   ` kbuild test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kbuild test robot @ 2020-03-22 17:20 UTC (permalink / raw)
  To: Liu, Yi L
  Cc: jean-philippe, kevin.tian, kbuild-all, ashok.raj, kvm, iommu,
	yi.y.sun, linux-kernel, alex.williamson, jun.j.tian, hao.wu

[-- Attachment #1: Type: text/plain, Size: 7135 bytes --]

Hi Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on vfio/next]
[also build test ERROR on v5.6-rc6 next-20200320]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Liu-Yi-L/vfio-expose-virtual-Shared-Virtual-Addressing-to-VMs/20200322-213259
base:   https://github.com/awilliam/linux-vfio.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=9.2.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/vfio/vfio.c: In function 'vfio_create_mm':
   drivers/vfio/vfio.c:2149:8: error: implicit declaration of function 'ioasid_alloc_set'; did you mean 'ioasid_alloc'? [-Werror=implicit-function-declaration]
    2149 |  ret = ioasid_alloc_set((struct ioasid_set *) mm,
         |        ^~~~~~~~~~~~~~~~
         |        ioasid_alloc
   drivers/vfio/vfio.c:2158:13: warning: assignment to 'long long unsigned int' from 'struct mm_struct *' makes integer from pointer without a cast [-Wint-conversion]
    2158 |  token->val = mm;
         |             ^
   drivers/vfio/vfio.c: In function 'vfio_mm_unlock_and_free':
   drivers/vfio/vfio.c:2170:2: error: implicit declaration of function 'ioasid_free_set'; did you mean 'ioasid_free'? [-Werror=implicit-function-declaration]
    2170 |  ioasid_free_set(vmm->ioasid_sid, true);
         |  ^~~~~~~~~~~~~~~
         |  ioasid_free
   drivers/vfio/vfio.c: In function 'vfio_mm_pasid_alloc':
>> drivers/vfio/vfio.c:2230:3: error: implicit declaration of function 'ioasid_adjust_set' [-Werror=implicit-function-declaration]
    2230 |   ioasid_adjust_set(vmm->ioasid_sid, quota);
         |   ^~~~~~~~~~~~~~~~~
   drivers/vfio/vfio.c:2233:26: warning: passing argument 1 of 'ioasid_alloc' makes pointer from integer without a cast [-Wint-conversion]
    2233 |  pasid = ioasid_alloc(vmm->ioasid_sid, min, max, NULL);
         |                       ~~~^~~~~~~~~~~~
         |                          |
         |                          int
   In file included from include/linux/iommu.h:16,
                    from drivers/vfio/vfio.c:20:
   include/linux/ioasid.h:45:56: note: expected 'struct ioasid_set *' but argument is of type 'int'
      45 | static inline ioasid_t ioasid_alloc(struct ioasid_set *set, ioasid_t min,
         |                                     ~~~~~~~~~~~~~~~~~~~^~~
   drivers/vfio/vfio.c: In function 'vfio_mm_pasid_free':
   drivers/vfio/vfio.c:2252:25: warning: passing argument 1 of 'ioasid_find' makes pointer from integer without a cast [-Wint-conversion]
    2252 |  pdata = ioasid_find(vmm->ioasid_sid, pasid, NULL);
         |                      ~~~^~~~~~~~~~~~
         |                         |
         |                         int
   In file included from include/linux/iommu.h:16,
                    from drivers/vfio/vfio.c:20:
   include/linux/ioasid.h:55:52: note: expected 'struct ioasid_set *' but argument is of type 'int'
      55 | static inline void *ioasid_find(struct ioasid_set *set, ioasid_t ioasid,
         |                                 ~~~~~~~~~~~~~~~~~~~^~~
   cc1: some warnings being treated as errors

vim +/ioasid_adjust_set +2230 drivers/vfio/vfio.c

  2133	
  2134	/**
  2135	 * VFIO_MM objects - create, release, get, put, search
  2136	 * Caller of the function should have held vfio.vfio_mm_lock.
  2137	 */
  2138	static struct vfio_mm *vfio_create_mm(struct mm_struct *mm)
  2139	{
  2140		struct vfio_mm *vmm;
  2141		struct vfio_mm_token *token;
  2142		int ret = 0;
  2143	
  2144		vmm = kzalloc(sizeof(*vmm), GFP_KERNEL);
  2145		if (!vmm)
  2146			return ERR_PTR(-ENOMEM);
  2147	
  2148		/* Per mm IOASID set used for quota control and group operations */
  2149		ret = ioasid_alloc_set((struct ioasid_set *) mm,
  2150				       VFIO_DEFAULT_PASID_QUOTA, &vmm->ioasid_sid);
  2151		if (ret) {
  2152			kfree(vmm);
  2153			return ERR_PTR(ret);
  2154		}
  2155	
  2156		kref_init(&vmm->kref);
  2157		token = &vmm->token;
> 2158		token->val = mm;
  2159		vmm->pasid_quota = VFIO_DEFAULT_PASID_QUOTA;
  2160		mutex_init(&vmm->pasid_lock);
  2161	
  2162		list_add(&vmm->vfio_next, &vfio.vfio_mm_list);
  2163	
  2164		return vmm;
  2165	}
  2166	
  2167	static void vfio_mm_unlock_and_free(struct vfio_mm *vmm)
  2168	{
  2169		/* destroy the ioasid set */
  2170		ioasid_free_set(vmm->ioasid_sid, true);
  2171		mutex_unlock(&vfio.vfio_mm_lock);
  2172		kfree(vmm);
  2173	}
  2174	
  2175	/* called with vfio.vfio_mm_lock held */
  2176	static void vfio_mm_release(struct kref *kref)
  2177	{
  2178		struct vfio_mm *vmm = container_of(kref, struct vfio_mm, kref);
  2179	
  2180		list_del(&vmm->vfio_next);
  2181		vfio_mm_unlock_and_free(vmm);
  2182	}
  2183	
  2184	void vfio_mm_put(struct vfio_mm *vmm)
  2185	{
  2186		kref_put_mutex(&vmm->kref, vfio_mm_release, &vfio.vfio_mm_lock);
  2187	}
  2188	EXPORT_SYMBOL_GPL(vfio_mm_put);
  2189	
  2190	/* Assume vfio_mm_lock or vfio_mm reference is held */
  2191	static void vfio_mm_get(struct vfio_mm *vmm)
  2192	{
  2193		kref_get(&vmm->kref);
  2194	}
  2195	
  2196	struct vfio_mm *vfio_mm_get_from_task(struct task_struct *task)
  2197	{
  2198		struct mm_struct *mm = get_task_mm(task);
  2199		struct vfio_mm *vmm;
  2200		unsigned long long val = (unsigned long long) mm;
  2201	
  2202		mutex_lock(&vfio.vfio_mm_lock);
  2203		list_for_each_entry(vmm, &vfio.vfio_mm_list, vfio_next) {
  2204			if (vmm->token.val == val) {
  2205				vfio_mm_get(vmm);
  2206				goto out;
  2207			}
  2208		}
  2209	
  2210		vmm = vfio_create_mm(mm);
  2211		if (IS_ERR(vmm))
  2212			vmm = NULL;
  2213	out:
  2214		mutex_unlock(&vfio.vfio_mm_lock);
  2215		mmput(mm);
  2216		return vmm;
  2217	}
  2218	EXPORT_SYMBOL_GPL(vfio_mm_get_from_task);
  2219	
  2220	int vfio_mm_pasid_alloc(struct vfio_mm *vmm, int quota, int min, int max)
  2221	{
  2222		ioasid_t pasid;
  2223		int ret = -ENOSPC;
  2224	
  2225		mutex_lock(&vmm->pasid_lock);
  2226	
  2227		/* update quota as it is tunable by admin */
  2228		if (vmm->pasid_quota != quota) {
  2229			vmm->pasid_quota = quota;
> 2230			ioasid_adjust_set(vmm->ioasid_sid, quota);
  2231		}
  2232	
  2233		pasid = ioasid_alloc(vmm->ioasid_sid, min, max, NULL);
  2234		if (pasid == INVALID_IOASID) {
  2235			ret = -ENOSPC;
  2236			goto out_unlock;
  2237		}
  2238	
  2239		ret = pasid;
  2240	out_unlock:
  2241		mutex_unlock(&vmm->pasid_lock);
  2242		return ret;
  2243	}
  2244	EXPORT_SYMBOL_GPL(vfio_mm_pasid_alloc);
  2245	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46471 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 6/8] vfio/type1: Bind guest page tables to host
  2020-03-22 12:32 ` [PATCH v1 6/8] vfio/type1: Bind guest page tables to host Liu, Yi L
@ 2020-03-22 18:10   ` kbuild test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kbuild test robot @ 2020-03-22 18:10 UTC (permalink / raw)
  To: Liu, Yi L
  Cc: jean-philippe, kevin.tian, kbuild-all, ashok.raj, kvm, iommu,
	yi.y.sun, linux-kernel, alex.williamson, jun.j.tian, hao.wu

[-- Attachment #1: Type: text/plain, Size: 8974 bytes --]

Hi Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on vfio/next]
[also build test ERROR on v5.6-rc6 next-20200320]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Liu-Yi-L/vfio-expose-virtual-Shared-Virtual-Addressing-to-VMs/20200322-213259
base:   https://github.com/awilliam/linux-vfio.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=9.2.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/vfio/vfio_iommu_type1.c: In function 'vfio_iommu_get_stage1_format':
   drivers/vfio/vfio_iommu_type1.c:2300:4: error: 'DOMAIN_ATTR_PASID_FORMAT' undeclared (first use in this function)
    2300 |    DOMAIN_ATTR_PASID_FORMAT, &format)) {
         |    ^~~~~~~~~~~~~~~~~~~~~~~~
   drivers/vfio/vfio_iommu_type1.c:2300:4: note: each undeclared identifier is reported only once for each function it appears in
   drivers/vfio/vfio_iommu_type1.c: In function 'vfio_iommu_type1_ioctl':
   drivers/vfio/vfio_iommu_type1.c:2464:11: error: implicit declaration of function 'iommu_get_uapi_version' [-Werror=implicit-function-declaration]
    2464 |    return iommu_get_uapi_version();
         |           ^~~~~~~~~~~~~~~~~~~~~~
>> drivers/vfio/vfio_iommu_type1.c:2626:15: error: implicit declaration of function 'iommu_uapi_get_data_size' [-Werror=implicit-function-declaration]
    2626 |   data_size = iommu_uapi_get_data_size(
         |               ^~~~~~~~~~~~~~~~~~~~~~~~
>> drivers/vfio/vfio_iommu_type1.c:2627:5: error: 'IOMMU_UAPI_BIND_GPASID' undeclared (first use in this function)
    2627 |     IOMMU_UAPI_BIND_GPASID, version);
         |     ^~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/iommu_uapi_get_data_size +2626 drivers/vfio/vfio_iommu_type1.c

  2446	
  2447	static long vfio_iommu_type1_ioctl(void *iommu_data,
  2448					   unsigned int cmd, unsigned long arg)
  2449	{
  2450		struct vfio_iommu *iommu = iommu_data;
  2451		unsigned long minsz;
  2452	
  2453		if (cmd == VFIO_CHECK_EXTENSION) {
  2454			switch (arg) {
  2455			case VFIO_TYPE1_IOMMU:
  2456			case VFIO_TYPE1v2_IOMMU:
  2457			case VFIO_TYPE1_NESTING_IOMMU:
  2458				return 1;
  2459			case VFIO_DMA_CC_IOMMU:
  2460				if (!iommu)
  2461					return 0;
  2462				return vfio_domains_have_iommu_cache(iommu);
  2463			case VFIO_NESTING_IOMMU_UAPI:
  2464				return iommu_get_uapi_version();
  2465			default:
  2466				return 0;
  2467			}
  2468		} else if (cmd == VFIO_IOMMU_GET_INFO) {
  2469			struct vfio_iommu_type1_info info;
  2470			struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
  2471			unsigned long capsz;
  2472			int ret;
  2473	
  2474			minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
  2475	
  2476			/* For backward compatibility, cannot require this */
  2477			capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
  2478	
  2479			if (copy_from_user(&info, (void __user *)arg, minsz))
  2480				return -EFAULT;
  2481	
  2482			if (info.argsz < minsz)
  2483				return -EINVAL;
  2484	
  2485			if (info.argsz >= capsz) {
  2486				minsz = capsz;
  2487				info.cap_offset = 0; /* output, no-recopy necessary */
  2488			}
  2489	
  2490			info.flags = VFIO_IOMMU_INFO_PGSIZES;
  2491	
  2492			info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
  2493	
  2494			ret = vfio_iommu_iova_build_caps(iommu, &caps);
  2495			if (ret)
  2496				return ret;
  2497	
  2498			ret = vfio_iommu_info_add_nesting_cap(iommu, &caps);
  2499			if (ret)
  2500				return ret;
  2501	
  2502			if (caps.size) {
  2503				info.flags |= VFIO_IOMMU_INFO_CAPS;
  2504	
  2505				if (info.argsz < sizeof(info) + caps.size) {
  2506					info.argsz = sizeof(info) + caps.size;
  2507				} else {
  2508					vfio_info_cap_shift(&caps, sizeof(info));
  2509					if (copy_to_user((void __user *)arg +
  2510							sizeof(info), caps.buf,
  2511							caps.size)) {
  2512						kfree(caps.buf);
  2513						return -EFAULT;
  2514					}
  2515					info.cap_offset = sizeof(info);
  2516				}
  2517	
  2518				kfree(caps.buf);
  2519			}
  2520	
  2521			return copy_to_user((void __user *)arg, &info, minsz) ?
  2522				-EFAULT : 0;
  2523	
  2524		} else if (cmd == VFIO_IOMMU_MAP_DMA) {
  2525			struct vfio_iommu_type1_dma_map map;
  2526			uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
  2527					VFIO_DMA_MAP_FLAG_WRITE;
  2528	
  2529			minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
  2530	
  2531			if (copy_from_user(&map, (void __user *)arg, minsz))
  2532				return -EFAULT;
  2533	
  2534			if (map.argsz < minsz || map.flags & ~mask)
  2535				return -EINVAL;
  2536	
  2537			return vfio_dma_do_map(iommu, &map);
  2538	
  2539		} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
  2540			struct vfio_iommu_type1_dma_unmap unmap;
  2541			long ret;
  2542	
  2543			minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size);
  2544	
  2545			if (copy_from_user(&unmap, (void __user *)arg, minsz))
  2546				return -EFAULT;
  2547	
  2548			if (unmap.argsz < minsz || unmap.flags)
  2549				return -EINVAL;
  2550	
  2551			ret = vfio_dma_do_unmap(iommu, &unmap);
  2552			if (ret)
  2553				return ret;
  2554	
  2555			return copy_to_user((void __user *)arg, &unmap, minsz) ?
  2556				-EFAULT : 0;
  2557	
  2558		} else if (cmd == VFIO_IOMMU_PASID_REQUEST) {
  2559			struct vfio_iommu_type1_pasid_request req;
  2560			unsigned long offset;
  2561	
  2562			minsz = offsetofend(struct vfio_iommu_type1_pasid_request,
  2563					    flags);
  2564	
  2565			if (copy_from_user(&req, (void __user *)arg, minsz))
  2566				return -EFAULT;
  2567	
  2568			if (req.argsz < minsz ||
  2569			    !vfio_iommu_type1_pasid_req_valid(req.flags))
  2570				return -EINVAL;
  2571	
  2572			if (copy_from_user((void *)&req + minsz,
  2573					   (void __user *)arg + minsz,
  2574					   sizeof(req) - minsz))
  2575				return -EFAULT;
  2576	
  2577			switch (req.flags & VFIO_PASID_REQUEST_MASK) {
  2578			case VFIO_IOMMU_PASID_ALLOC:
  2579			{
  2580				int ret = 0, result;
  2581	
  2582				result = vfio_iommu_type1_pasid_alloc(iommu,
  2583								req.alloc_pasid.min,
  2584								req.alloc_pasid.max);
  2585				if (result > 0) {
  2586					offset = offsetof(
  2587						struct vfio_iommu_type1_pasid_request,
  2588						alloc_pasid.result);
  2589					ret = copy_to_user(
  2590						      (void __user *) (arg + offset),
  2591						      &result, sizeof(result));
  2592				} else {
  2593					pr_debug("%s: PASID alloc failed\n", __func__);
  2594					ret = -EFAULT;
  2595				}
  2596				return ret;
  2597			}
  2598			case VFIO_IOMMU_PASID_FREE:
  2599				return vfio_iommu_type1_pasid_free(iommu,
  2600								   req.free_pasid);
  2601			default:
  2602				return -EINVAL;
  2603			}
  2604	
  2605		} else if (cmd == VFIO_IOMMU_BIND) {
  2606			struct vfio_iommu_type1_bind bind;
  2607			u32 version;
  2608			int data_size;
  2609			void *gbind_data;
  2610			int ret;
  2611	
  2612			minsz = offsetofend(struct vfio_iommu_type1_bind, flags);
  2613	
  2614			if (copy_from_user(&bind, (void __user *)arg, minsz))
  2615				return -EFAULT;
  2616	
  2617			if (bind.argsz < minsz)
  2618				return -EINVAL;
  2619	
  2620			/* Get the version of struct iommu_gpasid_bind_data */
  2621			if (copy_from_user(&version,
  2622				(void __user *) (arg + minsz),
  2623						sizeof(version)))
  2624				return -EFAULT;
  2625	
> 2626			data_size = iommu_uapi_get_data_size(
> 2627					IOMMU_UAPI_BIND_GPASID, version);
  2628			gbind_data = kzalloc(data_size, GFP_KERNEL);
  2629			if (!gbind_data)
  2630				return -ENOMEM;
  2631	
  2632			if (copy_from_user(gbind_data,
  2633				 (void __user *) (arg + minsz), data_size)) {
  2634				kfree(gbind_data);
  2635				return -EFAULT;
  2636			}
  2637	
  2638			switch (bind.flags & VFIO_IOMMU_BIND_MASK) {
  2639			case VFIO_IOMMU_BIND_GUEST_PGTBL:
  2640				ret = vfio_iommu_type1_bind_gpasid(iommu,
  2641								   gbind_data);
  2642				break;
  2643			case VFIO_IOMMU_UNBIND_GUEST_PGTBL:
  2644				ret = vfio_iommu_type1_unbind_gpasid(iommu,
  2645								     gbind_data);
  2646				break;
  2647			default:
  2648				ret = -EINVAL;
  2649				break;
  2650			}
  2651			kfree(gbind_data);
  2652			return ret;
  2653		}
  2654	
  2655		return -ENOTTY;
  2656	}
  2657	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46471 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* Re: [PATCH v1 4/8] vfio: Check nesting iommu uAPI version
  2020-03-22 12:32 ` [PATCH v1 4/8] vfio: Check nesting iommu uAPI version Liu, Yi L
@ 2020-03-22 18:30   ` kbuild test robot
  0 siblings, 0 replies; 15+ messages in thread
From: kbuild test robot @ 2020-03-22 18:30 UTC (permalink / raw)
  To: Liu, Yi L
  Cc: jean-philippe, kevin.tian, kbuild-all, ashok.raj, kvm, iommu,
	yi.y.sun, linux-kernel, alex.williamson, jun.j.tian, hao.wu

[-- Attachment #1: Type: text/plain, Size: 6618 bytes --]

Hi Yi,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on vfio/next]
[also build test ERROR on v5.6-rc6 next-20200320]
[if your patch is applied to the wrong git tree, please drop us a note to help
improve the system. BTW, we also suggest to use '--base' option to specify the
base tree in git format-patch, please see https://stackoverflow.com/a/37406982]

url:    https://github.com/0day-ci/linux/commits/Liu-Yi-L/vfio-expose-virtual-Shared-Virtual-Addressing-to-VMs/20200322-213259
base:   https://github.com/awilliam/linux-vfio.git next
config: arm64-defconfig (attached as .config)
compiler: aarch64-linux-gcc (GCC) 9.2.0
reproduce:
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # save the attached .config to linux build tree
        GCC_VERSION=9.2.0 make.cross ARCH=arm64 

If you fix the issue, kindly add following tag
Reported-by: kbuild test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/vfio/vfio_iommu_type1.c: In function 'vfio_iommu_type1_ioctl':
>> drivers/vfio/vfio_iommu_type1.c:2299:11: error: implicit declaration of function 'iommu_get_uapi_version' [-Werror=implicit-function-declaration]
    2299 |    return iommu_get_uapi_version();
         |           ^~~~~~~~~~~~~~~~~~~~~~
   cc1: some warnings being treated as errors

vim +/iommu_get_uapi_version +2299 drivers/vfio/vfio_iommu_type1.c

  2281	
  2282	static long vfio_iommu_type1_ioctl(void *iommu_data,
  2283					   unsigned int cmd, unsigned long arg)
  2284	{
  2285		struct vfio_iommu *iommu = iommu_data;
  2286		unsigned long minsz;
  2287	
  2288		if (cmd == VFIO_CHECK_EXTENSION) {
  2289			switch (arg) {
  2290			case VFIO_TYPE1_IOMMU:
  2291			case VFIO_TYPE1v2_IOMMU:
  2292			case VFIO_TYPE1_NESTING_IOMMU:
  2293				return 1;
  2294			case VFIO_DMA_CC_IOMMU:
  2295				if (!iommu)
  2296					return 0;
  2297				return vfio_domains_have_iommu_cache(iommu);
  2298			case VFIO_NESTING_IOMMU_UAPI:
> 2299				return iommu_get_uapi_version();
  2300			default:
  2301				return 0;
  2302			}
  2303		} else if (cmd == VFIO_IOMMU_GET_INFO) {
  2304			struct vfio_iommu_type1_info info;
  2305			struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
  2306			unsigned long capsz;
  2307			int ret;
  2308	
  2309			minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
  2310	
  2311			/* For backward compatibility, cannot require this */
  2312			capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
  2313	
  2314			if (copy_from_user(&info, (void __user *)arg, minsz))
  2315				return -EFAULT;
  2316	
  2317			if (info.argsz < minsz)
  2318				return -EINVAL;
  2319	
  2320			if (info.argsz >= capsz) {
  2321				minsz = capsz;
  2322				info.cap_offset = 0; /* output, no-recopy necessary */
  2323			}
  2324	
  2325			info.flags = VFIO_IOMMU_INFO_PGSIZES;
  2326	
  2327			info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
  2328	
  2329			ret = vfio_iommu_iova_build_caps(iommu, &caps);
  2330			if (ret)
  2331				return ret;
  2332	
  2333			ret = vfio_iommu_info_add_nesting_cap(iommu, &caps);
  2334			if (ret)
  2335				return ret;
  2336	
  2337			if (caps.size) {
  2338				info.flags |= VFIO_IOMMU_INFO_CAPS;
  2339	
  2340				if (info.argsz < sizeof(info) + caps.size) {
  2341					info.argsz = sizeof(info) + caps.size;
  2342				} else {
  2343					vfio_info_cap_shift(&caps, sizeof(info));
  2344					if (copy_to_user((void __user *)arg +
  2345							sizeof(info), caps.buf,
  2346							caps.size)) {
  2347						kfree(caps.buf);
  2348						return -EFAULT;
  2349					}
  2350					info.cap_offset = sizeof(info);
  2351				}
  2352	
  2353				kfree(caps.buf);
  2354			}
  2355	
  2356			return copy_to_user((void __user *)arg, &info, minsz) ?
  2357				-EFAULT : 0;
  2358	
  2359		} else if (cmd == VFIO_IOMMU_MAP_DMA) {
  2360			struct vfio_iommu_type1_dma_map map;
  2361			uint32_t mask = VFIO_DMA_MAP_FLAG_READ |
  2362					VFIO_DMA_MAP_FLAG_WRITE;
  2363	
  2364			minsz = offsetofend(struct vfio_iommu_type1_dma_map, size);
  2365	
  2366			if (copy_from_user(&map, (void __user *)arg, minsz))
  2367				return -EFAULT;
  2368	
  2369			if (map.argsz < minsz || map.flags & ~mask)
  2370				return -EINVAL;
  2371	
  2372			return vfio_dma_do_map(iommu, &map);
  2373	
  2374		} else if (cmd == VFIO_IOMMU_UNMAP_DMA) {
  2375			struct vfio_iommu_type1_dma_unmap unmap;
  2376			long ret;
  2377	
  2378			minsz = offsetofend(struct vfio_iommu_type1_dma_unmap, size);
  2379	
  2380			if (copy_from_user(&unmap, (void __user *)arg, minsz))
  2381				return -EFAULT;
  2382	
  2383			if (unmap.argsz < minsz || unmap.flags)
  2384				return -EINVAL;
  2385	
  2386			ret = vfio_dma_do_unmap(iommu, &unmap);
  2387			if (ret)
  2388				return ret;
  2389	
  2390			return copy_to_user((void __user *)arg, &unmap, minsz) ?
  2391				-EFAULT : 0;
  2392	
  2393		} else if (cmd == VFIO_IOMMU_PASID_REQUEST) {
  2394			struct vfio_iommu_type1_pasid_request req;
  2395			unsigned long offset;
  2396	
  2397			minsz = offsetofend(struct vfio_iommu_type1_pasid_request,
  2398					    flags);
  2399	
  2400			if (copy_from_user(&req, (void __user *)arg, minsz))
  2401				return -EFAULT;
  2402	
  2403			if (req.argsz < minsz ||
  2404			    !vfio_iommu_type1_pasid_req_valid(req.flags))
  2405				return -EINVAL;
  2406	
  2407			if (copy_from_user((void *)&req + minsz,
  2408					   (void __user *)arg + minsz,
  2409					   sizeof(req) - minsz))
  2410				return -EFAULT;
  2411	
  2412			switch (req.flags & VFIO_PASID_REQUEST_MASK) {
  2413			case VFIO_IOMMU_PASID_ALLOC:
  2414			{
  2415				int ret = 0, result;
  2416	
  2417				result = vfio_iommu_type1_pasid_alloc(iommu,
  2418								req.alloc_pasid.min,
  2419								req.alloc_pasid.max);
  2420				if (result > 0) {
  2421					offset = offsetof(
  2422						struct vfio_iommu_type1_pasid_request,
  2423						alloc_pasid.result);
  2424					ret = copy_to_user(
  2425						      (void __user *) (arg + offset),
  2426						      &result, sizeof(result));
  2427				} else {
  2428					pr_debug("%s: PASID alloc failed\n", __func__);
  2429					ret = -EFAULT;
  2430				}
  2431				return ret;
  2432			}
  2433			case VFIO_IOMMU_PASID_FREE:
  2434				return vfio_iommu_type1_pasid_free(iommu,
  2435								   req.free_pasid);
  2436			default:
  2437				return -EINVAL;
  2438			}
  2439		}
  2440	
  2441		return -ENOTTY;
  2442	}
  2443	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 46471 bytes --]

[-- Attachment #3: Type: text/plain, Size: 156 bytes --]

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

^ permalink raw reply	[flat|nested] 15+ messages in thread

* RE: [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs
  2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
                   ` (7 preceding siblings ...)
  2020-03-22 12:32 ` [PATCH v1 8/8] vfio/type1: Add vSVA support for IOMMU-backed mdevs Liu, Yi L
@ 2020-03-26 12:56 ` Liu, Yi L
  8 siblings, 0 replies; 15+ messages in thread
From: Liu, Yi L @ 2020-03-26 12:56 UTC (permalink / raw)
  To: alex.williamson, eric.auger
  Cc: jean-philippe, Tian, Kevin, Raj,  Ashok, kvm, Tian, Jun J, iommu,
	linux-kernel, Sun, Yi Y, Wu, Hao

> From: Liu, Yi L <yi.l.liu@intel.com>
> Sent: Sunday, March 22, 2020 8:32 PM
> To: alex.williamson@redhat.com; eric.auger@redhat.com
> Subject: [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs
> 
> From: Liu Yi L <yi.l.liu@intel.com>
> 
> Shared Virtual Addressing (SVA), a.k.a, Shared Virtual Memory (SVM) on
> Intel platforms allows address space sharing between device DMA and
> applications. SVA can reduce programming complexity and enhance security.
> 
> This VFIO series is intended to expose SVA usage to VMs. i.e. Sharing
> guest application address space with passthru devices. This is called
> vSVA in this series. The whole vSVA enabling requires QEMU/VFIO/IOMMU
> changes. For IOMMU and QEMU changes, they are in separate series (listed
> in the "Related series").
> 
> The high-level architecture for SVA virtualization is as below, the key
> design of vSVA support is to utilize the dual-stage IOMMU translation (
> also known as IOMMU nesting translation) capability in host IOMMU.
> 
> 
>     .-------------.  .---------------------------.
>     |   vIOMMU    |  | Guest process CR3, FL only|
>     |             |  '---------------------------'
>     .----------------/
>     | PASID Entry |--- PASID cache flush -
>     '-------------'                       |
>     |             |                       V
>     |             |                CR3 in GPA
>     '-------------'
> Guest
> ------| Shadow |--------------------------|--------
>       v        v                          v
> Host
>     .-------------.  .----------------------.
>     |   pIOMMU    |  | Bind FL for GVA-GPA  |
>     |             |  '----------------------'
>     .----------------/  |
>     | PASID Entry |     V (Nested xlate)
>     '----------------\.------------------------------.
>     |             |   |SL for GPA-HPA, default domain|
>     |             |   '------------------------------'
>     '-------------'
> Where:
>  - FL = First level/stage one page tables
>  - SL = Second level/stage two page tables
> 
> There are roughly four parts in this patchset which are
> corresponding to the basic vSVA support for PCI device
> assignment
>  1. vfio support for PASID allocation and free for VMs
>  2. vfio support for guest page table binding request from VMs
>  3. vfio support for IOMMU cache invalidation from VMs
>  4. vfio support for vSVA usage on IOMMU-backed mdevs
> 
> The complete vSVA kernel upstream patches are divided into three phases:
>     1. Common APIs and PCI device direct assignment
>     2. IOMMU-backed Mediated Device assignment
>     3. Page Request Services (PRS) support
> 
> This patchset is aiming for the phase 1 and phase 2, and based on Jacob's
> below series.
> [PATCH V10 00/11] Nested Shared Virtual Address (SVA) VT-d support:
> https://lkml.org/lkml/2020/3/20/1172
> 
> Complete set for current vSVA can be found in below branch.
> https://github.com/luxis1999/linux-vsva.git: vsva-linux-5.6-rc6
> 
> The corresponding QEMU patch series is as below, complete QEMU set can be
> found in below branch.
> [PATCH v1 00/22] intel_iommu: expose Shared Virtual Addressing to VMs
> complete QEMU set can be found in below link:
> https://github.com/luxis1999/qemu.git: sva_vtd_v10_v1

The ioasid extension is in the below link.

https://lkml.org/lkml/2020/3/25/874

Regards,
Yi Liu
_______________________________________________
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

^ permalink raw reply	[flat|nested] 15+ messages in thread

end of thread, back to index

Thread overview: 15+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-03-22 12:31 [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L
2020-03-22 12:31 ` [PATCH v1 1/8] vfio: Add VFIO_IOMMU_PASID_REQUEST(alloc/free) Liu, Yi L
2020-03-22 16:21   ` kbuild test robot
2020-03-22 12:31 ` [PATCH v1 2/8] vfio/type1: Add vfio_iommu_type1 parameter for quota tuning Liu, Yi L
2020-03-22 17:20   ` kbuild test robot
2020-03-22 12:32 ` [PATCH v1 3/8] vfio/type1: Report PASID alloc/free support to userspace Liu, Yi L
2020-03-22 12:32 ` [PATCH v1 4/8] vfio: Check nesting iommu uAPI version Liu, Yi L
2020-03-22 18:30   ` kbuild test robot
2020-03-22 12:32 ` [PATCH v1 5/8] vfio/type1: Report 1st-level/stage-1 format to userspace Liu, Yi L
2020-03-22 16:44   ` kbuild test robot
2020-03-22 12:32 ` [PATCH v1 6/8] vfio/type1: Bind guest page tables to host Liu, Yi L
2020-03-22 18:10   ` kbuild test robot
2020-03-22 12:32 ` [PATCH v1 7/8] vfio/type1: Add VFIO_IOMMU_CACHE_INVALIDATE Liu, Yi L
2020-03-22 12:32 ` [PATCH v1 8/8] vfio/type1: Add vSVA support for IOMMU-backed mdevs Liu, Yi L
2020-03-26 12:56 ` [PATCH v1 0/8] vfio: expose virtual Shared Virtual Addressing to VMs Liu, Yi L

IOMMU Archive on lore.kernel.org

Archives are clonable:
	git clone --mirror https://lore.kernel.org/linux-iommu/0 linux-iommu/git/0.git

	# If you have public-inbox 1.1+ installed, you may
	# initialize and index your mirror using the following commands:
	public-inbox-init -V2 linux-iommu linux-iommu/ https://lore.kernel.org/linux-iommu \
		iommu@lists.linux-foundation.org
	public-inbox-index linux-iommu

Example config snippet for mirrors

Newsgroup available over NNTP:
	nntp://nntp.lore.kernel.org/org.linux-foundation.lists.iommu


AGPL code for this site: git clone https://public-inbox.org/public-inbox.git