On Fri, Apr 23, 2021 at 03:21:45PM +0530, Vivek Gautam wrote:
> SVA bind and unbind implementations will allow to prepare translation
> context with CPU page tables that can be programmed into host iommu
> hardware to realize shared address space utilization between the CPU
> and virtualized devices using virtio-iommu.
>
> Signed-off-by: Vivek Gautam
> ---
> drivers/iommu/virtio-iommu.c | 199 +-
> include/uapi/linux/virtio_iommu.h | 2 +
> 2 files changed, 199 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/iommu/virtio-iommu.c b/drivers/iommu/virtio-iommu.c
> index 250c137a211b..08f1294baeab 100644
> --- a/drivers/iommu/virtio-iommu.c
> +++ b/drivers/iommu/virtio-iommu.c
> @@ -14,6 +14,9 @@
> #include
> #include
> #include
> +#include
> +#include
> +#include
> #include
> #include
> #include
> @@ -28,6 +31,7 @@
> #include
> #include "iommu-pasid-table.h"
> #include "iommu-sva-lib.h"
> +#include "io-pgtable-arm.h"
Is this used here?
>
> #define MSI_IOVA_BASE0x800
> #define MSI_IOVA_LENGTH 0x10
> @@ -41,6 +45,7 @@ DEFINE_XARRAY_ALLOC1(viommu_asid_xa);
>
> static DEFINE_MUTEX(sva_lock);
> static DEFINE_MUTEX(iopf_lock);
> +static DEFINE_MUTEX(viommu_asid_lock);
>
> struct viommu_dev_pri_work {
> struct work_struct work;
> @@ -88,10 +93,22 @@ struct viommu_mapping {
> struct viommu_mm {
> int pasid;
> u64 archid;
> + struct viommu_sva_bond *bond;
> struct io_pgtable_ops *ops;
> struct viommu_domain*domain;
> };
>
> +struct viommu_sva_bond {
> + struct iommu_svasva;
> + struct mm_struct*mm;
> + struct iommu_psdtable_mmu_notifier *viommu_mn;
> + struct list_headlist;
> + refcount_t refs;
> +};
> +
> +#define sva_to_viommu_bond(handle) \
> + container_of(handle, struct viommu_sva_bond, sva)
> +
> struct viommu_domain {
> struct iommu_domain domain;
> struct viommu_dev *viommu;
> @@ -136,6 +153,7 @@ struct viommu_endpoint {
> boolpri_supported;
> boolsva_enabled;
> booliopf_enabled;
> + struct list_headbonds;
> };
>
> struct viommu_ep_entry {
> @@ -1423,14 +1441,15 @@ static int viommu_attach_pasid_table(struct
> viommu_endpoint *vdev,
>
> pst_cfg->iommu_dev = viommu->dev->parent;
>
> + mutex_lock(_asid_lock);
> /* Prepare PASID tables info to allocate a new table */
> ret = viommu_prepare_pst(vdev, pst_cfg, fmt);
> if (ret)
> - return ret;
> + goto err_out_unlock;
>
> ret = iommu_psdtable_alloc(tbl, pst_cfg);
> if (ret)
> - return ret;
> + goto err_out_unlock;
>
> pst_cfg->iommu_dev = viommu->dev->parent;
> pst_cfg->fmt = PASID_TABLE_ARM_SMMU_V3;
> @@ -1452,6 +1471,7 @@ static int viommu_attach_pasid_table(struct
> viommu_endpoint *vdev,
> if (ret)
> goto err_free_ops;
> }
> + mutex_unlock(_asid_lock);
> } else {
> /* TODO: otherwise, check for compatibility with vdev. */
> return -ENOSYS;
> @@ -1467,6 +1487,8 @@ static int viommu_attach_pasid_table(struct
> viommu_endpoint *vdev,
> err_free_psdtable:
> iommu_psdtable_free(tbl, >cfg);
>
> +err_out_unlock:
> + mutex_unlock(_asid_lock);
> return ret;
> }
>
> @@ -1706,6 +1728,7 @@ static struct iommu_device *viommu_probe_device(struct
> device *dev)
> vdev->dev = dev;
> vdev->viommu = viommu;
> INIT_LIST_HEAD(>resv_regions);
> + INIT_LIST_HEAD(>bonds);
> dev_iommu_priv_set(dev, vdev);
>
> if (viommu->probe_size) {
> @@ -1755,6 +1778,175 @@ static int viommu_of_xlate(struct device *dev, struct
> of_phandle_args *args)
> return iommu_fwspec_add_ids(dev, args->args, 1);
> }
>
> +static u32 viommu_sva_get_pasid(struct iommu_sva *handle)
> +{
> + struct viommu_sva_bond *bond = sva_to_viommu_bond(handle);
> +
> + return bond->mm->pasid;
> +}
> +
> +static void viommu_mmu_notifier_free(struct mmu_notifier *mn)
> +{
> + kfree(mn_to_pstiommu(mn));
> +}
> +
> +static struct mmu_notifier_ops viommu_mmu_notifier_ops = {
> + .free_notifier = viommu_mmu_notifier_free,
.invalidate_range and .release will be needed as well, to keep up to date
with changes to the address space
> +};
> +
> +/* Allocate or get existing MMU notifier for this {domain, mm} pair */
> +static struct iommu_psdtable_mmu_notifier *
> +viommu_mmu_notifier_get(struct