]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Power PC, Approach 1, add Transactional Memory instruction support
authorCarl Love <cel@us.ibm.com>
Wed, 2 Oct 2013 16:25:57 +0000 (16:25 +0000)
committerCarl Love <cel@us.ibm.com>
Wed, 2 Oct 2013 16:25:57 +0000 (16:25 +0000)
The following Transactional Memory instructions are added:
  tbegin., tend., tsr., tcheck., tabortwc.,
  tabortdc., tabortwci., tabortdci., tabort.

The patch implements the first proposal by Julian on how to handle the
TM instructions. The proposal is as follows:

    translate "XBEGIN fail-addr" as "goto fail-addr"; that is: push
    simulated execution directly onto the failure path.  This is simple
    but will have poor performance, if (as is likely) the failure path
    uses normal locking and is not tuned for speed.

The tbegin instruction on Power sets the condition code register to
indicate if the tbegin instruction suceeded or failed.  The compiler
then generates a conditional branch instruction to take the success
or failure code path for the tbegin instruction.  In order to fail the
tbegin instruction, the condition code register is updated to indicate
that the tbegin instruction failed.  This patch assumes that there is
always an error handler for the tbegin instruction.  The other TM
instructions are all treated as no ops as we shouldn't be executing the
sucess transactional code path.

Signed-off-by: Carl Love <cel@us.ibm.com>
Bugzilla 323803

git-svn-id: svn://svn.valgrind.org/vex/trunk@2780

VEX/priv/guest_ppc_helpers.c
VEX/priv/guest_ppc_toIR.c
VEX/pub/libvex_guest_ppc32.h
VEX/pub/libvex_guest_ppc64.h

index f320149f4fbc0abc26737312676d762efe49030c..4b50547aaccdf0bf67876dce25c67b9e92ff368c 100644 (file)
@@ -511,7 +511,8 @@ void LibVEX_GuestPPC32_initialise ( /*OUT*/VexGuestPPC32State* vex_state )
    vex_state->guest_IP_AT_SYSCALL = 0;
    vex_state->guest_SPRG3_RO = 0;
 
-   vex_state->padding = 0;
+   vex_state->padding1 = 0;
+   vex_state->padding2 = 0;
 }
 
 
@@ -676,10 +677,9 @@ void LibVEX_GuestPPC64_initialise ( /*OUT*/VexGuestPPC64State* vex_state )
 
    vex_state->guest_IP_AT_SYSCALL = 0;
    vex_state->guest_SPRG3_RO = 0;
-
-   vex_state->padding2 = 0;
-   vex_state->padding3 = 0;
-   vex_state->padding4 = 0;
+   vex_state->guest_TFHAR  = 0;
+   vex_state->guest_TFIAR  = 0;
+   vex_state->guest_TEXASR = 0;
 }
 
 
index 8f17b64cdf2665f3477bba1f5495150460f8659d..1c343ce7a63efd1feb00b879449944968db238df 100644 (file)
@@ -232,6 +232,9 @@ static void* fnptr_to_fnentry( VexAbiInfo* vbi, void* f )
 #define OFFB_TILEN       offsetofPPCGuestState(guest_TILEN)
 #define OFFB_NRADDR      offsetofPPCGuestState(guest_NRADDR)
 #define OFFB_NRADDR_GPR2 offsetofPPCGuestState(guest_NRADDR_GPR2)
+#define OFFB_TFHAR       offsetofPPCGuestState(guest_TFHAR)
+#define OFFB_TEXASR      offsetofPPCGuestState(guest_TEXASR)
+#define OFFB_TFIAR       offsetofPPCGuestState(guest_TFIAR)
 
 
 /*------------------------------------------------------------*/
@@ -378,6 +381,9 @@ typedef enum {
     PPC_GST_TILEN,  // For icbi: length of area to invalidate
     PPC_GST_IP_AT_SYSCALL, // the CIA of the most recently executed SC insn
     PPC_GST_SPRG3_RO, // SPRG3
+    PPC_GST_TFHAR,  // Transactional Failure Handler Address Register
+    PPC_GST_TFIAR,  // Transactional Failure Instruction Address Register
+    PPC_GST_TEXASR, // Transactional EXception And Summary Register
     PPC_GST_MAX
 } PPC_GST;
 
@@ -2546,6 +2552,15 @@ static IRExpr* /* :: Ity_I32/64 */ getGST ( PPC_GST reg )
                          binop( Iop_Shl32, getXER_CA32(), mkU8(29)),
                          getXER_BC32()));
 
+   case PPC_GST_TFHAR:
+      return IRExpr_Get( OFFB_TFHAR, ty );
+
+   case PPC_GST_TEXASR:
+      return IRExpr_Get( OFFB_TEXASR, ty );
+
+   case PPC_GST_TFIAR:
+      return IRExpr_Get( OFFB_TFIAR, ty );
+
    default:
       vex_printf("getGST(ppc): reg = %u", reg);
       vpanic("getGST(ppc)");
@@ -2707,6 +2722,18 @@ static void putGST ( PPC_GST reg, IRExpr* src )
       stmt( IRStmt_Put( OFFB_TILEN, src) );
       break;
       
+   case PPC_GST_TEXASR:
+      vassert( ty_src == Ity_I64 );
+      stmt( IRStmt_Put( OFFB_TEXASR, src ) );
+      break;
+   case PPC_GST_TFIAR:
+      vassert( ty_src == Ity_I64 );
+      stmt( IRStmt_Put( OFFB_TFIAR, src ) );
+      break;
+   case PPC_GST_TFHAR:
+      vassert( ty_src == Ity_I64 );
+      stmt( IRStmt_Put( OFFB_TFHAR, src ) );
+      break;
    default:
       vex_printf("putGST(ppc): reg = %u", reg);
       vpanic("putGST(ppc)");
@@ -3052,6 +3079,50 @@ static IRTemp getNegatedResult_32(IRTemp intermediateResult)
    return negatedResult;
 }
 
+/*------------------------------------------------------------*/
+/* Transactional memory helpers
+ *
+ *------------------------------------------------------------*/
+
+static ULong generate_TMreason( UInt failure_code,
+                                             UInt persistant,
+                                             UInt nest_overflow,
+                                             UInt tm_exact )
+{
+   ULong tm_err_code =
+     ( (ULong) 0) << (63-6)   /* Failure code */
+     | ( (ULong) persistant) << (63-7)     /* Failure persistant */
+     | ( (ULong) 0) << (63-8)   /* Disallowed */
+     | ( (ULong) nest_overflow) << (63-9)   /* Nesting Overflow */
+     | ( (ULong) 0) << (63-10)  /* Footprint Overflow */
+     | ( (ULong) 0) << (63-11)  /* Self-Induced Conflict */
+     | ( (ULong) 0) << (63-12)  /* Non-Transactional Conflict */
+     | ( (ULong) 0) << (63-13)  /* Transactional Conflict */
+     | ( (ULong) 0) << (63-14)  /* Translation Invalidation Conflict */
+     | ( (ULong) 0) << (63-15)  /* Implementation-specific */
+     | ( (ULong) 0) << (63-16)  /* Instruction Fetch Conflict */
+     | ( (ULong) 0) << (63-30)  /* Reserved */
+     | ( (ULong) 0) << (63-31)  /* Abort */
+     | ( (ULong) 0) << (63-32)  /* Suspend */
+     | ( (ULong) 0) << (63-33)  /* Reserved */
+     | ( (ULong) 0) << (63-35)  /* Privilege */
+     | ( (ULong) 0) << (63-36)  /* Failure Summary */
+     | ( (ULong) tm_exact) << (63-37)  /* TFIAR Exact */
+     | ( (ULong) 0) << (63-38)  /* ROT */
+     | ( (ULong) 0) << (63-51)  /* Reserved */
+     | ( (ULong) 0) << (63-63);  /* Transaction Level */
+
+     return tm_err_code;
+}
+
+static void storeTMfailure( Addr64 err_address, ULong tm_reason,
+                            Addr64 handler_address )
+{
+   putGST( PPC_GST_TFIAR,  mkU64( err_address ) );
+   putGST( PPC_GST_TEXASR, mkU64( tm_reason ) );
+   putGST( PPC_GST_TFHAR,  mkU64( handler_address ) );
+}
+
 /*------------------------------------------------------------*/
 /*--- Integer Instruction Translation                     --- */
 /*------------------------------------------------------------*/
@@ -6680,6 +6751,18 @@ static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
          DIP("mfctr r%u\n", rD_addr);
          putIReg( rD_addr, getGST( PPC_GST_CTR ) ); 
          break;
