diff mbox series

[v2,10/33] accel/tcg: Implement translator_st

Message ID 20240424233131.988727-11-richard.henderson@linaro.org
State Superseded
Headers show
Series accel/tcg: Improve disassembly for target and plugin | expand

Commit Message

Richard Henderson April 24, 2024, 11:31 p.m. UTC
Copy data out of a completed translation.  This will be used
for both plugins and disassembly.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/translator.h | 23 ++++++++++++++++
 accel/tcg/translator.c    | 55 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

Comments

Philippe Mathieu-Daudé May 8, 2024, 3:20 p.m. UTC | #1
On 25/4/24 01:31, Richard Henderson wrote:
> Copy data out of a completed translation.  This will be used
> for both plugins and disassembly.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/exec/translator.h | 23 ++++++++++++++++
>   accel/tcg/translator.c    | 55 +++++++++++++++++++++++++++++++++++++++
>   2 files changed, 78 insertions(+)
> 
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index e92dfba035..3c354a4310 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -246,6 +246,29 @@ translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
>    */
>   void translator_fake_ldb(DisasContextBase *db, vaddr pc, uint8_t insn8);
>   
> +/**
> + * translator_st
> + * @db: disassembly context
> + * @dest: address to copy into

Or s/address/buffer/

> + * @addr: virtual address within TB
> + * @len: length
> + *
> + * Copy @len bytes from @addr into @dest.
> + * All bytes must have been read during translation.
> + * Return true on success or false on failure.
> + */
> +bool translator_st(const DisasContextBase *db, void *dest,
> +                   vaddr addr, size_t len);

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

Patch

diff --git a/include/exec/translator.h b/include/exec/translator.h
index e92dfba035..3c354a4310 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -246,6 +246,29 @@  translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
  */
 void translator_fake_ldb(DisasContextBase *db, vaddr pc, uint8_t insn8);
 
+/**
+ * translator_st
+ * @db: disassembly context
+ * @dest: address to copy into
+ * @addr: virtual address within TB
+ * @len: length
+ *
+ * Copy @len bytes from @addr into @dest.
+ * All bytes must have been read during translation.
+ * Return true on success or false on failure.
+ */
+bool translator_st(const DisasContextBase *db, void *dest,
+                   vaddr addr, size_t len);
+
+/**
+ * translator_st_len
+ * @db: disassembly context
+ *
+ * Return the number of bytes available to copy from the
+ * current translation block with translator_st.
+ */
+size_t translator_st_len(const DisasContextBase *db);
+
 #ifdef NEED_CPU_H
 /*
  * Return whether addr is on the same page as where disassembly started.
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 6863455ed9..7f63a8085d 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -353,6 +353,61 @@  static void record_save(DisasContextBase *db, vaddr pc,
     memcpy(db->record + (offset - db->record_start), from, size);
 }
 
+size_t translator_st_len(const DisasContextBase *db)
+{
+    return db->fake_insn ? db->record_len : db->tb->size;
+}
+
+bool translator_st(const DisasContextBase *db, void *dest,
+                   vaddr addr, size_t len)
+{
+    size_t offset, offset_end;
+
+    if (addr < db->pc_first) {
+        return false;
+    }
+    offset = addr - db->pc_first;
+    offset_end = offset + len;
+    if (offset_end > translator_st_len(db)) {
+        return false;
+    }
+
+    if (!db->fake_insn) {
+        size_t offset_page1 = -(db->pc_first | TARGET_PAGE_MASK);
+
+        /* Get all the bytes from the first page. */
+        if (db->host_addr[0]) {
+            if (offset_end <= offset_page1) {
+                memcpy(dest, db->host_addr[0] + offset, len);
+                return true;
+            }
+            if (offset < offset_page1) {
+                size_t len0 = offset_page1 - offset;
+                memcpy(dest, db->host_addr[0] + offset, len0);
+                offset += len0;
+                dest += len0;
+            }
+        }
+
+        /* Get any bytes from the second page. */
+        if (db->host_addr[1] && offset >= offset_page1) {
+            memcpy(dest, db->host_addr[1] + (offset - offset_page1),
+                   offset_end - offset);
+            return true;
+        }
+    }
+
+    /* Else get recorded bytes. */
+    if (db->record_len != 0 &&
+        offset >= db->record_start &&
+        offset_end <= db->record_start + db->record_len) {
+        memcpy(dest, db->record + (offset - db->record_start),
+               offset_end - offset);
+        return true;
+    }
+    return false;
+}
+
 static void plugin_insn_append(vaddr pc, const void *from, size_t size)
 {
 #ifdef CONFIG_PLUGIN