mirror of
https://github.com/torvalds/linux.git
synced 2026-05-31 10:33:41 +02:00
iommu/vt-d: Add set_dev_pasid callback for nested domain
Add intel_nested_set_dev_pasid() to set a nested type domain to a PASID of a device. Co-developed-by: Lu Baolu <baolu.lu@linux.intel.com> Signed-off-by: Lu Baolu <baolu.lu@linux.intel.com> Reviewed-by: Kevin Tian <kevin.tian@intel.com> Signed-off-by: Yi Liu <yi.l.liu@intel.com> Link: https://lore.kernel.org/r/20241107122234.7424-12-yi.l.liu@intel.com Signed-off-by: Joerg Roedel <jroedel@suse.de>
This commit is contained in:
parent
9bc18d283d
commit
67f6f56b59
|
|
@ -1812,12 +1812,6 @@ static int domain_setup_first_level(struct intel_iommu *iommu,
|
||||||
(pgd_t *)pgd, flags, old);
|
(pgd_t *)pgd, flags, old);
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool dev_is_real_dma_subdevice(struct device *dev)
|
|
||||||
{
|
|
||||||
return dev && dev_is_pci(dev) &&
|
|
||||||
pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev);
|
|
||||||
}
|
|
||||||
|
|
||||||
static int dmar_domain_attach_device(struct dmar_domain *domain,
|
static int dmar_domain_attach_device(struct dmar_domain *domain,
|
||||||
struct device *dev)
|
struct device *dev)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,7 @@
|
||||||
#include <linux/bitfield.h>
|
#include <linux/bitfield.h>
|
||||||
#include <linux/xarray.h>
|
#include <linux/xarray.h>
|
||||||
#include <linux/perf_event.h>
|
#include <linux/perf_event.h>
|
||||||
|
#include <linux/pci.h>
|
||||||
|
|
||||||
#include <asm/cacheflush.h>
|
#include <asm/cacheflush.h>
|
||||||
#include <asm/iommu.h>
|
#include <asm/iommu.h>
|
||||||
|
|
@ -832,6 +833,12 @@ iommu_domain_did(struct iommu_domain *domain, struct intel_iommu *iommu)
|
||||||
return domain_id_iommu(to_dmar_domain(domain), iommu);
|
return domain_id_iommu(to_dmar_domain(domain), iommu);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline bool dev_is_real_dma_subdevice(struct device *dev)
|
||||||
|
{
|
||||||
|
return dev && dev_is_pci(dev) &&
|
||||||
|
pci_real_dma_dev(to_pci_dev(dev)) != to_pci_dev(dev);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* 0: readable
|
* 0: readable
|
||||||
* 1: writable
|
* 1: writable
|
||||||
|
|
|
||||||
|
|
@ -130,8 +130,58 @@ static int intel_nested_cache_invalidate_user(struct iommu_domain *domain,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int domain_setup_nested(struct intel_iommu *iommu,
|
||||||
|
struct dmar_domain *domain,
|
||||||
|
struct device *dev, ioasid_t pasid,
|
||||||
|
struct iommu_domain *old)
|
||||||
|
{
|
||||||
|
if (!old)
|
||||||
|
return intel_pasid_setup_nested(iommu, dev, pasid, domain);
|
||||||
|
return intel_pasid_replace_nested(iommu, dev, pasid,
|
||||||
|
iommu_domain_did(old, iommu),
|
||||||
|
domain);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int intel_nested_set_dev_pasid(struct iommu_domain *domain,
|
||||||
|
struct device *dev, ioasid_t pasid,
|
||||||
|
struct iommu_domain *old)
|
||||||
|
{
|
||||||
|
struct device_domain_info *info = dev_iommu_priv_get(dev);
|
||||||
|
struct dmar_domain *dmar_domain = to_dmar_domain(domain);
|
||||||
|
struct intel_iommu *iommu = info->iommu;
|
||||||
|
struct dev_pasid_info *dev_pasid;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!pasid_supported(iommu) || dev_is_real_dma_subdevice(dev))
|
||||||
|
return -EOPNOTSUPP;
|
||||||
|
|
||||||
|
if (context_copied(iommu, info->bus, info->devfn))
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
ret = paging_domain_compatible(&dmar_domain->s2_domain->domain, dev);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
dev_pasid = domain_add_dev_pasid(domain, dev, pasid);
|
||||||
|
if (IS_ERR(dev_pasid))
|
||||||
|
return PTR_ERR(dev_pasid);
|
||||||
|
|
||||||
|
ret = domain_setup_nested(iommu, dmar_domain, dev, pasid, old);
|
||||||
|
if (ret)
|
||||||
|
goto out_remove_dev_pasid;
|
||||||
|
|
||||||
|
domain_remove_dev_pasid(old, dev, pasid);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
out_remove_dev_pasid:
|
||||||
|
domain_remove_dev_pasid(domain, dev, pasid);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static const struct iommu_domain_ops intel_nested_domain_ops = {
|
static const struct iommu_domain_ops intel_nested_domain_ops = {
|
||||||
.attach_dev = intel_nested_attach_dev,
|
.attach_dev = intel_nested_attach_dev,
|
||||||
|
.set_dev_pasid = intel_nested_set_dev_pasid,
|
||||||
.free = intel_nested_domain_free,
|
.free = intel_nested_domain_free,
|
||||||
.cache_invalidate_user = intel_nested_cache_invalidate_user,
|
.cache_invalidate_user = intel_nested_cache_invalidate_user,
|
||||||
};
|
};
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user