~mmach/netext73/mesa-ryzen

« back to all changes in this revision

Viewing changes to src/freedreno/vulkan/tu_knl_drm_msm.cc

  • Committer: mmach
  • Date: 2023-11-02 21:31:35 UTC
  • Revision ID: netbit73@gmail.com-20231102213135-18d4tzh7tj0uz752
2023-11-02 22:11:57

Show diffs side-by-side

added added

removed removed

Lines of Context:
51
51
};
52
52
 
53
53
static int
54
 
tu_drm_get_param(const struct tu_physical_device *dev,
55
 
                 uint32_t param,
56
 
                 uint64_t *value)
 
54
tu_drm_get_param(int fd, uint32_t param, uint64_t *value)
57
55
{
58
56
   /* Technically this requires a pipe, but the kernel only supports one pipe
59
57
    * anyway at the time of writing and most of these are clearly pipe
63
61
      .param = param,
64
62
   };
65
63
 
66
 
   int ret = drmCommandWriteRead(dev->local_fd, DRM_MSM_GET_PARAM, &req,
67
 
                                 sizeof(req));
 
64
   int ret = drmCommandWriteRead(fd, DRM_MSM_GET_PARAM, &req, sizeof(req));
68
65
   if (ret)
69
66
      return ret;
70
67
 
77
74
tu_drm_get_gpu_id(const struct tu_physical_device *dev, uint32_t *id)
78
75
{
79
76
   uint64_t value;
80
 
   int ret = tu_drm_get_param(dev, MSM_PARAM_GPU_ID, &value);
 
77
   int ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_GPU_ID, &value);
81
78
   if (ret)
82
79
      return ret;
83
80
 
89
86
tu_drm_get_gmem_size(const struct tu_physical_device *dev, uint32_t *size)
90
87
{
91
88
   uint64_t value;
92
 
   int ret = tu_drm_get_param(dev, MSM_PARAM_GMEM_SIZE, &value);
 
89
   int ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_GMEM_SIZE, &value);
93
90
   if (ret)
94
91
      return ret;
95
92
 
100
97
static int
101
98
tu_drm_get_gmem_base(const struct tu_physical_device *dev, uint64_t *base)
102
99
{
103
 
   return tu_drm_get_param(dev, MSM_PARAM_GMEM_BASE, base);
 
100
   return tu_drm_get_param(dev->local_fd, MSM_PARAM_GMEM_BASE, base);
104
101
}
105
102
 
106
103
static int
108
105
                   uint64_t *va_start, uint64_t *va_size)
109
106
{
110
107
   uint64_t value;
111
 
   int ret = tu_drm_get_param(dev, MSM_PARAM_VA_START, &value);
 
108
   int ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_VA_START, &value);
112
109
   if (ret)
113
110
      return ret;
114
111
 
115
112
   *va_start = value;
116
113
 
117
 
   ret = tu_drm_get_param(dev, MSM_PARAM_VA_SIZE, &value);
 
114
   ret = tu_drm_get_param(dev->local_fd, MSM_PARAM_VA_SIZE, &value);
118
115
   if (ret)
119
116
      return ret;
120
117
 
127
124
tu_drm_get_priorities(const struct tu_physical_device *dev)
128
125
{
129
126
   uint64_t val = 1;
130
 
   tu_drm_get_param(dev, MSM_PARAM_PRIORITIES, &val);
 
127
   tu_drm_get_param(dev->local_fd, MSM_PARAM_PRIORITIES, &val);
131
128
   assert(val >= 1);
132
129
 
133
130
   return val;
152
149
   return true;
153
150
}
154
151
 
 
152
static VkResult
 
153
msm_device_init(struct tu_device *dev)
 
154
{
 
155
   int fd = open(dev->physical_device->fd_path, O_RDWR | O_CLOEXEC);
 
156
   if (fd < 0) {
 
157
      return vk_startup_errorf(
 
158
            dev->physical_device->instance, VK_ERROR_INITIALIZATION_FAILED,
 
159
            "failed to open device %s", dev->physical_device->fd_path);
 
160
   }
 
161
 
 
162
   int ret = tu_drm_get_param(fd, MSM_PARAM_FAULTS, &dev->fault_count);
 
163
   if (ret != 0) {
 
164
      close(fd);
 
165
      return vk_startup_errorf(dev->physical_device->instance,
 
166
                               VK_ERROR_INITIALIZATION_FAILED,
 
167
                               "Failed to get initial fault count: %d", ret);
 
168
   }
 
169
 
 
170
   dev->fd = fd;
 
171
 
 
172
   return VK_SUCCESS;
 
173
}
 
174
 
 
175
static void
 
176
msm_device_finish(struct tu_device *dev)
 
177
{
 
178
   close(dev->fd);
 
179
}
 
180
 
155
181
static int
156
182
msm_device_get_gpu_timestamp(struct tu_device *dev, uint64_t *ts)
157
183
{
158
 
   return tu_drm_get_param(dev->physical_device, MSM_PARAM_TIMESTAMP, ts);
 
184
   return tu_drm_get_param(dev->fd, MSM_PARAM_TIMESTAMP, ts);
159
185
}
160
186
 
161
187
static int
162
188
msm_device_get_suspend_count(struct tu_device *dev, uint64_t *suspend_count)
163
189
{
164
 
   int ret = tu_drm_get_param(dev->physical_device, MSM_PARAM_SUSPENDS, suspend_count);
 
190
   int ret = tu_drm_get_param(dev->fd, MSM_PARAM_SUSPENDS, suspend_count);
165
191
   return ret;
166
192
}
167
193
 
168
194
static VkResult
169
195
msm_device_check_status(struct tu_device *device)
170
196
{
171
 
   struct tu_physical_device *physical_device = device->physical_device;
172
 
 
173
 
   uint64_t last_fault_count = physical_device->fault_count;
174
 
   int ret = tu_drm_get_param(physical_device, MSM_PARAM_FAULTS, &physical_device->fault_count);
 
197
   uint64_t last_fault_count = device->fault_count;
 
198
   int ret = tu_drm_get_param(device->fd, MSM_PARAM_FAULTS, &device->fault_count);
175
199
   if (ret != 0)
176
200
      return vk_device_set_lost(&device->vk, "error getting GPU fault count: %d", ret);
177
201
 
178
 
   if (last_fault_count != physical_device->fault_count)
 
202
   if (last_fault_count != device->fault_count)
179
203
      return vk_device_set_lost(&device->vk, "GPU faulted or hung");
180
204
 
181
205
   return VK_SUCCESS;
249
273
              VkDeviceSize size,
250
274
              enum tu_mem_sync_op op);
251
275
 
 
276
static inline void
 
277
get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns)
 
278
{
 
279
   struct timespec t;
 
280
   clock_gettime(CLOCK_MONOTONIC, &t);
 
281
   tv->tv_sec = t.tv_sec + ns / 1000000000;
 
282
   tv->tv_nsec = t.tv_nsec + ns % 1000000000;
 
283
}
 
284
 
 
285
static VkResult
 
286
tu_wait_fence(struct tu_device *dev,
 
287
              uint32_t queue_id,
 
288
              int fence,
 
289
              uint64_t timeout_ns)
 
290
{
 
291
   /* fence was created when no work was yet submitted */
 
292
   if (fence < 0)
 
293
      return VK_SUCCESS;
 
294
 
 
295
   struct drm_msm_wait_fence req = {
 
296
      .fence = fence,
 
297
      .queueid = queue_id,
 
298
   };
 
299
   int ret;
 
300
 
 
301
   get_abs_timeout(&req.timeout, timeout_ns);
 
302
 
 
303
   ret = drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &req, sizeof(req));
 
