[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PULL 24/39] tcg: Clean up direct block chaining safety che
From: |
Richard Henderson |
Subject: |
[Qemu-devel] [PULL 24/39] tcg: Clean up direct block chaining safety checks |
Date: |
Thu, 12 May 2016 14:13:25 -1000 |
From: Sergey Fedorov <address@hidden>
We don't take care of direct jumps when address mapping changes. Thus we
must be sure to generate direct jumps so that they always keep valid
even if address mapping changes. Luckily, we can only allow to execute a
TB if it was generated from the pages which match with current mapping.
Document tcg_gen_goto_tb() declaration and note the reason for
destination PC limitations.
Some targets with variable length instructions allow TB to straddle a
page boundary. However, we make sure that both of TB pages match the
current address mapping when looking up TBs. So it is safe to do direct
jumps into the both pages. Correct the checks for some of those targets.
Given that, we can safely patch a TB which spans two pages. Remove the
unnecessary check in cpu_exec() and allow such TBs to be patched.
Signed-off-by: Sergey Fedorov <address@hidden>
Signed-off-by: Sergey Fedorov <address@hidden>
Reviewed-by: Alex Bennée <address@hidden>
Signed-off-by: Richard Henderson <address@hidden>
---
cpu-exec.c | 7 ++-----
target-arm/translate.c | 3 ++-
target-cris/translate.c | 4 +++-
target-i386/translate.c | 2 +-
target-m68k/translate.c | 2 +-
target-s390x/translate.c | 2 +-
tcg/tcg-op.h | 10 ++++++++++
7 files changed, 20 insertions(+), 10 deletions(-)
diff --git a/cpu-exec.c b/cpu-exec.c
index debc65c..f984dc7 100644
--- a/cpu-exec.c
+++ b/cpu-exec.c
@@ -508,11 +508,8 @@ int cpu_exec(CPUState *cpu)
next_tb = 0;
tcg_ctx.tb_ctx.tb_invalidated_flag = 0;
}
- /* see if we can patch the calling TB. When the TB
- spans two pages, we cannot safely do a direct
- jump. */
- if (next_tb != 0 && tb->page_addr[1] == -1
- && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
+ /* See if we can patch the calling TB. */
+ if (next_tb != 0 && !qemu_loglevel_mask(CPU_LOG_TB_NOCHAIN)) {
tb_add_jump((TranslationBlock *)(next_tb & ~TB_EXIT_MASK),
next_tb & TB_EXIT_MASK, tb);
}
diff --git a/target-arm/translate.c b/target-arm/translate.c
index 940ec8d..34196a8 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -4054,7 +4054,8 @@ static inline void gen_goto_tb(DisasContext *s, int n,
target_ulong dest)
TranslationBlock *tb;
tb = s->tb;
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
+ ((s->pc - 1) & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
gen_set_pc_im(s, dest);
tcg_gen_exit_tb((uintptr_t)tb + n);
diff --git a/target-cris/translate.c b/target-cris/translate.c
index a73176c..9c8ff8f 100644
--- a/target-cris/translate.c
+++ b/target-cris/translate.c
@@ -524,7 +524,9 @@ static void gen_goto_tb(DisasContext *dc, int n,
target_ulong dest)
{
TranslationBlock *tb;
tb = dc->tb;
- if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+
+ if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
+ (dc->ppc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_tl(env_pc, dest);
tcg_gen_exit_tb((uintptr_t)tb + n);
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 3a32f65..058d85a 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -2094,7 +2094,7 @@ static inline void gen_goto_tb(DisasContext *s, int
tb_num, target_ulong eip)
tb = s->tb;
/* NOTE: we handle the case where the TB spans two pages here */
if ((pc & TARGET_PAGE_MASK) == (tb->pc & TARGET_PAGE_MASK) ||
- (pc & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK)) {
+ (pc & TARGET_PAGE_MASK) == (s->pc_start & TARGET_PAGE_MASK)) {
/* jump to same page: we can use a direct jump */
tcg_gen_goto_tb(tb_num);
gen_jmp_im(eip);
diff --git a/target-m68k/translate.c b/target-m68k/translate.c
index 7560c3a..e2ce6c6 100644
--- a/target-m68k/translate.c
+++ b/target-m68k/translate.c
@@ -861,7 +861,7 @@ static void gen_jmp_tb(DisasContext *s, int n, uint32_t
dest)
if (unlikely(s->singlestep_enabled)) {
gen_exception(s, dest, EXCP_DEBUG);
} else if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK) ||
- (s->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
+ (s->insn_pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
tcg_gen_goto_tb(n);
tcg_gen_movi_i32(QREG_PC, dest);
tcg_gen_exit_tb((uintptr_t)tb + n);
diff --git a/target-s390x/translate.c b/target-s390x/translate.c
index c871ef2..c5179fe 100644
--- a/target-s390x/translate.c
+++ b/target-s390x/translate.c
@@ -610,7 +610,7 @@ static int use_goto_tb(DisasContext *s, uint64_t dest)
{
/* NOTE: we handle the case where the TB spans two pages here */
return (((dest & TARGET_PAGE_MASK) == (s->tb->pc & TARGET_PAGE_MASK)
- || (dest & TARGET_PAGE_MASK) == ((s->pc - 1) & TARGET_PAGE_MASK))
+ || (dest & TARGET_PAGE_MASK) == (s->pc & TARGET_PAGE_MASK))
&& !s->singlestep_enabled
&& !(s->tb->cflags & CF_LAST_IO)
&& !(s->tb->flags & FLAG_MASK_PER));
diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h
index c446d3d..ace3961 100644
--- a/tcg/tcg-op.h
+++ b/tcg/tcg-op.h
@@ -753,6 +753,16 @@ static inline void tcg_gen_exit_tb(uintptr_t val)
tcg_gen_op1i(INDEX_op_exit_tb, val);
}
+/**
+ * tcg_gen_goto_tb() - output goto_tb TCG operation
+ * @idx: Direct jump slot index (0 or 1)
+ *
+ * See tcg/README for more info about this TCG operation.
+ *
+ * NOTE: Direct jumps with goto_tb are only safe within the pages this TB
+ * resides in because we don't take care of direct jumps when address mapping
+ * changes, e.g. in tlb_flush().
+ */
void tcg_gen_goto_tb(unsigned idx);
#if TARGET_LONG_BITS == 32
--
2.5.5
- [Qemu-devel] [PULL 15/39] translate-all: Adjust 256mb testing for mips64, (continued)
- [Qemu-devel] [PULL 15/39] translate-all: Adjust 256mb testing for mips64, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 14/39] translate-all: add missing munmap of the code_gen guard page for MIPS, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 16/39] tcg: Clean up direct block chaining data fields, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 17/39] tcg: Use uintptr_t type for jmp_list_{next|first} fields of TB, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 18/39] tcg: Rearrange tb_link_page() to avoid forward declaration, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 19/39] tcg: Init TB's direct jumps before making it visible, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 21/39] tcg: Rename tb_jmp_remove() to tb_remove_from_jmp_list(), Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 20/39] tcg: Clarify thread safety check in tb_add_jump(), Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 23/39] tcg: Clean up tb_jmp_unlink(), Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 22/39] tcg: Extract removing of jumps to TB from tb_phys_invalidate(), Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 24/39] tcg: Clean up direct block chaining safety checks,
Richard Henderson <=
- [Qemu-devel] [PULL 26/39] tcg: code_bitmap and code_write_count are not used by user-mode emulation, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 25/39] tcg: Allow goto_tb to any target PC in user mode, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 27/39] tcg: reorganize tb_find_physical loop, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 28/39] cpu-exec: elide more icount code if CONFIG_USER_ONLY, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 29/39] tcg: Clean up from 'next_tb', Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 31/39] cpu-exec: Move TB chaining into tb_find_fast(), Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 30/39] tcg: Rework tb_invalidated_flag, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 33/39] cpu-exec: Remove relic orphaned comment, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 32/39] tcg: Remove needless CPUState::current_tb, Richard Henderson, 2016/05/12
- [Qemu-devel] [PULL 35/39] cpu-exec: Move exception handling out of cpu_exec(), Richard Henderson, 2016/05/12