/* Page-shifted start position in mt_mmap to validate vma->vm_pgoff */ unsignedlong vm_pgoff;
/* Physical range for io_remap_pfn_range() */
phys_addr_t mmio_addr;
size_t length;
};
/* * The IOVA to PFN map. The map automatically copies the PFNs into multiple * domains and permits sharing of PFNs between io_pagetable instances. This * supports both a design where IOAS's are 1:1 with a domain (eg because the * domain is HW customized), or where the IOAS is 1:N with multiple generic * domains. The io_pagetable holds an interval tree of iopt_areas which point * to shared iopt_pages which hold the pfns mapped to the page table. * * The locking order is domains_rwsem -> iova_rwsem -> pages::mutex
*/ struct io_pagetable { struct rw_semaphore domains_rwsem; struct xarray domains; struct xarray access_list; unsignedint next_domain_id;
struct rw_semaphore iova_rwsem; struct rb_root_cached area_itree; /* IOVA that cannot become reserved, struct iopt_allowed */ struct rb_root_cached allowed_itree; /* IOVA that cannot be allocated, struct iopt_reserved */ struct rb_root_cached reserved_itree;
u8 disable_large_pages; unsignedlong iova_alignment;
};
int iommufd_vfio_ioctl(struct iommufd_ctx *ictx, unsignedint cmd, unsignedlong arg);
/* Copy the response in ucmd->cmd back to userspace. */ staticinlineint iommufd_ucmd_respond(struct iommufd_ucmd *ucmd,
size_t cmd_len)
{ if (copy_to_user(ucmd->ubuffer, ucmd->cmd,
min_t(size_t, ucmd->user_size, cmd_len))) return -EFAULT; return 0;
}
staticinlinebool iommufd_lock_obj(struct iommufd_object *obj)
{ if (!refcount_inc_not_zero(&obj->users)) returnfalse; if (!refcount_inc_not_zero(&obj->wait_cnt)) { /* * If the caller doesn't already have a ref on obj this must be * called under the xa_lock. Otherwise the caller is holding a * ref on users. Thus it cannot be one before this decrement.
*/
refcount_dec(&obj->users); returnfalse;
} returntrue;
}
struct iommufd_object *iommufd_get_object(struct iommufd_ctx *ictx, u32 id, enum iommufd_object_type type); staticinlinevoid iommufd_put_object(struct iommufd_ctx *ictx, struct iommufd_object *obj)
{ /* * Users first, then wait_cnt so that REMOVE_WAIT never sees a spurious * !0 users with a 0 wait_cnt.
*/
refcount_dec(&obj->users); if (refcount_dec_and_test(&obj->wait_cnt))
wake_up_interruptible_all(&ictx->destroy_wait);
}
/* * The caller holds a users refcount and wants to destroy the object. At this * point the caller has no wait_cnt reference and at least the xarray will be * holding one.
*/ staticinlinevoid iommufd_object_destroy_user(struct iommufd_ctx *ictx, struct iommufd_object *obj)
{ int ret;
ret = iommufd_object_remove(ictx, obj, obj->id, REMOVE_WAIT);
/* * If there is a bug and we couldn't destroy the object then we did put * back the caller's users refcount and will eventually try to free it * again during close.
*/
WARN_ON(ret);
}
/* * Similar to iommufd_object_destroy_user(), except that the object ID is left * reserved/tombstoned.
*/ staticinlinevoid iommufd_object_tombstone_user(struct iommufd_ctx *ictx, struct iommufd_object *obj)
{ int ret;
ret = iommufd_object_remove(ictx, obj, obj->id,
REMOVE_WAIT | REMOVE_OBJ_TOMBSTONE);
/* * If there is a bug and we couldn't destroy the object then we did put * back the caller's users refcount and will eventually try to free it * again during close.
*/
WARN_ON(ret);
}
/* * The HWPT allocated by autodomains is used in possibly many devices and * is automatically destroyed when its refcount reaches zero. * * If userspace uses the HWPT manually, even for a short term, then it will * disrupt this refcounting and the auto-free in the kernel will not work. * Userspace that tries to use the automatically allocated HWPT must be careful * to ensure that it is consistently destroyed, eg by not racing accesses * and by not attaching an automatic HWPT to a device manually.
*/ staticinlinevoid
iommufd_object_put_and_try_destroy(struct iommufd_ctx *ictx, struct iommufd_object *obj)
{
iommufd_object_remove(ictx, obj, obj->id, 0);
}
/* * Callers of these normal object allocators must call iommufd_object_finalize() * to finalize the object, or call iommufd_object_abort_and_destroy() to revert * the allocation.
*/ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
size_t size, enum iommufd_object_type type);
/* * Callers of these _ucmd allocators should not call iommufd_object_finalize() * or iommufd_object_abort_and_destroy(), as the core automatically does that.
*/ struct iommufd_object *
_iommufd_object_alloc_ucmd(struct iommufd_ucmd *ucmd, size_t size, enum iommufd_object_type type);
/* * The IO Address Space (IOAS) pagetable is a virtual page table backed by the * io_pagetable object. It is a user controlled mapping of IOVA -> PFNs. The * mapping is copied into all of the associated domains and made available to * in-kernel users. * * Every iommu_domain that is created is wrapped in a iommufd_hw_pagetable * object. When we go to attach a device to an IOAS we need to get an * iommu_domain and wrapping iommufd_hw_pagetable for it. * * An iommu_domain & iommfd_hw_pagetable will be automatically selected * for a device based on the hwpt_list. If no suitable iommu_domain * is found a new iommu_domain will be created.
*/ struct iommufd_ioas { struct iommufd_object obj; struct io_pagetable iopt; struct mutex mutex; struct list_head hwpt_list;
};
struct iommufd_ioas *iommufd_ioas_alloc(struct iommufd_ctx *ictx); int iommufd_ioas_alloc_ioctl(struct iommufd_ucmd *ucmd); void iommufd_ioas_destroy(struct iommufd_object *obj); int iommufd_ioas_iova_ranges(struct iommufd_ucmd *ucmd); int iommufd_ioas_allow_iovas(struct iommufd_ucmd *ucmd); int iommufd_ioas_map(struct iommufd_ucmd *ucmd); int iommufd_ioas_map_file(struct iommufd_ucmd *ucmd); int iommufd_ioas_change_process(struct iommufd_ucmd *ucmd); int iommufd_ioas_copy(struct iommufd_ucmd *ucmd); int iommufd_ioas_unmap(struct iommufd_ucmd *ucmd); int iommufd_ioas_option(struct iommufd_ucmd *ucmd); int iommufd_option_rlimit_mode(struct iommu_option *cmd, struct iommufd_ctx *ictx);
int iommufd_vfio_ioas(struct iommufd_ucmd *ucmd); int iommufd_check_iova_range(struct io_pagetable *iopt, struct iommu_hwpt_get_dirty_bitmap *bitmap);
/* * A HW pagetable is called an iommu_domain inside the kernel. This user object * allows directly creating and inspecting the domains. Domains that have kernel * owned page tables will be associated with an iommufd_ioas that provides the * IOVA to PFN map.
*/ struct iommufd_hw_pagetable { struct iommufd_object obj; struct iommu_domain *domain; struct iommufd_fault *fault; bool pasid_compat : 1;
};
/* Convert an iommu attach handle to iommufd handle. */ #define to_iommufd_handle(hdl) container_of(hdl, struct iommufd_attach_handle, handle)
/* * An iommufd_fault object represents an interface to deliver I/O page faults * to the user space. These objects are created/destroyed by the user space and * associated with hardware page table objects during page-table allocation.
*/ struct iommufd_fault { struct iommufd_eventq common; struct mutex mutex; /* serializes response flows */ struct xarray response;
};
/* * An iommufd_veventq object represents an interface to deliver vIOMMU events to * the user space. It is created/destroyed by the user space and associated with * a vIOMMU object during the allocations.
*/ struct iommufd_veventq { struct iommufd_eventq common; struct iommufd_viommu *viommu; struct list_head node; /* for iommufd_viommu::veventqs */ struct iommufd_vevent lost_events_header;
enum iommu_veventq_type type; unsignedint depth;
/* Use common.lock for protection */
u32 num_events;
u32 sequence;
};
/* * Remove the lost_events_header and add the new node at the same time. * Note the new node can be lost_events_header, for a sequence update.
*/ if (list_is_last(&veventq->lost_events_header.node, &eventq->deliver))
list_del(&veventq->lost_events_header.node);
list_add_tail(&vevent->node, &eventq->deliver);
vevent->header.sequence = veventq->sequence;
veventq->sequence = (veventq->sequence + 1) & INT_MAX;
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.