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: Split system allocator vma incase of madvise call

If the start or end of input address range lies within system allocator
vma split the vma to create new vma's as per input range.

v2 (Matthew Brost)
- Add lockdep_assert_write for vm->lock
- Remove unnecessary page aligned checks
- Add kerrnel-doc and comments
- Remove unnecessary unwind_ops and return

v3
- Fix copying of attributes

v4
- Nit fixes

v5
- Squash identifier for madvise in xe_vma_ops to this patch

v6/v7/v8
- Rebase on drm_gpuvm changes

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

+111
+108
drivers/gpu/drm/xe/xe_vm.c
··· 4207 4207 } 4208 4208 kvfree(snap); 4209 4209 } 4210 + 4211 + /** 4212 + * xe_vm_alloc_madvise_vma - Allocate VMA's with madvise ops 4213 + * @vm: Pointer to the xe_vm structure 4214 + * @start: Starting input address 4215 + * @range: Size of the input range 4216 + * 4217 + * This function splits existing vma to create new vma for user provided input range 4218 + * 4219 + * Return: 0 if success 4220 + */ 4221 + int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t start, uint64_t range) 4222 + { 4223 + struct drm_gpuvm_map_req map_req = { 4224 + .map.va.addr = start, 4225 + .map.va.range = range, 4226 + }; 4227 + 4228 + struct xe_vma_ops vops; 4229 + struct drm_gpuva_ops *ops = NULL; 4230 + struct drm_gpuva_op *__op; 4231 + bool is_cpu_addr_mirror = false; 4232 + bool remap_op = false; 4233 + struct xe_vma_mem_attr tmp_attr; 4234 + int err; 4235 + 4236 + lockdep_assert_held_write(&vm->lock); 4237 + 4238 + vm_dbg(&vm->xe->drm, "MADVISE_OPS_CREATE: addr=0x%016llx, size=0x%016llx", start, range); 4239 + ops = drm_gpuvm_madvise_ops_create(&vm->gpuvm, &map_req); 4240 + if (IS_ERR(ops)) 4241 + return PTR_ERR(ops); 4242 + 4243 + if (list_empty(&ops->list)) { 4244 + err = 0; 4245 + goto free_ops; 4246 + } 4247 + 4248 + drm_gpuva_for_each_op(__op, ops) { 4249 + struct xe_vma_op *op = gpuva_op_to_vma_op(__op); 4250 + 4251 + if (__op->op == DRM_GPUVA_OP_REMAP) { 4252 + xe_assert(vm->xe, !remap_op); 4253 + remap_op = true; 4254 + 4255 + if (xe_vma_is_cpu_addr_mirror(gpuva_to_vma(op->base.remap.unmap->va))) 4256 + is_cpu_addr_mirror = true; 4257 + else 4258 + is_cpu_addr_mirror = false; 4259 + } 4260 + 4261 + if (__op->op == DRM_GPUVA_OP_MAP) { 4262 + xe_assert(vm->xe, remap_op); 4263 + remap_op = false; 4264 + 4265 + /* In case of madvise ops DRM_GPUVA_OP_MAP is always after 4266 + * DRM_GPUVA_OP_REMAP, so ensure we assign op->map.is_cpu_addr_mirror true 4267 + * if REMAP is for xe_vma_is_cpu_addr_mirror vma 4268 + */ 4269 + op->map.is_cpu_addr_mirror = is_cpu_addr_mirror; 4270 + } 4271 + 4272 + print_op(vm->xe, __op); 4273 + } 4274 + 4275 + xe_vma_ops_init(&vops, vm, NULL, NULL, 0); 4276 + vops.flags |= XE_VMA_OPS_FLAG_MADVISE; 4277 + err = vm_bind_ioctl_ops_parse(vm, ops, &vops); 4278 + if (err) 4279 + goto unwind_ops; 4280 + 4281 + xe_vm_lock(vm, false); 4282 + 4283 + drm_gpuva_for_each_op(__op, ops) { 4284 + struct xe_vma_op *op = gpuva_op_to_vma_op(__op); 4285 + struct xe_vma *vma; 4286 + 4287 + if (__op->op == DRM_GPUVA_OP_UNMAP) { 4288 + /* There should be no unmap */ 4289 + XE_WARN_ON("UNEXPECTED UNMAP"); 4290 + xe_vma_destroy(gpuva_to_vma(op->base.unmap.va), NULL); 4291 + } else if (__op->op == DRM_GPUVA_OP_REMAP) { 4292 + vma = gpuva_to_vma(op->base.remap.unmap->va); 4293 + /* Store attributes for REMAP UNMAPPED VMA, so they can be assigned 4294 + * to newly MAP created vma. 4295 + */ 4296 + tmp_attr = vma->attr; 4297 + xe_vma_destroy(gpuva_to_vma(op->base.remap.unmap->va), NULL); 4298 + } else if (__op->op == DRM_GPUVA_OP_MAP) { 4299 + vma = op->map.vma; 4300 + /* In case of madvise call, MAP will always be follwed by REMAP. 4301 + * Therefore temp_attr will always have sane values, making it safe to 4302 + * copy them to new vma. 4303 + */ 4304 + vma->attr = tmp_attr; 4305 + } 4306 + } 4307 + 4308 + xe_vm_unlock(vm); 4309 + drm_gpuva_ops_free(&vm->gpuvm, ops); 4310 + return 0; 4311 + 4312 + unwind_ops: 4313 + vm_bind_ioctl_ops_unwind(vm, &ops, 1); 4314 + free_ops: 4315 + drm_gpuva_ops_free(&vm->gpuvm, ops); 4316 + return err; 4317 + }
+2
drivers/gpu/drm/xe/xe_vm.h
··· 171 171 172 172 struct xe_vma *xe_vm_find_vma_by_addr(struct xe_vm *vm, u64 page_addr); 173 173 174 + int xe_vm_alloc_madvise_vma(struct xe_vm *vm, uint64_t addr, uint64_t size); 175 + 174 176 /** 175 177 * to_userptr_vma() - Return a pointer to an embedding userptr vma 176 178 * @vma: Pointer to the embedded struct xe_vma
+1
drivers/gpu/drm/xe/xe_vm_types.h
··· 495 495 struct xe_vm_pgtable_update_ops pt_update_ops[XE_MAX_TILES_PER_DEVICE]; 496 496 /** @flag: signify the properties within xe_vma_ops*/ 497 497 #define XE_VMA_OPS_FLAG_HAS_SVM_PREFETCH BIT(0) 498 + #define XE_VMA_OPS_FLAG_MADVISE BIT(1) 498 499 u32 flags; 499 500 #ifdef TEST_VM_OPS_ERROR 500 501 /** @inject_error: inject error to test error handling */