qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
* [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio
@ 2024-04-06 22:32 Richard Henderson
  2024-04-06 22:32 ` [PATCH 1/9] tcg: Add TCGContext.emit_before_op Richard Henderson
                   ` (8 more replies)
  0 siblings, 9 replies; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

Bug report is
https://lore.kernel.org/qemu-devel/33748BB7-E617-4661-BDE3-5D29780FC9FF@wdc.com

Jørgen properly identified the problem, though calling set_can_do_io
in the middle of translator_access is incorrect.

It forced me to do something that's been in the back of my mind for
a while and track the insns being emitted so that we can go back and
insert the proper store to can_do_io after code for the final insn
has been emitted.

If we decide to take this for 9.0, most of the target changes could
technically be left for 9.1.  With the exception of i386 and its funky
case of "pretend we never started translating the current insn".
But I think the target changes are minor enough to take them anyway.


r~


Richard Henderson (9):
  tcg: Add TCGContext.emit_before_op
  accel/tcg: Add insn_start to DisasContextBase
  target/arm: Use insn_start from DisasContextBase
  target/hppa: Use insn_start from DisasContextBase
  target/i386: Preserve DisasContextBase.insn_start across rewind
  target/microblaze: Use insn_start from DisasContextBase
  target/riscv: Use insn_start from DisasContextBase
  target/s390x: Use insn_start from DisasContextBase
  accel/tcg: Improve can_do_io management

 include/exec/translator.h      |  4 ++-
 include/tcg/tcg.h              |  6 +++++
 target/arm/tcg/translate.h     | 12 ++++-----
 accel/tcg/translator.c         | 47 ++++++++++++++++++----------------
 target/arm/tcg/translate-a64.c |  2 +-
 target/arm/tcg/translate.c     |  2 +-
 target/hppa/translate.c        | 10 ++++----
 target/i386/tcg/translate.c    |  3 +++
 target/microblaze/translate.c  |  8 ++----
 target/riscv/translate.c       | 11 ++++----
 target/s390x/tcg/translate.c   |  4 +--
 tcg/tcg.c                      | 14 ++++++++--
 12 files changed, 70 insertions(+), 53 deletions(-)

-- 
2.34.1



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

* [PATCH 1/9] tcg: Add TCGContext.emit_before_op
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:13   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 2/9] accel/tcg: Add insn_start to DisasContextBase Richard Henderson
                   ` (7 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl,
	Pierrick Bouvier

Allow operations to be emitted via normal expanders
into the middle of the opcode stream.

Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/tcg/tcg.h |  6 ++++++
 tcg/tcg.c         | 14 ++++++++++++--
 2 files changed, 18 insertions(+), 2 deletions(-)

diff --git a/include/tcg/tcg.h b/include/tcg/tcg.h
index 451f3fec41..05a1912f8a 100644
--- a/include/tcg/tcg.h
+++ b/include/tcg/tcg.h
@@ -553,6 +553,12 @@ struct TCGContext {
     QTAILQ_HEAD(, TCGOp) ops, free_ops;
     QSIMPLEQ_HEAD(, TCGLabel) labels;
 
+    /*
+     * When clear, new ops are added to the tail of @ops.
+     * When set, new ops are added in front of @emit_before_op.
+     */
+    TCGOp *emit_before_op;
+
     /* Tells which temporary holds a given register.
        It does not take into account fixed registers */
     TCGTemp *reg_to_temp[TCG_TARGET_NB_REGS];
diff --git a/tcg/tcg.c b/tcg/tcg.c
index d6670237fb..0c0bb9d169 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1521,6 +1521,7 @@ void tcg_func_start(TCGContext *s)
 
     QTAILQ_INIT(&s->ops);
     QTAILQ_INIT(&s->free_ops);
+    s->emit_before_op = NULL;
     QSIMPLEQ_INIT(&s->labels);
 
     tcg_debug_assert(s->addr_type == TCG_TYPE_I32 ||
@@ -2332,7 +2333,11 @@ static void tcg_gen_callN(TCGHelperInfo *info, TCGTemp *ret, TCGTemp **args)
     op->args[pi++] = (uintptr_t)info;
     tcg_debug_assert(pi == total_args);
 
-    QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
+    if (tcg_ctx->emit_before_op) {
+        QTAILQ_INSERT_BEFORE(tcg_ctx->emit_before_op, op, link);
+    } else {
+        QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
+    }
 
     tcg_debug_assert(n_extend < ARRAY_SIZE(extend_free));
     for (i = 0; i < n_extend; ++i) {
@@ -3215,7 +3220,12 @@ static TCGOp *tcg_op_alloc(TCGOpcode opc, unsigned nargs)
 TCGOp *tcg_emit_op(TCGOpcode opc, unsigned nargs)
 {
     TCGOp *op = tcg_op_alloc(opc, nargs);
-    QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
+
+    if (tcg_ctx->emit_before_op) {
+        QTAILQ_INSERT_BEFORE(tcg_ctx->emit_before_op, op, link);
+    } else {
+        QTAILQ_INSERT_TAIL(&tcg_ctx->ops, op, link);
+    }
     return op;
 }
 
-- 
2.34.1



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

* [PATCH 2/9] accel/tcg: Add insn_start to DisasContextBase
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
  2024-04-06 22:32 ` [PATCH 1/9] tcg: Add TCGContext.emit_before_op Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:18   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 3/9] target/arm: Use insn_start from DisasContextBase Richard Henderson
                   ` (6 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

This is currently target-specific for many; begin making it
target independent.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/translator.h | 3 +++
 accel/tcg/translator.c    | 2 ++
 2 files changed, 5 insertions(+)

diff --git a/include/exec/translator.h b/include/exec/translator.h
index 51624feb10..ceaeca8c91 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -74,6 +74,8 @@ typedef enum DisasJumpType {
  * @singlestep_enabled: "Hardware" single stepping enabled.
  * @saved_can_do_io: Known value of cpu->neg.can_do_io, or -1 for unknown.
  * @plugin_enabled: TCG plugin enabled in this TB.
+ * @insn_start: The last op emitted by the insn_start hook,
+ *              which is expected to be INDEX_op_insn_start.
  *
  * Architecture-agnostic disassembly context.
  */
@@ -87,6 +89,7 @@ typedef struct DisasContextBase {
     bool singlestep_enabled;
     int8_t saved_can_do_io;
     bool plugin_enabled;
+    struct TCGOp *insn_start;
     void *host_addr[2];
 } DisasContextBase;
 
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index 38c34009a5..ae61c154c2 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -140,6 +140,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     db->max_insns = *max_insns;
     db->singlestep_enabled = cflags & CF_SINGLE_STEP;
     db->saved_can_do_io = -1;
+    db->insn_start = NULL;
     db->host_addr[0] = host_pc;
     db->host_addr[1] = NULL;
 
@@ -157,6 +158,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     while (true) {
         *max_insns = ++db->num_insns;
         ops->insn_start(db, cpu);
+        db->insn_start = tcg_last_op();
         tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
 
         if (plugin_enabled) {
-- 
2.34.1



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

* [PATCH 3/9] target/arm: Use insn_start from DisasContextBase
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
  2024-04-06 22:32 ` [PATCH 1/9] tcg: Add TCGContext.emit_before_op Richard Henderson
  2024-04-06 22:32 ` [PATCH 2/9] accel/tcg: Add insn_start to DisasContextBase Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:16   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 4/9] target/hppa: " Richard Henderson
                   ` (5 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

To keep the multiple update check, replace insn_start
with insn_start_updated.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/arm/tcg/translate.h     | 12 ++++++------
 target/arm/tcg/translate-a64.c |  2 +-
 target/arm/tcg/translate.c     |  2 +-
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/target/arm/tcg/translate.h b/target/arm/tcg/translate.h
index 93be745cf3..dc66ff2190 100644
--- a/target/arm/tcg/translate.h
+++ b/target/arm/tcg/translate.h
@@ -165,10 +165,10 @@ typedef struct DisasContext {
     uint8_t gm_blocksize;
     /* True if this page is guarded.  */
     bool guarded_page;
+    /* True if the current insn_start has been updated. */
+    bool insn_start_updated;
     /* Bottom two bits of XScale c15_cpar coprocessor access control reg */
     int c15_cpar;
-    /* TCG op of the current insn_start.  */
-    TCGOp *insn_start;
     /* Offset from VNCR_EL2 when FEAT_NV2 redirects this reg to memory */
     uint32_t nv2_redirect_offset;
 } DisasContext;
@@ -276,10 +276,10 @@ static inline void disas_set_insn_syndrome(DisasContext *s, uint32_t syn)
     syn &= ARM_INSN_START_WORD2_MASK;
     syn >>= ARM_INSN_START_WORD2_SHIFT;
 
-    /* We check and clear insn_start_idx to catch multiple updates.  */
-    assert(s->insn_start != NULL);
-    tcg_set_insn_start_param(s->insn_start, 2, syn);
-    s->insn_start = NULL;
+    /* Check for multiple updates.  */
+    assert(!s->insn_start_updated);
+    s->insn_start_updated = true;
+    tcg_set_insn_start_param(s->base.insn_start, 2, syn);
 }
 
 static inline int curr_insn_len(DisasContext *s)
