Skip to content

Commit b2f4481

Browse files
nicolincjgunthorpe
authored andcommitted
iommufd/device: Enforce reserved IOVA also when attached to hwpt_nested
Currently, device reserved regions are only enforced when the device is attached to an hwpt_paging. In other words, if the device gets attached to an hwpt_nested directly, the parent hwpt_paging of the hwpt_nested's would not enforce those reserved IOVAs. This works for most of reserved region types, but not for IOMMU_RESV_SW_MSI, which is a unique software defined window, required by a nesting case too to setup an MSI doorbell on the parent stage-2 hwpt/domain. Kevin pointed out in 1 that: 1) there is no usage using up closely the entire IOVA space yet, 2) guest may change the viommu mode to switch between nested and paging then VMM has to take all devices' reserved regions into consideration anyway, when composing the GPA space. So it would be actually convenient for us to also enforce reserved IOVA onto the parent hwpt_paging, when attaching a device to an hwpt_nested. Repurpose the existing attach/replace_paging helpers to attach device's reserved IOVAs exclusively. Add a new find_hwpt_paging helper, which is only used by these reserved IOVA functions, to allow an IOMMUFD_OBJ_HWPT_NESTED hwpt to redirect to its parent hwpt_paging. Return a NULL in these two helpers for any new HWPT type in the future. Link: https://patch.msgid.link/r/[email protected] Link: https://lore.kernel.org/all/BN9PR11MB5276497781C96415272E6FED8CB12@BN9PR11MB5276.namprd11.prod.outlook.com/ #1 Suggested-by: Kevin Tian <[email protected]> Signed-off-by: Nicolin Chen <[email protected]> Reviewed-by: Kevin Tian <[email protected]> Signed-off-by: Jason Gunthorpe <[email protected]>
1 parent 5be63fc commit b2f4481

File tree

2 files changed

+45
-26
lines changed

2 files changed

+45
-26
lines changed

drivers/iommu/iommufd/device.c

Lines changed: 26 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -327,8 +327,9 @@ static int iommufd_group_setup_msi(struct iommufd_group *igroup,
327327
return 0;
328328
}
329329

