• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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       return SQTT_GFXIP_LEVEL_GFXIP_11_0;
357    default:
358       unreachable("Invalid gfx level");
359    }
360 }
361 
ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)362 static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)
363 {
364    switch (vram_type) {
365    case AMD_VRAM_TYPE_UNKNOWN:
366       return SQTT_MEMORY_TYPE_UNKNOWN;
367    case AMD_VRAM_TYPE_DDR2:
368       return SQTT_MEMORY_TYPE_DDR2;
369    case AMD_VRAM_TYPE_DDR3:
370       return SQTT_MEMORY_TYPE_DDR3;
371    case AMD_VRAM_TYPE_DDR4:
372       return SQTT_MEMORY_TYPE_DDR4;
373    case AMD_VRAM_TYPE_DDR5:
374       return SQTT_MEMORY_TYPE_DDR5;
375    case AMD_VRAM_TYPE_GDDR3:
376       return SQTT_MEMORY_TYPE_GDDR3;
377    case AMD_VRAM_TYPE_GDDR4:
378       return SQTT_MEMORY_TYPE_GDDR4;
379    case AMD_VRAM_TYPE_GDDR5:
380       return SQTT_MEMORY_TYPE_GDDR5;
381    case AMD_VRAM_TYPE_GDDR6:
382       return SQTT_MEMORY_TYPE_GDDR6;
383    case AMD_VRAM_TYPE_HBM:
384       return SQTT_MEMORY_TYPE_HBM;
385    case AMD_VRAM_TYPE_LPDDR4:
386       return SQTT_MEMORY_TYPE_LPDDR4;
387    case AMD_VRAM_TYPE_LPDDR5:
388       return SQTT_MEMORY_TYPE_LPDDR5;
389    default:
390       unreachable("Invalid vram type");
391    }
392 }
393 
ac_sqtt_fill_asic_info(const struct radeon_info * rad_info,struct sqtt_file_chunk_asic_info * chunk)394 static void ac_sqtt_fill_asic_info(const struct radeon_info *rad_info,
395                                    struct sqtt_file_chunk_asic_info *chunk)
396 {
397    bool has_wave32 = rad_info->gfx_level >= GFX10;
398 
399    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
400    chunk->header.chunk_id.index = 0;
401    chunk->header.major_version = 0;
402    chunk->header.minor_version = 5;
403    chunk->header.size_in_bytes = sizeof(*chunk);
404 
405    chunk->flags = 0;
406 
407    /* All chips older than GFX9 are affected by the "SPI not
408     * differentiating pkr_id for newwave commands" bug.
409     */
410    if (rad_info->gfx_level < GFX9)
411       chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
412 
413    /* Only GFX9+ support PS1 events. */
414    if (rad_info->gfx_level >= GFX9)
415       chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
416 
417    chunk->trace_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000ull;
418    chunk->trace_memory_clock = rad_info->memory_freq_mhz * 1000000ull;
419 
420    /* RGP gets very confused if these clocks are 0. The numbers here are for profile_peak on
421     * VGH since that is the chips where we've seen the need for this workaround. */
422    if (!chunk->trace_shader_core_clock)
423       chunk->trace_shader_core_clock = 1300000000;
424    if (!chunk->trace_memory_clock)
425       chunk->trace_memory_clock = 687000000;
426 
427    chunk->device_id = rad_info->pci_id;
428    chunk->device_revision_id = rad_info->pci_rev_id;
429    chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd * (has_wave32 ? 2 : 1);
430    chunk->sgprs_per_simd = rad_info->num_physical_sgprs_per_simd;
431    chunk->shader_engines = rad_info->max_se;
432    chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa * rad_info->max_sa_per_se;
433    chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit;
434    chunk->wavefronts_per_simd = rad_info->max_waves_per_simd;
435 
436    chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc;
437    chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity * (has_wave32 ? 2 : 1);
438    chunk->minimum_sgpr_alloc = rad_info->min_sgpr_alloc;
439    chunk->sgpr_alloc_granularity = rad_info->sgpr_alloc_granularity;
440 
441    chunk->hardware_contexts = 8;
442    chunk->gpu_type =
443       rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
444    chunk->gfxip_level = ac_gfx_level_to_sqtt_gfxip_level(rad_info->gfx_level);
445    chunk->gpu_index = 0;
446 
447    chunk->max_number_of_dedicated_cus = 0;
448    chunk->ce_ram_size = 0;
449    chunk->ce_ram_size_graphics = 0;
450    chunk->ce_ram_size_compute = 0;
451 
452    chunk->vram_bus_width = rad_info->memory_bus_width;
453    chunk->vram_size = (uint64_t)rad_info->vram_size_kb * 1024;
454    chunk->l2_cache_size = rad_info->l2_cache_size;
455    chunk->l1_cache_size = rad_info->tcp_cache_size;
456    chunk->lds_size = rad_info->lds_size_per_workgroup;
457    if (rad_info->gfx_level >= GFX10) {
458       /* RGP expects the LDS size in CU mode. */
459       chunk->lds_size /= 2;
460    }
461 
462    strncpy(chunk->gpu_name, rad_info->name, SQTT_GPU_NAME_MAX_SIZE - 1);
463 
464    chunk->alu_per_clock = 0.0;
465    chunk->texture_per_clock = 0.0;
466    chunk->prims_per_clock = rad_info->max_se;
467    if (rad_info->gfx_level == GFX10)
468       chunk->prims_per_clock *= 2;
469    chunk->pixels_per_clock = 0.0;
470 
471    chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
472    chunk->max_shader_core_clock = rad_info->max_gpu_freq_mhz * 1000000;
473    chunk->max_memory_clock = rad_info->memory_freq_mhz * 1000000;
474    chunk->memory_ops_per_clock = ac_memory_ops_per_clock(rad_info->vram_type);
475    chunk->memory_chip_type = ac_vram_type_to_sqtt_memory_type(rad_info->vram_type);
476    chunk->lds_granularity = rad_info->lds_encode_granularity;
477 
478    for (unsigned se = 0; se < AMD_MAX_SE; se++) {
479       for (unsigned sa = 0; sa < AMD_MAX_SA_PER_SE; sa++) {
480          chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
481       }
482    }
483 
484    chunk->gl1_cache_size = rad_info->l1_cache_size;
485    chunk->instruction_cache_size = rad_info->sqc_inst_cache_size;
486    chunk->scalar_cache_size = rad_info->sqc_scalar_cache_size;
487    chunk->mall_cache_size = rad_info->l3_cache_size_mb * 1024 * 1024;
488 }
489 
490 /**
491  * SQTT API info.
492  */
493 enum sqtt_api_type
494 {
495    SQTT_API_TYPE_DIRECTX_12,
496    SQTT_API_TYPE_VULKAN,
497    SQTT_API_TYPE_GENERIC,
498    SQTT_API_TYPE_OPENCL
499 };
500 
501 enum sqtt_instruction_trace_mode
502 {
503    SQTT_INSTRUCTION_TRACE_DISABLED = 0x0,
504    SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
505    SQTT_INSTRUCTION_TRACE_API_PSO = 0x2,
506 };
507 
508 enum sqtt_profiling_mode
509 {
510    SQTT_PROFILING_MODE_PRESENT = 0x0,
511    SQTT_PROFILING_MODE_USER_MARKERS = 0x1,
512    SQTT_PROFILING_MODE_INDEX = 0x2,
513    SQTT_PROFILING_MODE_TAG = 0x3,
514 };
515 
516 union sqtt_profiling_mode_data {
517    struct {
518       char start[256];
519       char end[256];
520    } user_marker_profiling_data;
521 
522    struct {
523       uint32_t start;
524       uint32_t end;
525    } index_profiling_data;
526 
527    struct {
528       uint32_t begin_hi;
529       uint32_t begin_lo;
530       uint32_t end_hi;
531       uint32_t end_lo;
532    } tag_profiling_data;
533 };
534 
535 union sqtt_instruction_trace_data {
536    struct {
537       uint64_t api_pso_filter;
538    } api_pso_data;
539 
540    struct {
541       uint32_t mask;
542    } shader_engine_filter;
543 };
544 
545 struct sqtt_file_chunk_api_info {
546    struct sqtt_file_chunk_header header;
547    enum sqtt_api_type api_type;
548    uint16_t major_version;
549    uint16_t minor_version;
550    enum sqtt_profiling_mode profiling_mode;
551    uint32_t reserved;
552    union sqtt_profiling_mode_data profiling_mode_data;
553    enum sqtt_instruction_trace_mode instruction_trace_mode;
554    uint32_t reserved2;
555    union sqtt_instruction_trace_data instruction_trace_data;
556 };
557 
558 static_assert(sizeof(struct sqtt_file_chunk_api_info) == 560,
559               "sqtt_file_chunk_api_info doesn't match RGP spec");
560 
ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info * chunk)561 static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
562 {
563    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO;
564    chunk->header.chunk_id.index = 0;
565    chunk->header.major_version = 0;
566    chunk->header.minor_version = 2;
567    chunk->header.size_in_bytes = sizeof(*chunk);
568 
569    chunk->api_type = SQTT_API_TYPE_VULKAN;
570    chunk->major_version = 0;
571    chunk->minor_version = 0;
572    chunk->profiling_mode = SQTT_PROFILING_MODE_PRESENT;
573    chunk->instruction_trace_mode = SQTT_INSTRUCTION_TRACE_DISABLED;
574 }
575 
576 struct sqtt_code_object_database_record {
577    uint32_t size;
578 };
579 
580 struct sqtt_file_chunk_code_object_database {
581    struct sqtt_file_chunk_header header;
582    uint32_t offset;
583    uint32_t flags;
584    uint32_t size;
585    uint32_t record_count;
586 };
587 
588 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)589 ac_sqtt_fill_code_object(const struct rgp_code_object *rgp_code_object,
590                          struct sqtt_file_chunk_code_object_database *chunk, size_t file_offset,
591                          uint32_t chunk_size)
592 {
593    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE;
594    chunk->header.chunk_id.index = 0;
595    chunk->header.major_version = 0;
596    chunk->header.minor_version = 0;
597    chunk->header.size_in_bytes = chunk_size;
598    chunk->offset = file_offset;
599    chunk->flags = 0;
600    chunk->size = chunk_size;
601    chunk->record_count = rgp_code_object->record_count;
602 }
603 
604 struct sqtt_code_object_loader_events_record {
605    uint32_t loader_event_type;
606    uint32_t reserved;
607    uint64_t base_address;
608    uint64_t code_object_hash[2];
609    uint64_t time_stamp;
610 };
611 
612 struct sqtt_file_chunk_code_object_loader_events {
613    struct sqtt_file_chunk_header header;
614    uint32_t offset;
615    uint32_t flags;
616    uint32_t record_size;
617    uint32_t record_count;
618 };
619 
620 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)621 ac_sqtt_fill_loader_events(const struct rgp_loader_events *rgp_loader_events,
622                            struct sqtt_file_chunk_code_object_loader_events *chunk,
623                            size_t file_offset)
624 {
625    chunk->header.chunk_id.type =
626                                SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS;
627    chunk->header.chunk_id.index = 0;
628    chunk->header.major_version = 1;
629    chunk->header.minor_version = 0;
630    chunk->header.size_in_bytes = (rgp_loader_events->record_count *
631                                  sizeof(struct sqtt_code_object_loader_events_record)) +
632                                  sizeof(*chunk);
633    chunk->offset = file_offset;
634    chunk->flags = 0;
635    chunk->record_size = sizeof(struct sqtt_code_object_loader_events_record);
636    chunk->record_count = rgp_loader_events->record_count;
637 }
638 struct sqtt_pso_correlation_record {
639    uint64_t api_pso_hash;
640    uint64_t pipeline_hash[2];
641    char api_level_obj_name[64];
642 };
643 
644 struct sqtt_file_chunk_pso_correlation {
645    struct sqtt_file_chunk_header header;
646    uint32_t offset;
647    uint32_t flags;
648    uint32_t record_size;
649    uint32_t record_count;
650 };
651 
652 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)653 ac_sqtt_fill_pso_correlation(const struct rgp_pso_correlation *rgp_pso_correlation,
654                              struct sqtt_file_chunk_pso_correlation *chunk, size_t file_offset)
655 {
656    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION;
657    chunk->header.chunk_id.index = 0;
658    chunk->header.major_version = 0;
659    chunk->header.minor_version = 0;
660    chunk->header.size_in_bytes = (rgp_pso_correlation->record_count *
661                                  sizeof(struct sqtt_pso_correlation_record)) +
662                                  sizeof(*chunk);
663    chunk->offset = file_offset;
664    chunk->flags = 0;
665    chunk->record_size = sizeof(struct sqtt_pso_correlation_record);
666    chunk->record_count = rgp_pso_correlation->record_count;
667 }
668 
669 /**
670  * SQTT desc info.
671  */
672 struct sqtt_file_chunk_sqtt_desc {
673    struct sqtt_file_chunk_header header;
674    int32_t shader_engine_index;
675    enum sqtt_version sqtt_version;
676    union {
677       struct {
678          int32_t instrumentation_version;
679       } v0;
680       struct {
681          int16_t instrumentation_spec_version;
682          int16_t instrumentation_api_version;
683          int32_t compute_unit_index;
684       } v1;
685    };
686 };
687 
688 static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
689               "sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
690 
ac_gfx_level_to_sqtt_version(enum amd_gfx_level gfx_level)691 static enum sqtt_version ac_gfx_level_to_sqtt_version(enum amd_gfx_level gfx_level)
692 {
693    switch (gfx_level) {
694    case GFX8:
695       return SQTT_VERSION_2_2;
696    case GFX9:
697       return SQTT_VERSION_2_3;
698    case GFX10:
699       return SQTT_VERSION_2_4;
700    case GFX10_3:
701       return SQTT_VERSION_2_4;
702    case GFX11:
703       return SQTT_VERSION_3_2;
704    default:
705       unreachable("Invalid gfx level");
706    }
707 }
708 
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)709 static void ac_sqtt_fill_sqtt_desc(const struct radeon_info *info,
710                                    struct sqtt_file_chunk_sqtt_desc *chunk, int32_t chunk_index,
711                                    int32_t shader_engine_index, int32_t compute_unit_index)
712 {
713    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC;
714    chunk->header.chunk_id.index = chunk_index;
715    chunk->header.major_version = 0;
716    chunk->header.minor_version = 2;
717    chunk->header.size_in_bytes = sizeof(*chunk);
718 
719    chunk->sqtt_version =
720       ac_gfx_level_to_sqtt_version(info->gfx_level);
721    chunk->shader_engine_index = shader_engine_index;
722    chunk->v1.instrumentation_spec_version = 1;
723    chunk->v1.instrumentation_api_version = 0;
724    chunk->v1.compute_unit_index = compute_unit_index;
725 }
726 
727 /**
728  * SQTT data info.
729  */
730 struct sqtt_file_chunk_sqtt_data {
731    struct sqtt_file_chunk_header header;
732    int32_t offset; /* in bytes */
733    int32_t size;   /* in bytes */
734 };
735 
736 static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
737               "sqtt_file_chunk_sqtt_data doesn't match RGP spec");
738 
ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data * chunk,int32_t chunk_index,int32_t offset,int32_t size)739 static void ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk, int32_t chunk_index,
740                                    int32_t offset, int32_t size)
741 {
742    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA;
743    chunk->header.chunk_id.index = chunk_index;
744    chunk->header.major_version = 0;
745    chunk->header.minor_version = 0;
746    chunk->header.size_in_bytes = sizeof(*chunk) + size;
747 
748    chunk->offset = sizeof(*chunk) + offset;
749    chunk->size = size;
750 }
751 
752 /**
753  * SQTT queue event timings info.
754  */
755 struct sqtt_file_chunk_queue_event_timings {
756    struct sqtt_file_chunk_header header;
757    uint32_t queue_info_table_record_count;
758    uint32_t queue_info_table_size;
759    uint32_t queue_event_table_record_count;
760    uint32_t queue_event_table_size;
761 };
762 
763 static_assert(sizeof(struct sqtt_file_chunk_queue_event_timings) == 32,
764 	      "sqtt_file_chunk_queue_event_timings doesn't match RGP spec");
765 
766 struct sqtt_queue_info_record {
767    uint64_t queue_id;
768    uint64_t queue_context;
769    struct sqtt_queue_hardware_info hardware_info;
770    uint32_t reserved;
771 };
772 
773 static_assert(sizeof(struct sqtt_queue_info_record) == 24,
774 	      "sqtt_queue_info_record doesn't match RGP spec");
775 
776 struct sqtt_queue_event_record {
777    enum sqtt_queue_event_type event_type;
778    uint32_t sqtt_cb_id;
779    uint64_t frame_index;
780    uint32_t queue_info_index;
781    uint32_t submit_sub_index;
782    uint64_t api_id;
783    uint64_t cpu_timestamp;
784    uint64_t gpu_timestamps[2];
785 };
786 
787 static_assert(sizeof(struct sqtt_queue_event_record) == 56,
788 	      "sqtt_queue_event_record doesn't match RGP spec");
789 
790 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)791 ac_sqtt_fill_queue_event_timings(const struct rgp_queue_info *rgp_queue_info,
792                                  const struct rgp_queue_event *rgp_queue_event,
793                                  struct sqtt_file_chunk_queue_event_timings *chunk)
794 {
795    unsigned queue_info_size =
796       rgp_queue_info->record_count * sizeof(struct sqtt_queue_info_record);
797    unsigned queue_event_size =
798       rgp_queue_event->record_count * sizeof(struct sqtt_queue_event_record);
799 
800    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS;
801    chunk->header.chunk_id.index = 0;
802    chunk->header.major_version = 1;
803    chunk->header.minor_version = 1;
804    chunk->header.size_in_bytes = queue_info_size + queue_event_size +
805                                  sizeof(*chunk);
806 
807    chunk->queue_info_table_record_count = rgp_queue_info->record_count;
808    chunk->queue_info_table_size = queue_info_size;
809    chunk->queue_event_table_record_count = rgp_queue_event->record_count;
810    chunk->queue_event_table_size = queue_event_size;
811 }
812 
813 /**
814  * SQTT clock calibration info.
815  */
816 struct sqtt_file_chunk_clock_calibration {
817    struct sqtt_file_chunk_header header;
818    uint64_t cpu_timestamp;
819    uint64_t gpu_timestamp;
820    uint64_t reserved;
821 };
822 
823 static_assert(sizeof(struct sqtt_file_chunk_clock_calibration) == 40,
824 	      "sqtt_file_chunk_clock_calibration doesn't match RGP spec");
825 
826 static void
ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration * chunk,int32_t chunk_index)827 ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration *chunk,
828                                int32_t chunk_index)
829 {
830    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION;
831    chunk->header.chunk_id.index = chunk_index;
832    chunk->header.major_version = 0;
833    chunk->header.minor_version = 0;
834    chunk->header.size_in_bytes = sizeof(*chunk);
835 }
836 
837 /* Below values are from from llvm project
838  * llvm/include/llvm/BinaryFormat/ELF.h
839  */
840 enum elf_gfxip_level
841 {
842    EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
843    EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
844    EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
845    EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
846    EF_AMDGPU_MACH_AMDGCN_GFX1100 = 0x041,
847 };
848 
ac_gfx_level_to_elf_gfxip_level(enum amd_gfx_level gfx_level)849 static enum elf_gfxip_level ac_gfx_level_to_elf_gfxip_level(enum amd_gfx_level gfx_level)
850 {
851    switch (gfx_level) {
852    case GFX8:
853       return EF_AMDGPU_MACH_AMDGCN_GFX801;
854    case GFX9:
855       return EF_AMDGPU_MACH_AMDGCN_GFX900;
856    case GFX10:
857       return EF_AMDGPU_MACH_AMDGCN_GFX1010;
858    case GFX10_3:
859       return EF_AMDGPU_MACH_AMDGCN_GFX1030;
860    case GFX11:
861       return EF_AMDGPU_MACH_AMDGCN_GFX1100;
862    default:
863       unreachable("Invalid gfx level");
864    }
865 }
866 
867 /**
868  * SQTT SPM DB info.
869  */
870 struct sqtt_spm_counter_info {
871    enum ac_pc_gpu_block block;
872    uint32_t instance;
873    uint32_t event_index; /* index of counter within the block */
874    uint32_t data_offset; /* offset of counter from the beginning of the chunk */
875    uint32_t data_size;   /* size in bytes of a single counter data item */
876 };
877 
878 struct sqtt_file_chunk_spm_db {
879    struct sqtt_file_chunk_header header;
880    uint32_t flags;
881    uint32_t preamble_size;
882    uint32_t num_timestamps;
883    uint32_t num_spm_counter_info;
884    uint32_t spm_counter_info_size;
885    uint32_t sample_interval;
886 };
887 
888 static_assert(sizeof(struct sqtt_file_chunk_spm_db) == 40,
889               "sqtt_file_chunk_spm_db doesn't match RGP spec");
890 
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)891 static void ac_sqtt_fill_spm_db(const struct ac_spm_trace *spm_trace,
892                                 struct sqtt_file_chunk_spm_db *chunk,
893                                 uint32_t num_samples,
894                                 uint32_t chunk_size)
895 {
896    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SPM_DB;
897    chunk->header.chunk_id.index = 0;
898    chunk->header.major_version = 2;
899    chunk->header.minor_version = 0;
900    chunk->header.size_in_bytes = chunk_size;
901 
902    chunk->flags = 0;
903    chunk->preamble_size = sizeof(struct sqtt_file_chunk_spm_db);
904    chunk->num_timestamps = num_samples;
905    chunk->num_spm_counter_info = spm_trace->num_counters;
906    chunk->spm_counter_info_size = sizeof(struct sqtt_spm_counter_info);
907    chunk->sample_interval = spm_trace->sample_interval;
908 }
909 
ac_sqtt_dump_spm(const struct ac_spm_trace * spm_trace,size_t file_offset,FILE * output)910 static void ac_sqtt_dump_spm(const struct ac_spm_trace *spm_trace,
911                              size_t file_offset,
912                              FILE *output)
913 {
914    uint32_t sample_size_in_bytes = spm_trace->sample_size_in_bytes;
915    uint32_t num_samples = spm_trace->num_samples;
916    uint8_t *spm_data_ptr = (uint8_t *)spm_trace->ptr;
917    struct sqtt_file_chunk_spm_db spm_db;
918    size_t file_spm_db_offset = file_offset;
919 
920    fseek(output, sizeof(struct sqtt_file_chunk_spm_db), SEEK_CUR);
921    file_offset += sizeof(struct sqtt_file_chunk_spm_db);
922 
923    /* Skip the reserved 32 bytes of data at beginning. */
924    spm_data_ptr += 32;
925 
926    /* SPM timestamps. */
927    uint32_t sample_size_in_qwords = sample_size_in_bytes / sizeof(uint64_t);
928    uint64_t *timestamp_ptr = (uint64_t *)spm_data_ptr;
929 
930    for (uint32_t s = 0; s < num_samples; s++) {
931       uint64_t index = s * sample_size_in_qwords;
932       uint64_t timestamp = timestamp_ptr[index];
933 
934       file_offset += sizeof(timestamp);
935       fwrite(&timestamp, sizeof(timestamp), 1, output);
936    }
937 
938    /* SPM counter info. */
939    uint64_t counter_values_size = num_samples * sizeof(uint16_t);
940    uint64_t counter_values_offset = num_samples * sizeof(uint64_t) +
941                                     spm_trace->num_counters * sizeof(struct sqtt_spm_counter_info);
942 
943    for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
944       struct sqtt_spm_counter_info cntr_info = {
945          .block = spm_trace->counters[c].gpu_block,
946          .instance = spm_trace->counters[c].instance,
947          .data_offset = counter_values_offset,
948          .data_size = sizeof(uint16_t),
949          .event_index = spm_trace->counters[c].event_id,
950       };
951 
952       file_offset += sizeof(cntr_info);
953       fwrite(&cntr_info, sizeof(cntr_info), 1, output);
954 
955       counter_values_offset += counter_values_size;
956    }
957 
958    /* SPM counter values. */
959    uint32_t sample_size_in_hwords = sample_size_in_bytes / sizeof(uint16_t);
960    uint16_t *counter_values_ptr = (uint16_t *)spm_data_ptr;
961 
962    for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
963       uint64_t offset = spm_trace->counters[c].offset;
964 
965       for (uint32_t s = 0; s < num_samples; s++) {
966          uint64_t index = offset + (s * sample_size_in_hwords);
967          uint16_t value = counter_values_ptr[index];
968 
969          file_offset += sizeof(value);
970          fwrite(&value, sizeof(value), 1, output);
971       }
972    }
973 
974    /* SQTT SPM DB chunk. */
975    ac_sqtt_fill_spm_db(spm_trace, &spm_db, num_samples,
976                        file_offset - file_spm_db_offset);
977    fseek(output, file_spm_db_offset, SEEK_SET);
978    fwrite(&spm_db, sizeof(struct sqtt_file_chunk_spm_db), 1, output);
979    fseek(output, file_offset, SEEK_SET);
980 }
981 
982 #if defined(USE_LIBELF)
983 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)984 ac_sqtt_dump_data(const struct radeon_info *rad_info, struct ac_sqtt_trace *sqtt_trace,
985                   const struct ac_spm_trace *spm_trace, FILE *output)
986 {
987    struct sqtt_file_chunk_asic_info asic_info = {0};
988    struct sqtt_file_chunk_cpu_info cpu_info = {0};
989    struct sqtt_file_chunk_api_info api_info = {0};
990    struct sqtt_file_header header = {0};
991    size_t file_offset = 0;
992    const struct rgp_code_object *rgp_code_object = sqtt_trace->rgp_code_object;
993    const struct rgp_loader_events *rgp_loader_events = sqtt_trace->rgp_loader_events;
994    const struct rgp_pso_correlation *rgp_pso_correlation = sqtt_trace->rgp_pso_correlation;
995    const struct rgp_queue_info *rgp_queue_info = sqtt_trace->rgp_queue_info;
996    const struct rgp_queue_event *rgp_queue_event = sqtt_trace->rgp_queue_event;
997    const struct rgp_clock_calibration *rgp_clock_calibration = sqtt_trace->rgp_clock_calibration;
998 
999    /* SQTT header file. */
1000    ac_sqtt_fill_header(&header);
1001    file_offset += sizeof(header);
1002    fwrite(&header, sizeof(header), 1, output);
1003 
1004    /* SQTT cpu chunk. */
1005    ac_sqtt_fill_cpu_info(&cpu_info);
1006    file_offset += sizeof(cpu_info);
1007    fwrite(&cpu_info, sizeof(cpu_info), 1, output);
1008 
1009    /* SQTT asic chunk. */
1010    ac_sqtt_fill_asic_info(rad_info, &asic_info);
1011    file_offset += sizeof(asic_info);
1012    fwrite(&asic_info, sizeof(asic_info), 1, output);
1013 
1014    /* SQTT api chunk. */
1015    ac_sqtt_fill_api_info(&api_info);
1016    file_offset += sizeof(api_info);
1017    fwrite(&api_info, sizeof(api_info), 1, output);
1018 
1019     /* SQTT code object database chunk. */
1020    if (rgp_code_object->record_count) {
1021       size_t file_code_object_offset = file_offset;
1022       struct sqtt_file_chunk_code_object_database code_object;
1023       struct sqtt_code_object_database_record code_object_record;
1024       uint32_t elf_size_calc = 0;
1025       uint32_t flags = ac_gfx_level_to_elf_gfxip_level(rad_info->gfx_level);
1026 
1027       fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR);
1028       file_offset += sizeof(struct sqtt_file_chunk_code_object_database);
1029       list_for_each_entry_safe(struct rgp_code_object_record, record,
1030                                &rgp_code_object->record, list) {
1031          fseek(output, sizeof(struct sqtt_code_object_database_record), SEEK_CUR);
1032          ac_rgp_file_write_elf_object(output, file_offset +
1033                                       sizeof(struct sqtt_code_object_database_record),
1034                                       record, &elf_size_calc, flags);
1035          /* Align to 4 bytes per the RGP file spec. */
1036          code_object_record.size = ALIGN(elf_size_calc, 4);
1037          fseek(output, file_offset, SEEK_SET);
1038          fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record),
1039                 1, output);
1040          file_offset += (sizeof(struct sqtt_code_object_database_record) +
1041                          code_object_record.size);
1042          fseek(output, file_offset, SEEK_SET);
1043       }
1044       ac_sqtt_fill_code_object(rgp_code_object, &code_object,
1045                                file_code_object_offset,
1046                                file_offset - file_code_object_offset);
1047       fseek(output, file_code_object_offset, SEEK_SET);
1048       fwrite(&code_object, sizeof(struct sqtt_file_chunk_code_object_database), 1, output);
1049       fseek(output, file_offset, SEEK_SET);
1050    }
1051 
1052    /* SQTT code object loader events chunk. */
1053    if (rgp_loader_events->record_count) {
1054       struct sqtt_file_chunk_code_object_loader_events loader_events;
1055 
1056       ac_sqtt_fill_loader_events(rgp_loader_events, &loader_events,
1057                                  file_offset);
1058       fwrite(&loader_events, sizeof(struct sqtt_file_chunk_code_object_loader_events),
1059              1, output);
1060       file_offset += sizeof(struct sqtt_file_chunk_code_object_loader_events);
1061       list_for_each_entry_safe(struct rgp_loader_events_record, record,
1062                                &rgp_loader_events->record, list) {
1063          fwrite(record, sizeof(struct sqtt_code_object_loader_events_record), 1, output);
1064       }
1065       file_offset += (rgp_loader_events->record_count *
1066                       sizeof(struct sqtt_code_object_loader_events_record));
1067    }
1068 
1069    /* SQTT pso correlation chunk. */
1070    if (rgp_pso_correlation->record_count) {
1071       struct sqtt_file_chunk_pso_correlation pso_correlation;
1072 
1073       ac_sqtt_fill_pso_correlation(rgp_pso_correlation,
1074                                    &pso_correlation, file_offset);
1075       fwrite(&pso_correlation, sizeof(struct sqtt_file_chunk_pso_correlation), 1,
1076              output);
1077       file_offset += sizeof(struct sqtt_file_chunk_pso_correlation);
1078       list_for_each_entry_safe(struct rgp_pso_correlation_record, record,
1079                                &rgp_pso_correlation->record, list) {
1080          fwrite(record, sizeof(struct sqtt_pso_correlation_record),
1081                 1, output);
1082       }
1083       file_offset += (rgp_pso_correlation->record_count *
1084                       sizeof(struct sqtt_pso_correlation_record));
1085    }
1086 
1087    /* SQTT queue event timings. */
1088    if (rgp_queue_info->record_count || rgp_queue_event->record_count) {
1089       struct sqtt_file_chunk_queue_event_timings queue_event_timings;
1090 
1091       ac_sqtt_fill_queue_event_timings(rgp_queue_info, rgp_queue_event,
1092                                        &queue_event_timings);
1093       fwrite(&queue_event_timings, sizeof(struct sqtt_file_chunk_queue_event_timings), 1,
1094              output);
1095       file_offset += sizeof(struct sqtt_file_chunk_queue_event_timings);
1096 
1097       /* Queue info. */
1098       list_for_each_entry_safe(struct rgp_queue_info_record, record,
1099                                &rgp_queue_info->record, list) {
1100          fwrite(record, sizeof(struct sqtt_queue_info_record), 1, output);
1101       }
1102       file_offset += (rgp_queue_info->record_count *
1103                       sizeof(struct sqtt_queue_info_record));
1104 
1105       /* Queue event. */
1106       list_for_each_entry_safe(struct rgp_queue_event_record, record,
1107                                &rgp_queue_event->record, list) {
1108          struct sqtt_queue_event_record queue_event = {
1109             .event_type = record->event_type,
1110             .sqtt_cb_id = record->sqtt_cb_id,
1111             .frame_index = record->frame_index,
1112             .queue_info_index = record->queue_info_index,
1113             .submit_sub_index = record->submit_sub_index,
1114             .api_id = record->api_id,
1115             .cpu_timestamp = record->cpu_timestamp,
1116          };
1117 
1118          switch (queue_event.event_type)
1119          case SQTT_QUEUE_TIMING_EVENT_CMDBUF_SUBMIT: {
1120             queue_event.gpu_timestamps[0] = *record->gpu_timestamps[0];
1121             queue_event.gpu_timestamps[1] = *record->gpu_timestamps[1];
1122             break;
1123          case SQTT_QUEUE_TIMING_EVENT_PRESENT:
1124             queue_event.gpu_timestamps[0] = *record->gpu_timestamps[0];
1125             break;
1126          default:
1127             /* GPU timestamps are ignored for other queue events. */
1128             break;
1129          }
1130 
1131          fwrite(&queue_event, sizeof(struct sqtt_queue_event_record), 1, output);
1132       }
1133       file_offset += (rgp_queue_event->record_count *
1134                       sizeof(struct sqtt_queue_event_record));
1135    }
1136 
1137    /* SQTT clock calibration. */
1138    if (rgp_clock_calibration->record_count) {
1139       uint32_t num_records = 0;
1140 
1141       list_for_each_entry_safe(struct rgp_clock_calibration_record, record,
1142                                &rgp_clock_calibration->record, list) {
1143          struct sqtt_file_chunk_clock_calibration clock_calibration;
1144          memset(&clock_calibration, 0, sizeof(clock_calibration));
1145 
1146          ac_sqtt_fill_clock_calibration(&clock_calibration, num_records);
1147 
1148          clock_calibration.cpu_timestamp = record->cpu_timestamp;
1149          clock_calibration.gpu_timestamp = record->gpu_timestamp;
1150 
1151          fwrite(&clock_calibration, sizeof(struct sqtt_file_chunk_clock_calibration), 1,
1152              output);
1153          file_offset += sizeof(struct sqtt_file_chunk_clock_calibration);
1154 
1155          num_records++;
1156       }
1157    }
1158 
1159    if (sqtt_trace) {
1160       for (unsigned i = 0; i < sqtt_trace->num_traces; i++) {
1161          const struct ac_sqtt_data_se *se = &sqtt_trace->traces[i];
1162          const struct ac_sqtt_data_info *info = &se->info;
1163          struct sqtt_file_chunk_sqtt_desc desc = {0};
1164          struct sqtt_file_chunk_sqtt_data data = {0};
1165          uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
1166 
1167          /* SQTT desc chunk. */
1168          ac_sqtt_fill_sqtt_desc(rad_info, &desc, i, se->shader_engine, se->compute_unit);
1169          file_offset += sizeof(desc);
1170          fwrite(&desc, sizeof(desc), 1, output);
1171 
1172          /* SQTT data chunk. */
1173          ac_sqtt_fill_sqtt_data(&data, i, file_offset, size);
1174          file_offset += sizeof(data);
1175          fwrite(&data, sizeof(data), 1, output);
1176 
1177          /* Copy thread trace data generated by the hardware. */
1178          file_offset += size;
1179          fwrite(se->data_ptr, size, 1, output);
1180       }
1181    }
1182 
1183    if (spm_trace) {
1184       ac_sqtt_dump_spm(spm_trace, file_offset, output);
1185    }
1186 }
1187 #endif
1188 
1189 int
ac_dump_rgp_capture(const struct radeon_info * info,struct ac_sqtt_trace * sqtt_trace,const struct ac_spm_trace * spm_trace)1190 ac_dump_rgp_capture(const struct radeon_info *info, struct ac_sqtt_trace *sqtt_trace,
1191                     const struct ac_spm_trace *spm_trace)
1192 {
1193 #if !defined(USE_LIBELF)
1194    return -1;
1195 #else
1196    char filename[2048];
1197    struct tm now;
1198    time_t t;
1199    FILE *f;
1200 
1201    t = time(NULL);
1202    now = *localtime(&t);
1203 
1204    snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.%02d.rgp",
1205             util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour,
1206             now.tm_min, now.tm_sec);
1207 
1208    f = fopen(filename, "w+");
1209    if (!f)
1210       return -1;
1211 
1212    ac_sqtt_dump_data(info, sqtt_trace, spm_trace, f);
1213 
1214    fprintf(stderr, "RGP capture saved to '%s'\n", filename);
1215 
1216    fclose(f);
1217    return 0;
1218 #endif
1219 }
1220