Skip to content

Commit 8c6eaba

Browse files
yiliu1765jgunthorpe
authored andcommitted
iommufd: Add IOMMU_HWPT_INVALIDATE
In nested translation, the stage-1 page table is user-managed but cached by the IOMMU hardware, so an update on present page table entries in the stage-1 page table should be followed with a cache invalidation. Add an IOMMU_HWPT_INVALIDATE ioctl to support such a cache invalidation. It takes hwpt_id to specify the iommu_domain, and a multi-entry array to support multiple invalidation data in one ioctl. enum iommu_hwpt_invalidate_data_type is defined to tag the data type of the entries in the multi-entry array. Link: https://lore.kernel.org/r/[email protected] Reviewed-by: Kevin Tian <[email protected]> Co-developed-by: Nicolin Chen <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Signed-off-by: Yi Liu <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent f35b88b commit 8c6eaba

File tree

4 files changed

+97
-0
lines changed

4 files changed

+97
-0
lines changed

drivers/iommu/iommufd/hw_pagetable.c

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -371,3 +371,44 @@ int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd)
371371
iommufd_put_object(ucmd->ictx, &hwpt_paging->common.obj);
372372
return rc;
373373
}
374+
375+
int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd)
376+
{
377+
struct iommu_hwpt_invalidate *cmd = ucmd->cmd;
378+
struct iommu_user_data_array data_array = {
379+
.type = cmd->data_type,
380+
.uptr = u64_to_user_ptr(cmd->data_uptr),
381+
.entry_len = cmd->entry_len,
382+
.entry_num = cmd->entry_num,
383+
};
384+
struct iommufd_hw_pagetable *hwpt;
385+
u32 done_num = 0;
386+
int rc;
387+
388+
if (cmd->__reserved) {
389+
rc = -EOPNOTSUPP;
390+
goto out;
391+
}
392+
393+
if (cmd->entry_num && (!cmd->data_uptr || !cmd->entry_len)) {
394+
rc = -EINVAL;
395+
goto out;
396+
}
397+
398+
hwpt = iommufd_get_hwpt_nested(ucmd, cmd->hwpt_id);
399+
if (IS_ERR(hwpt)) {
400+
rc = PTR_ERR(hwpt);
401+
goto out;
402+
}
403+
404+
rc = hwpt->domain->ops->cache_invalidate_user(hwpt->domain,
405+
&data_array);
406+
done_num = data_array.entry_num;
407+
408+
iommufd_put_object(ucmd->ictx, &hwpt->obj);
409+
out:
410+
cmd->entry_num = done_num;
411+
if (iommufd_ucmd_respond(ucmd, sizeof(*cmd)))
412+
return -EFAULT;
413+
return rc;
414+
}

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -328,6 +328,15 @@ iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id)
328328
IOMMUFD_OBJ_HWPT_PAGING),
329329
struct iommufd_hwpt_paging, common.obj);
330330
}
331+
332+
static inline struct iommufd_hw_pagetable *
333+
iommufd_get_hwpt_nested(struct iommufd_ucmd *ucmd, u32 id)
334+
{
335+
return container_of(iommufd_get_object(ucmd->ictx, id,
336+
IOMMUFD_OBJ_HWPT_NESTED),
337+
struct iommufd_hw_pagetable, obj);
338+
}
339+
331340
int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd);
332341
int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd);
333342

@@ -345,6 +354,7 @@ void iommufd_hwpt_paging_abort(struct iommufd_object *obj);
345354
void iommufd_hwpt_nested_destroy(struct iommufd_object *obj);
346355
void iommufd_hwpt_nested_abort(struct iommufd_object *obj);
347356
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd);
357+
int iommufd_hwpt_invalidate(struct iommufd_ucmd *ucmd);
348358

349359
static inline void iommufd_hw_pagetable_put(struct iommufd_ctx *ictx,
350360
struct iommufd_hw_pagetable *hwpt)

