/* Driver should use a per-structure helper in include/linux/iommufd.h */ int _iommufd_object_depend(struct iommufd_object *obj_dependent, struct iommufd_object *obj_depended)
{ /* Reject self dependency that dead locks */ if (obj_dependent == obj_depended) return -EINVAL; /* Only support dependency between two objects of the same type */ if (obj_dependent->type != obj_depended->type) return -EINVAL;
/* * Allocate an @offset to return to user space to use for an mmap() syscall * * Driver should use a per-structure helper in include/linux/iommufd.h
*/ int _iommufd_alloc_mmap(struct iommufd_ctx *ictx, struct iommufd_object *owner,
phys_addr_t mmio_addr, size_t length, unsignedlong *offset)
{ struct iommufd_mmap *immap; unsignedlong startp; int rc;
if (!PAGE_ALIGNED(mmio_addr)) return -EINVAL; if (!length || !PAGE_ALIGNED(length)) return -EINVAL;
/* Return -ENOENT if device is not associated to the vIOMMU */ int iommufd_viommu_get_vdev_id(struct iommufd_viommu *viommu, struct device *dev, unsignedlong *vdev_id)
{ struct iommufd_vdevice *vdev; unsignedlong index; int rc = -ENOENT;
/* * Typically called in driver's threaded IRQ handler. * The @type and @event_data must be defined in include/uapi/linux/iommufd.h
*/ int iommufd_viommu_report_event(struct iommufd_viommu *viommu, enum iommu_veventq_type type, void *event_data,
size_t data_len)
{ struct iommufd_veventq *veventq; struct iommufd_vevent *vevent; int rc = 0;
if (WARN_ON_ONCE(!data_len || !event_data)) return -EINVAL;
#ifdef CONFIG_IRQ_MSI_IOMMU /* * Get a iommufd_sw_msi_map for the msi physical address requested by the irq * layer. The mapping to IOVA is global to the iommufd file descriptor, every * domain that is attached to a device using the same MSI parameters will use * the same IOVA.
*/ staticstruct iommufd_sw_msi_map *
iommufd_sw_msi_get_map(struct iommufd_ctx *ictx, phys_addr_t msi_addr,
phys_addr_t sw_msi_start)
{ struct iommufd_sw_msi_map *cur; unsignedint max_pgoff = 0;
/* * Called by the irq code if the platform translates the MSI address through the * IOMMU. msi_addr is the physical address of the MSI page. iommufd will * allocate a fd global iova for the physical page that is the same on all * domains and devices.
*/ int iommufd_sw_msi(struct iommu_domain *domain, struct msi_desc *desc,
phys_addr_t msi_addr)
{ struct device *dev = msi_desc_to_dev(desc); struct iommufd_hwpt_paging *hwpt_paging; struct iommu_attach_handle *raw_handle; struct iommufd_attach_handle *handle; struct iommufd_sw_msi_map *msi_map; struct iommufd_ctx *ictx; unsignedlong iova; int rc;
/* * It is safe to call iommu_attach_handle_get() here because the iommu * core code invokes this under the group mutex which also prevents any * change of the attach handle for the duration of this function.
*/
iommu_group_mutex_assert(dev);
handle = to_iommufd_handle(raw_handle); /* No IOMMU_RESV_SW_MSI means no change to the msi_msg */ if (handle->idev->igroup->sw_msi_start == PHYS_ADDR_MAX) return 0;
ictx = handle->idev->ictx;
guard(mutex)(&ictx->sw_msi_lock); /* * The input msi_addr is the exact byte offset of the MSI doorbell, we * assume the caller has checked that it is contained with a MMIO region * that is secure to map at PAGE_SIZE.
*/
msi_map = iommufd_sw_msi_get_map(handle->idev->ictx,
msi_addr & PAGE_MASK,
handle->idev->igroup->sw_msi_start); if (IS_ERR(msi_map)) return PTR_ERR(msi_map);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.