xref: /aosp_15_r20/external/mesa3d/src/nouveau/winsys/nouveau_device.c (revision 6104692788411f58d303aa86923a9ff6ecaded22)
1 #include "nouveau_device.h"
2 
3 #include "nouveau_context.h"
4 
5 #include "nvidia/g_nv_name_released.h"
6 
7 #include "drm-uapi/nouveau_drm.h"
8 #include "util/hash_table.h"
9 #include "util/u_debug.h"
10 #include "util/os_file.h"
11 #include "util/os_misc.h"
12 
13 #include <fcntl.h>
14 #include "nvif/cl0080.h"
15 #include "nvif/class.h"
16 #include "nvif/ioctl.h"
17 #include <unistd.h>
18 #include <xf86drm.h>
19 
20 static const char *
name_for_chip(uint32_t dev_id,uint16_t subsystem_id,uint16_t subsystem_vendor_id)21 name_for_chip(uint32_t dev_id,
22               uint16_t subsystem_id,
23               uint16_t subsystem_vendor_id)
24 {
25    const char *name = NULL;
26    for (uint32_t i = 0; i < ARRAY_SIZE(sChipsReleased); i++) {
27       const CHIPS_RELEASED *chip = &sChipsReleased[i];
28 
29       if (dev_id != chip->devID)
30          continue;
31 
32       if (chip->subSystemID == 0 && chip->subSystemVendorID == 0) {
33          /* When subSystemID and subSystemVendorID are both 0, this is the
34           * default name for the given chip.  A more specific name may exist
35           * elsewhere in the list.
36           */
37          assert(name == NULL);
38          name = chip->name;
39          continue;
40       }
41 
42       /* If we find a specific name, return it */
43       if (chip->subSystemID == subsystem_id &&
44           chip->subSystemVendorID == subsystem_vendor_id)
45          return chip->name;
46    }
47 
48    return name;
49 }
50 
51 static uint8_t
sm_for_chipset(uint16_t chipset)52 sm_for_chipset(uint16_t chipset)
53 {
54    if (chipset >= 0x190)
55       return 89;
56    // GH100 is older than AD10X, but is SM90
57    else if (chipset >= 0x180)
58       return 90;
59    else if (chipset == 0x17b)
60       return 87;
61    else if (chipset >= 0x172)
62       return 86;
63    else if (chipset >= 0x170)
64       return 80;
65    else if (chipset >= 0x160)
66       return 75;
67    else if (chipset >= 0x14b)
68       return 72;
69    else if (chipset >= 0x140)
70       return 70;
71    else if (chipset >= 0x13b)
72       return 62;
73    else if (chipset >= 0x132)
74       return 61;
75    else if (chipset >= 0x130)
76       return 60;
77    else if (chipset >= 0x12b)
78       return 53;
79    else if (chipset >= 0x120)
80       return 52;
81    else if (chipset >= 0x110)
82       return 50;
83    // TODO: 37
84    else if (chipset >= 0x0f0)
85       return 35;
86    else if (chipset >= 0x0ea)
87       return 32;
88    else if (chipset >= 0x0e0)
89       return 30;
90    // GF110 is SM20
91    else if (chipset == 0x0c8)
92       return 20;
93    else if (chipset >= 0x0c1)
94       return 21;
95    else if (chipset >= 0x0c0)
96       return 20;
97    else if (chipset >= 0x0a3)
98       return 12;
99    // GT200 is SM13
100    else if (chipset >= 0x0a0)
101       return 13;
102    else if (chipset >= 0x080)
103       return 11;
104    // this has to be == because 0x63 is older than 0x50 and has no compute
105    else if (chipset == 0x050)
106       return 10;
107    // no compute
108    return 0x00;
109 }
110 
111 static uint8_t
max_warps_per_mp_for_sm(uint8_t sm)112 max_warps_per_mp_for_sm(uint8_t sm)
113 {
114    switch (sm) {
115    case 10:
116    case 11:
117       return 24;
118    case 12:
119    case 13:
120    case 75:
121       return 32;
122    case 20:
123    case 21:
124    case 86:
125    case 87:
126    case 89:
127       return 48;
128    case 30:
129    case 32:
130    case 35:
131    case 37:
132    case 50:
133    case 52:
134    case 53:
135    case 60:
136    case 61:
137    case 62:
138    case 70:
139    case 72:
140    case 80:
141    case 90:
142       return 64;
143    default:
144       assert(!"unkown SM version");
145       // return the biggest known value
146       return 64;
147    }
148 }
149 
150 static uint8_t
mp_per_tpc_for_chipset(uint16_t chipset)151 mp_per_tpc_for_chipset(uint16_t chipset)
152 {
153    // GP100 is special and has two, otherwise it's a Volta and newer thing to have two
154    if (chipset == 0x130 || chipset >= 0x140)
155       return 2;
156    return 1;
157 }
158 
159 static int
nouveau_ws_param(int fd,uint64_t param,uint64_t * value)160 nouveau_ws_param(int fd, uint64_t param, uint64_t *value)
161 {
162    struct drm_nouveau_getparam data = { .param = param };
163 
164    int ret = drmCommandWriteRead(fd, DRM_NOUVEAU_GETPARAM, &data, sizeof(data));
165    if (ret)
166       return ret;
167 
168    *value = data.value;
169    return 0;
170 }
171 
172 static int
nouveau_ws_device_alloc(int fd,struct nouveau_ws_device * dev)173 nouveau_ws_device_alloc(int fd, struct nouveau_ws_device *dev)
174 {
175    struct {
176       struct nvif_ioctl_v0 ioctl;
177       struct nvif_ioctl_new_v0 new;
178       struct nv_device_v0 dev;
179    } args = {
180       .ioctl = {
181          .object = 0,
182          .owner = NVIF_IOCTL_V0_OWNER_ANY,
183          .route = 0x00,
184          .type = NVIF_IOCTL_V0_NEW,
185          .version = 0,
186       },
187       .new = {
188          .handle = 0,
189          .object = (uintptr_t)dev,
190          .oclass = NV_DEVICE,
191          .route = NVIF_IOCTL_V0_ROUTE_NVIF,
192          .token = (uintptr_t)dev,
193          .version = 0,
194       },
195       .dev = {
196          .device = ~0ULL,
197       },
198    };
199 
200    return drmCommandWrite(fd, DRM_NOUVEAU_NVIF, &args, sizeof(args));
201 }
202 
203 static int
nouveau_ws_device_info(int fd,struct nouveau_ws_device * dev)204 nouveau_ws_device_info(int fd, struct nouveau_ws_device *dev)
205 {
206    struct {
207       struct nvif_ioctl_v0 ioctl;
208       struct nvif_ioctl_mthd_v0 mthd;
209       struct nv_device_info_v0 info;
210    } args = {
211       .ioctl = {
212          .object = (uintptr_t)dev,
213          .owner = NVIF_IOCTL_V0_OWNER_ANY,
214          .route = 0x00,
215          .type = NVIF_IOCTL_V0_MTHD,
216          .version = 0,
217       },
218       .mthd = {
219          .method = NV_DEVICE_V0_INFO,
220          .version = 0,
221       },
222       .info = {
223          .version = 0,
224       },
225    };
226 
227    int ret = drmCommandWriteRead(fd, DRM_NOUVEAU_NVIF, &args, sizeof(args));
228    if (ret)
229       return ret;
230 
231    dev->info.chipset = args.info.chipset;
232    dev->info.vram_size_B = args.info.ram_user;
233 
234    switch (args.info.platform) {
235    case NV_DEVICE_INFO_V0_IGP:
236       dev->info.type = NV_DEVICE_TYPE_IGP;
237       break;
238    case NV_DEVICE_INFO_V0_SOC:
239       dev->info.type = NV_DEVICE_TYPE_SOC;
240       break;
241    case NV_DEVICE_INFO_V0_PCI:
242    case NV_DEVICE_INFO_V0_AGP:
243    case NV_DEVICE_INFO_V0_PCIE:
244    default:
245       dev->info.type = NV_DEVICE_TYPE_DIS;
246       break;
247    }
248 
249    STATIC_ASSERT(sizeof(dev->info.device_name) >= sizeof(args.info.name));
250    memcpy(dev->info.device_name, args.info.name, sizeof(args.info.name));
251 
252    STATIC_ASSERT(sizeof(dev->info.chipset_name) >= sizeof(args.info.chip));
253    memcpy(dev->info.chipset_name, args.info.chip, sizeof(args.info.chip));
254 
255    return 0;
256 }
257 
258 struct nouveau_ws_device *
nouveau_ws_device_new(drmDevicePtr drm_device)259 nouveau_ws_device_new(drmDevicePtr drm_device)
260 {
261    const char *path = drm_device->nodes[DRM_NODE_RENDER];
262    struct nouveau_ws_device *device = CALLOC_STRUCT(nouveau_ws_device);
263    uint64_t value = 0;
264    drmVersionPtr ver = NULL;
265 
266    int fd = open(path, O_RDWR | O_CLOEXEC);
267    if (fd < 0)
268       goto out_open;
269 
270    ver = drmGetVersion(fd);
271    if (!ver)
272       goto out_err;
273 
274    if (strncmp("nouveau", ver->name, ver->name_len) != 0) {
275       fprintf(stderr,
276               "DRM kernel driver '%.*s' in use. NVK requires nouveau.\n",
277               ver->name_len, ver->name);
278       goto out_err;
279    }
280 
281    uint32_t version =
282       ver->version_major << 24 |
283       ver->version_minor << 8  |
284       ver->version_patchlevel;
285    drmFreeVersion(ver);
286    ver = NULL;
287 
288    if (version < 0x01000301)
289       goto out_err;
290 
291    const uint64_t KERN = NOUVEAU_WS_DEVICE_KERNEL_RESERVATION_START;
292    const uint64_t TOP = 1ull << 40;
293    struct drm_nouveau_vm_init vminit = { KERN, TOP-KERN };
294    int ret = drmCommandWrite(fd, DRM_NOUVEAU_VM_INIT, &vminit, sizeof(vminit));
295    if (ret == 0)
296       device->has_vm_bind = true;
297 
298    if (nouveau_ws_device_alloc(fd, device))
299       goto out_err;
300 
301    if (nouveau_ws_param(fd, NOUVEAU_GETPARAM_PCI_DEVICE, &value))
302       goto out_err;
303 
304    device->info.device_id = value;
305 
306    if (nouveau_ws_device_info(fd, device))
307       goto out_err;
308 
309    const char *name;
310    if (drm_device->bustype == DRM_BUS_PCI) {
311       assert(device->info.type != NV_DEVICE_TYPE_SOC);
312       assert(device->info.device_id == drm_device->deviceinfo.pci->device_id);
313 
314       device->info.pci.domain       = drm_device->businfo.pci->domain;
315       device->info.pci.bus          = drm_device->businfo.pci->bus;
316       device->info.pci.dev          = drm_device->businfo.pci->dev;
317       device->info.pci.func         = drm_device->businfo.pci->func;
318       device->info.pci.revision_id  = drm_device->deviceinfo.pci->revision_id;
319 
320       name = name_for_chip(drm_device->deviceinfo.pci->device_id,
321                            drm_device->deviceinfo.pci->subdevice_id,
322                            drm_device->deviceinfo.pci->subvendor_id);
323    } else {
324       name = name_for_chip(device->info.device_id, 0, 0);
325    }
326 
327    if (name != NULL) {
328       size_t end = sizeof(device->info.device_name) - 1;
329       strncpy(device->info.device_name, name, end);
330       device->info.device_name[end] = 0;
331    }
332 
333    device->fd = fd;
334 
335    if (nouveau_ws_param(fd, NOUVEAU_GETPARAM_EXEC_PUSH_MAX, &value))
336       device->max_push = NOUVEAU_GEM_MAX_PUSH;
337    else
338       device->max_push = value;
339 
340    if (drm_device->bustype == DRM_BUS_PCI &&
341        !nouveau_ws_param(fd, NOUVEAU_GETPARAM_VRAM_BAR_SIZE, &value))
342       device->info.bar_size_B = value;
343 
344    if (nouveau_ws_param(fd, NOUVEAU_GETPARAM_GRAPH_UNITS, &value))
345       goto out_err;
346 
347    device->info.gpc_count = (value >> 0) & 0x000000ff;
348    device->info.tpc_count = (value >> 8) & 0x0000ffff;
349 
350    struct nouveau_ws_context *tmp_ctx;
351    if (nouveau_ws_context_create(device, ~0, &tmp_ctx))
352       goto out_err;
353 
354    device->info.sm = sm_for_chipset(device->info.chipset);
355    device->info.cls_copy = tmp_ctx->copy.cls;
356    device->info.cls_eng2d = tmp_ctx->eng2d.cls;
357    device->info.cls_eng3d = tmp_ctx->eng3d.cls;
358    device->info.cls_m2mf = tmp_ctx->m2mf.cls;
359    device->info.cls_compute = tmp_ctx->compute.cls;
360 
361    // for now we hardcode those values, but in the future Nouveau could provide that information to
362    // us instead.
363    device->info.max_warps_per_mp = max_warps_per_mp_for_sm(device->info.sm);
364    device->info.mp_per_tpc = mp_per_tpc_for_chipset(device->info.chipset);
365 
366    nouveau_ws_context_destroy(tmp_ctx);
367 
368    simple_mtx_init(&device->bos_lock, mtx_plain);
369    device->bos = _mesa_pointer_hash_table_create(NULL);
370 
371    return device;
372 
373 out_err:
374    if (ver)
375       drmFreeVersion(ver);
376 out_open:
377    FREE(device);
378    close(fd);
379    return NULL;
380 }
381 
382 void
nouveau_ws_device_destroy(struct nouveau_ws_device * device)383 nouveau_ws_device_destroy(struct nouveau_ws_device *device)
384 {
385    if (!device)
386       return;
387 
388    _mesa_hash_table_destroy(device->bos, NULL);
389    simple_mtx_destroy(&device->bos_lock);
390 
391    close(device->fd);
392    FREE(device);
393 }
394 
395 uint64_t
nouveau_ws_device_vram_used(struct nouveau_ws_device * device)396 nouveau_ws_device_vram_used(struct nouveau_ws_device *device)
397 {
398    uint64_t used = 0;
399    if (nouveau_ws_param(device->fd, NOUVEAU_GETPARAM_VRAM_USED, &used))
400       return 0;
401 
402    /* Zero memory used would be very strange given that it includes kernel
403     * internal allocations.
404     */
405    assert(used > 0);
406 
407    return used;
408 }
409 
410 uint64_t
nouveau_ws_device_timestamp(struct nouveau_ws_device * device)411 nouveau_ws_device_timestamp(struct nouveau_ws_device *device)
412 {
413    uint64_t timestamp = 0;
414    if (nouveau_ws_param(device->fd, NOUVEAU_GETPARAM_PTIMER_TIME, &timestamp))
415       return 0;
416 
417    return timestamp;
418 }
419 
420 bool
nouveau_ws_device_has_tiled_bo(struct nouveau_ws_device * device)421 nouveau_ws_device_has_tiled_bo(struct nouveau_ws_device *device)
422 {
423    uint64_t has = 0;
424    if (nouveau_ws_param(device->fd, NOUVEAU_GETPARAM_HAS_VMA_TILEMODE, &has))
425       return false;
426 
427    return has != 0;
428 }
429