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.

drm/xe/svm: Add xe_svm_ranges_zap_ptes_in_range() for PTE zapping

Introduce xe_svm_ranges_zap_ptes_in_range(), a function to zap page table
entries (PTEs) for all SVM ranges within a user-specified address range.

-v2 (Matthew Brost)
Lock should be called even for tlb_invalidation

v3(Matthew Brost)
- Update comment
- s/notifier->itree.start/drm_gpusvm_notifier_start
- s/notifier->itree.last + 1/drm_gpusvm_notifier_end
- use WRITE_ONCE

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

+71 -1
+13 -1
drivers/gpu/drm/xe/xe_pt.c
··· 950 950 struct xe_pt *pt = vm->pt_root[tile->id]; 951 951 u8 pt_mask = (range->tile_present & ~range->tile_invalidated); 952 952 953 - xe_svm_assert_in_notifier(vm); 953 + /* 954 + * Locking rules: 955 + * 956 + * - notifier_lock (write): full protection against page table changes 957 + * and MMU notifier invalidations. 958 + * 959 + * - notifier_lock (read) + vm_lock (write): combined protection against 960 + * invalidations and concurrent page table modifications. (e.g., madvise) 961 + * 962 + */ 963 + lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 0) || 964 + (lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) && 965 + lockdep_is_held_type(&vm->lock, 0))); 954 966 955 967 if (!(pt_mask & BIT(tile->id))) 956 968 return false;
+50
drivers/gpu/drm/xe/xe_svm.c
··· 1031 1031 return err; 1032 1032 } 1033 1033 1034 + /** 1035 + * xe_svm_ranges_zap_ptes_in_range - clear ptes of svm ranges in input range 1036 + * @vm: Pointer to the xe_vm structure 1037 + * @start: Start of the input range 1038 + * @end: End of the input range 1039 + * 1040 + * This function removes the page table entries (PTEs) associated 1041 + * with the svm ranges within the given input start and end 1042 + * 1043 + * Return: tile_mask for which gt's need to be tlb invalidated. 1044 + */ 1045 + u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end) 1046 + { 1047 + struct drm_gpusvm_notifier *notifier; 1048 + struct xe_svm_range *range; 1049 + u64 adj_start, adj_end; 1050 + struct xe_tile *tile; 1051 + u8 tile_mask = 0; 1052 + u8 id; 1053 + 1054 + lockdep_assert(lockdep_is_held_type(&vm->svm.gpusvm.notifier_lock, 1) && 1055 + lockdep_is_held_type(&vm->lock, 0)); 1056 + 1057 + drm_gpusvm_for_each_notifier(notifier, &vm->svm.gpusvm, start, end) { 1058 + struct drm_gpusvm_range *r = NULL; 1059 + 1060 + adj_start = max(start, drm_gpusvm_notifier_start(notifier)); 1061 + adj_end = min(end, drm_gpusvm_notifier_end(notifier)); 1062 + drm_gpusvm_for_each_range(r, notifier, adj_start, adj_end) { 1063 + range = to_xe_range(r); 1064 + for_each_tile(tile, vm->xe, id) { 1065 + if (xe_pt_zap_ptes_range(tile, vm, range)) { 1066 + tile_mask |= BIT(id); 1067 + /* 1068 + * WRITE_ONCE pairs with READ_ONCE in 1069 + * xe_vm_has_valid_gpu_mapping(). 1070 + * Must not fail after setting 1071 + * tile_invalidated and before 1072 + * TLB invalidation. 1073 + */ 1074 + WRITE_ONCE(range->tile_invalidated, 1075 + range->tile_invalidated | BIT(id)); 1076 + } 1077 + } 1078 + } 1079 + } 1080 + 1081 + return tile_mask; 1082 + } 1083 + 1034 1084 #if IS_ENABLED(CONFIG_DRM_XE_PAGEMAP) 1035 1085 1036 1086 static struct drm_pagemap *tile_local_pagemap(struct xe_tile *tile)
+8
drivers/gpu/drm/xe/xe_svm.h
··· 92 92 93 93 void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end); 94 94 95 + u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end); 96 + 95 97 /** 96 98 * xe_svm_range_has_dma_mapping() - SVM range has DMA mapping 97 99 * @range: SVM range ··· 310 308 static inline 311 309 void xe_svm_unmap_address_range(struct xe_vm *vm, u64 start, u64 end) 312 310 { 311 + } 312 + 313 + static inline 314 + u8 xe_svm_ranges_zap_ptes_in_range(struct xe_vm *vm, u64 start, u64 end) 315 + { 316 + return 0; 313 317 } 314 318 315 319 #define xe_svm_assert_in_notifier(...) do {} while (0)