vex: r3316 - in /trunk: priv/guest_mips_defs.h priv/guest_mips_helpers.c priv/guest_mips_toIR.c pub/libvex_guest_mips32.h pub/libvex_guest_mips64.h

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

vex: r3316 - in /trunk: priv/guest_mips_defs.h priv/guest_mips_helpers.c priv/guest_mips_toIR.c pub/libvex_guest_mips32.h pub/libvex_guest_mips64.h

svn-2
Author: petarj
Date: Mon Mar 13 17:50:25 2017
New Revision: 3316

Log:
mips: emulate LL/SC w/ guest_LLaddr and guest_LLdata

Improve LL/SC emulation with introduction of LLaddr and LLdata in the
guest state. LLaddr gets invalidated when the threads switch.

More info at KDE #344524. This patch should fix the issue.

Currently, this is effective for Cavium boards only.

Patch by Maran Pakkirisamy.

Modified:
    trunk/priv/guest_mips_defs.h
    trunk/priv/guest_mips_helpers.c
    trunk/priv/guest_mips_toIR.c
    trunk/pub/libvex_guest_mips32.h
    trunk/pub/libvex_guest_mips64.h

Modified: trunk/priv/guest_mips_defs.h
==============================================================================
--- trunk/priv/guest_mips_defs.h (original)
+++ trunk/priv/guest_mips_defs.h Mon Mar 13 17:50:25 2017
@@ -94,6 +94,12 @@
    SUBS,     SUBD,    DIVS
 } flt_op;
 
+#if defined (_MIPSEL)
+   #define MIPS_IEND Iend_LE
+#else
+   #define MIPS_IEND Iend_BE
+#endif
+
 #if defined(__mips__) && ((defined(__mips_isa_rev) && __mips_isa_rev >= 2))
 extern UInt mips32_dirtyhelper_rdhwr ( UInt rt, UInt rd );
 extern ULong mips64_dirtyhelper_rdhwr ( ULong rt, ULong rd );

Modified: trunk/priv/guest_mips_helpers.c
==============================================================================
--- trunk/priv/guest_mips_helpers.c (original)
+++ trunk/priv/guest_mips_helpers.c Mon Mar 13 17:50:25 2017
@@ -167,6 +167,9 @@
 
    vex_state->guest_CP0_status = 0;
 
+   vex_state->guest_LLaddr = 0xFFFFFFFF;
+   vex_state->guest_LLdata = 0;
+
    /* MIPS32 DSP ASE(r2) specific registers */
    vex_state->guest_DSPControl = 0;   /* DSPControl register */
    vex_state->guest_ac0 = 0;          /* Accumulator 0 */
@@ -276,6 +279,9 @@
    vex_state->guest_COND = 0;
 
    vex_state->guest_CP0_status = MIPS_CP0_STATUS_FR;
+
+   vex_state->guest_LLaddr = 0xFFFFFFFFFFFFFFFFULL;
+   vex_state->guest_LLdata = 0;
 }
 
 /*-----------------------------------------------------------*/

Modified: trunk/priv/guest_mips_toIR.c
==============================================================================
--- trunk/priv/guest_mips_toIR.c (original)
+++ trunk/priv/guest_mips_toIR.c Mon Mar 13 17:50:25 2017
@@ -549,6 +549,9 @@
    dres.jk_StopHere = Ijk_SigILL; \
    dres.whatNext    = Dis_StopHere;
 
+#define LLADDR_INVALID \
+   (mode64 ? mkU64(0xFFFFFFFFFFFFFFFFULL) : mkU32(0xFFFFFFFF))
+
 /*------------------------------------------------------------*/
 /*---                  Field helpers                       ---*/
 /*------------------------------------------------------------*/
@@ -1087,6 +1090,22 @@
       return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_FCSR), Ity_I32);
 }
 
+static IRExpr *getLLaddr(void)
+{
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLaddr), Ity_I64);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLaddr), Ity_I32);
+}
+
+static IRExpr *getLLdata(void)
+{
+   if (mode64)
+      return IRExpr_Get(offsetof(VexGuestMIPS64State, guest_LLdata), Ity_I64);
+   else
+      return IRExpr_Get(offsetof(VexGuestMIPS32State, guest_LLdata), Ity_I32);
+}
+
 /* Get byte from register reg, byte pos from 0 to 3 (or 7 for MIPS64) . */
 static IRExpr *getByteFromReg(UInt reg, UInt byte_pos)
 {
@@ -1109,6 +1128,22 @@
       stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_FCSR), e));
 }
 
