The plugin register API reads env->eflags through the gdbstub. During TCG execution, arithmetic flags are kept in the lazy CC state and DF in env->df, so this can return incorrect EFLAGS values.
Add eflags_in_tcg, set on TCG entry and cleared on exit, to select cpu_compute_eflags() while the flags are split. Also synchronize cc_op with gen_update_cc_op() before instruction callbacks when plugins are enabled, since the current value may still be in the translator context. Outside TCG execution, keep reading env->eflags, which holds the complete flags. Unconditional reconstruction can use stale lazy state and break GDB readback: in testing, writing 0x0202 through GDB was followed by a readback of 0x0203. Richard Henderson previously proposed EFLAGS reconstruction and cc_op synchronization for i386 plugin register reads. Link: https://www.mail-archive.com/[email protected]/msg1047061.html Signed-off-by: Artemii Mashanov <[email protected]> --- target/i386/cpu.h | 1 + target/i386/gdbstub.c | 3 +++ target/i386/tcg/tcg-cpu.c | 2 ++ target/i386/tcg/translate.c | 3 +++ 4 files changed, 9 insertions(+) diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 9ce8ca0038..b3b4528ea7 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2347,6 +2347,7 @@ struct ArchCPU { CPUState parent_obj; CPUX86State env; + bool eflags_in_tcg; VMChangeStateEntry *vmsentry; uint64_t ucode_rev; diff --git a/target/i386/gdbstub.c b/target/i386/gdbstub.c index 5c5fa72721..e636ca0f4a 100644 --- a/target/i386/gdbstub.c +++ b/target/i386/gdbstub.c @@ -151,6 +151,9 @@ int x86_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n) case IDX_IP_REG: return gdb_get_reg(env, mem_buf, env->eip); case IDX_FLAGS_REG: + if (cpu->eflags_in_tcg) { + return gdb_get_reg32(mem_buf, cpu_compute_eflags(env)); + } return gdb_get_reg32(mem_buf, env->eflags); case IDX_SEG_REGS: diff --git a/target/i386/tcg/tcg-cpu.c b/target/i386/tcg/tcg-cpu.c index 6f5dc06b3b..2402608fe9 100644 --- a/target/i386/tcg/tcg-cpu.c +++ b/target/i386/tcg/tcg-cpu.c @@ -38,6 +38,7 @@ static void x86_cpu_exec_enter(CPUState *cs) env->df = 1 - (2 * ((env->eflags >> 10) & 1)); CC_OP = CC_OP_EFLAGS; env->eflags &= ~(DF_MASK | CC_O | CC_S | CC_Z | CC_A | CC_P | CC_C); + cpu->eflags_in_tcg = true; } static void x86_cpu_exec_exit(CPUState *cs) @@ -46,6 +47,7 @@ static void x86_cpu_exec_exit(CPUState *cs) CPUX86State *env = &cpu->env; env->eflags = cpu_compute_eflags(env); + cpu->eflags_in_tcg = false; } static TCGTBCPUState x86_get_tb_cpu_state(CPUState *cs) diff --git a/target/i386/tcg/translate.c b/target/i386/tcg/translate.c index d8de290acb..c469d74efe 100644 --- a/target/i386/tcg/translate.c +++ b/target/i386/tcg/translate.c @@ -3483,6 +3483,9 @@ 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; + if (dcbase->plugin_enabled) { + gen_update_cc_op(dc); + } dc->prev_insn_start = dc->base.insn_start; dc->prev_insn_end = tcg_last_op(); if (tb_cflags(dcbase->tb) & CF_PCREL) { base-commit: 257bf4f160c50ca8c4ebd603f519f5c786013fb7 -- 2.55.0
