return ret;
 }
 EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);
+
+/**
+ * iommu_sva_bind_device() - Bind a process address space to a device
+ * @dev: the device
+ * @mm: the mm to bind, caller must hold a reference to it
+ *
+ * Create a bond between device and address space, allowing the device to access
+ * the mm using the returned PASID. If a bond already exists between @device and
+ * @mm, it is returned and an additional reference is taken. Caller must call
+ * iommu_sva_unbind_device() to release each reference.
+ *
+ * iommu_dev_enable_feature(dev, IOMMU_DEV_FEAT_SVA) must be called first, to
+ * initialize the required SVA features.
+ *
+ * On error, returns an ERR_PTR value.
+ */
+struct iommu_sva *
+iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)
+{
+       struct iommu_group *group;
+       struct iommu_sva *handle = ERR_PTR(-EINVAL);
+       const struct iommu_ops *ops = dev->bus->iommu_ops;
+
+       if (!ops || !ops->sva_bind)
+               return ERR_PTR(-ENODEV);
+
+       group = iommu_group_get(dev);
+       if (!group)
+               return ERR_PTR(-ENODEV);
+
+       /* Ensure device count and domain don't change while we're binding */
+       mutex_lock(&group->mutex);
+
+       /*
+        * To keep things simple, SVA currently doesn't support IOMMU groups
+        * with more than one device. Existing SVA-capable systems are not
+        * affected by the problems that required IOMMU groups (lack of ACS
+        * isolation, device ID aliasing and other hardware issues).
+        */
+       if (iommu_group_device_count(group) != 1)
+               goto out_unlock;
+
+       handle = ops->sva_bind(dev, mm, drvdata);
+
+out_unlock:
+       mutex_unlock(&group->mutex);
+       iommu_group_put(group);
+
+       return handle;
+}
+EXPORT_SYMBOL_GPL(iommu_sva_bind_device);
+
+/**
+ * iommu_sva_unbind_device() - Remove a bond created with iommu_sva_bind_device
+ * @handle: the handle returned by iommu_sva_bind_device()
+ *
+ * Put reference to a bond between device and address space. The device should
+ * not be issuing any more transaction for this PASID. All outstanding page
+ * requests for this PASID must have been flushed to the IOMMU.
+ *
+ * Returns 0 on success, or an error value
+ */
+void iommu_sva_unbind_device(struct iommu_sva *handle)
+{
+       struct iommu_group *group;
+       struct device *dev = handle->dev;
+       const struct iommu_ops *ops = dev->bus->iommu_ops;
+
+       if (!ops || !ops->sva_unbind)
+               return;
+
+       group = iommu_group_get(dev);
+       if (!group)
+               return;
+
+       mutex_lock(&group->mutex);
+       ops->sva_unbind(handle);
+       mutex_unlock(&group->mutex);
+
+       iommu_group_put(group);
+}
+EXPORT_SYMBOL_GPL(iommu_sva_unbind_device);
+
+int iommu_sva_set_ops(struct iommu_sva *handle,
+                     const struct iommu_sva_ops *sva_ops)
+{
+       if (handle->ops && handle->ops != sva_ops)
+               return -EEXIST;
+
+       handle->ops = sva_ops;
+       return 0;
+}
+EXPORT_SYMBOL_GPL(iommu_sva_set_ops);
+
+int iommu_sva_get_pasid(struct iommu_sva *handle)
+{
+       const struct iommu_ops *ops = handle->dev->bus->iommu_ops;
+
+       if (!ops || !ops->sva_get_pasid)
+               return IOMMU_PASID_INVALID;
+
+       return ops->sva_get_pasid(handle);
+}
+EXPORT_SYMBOL_GPL(iommu_sva_get_pasid);
 
 struct device;
 struct iommu_domain;
 struct notifier_block;
+struct iommu_sva;
 
 /* iommu fault flags */
 #define IOMMU_FAULT_READ       0x0
 
 typedef int (*iommu_fault_handler_t)(struct iommu_domain *,
                        struct device *, unsigned long, int, void *);
