45e84a0
From abf80f880410ebbdd01a289c41c87153802fe900 Mon Sep 17 00:00:00 2001
45e84a0
From: Andreas Gustafsson <gson@gson.org>
45e84a0
Date: Mon, 12 Dec 2011 00:46:32 +0400
45e84a0
Subject: [PATCH 10/25] target-i386: fix cmpxchg instruction emulation
45e84a0
45e84a0
When the i386 cmpxchg instruction is executed with a memory operand
45e84a0
and the comparison result is "unequal", do the memory write before
45e84a0
changing the accumulator instead of the other way around, because
45e84a0
otherwise the new accumulator value will incorrectly be used in the
45e84a0
comparison when the instruction is restarted after a page fault.
45e84a0
45e84a0
This bug was originally reported on 2010-04-25 as
45e84a0
https://bugs.launchpad.net/qemu/+bug/569760
45e84a0
45e84a0
Signed-off-by: Andreas Gustafsson <gson@gson.org>
45e84a0
---
45e84a0
 target-i386/translate.c |   11 +++++++----
45e84a0
 1 files changed, 7 insertions(+), 4 deletions(-)
45e84a0
45e84a0
diff --git a/target-i386/translate.c b/target-i386/translate.c
45e84a0
index 1ef8d16..8321bf3 100644
45e84a0
--- a/target-i386/translate.c
45e84a0
+++ b/target-i386/translate.c
45e84a0
@@ -4870,20 +4870,23 @@ static target_ulong disas_insn(DisasContext *s, target_ulong pc_start)
45e84a0
             tcg_gen_sub_tl(t2, cpu_regs[R_EAX], t0);
45e84a0
             gen_extu(ot, t2);
45e84a0
             tcg_gen_brcondi_tl(TCG_COND_EQ, t2, 0, label1);
45e84a0
+            label2 = gen_new_label();
45e84a0
             if (mod == 3) {
45e84a0
-                label2 = gen_new_label();
45e84a0
                 gen_op_mov_reg_v(ot, R_EAX, t0);
45e84a0
                 tcg_gen_br(label2);
45e84a0
                 gen_set_label(label1);
45e84a0
                 gen_op_mov_reg_v(ot, rm, t1);
45e84a0
-                gen_set_label(label2);
45e84a0
             } else {
45e84a0
-                tcg_gen_mov_tl(t1, t0);
45e84a0
+                /* perform no-op store cycle like physical cpu; must be
45e84a0
+                   before changing accumulator to ensure idempotency if
45e84a0
+                   the store faults and the instruction is restarted */
45e84a0
+                gen_op_st_v(ot + s->mem_index, t0, a0);
45e84a0
                 gen_op_mov_reg_v(ot, R_EAX, t0);
45e84a0
+                tcg_gen_br(label2);
45e84a0
                 gen_set_label(label1);
45e84a0
-                /* always store */
45e84a0
                 gen_op_st_v(ot + s->mem_index, t1, a0);
45e84a0
             }
45e84a0
+            gen_set_label(label2);
45e84a0
             tcg_gen_mov_tl(cpu_cc_src, t0);
45e84a0
             tcg_gen_mov_tl(cpu_cc_dst, t2);
45e84a0
             s->cc_op = CC_OP_SUBB + ot;
45e84a0
-- 
45e84a0
1.7.7.5
45e84a0