I'm working with an emulation for a proprietary processor on an older QEMU source base. It looks
like the problem I am seeing in the old sources would still be present in the current source base.
I'm seeing incorrect values when there is a write to a memory-mapped I/O device when icount is set.
What I see happening is that a TB with ~20 instructions is executed which contains a write to the
MM I/O address. When it gets to the io_write routine, can_do_io is false, which results in a call
to cpu_io_recompile.
cpu_io_recompile does what it (sort of) says it is supposed to do: it builds a new TB with the I/O
instruction as the last instruction in the block, then re-issues the TB. The problem is that the
new TB contains the instructions before the I/O instruction, so they are executed a second time.
There is a note in cpu_io_recompile which mentions the situation where the I/O instruction is not
the first in the TB has not been handled:
/* TODO: If env->pc != tb->pc (i.e. the faulting instruction was not
* the first in the TB) then we end up generating a whole new TB and
* repeating the fault, which is horribly inefficient.
* Better would be to execute just this insn uncached, or generate a
* second new TB.
I'm a bit unclear what this is saying. A new TB is generated which is issued setting can_do_io, and
which passes through io_write without a problem. I'm not sure what fault is repeated.
It seems to me that what cpu_io_recompile should do is create a new TB with the n instructions which
were already executed and cache it. Then it should create a TB with only the I/O instruction,
setting can_do_io, and re-issue this TB.
Am I understanding this correctly?
This code has been around for a long, long time. Has anyone noticed this
problem in the past?
--
Michael Eager [email protected]
1960 Park Blvd., Palo Alto, CA 94306 650-325-8077
--
Michael Eager [email protected]
1960 Park Blvd., Palo Alto, CA 94306 650-325-8077