1 /*
2 * Copyright 2020 Advanced Micro Devices, Inc.
3 * Copyright © 2020 Valve Corporation
4 *
5 * SPDX-License-Identifier: MIT
6 */
7 #include "ac_rgp.h"
8
9 #include "util/macros.h"
10 #include "util/os_misc.h"
11 #include "util/os_time.h"
12 #include "util/u_process.h"
13 #include "util/u_math.h"
14
15 #include "ac_spm.h"
16 #include "ac_sqtt.h"
17 #include "ac_gpu_info.h"
18 #include "amd_family.h"
19
20 #include <stdbool.h>
21 #include <string.h>
22
23 #define SQTT_FILE_MAGIC_NUMBER 0x50303042
24 #define SQTT_FILE_VERSION_MAJOR 1
25 #define SQTT_FILE_VERSION_MINOR 5
26
27 #define SQTT_GPU_NAME_MAX_SIZE 256
28 #define SQTT_MAX_NUM_SE 32
29 #define SQTT_SA_PER_SE 2
30 #define SQTT_ACTIVE_PIXEL_PACKER_MASK_DWORDS 4
31
32 enum sqtt_version
33 {
34 SQTT_VERSION_NONE = 0x0,
35 SQTT_VERSION_2_2 = 0x5, /* GFX8 */
36 SQTT_VERSION_2_3 = 0x6, /* GFX9 */
37 SQTT_VERSION_2_4 = 0x7, /* GFX10+ */
38 SQTT_VERSION_3_2 = 0xb, /* GFX11+ */
39 };
40
41 /**
42 * SQTT chunks.
43 */
44 enum sqtt_file_chunk_type
45 {
46 SQTT_FILE_CHUNK_TYPE_ASIC_INFO,
47 SQTT_FILE_CHUNK_TYPE_SQTT_DESC,
48 SQTT_FILE_CHUNK_TYPE_SQTT_DATA,
49 SQTT_FILE_CHUNK_TYPE_API_INFO,
50 SQTT_FILE_CHUNK_TYPE_RESERVED,
51 SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS,
52 SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION,
53 SQTT_FILE_CHUNK_TYPE_CPU_INFO,
54 SQTT_FILE_CHUNK_TYPE_SPM_DB,
55 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE,
56 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS,
57 SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION,
58 SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE,
59 SQTT_FILE_CHUNK_TYPE_COUNT
60 };
61
62 struct sqtt_file_chunk_id {
63 enum sqtt_file_chunk_type type : 8;
64 int32_t index : 8;
65 int32_t reserved : 16;
66 };
67
68 struct sqtt_file_chunk_header {
69 struct sqtt_file_chunk_id chunk_id;
70 uint16_t minor_version;
71 uint16_t major_version;
72 int32_t size_in_bytes;
73 int32_t padding;
74 };
75
76 /**
77 * SQTT file header.
78 */
79 struct sqtt_file_header_flags {
80 union {
81 struct {
82 uint32_t is_semaphore_queue_timing_etw : 1;
83 uint32_t no_queue_semaphore_timestamps : 1;
84 uint32_t reserved : 30;
85 };
86
87 uint32_t value;
88 };
89 };
90
91 struct sqtt_file_header {
92 uint32_t magic_number;
93 uint32_t version_major;
94 uint32_t version_minor;
95 struct sqtt_file_header_flags flags;
96 int32_t chunk_offset;
97 int32_t second;
98 int32_t minute;
99 int32_t hour;
100 int32_t day_in_month;
101 int32_t month;
102 int32_t year;
103 int32_t day_in_week;
104 int32_t day_in_year;
105 int32_t is_daylight_savings;
106 };
107
108 static_assert(sizeof(struct sqtt_file_header) == 56, "sqtt_file_header doesn't match RGP spec");
109
ac_sqtt_fill_header(struct sqtt_file_header * header)110 static void ac_sqtt_fill_header(struct sqtt_file_header *header)
111 {
112 struct tm *timep, result;
113 time_t raw_time;
114
115 header->magic_number = SQTT_FILE_MAGIC_NUMBER;
116 header->version_major = SQTT_FILE_VERSION_MAJOR;
117 header->version_minor = SQTT_FILE_VERSION_MINOR;
118 header->flags.value = 0;
119 header->flags.is_semaphore_queue_timing_etw = 1;
120 header->flags.no_queue_semaphore_timestamps = 0;
121 header->chunk_offset = sizeof(*header);
122
123 time(&raw_time);
124 timep = os_localtime(&raw_time, &result);
125
126 header->second = timep->tm_sec;
127 header->minute = timep->tm_min;
128 header->hour = timep->tm_hour;
129 header->day_in_month = timep->tm_mday;
130 header->month = timep->tm_mon;
131 header->year = timep->tm_year;
132 header->day_in_week = timep->tm_wday;
133 header->day_in_year = timep->tm_yday;
134 header->is_daylight_savings = timep->tm_isdst;
135 }
136
137 /**
138 * SQTT CPU info.
139 */
140 struct sqtt_file_chunk_cpu_info {
141 struct sqtt_file_chunk_header header;
142 uint32_t vendor_id[4];
143 uint32_t processor_brand[12];
144 uint32_t reserved[2];
145 uint64_t cpu_timestamp_freq;
146 uint32_t clock_speed;
147 uint32_t num_logical_cores;
148 uint32_t num_physical_cores;
149 uint32_t system_ram_size;
150 };
151
152 static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112,
153 "sqtt_file_chunk_cpu_info doesn't match RGP spec");
154
ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info * chunk)155 static void ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
156 {
157 uint32_t cpu_clock_speed_total = 0;
158 uint64_t system_ram_size = 0;
159 char line[1024];
160 FILE *f;
161
162 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CPU_INFO;
163 chunk->header.chunk_id.index = 0;
164 chunk->header.major_version = 0;
165 chunk->header.minor_version = 0;
166 chunk->header.size_in_bytes = sizeof(*chunk);
167
168 chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */
169
170 strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id));
171 strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand));
172 chunk->clock_speed = 0;
173 chunk->num_logical_cores = 0;
174 chunk->num_physical_cores = 0;
175 chunk->system_ram_size = 0;
176 if (os_get_total_physical_memory(&system_ram_size))
177 chunk->system_ram_size = system_ram_size / (1024 * 1024);
178
179 /* Parse cpuinfo to get more detailed information. */
180 f = fopen("/proc/cpuinfo", "r");
181 if (!f)
182 return;
183
184 while (fgets(line, sizeof(line), f)) {
185 char *str;
186
187 /* Parse vendor name. */
188 str = strstr(line, "vendor_id");
189 if (str) {
190 char *ptr = (char *)chunk->vendor_id;
191 char *v = strtok(str, ":");
192 v = strtok(NULL, ":");
193 strncpy(ptr, v + 1, sizeof(chunk->vendor_id) - 1);
194 ptr[sizeof(chunk->vendor_id) - 1] = '\0';
195 }
196
197 /* Parse processor name. */
198 str = strstr(line, "model name");
199 if (str) {
200 char *ptr = (char *)chunk->processor_brand;
201 char *v = strtok(str, ":");
202 v = strtok(NULL, ":");
203 strncpy(ptr, v + 1, sizeof(chunk->processor_brand) - 1);
204 ptr[sizeof(chunk->processor_brand) - 1] = '\0';
205 }
206
207 /* Parse the current CPU clock speed for each cores. */
208 str = strstr(line, "cpu MHz");
209 if (str) {
210 uint32_t v = 0;
211 if (sscanf(str, "cpu MHz : %d", &v) == 1)
212 cpu_clock_speed_total += v;
213 }
214
215 /* Parse the number of logical cores. */
216 str = strstr(line, "siblings");
217 if (str) {
218 uint32_t v = 0;
219 if (sscanf(str, "siblings : %d", &v) == 1)
220 chunk->num_logical_cores = v;
221 }
222
223 /* Parse the number of physical cores. */
224 str = strstr(line, "cpu cores");
225 if (str) {
226 uint32_t v = 0;
227 if (sscanf(str, "cpu cores : %d", &v) == 1)
228 chunk->num_physical_cores = v;
229 }
230 }
231
232 if (chunk->num_logical_cores)
233 chunk->clock_speed = cpu_clock_speed_total / chunk->num_logical_cores;
234
235 fclose(f);
236 }
237
238 /**
239 * SQTT ASIC info.
240 */
241 enum sqtt_file_chunk_asic_info_flags
242 {
243 SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING = (1 << 0),
244 SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1)
245 };
246
247 enum sqtt_gpu_type
248 {
249 SQTT_GPU_TYPE_UNKNOWN = 0x0,
250 SQTT_GPU_TYPE_INTEGRATED = 0x1,
251 SQTT_GPU_TYPE_DISCRETE = 0x2,
252 SQTT_GPU_TYPE_VIRTUAL = 0x3
253 };
254
255 enum sqtt_gfxip_level
256 {
257 SQTT_GFXIP_LEVEL_NONE = 0x0,
258 SQTT_GFXIP_LEVEL_GFXIP_6 = 0x1,
259 SQTT_GFXIP_LEVEL_GFXIP_7 = 0x2,
260 SQTT_GFXIP_LEVEL_GFXIP_8 = 0x3,
261 SQTT_GFXIP_LEVEL_GFXIP_8_1 = 0x4,
262 SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5,
263 SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
264 SQTT_GFXIP_LEVEL_GFXIP_10_3 = 0x9,
265 SQTT_GFXIP_LEVEL_GFXIP_11_0 = 0xc,
266 };
267
268 enum sqtt_memory_type
269 {
270 SQTT_MEMORY_TYPE_UNKNOWN = 0x0,
271 SQTT_MEMORY_TYPE_DDR = 0x1,
272 SQTT_MEMORY_TYPE_DDR2 = 0x2,
273 SQTT_MEMORY_TYPE_DDR3 = 0x3,
274 SQTT_MEMORY_TYPE_DDR4 = 0x4,
275 SQTT_MEMORY_TYPE_DDR5 = 0x5,
276 SQTT_MEMORY_TYPE_GDDR3 = 0x10,
277 SQTT_MEMORY_TYPE_GDDR4 = 0x11,
278 SQTT_MEMORY_TYPE_GDDR5 = 0x12,
279 SQTT_MEMORY_TYPE_GDDR6 = 0x13,
280 SQTT_MEMORY_TYPE_HBM = 0x20,
281 SQTT_MEMORY_TYPE_HBM2 = 0x21,
282 SQTT_MEMORY_TYPE_HBM3 = 0x22,
283 SQTT_MEMORY_TYPE_LPDDR4 = 0x30,
284 SQTT_MEMORY_TYPE_LPDDR5 = 0x31,
285 };
286
287 struct sqtt_file_chunk_asic_info {
288 struct sqtt_file_chunk_header header;
289 uint64_t flags;
290 uint64_t trace_shader_core_clock;
291 uint64_t trace_memory_clock;
292 int32_t device_id;
293 int32_t device_revision_id;
294 int32_t vgprs_per_simd;
295 int32_t sgprs_per_simd;
296 int32_t shader_engines;
297 int32_t compute_unit_per_shader_engine;
298 int32_t simd_per_compute_unit;
299 int32_t wavefronts_per_simd;
300 int32_t minimum_vgpr_alloc;
301 int32_t vgpr_alloc_granularity;
302 int32_t minimum_sgpr_alloc;
303 int32_t sgpr_alloc_granularity;
304 int32_t hardware_contexts;
305 enum sqtt_gpu_type gpu_type;
306 enum sqtt_gfxip_level gfxip_level;
307 int32_t gpu_index;
308 int32_t gds_size;
309 int32_t gds_per_shader_engine;
310 int32_t ce_ram_size;
311 int32_t ce_ram_size_graphics;
312 int32_t ce_ram_size_compute;
313 int32_t max_number_of_dedicated_cus;
314 int64_t vram_size;
315 int32_t vram_bus_width;
316 int32_t l2_cache_size;
317 int32_t l1_cache_size;
318 int32_t lds_size;
319 char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
320 float alu_per_clock;
321 float texture_per_clock;
322 float prims_per_clock;
323 float pixels_per_clock;
324 uint64_t gpu_timestamp_frequency;
325 uint64_t max_shader_core_clock;
326 uint64_t max_memory_clock;
327 uint32_t memory_ops_per_clock;
328 enum sqtt_memory_type memory_chip_type;
329 uint32_t lds_granularity;
330 uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
331 char reserved1[128];
332 uint32_t active_pixel_packer_mask[SQTT_ACTIVE_PIXEL_PACKER_MASK_DWORDS];
333 char reserved2[16];
334 uint32_t gl1_cache_size;
335 uint32_t instruction_cache_size;
336 uint32_t scalar_cache_size;
337 uint32_t mall_cache_size;
338 char padding[4];
339 };
340
341 static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 768,
342 "sqtt_file_chunk_asic_info doesn't match RGP spec");
343
ac_gfx_level_to_sqtt_gfxip_level(enum amd_gfx_level gfx_level)344 static enum sqtt_gfxip_level ac_gfx_level_to_sqtt_gfxip_level(enum amd_gfx_level gfx_level)
345 {
346 switch (gfx_level) {
347 case GFX8:
348 return SQTT_GFXIP_LEVEL_GFXIP_8;
349 case GFX9:
350 return SQTT_GFXIP_LEVEL_GFXIP_9;
351 case GFX10:
352 return SQTT_GFXIP_LEVEL_GFXIP_10_1;
353 case GFX10_3:
354 return SQTT_GFXIP_LEVEL_GFXIP_10_3;
355 case GFX11:
356 case GFX11_5:
357 return SQTT_GFXIP_LEVEL_GFXIP_11_0;
358 default:
359 unreachable("Invalid gfx level");
360 }
361 }
362
ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)363 static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)
364 {
365 switch (vram_type) {
366 case AMD_VRAM_TYPE_UNKNOWN:
367 return SQTT_MEMORY_TYPE_UNKNOWN;
368 case AMD_VRAM_TYPE_DDR2:
369 return SQTT_MEMORY_TYPE_DDR2;
370 case AMD_VRAM_TYPE_DDR3:
371 return SQTT_MEMORY_TYPE_DDR3;
372 case AMD_VRAM_TYPE_DDR4:
373 return SQTT_MEMORY_TYPE_DDR4;
374 case AMD_VRAM_TYPE_DDR5:
375 return SQTT_MEMORY_TYPE_DDR5;
376 case AMD_VRAM_TYPE_GDDR3:
377 return SQTT_MEMORY_TYPE_GDDR3;
378 case AMD_VRAM_TYPE_GDDR4:
379 return SQTT_MEMORY_TYPE_GDDR4;
380 case AMD_VRAM_TYPE_GDDR5:
381 return SQTT_MEMORY_TYPE_GDDR5;
382 case AMD_VRAM_TYPE_GDDR6:
383 return SQTT_MEMORY_TYPE_GDDR6;
384 case AMD_VRAM_TYPE_HBM:
385 return SQTT_MEMORY_TYPE_HBM;
386 case AMD_VRAM_TYPE_LPDDR4:
387 return SQTT_MEMORY_TYPE_LPDDR4;
388 case AMD_VRAM_TYPE_LPDDR5:
389 return SQTT_MEMORY_TYPE_LPDDR5;
390 default:
391 unreachable("Invalid vram type");
392 }
393 }
394
ac_sqtt_fill_asic_info(const struct radeon_info * rad_info,struct sqtt_file_chunk_asic_info * chunk)395 static void ac_sqtt_fill_asic_info(const struct radeon_info *rad_info,
396 struct sqtt_file_chunk_asic_info *chunk)
397 {
398 bool has_wave32 = rad_info->gfx_level >= GFX10;
399
400 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
401 chunk->header.chunk_id.index = 0;
402 chunk->header.major_version = 0;
403 chunk->header.minor_version = 5;
404 chunk->header.size_in_bytes = sizeof(*chunk);
405
406 chunk->flags = 0;
407
408 /* All chips older than GFX9 are affected by the "SPI not
409 * differentiating pkr_id for newwave commands" bug.
410 */
411 if (rad_info->gfx_level < GFX9)
412 chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
413
414 /* Only GFX9+ support PS1 events. */
415 if (rad_info->gfx_level >= GFX9)
416 chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
417
418 chunk->trace_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000ull;
419 chunk->trace_memory_clock = rad_info->memory_freq_mhz * 1000000ull;
420
421 /* RGP gets very confused if these clocks are 0. The numbers here are for profile_peak on
422 * VGH since that is the chips where we've seen the need for this workaround. */
423 if (!chunk->trace_shader_core_clock)
424 chunk->trace_shader_core_clock = 1300000000;
425 if (!chunk->trace_memory_clock)
426 chunk->trace_memory_clock = 687000000;
427
428 chunk->device_id = rad_info->pci_id;
429 chunk->device_revision_id = rad_info->pci_rev_id;
430 chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd * (has_wave32 ? 2 : 1);
431 chunk->sgprs_per_simd = rad_info->num_physical_sgprs_per_simd;
432 chunk->shader_engines = rad_info->max_se;
433 chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa * rad_info->max_sa_per_se;
434 chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit;
435 chunk->wavefronts_per_simd = rad_info->max_waves_per_simd;
436
437 chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc;
438 chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity * (has_wave32 ? 2 : 1);
439 chunk->minimum_sgpr_alloc = rad_info->min_sgpr_alloc;
440 chunk->sgpr_alloc_granularity = rad_info->sgpr_alloc_granularity;
441
442 chunk->hardware_contexts = 8;
443 chunk->gpu_type =
444 rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
445 chunk->gfxip_level = ac_gfx_level_to_sqtt_gfxip_level(rad_info->gfx_level);
446 chunk->gpu_index = 0;
447
448 chunk->max_number_of_dedicated_cus = 0;
449 chunk->ce_ram_size = 0;
450 chunk->ce_ram_size_graphics = 0;
451 chunk->ce_ram_size_compute = 0;
452
453 chunk->vram_bus_width = rad_info->memory_bus_width;
454 chunk->vram_size = (uint64_t)rad_info->vram_size_kb * 1024;
455 chunk->l2_cache_size = rad_info->l2_cache_size;
456 chunk->l1_cache_size = rad_info->tcp_cache_size;
457 chunk->lds_size = rad_info->lds_size_per_workgroup;
458 if (rad_info->gfx_level >= GFX10) {
459 /* RGP expects the LDS size in CU mode. */
460 chunk->lds_size /= 2;
461 }
462
463 strncpy(chunk->gpu_name, rad_info->name, SQTT_GPU_NAME_MAX_SIZE - 1);
464
465 chunk->alu_per_clock = 0.0;
466 chunk->texture_per_clock = 0.0;
467 chunk->prims_per_clock = rad_info->max_se;
468 if (rad_info->gfx_level == GFX10)
469 chunk->prims_per_clock *= 2;
470 chunk->pixels_per_clock = 0.0;
471
472 chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
473 chunk->max_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000;
474 chunk->max_memory_clock = rad_info->memory_freq_mhz * 1000000;
475 chunk->memory_ops_per_clock = ac_memory_ops_per_clock(rad_info->vram_type);
476 chunk->memory_chip_type = ac_vram_type_to_sqtt_memory_type(rad_info->vram_type);
477 chunk->lds_granularity = rad_info->lds_encode_granularity;
478
479 for (unsigned se = 0; se < AMD_MAX_SE; se++) {
480 for (unsigned sa = 0; sa < AMD_MAX_SA_PER_SE; sa++) {
481 chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
482 }
483 }
484
485 chunk->gl1_cache_size = rad_info->l1_cache_size;
486 chunk->instruction_cache_size = rad_info->sqc_inst_cache_size;
487 chunk->scalar_cache_size = rad_info->sqc_scalar_cache_size;
488 chunk->mall_cache_size = rad_info->l3_cache_size_mb * 1024 * 1024;
489 }
490
491 /**
492 * SQTT API info.
493 */
494 enum sqtt_api_type
495 {
496 SQTT_API_TYPE_DIRECTX_12,
497 SQTT_API_TYPE_VULKAN,
498 SQTT_API_TYPE_GENERIC,
499 SQTT_API_TYPE_OPENCL
500 };
501
502 enum sqtt_instruction_trace_mode
503 {
504 SQTT_INSTRUCTION_TRACE_DISABLED = 0x0,
505 SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
506 SQTT_INSTRUCTION_TRACE_API_PSO = 0x2,
507 };
508
509 enum sqtt_profiling_mode
510 {
511 SQTT_PROFILING_MODE_PRESENT = 0x0,
512 SQTT_PROFILING_MODE_USER_MARKERS = 0x1,
513 SQTT_PROFILING_MODE_INDEX = 0x2,
514 SQTT_PROFILING_MODE_TAG = 0x3,
515 };
516
517 union sqtt_profiling_mode_data {
518 struct {
519 char start[256];
520 char end[256];
521 } user_marker_profiling_data;
522
523 struct {
524 uint32_t start;
525 uint32_t end;
526 } index_profiling_data;
527
528 struct {
529 uint32_t begin_hi;
530 uint32_t begin_lo;
531 uint32_t end_hi;
532 uint32_t end_lo;
533 } tag_profiling_data;
534 };
535
536 union sqtt_instruction_trace_data {
537 struct {
538 uint64_t api_pso_filter;
539 } api_pso_data;
540
541 struct {
542 uint32_t mask;
543 } shader_engine_filter;
544 };
545
546 struct sqtt_file_chunk_api_info {
547 struct sqtt_file_chunk_header header;
548 enum sqtt_api_type api_type;
549 uint16_t major_version;
550 uint16_t minor_version;
551 enum sqtt_profiling_mode profiling_mode;
552 uint32_t reserved;
553 union sqtt_profiling_mode_data profiling_mode_data;
554 enum sqtt_instruction_trace_mode instruction_trace_mode;
555 uint32_t reserved2;
556 union sqtt_instruction_trace_data instruction_trace_data;
557 };
558
559 static_assert(sizeof(struct sqtt_file_chunk_api_info) == 560,
560 "sqtt_file_chunk_api_info doesn't match RGP spec");
561
ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info * chunk)562 static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
563 {
564 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO;
565 chunk->header.chunk_id.index = 0;
566 chunk->header.major_version = 0;
567 chunk->header.minor_version = 2;
568 chunk->header.size_in_bytes = sizeof(*chunk);
569
570 chunk->api_type = SQTT_API_TYPE_VULKAN;
571 chunk->major_version = 0;
572 chunk->minor_version = 0;
573 chunk->profiling_mode = SQTT_PROFILING_MODE_PRESENT;
574 chunk->instruction_trace_mode = SQTT_INSTRUCTION_TRACE_DISABLED;
575 }
576
577 struct sqtt_code_object_database_record {
578 uint32_t size;
579 };
580
581 struct sqtt_file_chunk_code_object_database {
582 struct sqtt_file_chunk_header header;
583 uint32_t offset;
584 uint32_t flags;
585 uint32_t size;
586 uint32_t record_count;
587 };
588
589 static void
ac_sqtt_fill_code_object(const struct rgp_code_object * rgp_code_object,struct sqtt_file_chunk_code_object_database * chunk,size_t file_offset,uint32_t chunk_size)590 ac_sqtt_fill_code_object(const struct rgp_code_object *rgp_code_object,
591 struct sqtt_file_chunk_code_object_database *chunk, size_t file_offset,
592 uint32_t chunk_size)
593 {
594 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE;
595 chunk->header.chunk_id.index = 0;
596 chunk->header.major_version = 0;
597 chunk->header.minor_version = 0;
598 chunk->header.size_in_bytes = chunk_size;
599 chunk->offset = file_offset;
600 chunk->flags = 0;
601 chunk->size = chunk_size;
602 chunk->record_count = rgp_code_object->record_count;
603 }
604
605 struct sqtt_code_object_loader_events_record {
606 uint32_t loader_event_type;
607 uint32_t reserved;
608 uint64_t base_address;
609 uint64_t code_object_hash[2];
610 uint64_t time_stamp;
611 };
612
613 struct sqtt_file_chunk_code_object_loader_events {
614 struct sqtt_file_chunk_header header;
615 uint32_t offset;
616 uint32_t flags;
617 uint32_t record_size;
618 uint32_t record_count;
619 };
620
621 static void
ac_sqtt_fill_loader_events(const struct rgp_loader_events * rgp_loader_events,struct sqtt_file_chunk_code_object_loader_events * chunk,size_t file_offset)622 ac_sqtt_fill_loader_events(const struct rgp_loader_events *rgp_loader_events,
623 struct sqtt_file_chunk_code_object_loader_events *chunk,
624 size_t file_offset)
625 {
626 chunk->header.chunk_id.type =
627 SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS;
628 chunk->header.chunk_id.index = 0;
629 chunk->header.major_version = 1;
630 chunk->header.minor_version = 0;
631 chunk->header.size_in_bytes = (rgp_loader_events->record_count *
632 sizeof(struct sqtt_code_object_loader_events_record)) +
633 sizeof(*chunk);
634 chunk->offset = file_offset;
635 chunk->flags = 0;
636 chunk->record_size = sizeof(struct sqtt_code_object_loader_events_record);
637 chunk->record_count = rgp_loader_events->record_count;
638 }
639 struct sqtt_pso_correlation_record {
640 uint64_t api_pso_hash;
641 uint64_t pipeline_hash[2];
642 char api_level_obj_name[64];
643 };
644
645 struct sqtt_file_chunk_pso_correlation {
646 struct sqtt_file_chunk_header header;
647 uint32_t offset;
648 uint32_t flags;
649 uint32_t record_size;
650 uint32_t record_count;
651 };
652
653 static void
ac_sqtt_fill_pso_correlation(const struct rgp_pso_correlation * rgp_pso_correlation,struct sqtt_file_chunk_pso_correlation * chunk,size_t file_offset)654 ac_sqtt_fill_pso_correlation(const struct rgp_pso_correlation *rgp_pso_correlation,
655 struct sqtt_file_chunk_pso_correlation *chunk, size_t file_offset)
656 {
657 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION;
658 chunk->header.chunk_id.index = 0;
659 chunk->header.major_version = 0;
660 chunk->header.minor_version = 0;
661 chunk->header.size_in_bytes = (rgp_pso_correlation->record_count *
662 sizeof(struct sqtt_pso_correlation_record)) +
663 sizeof(*chunk);
664 chunk->offset = file_offset;
665 chunk->flags = 0;
666 chunk->record_size = sizeof(struct sqtt_pso_correlation_record);
667 chunk->record_count = rgp_pso_correlation->record_count;
668 }
669
670 /**
671 * SQTT desc info.
672 */
673 struct sqtt_file_chunk_sqtt_desc {
674 struct sqtt_file_chunk_header header;
675 int32_t shader_engine_index;
676 enum sqtt_version sqtt_version;
677 union {
678 struct {
679 int32_t instrumentation_version;
680 } v0;
681 struct {
682 int16_t instrumentation_spec_version;
683 int16_t instrumentation_api_version;
684 int32_t compute_unit_index;
685 } v1;
686 };
687 };
688
689 static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
690 "sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
691
ac_gfx_level_to_sqtt_version(enum amd_gfx_level gfx_level)692 static enum sqtt_version ac_gfx_level_to_sqtt_version(enum amd_gfx_level gfx_level)
693 {
694 switch (gfx_level) {
695 case GFX8:
696 return SQTT_VERSION_2_2;
697 case GFX9:
698 return SQTT_VERSION_2_3;
699 case GFX10:
700 return SQTT_VERSION_2_4;
701 case GFX10_3:
702 return SQTT_VERSION_2_4;
703 case GFX11:
704 case GFX11_5:
705 return SQTT_VERSION_3_2;
706 default:
707 unreachable("Invalid gfx level");
708 }
709 }
710
ac_sqtt_fill_sqtt_desc(const struct radeon_info * info,struct sqtt_file_chunk_sqtt_desc * chunk,int32_t chunk_index,int32_t shader_engine_index,int32_t compute_unit_index)711 static void ac_sqtt_fill_sqtt_desc(const struct radeon_info *info,
712 struct sqtt_file_chunk_sqtt_desc *chunk, int32_t chunk_index,
713 int32_t shader_engine_index, int32_t compute_unit_index)
714 {
715 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC;
716 chunk->header.chunk_id.index = chunk_index;
717 chunk->header.major_version = 0;
718 chunk->header.minor_version = 2;
719 chunk->header.size_in_bytes = sizeof(*chunk);
720
721 chunk->sqtt_version =
722 ac_gfx_level_to_sqtt_version(info->gfx_level);
723 chunk->shader_engine_index = shader_engine_index;
724 chunk->v1.instrumentation_spec_version = 1;
725 chunk->v1.instrumentation_api_version = 0;
726 chunk->v1.compute_unit_index = compute_unit_index;
727 }
728
729 /**
730 * SQTT data info.
731 */
732 struct sqtt_file_chunk_sqtt_data {
733 struct sqtt_file_chunk_header header;
734 int32_t offset; /* in bytes */
735 int32_t size; /* in bytes */
736 };
737
738 static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
739 "sqtt_file_chunk_sqtt_data doesn't match RGP spec");
740
ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data * chunk,int32_t chunk_index,int32_t offset,int32_t size)741 static void ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk, int32_t chunk_index,
742 int32_t offset, int32_t size)
743 {
744 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA;
745 chunk->header.chunk_id.index = chunk_index;
746 chunk->header.major_version = 0;
747 chunk->header.minor_version = 0;
748 chunk->header.size_in_bytes = sizeof(*chunk) + size;
749
750 chunk->offset = sizeof(*chunk) + offset;
751 chunk->size = size;
752 }
753
754 /**
755 * SQTT queue event timings info.
756 */
757 struct sqtt_file_chunk_queue_event_timings {
758 struct sqtt_file_chunk_header header;
759 uint32_t queue_info_table_record_count;
760 uint32_t queue_info_table_size;
761 uint32_t queue_event_table_record_count;
762 uint32_t queue_event_table_size;
763 };
764
765 static_assert(sizeof(struct sqtt_file_chunk_queue_event_timings) == 32,
766 "sqtt_file_chunk_queue_event_timings doesn't match RGP spec");
767
768 struct sqtt_queue_info_record {
769 uint64_t queue_id;
770 uint64_t queue_context;
771 struct sqtt_queue_hardware_info hardware_info;
772 uint32_t reserved;
773 };
774
775 static_assert(sizeof(struct sqtt_queue_info_record) == 24,
776 "sqtt_queue_info_record doesn't match RGP spec");
777
778 struct sqtt_queue_event_record {
779 enum sqtt_queue_event_type event_type;
780 uint32_t sqtt_cb_id;
781 uint64_t frame_index;
782 uint32_t queue_info_index;
783 uint32_t submit_sub_index;
784 uint64_t api_id;
785 uint64_t cpu_timestamp;
786 uint64_t gpu_timestamps[2];
787 };
788
789 static_assert(sizeof(struct sqtt_queue_event_record) == 56,
790 "sqtt_queue_event_record doesn't match RGP spec");
791
792 static void
ac_sqtt_fill_queue_event_timings(const struct rgp_queue_info * rgp_queue_info,const struct rgp_queue_event * rgp_queue_event,struct sqtt_file_chunk_queue_event_timings * chunk)793 ac_sqtt_fill_queue_event_timings(const struct rgp_queue_info *rgp_queue_info,
794 const struct rgp_queue_event *rgp_queue_event,
795 struct sqtt_file_chunk_queue_event_timings *chunk)
796 {
797 unsigned queue_info_size =
798 rgp_queue_info->record_count * sizeof(struct sqtt_queue_info_record);
799 unsigned queue_event_size =
800 rgp_queue_event->record_count * sizeof(struct sqtt_queue_event_record);
801
802 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS;
803 chunk->header.chunk_id.index = 0;
804 chunk->header.major_version = 1;
805 chunk->header.minor_version = 1;
806 chunk->header.size_in_bytes = queue_info_size + queue_event_size +
807 sizeof(*chunk);
808
809 chunk->queue_info_table_record_count = rgp_queue_info->record_count;
810 chunk->queue_info_table_size = queue_info_size;
811 chunk->queue_event_table_record_count = rgp_queue_event->record_count;
812 chunk->queue_event_table_size = queue_event_size;
813 }
814
815 /**
816 * SQTT clock calibration info.
817 */
818 struct sqtt_file_chunk_clock_calibration {
819 struct sqtt_file_chunk_header header;
820 uint64_t cpu_timestamp;
821 uint64_t gpu_timestamp;
822 uint64_t reserved;
823 };
824
825 static_assert(sizeof(struct sqtt_file_chunk_clock_calibration) == 40,
826 "sqtt_file_chunk_clock_calibration doesn't match RGP spec");
827
828 static void
ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration * chunk,int32_t chunk_index)829 ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration *chunk,
830 int32_t chunk_index)
831 {
832 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION;
833 chunk->header.chunk_id.index = chunk_index;
834 chunk->header.major_version = 0;
835 chunk->header.minor_version = 0;
836 chunk->header.size_in_bytes = sizeof(*chunk);
837 }
838
839 /* Below values are from from llvm project
840 * llvm/include/llvm/BinaryFormat/ELF.h
841 */
842 enum elf_gfxip_level
843 {
844 EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
845 EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
846 EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
847 EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
848 EF_AMDGPU_MACH_AMDGCN_GFX1100 = 0x041,
849 };
850
ac_gfx_level_to_elf_gfxip_level(enum amd_gfx_level gfx_level)851 static enum elf_gfxip_level ac_gfx_level_to_elf_gfxip_level(enum amd_gfx_level gfx_level)
852 {
853 switch (gfx_level) {
854 case GFX8:
855 return EF_AMDGPU_MACH_AMDGCN_GFX801;
856 case GFX9:
857 return EF_AMDGPU_MACH_AMDGCN_GFX900;
858 case GFX10:
859 return EF_AMDGPU_MACH_AMDGCN_GFX1010;
860 case GFX10_3:
861 return EF_AMDGPU_MACH_AMDGCN_GFX1030;
862 case GFX11:
863 case GFX11_5:
864 return EF_AMDGPU_MACH_AMDGCN_GFX1100;
865 default:
866 unreachable("Invalid gfx level");
867 }
868 }
869
870 /**
871 * SQTT SPM DB info.
872 */
873 struct sqtt_spm_counter_info {
874 enum ac_pc_gpu_block block;
875 uint32_t instance;
876 uint32_t event_index; /* index of counter within the block */
877 uint32_t data_offset; /* offset of counter from the beginning of the chunk */
878 uint32_t data_size; /* size in bytes of a single counter data item */
879 };
880
881 struct sqtt_file_chunk_spm_db {
882 struct sqtt_file_chunk_header header;
883 uint32_t flags;
884 uint32_t preamble_size;
885 uint32_t num_timestamps;
886 uint32_t num_spm_counter_info;
887 uint32_t spm_counter_info_size;
888 uint32_t sample_interval;
889 };
890
891 static_assert(sizeof(struct sqtt_file_chunk_spm_db) == 40,
892 "sqtt_file_chunk_spm_db doesn't match RGP spec");
893
ac_sqtt_fill_spm_db(const struct ac_spm_trace * spm_trace,struct sqtt_file_chunk_spm_db * chunk,uint32_t num_samples,uint32_t chunk_size)894 static void ac_sqtt_fill_spm_db(const struct ac_spm_trace *spm_trace,
895 struct sqtt_file_chunk_spm_db *chunk,
896 uint32_t num_samples,
897 uint32_t chunk_size)
898 {
899 chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SPM_DB;
900 chunk->header.chunk_id.index = 0;
901 chunk->header.major_version = 2;
902 chunk->header.minor_version = 0;
903 chunk->header.size_in_bytes = chunk_size;
904
905 chunk->flags = 0;
906 chunk->preamble_size = sizeof(struct sqtt_file_chunk_spm_db);
907 chunk->num_timestamps = num_samples;
908 chunk->num_spm_counter_info = spm_trace->num_counters;
909 chunk->spm_counter_info_size = sizeof(struct sqtt_spm_counter_info);
910 chunk->sample_interval = spm_trace->sample_interval;
911 }
912
ac_sqtt_dump_spm(const struct ac_spm_trace * spm_trace,size_t file_offset,FILE * output)913 static void ac_sqtt_dump_spm(const struct ac_spm_trace *spm_trace,
914 size_t file_offset,
915 FILE *output)
916 {
917 uint32_t sample_size_in_bytes = spm_trace->sample_size_in_bytes;
918 uint32_t num_samples = spm_trace->num_samples;
919 uint8_t *spm_data_ptr = (uint8_t *)spm_trace->ptr;
920 struct sqtt_file_chunk_spm_db spm_db;
921 size_t file_spm_db_offset = file_offset;
922
923 fseek(output, sizeof(struct sqtt_file_chunk_spm_db), SEEK_CUR);
924 file_offset += sizeof(struct sqtt_file_chunk_spm_db);
925
926 /* Skip the reserved 32 bytes of data at beginning. */
927 spm_data_ptr += 32;
928
929 /* SPM timestamps. */
930 uint32_t sample_size_in_qwords = sample_size_in_bytes / sizeof(uint64_t);
931 uint64_t *timestamp_ptr = (uint64_t *)spm_data_ptr;
932
933 for (uint32_t s = 0; s < num_samples; s++) {
934 uint64_t index = s * sample_size_in_qwords;
935 uint64_t timestamp = timestamp_ptr[index];
936
937 file_offset += sizeof(timestamp);
938 fwrite(×tamp, sizeof(timestamp), 1, output);
939 }
940
941 /* SPM counter info. */
942 uint64_t counter_values_size = num_samples * sizeof(uint16_t);
943 uint64_t counter_values_offset = num_samples * sizeof(uint64_t) +
944 spm_trace->num_counters * sizeof(struct sqtt_spm_counter_info);
945
946 for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
947 struct sqtt_spm_counter_info cntr_info = {
948 .block = spm_trace->counters[c].gpu_block,
949 .instance = spm_trace->counters[c].instance,
950 .data_offset = counter_values_offset,
951 .data_size = sizeof(uint16_t),
952 .event_index = spm_trace->counters[c].event_id,
953 };
954
955 file_offset += sizeof(cntr_info);
956 fwrite(&cntr_info, sizeof(cntr_info), 1, output);
957
958 counter_values_offset += counter_values_size;
959 }
960
961 /* SPM counter values. */
962 uint32_t sample_size_in_hwords = sample_size_in_bytes / sizeof(uint16_t);
963 uint16_t *counter_values_ptr = (uint16_t *)spm_data_ptr;
964
965 for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
966 uint64_t offset = spm_trace->counters[c].offset;
967
968 for (uint32_t s = 0; s < num_samples; s++) {
969 uint64_t index = offset + (s * sample_size_in_hwords);
970 uint16_t value = counter_values_ptr[index];
971
972 file_offset += sizeof(value);
973 fwrite(&value, sizeof(value), 1, output);
974 }
975 }
976
977 /* SQTT SPM DB chunk. */
978 ac_sqtt_fill_spm_db(spm_trace, &spm_db, num_samples,
979 file_offset - file_spm_db_offset);
980 fseek(output, file_spm_db_offset, SEEK_SET);
981 fwrite(&spm_db, sizeof(struct sqtt_file_chunk_spm_db), 1, output);
982 fseek(output, file_offset, SEEK_SET);
983 }
984
985 #if defined(USE_LIBELF)
986 static void
ac_sqtt_dump_data(const struct radeon_info * rad_info,struct ac_sqtt_trace * sqtt_trace,const struct ac_spm_trace * spm_trace,FILE * output)987 ac_sqtt_dump_data(const struct radeon_info *rad_info, struct ac_sqtt_trace *sqtt_trace,
988 const struct ac_spm_trace *spm_trace, FILE *output)
989 {
990 struct sqtt_file_chunk_asic_info asic_info = {0};
991 struct sqtt_file_chunk_cpu_info cpu_info = {0};
992 struct sqtt_file_chunk_api_info api_info = {0};
993 struct sqtt_file_header header = {0};
994 size_t file_offset = 0;
995 const struct rgp_code_object *rgp_code_object = sqtt_trace->rgp_code_object;
996 const struct rgp_loader_events *rgp_loader_events = sqtt_trace->rgp_loader_events;
997 const struct rgp_pso_correlation *rgp_pso_correlation = sqtt_trace->rgp_pso_correlation;
998 const struct rgp_queue_info *rgp_queue_info = sqtt_trace->rgp_queue_info;
999 const struct rgp_queue_event *rgp_queue_event = sqtt_trace->rgp_queue_event;
1000 const struct rgp_clock_calibration *rgp_clock_calibration = sqtt_trace->rgp_clock_calibration;
1001
1002 /* SQTT header file. */
1003 ac_sqtt_fill_header(&header);
1004 file_offset += sizeof(header);
1005 fwrite(&header, sizeof(header), 1, output);
1006
1007 /* SQTT cpu chunk. */
1008 ac_sqtt_fill_cpu_info(&cpu_info);
1009 file_offset += sizeof(cpu_info);
1010 fwrite(&cpu_info, sizeof(cpu_info), 1, output);
1011
1012 /* SQTT asic chunk. */
1013 ac_sqtt_fill_asic_info(rad_info, &asic_info);
1014 file_offset += sizeof(asic_info);
1015 fwrite(&asic_info, sizeof(asic_info), 1, output);
1016
1017 /* SQTT api chunk. */
1018 ac_sqtt_fill_api_info(&api_info);
1019 file_offset += sizeof(api_info);
1020 fwrite(&api_info, sizeof(api_info), 1, output);
1021
1022 /* SQTT code object database chunk. */
1023 if (rgp_code_object->record_count) {
1024 size_t file_code_object_offset = file_offset;
1025 struct sqtt_file_chunk_code_object_database code_object;
1026 struct sqtt_code_object_database_record code_object_record;
1027 uint32_t elf_size_calc = 0;
1028 uint32_t flags = ac_gfx_level_to_elf_gfxip_level(rad_info->gfx_level);
1029
1030 fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR);
1031 file_offset += sizeof(struct sqtt_file_chunk_code_object_database);
1032 list_for_each_entry_safe(struct rgp_code_object_record, record,
1033 &rgp_code_object->record, list) {
1034 fseek(output, sizeof(struct sqtt_code_object_database_record), SEEK_CUR);
1035 ac_rgp_file_write_elf_object(output, file_offset +
1036 sizeof(struct sqtt_code_object_database_record),
1037 record, &elf_size_calc, flags);
1038 /* Align to 4 bytes per the RGP file spec. */
1039 code_object_record.size = ALIGN(elf_size_calc, 4);
1040 fseek(output, file_offset, SEEK_SET);
1041 fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record),
1042 1, output);
1043 file_offset += (sizeof(struct sqtt_code_object_database_record) +
1044 code_object_record.size);
1045 fseek(output, file_offset, SEEK_SET);
1046 }
1047 ac_sqtt_fill_code_object(rgp_code_object, &code_object,
1048 file_code_object_offset,
1049 file_offset - file_code_object_offset);
1050 fseek(output, file_code_object_offset, SEEK_SET);
1051 fwrite(&code_object, sizeof(struct sqtt_file_chunk_code_object_database), 1, output);
1052 fseek(output, file_offset, SEEK_SET);
1053 }
1054
1055 /* SQTT code object loader events chunk. */
1056 if (rgp_loader_events->record_count) {
1057 struct sqtt_file_chunk_code_object_loader_events loader_events;
1058
1059 ac_sqtt_fill_loader_events(rgp_loader_events, &loader_events,
1060 file_offset);
1061 fwrite(&loader_events, sizeof(struct sqtt_file_chunk_code_object_loader_events),
1062 1, output);
1063 file_offset += sizeof(struct sqtt_file_chunk_code_object_loader_events);
1064 list_for_each_entry_safe(struct rgp_loader_events_record, record,
1065 &rgp_loader_events->record, list) {
1066 fwrite(record, sizeof(struct sqtt_code_object_loader_events_record), 1, output);
1067 }
1068 file_offset += (rgp_loader_events->record_count *
1069 sizeof(struct sqtt_code_object_loader_events_record));
1070 }
1071
1072 /* SQTT pso correlation chunk. */
1073 if (rgp_pso_correlation->record_count) {
1074 struct sqtt_file_chunk_pso_correlation pso_correlation;
1075
1076 ac_sqtt_fill_pso_correlation(rgp_pso_correlation,
1077 &pso_correlation, file_offset);
1078 fwrite(&pso_correlation, sizeof(struct sqtt_file_chunk_pso_correlation), 1,
1079 output);
1080 file_offset += sizeof(struct sqtt_file_chunk_pso_correlation);
1081 list_for_each_entry_safe(struct rgp_pso_correlation_record, record,
1082 &rgp_pso_correlation->record, list) {
1083 fwrite(record, sizeof(struct sqtt_pso_correlation_record),
1084 1, output);
1085 }
1086 file_offset += (rgp_pso_correlation->record_count *
1087 sizeof(struct sqtt_pso_correlation_record));
1088 }
1089
1090 /* SQTT queue event timings. */
1091 if (rgp_queue_info->record_count || rgp_queue_event->record_count) {
1092 struct sqtt_file_chunk_queue_event_timings queue_event_timings;
1093
1094 ac_sqtt_fill_queue_event_timings(rgp_queue_info, rgp_queue_event,
1095 &queue_event_timings);
1096 fwrite(&queue_event_timings, sizeof(struct sqtt_file_chunk_queue_event_timings), 1,
1097 output);
1098 file_offset += sizeof(struct sqtt_file_chunk_queue_event_timings);
1099
1100 /* Queue info. */
1101 list_for_each_entry_safe(struct rgp_queue_info_record, record,
1102 &rgp_queue_info->record, list) {
1103 fwrite(record, sizeof(struct sqtt_queue_info_record), 1, output);
1104 }
1105 file_offset += (rgp_queue_info->record_count *
1106 sizeof(struct sqtt_queue_info_record));
1107
1108 /* Queue event. */
1109 list_for_each_entry_safe(struct rgp_queue_event_record, record,
1110 &rgp_queue_event->record, list) {
1111 struct sqtt_queue_event_record queue_event = {
1112 .event_type = record->event_type,
1113 .sqtt_cb_id = record->sqtt_cb_id,
1114 .frame_index = record->frame_index,
1115 .queue_info_index = record->queue_info_index,
1116 .submit_sub_index = record->submit_sub_index,
1117 .api_id = record->api_id,
1118 .cpu_timestamp = record->cpu_timestamp,
1119 };
1120
1121 switch (queue_event.event_type)
1122 case SQTT_QUEUE_TIMING_EVENT_CMDBUF_SUBMIT: {
1123 queue_event.gpu_timestamps[0] = *record->gpu_timestamps[0];
1124 queue_event.gpu_timestamps[1] = *record->gpu_timestamps[1];
1125 break;
1126 case SQTT_QUEUE_TIMING_EVENT_PRESENT:
1127 queue_event.gpu_timestamps[0] = *record->gpu_timestamps[0];
1128 break;
1129 default:
1130 /* GPU timestamps are ignored for other queue events. */
1131 break;
1132 }
1133
1134 fwrite(&queue_event, sizeof(struct sqtt_queue_event_record), 1, output);
1135 }
1136 file_offset += (rgp_queue_event->record_count *
1137 sizeof(struct sqtt_queue_event_record));
1138 }
1139
1140 /* SQTT clock calibration. */
1141 if (rgp_clock_calibration->record_count) {
1142 uint32_t num_records = 0;
1143
1144 list_for_each_entry_safe(struct rgp_clock_calibration_record, record,
1145 &rgp_clock_calibration->record, list) {
1146 struct sqtt_file_chunk_clock_calibration clock_calibration;
1147 memset(&clock_calibration, 0, sizeof(clock_calibration));
1148
1149 ac_sqtt_fill_clock_calibration(&clock_calibration, num_records);
1150
1151 clock_calibration.cpu_timestamp = record->cpu_timestamp;
1152 clock_calibration.gpu_timestamp = record->gpu_timestamp;
1153
1154 fwrite(&clock_calibration, sizeof(struct sqtt_file_chunk_clock_calibration), 1,
1155 output);
1156 file_offset += sizeof(struct sqtt_file_chunk_clock_calibration);
1157
1158 num_records++;
1159 }
1160 }
1161
1162 if (sqtt_trace) {
1163 for (unsigned i = 0; i < sqtt_trace->num_traces; i++) {
1164 const struct ac_sqtt_data_se *se = &sqtt_trace->traces[i];
1165 const struct ac_sqtt_data_info *info = &se->info;
1166 struct sqtt_file_chunk_sqtt_desc desc = {0};
1167 struct sqtt_file_chunk_sqtt_data data = {0};
1168 uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
1169
1170 /* SQTT desc chunk. */
1171 ac_sqtt_fill_sqtt_desc(rad_info, &desc, i, se->shader_engine, se->compute_unit);
1172 file_offset += sizeof(desc);
1173 fwrite(&desc, sizeof(desc), 1, output);
1174
1175 /* SQTT data chunk. */
1176 ac_sqtt_fill_sqtt_data(&data, i, file_offset, size);
1177 file_offset += sizeof(data);
1178 fwrite(&data, sizeof(data), 1, output);
1179
1180 /* Copy thread trace data generated by the hardware. */
1181 file_offset += size;
1182 fwrite(se->data_ptr, size, 1, output);
1183 }
1184 }
1185
1186 if (spm_trace) {
1187 ac_sqtt_dump_spm(spm_trace, file_offset, output);
1188 }
1189 }
1190 #endif
1191
1192 int
ac_dump_rgp_capture(const struct radeon_info * info,struct ac_sqtt_trace * sqtt_trace,const struct ac_spm_trace * spm_trace)1193 ac_dump_rgp_capture(const struct radeon_info *info, struct ac_sqtt_trace *sqtt_trace,
1194 const struct ac_spm_trace *spm_trace)
1195 {
1196 #if !defined(USE_LIBELF)
1197 return -1;
1198 #else
1199 char filename[2048];
1200 struct tm now;
1201 time_t t;
1202 FILE *f;
1203
1204 t = time(NULL);
1205 now = *localtime(&t);
1206
1207 snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.%02d.rgp",
1208 util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour,
1209 now.tm_min, now.tm_sec);
1210
1211 f = fopen(filename, "w+");
1212 if (!f)
1213 return -1;
1214
1215 ac_sqtt_dump_data(info, sqtt_trace, spm_trace, f);
1216
1217 fprintf(stderr, "RGP capture saved to '%s'\n", filename);
1218
1219 fclose(f);
1220 return 0;
1221 #endif
1222 }
1223