diff --git a/target/arm/tcg/translate-a64.c b/target/arm/tcg/translate-a64.c
index 340265beb0..2666d52711 100644
--- a/target/arm/tcg/translate-a64.c
+++ b/target/arm/tcg/translate-a64.c
@@ -14179,7 +14179,7 @@ static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
         pc_arg &= ~TARGET_PAGE_MASK;
     }
     tcg_gen_insn_start(pc_arg, 0, 0);
-    dc->insn_start = tcg_last_op();
+    dc->insn_start_updated = false;
 }
 
 static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
diff --git a/target/arm/tcg/translate.c b/target/arm/tcg/translate.c
index 69585e6003..dc49a8d806 100644
--- a/target/arm/tcg/translate.c
+++ b/target/arm/tcg/translate.c
@@ -9273,7 +9273,7 @@ static void arm_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
         condexec_bits = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
     }
     tcg_gen_insn_start(pc_arg, condexec_bits, 0);
-    dc->insn_start = tcg_last_op();
+    dc->insn_start_updated = false;
 }
 
 static bool arm_check_kernelpage(DisasContext *dc)
-- 
2.34.1



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

* [PATCH 4/9] target/hppa: Use insn_start from DisasContextBase
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
                   ` (2 preceding siblings ...)
  2024-04-06 22:32 ` [PATCH 3/9] target/arm: Use insn_start from DisasContextBase Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:17   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind Richard Henderson
                   ` (4 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

To keep the multiple update check, replace insn_start
with insn_start_updated.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/hppa/translate.c | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)

diff --git a/target/hppa/translate.c b/target/hppa/translate.c
index 8a1a8bc3aa..42fa480950 100644
--- a/target/hppa/translate.c
+++ b/target/hppa/translate.c
@@ -44,7 +44,6 @@ typedef struct DisasCond {
 typedef struct DisasContext {
     DisasContextBase base;
     CPUState *cs;
-    TCGOp *insn_start;
 
     uint64_t iaoq_f;
     uint64_t iaoq_b;
@@ -62,6 +61,7 @@ typedef struct DisasContext {
     int privilege;
     bool psw_n_nonzero;
     bool is_pa20;
+    bool insn_start_updated;
 
 #ifdef CONFIG_USER_ONLY
     MemOp unalign;
@@ -300,9 +300,9 @@ void hppa_translate_init(void)
 
 static void set_insn_breg(DisasContext *ctx, int breg)
 {
-    assert(ctx->insn_start != NULL);
-    tcg_set_insn_start_param(ctx->insn_start, 2, breg);
-    ctx->insn_start = NULL;
+    assert(!ctx->insn_start_updated);
+    ctx->insn_start_updated = true;
+    tcg_set_insn_start_param(ctx->base.insn_start, 2, breg);
 }
 
 static DisasCond cond_make_f(void)
@@ -4694,7 +4694,7 @@ static void hppa_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
     DisasContext *ctx = container_of(dcbase, DisasContext, base);
 
     tcg_gen_insn_start(ctx->iaoq_f, ctx->iaoq_b, 0);
-    ctx->insn_start = tcg_last_op();
+    ctx->insn_start_updated = false;
 }
 
 static void hppa_tr_translate_insn(DisasContextBase *dcbase, CPUState *cs)
-- 
2.34.1



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

* [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
                   ` (3 preceding siblings ...)
  2024-04-06 22:32 ` [PATCH 4/9] target/hppa: " Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-09 15:23   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 6/9] target/microblaze: Use insn_start from DisasContextBase Richard Henderson
                   ` (3 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

When aborting translation of the current insn, restore the
previous value of insn_start.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/i386/tcg/translate.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c
index 07f642dc9e..76a42c679c 100644
--- a/target/i386/tcg/translate.c
+++ b/target/i386/tcg/translate.c
@@ -139,6 +139,7 @@ typedef struct DisasContext {
     TCGv_i64 tmp1_i64;
 
     sigjmp_buf jmpbuf;
+    TCGOp *prev_insn_start;
     TCGOp *prev_insn_end;
 } DisasContext;
 
@@ -3123,6 +3124,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
         /* END TODO */
         s->base.num_insns--;
         tcg_remove_ops_after(s->prev_insn_end);
+        s->base.insn_start = s->prev_insn_start;
         s->base.is_jmp = DISAS_TOO_MANY;
         return false;
     default:
@@ -6995,6 +6997,7 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
     DisasContext *dc = container_of(dcbase, DisasContext, base);
     target_ulong pc_arg = dc->base.pc_next;
 
+    dc->prev_insn_start = dc->base.insn_start;
     dc->prev_insn_end = tcg_last_op();
     if (tb_cflags(dcbase->tb) & CF_PCREL) {
         pc_arg &= ~TARGET_PAGE_MASK;
-- 
2.34.1



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

* [PATCH 6/9] target/microblaze: Use insn_start from DisasContextBase
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
                   ` (4 preceding siblings ...)
  2024-04-06 22:32 ` [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:17   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 7/9] target/riscv: " Richard Henderson
                   ` (2 subsequent siblings)
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/microblaze/translate.c | 8 ++------
 1 file changed, 2 insertions(+), 6 deletions(-)

diff --git a/target/microblaze/translate.c b/target/microblaze/translate.c
index 4e52ef32db..fc451befae 100644
--- a/target/microblaze/translate.c
+++ b/target/microblaze/translate.c
@@ -62,9 +62,6 @@ typedef struct DisasContext {
     DisasContextBase base;
     const MicroBlazeCPUConfig *cfg;
 
-    /* TCG op of the current insn_start.  */
-    TCGOp *insn_start;
-
     TCGv_i32 r0;
     bool r0_set;
 
@@ -699,14 +696,14 @@ static TCGv compute_ldst_addr_ea(DisasContext *dc, int ra, int rb)
 static void record_unaligned_ess(DisasContext *dc, int rd,
                                  MemOp size, bool store)
 {
-    uint32_t iflags = tcg_get_insn_start_param(dc->insn_start, 1);
+    uint32_t iflags = tcg_get_insn_start_param(dc->base.insn_start, 1);
 
     iflags |= ESR_ESS_FLAG;
     iflags |= rd << 5;
     iflags |= store * ESR_S;
     iflags |= (size == MO_32) * ESR_W;
 
-    tcg_set_insn_start_param(dc->insn_start, 1, iflags);
+    tcg_set_insn_start_param(dc->base.insn_start, 1, iflags);
 }
 #endif
 
@@ -1624,7 +1621,6 @@ static void mb_tr_insn_start(DisasContextBase *dcb, CPUState *cs)
     DisasContext *dc = container_of(dcb, DisasContext, base);
 
     tcg_gen_insn_start(dc->base.pc_next, dc->tb_flags & ~MSR_TB_MASK);
-    dc->insn_start = tcg_last_op();
 }
 
 static void mb_tr_translate_insn(DisasContextBase *dcb, CPUState *cs)
-- 
2.34.1



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

* [PATCH 7/9] target/riscv: Use insn_start from DisasContextBase
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
                   ` (5 preceding siblings ...)
  2024-04-06 22:32 ` [PATCH 6/9] target/microblaze: Use insn_start from DisasContextBase Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:17   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 8/9] target/s390x: " Richard Henderson
  2024-04-06 22:32 ` [PATCH 9/9] accel/tcg: Improve can_do_io management Richard Henderson
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

To keep the multiple update check, replace insn_start
with insn_start_updated.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/riscv/translate.c | 11 +++++------
 1 file changed, 5 insertions(+), 6 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 9d57089fcc..9ff09ebdb6 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -115,8 +115,7 @@ typedef struct DisasContext {
     bool itrigger;
     /* FRM is known to contain a valid value. */
     bool frm_valid;
-    /* TCG of the current insn_start */
-    TCGOp *insn_start;
+    bool insn_start_updated;
 } DisasContext;
 
 static inline bool has_ext(DisasContext *ctx, uint32_t ext)
@@ -207,9 +206,9 @@ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
 
 static void decode_save_opc(DisasContext *ctx)
 {
-    assert(ctx->insn_start != NULL);
-    tcg_set_insn_start_param(ctx->insn_start, 1, ctx->opcode);
-    ctx->insn_start = NULL;
+    assert(!ctx->insn_start_updated);
+    ctx->insn_start_updated = true;
+    tcg_set_insn_start_param(ctx->base.insn_start, 1, ctx->opcode);
 }
 
 static void gen_pc_plus_diff(TCGv target, DisasContext *ctx,
@@ -1224,7 +1223,7 @@ static void riscv_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
     }
 
     tcg_gen_insn_start(pc_next, 0);
-    ctx->insn_start = tcg_last_op();
+    ctx->insn_start_updated = false;
 }
 
 static void riscv_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
-- 
2.34.1



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

* [PATCH 8/9] target/s390x: Use insn_start from DisasContextBase
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
                   ` (6 preceding siblings ...)
  2024-04-06 22:32 ` [PATCH 7/9] target/riscv: " Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:18   ` Philippe Mathieu-Daudé
  2024-04-06 22:32 ` [PATCH 9/9] accel/tcg: Improve can_do_io management Richard Henderson
  8 siblings, 1 reply; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 target/s390x/tcg/translate.c | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/target/s390x/tcg/translate.c b/target/s390x/tcg/translate.c
index 57b7db1ee9..90a74ee795 100644
--- a/target/s390x/tcg/translate.c
+++ b/target/s390x/tcg/translate.c
@@ -141,7 +141,6 @@ struct DisasFields {
 struct DisasContext {
     DisasContextBase base;
     const DisasInsn *insn;
-    TCGOp *insn_start;
     DisasFields fields;
     uint64_t ex_value;
     /*
@@ -6314,7 +6313,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
     insn = extract_insn(env, s);
 
     /* Update insn_start now that we know the ILEN.  */
-    tcg_set_insn_start_param(s->insn_start, 2, s->ilen);
+    tcg_set_insn_start_param(s->base.insn_start, 2, s->ilen);
 
     /* Not found means unimplemented/illegal opcode.  */
     if (insn == NULL) {
@@ -6468,7 +6467,6 @@ static void s390x_tr_insn_start(DisasContextBase *dcbase, CPUState *cs)
 
     /* Delay the set of ilen until we've read the insn. */
     tcg_gen_insn_start(dc->base.pc_next, dc->cc_op, 0);
-    dc->insn_start = tcg_last_op();
 }
 
 static target_ulong get_next_pc(CPUS390XState *env, DisasContext *s,
-- 
2.34.1



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

* [PATCH 9/9] accel/tcg: Improve can_do_io management
  2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
                   ` (7 preceding siblings ...)
  2024-04-06 22:32 ` [PATCH 8/9] target/s390x: " Richard Henderson
@ 2024-04-06 22:32 ` Richard Henderson
  2024-04-08  6:25   ` Philippe Mathieu-Daudé
                     ` (2 more replies)
  8 siblings, 3 replies; 22+ messages in thread
From: Richard Henderson @ 2024-04-06 22:32 UTC (permalink / raw)
  To: qemu-devel; +Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

We already attempted to set and clear can_do_io before the first
and last insns, but only used the initial value of max_insns and
the call to translator_io_start to find those insns.

Now that we track insn_start in DisasContextBase, and now that
we have emit_before_op, we can wait until we have finished
translation to identify the true first and last insns and emit
the sets of can_do_io at that time.

This fixes case of a translation block which crossed a page boundary,
and for which the second page turned out to be mmio.  In this case we
truncate the block, and the previous logic for can_do_io could leave
a block with a single insn with can_do_io set to false, which would
fail an assertion in cpu_io_recompile.

Reported-by: Jørgen Hansen <Jorgen.Hansen@wdc.com>
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 include/exec/translator.h |  1 -
 accel/tcg/translator.c    | 45 ++++++++++++++++++++-------------------
 2 files changed, 23 insertions(+), 23 deletions(-)

diff --git a/include/exec/translator.h b/include/exec/translator.h
index ceaeca8c91..2c4fb818e7 100644
--- a/include/exec/translator.h
+++ b/include/exec/translator.h
@@ -87,7 +87,6 @@ typedef struct DisasContextBase {
     int num_insns;
     int max_insns;
     bool singlestep_enabled;
-    int8_t saved_can_do_io;
     bool plugin_enabled;
     struct TCGOp *insn_start;
     void *host_addr[2];
diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
index ae61c154c2..9de0bc34c8 100644
--- a/accel/tcg/translator.c
+++ b/accel/tcg/translator.c
@@ -18,20 +18,14 @@
 
 static void set_can_do_io(DisasContextBase *db, bool val)
 {
-    if (db->saved_can_do_io != val) {
-        db->saved_can_do_io = val;
-
-        QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
-        tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
-                        offsetof(ArchCPU, parent_obj.neg.can_do_io) -
-                        offsetof(ArchCPU, env));
-    }
+    QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
+    tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
+                    offsetof(ArchCPU, parent_obj.neg.can_do_io) -
+                    offsetof(ArchCPU, env));
 }
 
 bool translator_io_start(DisasContextBase *db)
 {
-    set_can_do_io(db, true);
-
     /*
      * Ensure that this instruction will be the last in the TB.
      * The target may override this to something more forceful.
@@ -84,13 +78,6 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
                          - offsetof(ArchCPU, env));
     }
 
-    /*
-     * cpu->neg.can_do_io is set automatically here at the beginning of
-     * each translation block.  The cost is minimal, plus it would be
-     * very easy to forget doing it in the translator.
-     */
-    set_can_do_io(db, db->max_insns == 1);
-
     return icount_start_insn;
 }
 
@@ -129,6 +116,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
 {
     uint32_t cflags = tb_cflags(tb);
     TCGOp *icount_start_insn;
+    TCGOp *first_insn_start = NULL;
     bool plugin_enabled;
 
     /* Initialize DisasContext */
@@ -139,7 +127,6 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     db->num_insns = 0;
     db->max_insns = *max_insns;
     db->singlestep_enabled = cflags & CF_SINGLE_STEP;
-    db->saved_can_do_io = -1;
     db->insn_start = NULL;
     db->host_addr[0] = host_pc;
     db->host_addr[1] = NULL;
@@ -159,6 +146,9 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
         *max_insns = ++db->num_insns;
         ops->insn_start(db, cpu);
         db->insn_start = tcg_last_op();
+        if (first_insn_start == NULL) {
+            first_insn_start = db->insn_start;
+        }
         tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
 
         if (plugin_enabled) {
@@ -171,10 +161,6 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
          * done next -- either exiting this loop or locate the start of
          * the next instruction.
          */
-        if (db->num_insns == db->max_insns) {
-            /* Accept I/O on the last instruction.  */
-            set_can_do_io(db, true);
-        }
         ops->translate_insn(db, cpu);
 
         /*
@@ -207,6 +193,21 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
     ops->tb_stop(db, cpu);
     gen_tb_end(tb, cflags, icount_start_insn, db->num_insns);
 
+    /*
+     * Manage can_do_io for the translation block: set to false before
+     * the first insn and set to true before the last insn.
+     */
+    if (db->num_insns == 1) {
+        tcg_debug_assert(first_insn_start == db->insn_start);
+    } else {
+        tcg_debug_assert(first_insn_start != db->insn_start);
+        tcg_ctx->emit_before_op = first_insn_start;
+        set_can_do_io(db, false);
+    }
+    tcg_ctx->emit_before_op = db->insn_start;
+    set_can_do_io(db, true);
+    tcg_ctx->emit_before_op = NULL;
+
     if (plugin_enabled) {
         plugin_gen_tb_end(cpu, db->num_insns);
     }
-- 
2.34.1



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

* Re: [PATCH 1/9] tcg: Add TCGContext.emit_before_op
  2024-04-06 22:32 ` [PATCH 1/9] tcg: Add TCGContext.emit_before_op Richard Henderson
@ 2024-04-08  6:13   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:13 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl,
	Pierrick Bouvier

On 7/4/24 00:32, Richard Henderson wrote:
> Allow operations to be emitted via normal expanders
> into the middle of the opcode stream.
> 
> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@linaro.org>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/tcg/tcg.h |  6 ++++++
>   tcg/tcg.c         | 14 ++++++++++++--
>   2 files changed, 18 insertions(+), 2 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 3/9] target/arm: Use insn_start from DisasContextBase
  2024-04-06 22:32 ` [PATCH 3/9] target/arm: Use insn_start from DisasContextBase Richard Henderson
@ 2024-04-08  6:16   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:16 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> To keep the multiple update check, replace insn_start
> with insn_start_updated.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/arm/tcg/translate.h     | 12 ++++++------
>   target/arm/tcg/translate-a64.c |  2 +-
>   target/arm/tcg/translate.c     |  2 +-
>   3 files changed, 8 insertions(+), 8 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 4/9] target/hppa: Use insn_start from DisasContextBase
  2024-04-06 22:32 ` [PATCH 4/9] target/hppa: " Richard Henderson
@ 2024-04-08  6:17   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:17 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> To keep the multiple update check, replace insn_start
> with insn_start_updated.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/hppa/translate.c | 10 +++++-----
>   1 file changed, 5 insertions(+), 5 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 6/9] target/microblaze: Use insn_start from DisasContextBase
  2024-04-06 22:32 ` [PATCH 6/9] target/microblaze: Use insn_start from DisasContextBase Richard Henderson
@ 2024-04-08  6:17   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:17 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/microblaze/translate.c | 8 ++------
>   1 file changed, 2 insertions(+), 6 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 7/9] target/riscv: Use insn_start from DisasContextBase
  2024-04-06 22:32 ` [PATCH 7/9] target/riscv: " Richard Henderson
@ 2024-04-08  6:17   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:17 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> To keep the multiple update check, replace insn_start
> with insn_start_updated.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/riscv/translate.c | 11 +++++------
>   1 file changed, 5 insertions(+), 6 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 8/9] target/s390x: Use insn_start from DisasContextBase
  2024-04-06 22:32 ` [PATCH 8/9] target/s390x: " Richard Henderson
