mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 18:18:06 +02:00
intel/error2aub: write GGTT buffers into the aub file
Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com> Reviewed-by: Rafael Antognolli <rafael.antognolli@intel.com>
This commit is contained in:
parent
9b5dc2124f
commit
ca0161f890
3 changed files with 149 additions and 12 deletions
|
|
@ -543,6 +543,71 @@ aub_write_default_setup(struct aub_file *aub)
|
|||
write_execlists_default_setup(aub);
|
||||
else
|
||||
write_legacy_default_setup(aub);
|
||||
|
||||
aub->has_default_setup = true;
|
||||
}
|
||||
|
||||
void
|
||||
aub_write_ggtt(struct aub_file *aub, uint64_t virt_addr, uint64_t size, const void *data)
|
||||
{
|
||||
if (aub->verbose_log_file) {
|
||||
fprintf(aub->verbose_log_file,
|
||||
" Writting GGTT address: 0x%" PRIx64 ", size: %" PRIu64"\n",
|
||||
virt_addr, size);
|
||||
}
|
||||
|
||||
/* Default setup assumes a 1 to 1 mapping between physical and virtual GGTT
|
||||
* addresses. This is somewhat incompatible with the aub_write_ggtt()
|
||||
* function. In practice it doesn't matter as the GGTT writes are used to
|
||||
* replace the default setup and we've taken care to setup the PML4 as the
|
||||
* top of the GGTT.
|
||||
*/
|
||||
assert(!aub->has_default_setup);
|
||||
|
||||
/* Makes the code below a bit simpler. In practice all of the write we
|
||||
* receive from error2aub are page aligned.
|
||||
*/
|
||||
assert(virt_addr % 4096 == 0);
|
||||
assert((aub->phys_addrs_allocator + size) < (1UL << 32));
|
||||
|
||||
/* GGTT PT */
|
||||
uint32_t ggtt_ptes = DIV_ROUND_UP(size, 4096);
|
||||
uint64_t phys_addr = aub->phys_addrs_allocator << 12;
|
||||
aub->phys_addrs_allocator += ggtt_ptes;
|
||||
|
||||
if (aub->verbose_log_file) {
|
||||
fprintf(aub->verbose_log_file,
|
||||
" Writting GGTT address: 0x%" PRIx64 ", size: %" PRIu64" phys_addr=0x%lx entries=%u\n",
|
||||
virt_addr, size, phys_addr, ggtt_ptes);
|
||||
}
|
||||
|
||||
mem_trace_memory_write_header_out(aub,
|
||||
(virt_addr >> 12) * GEN8_PTE_SIZE,
|
||||
ggtt_ptes * GEN8_PTE_SIZE,
|
||||
AUB_MEM_TRACE_MEMORY_ADDRESS_SPACE_GGTT_ENTRY,
|
||||
"GGTT PT");
|
||||
for (uint32_t i = 0; i < ggtt_ptes; i++) {
|
||||
dword_out(aub, 1 + phys_addr + i * 4096);
|
||||
dword_out(aub, 0);
|
||||
}
|
||||
|
||||
/* We write the GGTT buffer through the GGTT aub command rather than the
|
||||
* PHYSICAL aub command. This is because the Gen9 simulator seems to have 2
|
||||
* different set of memory pools for GGTT and physical (probably someone
|
||||
* didn't really understand the concept?).
|
||||
*/
|
||||
static const char null_block[8 * 4096];
|
||||
for (uint64_t offset = 0; offset < size; offset += 4096) {
|
||||
uint32_t block_size = min(4096, size - offset);
|
||||
|
||||
mem_trace_memory_write_header_out(aub, virt_addr + offset, block_size,
|
||||
AUB_MEM_TRACE_MEMORY_ADDRESS_SPACE_GGTT,
|
||||
"GGTT buffer");
|
||||
data_out(aub, (char *) data + offset, block_size);
|
||||
|
||||
/* Pad to a multiple of 4 bytes. */
|
||||
data_out(aub, null_block, -block_size & 3);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -697,3 +762,12 @@ aub_write_exec(struct aub_file *aub, uint64_t batch_addr,
|
|||
}
|
||||
fflush(aub->file);
|
||||
}
|
||||
|
||||
void
|
||||
aub_write_context_execlists(struct aub_file *aub, uint64_t context_addr,
|
||||
enum drm_i915_gem_engine_class engine_class)
|
||||
{
|
||||
const struct engine *cs = engine_from_engine_class(engine_class);
|
||||
uint64_t descriptor = ((uint64_t)1 << 62 | context_addr | CONTEXT_FLAGS);
|
||||
aub_dump_execlist(aub, cs, descriptor);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -45,6 +45,8 @@ struct aub_ppgtt_table {
|
|||
struct aub_file {
|
||||
FILE *file;
|
||||
|
||||
bool has_default_setup;
|
||||
|
||||
/* Set if you want extra logging */
|
||||
FILE *verbose_log_file;
|
||||
|
||||
|
|
@ -85,11 +87,14 @@ aub_write_reloc(const struct gen_device_info *devinfo, void *p, uint64_t v)
|
|||
|
||||
void aub_write_default_setup(struct aub_file *aub);
|
||||
void aub_map_ppgtt(struct aub_file *aub, uint64_t start, uint64_t size);
|
||||
void aub_write_ggtt(struct aub_file *aub, uint64_t virt_addr, uint64_t size, const void *data);
|
||||
void aub_write_trace_block(struct aub_file *aub,
|
||||
uint32_t type, void *virtual,
|
||||
uint32_t size, uint64_t gtt_offset);
|
||||
void aub_write_exec(struct aub_file *aub, uint64_t batch_addr,
|
||||
uint64_t offset, enum drm_i915_gem_engine_class engine_class);
|
||||
void aub_write_context_execlists(struct aub_file *aub, uint64_t context_addr,
|
||||
enum drm_i915_gem_engine_class engine_class);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
|
|||
|
|
@ -308,8 +308,6 @@ main(int argc, char *argv[])
|
|||
NULL, pci_id, "error_state");
|
||||
fail_if(!aub_use_execlists(&aub),
|
||||
"%s currently only works on gen8+\n", argv[0]);
|
||||
|
||||
aub_write_default_setup(&aub);
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
@ -425,7 +423,18 @@ main(int argc, char *argv[])
|
|||
}
|
||||
}
|
||||
|
||||
/* Find the batch that trigger the hang */
|
||||
struct bo *batch_bo = NULL;
|
||||
list_for_each_entry(struct bo, bo_entry, &bo_list, link) {
|
||||
if (bo_entry->type == BO_TYPE_BATCH) {
|
||||
batch_bo = bo_entry;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fail_if(!batch_bo, "Failed to find batch buffer.\n");
|
||||
|
||||
/* Add all the BOs to the aub file */
|
||||
struct bo *hwsp_bo = NULL;
|
||||
list_for_each_entry(struct bo, bo_entry, &bo_list, link) {
|
||||
switch (bo_entry->type) {
|
||||
case BO_TYPE_BATCH:
|
||||
|
|
@ -437,21 +446,70 @@ main(int argc, char *argv[])
|
|||
aub_map_ppgtt(&aub, bo_entry->addr, bo_entry->size);
|
||||
aub_write_trace_block(&aub, AUB_TRACE_TYPE_NOTYPE,
|
||||
bo_entry->data, bo_entry->size, bo_entry->addr);
|
||||
break;
|
||||
case BO_TYPE_CONTEXT:
|
||||
if (bo_entry->engine_class == batch_bo->engine_class &&
|
||||
bo_entry->engine_instance == batch_bo->engine_instance) {
|
||||
hwsp_bo = bo_entry;
|
||||
|
||||
uint32_t *context = (uint32_t *) (bo_entry->data + 4096 /* GuC */ + 4096 /* HWSP */);
|
||||
|
||||
if (context[1] == 0) {
|
||||
fprintf(stderr,
|
||||
"Invalid context image data.\n"
|
||||
"This is likely a kernel issue : https://bugs.freedesktop.org/show_bug.cgi?id=107691\n");
|
||||
}
|
||||
|
||||
/* Update the ring buffer at the last known location. */
|
||||
context[5] = engines[bo_entry->engine_class].instances[bo_entry->engine_instance].ring_buffer_head;
|
||||
context[7] = engines[bo_entry->engine_class].instances[bo_entry->engine_instance].ring_buffer_tail;
|
||||
fprintf(stdout, "engine start=0x%x head/tail=0x%x/0x%x\n",
|
||||
context[9], context[5], context[7]);
|
||||
|
||||
/* The error state doesn't provide a dump of the page tables, so
|
||||
* we have to provide our own, that's easy enough.
|
||||
*/
|
||||
context[49] = aub.pml4.phys_addr >> 32;
|
||||
context[51] = aub.pml4.phys_addr & 0xffffffff;
|
||||
|
||||
fprintf(stdout, "context dump:\n");
|
||||
for (int i = 0; i < 60; i++) {
|
||||
if (i % 4 == 0)
|
||||
fprintf(stdout, "\n 0x%08lx: ", bo_entry->addr + 8192 + i * 4);
|
||||
fprintf(stdout, "0x%08x ", context[i]);
|
||||
}
|
||||
fprintf(stdout, "\n");
|
||||
|
||||
}
|
||||
aub_write_ggtt(&aub, bo_entry->addr, bo_entry->size, bo_entry->data);
|
||||
break;
|
||||
case BO_TYPE_RINGBUFFER:
|
||||
case BO_TYPE_STATUS:
|
||||
case BO_TYPE_CONTEXT_WA:
|
||||
aub_write_ggtt(&aub, bo_entry->addr, bo_entry->size, bo_entry->data);
|
||||
break;
|
||||
case BO_TYPE_UNKNOWN:
|
||||
if (bo_entry->gtt == PPGTT) {
|
||||
aub_map_ppgtt(&aub, bo_entry->addr, bo_entry->size);
|
||||
if (bo_entry->data) {
|
||||
aub_write_trace_block(&aub, AUB_TRACE_TYPE_NOTYPE,
|
||||
bo_entry->data, bo_entry->size, bo_entry->addr);
|
||||
}
|
||||
} else {
|
||||
if (bo_entry->size > 0) {
|
||||
void *zero_data = calloc(1, bo_entry->size);
|
||||
aub_write_ggtt(&aub, bo_entry->addr, bo_entry->size, zero_data);
|
||||
free(zero_data);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally exec the batch BO */
|
||||
bool batch_found = false;
|
||||
list_for_each_entry(struct bo, bo_entry, &bo_list, link) {
|
||||
if (bo_entry->type == BO_TYPE_BATCH) {
|
||||
aub_write_exec(&aub, bo_entry->addr, aub_gtt_size(&aub), bo_entry->engine_class);
|
||||
batch_found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
fail_if(!batch_found, "Failed to find batch buffer.\n");
|
||||
fail_if(!hwsp_bo, "Failed to find Context buffer.\n");
|
||||
aub_write_context_execlists(&aub, hwsp_bo->addr + 4096 /* skip GuC page */, hwsp_bo->engine_class);
|
||||
|
||||
/* Cleanup */
|
||||
list_for_each_entry_safe(struct bo, bo_entry, &bo_list, link) {
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue