mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-09 02:24:58 -06:00
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
7 changed files with 22 additions and 37 deletions
|
@ -721,7 +721,7 @@ static inline bool cpu_handle_exception(CPUState *cpu, int *ret)
|
||||||
&& cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0) {
|
&& cpu->neg.icount_decr.u16.low + cpu->icount_extra == 0) {
|
||||||
/* Execute just one insn to trigger exception pending in the log */
|
/* Execute just one insn to trigger exception pending in the log */
|
||||||
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
cpu->cflags_next_tb = (curr_cflags(cpu) & ~CF_USE_ICOUNT)
|
||||||
| CF_LAST_IO | CF_NOIRQ | 1;
|
| CF_NOIRQ | 1;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -1083,8 +1083,7 @@ bool tb_invalidate_phys_page_unwind(tb_page_addr_t addr, uintptr_t pc)
|
||||||
if (current_tb_modified) {
|
if (current_tb_modified) {
|
||||||
/* Force execution of one insn next time. */
|
/* Force execution of one insn next time. */
|
||||||
CPUState *cpu = current_cpu;
|
CPUState *cpu = current_cpu;
|
||||||
cpu->cflags_next_tb =
|
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
|
||||||
1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -1154,8 +1153,7 @@ tb_invalidate_phys_page_range__locked(struct page_collection *pages,
|
||||||
if (current_tb_modified) {
|
if (current_tb_modified) {
|
||||||
page_collection_unlock(pages);
|
page_collection_unlock(pages);
|
||||||
/* Force execution of one insn next time. */
|
/* Force execution of one insn next time. */
|
||||||
current_cpu->cflags_next_tb =
|
current_cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(current_cpu);
|
||||||
1 | CF_LAST_IO | CF_NOIRQ | curr_cflags(current_cpu);
|
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
cpu_loop_exit_noexc(current_cpu);
|
cpu_loop_exit_noexc(current_cpu);
|
||||||
}
|
}
|
||||||
|
|
|
@ -304,7 +304,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu,
|
||||||
|
|
||||||
if (phys_pc == -1) {
|
if (phys_pc == -1) {
|
||||||
/* Generate a one-shot TB with 1 insn in it */
|
/* 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;
|
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
|
* operations only (which execute after completion) so we don't
|
||||||
* double instrument the instruction.
|
* 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)) {
|
if (qemu_loglevel_mask(CPU_LOG_EXEC)) {
|
||||||
vaddr pc = log_pc(cpu, tb);
|
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
|
* each translation block. The cost is minimal, plus it would be
|
||||||
* very easy to forget doing it in the translator.
|
* 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;
|
return icount_start_insn;
|
||||||
}
|
}
|
||||||
|
@ -151,13 +151,7 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||||
ops->tb_start(db, cpu);
|
ops->tb_start(db, cpu);
|
||||||
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
tcg_debug_assert(db->is_jmp == DISAS_NEXT); /* no early exit */
|
||||||
|
|
||||||
if (cflags & CF_MEMI_ONLY) {
|
plugin_enabled = plugin_gen_tb_start(cpu, db, 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);
|
|
||||||
}
|
|
||||||
db->plugin_enabled = plugin_enabled;
|
db->plugin_enabled = plugin_enabled;
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -169,11 +163,13 @@ void translator_loop(CPUState *cpu, TranslationBlock *tb, int *max_insns,
|
||||||
plugin_gen_insn_start(cpu, db);
|
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
|
* Disassemble one instruction. The translate_insn hook should
|
||||||
done next -- either exiting this loop or locate the start of
|
* update db->pc_next and db->is_jmp to indicate what should be
|
||||||
the next instruction. */
|
* done next -- either exiting this loop or locate the start of
|
||||||
if (db->num_insns == db->max_insns && (cflags & CF_LAST_IO)) {
|
* the next instruction.
|
||||||
|
*/
|
||||||
|
if (db->num_insns == db->max_insns) {
|
||||||
/* Accept I/O on the last instruction. */
|
/* Accept I/O on the last instruction. */
|
||||||
set_can_do_io(db, true);
|
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
|
- re-compile a single [1]_ instruction block for the current PC
|
||||||
- exit the cpu loop and execute the re-compiled block
|
- 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
|
.. [1] sometimes two instructions if dealing with delay slots
|
||||||
|
|
||||||
Other I/O operations
|
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_TB 0x00000200 /* Do not chain with goto_tb */
|
||||||
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
|
#define CF_NO_GOTO_PTR 0x00000400 /* Do not chain with goto_ptr */
|
||||||
#define CF_SINGLE_STEP 0x00000800 /* gdbstub single-step in effect */
|
#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 0x00001000 /* Only instrument memory ops */
|
||||||
#define CF_MEMI_ONLY 0x00010000 /* Only instrument memory ops */
|
#define CF_USE_ICOUNT 0x00002000
|
||||||
#define CF_USE_ICOUNT 0x00020000
|
#define CF_INVALID 0x00004000 /* TB is stale. Set with @jmp_lock held */
|
||||||
#define CF_INVALID 0x00040000 /* TB is stale. Set with @jmp_lock held */
|
#define CF_PARALLEL 0x00008000 /* Generate code for a parallel context */
|
||||||
#define CF_PARALLEL 0x00080000 /* Generate code for a parallel context */
|
#define CF_NOIRQ 0x00010000 /* Generate an uninterruptible TB */
|
||||||
#define CF_NOIRQ 0x00100000 /* Generate an uninterruptible TB */
|
#define CF_PCREL 0x00020000 /* Opcodes in TB are PC-relative */
|
||||||
#define CF_PCREL 0x00200000 /* Opcodes in TB are PC-relative */
|
|
||||||
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
|
#define CF_CLUSTER_MASK 0xff000000 /* Top 8 bits are cluster ID */
|
||||||
#define CF_CLUSTER_SHIFT 24
|
#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) {
|
if (!cpu->neg.can_do_io) {
|
||||||
/* Force execution of one insn next time. */
|
/* Force execution of one insn next time. */
|
||||||
cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ
|
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
|
||||||
| curr_cflags(cpu);
|
|
||||||
cpu_loop_exit_restore(cpu, ra);
|
cpu_loop_exit_restore(cpu, ra);
|
||||||
}
|
}
|
||||||
/*
|
/*
|
||||||
|
@ -212,8 +211,7 @@ void cpu_check_watchpoint(CPUState *cpu, vaddr addr, vaddr len,
|
||||||
cpu_loop_exit(cpu);
|
cpu_loop_exit(cpu);
|
||||||
} else {
|
} else {
|
||||||
/* Force execution of one insn next time. */
|
/* Force execution of one insn next time. */
|
||||||
cpu->cflags_next_tb = 1 | CF_LAST_IO | CF_NOIRQ
|
cpu->cflags_next_tb = 1 | CF_NOIRQ | curr_cflags(cpu);
|
||||||
| curr_cflags(cpu);
|
|
||||||
mmap_unlock();
|
mmap_unlock();
|
||||||
cpu_loop_exit_noexc(cpu);
|
cpu_loop_exit_noexc(cpu);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue