struct cmdstream *shader_cs;
struct cmdstream *shader_log;
+ struct cmdstream *cp_log;
struct list_head cs_list;
}
static void
-rd_write_cs_buffer(FILE *out, struct cmdstream *cs)
+rd_write_gpu_addr_section(FILE *out, struct cmdstream *cs, enum rd_sect_type section)
{
- if (cs->cur == 0)
- return;
-
const uint32_t packet[] = {(uint32_t)cs->iova,
(uint32_t)(cs->cur * sizeof(uint32_t)),
(uint32_t)(cs->iova >> 32)};
- struct rd_section section_address = {.type = RD_GPUADDR,
+ struct rd_section section_address = {.type = section,
.size = sizeof(packet)};
fwrite(§ion_address, sizeof(section_address), 1, out);
fwrite(packet, sizeof(packet), 1, out);
+}
+
+static void
+rd_write_cs_buffer(FILE *out, struct cmdstream *cs)
+{
+ if (cs->cur == 0)
+ return;
+
+ rd_write_gpu_addr_section(out, cs, RD_GPUADDR);
struct rd_section section_contents = {.type = RD_BUFFER_CONTENTS,
.size = uint32_t(cs->cur * sizeof(uint32_t))};
ctx->shader_log->mem[1] = ctx->shader_log->iova >> 32;
ctx->shader_log->cur = ctx->shader_log->total_size;
+ ctx->cp_log = cs_alloc(ctx, 8 * 1024 * 1024);
+ ((uint64_t *)ctx->cp_log->mem)[0] = ctx->cp_log->iova + 2 * sizeof(uint64_t);
+ ((uint64_t *)ctx->cp_log->mem)[1] = sizeof(uint64_t);
+ ctx->cp_log->cur = ctx->cp_log->total_size;
+
struct ir3_compiler_options options{};
ctx->compiler =
ir3_compiler_create(NULL, dev_id, &options);
fwrite(§ion_gpu_id, sizeof(section_gpu_id), 1, out);
fwrite(&gpu_id, sizeof(uint32_t), 1, out);
- const uint32_t packet[] = {(uint32_t)ctx->shader_log->iova,
- (uint32_t)(ctx->shader_log->total_size),
- (uint32_t)(ctx->shader_log->iova >> 32)};
- struct rd_section section_shader_log = {.type = RD_SHADER_LOG_BUFFER,
- .size = sizeof(packet)};
- fwrite(§ion_shader_log, sizeof(section_shader_log), 1, out);
- fwrite(packet, sizeof(packet), 1, out);
+ rd_write_gpu_addr_section(out, ctx->shader_log, RD_SHADER_LOG_BUFFER);
+ rd_write_gpu_addr_section(out, ctx->cp_log, RD_CP_LOG_BUFFER);
list_for_each_entry (struct cmdstream, cs, &ctx->cs_list, link) {
rd_write_cs_buffer(out, cs);
pkt7(prev_cs, CP_INDIRECT_BUFFER, 3); \
pkt_qw(prev_cs, cs->iova); \
pkt(prev_cs, ibcs_size);
+
+static void
+gpu_print(struct replay_context *ctx, struct cmdstream *_cs, uint64_t iova,
+ uint32_t dwords)
+{
+ uint64_t header_iova, body_iova;
+ struct cmdstream *prev_cs = _cs;
+ struct cmdstream *cs = cs_alloc(ctx, 4096);
+ /* Commands that are being modified should be in a separate cmdstream,
+ * otherwise they would be prefetched and writes would not be visible.
+ */
+ {
+ /* Write size into entry's header */
+ pkt7(cs, CP_MEM_WRITE, 4);
+ header_iova = cs_get_cur_iova(cs);
+ pkt_qw(cs, 0xdeadbeef);
+ uint64_t size_iova = cs_get_cur_iova(cs);
+ pkt(cs, dwords * 4);
+ pkt(cs, 0);
+
+ /* Copy the data into entry's body */
+ pkt7(cs, CP_MEMCPY, 5);
+ pkt(cs, dwords);
+ pkt_qw(cs, iova);
+ body_iova = cs_get_cur_iova(cs);
+ pkt_qw(cs, 0xdeadbeef);
+
+ /* iova = iova + body_size + header_size */
+ pkt7(cs, CP_MEM_TO_MEM, 9);
+ pkt(cs, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_WAIT_FOR_MEM_WRITES);
+ pkt_qw(cs, ctx->cp_log->iova);
+ pkt_qw(cs, ctx->cp_log->iova);
+ pkt_qw(cs, size_iova);
+ pkt_qw(cs, ctx->cp_log->iova + sizeof(uint64_t));
+ }
+
+ {
+ struct cmdstream *cs = prev_cs;
+ pkt7(cs, CP_MEM_TO_MEM, 5);
+ pkt(cs, CP_MEM_TO_MEM_0_DOUBLE | CP_MEM_TO_MEM_0_WAIT_FOR_MEM_WRITES);
+ pkt_qw(cs, header_iova);
+ pkt_qw(cs, ctx->cp_log->iova);
+
+ pkt7(cs, CP_MEM_TO_MEM, 7);
+ pkt(cs, CP_MEM_TO_MEM_0_DOUBLE);
+ pkt_qw(cs, body_iova);
+ pkt_qw(cs, ctx->cp_log->iova);
+ pkt_qw(cs, ctx->cp_log->iova + sizeof(uint64_t));
+
+ pkt7(cs, CP_WAIT_MEM_WRITES, 0);
+ pkt7(cs, CP_WAIT_FOR_ME, 0);
+ }
+
+ end_ib();
+}
\ No newline at end of file
struct u_vector cmdstreams;
uint64_t shader_log_iova;
+ uint64_t cp_log_iova;
bool has_set_iova;
}
}
+static void
+device_print_cp_log(struct device *dev)
+{
+ struct cp_log {
+ uint64_t cur_iova;
+ uint64_t tmp;
+ uint64_t first_entry_size;
+ };
+
+ struct cp_log_entry {
+ uint64_t size;
+ uint32_t data[0];
+ };
+
+ if (dev->cp_log_iova == 0)
+ return;
+
+ struct buffer *buf = device_get_buffer(dev, dev->cp_log_iova);
+ if (!buf)
+ return;
+
+ struct cp_log *log = buf->map + (dev->cp_log_iova - buf->iova);
+ if (log->first_entry_size == 0)
+ return;
+
+ struct cp_log_entry *log_entry =
+ buf->map + offsetof(struct cp_log, first_entry_size);
+ uint32_t idx = 0;
+ while (log_entry->size != 0) {
+ printf("\nCP Log [%u]:\n", idx++);
+ uint32_t dwords = log_entry->size / 4;
+
+ for (uint32_t i = 0; i < dwords; i++) {
+ if (i % 8 == 0)
+ printf("\t");
+ printf("%08x ", log_entry->data[i]);
+ if (i % 8 == 7)
+ printf("\n");
+ }
+ printf("\n");
+
+ log_entry = (void *)log_entry + log_entry->size +
+ offsetof(struct cp_log_entry, data);
+ }
+}
+
#if !FD_REPLAY_KGSL
static inline void
get_abs_timeout(struct drm_msm_timespec *tv, uint64_t ns)
u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
device_print_shader_log(dev);
+ device_print_cp_log(dev);
}
static void
u_vector_init(&dev->cmdstreams, 8, sizeof(struct cmdstream));
device_print_shader_log(dev);
+ device_print_cp_log(dev);
}
static void
parse_addr(ps.buf, ps.sz, &sizedwords, &dev->shader_log_iova);
break;
}
+ case RD_CP_LOG_BUFFER: {
+ unsigned int sizedwords;
+ parse_addr(ps.buf, ps.sz, &sizedwords, &dev->cp_log_iova);
+ break;
+ }
default:
break;
}