[RFC PATCH v4 03/16] iommu/arm-smmu-v3: Add initial pSMMU realm viommu plumbing

Aneesh Kumar K.V aneesh.kumar at kernel.org
Wed Sep 9 03:09:31 PDT 2026


Jason Gunthorpe <jgg at ziepe.ca> writes:

> On Mon, Sep 07, 2026 at 03:15:25PM +0530, Aneesh Kumar K.V wrote:
>
>> I looked into this, and it becomes fairly complicated. We can move all
>> vdev/TDI-related code to arm-smmu-realm-v3.c, but that would result in:
>
> I was going for the opposite, you'd move everything out of arm-smmu-v3
> and into the arm-cca-host and obtain the viommu through tsm_ops not
> through iommu_ops.
>
> I guess I pointed to that in another email.
>
> The only thing arm-smmu-v3 should provide is a simple function to give
> the pdev phys and irq parameters. arm-cca-host calls that when it
> creates an viommu object.
>


So ended up with

static const struct tsm_viommu_ops cca_tsm_viommu_ops = {
	.owner = THIS_MODULE,
	.type = IOMMU_VIOMMU_TYPE_ARM_REALM_SMMUV3,
	.get_size = cca_viommu_get_size,
	.init = cca_viommu_init,
};

struct cca_viommu {
	struct cca_psmmu *psmmu;
	struct iommu_viommu_provider *iommu_provider;
	const struct iommufd_viommu_ops *iommu_ops; // backing SMMU ops
};


// backing ops are mostly used for

static struct iommu_domain *
cca_viommu_alloc_domain_nested(struct iommufd_viommu *viommu, u32 flags,
			       const struct iommu_user_data *user_data)
{
	struct cca_viommu *cca = viommu->provider_data;

	return cca->iommu_ops->alloc_domain_nested(viommu, flags, user_data);
}

static int cca_viommu_cache_invalidate(struct iommufd_viommu *viommu,
				       struct iommu_user_data_array *array)
{
	struct cca_viommu *cca = viommu->provider_data;

	return cca->iommu_ops->cache_invalidate(viommu, array);
}


struct cca_vdevice {
	struct iommufd_vdevice core;
	struct pci_tsm_context *tsm_context;
	struct cca_host_tdi host_tdi;
	u32 l2_sid;
};

static const struct iommufd_viommu_ops cca_viommu_ops = {
	.destroy = cca_viommu_destroy,
	.alloc_domain_nested = cca_viommu_alloc_domain_nested,
	.cache_invalidate = cca_viommu_cache_invalidate,
	.vdevice_size = VDEVICE_STRUCT_SIZE(struct cca_vdevice, core),
	.vdevice_init = cca_vdevice_init,
	.vdevice_tsm_req = cca_vdevice_tsm_req,
};


and on iommu side

struct iommu_viommu_provider {
	size_t size;
	int (*init)(struct iommufd_viommu *viommu, struct device *dev,
		    enum iommu_viommu_type type,
		    struct iommu_domain *parent_domain,
		    const struct iommu_user_data *user_data);
	int (*get_params)(struct iommu_viommu_provider *provider,
			  struct device *dev, enum iommu_viommu_type type,
			  void *params, size_t params_size);
	void (*release)(struct iommu_viommu_provider *provider);
	void *data;
};


The TSM disconnect path will now fail while any vdevice is alive or
active. Destroying a vdevice will unlock and destroy the VDEV. I think
we can also unmap its MMIO mappings at that point, provided we track the
mapping requests in a list alongside the vdevice details.

All CCA operations will use pci_tsm_pf0::lock, though I think the
locking can be made more fine-grained.

I will send a cleaned-up series so that we can review the code changes.

-aneesh



More information about the linux-arm-kernel mailing list