+typedef int (*iommu_mm_exit_handler_t)(struct device *dev, struct iommu_sva *,
+                                      void *);
 
 struct iommu_domain_geometry {
        dma_addr_t aperture_start; /* First address that can be mapped    */
 /* Per device IOMMU features */
 enum iommu_dev_features {
        IOMMU_DEV_FEAT_AUX,     /* Aux-domain feature */
+       IOMMU_DEV_FEAT_SVA,     /* Shared Virtual Addresses */
+};
+
+#define IOMMU_PASID_INVALID    (-1U)
+
+/**
+ * struct iommu_sva_ops - device driver callbacks for an SVA context
+ *
+ * @mm_exit: called when the mm is about to be torn down by exit_mmap. After
+ *           @mm_exit returns, the device must not issue any more transaction
+ *           with the PASID given as argument.
+ *
+ *           The @mm_exit handler is allowed to sleep. Be careful about the
+ *           locks taken in @mm_exit, because they might lead to deadlocks if
+ *           they are also held when dropping references to the mm. Consider the
+ *           following call chain:
+ *           mutex_lock(A); mmput(mm) -> exit_mm() -> @mm_exit() -> mutex_lock(A)
+ *           Using mmput_async() prevents this scenario.
+ *
+ */
+struct iommu_sva_ops {
+       iommu_mm_exit_handler_t mm_exit;
 };
 
 #ifdef CONFIG_IOMMU_API
  * @dev_feat_enabled: check enabled feature
  * @aux_attach/detach_dev: aux-domain specific attach/detach entries.
  * @aux_get_pasid: get the pasid given an aux-domain
+ * @sva_bind: Bind process address space to device
+ * @sva_unbind: Unbind process address space from device
+ * @sva_get_pasid: Get PASID associated to a SVA handle
  * @pgsize_bitmap: bitmap of all possible supported page sizes
  */
 struct iommu_ops {
        void (*aux_detach_dev)(struct iommu_domain *domain, struct device *dev);
        int (*aux_get_pasid)(struct iommu_domain *domain, struct device *dev);
 
+       struct iommu_sva *(*sva_bind)(struct device *dev, struct mm_struct *mm,
+                                     void *drvdata);
+       void (*sva_unbind)(struct iommu_sva *handle);
+       int (*sva_get_pasid)(struct iommu_sva *handle);
+
        unsigned long pgsize_bitmap;
 };
 
        u32                     ids[1];
 };
 
+/**
+ * struct iommu_sva - handle to a device-mm bond
+ */
+struct iommu_sva {
+       struct device                   *dev;
+       const struct iommu_sva_ops      *ops;
+};
+
 int iommu_fwspec_init(struct device *dev, struct fwnode_handle *iommu_fwnode,
                      const struct iommu_ops *ops);
 void iommu_fwspec_free(struct device *dev);
 void iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev);
 int iommu_aux_get_pasid(struct iommu_domain *domain, struct device *dev);
 
+struct iommu_sva *iommu_sva_bind_device(struct device *dev,
+                                       struct mm_struct *mm,
+                                       void *drvdata);
+void iommu_sva_unbind_device(struct iommu_sva *handle);
+int iommu_sva_set_ops(struct iommu_sva *handle,
+                     const struct iommu_sva_ops *ops);
+int iommu_sva_get_pasid(struct iommu_sva *handle);
+
 #else /* CONFIG_IOMMU_API */
 
 struct iommu_ops {};
        return -ENODEV;
 }
 
+static inline struct iommu_sva *
+iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)
+{
+       return NULL;
+}
+
+static inline void iommu_sva_unbind_device(struct iommu_sva *handle)
+{
+}
+
+static inline int iommu_sva_set_ops(struct iommu_sva *handle,
+                                   const struct iommu_sva_ops *ops)
+{
+       return -EINVAL;
+}
+
+static inline int iommu_sva_get_pasid(struct iommu_sva *handle)
+{
+       return IOMMU_PASID_INVALID;
+}
+
 #endif /* CONFIG_IOMMU_API */
 
 #ifdef CONFIG_IOMMU_DEBUGFS