xref: /aosp_15_r20/external/mesa3d/src/gallium/drivers/nouveau/nouveau_screen.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 #include "git_sha1.h"
2 
3 #include "pipe/p_defines.h"
4 #include "pipe/p_screen.h"
5 #include "pipe/p_state.h"
6 
7 #include "util/u_memory.h"
8 #include "util/u_inlines.h"
9 #include "util/format/u_format.h"
10 #include "util/format/u_format_s3tc.h"
11 #include "util/u_string.h"
12 #include "util/hex.h"
13 
14 #include "util/os_mman.h"
15 #include "util/os_time.h"
16 
17 #include <stdio.h>
18 #include <errno.h>
19 #include <stdlib.h>
20 
21 #include "drm-uapi/nouveau_drm.h"
22 #include <xf86drm.h>
23 #include "nvif/class.h"
24 #include "nvif/cl0080.h"
25 
26 #include "nouveau_winsys.h"
27 #include "nouveau_screen.h"
28 #include "nouveau_context.h"
29 #include "nouveau_fence.h"
30 #include "nouveau_mm.h"
31 #include "nouveau_buffer.h"
32 
33 #include <compiler/glsl_types.h>
34 
35 /* XXX this should go away */
36 #include "frontend/drm_driver.h"
37 
38 /* Even though GPUs might allow addresses with more bits, some engines do not.
39  * Stick with 40 for compatibility.
40  */
41 #define NV_GENERIC_VM_LIMIT_SHIFT 39
42 
43 int nouveau_mesa_debug = 0;
44 
45 static const char *
nouveau_screen_get_name(struct pipe_screen * pscreen)46 nouveau_screen_get_name(struct pipe_screen *pscreen)
47 {
48    struct nouveau_screen *screen = nouveau_screen(pscreen);
49    return screen->chipset_name;
50 }
51 
52 static const char *
nouveau_screen_get_vendor(struct pipe_screen * pscreen)53 nouveau_screen_get_vendor(struct pipe_screen *pscreen)
54 {
55    return "Mesa";
56 }
57 
58 static const char *
nouveau_screen_get_device_vendor(struct pipe_screen * pscreen)59 nouveau_screen_get_device_vendor(struct pipe_screen *pscreen)
60 {
61    return "NVIDIA";
62 }
63 
64 static uint64_t
nouveau_screen_get_timestamp(struct pipe_screen * pscreen)65 nouveau_screen_get_timestamp(struct pipe_screen *pscreen)
66 {
67    int64_t cpu_time = os_time_get_nano();
68 
69    /* getparam of PTIMER_TIME takes about x10 as long (several usecs) */
70 
71    return cpu_time + nouveau_screen(pscreen)->cpu_gpu_time_delta;
72 }
73 
74 static struct disk_cache *
nouveau_screen_get_disk_shader_cache(struct pipe_screen * pscreen)75 nouveau_screen_get_disk_shader_cache(struct pipe_screen *pscreen)
76 {
77    return nouveau_screen(pscreen)->disk_shader_cache;
78 }
79 
80 static void
nouveau_screen_fence_ref(struct pipe_screen * pscreen,struct pipe_fence_handle ** ptr,struct pipe_fence_handle * pfence)81 nouveau_screen_fence_ref(struct pipe_screen *pscreen,
82                          struct pipe_fence_handle **ptr,
83                          struct pipe_fence_handle *pfence)
84 {
85    nouveau_fence_ref((pfence ? nouveau_fence(pfence) : NULL),
86                      (ptr ? (struct nouveau_fence **)ptr : NULL));
87 }
88 
89 static bool
nouveau_screen_fence_finish(struct pipe_screen * screen,struct pipe_context * ctx,struct pipe_fence_handle * pfence,uint64_t timeout)90 nouveau_screen_fence_finish(struct pipe_screen *screen,
91                             struct pipe_context *ctx,
92                             struct pipe_fence_handle *pfence,
93                             uint64_t timeout)
94 {
95    if (!timeout)
96       return nouveau_fence_signalled(nouveau_fence(pfence));
97 
98    return nouveau_fence_wait(nouveau_fence(pfence), NULL);
99 }
100 
101 
102 struct nouveau_bo *
nouveau_screen_bo_from_handle(struct pipe_screen * pscreen,struct winsys_handle * whandle,unsigned * out_stride)103 nouveau_screen_bo_from_handle(struct pipe_screen *pscreen,
104                               struct winsys_handle *whandle,
105                               unsigned *out_stride)
106 {
107    struct nouveau_device *dev = nouveau_screen(pscreen)->device;
108    struct nouveau_bo *bo = NULL;
109    int ret;
110 
111    if (whandle->offset != 0) {
112       debug_printf("%s: attempt to import unsupported winsys offset %d\n",
113                    __func__, whandle->offset);
114       return NULL;
115    }
116 
117    if (whandle->type != WINSYS_HANDLE_TYPE_SHARED &&
118        whandle->type != WINSYS_HANDLE_TYPE_FD) {
119       debug_printf("%s: attempt to import unsupported handle type %d\n",
120                    __func__, whandle->type);
121       return NULL;
122    }
123 
124    if (whandle->type == WINSYS_HANDLE_TYPE_SHARED)
125       ret = nouveau_bo_name_ref(dev, whandle->handle, &bo);
126    else
127       ret = nouveau_bo_prime_handle_ref(dev, whandle->handle, &bo);
128 
129    if (ret) {
130       debug_printf("%s: ref name 0x%08x failed with %d\n",
131                    __func__, whandle->handle, ret);
132       return NULL;
133    }
134 
135    *out_stride = whandle->stride;
136    return bo;
137 }
138 
139 
140 bool
nouveau_screen_bo_get_handle(struct pipe_screen * pscreen,struct nouveau_bo * bo,unsigned stride,struct winsys_handle * whandle)141 nouveau_screen_bo_get_handle(struct pipe_screen *pscreen,
142                              struct nouveau_bo *bo,
143                              unsigned stride,
144                              struct winsys_handle *whandle)
145 {
146    whandle->stride = stride;
147 
148    if (whandle->type == WINSYS_HANDLE_TYPE_SHARED) {
149       return nouveau_bo_name_get(bo, &whandle->handle) == 0;
150    } else if (whandle->type == WINSYS_HANDLE_TYPE_KMS) {
151       int fd;
152       int ret;
153 
154       /* The handle is exported in this case, but the global list of
155        * handles is in libdrm and there is no libdrm API to add
156        * handles to the list without additional side effects. The
157        * closest API available also gets a fd for the handle, which
158        * is not necessary in this case. Call it and close the fd.
159        */
160       ret = nouveau_bo_set_prime(bo, &fd);
161       if (ret != 0)
162         return false;
163 
164       close(fd);
165 
166       whandle->handle = bo->handle;
167       return true;
168    } else if (whandle->type == WINSYS_HANDLE_TYPE_FD) {
169       return nouveau_bo_set_prime(bo, (int *)&whandle->handle) == 0;
170    } else {
171       return false;
172    }
173 }
174 
175 static void
nouveau_disk_cache_create(struct nouveau_screen * screen)176 nouveau_disk_cache_create(struct nouveau_screen *screen)
177 {
178    struct mesa_sha1 ctx;
179    unsigned char sha1[20];
180    char cache_id[20 * 2 + 1];
181    uint64_t driver_flags = 0;
182 
183    _mesa_sha1_init(&ctx);
184    if (!disk_cache_get_function_identifier(nouveau_disk_cache_create,
185                                            &ctx))
186       return;
187 
188    _mesa_sha1_final(&ctx, sha1);
189    mesa_bytes_to_hex(cache_id, sha1, 20);
190 
191    driver_flags |= NOUVEAU_SHADER_CACHE_FLAGS_IR_NIR;
192 
193    screen->disk_shader_cache =
194       disk_cache_create(nouveau_screen_get_name(&screen->base),
195                         cache_id, driver_flags);
196 }
197 
198 static void*
reserve_vma(uintptr_t start,uint64_t reserved_size)199 reserve_vma(uintptr_t start, uint64_t reserved_size)
200 {
201    void *reserved = os_mmap((void*)start, reserved_size, PROT_NONE,
202                             MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
203    if (reserved == MAP_FAILED)
204       return NULL;
205    return reserved;
206 }
207 
208 static void
nouveau_query_memory_info(struct pipe_screen * pscreen,struct pipe_memory_info * info)209 nouveau_query_memory_info(struct pipe_screen *pscreen,
210                           struct pipe_memory_info *info)
211 {
212    const struct nouveau_screen *screen = nouveau_screen(pscreen);
213    struct nouveau_device *dev = screen->device;
214 
215    info->total_device_memory = dev->vram_size / 1024;
216    info->total_staging_memory = dev->gart_size / 1024;
217 
218    info->avail_device_memory = dev->vram_limit / 1024;
219    info->avail_staging_memory = dev->gart_limit / 1024;
220 }
221 
222 static void
nouveau_pushbuf_cb(struct nouveau_pushbuf * push)223 nouveau_pushbuf_cb(struct nouveau_pushbuf *push)
224 {
225    struct nouveau_pushbuf_priv *p = (struct nouveau_pushbuf_priv *)push->user_priv;
226 
227    if (p->context)
228       p->context->kick_notify(p->context);
229    else
230       _nouveau_fence_update(p->screen, true);
231 
232    NOUVEAU_DRV_STAT(p->screen, pushbuf_count, 1);
233 }
234 
235 int
nouveau_pushbuf_create(struct nouveau_screen * screen,struct nouveau_context * context,struct nouveau_client * client,struct nouveau_object * chan,int nr,uint32_t size,struct nouveau_pushbuf ** push)236 nouveau_pushbuf_create(struct nouveau_screen *screen, struct nouveau_context *context,
237                        struct nouveau_client *client, struct nouveau_object *chan, int nr,
238                        uint32_t size, struct nouveau_pushbuf **push)
239 {
240    int ret;
241    ret = nouveau_pushbuf_new(client, chan, nr, size, push);
242    if (ret)
243       return ret;
244 
245    struct nouveau_pushbuf_priv *p = MALLOC_STRUCT(nouveau_pushbuf_priv);
246    if (!p) {
247       nouveau_pushbuf_del(push);
248       return -ENOMEM;
249    }
250    p->screen = screen;
251    p->context = context;
252    (*push)->kick_notify = nouveau_pushbuf_cb;
253    (*push)->user_priv = p;
254    return 0;
255 }
256 
257 void
nouveau_pushbuf_destroy(struct nouveau_pushbuf ** push)258 nouveau_pushbuf_destroy(struct nouveau_pushbuf **push)
259 {
260    if (!*push)
261       return;
262    FREE((*push)->user_priv);
263    nouveau_pushbuf_del(push);
264 }
265 
266 static int
nouveau_screen_get_fd(struct pipe_screen * pscreen)267 nouveau_screen_get_fd(struct pipe_screen *pscreen)
268 {
269    const struct nouveau_screen *screen = nouveau_screen(pscreen);
270 
271    return screen->drm->fd;
272 }
273 
274 static void
nouveau_driver_uuid(struct pipe_screen * screen,char * uuid)275 nouveau_driver_uuid(struct pipe_screen *screen, char *uuid)
276 {
277    const char* driver = PACKAGE_VERSION MESA_GIT_SHA1;
278    struct mesa_sha1 sha1_ctx;
279    uint8_t sha1[20];
280 
281    _mesa_sha1_init(&sha1_ctx);
282    _mesa_sha1_update(&sha1_ctx, driver, strlen(driver));
283    _mesa_sha1_final(&sha1_ctx, sha1);
284    memcpy(uuid, sha1, PIPE_UUID_SIZE);
285 }
286 
287 static void
nouveau_device_uuid(struct pipe_screen * pscreen,char * uuid)288 nouveau_device_uuid(struct pipe_screen *pscreen, char *uuid)
289 {
290    const struct nouveau_screen *screen = nouveau_screen(pscreen);
291    nv_device_uuid(&screen->device->info, (void *)uuid, PIPE_UUID_SIZE, false);
292 }
293 
294 int
nouveau_screen_init(struct nouveau_screen * screen,struct nouveau_device * dev)295 nouveau_screen_init(struct nouveau_screen *screen, struct nouveau_device *dev)
296 {
297    struct pipe_screen *pscreen = &screen->base;
298    struct nv04_fifo nv04_data = { .vram = 0xbeef0201, .gart = 0xbeef0202 };
299    struct nvc0_fifo nvc0_data = { };
300    struct nve0_fifo nve0_data = { .engine = NOUVEAU_FIFO_ENGINE_GR };
301    uint64_t time;
302    int size, ret;
303    void *data;
304    union nouveau_bo_config mm_config;
305 
306    glsl_type_singleton_init_or_ref();
307 
308    char *nv_dbg = getenv("NOUVEAU_MESA_DEBUG");
309    if (nv_dbg)
310       nouveau_mesa_debug = atoi(nv_dbg);
311 
312    screen->force_enable_cl = debug_get_bool_option("NOUVEAU_ENABLE_CL", false);
313    screen->disable_fences = debug_get_bool_option("NOUVEAU_DISABLE_FENCES", false);
314 
315    /* These must be set before any failure is possible, as the cleanup
316     * paths assume they're responsible for deleting them.
317     */
318    screen->drm = nouveau_drm(&dev->object);
319    screen->device = dev;
320 
321    /*
322     * this is initialized to 1 in nouveau_drm_screen_create after screen
323     * is fully constructed and added to the global screen list.
324     */
325    screen->refcount = -1;
326 
327    if (dev->chipset < 0xc0) {
328       data = &nv04_data;
329       size = sizeof(nv04_data);
330    } else if (dev->chipset < 0xe0) {
331       data = &nvc0_data;
332       size = sizeof(nvc0_data);
333    } else {
334       data = &nve0_data;
335       size = sizeof(nve0_data);
336    }
337 
338    bool enable_svm = debug_get_bool_option("NOUVEAU_SVM", false);
339    screen->has_svm = false;
340    /* we only care about HMM with OpenCL enabled */
341    if (dev->chipset > 0x130 && enable_svm) {
342       /* Before being able to enable SVM we need to carve out some memory for
343        * driver bo allocations. Let's just base the size on the available VRAM.
344        *
345        * 40 bit is the biggest we care about and for 32 bit systems we don't
346        * want to allocate all of the available memory either.
347        *
348        * Also we align the size we want to reserve to the next POT to make use
349        * of hugepages.
350        */
351       const int vram_shift = util_logbase2_ceil64(dev->vram_size);
352       const int limit_bit =
353          MIN2(sizeof(void*) * 8 - 1, NV_GENERIC_VM_LIMIT_SHIFT);
354       screen->svm_cutout_size =
355          BITFIELD64_BIT(MIN2(sizeof(void*) == 4 ? 26 : NV_GENERIC_VM_LIMIT_SHIFT, vram_shift));
356 
357       size_t start = screen->svm_cutout_size;
358       do {
359          screen->svm_cutout = reserve_vma(start, screen->svm_cutout_size);
360          if (!screen->svm_cutout) {
361             start += screen->svm_cutout_size;
362             continue;
363          }
364 
365          struct drm_nouveau_svm_init svm_args = {
366             .unmanaged_addr = (uintptr_t)screen->svm_cutout,
367             .unmanaged_size = screen->svm_cutout_size,
368          };
369 
370          ret = drmCommandWrite(screen->drm->fd, DRM_NOUVEAU_SVM_INIT,
371                                &svm_args, sizeof(svm_args));
372          screen->has_svm = !ret;
373          if (!screen->has_svm)
374             os_munmap(screen->svm_cutout, screen->svm_cutout_size);
375          break;
376       } while ((start + screen->svm_cutout_size) < BITFIELD64_MASK(limit_bit));
377    }
378 
379    switch (dev->chipset) {
380    case 0x0ea: /* TK1, GK20A */
381    case 0x12b: /* TX1, GM20B */
382    case 0x13b: /* TX2, GP10B */
383       screen->tegra_sector_layout = true;
384       break;
385    default:
386       /* Xavier's GPU and everything else */
387       screen->tegra_sector_layout = false;
388       break;
389    }
390 
391    /*
392     * Set default VRAM domain if not overridden
393     */
394    if (!screen->vram_domain) {
395       if (dev->vram_size > 0)
396          screen->vram_domain = NOUVEAU_BO_VRAM;
397       else
398          screen->vram_domain = NOUVEAU_BO_GART;
399    }
400 
401    ret = nouveau_object_new(&dev->object, 0, NOUVEAU_FIFO_CHANNEL_CLASS,
402                             data, size, &screen->channel);
403    if (ret)
404       goto err;
405 
406    ret = nouveau_client_new(screen->device, &screen->client);
407    if (ret)
408       goto err;
409    ret = nouveau_pushbuf_create(screen, NULL, screen->client, screen->channel,
410                                 4, 512 * 1024, &screen->pushbuf);
411    if (ret)
412       goto err;
413 
414    /* getting CPU time first appears to be more accurate */
415    screen->cpu_gpu_time_delta = os_time_get();
416 
417    ret = nouveau_getparam(dev, NOUVEAU_GETPARAM_PTIMER_TIME, &time);
418    if (!ret)
419       screen->cpu_gpu_time_delta = time - screen->cpu_gpu_time_delta * 1000;
420 
421    snprintf(screen->chipset_name, sizeof(screen->chipset_name), "NV%02X", dev->chipset);
422    pscreen->get_name = nouveau_screen_get_name;
423    pscreen->get_screen_fd = nouveau_screen_get_fd;
424    pscreen->get_vendor = nouveau_screen_get_vendor;
425    pscreen->get_device_vendor = nouveau_screen_get_device_vendor;
426    pscreen->get_disk_shader_cache = nouveau_screen_get_disk_shader_cache;
427 
428    pscreen->get_timestamp = nouveau_screen_get_timestamp;
429 
430    pscreen->fence_reference = nouveau_screen_fence_ref;
431    pscreen->fence_finish = nouveau_screen_fence_finish;
432 
433    pscreen->query_memory_info = nouveau_query_memory_info;
434    pscreen->get_driver_uuid = nouveau_driver_uuid;
435    pscreen->get_device_uuid = nouveau_device_uuid;
436 
437    nouveau_disk_cache_create(screen);
438 
439    screen->transfer_pushbuf_threshold = 192;
440    screen->lowmem_bindings = PIPE_BIND_GLOBAL; /* gallium limit */
441    screen->vidmem_bindings =
442       PIPE_BIND_RENDER_TARGET | PIPE_BIND_DEPTH_STENCIL |
443       PIPE_BIND_DISPLAY_TARGET | PIPE_BIND_SCANOUT |
444       PIPE_BIND_CURSOR |
445       PIPE_BIND_SAMPLER_VIEW |
446       PIPE_BIND_SHADER_BUFFER | PIPE_BIND_SHADER_IMAGE |
447       PIPE_BIND_COMPUTE_RESOURCE |
448       PIPE_BIND_GLOBAL;
449    screen->sysmem_bindings =
450       PIPE_BIND_SAMPLER_VIEW | PIPE_BIND_STREAM_OUTPUT |
451       PIPE_BIND_COMMAND_ARGS_BUFFER;
452 
453    screen->is_uma = dev->info.type != NV_DEVICE_TYPE_DIS;
454 
455    memset(&mm_config, 0, sizeof(mm_config));
456    nouveau_fence_list_init(&screen->fence);
457 
458    screen->mm_GART = nouveau_mm_create(dev,
459                                        NOUVEAU_BO_GART | NOUVEAU_BO_MAP,
460                                        &mm_config);
461    screen->mm_VRAM = nouveau_mm_create(dev, NOUVEAU_BO_VRAM, &mm_config);
462 
463    return 0;
464 
465 err:
466    if (screen->svm_cutout)
467       os_munmap(screen->svm_cutout, screen->svm_cutout_size);
468    return ret;
469 }
470 
471 void
nouveau_screen_fini(struct nouveau_screen * screen)472 nouveau_screen_fini(struct nouveau_screen *screen)
473 {
474    int fd = screen->drm->fd;
475 
476    glsl_type_singleton_decref();
477    if (screen->has_svm)
478       os_munmap(screen->svm_cutout, screen->svm_cutout_size);
479 
480    nouveau_mm_destroy(screen->mm_GART);
481    nouveau_mm_destroy(screen->mm_VRAM);
482 
483    nouveau_pushbuf_destroy(&screen->pushbuf);
484 
485    nouveau_client_del(&screen->client);
486    nouveau_object_del(&screen->channel);
487 
488    nouveau_device_del(&screen->device);
489    nouveau_drm_del(&screen->drm);
490    close(fd);
491 
492    disk_cache_destroy(screen->disk_shader_cache);
493    nouveau_fence_list_destroy(&screen->fence);
494 }
495 
496 static void
nouveau_set_debug_callback(struct pipe_context * pipe,const struct util_debug_callback * cb)497 nouveau_set_debug_callback(struct pipe_context *pipe,
498                            const struct util_debug_callback *cb)
499 {
500    struct nouveau_context *context = nouveau_context(pipe);
501 
502    if (cb)
503       context->debug = *cb;
504    else
505       memset(&context->debug, 0, sizeof(context->debug));
506 }
507 
508 int
nouveau_context_init(struct nouveau_context * context,struct nouveau_screen * screen)509 nouveau_context_init(struct nouveau_context *context, struct nouveau_screen *screen)
510 {
511    int ret;
512 
513    context->pipe.set_debug_callback = nouveau_set_debug_callback;
514    context->screen = screen;
515 
516    ret = nouveau_client_new(screen->device, &context->client);
517    if (ret)
518       return ret;
519 
520    ret = nouveau_pushbuf_create(screen, context, context->client, screen->channel,
521                                 4, 512 * 1024, &context->pushbuf);
522    if (ret)
523       return ret;
524 
525    return 0;
526 }
527