qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <richard.henderson@linaro.org>
To: qemu-devel@nongnu.org
Cc: "Philippe Mathieu-Daudé" <philmd@linaro.org>
Subject: [PULL 04/34] accel/tcg: Reorg translator_ld*
Date: Wed, 15 May 2024 09:52:17 +0200	[thread overview]
Message-ID: <20240515075247.68024-5-richard.henderson@linaro.org> (raw)
In-Reply-To: <20240515075247.68024-1-richard.henderson@linaro.org>

Reorg translator_access into translator_ld, with a more
memcpy-ish interface.  If both pages are in ram, do not
go through the caller's slow path.

Assert that the access is within the two pages that we are
prepared to protect, per TranslationBlock.  Allow access
prior to pc_first, so long as it is within the first page.

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 accel/tcg/translator.c | 189 ++++++++++++++++++++++-------------------
 1 file changed, 101 insertions(+), 88 deletions(-)

diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 3456455fa5..0848026935 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -230,69 +230,88 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     }
 }
 
-static void *translator_access(CPUArchState *env, DisasContextBase *db,
-                               vaddr pc, size_t len)
+static bool translator_ld(CPUArchState *env, DisasContextBase *db,
+                          void *dest, vaddr pc, size_t len)
 {
+    TranslationBlock *tb = db->tb;
+    vaddr last = pc + len - 1;
     void *host;
-    vaddr base, end;
-    TranslationBlock *tb;
-
-    tb = db->tb;
+    vaddr base;
 
     /* Use slow path if first page is MMIO. */
     if (unlikely(tb_page_addr0(tb) == -1)) {
-        return NULL;
+        return false;
     }
 
-    end = pc + len - 1;
-    if (likely(is_same_page(db, end))) {
-        host = db->host_addr[0];
-        base = db->pc_first;
-    } else {
+    host = db->host_addr[0];
+    base = db->pc_first;
+
+    if (likely(((base ^ last) & TARGET_PAGE_MASK) == 0)) {
+        /* Entire read is from the first page. */
+        memcpy(dest, host + (pc - base), len);
+        return true;
+    }
+
+    if (unlikely(((base ^ pc) & TARGET_PAGE_MASK) == 0)) {
+        /* Read begins on the first page and extends to the second. */
+        size_t len0 = -(pc | TARGET_PAGE_MASK);
+        memcpy(dest, host + (pc - base), len0);
+        pc += len0;
+        dest += len0;
+        len -= len0;
+    }
+
+    /*
+     * The read must conclude on the second page and not extend to a third.
+     *
+     * TODO: We could allow the two pages to be virtually discontiguous,
+     * since we already allow the two pages to be physically discontiguous.
+     * The only reasonable use case would be executing an insn at the end
+     * of the address space wrapping around to the beginning.  For that,
+     * we would need to know the current width of the address space.
+     * In the meantime, assert.
+     */
+    base = (base & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
+    assert(((base ^ pc) & TARGET_PAGE_MASK) == 0);
+    assert(((base ^ last) & TARGET_PAGE_MASK) == 0);
+    host = db->host_addr[1];
+
+    if (host == NULL) {
+        tb_page_addr_t page0, old_page1, new_page1;
+
+        new_page1 = get_page_addr_code_hostp(env, base, &db->host_addr[1]);
+
+        /*
+         * If the second page is MMIO, treat as if the first page
+         * was MMIO as well, so that we do not cache the TB.
+         */
+        if (unlikely(new_page1 == -1)) {
+            tb_unlock_pages(tb);
+            tb_set_page_addr0(tb, -1);
+            return false;
+        }
+
+        /*
+         * If this is not the first time around, and page1 matches,
+         * then we already have the page locked.  Alternately, we're
+         * not doing anything to prevent the PTE from changing, so
+         * we might wind up with a different page, requiring us to
+         * re-do the locking.
+         */
+        old_page1 = tb_page_addr1(tb);
+        if (likely(new_page1 != old_page1)) {
+            page0 = tb_page_addr0(tb);
+            if (unlikely(old_page1 != -1)) {
+                tb_unlock_page1(page0, old_page1);
+            }
+            tb_set_page_addr1(tb, new_page1);
+            tb_lock_page1(page0, new_page1);
+        }
         host = db->host_addr[1];
-        base = TARGET_PAGE_ALIGN(db->pc_first);
-        if (host == NULL) {
-            tb_page_addr_t page0, old_page1, new_page1;
-
-            new_page1 = get_page_addr_code_hostp(env, base, &db->host_addr[1]);
-
-            /*
-             * If the second page is MMIO, treat as if the first page
-             * was MMIO as well, so that we do not cache the TB.
-             */
-            if (unlikely(new_page1 == -1)) {
-                tb_unlock_pages(tb);
-                tb_set_page_addr0(tb, -1);
-                return NULL;
-            }
-
-            /*
-             * If this is not the first time around, and page1 matches,
-             * then we already have the page locked.  Alternately, we're
-             * not doing anything to prevent the PTE from changing, so
-             * we might wind up with a different page, requiring us to
-             * re-do the locking.
-             */
-            old_page1 = tb_page_addr1(tb);
-            if (likely(new_page1 != old_page1)) {
-                page0 = tb_page_addr0(tb);
-                if (unlikely(old_page1 != -1)) {
-                    tb_unlock_page1(page0, old_page1);
-                }
-                tb_set_page_addr1(tb, new_page1);
-                tb_lock_page1(page0, new_page1);
-            }
-            host = db->host_addr[1];
-        }
-
-        /* Use slow path when crossing pages. */
-        if (is_same_page(db, pc)) {
-            return NULL;
-        }
     }
 
-    tcg_debug_assert(pc >= base);
-    return host + (pc - base);
+    memcpy(dest, host + (pc - base), len);
+    return true;
 }
 
 static void plugin_insn_append(vaddr pc, const void *from, size_t size)
@@ -318,61 +337,55 @@ static void plugin_insn_append(vaddr pc, const void *from, size_t size)
 
 uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, vaddr pc)
 {
-    uint8_t ret;
-    void *p = translator_access(env, db, pc, sizeof(ret));
+    uint8_t raw;
 
-    if (p) {
-        plugin_insn_append(pc, p, sizeof(ret));
-        return ldub_p(p);
+    if (!translator_ld(env, db, &raw, pc, sizeof(raw))) {
+        raw = cpu_ldub_code(env, pc);
     }
-    ret = cpu_ldub_code(env, pc);
-    plugin_insn_append(pc, &ret, sizeof(ret));
-    return ret;
+    plugin_insn_append(pc, &raw, sizeof(raw));
+    return raw;
 }
 
 uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, vaddr pc)
 {
-    uint16_t ret, plug;
-    void *p = translator_access(env, db, pc, sizeof(ret));
+    uint16_t raw, tgt;
 
-    if (p) {
-        plugin_insn_append(pc, p, sizeof(ret));
-        return lduw_p(p);
+    if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
+        tgt = tswap16(raw);
+    } else {
+        tgt = cpu_lduw_code(env, pc);
+        raw = tswap16(tgt);
     }
-    ret = cpu_lduw_code(env, pc);
-    plug = tswap16(ret);
-    plugin_insn_append(pc, &plug, sizeof(ret));
-    return ret;
+    plugin_insn_append(pc, &raw, sizeof(raw));
+    return tgt;
 }
 
 uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, vaddr pc)
 {
-    uint32_t ret, plug;
-    void *p = translator_access(env, db, pc, sizeof(ret));
+    uint32_t raw, tgt;
 
-    if (p) {
-        plugin_insn_append(pc, p, sizeof(ret));
-        return ldl_p(p);
+    if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
+        tgt = tswap32(raw);
+    } else {
+        tgt = cpu_ldl_code(env, pc);
+        raw = tswap32(tgt);
     }
-    ret = cpu_ldl_code(env, pc);
-    plug = tswap32(ret);
-    plugin_insn_append(pc, &plug, sizeof(ret));
-    return ret;
+    plugin_insn_append(pc, &raw, sizeof(raw));
+    return tgt;
 }
 
 uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, vaddr pc)
 {
-    uint64_t ret, plug;
-    void *p = translator_access(env, db, pc, sizeof(ret));
+    uint64_t raw, tgt;
 
-    if (p) {
-        plugin_insn_append(pc, p, sizeof(ret));
-        return ldq_p(p);
+    if (translator_ld(env, db, &raw, pc, sizeof(raw))) {
+        tgt = tswap64(raw);
+    } else {
+        tgt = cpu_ldq_code(env, pc);
+        raw = tswap64(tgt);
     }
-    ret = cpu_ldq_code(env, pc);
-    plug = tswap64(ret);
-    plugin_insn_append(pc, &plug, sizeof(ret));
-    return ret;
+    plugin_insn_append(pc, &raw, sizeof(raw));
+    return tgt;
 }
 
 void translator_fake_ldb(DisasContextBase *db, vaddr pc, uint8_t insn8)
-- 
2.34.1



  parent reply	other threads:[~2024-05-15  7:53 UTC|newest]

Thread overview: 37+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-05-15  7:52 [PULL 00/34] tcg patch queue Richard Henderson
2024-05-15  7:52 ` [PULL 01/34] accel/tcg: Use vaddr in translator_ld* Richard Henderson
2024-05-15  7:52 ` [PULL 02/34] accel/tcg: Hide in_same_page outside of a target-specific context Richard Henderson
2024-05-15  7:52 ` [PULL 03/34] accel/tcg: Pass DisasContextBase to translator_fake_ldb Richard Henderson
2024-05-15  7:52 ` Richard Henderson [this message]
2024-05-15  7:52 ` [PULL 05/34] accel/tcg: Cap the translation block when we encounter mmio Richard Henderson
2024-05-15  7:52 ` [PULL 06/34] accel/tcg: Record mmio bytes during translation Richard Henderson
2024-05-15  7:52 ` [PULL 07/34] accel/tcg: Record when translator_fake_ldb is used Richard Henderson
2024-05-15  7:52 ` [PULL 08/34] accel/tcg: Record DisasContextBase in tcg_ctx for plugins Richard Henderson
2024-05-15  7:52 ` [PULL 09/34] plugins: Copy memory in qemu_plugin_insn_data Richard Henderson
2024-05-15  7:52 ` [PULL 10/34] accel/tcg: Implement translator_st Richard Henderson
2024-05-15  7:52 ` [PULL 11/34] plugins: Use translator_st for qemu_plugin_insn_data Richard Henderson
2024-05-15  7:52 ` [PULL 12/34] plugins: Read mem_only directly from TB cflags Richard Henderson
2024-05-15  7:52 ` [PULL 13/34] plugins: Use DisasContextBase for qemu_plugin_insn_haddr Richard Henderson
2024-05-15  7:52 ` [PULL 14/34] plugins: Use DisasContextBase for qemu_plugin_tb_vaddr Richard Henderson
2024-05-15  7:52 ` [PULL 15/34] plugins: Merge alloc_tcg_plugin_context into plugin_gen_tb_start Richard Henderson
2024-05-15  7:52 ` [PULL 16/34] accel/tcg: Provide default implementation of disas_log Richard Henderson
2024-05-15  7:52 ` [PULL 17/34] accel/tcg: Return bool from TranslatorOps.disas_log Richard Henderson
2024-05-15  7:52 ` [PULL 18/34] disas: Split disas.c Richard Henderson
2024-05-15  7:52 ` [PULL 19/34] disas: Use translator_st to get disassembly data Richard Henderson
2024-05-20 11:50   ` Bernhard Beschow
2024-05-15  7:52 ` [PULL 20/34] accel/tcg: Introduce translator_fake_ld Richard Henderson
2024-05-15  7:52 ` [PULL 21/34] target/s390x: Fix translator_fake_ld length Richard Henderson
2024-05-15  7:52 ` [PULL 22/34] target/s390x: Disassemble EXECUTEd instructions Richard Henderson
2024-05-15  7:52 ` [PULL 23/34] target/hexagon: Use translator_ldl in pkt_crosses_page Richard Henderson
2024-05-15  7:52 ` [PULL 24/34] target/microblaze: Use translator_ldl Richard Henderson
2024-05-15  7:52 ` [PULL 25/34] target/i386: Use translator_ldub for everything Richard Henderson
2024-05-15  7:52 ` [PULL 26/34] target/avr: Use translator_lduw Richard Henderson
2024-05-15  7:52 ` [PULL 27/34] target/cris: Use translator_ld* in cris_fetch Richard Henderson
2024-05-15  7:52 ` [PULL 28/34] target/cris: Use cris_fetch in translate_v10.c.inc Richard Henderson
2024-05-15  7:52 ` [PULL 29/34] target/riscv: Use translator_ld* for everything Richard Henderson
2024-05-15  7:52 ` [PULL 30/34] target/rx: Use translator_ld* Richard Henderson
2024-05-15  7:52 ` [PULL 31/34] target/xtensa: Use translator_ldub in xtensa_insn_len Richard Henderson
2024-05-15  7:52 ` [PULL 32/34] target/s390x: Use translator_lduw in get_next_pc Richard Henderson
2024-05-15  7:52 ` [PULL 33/34] accel/tcg: Remove cpu_ldsb_code / cpu_ldsw_code Richard Henderson
2024-05-15  7:52 ` [PULL 34/34] tcg/loongarch64: Fill out tcg_out_{ld, st} for vector regs Richard Henderson
2024-05-15 12:59 ` [PULL 00/34] tcg patch queue Richard Henderson

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20240515075247.68024-5-richard.henderson@linaro.org \
    --to=richard.henderson@linaro.org \
    --cc=philmd@linaro.org \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).