From: Andreas Arnez Date: Wed, 15 May 2024 12:32:42 +0000 (+0200) Subject: s390x: Support the deflate-conversion facility (DFLTCC) X-Git-Tag: VALGRIND_3_24_0~136 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=fef1d8f01d47ee0398d7b28eda4c6707ce7f4332;p=thirdparty%2Fvalgrind.git s390x: Support the deflate-conversion facility (DFLTCC) So far the DFLTCC (deflate conversion call) instruction is not supported by Valgrind. Similar to PRNO and NNPA, it is a "complex" instruction whose memory effects cannot be adequately expressed with a dirty helper. Add support for the DFLTCC instruction using the new "extension" mechanism and reflect this accordingly in the supported facilities and HWCAPs. --- diff --git a/NEWS b/NEWS index 9dbb03216..f6ed17995 100644 --- a/NEWS +++ b/NEWS @@ -12,6 +12,9 @@ AMD64/macOS 10.13 and nanoMIPS/Linux. * ================== PLATFORM CHANGES ================= +* S390X added support for the DFLTCC instruction provided by the + deflate-conversion facility (z15/arch13). + * ==================== TOOL CHANGES =================== * ==================== FIXED BUGS ==================== diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c index bb5e9c939..9642a013e 100644 --- a/VEX/priv/guest_s390_helpers.c +++ b/VEX/priv/guest_s390_helpers.c @@ -385,7 +385,7 @@ s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr) /* 146: MSA8, not supported */ | s390_stfle_range(147, 149) /* 150: unassigned */ - /* 151: DEFLATE-conversion, not supported */ + | s390_stfle_range(151, 151) /* 152: vector packed decimal enhancement, not supported */ /* 153: unassigned */ /* 154: unassigned */ diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 7e836faf3..0da0b941b 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -17105,6 +17105,19 @@ s390_irgen_PPNO(UChar r1, UChar r2) return "ppno"; } +static const HChar * +s390_irgen_DFLTCC(UChar r3, UChar r1, UChar r2) +{ + s390_insn_assert("dfltcc", s390_host_has_dflt); + + /* Check for obvious specification exceptions */ + s390_insn_assert("dfltcc", r1 % 2 == 0 && r1 != 0 && + r2 % 2 == 0 && r2 != 0 && r3 >= 2); + + extension(S390_EXT_DFLT, r1 | (r2 << 4) | (r3 << 8)); + return "dfltcc"; +} + enum s390_VStrX { s390_VStrX_VSTRC, s390_VStrX_VFAE, @@ -20452,7 +20465,8 @@ s390_decode_4byte_and_irgen(const UChar *bytes) case 0xb931: s390_format_RRE_RR(s390_irgen_CLGFR, RRE_r1(ovl), RRE_r2(ovl)); goto ok; case 0xb938: /* SORTL */ goto unimplemented; - case 0xb939: /* DFLTCC */ goto unimplemented; + case 0xb939: s390_format_RRF_R0RR2(s390_irgen_DFLTCC, RRF4_r3(ovl), + RRF4_r1(ovl), RRF4_r2(ovl)); goto ok; case 0xb93a: /* KDSA */ goto unimplemented; case 0xb93b: s390_format_E(s390_irgen_NNPA); goto ok; case 0xb93c: s390_format_RRE_RR(s390_irgen_PPNO, RRE_r1(ovl), diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h index 912db6104..9d844beee 100644 --- a/VEX/priv/host_s390_defs.h +++ b/VEX/priv/host_s390_defs.h @@ -945,6 +945,8 @@ extern UInt s390_host_hwcaps; (s390_host_hwcaps & (VEX_HWCAPS_S390X_VXE)) #define s390_host_has_nnpa \ (s390_host_hwcaps & (VEX_HWCAPS_S390X_NNPA)) +#define s390_host_has_dflt \ + (s390_host_hwcaps & (VEX_HWCAPS_S390X_DFLT)) #endif /* ndef __VEX_HOST_S390_DEFS_H */ /*---------------------------------------------------------------*/ diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c index 4d0551c28..e6c788d0c 100644 --- a/VEX/priv/main_main.c +++ b/VEX/priv/main_main.c @@ -1824,7 +1824,8 @@ static const HChar* show_hwcaps_s390x ( UInt hwcaps ) { VEX_HWCAPS_S390X_MSA5, "msa5" }, { VEX_HWCAPS_S390X_MI2, "mi2" }, { VEX_HWCAPS_S390X_LSC2, "lsc2" }, - { VEX_HWCAPS_S390X_LSC2, "vxe" }, + { VEX_HWCAPS_S390X_VXE, "vxe" }, + { VEX_HWCAPS_S390X_DFLT, "dflt" }, }; /* Allocate a large enough buffer */ static HChar buf[sizeof prefix + diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h index 544cf0348..168107734 100644 --- a/VEX/pub/libvex.h +++ b/VEX/pub/libvex.h @@ -178,6 +178,7 @@ typedef #define VEX_HWCAPS_S390X_LSC2 (1<<21) /* Conditional load/store facility2 */ #define VEX_HWCAPS_S390X_VXE (1<<22) /* Vector-enhancements facility */ #define VEX_HWCAPS_S390X_NNPA (1<<23) /* NNPA facility */ +#define VEX_HWCAPS_S390X_DFLT (1<<24) /* Deflate-conversion facility */ /* Special value representing all available s390x hwcaps */ #define VEX_HWCAPS_S390X_ALL (VEX_HWCAPS_S390X_LDISP | \ @@ -197,7 +198,8 @@ typedef VEX_HWCAPS_S390X_MI2 | \ VEX_HWCAPS_S390X_LSC2 | \ VEX_HWCAPS_S390X_VXE | \ - VEX_HWCAPS_S390X_NNPA) + VEX_HWCAPS_S390X_NNPA | \ + VEX_HWCAPS_S390X_DFLT) #define VEX_HWCAPS_S390X(x) ((x) & ~VEX_S390X_MODEL_MASK) #define VEX_S390X_MODEL(x) ((x) & VEX_S390X_MODEL_MASK) diff --git a/VEX/pub/libvex_s390x_common.h b/VEX/pub/libvex_s390x_common.h index 4ed848c5c..9b1168a4e 100644 --- a/VEX/pub/libvex_s390x_common.h +++ b/VEX/pub/libvex_s390x_common.h @@ -118,6 +118,7 @@ #define S390_EXT_PRNO 1 #define S390_EXT_NNPA 2 +#define S390_EXT_DFLT 3 /*--------------------------------------------------------------*/ /*--- Miscellaneous ---*/ diff --git a/coregrind/m_extension/extension-s390x.c b/coregrind/m_extension/extension-s390x.c index 735406e6e..95116587c 100644 --- a/coregrind/m_extension/extension-s390x.c +++ b/coregrind/m_extension/extension-s390x.c @@ -585,6 +585,172 @@ static enum ExtensionError do_extension_NNPA(ThreadState* tst, ULong variant) return ExtErr_OK; } +/*---------------------------------------------------------------*/ +/*--- DFLTCC (deflate conversion call) ---*/ +/*---------------------------------------------------------------*/ + +static Int do_DFLTCC_insn(UChar func, + ULong parms, + ULong* addr1, + ULong* len1, + ULong* addr2, + ULong* len2, + ULong addr3) +{ + register UChar reg0 asm("0") = func; + register void* reg1 asm("1") = (void*)parms; + union reg_pair op1 = {{*addr1, *len1}}; + union reg_pair op2 = {{*addr2, *len2}}; + Int cc; + + asm volatile(".insn rrf, 0xb9390000, %[op1], %[op2], %[op3], 0\n" + "ipm %[cc]\n" + "srl %[cc], 28\n" + : [cc] "=d"(cc), [op1] "+a"(op1.pair), [op2] "+a"(op2.pair) + : "d"(reg0), "d"(reg1), [op3] "d"(addr3) + : "cc", "memory"); + *addr1 = op1.a; + *len1 = op1.b; + *addr2 = op2.a; + *len2 = op2.b; + return cc; +} + +struct s390_DFLTCC_parms0 { + UShort pbvn; + UChar mvn; + UChar ribm[3]; + UShort reserved0 : 15; + UShort cf : 1; + ULong reserved1; + UShort nt : 1; + UShort reserved2 : 1; + UShort cvt : 1; + UShort reserved3 : 1; + UShort htt : 1; + UShort bcf : 1; + UShort bcc : 1; + UShort bhf : 1; + UShort reserved4 : 1; + UShort reserved5 : 1; + UShort dhtgc : 1; + UShort reserved6 : 5; + UChar reserved7 : 5; + UChar sbb : 3; + UChar oesc : 8; + UShort reserved8 : 12; + UShort ifs : 4; + UShort ifl; + UChar reserved9[20]; + UShort hl; + UShort reserved10 : 1; + UShort ho : 15; + UChar data[1488]; +}; + +/* DFLTCC functions that we support if the hardware does. */ +static const ULong DFLTCC_functions[] = { + (S390_SETBIT(0) // Query + | S390_SETBIT(1) // GDHT + | S390_SETBIT(2) // CMPR + | S390_SETBIT(4)), // XPND +}; + +static UWord do_extension_DFLTCC(ThreadState* tst, ULong variant) +{ + enum { circ_hist_len = 32768 }; + UChar r1 = variant & 0xf; + UChar r2 = (variant >> 4) & 0xf; + UChar r3 = (variant >> 8) & 0xf; + UChar func = READ_FUNCTION_CODE(tst, "DFLTCC"); + UChar fc = func & 0x7f; + Bool hbt = (func & 128) != 0; + ULong parms = READ_GPR(tst, "DFLTCC(r1)", 1); + ULong parms_len; + Int cc = 0; + ULong orig_addr1 = 0, orig_len1 = 0; + ULong addr1 = 0, len1 = 0, addr2 = 0, len2 = 0, addr3 = 0; + Bool do_compress = 0; + + switch (fc) { + case 0: // Query + parms_len = 32; + PRE_MEM_WRITE(tst, "DFLTCC(parms)", parms, parms_len); + cc = do_DFLTCC_insn(func, parms, &addr1, &len1, &addr2, &len2, addr3); + s390_filter_functions((ULong*)parms, 16, DFLTCC_functions, + sizeof(DFLTCC_functions)); + POST_MEM_WRITE(tst, parms, parms_len); + break; + case 1: // GDHT + parms_len = 384; + PRE_MEM_READ(tst, "DFLTCC(parms)", parms, parms_len); + PRE_MEM_WRITE(tst, "DFLTCC(parms)", parms, parms_len); + addr2 = READ_GPR(tst, "DFLTCC(op2_addr)", r2); + len2 = READ_GPR(tst, "DFLTCC(op2_len)", r2 + 1); + if (len2 > 32768) + len2 = 32768; + PRE_MEM_READ(tst, "DFLTCC(parms)", addr2, len2); + cc = do_DFLTCC_insn(func, parms, &addr1, &len1, &addr2, &len2, addr3); + POST_MEM_WRITE(tst, parms, parms_len); + break; + case 2: // CMPR + do_compress = 1; + /* fallthrough */ + case 4: // XPND + { + struct s390_DFLTCC_parms0* p; + parms_len = 1536; + PRE_MEM_READ(tst, "DFLTCC(parms)", parms, parms_len); + p = (void*)parms; + addr1 = orig_addr1 = READ_GPR(tst, "DFLTCC(op1_addr)", r1); + len1 = orig_len1 = READ_GPR(tst, "DFLTCC(op1_len)", r1 + 1); + PRE_MEM_WRITE(tst, "DFLTCC(op1)", addr1, len1); + addr2 = READ_GPR(tst, "DFLTCC(op2_addr)", r2); + len2 = READ_GPR(tst, "DFLTCC(op2_len)", r2 + 1); + PRE_MEM_READ(tst, "DFLTCC(op2)", addr2, len2); + addr3 = READ_GPR(tst, "DFLTCC(op3)", r3); + if (hbt) { + PRE_MEM_WRITE(tst, "DFLTCC(op3)", addr3, circ_hist_len); + } + if (!p->nt) { + if (hbt) { + ULong hl1 = circ_hist_len - p->ho; + if (hl1 >= p->hl) { + hl1 = p->hl; + } else { + PRE_MEM_READ(tst, "DFLTCC(op3)", addr3, p->hl - hl1); + } + PRE_MEM_READ(tst, "DFLTCC(op3)", addr3 + p->ho, hl1); + } else { + PRE_MEM_READ(tst, "DFLTCC(op2.hist)", addr2 - p->hl, p->hl); + } + } + cc = do_DFLTCC_insn(func, parms, &addr1, &len1, &addr2, &len2, addr3); + POST_MEM_WRITE(tst, parms, parms_len); + POST_MEM_WRITE(tst, orig_addr1, + orig_len1 - len1 + (do_compress && p->sbb ? 1 : 0)); + if (hbt) { + ULong hl1 = circ_hist_len - p->ho; + if (hl1 >= p->hl) { + hl1 = p->hl; + } else { + POST_MEM_WRITE(tst, addr3, p->hl - hl1); + } + POST_MEM_WRITE(tst, addr3 + p->ho, hl1); + } + WRITE_GPR(tst, r1, addr1); + WRITE_GPR(tst, r1 + 1, len1); + WRITE_GPR(tst, r2, addr2); + WRITE_GPR(tst, r2 + 1, len2); + break; + } + default: + return INSN_ERR("DFLTCC: unknown function code\n"); + } + WRITE_CC(tst, cc); + return ExtErr_OK; +} + /*---------------------------------------------------------------*/ /*--- Main function: select and call appropriate extension ---*/ /*---------------------------------------------------------------*/ @@ -600,6 +766,8 @@ enum ExtensionError ML_(do_client_extension)(ThreadState* tst) return do_extension_PRNO(tst, variant); case S390_EXT_NNPA: return do_extension_NNPA(tst, variant); + case S390_EXT_DFLT: + return do_extension_DFLTCC(tst, variant); default: VG_(core_panic)("unknown extension ID"); } diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c index c92c3cfb2..5f35637d7 100644 --- a/coregrind/m_initimg/initimg-linux.c +++ b/coregrind/m_initimg/initimg-linux.c @@ -722,6 +722,7 @@ Addr setup_client_stack( void* init_sp, | VKI_HWCAP_S390_VXRS | VKI_HWCAP_S390_VXRS_EXT | VKI_HWCAP_S390_VXRS_EXT2 + | VKI_HWCAP_S390_DFLT | VKI_HWCAP_S390_NNPA); } # elif defined(VGP_arm64_linux) diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index 36db3ab9c..234efb312 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -1597,6 +1597,7 @@ Bool VG_(machine_get_hwcaps)( void ) { False, S390_FAC_MI2, VEX_HWCAPS_S390X_MI2, "MI2" }, { False, S390_FAC_LSC2, VEX_HWCAPS_S390X_LSC2, "LSC2" }, { False, S390_FAC_VXE, VEX_HWCAPS_S390X_VXE, "VXE" }, + { False, S390_FAC_DFLT, VEX_HWCAPS_S390X_DFLT, "DFLT" }, { False, S390_FAC_NNPA, VEX_HWCAPS_S390X_NNPA, "NNPA" }, }; diff --git a/docs/internals/s390-opcodes.csv b/docs/internals/s390-opcodes.csv index a65ceea31..97eb66bee 100644 --- a/docs/internals/s390-opcodes.csv +++ b/docs/internals/s390-opcodes.csv @@ -1743,7 +1743,7 @@ wcfeb,"vector fp convert to fixed 32 bit",implemented,arch13 vclfp,"vector fp convert to logical",implemented,arch13 vclfeb,"vector fp convert to logical 32 bit",implemented,arch13 wclfeb,"vector fp convert to logical 32 bit",implemented,arch13 -dfltcc,"deflate conversion call","not implemented",arch13 +dfltcc,"deflate conversion call",implemented,arch13 sortl,"sort lists","not implemented",arch13 kdsa,"compute digital signature authentication","not implemented",arch13 vschp,"decimal scale and convert to hfp","not implemented",arch14 diff --git a/include/vki/vki-s390x-linux.h b/include/vki/vki-s390x-linux.h index 829382f7b..726f068a0 100644 --- a/include/vki/vki-s390x-linux.h +++ b/include/vki/vki-s390x-linux.h @@ -809,6 +809,7 @@ typedef vki_s390_regs vki_elf_gregset_t; #define VKI_HWCAP_S390_VXRS 2048 #define VKI_HWCAP_S390_VXRS_EXT 8192 #define VKI_HWCAP_S390_VXRS_EXT2 32768 +#define VKI_HWCAP_S390_DFLT (1<<18) #define VKI_HWCAP_S390_NNPA (1<<20)