]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390x: Re-implement STFLE as an extension
authorAndreas Arnez <arnez@linux.ibm.com>
Wed, 10 Jul 2024 16:47:07 +0000 (18:47 +0200)
committerAndreas Arnez <arnez@linux.ibm.com>
Wed, 10 Jul 2024 16:47:07 +0000 (18:47 +0200)
The existing implementation of the STFLE instruction does not use the
correct operand size when tracking memory effects.  Instead of respecting
the user-provided maximum number of doublewords and the returned value
from the instruction, it assumes a hard coded value (S390_NUM_FACILITY_DW)
instead.

For example, if an application passes a buffer of 3 doublewords to STFLE
while Valgrind assumes a fixed size of 4 doublewords, Valgrind may falsely
complain about an invalid write for the last doubleword.

Fix this by re-implementing STFLE via the extension mechanism.

VEX/priv/guest_s390_defs.h
VEX/priv/guest_s390_helpers.c
VEX/priv/guest_s390_toIR.c
VEX/pub/libvex_s390x_common.h
coregrind/m_extension/extension-s390x.c

index 1436ce3e8e23d39ce75cf08d1639e11c7746a839..69e804cce2c8de196f0c30ad0f3fff620883a0f0 100644 (file)
@@ -73,7 +73,6 @@ void s390x_dirtyhelper_EX(ULong torun);
 ULong s390x_dirtyhelper_STCK(ULong *addr);
 ULong s390x_dirtyhelper_STCKF(ULong *addr);
 ULong s390x_dirtyhelper_STCKE(ULong *addr);
-ULong s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr);
 void  s390x_dirtyhelper_CUxy(UChar *addr, ULong data, ULong num_bytes);
 ULong s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
                                ULong details);
index 9642a013e6a5e3d112103944a0af6b5b9330dd32..69a7c7d061bb29cdad10cb76dcd536d0f6e36a51 100644 (file)
@@ -310,129 +310,6 @@ ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
 ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
 #endif /* VGA_s390x */
 
