From a7651d833751e4972834c01021f86c183e68fd79 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jos=C3=A9=20Roberto=20de=20Souza?= Date: Wed, 3 Apr 2024 13:07:18 -0700 Subject: [PATCH] intel/tools: Move more Xe KMD error decode functions to error_decode_xe_lib MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit More code tha now is used by aubinator_error_decode but in next patches will also be used by error2hangdump. No changes in behavior expected here. Reviewed-by: Lionel Landwerlin Signed-off-by: José Roberto de Souza Part-of: --- src/intel/tools/aubinator_error_decode_xe.c | 241 ++------------------ src/intel/tools/error_decode_xe_lib.c | 194 ++++++++++++++++ src/intel/tools/error_decode_xe_lib.h | 36 +++ 3 files changed, 244 insertions(+), 227 deletions(-) diff --git a/src/intel/tools/aubinator_error_decode_xe.c b/src/intel/tools/aubinator_error_decode_xe.c index a9058922734..60695583c52 100644 --- a/src/intel/tools/aubinator_error_decode_xe.c +++ b/src/intel/tools/aubinator_error_decode_xe.c @@ -15,219 +15,6 @@ #include "intel/compiler/brw_isa_info.h" #include "intel/dev/intel_device_info.h" -enum xe_vm_topic_type { - XE_VM_TOPIC_TYPE_UNKNOWN = 0, - XE_VM_TOPIC_TYPE_LENGTH, - XE_VM_TOPIC_TYPE_DATA, - XE_VM_TOPIC_TYPE_ERROR, -}; - -struct xe_vm_entry { - uint64_t address; - uint32_t length; - const uint32_t *data; -}; - -struct xe_vm { - /* TODO: entries could be appended sorted or a hash could be used to - * optimize performance - */ - struct xe_vm_entry *entries; - uint32_t entries_len; - - struct xe_vm_entry hw_context; -}; - -/* return type of VM topic lines like '[200000].data: x...' and points - * value_ptr to first char of data of topic type - */ -static enum xe_vm_topic_type -read_xe_vm_line(const char *line, uint64_t *address, const char **value_ptr) -{ - enum xe_vm_topic_type type; - char text_addr[64]; - int i; - - if (*line != '[') - return XE_VM_TOPIC_TYPE_UNKNOWN; - - for (i = 0, line++; *line != ']'; i++, line++) - text_addr[i] = *line; - - text_addr[i] = 0; - *address = (uint64_t)strtoull(text_addr, NULL, 16); - - /* at this point line points to last address digit so +3 to point to type */ - line += 2; - switch (*line) { - case 'd': - type = XE_VM_TOPIC_TYPE_DATA; - break; - case 'l': - type = XE_VM_TOPIC_TYPE_LENGTH; - break; - case 'e': - type = XE_VM_TOPIC_TYPE_ERROR; - break; - default: - printf("type char: %c\n", *line); - return XE_VM_TOPIC_TYPE_UNKNOWN; - } - - for (; *line != ':'; line++); - - *value_ptr = line + 2; - return type; -} - -/* - * similar to read_xe_vm_line() but it parses '[HWCTX].data: ...' - */ -static enum xe_vm_topic_type -read_xe_hw_sp_or_ctx_line(const char *line, const char **value_ptr, bool *is_hw_ctx) -{ - enum xe_vm_topic_type type; - char text_addr[64]; - bool is_hw_sp; - int i; - - if (*line != '\t') - return XE_VM_TOPIC_TYPE_UNKNOWN; - - line++; - if (*line != '[') - return XE_VM_TOPIC_TYPE_UNKNOWN; - - for (i = 0, line++; *line != ']'; i++, line++) - text_addr[i] = *line; - - text_addr[i] = 0; - *is_hw_ctx = strncmp(text_addr, "HWCTX", strlen("HWCTX")) == 0; - is_hw_sp = strncmp(text_addr, "HWSP", strlen("HWSP")) == 0; - if (*is_hw_ctx == false && is_hw_sp == false) - return XE_VM_TOPIC_TYPE_UNKNOWN; - - /* at this point line points to last address digit so +3 to point to type */ - line += 2; - switch (*line) { - case 'd': - type = XE_VM_TOPIC_TYPE_DATA; - break; - case 'l': - type = XE_VM_TOPIC_TYPE_LENGTH; - break; - case 'e': - type = XE_VM_TOPIC_TYPE_ERROR; - break; - default: - printf("type char: %c\n", *line); - return XE_VM_TOPIC_TYPE_UNKNOWN; - } - - for (; *line != ':'; line++); - - *value_ptr = line + 2; - return type; -} - -static void xe_vm_init(struct xe_vm *xe_vm) -{ - xe_vm->entries = NULL; - xe_vm->entries_len = 0; - memset(&xe_vm->hw_context, 0, sizeof(xe_vm->hw_context)); -} - -static void xe_vm_fini(struct xe_vm *xe_vm) -{ - uint32_t i; - - for (i = 0; i < xe_vm->entries_len; i++) - free((uint32_t *)xe_vm->entries[i].data); - - free((uint32_t *)xe_vm->hw_context.data); - free(xe_vm->entries); -} - -static void -xe_vm_entry_set(struct xe_vm_entry *entry, const uint64_t address, - const uint32_t length, const uint32_t *data) -{ - entry->address = address; - entry->length = length; - entry->data = data; -} - -static void -xe_vm_hw_ctx_set(struct xe_vm *xe_vm, const uint32_t length, - const uint32_t *data) -{ - xe_vm_entry_set(&xe_vm->hw_context, 0, length, data); -} - -/* - * xe_vm_fini() will take care to free data - */ -static bool -xe_vm_append(struct xe_vm *xe_vm, const uint64_t address, const uint32_t length, const uint32_t *data) -{ - size_t len = sizeof(*xe_vm->entries) * (xe_vm->entries_len + 1); - - xe_vm->entries = realloc(xe_vm->entries, len); - if (!xe_vm->entries) - return false; - - xe_vm_entry_set(&xe_vm->entries[xe_vm->entries_len], address, length, data); - xe_vm->entries_len++; - return true; -} - -static const struct xe_vm_entry * -xe_vm_entry_get(struct xe_vm *xe_vm, const uint64_t address) -{ - uint32_t i; - - for (i = 0; i < xe_vm->entries_len; i++) { - struct xe_vm_entry *entry = &xe_vm->entries[i]; - - if (entry->address == address) - return entry; - - if (address > entry->address && - address < (entry->address + entry->length)) - return entry; - } - - return NULL; -} - -static uint32_t * -xe_vm_entry_address_get_data(const struct xe_vm_entry *entry, const uint64_t address) -{ - uint32_t offset = (address - entry->address) / sizeof(uint32_t); - return (uint32_t *)&entry->data[offset]; -} - -static uint32_t -xe_vm_entry_address_get_len(const struct xe_vm_entry *entry, const uint64_t address) -{ - return entry->length - (address - entry->address); -} - -static bool -ascii85_decode_allocated(const char *in, uint32_t *out, uint32_t vm_entry_bytes_len) -{ - const uint32_t dword_len = vm_entry_bytes_len / sizeof(uint32_t); - uint32_t i; - - for (i = 0; (*in >= '!') && (*in <= 'z') && (i < dword_len); i++) - in = ascii85_decode_char(in, &out[i]); - - if (dword_len != i) - printf("mismatch dword_len=%u i=%u\n", dword_len, i); - - return dword_len == i && (*in < '!' || *in > 'z'); -} - static struct intel_batch_decode_bo get_bo(void *user_data, bool ppgtt, uint64_t bo_addr) { @@ -238,13 +25,13 @@ get_bo(void *user_data, bool ppgtt, uint64_t bo_addr) if (!ppgtt) return ret; - vm_entry = xe_vm_entry_get(xe_vm, bo_addr); + vm_entry = error_decode_xe_vm_entry_get(xe_vm, bo_addr); if (!vm_entry) return ret; ret.addr = bo_addr; - ret.map = xe_vm_entry_address_get_data(vm_entry, bo_addr); - ret.size = xe_vm_entry_address_get_len(vm_entry, bo_addr); + ret.map = error_decode_xe_vm_entry_address_get_data(vm_entry, bo_addr); + ret.size = error_decode_xe_vm_entry_address_get_len(vm_entry, bo_addr); return ret; } @@ -302,7 +89,7 @@ read_xe_data_file(FILE *file, size_t line_size; enum xe_topic xe_topic = XE_TOPIC_INVALID; - xe_vm_init(&xe_vm); + error_decode_xe_vm_init(&xe_vm); while (getline(&line, &line_size, file) > 0) { bool topic_changed = false; @@ -366,7 +153,7 @@ read_xe_data_file(FILE *file, bool is_hw_ctx; /* TODO: what to do with HWSP? */ - type = read_xe_hw_sp_or_ctx_line(line, &value_ptr, &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) { print_line = false; @@ -375,7 +162,7 @@ read_xe_data_file(FILE *file, switch (type) { case XE_VM_TOPIC_TYPE_DATA: - if (!ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len)) + 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: { @@ -387,7 +174,7 @@ read_xe_data_file(FILE *file, } if (is_hw_ctx) - xe_vm_hw_ctx_set(&xe_vm, vm_entry_len, vm_entry_data); + error_decode_xe_vm_hw_ctx_set(&xe_vm, vm_entry_len, vm_entry_data); break; } case XE_VM_TOPIC_TYPE_ERROR: @@ -406,10 +193,10 @@ read_xe_data_file(FILE *file, uint64_t address; print_line = false; - type = read_xe_vm_line(line, &address, &value_ptr); + type = error_decode_xe_read_vm_line(line, &address, &value_ptr); switch (type) { case XE_VM_TOPIC_TYPE_DATA: { - if (!ascii85_decode_allocated(value_ptr, vm_entry_data, vm_entry_len)) + 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; } @@ -420,7 +207,7 @@ read_xe_data_file(FILE *file, printf("Out of memory to allocate a buffer to store content of VMA 0x%" PRIx64 "\n", address); break; } - if (!xe_vm_append(&xe_vm, address, vm_entry_len, vm_entry_data)) { + 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; } @@ -453,7 +240,7 @@ read_xe_data_file(FILE *file, for (int i = 0; i < batch_buffers.len; i++) { const uint64_t bb_addr = batch_buffers.addrs[i]; - const struct xe_vm_entry *vm_entry = xe_vm_entry_get(&xe_vm, bb_addr); + const struct xe_vm_entry *vm_entry = error_decode_xe_vm_entry_get(&xe_vm, bb_addr); const char *engine_name = intel_engines_class_to_string(engine_class); const char *buffer_name = "batch buffer"; const uint32_t *bb_data; @@ -462,8 +249,8 @@ read_xe_data_file(FILE *file, if (!vm_entry) continue; - bb_data = xe_vm_entry_address_get_data(vm_entry, bb_addr); - bb_len = xe_vm_entry_address_get_len(vm_entry, bb_addr); + bb_data = error_decode_xe_vm_entry_address_get_data(vm_entry, bb_addr); + bb_len = error_decode_xe_vm_entry_address_get_len(vm_entry, bb_addr); print_batch(&batch_ctx, bb_data, bb_addr, bb_len, buffer_name, engine_name, engine_class, batch_flags, option_print_all_bb, ring_wraps); @@ -488,5 +275,5 @@ read_xe_data_file(FILE *file, intel_spec_destroy(spec); free(batch_buffers.addrs); free(line); - xe_vm_fini(&xe_vm); + error_decode_xe_vm_fini(&xe_vm); } diff --git a/src/intel/tools/error_decode_xe_lib.c b/src/intel/tools/error_decode_xe_lib.c index 7a202334589..dc2fb0b5e79 100644 --- a/src/intel/tools/error_decode_xe_lib.c +++ b/src/intel/tools/error_decode_xe_lib.c @@ -8,6 +8,7 @@ #include #include +#include "error_decode_lib.h" #include "util/macros.h" static const char * @@ -91,3 +92,196 @@ error_decode_xe_decode_topic(const char *line, enum xe_topic *new_topic) return topic_changed; } + +/* return type of VM topic lines like '[200000].data: x...' and points + * value_ptr to first char of data of topic type + */ +enum xe_vm_topic_type +error_decode_xe_read_vm_line(const char *line, uint64_t *address, const char **value_ptr) +{ + enum xe_vm_topic_type type; + char text_addr[64]; + int i; + + if (*line != '[') + return XE_VM_TOPIC_TYPE_UNKNOWN; + + for (i = 0, line++; *line != ']'; i++, line++) + text_addr[i] = *line; + + text_addr[i] = 0; + *address = (uint64_t)strtoull(text_addr, NULL, 16); + + /* at this point line points to last address digit so +3 to point to type */ + line += 2; + switch (*line) { + case 'd': + type = XE_VM_TOPIC_TYPE_DATA; + break; + case 'l': + type = XE_VM_TOPIC_TYPE_LENGTH; + break; + case 'e': + type = XE_VM_TOPIC_TYPE_ERROR; + break; + default: + printf("type char: %c\n", *line); + return XE_VM_TOPIC_TYPE_UNKNOWN; + } + + for (; *line != ':'; line++); + + *value_ptr = line + 2; + return type; +} + +/* + * similar to read_xe_vm_line() but it parses '[HWCTX].data: ...' + */ +enum xe_vm_topic_type +error_decode_xe_read_hw_sp_or_ctx_line(const char *line, const char **value_ptr, bool *is_hw_ctx) +{ + enum xe_vm_topic_type type; + char text_addr[64]; + bool is_hw_sp; + int i; + + if (*line != '\t') + return XE_VM_TOPIC_TYPE_UNKNOWN; + + line++; + if (*line != '[') + return XE_VM_TOPIC_TYPE_UNKNOWN; + + for (i = 0, line++; *line != ']'; i++, line++) + text_addr[i] = *line; + + text_addr[i] = 0; + *is_hw_ctx = strncmp(text_addr, "HWCTX", strlen("HWCTX")) == 0; + is_hw_sp = strncmp(text_addr, "HWSP", strlen("HWSP")) == 0; + if (*is_hw_ctx == false && is_hw_sp == false) + return XE_VM_TOPIC_TYPE_UNKNOWN; + + /* at this point line points to last address digit so +3 to point to type */ + line += 2; + switch (*line) { + case 'd': + type = XE_VM_TOPIC_TYPE_DATA; + break; + case 'l': + type = XE_VM_TOPIC_TYPE_LENGTH; + break; + case 'e': + type = XE_VM_TOPIC_TYPE_ERROR; + break; + default: + printf("type char: %c\n", *line); + return XE_VM_TOPIC_TYPE_UNKNOWN; + } + + for (; *line != ':'; line++); + + *value_ptr = line + 2; + return type; +} + +void error_decode_xe_vm_init(struct xe_vm *xe_vm) +{ + xe_vm->entries = NULL; + xe_vm->entries_len = 0; + memset(&xe_vm->hw_context, 0, sizeof(xe_vm->hw_context)); +} + +void error_decode_xe_vm_fini(struct xe_vm *xe_vm) +{ + uint32_t i; + + for (i = 0; i < xe_vm->entries_len; i++) + free((uint32_t *)xe_vm->entries[i].data); + + free((uint32_t *)xe_vm->hw_context.data); + free(xe_vm->entries); +} + +static void +xe_vm_entry_set(struct xe_vm_entry *entry, const uint64_t address, + const uint32_t length, const uint32_t *data) +{ + entry->address = address; + entry->length = length; + entry->data = data; +} + +void +error_decode_xe_vm_hw_ctx_set(struct xe_vm *xe_vm, const uint32_t length, + const uint32_t *data) +{ + xe_vm_entry_set(&xe_vm->hw_context, 0, length, data); +} + +/* + * error_decode_xe_vm_fini() will take care to free data + */ +bool +error_decode_xe_vm_append(struct xe_vm *xe_vm, const uint64_t address, + const uint32_t length, const uint32_t *data) +{ + size_t len = sizeof(*xe_vm->entries) * (xe_vm->entries_len + 1); + + xe_vm->entries = realloc(xe_vm->entries, len); + if (!xe_vm->entries) + return false; + + xe_vm_entry_set(&xe_vm->entries[xe_vm->entries_len], address, length, data); + xe_vm->entries_len++; + return true; +} + +const struct xe_vm_entry * +error_decode_xe_vm_entry_get(struct xe_vm *xe_vm, const uint64_t address) +{ + uint32_t i; + + for (i = 0; i < xe_vm->entries_len; i++) { + struct xe_vm_entry *entry = &xe_vm->entries[i]; + + if (entry->address == address) + return entry; + + if (address > entry->address && + address < (entry->address + entry->length)) + return entry; + } + + return NULL; +} + +uint32_t * +error_decode_xe_vm_entry_address_get_data(const struct xe_vm_entry *entry, + const uint64_t address) +{ + uint32_t offset = (address - entry->address) / sizeof(uint32_t); + return (uint32_t *)&entry->data[offset]; +} + +uint32_t +error_decode_xe_vm_entry_address_get_len(const struct xe_vm_entry *entry, + const uint64_t address) +{ + return entry->length - (address - entry->address); +} + +bool +error_decode_xe_ascii85_decode_allocated(const char *in, uint32_t *out, uint32_t vm_entry_bytes_len) +{ + const uint32_t dword_len = vm_entry_bytes_len / sizeof(uint32_t); + uint32_t i; + + for (i = 0; (*in >= '!') && (*in <= 'z') && (i < dword_len); i++) + in = ascii85_decode_char(in, &out[i]); + + if (dword_len != i) + printf("mismatch dword_len=%u i=%u\n", dword_len, i); + + return dword_len == i && (*in < '!' || *in > 'z'); +} diff --git a/src/intel/tools/error_decode_xe_lib.h b/src/intel/tools/error_decode_xe_lib.h index 65028a000ee..5ce538e44cf 100644 --- a/src/intel/tools/error_decode_xe_lib.h +++ b/src/intel/tools/error_decode_xe_lib.h @@ -17,8 +17,44 @@ enum xe_topic { XE_TOPIC_INVALID, }; +enum xe_vm_topic_type { + XE_VM_TOPIC_TYPE_UNKNOWN = 0, + XE_VM_TOPIC_TYPE_LENGTH, + XE_VM_TOPIC_TYPE_DATA, + XE_VM_TOPIC_TYPE_ERROR, +}; + +struct xe_vm_entry { + uint64_t address; + uint32_t length; + const uint32_t *data; +}; + +struct xe_vm { + /* TODO: entries could be appended sorted or a hash could be used to + * optimize performance + */ + struct xe_vm_entry *entries; + uint32_t entries_len; + + struct xe_vm_entry hw_context; +}; + bool error_decode_xe_read_u64_hexacimal_parameter(const char *line, const char *parameter, uint64_t *value); bool error_decode_xe_read_hexacimal_parameter(const char *line, const char *parameter, int *value); bool error_decode_xe_read_engine_name(const char *line, char *ring_name); bool error_decode_xe_decode_topic(const char *line, enum xe_topic *new_topic); + +enum xe_vm_topic_type error_decode_xe_read_vm_line(const char *line, uint64_t *address, const char **value_ptr); +enum xe_vm_topic_type error_decode_xe_read_hw_sp_or_ctx_line(const char *line, const char **value_ptr, bool *is_hw_ctx); + +void error_decode_xe_vm_init(struct xe_vm *xe_vm); +void error_decode_xe_vm_fini(struct xe_vm *xe_vm); +void error_decode_xe_vm_hw_ctx_set(struct xe_vm *xe_vm, const uint32_t length, const uint32_t *data); +bool error_decode_xe_vm_append(struct xe_vm *xe_vm, const uint64_t address, const uint32_t length, const uint32_t *data); +const struct xe_vm_entry *error_decode_xe_vm_entry_get(struct xe_vm *xe_vm, const uint64_t address); +uint32_t *error_decode_xe_vm_entry_address_get_data(const struct xe_vm_entry *entry, const uint64_t address); +uint32_t error_decode_xe_vm_entry_address_get_len(const struct xe_vm_entry *entry, const uint64_t address); + +bool error_decode_xe_ascii85_decode_allocated(const char *in, uint32_t *out, uint32_t vm_entry_bytes_len);