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

drm/xe/madvise: Skip vma invalidation if mem attr are unchanged

If a VMA within the madvise input range already has the same memory
attribute as the one requested by the user, skip PTE zapping for that
VMA to avoid unnecessary invalidation.

v2 (Matthew Brost)
- fix skip_invalidation for new attributes
- s/u32/bool
- Remove unnecessary assignment for kzalloc'ed

Suggested-by: Matthew Brost <matthew.brost@intel.com>
Reviewed-by: Matthew Brost <matthew.brost@intel.com>
Link: https://lore.kernel.org/r/20250821173104.3030148-17-himal.prasad.ghimiray@intel.com
Signed-off-by: Himal Prasad Ghimiray <himal.prasad.ghimiray@intel.com>

+52 -22
+46 -22
drivers/gpu/drm/xe/xe_vm_madvise.c
··· 85 85 86 86 for (i = 0; i < num_vmas; i++) { 87 87 /*TODO: Extend attributes to bo based vmas */ 88 - if (!xe_vma_is_cpu_addr_mirror(vmas[i])) 89 - continue; 90 - 91 - vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd; 92 - 93 - /* Till multi-device support is not added migration_policy 94 - * is of no use and can be ignored. 95 - */ 96 - vmas[i]->attr.preferred_loc.migration_policy = 88 + if ((vmas[i]->attr.preferred_loc.devmem_fd == op->preferred_mem_loc.devmem_fd && 89 + vmas[i]->attr.preferred_loc.migration_policy == 90 + op->preferred_mem_loc.migration_policy) || 91 + !xe_vma_is_cpu_addr_mirror(vmas[i])) { 92 + vmas[i]->skip_invalidation = true; 93 + } else { 94 + vmas[i]->skip_invalidation = false; 95 + vmas[i]->attr.preferred_loc.devmem_fd = op->preferred_mem_loc.devmem_fd; 96 + /* Till multi-device support is not added migration_policy 97 + * is of no use and can be ignored. 98 + */ 99 + vmas[i]->attr.preferred_loc.migration_policy = 97 100 op->preferred_mem_loc.migration_policy; 101 + } 98 102 } 99 103 } 100 104 ··· 113 109 xe_assert(vm->xe, op->atomic.val <= DRM_XE_ATOMIC_CPU); 114 110 115 111 for (i = 0; i < num_vmas; i++) { 116 - if ((xe_vma_is_userptr(vmas[i]) && 117 - !(op->atomic.val == DRM_XE_ATOMIC_DEVICE && 118 - xe->info.has_device_atomics_on_smem))) 112 + if (xe_vma_is_userptr(vmas[i]) && 113 + !(op->atomic.val == DRM_XE_ATOMIC_DEVICE && 114 + xe->info.has_device_atomics_on_smem)) { 115 + vmas[i]->skip_invalidation = true; 119 116 continue; 117 + } 118 + 119 + if (vmas[i]->attr.atomic_access == op->atomic.val) { 120 + vmas[i]->skip_invalidation = true; 121 + } else { 122 + vmas[i]->skip_invalidation = false; 123 + vmas[i]->attr.atomic_access = op->atomic.val; 124 + } 120 125 121 126 vmas[i]->attr.atomic_access = op->atomic.val; 122 127 123 128 bo = xe_vma_bo(vmas[i]); 124 - if (!bo) 129 + if (!bo || bo->attr.atomic_access == op->atomic.val) 125 130 continue; 126 131 132 + vmas[i]->skip_invalidation = false; 127 133 xe_bo_assert_held(bo); 128 134 bo->attr.atomic_access = op->atomic.val; 129 135 ··· 153 139 154 140 xe_assert(vm->xe, op->type == DRM_XE_MEM_RANGE_ATTR_PAT); 155 141 156 - for (i = 0; i < num_vmas; i++) 157 - vmas[i]->attr.pat_index = op->pat_index.val; 142 + for (i = 0; i < num_vmas; i++) { 143 + if (vmas[i]->attr.pat_index == op->pat_index.val) { 144 + vmas[i]->skip_invalidation = true; 145 + } else { 146 + vmas[i]->skip_invalidation = false; 147 + vmas[i]->attr.pat_index = op->pat_index.val; 148 + } 149 + } 158 150 } 159 151 160 152 typedef void (*madvise_func)(struct xe_device *xe, struct xe_vm *vm, ··· 177 157 { 178 158 struct drm_gpuva *gpuva; 179 159 struct xe_tile *tile; 180 - u8 id, tile_mask; 160 + u8 id, tile_mask = 0; 181 161 182 162 lockdep_assert_held_write(&vm->lock); 183 163 ··· 186 166 false, MAX_SCHEDULE_TIMEOUT) <= 0) 187 167 XE_WARN_ON(1); 188 168 189 - tile_mask = xe_svm_ranges_zap_ptes_in_range(vm, start, end); 190 - 191 169 drm_gpuvm_for_each_va_range(gpuva, &vm->gpuvm, start, end) { 192 170 struct xe_vma *vma = gpuva_to_vma(gpuva); 193 171 194 - if (xe_vma_is_cpu_addr_mirror(vma) || xe_vma_is_null(vma)) 172 + if (vma->skip_invalidation || xe_vma_is_null(vma)) 195 173 continue; 196 174 197 - for_each_tile(tile, vm->xe, id) { 198 - if (xe_pt_zap_ptes(tile, vma)) { 199 - tile_mask |= BIT(id); 175 + if (xe_vma_is_cpu_addr_mirror(vma)) { 176 + tile_mask |= xe_svm_ranges_zap_ptes_in_range(vm, 177 + xe_vma_start(vma), 178 + xe_vma_end(vma)); 179 + } else { 180 + for_each_tile(tile, vm->xe, id) { 181 + if (xe_pt_zap_ptes(tile, vma)) { 182 + tile_mask |= BIT(id); 200 183 201 184 /* 202 185 * WRITE_ONCE pairs with READ_ONCE ··· 207 184 */ 208 185 WRITE_ONCE(vma->tile_invalidated, 209 186 vma->tile_invalidated | BIT(id)); 187 + } 210 188 } 211 189 } 212 190 }
+6
drivers/gpu/drm/xe/xe_vm_types.h
··· 158 158 u8 tile_staged; 159 159 160 160 /** 161 + * @skip_invalidation: Used in madvise to avoid invalidation 162 + * if mem attributes doesn't change 163 + */ 164 + bool skip_invalidation; 165 + 166 + /** 161 167 * @ufence: The user fence that was provided with MAP. 162 168 * Needs to be signalled before UNMAP can be processed. 163 169 */