summary refs log tree commit diff stats
path: root/include/exec/translator.h
diff options
context:
space:
mode:
authorStefan Hajnoczi <stefanha@redhat.com>2022-09-06 07:31:43 -0400
committerStefan Hajnoczi <stefanha@redhat.com>2022-09-06 07:31:43 -0400
commitb34b42f1b6a33c455dccce6ceb49962dddbb7a8a (patch)
tree68143a8c84528fdd3caf8b5206a5df9427ae7263 /include/exec/translator.h
parentfd28528ece590dc709d1a893fce2ff2f68ddca70 (diff)
parent00c07344fa245b22e895b363320ba4cd0ec1088a (diff)
downloadfocaccia-qemu-b34b42f1b6a33c455dccce6ceb49962dddbb7a8a.tar.gz
focaccia-qemu-b34b42f1b6a33c455dccce6ceb49962dddbb7a8a.zip
Merge tag 'pull-tcg-20220906' of https://gitlab.com/rth7680/qemu into staging
Respect PROT_EXEC in user-only mode.
Fix s390x, i386 and riscv for translations crossing a page.

# -----BEGIN PGP SIGNATURE-----
#
# iQFRBAABCgA7FiEEekgeeIaLTbaoWgXAZN846K9+IV8FAmMW8TcdHHJpY2hhcmQu
# aGVuZGVyc29uQGxpbmFyby5vcmcACgkQZN846K9+IV8qfwf9EYjXywES/UYzfeJC
# 7irryE3iYddWP+ix3Q4WKaTc61plwP5MMCmeq4PjRo1IBAL5dTtUE1+AFXkEvm4L
# EckSiT5D5d/wYOfhWSWxjblmMk7GUXRRgKzkF1ir3soIftQgXdb43PwAswuOca/v
# dX7wXBJOoWmGWqXNNlQmGIl7c4uQTkOM6iTTLlm4Qg7SJC4MA6EiSZmXlvAs80lN
# TCbBV5P89qseHwzhJUTMZEO+ZMAuTSjFSd/RqBexVa4ty5UJxxgBk21A8JtQPUhr
# Y/Ezb0yhOcwrdjJ8REc267BZbdNgbaVNlUd7c9GKbv8bQUh0AoM9gnjGdoID88x9
# q0f+Pw==
# =HmJB
# -----END PGP SIGNATURE-----
# gpg: Signature made Tue 06 Sep 2022 03:05:27 EDT
# gpg:                using RSA key 7A481E78868B4DB6A85A05C064DF38E8AF7E215F
# gpg:                issuer "richard.henderson@linaro.org"
# gpg: Good signature from "Richard Henderson <richard.henderson@linaro.org>" [full]
# Primary key fingerprint: 7A48 1E78 868B 4DB6 A85A  05C0 64DF 38E8 AF7E 215F

* tag 'pull-tcg-20220906' of https://gitlab.com/rth7680/qemu:
  target/riscv: Make translator stop before the end of a page
  target/riscv: Add MAX_INSN_LEN and insn_len
  target/i386: Make translator stop before the end of a page
  target/s390x: Make translator stop before the end of a page
  accel/tcg: Add fast path for translator_ld*
  accel/tcg: Add pc and host_pc params to gen_intermediate_code
  accel/tcg: Remove translator_ldsw
  accel/tcg: Document the faulting lookup in tb_lookup_cmp
  accel/tcg: Use probe_access_internal for softmmu get_page_addr_code_hostp
  accel/tcg: Move qemu_ram_addr_from_host_nofail to physmem.c
  accel/tcg: Make tb_htable_lookup static
  accel/tcg: Unlock mmap_lock after longjmp
  accel/tcg: Properly implement get_page_addr_code for user-only
  accel/tcg: Introduce is_same_page()
  tests/tcg/i386: Move smc_code2 to an executable section
  linux-user: Clear translations on mprotect()
  linux-user: Honor PT_GNU_STACK
  linux-user/x86_64: Allocate vsyscall page as a commpage
  linux-user/hppa: Allocate page zero as a commpage
  linux-user/arm: Mark the commpage executable

Signed-off-by: Stefan Hajnoczi <stefanha@redhat.com>
Diffstat (limited to 'include/exec/translator.h')
-rw-r--r--include/exec/translator.h100
1 files changed, 67 insertions, 33 deletions
diff --git a/include/exec/translator.h b/include/exec/translator.h
index 7db6845535..3b77f5f4aa 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -26,6 +26,19 @@
 #include "exec/translate-all.h"
 #include "tcg/tcg.h"
 
