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:
committed by
Marge Bot
parent
c2e0ce16fb
commit
5d71bf46a7
@@ -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
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user