• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright © 2020 Valve Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
21  * IN THE SOFTWARE.
22  */
23 #include <stdbool.h>
24 #include <string.h>
25 #include <unistd.h>
26 #include "radv_private.h"
27 
28 #include "util/u_process.h"
29 
30 #include "drm-uapi/amdgpu_drm.h"
31 
32 #define SQTT_FILE_MAGIC_NUMBER 0x50303042
33 #define SQTT_FILE_VERSION_MAJOR 1
34 #define SQTT_FILE_VERSION_MINOR 4
35 
36 #define SQTT_GPU_NAME_MAX_SIZE 256
37 #define SQTT_MAX_NUM_SE 32
38 #define SQTT_SA_PER_SE 2
39 
40 enum sqtt_version {
41 	SQTT_VERSION_NONE = 0x0,
42 	SQTT_VERSION_1_0  = 0x1,
43 	SQTT_VERSION_1_1  = 0x2,
44 	SQTT_VERSION_2_0  = 0x3, /* GFX6 */
45 	SQTT_VERSION_2_1  = 0x4, /* GFX7 */
46 	SQTT_VERSION_2_2  = 0x5, /* GFX8 */
47 	SQTT_VERSION_2_3  = 0x6, /* GFX9 */
48 	SQTT_VERSION_2_4  = 0x7  /* GFX10 */
49 };
50 
51 /**
52  * SQTT chunks.
53  */
54 enum sqtt_file_chunk_type {
55 	SQTT_FILE_CHUNK_TYPE_ASIC_INFO,
56 	SQTT_FILE_CHUNK_TYPE_SQTT_DESC,
57 	SQTT_FILE_CHUNK_TYPE_SQTT_DATA,
58 	SQTT_FILE_CHUNK_TYPE_API_INFO,
59 	SQTT_FILE_CHUNK_TYPE_ISA_DATABASE,
60 	SQTT_FILE_CHUNK_TYPE_QUEUE_EVENT_TIMINGS,
61 	SQTT_FILE_CHUNK_TYPE_CLOCK_CALIBRATION,
62 	SQTT_FILE_CHUNK_TYPE_CPU_INFO,
63 	SQTT_FILE_CHUNK_TYPE_SPM_DB,
64 	SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_DATABASE,
65 	SQTT_FILE_CHUNK_TYPE_CODE_OBJECT_LOADER_EVENTS,
66 	SQTT_FILE_CHUNK_TYPE_PSO_CORRELATION,
67 	SQTT_FILE_CHUNK_TYPE_INSTRUMENTATION_TABLE,
68 	SQTT_FILE_CHUNK_TYPE_COUNT
69 };
70 
71 struct sqtt_file_chunk_id {
72 	enum sqtt_file_chunk_type type : 8;
73 	int32_t index : 8;
74 	int32_t reserved : 16;
75 };
76 
77 struct sqtt_file_chunk_header {
78 	struct sqtt_file_chunk_id chunk_id;
79 	uint16_t minor_version;
80 	uint16_t major_version;
81 	int32_t size_in_bytes;
82 	int32_t padding;
83 };
84 
85 /**
86  * SQTT file header.
87  */
88 struct sqtt_file_header_flags {
89 	union {
90 		struct {
91 			int32_t is_semaphore_queue_timing_etw : 1;
92 			int32_t no_queue_semaphore_timestamps : 1;
93 			int32_t reserved : 30;
94 		};
95 
96 		uint32_t value;
97 	};
98 };
99 
100 struct sqtt_file_header {
101 	uint32_t magic_number;
102 	uint32_t version_major;
103 	uint32_t version_minor;
104 	struct sqtt_file_header_flags flags;
105 	int32_t chunk_offset;
106 	int32_t second;
107 	int32_t minute;
108 	int32_t hour;
109 	int32_t day_in_month;
110 	int32_t month;
111 	int32_t year;
112 	int32_t day_in_week;
113 	int32_t day_in_year;
114 	int32_t is_daylight_savings;
115 };
116 
117 static_assert(sizeof(struct sqtt_file_header) == 56,
118 	      "sqtt_file_header doesn't match RGP spec");
119 
120 static void
radv_sqtt_fill_header(struct sqtt_file_header * header)121 radv_sqtt_fill_header(struct sqtt_file_header *header)
122 {
123 	struct tm *timep, result;
124 	time_t raw_time;
125 
126 	header->magic_number = SQTT_FILE_MAGIC_NUMBER;
127 	header->version_major = SQTT_FILE_VERSION_MAJOR;
128 	header->version_minor = SQTT_FILE_VERSION_MINOR;
129 	header->flags.value = 0;
130 	header->flags.is_semaphore_queue_timing_etw = 1;
131 	header->flags.no_queue_semaphore_timestamps = 0;
132 	header->chunk_offset = sizeof(*header);
133 
134 	time(&raw_time);
135 	timep = localtime_r(&raw_time, &result);
136 
137 	header->second = timep->tm_sec;
138 	header->minute = timep->tm_min;
139 	header->hour = timep->tm_hour;
140 	header->day_in_month = timep->tm_mday;
141 	header->month = timep->tm_mon;
142 	header->year = timep->tm_year;
143 	header->day_in_week = timep->tm_wday;
144 	header->day_in_year = timep->tm_yday;
145 	header->is_daylight_savings = timep->tm_isdst;
146 }
147 
148 /**
149  * SQTT CPU info.
150  */
151 struct sqtt_file_chunk_cpu_info {
152 	struct sqtt_file_chunk_header header;
153 	uint32_t vendor_id[4];
154 	uint32_t processor_brand[12];
155 	uint32_t reserved[2];
156 	uint64_t cpu_timestamp_freq;
157 	uint32_t clock_speed;
158 	uint32_t num_logical_cores;
159 	uint32_t num_physical_cores;
160 	uint32_t system_ram_size;
161 };
162 
163 static_assert(sizeof(struct sqtt_file_chunk_cpu_info) == 112,
164 	      "sqtt_file_chunk_cpu_info doesn't match RGP spec");
165 
166 static void
radv_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info * chunk)167 radv_sqtt_fill_cpu_info(struct sqtt_file_chunk_cpu_info *chunk)
168 {
169 	uint64_t system_ram_size = 0;
170 
171 	chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_CPU_INFO;
172 	chunk->header.chunk_id.index = 0;
173 	chunk->header.major_version = 0;
174 	chunk->header.minor_version = 0;
175 	chunk->header.size_in_bytes = sizeof(*chunk);
176 
177 	chunk->cpu_timestamp_freq = 1000000000; /* tick set to 1ns */
178 
179 	/* TODO: fill with real info. */
180 
181 	strncpy((char *)chunk->vendor_id, "Unknown", sizeof(chunk->vendor_id));
182 	strncpy((char *)chunk->processor_brand, "Unknown", sizeof(chunk->processor_brand));
183 	chunk->clock_speed = 0;
184 	chunk->num_logical_cores = 0;
185 	chunk->num_physical_cores = 0;
186 
187 	chunk->system_ram_size = 0;
188 	if (os_get_total_physical_memory(&system_ram_size))
189 		chunk->system_ram_size = system_ram_size / (1024 * 1024);
190 }
191 
192 /**
193  * SQTT ASIC info.
194  */
195 enum sqtt_file_chunk_asic_info_flags
196 {
197 	SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING      = (1 << 0),
198 	SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED = (1 << 1)
199 };
200 
201 enum sqtt_gpu_type {
202 	SQTT_GPU_TYPE_UNKNOWN    = 0x0,
203 	SQTT_GPU_TYPE_INTEGRATED = 0x1,
204 	SQTT_GPU_TYPE_DISCRETE   = 0x2,
205 	SQTT_GPU_TYPE_VIRTUAL    = 0x3
206 };
207 
208 enum sqtt_gfxip_level {
209 	SQTT_GFXIP_LEVEL_NONE       = 0x0,
210 	SQTT_GFXIP_LEVEL_GFXIP_6    = 0x1,
211 	SQTT_GFXIP_LEVEL_GFXIP_7    = 0x2,
212 	SQTT_GFXIP_LEVEL_GFXIP_8    = 0x3,
213 	SQTT_GFXIP_LEVEL_GFXIP_8_1  = 0x4,
214 	SQTT_GFXIP_LEVEL_GFXIP_9    = 0x5,
215 	SQTT_GFXIP_LEVEL_GFXIP_10_1 = 0x7,
216 };
217 
218 enum sqtt_memory_type {
219 	SQTT_MEMORY_TYPE_UNKNOWN = 0x0,
220 	SQTT_MEMORY_TYPE_DDR     = 0x1,
221 	SQTT_MEMORY_TYPE_DDR2    = 0x2,
222 	SQTT_MEMORY_TYPE_DDR3    = 0x3,
223 	SQTT_MEMORY_TYPE_DDR4    = 0x4,
224 	SQTT_MEMORY_TYPE_GDDR3   = 0x10,
225 	SQTT_MEMORY_TYPE_GDDR4   = 0x11,
226 	SQTT_MEMORY_TYPE_GDDR5   = 0x12,
227 	SQTT_MEMORY_TYPE_GDDR6   = 0x13,
228 	SQTT_MEMORY_TYPE_HBM     = 0x20,
229 	SQTT_MEMORY_TYPE_HBM2    = 0x21,
230 	SQTT_MEMORY_TYPE_HBM3    = 0x22,
231 };
232 
233 struct sqtt_file_chunk_asic_info {
234 	struct sqtt_file_chunk_header header;
235 	uint64_t flags;
236 	uint64_t trace_shader_core_clock;
237 	uint64_t trace_memory_clock;
238 	int32_t device_id;
239 	int32_t device_revision_id;
240 	int32_t vgprs_per_simd;
241 	int32_t sgprs_per_simd;
242 	int32_t shader_engines;
243 	int32_t compute_unit_per_shader_engine;
244 	int32_t simd_per_compute_unit;
245 	int32_t wavefronts_per_simd;
246 	int32_t minimum_vgpr_alloc;
247 	int32_t vgpr_alloc_granularity;
248 	int32_t minimum_sgpr_alloc;
249 	int32_t sgpr_alloc_granularity;
250 	int32_t hardware_contexts;
251 	enum sqtt_gpu_type gpu_type;
252 	enum sqtt_gfxip_level gfxip_level;
253 	int32_t gpu_index;
254 	int32_t gds_size;
255 	int32_t gds_per_shader_engine;
256 	int32_t ce_ram_size;
257 	int32_t ce_ram_size_graphics;
258 	int32_t	ce_ram_size_compute;
259 	int32_t max_number_of_dedicated_cus;
260 	int64_t vram_size;
261 	int32_t vram_bus_width;
262 	int32_t l2_cache_size;
263 	int32_t l1_cache_size;
264 	int32_t	lds_size;
265 	char gpu_name[SQTT_GPU_NAME_MAX_SIZE];
266 	float alu_per_clock;
267 	float texture_per_clock;
268 	float prims_per_clock;
269 	float pixels_per_clock;
270 	uint64_t gpu_timestamp_frequency;
271 	uint64_t max_shader_core_clock;
272 	uint64_t max_memory_clock;
273 	uint32_t memory_ops_per_clock;
274 	enum sqtt_memory_type memory_chip_type;
275 	uint32_t lds_granularity;
276 	uint16_t cu_mask[SQTT_MAX_NUM_SE][SQTT_SA_PER_SE];
277 	char reserved1[128];
278 	char padding[4];
279 };
280 
281 static_assert(sizeof(struct sqtt_file_chunk_asic_info) == 720,
282 	      "sqtt_file_chunk_asic_info doesn't match RGP spec");
283 
284 static enum sqtt_gfxip_level
radv_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)285 radv_chip_class_to_sqtt_gfxip_level(enum chip_class chip_class)
286 {
287 	switch (chip_class) {
288 	case GFX6:
289 		return SQTT_GFXIP_LEVEL_GFXIP_6;
290 	case GFX7:
291 		return SQTT_GFXIP_LEVEL_GFXIP_7;
292 	case GFX8:
293 		return SQTT_GFXIP_LEVEL_GFXIP_8;
294 	case GFX9:
295 		return SQTT_GFXIP_LEVEL_GFXIP_9;
296 	case GFX10:
297 		return SQTT_GFXIP_LEVEL_GFXIP_10_1;
298 	default:
299 		unreachable("Invalid chip class");
300 	}
301 }
302 
303 static enum sqtt_memory_type
radv_vram_type_to_sqtt_memory_type(uint32_t vram_type)304 radv_vram_type_to_sqtt_memory_type(uint32_t vram_type)
305 {
306 	switch (vram_type) {
307 	case AMDGPU_VRAM_TYPE_UNKNOWN:
308 		return SQTT_MEMORY_TYPE_UNKNOWN;
309 	case AMDGPU_VRAM_TYPE_DDR2:
310 		return SQTT_MEMORY_TYPE_DDR2;
311 	case AMDGPU_VRAM_TYPE_DDR3:
312 		return SQTT_MEMORY_TYPE_DDR3;
313 	case AMDGPU_VRAM_TYPE_DDR4:
314 		return SQTT_MEMORY_TYPE_DDR4;
315 	case AMDGPU_VRAM_TYPE_GDDR5:
316 		return SQTT_MEMORY_TYPE_GDDR5;
317 	case AMDGPU_VRAM_TYPE_HBM:
318 		return SQTT_MEMORY_TYPE_HBM;
319 	case AMDGPU_VRAM_TYPE_GDDR6:
320 		return SQTT_MEMORY_TYPE_GDDR6;
321 	case AMDGPU_VRAM_TYPE_GDDR1:
322 	case AMDGPU_VRAM_TYPE_GDDR3:
323 	case AMDGPU_VRAM_TYPE_GDDR4:
324 	default:
325 		unreachable("Invalid vram type");
326 	}
327 }
328 
329 static void
radv_fill_sqtt_asic_info(struct radv_device * device,struct sqtt_file_chunk_asic_info * chunk)330 radv_fill_sqtt_asic_info(struct radv_device *device,
331 			 struct sqtt_file_chunk_asic_info *chunk)
332 {
333 	struct radeon_info *rad_info = &device->physical_device->rad_info;
334 	bool has_wave32 = rad_info->chip_class >= GFX10;
335 
336 	chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_ASIC_INFO;
337 	chunk->header.chunk_id.index = 0;
338 	chunk->header.major_version = 0;
339 	chunk->header.minor_version = 4;
340 	chunk->header.size_in_bytes = sizeof(*chunk);
341 
342 	chunk->flags = 0;
343 
344 	/* All chips older than GFX9 are affected by the "SPI not
345 	 * differentiating pkr_id for newwave commands" bug.
346 	 */
347 	if (rad_info->chip_class < GFX9)
348 		chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_SC_PACKER_NUMBERING;
349 
350 	/* Only FIJI and GFX9+ support PS1 events. */
351 	if (rad_info->family == CHIP_FIJI || rad_info->chip_class >= GFX9)
352 		chunk->flags |= SQTT_FILE_CHUNK_ASIC_INFO_FLAG_PS1_EVENT_TOKENS_ENABLED;
353 
354 	chunk->trace_shader_core_clock = rad_info->max_shader_clock * 1000000;
355 	chunk->trace_memory_clock = rad_info->max_memory_clock * 1000000;
356 
357 	chunk->device_id = rad_info->pci_id;
358 	chunk->device_revision_id = rad_info->pci_rev_id;
359 	chunk->vgprs_per_simd = rad_info->num_physical_wave64_vgprs_per_simd *
360 	                        (has_wave32 ? 2 : 1);
361 	chunk->sgprs_per_simd = rad_info->num_physical_sgprs_per_simd;
362 	chunk->shader_engines = rad_info->max_se;
363 	chunk->compute_unit_per_shader_engine = rad_info->min_good_cu_per_sa *
364 	                                        rad_info->max_sh_per_se;
365 	chunk->simd_per_compute_unit = rad_info->num_simd_per_compute_unit;
366 	chunk->wavefronts_per_simd = rad_info->max_wave64_per_simd;
367 
368 	chunk->minimum_vgpr_alloc = rad_info->min_wave64_vgpr_alloc;
369 	chunk->vgpr_alloc_granularity = rad_info->wave64_vgpr_alloc_granularity *
370 	                                (has_wave32 ? 2 : 1);
371 	chunk->minimum_sgpr_alloc = rad_info->min_sgpr_alloc;
372 	chunk->sgpr_alloc_granularity = rad_info->sgpr_alloc_granularity;
373 
374 	chunk->hardware_contexts = 8;
375 	chunk->gpu_type = rad_info->has_dedicated_vram ? SQTT_GPU_TYPE_DISCRETE : SQTT_GPU_TYPE_INTEGRATED;
376 	chunk->gfxip_level = radv_chip_class_to_sqtt_gfxip_level(rad_info->chip_class);
377 	chunk->gpu_index = 0;
378 
379 	chunk->max_number_of_dedicated_cus = 0;
380 	chunk->ce_ram_size = rad_info->ce_ram_size;
381 	chunk->ce_ram_size_graphics = 0;
382 	chunk->ce_ram_size_compute = 0;
383 
384 	chunk->vram_bus_width = rad_info->vram_bit_width;
385 	chunk->vram_size = rad_info->vram_size;
386 	chunk->l2_cache_size = rad_info->l2_cache_size;
387 	chunk->l1_cache_size = rad_info->l1_cache_size;
388 	chunk->lds_size = rad_info->lds_size_per_workgroup;
389 
390 	strncpy(chunk->gpu_name, device->physical_device->name, SQTT_GPU_NAME_MAX_SIZE);
391 
392 	chunk->alu_per_clock = 0.0;
393 	chunk->texture_per_clock = 0.0;
394 	chunk->prims_per_clock = 0.0;
395 	chunk->pixels_per_clock = 0.0;
396 
397 	chunk->gpu_timestamp_frequency = rad_info->clock_crystal_freq * 1000;
398 	chunk->max_shader_core_clock = rad_info->max_shader_clock * 1000000;
399 	chunk->max_memory_clock = rad_info->max_memory_clock * 1000000;
400 	chunk->memory_ops_per_clock = 0;
401 	chunk->memory_chip_type = radv_vram_type_to_sqtt_memory_type(rad_info->vram_type);
402 	chunk->lds_granularity = rad_info->lds_granularity;
403 
404 	for (unsigned se = 0; se < 4; se++) {
405 		for (unsigned sa = 0; sa < 2; sa++) {
406 			chunk->cu_mask[se][sa] = rad_info->cu_mask[se][sa];
407 		}
408 	}
409 }
410 
411 /**
412  * SQTT API info.
413  */
414 enum sqtt_api_type {
415 	SQTT_API_TYPE_DIRECTX_12,
416 	SQTT_API_TYPE_VULKAN,
417 	SQTT_API_TYPE_GENERIC,
418 	SQTT_API_TYPE_OPENCL
419 };
420 
421 enum sqtt_instruction_trace_mode
422 {
423 	SQTT_INSTRUCTION_TRACE_DISABLED   = 0x0,
424 	SQTT_INSTRUCTION_TRACE_FULL_FRAME = 0x1,
425 	SQTT_INSTRUCTION_TRACE_API_PSO    = 0x2,
426 };
427 
428 enum sqtt_profiling_mode {
429 	SQTT_PROFILING_MODE_PRESENT      = 0x0,
430 	SQTT_PROFILING_MODE_USER_MARKERS = 0x1,
431 	SQTT_PROFILING_MODE_INDEX        = 0x2,
432 	SQTT_PROFILING_MODE_TAG          = 0x3,
433 };
434 
435 union sqtt_profiling_mode_data {
436 	struct {
437 		char start[256];
438 		char end[256];
439 	} user_marker_profiling_data;
440 
441 	struct {
442 		uint32_t start;
443 		uint32_t end;
444 	} index_profiling_data;
445 
446 	struct {
447 		uint32_t begin_hi;
448 		uint32_t begin_lo;
449 		uint32_t end_hi;
450 		uint32_t end_lo;
451 	} tag_profiling_data;
452 };
453 
454 union sqtt_instruction_trace_data {
455 	struct {
456 		uint64_t api_pso_filter;
457 	} api_pso_data;
458 
459 	struct {
460 		char start[256];
461 		char end[256];
462 	} user_marker_data;
463 };
464 
465 struct sqtt_file_chunk_api_info {
466 	struct sqtt_file_chunk_header header;
467 	enum sqtt_api_type api_type;
468 	uint16_t major_version;
469 	uint16_t minor_version;
470 	enum sqtt_profiling_mode profiling_mode;
471 	uint32_t reserved;
472 	union sqtt_profiling_mode_data profiling_mode_data;
473 	enum sqtt_instruction_trace_mode instruction_trace_mode;
474 	uint32_t reserved2;
475 	union sqtt_instruction_trace_data instruction_trace_data;
476 };
477 
478 static_assert(sizeof(struct sqtt_file_chunk_api_info) == 1064,
479 	      "sqtt_file_chunk_api_info doesn't match RGP spec");
480 
481 static void
radv_sqtt_fill_api_info(struct sqtt_file_chunk_api_info * chunk)482 radv_sqtt_fill_api_info(struct sqtt_file_chunk_api_info *chunk)
483 {
484 	chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_API_INFO;
485 	chunk->header.chunk_id.index = 0;
486 	chunk->header.major_version = 0;
487 	chunk->header.minor_version = 1;
488 	chunk->header.size_in_bytes = sizeof(*chunk);
489 
490 	chunk->api_type = SQTT_API_TYPE_VULKAN;
491 	chunk->major_version = 0;
492 	chunk->minor_version = 0;
493 	chunk->profiling_mode = SQTT_PROFILING_MODE_PRESENT;
494 	chunk->instruction_trace_mode = SQTT_INSTRUCTION_TRACE_DISABLED;
495 }
496 
497 /**
498  * SQTT desc info.
499  */
500 struct sqtt_file_chunk_sqtt_desc {
501 	struct sqtt_file_chunk_header header;
502 	int32_t shader_engine_index;
503 	enum sqtt_version sqtt_version;
504 	union {
505 		struct {
506 			int32_t instrumentation_version;
507 		} v0;
508 		struct {
509 			int16_t instrumentation_spec_version;
510 			int16_t instrumentation_api_version;
511 			int32_t compute_unit_index;
512 		} v1;
513 	};
514 };
515 
516 static_assert(sizeof(struct sqtt_file_chunk_sqtt_desc) == 32,
517 	      "sqtt_file_chunk_sqtt_desc doesn't match RGP spec");
518 
519 static enum sqtt_version
radv_chip_class_to_sqtt_version(enum chip_class chip_class)520 radv_chip_class_to_sqtt_version(enum chip_class chip_class)
521 {
522 	switch (chip_class) {
523 	case GFX6:
524 		return SQTT_VERSION_2_0;
525 	case GFX7:
526 		return SQTT_VERSION_2_1;
527 	case GFX8:
528 		return SQTT_VERSION_2_2;
529 	case GFX9:
530 		return SQTT_VERSION_2_3;
531 	case GFX10:
532 		return SQTT_VERSION_2_4;
533 	default:
534 		unreachable("Invalid chip class");
535 	}
536 }
537 
538 static void
radv_sqtt_fill_sqtt_desc(struct radv_device * device,struct sqtt_file_chunk_sqtt_desc * chunk,int32_t chunk_index,int32_t shader_engine_index,int32_t compute_unit_index)539 radv_sqtt_fill_sqtt_desc(struct radv_device *device,
540 			 struct sqtt_file_chunk_sqtt_desc *chunk,
541 			 int32_t chunk_index,
542 			 int32_t shader_engine_index,
543 			 int32_t compute_unit_index)
544 {
545 	chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DESC;
546 	chunk->header.chunk_id.index = chunk_index;
547 	chunk->header.major_version = 0;
548 	chunk->header.minor_version = 2;
549 	chunk->header.size_in_bytes = sizeof(*chunk);
550 
551 	chunk->sqtt_version = radv_chip_class_to_sqtt_version(device->physical_device->rad_info.chip_class);
552 	chunk->shader_engine_index = shader_engine_index;
553 	chunk->v1.instrumentation_spec_version = 1;
554 	chunk->v1.instrumentation_api_version = 0;
555 	chunk->v1.compute_unit_index = compute_unit_index;
556 }
557 
558 /**
559  * SQTT data info.
560  */
561 struct sqtt_file_chunk_sqtt_data {
562 	struct sqtt_file_chunk_header header;
563 	int32_t offset; /* in bytes */
564 	int32_t size; /* in bytes */
565 };
566 
567 static_assert(sizeof(struct sqtt_file_chunk_sqtt_data) == 24,
568 	      "sqtt_file_chunk_sqtt_data doesn't match RGP spec");
569 
570 static void
radv_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data * chunk,int32_t chunk_index,int32_t offset,int32_t size)571 radv_sqtt_fill_sqtt_data(struct sqtt_file_chunk_sqtt_data *chunk,
572 			 int32_t chunk_index, int32_t offset, int32_t size)
573 {
574 	chunk->header.chunk_id.type = SQTT_FILE_CHUNK_TYPE_SQTT_DATA;
575 	chunk->header.chunk_id.index = chunk_index;
576 	chunk->header.major_version = 0;
577 	chunk->header.minor_version = 0;
578 	chunk->header.size_in_bytes = sizeof(*chunk) + size;
579 
580 	chunk->offset = sizeof(*chunk) + offset;
581 	chunk->size = size;
582 }
583 
584 static void
radv_sqtt_dump_data(struct radv_device * device,const struct radv_thread_trace * thread_trace,FILE * output)585 radv_sqtt_dump_data(struct radv_device *device,
586 		    const struct radv_thread_trace *thread_trace,
587 		    FILE *output)
588 {
589 	struct sqtt_file_chunk_asic_info asic_info = {0};
590 	struct sqtt_file_chunk_cpu_info cpu_info = {0};
591 	struct sqtt_file_chunk_api_info api_info = {0};
592 	struct sqtt_file_header header = {0};
593 	size_t file_offset = 0;
594 
595 	/* SQTT header file. */
596 	radv_sqtt_fill_header(&header);
597 	file_offset += sizeof(header);
598 	fwrite(&header, sizeof(header), 1, output);
599 
600 	/* SQTT cpu chunk. */
601 	radv_sqtt_fill_cpu_info(&cpu_info);
602 	file_offset += sizeof(cpu_info);
603 	fwrite(&cpu_info, sizeof(cpu_info), 1, output);
604 
605 	/* SQTT asic chunk. */
606 	radv_fill_sqtt_asic_info(device, &asic_info);
607 	file_offset += sizeof(asic_info);
608 	fwrite(&asic_info, sizeof(asic_info), 1, output);
609 
610 	/* SQTT api chunk. */
611 	radv_sqtt_fill_api_info(&api_info);
612 	file_offset += sizeof(api_info);
613 	fwrite(&api_info, sizeof(api_info), 1, output);
614 
615 	if (thread_trace) {
616 		for (unsigned i = 0; i < thread_trace->num_traces; i++) {
617 			const struct radv_thread_trace_se *se = &thread_trace->traces[i];
618 			const struct radv_thread_trace_info *info = &se->info;
619 			struct sqtt_file_chunk_sqtt_desc desc = {0};
620 			struct sqtt_file_chunk_sqtt_data data = {0};
621 			uint64_t size = info->cur_offset * 32; /* unit of 32 bytes */
622 
623 			/* SQTT desc chunk. */
624 			radv_sqtt_fill_sqtt_desc(device, &desc, i,
625 						 se->shader_engine,
626 						 se->compute_unit);
627 			file_offset += sizeof(desc);
628 			fwrite(&desc, sizeof(desc), 1, output);
629 
630 			/* SQTT data chunk. */
631 			radv_sqtt_fill_sqtt_data(&data, i, file_offset, size);
632 			file_offset += sizeof(data);
633 			fwrite(&data, sizeof(data), 1, output);
634 
635 			/* Copy thread trace data generated by the hardware. */
636 			file_offset += size;
637 			fwrite(se->data_ptr, size, 1, output);
638 		}
639 	}
640 }
641 
642 int
radv_dump_thread_trace(struct radv_device * device,const struct radv_thread_trace * thread_trace)643 radv_dump_thread_trace(struct radv_device *device,
644 		       const struct radv_thread_trace *thread_trace)
645 {
646 	char filename[2048];
647 	struct tm now;
648 	time_t t;
649 	FILE *f;
650 
651 	t = time(NULL);
652 	now = *localtime(&t);
653 
654 	snprintf(filename, sizeof(filename), "/tmp/%s_%04d.%02d.%02d_%02d.%02d.rgp",
655 		 util_get_process_name(), 1900 + now.tm_year, now.tm_mon + 1,
656 		 now.tm_mday, now.tm_hour, now.tm_min);
657 
658 	f = fopen(filename, "w+");
659 	if (!f)
660 		return -1;
661 
662 	radv_sqtt_dump_data(device, thread_trace, f);
663 
664 	fprintf(stderr, "Thread trace capture saved to '%s'\n", filename);
665 
666 	fclose(f);
667 	return 0;
668 }
669 
670