Commit 89db3163 authored by Nicolin Chen's avatar Nicolin Chen Committed by Jason Gunthorpe

iommufd: Derive iommufd_hwpt_paging from iommufd_hw_pagetable

To prepare for IOMMUFD_OBJ_HWPT_NESTED, derive struct iommufd_hwpt_paging
from struct iommufd_hw_pagetable, by leaving the common members in struct
iommufd_hw_pagetable. Add a __iommufd_object_alloc and to_hwpt_paging()
helpers for the new structure.

Then, update "hwpt" to "hwpt_paging" throughout the files, accordingly.

Link: https://lore.kernel.org/r/20231026043938.63898-5-yi.l.liu@intel.comSuggested-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarNicolin Chen <nicolinc@nvidia.com>
Signed-off-by: default avatarYi Liu <yi.l.liu@intel.com>
Reviewed-by: default avatarKevin Tian <kevin.tian@intel.com>
Reviewed-by: default avatarJason Gunthorpe <jgg@nvidia.com>
Signed-off-by: default avatarJason Gunthorpe <jgg@nvidia.com>
parent 58d84f43
...@@ -293,7 +293,7 @@ u32 iommufd_device_to_id(struct iommufd_device *idev) ...@@ -293,7 +293,7 @@ u32 iommufd_device_to_id(struct iommufd_device *idev)
EXPORT_SYMBOL_NS_GPL(iommufd_device_to_id, IOMMUFD); EXPORT_SYMBOL_NS_GPL(iommufd_device_to_id, IOMMUFD);
static int iommufd_group_setup_msi(struct iommufd_group *igroup, static int iommufd_group_setup_msi(struct iommufd_group *igroup,
struct iommufd_hw_pagetable *hwpt) struct iommufd_hwpt_paging *hwpt_paging)
{ {
phys_addr_t sw_msi_start = igroup->sw_msi_start; phys_addr_t sw_msi_start = igroup->sw_msi_start;
int rc; int rc;
...@@ -311,8 +311,9 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup, ...@@ -311,8 +311,9 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup,
* matches what the IRQ layer actually expects in a newly created * matches what the IRQ layer actually expects in a newly created
* domain. * domain.
*/ */
if (sw_msi_start != PHYS_ADDR_MAX && !hwpt->msi_cookie) { if (sw_msi_start != PHYS_ADDR_MAX && !hwpt_paging->msi_cookie) {
rc = iommu_get_msi_cookie(hwpt->domain, sw_msi_start); rc = iommu_get_msi_cookie(hwpt_paging->common.domain,
sw_msi_start);
if (rc) if (rc)
return rc; return rc;
...@@ -320,27 +321,29 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup, ...@@ -320,27 +321,29 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup,
* iommu_get_msi_cookie() can only be called once per domain, * iommu_get_msi_cookie() can only be called once per domain,
* it returns -EBUSY on later calls. * it returns -EBUSY on later calls.
*/ */
hwpt->msi_cookie = true; hwpt_paging->msi_cookie = true;
} }
return 0; return 0;
} }
static int iommufd_hwpt_paging_attach(struct iommufd_hw_pagetable *hwpt, static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging,
struct iommufd_device *idev) struct iommufd_device *idev)
{ {
int rc; int rc;
lockdep_assert_held(&idev->igroup->lock); lockdep_assert_held(&idev->igroup->lock);
rc = iopt_table_enforce_dev_resv_regions(&hwpt->ioas->iopt, idev->dev, rc = iopt_table_enforce_dev_resv_regions(&hwpt_paging->ioas->iopt,
idev->dev,
&idev->igroup->sw_msi_start); &idev->igroup->sw_msi_start);
if (rc) if (rc)
return rc; return rc;
if (list_empty(&idev->igroup->device_list)) { if (list_empty(&idev->igroup->device_list)) {
rc = iommufd_group_setup_msi(idev->igroup, hwpt); rc = iommufd_group_setup_msi(idev->igroup, hwpt_paging);
if (rc) { if (rc) {
iopt_remove_reserved_iova(&hwpt->ioas->iopt, idev->dev); iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt,
idev->dev);
return rc; return rc;
} }
} }
...@@ -360,7 +363,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, ...@@ -360,7 +363,7 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
} }
if (hwpt_is_paging(hwpt)) { if (hwpt_is_paging(hwpt)) {
rc = iommufd_hwpt_paging_attach(hwpt, idev); rc = iommufd_hwpt_paging_attach(to_hwpt_paging(hwpt), idev);
if (rc) if (rc)
goto err_unlock; goto err_unlock;
} }
...@@ -384,7 +387,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, ...@@ -384,7 +387,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
return 0; return 0;
err_unresv: err_unresv:
if (hwpt_is_paging(hwpt)) if (hwpt_is_paging(hwpt))
iopt_remove_reserved_iova(&hwpt->ioas->iopt, idev->dev); iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt,
idev->dev);
err_unlock: err_unlock:
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
return rc; return rc;
...@@ -402,7 +406,8 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev) ...@@ -402,7 +406,8 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev)
idev->igroup->hwpt = NULL; idev->igroup->hwpt = NULL;
} }
if (hwpt_is_paging(hwpt)) if (hwpt_is_paging(hwpt))
iopt_remove_reserved_iova(&hwpt->ioas->iopt, idev->dev); iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt,
idev->dev);
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
/* Caller must destroy hwpt */ /* Caller must destroy hwpt */
...@@ -423,18 +428,19 @@ iommufd_device_do_attach(struct iommufd_device *idev, ...@@ -423,18 +428,19 @@ iommufd_device_do_attach(struct iommufd_device *idev,
static void static void
iommufd_group_remove_reserved_iova(struct iommufd_group *igroup, iommufd_group_remove_reserved_iova(struct iommufd_group *igroup,
struct iommufd_hw_pagetable *hwpt) struct iommufd_hwpt_paging *hwpt_paging)
{ {
struct iommufd_device *cur; struct iommufd_device *cur;
lockdep_assert_held(&igroup->lock); lockdep_assert_held(&igroup->lock);
list_for_each_entry(cur, &igroup->device_list, group_item) list_for_each_entry(cur, &igroup->device_list, group_item)
iopt_remove_reserved_iova(&hwpt->ioas->iopt, cur->dev); iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, cur->dev);
} }
static int iommufd_group_do_replace_paging(struct iommufd_group *igroup, static int
struct iommufd_hw_pagetable *hwpt) iommufd_group_do_replace_paging(struct iommufd_group *igroup,
struct iommufd_hwpt_paging *hwpt_paging)
{ {
struct iommufd_hw_pagetable *old_hwpt = igroup->hwpt; struct iommufd_hw_pagetable *old_hwpt = igroup->hwpt;
struct iommufd_device *cur; struct iommufd_device *cur;
...@@ -442,22 +448,23 @@ static int iommufd_group_do_replace_paging(struct iommufd_group *igroup, ...@@ -442,22 +448,23 @@ static int iommufd_group_do_replace_paging(struct iommufd_group *igroup,
lockdep_assert_held(&igroup->lock); lockdep_assert_held(&igroup->lock);
if (!hwpt_is_paging(old_hwpt) || hwpt->ioas != old_hwpt->ioas) { if (!hwpt_is_paging(old_hwpt) ||
hwpt_paging->ioas != to_hwpt_paging(old_hwpt)->ioas) {
list_for_each_entry(cur, &igroup->device_list, group_item) { list_for_each_entry(cur, &igroup->device_list, group_item) {
rc = iopt_table_enforce_dev_resv_regions( rc = iopt_table_enforce_dev_resv_regions(
&hwpt->ioas->iopt, cur->dev, NULL); &hwpt_paging->ioas->iopt, cur->dev, NULL);
if (rc) if (rc)
goto err_unresv; goto err_unresv;
} }
} }
rc = iommufd_group_setup_msi(igroup, hwpt); rc = iommufd_group_setup_msi(igroup, hwpt_paging);
if (rc) if (rc)
goto err_unresv; goto err_unresv;
return 0; return 0;
err_unresv: err_unresv:
iommufd_group_remove_reserved_iova(igroup, hwpt); iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
return rc; return rc;
} }
...@@ -482,8 +489,10 @@ iommufd_device_do_replace(struct iommufd_device *idev, ...@@ -482,8 +489,10 @@ iommufd_device_do_replace(struct iommufd_device *idev,
return NULL; return NULL;
} }
old_hwpt = igroup->hwpt;
if (hwpt_is_paging(hwpt)) { if (hwpt_is_paging(hwpt)) {
rc = iommufd_group_do_replace_paging(igroup, hwpt); rc = iommufd_group_do_replace_paging(igroup,
to_hwpt_paging(hwpt));
if (rc) if (rc)
goto err_unlock; goto err_unlock;
} }
...@@ -492,10 +501,11 @@ iommufd_device_do_replace(struct iommufd_device *idev, ...@@ -492,10 +501,11 @@ iommufd_device_do_replace(struct iommufd_device *idev,
if (rc) if (rc)
goto err_unresv; goto err_unresv;
old_hwpt = igroup->hwpt;
if (hwpt_is_paging(old_hwpt) && if (hwpt_is_paging(old_hwpt) &&
(!hwpt_is_paging(hwpt) || hwpt->ioas != old_hwpt->ioas)) (!hwpt_is_paging(hwpt) ||
iommufd_group_remove_reserved_iova(igroup, old_hwpt); to_hwpt_paging(hwpt)->ioas != to_hwpt_paging(old_hwpt)->ioas))
iommufd_group_remove_reserved_iova(igroup,
to_hwpt_paging(old_hwpt));
igroup->hwpt = hwpt; igroup->hwpt = hwpt;
...@@ -514,7 +524,8 @@ iommufd_device_do_replace(struct iommufd_device *idev, ...@@ -514,7 +524,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
return old_hwpt; return old_hwpt;
err_unresv: err_unresv:
if (hwpt_is_paging(hwpt)) if (hwpt_is_paging(hwpt))
iommufd_group_remove_reserved_iova(igroup, hwpt); iommufd_group_remove_reserved_iova(igroup,
to_hwpt_paging(old_hwpt));
err_unlock: err_unlock:
mutex_unlock(&idev->igroup->lock); mutex_unlock(&idev->igroup->lock);
return ERR_PTR(rc); return ERR_PTR(rc);
...@@ -542,6 +553,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, ...@@ -542,6 +553,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
*/ */
bool immediate_attach = do_attach == iommufd_device_do_attach; bool immediate_attach = do_attach == iommufd_device_do_attach;
struct iommufd_hw_pagetable *destroy_hwpt; struct iommufd_hw_pagetable *destroy_hwpt;
struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_hw_pagetable *hwpt; struct iommufd_hw_pagetable *hwpt;
/* /*
...@@ -550,10 +562,11 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, ...@@ -550,10 +562,11 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
* other. * other.
*/ */
mutex_lock(&ioas->mutex); mutex_lock(&ioas->mutex);
list_for_each_entry(hwpt, &ioas->hwpt_list, hwpt_item) { list_for_each_entry(hwpt_paging, &ioas->hwpt_list, hwpt_item) {
if (!hwpt->auto_domain) if (!hwpt_paging->auto_domain)
continue; continue;
hwpt = &hwpt_paging->common;
if (!iommufd_lock_obj(&hwpt->obj)) if (!iommufd_lock_obj(&hwpt->obj))
continue; continue;
destroy_hwpt = (*do_attach)(idev, hwpt); destroy_hwpt = (*do_attach)(idev, hwpt);
...@@ -574,12 +587,13 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, ...@@ -574,12 +587,13 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
goto out_unlock; goto out_unlock;
} }
hwpt = iommufd_hw_pagetable_alloc(idev->ictx, ioas, idev, hwpt_paging = iommufd_hwpt_paging_alloc(idev->ictx, ioas, idev, 0,
0, immediate_attach); immediate_attach);
if (IS_ERR(hwpt)) { if (IS_ERR(hwpt_paging)) {
destroy_hwpt = ERR_CAST(hwpt); destroy_hwpt = ERR_CAST(hwpt_paging);
goto out_unlock; goto out_unlock;
} }
hwpt = &hwpt_paging->common;
if (!immediate_attach) { if (!immediate_attach) {
destroy_hwpt = (*do_attach)(idev, hwpt); destroy_hwpt = (*do_attach)(idev, hwpt);
...@@ -589,7 +603,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev, ...@@ -589,7 +603,7 @@ iommufd_device_auto_get_domain(struct iommufd_device *idev,
destroy_hwpt = NULL; destroy_hwpt = NULL;
} }
hwpt->auto_domain = true; hwpt_paging->auto_domain = true;
*pt_id = hwpt->obj.id; *pt_id = hwpt->obj.id;
iommufd_object_finalize(idev->ictx, &hwpt->obj); iommufd_object_finalize(idev->ictx, &hwpt->obj);
......
...@@ -8,56 +8,61 @@ ...@@ -8,56 +8,61 @@
#include "../iommu-priv.h" #include "../iommu-priv.h"
#include "iommufd_private.h" #include "iommufd_private.h"
void iommufd_hw_pagetable_destroy(struct iommufd_object *obj) void iommufd_hwpt_paging_destroy(struct iommufd_object *obj)
{ {
struct iommufd_hw_pagetable *hwpt = struct iommufd_hwpt_paging *hwpt_paging =
container_of(obj, struct iommufd_hw_pagetable, obj); container_of(obj, struct iommufd_hwpt_paging, common.obj);
if (!list_empty(&hwpt->hwpt_item)) { if (!list_empty(&hwpt_paging->hwpt_item)) {
mutex_lock(&hwpt->ioas->mutex); mutex_lock(&hwpt_paging->ioas->mutex);
list_del(&hwpt->hwpt_item); list_del(&hwpt_paging->hwpt_item);
mutex_unlock(&hwpt->ioas->mutex); mutex_unlock(&hwpt_paging->ioas->mutex);
iopt_table_remove_domain(&hwpt->ioas->iopt, hwpt->domain); iopt_table_remove_domain(&hwpt_paging->ioas->iopt,
hwpt_paging->common.domain);
} }
if (hwpt->domain) if (hwpt_paging->common.domain)
iommu_domain_free(hwpt->domain); iommu_domain_free(hwpt_paging->common.domain);
refcount_dec(&hwpt->ioas->obj.users); refcount_dec(&hwpt_paging->ioas->obj.users);
} }
void iommufd_hw_pagetable_abort(struct iommufd_object *obj) void iommufd_hwpt_paging_abort(struct iommufd_object *obj)
{ {
struct iommufd_hw_pagetable *hwpt = struct iommufd_hwpt_paging *hwpt_paging =
container_of(obj, struct iommufd_hw_pagetable, obj); container_of(obj, struct iommufd_hwpt_paging, common.obj);
/* The ioas->mutex must be held until finalize is called. */ /* The ioas->mutex must be held until finalize is called. */
lockdep_assert_held(&hwpt->ioas->mutex); lockdep_assert_held(&hwpt_paging->ioas->mutex);
if (!list_empty(&hwpt->hwpt_item)) { if (!list_empty(&hwpt_paging->hwpt_item)) {
list_del_init(&hwpt->hwpt_item); list_del_init(&hwpt_paging->hwpt_item);
iopt_table_remove_domain(&hwpt->ioas->iopt, hwpt->domain); iopt_table_remove_domain(&hwpt_paging->ioas->iopt,
hwpt_paging->common.domain);
} }
iommufd_hw_pagetable_destroy(obj); iommufd_hwpt_paging_destroy(obj);
} }
static int iommufd_hw_pagetable_enforce_cc(struct iommufd_hw_pagetable *hwpt) static int
iommufd_hwpt_paging_enforce_cc(struct iommufd_hwpt_paging *hwpt_paging)
{ {
if (hwpt->enforce_cache_coherency) struct iommu_domain *paging_domain = hwpt_paging->common.domain;
if (hwpt_paging->enforce_cache_coherency)
return 0; return 0;
if (hwpt->domain->ops->enforce_cache_coherency) if (paging_domain->ops->enforce_cache_coherency)
hwpt->enforce_cache_coherency = hwpt_paging->enforce_cache_coherency =
hwpt->domain->ops->enforce_cache_coherency( paging_domain->ops->enforce_cache_coherency(
hwpt->domain); paging_domain);
if (!hwpt->enforce_cache_coherency) if (!hwpt_paging->enforce_cache_coherency)
return -EINVAL; return -EINVAL;
return 0; return 0;
} }
/** /**
* iommufd_hw_pagetable_alloc() - Get an iommu_domain for a device * iommufd_hwpt_paging_alloc() - Get a PAGING iommu_domain for a device
* @ictx: iommufd context * @ictx: iommufd context
* @ioas: IOAS to associate the domain with * @ioas: IOAS to associate the domain with
* @idev: Device to get an iommu_domain for * @idev: Device to get an iommu_domain for
...@@ -72,12 +77,13 @@ static int iommufd_hw_pagetable_enforce_cc(struct iommufd_hw_pagetable *hwpt) ...@@ -72,12 +77,13 @@ static int iommufd_hw_pagetable_enforce_cc(struct iommufd_hw_pagetable *hwpt)
* iommufd_object_abort_and_destroy() or iommufd_object_finalize() is called on * iommufd_object_abort_and_destroy() or iommufd_object_finalize() is called on
* the returned hwpt. * the returned hwpt.
*/ */
struct iommufd_hw_pagetable * struct iommufd_hwpt_paging *
iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
struct iommufd_device *idev, u32 flags, struct iommufd_device *idev, u32 flags,
bool immediate_attach) bool immediate_attach)
{ {
const struct iommu_ops *ops = dev_iommu_ops(idev->dev); const struct iommu_ops *ops = dev_iommu_ops(idev->dev);
struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_hw_pagetable *hwpt; struct iommufd_hw_pagetable *hwpt;
int rc; int rc;
...@@ -86,14 +92,16 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, ...@@ -86,14 +92,16 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
if (flags && !ops->domain_alloc_user) if (flags && !ops->domain_alloc_user)
return ERR_PTR(-EOPNOTSUPP); return ERR_PTR(-EOPNOTSUPP);
hwpt = iommufd_object_alloc(ictx, hwpt, IOMMUFD_OBJ_HWPT_PAGING); hwpt_paging = __iommufd_object_alloc(
if (IS_ERR(hwpt)) ictx, hwpt_paging, IOMMUFD_OBJ_HWPT_PAGING, common.obj);
return hwpt; if (IS_ERR(hwpt_paging))
return ERR_CAST(hwpt_paging);
hwpt = &hwpt_paging->common;
INIT_LIST_HEAD(&hwpt->hwpt_item); INIT_LIST_HEAD(&hwpt_paging->hwpt_item);
/* Pairs with iommufd_hw_pagetable_destroy() */ /* Pairs with iommufd_hw_pagetable_destroy() */
refcount_inc(&ioas->obj.users); refcount_inc(&ioas->obj.users);
hwpt->ioas = ioas; hwpt_paging->ioas = ioas;
if (ops->domain_alloc_user) { if (ops->domain_alloc_user) {
hwpt->domain = ops->domain_alloc_user(idev->dev, flags); hwpt->domain = ops->domain_alloc_user(idev->dev, flags);
...@@ -125,7 +133,7 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, ...@@ -125,7 +133,7 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
* allocate a separate HWPT (non-CC). * allocate a separate HWPT (non-CC).
*/ */
if (idev->enforce_cache_coherency) { if (idev->enforce_cache_coherency) {
rc = iommufd_hw_pagetable_enforce_cc(hwpt); rc = iommufd_hwpt_paging_enforce_cc(hwpt_paging);
if (WARN_ON(rc)) if (WARN_ON(rc))
goto out_abort; goto out_abort;
} }
...@@ -142,11 +150,11 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, ...@@ -142,11 +150,11 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
goto out_abort; goto out_abort;
} }
rc = iopt_table_add_domain(&hwpt->ioas->iopt, hwpt->domain); rc = iopt_table_add_domain(&ioas->iopt, hwpt->domain);
if (rc) if (rc)
goto out_detach; goto out_detach;
list_add_tail(&hwpt->hwpt_item, &hwpt->ioas->hwpt_list); list_add_tail(&hwpt_paging->hwpt_item, &ioas->hwpt_list);
return hwpt; return hwpt_paging;
out_detach: out_detach:
if (immediate_attach) if (immediate_attach)
...@@ -159,6 +167,7 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, ...@@ -159,6 +167,7 @@ iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
{ {
struct iommu_hwpt_alloc *cmd = ucmd->cmd; struct iommu_hwpt_alloc *cmd = ucmd->cmd;
struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_hw_pagetable *hwpt; struct iommufd_hw_pagetable *hwpt;
struct iommufd_device *idev; struct iommufd_device *idev;
struct iommufd_ioas *ioas; struct iommufd_ioas *ioas;
...@@ -180,12 +189,13 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) ...@@ -180,12 +189,13 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
} }
mutex_lock(&ioas->mutex); mutex_lock(&ioas->mutex);
hwpt = iommufd_hw_pagetable_alloc(ucmd->ictx, ioas, hwpt_paging = iommufd_hwpt_paging_alloc(ucmd->ictx, ioas, idev,
idev, cmd->flags, false); cmd->flags, false);
if (IS_ERR(hwpt)) { if (IS_ERR(hwpt_paging)) {
rc = PTR_ERR(hwpt); rc = PTR_ERR(hwpt_paging);
goto out_unlock; goto out_unlock;
} }
hwpt = &hwpt_paging->common;
cmd->out_hwpt_id = hwpt->obj.id; cmd->out_hwpt_id = hwpt->obj.id;
rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd)); rc = iommufd_ucmd_respond(ucmd, sizeof(*cmd));
...@@ -207,7 +217,7 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd) ...@@ -207,7 +217,7 @@ int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd)
int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd) int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd)
{ {
struct iommu_hwpt_set_dirty_tracking *cmd = ucmd->cmd; struct iommu_hwpt_set_dirty_tracking *cmd = ucmd->cmd;
struct iommufd_hw_pagetable *hwpt; struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_ioas *ioas; struct iommufd_ioas *ioas;
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
bool enable; bool enable;
...@@ -215,23 +225,24 @@ int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd) ...@@ -215,23 +225,24 @@ int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd)
if (cmd->flags & ~IOMMU_HWPT_DIRTY_TRACKING_ENABLE) if (cmd->flags & ~IOMMU_HWPT_DIRTY_TRACKING_ENABLE)
return rc; return rc;
hwpt = iommufd_get_hwpt(ucmd, cmd->hwpt_id); hwpt_paging = iommufd_get_hwpt_paging(ucmd, cmd->hwpt_id);
if (IS_ERR(hwpt)) if (IS_ERR(hwpt_paging))
return PTR_ERR(hwpt); return PTR_ERR(hwpt_paging);
ioas = hwpt->ioas; ioas = hwpt_paging->ioas;
enable = cmd->flags & IOMMU_HWPT_DIRTY_TRACKING_ENABLE; enable = cmd->flags & IOMMU_HWPT_DIRTY_TRACKING_ENABLE;
rc = iopt_set_dirty_tracking(&ioas->iopt, hwpt->domain, enable); rc = iopt_set_dirty_tracking(&ioas->iopt, hwpt_paging->common.domain,
enable);
iommufd_put_object(&hwpt->obj); iommufd_put_object(&hwpt_paging->common.obj);
return rc; return rc;
} }
int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd) int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd)
{ {
struct iommu_hwpt_get_dirty_bitmap *cmd = ucmd->cmd; struct iommu_hwpt_get_dirty_bitmap *cmd = ucmd->cmd;
struct iommufd_hw_pagetable *hwpt; struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_ioas *ioas; struct iommufd_ioas *ioas;
int rc = -EOPNOTSUPP; int rc = -EOPNOTSUPP;
...@@ -239,14 +250,14 @@ int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd) ...@@ -239,14 +250,14 @@ int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd)
cmd->__reserved) cmd->__reserved)
return -EOPNOTSUPP; return -EOPNOTSUPP;
hwpt = iommufd_get_hwpt(ucmd, cmd->hwpt_id); hwpt_paging = iommufd_get_hwpt_paging(ucmd, cmd->hwpt_id);
if (IS_ERR(hwpt)) if (IS_ERR(hwpt_paging))
return PTR_ERR(hwpt); return PTR_ERR(hwpt_paging);
ioas = hwpt->ioas; ioas = hwpt_paging->ioas;
rc = iopt_read_and_clear_dirty_data(&ioas->iopt, hwpt->domain, rc = iopt_read_and_clear_dirty_data(
cmd->flags, cmd); &ioas->iopt, hwpt_paging->common.domain, cmd->flags, cmd);
iommufd_put_object(&hwpt->obj); iommufd_put_object(&hwpt_paging->common.obj);
return rc; return rc;
} }
...@@ -181,7 +181,7 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx, ...@@ -181,7 +181,7 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
size_t size, size_t size,
enum iommufd_object_type type); enum iommufd_object_type type);
#define iommufd_object_alloc(ictx, ptr, type) \ #define __iommufd_object_alloc(ictx, ptr, type, obj) \
container_of(_iommufd_object_alloc( \ container_of(_iommufd_object_alloc( \
ictx, \ ictx, \
sizeof(*(ptr)) + BUILD_BUG_ON_ZERO( \ sizeof(*(ptr)) + BUILD_BUG_ON_ZERO( \
...@@ -190,6 +190,9 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx, ...@@ -190,6 +190,9 @@ struct iommufd_object *_iommufd_object_alloc(struct iommufd_ctx *ictx,
type), \ type), \
typeof(*(ptr)), obj) typeof(*(ptr)), obj)
#define iommufd_object_alloc(ictx, ptr, type) \
__iommufd_object_alloc(ictx, ptr, type, obj)
/* /*
* The IO Address Space (IOAS) pagetable is a virtual page table backed by the * 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 * io_pagetable object. It is a user controlled mapping of IOVA -> PFNs. The
...@@ -243,8 +246,12 @@ int iommufd_check_iova_range(struct io_pagetable *iopt, ...@@ -243,8 +246,12 @@ int iommufd_check_iova_range(struct io_pagetable *iopt,
*/ */
struct iommufd_hw_pagetable { struct iommufd_hw_pagetable {
struct iommufd_object obj; struct iommufd_object obj;
struct iommufd_ioas *ioas;
struct iommu_domain *domain; struct iommu_domain *domain;
};
struct iommufd_hwpt_paging {
struct iommufd_hw_pagetable common;
struct iommufd_ioas *ioas;
bool auto_domain : 1; bool auto_domain : 1;
bool enforce_cache_coherency : 1; bool enforce_cache_coherency : 1;
bool msi_cookie : 1; bool msi_cookie : 1;
...@@ -257,33 +264,41 @@ static inline bool hwpt_is_paging(struct iommufd_hw_pagetable *hwpt) ...@@ -257,33 +264,41 @@ static inline bool hwpt_is_paging(struct iommufd_hw_pagetable *hwpt)
return hwpt->obj.type == IOMMUFD_OBJ_HWPT_PAGING; return hwpt->obj.type == IOMMUFD_OBJ_HWPT_PAGING;
} }
static inline struct iommufd_hw_pagetable * static inline struct iommufd_hwpt_paging *
iommufd_get_hwpt(struct iommufd_ucmd *ucmd, u32 id) to_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
{
return container_of(hwpt, struct iommufd_hwpt_paging, common);
}
static inline struct iommufd_hwpt_paging *
iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id)
{ {
return container_of(iommufd_get_object(ucmd->ictx, id, return container_of(iommufd_get_object(ucmd->ictx, id,
IOMMUFD_OBJ_HWPT_PAGING), IOMMUFD_OBJ_HWPT_PAGING),
struct iommufd_hw_pagetable, obj); struct iommufd_hwpt_paging, common.obj);
} }
int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd); int iommufd_hwpt_set_dirty_tracking(struct iommufd_ucmd *ucmd);
int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd); int iommufd_hwpt_get_dirty_bitmap(struct iommufd_ucmd *ucmd);
struct iommufd_hw_pagetable * struct iommufd_hwpt_paging *
iommufd_hw_pagetable_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas, iommufd_hwpt_paging_alloc(struct iommufd_ctx *ictx, struct iommufd_ioas *ioas,
struct iommufd_device *idev, u32 flags, struct iommufd_device *idev, u32 flags,
bool immediate_attach); bool immediate_attach);
int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt, int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
struct iommufd_device *idev); struct iommufd_device *idev);
struct iommufd_hw_pagetable * struct iommufd_hw_pagetable *
iommufd_hw_pagetable_detach(struct iommufd_device *idev); iommufd_hw_pagetable_detach(struct iommufd_device *idev);
void iommufd_hw_pagetable_destroy(struct iommufd_object *obj); void iommufd_hwpt_paging_destroy(struct iommufd_object *obj);
void iommufd_hw_pagetable_abort(struct iommufd_object *obj); void iommufd_hwpt_paging_abort(struct iommufd_object *obj);
int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd); int iommufd_hwpt_alloc(struct iommufd_ucmd *ucmd);
static inline void iommufd_hw_pagetable_put(struct iommufd_ctx *ictx, static inline void iommufd_hw_pagetable_put(struct iommufd_ctx *ictx,
struct iommufd_hw_pagetable *hwpt) struct iommufd_hw_pagetable *hwpt)
{ {
lockdep_assert_not_held(&hwpt->ioas->mutex); struct iommufd_hwpt_paging *hwpt_paging = to_hwpt_paging(hwpt);
if (hwpt->auto_domain)
lockdep_assert_not_held(&hwpt_paging->ioas->mutex);
if (hwpt_paging->auto_domain)
iommufd_object_deref_user(ictx, &hwpt->obj); iommufd_object_deref_user(ictx, &hwpt->obj);
else else
refcount_dec(&hwpt->obj.users); refcount_dec(&hwpt->obj.users);
......
...@@ -489,8 +489,8 @@ static const struct iommufd_object_ops iommufd_object_ops[] = { ...@@ -489,8 +489,8 @@ static const struct iommufd_object_ops iommufd_object_ops[] = {
.destroy = iommufd_ioas_destroy, .destroy = iommufd_ioas_destroy,
}, },
[IOMMUFD_OBJ_HWPT_PAGING] = { [IOMMUFD_OBJ_HWPT_PAGING] = {
.destroy = iommufd_hw_pagetable_destroy, .destroy = iommufd_hwpt_paging_destroy,
.abort = iommufd_hw_pagetable_abort, .abort = iommufd_hwpt_paging_abort,
}, },
#ifdef CONFIG_IOMMUFD_TEST #ifdef CONFIG_IOMMUFD_TEST
[IOMMUFD_OBJ_SELFTEST] = { [IOMMUFD_OBJ_SELFTEST] = {
......
...@@ -255,7 +255,7 @@ static int iommufd_vfio_unmap_dma(struct iommufd_ctx *ictx, unsigned int cmd, ...@@ -255,7 +255,7 @@ static int iommufd_vfio_unmap_dma(struct iommufd_ctx *ictx, unsigned int cmd,
static int iommufd_vfio_cc_iommu(struct iommufd_ctx *ictx) static int iommufd_vfio_cc_iommu(struct iommufd_ctx *ictx)
{ {
struct iommufd_hw_pagetable *hwpt; struct iommufd_hwpt_paging *hwpt_paging;
struct iommufd_ioas *ioas; struct iommufd_ioas *ioas;
int rc = 1; int rc = 1;
...@@ -264,8 +264,8 @@ static int iommufd_vfio_cc_iommu(struct iommufd_ctx *ictx) ...@@ -264,8 +264,8 @@ static int iommufd_vfio_cc_iommu(struct iommufd_ctx *ictx)
return PTR_ERR(ioas); return PTR_ERR(ioas);
mutex_lock(&ioas->mutex); mutex_lock(&ioas->mutex);
list_for_each_entry(hwpt, &ioas->hwpt_list, hwpt_item) { list_for_each_entry(hwpt_paging, &ioas->hwpt_list, hwpt_item) {
if (!hwpt->enforce_cache_coherency) { if (!hwpt_paging->enforce_cache_coherency) {
rc = 0; rc = 0;
break; break;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment