• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 2023 Google LLC
3  * SPDX-License-Identifier: MIT
4  */
5 
6 #include <fcntl.h>
7 #include <stdio.h>
8 #include <string.h>
9 #include <unistd.h>
10 #include <xf86drm.h>
11 #include <inttypes.h>
12 
13 #include "drm-uapi/amdgpu_drm.h"
14 #include "util/macros.h"
15 
16 static int
amdgpu_info_hw_ip_info(int fd,uint32_t type,struct drm_amdgpu_info_hw_ip * info)17 amdgpu_info_hw_ip_info(int fd, uint32_t type, struct drm_amdgpu_info_hw_ip *info)
18 {
19    struct drm_amdgpu_info arg = {
20       .return_pointer = (uint64_t)info,
21       .return_size = sizeof(*info),
22       .query = AMDGPU_INFO_HW_IP_INFO,
23       .query_hw_ip = {
24          .type = type,
25       },
26    };
27 
28    memset(info, 0, sizeof(*info));
29 
30    return drmIoctl(fd, DRM_IOCTL_AMDGPU_INFO, &arg);
31 }
32 
33 static int
amdgpu_info_fw_version(int fd,uint32_t type,struct drm_amdgpu_info_firmware * info)34 amdgpu_info_fw_version(int fd, uint32_t type, struct drm_amdgpu_info_firmware *info)
35 {
36    struct drm_amdgpu_info arg = {
37       .return_pointer = (uint64_t)info,
38       .return_size = sizeof(*info),
39       .query = AMDGPU_INFO_FW_VERSION,
40       .query_fw = {
41          .fw_type = type,
42       },
43    };
44 
45    memset(info, 0, sizeof(*info));
46 
47    return drmIoctl(fd, DRM_IOCTL_AMDGPU_INFO, &arg);
48 }
49 
50 static int
amdgpu_info_read_mmr_reg(int fd,uint32_t reg,uint32_t count,uint32_t instance,uint32_t * vals)51 amdgpu_info_read_mmr_reg(int fd, uint32_t reg, uint32_t count, uint32_t instance, uint32_t *vals)
52 {
53    struct drm_amdgpu_info arg = {
54       .return_pointer = (uint64_t)vals,
55       .return_size = sizeof(*vals) * count,
56       .query = AMDGPU_INFO_READ_MMR_REG,
57       .read_mmr_reg = {
58          .dword_offset = reg,
59          .count = count,
60          .instance = instance,
61       },
62    };
63 
64    memset(vals, 0, sizeof(*vals) * count);
65 
66    return drmIoctl(fd, DRM_IOCTL_AMDGPU_INFO, &arg);
67 }
68 
69 static int
amdgpu_info_dev_info(int fd,struct drm_amdgpu_info_device * info)70 amdgpu_info_dev_info(int fd, struct drm_amdgpu_info_device *info)
71 {
72    struct drm_amdgpu_info arg = {
73       .return_pointer = (uint64_t)info,
74       .return_size = sizeof(*info),
75       .query = AMDGPU_INFO_DEV_INFO,
76    };
77 
78    memset(info, 0, sizeof(*info));
79 
80    return drmIoctl(fd, DRM_IOCTL_AMDGPU_INFO, &arg);
81 }
82 
83 static int
amdgpu_info_memory(int fd,struct drm_amdgpu_memory_info * info)84 amdgpu_info_memory(int fd, struct drm_amdgpu_memory_info *info)
85 {
86    struct drm_amdgpu_info arg = {
87       .return_pointer = (uint64_t)info,
88       .return_size = sizeof(*info),
89       .query = AMDGPU_INFO_MEMORY,
90    };
91 
92    memset(info, 0, sizeof(*info));
93 
94    return drmIoctl(fd, DRM_IOCTL_AMDGPU_INFO, &arg);
95 }
96 
97 static void
amdgpu_dump_memory(int fd)98 amdgpu_dump_memory(int fd)
99 {
100    struct drm_amdgpu_memory_info info;
101    if (amdgpu_info_memory(fd, &info))
102       return;
103 
104    printf(".mem = {\n");
105    printf("   .vram = {\n");
106    printf("      .total_heap_size = UINT64_C(%"PRIu64"),\n", (uint64_t)info.vram.total_heap_size);
107    printf("      .usable_heap_size = UINT64_C(%"PRIu64"),\n", (uint64_t)info.vram.usable_heap_size);
108    printf("      .heap_usage = UINT64_C(%"PRIu64"),\n", (uint64_t)info.vram.heap_usage);
109    printf("      .max_allocation = UINT64_C(%"PRIu64"),\n", (uint64_t)info.vram.max_allocation);
110    printf("   },\n");
111    printf("   .cpu_accessible_vram = {\n");
112    printf("      .total_heap_size = UINT64_C(%"PRIu64"),\n",
113           (uint64_t)info.cpu_accessible_vram.total_heap_size);
114    printf("      .usable_heap_size = UINT64_C(%"PRIu64"),\n",
115           (uint64_t)info.cpu_accessible_vram.usable_heap_size);
116    printf("      .heap_usage = UINT64_C(%"PRIu64"),\n",
117           (uint64_t)info.cpu_accessible_vram.heap_usage);
118    printf("      .max_allocation = UINT64_C(%"PRIu64"),\n",
119           (uint64_t)info.cpu_accessible_vram.max_allocation);
120    printf("   },\n");
121    printf("   .gtt = {\n");
122    printf("      .total_heap_size = UINT64_C(%"PRIu64"),\n", (uint64_t)info.gtt.total_heap_size);
123    printf("      .usable_heap_size = UINT64_C(%"PRIu64"),\n", (uint64_t)info.gtt.usable_heap_size);
124    printf("      .heap_usage = UINT64_C(%"PRIu64"),\n", (uint64_t)info.gtt.heap_usage);
125    printf("      .max_allocation = UINT64_C(%"PRIu64"),\n", (uint64_t)info.gtt.max_allocation);
126    printf("   },\n");
127    printf("},\n");
128 }
129 
130 static void
amdgpu_dump_dev_info(int fd)131 amdgpu_dump_dev_info(int fd)
132 {
133    static const struct {
134       const char *name;
135       uint32_t family;
136    } families[] = {
137 #define FAMILY(x) { "AMDGPU_FAMILY_" #x, AMDGPU_FAMILY_##x }
138       /* clang-format off */
139       FAMILY(SI),
140       FAMILY(CI),
141       FAMILY(KV),
142       FAMILY(VI),
143       FAMILY(CZ),
144       FAMILY(AI),
145       FAMILY(RV),
146       FAMILY(NV),
147       FAMILY(VGH),
148       FAMILY(GC_11_0_0),
149       FAMILY(YC),
150       FAMILY(GC_11_0_1),
151       FAMILY(GC_10_3_6),
152       FAMILY(GC_10_3_7),
153    /* clang-format on */
154 #undef FAMILY
155    };
156 
157    struct drm_amdgpu_info_device info;
158    if (amdgpu_info_dev_info(fd, &info))
159       return;
160 
161    const char *family_name = NULL;
162    for (int i = 0; i < ARRAY_SIZE(families); i++) {
163       if (families[i].family == info.family) {
164          family_name = families[i].name;
165          break;
166       }
167    }
168    if (!family_name)
169       return;
170 
171    printf(".dev = {\n");
172    printf("   .device_id = 0x%04x,\n", info.device_id);
173    printf("   .chip_rev = 0x%02x,\n", info.chip_rev);
174    printf("   .external_rev = 0x%02x,\n", info.external_rev);
175    printf("   .pci_rev = 0x%02x,\n", info.pci_rev);
176 
177    printf("   .family = %s,\n", family_name);
178 
179    printf("   .num_shader_engines = %u,\n", info.num_shader_engines);
180    printf("   .num_shader_arrays_per_engine = %u,\n", info.num_shader_arrays_per_engine);
181    printf("   .gpu_counter_freq = %u,\n", info.gpu_counter_freq);
182    printf("   .max_engine_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.max_engine_clock);
183    printf("   .max_memory_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.max_memory_clock);
184    printf("   .cu_active_number = %u,\n", info.cu_active_number);
185    printf("   .cu_ao_mask = 0x%x,\n", info.cu_ao_mask);
186 
187    printf("   .cu_bitmap = {\n");
188    for (int i = 0; i < ARRAY_SIZE(info.cu_bitmap); i++) {
189       printf("      {");
190       for (int j = 0; j < ARRAY_SIZE(info.cu_bitmap[i]); j++)
191          printf(" 0x%x,", info.cu_bitmap[i][j]);
192       printf(" },\n");
193    }
194    printf("   },\n");
195 
196    printf("   .enabled_rb_pipes_mask = 0x%x,\n", info.enabled_rb_pipes_mask);
197    printf("   .num_rb_pipes = %u,\n", info.num_rb_pipes);
198    printf("   .num_hw_gfx_contexts = %u,\n", info.num_hw_gfx_contexts);
199    printf("   .pcie_gen = %u,\n", info.pcie_gen);
200    printf("   .ids_flags = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.ids_flags);
201    printf("   .virtual_address_offset = UINT64_C(0x%"PRIx64"),\n",
202           (uint64_t)info.virtual_address_offset);
203    printf("   .virtual_address_max = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.virtual_address_max);
204    printf("   .virtual_address_alignment = %u,\n", info.virtual_address_alignment);
205    printf("   .pte_fragment_size = %u,\n", info.pte_fragment_size);
206    printf("   .gart_page_size = %u,\n", info.gart_page_size);
207    printf("   .ce_ram_size = %u,\n", info.ce_ram_size);
208    printf("   .vram_type = %u,\n", info.vram_type);
209    printf("   .vram_bit_width = %u,\n", info.vram_bit_width);
210    printf("   .vce_harvest_config = %u,\n", info.vce_harvest_config);
211    printf("   .gc_double_offchip_lds_buf = %u,\n", info.gc_double_offchip_lds_buf);
212    printf("   .prim_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.prim_buf_gpu_addr);
213    printf("   .pos_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.pos_buf_gpu_addr);
214    printf("   .cntl_sb_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.cntl_sb_buf_gpu_addr);
215    printf("   .param_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.param_buf_gpu_addr);
216    printf("   .prim_buf_size = %u,\n", info.prim_buf_size);
217    printf("   .pos_buf_size = %u,\n", info.pos_buf_size);
218    printf("   .cntl_sb_buf_size = %u,\n", info.cntl_sb_buf_size);
219    printf("   .param_buf_size = %u,\n", info.param_buf_size);
220    printf("   .wave_front_size = %u,\n", info.wave_front_size);
221    printf("   .num_shader_visible_vgprs = %u,\n", info.num_shader_visible_vgprs);
222    printf("   .num_cu_per_sh = %u,\n", info.num_cu_per_sh);
223    printf("   .num_tcc_blocks = %u,\n", info.num_tcc_blocks);
224    printf("   .gs_vgt_table_depth = %u,\n", info.gs_vgt_table_depth);
225    printf("   .gs_prim_buffer_depth = %u,\n", info.gs_prim_buffer_depth);
226    printf("   .max_gs_waves_per_vgt = %u,\n", info.max_gs_waves_per_vgt);
227    printf("   .pcie_num_lanes = %u,\n", info.pcie_num_lanes);
228 
229    printf("   .cu_ao_bitmap = {\n");
230    for (int i = 0; i < ARRAY_SIZE(info.cu_ao_bitmap); i++) {
231       printf("      {");
232       for (int j = 0; j < ARRAY_SIZE(info.cu_ao_bitmap[i]); j++)
233          printf(" 0x%x,", info.cu_ao_bitmap[i][j]);
234       printf(" },\n");
235    }
236    printf("   },\n");
237 
238    printf("   .high_va_offset = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.high_va_offset);
239    printf("   .high_va_max = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.high_va_max);
240    printf("   .pa_sc_tile_steering_override = %u,\n", info.pa_sc_tile_steering_override);
241    printf("   .tcc_disabled_mask = UINT64_C(%"PRIu64"),\n", (uint64_t)info.tcc_disabled_mask);
242    printf("   .min_engine_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.min_engine_clock);
243    printf("   .min_memory_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.min_memory_clock);
244    printf("   .tcp_cache_size = %u,\n", info.tcp_cache_size);
245    printf("   .num_sqc_per_wgp = %u,\n", info.num_sqc_per_wgp);
246    printf("   .sqc_data_cache_size = %u,\n", info.sqc_data_cache_size);
247    printf("   .sqc_inst_cache_size = %u,\n", info.sqc_inst_cache_size);
248    printf("   .gl1c_cache_size = %u,\n", info.gl1c_cache_size);
249    printf("   .gl2c_cache_size = %u,\n", info.gl2c_cache_size);
250    printf("   .mall_size = UINT64_C(%"PRIu64"),\n", (uint64_t)info.mall_size);
251    printf("   .enabled_rb_pipes_mask_hi = %u,\n", info.enabled_rb_pipes_mask_hi);
252    printf("},\n");
253 }
254 
255 static void
amdgpu_dump_mmr_regs(int fd)256 amdgpu_dump_mmr_regs(int fd)
257 {
258    struct drm_amdgpu_info_device info;
259    if (amdgpu_info_dev_info(fd, &info))
260       return;
261 
262 #define READ_REG(fd, reg, cnt, instance, rec)                                                      \
263    do {                                                                                            \
264       if (rec.count + cnt > ARRAY_SIZE(rec.vals))                                                  \
265          return;                                                                                   \
266       if (amdgpu_info_read_mmr_reg(fd, reg, cnt, instance, rec.vals + rec.count))                  \
267          return;                                                                                   \
268       for (int i = 0; i < cnt; i++) {                                                              \
269          rec.regs[rec.count + i] = reg + i;                                                        \
270          rec.instances[rec.count + i] = instance;                                                  \
271       }                                                                                            \
272       rec.count += cnt;                                                                            \
273    } while (0)
274 
275    struct {
276       uint32_t regs[256];
277       uint32_t instances[256];
278       uint32_t vals[256];
279       uint32_t count;
280    } rec = { 0 };
281 
282    /* GB_ADDR_CONFIG */
283    READ_REG(fd, 0x263e, 1, 0xffffffff, rec);
284 
285    if (info.family < AMDGPU_FAMILY_AI) {
286       for (int i = 0; i < info.num_shader_engines; i++) {
287          const uint32_t instance =
288             (i << AMDGPU_INFO_MMR_SE_INDEX_SHIFT) |
289             (AMDGPU_INFO_MMR_SH_INDEX_MASK << AMDGPU_INFO_MMR_SH_INDEX_SHIFT);
290          /* CC_RB_BACKEND_DISABLE */
291          READ_REG(fd, 0x263d, 1, instance, rec);
292          /* PA_SC_RASTER_CONFIG */
293          READ_REG(fd, 0xa0d4, 1, instance, rec);
294          /* PA_SC_RASTER_CONFIG_1 */
295          if (info.family >= AMDGPU_FAMILY_CI)
296             READ_REG(fd, 0xa0d5, 1, instance, rec);
297       }
298 
299       /* MC_ARB_RAMCFG */
300       READ_REG(fd, 0x9d8, 1, 0xffffffff, rec);
301       /* GB_TILE_MODE0 */
302       READ_REG(fd, 0x2644, 32, 0xffffffff, rec);
303       /* GB_MACROTILE_MODE0 */
304       if (info.family >= AMDGPU_FAMILY_CI)
305          READ_REG(fd, 0x2664, 16, 0xffffffff, rec);
306    }
307 
308 #undef READ_REG
309 
310    printf(".mmr_regs = {\n");
311    for (int i = 0; i < rec.count; i++)
312       printf("   0x%04x, 0x%08x, 0x%08x,\n", rec.regs[i], rec.instances[i], rec.vals[i]);
313    printf("},\n");
314    printf(".mmr_reg_count = %d,\n", rec.count);
315 }
316 
317 static void
amdgpu_dump_fw_versions(int fd)318 amdgpu_dump_fw_versions(int fd)
319 {
320    static const struct {
321       const char *name;
322       uint32_t type;
323    } fw_vers[] = {
324       {
325          .name = "gfx_me",
326          .type = AMDGPU_INFO_FW_GFX_ME,
327       },
328       {
329          .name = "gfx_pfp",
330          .type = AMDGPU_INFO_FW_GFX_PFP,
331       },
332       {
333          .name = "gfx_mec",
334          .type = AMDGPU_INFO_FW_GFX_MEC,
335       },
336    };
337 
338    for (int i = 0; i < ARRAY_SIZE(fw_vers); i++) {
339       struct drm_amdgpu_info_firmware info;
340       if (amdgpu_info_fw_version(fd, fw_vers[i].type, &info))
341          continue;
342 
343       printf(".fw_%s = {\n", fw_vers[i].name);
344       printf("   .ver = %u,\n", info.ver);
345       printf("   .feature = %u,\n", info.feature);
346       printf("},\n");
347    }
348 }
349 
350 static void
amdgpu_dump_hw_ips(int fd)351 amdgpu_dump_hw_ips(int fd)
352 {
353    static const struct {
354       const char *name;
355       uint32_t type;
356    } hw_ips[] = {
357       {
358          .name = "gfx",
359          .type = AMDGPU_HW_IP_GFX,
360       },
361       {
362          .name = "compute",
363          .type = AMDGPU_HW_IP_COMPUTE,
364       },
365    };
366 
367    for (int i = 0; i < ARRAY_SIZE(hw_ips); i++) {
368       struct drm_amdgpu_info_hw_ip info;
369       if (amdgpu_info_hw_ip_info(fd, hw_ips[i].type, &info))
370          continue;
371 
372       printf(".hw_ip_%s = {\n", hw_ips[i].name);
373       printf("   .hw_ip_version_major = %u,\n", info.hw_ip_version_major);
374       printf("   .hw_ip_version_minor = %u,\n", info.hw_ip_version_minor);
375       printf("   .capabilities_flags = UINT64_C(%"PRIu64"),\n", (uint64_t)info.capabilities_flags);
376       printf("   .ib_start_alignment = %u,\n", info.ib_start_alignment);
377       printf("   .ib_size_alignment = %u,\n", info.ib_size_alignment);
378       printf("   .available_rings = 0x%x,\n", info.available_rings);
379       printf("   .ip_discovery_version = 0x%04x,\n", info.ip_discovery_version);
380       printf("},\n");
381    }
382 }
383 
384 static void
amdgpu_dump_version(int fd)385 amdgpu_dump_version(int fd)
386 {
387    const drmVersionPtr ver = drmGetVersion(fd);
388    if (!ver)
389       return;
390 
391    printf(".drm = {\n");
392    printf("   .version_major = %d,\n", ver->version_major);
393    printf("   .version_minor = %d,\n", ver->version_minor);
394    printf("   .version_patchlevel = %d,\n", ver->version_patchlevel);
395    printf("   .name = \"%s\",\n", ver->name);
396    printf("},\n");
397 
398    drmFreeVersion(ver);
399 }
400 
401 static void
amdgpu_dump_pci(drmDevicePtr dev)402 amdgpu_dump_pci(drmDevicePtr dev)
403 {
404    printf(".pci = {\n");
405    printf("   .vendor_id = 0x%04x,\n", dev->deviceinfo.pci->vendor_id);
406    printf("   .device_id = 0x%04x,\n", dev->deviceinfo.pci->device_id);
407    printf("   .subvendor_id = 0x%04x,\n", dev->deviceinfo.pci->subvendor_id);
408    printf("   .subdevice_id = 0x%04x,\n", dev->deviceinfo.pci->subdevice_id);
409    printf("   .revision_id = 0x%02x,\n", dev->deviceinfo.pci->revision_id);
410    printf("},\n");
411 }
412 
413 static void
amdgpu_dump(drmDevicePtr dev)414 amdgpu_dump(drmDevicePtr dev)
415 {
416    if (!(dev->available_nodes & (1 << DRM_NODE_RENDER)))
417       return;
418    if (dev->bustype != DRM_BUS_PCI)
419       return;
420    if (dev->deviceinfo.pci->vendor_id != 0x1002)
421       return;
422 
423    int fd = open(dev->nodes[DRM_NODE_RENDER], O_RDWR | O_CLOEXEC);
424    if (fd < 0)
425       return;
426 
427    amdgpu_dump_pci(dev);
428    amdgpu_dump_version(fd);
429    amdgpu_dump_hw_ips(fd);
430    amdgpu_dump_fw_versions(fd);
431    amdgpu_dump_mmr_regs(fd);
432    amdgpu_dump_dev_info(fd);
433    amdgpu_dump_memory(fd);
434 
435    close(fd);
436 }
437 
438 int
main()439 main()
440 {
441    drmDevicePtr devs[8];
442    const int count = drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devs, ARRAY_SIZE(devs));
443 
444    for (int i = 0; i < count; i++)
445       amdgpu_dump(devs[i]);
446 
447    drmFreeDevices(devs, count);
448 
449    return 0;
450 }
451