accel/tcg: Remove CF_LAST_IO
In cpu_exec_step_atomic, we did not set CF_LAST_IO, which lead
to a loop with cpu_io_recompile.
But since 18a536f1f8
("Always require can_do_io") we no longer
need a flag to indicate when the last insn should have can_do_io set,
so remove the flag entirely.
Reported-by: Clément Chigot <chigot@adacore.com>
Tested-by: Clément Chigot <chigot@adacore.com>
Reviewed-by: Claudio Fontana <cfontana@suse.de>
Resolves: https://gitlab.com/qemu-project/qemu/-/issues/1961
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
6d44474b3b
commit
cf9b5790db
@ -721,7 +721,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||
&& cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||
/* Execute just one insn to trigger exception pending in the log */
|
||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
||||
| CF_LAST_IO | CF_NOIRQ | 1;
|
||||
| CF_NOIRQ | 1;
|
||||
}
|
||||
#endif
|
||||
return false;
|
||||
|
@ -1083,8 +1083,7 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
|
||||
if (current_tb_modified) {
|
||||
/* Force execution of one insn next time. */
|
||||
CPUState *cpu = current_cpu;
|
||||
cpu->cflags_next_tb =
|
||||
1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@ -1154,8 +1153,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||
if (current_tb_modified) {
|
||||
page_collection_unlock(pages);
|
||||
/* Force execution of one insn next time. */
|
||||
current_cpu->cflags_next_tb =
|
||||
1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
current_cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
|
||||
mmap_unlock();
|
||||
cpu_loop_exit_noexc(current_cpu);
|
||||
}
|
||||
|
@ -304,7 +304,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||
|
||||
if (phys_pc == -1) {
|
||||
/* Generate a one-shot TB with 1 insn in it */
|
||||
cflags = (cflags & ~CF_COUNT_MASK) | CF_LAST_IO | 1;
|
||||
cflags = (cflags & ~CF_COUNT_MASK) | 1;
|
||||
}
|
||||
|
||||
max_insns = cflags & CF_COUNT_MASK;
|
||||
@ -632,7 +632,7 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
|
||||
* operations only (which execute after completion) so we don't
|
||||
* double instrument the instruction.
|
||||
*/
|
||||
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | CF_LAST_IO | n;
|
||||
cpu->cflags_next_tb = curr_cflags(cpu) | CF_MEMI_ONLY | n;
|
||||
|
||||
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||
vaddr pc = log_pc(cpu, tb);
|
||||
|
@ -89,7 +89,7 @@ static TCGOp *gen_tb_start(DisasContextBase *db, uint32_t cflags)
|
||||
* 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 && (cflags & CF_LAST_IO));
|
||||
set_can_do_io(db, db->max_insns == 1);
|
||||
|
||||
return icount_start_insn;
|
||||
}
|
||||
@ -151,13 +151,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
ops->tb_start(db, cpu);
|
||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||
|
||||
if (cflags & CF_MEMI_ONLY) {
|
||||
/* We should only see CF_MEMI_ONLY for io_recompile. */
|
||||
assert(cflags & CF_LAST_IO);
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, true);
|
||||
} else {
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, false);
|
||||
}
|
||||
plugin_enabled = plugin_gen_tb_start(cpu, db, cflags & CF_MEMI_ONLY);
|
||||
db->plugin_enabled = plugin_enabled;
|
||||
|
||||
while (true) {
|
||||
@ -169,11 +163,13 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||
plugin_gen_insn_start(cpu, db);
|
||||
}
|
||||
|
||||
/* Disassemble one instruction. The translate_insn hook should
|
||||
update db->pc_next and db->is_jmp to indicate what should be
|
||||
done next -- either exiting this loop or locate the start of
|
||||
the next instruction. */
|
||||
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
|
||||
/*
|
||||
* Disassemble one instruction. The translate_insn hook should
|
||||
* update db->pc_next and db->is_jmp to indicate what should be
|
||||
* 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);
|
||||
}
|
||||
|
@ -62,12 +62,6 @@ To deal with this case, when an I/O access is made we:
|
||||
- re-compile a single [1]_ instruction block for the current PC
|
||||
- exit the cpu loop and execute the re-compiled block
|
||||
|
||||
The new block is created with the CF_LAST_IO compile flag which
|
||||
ensures the final instruction translation starts with a call to
|
||||
gen_io_start() so we don't enter a perpetual loop constantly
|
||||
recompiling a single instruction block. For translators using the
|
||||
common translator_loop this is done automatically.
|
||||
|
||||
.. [1] sometimes two instructions if dealing with delay slots
|
||||
|
||||
Other I/O operations
|
||||
|
@ -71,13 +71,12 @@ struct TranslationBlock {
|
||||
#define CF_NO_GOTO_TB 0x00000200 /* Do not chain with goto_tb */
|
||||
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
|
||||
#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */
|
||||
#define CF_LAST_IO 0x00008000 /* Last insn may be an IO access. */
|
||||
#define CF_MEMI_ONLY 0x00010000 /* Only instrument memory ops */
|
||||
#define CF_USE_ICOUNT 0x00020000
|
||||
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
|
||||
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
|
||||
#define CF_NOIRQ 0x00100000 /* Generate an uninterruptible TB */
|
||||
#define CF_PCREL 0x00200000 /* Opcodes in TB are PC-relative */
|
||||
#define CF_MEMI_ONLY 0x00001000 /* Only instrument memory ops */
|
||||
#define CF_USE_ICOUNT 0x00002000
|
||||
#define CF_INVALID 0x00004000 /* TB is stale. Set with @jmp_lock held */
|
||||
#define CF_PARALLEL 0x00008000 /* Generate code for a parallel context */
|
||||
#define CF_NOIRQ 0x00010000 /* Generate an uninterruptible TB */
|
||||
#define CF_PCREL 0x00020000 /* Opcodes in TB are PC-relative */
|
||||
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
|
||||
#define CF_CLUSTER_SHIFT 24
|
||||
|
||||
|
@ -179,8 +179,7 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
|
||||
*/
|
||||
if (!cpu->neg.can_do_io) {
|
||||
/* Force execution of one insn next time. */
|
||||
cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ
|
||||
| curr_cflags(cpu);
|
||||
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
|
||||
cpu_loop_exit_restore(cpu, ra);
|
||||
}
|
||||
/*
|
||||
@ -212,8 +211,7 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
|
||||
cpu_loop_exit(cpu);
|
||||
} else {
|
||||
/* Force execution of one insn next time. */
|
||||
cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ
|
||||
| curr_cflags(cpu);
|
||||
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
|
||||
mmap_unlock();
|
||||
cpu_loop_exit_noexc(cpu);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user