ANDROID: drivers: iommu: pviommu: Add pasid support

Add set_dev_pasid and remove_dev_pasid calls.
However SVA domains are not supported.

Bug: 357781595
Bug: 348382247
Bug: 236685427
Change-Id: I521b568121d970210f63e116576b3c5827f882b2
Signed-off-by: Mostafa Saleh <smostafa@google.com>
This commit is contained in:
Mostafa Saleh
2023-08-07 08:39:49 +00:00
committed by Carlos Llamas
parent f185914e77
commit 230765d93d
+26 -10
View File
@@ -185,9 +185,10 @@ static void pviommu_domain_free(struct iommu_domain *domain)
kfree(pv_domain);
}
static void pviommu_detach_dev(struct pviommu_master *master)
static void pviommu_remove_dev_pasid(struct device *dev, ioasid_t pasid,
struct iommu_domain *domain)
{
struct device *dev = master->dev;
struct pviommu_master *master = dev_iommu_priv_get(dev);
struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
struct pviommu *pv = master->iommu;
struct pviommu_domain *pv_domain = master->domain;
@@ -202,15 +203,23 @@ static void pviommu_detach_dev(struct pviommu_master *master)
sid = fwspec->ids[i];
arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_KVM_PVIOMMU_OP_FUNC_ID,
KVM_PVIOMMU_OP_DETACH_DEV,
pv->id, sid, 0, pv_domain->id, 0, &res);
pv->id, sid, pasid, pv_domain->id, 0, &res);
if (res.a0 != SMCCC_RET_SUCCESS)
dev_err(dev, "Failed to detach_dev sid %d, err %ld\n", sid, res.a0);
}
master->domain = NULL;
if (!pasid)
master->domain = NULL;
}
static int pviommu_attach_dev(struct iommu_domain *domain, struct device *dev)
static void pviommu_detach_dev(struct pviommu_master *master)
{
if (master->domain)
pviommu_remove_dev_pasid(master->dev, 0, &master->domain->domain);
}
static int pviommu_set_dev_pasid(struct iommu_domain *domain,
struct device *dev, ioasid_t pasid)
{
int ret = 0, i;
struct arm_smccc_res res;
@@ -223,14 +232,16 @@ static int pviommu_attach_dev(struct iommu_domain *domain, struct device *dev)
if (!fwspec)
return -ENOENT;
if (master->domain)
if (!pasid && master->domain) {
pviommu_detach_dev(master);
master->domain = pv_domain;
}
for (i = 0; i < fwspec->num_ids; i++) {
sid = fwspec->ids[i];
arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_KVM_PVIOMMU_OP_FUNC_ID,
KVM_PVIOMMU_OP_ATTACH_DEV,
pv->id, sid, 0 /* PASID */,
pv->id, sid, pasid,
pv_domain->id, master->ssid_bits, &res);
if (res.a0) {
ret = smccc_to_linux_ret(res.a0);
@@ -242,16 +253,19 @@ static int pviommu_attach_dev(struct iommu_domain *domain, struct device *dev)
while (i--) {
arm_smccc_1_1_hvc(ARM_SMCCC_VENDOR_HYP_KVM_PVIOMMU_OP_FUNC_ID,
KVM_PVIOMMU_OP_DETACH_DEV,
pv->id, sid, 0 /* PASID */,
pv->id, sid, pasid,
pv_domain->id, 0, &res);
}
} else {
master->domain = pv_domain;
}
return ret;
}
static int pviommu_attach_dev(struct iommu_domain *domain, struct device *dev)
{
return pviommu_set_dev_pasid(domain, dev, 0);
}
static struct iommu_domain *pviommu_domain_alloc(unsigned int type)
{
struct pviommu_domain *pv_domain;
@@ -342,12 +356,14 @@ static struct iommu_ops pviommu_ops = {
.probe_device = pviommu_probe_device,
.release_device = pviommu_release_device,
.domain_alloc = pviommu_domain_alloc,
.remove_dev_pasid = pviommu_remove_dev_pasid,
.owner = THIS_MODULE,
.default_domain_ops = &(const struct iommu_domain_ops) {
.attach_dev = pviommu_attach_dev,
.map_pages = pviommu_map_pages,
.unmap_pages = pviommu_unmap_pages,
.iova_to_phys = pviommu_iova_to_phys,
.set_dev_pasid = pviommu_set_dev_pasid,
.free = pviommu_domain_free,
}
};