[PATCH v2 06/33] accel/tcg: Record mmio bytes during translation

Richard Henderson posted 33 patches 1 year, 9 months ago
Maintainers: Richard Henderson <richard.henderson@linaro.org>, Paolo Bonzini <pbonzini@redhat.com>, "Alex Bennée" <alex.bennee@linaro.org>, Alexandre Iooss <erdnaxe@crans.org>, Mahmoud Mandour <ma.mandourr@gmail.com>, Pierrick Bouvier <pierrick.bouvier@linaro.org>, Peter Maydell <peter.maydell@linaro.org>, Michael Rolnik <mrolnik@gmail.com>, "Edgar E. Iglesias" <edgar.iglesias@gmail.com>, Brian Cain <bcain@quicinc.com>, Eduardo Habkost <eduardo@habkost.net>, Song Gao <gaosong@loongson.cn>, Laurent Vivier <laurent@vivier.eu>, "Philippe Mathieu-Daudé" <philmd@linaro.org>, Aurelien Jarno <aurelien@aurel32.net>, Jiaxun Yang <jiaxun.yang@flygoat.com>, Aleksandar Rikalo <aleksandar.rikalo@syrmia.com>, Stafford Horne <shorne@gmail.com>, Nicholas Piggin <npiggin@gmail.com>, Daniel Henrique Barboza <danielhb413@gmail.com>, Palmer Dabbelt <palmer@dabbelt.com>, Alistair Francis <alistair.francis@wdc.com>, Bin Meng <bin.meng@windriver.com>, Weiwei Li <liwei1518@gmail.com>, Liu Zhiwei <zhiwei_liu@linux.alibaba.com>, Yoshinori Sato <ysato@users.sourceforge.jp>, David Hildenbrand <david@redhat.com>, Ilya Leoshkevich <iii@linux.ibm.com>, Thomas Huth <thuth@redhat.com>, Mark Cave-Ayland <mark.cave-ayland@ilande.co.uk>, Artyom Tarasenko <atar4qemu@gmail.com>, Bastian Koppelmann <kbastian@mail.uni-paderborn.de>, Max Filippov <jcmvbkbc@gmail.com>
[PATCH v2 06/33] accel/tcg: Record mmio bytes during translation
Posted by Richard Henderson 1 year, 9 months ago
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 83fe66cba0..974cc4f9c4 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -90,6 +90,18 @@ typedef struct DisasContextBase {
     bool plugin_enabled;
     struct TCGOp *insn_start;
     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 c3f4d0e252..a3c246ea37 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -131,6 +131,8 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     db->insn_start = NULL;
     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 */
@@ -317,6 +319,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
@@ -344,6 +379,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;
@@ -358,6 +394,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;
@@ -372,6 +409,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;
@@ -386,6 +424,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;
@@ -393,5 +432,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
Re: [PATCH v2 06/33] accel/tcg: Record mmio bytes during translation
Posted by Philippe Mathieu-Daudé 1 year, 9 months ago
On 25/4/24 01:31, Richard Henderson wrote:
> 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 83fe66cba0..974cc4f9c4 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -90,6 +90,18 @@ typedef struct DisasContextBase {
>       bool plugin_enabled;
>       struct TCGOp *insn_start;
>       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];

Alternatively (matter of style):

        struct {
            unsigned start;
            unsigned len;
            uint8_t data[32];
        }

>   } DisasContextBase;

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>