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