Commit 0790f868 authored by Pavel Dovgalyuk's avatar Pavel Dovgalyuk Committed by Paolo Bonzini
Browse files

tcg: fix cpu_io_recompile



cpu_io_recompile() function was broken by
the commit 9b990ee5. Instead of regenerating
the block starting from PC of the original block, it just set the instruction
counter for TCG. In most cases this was unnoticed, but in icount mode
there was an exception for incorrect usage of CF_LAST_IO flag.
This patch recovers recompilation of the original block and also
configures translation for executing single IO instruction which
caused a recompilation.

Signed-off-by: default avatarPavel Dovgalyuk <pavel.dovgaluk@ispras.ru>
Message-Id: <20180227095338.1060.27385.stgit@pasha-VirtualBox>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
Signed-off-by: default avatarPavel Dovgalyuk <Pavel.Dovgaluk@ispras.ru>
parent 7273db9d
Loading
Loading
Loading
Loading
+15 −3
Original line number Diff line number Diff line
@@ -1728,7 +1728,8 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
    CPUArchState *env = cpu->env_ptr;
#endif
    TranslationBlock *tb;
    uint32_t n;
    uint32_t n, flags;
    target_ulong pc, cs_base;

    tb_lock();
    tb = tb_find_pc(retaddr);
@@ -1766,8 +1767,14 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
        cpu_abort(cpu, "TB too big during recompile");
    }

    /* Adjust the execution state of the next TB.  */
    cpu->cflags_next_tb = curr_cflags() | CF_LAST_IO | n;
    pc = tb->pc;
    cs_base = tb->cs_base;
    flags = tb->flags;
    tb_phys_invalidate(tb, -1);

    /* Execute one IO instruction without caching
       instead of creating large TB. */
    cpu->cflags_next_tb = curr_cflags() | CF_LAST_IO | CF_NOCACHE | 1;

    if (tb->cflags & CF_NOCACHE) {
        if (tb->orig_tb) {
@@ -1778,6 +1785,11 @@ void cpu_io_recompile(CPUState *cpu, uintptr_t retaddr)
        tb_remove(tb);
    }

    /* Generate new TB instead of the current one. */
    /* FIXME: In theory this could raise an exception.  In practice
       we have already translated the block once so it's probably ok.  */
    tb_gen_code(cpu, pc, cs_base, flags, curr_cflags() | CF_LAST_IO | n);

    /* 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.