+static void putLLaddr(IRExpr * e)
+{
+   if (mode64)
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLaddr), e));
+   else
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLaddr), e));
+}
+
+static void putLLdata(IRExpr * e)
+{
+   if (mode64)
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS64State, guest_LLdata), e));
+   else
+      stmt(IRStmt_Put(offsetof(VexGuestMIPS32State, guest_LLdata), e));
+}
+
 /* fs   - fpu source register number.
    inst - fpu instruction that needs to be executed.
    sz32 - size of source register.
@@ -1339,6 +1374,16 @@
       return src;
 }
 
+/* Convenience function to move to next instruction on condition. */
+static void mips_next_insn_if(IRExpr *condition) {
+   vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
+
+   stmt(IRStmt_Exit(condition, Ijk_Boring,
+        mode64 ? IRConst_U64(guest_PC_curr_instr + 4) :
+                 IRConst_U32(guest_PC_curr_instr + 4),
+        OFFB_PC));
+}
+
 static IRExpr *dis_branch_likely(IRExpr * guard, UInt imm)
 {
    ULong branch_offset;
@@ -16935,64 +16980,106 @@
       putIReg(rt, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), False));
       break;
 
-   case 0x30:  /* LL / LWC0 */
+   case 0x30:  /* LL */
       DIP("ll r%u, %u(r%u)", rt, imm, rs);
       LOAD_STORE_PATTERN;
-
-      t2 = newTemp(Ity_I32);
-#if defined (_MIPSEL)
-      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), NULL /* this is a load */ ));
-#elif defined (_MIPSEB)
-      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), NULL /* this is a load */ ));
-#endif
-      if (mode64)
-         putIReg(rt, unop(Iop_32Sto64, mkexpr(t2)));
-      else
+      if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+         t2 = newTemp(ty);
+         assign(t2, mkWidenFrom32(ty, load(Ity_I32, mkexpr(t1)), True));
+         putLLaddr(mkexpr(t1));
+         putLLdata(mkexpr(t2));
          putIReg(rt, mkexpr(t2));
+      } else {
+         t2 = newTemp(Ity_I32);
+         stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
+         putIReg(rt, mkWidenFrom32(ty, mkexpr(t2), True));
+      }
       break;
 
    case 0x34:  /* Load Linked Doubleword - LLD; MIPS64 */
       DIP("lld r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
-
-      t2 = newTemp(Ity_I64);
-#if defined (_MIPSEL)
-      stmt(IRStmt_LLSC
-           (Iend_LE, t2, mkexpr(t1), NULL /* this is a load */ ));
-#elif defined (_MIPSEB)
-      stmt(IRStmt_LLSC
-           (Iend_BE, t2, mkexpr(t1), NULL /* this is a load */ ));
-#endif
-
-      putIReg(rt, mkexpr(t2));
+      if (mode64) {
+         LOAD_STORE_PATTERN;
+         t2 = newTemp(Ity_I64);
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            assign(t2, load(Ity_I64, mkexpr(t1)));
+            putLLaddr(mkexpr(t1));
+            putLLdata(mkexpr(t2));
+         } else {
+            stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), NULL));
+         }
+         putIReg(rt, mkexpr(t2));
+      } else {
+         ILLEGAL_INSTRUCTON;
+      }
       break;
 
-   case 0x38:  /* SC / SWC0 */
+   case 0x38:  /* SC */
       DIP("sc r%u, %u(r%u)", rt, imm, rs);
+      t2 = newTemp(Ity_I1);
       LOAD_STORE_PATTERN;
+      if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+         t3 = newTemp(Ity_I32);
+         assign(t2, binop(mode64 ? Iop_CmpNE64 : Iop_CmpNE32,
+                          mkexpr(t1), getLLaddr()));
+         assign(t3, mkNarrowTo32(ty, getIReg(rt)));
+         putLLaddr(LLADDR_INVALID);
+         putIReg(rt, getIReg(0));
 
-      t2 = newTemp(Ity_I1);
-#if defined (_MIPSEL)
-      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
-#elif defined (_MIPSEB)
-      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), mkNarrowTo32(ty, getIReg(rt))));
-#endif
+         mips_next_insn_if(mkexpr(t2));
+
+         t4 = newTemp(Ity_I32);
+         t5 = newTemp(Ity_I32);
+
+         assign(t5, mkNarrowTo32(ty, getLLdata()));
+
+         stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+              MIPS_IEND, mkexpr(t1),                 /* addr */
+              NULL, mkexpr(t5),                      /* expected value */
+              NULL, mkexpr(t3)                       /* new value */)));
 