-/*------------------------------------------------------------*/
-/*--- Dirty helper for Store Facility instruction          ---*/
-/*------------------------------------------------------------*/
-#if defined(VGA_s390x)
-
-static ULong
-s390_stfle_range(UInt lo, UInt hi)
-{
-   return ((1UL << (hi + 1 - lo)) - 1) << (63 - (hi % 64));
-}
-
-ULong
-s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
-{
-   ULong hoststfle[S390_NUM_FACILITY_DW], cc, last_dw, i;
-   register ULong reg0 asm("0") = guest_state->guest_r0;
-   last_dw = reg0 & 0xf;
-
-   /* Restrict to facilities that we know about and that we assume to be
-      compatible with Valgrind.  Of course, in this way we may reject features
-      that Valgrind is not really involved in (and thus would be compatible
-      with), but quering for such features doesn't seem like a typical use
-      case. */
-   ULong accepted_facility[S390_NUM_FACILITY_DW] = {
-      /* ===  0 .. 63  === */
-      (s390_stfle_range(0, 16)
-       /* 17: message-security-assist, not supported */
-       | s390_stfle_range(18, 19)
-       /* 20: HFP-multiply-and-add/subtract, not supported */
-       | s390_stfle_range(21, 22)
-       /* 23: HFP-unnormalized-extension, not supported */
-       | s390_stfle_range(24, 25)
-       /* 26: parsing-enhancement, not supported */
-       | s390_stfle_range(27, 28)
-       /* 29: unassigned */
-       | s390_stfle_range(30, 30)
-       /* 31: extract-CPU-time, not supported */
-       | s390_stfle_range(32, 41)
-       /* 42-43: DFP, not fully supported */
-       /* 44: PFPO, not fully supported */
-       | s390_stfle_range(45, 47)
-       /* 48: DFP zoned-conversion, not supported */
-       /* 49: includes PPA, not supported */
-       /* 50: constrained transactional-execution, not supported */
-       | s390_stfle_range(51, 55)
-       /* 56: unassigned */
-       /* 57: MSA5, not supported */
-       | s390_stfle_range(58, 63)),
-
-      /* ===  64 .. 127  === */
-      (s390_stfle_range(64, 72)
-       /* 73: transactional-execution, not supported */
-       | s390_stfle_range(74, 75)
-       /* 76: MSA3, not supported */
-       /* 77: MSA4, not supported */
-       | s390_stfle_range(78, 78)
-       /* 80: DFP packed-conversion, not supported */
-       /* 81: PPA-in-order, not supported */
-       | s390_stfle_range(82, 82)
-       /* 83-127: unassigned */ ),
-
-      /* ===  128 .. 191  === */
-      (s390_stfle_range(128, 131)
-       /* 132: unassigned */
-       /* 133: guarded-storage, not supported */
-       /* 134: vector packed decimal, not supported */
-       | s390_stfle_range(135, 135)
-       /* 136: unassigned */
-       /* 137: unassigned */
-       | s390_stfle_range(138, 142)
-       /* 143: unassigned */
-       | s390_stfle_range(144, 145)
-       /* 146: MSA8, not supported */
-       | s390_stfle_range(147, 149)
-       /* 150: unassigned */
-       | s390_stfle_range(151, 151)
-       /* 152: vector packed decimal enhancement, not supported */
-       /* 153: unassigned */
-       /* 154: unassigned */
-       /* 155: MSA9, not supported */
-       | s390_stfle_range(156, 156)
-       /* 157-164: unassigned */
-       | s390_stfle_range(165, 165)
-       /* 166-167: unassigned */
-       | s390_stfle_range(168, 168)
-       /* 168-191: unassigned */ ),
-
-      /* ===  192 .. 255  === */
-      /* 192: vector-packed-decimal, not supported */
-      (s390_stfle_range(193, 194)
-       /* 195: unassigned */
-       | s390_stfle_range(196, 197)),
-   };
-
-   asm(".insn s,0xb2b00000,%0\n" /* stfle */
-       "ipm   %2\n"
-       "srl   %2,28\n"
-       : "=Q"(hoststfle), "+d"(reg0), "=d"(cc)
-       :
-       : "cc");
-
-   /* Update guest register 0  with what STFLE set r0 to */
-   guest_state->guest_r0 = reg0;
-
-   /* VM facilities = host facilities, filtered by acceptance */
-   for (i = 0; i <= last_dw; ++i) {
-      if (i < S390_NUM_FACILITY_DW)
-         addr[i] = hoststfle[i] & accepted_facility[i];
-      else
-         addr[i] = 0; /* mask out any excess doublewords */
-   }
-
-   return cc;
-}
-
-#else
-
-ULong
-s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
-{
-   return 3;
-}
-#endif /* VGA_s390x */
 
 /*------------------------------------------------------------*/
 /*--- Dirty helper for the "convert unicode" insn family.  ---*/
index 0da0b941bb3f3fd3cd421deb4491a24e69adc2d8..35cba270da4092ac055775980123568315110cfa 100644 (file)
@@ -3528,6 +3528,18 @@ s390_format_S_RD(const HChar *(*irgen)(IRTemp op2addr),
       s390_disasm(ENC2(MNM, UDXB), mnm, d2, 0, b2);
 }
 
+static void
+s390_format_S_RD_raw(const HChar *(*irgen)(UChar b2, UShort d2),
+                     UChar b2, UShort d2)
+{
+   const HChar *mnm;
+
+   mnm = irgen(b2, d2);
+
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_FE))
+      s390_disasm(ENC2(MNM, UDXB), mnm, d2, 0, b2);
+}
+
 static void
 s390_format_SI_URD(const HChar *(*irgen)(UChar i2, IRTemp op1addr),
                    UChar i2, UChar b1, UShort d1)
@@ -15287,37 +15299,13 @@ s390_irgen_STCKE(IRTemp op2addr)
 }
 
 static const HChar *
-s390_irgen_STFLE(IRTemp op2addr)
+s390_irgen_STFLE(UChar b2, UShort d2)
 {
    if (! s390_host_has_stfle) {
       emulation_failure(EmFail_S390X_stfle);
       return "stfle";
    }
-
-   IRDirty *d;
-   IRTemp cc = newTemp(Ity_I64);
-
-   /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper */
-   d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_STFLE",
-                         &s390x_dirtyhelper_STFLE,
-                         mkIRExprVec_2(IRExpr_GSPTR(), mkexpr(op2addr)));
-
-   d->nFxState = 1;
-   vex_bzero(&d->fxState, sizeof(d->fxState));
-
-   d->fxState[0].fx     = Ifx_Modify;  /* read then write */
-   d->fxState[0].offset = S390X_GUEST_OFFSET(guest_r0);
-   d->fxState[0].size   = sizeof(ULong);
-
-   d->mAddr = mkexpr(op2addr);
-   /* Pretend all double words are written */
-   d->mSize = S390_NUM_FACILITY_DW * sizeof(ULong);
-   d->mFx   = Ifx_Write;
-
-   stmt(IRStmt_Dirty(d));
-
-   s390_cc_set(cc);
-
+   extension(S390_EXT_STFLE, b2 | (d2 << 8));
    return "stfle";
 }
 
@@ -20034,7 +20022,7 @@ s390_decode_4byte_and_irgen(const UChar *bytes)
    case 0xb2a7: s390_format_RRF_M0RERE(s390_irgen_CU12, RRF3_r3(ovl),
                                        RRF3_r1(ovl), RRF3_r2(ovl));
       goto ok;
-   case 0xb2b0: s390_format_S_RD(s390_irgen_STFLE, S_b2(ovl), S_d2(ovl));
+   case 0xb2b0: s390_format_S_RD_raw(s390_irgen_STFLE, S_b2(ovl), S_d2(ovl));
                                  goto ok;
    case 0xb2b1: /* STFL */ goto unimplemented;
    case 0xb2b2: /* LPSWE */ goto unimplemented;
index 9b1168a4e6c7ec6146f2b8cb82bdb28013ea5194..5b03fb7c4e1e525a007d6cba75e8ee1506a9bf15 100644 (file)
 #define S390_EXT_PRNO    1
 #define S390_EXT_NNPA    2
 #define S390_EXT_DFLT    3
+#define S390_EXT_STFLE   4
 
 /*--------------------------------------------------------------*/
 /*--- Miscellaneous                                          ---*/
index e94e7933c85407206187dc32d2f5217c8dca2ea5..82bd231cf1fbc59869a88f74af759cd0142a30b5 100644 (file)
@@ -79,7 +79,8 @@ union reg_pair {
    unsigned __int128 pair;
 };
 
-#define S390_SETBIT(x) (1UL << (63 - (x % 64)))
+#define S390_SETBIT(x)       (1UL << (63 - (x % 64)))
+#define S390_SETBITS(lo, hi) (((1UL << (hi + 1 - lo)) - 1) << (63 - (hi % 64)))
 
 /* Helper routine for query functions: Filter the bit vector `fc' using a given
    `filter' vector */
@@ -752,6 +753,111 @@ static UWord do_extension_DFLTCC(ThreadState* tst, ULong variant)
    return ExtErr_OK;
 }
 