@ 2024-04-08  6:18   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:18 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/s390x/tcg/translate.c | 4 +---
>   1 file changed, 1 insertion(+), 3 deletions(-)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 2/9] accel/tcg: Add insn_start to DisasContextBase
  2024-04-06 22:32 ` [PATCH 2/9] accel/tcg: Add insn_start to DisasContextBase Richard Henderson
@ 2024-04-08  6:18   ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:18 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> This is currently target-specific for many; begin making it
> target independent.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/exec/translator.h | 3 +++
>   accel/tcg/translator.c    | 2 ++
>   2 files changed, 5 insertions(+)

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 9/9] accel/tcg: Improve can_do_io management
  2024-04-06 22:32 ` [PATCH 9/9] accel/tcg: Improve can_do_io management Richard Henderson
@ 2024-04-08  6:25   ` Philippe Mathieu-Daudé
  2024-04-08 13:13   ` Jørgen Hansen
  2024-04-09 23:03   ` Gregory Price
  2 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-08  6:25 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> We already attempted to set and clear can_do_io before the first
> and last insns, but only used the initial value of max_insns and
> the call to translator_io_start to find those insns.
> 
> Now that we track insn_start in DisasContextBase, and now that
> we have emit_before_op, we can wait until we have finished
> translation to identify the true first and last insns and emit
> the sets of can_do_io at that time.
> 
> This fixes case of a translation block which crossed a page boundary,
> and for which the second page turned out to be mmio.  In this case we
> truncate the block, and the previous logic for can_do_io could leave
> a block with a single insn with can_do_io set to false, which would
> fail an assertion in cpu_io_recompile.
> 
> Reported-by: Jørgen Hansen <Jorgen.Hansen@wdc.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/exec/translator.h |  1 -
>   accel/tcg/translator.c    | 45 ++++++++++++++++++++-------------------
>   2 files changed, 23 insertions(+), 23 deletions(-)

Nice!

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 9/9] accel/tcg: Improve can_do_io management
  2024-04-06 22:32 ` [PATCH 9/9] accel/tcg: Improve can_do_io management Richard Henderson
  2024-04-08  6:25   ` Philippe Mathieu-Daudé
@ 2024-04-08 13:13   ` Jørgen Hansen
  2024-04-09 23:03   ` Gregory Price
  2 siblings, 0 replies; 22+ messages in thread
From: Jørgen Hansen @ 2024-04-08 13:13 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel@nongnu.org
  Cc: peter.maydell@linaro.org, Jonathan.Cameron@huawei.com,
	linux-cxl@vger.kernel.org

On 4/7/24 00:32, Richard Henderson wrote:
> We already attempted to set and clear can_do_io before the first
> and last insns, but only used the initial value of max_insns and
> the call to translator_io_start to find those insns.
> 
> Now that we track insn_start in DisasContextBase, and now that
> we have emit_before_op, we can wait until we have finished
> translation to identify the true first and last insns and emit
> the sets of can_do_io at that time.
> 
> This fixes case of a translation block which crossed a page boundary,
> and for which the second page turned out to be mmio.  In this case we
> truncate the block, and the previous logic for can_do_io could leave
> a block with a single insn with can_do_io set to false, which would
> fail an assertion in cpu_io_recompile.
> 
> Reported-by: Jørgen Hansen <Jorgen.Hansen@wdc.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   include/exec/translator.h |  1 -
>   accel/tcg/translator.c    | 45 ++++++++++++++++++++-------------------
>   2 files changed, 23 insertions(+), 23 deletions(-)

Thanks for the quick fix! I verified the patch series fixes the issue on 
my setup, and also verified that no issues were seen with full MMIO 
backing for the otherwise same test case.

Tested-by: Jørgen Hansen <Jorgen.Hansen@wdc.com>

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

* Re: [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind
  2024-04-06 22:32 ` [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind Richard Henderson
@ 2024-04-09 15:23   ` Philippe Mathieu-Daudé
  2024-04-09 15:28     ` Philippe Mathieu-Daudé
  0 siblings, 1 reply; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 15:23 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 7/4/24 00:32, Richard Henderson wrote:
> When aborting translation of the current insn, restore the
> previous value of insn_start.
> 
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>   target/i386/tcg/translate.c | 3 +++
>   1 file changed, 3 insertions(+)


> @@ -3123,6 +3124,7 @@ static bool disas_insn(DisasContext *s, CPUState *cpu)
>           /* END TODO */
>           s->base.num_insns--;
>           tcg_remove_ops_after(s->prev_insn_end);
> +        s->base.insn_start = s->prev_insn_start;
>           s->base.is_jmp = DISAS_TOO_MANY;
>           return false;
>       default:
> @@ -6995,6 +6997,7 @@ static void i386_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
>       DisasContext *dc = container_of(dcbase, DisasContext, base);
>       target_ulong pc_arg = dc->base.pc_next;
>   
> +    dc->prev_insn_start = dc->base.insn_start;
>       dc->prev_insn_end = tcg_last_op();
>       if (tb_cflags(dcbase->tb) & CF_PCREL) {
>           pc_arg &= ~TARGET_PAGE_MASK;

Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>



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

* Re: [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind
  2024-04-09 15:23   ` Philippe Mathieu-Daudé
@ 2024-04-09 15:28     ` Philippe Mathieu-Daudé
  0 siblings, 0 replies; 22+ messages in thread
From: Philippe Mathieu-Daudé @ 2024-04-09 15:28 UTC (permalink / raw)
  To: Richard Henderson, qemu-devel
  Cc: peter.maydell, Jorgen.Hansen, Jonathan.Cameron, linux-cxl

On 9/4/24 17:23, Philippe Mathieu-Daudé wrote:
> On 7/4/24 00:32, Richard Henderson wrote:
>> When aborting translation of the current insn, restore the
>> previous value of insn_start.
>>
>> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
>> ---
>>   target/i386/tcg/translate.c | 3 +++
>>   1 file changed, 3 insertions(+)
> 
> 
>> @@ -3123,6 +3124,7 @@ static bool disas_insn(DisasContext *s, CPUState 
>> *cpu)
>>           /* END TODO */
>>           s->base.num_insns--;
>>           tcg_remove_ops_after(s->prev_insn_end);
>> +        s->base.insn_start = s->prev_insn_start;
>>           s->base.is_jmp = DISAS_TOO_MANY;
>>           return false;
>>       default:
>> @@ -6995,6 +6997,7 @@ static void i386_tr_insn_start(DisasContextBase 
>> *dcbase, CPUState *cpu)
>>       DisasContext *dc = container_of(dcbase, DisasContext, base);
>>       target_ulong pc_arg = dc->base.pc_next;
>> +    dc->prev_insn_start = dc->base.insn_start;
>>       dc->prev_insn_end = tcg_last_op();
>>       if (tb_cflags(dcbase->tb) & CF_PCREL) {
>>           pc_arg &= ~TARGET_PAGE_MASK;
> 
> Reviewed-by: Philippe Mathieu-Daudé <philmd@linaro.org>

And:
Tested-by: Jørgen Hansen <Jorgen.Hansen@wdc.com>
(also to patches 1 & 2)

:)


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

* Re: [PATCH 9/9] accel/tcg: Improve can_do_io management
  2024-04-06 22:32 ` [PATCH 9/9] accel/tcg: Improve can_do_io management Richard Henderson
  2024-04-08  6:25   ` Philippe Mathieu-Daudé
  2024-04-08 13:13   ` Jørgen Hansen
@ 2024-04-09 23:03   ` Gregory Price
  2 siblings, 0 replies; 22+ messages in thread
From: Gregory Price @ 2024-04-09 23:03 UTC (permalink / raw)
  To: Richard Henderson
  Cc: qemu-devel, peter.maydell, Jorgen.Hansen, Jonathan.Cameron,
	linux-cxl

On Sat, Apr 06, 2024 at 12:32:48PM -1000, Richard Henderson wrote:
> We already attempted to set and clear can_do_io before the first
> and last insns, but only used the initial value of max_insns and
> the call to translator_io_start to find those insns.
> 
> Now that we track insn_start in DisasContextBase, and now that
> we have emit_before_op, we can wait until we have finished
> translation to identify the true first and last insns and emit
> the sets of can_do_io at that time.
> 
> This fixes case of a translation block which crossed a page boundary,
> and for which the second page turned out to be mmio.

I love when I get to say this: I knew it! :D

https://lore.kernel.org/qemu-devel/ZbvVB4J+AHkLNuE2@memverge.com/

Great fix, much appreciate the effort!

Reviewed-by: Gregory Price <gregory.price@memverge.com>

> In this case we
> truncate the block, and the previous logic for can_do_io could leave
> a block with a single insn with can_do_io set to false, which would
> fail an assertion in cpu_io_recompile.
> 
> Reported-by: Jørgen Hansen <Jorgen.Hansen@wdc.com>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
>  include/exec/translator.h |  1 -
>  accel/tcg/translator.c    | 45 ++++++++++++++++++++-------------------
>  2 files changed, 23 insertions(+), 23 deletions(-)
> 
> diff --git a/include/exec/translator.h b/include/exec/translator.h
> index ceaeca8c91..2c4fb818e7 100644
> --- a/include/exec/translator.h
> +++ b/include/exec/translator.h
> @@ -87,7 +87,6 @@ typedef struct DisasContextBase {
>      int num_insns;
>      int max_insns;
>      bool singlestep_enabled;
> -    int8_t saved_can_do_io;
>      bool plugin_enabled;
>      struct TCGOp *insn_start;
>      void *host_addr[2];
> diff --git a/accel/tcg/translator.c b/accel/tcg/translator.c
> index ae61c154c2..9de0bc34c8 100644
> --- a/accel/tcg/translator.c
> +++ b/accel/tcg/translator.c
> @@ -18,20 +18,14 @@
>  
>  static void set_can_do_io(DisasContextBase *db, bool val)
>  {
> -    if (db->saved_can_do_io != val) {
> -        db->saved_can_do_io = val;
> -
> -        QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
> -        tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
> -                        offsetof(ArchCPU, parent_obj.neg.can_do_io) -
> -                        offsetof(ArchCPU, env));
> -    }
> +    QEMU_BUILD_BUG_ON(sizeof_field(CPUState, neg.can_do_io) != 1);
> +    tcg_gen_st8_i32(tcg_constant_i32(val), tcg_env,
> +                    offsetof(ArchCPU, parent_obj.neg.can_do_io) -
> +                    offsetof(ArchCPU, env));
>  }
>  
>  bool translator_io_start(DisasContextBase *db)
>  {
> -    set_can_do_io(db, true);
> -
>      /*
>       * Ensure that this instruction will be the last in the TB.
>       * The target may override this to something more forceful.
> @@ -84,13 +78,6 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
>                           - offsetof(ArchCPU, env));
>      }
>  
> -    /*
> -     * cpu->neg.can_do_io is set automatically here at the beginning of
> -     * each translation block.  The cost is minimal, plus it would be
> -     * very easy to forget doing it in the translator.
> -     */
> -    set_can_do_io(db, db->max_insns == 1);
> -
>      return icount_start_insn;
>  }
>  
> @@ -129,6 +116,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
>  {
>      uint32_t cflags = tb_cflags(tb);
>      TCGOp *icount_start_insn;
> +    TCGOp *first_insn_start = NULL;
>      bool plugin_enabled;
>  
>      /* Initialize DisasContext */
> @@ -139,7 +127,6 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
>      db->num_insns = 0;
>      db->max_insns = *max_insns;
>      db->singlestep_enabled = cflags & CF_SINGLE_STEP;
> -    db->saved_can_do_io = -1;
>      db->insn_start = NULL;
>      db->host_addr[0] = host_pc;
>      db->host_addr[1] = NULL;
> @@ -159,6 +146,9 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
>          *max_insns = ++db->num_insns;
>          ops->insn_start(db, cpu);
>          db->insn_start = tcg_last_op();
> +        if (first_insn_start == NULL) {
> +            first_insn_start = db->insn_start;
> +        }
>          tcg_debug_assert(db->is_jmp == DISAS_NEXT);  /* no early exit */
>  
>          if (plugin_enabled) {
> @@ -171,10 +161,6 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
>           * done next -- either exiting this loop or locate the start of
>           * the next instruction.
>           */
> -        if (db->num_insns == db->max_insns) {
> -            /* Accept I/O on the last instruction.  */
> -            set_can_do_io(db, true);
> -        }
>          ops->translate_insn(db, cpu);
>  
>          /*
> @@ -207,6 +193,21 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
>      ops->tb_stop(db, cpu);
>      gen_tb_end(tb, cflags, icount_start_insn, db->num_insns);
>  
> +    /*
> +     * Manage can_do_io for the translation block: set to false before
> +     * the first insn and set to true before the last insn.
> +     */
> +    if (db->num_insns == 1) {
> +        tcg_debug_assert(first_insn_start == db->insn_start);
> +    } else {
> +        tcg_debug_assert(first_insn_start != db->insn_start);
> +        tcg_ctx->emit_before_op = first_insn_start;
> +        set_can_do_io(db, false);
> +    }
> +    tcg_ctx->emit_before_op = db->insn_start;
> +    set_can_do_io(db, true);
> +    tcg_ctx->emit_before_op = NULL;
> +
>      if (plugin_enabled) {
>          plugin_gen_tb_end(cpu, db->num_insns);
>      }
> -- 
> 2.34.1
> 
> 


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

end of thread, other threads:[~2024-04-09 23:09 UTC | newest]

Thread overview: 22+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-04-06 22:32 [PATCH for-9.0? 0/9] accel/tcg: Fix can_do_io vs 2nd page mmio Richard Henderson
2024-04-06 22:32 ` [PATCH 1/9] tcg: Add TCGContext.emit_before_op Richard Henderson
2024-04-08  6:13   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 2/9] accel/tcg: Add insn_start to DisasContextBase Richard Henderson
2024-04-08  6:18   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 3/9] target/arm: Use insn_start from DisasContextBase Richard Henderson
2024-04-08  6:16   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 4/9] target/hppa: " Richard Henderson
2024-04-08  6:17   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 5/9] target/i386: Preserve DisasContextBase.insn_start across rewind Richard Henderson
2024-04-09 15:23   ` Philippe Mathieu-Daudé
2024-04-09 15:28     ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 6/9] target/microblaze: Use insn_start from DisasContextBase Richard Henderson
2024-04-08  6:17   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 7/9] target/riscv: " Richard Henderson
2024-04-08  6:17   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 8/9] target/s390x: " Richard Henderson
2024-04-08  6:18   ` Philippe Mathieu-Daudé
2024-04-06 22:32 ` [PATCH 9/9] accel/tcg: Improve can_do_io management Richard Henderson
2024-04-08  6:25   ` Philippe Mathieu-Daudé
2024-04-08 13:13   ` Jørgen Hansen
2024-04-09 23:03   ` Gregory Price

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