• 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_sqtt.h"
33 #include "ac_gpu_info.h"
34 #ifdef _WIN32
35 #define AMDGPU_VRAM_TYPE_UNKNOWN 0
36 #define AMDGPU_VRAM_TYPE_GDDR1 1
37 #define AMDGPU_VRAM_TYPE_DDR2  2
38 #define AMDGPU_VRAM_TYPE_GDDR3 3
39 #define AMDGPU_VRAM_TYPE_GDDR4 4
40 #define AMDGPU_VRAM_TYPE_GDDR5 5
41 #define AMDGPU_VRAM_TYPE_HBM   6
42 #define AMDGPU_VRAM_TYPE_DDR3  7
43 #define AMDGPU_VRAM_TYPE_DDR4  8
44 #define AMDGPU_VRAM_TYPE_GDDR6 9
45 #define AMDGPU_VRAM_TYPE_DDR5  10
46 #else
47 #include "drm-uapi/amdgpu_drm.h"
48 #endif
49 
50 #include <stdbool.h>
51 #include <string.h>
52 
53 #define SQTT_FILE_MAGIC_NUMBER  0x50303042
54 #define SQTT_FILE_VERSION_MAJOR 1
55 #define SQTT_FILE_VERSION_MINOR 5
56 
57 #define SQTT_GPU_NAME_MAX_SIZE 256
58 #define SQTT_MAX_NUM_SE        32
59 #define SQTT_SA_PER_SE         2
60 
61 enum sqtt_version
62 {
63    SQTT_VERSION_NONE = 0x0,
64    SQTT_VERSION_1_0 = 0x1,
65    SQTT_VERSION_1_1 = 0x2,
66    SQTT_VERSION_2_0 = 0x3, /* GFX6 */
67    SQTT_VERSION_2_1 = 0x4, /* GFX7 */
68    SQTT_VERSION_2_2 = 0x5, /* GFX8 */
69    SQTT_VERSION_2_3 = 0x6, /* GFX9 */
70    SQTT_VERSION_2_4 = 0x7  /* GFX10+ */
71 };
72 
73 /**
74  * SQTT chunks.
75  */
76 enum sqtt_file_chunk_type
77 {
78    SQTT_FILE_CHUNK_TYPE_ASIC_INFO,
79    SQTT_FILE_CHUNK_TYPE_SQTT_DESC,
80    SQTT_FILE_CHUNK_TYPE_SQTT_DATA,
81    SQTT_FILE_CHUNK_TYPE_API_INFO,
82    SQTT_FILE_CHUNK_TYPE_RESERVED,
83    SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS,
84    SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION,
85    SQTT_FILE_CHUNK_TYPE_CPU_INFO,
86    SQTT_FILE_CHUNK_TYPE_SPM_DB,
87    SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE,
88    SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS,
89    SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION,
90    SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE,
91    SQTT_FILE_CHUNK_TYPE_COUNT
92 };
93 
94 struct sqtt_file_chunk_id {
95    enum sqtt_file_chunk_type type : 8;
96    int32_t index : 8;
97    int32_t reserved : 16;
98 };
99 
100 struct sqtt_file_chunk_header {
101    struct sqtt_file_chunk_id chunk_id;
102    uint16_t minor_version;
103    uint16_t major_version;
104    int32_t size_in_bytes;
105    int32_t padding;
106 };
107 
108 /**
109  * SQTT file header.
110  */
111 struct sqtt_file_header_flags {
112    union {
113       struct {
114          int32_t is_semaphore_queue_timing_etw : 1;
115          int32_t no_queue_semaphore_timestamps : 1;
116          int32_t reserved : 30;
117       };
118 
119       uint32_t value;
120    };
121 };
122 
123 struct sqtt_file_header {
124    uint32_t magic_number;
125    uint32_t version_major;
126    uint32_t version_minor;
127    struct sqtt_file_header_flags flags;
128    int32_t chunk_offset;
129    int32_t second;
130    int32_t minute;
131    int32_t hour;
132    int32_t day_in_month;
133    int32_t month;
134    int32_t year;
135    int32_t day_in_week;
136    int32_t day_in_year;
137    int32_t is_daylight_savings;
138 };
139 
140 static_assert(sizeof(struct sqtt_file_header) == 56, "sqtt_file_header doesn't match RGP spec");
141 
ac_sqtt_fill_header(struct sqtt_file_header * header)142 static void ac_sqtt_fill_header(struct sqtt_file_header *header)
143 {
144    struct tm *timep, result;
145    time_t raw_time;
146 
147    header->magic_number = SQTT_FILE_MAGIC_NUMBER;
148    header->version_major = SQTT_FILE_VERSION_MAJOR;
149    header->version_minor = SQTT_FILE_VERSION_MINOR;
150    header->flags.value = 0;
151    header->flags.is_semaphore_queue_timing_etw = 1;
152    header->flags.no_queue_semaphore_timestamps = 0;
153    header->chunk_offset = sizeof(*header);
154 
155    time(&raw_time);
156    timep = os_localtime(&raw_time, &result);
157 
158    header->second = timep->tm_sec;
159    header->minute = timep->tm_min;
160    header->hour = timep->tm_hour;
161    header->day_in_month = timep->tm_mday;
162    header->month = timep->tm_mon;
163    header->year = timep->tm_year;
164    header->day_in_week = timep->tm_wday;
165    header->day_in_year = timep->tm_yday;
166    header->is_daylight_savings = timep->tm_isdst;
167 }
168 
169 /**
170  * SQTT CPU info.
171  */
172 struct sqtt_file_chunk_cpu_info {
173    struct sqtt_file_chunk_header header;
174    uint32_t vendor_id[4];
175    uint32_t processor_brand[12];
176    uint32_t reserved[2];
177    uint64_t cpu_timestamp_freq;
178    uint32_t clock_speed;
179    uint32_t num_logical_cores;
180    uint32_t num_physical_cores;
181    uint32_t system_ram_size;
182 };
183 
184 static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112,
185               "sqtt_file_chunk_cpu_info doesn't match RGP spec");
186 
ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info * chunk)187 static void ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
188 {
189    uint32_t cpu_clock_speed_total = 0;
190    uint64_t system_ram_size = 0;
191    char line[1024];
192    FILE *f;
193 
194    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CPU_INFO;
195    chunk->header.chunk_id.index = 0;
196    chunk->header.major_version = 0;
197    chunk->header.minor_version = 0;
198    chunk->header.size_in_bytes = sizeof(*chunk);
199 
200    chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */
201 
202    strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id));
203    strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand));
204    chunk->clock_speed = 0;
205    chunk->num_logical_cores = 0;
206    chunk->num_physical_cores = 0;
207    chunk->system_ram_size = 0;
208    if (os_get_total_physical_memory(&system_ram_size))
209       chunk->system_ram_size = system_ram_size / (1024 * 1024);
210 
211    /* Parse cpuinfo to get more detailled information. */
212    f = fopen("/proc/cpuinfo", "r");
213    if (!f)
214       return;
215 
216    while (fgets(line, sizeof(line), f)) {
217       char *str;
218 
219       /* Parse vendor name. */
220       str = strstr(line, "vendor_id");
221       if (str) {
222          char *ptr = (char *)chunk->vendor_id;
223          char *v = strtok(str, ":");
224          v = strtok(NULL, ":");
225          strncpy(ptr, v + 1, sizeof(chunk->vendor_id) - 1);
226          ptr[sizeof(chunk->vendor_id) - 1] = '\0';
227       }
228 
229       /* Parse processor name. */
230       str = strstr(line, "model name");
231       if (str) {
232          char *ptr = (char *)chunk->processor_brand;
233          char *v = strtok(str, ":");
234          v = strtok(NULL, ":");
235          strncpy(ptr, v + 1, sizeof(chunk->processor_brand) - 1);
236          ptr[sizeof(chunk->processor_brand) - 1] = '\0';
237       }
238 
239       /* Parse the current CPU clock speed for each cores. */
240       str = strstr(line, "cpu MHz");
241       if (str) {
242          uint32_t v = 0;
243          if (sscanf(str, "cpu MHz : %d", &v) == 1)
244             cpu_clock_speed_total += v;
245       }
246 
247       /* Parse the number of logical cores. */
248       str = strstr(line, "siblings");
249       if (str) {
250          uint32_t v = 0;
251          if (sscanf(str, "siblings : %d", &v) == 1)
252             chunk->num_logical_cores = v;
253       }
254 
255       /* Parse the number of physical cores. */
256       str = strstr(line, "cpu cores");
257       if (str) {
258          uint32_t v = 0;
259          if (sscanf(str, "cpu cores : %d", &v) == 1)
260             chunk->num_physical_cores = v;
261       }
262    }
263 
264    if (chunk->num_logical_cores)
265       chunk->clock_speed = cpu_clock_speed_total / chunk->num_logical_cores;
266 
267    fclose(f);
268 }
269 
270 /**
271  * SQTT ASIC info.
272  */
273 enum sqtt_file_chunk_asic_info_flags
274 {
275    SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING = (1 << 0),
276    SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1)
277 };
278 
279 enum sqtt_gpu_type
280 {
281    SQTT_GPU_TYPE_UNKNOWN = 0x0,
282    SQTT_GPU_TYPE_INTEGRATED = 0x1,
283    SQTT_GPU_TYPE_DISCRETE = 0x2,
284    SQTT_GPU_TYPE_VIRTUAL = 0x3
285 };
286 
287 enum sqtt_gfxip_level
288 {
289    SQTT_GFXIP_LEVEL_NONE = 0x0,
290    SQTT_GFXIP_LEVEL_GFXIP_6 = 0x1,
291    SQTT_GFXIP_LEVEL_GFXIP_7 = 0x2,
292    SQTT_GFXIP_LEVEL_GFXIP_8 = 0x3,
293    SQTT_GFXIP_LEVEL_GFXIP_8_1 = 0x4,
294    SQTT_GFXIP_LEVEL_GFXIP_9 = 0x5,
295    SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
296    SQTT_GFXIP_LEVEL_GFXIP_10_3 = 0x9,
297 };
298 
299 enum sqtt_memory_type
300 {
301    SQTT_MEMORY_TYPE_UNKNOWN = 0x0,
302    SQTT_MEMORY_TYPE_DDR = 0x1,
303    SQTT_MEMORY_TYPE_DDR2 = 0x2,
304    SQTT_MEMORY_TYPE_DDR3 = 0x3,
305    SQTT_MEMORY_TYPE_DDR4 = 0x4,
306    SQTT_MEMORY_TYPE_GDDR3 = 0x10,
307    SQTT_MEMORY_TYPE_GDDR4 = 0x11,
308    SQTT_MEMORY_TYPE_GDDR5 = 0x12,
309    SQTT_MEMORY_TYPE_GDDR6 = 0x13,
310    SQTT_MEMORY_TYPE_HBM = 0x20,
311    SQTT_MEMORY_TYPE_HBM2 = 0x21,
312    SQTT_MEMORY_TYPE_HBM3 = 0x22,
313    SQTT_MEMORY_TYPE_LPDDR4 = 0x30,
314    SQTT_MEMORY_TYPE_LPDDR5 = 0x31,
315 };
316 
317 struct sqtt_file_chunk_asic_info {
318    struct sqtt_file_chunk_header header;
319    uint64_t flags;
320    uint64_t trace_shader_core_clock;
321    uint64_t trace_memory_clock;
322    int32_t device_id;
323    int32_t device_revision_id;
324    int32_t vgprs_per_simd;
325    int32_t sgprs_per_simd;
326    int32_t shader_engines;
327    int32_t compute_unit_per_shader_engine;
328    int32_t simd_per_compute_unit;
329    int32_t wavefronts_per_simd;
330    int32_t minimum_vgpr_alloc;
331    int32_t vgpr_alloc_granularity;
332    int32_t minimum_sgpr_alloc;
333    int32_t sgpr_alloc_granularity;
334    int32_t hardware_contexts;
335    enum sqtt_gpu_type gpu_type;
336    enum sqtt_gfxip_level gfxip_level;
337    int32_t gpu_index;
338    int32_t gds_size;
339    int32_t gds_per_shader_engine;
340    int32_t ce_ram_size;
341    int32_t ce_ram_size_graphics;
342    int32_t ce_ram_size_compute;
343    int32_t max_number_of_dedicated_cus;
344    int64_t vram_size;
345    int32_t vram_bus_width;
346    int32_t l2_cache_size;
347    int32_t l1_cache_size;
348    int32_t lds_size;
349    char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
350    float alu_per_clock;
351    float texture_per_clock;
352    float prims_per_clock;
353    float pixels_per_clock;
354    uint64_t gpu_timestamp_frequency;
355    uint64_t max_shader_core_clock;
356    uint64_t max_memory_clock;
357    uint32_t memory_ops_per_clock;
358    enum sqtt_memory_type memory_chip_type;
359    uint32_t lds_granularity;
360    uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
361    char reserved1[128];
362    char padding[4];
363 };
364 
365 static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720,
366               "sqtt_file_chunk_asic_info doesn't match RGP spec");
367 
ac_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)368 static enum sqtt_gfxip_level ac_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)
369 {
370    switch (chip_class) {
371    case GFX6:
372       return SQTT_GFXIP_LEVEL_GFXIP_6;
373    case GFX7:
374       return SQTT_GFXIP_LEVEL_GFXIP_7;
375    case GFX8:
376       return SQTT_GFXIP_LEVEL_GFXIP_8;
377    case GFX9:
378       return SQTT_GFXIP_LEVEL_GFXIP_9;
379    case GFX10:
380       return SQTT_GFXIP_LEVEL_GFXIP_10_1;
381    case GFX10_3:
382       return SQTT_GFXIP_LEVEL_GFXIP_10_3;
383    default:
384       unreachable("Invalid chip class");
385    }
386 }
387 
ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)388 static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t vram_type)
389 {
390    switch (vram_type) {
391    case AMDGPU_VRAM_TYPE_UNKNOWN:
392       return SQTT_MEMORY_TYPE_UNKNOWN;
393    case AMDGPU_VRAM_TYPE_DDR2:
394       return SQTT_MEMORY_TYPE_DDR2;
395    case AMDGPU_VRAM_TYPE_DDR3:
396       return SQTT_MEMORY_TYPE_DDR3;
397    case AMDGPU_VRAM_TYPE_DDR4:
398       return SQTT_MEMORY_TYPE_DDR4;
399    case AMDGPU_VRAM_TYPE_GDDR5:
400       return SQTT_MEMORY_TYPE_GDDR5;
401    case AMDGPU_VRAM_TYPE_HBM:
402       return SQTT_MEMORY_TYPE_HBM;
403    case AMDGPU_VRAM_TYPE_GDDR6:
404       return SQTT_MEMORY_TYPE_GDDR6;
405    case AMDGPU_VRAM_TYPE_DDR5:
406       return SQTT_MEMORY_TYPE_LPDDR5;
407    case AMDGPU_VRAM_TYPE_GDDR1:
408    case AMDGPU_VRAM_TYPE_GDDR3:
409    case AMDGPU_VRAM_TYPE_GDDR4:
410    default:
411       unreachable("Invalid vram type");
412    }
413 }
414 
ac_memory_ops_per_clock(uint32_t vram_type)415 static uint32_t ac_memory_ops_per_clock(uint32_t vram_type)
416 {
417    switch (vram_type) {
418    case AMDGPU_VRAM_TYPE_UNKNOWN:
419       return 0;
420    case AMDGPU_VRAM_TYPE_DDR2:
421    case AMDGPU_VRAM_TYPE_DDR3:
422    case AMDGPU_VRAM_TYPE_DDR4:
423    case AMDGPU_VRAM_TYPE_HBM:
424       return 2;
425    case AMDGPU_VRAM_TYPE_DDR5:
426    case AMDGPU_VRAM_TYPE_GDDR5:
427       return 4;
428    case AMDGPU_VRAM_TYPE_GDDR6:
429       return 16;
430    case AMDGPU_VRAM_TYPE_GDDR1:
431    case AMDGPU_VRAM_TYPE_GDDR3:
432    case AMDGPU_VRAM_TYPE_GDDR4:
433    default:
434       unreachable("Invalid vram type");
435    }
436 }
437 
ac_sqtt_fill_asic_info(struct radeon_info * rad_info,struct sqtt_file_chunk_asic_info * chunk)438 static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
439                                    struct sqtt_file_chunk_asic_info *chunk)
440 {
441    bool has_wave32 = rad_info->chip_class >= GFX10;
442 
443    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
444    chunk->header.chunk_id.index = 0;
445    chunk->header.major_version = 0;
446    chunk->header.minor_version = 4;
447    chunk->header.size_in_bytes = sizeof(*chunk);
448 
449    chunk->flags = 0;
450 
451    /* All chips older than GFX9 are affected by the "SPI not
452     * differentiating pkr_id for newwave commands" bug.
453     */
454    if (rad_info->chip_class < GFX9)
455       chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
456 
457    /* Only FIJI and GFX9+ support PS1 events. */
458    if (rad_info->family == CHIP_FIJI || rad_info->chip_class >= GFX9)
459       chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
460 
461    chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
462    chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
463 
464    /* RGP gets very confused if these clocks are 0. The 1 GHz clocks are not necessarily correct,
465     * but the resulting traces are at least somewhat useful. */
466    if (!chunk->trace_shader_core_clock)
467       chunk->trace_shader_core_clock = 1e9;
468    if (!chunk->trace_memory_clock)
469       chunk->trace_memory_clock = 1e9;
470 
471    chunk->device_id = rad_info->pci_id;
472    chunk->device_revision_id = rad_info->pci_rev_id;
473    chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd * (has_wave32 ? 2 : 1);
474    chunk->sgprs_per_simd = rad_info->num_physical_sgprs_per_simd;
475    chunk->shader_engines = rad_info->max_se;
476    chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa * rad_info->max_sa_per_se;
477    chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit;
478    chunk->wavefronts_per_simd = rad_info->max_wave64_per_simd;
479 
480    chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc;
481    chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity * (has_wave32 ? 2 : 1);
482    chunk->minimum_sgpr_alloc = rad_info->min_sgpr_alloc;
483    chunk->sgpr_alloc_granularity = rad_info->sgpr_alloc_granularity;
484 
485    chunk->hardware_contexts = 8;
486    chunk->gpu_type =
487       rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
488    chunk->gfxip_level = ac_chip_class_to_sqtt_gfxip_level(rad_info->chip_class);
489    chunk->gpu_index = 0;
490 
491    chunk->max_number_of_dedicated_cus = 0;
492    chunk->ce_ram_size = rad_info->ce_ram_size;
493    chunk->ce_ram_size_graphics = 0;
494    chunk->ce_ram_size_compute = 0;
495 
496    chunk->vram_bus_width = rad_info->vram_bit_width;
497    chunk->vram_size = rad_info->vram_size;
498    chunk->l2_cache_size = rad_info->l2_cache_size;
499    chunk->l1_cache_size = rad_info->l1_cache_size;
500    chunk->lds_size = rad_info->lds_size_per_workgroup;
501    if (rad_info->chip_class >= GFX10) {
502       /* RGP expects the LDS size in CU mode. */
503       chunk->lds_size /= 2;
504    }
505 
506    strncpy(chunk->gpu_name, rad_info->name, SQTT_GPU_NAME_MAX_SIZE - 1);
507 
508    chunk->alu_per_clock = 0.0;
509    chunk->texture_per_clock = 0.0;
510    chunk->prims_per_clock = rad_info->max_se;
511    if (rad_info->chip_class == GFX10)
512       chunk->prims_per_clock *= 2;
513    chunk->pixels_per_clock = 0.0;
514 
515    chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
516    chunk->max_shader_core_clock = rad_info->max_shader_clock * 1000000;
517    chunk->max_memory_clock = rad_info->max_memory_clock * 1000000;
518    chunk->memory_ops_per_clock = ac_memory_ops_per_clock(rad_info->vram_type);
519    chunk->memory_chip_type = ac_vram_type_to_sqtt_memory_type(rad_info->vram_type);
520    chunk->lds_granularity = rad_info->lds_encode_granularity;
521 
522    for (unsigned se = 0; se < 4; se++) {
523       for (unsigned sa = 0; sa < 2; sa++) {
524          chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
525       }
526    }
527 }
528 
529 /**
530  * SQTT API info.
531  */
532 enum sqtt_api_type
533 {
534    SQTT_API_TYPE_DIRECTX_12,
535    SQTT_API_TYPE_VULKAN,
536    SQTT_API_TYPE_GENERIC,
537    SQTT_API_TYPE_OPENCL
538 };
539 
540 enum sqtt_instruction_trace_mode
541 {
542    SQTT_INSTRUCTION_TRACE_DISABLED = 0x0,
543    SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
544    SQTT_INSTRUCTION_TRACE_API_PSO = 0x2,
545 };
546 
547 enum sqtt_profiling_mode
548 {
549    SQTT_PROFILING_MODE_PRESENT = 0x0,
550    SQTT_PROFILING_MODE_USER_MARKERS = 0x1,
551    SQTT_PROFILING_MODE_INDEX = 0x2,
552    SQTT_PROFILING_MODE_TAG = 0x3,
553 };
554 
555 union sqtt_profiling_mode_data {
556    struct {
557       char start[256];
558       char end[256];
559    } user_marker_profiling_data;
560 
561    struct {
562       uint32_t start;
563       uint32_t end;
564    } index_profiling_data;
565 
566    struct {
567       uint32_t begin_hi;
568       uint32_t begin_lo;
569       uint32_t end_hi;
570       uint32_t end_lo;
571    } tag_profiling_data;
572 };
573 
574 union sqtt_instruction_trace_data {
575    struct {
576       uint64_t api_pso_filter;
577    } api_pso_data;
578 
579    struct {
580       char start[256];
581       char end[256];
582    } user_marker_data;
583 };
584 
585 struct sqtt_file_chunk_api_info {
586    struct sqtt_file_chunk_header header;
587    enum sqtt_api_type api_type;
588    uint16_t major_version;
589    uint16_t minor_version;
590    enum sqtt_profiling_mode profiling_mode;
591    uint32_t reserved;
592    union sqtt_profiling_mode_data profiling_mode_data;
593    enum sqtt_instruction_trace_mode instruction_trace_mode;
594    uint32_t reserved2;
595    union sqtt_instruction_trace_data instruction_trace_data;
596 };
597 
598 static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064,
599               "sqtt_file_chunk_api_info doesn't match RGP spec");
600 
ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info * chunk)601 static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
602 {
603    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO;
604    chunk->header.chunk_id.index = 0;
605    chunk->header.major_version = 0;
606    chunk->header.minor_version = 1;
607    chunk->header.size_in_bytes = sizeof(*chunk);
608 
609    chunk->api_type = SQTT_API_TYPE_VULKAN;
610    chunk->major_version = 0;
611    chunk->minor_version = 0;
612    chunk->profiling_mode = SQTT_PROFILING_MODE_PRESENT;
613    chunk->instruction_trace_mode = SQTT_INSTRUCTION_TRACE_DISABLED;
614 }
615 
616 struct sqtt_code_object_database_record {
617    uint32_t size;
618 };
619 
620 struct sqtt_file_chunk_code_object_database {
621    struct sqtt_file_chunk_header header;
622    uint32_t offset;
623    uint32_t flags;
624    uint32_t size;
625    uint32_t record_count;
626 };
627 
628 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)629 ac_sqtt_fill_code_object(struct rgp_code_object *rgp_code_object,
630                          struct sqtt_file_chunk_code_object_database *chunk,
631                          size_t file_offset, uint32_t chunk_size)
632 {
633    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE;
634    chunk->header.chunk_id.index = 0;
635    chunk->header.major_version = 0;
636    chunk->header.minor_version = 0;
637    chunk->header.size_in_bytes = chunk_size;
638    chunk->offset = file_offset;
639    chunk->flags = 0;
640    chunk->size = chunk_size;
641    chunk->record_count = rgp_code_object->record_count;
642 }
643 
644 struct sqtt_code_object_loader_events_record {
645    uint32_t loader_event_type;
646    uint32_t reserved;
647    uint64_t base_address;
648    uint64_t code_object_hash[2];
649    uint64_t time_stamp;
650 };
651 
652 struct sqtt_file_chunk_code_object_loader_events {
653    struct sqtt_file_chunk_header header;
654    uint32_t offset;
655    uint32_t flags;
656    uint32_t record_size;
657    uint32_t record_count;
658 };
659 
660 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)661 ac_sqtt_fill_loader_events(struct rgp_loader_events *rgp_loader_events,
662                            struct sqtt_file_chunk_code_object_loader_events *chunk,
663                            size_t file_offset)
664 {
665    chunk->header.chunk_id.type =
666                                SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS;
667    chunk->header.chunk_id.index = 0;
668    chunk->header.major_version = 1;
669    chunk->header.minor_version = 0;
670    chunk->header.size_in_bytes = (rgp_loader_events->record_count *
671                                  sizeof(struct sqtt_code_object_loader_events_record)) +
672                                  sizeof(*chunk);
673    chunk->offset = file_offset;
674    chunk->flags = 0;
675    chunk->record_size = sizeof(struct sqtt_code_object_loader_events_record);
676    chunk->record_count = rgp_loader_events->record_count;
677 }
678 struct sqtt_pso_correlation_record {
679    uint64_t api_pso_hash;
680    uint64_t pipeline_hash[2];
681    char api_level_obj_name[64];
682 };
683 
684 struct sqtt_file_chunk_pso_correlation {
685    struct sqtt_file_chunk_header header;
686    uint32_t offset;
687    uint32_t flags;
688    uint32_t record_size;
689    uint32_t record_count;
690 };
691 
692 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)693 ac_sqtt_fill_pso_correlation(struct rgp_pso_correlation *rgp_pso_correlation,
694                              struct sqtt_file_chunk_pso_correlation *chunk,
695                              size_t file_offset)
696 {
697    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION;
698    chunk->header.chunk_id.index = 0;
699    chunk->header.major_version = 0;
700    chunk->header.minor_version = 0;
701    chunk->header.size_in_bytes = (rgp_pso_correlation->record_count *
702                                  sizeof(struct sqtt_pso_correlation_record)) +
703                                  sizeof(*chunk);
704    chunk->offset = file_offset;
705    chunk->flags = 0;
706    chunk->record_size = sizeof(struct sqtt_pso_correlation_record);
707    chunk->record_count = rgp_pso_correlation->record_count;
708 }
709 
710 /**
711  * SQTT desc info.
712  */
713 struct sqtt_file_chunk_sqtt_desc {
714    struct sqtt_file_chunk_header header;
715    int32_t shader_engine_index;
716    enum sqtt_version sqtt_version;
717    union {
718       struct {
719          int32_t instrumentation_version;
720       } v0;
721       struct {
722          int16_t instrumentation_spec_version;
723          int16_t instrumentation_api_version;
724          int32_t compute_unit_index;
725       } v1;
726    };
727 };
728 
729 static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
730               "sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
731 
ac_chip_class_to_sqtt_version(enum chip_class chip_class)732 static enum sqtt_version ac_chip_class_to_sqtt_version(enum chip_class chip_class)
733 {
734    switch (chip_class) {
735    case GFX6:
736       return SQTT_VERSION_2_0;
737    case GFX7:
738       return SQTT_VERSION_2_1;
739    case GFX8:
740       return SQTT_VERSION_2_2;
741    case GFX9:
742       return SQTT_VERSION_2_3;
743    case GFX10:
744       return SQTT_VERSION_2_4;
745    case GFX10_3:
746       return SQTT_VERSION_2_4;
747    default:
748       unreachable("Invalid chip class");
749    }
750 }
751 
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)752 static void ac_sqtt_fill_sqtt_desc(struct radeon_info *info,
753                                    struct sqtt_file_chunk_sqtt_desc *chunk, int32_t chunk_index,
754                                    int32_t shader_engine_index, int32_t compute_unit_index)
755 {
756    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC;
757    chunk->header.chunk_id.index = chunk_index;
758    chunk->header.major_version = 0;
759    chunk->header.minor_version = 2;
760    chunk->header.size_in_bytes = sizeof(*chunk);
761 
762    chunk->sqtt_version =
763       ac_chip_class_to_sqtt_version(info->chip_class);
764    chunk->shader_engine_index = shader_engine_index;
765    chunk->v1.instrumentation_spec_version = 1;
766    chunk->v1.instrumentation_api_version = 0;
767    chunk->v1.compute_unit_index = compute_unit_index;
768 }
769 
770 /**
771  * SQTT data info.
772  */
773 struct sqtt_file_chunk_sqtt_data {
774    struct sqtt_file_chunk_header header;
775    int32_t offset; /* in bytes */
776    int32_t size;   /* in bytes */
777 };
778 
779 static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
780               "sqtt_file_chunk_sqtt_data doesn't match RGP spec");
781 
ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data * chunk,int32_t chunk_index,int32_t offset,int32_t size)782 static void ac_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk, int32_t chunk_index,
783                                    int32_t offset, int32_t size)
784 {
785    chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA;
786    chunk->header.chunk_id.index = chunk_index;
787    chunk->header.major_version = 0;
788    chunk->header.minor_version = 0;
789    chunk->header.size_in_bytes = sizeof(*chunk) + size;
790 
791    chunk->offset = sizeof(*chunk) + offset;
792    chunk->size = size;
793 }
794 
795 /* Below values are from from llvm project
796  * llvm/include/llvm/BinaryFormat/ELF.h
797  */
798 enum elf_gfxip_level
799 {
800    EF_AMDGPU_MACH_AMDGCN_GFX600 = 0x020,
801    EF_AMDGPU_MACH_AMDGCN_GFX700 = 0x022,
802    EF_AMDGPU_MACH_AMDGCN_GFX801 = 0x028,
803    EF_AMDGPU_MACH_AMDGCN_GFX900 = 0x02c,
804    EF_AMDGPU_MACH_AMDGCN_GFX1010 = 0x033,
805    EF_AMDGPU_MACH_AMDGCN_GFX1030 = 0x036,
806 };
807 
ac_chip_class_to_elf_gfxip_level(enum chip_class chip_class)808 static enum elf_gfxip_level ac_chip_class_to_elf_gfxip_level(enum chip_class chip_class)
809 {
810    switch (chip_class) {
811    case GFX6:
812       return EF_AMDGPU_MACH_AMDGCN_GFX600;
813    case GFX7:
814       return EF_AMDGPU_MACH_AMDGCN_GFX700;
815    case GFX8:
816       return EF_AMDGPU_MACH_AMDGCN_GFX801;
817    case GFX9:
818       return EF_AMDGPU_MACH_AMDGCN_GFX900;
819    case GFX10:
820       return EF_AMDGPU_MACH_AMDGCN_GFX1010;
821    case GFX10_3:
822       return EF_AMDGPU_MACH_AMDGCN_GFX1030;
823    default:
824       unreachable("Invalid chip class");
825    }
826 }
827 
ac_sqtt_dump_data(struct radeon_info * rad_info,struct ac_thread_trace * thread_trace,FILE * output)828 static void ac_sqtt_dump_data(struct radeon_info *rad_info,
829                               struct ac_thread_trace *thread_trace,
830                               FILE *output)
831 {
832    struct ac_thread_trace_data *thread_trace_data = thread_trace->data;
833    struct sqtt_file_chunk_asic_info asic_info = {0};
834    struct sqtt_file_chunk_cpu_info cpu_info = {0};
835    struct sqtt_file_chunk_api_info api_info = {0};
836    struct sqtt_file_header header = {0};
837    size_t file_offset = 0;
838    struct rgp_code_object *rgp_code_object =
839                                           &thread_trace_data->rgp_code_object;
840    struct rgp_loader_events *rgp_loader_events =
841                                         &thread_trace_data->rgp_loader_events;
842    struct rgp_pso_correlation *rgp_pso_correlation =
843                                       &thread_trace_data->rgp_pso_correlation;
844 
845    /* SQTT header file. */
846    ac_sqtt_fill_header(&header);
847    file_offset += sizeof(header);
848    fwrite(&header, sizeof(header), 1, output);
849 
850    /* SQTT cpu chunk. */
851    ac_sqtt_fill_cpu_info(&cpu_info);
852    file_offset += sizeof(cpu_info);
853    fwrite(&cpu_info, sizeof(cpu_info), 1, output);
854 
855    /* SQTT asic chunk. */
856    ac_sqtt_fill_asic_info(rad_info, &asic_info);
857    file_offset += sizeof(asic_info);
858    fwrite(&asic_info, sizeof(asic_info), 1, output);
859 
860    /* SQTT api chunk. */
861    ac_sqtt_fill_api_info(&api_info);
862    file_offset += sizeof(api_info);
863    fwrite(&api_info, sizeof(api_info), 1, output);
864 
865     /* SQTT code object database chunk. */
866    if (rgp_code_object->record_count) {
867       size_t file_code_object_offset = file_offset;
868       struct sqtt_file_chunk_code_object_database code_object;
869       struct sqtt_code_object_database_record code_object_record;
870       uint32_t elf_size_calc = 0;
871       uint32_t flags = ac_chip_class_to_elf_gfxip_level(rad_info->chip_class);
872 
873       fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR);
874       file_offset += sizeof(struct sqtt_file_chunk_code_object_database);
875       list_for_each_entry_safe(struct rgp_code_object_record, record,
876                                &rgp_code_object->record, list) {
877          fseek(output, sizeof(struct sqtt_code_object_database_record), SEEK_CUR);
878          ac_rgp_file_write_elf_object(output, file_offset +
879                                       sizeof(struct sqtt_code_object_database_record),
880                                       record, &elf_size_calc, flags);
881          code_object_record.size = elf_size_calc;
882          fseek(output, file_offset, SEEK_SET);
883          fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record),
884                 1, output);
885          file_offset += (sizeof(struct sqtt_code_object_database_record) +
886                          elf_size_calc);
887          fseek(output, file_offset, SEEK_SET);
888       }
889       ac_sqtt_fill_code_object(rgp_code_object, &code_object,
890                                file_code_object_offset,
891                                file_offset - file_code_object_offset);
892       fseek(output, file_code_object_offset, SEEK_SET);
893       fwrite(&code_object, sizeof(struct sqtt_file_chunk_code_object_database), 1, output);
894       fseek(output, file_offset, SEEK_SET);
895    }
896 
897    /* SQTT code object loader events chunk. */
898    if (rgp_loader_events->record_count) {
899       struct sqtt_file_chunk_code_object_loader_events loader_events;
900 
901       ac_sqtt_fill_loader_events(rgp_loader_events, &loader_events,
902                                  file_offset);
903       fwrite(&loader_events, sizeof(struct sqtt_file_chunk_code_object_loader_events),
904              1, output);
905       file_offset += sizeof(struct sqtt_file_chunk_code_object_loader_events);
906       list_for_each_entry_safe(struct rgp_loader_events_record, record,
907                                &rgp_loader_events->record, list) {
908          fwrite(record, sizeof(struct sqtt_code_object_loader_events_record), 1, output);
909       }
910       file_offset += (rgp_loader_events->record_count *
911                       sizeof(struct sqtt_code_object_loader_events_record));
912    }
913 
914    /* SQTT pso correlation chunk. */
915    if (rgp_pso_correlation->record_count) {
916       struct sqtt_file_chunk_pso_correlation pso_correlation;
917 
918       ac_sqtt_fill_pso_correlation(rgp_pso_correlation,
919                                    &pso_correlation, file_offset);
920       fwrite(&pso_correlation, sizeof(struct sqtt_file_chunk_pso_correlation), 1,
921              output);
922       file_offset += sizeof(struct sqtt_file_chunk_pso_correlation);
923       list_for_each_entry_safe(struct rgp_pso_correlation_record, record,
924                                &rgp_pso_correlation->record, list) {
925          fwrite(record, sizeof(struct sqtt_pso_correlation_record),
926                 1, output);
927       }
928       file_offset += (rgp_pso_correlation->record_count *
929                       sizeof(struct sqtt_pso_correlation_record));
930    }
931 
932    if (thread_trace) {
933       for (unsigned i = 0; i < thread_trace->num_traces; i++) {
934          const struct ac_thread_trace_se *se = &thread_trace->traces[i];
935          const struct ac_thread_trace_info *info = &se->info;
936          struct sqtt_file_chunk_sqtt_desc desc = {0};
937          struct sqtt_file_chunk_sqtt_data data = {0};
938          uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
939 
940          /* SQTT desc chunk. */
941          ac_sqtt_fill_sqtt_desc(rad_info, &desc, i, se->shader_engine, se->compute_unit);
942          file_offset += sizeof(desc);
943          fwrite(&desc, sizeof(desc), 1, output);
944 
945          /* SQTT data chunk. */
946          ac_sqtt_fill_sqtt_data(&data, i, file_offset, size);
947          file_offset += sizeof(data);
948          fwrite(&data, sizeof(data), 1, output);
949 
950          /* Copy thread trace data generated by the hardware. */
951          file_offset += size;
952          fwrite(se->data_ptr, size, 1, output);
953       }
954    }
955 }
956 
ac_dump_rgp_capture(struct radeon_info * info,struct ac_thread_trace * thread_trace)957 int ac_dump_rgp_capture(struct radeon_info *info,
958                         struct ac_thread_trace *thread_trace)
959 {
960    char filename[2048];
961    struct tm now;
962    time_t t;
963    FILE *f;
964 
965    t = time(NULL);
966    now = *localtime(&t);
967 
968    snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.%02d.rgp",
969             util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1, now.tm_mday, now.tm_hour,
970             now.tm_min, now.tm_sec);
971 
972    f = fopen(filename, "w+");
973    if (!f)
974       return -1;
975 
976    ac_sqtt_dump_data(info, thread_trace, f);
977 
978    fprintf(stderr, "RGP capture saved to '%s'\n", filename);
979 
980    fclose(f);
981    return 0;
982 }
983