* [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
* 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
* [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
* 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
* [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
* 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
* [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
* 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
* [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 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 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