[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 06/32] accel/tcg: Record mmio bytes during translation
From: |
Richard Henderson |
Subject: |
[PATCH 06/32] accel/tcg: Record mmio bytes during translation |
Date: |
Fri, 5 Apr 2024 00:24:33 -1000 |
This will be able to replace plugin_insn_append, and will
be usable for disassembly.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/exec/translator.h | 12 ++++++++++++
accel/tcg/translator.c | 41 +++++++++++++++++++++++++++++++++++++++
2 files changed, 53 insertions(+)
diff --git a/include/exec/translator.h b/include/exec/translator.h
index 65d0c6489a..b341dfbf02 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -88,6 +88,18 @@ typedef struct DisasContextBase {
int8_t saved_can_do_io;
bool plugin_enabled;
void *host_addr[2];
+
+ /*
+ * Record insn data that we cannot read directly from host memory.
+ * There are only two reasons we cannot use host memory:
+ * (1) We are executing from I/O,
+ * (2) We are executing a synthetic instruction (s390x EX).
+ * In both cases we need record exactly one instruction,
+ * and thus the maximum amount of data we record is limited.
+ */
+ int record_start;
+ int record_len;
+ uint8_t record[32];
} DisasContextBase;
/**
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 438b6d4cba..401c0ca30c 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -143,6 +143,8 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb,
int *max_insns,
db->saved_can_do_io = -1;
db->host_addr[0] = host_pc;
db->host_addr[1] = NULL;
+ db->record_start = 0;
+ db->record_len = 0;
ops->init_disas_context(db, cpu);
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
@@ -314,6 +316,39 @@ static bool translator_ld(CPUArchState *env,
DisasContextBase *db,
return true;
}
+static void record_save(DisasContextBase *db, vaddr pc,
+ const void *from, int size)
+{
+ int offset;
+
+ /* Do not record probes before the start of TB. */
+ if (pc < db->pc_first) {
+ return;
+ }
+
+ /*
+ * In translator_access, we verified that pc is within 2 pages
+ * of pc_first, thus this will never overflow.
+ */
+ offset = pc - db->pc_first;
+
+ /*
+ * Either the first or second page may be I/O. If it is the second,
+ * then the first byte we need to record will be at a non-zero offset.
+ * In either case, we should not need to record but a single insn.
+ */
+ if (db->record_len == 0) {
+ db->record_start = offset;
+ db->record_len = size;
+ } else {
+ assert(offset == db->record_start + db->record_len);
+ assert(db->record_len + size <= sizeof(db->record));
+ db->record_len += size;
+ }
+
+ memcpy(db->record + (offset - db->record_start), from, size);
+}
+
static void plugin_insn_append(vaddr pc, const void *from, size_t size)
{
#ifdef CONFIG_PLUGIN
@@ -341,6 +376,7 @@ uint8_t translator_ldub(CPUArchState *env, DisasContextBase
*db, vaddr pc)
if (!translator_ld(env, db, &raw, pc, sizeof(raw))) {
raw = cpu_ldub_code(env, pc);
+ record_save(db, pc, &raw, sizeof(raw));
}
plugin_insn_append(pc, &raw, sizeof(raw));
return raw;
@@ -355,6 +391,7 @@ uint16_t translator_lduw(CPUArchState *env,
DisasContextBase *db, vaddr pc)
} else {
tgt = cpu_lduw_code(env, pc);
raw = tswap16(tgt);
+ record_save(db, pc, &raw, sizeof(raw));
}
plugin_insn_append(pc, &raw, sizeof(raw));
return tgt;
@@ -369,6 +406,7 @@ uint32_t translator_ldl(CPUArchState *env, DisasContextBase
*db, vaddr pc)
} else {
tgt = cpu_ldl_code(env, pc);
raw = tswap32(tgt);
+ record_save(db, pc, &raw, sizeof(raw));
}
plugin_insn_append(pc, &raw, sizeof(raw));
return tgt;
@@ -383,6 +421,7 @@ uint64_t translator_ldq(CPUArchState *env, DisasContextBase
*db, vaddr pc)
} else {
tgt = cpu_ldl_code(env, pc);
raw = tswap64(tgt);
+ record_save(db, pc, &raw, sizeof(raw));
}
plugin_insn_append(pc, &raw, sizeof(raw));
return tgt;
@@ -390,5 +429,7 @@ uint64_t translator_ldq(CPUArchState *env, DisasContextBase
*db, vaddr pc)
void translator_fake_ldb(DisasContextBase *db, vaddr pc, uint8_t insn8)
{
+ assert(pc >= db->pc_first);
+ record_save(db, pc, &insn8, sizeof(insn8));
plugin_insn_append(pc, &insn8, sizeof(insn8));
}
--
2.34.1
- [PATCH 07/32] accel/tcg: Record when translator_fake_ldb is used, (continued)
- [PATCH 07/32] accel/tcg: Record when translator_fake_ldb is used, Richard Henderson, 2024/04/05
- [PATCH 09/32] plugins: Copy memory in qemu_plugin_insn_data, Richard Henderson, 2024/04/05
- [PATCH 10/32] accel/tcg: Implement translator_st, Richard Henderson, 2024/04/05
- [PATCH 08/32] accel/tcg: Record DisasContextBase in tcg_ctx for plugins, Richard Henderson, 2024/04/05
- [PATCH 11/32] plugins: Use translator_st for qemu_plugin_insn_data, Richard Henderson, 2024/04/05
- [PATCH 15/32] plugins: Merge alloc_tcg_plugin_context into plugin_gen_tb_start, Richard Henderson, 2024/04/05
- [PATCH 03/32] accel/tcg: Pass DisasContextBase to translator_fake_ldb, Richard Henderson, 2024/04/05
- [PATCH 01/32] accel/tcg: Use vaddr in translator_ld*, Richard Henderson, 2024/04/05
- [PATCH 06/32] accel/tcg: Record mmio bytes during translation,
Richard Henderson <=
- [PATCH 12/32] plugins: Read mem_only directly from TB cflags, Richard Henderson, 2024/04/05
- [PATCH 13/32] plugins: Use DisasContextBase for qemu_plugin_insn_haddr, Richard Henderson, 2024/04/05
- [PATCH 14/32] plugins: Use DisasContextBase for qemu_plugin_tb_vaddr, Richard Henderson, 2024/04/05
- [PATCH 19/32] disas: Use translator_st to get disassembly data, Richard Henderson, 2024/04/05
- [PATCH 17/32] accel/tcg: Return bool from TranslatorOps.disas_log, Richard Henderson, 2024/04/05
- [PATCH 16/32] accel/tcg: Provide default implementation of disas_log, Richard Henderson, 2024/04/05
- [PATCH 20/32] accel/tcg: Introduce translator_fake_ld, Richard Henderson, 2024/04/05