304
   if (ret) {
 
305
      if (ret == -ETIMEDOUT) {
 
306
         return VK_TIMEOUT;
 
307
      } else {
 
308
         mesa_loge("tu_wait_fence failed! %d (%s)", ret, strerror(errno));
 
309
         return VK_ERROR_UNKNOWN;
 
310
      }
 
311
   }
 
312
 
 
313
   return VK_SUCCESS;
 
314
}
 
315
 
 
316
static VkResult
 
317
tu_free_zombie_vma_locked(struct tu_device *dev, bool wait)
 
318
{
 
319
   if (!u_vector_length(&dev->zombie_vmas))
 
320
      return VK_SUCCESS;
 
321
 
 
322
   if (wait) {
 
323
      struct tu_zombie_vma *vma = (struct tu_zombie_vma *)
 
324
            u_vector_head(&dev->zombie_vmas);
 
325
      /* Wait for 3s (arbitrary timeout) */
 
326
      VkResult ret = tu_wait_fence(dev, dev->queues[0]->msm_queue_id,
 
327
                                   vma->fence, 3000000000);
 
328
 
 
329
      if (ret != VK_SUCCESS)
 
330
         return ret;
 
331
   }
 
332
 
 
333
   int last_signaled_fence = -1;
 
334
   while (u_vector_length(&dev->zombie_vmas) > 0) {
 
335
      struct tu_zombie_vma *vma = (struct tu_zombie_vma *)
 
336
            u_vector_tail(&dev->zombie_vmas);
 
337
      if (vma->fence > last_signaled_fence) {
 
338
         VkResult ret =
 
339
            tu_wait_fence(dev, dev->queues[0]->msm_queue_id, vma->fence, 0);
 
340
         if (ret != VK_SUCCESS)
 
341
            return ret;
 
342
 
 
343
         last_signaled_fence = vma->fence;
 
344
      }
 
345
 
 
346
      /* Ensure that internal kernel's vma is freed. */
 
347
      struct drm_msm_gem_info req = {
 
348
         .handle = vma->gem_handle,
 
349
         .info = MSM_INFO_SET_IOVA,
 
350
         .value = 0,
 
351
      };
 
352
 
 
353
      int ret =
 
354
         drmCommandWriteRead(dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
 
355
      if (ret < 0) {
 
356
         mesa_loge("MSM_INFO_SET_IOVA(0) failed! %d (%s)", ret,
 
357
                   strerror(errno));
 
358
         return VK_ERROR_UNKNOWN;
 
359
      }
 
360
 
 
361
      tu_gem_close(dev, vma->gem_handle);
 
362
 
 
363
      util_vma_heap_free(&dev->vma, vma->iova, vma->size);
 
364
      u_vector_remove(&dev->zombie_vmas);
 
365
   }
 
366
 
 
367
   return VK_SUCCESS;
 
368
}
 
369
 
252
370
static VkResult
253
371
tu_allocate_userspace_iova(struct tu_device *dev,
254
372
                           uint32_t gem_handle,
257
375
                           enum tu_bo_alloc_flags flags,
258
376
                           uint64_t *iova)
259
377
{
260
 
   mtx_lock(&dev->physical_device->vma_mutex);
 
378
   mtx_lock(&dev->vma_mutex);
261
379
 
262
380
   *iova = 0;
263
381
 
 
382
   tu_free_zombie_vma_locked(dev, false);
 
383
 
264
384
   if (flags & TU_BO_ALLOC_REPLAYABLE) {
265
385
      if (client_iova) {
266
 
         if (util_vma_heap_alloc_addr(&dev->physical_device->vma, client_iova,
267
 
                                      size)) {
 
386
         if (util_vma_heap_alloc_addr(&dev->vma, client_iova, size)) {
268
387
            *iova = client_iova;
269
388
         } else {
270
 
            return VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS;
 
389
            /* Address may be already freed by us, but not considered as
 
390
             * freed by the kernel. We have to wait until all work that
 
391
             * may hold the address is done. Since addresses are meant to
 
392
             * be replayed only by debug tooling, it should be ok to wait.
 
393
             */
 
394
            if (tu_free_zombie_vma_locked(dev, true) == VK_SUCCESS &&
 
395
                util_vma_heap_alloc_addr(&dev->vma, client_iova, size)) {
 
396
               *iova = client_iova;
 
397
            } else {
 
398
               mtx_unlock(&dev->vma_mutex);
 
399
               return VK_ERROR_INVALID_OPAQUE_CAPTURE_ADDRESS;
 
400
            }
271
401
         }
272
402
      } else {
273
403
         /* We have to separate replayable IOVAs from ordinary one in order to
274
404
          * for them not to clash. The easiest way to do this is to allocate
275
405
          * them from the other end of the address space.
276
406
          */
277
 
         dev->physical_device->vma.alloc_high = true;
278
 
         *iova =
279
 
            util_vma_heap_alloc(&dev->physical_device->vma, size, 0x1000);
 
407
         dev->vma.alloc_high = true;
 
408
         *iova = util_vma_heap_alloc(&dev->vma, size, 0x1000);
280
409
      }
281
410
   } else {
282
 
      dev->physical_device->vma.alloc_high = false;
283
 
      *iova = util_vma_heap_alloc(&dev->physical_device->vma, size, 0x1000);
 
411
      dev->vma.alloc_high = false;
 
412
      *iova = util_vma_heap_alloc(&dev->vma, size, 0x1000);
284
413
   }
285
414
 
286
 
   mtx_unlock(&dev->physical_device->vma_mutex);
 
415
   mtx_unlock(&dev->vma_mutex);
287
416
 
288
417
   if (!*iova)
289
418
      return VK_ERROR_OUT_OF_DEVICE_MEMORY;
296
425
 
297
426
   int ret =
298
427
      drmCommandWriteRead(dev->fd, DRM_MSM_GEM_INFO, &req, sizeof(req));
299
 
   if (ret < 0)
 
428
   if (ret < 0) {
 
429
      mesa_loge("MSM_INFO_SET_IOVA failed! %d (%s)", ret, strerror(errno));
300
430
      return VK_ERROR_OUT_OF_HOST_MEMORY;
 
431
   }
301
432
 
302
433
   return VK_SUCCESS;
303
434
}
352
483
         vk_realloc(&dev->vk.alloc, dev->bo_list, new_len * sizeof(*dev->bo_list),
353
484
                    8, VK_SYSTEM_ALLOCATION_SCOPE_DEVICE);
354
485
      if (!new_ptr) {
 
486
         dev->bo_count--;
 
487
         mtx_unlock(&dev->bo_mutex);
355
488
         tu_gem_close(dev, gem_handle);
356
489
         return VK_ERROR_OUT_OF_HOST_MEMORY;
357
490
      }
488
621
   if (real_size < 0 || (uint64_t) real_size < size)
489
622
      return vk_error(dev, VK_ERROR_INVALID_EXTERNAL_HANDLE);
490
623
 
 
624
   /* iova allocation needs to consider the object's *real* size: */
 
625
   size = real_size;
 
626
 
491
627
   /* Importing the same dmabuf several times would yield the same
492
628
    * gem_handle. Thus there could be a race when destroying
493
629
    * BO and importing the same dmabuf from different threads.
595
731
   mtx_unlock(&dev->bo_mutex);
596
732
 
597
733
   if (dev->physical_device->has_set_iova) {
598
 
      mtx_lock(&dev->physical_device->vma_mutex);
599
 
      util_vma_heap_free(&dev->physical_device->vma, bo->iova, bo->size);
600
 
      mtx_unlock(&dev->physical_device->vma_mutex);
 
734
      mtx_lock(&dev->vma_mutex);
 
735
      struct tu_zombie_vma *vma = (struct tu_zombie_vma *)
 
736
            u_vector_add(&dev->zombie_vmas);
 
737
      vma->gem_handle = bo->gem_handle;
 
738
      vma->iova = bo->iova;
 
739
      vma->size = bo->size;
 
740
      vma->fence = p_atomic_read(&dev->queues[0]->fence);
 
741
      mtx_unlock(&dev->vma_mutex);
 
742
 
 
743
      memset(bo, 0, sizeof(*bo));
 
744
   } else {
 
745
      /* Our BO structs are stored in a sparse array in the physical device,
 
746
       * so we don't want to free the BO pointer, instead we want to reset it
 
747
       * to 0, to signal that array entry as being free.
 
748
       */
 
749
      uint32_t gem_handle = bo->gem_handle;
 
750
      memset(bo, 0, sizeof(*bo));
 
751
 
 
752
      tu_gem_close(dev, gem_handle);
601
753
   }
602
754
 
603
 
   /* Our BO structs are stored in a sparse array in the physical device,
604
 
    * so we don't want to free the BO pointer, instead we want to reset it
605
 
    * to 0, to signal that array entry as being free.
606
 
    */
607
 
   uint32_t gem_handle = bo->gem_handle;
608
 
   memset(bo, 0, sizeof(*bo));
609
 
 
610
 
   tu_gem_close(dev, gem_handle);
611
 
 
612
755
   u_rwlock_rdunlock(&dev->dma_bo_lock);
613
756
}
614
757
 
