mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-29 07:20:23 +01:00
Xe KMD originally put the exec queue snapshot in the wrong topic, XE_TOPIC_GUC_CT. Add it to the right one while still keeping a fallback to the previous place so the new version of the tool is able to parse both before and after the kernel change. Based on previous version by José Roberto de Souza <jose.souza@intel.com> at https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32617 Cc: stable Acked-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: José Roberto de Souza <jose.souza@intel.com> Signed-off-by: Lucas De Marchi <lucas.demarchi@intel.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/33177>
164 lines
5.1 KiB
C
164 lines
5.1 KiB
C
/*
|
|
* Copyright 2024 Intel Corporation
|
|
* SPDX-License-Identifier: MIT
|
|
*/
|
|
|
|
#include "error2hangdump_xe.h"
|
|
|
|
#include <inttypes.h>
|
|
#include <stdint.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
|
|
#include "error_decode_xe_lib.h"
|
|
#include "error2hangdump_lib.h"
|
|
#include "intel/dev/intel_device_info.h"
|
|
#include "util/macros.h"
|
|
|
|
void
|
|
read_xe_data_file(FILE *dump_file, FILE *hang_dump_file, bool verbose)
|
|
{
|
|
enum xe_topic xe_topic = XE_TOPIC_INVALID;
|
|
uint32_t *vm_entry_data = NULL;
|
|
uint32_t vm_entry_len = 0;
|
|
struct xe_vm xe_vm;
|
|
char *line = NULL;
|
|
size_t line_size;
|
|
struct {
|
|
uint64_t *addrs;
|
|
uint8_t len;
|
|
} batch_buffers = { .addrs = NULL, .len = 0 };
|
|
uint32_t i;
|
|
|
|
error_decode_xe_vm_init(&xe_vm);
|
|
|
|
while (getline(&line, &line_size, dump_file) > 0) {
|
|
if (error_decode_xe_decode_topic(line, &xe_topic))
|
|
continue;
|
|
|
|
switch (xe_topic) {
|
|
case XE_TOPIC_JOB: {
|
|
uint64_t u64_value;
|
|
|
|
if (error_decode_xe_read_u64_hexacimal_parameter(line, "batch_addr[", &u64_value)) {
|
|
batch_buffers.addrs = realloc(batch_buffers.addrs, sizeof(uint64_t) * (batch_buffers.len + 1));
|
|
batch_buffers.addrs[batch_buffers.len] = u64_value;
|
|
batch_buffers.len++;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case XE_TOPIC_GUC_CT:
|
|
/*
|
|
* Workaround bug in the kernel that would put the exec queue dump
|
|
* in the wrong place, under "GuC CT" topic.
|
|
*/
|
|
case XE_TOPIC_CONTEXT: {
|
|
enum xe_vm_topic_type type;
|
|
const char *value_ptr;
|
|
bool is_hw_ctx;
|
|
|
|
type = error_decode_xe_read_hw_sp_or_ctx_line(line, &value_ptr, &is_hw_ctx);
|
|
if (type == XE_VM_TOPIC_TYPE_UNKNOWN || !is_hw_ctx) {
|
|
break;
|
|
}
|
|
|
|
switch (type) {
|
|
case XE_VM_TOPIC_TYPE_DATA:
|
|
if (!error_decode_xe_ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len))
|
|
printf("Failed to parse HWCTX data\n");
|
|
break;
|
|
case XE_VM_TOPIC_TYPE_LENGTH: {
|
|
vm_entry_len = strtoul(value_ptr, NULL, 0);
|
|
vm_entry_data = calloc(1, vm_entry_len);
|
|
if (!vm_entry_data) {
|
|
printf("Out of memory to allocate a buffer to store content of HWCTX\n");
|
|
break;
|
|
}
|
|
|
|
error_decode_xe_vm_hw_ctx_set(&xe_vm, vm_entry_len, vm_entry_data);
|
|
break;
|
|
}
|
|
case XE_VM_TOPIC_TYPE_ERROR:
|
|
printf("HWCTX not present in dump, content will be zeroed: %s\n", line);
|
|
break;
|
|
default:
|
|
printf("Not expected line in HWCTX: %s", line);
|
|
}
|
|
|
|
break;
|
|
}
|
|
case XE_TOPIC_VM: {
|
|
enum xe_vm_topic_type type;
|
|
const char *value_ptr;
|
|
uint64_t address;
|
|
|
|
type = error_decode_xe_read_vm_line(line, &address, &value_ptr);
|
|
switch (type) {
|
|
case XE_VM_TOPIC_TYPE_DATA: {
|
|
if (!error_decode_xe_ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len))
|
|
printf("Failed to parse VMA 0x%" PRIx64 " data\n", address);
|
|
break;
|
|
}
|
|
case XE_VM_TOPIC_TYPE_LENGTH: {
|
|
vm_entry_len = strtoul(value_ptr, NULL, 0);
|
|
vm_entry_data = calloc(1, vm_entry_len);
|
|
if (!vm_entry_data) {
|
|
printf("Out of memory to allocate a buffer to store content of VMA 0x%" PRIx64 "\n", address);
|
|
break;
|
|
}
|
|
if (!error_decode_xe_vm_append(&xe_vm, address, vm_entry_len, vm_entry_data)) {
|
|
printf("xe_vm_append() failed for VMA 0x%" PRIx64 "\n", address);
|
|
}
|
|
break;
|
|
}
|
|
case XE_VM_TOPIC_TYPE_ERROR:
|
|
printf("VMA 0x%" PRIx64 " not present in dump, content will be zeroed: %s\n", address, line);
|
|
break;
|
|
default:
|
|
printf("Not expected line in VM state: %s", line);
|
|
}
|
|
|
|
break;
|
|
}
|
|
default:
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (verbose) {
|
|
fprintf(stdout, "BOs found:\n");
|
|
for (i = 0; i < xe_vm.entries_len; i++) {
|
|
struct xe_vm_entry *entry = &xe_vm.entries[i];
|
|
|
|
fprintf(stdout, "\taddr=0x%016" PRIx64 " size=%" PRIu32 "\n", entry->address, entry->length);
|
|
}
|
|
}
|
|
|
|
fail_if(!batch_buffers.len, "Failed to find batch buffer.\n");
|
|
fail_if(!xe_vm.hw_context.length, "Failed to find HW image buffer.\n");
|
|
|
|
for (i = 0; i < xe_vm.entries_len; i++) {
|
|
struct xe_vm_entry *entry = &xe_vm.entries[i];
|
|
const char *name = "user";
|
|
uint32_t j;
|
|
|
|
for (j = 0; j < batch_buffers.len; j++) {
|
|
if (batch_buffers.addrs[j] == entry->address)
|
|
name = "batch";
|
|
}
|
|
|
|
write_buffer(hang_dump_file, entry->address, entry->data, entry->length, name);
|
|
}
|
|
|
|
fprintf(stderr, "writing image buffer size=0x%016" PRIx32 "\n", xe_vm.hw_context.length);
|
|
write_hw_image_buffer(hang_dump_file, xe_vm.hw_context.data, xe_vm.hw_context.length);
|
|
|
|
for (i = 0; i < batch_buffers.len; i++) {
|
|
write_exec(hang_dump_file, batch_buffers.addrs[i]);
|
|
}
|
|
|
|
free(batch_buffers.addrs);
|
|
free(line);
|
|
error_decode_xe_vm_fini(&xe_vm);
|
|
}
|