2
* Copyright 2020 Advanced Micro Devices, Inc.
3
* Copyright © 2020 Valve Corporation
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:
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
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
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"
34
#include "ac_gpu_info.h"
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
48
#include "drm-uapi/amdgpu_drm.h"
54
#define SQTT_FILE_MAGIC_NUMBER 0x50303042
55
#define SQTT_FILE_VERSION_MAJOR 1
56
#define SQTT_FILE_VERSION_MINOR 5
58
#define SQTT_GPU_NAME_MAX_SIZE 256
59
#define SQTT_MAX_NUM_SE 32
60
#define SQTT_SA_PER_SE 2
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+ */
73
enum sqtt_file_chunk_type
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
91
struct sqtt_file_chunk_id {
92
enum sqtt_file_chunk_type type : 8;
94
int32_t reserved : 16;
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;
108
struct sqtt_file_header_flags {
111
int32_t is_semaphore_queue_timing_etw : 1;
112
int32_t no_queue_semaphore_timestamps : 1;
113
int32_t reserved : 30;
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;
129
int32_t day_in_month;
134
int32_t is_daylight_savings;
137
static_assert(sizeof(struct sqtt_file_header) == 56, "sqtt_file_header doesn't match RGP spec");
139
static void ac_sqtt_fill_header(struct sqtt_file_header *header)
141
struct tm *timep, result;
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);
153
timep = os_localtime(&raw_time, &result);
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;
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;
181
static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112,
182
"sqtt_file_chunk_cpu_info doesn't match RGP spec");
184
static void ac_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
186
uint32_t cpu_clock_speed_total = 0;
187
uint64_t system_ram_size = 0;
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);
197
chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */
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);
208
/* Parse cpuinfo to get more detailled information. */
209
f = fopen("/proc/cpuinfo", "r");
213
while (fgets(line, sizeof(line), f)) {
216
/* Parse vendor name. */
217
str = strstr(line, "vendor_id");
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';
226
/* Parse processor name. */
227
str = strstr(line, "model name");
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';
236
/* Parse the current CPU clock speed for each cores. */
237
str = strstr(line, "cpu MHz");
240
if (sscanf(str, "cpu MHz : %d", &v) == 1)
241
cpu_clock_speed_total += v;
244
/* Parse the number of logical cores. */
245
str = strstr(line, "siblings");
248
if (sscanf(str, "siblings : %d", &v) == 1)
249
chunk->num_logical_cores = v;
252
/* Parse the number of physical cores. */
253
str = strstr(line, "cpu cores");
256
if (sscanf(str, "cpu cores : %d", &v) == 1)
257
chunk->num_physical_cores = v;
261
if (chunk->num_logical_cores)
262
chunk->clock_speed = cpu_clock_speed_total / chunk->num_logical_cores;
270
enum sqtt_file_chunk_asic_info_flags
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)
278
SQTT_GPU_TYPE_UNKNOWN = 0x0,
279
SQTT_GPU_TYPE_INTEGRATED = 0x1,
280
SQTT_GPU_TYPE_DISCRETE = 0x2,
281
SQTT_GPU_TYPE_VIRTUAL = 0x3
284
enum sqtt_gfxip_level
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,
296
enum sqtt_memory_type
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,
314
struct sqtt_file_chunk_asic_info {
315
struct sqtt_file_chunk_header header;
317
uint64_t trace_shader_core_clock;
318
uint64_t trace_memory_clock;
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;
336
int32_t gds_per_shader_engine;
338
int32_t ce_ram_size_graphics;
339
int32_t ce_ram_size_compute;
340
int32_t max_number_of_dedicated_cus;
342
int32_t vram_bus_width;
343
int32_t l2_cache_size;
344
int32_t l1_cache_size;
346
char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
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];
362
static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720,
363
"sqtt_file_chunk_asic_info doesn't match RGP spec");
365
static enum sqtt_gfxip_level ac_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)
367
switch (chip_class) {
369
return SQTT_GFXIP_LEVEL_GFXIP_8;
371
return SQTT_GFXIP_LEVEL_GFXIP_9;
373
return SQTT_GFXIP_LEVEL_GFXIP_10_1;
375
return SQTT_GFXIP_LEVEL_GFXIP_10_3;
377
unreachable("Invalid chip class");
381
static enum sqtt_memory_type ac_vram_type_to_sqtt_memory_type(uint32_t 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:
404
unreachable("Invalid vram type");
408
static uint32_t ac_memory_ops_per_clock(uint32_t vram_type)
411
case AMDGPU_VRAM_TYPE_UNKNOWN:
413
case AMDGPU_VRAM_TYPE_DDR2:
414
case AMDGPU_VRAM_TYPE_DDR3:
415
case AMDGPU_VRAM_TYPE_DDR4:
416
case AMDGPU_VRAM_TYPE_HBM:
418
case AMDGPU_VRAM_TYPE_DDR5:
419
case AMDGPU_VRAM_TYPE_GDDR5:
421
case AMDGPU_VRAM_TYPE_GDDR6:
423
case AMDGPU_VRAM_TYPE_GDDR1:
424
case AMDGPU_VRAM_TYPE_GDDR3:
425
case AMDGPU_VRAM_TYPE_GDDR4:
427
unreachable("Invalid vram type");
431
static void ac_sqtt_fill_asic_info(struct radeon_info *rad_info,
432
struct sqtt_file_chunk_asic_info *chunk)
434
bool has_wave32 = rad_info->chip_class >= GFX10;
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);
444
/* All chips older than GFX9 are affected by the "SPI not
445
* differentiating pkr_id for newwave commands" bug.
447
if (rad_info->chip_class < GFX9)
448
chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
450
/* Only GFX9+ support PS1 events. */
451
if (rad_info->chip_class >= GFX9)
452
chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
454
chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
455
chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
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;
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;
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;
478
chunk->hardware_contexts = 8;
480
rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
481
chunk->gfxip_level = ac_chip_class_to_sqtt_gfxip_level(rad_info->chip_class);
482
chunk->gpu_index = 0;
484
chunk->max_number_of_dedicated_cus = 0;
485
chunk->ce_ram_size = rad_info->ce_ram_size;
486
chunk->ce_ram_size_graphics = 0;
487
chunk->ce_ram_size_compute = 0;
489
chunk->vram_bus_width = rad_info->vram_bit_width;
490
chunk->vram_size = rad_info->vram_size;
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->chip_class >= GFX10) {
495
/* RGP expects the LDS size in CU mode. */
496
chunk->lds_size /= 2;
499
strncpy(chunk->gpu_name, rad_info->name, SQTT_GPU_NAME_MAX_SIZE - 1);
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->chip_class == GFX10)
505
chunk->prims_per_clock *= 2;
506
chunk->pixels_per_clock = 0.0;
508
chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
509
chunk->max_shader_core_clock = rad_info->max_shader_clock * 1000000;
510
chunk->max_memory_clock = rad_info->max_memory_clock * 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;
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];
527
SQTT_API_TYPE_DIRECTX_12,
528
SQTT_API_TYPE_VULKAN,
529
SQTT_API_TYPE_GENERIC,
533
enum sqtt_instruction_trace_mode
535
SQTT_INSTRUCTION_TRACE_DISABLED = 0x0,
536
SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
537
SQTT_INSTRUCTION_TRACE_API_PSO = 0x2,
540
enum sqtt_profiling_mode
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,
548
union sqtt_profiling_mode_data {
552
} user_marker_profiling_data;
557
} index_profiling_data;
564
} tag_profiling_data;
567
union sqtt_instruction_trace_data {
569
uint64_t api_pso_filter;
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;
585
union sqtt_profiling_mode_data profiling_mode_data;
586
enum sqtt_instruction_trace_mode instruction_trace_mode;
588
union sqtt_instruction_trace_data instruction_trace_data;
591
static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064,
592
"sqtt_file_chunk_api_info doesn't match RGP spec");
594
static void ac_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
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);
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;
609
struct sqtt_code_object_database_record {
613
struct sqtt_file_chunk_code_object_database {
614
struct sqtt_file_chunk_header header;
618
uint32_t record_count;
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)
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;
633
chunk->size = chunk_size;
634
chunk->record_count = rgp_code_object->record_count;
637
struct sqtt_code_object_loader_events_record {
638
uint32_t loader_event_type;
640
uint64_t base_address;
641
uint64_t code_object_hash[2];
645
struct sqtt_file_chunk_code_object_loader_events {
646
struct sqtt_file_chunk_header header;
649
uint32_t record_size;
650
uint32_t record_count;
654
ac_sqtt_fill_loader_events(struct rgp_loader_events *rgp_loader_events,
655
struct sqtt_file_chunk_code_object_loader_events *chunk,
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)) +
666
chunk->offset = file_offset;
668
chunk->record_size = sizeof(struct sqtt_code_object_loader_events_record);
669
chunk->record_count = rgp_loader_events->record_count;
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];
677
struct sqtt_file_chunk_pso_correlation {
678
struct sqtt_file_chunk_header header;
681
uint32_t record_size;
682
uint32_t record_count;
686
ac_sqtt_fill_pso_correlation(struct rgp_pso_correlation *rgp_pso_correlation,
687
struct sqtt_file_chunk_pso_correlation *chunk,
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)) +
697
chunk->offset = file_offset;
699
chunk->record_size = sizeof(struct sqtt_pso_correlation_record);
700
chunk->record_count = rgp_pso_correlation->record_count;
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;
712
int32_t instrumentation_version;
715
int16_t instrumentation_spec_version;
716
int16_t instrumentation_api_version;
717
int32_t compute_unit_index;
722
static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
723
"sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
725
static enum sqtt_version ac_chip_class_to_sqtt_version(enum chip_class chip_class)
727
switch (chip_class) {
729
return SQTT_VERSION_2_2;
731
return SQTT_VERSION_2_3;
733
return SQTT_VERSION_2_4;
735
return SQTT_VERSION_2_4;
737
unreachable("Invalid chip class");
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)
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);
751
chunk->sqtt_version =
752
ac_chip_class_to_sqtt_version(info->chip_class);
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;
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 */
768
static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
769
"sqtt_file_chunk_sqtt_data doesn't match RGP spec");
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)
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;
780
chunk->offset = sizeof(*chunk) + offset;
785
* SQTT queue event timings info.
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;
795
static_assert(sizeof(struct sqtt_file_chunk_queue_event_timings) == 32,
796
"sqtt_file_chunk_queue_event_timings doesn't match RGP spec");
798
struct sqtt_queue_info_record {
800
uint64_t queue_context;
801
struct sqtt_queue_hardware_info hardware_info;
805
static_assert(sizeof(struct sqtt_queue_info_record) == 24,
806
"sqtt_queue_info_record doesn't match RGP spec");
808
struct sqtt_queue_event_record {
809
enum sqtt_queue_event_type event_type;
811
uint64_t frame_index;
812
uint32_t queue_info_index;
813
uint32_t submit_sub_index;
815
uint64_t cpu_timestamp;
816
uint64_t gpu_timestamps[2];
819
static_assert(sizeof(struct sqtt_queue_event_record) == 56,
820
"sqtt_queue_event_record doesn't match RGP spec");
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)
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);
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 +
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;
846
* SQTT clock calibration info.
848
struct sqtt_file_chunk_clock_calibration {
849
struct sqtt_file_chunk_header header;
850
uint64_t cpu_timestamp;
851
uint64_t gpu_timestamp;
855
static_assert(sizeof(struct sqtt_file_chunk_clock_calibration) == 40,
856
"sqtt_file_chunk_clock_calibration doesn't match RGP spec");
859
ac_sqtt_fill_clock_calibration(struct sqtt_file_chunk_clock_calibration *chunk,
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);
869
/* Below values are from from llvm project
870
* llvm/include/llvm/BinaryFormat/ELF.h
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,
880
static enum elf_gfxip_level ac_chip_class_to_elf_gfxip_level(enum chip_class chip_class)
882
switch (chip_class) {
884
return EF_AMDGPU_MACH_AMDGCN_GFX801;
886
return EF_AMDGPU_MACH_AMDGCN_GFX900;
888
return EF_AMDGPU_MACH_AMDGCN_GFX1010;
890
return EF_AMDGPU_MACH_AMDGCN_GFX1030;
892
unreachable("Invalid chip class");
899
struct sqtt_spm_counter_info {
900
enum ac_pc_gpu_block block;
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 */
906
struct sqtt_file_chunk_spm_db {
907
struct sqtt_file_chunk_header header;
909
uint32_t num_timestamps;
910
uint32_t num_spm_counter_info;
911
uint32_t sample_interval;
914
static_assert(sizeof(struct sqtt_file_chunk_spm_db) == 32,
915
"sqtt_file_chunk_spm_db doesn't match RGP spec");
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,
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;
929
chunk->num_timestamps = num_samples;
930
chunk->num_spm_counter_info = spm_trace->num_counters;
931
chunk->sample_interval = spm_trace->sample_interval;
934
static void ac_sqtt_dump_spm(const struct ac_spm_trace_data *spm_trace,
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;
944
fseek(output, sizeof(struct sqtt_file_chunk_spm_db), SEEK_CUR);
945
file_offset += sizeof(struct sqtt_file_chunk_spm_db);
947
/* Skip the reserved 32 bytes of data at beginning. */
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;
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];
958
file_offset += sizeof(timestamp);
959
fwrite(×tamp, sizeof(timestamp), 1, output);
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);
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,
975
file_offset += sizeof(cntr_info);
976
fwrite(&cntr_info, sizeof(cntr_info), 1, output);
978
counter_values_offset += counter_values_size;
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;
985
for (uint32_t c = 0; c < spm_trace->num_counters; c++) {
986
uint64_t offset = spm_trace->counters[c].offset;
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];
992
file_offset += sizeof(value);
993
fwrite(&value, sizeof(value), 1, output);
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);
1005
static void ac_sqtt_dump_data(struct radeon_info *rad_info,
1006
struct ac_thread_trace *thread_trace,
1007
const struct ac_spm_trace_data *spm_trace,
1010
struct ac_thread_trace_data *thread_trace_data = thread_trace->data;
1011
struct sqtt_file_chunk_asic_info asic_info = {0};
1012
struct sqtt_file_chunk_cpu_info cpu_info = {0};
1013
struct sqtt_file_chunk_api_info api_info = {0};
1014
struct sqtt_file_header header = {0};
1015
size_t file_offset = 0;
1016
struct rgp_code_object *rgp_code_object =
1017
&thread_trace_data->rgp_code_object;
1018
struct rgp_loader_events *rgp_loader_events =
1019
&thread_trace_data->rgp_loader_events;
1020
struct rgp_pso_correlation *rgp_pso_correlation =
1021
&thread_trace_data->rgp_pso_correlation;
1022
struct rgp_queue_info *rgp_queue_info = &thread_trace_data->rgp_queue_info;
1023
struct rgp_queue_event *rgp_queue_event = &thread_trace_data->rgp_queue_event;
1024
struct rgp_clock_calibration *rgp_clock_calibration = &thread_trace_data->rgp_clock_calibration;
1026
/* SQTT header file. */
1027
ac_sqtt_fill_header(&header);
1028
file_offset += sizeof(header);
1029
fwrite(&header, sizeof(header), 1, output);
1031
/* SQTT cpu chunk. */
1032
ac_sqtt_fill_cpu_info(&cpu_info);
1033
file_offset += sizeof(cpu_info);
1034
fwrite(&cpu_info, sizeof(cpu_info), 1, output);
1036
/* SQTT asic chunk. */
1037
ac_sqtt_fill_asic_info(rad_info, &asic_info);
1038
file_offset += sizeof(asic_info);
1039
fwrite(&asic_info, sizeof(asic_info), 1, output);
1041
/* SQTT api chunk. */
1042
ac_sqtt_fill_api_info(&api_info);
1043
file_offset += sizeof(api_info);
1044
fwrite(&api_info, sizeof(api_info), 1, output);
1046
/* SQTT code object database chunk. */
1047
if (rgp_code_object->record_count) {
1048
size_t file_code_object_offset = file_offset;
1049
struct sqtt_file_chunk_code_object_database code_object;
1050
struct sqtt_code_object_database_record code_object_record;
1051
uint32_t elf_size_calc = 0;
1052
uint32_t flags = ac_chip_class_to_elf_gfxip_level(rad_info->chip_class);
1054
fseek(output, sizeof(struct sqtt_file_chunk_code_object_database), SEEK_CUR);
1055
file_offset += sizeof(struct sqtt_file_chunk_code_object_database);
1056
list_for_each_entry_safe(struct rgp_code_object_record, record,
1057
&rgp_code_object->record, list) {
1058
fseek(output, sizeof(struct sqtt_code_object_database_record), SEEK_CUR);
1059
ac_rgp_file_write_elf_object(output, file_offset +
1060
sizeof(struct sqtt_code_object_database_record),
1061
record, &elf_size_calc, flags);
1062
/* Align to 4 bytes per the RGP file spec. */
1063
code_object_record.size = ALIGN(elf_size_calc, 4);
1064
fseek(output, file_offset, SEEK_SET);
1065
fwrite(&code_object_record, sizeof(struct sqtt_code_object_database_record),
1067
file_offset += (sizeof(struct sqtt_code_object_database_record) +
1068
code_object_record.size);
1069
fseek(output, file_offset, SEEK_SET);
1071
ac_sqtt_fill_code_object(rgp_code_object, &code_object,
1072
file_code_object_offset,
1073
file_offset - file_code_object_offset);
1074
fseek(output, file_code_object_offset, SEEK_SET);
1075
fwrite(&code_object, sizeof(struct sqtt_file_chunk_code_object_database), 1, output);
1076
fseek(output, file_offset, SEEK_SET);
1079
/* SQTT code object loader events chunk. */
1080
if (rgp_loader_events->record_count) {
1081
struct sqtt_file_chunk_code_object_loader_events loader_events;
1083
ac_sqtt_fill_loader_events(rgp_loader_events, &loader_events,
1085
fwrite(&loader_events, sizeof(struct sqtt_file_chunk_code_object_loader_events),
1087
file_offset += sizeof(struct sqtt_file_chunk_code_object_loader_events);
1088
list_for_each_entry_safe(struct rgp_loader_events_record, record,
1089
&rgp_loader_events->record, list) {
1090
fwrite(record, sizeof(struct sqtt_code_object_loader_events_record), 1, output);
1092
file_offset += (rgp_loader_events->record_count *
1093
sizeof(struct sqtt_code_object_loader_events_record));
1096
/* SQTT pso correlation chunk. */
1097
if (rgp_pso_correlation->record_count) {
1098
struct sqtt_file_chunk_pso_correlation pso_correlation;
1100
ac_sqtt_fill_pso_correlation(rgp_pso_correlation,
1101
&pso_correlation, file_offset);
1102
fwrite(&pso_correlation, sizeof(struct sqtt_file_chunk_pso_correlation), 1,
1104
file_offset += sizeof(struct sqtt_file_chunk_pso_correlation);
1105
list_for_each_entry_safe(struct rgp_pso_correlation_record, record,
1106
&rgp_pso_correlation->record, list) {
1107
fwrite(record, sizeof(struct sqtt_pso_correlation_record),
1110
file_offset += (rgp_pso_correlation->record_count *
1111
sizeof(struct sqtt_pso_correlation_record));
1114
/* SQTT queue event timings. */
1115
if (rgp_queue_info->record_count || rgp_queue_event->record_count) {
1116
struct sqtt_file_chunk_queue_event_timings queue_event_timings;
1118
ac_sqtt_fill_queue_event_timings(rgp_queue_info, rgp_queue_event,
1119
&queue_event_timings);
1120
fwrite(&queue_event_timings, sizeof(struct sqtt_file_chunk_queue_event_timings), 1,
1122
file_offset += sizeof(struct sqtt_file_chunk_queue_event_timings);
1125
list_for_each_entry_safe(struct rgp_queue_info_record, record,
1126
&rgp_queue_info->record, list) {
1127
fwrite(record, sizeof(struct sqtt_queue_info_record), 1, output);
1129
file_offset += (rgp_queue_info->record_count *
1130
sizeof(struct sqtt_queue_info_record));
1133
list_for_each_entry_safe(struct rgp_queue_event_record, record,
1134
&rgp_queue_event->record, list) {
1135
fwrite(record, sizeof(struct sqtt_queue_event_record), 1, output);
1137
file_offset += (rgp_queue_event->record_count *
1138
sizeof(struct sqtt_queue_event_record));
1141
/* SQTT clock calibration. */
1142
if (rgp_clock_calibration->record_count) {
1143
uint32_t num_records = 0;
1145
list_for_each_entry_safe(struct rgp_clock_calibration_record, record,
1146
&rgp_clock_calibration->record, list) {
1147
struct sqtt_file_chunk_clock_calibration clock_calibration;
1148
memset(&clock_calibration, 0, sizeof(clock_calibration));
1150
ac_sqtt_fill_clock_calibration(&clock_calibration, num_records);
1152
clock_calibration.cpu_timestamp = record->cpu_timestamp;
1153
clock_calibration.gpu_timestamp = record->gpu_timestamp;
1155
fwrite(&clock_calibration, sizeof(struct sqtt_file_chunk_clock_calibration), 1,
1157
file_offset += sizeof(struct sqtt_file_chunk_clock_calibration);
1164
for (unsigned i = 0; i < thread_trace->num_traces; i++) {
1165
const struct ac_thread_trace_se *se = &thread_trace->traces[i];
1166
const struct ac_thread_trace_info *info = &se->info;
1167
struct sqtt_file_chunk_sqtt_desc desc = {0};
1168
struct sqtt_file_chunk_sqtt_data data = {0};
1169
uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
1171
/* SQTT desc chunk. */
1172
ac_sqtt_fill_sqtt_desc(rad_info, &desc, i, se->shader_engine, se->compute_unit);
1173
file_offset += sizeof(desc);
1174
fwrite(&desc, sizeof(desc), 1, output);
1176
/* SQTT data chunk. */
1177
ac_sqtt_fill_sqtt_data(&data, i, file_offset, size);
1178
file_offset += sizeof(data);
1179
fwrite(&data, sizeof(data), 1, output);
1181
/* Copy thread trace data generated by the hardware. */
1182
file_offset += size;
1183
fwrite(se->data_ptr, size, 1, output);
1188
ac_sqtt_dump_spm(spm_trace, file_offset, output);
1192
int ac_dump_rgp_capture(struct radeon_info *info,
1193
struct ac_thread_trace *thread_trace,
1194
const struct ac_spm_trace_data *spm_trace)
1196
char filename[2048];
1202
now = *localtime(&t);
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);
1208
f = fopen(filename, "w+");
1212
ac_sqtt_dump_data(info, thread_trace, spm_trace, f);
1214
fprintf(stderr, "RGP capture saved to '%s'\n", filename);