• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2023 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * 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 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 #include "iris_kmd_backend.h"
24 
25 #include <sys/mman.h>
26 
27 #include "common/intel_gem.h"
28 #include "dev/intel_debug.h"
29 #include "iris/iris_bufmgr.h"
30 #include "iris/iris_batch.h"
31 #include "iris/iris_context.h"
32 
33 #include "drm-uapi/xe_drm.h"
34 
35 #define FILE_DEBUG_FLAG DEBUG_BUFMGR
36 
37 static uint32_t
xe_gem_create(struct iris_bufmgr * bufmgr,const struct intel_memory_class_instance ** regions,uint16_t regions_count,uint64_t size,enum iris_heap heap_flags,unsigned alloc_flags)38 xe_gem_create(struct iris_bufmgr *bufmgr,
39               const struct intel_memory_class_instance **regions,
40               uint16_t regions_count, uint64_t size,
41               enum iris_heap heap_flags, unsigned alloc_flags)
42 {
43    /* Xe still don't have support for protected content */
44    if (alloc_flags & BO_ALLOC_PROTECTED)
45       return -EINVAL;
46 
47    uint32_t vm_id = iris_bufmgr_get_global_vm_id(bufmgr);
48    vm_id = alloc_flags & BO_ALLOC_SHARED ? 0 : vm_id;
49 
50    uint32_t flags = 0;
51    /* TODO: we might need to consider scanout for shared buffers too as we
52     * do not know what the process this is shared with will do with it
53     */
54    if (alloc_flags & BO_ALLOC_SCANOUT)
55       flags |= DRM_XE_GEM_CREATE_FLAG_SCANOUT;
56    if (!intel_vram_all_mappable(iris_bufmgr_get_device_info(bufmgr)) &&
57        heap_flags == IRIS_HEAP_DEVICE_LOCAL_PREFERRED)
58       flags |= DRM_XE_GEM_CREATE_FLAG_NEEDS_VISIBLE_VRAM;
59 
60    struct drm_xe_gem_create gem_create = {
61      .vm_id = vm_id,
62      .size = align64(size, iris_bufmgr_get_device_info(bufmgr)->mem_alignment),
63      .flags = flags,
64    };
65    for (uint16_t i = 0; i < regions_count; i++)
66       gem_create.placement |= BITFIELD_BIT(regions[i]->instance);
67 
68    const struct intel_device_info *devinfo = iris_bufmgr_get_device_info(bufmgr);
69    const struct intel_device_info_pat_entry *pat_entry;
70    pat_entry = iris_heap_to_pat_entry(devinfo, heap_flags);
71    switch (pat_entry->mmap) {
72    case INTEL_DEVICE_INFO_MMAP_MODE_WC:
73       gem_create.cpu_caching = DRM_XE_GEM_CPU_CACHING_WC;
74       break;
75    case INTEL_DEVICE_INFO_MMAP_MODE_WB:
76       gem_create.cpu_caching = DRM_XE_GEM_CPU_CACHING_WB;
77       break;
78    default:
79       unreachable("missing");
80       gem_create.cpu_caching = DRM_XE_GEM_CPU_CACHING_WC;
81    }
82 
83    if (intel_ioctl(iris_bufmgr_get_fd(bufmgr), DRM_IOCTL_XE_GEM_CREATE,
84                    &gem_create))
85       return 0;
86 
87    return gem_create.handle;
88 }
89 
90 static void *
xe_gem_mmap(struct iris_bufmgr * bufmgr,struct iris_bo * bo)91 xe_gem_mmap(struct iris_bufmgr *bufmgr, struct iris_bo *bo)
92 {
93    struct drm_xe_gem_mmap_offset args = {
94       .handle = bo->gem_handle,
95    };
96    if (intel_ioctl(iris_bufmgr_get_fd(bufmgr), DRM_IOCTL_XE_GEM_MMAP_OFFSET, &args))
97       return NULL;
98 
99    void *map = mmap(NULL, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED,
100                     iris_bufmgr_get_fd(bufmgr), args.offset);
101    return map != MAP_FAILED ? map : NULL;
102 }
103 
104 static inline int
xe_gem_vm_bind_op(struct iris_bo * bo,uint32_t op)105 xe_gem_vm_bind_op(struct iris_bo *bo, uint32_t op)
106 {
107    struct iris_bufmgr *bufmgr = bo->bufmgr;
108    struct intel_bind_timeline *bind_timeline = iris_bufmgr_get_bind_timeline(bufmgr);
109    const struct intel_device_info *devinfo = iris_bufmgr_get_device_info(bufmgr);
110    uint32_t handle = op == DRM_XE_VM_BIND_OP_UNMAP ? 0 : bo->gem_handle;
111    struct drm_xe_sync xe_sync = {
112       .handle = intel_bind_timeline_get_syncobj(bind_timeline),
113       .type = DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ,
114       .flags = DRM_XE_SYNC_FLAG_SIGNAL,
115    };
116    uint64_t range, obj_offset = 0;
117    uint32_t flags = 0;
118    int ret, fd;
119 
120    fd = iris_bufmgr_get_fd(bufmgr);
121 
122    if (iris_bo_is_imported(bo))
123       range = bo->size;
124    else
125       range = align64(bo->size, devinfo->mem_alignment);
126 
127    if (bo->real.userptr) {
128       handle = 0;
129       obj_offset = (uintptr_t)bo->real.map;
130       if (op == DRM_XE_VM_BIND_OP_MAP)
131          op = DRM_XE_VM_BIND_OP_MAP_USERPTR;
132    }
133 
134    uint16_t pat_index = 0;
135    if (op != DRM_XE_VM_BIND_OP_UNMAP)
136       pat_index = iris_heap_to_pat_entry(devinfo, bo->real.heap)->index;
137 
138    if (bo->real.capture)
139       flags |= DRM_XE_VM_BIND_FLAG_DUMPABLE;
140 
141    struct drm_xe_vm_bind args = {
142       .vm_id = iris_bufmgr_get_global_vm_id(bufmgr),
143       .num_syncs = 1,
144       .syncs = (uintptr_t)&xe_sync,
145       .num_binds = 1,
146       .bind.obj = handle,
147       .bind.obj_offset = obj_offset,
148       .bind.range = range,
149       .bind.addr = intel_48b_address(bo->address),
150       .bind.op = op,
151       .bind.pat_index = pat_index,
152       .bind.flags = flags,
153    };
154 
155    xe_sync.timeline_value = intel_bind_timeline_bind_begin(bind_timeline);
156    ret = intel_ioctl(fd, DRM_IOCTL_XE_VM_BIND, &args);
157    intel_bind_timeline_bind_end(bind_timeline);
158 
159    if (ret)
160       DBG("vm_bind_op: DRM_IOCTL_XE_VM_BIND failed(%i)", ret);
161 
162    return ret;
163 }
164 
165 static bool
xe_gem_vm_bind(struct iris_bo * bo)166 xe_gem_vm_bind(struct iris_bo *bo)
167 {
168    return xe_gem_vm_bind_op(bo, DRM_XE_VM_BIND_OP_MAP) == 0;
169 }
170 
171 static bool
xe_gem_vm_unbind(struct iris_bo * bo)172 xe_gem_vm_unbind(struct iris_bo *bo)
173 {
174    return xe_gem_vm_bind_op(bo, DRM_XE_VM_BIND_OP_UNMAP) == 0;
175 }
176 
177 static bool
xe_bo_madvise(struct iris_bo * bo,enum iris_madvice state)178 xe_bo_madvise(struct iris_bo *bo, enum iris_madvice state)
179 {
180    /* Only applicable if VM was created with DRM_XE_VM_CREATE_FAULT_MODE but
181     * that is not compatible with DRM_XE_VM_CREATE_SCRATCH_PAGE
182     *
183     * So returning as retained.
184     */
185    return true;
186 }
187 
188 static int
xe_bo_set_caching(struct iris_bo * bo,bool cached)189 xe_bo_set_caching(struct iris_bo *bo, bool cached)
190 {
191    /* Xe don't have caching UAPI so this function should never be called */
192    assert(0);
193    return -1;
194 }
195 
196 static enum pipe_reset_status
xe_batch_check_for_reset(struct iris_batch * batch)197 xe_batch_check_for_reset(struct iris_batch *batch)
198 {
199    enum pipe_reset_status status = PIPE_NO_RESET;
200    struct drm_xe_exec_queue_get_property exec_queue_get_property = {
201       .exec_queue_id = batch->xe.exec_queue_id,
202       .property = DRM_XE_EXEC_QUEUE_GET_PROPERTY_BAN,
203    };
204    int ret = intel_ioctl(iris_bufmgr_get_fd(batch->screen->bufmgr),
205                          DRM_IOCTL_XE_EXEC_QUEUE_GET_PROPERTY,
206                          &exec_queue_get_property);
207 
208    if (ret || exec_queue_get_property.value)
209       status = PIPE_GUILTY_CONTEXT_RESET;
210 
211    return status;
212 }
213 
214 static uint32_t
xe_batch_submit_external_bo_count(struct iris_batch * batch)215 xe_batch_submit_external_bo_count(struct iris_batch *batch)
216 {
217    uint32_t count = 0;
218 
219    for (int i = 0; i < batch->exec_count; i++) {
220       if (iris_bo_is_external(batch->exec_bos[i]))
221          count++;
222    }
223 
224    return count;
225 }
226 
227 struct iris_implicit_sync {
228    struct iris_implicit_sync_entry {
229       struct iris_bo *bo;
230       struct iris_syncobj *iris_syncobj;
231    } *entries;
232    uint32_t entry_count;
233 
234    struct iris_syncobj *batch_signal_syncobj;
235 };
236 
237 static bool
iris_implicit_sync_add_bo(struct iris_batch * batch,struct iris_implicit_sync * sync,struct iris_bo * bo)238 iris_implicit_sync_add_bo(struct iris_batch *batch,
239                           struct iris_implicit_sync *sync,
240                           struct iris_bo *bo)
241 {
242    struct iris_syncobj *syncobj = iris_bo_export_sync_state(bo);
243 
244    if (!syncobj)
245       return false;
246 
247    sync->entries[sync->entry_count].bo = bo;
248    sync->entries[sync->entry_count].iris_syncobj = syncobj;
249    sync->entry_count++;
250 
251    iris_batch_add_syncobj(batch, syncobj, IRIS_BATCH_FENCE_WAIT);
252 
253    return true;
254 }
255 
256 /* Cleans up the state of 'sync'. */
257 static void
iris_implicit_sync_finish(struct iris_batch * batch,struct iris_implicit_sync * sync)258 iris_implicit_sync_finish(struct iris_batch *batch,
259                           struct iris_implicit_sync *sync)
260 {
261    struct iris_bufmgr *bufmgr = batch->screen->bufmgr;
262 
263    for (int i = 0; i < sync->entry_count; i++)
264       iris_syncobj_reference(bufmgr, &sync->entries[i].iris_syncobj, NULL);
265 
266    free(sync->entries);
267    sync->entry_count = 0;
268 }
269 
270 /* Import implicit synchronization data from the batch bos that require
271  * implicit synchronization int our batch buffer so the batch will wait for
272  * these bos to be idle before starting.
273  */
274 static int
iris_implicit_sync_import(struct iris_batch * batch,struct iris_implicit_sync * sync)275 iris_implicit_sync_import(struct iris_batch *batch,
276                           struct iris_implicit_sync *sync)
277 {
278    uint32_t len = xe_batch_submit_external_bo_count(batch);
279 
280    if (!len)
281       return 0;
282 
283    sync->entries = malloc(sizeof(*sync->entries) * len);
284    if (!sync->entries)
285       return -ENOMEM;
286 
287    for (int i = 0; i < batch->exec_count; i++) {
288       struct iris_bo *bo = batch->exec_bos[i];
289 
290       if (!iris_bo_is_real(bo) || !iris_bo_is_external(bo)) {
291          assert(iris_get_backing_bo(bo)->real.prime_fd == -1);
292          continue;
293       }
294 
295       if (bo->real.prime_fd == -1) {
296          fprintf(stderr, "Bo(%s/%i %sported) with prime_fd unset in iris_implicit_sync_import()\n",
297                  bo->name, bo->gem_handle, bo->real.imported ? "im" : "ex");
298          continue;
299       }
300 
301       if (!iris_implicit_sync_add_bo(batch, sync, bo)) {
302          iris_implicit_sync_finish(batch, sync);
303          return -1;
304       }
305    }
306 
307    return 0;
308 }
309 
310 /* Export implicit synchronization data from our batch buffer into the bos
311  * that require implicit synchronization so other clients relying on it can do
312  * implicit synchronization with these bos, which will wait for the batch
313  * buffer we just submitted to signal its syncobj.
314  */
315 static bool
iris_implicit_sync_export(struct iris_batch * batch,struct iris_implicit_sync * sync)316 iris_implicit_sync_export(struct iris_batch *batch,
317                           struct iris_implicit_sync *sync)
318 {
319    int sync_file_fd;
320 
321    if (!iris_batch_syncobj_to_sync_file_fd(batch, &sync_file_fd))
322       return false;
323 
324    for (int i = 0; i < sync->entry_count; i++)
325       iris_bo_import_sync_state(sync->entries[i].bo, sync_file_fd);
326 
327    close(sync_file_fd);
328 
329    return true;
330 }
331 
332 static int
xe_batch_submit(struct iris_batch * batch)333 xe_batch_submit(struct iris_batch *batch)
334 {
335    struct iris_bufmgr *bufmgr = batch->screen->bufmgr;
336    struct intel_bind_timeline *bind_timeline = iris_bufmgr_get_bind_timeline(bufmgr);
337    simple_mtx_t *bo_deps_lock = iris_bufmgr_get_bo_deps_lock(bufmgr);
338    struct iris_implicit_sync implicit_sync = {};
339    struct drm_xe_sync *syncs = NULL;
340    unsigned long sync_len;
341    int ret, i;
342 
343    iris_bo_unmap(batch->bo);
344 
345    /* The decode operation may map and wait on the batch buffer, which could
346     * in theory try to grab bo_deps_lock. Let's keep it safe and decode
347     * outside the lock.
348     */
349    if (INTEL_DEBUG(DEBUG_BATCH) &&
350        intel_debug_batch_in_range(batch->ice->frame))
351       iris_batch_decode_batch(batch);
352 
353    simple_mtx_lock(bo_deps_lock);
354 
355    iris_batch_update_syncobjs(batch);
356 
357    ret = iris_implicit_sync_import(batch, &implicit_sync);
358    if (ret)
359       goto error_implicit_sync_import;
360 
361    sync_len = iris_batch_num_fences(batch) + 1 /* vm bind sync */;
362    syncs = calloc(sync_len, sizeof(*syncs));
363    if (!syncs) {
364       ret = -ENOMEM;
365       goto error_no_sync_mem;
366    }
367 
368    i = 0;
369    util_dynarray_foreach(&batch->exec_fences, struct iris_batch_fence, fence) {
370       if (fence->flags & IRIS_BATCH_FENCE_SIGNAL)
371          syncs[i].flags = DRM_XE_SYNC_FLAG_SIGNAL;
372 
373       syncs[i].handle = fence->handle;
374       syncs[i].type = DRM_XE_SYNC_TYPE_SYNCOBJ;
375       i++;
376    }
377 
378    syncs[i].handle = intel_bind_timeline_get_syncobj(bind_timeline);
379    syncs[i].type = DRM_XE_SYNC_TYPE_TIMELINE_SYNCOBJ;
380    syncs[i].timeline_value = intel_bind_timeline_get_last_point(bind_timeline);
381 
382    if ((INTEL_DEBUG(DEBUG_BATCH) &&
383         intel_debug_batch_in_range(batch->ice->frame)) ||
384        INTEL_DEBUG(DEBUG_SUBMIT)) {
385       iris_dump_fence_list(batch);
386       iris_dump_bo_list(batch);
387    }
388 
389    struct drm_xe_exec exec = {
390       .exec_queue_id = batch->xe.exec_queue_id,
391       .num_batch_buffer = 1,
392       .address = batch->exec_bos[0]->address,
393       .syncs = (uintptr_t)syncs,
394       .num_syncs = sync_len,
395    };
396    if (!batch->screen->devinfo->no_hw)
397        ret = intel_ioctl(iris_bufmgr_get_fd(bufmgr), DRM_IOCTL_XE_EXEC, &exec);
398 
399    if (ret) {
400       ret = -errno;
401       goto error_exec;
402    }
403 
404    if (!iris_implicit_sync_export(batch, &implicit_sync))
405       ret = -1;
406 
407 error_exec:
408    iris_implicit_sync_finish(batch, &implicit_sync);
409 
410    simple_mtx_unlock(bo_deps_lock);
411 
412    free(syncs);
413 
414    for (int i = 0; i < batch->exec_count; i++) {
415       struct iris_bo *bo = batch->exec_bos[i];
416 
417       bo->idle = false;
418       bo->index = -1;
419 
420       iris_get_backing_bo(bo)->idle = false;
421 
422       iris_bo_unreference(bo);
423    }
424 
425    return ret;
426 
427 error_no_sync_mem:
428    iris_implicit_sync_finish(batch, &implicit_sync);
429 error_implicit_sync_import:
430    simple_mtx_unlock(bo_deps_lock);
431    return ret;
432 }
433 
434 static int
xe_gem_close(struct iris_bufmgr * bufmgr,struct iris_bo * bo)435 xe_gem_close(struct iris_bufmgr *bufmgr, struct iris_bo *bo)
436 {
437    if (bo->real.userptr)
438       return 0;
439 
440    struct drm_gem_close close = {
441       .handle = bo->gem_handle,
442    };
443    return intel_ioctl(iris_bufmgr_get_fd(bufmgr), DRM_IOCTL_GEM_CLOSE, &close);
444 }
445 
446 static uint32_t
xe_gem_create_userptr(struct iris_bufmgr * bufmgr,void * ptr,uint64_t size)447 xe_gem_create_userptr(struct iris_bufmgr *bufmgr, void *ptr, uint64_t size)
448 {
449    /* We return UINT32_MAX, because Xe doesn't create handles for userptrs but
450     * it needs a gem_handle different than 0 so iris_bo_is_real() returns true
451     * for userptr bos.
452     * UINT32_MAX handle here will not conflict with an actual gem handle with
453     * same id as userptr bos are not put to slab or bo cache.
454     */
455    return UINT32_MAX;
456 }
457 
xe_get_backend(void)458 const struct iris_kmd_backend *xe_get_backend(void)
459 {
460    static const struct iris_kmd_backend xe_backend = {
461       .gem_create = xe_gem_create,
462       .gem_create_userptr = xe_gem_create_userptr,
463       .gem_close = xe_gem_close,
464       .gem_mmap = xe_gem_mmap,
465       .gem_vm_bind = xe_gem_vm_bind,
466       .gem_vm_unbind = xe_gem_vm_unbind,
467       .bo_madvise = xe_bo_madvise,
468       .bo_set_caching = xe_bo_set_caching,
469       .batch_check_for_reset = xe_batch_check_for_reset,
470       .batch_submit = xe_batch_submit,
471    };
472    return &xe_backend;
473 }
474