1142
1285
   if (ret)
1143
1286
      return vk_device_set_lost(&queue->device->vk, "submit failed: %m");
1144
1287
 
 
1288
   p_atomic_set(&queue->fence, req.fence);
 
1289
 
1145
1290
#if HAVE_PERFETTO
1146
1291
   tu_perfetto_submit(queue->device, queue->device->submit_count);
1147
1292
#endif
1206
1351
   return VK_SUCCESS;
1207
1352
}
1208
1353
 
1209
 
static inline void
1210
 
get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns)
1211
 
{
1212
 
   struct timespec t;
1213
 
   clock_gettime(CLOCK_MONOTONIC, &t);
1214
 
   tv->tv_sec = t.tv_sec + ns / 1000000000;
1215
 
   tv->tv_nsec = t.tv_nsec + ns % 1000000000;
1216
 
}
1217
 
 
1218
1354
static VkResult
1219
1355
msm_device_wait_u_trace(struct tu_device *dev, struct tu_u_trace_syncobj *syncobj)
1220
1356
{
1221
 
   struct drm_msm_wait_fence req = {
1222
 
      .fence = syncobj->fence,
1223
 
      .queueid = syncobj->msm_queue_id,
1224
 
   };
1225
 
   int ret;
1226
 
 
1227
 
   get_abs_timeout(&req.timeout, 1000000000);
1228
 
 
1229
 
   ret = drmCommandWrite(dev->fd, DRM_MSM_WAIT_FENCE, &req, sizeof(req));
1230
 
   if (ret && (ret != -ETIMEDOUT)) {
1231
 
      fprintf(stderr, "wait-fence failed! %d (%s)", ret, strerror(errno));
1232
 
      return VK_TIMEOUT;
1233
 
   }
1234
 
 
1235
 
   return VK_SUCCESS;
 
1357
   return tu_wait_fence(dev, syncobj->msm_queue_id, syncobj->fence, 1000000000);
1236
1358
}
1237
1359
 