+      case 0x80:  // 128
+         DIP("mfspr r%u (TFHAR)\n", rD_addr);
+         putIReg( rD_addr, getGST( PPC_GST_TFHAR) );
+         break;
+      case 0x81:  // 129
+         DIP("mfspr r%u (TFIAR)\n", rD_addr);
+         putIReg( rD_addr, getGST( PPC_GST_TFIAR) );
+         break;
+      case 0x82:  // 130
+         DIP("mfspr r%u (TEXASR)\n", rD_addr);
+         putIReg( rD_addr, getGST( PPC_GST_TEXASR) );
+         break;
       case 0x100: 
          DIP("mfvrsave r%u\n", rD_addr);
          putIReg( rD_addr, mkWidenFrom32(ty, getGST( PPC_GST_VRSAVE ),
@@ -6824,7 +6907,18 @@ static Bool dis_proc_ctl ( VexAbiInfo* vbi, UInt theInstr )
          DIP("mtvrsave r%u\n", rS_addr);
          putGST( PPC_GST_VRSAVE, mkNarrowTo32(ty, mkexpr(rS)) );
          break;
-
+      case 0x80:  // 128
+         DIP("mtspr r%u (TFHAR)\n", rS_addr);
+         putGST( PPC_GST_TFHAR, mkexpr(rS) );
+         break;
+      case 0x81:  // 129
+         DIP("mtspr r%u (TFIAR)\n", rS_addr);
+         putGST( PPC_GST_TFIAR, mkexpr(rS) );
+         break;
+      case 0x82:  // 130
+         DIP("mtspr r%u (TEXASR)\n", rS_addr);
+         putGST( PPC_GST_TEXASR, mkexpr(rS) );
+         break;
       default:
          vex_printf("dis_proc_ctl(ppc)(mtspr,SPR)(%u)\n", SPR);
          return False;
@@ -16894,6 +16988,148 @@ static Bool dis_av_fp_convert ( UInt theInstr )
    return True;
 }
 
+static Bool dis_transactional_memory ( UInt theInstr, UInt nextInstr,
+                                       VexAbiInfo* vbi,
+                                       /*OUT*/DisResult* dres,
+                                       Bool (*resteerOkFn)(void*,Addr64),
+                                       void* callback_opaque )
+{
+   UInt   opc2      = IFIELD( theInstr, 1, 10 );
+
+   switch (opc2) {
+   case 0x28E: {        //tbegin.
+      /* The current implementation is to just fail the tbegin and execute
+       * the failure path.  The failure path is assumed to be functionaly
+       * equivalent to the transactional path with the needed data locking
+       * to ensure correctness.  The tend is just a noop and shouldn't
+       * actually get executed.
+       *   1) set cr0 to 0x2
+       *   2) Initialize TFHAR to CIA+4
+       *   3) Initialize TEXASR
+       *   4) Initialize TFIAR (probably to CIA, ie, the address of tbegin.)
+       *   5) Continue executing at the next instruction.
+       */
+      UInt R = IFIELD( theInstr, 21, 1 );
+
+      ULong tm_reason;
+      UInt failure_code = 0;  /* Forcing failure, will not be due to tabort
+                               * or treclaim.
+                               */
+      UInt persistant = 1;    /* set persistant since we are always failing
+                               * the tbegin.
+                               */
+      UInt nest_overflow = 1; /* Alowed nesting depth overflow, we use this
+                                 as the reason for failing the trasaction */
+      UInt tm_exact   = 1;    /* have exact address for failure */
+
+      DIP("tbegin. %d\n", R);
+
+      /* Set the CR0 field to indicate the tbegin failed.  Then let
+       * the code do the branch to the failure path.
+       *
+       * 000 || 0  Transaction initiation successful,
+       *           unnested (Transaction state of
+       *           Non-transactional prior to tbegin.)
+       * 010 || 0  Transaction initiation successful, nested
+       *           (Transaction state of Transactional
+       *           prior to tbegin.)
+       * 001 || 0  Transaction initiation unsuccessful,
+       *           (Transaction state of Suspended prior
+       *           to tbegin.)
+       */
+      putCR321( 0, mkU8( 0x2 ) );
+
+      tm_reason = generate_TMreason( failure_code, persistant,
+                                     nest_overflow, tm_exact );
+
+      storeTMfailure( guest_CIA_curr_instr, tm_reason,
+                      guest_CIA_curr_instr+4 );
+
+      return True;
+
+      break;
+   }
+
+   case 0x2AE: {        //tend.
+      /* The tend. is just a noop.  Do nothing */
+      UInt A = IFIELD( theInstr, 25, 1 );
+
+      DIP("tend. %d\n", A);
+      break;
+   }
+
+   case 0x2EE: {        //tsr.
+      /* The tsr. is just a noop.  Do nothing */
+      UInt L = IFIELD( theInstr, 21, 1 );
+
+      DIP("tsr. %d\n", L);
+      break;
+   }
+
+   case 0x2CE: {        //tcheck.
+      /* The tcheck. is just a noop.  Do nothing */
+      UInt BF = IFIELD( theInstr, 25, 1 );
+
+      DIP("tcheck. %d\n", BF);
+      break;
+   }
+
+   case 0x30E: {        //tbortwc.
+      /* The tabortwc. is just a noop.  Do nothing */
+      UInt TO = IFIELD( theInstr, 25, 1 );
+      UInt RA = IFIELD( theInstr, 16, 5 );
+      UInt RB = IFIELD( theInstr, 11, 5 );
+
+      DIP("tabortwc. %d,%d,%d\n", TO, RA, RB);
+      break;
+   }
+
+   case 0x32E: {        //tbortdc.
+      /* The tabortdc. is just a noop.  Do nothing */
+      UInt TO = IFIELD( theInstr, 25, 1 );
+      UInt RA = IFIELD( theInstr, 16, 5 );
+      UInt RB = IFIELD( theInstr, 11, 5 );
+
+      DIP("tabortdc. %d,%d,%d\n", TO, RA, RB);
+      break;
+   }
+
+   case 0x34E: {        //tbortwci.
+      /* The tabortwci. is just a noop.  Do nothing */
+      UInt TO = IFIELD( theInstr, 25, 1 );
+      UInt RA = IFIELD( theInstr, 16, 5 );
+      UInt SI = IFIELD( theInstr, 11, 5 );
+
+      DIP("tabortwci. %d,%d,%d\n", TO, RA, SI);
+      break;
+   }
+
+   case 0x36E: {        //tbortdci.
+      /* The tabortdci. is just a noop.  Do nothing */
+      UInt TO = IFIELD( theInstr, 25, 1 );
+      UInt RA = IFIELD( theInstr, 16, 5 );
+      UInt SI = IFIELD( theInstr, 11, 5 );
+
+      DIP("tabortdci. %d,%d,%d\n", TO, RA, SI);
+      break;
+   }
+
+   case 0x38E: {        //tbort.
+      /* The tabort. is just a noop.  Do nothing */
+      UInt RA = IFIELD( theInstr, 16, 5 );
+
+      DIP("tabort. %d\n", RA);
+      break;
+   }
+
+   default:
+      vex_printf("dis_transactional_memory(ppc): unrecognized instruction\n");
+      return False;
+   }
+
+   return True;
+}
+
 
 /* The 0x3C primary opcode (VSX category) uses several different forms of
  * extended opcodes:
@@ -17951,6 +18187,17 @@ DisResult disInstr_PPC_WRK (
          if (dis_int_logic( theInstr )) goto decode_success;
          goto decode_failure;
 
+      case 0x28E: case 0x2AE:             // tbegin., tend.
+      case 0x2EE: case 0x2CE: case 0x30E: // tsr., tcheck., tabortwc.
+      case 0x32E: case 0x34E: case 0x36E: // tabortdc., tabortwci., tabortdci.
+      case 0x38E:                         // tabort.
+      if (dis_transactional_memory( theInstr,
+                                    getUIntBigendianly( (UChar*)(&guest_code[delta + 4])),
+                                    abiinfo, &dres,
+                                    resteerOkFn, callback_opaque))
+            goto decode_success;
+         goto decode_failure;
+
       /* 64bit Integer Logical Instructions */
       case 0x3DA: case 0x03A: // extsw, cntlzd
          if (!mode64) goto decode_failure;
index d90b7d3bde462f5d0023b232e8571ae173c1ca62..11938cc6522b2dd5d1dba13adc385e3f271c9e28 100644 (file)
@@ -237,9 +237,14 @@ typedef
       /* SPRG3, which AIUI is readonly in user space.  Needed for
          threading on AIX. */
       /* 1352 */ UInt guest_SPRG3_RO;
+      /* 1356 */ UInt  padding1;
+      /* 1360 */ ULong guest_TFHAR;     // Transaction Failure Handler Address Register 
+      /* 1368 */ ULong guest_TEXASR;    // Transaction EXception And Summary Register
+      /* 1376 */ ULong guest_TFIAR;     // Transaction Failure Instruction Address Register
 
       /* Padding to make it have an 8-aligned size */
-      /* 1356 */ UInt  padding;
+      /* 1384 */ UInt  padding2;
+
    }
    VexGuestPPC32State;
 
index 1c9502c24063fd6a5cea220cd5ff81f33ec84a1a..d5a7f2d3b4a105e55cfdf0f15c03c61718a5fafd 100644 (file)
@@ -279,11 +279,10 @@ typedef
          threading on AIX. */
       /* 1648 */ ULong guest_SPRG3_RO;
 
-      /* offsets in comments are wrong ..*/
-      /* Padding to make it have an 16-aligned size */
-      /* 1656 */ ULong padding2;
-      /* 16XX */ ULong padding3;
-      /* 16XX */ ULong padding4;
+      /* 1656 */ ULong guest_TFHAR;     // Transaction Failure Handler Address Register 
+      /* 1664 */ ULong guest_TEXASR;    // Transaction EXception And Summary Register
+      /* 1672 */ ULong guest_TFIAR;     // Transaction Failure Instruction Address Register
+
    }
    VexGuestPPC64State;