Skip to content

Commit b43e864

Browse files
committed
drm/xe/uapi: Add DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR
Add the DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR flag, which is used to create unpopulated virtual memory areas (VMAs) without memory backing or GPU page tables. These VMAs are referred to as CPU address mirror VMAs. The idea is that upon a page fault or prefetch, the memory backing and GPU page tables will be populated. CPU address mirror VMAs only update GPUVM state; they do not have an internal page table (PT) state, nor do they have GPU mappings. It is expected that CPU address mirror VMAs will be mixed with buffer object (BO) VMAs within a single VM. In other words, system allocations and runtime allocations can be mixed within a single user-mode driver (UMD) program. Expected usage: - Bind the entire virtual address (VA) space upon program load using the DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR flag. - If a buffer object (BO) requires GPU mapping (runtime allocation), allocate a CPU address using mmap(PROT_NONE), bind the BO to the mmapped address using existing bind IOCTLs. If a CPU map of the BO is needed, mmap it again to the same CPU address using mmap(MAP_FIXED) - If a BO no longer requires GPU mapping, munmap it from the CPU address space and them bind the mapping address with the DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR flag. - Any malloc'd or mmapped CPU address accessed by the GPU will be faulted in via the SVM implementation (system allocation). - Upon freeing any mmapped or malloc'd data, the SVM implementation will remove GPU mappings. Only supporting 1 to 1 mapping between user address space and GPU address space at the moment as that is the expected use case. uAPI defines interface for non 1 to 1 but enforces 1 to 1, this restriction can be lifted if use cases arrise for non 1 to 1 mappings. This patch essentially short-circuits the code in the existing VM bind paths to avoid populating page tables when the DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR flag is set. v3: - Call vm_bind_ioctl_ops_fini on -ENODATA - Don't allow DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR on non-faulting VMs - s/DRM_XE_VM_BIND_FLAG_SYSTEM_ALLOCATOR/DRM_XE_VM_BIND_FLAG_CPU_ADDR_MIRROR (Thomas) - Rework commit message for expected usage (Thomas) - Describe state of code after patch in commit message (Thomas) v4: - Fix alignment (Checkpatch) Signed-off-by: Matthew Brost <[email protected]> Reviewed-by: Thomas Hellström <[email protected]> Reviewed-by: Himal Prasad Ghimiray <[email protected]> Link: https://patchwork.freedesktop.org/patch/msgid/[email protected]
1 parent 0a8d6d4 commit b43e864

File tree

5 files changed

+176
-75
lines changed

5 files changed

+176
-75
lines changed

drivers/gpu/drm/xe/xe_pt.c

