@@ -27,7 +27,7 @@ static void iommufd_group_release(struct kref *kref)
27
27
struct iommufd_group * igroup =
28
28
container_of (kref , struct iommufd_group , ref );
29
29
30
- WARN_ON (igroup -> attach );
30
+ WARN_ON (! xa_empty ( & igroup -> pasid_attach ) );
31
31
32
32
xa_cmpxchg (& igroup -> ictx -> groups , iommu_group_id (igroup -> group ), igroup ,
33
33
NULL , GFP_KERNEL );
@@ -94,6 +94,7 @@ static struct iommufd_group *iommufd_get_group(struct iommufd_ctx *ictx,
94
94
95
95
kref_init (& new_igroup -> ref );
96
96
mutex_init (& new_igroup -> lock );
97
+ xa_init (& new_igroup -> pasid_attach );
97
98
new_igroup -> sw_msi_start = PHYS_ADDR_MAX ;
98
99
/* group reference moves into new_igroup */
99
100
new_igroup -> group = group ;
@@ -297,16 +298,19 @@ u32 iommufd_device_to_id(struct iommufd_device *idev)
297
298
}
298
299
EXPORT_SYMBOL_NS_GPL (iommufd_device_to_id , "IOMMUFD" );
299
300
300
- static unsigned int iommufd_group_device_num (struct iommufd_group * igroup )
301
+ static unsigned int iommufd_group_device_num (struct iommufd_group * igroup ,
302
+ ioasid_t pasid )
301
303
{
304
+ struct iommufd_attach * attach ;
302
305
struct iommufd_device * idev ;
303
306
unsigned int count = 0 ;
304
307
unsigned long index ;
305
308
306
309
lockdep_assert_held (& igroup -> lock );
307
310
308
- if (igroup -> attach )
309
- xa_for_each (& igroup -> attach -> device_array , index , idev )
311
+ attach = xa_load (& igroup -> pasid_attach , pasid );
312
+ if (attach )
313
+ xa_for_each (& attach -> device_array , index , idev )
310
314
count ++ ;
311
315
return count ;
312
316
}
@@ -351,7 +355,7 @@ static bool
351
355
iommufd_group_first_attach (struct iommufd_group * igroup , ioasid_t pasid )
352
356
{
353
357
lockdep_assert_held (& igroup -> lock );
354
- return !igroup -> attach ;
358
+ return !xa_load ( & igroup -> pasid_attach , pasid ) ;
355
359
}
356
360
357
361
static int
@@ -382,10 +386,13 @@ iommufd_device_attach_reserved_iova(struct iommufd_device *idev,
382
386
383
387
/* The device attach/detach/replace helpers for attach_handle */
384
388
385
- /* Check if idev is attached to igroup->hwpt */
386
- static bool iommufd_device_is_attached ( struct iommufd_device * idev )
389
+ static bool iommufd_device_is_attached ( struct iommufd_device * idev ,
390
+ ioasid_t pasid )
387
391
{
388
- return xa_load (& idev -> igroup -> attach -> device_array , idev -> obj .id );
392
+ struct iommufd_attach * attach ;
393
+
394
+ attach = xa_load (& idev -> igroup -> pasid_attach , pasid );
395
+ return xa_load (& attach -> device_array , idev -> obj .id );
389
396
}
390
397
391
398
static int iommufd_hwpt_attach_device (struct iommufd_hw_pagetable * hwpt ,
@@ -512,12 +519,18 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
512
519
513
520
mutex_lock (& igroup -> lock );
514
521
515
- attach = igroup -> attach ;
522
+ attach = xa_cmpxchg (& igroup -> pasid_attach , pasid , NULL ,
523
+ XA_ZERO_ENTRY , GFP_KERNEL );
524
+ if (xa_is_err (attach )) {
525
+ rc = xa_err (attach );
526
+ goto err_unlock ;
527
+ }
528
+
516
529
if (!attach ) {
517
530
attach = kzalloc (sizeof (* attach ), GFP_KERNEL );
518
531
if (!attach ) {
519
532
rc = - ENOMEM ;
520
- goto err_unlock ;
533
+ goto err_release_pasid ;
521
534
}
522
535
xa_init (& attach -> device_array );
523
536
}
@@ -554,7 +567,8 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
554
567
if (rc )
555
568
goto err_unresv ;
556
569
attach -> hwpt = hwpt ;
557
- igroup -> attach = attach ;
570
+ WARN_ON (xa_is_err (xa_store (& igroup -> pasid_attach , pasid , attach ,
571
+ GFP_KERNEL )));
558
572
}
559
573
refcount_inc (& hwpt -> obj .users );
560
574
WARN_ON (xa_is_err (xa_store (& attach -> device_array , idev -> obj .id ,
@@ -569,6 +583,9 @@ int iommufd_hw_pagetable_attach(struct iommufd_hw_pagetable *hwpt,
569
583
err_free_attach :
570
584
if (iommufd_group_first_attach (igroup , pasid ))
571
585
kfree (attach );
586
+ err_release_pasid :
587
+ if (iommufd_group_first_attach (igroup , pasid ))
588
+ xa_release (& igroup -> pasid_attach , pasid );
572
589
err_unlock :
573
590
mutex_unlock (& igroup -> lock );
574
591
return rc ;
@@ -583,14 +600,14 @@ iommufd_hw_pagetable_detach(struct iommufd_device *idev, ioasid_t pasid)
583
600
struct iommufd_attach * attach ;
584
601
585
602
mutex_lock (& igroup -> lock );
586
- attach = igroup -> attach ;
603
+ attach = xa_load ( & igroup -> pasid_attach , pasid ) ;
587
604
hwpt = attach -> hwpt ;
588
605
hwpt_paging = find_hwpt_paging (hwpt );
589
606
590
607
xa_erase (& attach -> device_array , idev -> obj .id );
591
608
if (xa_empty (& attach -> device_array )) {
592
609
iommufd_hwpt_detach_device (hwpt , idev , pasid );
593
- igroup -> attach = NULL ;
610
+ xa_erase ( & igroup -> pasid_attach , pasid ) ;
594
611
kfree (attach );
595
612
}
596
613
if (hwpt_paging && pasid == IOMMU_NO_PASID )
@@ -617,12 +634,14 @@ static void
617
634
iommufd_group_remove_reserved_iova (struct iommufd_group * igroup ,
618
635
struct iommufd_hwpt_paging * hwpt_paging )
619
636
{
637
+ struct iommufd_attach * attach ;
620
638
struct iommufd_device * cur ;
621
639
unsigned long index ;
622
640
623
641
lockdep_assert_held (& igroup -> lock );
624
642
625
- xa_for_each (& igroup -> attach -> device_array , index , cur )
643
+ attach = xa_load (& igroup -> pasid_attach , IOMMU_NO_PASID );
644
+ xa_for_each (& attach -> device_array , index , cur )
626
645
iopt_remove_reserved_iova (& hwpt_paging -> ioas -> iopt , cur -> dev );
627
646
}
628
647
@@ -631,15 +650,17 @@ iommufd_group_do_replace_reserved_iova(struct iommufd_group *igroup,
631
650
struct iommufd_hwpt_paging * hwpt_paging )
632
651
{
633
652
struct iommufd_hwpt_paging * old_hwpt_paging ;
653
+ struct iommufd_attach * attach ;
634
654
struct iommufd_device * cur ;
635
655
unsigned long index ;
636
656
int rc ;
637
657
638
658
lockdep_assert_held (& igroup -> lock );
639
659
640
- old_hwpt_paging = find_hwpt_paging (igroup -> attach -> hwpt );
660
+ attach = xa_load (& igroup -> pasid_attach , IOMMU_NO_PASID );
661
+ old_hwpt_paging = find_hwpt_paging (attach -> hwpt );
641
662
if (!old_hwpt_paging || hwpt_paging -> ioas != old_hwpt_paging -> ioas ) {
642
- xa_for_each (& igroup -> attach -> device_array , index , cur ) {
663
+ xa_for_each (& attach -> device_array , index , cur ) {
643
664
rc = iopt_table_enforce_dev_resv_regions (
644
665
& hwpt_paging -> ioas -> iopt , cur -> dev , NULL );
645
666
if (rc )
@@ -672,7 +693,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
672
693
673
694
mutex_lock (& igroup -> lock );
674
695
675
- attach = igroup -> attach ;
696
+ attach = xa_load ( & igroup -> pasid_attach , pasid ) ;
676
697
if (!attach ) {
677
698
rc = - EINVAL ;
678
699
goto err_unlock ;
@@ -682,7 +703,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
682
703
683
704
WARN_ON (!old_hwpt || xa_empty (& attach -> device_array ));
684
705
685
- if (!iommufd_device_is_attached (idev )) {
706
+ if (!iommufd_device_is_attached (idev , pasid )) {
686
707
rc = - EINVAL ;
687
708
goto err_unlock ;
688
709
}
@@ -709,7 +730,7 @@ iommufd_device_do_replace(struct iommufd_device *idev, ioasid_t pasid,
709
730
710
731
attach -> hwpt = hwpt ;
711
732
712
- num_devices = iommufd_group_device_num (igroup );
733
+ num_devices = iommufd_group_device_num (igroup , pasid );
713
734
/*
714
735
* Move the refcounts held by the device_array to the new hwpt. Retain a
715
736
* refcount for this thread as the caller will free it.
0 commit comments