drivers/iommu/iommufd/main.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -322,6 +322,7 @@ union ucmd_buffer {
322322
struct iommu_hw_info info;
323323
struct iommu_hwpt_alloc hwpt;
324324
struct iommu_hwpt_get_dirty_bitmap get_dirty_bitmap;
325+
struct iommu_hwpt_invalidate cache;
325326
struct iommu_hwpt_set_dirty_tracking set_dirty_tracking;
326327
struct iommu_ioas_alloc alloc;
327328
struct iommu_ioas_allow_iovas allow_iovas;
@@ -360,6 +361,8 @@ static const struct iommufd_ioctl_op iommufd_ioctl_ops[] = {
360361
__reserved),
361362
IOCTL_OP(IOMMU_HWPT_GET_DIRTY_BITMAP, iommufd_hwpt_get_dirty_bitmap,
362363
struct iommu_hwpt_get_dirty_bitmap, data),
364+
IOCTL_OP(IOMMU_HWPT_INVALIDATE, iommufd_hwpt_invalidate,
365+
struct iommu_hwpt_invalidate, __reserved),
363366
IOCTL_OP(IOMMU_HWPT_SET_DIRTY_TRACKING, iommufd_hwpt_set_dirty_tracking,
364367
struct iommu_hwpt_set_dirty_tracking, __reserved),
365368
IOCTL_OP(IOMMU_IOAS_ALLOC, iommufd_ioas_alloc_ioctl,

include/uapi/linux/iommufd.h

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@ enum {
4949
IOMMUFD_CMD_GET_HW_INFO,
5050
IOMMUFD_CMD_HWPT_SET_DIRTY_TRACKING,
5151
IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP,
52+
IOMMUFD_CMD_HWPT_INVALIDATE,
5253
};
5354

5455
/**
@@ -613,4 +614,46 @@ struct iommu_hwpt_get_dirty_bitmap {
613614
#define IOMMU_HWPT_GET_DIRTY_BITMAP _IO(IOMMUFD_TYPE, \
614615
IOMMUFD_CMD_HWPT_GET_DIRTY_BITMAP)
615616

617+
/**
618+
* enum iommu_hwpt_invalidate_data_type - IOMMU HWPT Cache Invalidation
619+
* Data Type
620+
* @IOMMU_HWPT_INVALIDATE_DATA_VTD_S1: Invalidation data for VTD_S1
621+
*/
622+
enum iommu_hwpt_invalidate_data_type {
623+
IOMMU_HWPT_INVALIDATE_DATA_VTD_S1,
624+
};
625+
626+
/**
627+
* struct iommu_hwpt_invalidate - ioctl(IOMMU_HWPT_INVALIDATE)
628+
* @size: sizeof(struct iommu_hwpt_invalidate)
629+
* @hwpt_id: ID of a nested HWPT for cache invalidation
630+
* @data_uptr: User pointer to an array of driver-specific cache invalidation
631+
* data.
632+
* @data_type: One of enum iommu_hwpt_invalidate_data_type, defining the data
633+
* type of all the entries in the invalidation request array. It
634+
* should be a type supported by the hwpt pointed by @hwpt_id.
635+
* @entry_len: Length (in bytes) of a request entry in the request array
636+
* @entry_num: Input the number of cache invalidation requests in the array.
637+
* Output the number of requests successfully handled by kernel.
638+
* @__reserved: Must be 0.
639+
*
640+
* Invalidate the iommu cache for user-managed page table. Modifications on a
641+
* user-managed page table should be followed by this operation to sync cache.
642+
* Each ioctl can support one or more cache invalidation requests in the array
643+
* that has a total size of @entry_len * @entry_num.
644+
*
645+
* An empty invalidation request array by setting @entry_num==0 is allowed, and
646+
* @entry_len and @data_uptr would be ignored in this case. This can be used to
647+
* check if the given @data_type is supported or not by kernel.
648+
*/
649+
struct iommu_hwpt_invalidate {
650+
__u32 size;
651+
__u32 hwpt_id;
652+
__aligned_u64 data_uptr;
653+
__u32 data_type;
654+
__u32 entry_len;
655+
__u32 entry_num;
656+
__u32 __reserved;
657+
};
658+
#define IOMMU_HWPT_INVALIDATE _IO(IOMMUFD_TYPE, IOMMUFD_CMD_HWPT_INVALIDATE)
616659
#endif

0 commit comments

Comments
 (0)