Lines changed: 61 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1090,6 +1090,11 @@ static int op_add_deps(struct xe_vm *vm, struct xe_vma_op *op,
10901090
{
10911091
int err = 0;
10921092

1093+
/*
1094+
* No need to check for is_cpu_addr_mirror here as vma_add_deps is a
1095+
* NOP if VMA is_cpu_addr_mirror
1096+
*/
1097+
10931098
switch (op->base.op) {
10941099
case DRM_GPUVA_OP_MAP:
10951100
if (!op->map.immediate && xe_vm_in_fault_mode(vm))
@@ -1648,6 +1653,7 @@ static int bind_op_prepare(struct xe_vm *vm, struct xe_tile *tile,
16481653
struct xe_vm_pgtable_update_op *pt_op = &pt_update_ops->ops[current_op];
16491654
int err;
16501655

1656+
xe_tile_assert(tile, !xe_vma_is_cpu_addr_mirror(vma));
16511657
xe_bo_assert_held(xe_vma_bo(vma));
16521658

16531659
vm_dbg(&xe_vma_vm(vma)->xe->drm,
@@ -1715,6 +1721,7 @@ static int unbind_op_prepare(struct xe_tile *tile,
17151721
if (!((vma->tile_present | vma->tile_staged) & BIT(tile->id)))
17161722
return 0;
17171723

1724+
xe_tile_assert(tile, !xe_vma_is_cpu_addr_mirror(vma));
17181725
xe_bo_assert_held(xe_vma_bo(vma));
17191726

17201727
vm_dbg(&xe_vma_vm(vma)->xe->drm,
@@ -1761,15 +1768,21 @@ static int op_prepare(struct xe_vm *vm,
17611768

17621769
switch (op->base.op) {
17631770
case DRM_GPUVA_OP_MAP:
1764-
if (!op->map.immediate && xe_vm_in_fault_mode(vm))
1771+
if ((!op->map.immediate && xe_vm_in_fault_mode(vm)) ||
1772+
op->map.is_cpu_addr_mirror)
17651773
break;
17661774

17671775
err = bind_op_prepare(vm, tile, pt_update_ops, op->map.vma);
17681776
pt_update_ops->wait_vm_kernel = true;
17691777
break;
17701778
case DRM_GPUVA_OP_REMAP:
1771-
err = unbind_op_prepare(tile, pt_update_ops,
1772-
gpuva_to_vma(op->base.remap.unmap->va));
1779+
{
1780+
struct xe_vma *old = gpuva_to_vma(op->base.remap.unmap->va);
1781+
1782+
if (xe_vma_is_cpu_addr_mirror(old))
1783+
break;
1784+
1785+
err = unbind_op_prepare(tile, pt_update_ops, old);
17731786

17741787
if (!err && op->remap.prev) {
17751788
err = bind_op_prepare(vm, tile, pt_update_ops,
@@ -1782,15 +1795,28 @@ static int op_prepare(struct xe_vm *vm,
17821795
pt_update_ops->wait_vm_bookkeep = true;
17831796
}
17841797
break;
1798+
}
17851799
case DRM_GPUVA_OP_UNMAP:
1786-
err = unbind_op_prepare(tile, pt_update_ops,
1787-
gpuva_to_vma(op->base.unmap.va));
1800+
{
1801+
struct xe_vma *vma = gpuva_to_vma(op->base.unmap.va);
1802+
1803+
if (xe_vma_is_cpu_addr_mirror(vma))
1804+
break;
1805+
1806+
err = unbind_op_prepare(tile, pt_update_ops, vma);
17881807
break;
1808+
}
17891809
case DRM_GPUVA_OP_PREFETCH:
1790-
err = bind_op_prepare(vm, tile, pt_update_ops,
1791-
gpuva_to_vma(op->base.prefetch.va));
1810+
{
1811+
struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
1812+
1813+
if (xe_vma_is_cpu_addr_mirror(vma))
1814+
break;
1815+
1816+
err = bind_op_prepare(vm, tile, pt_update_ops, vma);
17921817
pt_update_ops->wait_vm_kernel = true;
17931818
break;
1819+
}
17941820
default:
17951821
drm_warn(&vm->xe->drm, "NOT POSSIBLE");
17961822
}
@@ -1860,6 +1886,8 @@ static void bind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
18601886
struct xe_vma *vma, struct dma_fence *fence,
18611887
struct dma_fence *fence2)
18621888
{
1889+
xe_tile_assert(tile, !xe_vma_is_cpu_addr_mirror(vma));
1890+
18631891
if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) {
18641892
dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
18651893
pt_update_ops->wait_vm_bookkeep ?
@@ -1893,6 +1921,8 @@ static void unbind_op_commit(struct xe_vm *vm, struct xe_tile *tile,
18931921
struct xe_vma *vma, struct dma_fence *fence,
18941922
struct dma_fence *fence2)
18951923
{
1924+
xe_tile_assert(tile, !xe_vma_is_cpu_addr_mirror(vma));
1925+
18961926
if (!xe_vma_has_no_bo(vma) && !xe_vma_bo(vma)->vm) {
18971927
dma_resv_add_fence(xe_vma_bo(vma)->ttm.base.resv, fence,
18981928
pt_update_ops->wait_vm_bookkeep ?
@@ -1927,16 +1957,21 @@ static void op_commit(struct xe_vm *vm,
19271957

19281958
switch (op->base.op) {
19291959
case DRM_GPUVA_OP_MAP:
1930-
if (!op->map.immediate && xe_vm_in_fault_mode(vm))
1960+
if ((!op->map.immediate && xe_vm_in_fault_mode(vm)) ||
1961+
op->map.is_cpu_addr_mirror)
19311962
break;
19321963

19331964
bind_op_commit(vm, tile, pt_update_ops, op->map.vma, fence,
19341965
fence2);
19351966
break;
19361967
case DRM_GPUVA_OP_REMAP:
1937-
unbind_op_commit(vm, tile, pt_update_ops,
1938-
gpuva_to_vma(op->base.remap.unmap->va), fence,
1939-
fence2);
1968+
{
1969+
struct xe_vma *old = gpuva_to_vma(op->base.remap.unmap->va);
1970+
1971+
if (xe_vma_is_cpu_addr_mirror(old))
1972+
break;
1973+
1974+
unbind_op_commit(vm, tile, pt_update_ops, old, fence, fence2);
19401975

19411976
if (op->remap.prev)
19421977
bind_op_commit(vm, tile, pt_update_ops, op->remap.prev,
@@ -1945,14 +1980,25 @@ static void op_commit(struct xe_vm *vm,
19451980
bind_op_commit(vm, tile, pt_update_ops, op->remap.next,
19461981
fence, fence2);
19471982
break;
1983+
}
19481984
case DRM_GPUVA_OP_UNMAP:
1949-
unbind_op_commit(vm, tile, pt_update_ops,
1950-
gpuva_to_vma(op->base.unmap.va), fence, fence2);
1985+
{
1986+
struct xe_vma *vma = gpuva_to_vma(op->base.unmap.va);
1987+
1988+
if (!xe_vma_is_cpu_addr_mirror(vma))
1989+
unbind_op_commit(vm, tile, pt_update_ops, vma, fence,
1990+
fence2);
19511991
break;
1992+
}
19521993
case DRM_GPUVA_OP_PREFETCH:
1953-
bind_op_commit(vm, tile, pt_update_ops,
1954-
gpuva_to_vma(op->base.prefetch.va), fence, fence2);
1994+
{
1995+
struct xe_vma *vma = gpuva_to_vma(op->base.prefetch.va);
1996+
1997+
if (!xe_vma_is_cpu_addr_mirror(vma))
1998+
bind_op_commit(vm, tile, pt_update_ops, vma, fence,
1999+
fence2);
19552000
break;
2001+
}
19562002
default:
19572003
drm_warn(&vm->xe->drm, "NOT POSSIBLE");
19582004
}

0 commit comments

Comments
 (0)