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 FAMILY(GC_11_5_0),
154 /* clang-format on */
155 #undef FAMILY
156 };
157
158 struct drm_amdgpu_info_device info;
159 if (amdgpu_info_dev_info(fd, &info))
160 return;
161
162 const char *family_name = NULL;
163 for (int i = 0; i < ARRAY_SIZE(families); i++) {
164 if (families[i].family == info.family) {
165 family_name = families[i].name;
166 break;
167 }
168 }
169 if (!family_name)
170 return;
171
172 printf(".dev = {\n");
173 printf(" .device_id = 0x%04x,\n", info.device_id);
174 printf(" .chip_rev = 0x%02x,\n", info.chip_rev);
175 printf(" .external_rev = 0x%02x,\n", info.external_rev);
176 printf(" .pci_rev = 0x%02x,\n", info.pci_rev);
177
178 printf(" .family = %s,\n", family_name);
179
180 printf(" .num_shader_engines = %u,\n", info.num_shader_engines);
181 printf(" .num_shader_arrays_per_engine = %u,\n", info.num_shader_arrays_per_engine);
182 printf(" .gpu_counter_freq = %u,\n", info.gpu_counter_freq);
183 printf(" .max_engine_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.max_engine_clock);
184 printf(" .max_memory_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.max_memory_clock);
185 printf(" .cu_active_number = %u,\n", info.cu_active_number);
186 printf(" .cu_ao_mask = 0x%x,\n", info.cu_ao_mask);
187
188 printf(" .cu_bitmap = {\n");
189 for (int i = 0; i < ARRAY_SIZE(info.cu_bitmap); i++) {
190 printf(" {");
191 for (int j = 0; j < ARRAY_SIZE(info.cu_bitmap[i]); j++)
192 printf(" 0x%x,", info.cu_bitmap[i][j]);
193 printf(" },\n");
194 }
195 printf(" },\n");
196
197 printf(" .enabled_rb_pipes_mask = 0x%x,\n", info.enabled_rb_pipes_mask);
198 printf(" .num_rb_pipes = %u,\n", info.num_rb_pipes);
199 printf(" .num_hw_gfx_contexts = %u,\n", info.num_hw_gfx_contexts);
200 printf(" .pcie_gen = %u,\n", info.pcie_gen);
201 printf(" .ids_flags = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.ids_flags);
202 printf(" .virtual_address_offset = UINT64_C(0x%"PRIx64"),\n",
203 (uint64_t)info.virtual_address_offset);
204 printf(" .virtual_address_max = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.virtual_address_max);
205 printf(" .virtual_address_alignment = %u,\n", info.virtual_address_alignment);
206 printf(" .pte_fragment_size = %u,\n", info.pte_fragment_size);
207 printf(" .gart_page_size = %u,\n", info.gart_page_size);
208 printf(" .ce_ram_size = %u,\n", info.ce_ram_size);
209 printf(" .vram_type = %u,\n", info.vram_type);
210 printf(" .vram_bit_width = %u,\n", info.vram_bit_width);
211 printf(" .vce_harvest_config = %u,\n", info.vce_harvest_config);
212 printf(" .gc_double_offchip_lds_buf = %u,\n", info.gc_double_offchip_lds_buf);
213 printf(" .prim_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.prim_buf_gpu_addr);
214 printf(" .pos_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.pos_buf_gpu_addr);
215 printf(" .cntl_sb_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.cntl_sb_buf_gpu_addr);
216 printf(" .param_buf_gpu_addr = UINT64_C(%"PRIu64"),\n", (uint64_t)info.param_buf_gpu_addr);
217 printf(" .prim_buf_size = %u,\n", info.prim_buf_size);
218 printf(" .pos_buf_size = %u,\n", info.pos_buf_size);
219 printf(" .cntl_sb_buf_size = %u,\n", info.cntl_sb_buf_size);
220 printf(" .param_buf_size = %u,\n", info.param_buf_size);
221 printf(" .wave_front_size = %u,\n", info.wave_front_size);
222 printf(" .num_shader_visible_vgprs = %u,\n", info.num_shader_visible_vgprs);
223 printf(" .num_cu_per_sh = %u,\n", info.num_cu_per_sh);
224 printf(" .num_tcc_blocks = %u,\n", info.num_tcc_blocks);
225 printf(" .gs_vgt_table_depth = %u,\n", info.gs_vgt_table_depth);
226 printf(" .gs_prim_buffer_depth = %u,\n", info.gs_prim_buffer_depth);
227 printf(" .max_gs_waves_per_vgt = %u,\n", info.max_gs_waves_per_vgt);
228 printf(" .pcie_num_lanes = %u,\n", info.pcie_num_lanes);
229
230 printf(" .cu_ao_bitmap = {\n");
231 for (int i = 0; i < ARRAY_SIZE(info.cu_ao_bitmap); i++) {
232 printf(" {");
233 for (int j = 0; j < ARRAY_SIZE(info.cu_ao_bitmap[i]); j++)
234 printf(" 0x%x,", info.cu_ao_bitmap[i][j]);
235 printf(" },\n");
236 }
237 printf(" },\n");
238
239 printf(" .high_va_offset = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.high_va_offset);
240 printf(" .high_va_max = UINT64_C(0x%"PRIx64"),\n", (uint64_t)info.high_va_max);
241 printf(" .pa_sc_tile_steering_override = %u,\n", info.pa_sc_tile_steering_override);
242 printf(" .tcc_disabled_mask = UINT64_C(%"PRIu64"),\n", (uint64_t)info.tcc_disabled_mask);
243 printf(" .min_engine_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.min_engine_clock);
244 printf(" .min_memory_clock = UINT64_C(%"PRIu64"),\n", (uint64_t)info.min_memory_clock);
245 printf(" .tcp_cache_size = %u,\n", info.tcp_cache_size);
246 printf(" .num_sqc_per_wgp = %u,\n", info.num_sqc_per_wgp);
247 printf(" .sqc_data_cache_size = %u,\n", info.sqc_data_cache_size);
248 printf(" .sqc_inst_cache_size = %u,\n", info.sqc_inst_cache_size);
249 printf(" .gl1c_cache_size = %u,\n", info.gl1c_cache_size);
250 printf(" .gl2c_cache_size = %u,\n", info.gl2c_cache_size);
251 printf(" .mall_size = UINT64_C(%"PRIu64"),\n", (uint64_t)info.mall_size);
252 printf(" .enabled_rb_pipes_mask_hi = %u,\n", info.enabled_rb_pipes_mask_hi);
253 printf("},\n");
254 }
255
256 static void
amdgpu_dump_mmr_regs(int fd)257 amdgpu_dump_mmr_regs(int fd)
258 {
259 struct drm_amdgpu_info_device info;
260 if (amdgpu_info_dev_info(fd, &info))
261 return;
262
263 #define READ_REG(fd, reg, cnt, instance, rec) \
264 do { \
265 if (rec.count + cnt > ARRAY_SIZE(rec.vals)) \
266 return; \
267 if (amdgpu_info_read_mmr_reg(fd, reg, cnt, instance, rec.vals + rec.count)) \
268 return; \
269 for (int i = 0; i < cnt; i++) { \
270 rec.regs[rec.count + i] = reg + i; \
271 rec.instances[rec.count + i] = instance; \
272 } \
273 rec.count += cnt; \
274 } while (0)
275
276 struct {
277 uint32_t regs[256];
278 uint32_t instances[256];
279 uint32_t vals[256];
280 uint32_t count;
281 } rec = { 0 };
282
283 /* GB_ADDR_CONFIG */
284 READ_REG(fd, 0x263e, 1, 0xffffffff, rec);
285
286 if (info.family < AMDGPU_FAMILY_AI) {
287 for (int i = 0; i < info.num_shader_engines; i++) {
288 const uint32_t instance =
289 (i << AMDGPU_INFO_MMR_SE_INDEX_SHIFT) |
290 (AMDGPU_INFO_MMR_SH_INDEX_MASK << AMDGPU_INFO_MMR_SH_INDEX_SHIFT);
291 /* CC_RB_BACKEND_DISABLE */
292 READ_REG(fd, 0x263d, 1, instance, rec);
293 /* PA_SC_RASTER_CONFIG */
294 READ_REG(fd, 0xa0d4, 1, instance, rec);
295 /* PA_SC_RASTER_CONFIG_1 */
296 if (info.family >= AMDGPU_FAMILY_CI)
297 READ_REG(fd, 0xa0d5, 1, instance, rec);
298 }
299
300 /* MC_ARB_RAMCFG */
301 READ_REG(fd, 0x9d8, 1, 0xffffffff, rec);
302 /* GB_TILE_MODE0 */
303 READ_REG(fd, 0x2644, 32, 0xffffffff, rec);
304 /* GB_MACROTILE_MODE0 */
305 if (info.family >= AMDGPU_FAMILY_CI)
306 READ_REG(fd, 0x2664, 16, 0xffffffff, rec);
307 }
308
309 #undef READ_REG
310
311 printf(".mmr_regs = {\n");
312 for (int i = 0; i < rec.count; i++)
313 printf(" 0x%04x, 0x%08x, 0x%08x,\n", rec.regs[i], rec.instances[i], rec.vals[i]);
314 printf("},\n");
315 printf(".mmr_reg_count = %d,\n", rec.count);
316 }
317
318 static void
amdgpu_dump_fw_versions(int fd)319 amdgpu_dump_fw_versions(int fd)
320 {
321 static const struct {
322 const char *name;
323 uint32_t type;
324 } fw_vers[] = {
325 {
326 .name = "gfx_me",
327 .type = AMDGPU_INFO_FW_GFX_ME,
328 },
329 {
330 .name = "gfx_pfp",
331 .type = AMDGPU_INFO_FW_GFX_PFP,
332 },
333 {
334 .name = "gfx_mec",
335 .type = AMDGPU_INFO_FW_GFX_MEC,
336 },
337 };
338
339 for (int i = 0; i < ARRAY_SIZE(fw_vers); i++) {
340 struct drm_amdgpu_info_firmware info;
341 if (amdgpu_info_fw_version(fd, fw_vers[i].type, &info))
342 continue;
343
344 printf(".fw_%s = {\n", fw_vers[i].name);
345 printf(" .ver = %u,\n", info.ver);
346 printf(" .feature = %u,\n", info.feature);
347 printf("},\n");
348 }
349 }
350
351 static void
amdgpu_dump_hw_ips(int fd)352 amdgpu_dump_hw_ips(int fd)
353 {
354 static const struct {
355 const char *name;
356 uint32_t type;
357 } hw_ips[] = {
358 {
359 .name = "gfx",
360 .type = AMDGPU_HW_IP_GFX,
361 },
362 {
363 .name = "compute",
364 .type = AMDGPU_HW_IP_COMPUTE,
365 },
366 };
367
368 for (int i = 0; i < ARRAY_SIZE(hw_ips); i++) {
369 struct drm_amdgpu_info_hw_ip info;
370 if (amdgpu_info_hw_ip_info(fd, hw_ips[i].type, &info))
371 continue;
372
373 printf(".hw_ip_%s = {\n", hw_ips[i].name);
374 printf(" .hw_ip_version_major = %u,\n", info.hw_ip_version_major);
375 printf(" .hw_ip_version_minor = %u,\n", info.hw_ip_version_minor);
376 printf(" .capabilities_flags = UINT64_C(%"PRIu64"),\n", (uint64_t)info.capabilities_flags);
377 printf(" .ib_start_alignment = %u,\n", info.ib_start_alignment);
378 printf(" .ib_size_alignment = %u,\n", info.ib_size_alignment);
379 printf(" .available_rings = 0x%x,\n", info.available_rings);
380 printf(" .ip_discovery_version = 0x%04x,\n", info.ip_discovery_version);
381 printf("},\n");
382 }
383 }
384
385 static void
amdgpu_dump_version(int fd)386 amdgpu_dump_version(int fd)
387 {
388 const drmVersionPtr ver = drmGetVersion(fd);
389 if (!ver)
390 return;
391
392 printf(".drm = {\n");
393 printf(" .version_major = %d,\n", ver->version_major);
394 printf(" .version_minor = %d,\n", ver->version_minor);
395 printf(" .version_patchlevel = %d,\n", ver->version_patchlevel);
396 printf(" .name = \"%s\",\n", ver->name);
397 printf("},\n");
398
399 drmFreeVersion(ver);
400 }
401
402 static void
amdgpu_dump_pci(drmDevicePtr dev)403 amdgpu_dump_pci(drmDevicePtr dev)
404 {
405 printf(".pci = {\n");
406 printf(" .vendor_id = 0x%04x,\n", dev->deviceinfo.pci->vendor_id);
407 printf(" .device_id = 0x%04x,\n", dev->deviceinfo.pci->device_id);
408 printf(" .subvendor_id = 0x%04x,\n", dev->deviceinfo.pci->subvendor_id);
409 printf(" .subdevice_id = 0x%04x,\n", dev->deviceinfo.pci->subdevice_id);
410 printf(" .revision_id = 0x%02x,\n", dev->deviceinfo.pci->revision_id);
411 printf("},\n");
412 }
413
414 static void
amdgpu_dump(drmDevicePtr dev)415 amdgpu_dump(drmDevicePtr dev)
416 {
417 if (!(dev->available_nodes & (1 << DRM_NODE_RENDER)))
418 return;
419 if (dev->bustype != DRM_BUS_PCI)
420 return;
421 if (dev->deviceinfo.pci->vendor_id != 0x1002)
422 return;
423
424 int fd = open(dev->nodes[DRM_NODE_RENDER], O_RDWR | O_CLOEXEC);
425 if (fd < 0)
426 return;
427
428 amdgpu_dump_pci(dev);
429 amdgpu_dump_version(fd);
430 amdgpu_dump_hw_ips(fd);
431 amdgpu_dump_fw_versions(fd);
432 amdgpu_dump_mmr_regs(fd);
433 amdgpu_dump_dev_info(fd);
434 amdgpu_dump_memory(fd);
435
436 close(fd);
437 }
438
439 int
main()440 main()
441 {
442 drmDevicePtr devs[8];
443 const int count = drmGetDevices2(DRM_DEVICE_GET_PCI_REVISION, devs, ARRAY_SIZE(devs));
444
445 for (int i = 0; i < count; i++)
446 amdgpu_dump(devs[i]);
447
448 drmFreeDevices(devs, count);
449
450 return 0;
451 }
452