aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>2014-11-26 13:39:42 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2014-12-15 12:21:02 +0100
commit5b9efc39aee90bbd343793e942bf8f582a0c9e4f (patch)
treed16faa3d215c4c544d43cd30df5d8d140b44f15b
parentbf2a7ddb0a066c27ed1432b918baa046b6b7dfc5 (diff)
i386: do not cross the pages boundaries in replay mode
This patch denies crossing the boundary of the pages in the replay mode, because it can cause an exception. Do it only when boundary is crossed by the first instruction in the block. If current instruction already crossed the bound - it's ok, because an exception hasn't stopped this code. Signed-off-by: Pavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--target-i386/cpu.h3
-rw-r--r--target-i386/translate.c14
2 files changed, 17 insertions, 0 deletions
diff --git a/target-i386/cpu.h b/target-i386/cpu.h
index 7e363654b8..3ecff96325 100644
--- a/target-i386/cpu.h
+++ b/target-i386/cpu.h
@@ -28,6 +28,9 @@
#define TARGET_LONG_BITS 32
#endif
+/* Maximum instruction code size */
+#define TARGET_MAX_INSN_SIZE 16
+
/* target supports implicit self modifying code */
#define TARGET_HAS_SMC
/* support for self modifying code even if the modified instruction is
diff --git a/target-i386/translate.c b/target-i386/translate.c
index 782f7d2666..31a9f74467 100644
--- a/target-i386/translate.c
+++ b/target-i386/translate.c
@@ -8022,6 +8022,20 @@ static inline void gen_intermediate_code_internal(X86CPU *cpu,
gen_eob(dc);
break;
}
+ /* Do not cross the boundary of the pages in icount mode,
+ it can cause an exception. Do it only when boundary is
+ crossed by the first instruction in the block.
+ If current instruction already crossed the bound - it's ok,
+ because an exception hasn't stopped this code.
+ */
+ if (use_icount
+ && ((pc_ptr & TARGET_PAGE_MASK)
+ != ((pc_ptr + TARGET_MAX_INSN_SIZE - 1) & TARGET_PAGE_MASK)
+ || (pc_ptr & ~TARGET_PAGE_MASK) == 0)) {
+ gen_jmp_im(pc_ptr - dc->cs_base);
+ gen_eob(dc);
+ break;
+ }
/* if too long translation, stop generation too */
if (tcg_ctx.gen_opc_ptr >= gen_opc_end ||
(pc_ptr - pc_start) >= (TARGET_PAGE_SIZE - 32) ||