@@ -608,6 +608,7 @@ static const struct xe_pt_walk_ops xe_pt_stage_bind_ops = {
608608 * range.
609609 * @tile: The tile we're building for.
610610 * @vma: The vma indicating the address range.
611+ * @range: The range indicating the address range.
611612 * @entries: Storage for the update entries used for connecting the tree to
612613 * the main tree at commit time.
613614 * @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 = {
623624 */
624625static int
625626xe_pt_stage_bind (struct xe_tile * tile , struct xe_vma * vma ,
627+ struct xe_svm_range * range ,
626628 struct xe_vm_pgtable_update * entries , u32 * num_entries )
627629{
628630 struct xe_device * xe = tile_to_xe (tile );
@@ -640,14 +642,38 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
640642 .vm = xe_vma_vm (vma ),
641643 .tile = tile ,
642644 .curs = & curs ,
643- .va_curs_start = xe_vma_start (vma ),
645+ .va_curs_start = range ? range -> base .itree .start :
646+ xe_vma_start (vma ),
644647 .vma = vma ,
645648 .wupd .entries = entries ,
646- .needs_64K = (xe_vma_vm (vma )-> flags & XE_VM_FLAG_64K ) && is_devmem ,
647649 };
648650 struct xe_pt * pt = xe_vma_vm (vma )-> pt_root [tile -> id ];
649651 int ret ;
650652
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+
651677 /**
652678 * Default atomic expectations for different allocation scenarios are as follows:
653679 *
@@ -669,7 +695,7 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
669695 * gets migrated to LMEM, bind such allocations with
670696 * device atomics enabled.
671697 */
672- else if (is_devmem && ! xe_bo_has_single_placement ( bo ) )
698+ else if (is_devmem )
673699 xe_walk .default_pte |= XE_USM_PPGTT_PTE_AE ;
674700 } else {
675701 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,
685711
686712 if (is_devmem ) {
687713 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 ;
689715 }
690716
691717 if (!xe_vma_has_no_bo (vma ) && xe_bo_is_stolen (bo ))
692718 xe_walk .dma_offset = xe_ttm_stolen_gpu_offset (xe_bo_device (bo ));
693719
694- xe_bo_assert_held (bo );
720+ if (!range )
721+ xe_bo_assert_held (bo );
695722
696- if (!xe_vma_is_null (vma )) {
723+ if (!xe_vma_is_null (vma ) && ! range ) {
697724 if (xe_vma_is_userptr (vma ))
698725 xe_res_first_sg (to_userptr_vma (vma )-> userptr .sg , 0 ,
699726 xe_vma_size (vma ), & curs );
@@ -703,12 +730,14 @@ xe_pt_stage_bind(struct xe_tile *tile, struct xe_vma *vma,
703730 else
704731 xe_res_first_sg (xe_bo_sg (bo ), xe_vma_bo_offset (vma ),
705732 xe_vma_size (vma ), & curs );
706- } else {
733+ } else if (! range ) {
707734 curs .size = xe_vma_size (vma );
708735 }
709736
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 );
712741
713742 * num_entries = xe_walk .wupd .num_used_entries ;
714743 return ret ;
@@ -941,7 +970,7 @@ static void xe_pt_commit_prepare_locks_assert(struct xe_vma *vma)
941970
942971 lockdep_assert_held (& vm -> lock );
943972
944- if (!xe_vma_is_userptr ( vma ) && ! xe_vma_is_null (vma ))
973+ if (!xe_vma_has_no_bo (vma ))
945974 dma_resv_assert_held (xe_vma_bo (vma )-> ttm .base .resv );
946975
947976 xe_vm_assert_held (vm );
@@ -1057,12 +1086,13 @@ static void xe_pt_free_bind(struct xe_vm_pgtable_update *entries,
10571086
10581087static int
10591088xe_pt_prepare_bind (struct xe_tile * tile , struct xe_vma * vma ,
1089+ struct xe_svm_range * range ,
10601090 struct xe_vm_pgtable_update * entries , u32 * num_entries )
10611091{
10621092 int err ;
10631093
10641094 * 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 );
10661096 if (!err )
10671097 xe_tile_assert (tile , * num_entries );
10681098
@@ -1168,6 +1198,8 @@ static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op,
11681198 case DRM_GPUVA_OP_PREFETCH :
11691199 err = vma_add_deps (gpuva_to_vma (op -> base .prefetch .va ), job );
11701200 break ;
1201+ case DRM_GPUVA_OP_DRIVER :
1202+ break ;
11711203 default :
11721204 drm_warn (& vm -> xe -> drm , "NOT POSSIBLE" );
11731205 }
@@ -1372,6 +1404,34 @@ static int xe_pt_userptr_pre_commit(struct xe_migrate_pt_update *pt_update)
13721404 return err ;
13731405}
13741406
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+
13751435struct invalidation_fence {
13761436 struct xe_gt_tlb_invalidation_fence base ;
13771437 struct xe_gt * gt ;
@@ -1665,12 +1725,12 @@ xe_pt_commit_prepare_unbind(struct xe_vma *vma,
16651725
16661726static void
16671727xe_pt_update_ops_rfence_interval (struct xe_vm_pgtable_update_ops * pt_update_ops ,
1668- struct xe_vma * vma )
1728+ u64 start , u64 end )
16691729{
1730+ u64 last ;
16701731 u32 current_op = pt_update_ops -> current_op ;
16711732 struct xe_vm_pgtable_update_op * pt_op = & pt_update_ops -> ops [current_op ];
16721733 int i , level = 0 ;
1673- u64 start , last ;
16741734
16751735 for (i = 0 ; i < pt_op -> num_entries ; i ++ ) {
16761736 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,
16801740 }
16811741
16821742 /* 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 ;
16851745
16861746 if (start < pt_update_ops -> start )
16871747 pt_update_ops -> start = start ;
@@ -1723,15 +1783,17 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
17231783 if (err )
17241784 return err ;
17251785
1726- err = xe_pt_prepare_bind (tile , vma , pt_op -> entries ,
1786+ err = xe_pt_prepare_bind (tile , vma , NULL , pt_op -> entries ,
17271787 & pt_op -> num_entries );
17281788 if (!err ) {
17291789 xe_tile_assert (tile , pt_op -> num_entries <=
17301790 ARRAY_SIZE (pt_op -> entries ));
17311791 xe_vm_dbg_print_entries (tile_to_xe (tile ), pt_op -> entries ,
17321792 pt_op -> num_entries , true);
17331793
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 ));
17351797 ++ pt_update_ops -> current_op ;
17361798 pt_update_ops -> needs_userptr_lock |= xe_vma_is_userptr (vma );
17371799
@@ -1765,6 +1827,48 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
17651827 return err ;
17661828}
17671829
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+
17681872static int unbind_op_prepare (struct xe_tile * tile ,
17691873 struct xe_vm_pgtable_update_ops * pt_update_ops ,
17701874 struct xe_vma * vma )
@@ -1802,7 +1906,8 @@ static int unbind_op_prepare(struct xe_tile *tile,
18021906
18031907 xe_vm_dbg_print_entries (tile_to_xe (tile ), pt_op -> entries ,
18041908 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 ));
18061911 ++ pt_update_ops -> current_op ;
18071912 pt_update_ops -> needs_userptr_lock |= xe_vma_is_userptr (vma );
18081913 pt_update_ops -> needs_invalidation = true;
@@ -1872,6 +1977,15 @@ static int op_prepare(struct xe_vm *vm,
18721977 pt_update_ops -> wait_vm_kernel = true;
18731978 break ;
18741979 }
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 ;
18751989 default :
18761990 drm_warn (& vm -> xe -> drm , "NOT POSSIBLE" );
18771991 }
@@ -2054,6 +2168,14 @@ static void op_commit(struct xe_vm *vm,
20542168 fence2 );
20552169 break ;
20562170 }
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+ }
20572179 default :
20582180 drm_warn (& vm -> xe -> drm , "NOT POSSIBLE" );
20592181 }
@@ -2071,6 +2193,12 @@ static const struct xe_migrate_pt_update_ops userptr_migrate_ops = {
20712193 .pre_commit = xe_pt_userptr_pre_commit ,
20722194};
20732195
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+
20742202/**
20752203 * xe_pt_update_ops_run() - Run PT update operations
20762204 * @tile: Tile of PT update operations
@@ -2096,7 +2224,9 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
20962224 struct xe_vma_op * op ;
20972225 int err = 0 , i ;
20982226 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 ?
21002230 & userptr_migrate_ops :
21012231 & migrate_ops ,
21022232 .vops = vops ,
@@ -2217,6 +2347,8 @@ xe_pt_update_ops_run(struct xe_tile *tile, struct xe_vma_ops *vops)
22172347 & ifence -> base .base , & mfence -> base .base );
22182348 }
22192349
2350+ if (pt_update_ops -> needs_svm_lock )
2351+ xe_svm_notifier_unlock (vm );
22202352 if (pt_update_ops -> needs_userptr_lock )
22212353 up_read (& vm -> userptr .notifier_lock );
22222354
0 commit comments