+/*---------------------------------------------------------------*/
+/*--- STFLE (store facility list extended)                    ---*/
+/*---------------------------------------------------------------*/
+
+static enum ExtensionError do_extension_STFLE(ThreadState* tst, ULong variant)
+{
+   Int    cc      = 0;
+   UChar  b2      = variant & 0xf;
+   UShort d2      = (variant >> 8) & 0xfff;
+   ULong  gpr0    = READ_GPR(tst, "STFLE(r0)", 0);
+   ULong  last_dw = gpr0 & 0xff;
+   ULong  addr    = READ_GPR(tst, "STFLE(b2)", b2) + d2;
+
+   PRE_MEM_WRITE(tst, "STFLE(bits)", addr, (last_dw + 1) * sizeof(ULong));
+   static const ULong accepted_facility[] = {
+      /* ===  0 .. 63  === */
+      (S390_SETBITS(0, 16)
+       /* 17: message-security-assist, not supported */
+       | S390_SETBITS(18, 19)
+       /* 20: HFP-multiply-and-add/subtract, not supported */
+       | S390_SETBITS(21, 22)
+       /* 23: HFP-unnormalized-extension, not supported */
+       | S390_SETBITS(24, 25)
+       /* 26: parsing-enhancement, not supported */
+       | S390_SETBITS(27, 28)
+       /* 29: unassigned */
+       | S390_SETBITS(30, 30)
+       /* 31: extract-CPU-time, not supported */
+       | S390_SETBITS(32, 41)
+       /* 42-43: DFP, not fully supported */
+       /* 44: PFPO, not fully supported */
+       | S390_SETBITS(45, 47)
+       /* 48: DFP zoned-conversion, not supported */
+       /* 49: includes PPA, not supported */
+       /* 50: constrained transactional-execution, not supported */
+       | S390_SETBITS(51, 55)
+       /* 56: unassigned */
+       /* 57: MSA5, not supported */
+       | S390_SETBITS(58, 63)),
+
+      /* ===  64 .. 127  === */
+      (S390_SETBITS(64, 72)
+       /* 73: transactional-execution, not supported */
+       | S390_SETBITS(74, 75)
+       /* 76: MSA3, not supported */
+       /* 77: MSA4, not supported */
+       | S390_SETBITS(78, 78)
+       /* 80: DFP packed-conversion, not supported */
+       /* 81: PPA-in-order, not supported */
+       | S390_SETBITS(82, 82)
+       /* 83-127: unassigned */),
+
+      /* ===  128 .. 191  === */
+      (S390_SETBITS(128, 131)
+       /* 132: unassigned */
+       /* 133: guarded-storage, not supported */
+       /* 134: vector packed decimal, not supported */
+       | S390_SETBITS(135, 135)
+       /* 136: unassigned */
+       /* 137: unassigned */
+       | S390_SETBITS(138, 142)
+       /* 143: unassigned */
+       | S390_SETBITS(144, 145)
+       /* 146: MSA8, not supported */
+       | S390_SETBITS(147, 149)
+       /* 150: unassigned */
+       | S390_SETBITS(151, 151)
+       /* 152: vector packed decimal enhancement, not supported */
+       /* 153: unassigned */
+       /* 154: unassigned */
+       /* 155: MSA9, not supported */
+       | S390_SETBITS(156, 156)
+       /* 157-164: unassigned */
+       | S390_SETBITS(165, 165)
+       /* 166-167: unassigned */
+       | S390_SETBITS(168, 168)
+       /* 168-191: unassigned */),
+
+      /* ===  192 .. 255  === */
+      /* 192: vector-packed-decimal, not supported */
+      (S390_SETBITS(193, 194)
+       /* 195: unassigned */
+       | S390_SETBITS(196, 197)),
+   };
+   asm("lgr 0,%[r0]\n"
+       ".insn s,0xb2b00000,%[out]\n" /* stfle */
+       "lgr %[r0],0\n"
+       "ipm %[cc]\n"
+       "srl %[cc],28\n"
+       : [out] "=Q"(*(ULong(*)[last_dw + 1])(void*)addr), [r0] "+d"(gpr0),
+         [cc] "=d"(cc)
+       :
+       : "cc");
+
+   WRITE_GPR(tst, 0, gpr0);
+   if (last_dw > (gpr0 & 0xff))
+      last_dw = gpr0 & 0xff;
+   s390_filter_functions((ULong*)addr, (last_dw + 1) * sizeof(ULong),
+                         accepted_facility, sizeof(accepted_facility));
+   POST_MEM_WRITE(tst, addr, (last_dw + 1) * sizeof(ULong));
+
+   WRITE_CC(tst, cc);
+   return ExtErr_OK;
+}
+
 /*---------------------------------------------------------------*/
 /*--- Main function: select and call appropriate extension    ---*/
 /*---------------------------------------------------------------*/
@@ -769,6 +875,8 @@ enum ExtensionError ML_(do_client_extension)(ThreadState* tst)
       return do_extension_NNPA(tst, variant);
    case S390_EXT_DFLT:
       return do_extension_DFLTCC(tst, variant);
+   case S390_EXT_STFLE:
+      return do_extension_STFLE(tst, variant);
    default:
       VG_(core_panic)("unknown extension ID");
    }