@@ -608,6 +608,7 @@ static const struct xe_pt_walk_ops xe_pt_stage_bind_ops = {
608
608
* range.
609
609
* @tile: The tile we're building for.
610
610
* @vma: The vma indicating the address range.
611
+ * @range: The range indicating the address range.
611
612
* @entries: Storage for the update entries used for connecting the tree to
612
613
* the main tree at commit time.
613
614
* @num_entries: On output contains the number of @entries used.
@@ -623,6 +624,7 @@ static const struct xe_pt_walk_ops xe_pt_stage_bind_ops = {
623
624
*/
624
625
static int
625
626
xe_pt_stage_bind (struct xe_tile * tile , struct xe_vma * vma ,
627
+ struct xe_svm_range * range ,
626
628
struct xe_vm_pgtable_update * entries , u32 * num_entries )
627
629
{
628
630
struct xe_device * xe = tile_to_xe (tile );
@@ -640,14 +642,38 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
640
642
.vm = xe_vma_vm (vma ),
641
643
.tile = tile ,
642
644
.curs = & curs ,
643
- .va_curs_start = xe_vma_start (vma ),
645
+ .va_curs_start = range ? range -> base .itree .start :
646
+ xe_vma_start (vma ),
644
647
.vma = vma ,
645
648
.wupd .entries = entries ,
646
- .needs_64K = (xe_vma_vm (vma )-> flags & XE_VM_FLAG_64K ) && is_devmem ,
647
649
};
648
650
struct xe_pt * pt = xe_vma_vm (vma )-> pt_root [tile -> id ];
649
651
int ret ;
650
652
653
+ if (range ) {
654
+ /* Move this entire thing to xe_svm.c? */
655
+ xe_svm_notifier_lock (xe_vma_vm (vma ));
656
+ if (!xe_svm_range_pages_valid (range )) {
657
+ xe_svm_notifier_unlock (xe_vma_vm (vma ));
658
+ return - EAGAIN ;
659
+ }
660
+ if (xe_svm_range_has_dma_mapping (range )) {
661
+ xe_res_first_dma (range -> base .dma_addr , 0 ,
662
+ range -> base .itree .last + 1 - range -> base .itree .start ,
663
+ & curs );
664
+ is_devmem = xe_res_is_vram (& curs );
665
+ } else {
666
+ xe_assert (xe , false);
667
+ }
668
+ /*
669
+ * Note, when unlocking the resource cursor dma addresses may become
670
+ * stale, but the bind will be aborted anyway at commit time.
671
+ */
672
+ xe_svm_notifier_unlock (xe_vma_vm (vma ));
673
+ }
674
+
675
+ xe_walk .needs_64K = (xe_vma_vm (vma )-> flags & XE_VM_FLAG_64K ) && is_devmem ;
676
+
651
677
/**
652
678
* Default atomic expectations for different allocation scenarios are as follows:
653
679
*
@@ -669,7 +695,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
669
695
* gets migrated to LMEM, bind such allocations with
670
696
* device atomics enabled.
671
697
*/
672
- else if (is_devmem && ! xe_bo_has_single_placement ( bo ) )
698
+ else if (is_devmem )
673
699
xe_walk .default_pte |= XE_USM_PPGTT_PTE_AE ;
674
700
} else {
675
701
xe_walk .default_pte |= XE_USM_PPGTT_PTE_AE ;
@@ -685,15 +711,16 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
685
711
686
712
if (is_devmem ) {
687
713
xe_walk .default_pte |= XE_PPGTT_PTE_DM ;
688
- xe_walk .dma_offset = vram_region_gpu_offset (bo -> ttm .resource );
714
+ xe_walk .dma_offset = bo ? vram_region_gpu_offset (bo -> ttm .resource ) : 0 ;
689
715
}
690
716
691
717
if (!xe_vma_has_no_bo (vma ) && xe_bo_is_stolen (bo ))
692
718
xe_walk .dma_offset = xe_ttm_stolen_gpu_offset (xe_bo_device (bo ));
693
719
694
- xe_bo_assert_held (bo );
720
+ if (!range )
721
+ xe_bo_assert_held (bo );
695
722
696
- if (!xe_vma_is_null (vma )) {
723
+ if (!xe_vma_is_null (vma ) && ! range ) {
697
724
if (xe_vma_is_userptr (vma ))
698
725
xe_res_first_sg (to_userptr_vma (vma )-> userptr .sg , 0 ,
699
726
xe_vma_size (vma ), & curs );
@@ -703,12 +730,14 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
703
730
else
704
731
xe_res_first_sg (xe_bo_sg (bo ), xe_vma_bo_offset (vma ),
705
732
xe_vma_size (vma ), & curs );
706
- } else {
733
+ } else if (! range ) {
707
734
curs .size = xe_vma_size (vma );
708
735
}
709
736
710
- ret = xe_pt_walk_range (& pt -> base , pt -> level , xe_vma_start (vma ),
711
- xe_vma_end (vma ), & xe_walk .base );
737
+ ret = xe_pt_walk_range (& pt -> base , pt -> level ,
738
+ range ? range -> base .itree .start : xe_vma_start (vma ),
739
+ range ? range -> base .itree .last + 1 : xe_vma_end (vma ),
740
+ & xe_walk .base );
712
741
713
742
* num_entries = xe_walk .wupd .num_used_entries ;
714
743
return ret ;
@@ -941,7 +970,7 @@ static void xe_pt_commit_prepare_locks_assert(struct xe_vma *vma)
941
970
942
971
lockdep_assert_held (& vm -> lock );
943
972
944
- if (!xe_vma_is_userptr ( vma ) && ! xe_vma_is_null (vma ))
973
+ if (!xe_vma_has_no_bo (vma ))
945
974
dma_resv_assert_held (xe_vma_bo (vma )-> ttm .base .resv );
946
975
947
976
xe_vm_assert_held (vm );
@@ -1057,12 +1086,13 @@ static void xe_pt_free_bind(struct xe_vm_pgtable_update *entries,
1057
1086
1058
1087
static int
1059
1088
xe_pt_prepare_bind (struct xe_tile * tile , struct xe_vma * vma ,
1089
+ struct xe_svm_range * range ,
1060
1090
struct xe_vm_pgtable_update * entries , u32 * num_entries )
1061
1091
{
1062
1092
int err ;
1063
1093
1064
1094
* num_entries = 0 ;
1065
- err = xe_pt_stage_bind (tile , vma , entries , num_entries );
1095
+ err = xe_pt_stage_bind (tile , vma , range , entries , num_entries );
1066
1096
if (!err )
1067
1097
xe_tile_assert (tile , * num_entries );
1068
1098
@@ -1168,6 +1198,8 @@ static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op,
1168
1198
case DRM_GPUVA_OP_PREFETCH :
1169
1199
err = vma_add_deps (gpuva_to_vma (op -> base .prefetch .va ), job );
1170
1200
break ;
1201
+ case DRM_GPUVA_OP_DRIVER :
1202
+ break ;
1171
1203
default :
1172
1204
drm_warn (& vm -> xe -> drm , "NOT POSSIBLE" );
1173
1205
}
@@ -1372,6 +1404,34 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
1372
1404
return err ;
1373
1405
}
1374
1406
1407
+ static int xe_pt_svm_pre_commit (struct xe_migrate_pt_update * pt_update )
1408
+ {
1409
+ struct xe_vm * vm = pt_update -> vops -> vm ;
1410
+ struct xe_vma_ops * vops = pt_update -> vops ;
1411
+ struct xe_vma_op * op ;
1412
+ int err ;
1413
+
1414
+ err = xe_pt_pre_commit (pt_update );
1415
+ if (err )
1416
+ return err ;
1417
+
1418
+ xe_svm_notifier_lock (vm );
1419
+
1420
+ list_for_each_entry (op , & vops -> list , link ) {
1421
+ struct xe_svm_range * range = op -> map_range .range ;
1422
+
1423
+ xe_assert (vm -> xe , xe_vma_is_cpu_addr_mirror (op -> map_range .vma ));
1424
+ xe_assert (vm -> xe , op -> subop == XE_VMA_SUBOP_MAP_RANGE );
1425
+
1426
+ if (!xe_svm_range_pages_valid (range )) {
1427
+ xe_svm_notifier_unlock (vm );
1428
+ return - EAGAIN ;
1429
+ }
1430
+ }
1431
+
1432
+ return 0 ;
1433
+ }
1434
+
1375
1435
struct invalidation_fence {
1376
1436
struct xe_gt_tlb_invalidation_fence base ;
1377
1437
struct xe_gt * gt ;
@@ -1665,12 +1725,12 @@ xe_pt_commit_prepare_unbind(struct xe_vma *vma,
1665
1725
1666
1726
static void
1667
1727
xe_pt_update_ops_rfence_interval (struct xe_vm_pgtable_update_ops * pt_update_ops ,
1668
- struct xe_vma * vma )
1728
+ u64 start , u64 end )
1669
1729
{
1730
+ u64 last ;
1670
1731
u32 current_op = pt_update_ops -> current_op ;
1671
1732
struct xe_vm_pgtable_update_op * pt_op = & pt_update_ops -> ops [current_op ];
1672
1733
int i , level = 0 ;
1673
- u64 start , last ;
1674
1734
1675
1735
for (i = 0 ; i < pt_op -> num_entries ; i ++ ) {
1676
1736
const struct xe_vm_pgtable_update * entry = & pt_op -> entries [i ];
@@ -1680,8 +1740,8 @@ xe_pt_update_ops_rfence_interval(struct xe_vm_pgtable_update_ops *pt_update_ops,
1680
1740
}
1681
1741
1682
1742
/* Greedy (non-optimal) calculation but simple */
1683
- start = ALIGN_DOWN (xe_vma_start ( vma ) , 0x1ull << xe_pt_shift (level ));
1684
- last = ALIGN (xe_vma_end ( vma ) , 0x1ull << xe_pt_shift (level )) - 1 ;
1743
+ start = ALIGN_DOWN (start , 0x1ull << xe_pt_shift (level ));
1744
+ last = ALIGN (end , 0x1ull << xe_pt_shift (level )) - 1 ;
1685
1745
1686
1746
if (start < pt_update_ops -> start )
1687
1747
pt_update_ops -> start = start ;
@@ -1723,15 +1783,17 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
1723
1783
if (err )
1724
1784
return err ;
1725
1785
1726
- err = xe_pt_prepare_bind (tile , vma , pt_op -> entries ,
1786
+ err = xe_pt_prepare_bind (tile , vma , NULL , pt_op -> entries ,
1727
1787
& pt_op -> num_entries );
1728
1788
if (!err ) {
1729
1789
xe_tile_assert (tile , pt_op -> num_entries <=
1730
1790
ARRAY_SIZE (pt_op -> entries ));
1731
1791
xe_vm_dbg_print_entries (tile_to_xe (tile ), pt_op -> entries ,
1732
1792
pt_op -> num_entries , true);
1733
1793
1734
- xe_pt_update_ops_rfence_interval (pt_update_ops , vma );
1794
+ xe_pt_update_ops_rfence_interval (pt_update_ops ,
1795
+ xe_vma_start (vma ),
1796
+ xe_vma_end (vma ));
1735
1797
++ pt_update_ops -> current_op ;
1736
1798
pt_update_ops -> needs_userptr_lock |= xe_vma_is_userptr (vma );
1737
1799
@@ -1765,6 +1827,48 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
1765
1827
return err ;
1766
1828
}
1767
1829
1830
+ static int bind_range_prepare (struct xe_vm * vm , struct xe_tile * tile ,
1831
+ struct xe_vm_pgtable_update_ops * pt_update_ops ,
1832
+ struct xe_vma * vma , struct xe_svm_range * range )
1833
+ {
1834
+ u32 current_op = pt_update_ops -> current_op ;
1835
+ struct xe_vm_pgtable_update_op * pt_op = & pt_update_ops -> ops [current_op ];
1836
+ int err ;
1837
+
1838
+ xe_tile_assert (tile , xe_vma_is_cpu_addr_mirror (vma ));
1839
+
1840
+ vm_dbg (& xe_vma_vm (vma )-> xe -> drm ,
1841
+ "Preparing bind, with range [%lx...%lx)\n" ,
1842
+ range -> base .itree .start , range -> base .itree .last );
1843
+
1844
+ pt_op -> vma = NULL ;
1845
+ pt_op -> bind = true;
1846
+ pt_op -> rebind = BIT (tile -> id ) & range -> tile_present ;
1847
+
1848
+ err = xe_pt_prepare_bind (tile , vma , range , pt_op -> entries ,
1849
+ & pt_op -> num_entries );
1850
+ if (!err ) {
1851
+ xe_tile_assert (tile , pt_op -> num_entries <=
1852
+ ARRAY_SIZE (pt_op -> entries ));
1853
+ xe_vm_dbg_print_entries (tile_to_xe (tile ), pt_op -> entries ,
1854
+ pt_op -> num_entries , true);
1855
+
1856
+ xe_pt_update_ops_rfence_interval (pt_update_ops ,
1857
+ range -> base .itree .start ,
1858
+ range -> base .itree .last + 1 );
1859
+ ++ pt_update_ops -> current_op ;
1860
+ pt_update_ops -> needs_svm_lock = true;
1861
+
1862
+ pt_op -> vma = vma ;
1863
+ xe_pt_commit_prepare_bind (vma , pt_op -> entries ,
1864
+ pt_op -> num_entries , pt_op -> rebind );
1865
+ } else {
1866
+ xe_pt_cancel_bind (vma , pt_op -> entries , pt_op -> num_entries );
1867
+ }
1868
+
1869
+ return err ;
1870
+ }
1871
+
1768
1872
static int unbind_op_prepare (struct xe_tile * tile ,
1769
1873
struct xe_vm_pgtable_update_ops * pt_update_ops ,
1770
1874
struct xe_vma * vma )
@@ -1802,7 +1906,8 @@ static int unbind_op_prepare(struct xe_tile *tile,
1802
1906
1803
1907
xe_vm_dbg_print_entries (tile_to_xe (tile ), pt_op -> entries ,
1804
1908
pt_op -> num_entries , false);
1805
- xe_pt_update_ops_rfence_interval (pt_update_ops , vma );
1909
+ xe_pt_update_ops_rfence_interval (pt_update_ops , xe_vma_start (vma ),
1910
+ xe_vma_end (vma ));
1806
1911
++ pt_update_ops -> current_op ;
1807
1912
pt_update_ops -> needs_userptr_lock |= xe_vma_is_userptr (vma );
1808
1913
pt_update_ops -> needs_invalidation = true;
@@ -1872,6 +1977,15 @@ static int op_prepare(struct xe_vm *vm,
1872
1977
pt_update_ops -> wait_vm_kernel = true;
1873
1978
break ;
1874
1979
}
1980
+ case DRM_GPUVA_OP_DRIVER :
1981
+ if (op -> subop == XE_VMA_SUBOP_MAP_RANGE ) {
1982
+ xe_assert (vm -> xe , xe_vma_is_cpu_addr_mirror (op -> map_range .vma ));
1983
+
1984
+ err = bind_range_prepare (vm , tile , pt_update_ops ,
1985
+ op -> map_range .vma ,
1986
+ op -> map_range .range );
1987
+ }
1988
+ break ;
1875
1989
default :
1876
1990
drm_warn (& vm -> xe -> drm , "NOT POSSIBLE" );
1877
1991
}
@@ -2054,6 +2168,14 @@ static void op_commit(struct xe_vm *vm,
2054
2168
fence2 );
2055
2169
break ;
2056
2170
}
2171
+ case DRM_GPUVA_OP_DRIVER :
2172
+ {
2173
+ if (op -> subop == XE_VMA_SUBOP_MAP_RANGE ) {
2174
+ op -> map_range .range -> tile_present |= BIT (tile -> id );
2175
+ op -> map_range .range -> tile_invalidated &= ~BIT (tile -> id );
2176
+ }
2177
+ break ;
2178
+ }
2057
2179
default :
2058
2180
drm_warn (& vm -> xe -> drm , "NOT POSSIBLE" );
2059
2181
}
@@ -2071,6 +2193,12 @@ static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
2071
2193
.pre_commit = xe_pt_userptr_pre_commit ,
2072
2194
};
2073
2195
2196
+ static const struct xe_migrate_pt_update_ops svm_migrate_ops = {
2197
+ .populate = xe_vm_populate_pgtable ,
2198
+ .clear = xe_migrate_clear_pgtable_callback ,
2199
+ .pre_commit = xe_pt_svm_pre_commit ,
2200
+ };
2201
+
2074
2202
/**
2075
2203
* xe_pt_update_ops_run() - Run PT update operations
2076
2204
* @tile: Tile of PT update operations
@@ -2096,7 +2224,9 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
2096
2224
struct xe_vma_op * op ;
2097
2225
int err = 0 , i ;
2098
2226
struct xe_migrate_pt_update update = {
2099
- .ops = pt_update_ops -> needs_userptr_lock ?
2227
+ .ops = pt_update_ops -> needs_svm_lock ?
2228
+ & svm_migrate_ops :
2229
+ pt_update_ops -> needs_userptr_lock ?
2100
2230
& userptr_migrate_ops :
2101
2231
& migrate_ops ,
2102
2232
.vops = vops ,
@@ -2217,6 +2347,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
2217
2347
& ifence -> base .base , & mfence -> base .base );
2218
2348
}
2219
2349
2350
+ if (pt_update_ops -> needs_svm_lock )
2351
+ xe_svm_notifier_unlock (vm );
2220
2352
if (pt_update_ops -> needs_userptr_lock )
2221
2353
up_read (& vm -> userptr .notifier_lock );
2222
2354
0 commit comments