Add new obj type IOMMUFD_OBJ_HWPT_KVM for KVM HW page tables, which correspond to iommu stage 2 domains whose paging strcutures and mappings are managed by KVM. Extend the IOMMU_HWPT_ALLOC ioctl to accept KVM HW page table specific data of "struct iommu_hwpt_kvm_info". The real allocator iommufd_hwpt_kvm_alloc() is now an empty function and will be implemented in next patch when config IOMMUFD_KVM_HWPT is on. Signed-off-by: Yan Zhao <yan.y.zhao@xxxxxxxxx> --- drivers/iommu/iommufd/device.c | 13 +++++---- drivers/iommu/iommufd/hw_pagetable.c | 29 +++++++++++++++++++- drivers/iommu/iommufd/iommufd_private.h | 35 +++++++++++++++++++++++++ drivers/iommu/iommufd/main.c | 4 +++ 4 files changed, 75 insertions(+), 6 deletions(-) diff --git a/drivers/iommu/iommufd/device.c b/drivers/iommu/iommufd/device.c index 59d3a07300d93..83af6b7e2784b 100644 --- a/drivers/iommu/iommufd/device.c +++ b/drivers/iommu/iommufd/device.c @@ -629,7 +629,8 @@ static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id, switch (pt_obj->type) { case IOMMUFD_OBJ_HWPT_NESTED: - case IOMMUFD_OBJ_HWPT_PAGING: { + case IOMMUFD_OBJ_HWPT_PAGING: + case IOMMUFD_OBJ_HWPT_KVM: { struct iommufd_hw_pagetable *hwpt = container_of(pt_obj, struct iommufd_hw_pagetable, obj); @@ -667,8 +668,9 @@ static int iommufd_device_change_pt(struct iommufd_device *idev, u32 *pt_id, /** * iommufd_device_attach - Connect a device to an iommu_domain * @idev: device to attach - * @pt_id: Input a IOMMUFD_OBJ_IOAS, or IOMMUFD_OBJ_HWPT_PAGING - * Output the IOMMUFD_OBJ_HWPT_PAGING ID + * @pt_id: Input a IOMMUFD_OBJ_IOAS, or IOMMUFD_OBJ_HWPT_PAGING, or + * IOMMUFD_OBJ_HWPT_KVM + * Output the IOMMUFD_OBJ_HWPT_PAGING ID or IOMMUFD_OBJ_HWPT_KVM ID * * This connects the device to an iommu_domain, either automatically or manually * selected. Once this completes the device could do DMA. @@ -696,8 +698,9 @@ EXPORT_SYMBOL_NS_GPL(iommufd_device_attach, IOMMUFD); /** * iommufd_device_replace - Change the device's iommu_domain * @idev: device to change - * @pt_id: Input a IOMMUFD_OBJ_IOAS, or IOMMUFD_OBJ_HWPT_PAGING - * Output the IOMMUFD_OBJ_HWPT_PAGING ID + * @pt_id: Input a IOMMUFD_OBJ_IOAS, or IOMMUFD_OBJ_HWPT_PAGING, or + * IOMMUFD_OBJ_HWPT_KVM + * Output the IOMMUFD_OBJ_HWPT_PAGING ID or IOMMUFD_OBJ_HWPT_KVM ID * * This is the same as:: * diff --git a/drivers/iommu/iommufd/hw_pagetable.c b/drivers/iommu/iommufd/hw_pagetable.c index 367459d92f696..c8430ec42cdf8 100644 --- a/drivers/iommu/iommufd/hw_pagetable.c +++ b/drivers/iommu/iommufd/hw_pagetable.c @@ -273,6 +273,31 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) if (IS_ERR(idev)) return PTR_ERR(idev); + if (cmd->data_type == IOMMU_HWPT_DATA_KVM) { + struct iommu_hwpt_kvm_info kvm_data; + struct iommufd_hwpt_kvm *hwpt_kvm; + + if (!cmd->data_len || cmd->data_len != sizeof(kvm_data) || + !cmd->data_uptr) { + rc = -EINVAL; + goto out_put_idev; + } + rc = copy_struct_from_user(&kvm_data, sizeof(kvm_data), + u64_to_user_ptr(cmd->data_uptr), + cmd->data_len); + if (rc) + goto out_put_idev; + + hwpt_kvm = iommufd_hwpt_kvm_alloc(ucmd->ictx, idev, cmd->flags, + &kvm_data); + if (IS_ERR(hwpt_kvm)) { + rc = PTR_ERR(hwpt_kvm); + goto out_put_idev; + } + hwpt = &hwpt_kvm->common; + goto out_respond; + } + pt_obj = iommufd_get_object(ucmd->ictx, cmd->pt_id, IOMMUFD_OBJ_ANY); if (IS_ERR(pt_obj)) { rc = -EINVAL; @@ -310,6 +335,7 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) goto out_put_pt; } +out_respond: cmd->out_hwpt_id = hwpt->obj.id; rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); if (rc) @@ -323,7 +349,8 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) if (ioas) mutex_unlock(&ioas->mutex); out_put_pt: - iommufd_put_object(pt_obj); + if (cmd->data_type != IOMMU_HWPT_DATA_KVM) + iommufd_put_object(pt_obj); out_put_idev: iommufd_put_object(&idev->obj); return rc; diff --git a/drivers/iommu/iommufd/iommufd_private.h b/drivers/iommu/iommufd/iommufd_private.h index 160521800d9b4..a46a6e3e537f9 100644 --- a/drivers/iommu/iommufd/iommufd_private.h +++ b/drivers/iommu/iommufd/iommufd_private.h @@ -125,6 +125,7 @@ enum iommufd_object_type { IOMMUFD_OBJ_DEVICE, IOMMUFD_OBJ_HWPT_PAGING, IOMMUFD_OBJ_HWPT_NESTED, + IOMMUFD_OBJ_HWPT_KVM, IOMMUFD_OBJ_IOAS, IOMMUFD_OBJ_ACCESS, #ifdef CONFIG_IOMMUFD_TEST @@ -266,17 +267,33 @@ struct iommufd_hwpt_nested { struct iommufd_hwpt_paging *parent; }; +struct iommufd_hwpt_kvm { + struct iommufd_hw_pagetable common; + void *context; +}; + static inline bool hwpt_is_paging(struct iommufd_hw_pagetable *hwpt) { return hwpt->obj.type == IOMMUFD_OBJ_HWPT_PAGING; } +static inline bool hwpt_is_kvm(struct iommufd_hw_pagetable *hwpt) +{ + return hwpt->obj.type == IOMMUFD_OBJ_HWPT_KVM; +} + static inline struct iommufd_hwpt_paging * to_hwpt_paging(struct iommufd_hw_pagetable *hwpt) { return container_of(hwpt, struct iommufd_hwpt_paging, common); } +static inline struct iommufd_hwpt_kvm * +to_hwpt_kvm(struct iommufd_hw_pagetable *hwpt) +{ + return container_of(hwpt, struct iommufd_hwpt_kvm, common); +} + static inline struct iommufd_hwpt_paging * iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id) { @@ -413,4 +430,22 @@ static inline bool iommufd_selftest_is_mock_dev(struct device *dev) return false; } #endif + +struct iommu_hwpt_kvm_info; +static inline struct iommufd_hwpt_kvm * +iommufd_hwpt_kvm_alloc(struct iommufd_ctx *ictx, + struct iommufd_device *idev, u32 flags, + const struct iommu_hwpt_kvm_info *kvm_data) +{ + return ERR_PTR(-EOPNOTSUPP); +} + +static inline void iommufd_hwpt_kvm_abort(struct iommufd_object *obj) +{ +} + +static inline void iommufd_hwpt_kvm_destroy(struct iommufd_object *obj) +{ +} + #endif diff --git a/drivers/iommu/iommufd/main.c b/drivers/iommu/iommufd/main.c index 6edef860f91cc..0798c1279133f 100644 --- a/drivers/iommu/iommufd/main.c +++ b/drivers/iommu/iommufd/main.c @@ -499,6 +499,10 @@ static const struct iommufd_object_ops iommufd_object_ops[] = { .destroy = iommufd_hwpt_nested_destroy, .abort = iommufd_hwpt_nested_abort, }, + [IOMMUFD_OBJ_HWPT_KVM] = { + .destroy = iommufd_hwpt_kvm_destroy, + .abort = iommufd_hwpt_kvm_abort, + }, #ifdef CONFIG_IOMMUFD_TEST [IOMMUFD_OBJ_SELFTEST] = { .destroy = iommufd_selftest_destroy, -- 2.17.1