panvk/utrace: Add support for storing registers

Add the ability to store specific register values during tracing by
using the indirect capture capability.

Reviewed-by: Christoph Pillmayer <christoph.pillmayer@arm.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/36519>
This commit is contained in:
Lars-Ivar Hesselberg Simonsen
2025-07-31 15:08:47 +02:00
committed by Marge Bot
parent c2e0ce16fb
commit 5d71bf46a7
2 changed files with 55 additions and 5 deletions
+51 -5
View File
@@ -16,7 +16,10 @@ static void
cmd_write_timestamp(const struct panvk_device *dev, struct cs_builder *b,
uint64_t addr, struct cs_async_op ts_async_op)
{
const struct cs_index addr_reg = cs_scratch_reg64(b, 0);
/* Unless we dedicate a register, this will potentially overwrite something
* during begin/end. */
const struct cs_index addr_reg =
cs_scratch_reg64(b, CS_REG_SCRATCH_COUNT - 2);
/* Overwrite the signal_slot. Note that this has no effect in case of
* synchronous or indirect syncs. */
@@ -74,6 +77,44 @@ cmd_copy_data(struct cs_builder *b, uint64_t dst_addr, uint64_t src_addr,
}
}
static void
cmd_store_regs(struct cs_builder *b, uint64_t dst_addr, uint64_t src_addr,
uint32_t size, bool wait_for_timestamp)
{
assert((dst_addr | size) % sizeof(uint32_t) == 0);
uint32_t num_regs = size / sizeof(uint32_t);
assert(num_regs <= CS_MAX_REG_TUPLE_SIZE);
assert(src_addr + num_regs <= PANVK_CS_REG_SCRATCH_END);
if (wait_for_timestamp)
cs_wait_slot(b, SB_ID(DEFERRED_SYNC));
bool valid_dst_regs = false;
struct cs_index dst_addr_reg;
/* Unless we dedicate a register, this will potentially overwrite
* something during indirect capture. For now, we only ensure we don't
* corrupt the registers we're capturing. */
for (uint32_t dst_scratch_base = PANVK_CS_REG_SCRATCH_END - 1;
dst_scratch_base >= PANVK_CS_REG_SCRATCH_START; dst_scratch_base -= 2) {
if (src_addr + num_regs <= dst_scratch_base ||
dst_scratch_base + 2 <= src_addr) {
dst_addr_reg =
cs_scratch_reg64(b, dst_scratch_base - PANVK_CS_REG_SCRATCH_START);
valid_dst_regs = true;
break;
}
}
if (!valid_dst_regs) {
assert(!"No unused scratch registers found");
return;
}
const struct cs_index src_addr_reg = cs_reg_tuple(b, src_addr, num_regs);
cs_move64_to(b, dst_addr_reg, dst_addr);
cs_store(b, src_addr_reg, dst_addr_reg, BITFIELD_MASK(num_regs), 0);
}
static struct cs_builder *
get_builder(struct panvk_cmd_buffer *cmdbuf, struct u_trace *ut)
{
@@ -112,11 +153,16 @@ panvk_utrace_capture_data(struct u_trace *ut, void *cs, void *dst_buffer,
const uint64_t dst_addr = dst_bo->addr.dev + dst_offset_B;
const uint64_t src_addr = src_offset_B;
/* src_offset_B is absolute */
assert(!src_buffer);
/* src_offset_B is absolute, src_buffer is used to indicate register capture */
assert(!src_buffer ||
(uintptr_t)src_buffer == PANVK_UTRACE_CAPTURE_REGISTERS);
cmd_copy_data(b, dst_addr, src_addr, size_B,
cs_info->capture_data_wait_for_ts);
if ((uintptr_t)src_buffer == PANVK_UTRACE_CAPTURE_REGISTERS)
cmd_store_regs(b, dst_addr, src_addr, size_B,
cs_info->capture_data_wait_for_ts);
else
cmd_copy_data(b, dst_addr, src_addr, size_B,
cs_info->capture_data_wait_for_ts);
}
void
+4
View File
@@ -49,6 +49,10 @@ struct panvk_utrace_cs_info {
bool capture_data_wait_for_ts;
};
/* Special value indicating that an indirect capture should be of registers
* rather than an address. */
#define PANVK_UTRACE_CAPTURE_REGISTERS 0x1
void panvk_per_arch(utrace_context_init)(struct panvk_device *dev);
void panvk_per_arch(utrace_context_fini)(struct panvk_device *dev);