-      putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
+         putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32,
+                          binop(Iop_CmpEQ32, mkexpr(t4), mkexpr(t5))));
+      } else {
+         stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1),
+                          mkNarrowTo32(ty, getIReg(rt))));
+         putIReg(rt, unop(mode64 ? Iop_1Uto64 : Iop_1Uto32, mkexpr(t2)));
+      }
       break;
 
    case 0x3C:  /* Store Conditional Doubleword - SCD; MIPS64 */
-      DIP("sdc r%u, %u(r%u)", rt, imm, rs);
-      LOAD_STORE_PATTERN;
+      DIP("scd r%u, %u(r%u)", rt, imm, rs);
+      if (mode64) {
+         t2 = newTemp(Ity_I1);
+         LOAD_STORE_PATTERN;
+         if (VEX_MIPS_COMP_ID(archinfo->hwcaps) == VEX_PRID_COMP_CAVIUM) {
+            t3 = newTemp(Ity_I64);
+            assign(t2, binop(Iop_CmpNE64, mkexpr(t1), getLLaddr()));
+            assign(t3, getIReg(rt));
+            putLLaddr(LLADDR_INVALID);
+            putIReg(rt, getIReg(0));
 
-      t2 = newTemp(Ity_I1);
-#if defined (_MIPSEL)
-      stmt(IRStmt_LLSC(Iend_LE, t2, mkexpr(t1), getIReg(rt)));
-#elif defined (_MIPSEB)
-      stmt(IRStmt_LLSC(Iend_BE, t2, mkexpr(t1), getIReg(rt)));
-#endif
+            mips_next_insn_if(mkexpr(t2));
 
-      putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
+            t4 = newTemp(Ity_I64);
+            t5 = newTemp(Ity_I64);
+
+            assign(t5, getLLdata());
+
+            stmt(IRStmt_CAS(mkIRCAS(IRTemp_INVALID, t4, /* old_mem */
+                 MIPS_IEND, mkexpr(t1),                 /* addr */
+                 NULL, mkexpr(t5),                      /* expected value */
+                 NULL, mkexpr(t3)                       /* new value */)));
+
+            putIReg(rt, unop(Iop_1Uto64,
+                             binop(Iop_CmpEQ64, mkexpr(t4), mkexpr(t5))));
+         } else {
+            stmt(IRStmt_LLSC(MIPS_IEND, t2, mkexpr(t1), getIReg(rt)));
+            putIReg(rt, unop(Iop_1Uto64, mkexpr(t2)));
+         }
+      } else {
+         ILLEGAL_INSTRUCTON;
+      }
       break;
 
    case 0x37:  /* Load Doubleword - LD; MIPS64 */

Modified: trunk/pub/libvex_guest_mips32.h
==============================================================================
--- trunk/pub/libvex_guest_mips32.h (original)
+++ trunk/pub/libvex_guest_mips32.h Mon Mar 13 17:50:25 2017
@@ -151,7 +151,10 @@
 
       /*  488 */ UInt guest_CP0_status;
 
-      /*  492 */ UInt _padding2;
+      /*  492 */ UInt guest_LLaddr;
+      /*  496 */ UInt guest_LLdata;
+
+      /*  500 */ UInt _padding2[3];
 } VexGuestMIPS32State;
 /*---------------------------------------------------------------*/
 /*--- Utility functions for MIPS32 guest stuff.               ---*/

Modified: trunk/pub/libvex_guest_mips64.h
==============================================================================
--- trunk/pub/libvex_guest_mips64.h (original)
+++ trunk/pub/libvex_guest_mips64.h Mon Mar 13 17:50:25 2017
@@ -148,7 +148,10 @@
 
       /*  608 */ ULong guest_NRADDR;
 
-      /*  616 */ ULong _padding2;
+      /*  616 */ ULong guest_LLaddr;
+      /*  624 */ ULong guest_LLdata;
+
+      /*  632 */ ULong _padding2;
 } VexGuestMIPS64State;
 
 /*---------------------------------------------------------------*/


------------------------------------------------------------------------------
Check out the vibrant tech community on one of the world's most
engaging tech sites, Slashdot.org! http://sdm.link/slashdot
_______________________________________________
Valgrind-developers mailing list
[hidden email]
https://lists.sourceforge.net/lists/listinfo/valgrind-developers