qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Richard Henderson <rth@twiddle.net>
To: qemu-devel@nongnu.org
Cc: dl.soluz@gmx.net, atar4qemu@gmail.com, aurelien@aurel32.net
Subject: [Qemu-devel] [PATCH 18/20] tcg: Save insn data and use it in cpu_restore_state_from_tb
Date: Tue,  1 Sep 2015 22:52:01 -0700	[thread overview]
Message-ID: <1441173123-25540-19-git-send-email-rth@twiddle.net> (raw)
In-Reply-To: <1441173123-25540-1-git-send-email-rth@twiddle.net>

We can now restore state without retranslation.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 include/exec/exec-all.h |   1 +
 tcg/tcg.c               |  11 ++++-
 tcg/tcg.h               |   3 +-
 translate-all.c         | 129 +++++++++++++++++++++++++++++++++---------------
 4 files changed, 100 insertions(+), 44 deletions(-)

diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h
index 8c347ba..315f20a 100644
--- a/include/exec/exec-all.h
+++ b/include/exec/exec-all.h
@@ -198,6 +198,7 @@ struct TranslationBlock {
 #define CF_USE_ICOUNT  0x20000
 
     void *tc_ptr;    /* pointer to the translated code */
+    uint8_t *tc_search;  /* pointer to search data */
     /* next matching tb for physical address. */
     struct TranslationBlock *phys_hash_next;
     /* original tb when cflags has CF_NOCACHE */
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d956f0b..3541d4c 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -2300,7 +2300,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
                                       tcg_insn_unit *gen_code_buf,
                                       long search_pc)
 {
-    int i, oi, oi_next;
+    int i, oi, oi_next, num_insns;
 
 #ifdef DEBUG_DISAS
     if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP))) {
@@ -2344,6 +2344,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
 
     tcg_out_tb_init(s);
 
+    num_insns = -1;
     for (oi = s->gen_first_op_idx; oi >= 0; oi = oi_next) {
         TCGOp * const op = &s->gen_op_buf[oi];
         TCGArg * const args = &s->gen_opparam_buf[op->args];
@@ -2367,6 +2368,10 @@ static inline int tcg_gen_code_common(TCGContext *s,
             tcg_reg_alloc_movi(s, args, dead_args, sync_args);
             break;
         case INDEX_op_insn_start:
+            if (num_insns >= 0) {
+                s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
+            }
+            num_insns++;
             for (i = 0; i < TARGET_INSN_START_WORDS; ++i) {
                 target_ulong a;
 #if TARGET_LONG_BITS > TCG_TARGET_REG_BITS
@@ -2374,7 +2379,7 @@ static inline int tcg_gen_code_common(TCGContext *s,
 #else
                 a = args[i];
 #endif
-                s->gen_opc_data[i] = a;
+                s->gen_insn_data[num_insns][i] = a;
             }
             break;
         case INDEX_op_discard:
@@ -2406,6 +2411,8 @@ static inline int tcg_gen_code_common(TCGContext *s,
         check_regs(s);
 #endif
     }
+    tcg_debug_assert(num_insns >= 0);
+    s->gen_insn_end_off[num_insns] = tcg_current_code_size(s);
 
     /* Generate TB finalization at the end of block */
     tcg_out_tb_finalize(s);
diff --git a/tcg/tcg.h b/tcg/tcg.h
index 794b757..11cc107 100644
--- a/tcg/tcg.h
+++ b/tcg/tcg.h
@@ -581,7 +581,8 @@ struct TCGContext {
     uint16_t gen_opc_icount[OPC_BUF_SIZE];
     uint8_t gen_opc_instr_start[OPC_BUF_SIZE];
 
-    target_ulong gen_opc_data[TARGET_INSN_START_WORDS];
+    uint16_t gen_insn_end_off[TCG_MAX_INSNS];
+    target_ulong gen_insn_data[TCG_MAX_INSNS][TARGET_INSN_START_WORDS];
 };
 
 extern TCGContext tcg_ctx;
diff --git a/translate-all.c b/translate-all.c
index 74be98a..a31f839 100644
--- a/translate-all.c
+++ b/translate-all.c
@@ -138,58 +138,65 @@ void cpu_gen_init(void)
     tcg_context_init(&tcg_ctx); 
 }
 
-/* The cpu state corresponding to 'searched_pc' is restored.
- */
+static target_long decode_sleb128(uint8_t **pp)
+{
+    uint8_t *p = *pp;
+    target_long val = 0;
+    int byte, shift = 0;
+
+    do {
+        byte = *p++;
+        val |= (target_ulong)(byte & 0x7f) << shift;
+        shift += 7;
+    } while (byte & 0x80);
+    if (shift < TARGET_LONG_BITS && (byte & 0x40)) {
+        val |= -(target_ulong)1 << shift;
+    }
+
+    *pp = p;
+    return val;
+}
+
+/* The cpu state corresponding to 'searched_pc' is restored.  */
 static int cpu_restore_state_from_tb(CPUState *cpu, TranslationBlock *tb,
                                      uintptr_t searched_pc)
 {
+    target_ulong data[TARGET_INSN_START_WORDS] = { };
+    uintptr_t host_pc = (uintptr_t)tb->tc_ptr;
     CPUArchState *env = cpu->env_ptr;
-    TCGContext *s = &tcg_ctx;
-    int j;
-    uintptr_t tc_ptr;
+    uint8_t *p = tb->tc_search;
+    int i, j, num_insns = tb->icount;
 #ifdef CONFIG_PROFILER
-    int64_t ti;
+    int64_t ti = profile_getclock();
 #endif
 
-#ifdef CONFIG_PROFILER
-    ti = profile_getclock();
-#endif
-    tcg_func_start(s);
+    if (searched_pc < host_pc) {
+        return -1;
+    }
 
-    gen_intermediate_code_pc(env, tb);
+    /* Reconstruct the stored insn data while looking for the point at
+       which the end of the insn exceeds the searched_pc.  */
+    for (i = 0; i < num_insns; ++i) {
+        for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
+            data[j] += decode_sleb128(&p);
+        }
+        host_pc += decode_sleb128(&p);
+        if (host_pc > searched_pc) {
+            goto found;
+        }
+    }
+    return -1;
 
+ found:
     if (tb->cflags & CF_USE_ICOUNT) {
         assert(use_icount);
         /* Reset the cycle counter to the start of the block.  */
-        cpu->icount_decr.u16.low += tb->icount;
+        cpu->icount_decr.u16.low += num_insns;
         /* Clear the IO flag.  */
         cpu->can_do_io = 0;
     }
-
-    /* find opc index corresponding to search_pc */
-    tc_ptr = (uintptr_t)tb->tc_ptr;
-    if (searched_pc < tc_ptr)
-        return -1;
-
-    s->tb_next_offset = tb->tb_next_offset;
-#ifdef USE_DIRECT_JUMP
-    s->tb_jmp_offset = tb->tb_jmp_offset;
-    s->tb_next = NULL;
-#else
-    s->tb_jmp_offset = NULL;
-    s->tb_next = tb->tb_next;
-#endif
-    j = tcg_gen_code_search_pc(s, (tcg_insn_unit *)tc_ptr,
-                               searched_pc - tc_ptr);
-    if (j < 0)
-        return -1;
-    /* now find start of instruction before */
-    while (s->gen_opc_instr_start[j] == 0) {
-        j--;
-    }
-    cpu->icount_decr.u16.low -= s->gen_opc_icount[j];
-
-    restore_state_to_opc(env, tb, s->gen_opc_data);
+    cpu->icount_decr.u16.low -= i;
+    restore_state_to_opc(env, tb, data);
 
 #ifdef CONFIG_PROFILER
     s->restore_time += profile_getclock() - ti;
@@ -933,6 +940,44 @@ static void build_page_bitmap(PageDesc *p)
     }
 }
 
+static uint8_t *encode_sleb128(uint8_t *p, target_long val)
+{
+    int more, byte;
+
+    do {
+        byte = val & 0x7f;
+        val >>= 7;
+        more = !((val == 0 && (byte & 0x40) == 0)
+                 || (val == -1 && (byte & 0x40) != 0));
+        if (more)
+          byte |= 0x80;
+        *p++ = byte;
+    } while (more);
+
+    return p;
+}
+
+static int encode_search(TranslationBlock *tb, uint8_t *block)
+{
+    uint8_t *p = block;
+    int i, j, n;
+
+    tb->tc_search = block;
+
+    for (i = 0, n = tb->icount; i < n; ++i) {
+        target_ulong prev;
+
+        for (j = 0; j < TARGET_INSN_START_WORDS; ++j) {
+            prev = (i == 0 ? 0 : tcg_ctx.gen_insn_data[i - 1][j]);
+            p = encode_sleb128(p, tcg_ctx.gen_insn_data[i][j] - prev);
+        }
+        prev = (i == 0 ? 0 : tcg_ctx.gen_insn_end_off[i - 1]);
+        p = encode_sleb128(p, tcg_ctx.gen_insn_end_off[i] - prev);
+    }
+
+    return p - block;
+}
+
 TranslationBlock *tb_gen_code(CPUState *cpu,
                               target_ulong pc, target_ulong cs_base,
                               int flags, int cflags)
@@ -942,7 +987,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     tb_page_addr_t phys_pc, phys_page2;
     target_ulong virt_page2;
     tcg_insn_unit *gen_code_buf;
-    int gen_code_size;
+    int gen_code_size, search_size;
 #ifdef CONFIG_PROFILER
     int64_t ti;
 #endif
@@ -998,11 +1043,12 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
 #endif
 
     gen_code_size = tcg_gen_code(&tcg_ctx, gen_code_buf);
+    search_size = encode_search(tb, (void *)gen_code_buf + gen_code_size);
 
 #ifdef CONFIG_PROFILER
     tcg_ctx.code_time += profile_getclock();
     tcg_ctx.code_in_len += tb->size;
-    tcg_ctx.code_out_len += gen_code_size;
+    tcg_ctx.code_out_len += gen_code_size + search_size;
 #endif
 
 #ifdef DEBUG_DISAS
@@ -1014,8 +1060,9 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
     }
 #endif
 
