diff mbox

-icount changes physical address assignments in QEMU 2.10/2.11

Message ID CAFEAcA9oLqZYhmLcNp6H6e_e-3sh17btZs00oZSJhdwgTd7Y=A@mail.gmail.com (mailing list archive)
State New, archived
Headers show

Commit Message

Peter Maydell April 6, 2018, 4:16 p.m. UTC
On 6 April 2018 at 15:51, Peter Maydell <peter.maydell@linaro.org> wrote:
> On 6 April 2018 at 14:33, Peter Maydell <peter.maydell@linaro.org> wrote:
>> On this end I should try this with a 32-bit Linux host.
> I've now done this, and can reproduce the problem. So the
> issue is generic to 32-bit hosts.
> I'll see if I can figure out what's going wrong.

I've tracked down the issue -- it is with the arm frontend's
handling of the tcg_insn_start parameters. Specifically, we
have a 3-operand tcg_insn_start:
                       (dc->condexec_cond << 4) | (dc->condexec_mask >> 1),
    dc->insn_start = tcg_last_op();

where we patch in the 3rd operand later sometimes in
    tcg_set_insn_param(s->insn_start, 2, syn);

Unfortunately, if we're running on a setup where
on 64 bit host), tcg_gen_insn_start() has under the hood
split the 3 operands we gave it into 6, and so we end
up patching the wrong one.

The effect is that the first time the icount code needs to
call io_recompile, we set condexec_bits to a bogus value
which is also too big for its space in tb_flags and the
CPSR, and execution starts to diverge from there onward.

The following change fixes this:

but I'm not convinced it's the neatest way to do it.

Nobody else plays this game with tcg_set_insn_param() (except
icount, which doesn't do it with target_ulong sized values),
so this bug is specific to the arm target.

Richard: do you have a cleaner suggestion than throwing this
ifdef into the arm code?

-- PMM
diff mbox


diff --git a/target/arm/translate.h b/target/arm/translate.h
index c47febf99d..f04ece9cfd 100644
--- a/target/arm/translate.h
+++ b/target/arm/translate.h
@@ -120,7 +120,15 @@  static inline void
disas_set_insn_syndrome(DisasContext *s, uint32_t syn)

     /* We check and clear insn_start_idx to catch multiple updates.  */
     assert(s->insn_start != NULL);
     tcg_set_insn_param(s->insn_start, 2, syn);
+    /* tcg_gen_insn_start has split every target_ulong argument to
+     * op_insn_start into two 32-bit arguments, so we want the low
+     * half of the 3rd input argument, which is at index 4.
+     */
+    tcg_set_insn_param(s->insn_start, 4, syn);
     s->insn_start = NULL;