1238
1360
static VkResult
1298
1420
static const struct tu_knl msm_knl_funcs = {
1299
1421
      .name = "msm",
1300
1422
 
 
1423
      .device_init = msm_device_init,
 
1424
      .device_finish = msm_device_finish,
1301
1425
      .device_get_gpu_timestamp = msm_device_get_gpu_timestamp,
1302
1426
      .device_get_suspend_count = msm_device_get_suspend_count,
1303
1427
      .device_check_status = msm_device_check_status,
1332
1456
                    struct tu_physical_device **out)
1333
1457
{
1334
1458
   VkResult result = VK_SUCCESS;
1335
 
   int ret;
1336
1459
 
1337
1460
   /* Version 1.6 added SYNCOBJ support. */
1338
1461
   const int min_version_major = 1;
1369
1492
      goto fail;
1370
1493
   }
1371
1494
 
1372
 
   if (tu_drm_get_param(device, MSM_PARAM_CHIP_ID, &device->dev_id.chip_id)) {
 
1495
   if (tu_drm_get_param(fd, MSM_PARAM_CHIP_ID, &device->dev_id.chip_id)) {
1373
1496
      result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
1374
1497
                                 "could not get CHIP ID");
1375
1498
      goto fail;
1388
1511
      goto fail;
1389
1512
   }
1390
1513
 
1391
 
   /*
1392
 
    * device->has_set_iova = !tu_drm_get_va_prop(device, &device->va_start,
1393
 
    *                                            &device->va_size);
1394
 
    *
1395
 
    * If BO is freed while kernel considers it busy, our VMA state gets
1396
 
    * desynchronized from kernel's VMA state, because kernel waits
1397
 
    * until BO stops being busy. And whether BO is busy decided at
1398
 
    * submission granularity.
1399
 
    *
1400
 
    * Disable this capability until solution is found.
1401
 
    */
1402
 
   device->has_set_iova = false;
 
1514
   device->has_set_iova = !tu_drm_get_va_prop(device, &device->va_start,
 
1515
                                              &device->va_size);
1403
1516
 
1404
1517
   /* Even if kernel is new enough, the GPU itself may not support it. */
1405
1518
   device->has_cached_coherent_memory =
1413
1526
   }
1414
1527
#endif
1415
1528
 
1416
 
 
1417
 
   ret = tu_drm_get_param(device, MSM_PARAM_FAULTS, &device->fault_count);
1418
 
   if (ret != 0) {
1419
 
      result = vk_startup_errorf(instance, VK_ERROR_INITIALIZATION_FAILED,
1420
 
                                 "Failed to get initial fault count: %d", ret);
1421
 
      goto fail;
1422
 
   }
1423
 
 
1424
1529
   device->submitqueue_priority_count = tu_drm_get_priorities(device);
1425
1530
 
1426
1531
   device->syncobj_type = vk_drm_syncobj_get_type(fd);