-    tcg_ctx.code_gen_ptr = (void *)(((uintptr_t)gen_code_buf +
-            gen_code_size + CODE_GEN_ALIGN - 1) & ~(CODE_GEN_ALIGN - 1));
+    tcg_ctx.code_gen_ptr = (void *)
+        (((uintptr_t)gen_code_buf + gen_code_size + search_size
+          + CODE_GEN_ALIGN - 1) & -CODE_GEN_ALIGN);
 
     /* check next page if needed */
     virt_page2 = (pc + tb->size - 1) & TARGET_PAGE_MASK;
-- 
2.4.3

  parent reply	other threads:[~2015-09-02  5:53 UTC|newest]

Thread overview: 62+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2015-09-02  5:51 [Qemu-devel] [RFC 00/20] Do away with TB retranslation Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 02/20] target-*: Unconditionally emit tcg_gen_insn_start Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 03/20] tcg: Allow extra data to be attached to insn_start Richard Henderson
2015-09-08 18:44   ` Peter Maydell
2015-09-02  5:51 ` [Qemu-devel] [PATCH 04/20] target-arm: Add condexec state " Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 05/20] target-i386: Add cc_op " Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 06/20] target-mips: Add delayed branch " Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 07/20] target-s390x: Add cc_op " Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 08/20] target-sh4: Add flags " Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 09/20] target-cris: Mirror gen_opc_pc into insn_start Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 10/20] target-sparc: Tidy gen_branch_a interface Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 11/20] target-sparc: Split out gen_branch_n Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 12/20] target-sparc: Remove gen_opc_jump_pc Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 13/20] target-sparc: Add npc state to insn_start Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 14/20] tcg: Merge cpu_gen_code into tb_gen_code Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 15/20] target-*: Drop cpu_gen_code define Richard Henderson
2015-09-02  5:51 ` [Qemu-devel] [PATCH 16/20] tcg: Add TCG_MAX_INSNS Richard Henderson
2015-09-02  5:52 ` [Qemu-devel] [PATCH 17/20] tcg: Pass data argument to restore_state_to_opc Richard Henderson
2015-09-08 18:46   ` Peter Maydell
2015-09-17 19:39     ` Richard Henderson
2015-09-02  5:52 ` Richard Henderson [this message]
2015-09-10 13:49   ` [Qemu-devel] [PATCH 18/20] tcg: Save insn data and use it in cpu_restore_state_from_tb Peter Maydell
2015-09-11 10:29     ` Sergey Fedorov
2015-09-11 10:32       ` Peter Maydell
2015-09-11 10:46         ` Sergey Fedorov
2015-09-15 20:08     ` Richard Henderson
2015-09-02  5:52 ` [Qemu-devel] [PATCH 19/20] tcg: Remove gen_intermediate_code_pc Richard Henderson
2015-09-08 18:49   ` Peter Maydell
2015-09-02  5:52 ` [Qemu-devel] [PATCH 20/20] tcg: Remove tcg_gen_code_search_pc Richard Henderson
2015-09-02 12:21 ` [Qemu-devel] [RFC 00/20] Do away with TB retranslation Max Filippov
2015-09-02 14:21   ` Richard Henderson
2015-09-04 15:18     ` Max Filippov
2015-09-04 15:31       ` Peter Maydell
2015-09-04 16:46       ` Richard Henderson
2015-09-04 17:07         ` Max Filippov
2015-09-05 14:11         ` Mark Cave-Ayland
2015-09-06 20:19           ` Richard Henderson
2015-09-09 15:35             ` Artyom Tarasenko
2015-09-08 18:56 ` Peter Maydell
2015-09-08 19:00   ` Richard Henderson
2015-09-08 19:06     ` Peter Maydell
2015-09-08 19:28       ` Richard Henderson
2015-09-08 20:25         ` Peter Maydell
2015-09-09 15:05     ` Artyom Tarasenko
2015-09-09 16:18       ` Paolo Bonzini
2015-09-09 17:48         ` Artyom Tarasenko
2015-09-10  6:07     ` Dennis Luehring
2015-09-10  7:00       ` Artyom Tarasenko
2015-09-10  9:32         ` Dennis Luehring
2015-09-10  9:54           ` Artyom Tarasenko
2015-09-10 10:37             ` Dennis Luehring
2015-09-10 10:57               ` Paolo Bonzini
2015-09-10 11:02               ` Dennis Luehring
2015-09-10 11:20                 ` Artyom Tarasenko
2015-09-10 13:54   ` Peter Maydell
2015-09-10 17:48 ` Aurelien Jarno
2015-09-13 21:00   ` Aurelien Jarno
2015-09-10 18:55 ` Alex Bennée
2015-09-15 20:19   ` Richard Henderson
2015-09-16  6:19     ` Dennis Luehring
2015-09-16  8:59     ` Alex Bennée
2015-09-16 20:41       ` 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=1441173123-25540-19-git-send-email-rth@twiddle.net \
    --to=rth@twiddle.net \
    --cc=atar4qemu@gmail.com \
    --cc=aurelien@aurel32.net \
    --cc=dl.soluz@gmx.net \
    --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).