1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Copyright (c) 2022 Red Hat. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included in 13 * all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 * Authors: 24 * Danilo Krummrich <dakr@redhat.com> 25 * 26 */ 27 28 #include <drm/drm_gpuva_mgr.h> 29 30 #include <linux/interval_tree_generic.h> 31 #include <linux/mm.h> 32 33 /** 34 * DOC: Overview 35 * 36 * The DRM GPU VA Manager, represented by struct drm_gpuva_manager keeps track 37 * of a GPU's virtual address (VA) space and manages the corresponding virtual 38 * mappings represented by &drm_gpuva objects. It also keeps track of the 39 * mapping's backing &drm_gem_object buffers. 40 * 41 * &drm_gem_object buffers maintain a list of &drm_gpuva objects representing 42 * all existent GPU VA mappings using this &drm_gem_object as backing buffer. 43 * 44 * GPU VAs can be flagged as sparse, such that drivers may use GPU VAs to also 45 * keep track of sparse PTEs in order to support Vulkan 'Sparse Resources'. 46 * 47 * The GPU VA manager internally uses a rb-tree to manage the 48 * &drm_gpuva mappings within a GPU's virtual address space. 49 * 50 * The &drm_gpuva_manager contains a special &drm_gpuva representing the 51 * portion of VA space reserved by the kernel. This node is initialized together 52 * with the GPU VA manager instance and removed when the GPU VA manager is 53 * destroyed. 54 * 55 * In a typical application drivers would embed struct drm_gpuva_manager and 56 * struct drm_gpuva within their own driver specific structures, there won't be 57 * any memory allocations of its own nor memory allocations of &drm_gpuva 58 * entries. 59 * 60 * The data structures needed to store &drm_gpuvas within the &drm_gpuva_manager 61 * are contained within struct drm_gpuva already. Hence, for inserting 62 * &drm_gpuva entries from within dma-fence signalling critical sections it is 63 * enough to pre-allocate the &drm_gpuva structures. 64 */ 65 66 /** 67 * DOC: Split and Merge 68 * 69 * Besides its capability to manage and represent a GPU VA space, the 70 * &drm_gpuva_manager also provides functions to let the &drm_gpuva_manager 71 * calculate a sequence of operations to satisfy a given map or unmap request. 72 * 73 * Therefore the DRM GPU VA manager provides an algorithm implementing splitting 74 * and merging of existent GPU VA mappings with the ones that are requested to 75 * be mapped or unmapped. This feature is required by the Vulkan API to 76 * implement Vulkan 'Sparse Memory Bindings' - drivers UAPIs often refer to this 77 * as VM BIND. 78 * 79 * Drivers can call drm_gpuva_sm_map() to receive a sequence of callbacks 80 * containing map, unmap and remap operations for a given newly requested 81 * mapping. The sequence of callbacks represents the set of operations to 82 * execute in order to integrate the new mapping cleanly into the current state 83 * of the GPU VA space. 84 * 85 * Depending on how the new GPU VA mapping intersects with the existent mappings 86 * of the GPU VA space the &drm_gpuva_fn_ops callbacks contain an arbitrary 87 * amount of unmap operations, a maximum of two remap operations and a single 88 * map operation. The caller might receive no callback at all if no operation is 89 * required, e.g. if the requested mapping already exists in the exact same way. 90 * 91 * The single map operation represents the original map operation requested by 92 * the caller. 93 * 94 * &drm_gpuva_op_unmap contains a 'keep' field, which indicates whether the 95 * &drm_gpuva to unmap is physically contiguous with the original mapping 96 * request. Optionally, if 'keep' is set, drivers may keep the actual page table 97 * entries for this &drm_gpuva, adding the missing page table entries only and 98 * update the &drm_gpuva_manager's view of things accordingly. 99 * 100 * Drivers may do the same optimization, namely delta page table updates, also 101 * for remap operations. This is possible since &drm_gpuva_op_remap consists of 102 * one unmap operation and one or two map operations, such that drivers can 103 * derive the page table update delta accordingly. 104 * 105 * Note that there can't be more than two existent mappings to split up, one at 106 * the beginning and one at the end of the new mapping, hence there is a 107 * maximum of two remap operations. 108 * 109 * Analogous to drm_gpuva_sm_map() drm_gpuva_sm_unmap() uses &drm_gpuva_fn_ops 110 * to call back into the driver in order to unmap a range of GPU VA space. The 111 * logic behind this function is way simpler though: For all existent mappings 112 * enclosed by the given range unmap operations are created. For mappings which 113 * are only partically located within the given range, remap operations are 114 * created such that those mappings are split up and re-mapped partically. 115 * 116 * As an alternative to drm_gpuva_sm_map() and drm_gpuva_sm_unmap(), 117 * drm_gpuva_sm_map_ops_create() and drm_gpuva_sm_unmap_ops_create() can be used 118 * to directly obtain an instance of struct drm_gpuva_ops containing a list of 119 * &drm_gpuva_op, which can be iterated with drm_gpuva_for_each_op(). This list 120 * contains the &drm_gpuva_ops analogous to the callbacks one would receive when 121 * calling drm_gpuva_sm_map() or drm_gpuva_sm_unmap(). While this way requires 122 * more memory (to allocate the &drm_gpuva_ops), it provides drivers a way to 123 * iterate the &drm_gpuva_op multiple times, e.g. once in a context where memory 124 * allocations are possible (e.g. to allocate GPU page tables) and once in the 125 * dma-fence signalling critical path. 126 * 127 * To update the &drm_gpuva_manager's view of the GPU VA space 128 * drm_gpuva_insert() and drm_gpuva_remove() may be used. These functions can 129 * safely be used from &drm_gpuva_fn_ops callbacks originating from 130 * drm_gpuva_sm_map() or drm_gpuva_sm_unmap(). However, it might be more 131 * convenient to use the provided helper functions drm_gpuva_map(), 132 * drm_gpuva_remap() and drm_gpuva_unmap() instead. 133 * 134 * The following diagram depicts the basic relationships of existent GPU VA 135 * mappings, a newly requested mapping and the resulting mappings as implemented 136 * by drm_gpuva_sm_map() - it doesn't cover any arbitrary combinations of these. 137 * 138 * 1) Requested mapping is identical. Replace it, but indicate the backing PTEs 139 * could be kept. 140 * 141 * :: 142 * 143 * 0 a 1 144 * old: |-----------| (bo_offset=n) 145 * 146 * 0 a 1 147 * req: |-----------| (bo_offset=n) 148 * 149 * 0 a 1 150 * new: |-----------| (bo_offset=n) 151 * 152 * 153 * 2) Requested mapping is identical, except for the BO offset, hence replace 154 * the mapping. 155 * 156 * :: 157 * 158 * 0 a 1 159 * old: |-----------| (bo_offset=n) 160 * 161 * 0 a 1 162 * req: |-----------| (bo_offset=m) 163 * 164 * 0 a 1 165 * new: |-----------| (bo_offset=m) 166 * 167 * 168 * 3) Requested mapping is identical, except for the backing BO, hence replace 169 * the mapping. 170 * 171 * :: 172 * 173 * 0 a 1 174 * old: |-----------| (bo_offset=n) 175 * 176 * 0 b 1 177 * req: |-----------| (bo_offset=n) 178 * 179 * 0 b 1 180 * new: |-----------| (bo_offset=n) 181 * 182 * 183 * 4) Existent mapping is a left aligned subset of the requested one, hence 184 * replace the existent one. 185 * 186 * :: 187 * 188 * 0 a 1 189 * old: |-----| (bo_offset=n) 190 * 191 * 0 a 2 192 * req: |-----------| (bo_offset=n) 193 * 194 * 0 a 2 195 * new: |-----------| (bo_offset=n) 196 * 197 * .. note:: 198 * We expect to see the same result for a request with a different BO 199 * and/or non-contiguous BO offset. 200 * 201 * 202 * 5) Requested mapping's range is a left aligned subset of the existent one, 203 * but backed by a different BO. Hence, map the requested mapping and split 204 * the existent one adjusting its BO offset. 205 * 206 * :: 207 * 208 * 0 a 2 209 * old: |-----------| (bo_offset=n) 210 * 211 * 0 b 1 212 * req: |-----| (bo_offset=n) 213 * 214 * 0 b 1 a' 2 215 * new: |-----|-----| (b.bo_offset=n, a.bo_offset=n+1) 216 * 217 * .. note:: 218 * We expect to see the same result for a request with a different BO 219 * and/or non-contiguous BO offset. 220 * 221 * 222 * 6) Existent mapping is a superset of the requested mapping. Split it up, but 223 * indicate that the backing PTEs could be kept. 224 * 225 * :: 226 * 227 * 0 a 2 228 * old: |-----------| (bo_offset=n) 229 * 230 * 0 a 1 231 * req: |-----| (bo_offset=n) 232 * 233 * 0 a 1 a' 2 234 * new: |-----|-----| (a.bo_offset=n, a'.bo_offset=n+1) 235 * 236 * 237 * 7) Requested mapping's range is a right aligned subset of the existent one, 238 * but backed by a different BO. Hence, map the requested mapping and split 239 * the existent one, without adjusting the BO offset. 240 * 241 * :: 242 * 243 * 0 a 2 244 * old: |-----------| (bo_offset=n) 245 * 246 * 1 b 2 247 * req: |-----| (bo_offset=m) 248 * 249 * 0 a 1 b 2 250 * new: |-----|-----| (a.bo_offset=n,b.bo_offset=m) 251 * 252 * 253 * 8) Existent mapping is a superset of the requested mapping. Split it up, but 254 * indicate that the backing PTEs could be kept. 255 * 256 * :: 257 * 258 * 0 a 2 259 * old: |-----------| (bo_offset=n) 260 * 261 * 1 a 2 262 * req: |-----| (bo_offset=n+1) 263 * 264 * 0 a' 1 a 2 265 * new: |-----|-----| (a'.bo_offset=n, a.bo_offset=n+1) 266 * 267 * 268 * 9) Existent mapping is overlapped at the end by the requested mapping backed 269 * by a different BO. Hence, map the requested mapping and split up the 270 * existent one, without adjusting the BO offset. 271 * 272 * :: 273 * 274 * 0 a 2 275 * old: |-----------| (bo_offset=n) 276 * 277 * 1 b 3 278 * req: |-----------| (bo_offset=m) 279 * 280 * 0 a 1 b 3 281 * new: |-----|-----------| (a.bo_offset=n,b.bo_offset=m) 282 * 283 * 284 * 10) Existent mapping is overlapped by the requested mapping, both having the 285 * same backing BO with a contiguous offset. Indicate the backing PTEs of 286 * the old mapping could be kept. 287 * 288 * :: 289 * 290 * 0 a 2 291 * old: |-----------| (bo_offset=n) 292 * 293 * 1 a 3 294 * req: |-----------| (bo_offset=n+1) 295 * 296 * 0 a' 1 a 3 297 * new: |-----|-----------| (a'.bo_offset=n, a.bo_offset=n+1) 298 * 299 * 300 * 11) Requested mapping's range is a centered subset of the existent one 301 * having a different backing BO. Hence, map the requested mapping and split 302 * up the existent one in two mappings, adjusting the BO offset of the right 303 * one accordingly. 304 * 305 * :: 306 * 307 * 0 a 3 308 * old: |-----------------| (bo_offset=n) 309 * 310 * 1 b 2 311 * req: |-----| (bo_offset=m) 312 * 313 * 0 a 1 b 2 a' 3 314 * new: |-----|-----|-----| (a.bo_offset=n,b.bo_offset=m,a'.bo_offset=n+2) 315 * 316 * 317 * 12) Requested mapping is a contiguous subset of the existent one. Split it 318 * up, but indicate that the backing PTEs could be kept. 319 * 320 * :: 321 * 322 * 0 a 3 323 * old: |-----------------| (bo_offset=n) 324 * 325 * 1 a 2 326 * req: |-----| (bo_offset=n+1) 327 * 328 * 0 a' 1 a 2 a'' 3 329 * old: |-----|-----|-----| (a'.bo_offset=n, a.bo_offset=n+1, a''.bo_offset=n+2) 330 * 331 * 332 * 13) Existent mapping is a right aligned subset of the requested one, hence 333 * replace the existent one. 334 * 335 * :: 336 * 337 * 1 a 2 338 * old: |-----| (bo_offset=n+1) 339 * 340 * 0 a 2 341 * req: |-----------| (bo_offset=n) 342 * 343 * 0 a 2 344 * new: |-----------| (bo_offset=n) 345 * 346 * .. note:: 347 * We expect to see the same result for a request with a different bo 348 * and/or non-contiguous bo_offset. 349 * 350 * 351 * 14) Existent mapping is a centered subset of the requested one, hence 352 * replace the existent one. 353 * 354 * :: 355 * 356 * 1 a 2 357 * old: |-----| (bo_offset=n+1) 358 * 359 * 0 a 3 360 * req: |----------------| (bo_offset=n) 361 * 362 * 0 a 3 363 * new: |----------------| (bo_offset=n) 364 * 365 * .. note:: 366 * We expect to see the same result for a request with a different bo 367 * and/or non-contiguous bo_offset. 368 * 369 * 370 * 15) Existent mappings is overlapped at the beginning by the requested mapping 371 * backed by a different BO. Hence, map the requested mapping and split up 372 * the existent one, adjusting its BO offset accordingly. 373 * 374 * :: 375 * 376 * 1 a 3 377 * old: |-----------| (bo_offset=n) 378 * 379 * 0 b 2 380 * req: |-----------| (bo_offset=m) 381 * 382 * 0 b 2 a' 3 383 * new: |-----------|-----| (b.bo_offset=m,a.bo_offset=n+2) 384 */ 385 386 /** 387 * DOC: Locking 388 * 389 * Generally, the GPU VA manager does not take care of locking itself, it is 390 * the drivers responsibility to take care about locking. Drivers might want to 391 * protect the following operations: inserting, removing and iterating 392 * &drm_gpuva objects as well as generating all kinds of operations, such as 393 * split / merge or prefetch. 394 * 395 * The GPU VA manager also does not take care of the locking of the backing 396 * &drm_gem_object buffers GPU VA lists by itself; drivers are responsible to 397 * enforce mutual exclusion using either the GEMs dma_resv lock or alternatively 398 * a driver specific external lock. For the latter see also 399 * drm_gem_gpuva_set_lock(). 400 * 401 * However, the GPU VA manager contains lockdep checks to ensure callers of its 402 * API hold the corresponding lock whenever the &drm_gem_objects GPU VA list is 403 * accessed by functions such as drm_gpuva_link() or drm_gpuva_unlink(). 404 */ 405 406 /** 407 * DOC: Examples 408 * 409 * This section gives two examples on how to let the DRM GPUVA Manager generate 410 * &drm_gpuva_op in order to satisfy a given map or unmap request and how to 411 * make use of them. 412 * 413 * The below code is strictly limited to illustrate the generic usage pattern. 414 * To maintain simplicitly, it doesn't make use of any abstractions for common 415 * code, different (asyncronous) stages with fence signalling critical paths, 416 * any other helpers or error handling in terms of freeing memory and dropping 417 * previously taken locks. 418 * 419 * 1) Obtain a list of &drm_gpuva_op to create a new mapping:: 420 * 421 * // Allocates a new &drm_gpuva. 422 * struct drm_gpuva * driver_gpuva_alloc(void); 423 * 424 * // Typically drivers would embedd the &drm_gpuva_manager and &drm_gpuva 425 * // structure in individual driver structures and lock the dma-resv with 426 * // drm_exec or similar helpers. 427 * int driver_mapping_create(struct drm_gpuva_manager *mgr, 428 * u64 addr, u64 range, 429 * struct drm_gem_object *obj, u64 offset) 430 * { 431 * struct drm_gpuva_ops *ops; 432 * struct drm_gpuva_op *op 433 * 434 * driver_lock_va_space(); 435 * ops = drm_gpuva_sm_map_ops_create(mgr, addr, range, 436 * obj, offset); 437 * if (IS_ERR(ops)) 438 * return PTR_ERR(ops); 439 * 440 * drm_gpuva_for_each_op(op, ops) { 441 * struct drm_gpuva *va; 442 * 443 * switch (op->op) { 444 * case DRM_GPUVA_OP_MAP: 445 * va = driver_gpuva_alloc(); 446 * if (!va) 447 * ; // unwind previous VA space updates, 448 * // free memory and unlock 449 * 450 * driver_vm_map(); 451 * drm_gpuva_map(mgr, va, &op->map); 452 * drm_gpuva_link(va); 453 * 454 * break; 455 * case DRM_GPUVA_OP_REMAP: { 456 * struct drm_gpuva *prev = NULL, *next = NULL; 457 * 458 * va = op->remap.unmap->va; 459 * 460 * if (op->remap.prev) { 461 * prev = driver_gpuva_alloc(); 462 * if (!prev) 463 * ; // unwind previous VA space 464 * // updates, free memory and 465 * // unlock 466 * } 467 * 468 * if (op->remap.next) { 469 * next = driver_gpuva_alloc(); 470 * if (!next) 471 * ; // unwind previous VA space 472 * // updates, free memory and 473 * // unlock 474 * } 475 * 476 * driver_vm_remap(); 477 * drm_gpuva_remap(prev, next, &op->remap); 478 * 479 * drm_gpuva_unlink(va); 480 * if (prev) 481 * drm_gpuva_link(prev); 482 * if (next) 483 * drm_gpuva_link(next); 484 * 485 * break; 486 * } 487 * case DRM_GPUVA_OP_UNMAP: 488 * va = op->unmap->va; 489 * 490 * driver_vm_unmap(); 491 * drm_gpuva_unlink(va); 492 * drm_gpuva_unmap(&op->unmap); 493 * 494 * break; 495 * default: 496 * break; 497 * } 498 * } 499 * driver_unlock_va_space(); 500 * 501 * return 0; 502 * } 503 * 504 * 2) Receive a callback for each &drm_gpuva_op to create a new mapping:: 505 * 506 * struct driver_context { 507 * struct drm_gpuva_manager *mgr; 508 * struct drm_gpuva *new_va; 509 * struct drm_gpuva *prev_va; 510 * struct drm_gpuva *next_va; 511 * }; 512 * 513 * // ops to pass to drm_gpuva_manager_init() 514 * static const struct drm_gpuva_fn_ops driver_gpuva_ops = { 515 * .sm_step_map = driver_gpuva_map, 516 * .sm_step_remap = driver_gpuva_remap, 517 * .sm_step_unmap = driver_gpuva_unmap, 518 * }; 519 * 520 * // Typically drivers would embedd the &drm_gpuva_manager and &drm_gpuva 521 * // structure in individual driver structures and lock the dma-resv with 522 * // drm_exec or similar helpers. 523 * int driver_mapping_create(struct drm_gpuva_manager *mgr, 524 * u64 addr, u64 range, 525 * struct drm_gem_object *obj, u64 offset) 526 * { 527 * struct driver_context ctx; 528 * struct drm_gpuva_ops *ops; 529 * struct drm_gpuva_op *op; 530 * int ret = 0; 531 * 532 * ctx.mgr = mgr; 533 * 534 * ctx.new_va = kzalloc(sizeof(*ctx.new_va), GFP_KERNEL); 535 * ctx.prev_va = kzalloc(sizeof(*ctx.prev_va), GFP_KERNEL); 536 * ctx.next_va = kzalloc(sizeof(*ctx.next_va), GFP_KERNEL); 537 * if (!ctx.new_va || !ctx.prev_va || !ctx.next_va) { 538 * ret = -ENOMEM; 539 * goto out; 540 * } 541 * 542 * driver_lock_va_space(); 543 * ret = drm_gpuva_sm_map(mgr, &ctx, addr, range, obj, offset); 544 * driver_unlock_va_space(); 545 * 546 * out: 547 * kfree(ctx.new_va); 548 * kfree(ctx.prev_va); 549 * kfree(ctx.next_va); 550 * return ret; 551 * } 552 * 553 * int driver_gpuva_map(struct drm_gpuva_op *op, void *__ctx) 554 * { 555 * struct driver_context *ctx = __ctx; 556 * 557 * drm_gpuva_map(ctx->mgr, ctx->new_va, &op->map); 558 * 559 * drm_gpuva_link(ctx->new_va); 560 * 561 * // prevent the new GPUVA from being freed in 562 * // driver_mapping_create() 563 * ctx->new_va = NULL; 564 * 565 * return 0; 566 * } 567 * 568 * int driver_gpuva_remap(struct drm_gpuva_op *op, void *__ctx) 569 * { 570 * struct driver_context *ctx = __ctx; 571 * 572 * drm_gpuva_remap(ctx->prev_va, ctx->next_va, &op->remap); 573 * 574 * drm_gpuva_unlink(op->remap.unmap->va); 575 * kfree(op->remap.unmap->va); 576 * 577 * if (op->remap.prev) { 578 * drm_gpuva_link(ctx->prev_va); 579 * ctx->prev_va = NULL; 580 * } 581 * 582 * if (op->remap.next) { 583 * drm_gpuva_link(ctx->next_va); 584 * ctx->next_va = NULL; 585 * } 586 * 587 * return 0; 588 * } 589 * 590 * int driver_gpuva_unmap(struct drm_gpuva_op *op, void *__ctx) 591 * { 592 * drm_gpuva_unlink(op->unmap.va); 593 * drm_gpuva_unmap(&op->unmap); 594 * kfree(op->unmap.va); 595 * 596 * return 0; 597 * } 598 */ 599 600 #define to_drm_gpuva(__node) container_of((__node), struct drm_gpuva, rb.node) 601 602 #define GPUVA_START(node) ((node)->va.addr) 603 #define GPUVA_LAST(node) ((node)->va.addr + (node)->va.range - 1) 604 605 /* We do not actually use drm_gpuva_it_next(), tell the compiler to not complain 606 * about this. 607 */ 608 INTERVAL_TREE_DEFINE(struct drm_gpuva, rb.node, u64, rb.__subtree_last, 609 GPUVA_START, GPUVA_LAST, static __maybe_unused, 610 drm_gpuva_it) 611 612 static int __drm_gpuva_insert(struct drm_gpuva_manager *mgr, 613 struct drm_gpuva *va); 614 static void __drm_gpuva_remove(struct drm_gpuva *va); 615 616 static bool 617 drm_gpuva_check_overflow(u64 addr, u64 range) 618 { 619 u64 end; 620 621 return WARN(check_add_overflow(addr, range, &end), 622 "GPUVA address limited to %zu bytes.\n", sizeof(end)); 623 } 624 625 static bool 626 drm_gpuva_in_mm_range(struct drm_gpuva_manager *mgr, u64 addr, u64 range) 627 { 628 u64 end = addr + range; 629 u64 mm_start = mgr->mm_start; 630 u64 mm_end = mm_start + mgr->mm_range; 631 632 return addr >= mm_start && end <= mm_end; 633 } 634 635 static bool 636 drm_gpuva_in_kernel_node(struct drm_gpuva_manager *mgr, u64 addr, u64 range) 637 { 638 u64 end = addr + range; 639 u64 kstart = mgr->kernel_alloc_node.va.addr; 640 u64 krange = mgr->kernel_alloc_node.va.range; 641 u64 kend = kstart + krange; 642 643 return krange && addr < kend && kstart < end; 644 } 645 646 static bool 647 drm_gpuva_range_valid(struct drm_gpuva_manager *mgr, 648 u64 addr, u64 range) 649 { 650 return !drm_gpuva_check_overflow(addr, range) && 651 drm_gpuva_in_mm_range(mgr, addr, range) && 652 !drm_gpuva_in_kernel_node(mgr, addr, range); 653 } 654 655 /** 656 * drm_gpuva_manager_init() - initialize a &drm_gpuva_manager 657 * @mgr: pointer to the &drm_gpuva_manager to initialize 658 * @name: the name of the GPU VA space 659 * @start_offset: the start offset of the GPU VA space 660 * @range: the size of the GPU VA space 661 * @reserve_offset: the start of the kernel reserved GPU VA area 662 * @reserve_range: the size of the kernel reserved GPU VA area 663 * @ops: &drm_gpuva_fn_ops called on &drm_gpuva_sm_map / &drm_gpuva_sm_unmap 664 * 665 * The &drm_gpuva_manager must be initialized with this function before use. 666 * 667 * Note that @mgr must be cleared to 0 before calling this function. The given 668 * &name is expected to be managed by the surrounding driver structures. 669 */ 670 void 671 drm_gpuva_manager_init(struct drm_gpuva_manager *mgr, 672 const char *name, 673 u64 start_offset, u64 range, 674 u64 reserve_offset, u64 reserve_range, 675 const struct drm_gpuva_fn_ops *ops) 676 { 677 mgr->rb.tree = RB_ROOT_CACHED; 678 INIT_LIST_HEAD(&mgr->rb.list); 679 680 drm_gpuva_check_overflow(start_offset, range); 681 mgr->mm_start = start_offset; 682 mgr->mm_range = range; 683 684 mgr->name = name ? name : "unknown"; 685 mgr->ops = ops; 686 687 memset(&mgr->kernel_alloc_node, 0, sizeof(struct drm_gpuva)); 688 689 if (reserve_range) { 690 mgr->kernel_alloc_node.va.addr = reserve_offset; 691 mgr->kernel_alloc_node.va.range = reserve_range; 692 693 if (likely(!drm_gpuva_check_overflow(reserve_offset, 694 reserve_range))) 695 __drm_gpuva_insert(mgr, &mgr->kernel_alloc_node); 696 } 697 } 698 EXPORT_SYMBOL_GPL(drm_gpuva_manager_init); 699 700 /** 701 * drm_gpuva_manager_destroy() - cleanup a &drm_gpuva_manager 702 * @mgr: pointer to the &drm_gpuva_manager to clean up 703 * 704 * Note that it is a bug to call this function on a manager that still 705 * holds GPU VA mappings. 706 */ 707 void 708 drm_gpuva_manager_destroy(struct drm_gpuva_manager *mgr) 709 { 710 mgr->name = NULL; 711 712 if (mgr->kernel_alloc_node.va.range) 713 __drm_gpuva_remove(&mgr->kernel_alloc_node); 714 715 WARN(!RB_EMPTY_ROOT(&mgr->rb.tree.rb_root), 716 "GPUVA tree is not empty, potentially leaking memory."); 717 } 718 EXPORT_SYMBOL_GPL(drm_gpuva_manager_destroy); 719 720 static int 721 __drm_gpuva_insert(struct drm_gpuva_manager *mgr, 722 struct drm_gpuva *va) 723 { 724 struct rb_node *node; 725 struct list_head *head; 726 727 if (drm_gpuva_it_iter_first(&mgr->rb.tree, 728 GPUVA_START(va), 729 GPUVA_LAST(va))) 730 return -EEXIST; 731 732 va->mgr = mgr; 733 734 drm_gpuva_it_insert(va, &mgr->rb.tree); 735 736 node = rb_prev(&va->rb.node); 737 if (node) 738 head = &(to_drm_gpuva(node))->rb.entry; 739 else 740 head = &mgr->rb.list; 741 742 list_add(&va->rb.entry, head); 743 744 return 0; 745 } 746 747 /** 748 * drm_gpuva_insert() - insert a &drm_gpuva 749 * @mgr: the &drm_gpuva_manager to insert the &drm_gpuva in 750 * @va: the &drm_gpuva to insert 751 * 752 * Insert a &drm_gpuva with a given address and range into a 753 * &drm_gpuva_manager. 754 * 755 * It is safe to use this function using the safe versions of iterating the GPU 756 * VA space, such as drm_gpuva_for_each_va_safe() and 757 * drm_gpuva_for_each_va_range_safe(). 758 * 759 * Returns: 0 on success, negative error code on failure. 760 */ 761 int 762 drm_gpuva_insert(struct drm_gpuva_manager *mgr, 763 struct drm_gpuva *va) 764 { 765 u64 addr = va->va.addr; 766 u64 range = va->va.range; 767 768 if (unlikely(!drm_gpuva_range_valid(mgr, addr, range))) 769 return -EINVAL; 770 771 return __drm_gpuva_insert(mgr, va); 772 } 773 EXPORT_SYMBOL_GPL(drm_gpuva_insert); 774 775 static void 776 __drm_gpuva_remove(struct drm_gpuva *va) 777 { 778 drm_gpuva_it_remove(va, &va->mgr->rb.tree); 779 list_del_init(&va->rb.entry); 780 } 781 782 /** 783 * drm_gpuva_remove() - remove a &drm_gpuva 784 * @va: the &drm_gpuva to remove 785 * 786 * This removes the given &va from the underlaying tree. 787 * 788 * It is safe to use this function using the safe versions of iterating the GPU 789 * VA space, such as drm_gpuva_for_each_va_safe() and 790 * drm_gpuva_for_each_va_range_safe(). 791 */ 792 void 793 drm_gpuva_remove(struct drm_gpuva *va) 794 { 795 struct drm_gpuva_manager *mgr = va->mgr; 796 797 if (unlikely(va == &mgr->kernel_alloc_node)) { 798 WARN(1, "Can't destroy kernel reserved node.\n"); 799 return; 800 } 801 802 __drm_gpuva_remove(va); 803 } 804 EXPORT_SYMBOL_GPL(drm_gpuva_remove); 805 806 /** 807 * drm_gpuva_link() - link a &drm_gpuva 808 * @va: the &drm_gpuva to link 809 * 810 * This adds the given &va to the GPU VA list of the &drm_gem_object it is 811 * associated with. 812 * 813 * This function expects the caller to protect the GEM's GPUVA list against 814 * concurrent access using the GEMs dma_resv lock. 815 */ 816 void 817 drm_gpuva_link(struct drm_gpuva *va) 818 { 819 struct drm_gem_object *obj = va->gem.obj; 820 821 if (unlikely(!obj)) 822 return; 823 824 drm_gem_gpuva_assert_lock_held(obj); 825 826 list_add_tail(&va->gem.entry, &obj->gpuva.list); 827 } 828 EXPORT_SYMBOL_GPL(drm_gpuva_link); 829 830 /** 831 * drm_gpuva_unlink() - unlink a &drm_gpuva 832 * @va: the &drm_gpuva to unlink 833 * 834 * This removes the given &va from the GPU VA list of the &drm_gem_object it is 835 * associated with. 836 * 837 * This function expects the caller to protect the GEM's GPUVA list against 838 * concurrent access using the GEMs dma_resv lock. 839 */ 840 void 841 drm_gpuva_unlink(struct drm_gpuva *va) 842 { 843 struct drm_gem_object *obj = va->gem.obj; 844 845 if (unlikely(!obj)) 846 return; 847 848 drm_gem_gpuva_assert_lock_held(obj); 849 850 list_del_init(&va->gem.entry); 851 } 852 EXPORT_SYMBOL_GPL(drm_gpuva_unlink); 853 854 /** 855 * drm_gpuva_find_first() - find the first &drm_gpuva in the given range 856 * @mgr: the &drm_gpuva_manager to search in 857 * @addr: the &drm_gpuvas address 858 * @range: the &drm_gpuvas range 859 * 860 * Returns: the first &drm_gpuva within the given range 861 */ 862 struct drm_gpuva * 863 drm_gpuva_find_first(struct drm_gpuva_manager *mgr, 864 u64 addr, u64 range) 865 { 866 u64 last = addr + range - 1; 867 868 return drm_gpuva_it_iter_first(&mgr->rb.tree, addr, last); 869 } 870 EXPORT_SYMBOL_GPL(drm_gpuva_find_first); 871 872 /** 873 * drm_gpuva_find() - find a &drm_gpuva 874 * @mgr: the &drm_gpuva_manager to search in 875 * @addr: the &drm_gpuvas address 876 * @range: the &drm_gpuvas range 877 * 878 * Returns: the &drm_gpuva at a given &addr and with a given &range 879 */ 880 struct drm_gpuva * 881 drm_gpuva_find(struct drm_gpuva_manager *mgr, 882 u64 addr, u64 range) 883 { 884 struct drm_gpuva *va; 885 886 va = drm_gpuva_find_first(mgr, addr, range); 887 if (!va) 888 goto out; 889 890 if (va->va.addr != addr || 891 va->va.range != range) 892 goto out; 893 894 return va; 895 896 out: 897 return NULL; 898 } 899 EXPORT_SYMBOL_GPL(drm_gpuva_find); 900 901 /** 902 * drm_gpuva_find_prev() - find the &drm_gpuva before the given address 903 * @mgr: the &drm_gpuva_manager to search in 904 * @start: the given GPU VA's start address 905 * 906 * Find the adjacent &drm_gpuva before the GPU VA with given &start address. 907 * 908 * Note that if there is any free space between the GPU VA mappings no mapping 909 * is returned. 910 * 911 * Returns: a pointer to the found &drm_gpuva or NULL if none was found 912 */ 913 struct drm_gpuva * 914 drm_gpuva_find_prev(struct drm_gpuva_manager *mgr, u64 start) 915 { 916 if (!drm_gpuva_range_valid(mgr, start - 1, 1)) 917 return NULL; 918 919 return drm_gpuva_it_iter_first(&mgr->rb.tree, start - 1, start); 920 } 921 EXPORT_SYMBOL_GPL(drm_gpuva_find_prev); 922 923 /** 924 * drm_gpuva_find_next() - find the &drm_gpuva after the given address 925 * @mgr: the &drm_gpuva_manager to search in 926 * @end: the given GPU VA's end address 927 * 928 * Find the adjacent &drm_gpuva after the GPU VA with given &end address. 929 * 930 * Note that if there is any free space between the GPU VA mappings no mapping 931 * is returned. 932 * 933 * Returns: a pointer to the found &drm_gpuva or NULL if none was found 934 */ 935 struct drm_gpuva * 936 drm_gpuva_find_next(struct drm_gpuva_manager *mgr, u64 end) 937 { 938 if (!drm_gpuva_range_valid(mgr, end, 1)) 939 return NULL; 940 941 return drm_gpuva_it_iter_first(&mgr->rb.tree, end, end + 1); 942 } 943 EXPORT_SYMBOL_GPL(drm_gpuva_find_next); 944 945 /** 946 * drm_gpuva_interval_empty() - indicate whether a given interval of the VA space 947 * is empty 948 * @mgr: the &drm_gpuva_manager to check the range for 949 * @addr: the start address of the range 950 * @range: the range of the interval 951 * 952 * Returns: true if the interval is empty, false otherwise 953 */ 954 bool 955 drm_gpuva_interval_empty(struct drm_gpuva_manager *mgr, u64 addr, u64 range) 956 { 957 return !drm_gpuva_find_first(mgr, addr, range); 958 } 959 EXPORT_SYMBOL_GPL(drm_gpuva_interval_empty); 960 961 /** 962 * drm_gpuva_map() - helper to insert a &drm_gpuva according to a 963 * &drm_gpuva_op_map 964 * @mgr: the &drm_gpuva_manager 965 * @va: the &drm_gpuva to insert 966 * @op: the &drm_gpuva_op_map to initialize @va with 967 * 968 * Initializes the @va from the @op and inserts it into the given @mgr. 969 */ 970 void 971 drm_gpuva_map(struct drm_gpuva_manager *mgr, 972 struct drm_gpuva *va, 973 struct drm_gpuva_op_map *op) 974 { 975 drm_gpuva_init_from_op(va, op); 976 drm_gpuva_insert(mgr, va); 977 } 978 EXPORT_SYMBOL_GPL(drm_gpuva_map); 979 980 /** 981 * drm_gpuva_remap() - helper to remap a &drm_gpuva according to a 982 * &drm_gpuva_op_remap 983 * @prev: the &drm_gpuva to remap when keeping the start of a mapping 984 * @next: the &drm_gpuva to remap when keeping the end of a mapping 985 * @op: the &drm_gpuva_op_remap to initialize @prev and @next with 986 * 987 * Removes the currently mapped &drm_gpuva and remaps it using @prev and/or 988 * @next. 989 */ 990 void 991 drm_gpuva_remap(struct drm_gpuva *prev, 992 struct drm_gpuva *next, 993 struct drm_gpuva_op_remap *op) 994 { 995 struct drm_gpuva *curr = op->unmap->va; 996 struct drm_gpuva_manager *mgr = curr->mgr; 997 998 drm_gpuva_remove(curr); 999 1000 if (op->prev) { 1001 drm_gpuva_init_from_op(prev, op->prev); 1002 drm_gpuva_insert(mgr, prev); 1003 } 1004 1005 if (op->next) { 1006 drm_gpuva_init_from_op(next, op->next); 1007 drm_gpuva_insert(mgr, next); 1008 } 1009 } 1010 EXPORT_SYMBOL_GPL(drm_gpuva_remap); 1011 1012 /** 1013 * drm_gpuva_unmap() - helper to remove a &drm_gpuva according to a 1014 * &drm_gpuva_op_unmap 1015 * @op: the &drm_gpuva_op_unmap specifying the &drm_gpuva to remove 1016 * 1017 * Removes the &drm_gpuva associated with the &drm_gpuva_op_unmap. 1018 */ 1019 void 1020 drm_gpuva_unmap(struct drm_gpuva_op_unmap *op) 1021 { 1022 drm_gpuva_remove(op->va); 1023 } 1024 EXPORT_SYMBOL_GPL(drm_gpuva_unmap); 1025 1026 static int 1027 op_map_cb(const struct drm_gpuva_fn_ops *fn, void *priv, 1028 u64 addr, u64 range, 1029 struct drm_gem_object *obj, u64 offset) 1030 { 1031 struct drm_gpuva_op op = {}; 1032 1033 op.op = DRM_GPUVA_OP_MAP; 1034 op.map.va.addr = addr; 1035 op.map.va.range = range; 1036 op.map.gem.obj = obj; 1037 op.map.gem.offset = offset; 1038 1039 return fn->sm_step_map(&op, priv); 1040 } 1041 1042 static int 1043 op_remap_cb(const struct drm_gpuva_fn_ops *fn, void *priv, 1044 struct drm_gpuva_op_map *prev, 1045 struct drm_gpuva_op_map *next, 1046 struct drm_gpuva_op_unmap *unmap) 1047 { 1048 struct drm_gpuva_op op = {}; 1049 struct drm_gpuva_op_remap *r; 1050 1051 op.op = DRM_GPUVA_OP_REMAP; 1052 r = &op.remap; 1053 r->prev = prev; 1054 r->next = next; 1055 r->unmap = unmap; 1056 1057 return fn->sm_step_remap(&op, priv); 1058 } 1059 1060 static int 1061 op_unmap_cb(const struct drm_gpuva_fn_ops *fn, void *priv, 1062 struct drm_gpuva *va, bool merge) 1063 { 1064 struct drm_gpuva_op op = {}; 1065 1066 op.op = DRM_GPUVA_OP_UNMAP; 1067 op.unmap.va = va; 1068 op.unmap.keep = merge; 1069 1070 return fn->sm_step_unmap(&op, priv); 1071 } 1072 1073 static int 1074 __drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, 1075 const struct drm_gpuva_fn_ops *ops, void *priv, 1076 u64 req_addr, u64 req_range, 1077 struct drm_gem_object *req_obj, u64 req_offset) 1078 { 1079 struct drm_gpuva *va, *next, *prev = NULL; 1080 u64 req_end = req_addr + req_range; 1081 int ret; 1082 1083 if (unlikely(!drm_gpuva_range_valid(mgr, req_addr, req_range))) 1084 return -EINVAL; 1085 1086 drm_gpuva_for_each_va_range_safe(va, next, mgr, req_addr, req_end) { 1087 struct drm_gem_object *obj = va->gem.obj; 1088 u64 offset = va->gem.offset; 1089 u64 addr = va->va.addr; 1090 u64 range = va->va.range; 1091 u64 end = addr + range; 1092 bool merge = !!va->gem.obj; 1093 1094 if (addr == req_addr) { 1095 merge &= obj == req_obj && 1096 offset == req_offset; 1097 1098 if (end == req_end) { 1099 ret = op_unmap_cb(ops, priv, va, merge); 1100 if (ret) 1101 return ret; 1102 break; 1103 } 1104 1105 if (end < req_end) { 1106 ret = op_unmap_cb(ops, priv, va, merge); 1107 if (ret) 1108 return ret; 1109 goto next; 1110 } 1111 1112 if (end > req_end) { 1113 struct drm_gpuva_op_map n = { 1114 .va.addr = req_end, 1115 .va.range = range - req_range, 1116 .gem.obj = obj, 1117 .gem.offset = offset + req_range, 1118 }; 1119 struct drm_gpuva_op_unmap u = { 1120 .va = va, 1121 .keep = merge, 1122 }; 1123 1124 ret = op_remap_cb(ops, priv, NULL, &n, &u); 1125 if (ret) 1126 return ret; 1127 break; 1128 } 1129 } else if (addr < req_addr) { 1130 u64 ls_range = req_addr - addr; 1131 struct drm_gpuva_op_map p = { 1132 .va.addr = addr, 1133 .va.range = ls_range, 1134 .gem.obj = obj, 1135 .gem.offset = offset, 1136 }; 1137 struct drm_gpuva_op_unmap u = { .va = va }; 1138 1139 merge &= obj == req_obj && 1140 offset + ls_range == req_offset; 1141 u.keep = merge; 1142 1143 if (end == req_end) { 1144 ret = op_remap_cb(ops, priv, &p, NULL, &u); 1145 if (ret) 1146 return ret; 1147 break; 1148 } 1149 1150 if (end < req_end) { 1151 ret = op_remap_cb(ops, priv, &p, NULL, &u); 1152 if (ret) 1153 return ret; 1154 goto next; 1155 } 1156 1157 if (end > req_end) { 1158 struct drm_gpuva_op_map n = { 1159 .va.addr = req_end, 1160 .va.range = end - req_end, 1161 .gem.obj = obj, 1162 .gem.offset = offset + ls_range + 1163 req_range, 1164 }; 1165 1166 ret = op_remap_cb(ops, priv, &p, &n, &u); 1167 if (ret) 1168 return ret; 1169 break; 1170 } 1171 } else if (addr > req_addr) { 1172 merge &= obj == req_obj && 1173 offset == req_offset + 1174 (addr - req_addr); 1175 1176 if (end == req_end) { 1177 ret = op_unmap_cb(ops, priv, va, merge); 1178 if (ret) 1179 return ret; 1180 break; 1181 } 1182 1183 if (end < req_end) { 1184 ret = op_unmap_cb(ops, priv, va, merge); 1185 if (ret) 1186 return ret; 1187 goto next; 1188 } 1189 1190 if (end > req_end) { 1191 struct drm_gpuva_op_map n = { 1192 .va.addr = req_end, 1193 .va.range = end - req_end, 1194 .gem.obj = obj, 1195 .gem.offset = offset + req_end - addr, 1196 }; 1197 struct drm_gpuva_op_unmap u = { 1198 .va = va, 1199 .keep = merge, 1200 }; 1201 1202 ret = op_remap_cb(ops, priv, NULL, &n, &u); 1203 if (ret) 1204 return ret; 1205 break; 1206 } 1207 } 1208 next: 1209 prev = va; 1210 } 1211 1212 return op_map_cb(ops, priv, 1213 req_addr, req_range, 1214 req_obj, req_offset); 1215 } 1216 1217 static int 1218 __drm_gpuva_sm_unmap(struct drm_gpuva_manager *mgr, 1219 const struct drm_gpuva_fn_ops *ops, void *priv, 1220 u64 req_addr, u64 req_range) 1221 { 1222 struct drm_gpuva *va, *next; 1223 u64 req_end = req_addr + req_range; 1224 int ret; 1225 1226 if (unlikely(!drm_gpuva_range_valid(mgr, req_addr, req_range))) 1227 return -EINVAL; 1228 1229 drm_gpuva_for_each_va_range_safe(va, next, mgr, req_addr, req_end) { 1230 struct drm_gpuva_op_map prev = {}, next = {}; 1231 bool prev_split = false, next_split = false; 1232 struct drm_gem_object *obj = va->gem.obj; 1233 u64 offset = va->gem.offset; 1234 u64 addr = va->va.addr; 1235 u64 range = va->va.range; 1236 u64 end = addr + range; 1237 1238 if (addr < req_addr) { 1239 prev.va.addr = addr; 1240 prev.va.range = req_addr - addr; 1241 prev.gem.obj = obj; 1242 prev.gem.offset = offset; 1243 1244 prev_split = true; 1245 } 1246 1247 if (end > req_end) { 1248 next.va.addr = req_end; 1249 next.va.range = end - req_end; 1250 next.gem.obj = obj; 1251 next.gem.offset = offset + (req_end - addr); 1252 1253 next_split = true; 1254 } 1255 1256 if (prev_split || next_split) { 1257 struct drm_gpuva_op_unmap unmap = { .va = va }; 1258 1259 ret = op_remap_cb(ops, priv, 1260 prev_split ? &prev : NULL, 1261 next_split ? &next : NULL, 1262 &unmap); 1263 if (ret) 1264 return ret; 1265 } else { 1266 ret = op_unmap_cb(ops, priv, va, false); 1267 if (ret) 1268 return ret; 1269 } 1270 } 1271 1272 return 0; 1273 } 1274 1275 /** 1276 * drm_gpuva_sm_map() - creates the &drm_gpuva_op split/merge steps 1277 * @mgr: the &drm_gpuva_manager representing the GPU VA space 1278 * @req_addr: the start address of the new mapping 1279 * @req_range: the range of the new mapping 1280 * @req_obj: the &drm_gem_object to map 1281 * @req_offset: the offset within the &drm_gem_object 1282 * @priv: pointer to a driver private data structure 1283 * 1284 * This function iterates the given range of the GPU VA space. It utilizes the 1285 * &drm_gpuva_fn_ops to call back into the driver providing the split and merge 1286 * steps. 1287 * 1288 * Drivers may use these callbacks to update the GPU VA space right away within 1289 * the callback. In case the driver decides to copy and store the operations for 1290 * later processing neither this function nor &drm_gpuva_sm_unmap is allowed to 1291 * be called before the &drm_gpuva_manager's view of the GPU VA space was 1292 * updated with the previous set of operations. To update the 1293 * &drm_gpuva_manager's view of the GPU VA space drm_gpuva_insert(), 1294 * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be 1295 * used. 1296 * 1297 * A sequence of callbacks can contain map, unmap and remap operations, but 1298 * the sequence of callbacks might also be empty if no operation is required, 1299 * e.g. if the requested mapping already exists in the exact same way. 1300 * 1301 * There can be an arbitrary amount of unmap operations, a maximum of two remap 1302 * operations and a single map operation. The latter one represents the original 1303 * map operation requested by the caller. 1304 * 1305 * Returns: 0 on success or a negative error code 1306 */ 1307 int 1308 drm_gpuva_sm_map(struct drm_gpuva_manager *mgr, void *priv, 1309 u64 req_addr, u64 req_range, 1310 struct drm_gem_object *req_obj, u64 req_offset) 1311 { 1312 const struct drm_gpuva_fn_ops *ops = mgr->ops; 1313 1314 if (unlikely(!(ops && ops->sm_step_map && 1315 ops->sm_step_remap && 1316 ops->sm_step_unmap))) 1317 return -EINVAL; 1318 1319 return __drm_gpuva_sm_map(mgr, ops, priv, 1320 req_addr, req_range, 1321 req_obj, req_offset); 1322 } 1323 EXPORT_SYMBOL_GPL(drm_gpuva_sm_map); 1324 1325 /** 1326 * drm_gpuva_sm_unmap() - creates the &drm_gpuva_ops to split on unmap 1327 * @mgr: the &drm_gpuva_manager representing the GPU VA space 1328 * @priv: pointer to a driver private data structure 1329 * @req_addr: the start address of the range to unmap 1330 * @req_range: the range of the mappings to unmap 1331 * 1332 * This function iterates the given range of the GPU VA space. It utilizes the 1333 * &drm_gpuva_fn_ops to call back into the driver providing the operations to 1334 * unmap and, if required, split existent mappings. 1335 * 1336 * Drivers may use these callbacks to update the GPU VA space right away within 1337 * the callback. In case the driver decides to copy and store the operations for 1338 * later processing neither this function nor &drm_gpuva_sm_map is allowed to be 1339 * called before the &drm_gpuva_manager's view of the GPU VA space was updated 1340 * with the previous set of operations. To update the &drm_gpuva_manager's view 1341 * of the GPU VA space drm_gpuva_insert(), drm_gpuva_destroy_locked() and/or 1342 * drm_gpuva_destroy_unlocked() should be used. 1343 * 1344 * A sequence of callbacks can contain unmap and remap operations, depending on 1345 * whether there are actual overlapping mappings to split. 1346 * 1347 * There can be an arbitrary amount of unmap operations and a maximum of two 1348 * remap operations. 1349 * 1350 * Returns: 0 on success or a negative error code 1351 */ 1352 int 1353 drm_gpuva_sm_unmap(struct drm_gpuva_manager *mgr, void *priv, 1354 u64 req_addr, u64 req_range) 1355 { 1356 const struct drm_gpuva_fn_ops *ops = mgr->ops; 1357 1358 if (unlikely(!(ops && ops->sm_step_remap && 1359 ops->sm_step_unmap))) 1360 return -EINVAL; 1361 1362 return __drm_gpuva_sm_unmap(mgr, ops, priv, 1363 req_addr, req_range); 1364 } 1365 EXPORT_SYMBOL_GPL(drm_gpuva_sm_unmap); 1366 1367 static struct drm_gpuva_op * 1368 gpuva_op_alloc(struct drm_gpuva_manager *mgr) 1369 { 1370 const struct drm_gpuva_fn_ops *fn = mgr->ops; 1371 struct drm_gpuva_op *op; 1372 1373 if (fn && fn->op_alloc) 1374 op = fn->op_alloc(); 1375 else 1376 op = kzalloc(sizeof(*op), GFP_KERNEL); 1377 1378 if (unlikely(!op)) 1379 return NULL; 1380 1381 return op; 1382 } 1383 1384 static void 1385 gpuva_op_free(struct drm_gpuva_manager *mgr, 1386 struct drm_gpuva_op *op) 1387 { 1388 const struct drm_gpuva_fn_ops *fn = mgr->ops; 1389 1390 if (fn && fn->op_free) 1391 fn->op_free(op); 1392 else 1393 kfree(op); 1394 } 1395 1396 static int 1397 drm_gpuva_sm_step(struct drm_gpuva_op *__op, 1398 void *priv) 1399 { 1400 struct { 1401 struct drm_gpuva_manager *mgr; 1402 struct drm_gpuva_ops *ops; 1403 } *args = priv; 1404 struct drm_gpuva_manager *mgr = args->mgr; 1405 struct drm_gpuva_ops *ops = args->ops; 1406 struct drm_gpuva_op *op; 1407 1408 op = gpuva_op_alloc(mgr); 1409 if (unlikely(!op)) 1410 goto err; 1411 1412 memcpy(op, __op, sizeof(*op)); 1413 1414 if (op->op == DRM_GPUVA_OP_REMAP) { 1415 struct drm_gpuva_op_remap *__r = &__op->remap; 1416 struct drm_gpuva_op_remap *r = &op->remap; 1417 1418 r->unmap = kmemdup(__r->unmap, sizeof(*r->unmap), 1419 GFP_KERNEL); 1420 if (unlikely(!r->unmap)) 1421 goto err_free_op; 1422 1423 if (__r->prev) { 1424 r->prev = kmemdup(__r->prev, sizeof(*r->prev), 1425 GFP_KERNEL); 1426 if (unlikely(!r->prev)) 1427 goto err_free_unmap; 1428 } 1429 1430 if (__r->next) { 1431 r->next = kmemdup(__r->next, sizeof(*r->next), 1432 GFP_KERNEL); 1433 if (unlikely(!r->next)) 1434 goto err_free_prev; 1435 } 1436 } 1437 1438 list_add_tail(&op->entry, &ops->list); 1439 1440 return 0; 1441 1442 err_free_unmap: 1443 kfree(op->remap.unmap); 1444 err_free_prev: 1445 kfree(op->remap.prev); 1446 err_free_op: 1447 gpuva_op_free(mgr, op); 1448 err: 1449 return -ENOMEM; 1450 } 1451 1452 static const struct drm_gpuva_fn_ops gpuva_list_ops = { 1453 .sm_step_map = drm_gpuva_sm_step, 1454 .sm_step_remap = drm_gpuva_sm_step, 1455 .sm_step_unmap = drm_gpuva_sm_step, 1456 }; 1457 1458 /** 1459 * drm_gpuva_sm_map_ops_create() - creates the &drm_gpuva_ops to split and merge 1460 * @mgr: the &drm_gpuva_manager representing the GPU VA space 1461 * @req_addr: the start address of the new mapping 1462 * @req_range: the range of the new mapping 1463 * @req_obj: the &drm_gem_object to map 1464 * @req_offset: the offset within the &drm_gem_object 1465 * 1466 * This function creates a list of operations to perform splitting and merging 1467 * of existent mapping(s) with the newly requested one. 1468 * 1469 * The list can be iterated with &drm_gpuva_for_each_op and must be processed 1470 * in the given order. It can contain map, unmap and remap operations, but it 1471 * also can be empty if no operation is required, e.g. if the requested mapping 1472 * already exists is the exact same way. 1473 * 1474 * There can be an arbitrary amount of unmap operations, a maximum of two remap 1475 * operations and a single map operation. The latter one represents the original 1476 * map operation requested by the caller. 1477 * 1478 * Note that before calling this function again with another mapping request it 1479 * is necessary to update the &drm_gpuva_manager's view of the GPU VA space. The 1480 * previously obtained operations must be either processed or abandoned. To 1481 * update the &drm_gpuva_manager's view of the GPU VA space drm_gpuva_insert(), 1482 * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be 1483 * used. 1484 * 1485 * After the caller finished processing the returned &drm_gpuva_ops, they must 1486 * be freed with &drm_gpuva_ops_free. 1487 * 1488 * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure 1489 */ 1490 struct drm_gpuva_ops * 1491 drm_gpuva_sm_map_ops_create(struct drm_gpuva_manager *mgr, 1492 u64 req_addr, u64 req_range, 1493 struct drm_gem_object *req_obj, u64 req_offset) 1494 { 1495 struct drm_gpuva_ops *ops; 1496 struct { 1497 struct drm_gpuva_manager *mgr; 1498 struct drm_gpuva_ops *ops; 1499 } args; 1500 int ret; 1501 1502 ops = kzalloc(sizeof(*ops), GFP_KERNEL); 1503 if (unlikely(!ops)) 1504 return ERR_PTR(-ENOMEM); 1505 1506 INIT_LIST_HEAD(&ops->list); 1507 1508 args.mgr = mgr; 1509 args.ops = ops; 1510 1511 ret = __drm_gpuva_sm_map(mgr, &gpuva_list_ops, &args, 1512 req_addr, req_range, 1513 req_obj, req_offset); 1514 if (ret) 1515 goto err_free_ops; 1516 1517 return ops; 1518 1519 err_free_ops: 1520 drm_gpuva_ops_free(mgr, ops); 1521 return ERR_PTR(ret); 1522 } 1523 EXPORT_SYMBOL_GPL(drm_gpuva_sm_map_ops_create); 1524 1525 /** 1526 * drm_gpuva_sm_unmap_ops_create() - creates the &drm_gpuva_ops to split on 1527 * unmap 1528 * @mgr: the &drm_gpuva_manager representing the GPU VA space 1529 * @req_addr: the start address of the range to unmap 1530 * @req_range: the range of the mappings to unmap 1531 * 1532 * This function creates a list of operations to perform unmapping and, if 1533 * required, splitting of the mappings overlapping the unmap range. 1534 * 1535 * The list can be iterated with &drm_gpuva_for_each_op and must be processed 1536 * in the given order. It can contain unmap and remap operations, depending on 1537 * whether there are actual overlapping mappings to split. 1538 * 1539 * There can be an arbitrary amount of unmap operations and a maximum of two 1540 * remap operations. 1541 * 1542 * Note that before calling this function again with another range to unmap it 1543 * is necessary to update the &drm_gpuva_manager's view of the GPU VA space. The 1544 * previously obtained operations must be processed or abandoned. To update the 1545 * &drm_gpuva_manager's view of the GPU VA space drm_gpuva_insert(), 1546 * drm_gpuva_destroy_locked() and/or drm_gpuva_destroy_unlocked() should be 1547 * used. 1548 * 1549 * After the caller finished processing the returned &drm_gpuva_ops, they must 1550 * be freed with &drm_gpuva_ops_free. 1551 * 1552 * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure 1553 */ 1554 struct drm_gpuva_ops * 1555 drm_gpuva_sm_unmap_ops_create(struct drm_gpuva_manager *mgr, 1556 u64 req_addr, u64 req_range) 1557 { 1558 struct drm_gpuva_ops *ops; 1559 struct { 1560 struct drm_gpuva_manager *mgr; 1561 struct drm_gpuva_ops *ops; 1562 } args; 1563 int ret; 1564 1565 ops = kzalloc(sizeof(*ops), GFP_KERNEL); 1566 if (unlikely(!ops)) 1567 return ERR_PTR(-ENOMEM); 1568 1569 INIT_LIST_HEAD(&ops->list); 1570 1571 args.mgr = mgr; 1572 args.ops = ops; 1573 1574 ret = __drm_gpuva_sm_unmap(mgr, &gpuva_list_ops, &args, 1575 req_addr, req_range); 1576 if (ret) 1577 goto err_free_ops; 1578 1579 return ops; 1580 1581 err_free_ops: 1582 drm_gpuva_ops_free(mgr, ops); 1583 return ERR_PTR(ret); 1584 } 1585 EXPORT_SYMBOL_GPL(drm_gpuva_sm_unmap_ops_create); 1586 1587 /** 1588 * drm_gpuva_prefetch_ops_create() - creates the &drm_gpuva_ops to prefetch 1589 * @mgr: the &drm_gpuva_manager representing the GPU VA space 1590 * @addr: the start address of the range to prefetch 1591 * @range: the range of the mappings to prefetch 1592 * 1593 * This function creates a list of operations to perform prefetching. 1594 * 1595 * The list can be iterated with &drm_gpuva_for_each_op and must be processed 1596 * in the given order. It can contain prefetch operations. 1597 * 1598 * There can be an arbitrary amount of prefetch operations. 1599 * 1600 * After the caller finished processing the returned &drm_gpuva_ops, they must 1601 * be freed with &drm_gpuva_ops_free. 1602 * 1603 * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure 1604 */ 1605 struct drm_gpuva_ops * 1606 drm_gpuva_prefetch_ops_create(struct drm_gpuva_manager *mgr, 1607 u64 addr, u64 range) 1608 { 1609 struct drm_gpuva_ops *ops; 1610 struct drm_gpuva_op *op; 1611 struct drm_gpuva *va; 1612 u64 end = addr + range; 1613 int ret; 1614 1615 ops = kzalloc(sizeof(*ops), GFP_KERNEL); 1616 if (!ops) 1617 return ERR_PTR(-ENOMEM); 1618 1619 INIT_LIST_HEAD(&ops->list); 1620 1621 drm_gpuva_for_each_va_range(va, mgr, addr, end) { 1622 op = gpuva_op_alloc(mgr); 1623 if (!op) { 1624 ret = -ENOMEM; 1625 goto err_free_ops; 1626 } 1627 1628 op->op = DRM_GPUVA_OP_PREFETCH; 1629 op->prefetch.va = va; 1630 list_add_tail(&op->entry, &ops->list); 1631 } 1632 1633 return ops; 1634 1635 err_free_ops: 1636 drm_gpuva_ops_free(mgr, ops); 1637 return ERR_PTR(ret); 1638 } 1639 EXPORT_SYMBOL_GPL(drm_gpuva_prefetch_ops_create); 1640 1641 /** 1642 * drm_gpuva_gem_unmap_ops_create() - creates the &drm_gpuva_ops to unmap a GEM 1643 * @mgr: the &drm_gpuva_manager representing the GPU VA space 1644 * @obj: the &drm_gem_object to unmap 1645 * 1646 * This function creates a list of operations to perform unmapping for every 1647 * GPUVA attached to a GEM. 1648 * 1649 * The list can be iterated with &drm_gpuva_for_each_op and consists out of an 1650 * arbitrary amount of unmap operations. 1651 * 1652 * After the caller finished processing the returned &drm_gpuva_ops, they must 1653 * be freed with &drm_gpuva_ops_free. 1654 * 1655 * It is the callers responsibility to protect the GEMs GPUVA list against 1656 * concurrent access using the GEMs dma_resv lock. 1657 * 1658 * Returns: a pointer to the &drm_gpuva_ops on success, an ERR_PTR on failure 1659 */ 1660 struct drm_gpuva_ops * 1661 drm_gpuva_gem_unmap_ops_create(struct drm_gpuva_manager *mgr, 1662 struct drm_gem_object *obj) 1663 { 1664 struct drm_gpuva_ops *ops; 1665 struct drm_gpuva_op *op; 1666 struct drm_gpuva *va; 1667 int ret; 1668 1669 drm_gem_gpuva_assert_lock_held(obj); 1670 1671 ops = kzalloc(sizeof(*ops), GFP_KERNEL); 1672 if (!ops) 1673 return ERR_PTR(-ENOMEM); 1674 1675 INIT_LIST_HEAD(&ops->list); 1676 1677 drm_gem_for_each_gpuva(va, obj) { 1678 op = gpuva_op_alloc(mgr); 1679 if (!op) { 1680 ret = -ENOMEM; 1681 goto err_free_ops; 1682 } 1683 1684 op->op = DRM_GPUVA_OP_UNMAP; 1685 op->unmap.va = va; 1686 list_add_tail(&op->entry, &ops->list); 1687 } 1688 1689 return ops; 1690 1691 err_free_ops: 1692 drm_gpuva_ops_free(mgr, ops); 1693 return ERR_PTR(ret); 1694 } 1695 EXPORT_SYMBOL_GPL(drm_gpuva_gem_unmap_ops_create); 1696 1697 /** 1698 * drm_gpuva_ops_free() - free the given &drm_gpuva_ops 1699 * @mgr: the &drm_gpuva_manager the ops were created for 1700 * @ops: the &drm_gpuva_ops to free 1701 * 1702 * Frees the given &drm_gpuva_ops structure including all the ops associated 1703 * with it. 1704 */ 1705 void 1706 drm_gpuva_ops_free(struct drm_gpuva_manager *mgr, 1707 struct drm_gpuva_ops *ops) 1708 { 1709 struct drm_gpuva_op *op, *next; 1710 1711 drm_gpuva_for_each_op_safe(op, next, ops) { 1712 list_del(&op->entry); 1713 1714 if (op->op == DRM_GPUVA_OP_REMAP) { 1715 kfree(op->remap.prev); 1716 kfree(op->remap.next); 1717 kfree(op->remap.unmap); 1718 } 1719 1720 gpuva_op_free(mgr, op); 1721 } 1722 1723 kfree(ops); 1724 } 1725 EXPORT_SYMBOL_GPL(drm_gpuva_ops_free); 1726