Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

iommufd/device: Wrap igroup->hwpt and igroup->device_list into attach struct

The igroup->hwpt and igroup->device_list are used to track the hwpt attach
of a group in the RID path. While the coming PASID path also needs such
tracking. To be prepared, wrap igroup->hwpt and igroup->device_list into
attach struct which is allocated per attaching the first device of the
group and freed per detaching the last device of the group.

Link: https://patch.msgid.link/r/20250321171940.7213-8-yi.l.liu@intel.com
Reviewed-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Lu Baolu <baolu.lu@linux.intel.com>
Reviewed-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Yi Liu <yi.l.liu@intel.com>
Tested-by: Nicolin Chen <nicolinc@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>

authored by

Yi Liu and committed by
Jason Gunthorpe
75f990ae ba1de6cd

+58 -23
+55 -21
drivers/iommu/iommufd/device.c
··· 17 17 "Allow IOMMUFD to bind to devices even if the platform cannot isolate " 18 18 "the MSI interrupt window. Enabling this is a security weakness."); 19 19 20 + struct iommufd_attach { 21 + struct iommufd_hw_pagetable *hwpt; 22 + struct list_head device_list; 23 + }; 24 + 20 25 static void iommufd_group_release(struct kref *kref) 21 26 { 22 27 struct iommufd_group *igroup = 23 28 container_of(kref, struct iommufd_group, ref); 24 29 25 - WARN_ON(igroup->hwpt || !list_empty(&igroup->device_list)); 30 + WARN_ON(igroup->attach); 26 31 27 32 xa_cmpxchg(&igroup->ictx->groups, iommu_group_id(igroup->group), igroup, 28 33 NULL, GFP_KERNEL); ··· 94 89 95 90 kref_init(&new_igroup->ref); 96 91 mutex_init(&new_igroup->lock); 97 - INIT_LIST_HEAD(&new_igroup->device_list); 98 92 new_igroup->sw_msi_start = PHYS_ADDR_MAX; 99 93 /* group reference moves into new_igroup */ 100 94 new_igroup->group = group; ··· 337 333 iommufd_group_first_attach(struct iommufd_group *igroup, ioasid_t pasid) 338 334 { 339 335 lockdep_assert_held(&igroup->lock); 340 - return !igroup->hwpt; 336 + return !igroup->attach; 341 337 } 342 338 343 339 static int ··· 373 369 { 374 370 struct iommufd_device *cur; 375 371 376 - list_for_each_entry(cur, &idev->igroup->device_list, group_item) 372 + list_for_each_entry(cur, &idev->igroup->attach->device_list, group_item) 377 373 if (cur == idev) 378 374 return true; 379 375 return false; ··· 497 493 struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt); 498 494 bool attach_resv = hwpt_paging && pasid == IOMMU_NO_PASID; 499 495 struct iommufd_group *igroup = idev->igroup; 496 + struct iommufd_hw_pagetable *old_hwpt; 497 + struct iommufd_attach *attach; 500 498 int rc; 501 499 502 500 mutex_lock(&igroup->lock); 503 501 504 - if (igroup->hwpt && igroup->hwpt != hwpt) { 502 + attach = igroup->attach; 503 + if (!attach) { 504 + attach = kzalloc(sizeof(*attach), GFP_KERNEL); 505 + if (!attach) { 506 + rc = -ENOMEM; 507 + goto err_unlock; 508 + } 509 + INIT_LIST_HEAD(&attach->device_list); 510 + } 511 + 512 + old_hwpt = attach->hwpt; 513 + 514 + if (old_hwpt && old_hwpt != hwpt) { 505 515 rc = -EINVAL; 506 - goto err_unlock; 516 + goto err_free_attach; 507 517 } 508 518 509 519 if (attach_resv) { 510 520 rc = iommufd_device_attach_reserved_iova(idev, hwpt_paging); 511 521 if (rc) 512 - goto err_unlock; 522 + goto err_free_attach; 513 523 } 514 524 515 525 /* ··· 537 519 rc = iommufd_hwpt_attach_device(hwpt, idev, pasid); 538 520 if (rc) 539 521 goto err_unresv; 540 - igroup->hwpt = hwpt; 522 + attach->hwpt = hwpt; 523 + igroup->attach = attach; 541 524 } 542 525 refcount_inc(&hwpt->obj.users); 543 - list_add_tail(&idev->group_item, &igroup->device_list); 526 + list_add_tail(&idev->group_item, &attach->device_list); 544 527 mutex_unlock(&igroup->lock); 545 528 return 0; 546 529 err_unresv: 547 530 if (attach_resv) 548 531 iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev); 532 + err_free_attach: 533 + if (iommufd_group_first_attach(igroup, pasid)) 534 + kfree(attach); 549 535 err_unlock: 550 536 mutex_unlock(&igroup->lock); 551 537 return rc; ··· 559 537 iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid) 560 538 { 561 539 struct iommufd_group *igroup = idev->igroup; 562 - struct iommufd_hw_pagetable *hwpt = igroup->hwpt; 563 - struct iommufd_hwpt_paging *hwpt_paging = find_hwpt_paging(hwpt); 540 + struct iommufd_hwpt_paging *hwpt_paging; 541 + struct iommufd_hw_pagetable *hwpt; 542 + struct iommufd_attach *attach; 564 543 565 544 mutex_lock(&igroup->lock); 545 + attach = igroup->attach; 546 + hwpt = attach->hwpt; 547 + hwpt_paging = find_hwpt_paging(hwpt); 548 + 566 549 list_del(&idev->group_item); 567 - if (list_empty(&igroup->device_list)) { 550 + if (list_empty(&attach->device_list)) { 568 551 iommufd_hwpt_detach_device(hwpt, idev, pasid); 569 - igroup->hwpt = NULL; 552 + igroup->attach = NULL; 553 + kfree(attach); 570 554 } 571 555 if (hwpt_paging && pasid == IOMMU_NO_PASID) 572 556 iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, idev->dev); ··· 602 574 603 575 lockdep_assert_held(&igroup->lock); 604 576 605 - list_for_each_entry(cur, &igroup->device_list, group_item) 577 + list_for_each_entry(cur, &igroup->attach->device_list, group_item) 606 578 iopt_remove_reserved_iova(&hwpt_paging->ioas->iopt, cur->dev); 607 579 } 608 580 ··· 616 588 617 589 lockdep_assert_held(&igroup->lock); 618 590 619 - old_hwpt_paging = find_hwpt_paging(igroup->hwpt); 591 + old_hwpt_paging = find_hwpt_paging(igroup->attach->hwpt); 620 592 if (!old_hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas) { 621 - list_for_each_entry(cur, &igroup->device_list, group_item) { 593 + list_for_each_entry(cur, 594 + &igroup->attach->device_list, group_item) { 622 595 rc = iopt_table_enforce_dev_resv_regions( 623 596 &hwpt_paging->ioas->iopt, cur->dev, NULL); 624 597 if (rc) ··· 646 617 struct iommufd_hwpt_paging *old_hwpt_paging; 647 618 struct iommufd_group *igroup = idev->igroup; 648 619 struct iommufd_hw_pagetable *old_hwpt; 620 + struct iommufd_attach *attach; 649 621 unsigned int num_devices; 650 622 int rc; 651 623 652 624 mutex_lock(&igroup->lock); 653 625 654 - if (igroup->hwpt == NULL) { 626 + attach = igroup->attach; 627 + if (!attach) { 655 628 rc = -EINVAL; 656 629 goto err_unlock; 657 630 } 631 + 632 + old_hwpt = attach->hwpt; 633 + 634 + WARN_ON(!old_hwpt || list_empty(&attach->device_list)); 658 635 659 636 if (!iommufd_device_is_attached(idev)) { 660 637 rc = -EINVAL; 661 638 goto err_unlock; 662 639 } 663 640 664 - if (hwpt == igroup->hwpt) { 641 + if (hwpt == old_hwpt) { 665 642 mutex_unlock(&igroup->lock); 666 643 return NULL; 667 644 } 668 645 669 - old_hwpt = igroup->hwpt; 670 646 if (attach_resv) { 671 647 rc = iommufd_group_do_replace_reserved_iova(igroup, hwpt_paging); 672 648 if (rc) ··· 687 653 (!hwpt_paging || hwpt_paging->ioas != old_hwpt_paging->ioas)) 688 654 iommufd_group_remove_reserved_iova(igroup, old_hwpt_paging); 689 655 690 - igroup->hwpt = hwpt; 656 + attach->hwpt = hwpt; 691 657 692 - num_devices = list_count_nodes(&igroup->device_list); 658 + num_devices = list_count_nodes(&attach->device_list); 693 659 /* 694 660 * Move the refcounts held by the device_list to the new hwpt. Retain a 695 661 * refcount for this thread as the caller will free it.
+3 -2
drivers/iommu/iommufd/iommufd_private.h
··· 399 399 refcount_dec(&hwpt->obj.users); 400 400 } 401 401 402 + struct iommufd_attach; 403 + 402 404 struct iommufd_group { 403 405 struct kref ref; 404 406 struct mutex lock; 405 407 struct iommufd_ctx *ictx; 406 408 struct iommu_group *group; 407 - struct iommufd_hw_pagetable *hwpt; 408 - struct list_head device_list; 409 + struct iommufd_attach *attach; 409 410 struct iommufd_sw_msi_maps required_sw_msi; 410 411 phys_addr_t sw_msi_start; 411 412 };