+/**
+ * gen_intermediate_code
+ * @cpu: cpu context
+ * @tb: translation block
+ * @max_insns: max number of instructions to translate
+ * @pc: guest virtual program counter address
+ * @host_pc: host physical program counter address
+ *
+ * This function must be provided by the target, which should create
+ * the target-specific DisasContext, and then invoke translator_loop.
+ */
+void gen_intermediate_code(CPUState *cpu, TranslationBlock *tb, int max_insns,
+                           target_ulong pc, void *host_pc);
 
 /**
  * DisasJumpType:
@@ -68,24 +81,14 @@ typedef enum DisasJumpType {
  * Architecture-agnostic disassembly context.
  */
 typedef struct DisasContextBase {
-    const TranslationBlock *tb;
+    TranslationBlock *tb;
     target_ulong pc_first;
     target_ulong pc_next;
     DisasJumpType is_jmp;
     int num_insns;
     int max_insns;
     bool singlestep_enabled;
-#ifdef CONFIG_USER_ONLY
-    /*
-     * Guest address of the last byte of the last protected page.
-     *
-     * Pages containing the translated instructions are made non-writable in
-     * order to achieve consistency in case another thread is modifying the
-     * code while translate_insn() fetches the instruction bytes piecemeal.
-     * Such writer threads are blocked on mmap_lock() in page_unprotect().
-     */
-    target_ulong page_protect_end;
-#endif
+    void *host_addr[2];
 } DisasContextBase;
 
 /**
@@ -123,11 +126,13 @@ typedef struct TranslatorOps {
 
 /**
  * translator_loop:
- * @ops: Target-specific operations.
- * @db: Disassembly context.
  * @cpu: Target vCPU.
  * @tb: Translation block.
  * @max_insns: Maximum number of insns to translate.
+ * @pc: guest virtual program counter address
+ * @host_pc: host physical program counter address
+ * @ops: Target-specific operations.
+ * @db: Disassembly context.
  *
  * Generic translator loop.
  *
@@ -141,8 +146,9 @@ typedef struct TranslatorOps {
  * - When single-stepping is enabled (system-wide or on the current vCPU).
  * - When too many instructions have been translated.
  */
-void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
-                     CPUState *cpu, TranslationBlock *tb, int max_insns);
+void translator_loop(CPUState *cpu, TranslationBlock *tb, int max_insns,
+                     target_ulong pc, void *host_pc,
+                     const TranslatorOps *ops, DisasContextBase *db);
 
 void translator_loop_temp_check(DisasContextBase *db);
 
@@ -167,24 +173,52 @@ bool translator_use_goto_tb(DisasContextBase *db, target_ulong dest);
  * the relevant information at translation time.
  */
 
-#define GEN_TRANSLATOR_LD(fullname, type, load_fn, swap_fn)             \
-    type fullname ## _swap(CPUArchState *env, DisasContextBase *dcbase, \
-                           abi_ptr pc, bool do_swap);                   \
-    static inline type fullname(CPUArchState *env,                      \
-                                DisasContextBase *dcbase, abi_ptr pc)   \
-    {                                                                   \
-        return fullname ## _swap(env, dcbase, pc, false);               \
+uint8_t translator_ldub(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
+uint16_t translator_lduw(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
+uint32_t translator_ldl(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
+uint64_t translator_ldq(CPUArchState *env, DisasContextBase *db, abi_ptr pc);
+
+static inline uint16_t
+translator_lduw_swap(CPUArchState *env, DisasContextBase *db,
+                     abi_ptr pc, bool do_swap)
+{
+    uint16_t ret = translator_lduw(env, db, pc);
+    if (do_swap) {
+        ret = bswap16(ret);
     }
+    return ret;
+}
+
+static inline uint32_t
+translator_ldl_swap(CPUArchState *env, DisasContextBase *db,
+                    abi_ptr pc, bool do_swap)
+{
+    uint32_t ret = translator_ldl(env, db, pc);
+    if (do_swap) {
+        ret = bswap32(ret);
+    }
+    return ret;
+}
+
+static inline uint64_t
+translator_ldq_swap(CPUArchState *env, DisasContextBase *db,
+                    abi_ptr pc, bool do_swap)
+{
+    uint64_t ret = translator_ldq(env, db, pc);
+    if (do_swap) {
+        ret = bswap64(ret);
+    }
+    return ret;
+}
 
-#define FOR_EACH_TRANSLATOR_LD(F)                                       \
-    F(translator_ldub, uint8_t, cpu_ldub_code, /* no swap */)           \
-    F(translator_ldsw, int16_t, cpu_ldsw_code, bswap16)                 \
-    F(translator_lduw, uint16_t, cpu_lduw_code, bswap16)                \
-    F(translator_ldl, uint32_t, cpu_ldl_code, bswap32)                  \
-    F(translator_ldq, uint64_t, cpu_ldq_code, bswap64)
-
-FOR_EACH_TRANSLATOR_LD(GEN_TRANSLATOR_LD)
-
-#undef GEN_TRANSLATOR_LD
+/*
+ * Return whether addr is on the same page as where disassembly started.
+ * Translators can use this to enforce the rule that only single-insn
+ * translation blocks are allowed to cross page boundaries.
+ */
+static inline bool is_same_page(const DisasContextBase *db, target_ulong addr)
+{
+    return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
+}
 
 #endif /* EXEC__TRANSLATOR_H */