qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages
@ 2022-08-08 17:10 Ilya Leoshkevich
  2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
                   ` (3 more replies)
  0 siblings, 4 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
  To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich

Hi,

I noticed that when we get a SEGV due to jumping to non-readable
memory, sometimes si_addr and program counter in siginfo_t are slightly
off. I tracked this down to the assumption that translators stop before
the end of a page, while in reality they may stop right after it.

Patch 1 fixes a minor invalidation issue, which may prevent SEGV from
happening altogether.
Patches 2-3 fix the main issue on x86_64 and s390x. Many other
architectures have fixed-size instructions and are not affected.
Patch 4 adds tests.

Best regards,
Ilya

v1: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg00822.html
v1 -> v2: Fix individual translators instead of translator_loop
          (Peter).

v2: https://lists.gnu.org/archive/html/qemu-devel/2022-08/msg01079.html
v2 -> v3: Peek at the next instruction on s390x (Richard).
          Undo more on i386 (Richard).
          Check PAGE_EXEC, not PAGE_READ (Peter, Richard).

Ilya Leoshkevich (4):
  accel/tcg: Invalidate translations when clearing PAGE_EXEC
  target/s390x: Make translator stop before the end of a page
  target/i386: Make translator stop before the end of a page
  tests/tcg: Test siginfo_t contents when jumping to non-readable pages

 accel/tcg/translate-all.c        |  17 ++--
 accel/tcg/translator.c           |   8 ++
 include/exec/translator.h        |  13 +++
 target/i386/tcg/translate.c      |  21 ++++-
 target/s390x/tcg/translate.c     |  15 +++-
 tests/tcg/multiarch/noexec.h     | 114 ++++++++++++++++++++++++
 tests/tcg/s390x/Makefile.target  |   1 +
 tests/tcg/s390x/noexec.c         | 145 +++++++++++++++++++++++++++++++
 tests/tcg/x86_64/Makefile.target |   3 +-
 tests/tcg/x86_64/noexec.c        | 116 +++++++++++++++++++++++++
 10 files changed, 442 insertions(+), 11 deletions(-)
 create mode 100644 tests/tcg/multiarch/noexec.h
 create mode 100644 tests/tcg/s390x/noexec.c
 create mode 100644 tests/tcg/x86_64/noexec.c

-- 
2.37.1



^ permalink raw reply	[flat|nested] 13+ messages in thread

* [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
  2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
  2022-08-10 20:29   ` Richard Henderson
  2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
                   ` (2 subsequent siblings)
  3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
  To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich

After mprotect(addr, PROT_NONE), addr can still be executed if there
are cached translations. Drop them.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 accel/tcg/translate-all.c | 17 ++++++++++++-----
 1 file changed, 12 insertions(+), 5 deletions(-)

diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
index ef62a199c7..32ea5f0adf 100644
--- a/accel/tcg/translate-all.c
+++ b/accel/tcg/translate-all.c
@@ -2295,12 +2295,19 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
          len != 0;
          len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
         PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
+        bool write_set, exec_cleared;
 
-        /* If the write protection bit is set, then we invalidate
-           the code inside.  */
-        if (!(p->flags & PAGE_WRITE) &&
-            (flags & PAGE_WRITE) &&
-            p->first_tb) {
+        /*
+         * If the write protection bit is set, then we invalidate the code
+         * inside.
+         */
+        write_set = !(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE);
+        /*
+         * If PAGE_EXEC is cleared, we also need to invalidate the code in
+         * order to force a fault when trying to run it.
+         */
+        exec_cleared = (p->flags & PAGE_EXEC) && !(flags & PAGE_EXEC);
+        if ((write_set || exec_cleared) && p->first_tb) {
             tb_invalidate_phys_page(addr, 0);
         }
         if (reset_target_data) {
-- 
2.37.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page
  2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
  2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
  2022-08-10 20:30   ` Richard Henderson
  2022-08-11  4:08   ` Richard Henderson
  2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
  2022-08-08 17:10 ` [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
  3 siblings, 2 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
  To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich

Right now translator stops right *after* the end of a page, which
breaks reporting of fault locations when the last instruction of a
multi-insn translation block crosses a page boundary.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 include/exec/translator.h    | 10 ++++++++++
 target/s390x/tcg/translate.c | 15 +++++++++++----
 2 files changed, 21 insertions(+), 4 deletions(-)

diff --git a/include/exec/translator.h b/include/exec/translator.h
index 7db6845535..d27f8c33b6 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -187,4 +187,14 @@ 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(DisasContextBase *db, target_ulong addr)
+{
+    return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
+}
+
 #endif /* EXEC__TRANSLATOR_H */
diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
index e2ee005671..8e45a0e0d3 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -6609,6 +6609,14 @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
     dc->insn_start = tcg_last_op();
 }
 
+static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
+                                uint64_t pc)
+{
+    uint64_t insn = ld_code2(env, s, pc);
+
+    return pc + get_ilen((insn >> 8) & 0xff);
+}
+
 static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 {
     CPUS390XState *env = cs->env_ptr;
@@ -6616,10 +6624,9 @@ static void s390x_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
 
     dc->base.is_jmp = translate_one(env, dc);
     if (dc->base.is_jmp == DISAS_NEXT) {
-        uint64_t page_start;
-
-        page_start = dc->base.pc_first & TARGET_PAGE_MASK;
-        if (dc->base.pc_next - page_start >= TARGET_PAGE_SIZE || dc->ex_value) {
+        if (!is_same_page(dcbase, dc->base.pc_next) ||
+            !is_same_page(dcbase, get_next_pc(env, dc, dc->base.pc_next)) ||
+            dc->ex_value) {
             dc->base.is_jmp = DISAS_TOO_MANY;
         }
     }
-- 
2.37.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 3/4] target/i386: Make translator stop before the end of a page
  2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
  2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
  2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
  2022-08-10 20:35   ` Richard Henderson
  2022-08-08 17:10 ` [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
  3 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
  To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich

Right now translator stops right *after* the end of a page, which
breaks reporting of fault locations when the last instruction of a
multi-insn translation block crosses a page boundary.

An implementation, like the one arm and s390x have, would require an
i386 length disassembler, which is burdensome to maintain. Another
alternative would be to single-step at the end of a guest page, but
this may come with a performance impact.

Fix by snapshotting disassembly state and restoring it after we figure
out we crossed a page boundary. This includes rolling back cc_op
updates and emitted ops. Even though i386 is the only architecture that
does rollback, split it into common and architecture-dependent parts to
improve readability.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 accel/tcg/translator.c      |  8 ++++++++
 include/exec/translator.h   |  3 +++
 target/i386/tcg/translate.c | 21 ++++++++++++++++++++-
 3 files changed, 31 insertions(+), 1 deletion(-)

diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index fe7af9b943..2c4dd09df8 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -56,6 +56,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
 {
     uint32_t cflags = tb_cflags(tb);
     bool plugin_enabled;
+    TCGOp *last_op;
 
     /* Initialize DisasContext */
     db->tb = tb;
@@ -82,6 +83,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
 
     while (true) {
         db->num_insns++;
+        last_op = tcg_last_op();
         ops->insn_start(db, cpu);
         tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
 
@@ -103,6 +105,12 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
             ops->translate_insn(db, cpu);
         }
 
+        if (db->is_jmp == DISAS_TOO_MANY_UNDO) {
+            db->num_insns--;
+            tcg_remove_ops_after(last_op);
+            db->is_jmp = DISAS_TOO_MANY;
+        }
+
         /* Stop translation if translate_insn so indicated.  */
         if (db->is_jmp != DISAS_NEXT) {
             break;
diff --git a/include/exec/translator.h b/include/exec/translator.h
index d27f8c33b6..e1533aee87 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -31,6 +31,8 @@
  * DisasJumpType:
  * @DISAS_NEXT: Next instruction in program order.
  * @DISAS_TOO_MANY: Too many instructions translated.
+ * @DISAS_TOO_MANY_UNDO: Too many instructions translated. Everything that was
+ *                       done for the current instruction must be undone.
  * @DISAS_NORETURN: Following code is dead.
  * @DISAS_TARGET_*: Start of target-specific conditions.
  *
@@ -39,6 +41,7 @@
 typedef enum DisasJumpType {
     DISAS_NEXT,
     DISAS_TOO_MANY,
+    DISAS_TOO_MANY_UNDO,
     DISAS_NORETURN,
     DISAS_TARGET_0,
     DISAS_TARGET_1,
diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index b7972f0ff5..14d4ed1412 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -2008,6 +2008,12 @@ static uint64_t advance_pc(CPUX86State *env, DisasContext *s, int num_bytes)
 {
     uint64_t pc = s->pc;
 
+    /* This is a subsequent insn that crosses a page boundary.  */
+    if (s->base.num_insns > 1 &&
+        !is_same_page(&s->base, s->pc + num_bytes - 1)) {
+        siglongjmp(s->jmpbuf, 2);
+    }
+
     s->pc += num_bytes;
     if (unlikely(s->pc - s->pc_start > X86_MAX_INSN_LENGTH)) {
         /* If the instruction's 16th byte is on a different page than the 1st, a
@@ -4556,6 +4562,8 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
     int modrm, reg, rm, mod, op, opreg, val;
     target_ulong next_eip, tval;
     target_ulong pc_start = s->base.pc_next;
+    bool orig_cc_op_dirty = s->cc_op_dirty;
+    CCOp orig_cc_op = s->cc_op;
 
     s->pc_start = s->pc = pc_start;
     s->override = -1;
@@ -4568,9 +4576,20 @@ static target_ulong disas_insn(DisasContext *s, CPUState *cpu)
     s->rip_offset = 0; /* for relative ip address */
     s->vex_l = 0;
     s->vex_v = 0;
-    if (sigsetjmp(s->jmpbuf, 0) != 0) {
+    switch (sigsetjmp(s->jmpbuf, 0)) {
+    case 0:
+        break;
+    case 1:
         gen_exception_gpf(s);
         return s->pc;
+    case 2:
+        /* Restore state that may affect the next instruction. */
+        s->cc_op_dirty = orig_cc_op_dirty;
+        s->cc_op = orig_cc_op;
+        s->base.is_jmp = DISAS_TOO_MANY_UNDO;
+        return pc_start;
+    default:
+        g_assert_not_reached();
     }
 
     prefixes = 0;
-- 
2.37.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages
  2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
                   ` (2 preceding siblings ...)
  2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
@ 2022-08-08 17:10 ` Ilya Leoshkevich
  3 siblings, 0 replies; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-08 17:10 UTC (permalink / raw)
  To: Laurent Vivier, Eduardo Habkost, Marcel Apfelbaum,
	Philippe Mathieu-Daudé, Yanan Wang, Richard Henderson,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger, Ilya Leoshkevich

Add x86_64 and s390x tests to prevent regressions.

Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
---
 tests/tcg/multiarch/noexec.h     | 114 ++++++++++++++++++++++++
 tests/tcg/s390x/Makefile.target  |   1 +
 tests/tcg/s390x/noexec.c         | 145 +++++++++++++++++++++++++++++++
 tests/tcg/x86_64/Makefile.target |   3 +-
 tests/tcg/x86_64/noexec.c        | 116 +++++++++++++++++++++++++
 5 files changed, 378 insertions(+), 1 deletion(-)
 create mode 100644 tests/tcg/multiarch/noexec.h
 create mode 100644 tests/tcg/s390x/noexec.c
 create mode 100644 tests/tcg/x86_64/noexec.c

diff --git a/tests/tcg/multiarch/noexec.h b/tests/tcg/multiarch/noexec.h
new file mode 100644
index 0000000000..a76e0aa9ea
--- /dev/null
+++ b/tests/tcg/multiarch/noexec.h
@@ -0,0 +1,114 @@
+/*
+ * Common code for arch-specific MMU_INST_FETCH fault testing.
+ *
+ * Declare struct arch_noexec_test before including this file and define
+ * arch_check_mcontext() after that.
+ */
+
+#include <assert.h>
+#include <signal.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/mman.h>
+#include <sys/ucontext.h>
+#include <unistd.h>
+
+/* Forward declarations. */
+
+static void arch_check_mcontext(const struct arch_noexec_test *test,
+                                const mcontext_t *ctx);
+
+/* Utility functions. */
+
+static void safe_print(const char *s)
+{
+    write(0, s, strlen(s));
+}
+
+static void safe_puts(const char *s)
+{
+    safe_print(s);
+    safe_print("\n");
+}
+
+#define PAGE_ALIGN(p) (void *)((unsigned long)(p) & ~0xfffUL)
+
+/* Testing infrastructure. */
+
+struct noexec_test {
+    const char *name;
+    void (*func)(int);
+    void *page;
+    void *expected_si_addr;
+    struct arch_noexec_test arch;
+};
+
+static const struct noexec_test *current_noexec_test;
+
+static void handle_segv(int sig, siginfo_t *info, void *ucontext)
+{
+    int err;
+
+    if (current_noexec_test == NULL) {
+        safe_puts("[  FAILED  ] unexpected SEGV");
+        _exit(1);
+    }
+
+    if (info->si_addr != current_noexec_test->expected_si_addr) {
+        safe_puts("[  FAILED  ] wrong si_addr");
+        _exit(1);
+    }
+
+    arch_check_mcontext(&current_noexec_test->arch,
+                        &((ucontext_t *)ucontext)->uc_mcontext);
+
+    err = mprotect(current_noexec_test->page, 0x1000, PROT_READ | PROT_EXEC);
+    if (err != 0) {
+        safe_puts("[  FAILED  ] mprotect() failed");
+        _exit(1);
+    }
+
+    current_noexec_test = NULL;
+}
+
+static void test_noexec_1(const struct noexec_test *test)
+{
+    int ret;
+
+    /* Trigger TB creation in order to test invalidation. */
+    test->func(0);
+
+    ret = mprotect(test->page, 0x1000, PROT_NONE);
+    assert(ret == 0);
+
+    /* Trigger SEGV and check that handle_segv() ran. */
+    current_noexec_test = test;
+    test->func(0);
+    assert(current_noexec_test == NULL);
+}
+
+static int test_noexec(struct noexec_test *tests, size_t n_tests)
+{
+    struct sigaction act;
+    size_t i;
+    int err;
+
+    memset(&act, 0, sizeof(act));
+    act.sa_sigaction = handle_segv;
+    act.sa_flags = SA_SIGINFO;
+    err = sigaction(SIGSEGV, &act, NULL);
+    assert(err == 0);
+
+    for (i = 0; i < n_tests; i++) {
+        struct noexec_test *test = &tests[i];
+
+        safe_print("[ RUN      ] ");
+        safe_puts(test->name);
+        test_noexec_1(test);
+        safe_puts("[       OK ]");
+    }
+
+    safe_puts("[  PASSED  ]");
+
+    return EXIT_SUCCESS;
+}
diff --git a/tests/tcg/s390x/Makefile.target b/tests/tcg/s390x/Makefile.target
index 1a7a4a2f59..5e13a41c3f 100644
--- a/tests/tcg/s390x/Makefile.target
+++ b/tests/tcg/s390x/Makefile.target
@@ -16,6 +16,7 @@ TESTS+=shift
 TESTS+=trap
 TESTS+=signals-s390x
 TESTS+=branch-relative-long
+TESTS+=noexec
 
 Z14_TESTS=vfminmax
 vfminmax: LDFLAGS+=-lm
diff --git a/tests/tcg/s390x/noexec.c b/tests/tcg/s390x/noexec.c
new file mode 100644
index 0000000000..2dfc9ee817
--- /dev/null
+++ b/tests/tcg/s390x/noexec.c
@@ -0,0 +1,145 @@
+#define _GNU_SOURCE
+
+struct arch_noexec_test {
+    void *expected_pswa;
+    unsigned long expected_r2;
+};
+
+#include "../multiarch/noexec.h"
+
+static void arch_check_mcontext(const struct arch_noexec_test *test,
+                                const mcontext_t *ctx) {
+    if (ctx->psw.addr != (unsigned long)test->expected_pswa) {
+        safe_puts("[  FAILED  ] wrong psw.addr");
+        _exit(1);
+    }
+
+    if (ctx->gregs[2] != test->expected_r2) {
+        safe_puts("[  FAILED  ] wrong r2");
+        _exit(1);
+    }
+}
+
+#define DEFINE_NX(name, offset) \
+    void name ## _1(int); \
+    void name ## _2(int); \
+    void name ## _exrl(int); \
+    extern const short name ## _end[]; \
+    asm(/* Go to the specified page offset. */ \
+        ".align 0x1000\n" \
+        ".org .+" #offset "\n" \
+        /* %r2 is 0 on entry, overwrite it with 1. */ \
+        ".globl " #name "_1\n" \
+        #name "_1:\n" \
+        ".cfi_startproc\n" \
+        "lgfi %r2,1\n" \
+        /* Overwrite %2 with 2. */ \
+        ".globl " #name "_2\n" \
+        #name "_2:\n" \
+        "lgfi %r2,2\n" \
+        "br %r14\n" \
+        /* End of code. */ \
+        ".globl " #name "_end\n" \
+        #name "_end:\n" \
+        ".cfi_endproc\n" \
+        /* Go to the next page. */ \
+        ".align 0x1000\n" \
+        /* Break alignment. */ \
+        "nopr %r7\n" \
+        ".globl " #name "_exrl\n" \
+        #name "_exrl:\n" \
+        ".cfi_startproc\n" \
+        "exrl %r0," #name "_2\n" \
+        "br %r14\n" \
+        ".cfi_endproc");
+
+/* noexec_1 is executable, noexec_2 is non-executable. */
+DEFINE_NX(noexec, 0xffa);
+
+/*
+ * noexec_cross_1 is executable, noexec_cross_2 crosses non-executable page
+ * boundary.
+ */
+DEFINE_NX(noexec_cross, 0xff8);
+
+/* noexec_full_1 and noexec_full_2 are non-executable. */
+DEFINE_NX(noexec_full, 0x322);
+
+int main(void)
+{
+    struct noexec_test noexec_tests[] = {
+        {
+            .name = "Fallthrough",
+            .func = noexec_1,
+            .page = noexec_2,
+            .expected_si_addr = noexec_2,
+            .arch = {
+                .expected_pswa = noexec_2,
+                .expected_r2 = 1,
+            },
+        },
+        {
+            .name = "Jump",
+            .func = noexec_2,
+            .page = noexec_2,
+            .expected_si_addr = noexec_2,
+            .arch = {
+                .expected_pswa = noexec_2,
+                .expected_r2 = 0,
+            },
+        },
+        {
+            .name = "EXRL",
+            .func = noexec_exrl,
+            .page = noexec_2,
+            .expected_si_addr = PAGE_ALIGN(noexec_end),
+            .arch = {
+                .expected_pswa = noexec_exrl,
+                .expected_r2 = 0,
+            },
+        },
+        {
+            .name = "Fallthrough [cross]",
+            .func = noexec_cross_1,
+            .page = PAGE_ALIGN(noexec_cross_end),
+            .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+            .arch = {
+                .expected_pswa = noexec_cross_2,
+                .expected_r2 = 1,
+            },
+        },
+        {
+            .name = "Jump [cross]",
+            .func = noexec_cross_2,
+            .page = PAGE_ALIGN(noexec_cross_end),
+            .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+            .arch = {
+                .expected_pswa = noexec_cross_2,
+                .expected_r2 = 0,
+            },
+        },
+        {
+            .name = "EXRL [cross]",
+            .func = noexec_cross_exrl,
+            .page = PAGE_ALIGN(noexec_cross_end),
+            .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+            .arch = {
+                .expected_pswa = noexec_cross_exrl,
+                .expected_r2 = 0,
+            },
+        },
+        {
+            .name = "Jump [full]",
+            .func = noexec_full_1,
+            .page = PAGE_ALIGN(noexec_full_1),
+            .expected_si_addr = PAGE_ALIGN(noexec_full_1),
+            .arch = {
+                .expected_pswa = noexec_full_1,
+                .expected_r2 = 0,
+            },
+        },
+    };
+
+    return test_noexec(noexec_tests,
+                       sizeof(noexec_tests) / sizeof(noexec_tests[0]));
+}
diff --git a/tests/tcg/x86_64/Makefile.target b/tests/tcg/x86_64/Makefile.target
index b71a6bcd5e..c0e7e5b005 100644
--- a/tests/tcg/x86_64/Makefile.target
+++ b/tests/tcg/x86_64/Makefile.target
@@ -10,6 +10,7 @@ include $(SRC_PATH)/tests/tcg/i386/Makefile.target
 
 ifeq ($(filter %-linux-user, $(TARGET)),$(TARGET))
 X86_64_TESTS += vsyscall
+X86_64_TESTS += noexec
 TESTS=$(MULTIARCH_TESTS) $(X86_64_TESTS) test-x86_64
 else
 TESTS=$(MULTIARCH_TESTS)
@@ -20,5 +21,5 @@ test-x86_64: LDFLAGS+=-lm -lc
 test-x86_64: test-i386.c test-i386.h test-i386-shift.h test-i386-muldiv.h
 	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
 
-vsyscall: $(SRC_PATH)/tests/tcg/x86_64/vsyscall.c
+%: $(SRC_PATH)/tests/tcg/x86_64/%.c
 	$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
diff --git a/tests/tcg/x86_64/noexec.c b/tests/tcg/x86_64/noexec.c
new file mode 100644
index 0000000000..ec07c9f0ba
--- /dev/null
+++ b/tests/tcg/x86_64/noexec.c
@@ -0,0 +1,116 @@
+#define _GNU_SOURCE
+
+struct arch_noexec_test {
+    void *expected_rip;
+    unsigned long expected_rdi;
+};
+
+#include "../multiarch/noexec.h"
+
+static void arch_check_mcontext(const struct arch_noexec_test *test,
+                                const mcontext_t *ctx) {
+    if (ctx->gregs[REG_RIP] != (unsigned long)test->expected_rip) {
+        safe_puts("[  FAILED  ] wrong rip");
+        _exit(1);
+    }
+
+    if (ctx->gregs[REG_RDI] != test->expected_rdi) {
+        safe_puts("[  FAILED  ] wrong rdi");
+        _exit(1);
+    }
+}
+
+#define DEFINE_NX(name, offset) \
+    void name ## _1(int); \
+    void name ## _2(int); \
+    extern const short name ## _end[]; \
+    asm(/* Go to the specified page offset. */ \
+        ".align 0x1000\n" \
+        ".org .+" #offset "\n" \
+        /* %rdi is 0 on entry, overwrite it with 1. */ \
+        ".globl " #name "_1\n" \
+        #name "_1:\n" \
+        ".cfi_startproc\n" \
+        "movq $1,%rdi\n" \
+        /* Overwrite %rdi with 2. */ \
+        ".globl " #name "_2\n" \
+        #name "_2:\n" \
+        "movq $2,%rdi\n" \
+        "ret\n" \
+        /* End of code. */ \
+        ".globl " #name "_end\n" \
+        #name "_end:\n" \
+        ".cfi_endproc\n" \
+        /* Go to the next page. */ \
+        ".align 0x1000");
+
+/* noexec_1 is executable, noexec_2 is non-executable. */
+DEFINE_NX(noexec, 0xff9);
+
+/*
+ * noexec_cross_1 is executable, noexec_cross_2 crosses non-executable page
+ * boundary.
+ */
+DEFINE_NX(noexec_cross, 0xff8);
+
+/* noexec_full_1 and noexec_full_2 are non-executable. */
+DEFINE_NX(noexec_full, 0x321);
+
+int main(void)
+{
+    struct noexec_test noexec_tests[] = {
+        {
+            .name = "Fallthrough",
+            .func = noexec_1,
+            .page = noexec_2,
+            .expected_si_addr = noexec_2,
+            .arch = {
+                .expected_rip = noexec_2,
+                .expected_rdi = 1,
+            },
+        },
+        {
+            .name = "Jump",
+            .func = noexec_2,
+            .page = noexec_2,
+            .expected_si_addr = noexec_2,
+            .arch = {
+                .expected_rip = noexec_2,
+                .expected_rdi = 0,
+            },
+        },
+        {
+            .name = "Fallthrough [cross]",
+            .func = noexec_cross_1,
+            .page = PAGE_ALIGN(noexec_cross_end),
+            .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+            .arch = {
+                .expected_rip = noexec_cross_2,
+                .expected_rdi = 1,
+            },
+        },
+        {
+            .name = "Jump [cross]",
+            .func = noexec_cross_2,
+            .page = PAGE_ALIGN(noexec_cross_end),
+            .expected_si_addr = PAGE_ALIGN(noexec_cross_end),
+            .arch = {
+                .expected_rip = noexec_cross_2,
+                .expected_rdi = 0,
+            },
+        },
+        {
+            .name = "Jump [full]",
+            .func = noexec_full_1,
+            .page = PAGE_ALIGN(noexec_full_1),
+            .expected_si_addr = noexec_full_1,
+            .arch = {
+                .expected_rip = noexec_full_1,
+                .expected_rdi = 0,
+            },
+        },
+    };
+
+    return test_noexec(noexec_tests,
+                       sizeof(noexec_tests) / sizeof(noexec_tests[0]));
+}
-- 
2.37.1



^ permalink raw reply related	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
  2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
@ 2022-08-10 20:29   ` Richard Henderson
  2022-08-11  9:28     ` Ilya Leoshkevich
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2022-08-10 20:29 UTC (permalink / raw)
  To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On 8/8/22 10:10, Ilya Leoshkevich wrote:
> After mprotect(addr, PROT_NONE), addr can still be executed if there
> are cached translations. Drop them.
> 
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
>   accel/tcg/translate-all.c | 17 ++++++++++++-----
>   1 file changed, 12 insertions(+), 5 deletions(-)
> 
> diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> index ef62a199c7..32ea5f0adf 100644
> --- a/accel/tcg/translate-all.c
> +++ b/accel/tcg/translate-all.c
> @@ -2295,12 +2295,19 @@ void page_set_flags(target_ulong start, target_ulong end, int flags)
>            len != 0;
>            len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
>           PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS, 1);
> +        bool write_set, exec_cleared;
>   
> -        /* If the write protection bit is set, then we invalidate
> -           the code inside.  */
> -        if (!(p->flags & PAGE_WRITE) &&
> -            (flags & PAGE_WRITE) &&
> -            p->first_tb) {
> +        /*
> +         * If the write protection bit is set, then we invalidate the code
> +         * inside.
> +         */
> +        write_set = !(p->flags & PAGE_WRITE) && (flags & PAGE_WRITE);
> +        /*
> +         * If PAGE_EXEC is cleared, we also need to invalidate the code in
> +         * order to force a fault when trying to run it.
> +         */
> +        exec_cleared = (p->flags & PAGE_EXEC) && !(flags & PAGE_EXEC);
> +        if ((write_set || exec_cleared) && p->first_tb) {

I believe the bug you're trying to fix is in get_page_addr_code, which for USER_ONLY is 
currently a no-op.  It ought to be checking the page permissions there, as we do for softmmu.

I have a patch for get_page_addr_code in the works, because I was working on pther stuff 
in the area.


r~


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page
  2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
@ 2022-08-10 20:30   ` Richard Henderson
  2022-08-11  4:08   ` Richard Henderson
  1 sibling, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-10 20:30 UTC (permalink / raw)
  To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On 8/8/22 10:10, Ilya Leoshkevich wrote:
> Right now translator stops right*after*  the end of a page, which
> breaks reporting of fault locations when the last instruction of a
> multi-insn translation block crosses a page boundary.
> 
> Signed-off-by: Ilya Leoshkevich<iii@linux.ibm.com>
> ---
>   include/exec/translator.h    | 10 ++++++++++
>   target/s390x/tcg/translate.c | 15 +++++++++++----
>   2 files changed, 21 insertions(+), 4 deletions(-)

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>


r~


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 3/4] target/i386: Make translator stop before the end of a page
  2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
@ 2022-08-10 20:35   ` Richard Henderson
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-10 20:35 UTC (permalink / raw)
  To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On 8/8/22 10:10, Ilya Leoshkevich wrote:
> Right now translator stops right *after* the end of a page, which
> breaks reporting of fault locations when the last instruction of a
> multi-insn translation block crosses a page boundary.
> 
> An implementation, like the one arm and s390x have, would require an
> i386 length disassembler, which is burdensome to maintain. Another
> alternative would be to single-step at the end of a guest page, but
> this may come with a performance impact.
> 
> Fix by snapshotting disassembly state and restoring it after we figure
> out we crossed a page boundary. This includes rolling back cc_op
> updates and emitted ops. Even though i386 is the only architecture that
> does rollback, split it into common and architecture-dependent parts to
> improve readability.
> 
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
>   accel/tcg/translator.c      |  8 ++++++++
>   include/exec/translator.h   |  3 +++
>   target/i386/tcg/translate.c | 21 ++++++++++++++++++++-
>   3 files changed, 31 insertions(+), 1 deletion(-)
> 
> diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
> index fe7af9b943..2c4dd09df8 100644
> --- a/accel/tcg/translator.c
> +++ b/accel/tcg/translator.c
> @@ -56,6 +56,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
>   {
>       uint32_t cflags = tb_cflags(tb);
>       bool plugin_enabled;
> +    TCGOp *last_op;
>   
>       /* Initialize DisasContext */
>       db->tb = tb;
> @@ -82,6 +83,7 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
>   
>       while (true) {
>           db->num_insns++;
> +        last_op = tcg_last_op();
>           ops->insn_start(db, cpu);
>           tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
>   
> @@ -103,6 +105,12 @@ void translator_loop(const TranslatorOps *ops, DisasContextBase *db,
>               ops->translate_insn(db, cpu);
>           }
>   
> +        if (db->is_jmp == DISAS_TOO_MANY_UNDO) {
> +            db->num_insns--;
> +            tcg_remove_ops_after(last_op);
> +            db->is_jmp = DISAS_TOO_MANY;
> +        }
> +
>           /* Stop translation if translate_insn so indicated.  */
>           if (db->is_jmp != DISAS_NEXT) {
>               break;
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index d27f8c33b6..e1533aee87 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -31,6 +31,8 @@
>    * DisasJumpType:
>    * @DISAS_NEXT: Next instruction in program order.
>    * @DISAS_TOO_MANY: Too many instructions translated.
> + * @DISAS_TOO_MANY_UNDO: Too many instructions translated. Everything that was
> + *                       done for the current instruction must be undone.
>    * @DISAS_NORETURN: Following code is dead.
>    * @DISAS_TARGET_*: Start of target-specific conditions.
>    *
> @@ -39,6 +41,7 @@
>   typedef enum DisasJumpType {
>       DISAS_NEXT,
>       DISAS_TOO_MANY,
> +    DISAS_TOO_MANY_UNDO,

Hmm, maybe.  I'm not overly keen on the generic change, because I think it would be easy 
to use incorrectly.

> +    case 2:
> +        /* Restore state that may affect the next instruction. */
> +        s->cc_op_dirty = orig_cc_op_dirty;
> +        s->cc_op = orig_cc_op;
> +        s->base.is_jmp = DISAS_TOO_MANY_UNDO;

I think you can simply set s->prev_insn_end in i386_tr_insn_start, for discarding opcodes.


r~


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page
  2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
  2022-08-10 20:30   ` Richard Henderson
@ 2022-08-11  4:08   ` Richard Henderson
  1 sibling, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-11  4:08 UTC (permalink / raw)
  To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On 8/8/22 10:10, Ilya Leoshkevich wrote:
> Right now translator stops right *after* the end of a page, which
> breaks reporting of fault locations when the last instruction of a
> multi-insn translation block crosses a page boundary.
> 
> Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> ---
>   include/exec/translator.h    | 10 ++++++++++
>   target/s390x/tcg/translate.c | 15 +++++++++++----
>   2 files changed, 21 insertions(+), 4 deletions(-)
> 
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index 7db6845535..d27f8c33b6 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -187,4 +187,14 @@ 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(DisasContextBase *db, target_ulong addr)
> +{
> +    return ((addr ^ db->pc_first) & TARGET_PAGE_MASK) == 0;
> +}

FYI, I've had occasion to pull this out to a separate patch locally.


r~


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
  2022-08-10 20:29   ` Richard Henderson
@ 2022-08-11  9:28     ` Ilya Leoshkevich
  2022-08-11 15:42       ` Richard Henderson
  0 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-11  9:28 UTC (permalink / raw)
  To: Richard Henderson, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On Wed, 2022-08-10 at 13:29 -0700, Richard Henderson wrote:
> On 8/8/22 10:10, Ilya Leoshkevich wrote:
> > After mprotect(addr, PROT_NONE), addr can still be executed if
> > there
> > are cached translations. Drop them.
> > 
> > Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
> > ---
> >   accel/tcg/translate-all.c | 17 ++++++++++++-----
> >   1 file changed, 12 insertions(+), 5 deletions(-)
> > 
> > diff --git a/accel/tcg/translate-all.c b/accel/tcg/translate-all.c
> > index ef62a199c7..32ea5f0adf 100644
> > --- a/accel/tcg/translate-all.c
> > +++ b/accel/tcg/translate-all.c
> > @@ -2295,12 +2295,19 @@ void page_set_flags(target_ulong start,
> > target_ulong end, int flags)
> >            len != 0;
> >            len -= TARGET_PAGE_SIZE, addr += TARGET_PAGE_SIZE) {
> >           PageDesc *p = page_find_alloc(addr >> TARGET_PAGE_BITS,
> > 1);
> > +        bool write_set, exec_cleared;
> >   
> > -        /* If the write protection bit is set, then we invalidate
> > -           the code inside.  */
> > -        if (!(p->flags & PAGE_WRITE) &&
> > -            (flags & PAGE_WRITE) &&
> > -            p->first_tb) {
> > +        /*
> > +         * If the write protection bit is set, then we invalidate
> > the code
> > +         * inside.
> > +         */
> > +        write_set = !(p->flags & PAGE_WRITE) && (flags &
> > PAGE_WRITE);
> > +        /*
> > +         * If PAGE_EXEC is cleared, we also need to invalidate the
> > code in
> > +         * order to force a fault when trying to run it.
> > +         */
> > +        exec_cleared = (p->flags & PAGE_EXEC) && !(flags &
> > PAGE_EXEC);
> > +        if ((write_set || exec_cleared) && p->first_tb) {
> 
> I believe the bug you're trying to fix is in get_page_addr_code,
> which for USER_ONLY is 
> currently a no-op.  It ought to be checking the page permissions
> there, as we do for softmmu.
> 
> I have a patch for get_page_addr_code in the works, because I was
> working on pther stuff 
> in the area.

How is qemu-user's get_page_addr_code() involved here?

I tried to experiment with it, and while I agree that it looks buggy,
it's called only from translation code paths. If we already have a
translation block, these code paths are not used.


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
  2022-08-11  9:28     ` Ilya Leoshkevich
@ 2022-08-11 15:42       ` Richard Henderson
  2022-08-12 15:02         ` Ilya Leoshkevich
  0 siblings, 1 reply; 13+ messages in thread
From: Richard Henderson @ 2022-08-11 15:42 UTC (permalink / raw)
  To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On 8/11/22 02:28, Ilya Leoshkevich wrote:
> How is qemu-user's get_page_addr_code() involved here?
> 
> I tried to experiment with it, and while I agree that it looks buggy,
> it's called only from translation code paths. If we already have a
> translation block, these code paths are not used.

It's called from tb_lookup too, when we're trying to find an existing TB.


r~


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
  2022-08-11 15:42       ` Richard Henderson
@ 2022-08-12 15:02         ` Ilya Leoshkevich
  2022-08-12 17:59           ` Richard Henderson
  0 siblings, 1 reply; 13+ messages in thread
From: Ilya Leoshkevich @ 2022-08-12 15:02 UTC (permalink / raw)
  To: Richard Henderson, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On Thu, 2022-08-11 at 08:42 -0700, Richard Henderson wrote:
> On 8/11/22 02:28, Ilya Leoshkevich wrote:
> > How is qemu-user's get_page_addr_code() involved here?
> > 
> > I tried to experiment with it, and while I agree that it looks
> > buggy,
> > it's called only from translation code paths. If we already have a
> > translation block, these code paths are not used.
> 
> It's called from tb_lookup too, when we're trying to find an existing
> TB.
> 
> 
> r~
> 

Oh, I see. I was first worried about direct block chaining with
goto_tb, but it turned out that translator_use_goto_tb() prevented it.

tb_lookup() skips get_page_addr_code() if tb is found in tb_jmp_cache.
I assume it's a bug?


^ permalink raw reply	[flat|nested] 13+ messages in thread

* Re: [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC
  2022-08-12 15:02         ` Ilya Leoshkevich
@ 2022-08-12 17:59           ` Richard Henderson
  0 siblings, 0 replies; 13+ messages in thread
From: Richard Henderson @ 2022-08-12 17:59 UTC (permalink / raw)
  To: Ilya Leoshkevich, Laurent Vivier, Eduardo Habkost,
	Marcel Apfelbaum, Philippe Mathieu-Daudé, Yanan Wang,
	Paolo Bonzini, David Hildenbrand, Peter Maydell
  Cc: qemu-devel, qemu-s390x, Christian Borntraeger

On 8/12/22 08:02, Ilya Leoshkevich wrote:
> tb_lookup() skips get_page_addr_code() if tb is found in tb_jmp_cache.
> I assume it's a bug?

Yes, I think so.  I've rearranged that for other reasons, and so may have inadvertently 
fix this.  I'll post the in-progress work in a moment.


r~


^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2022-08-12 18:01 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2022-08-08 17:10 [PATCH v3 0/4] linux-user: Fix siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich
2022-08-08 17:10 ` [PATCH v3 1/4] accel/tcg: Invalidate translations when clearing PAGE_EXEC Ilya Leoshkevich
2022-08-10 20:29   ` Richard Henderson
2022-08-11  9:28     ` Ilya Leoshkevich
2022-08-11 15:42       ` Richard Henderson
2022-08-12 15:02         ` Ilya Leoshkevich
2022-08-12 17:59           ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 2/4] target/s390x: Make translator stop before the end of a page Ilya Leoshkevich
2022-08-10 20:30   ` Richard Henderson
2022-08-11  4:08   ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 3/4] target/i386: " Ilya Leoshkevich
2022-08-10 20:35   ` Richard Henderson
2022-08-08 17:10 ` [PATCH v3 4/4] tests/tcg: Test siginfo_t contents when jumping to non-readable pages Ilya Leoshkevich

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).