330-
static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging,
331-
struct iommufd_device *idev)
330+
static int
331+
iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
332+
struct iommufd_hwpt_paging *hwpt_paging)
332333
{
333334
int rc;
334335

@@ -354,6 +355,7 @@ static int iommufd_hwpt_paging_attach(struct iommufd_hwpt_paging *hwpt_paging,
354355
int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
355356
struct iommufd_device *idev)
356357
{
358+
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
357359
int rc;
358360

359361
mutex_lock(&idev->igroup->lock);
@@ -363,8 +365,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
363365
goto err_unlock;
364366
}
365367

366-
if (hwpt_is_paging(hwpt)) {
367-
rc = iommufd_hwpt_paging_attach(to_hwpt_paging(hwpt), idev);
368+
if (hwpt_paging) {
369+
rc = iommufd_device_attach_reserved_iova(idev, hwpt_paging);
368370
if (rc)
369371
goto err_unlock;
370372
}
@@ -387,9 +389,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
387389
mutex_unlock(&idev->igroup->lock);
388390
return 0;
389391
err_unresv:
390-
if (hwpt_is_paging(hwpt))
391-
iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt,
392-
idev->dev);
392+
if (hwpt_paging)
393+
iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
393394
err_unlock:
394395
mutex_unlock(&idev->igroup->lock);
395396
return rc;
@@ -399,16 +400,16 @@ struct iommufd_hw_pagetable *
399400
iommufd_hw_pagetable_detach(struct iommufd_device *idev)
400401
{
401402
struct iommufd_hw_pagetable *hwpt = idev->igroup->hwpt;
403+
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
402404

403405
mutex_lock(&idev->igroup->lock);
404406
list_del(&idev->group_item);
405407
if (list_empty(&idev->igroup->device_list)) {
406408
iommufd_hwpt_detach_device(hwpt, idev);
407409
idev->igroup->hwpt = NULL;
408410
}
409-
if (hwpt_is_paging(hwpt))
410-
iopt_remove_reserved_iova(&to_hwpt_paging(hwpt)->ioas->iopt,
411-
idev->dev);
411+
if (hwpt_paging)
412+
iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev);
412413
mutex_unlock(&idev->igroup->lock);
413414

414415
/* Caller must destroy hwpt */
@@ -440,17 +441,17 @@ iommufd_group_remove_reserved_iova(struct iommufd_group *igroup,
440441
}
441442

442443
static int
443-
iommufd_group_do_replace_paging(struct iommufd_group *igroup,
444-
struct iommufd_hwpt_paging *hwpt_paging)
444+
iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
445+
struct iommufd_hwpt_paging *hwpt_paging)
445446
{
446-
struct iommufd_hw_pagetable *old_hwpt = igroup->hwpt;
447+
struct iommufd_hwpt_paging *old_hwpt_paging;
447448
struct iommufd_device *cur;
448449
int rc;
449450

450451
lockdep_assert_held(&igroup->lock);
451452

452-
if (!hwpt_is_paging(old_hwpt) ||
453-
hwpt_paging->ioas != to_hwpt_paging(old_hwpt)->ioas) {
453+
old_hwpt_paging = find_hwpt_paging(igroup->hwpt);
454+
if (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas) {
454455
list_for_each_entry(cur, &igroup->device_list, group_item) {
455456
rc = iopt_table_enforce_dev_resv_regions(
456457
&hwpt_paging->ioas->iopt, cur->dev, NULL);
@@ -473,6 +474,8 @@ static struct iommufd_hw_pagetable *
473474
iommufd_device_do_replace(struct iommufd_device *idev,
474475
struct iommufd_hw_pagetable *hwpt)
475476
{
477+
struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt);
478+
struct iommufd_hwpt_paging *old_hwpt_paging;
476479
struct iommufd_group *igroup = idev->igroup;
477480
struct iommufd_hw_pagetable *old_hwpt;
478481
unsigned int num_devices;
@@ -491,9 +494,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
491494
}
492495

493496
old_hwpt = igroup->hwpt;
494-
if (hwpt_is_paging(hwpt)) {
495-
rc = iommufd_group_do_replace_paging(igroup,
496-
to_hwpt_paging(hwpt));
497+
if (hwpt_paging) {
498+
rc = iommufd_group_do_replace_reserved_iova(igroup, hwpt_paging);
497499
if (rc)
498500
goto err_unlock;
499501
}
@@ -502,11 +504,10 @@ iommufd_device_do_replace(struct iommufd_device *idev,
502504
if (rc)
503505
goto err_unresv;
504506

505-
if (hwpt_is_paging(old_hwpt) &&
506-
(!hwpt_is_paging(hwpt) ||
507-
to_hwpt_paging(hwpt)->ioas != to_hwpt_paging(old_hwpt)->ioas))
508-
iommufd_group_remove_reserved_iova(igroup,
509-
to_hwpt_paging(old_hwpt));
507+
old_hwpt_paging = find_hwpt_paging(old_hwpt);
508+
if (old_hwpt_paging &&
509+
(!hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas))
510+
iommufd_group_remove_reserved_iova(igroup, old_hwpt_paging);
510511

511512
igroup->hwpt = hwpt;
512513

@@ -524,9 +525,8 @@ iommufd_device_do_replace(struct iommufd_device *idev,
524525
/* Caller must destroy old_hwpt */
525526
return old_hwpt;
526527
err_unresv:
527-
if (hwpt_is_paging(hwpt))
528-
iommufd_group_remove_reserved_iova(igroup,
529-
to_hwpt_paging(hwpt));
528+
if (hwpt_paging)
529+
iommufd_group_remove_reserved_iova(igroup, hwpt_paging);
530530
err_unlock:
531531
mutex_unlock(&idev->igroup->lock);
532532
return ERR_PTR(rc);

drivers/iommu/iommufd/iommufd_private.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -324,6 +324,25 @@ to_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
324324
return container_of(hwpt, struct iommufd_hwpt_paging, common);
325325
}
326326

327+
static inline struct iommufd_hwpt_nested *
328+
to_hwpt_nested(struct iommufd_hw_pagetable *hwpt)
329+
{
330+
return container_of(hwpt, struct iommufd_hwpt_nested, common);
331+
}
332+
333+
static inline struct iommufd_hwpt_paging *
334+
find_hwpt_paging(struct iommufd_hw_pagetable *hwpt)
335+
{
336+
switch (hwpt->obj.type) {
337+
case IOMMUFD_OBJ_HWPT_PAGING:
338+
return to_hwpt_paging(hwpt);
339+
case IOMMUFD_OBJ_HWPT_NESTED:
340+
return to_hwpt_nested(hwpt)->parent;
341+
default:
342+
return NULL;
343+
}
344+
}
345+
327346
static inline struct iommufd_hwpt_paging *
328347
iommufd_get_hwpt_paging(struct iommufd_ucmd *ucmd, u32 id)
329348
{

0 commit comments

Comments
 (0)