/* Number of arguments that can be passed in registers */
#define S390_NUM_GPRPARMS 5
-/* Number of double words needed to store all facility bits. */
-#define S390_NUM_FACILITY_DW 4
-
#endif /* __LIBVEX_PUB_S390X_H */
/*--------------------------------------------------------------------*/
VG_(exit)(1);
}
- ULong hoststfle[S390_NUM_FACILITY_DW];
+ /* Get number of double words to store all facilities */
+ unsigned long long dummy[1];
- for (i = 0; i < S390_NUM_FACILITY_DW; ++i)
- hoststfle[i] = 0;
+ register ULong r0 asm("0") = 0;
+ asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
+ : "=Q" (dummy), "+d"(r0)
+ :
+ : "cc", "memory");
+ UInt num_dw = r0 + 1;
+
+ /* Get the facility bits */
+ ULong hoststfle[num_dw];
- register ULong reg0 asm("0") = S390_NUM_FACILITY_DW - 1;
+ for (i = 0; i < num_dw; ++i)
+ hoststfle[i] = 0;
__asm__(".insn s,0xb2b00000,%0" /* stfle */
- : "=Q"(hoststfle), "+d"(reg0)
+ : "=Q"(hoststfle), "+d"(r0)
:
: "cc");
UChar dw_number = 0;
UChar fac_bit = 0;
for (i=0; i < sizeof fac_hwcaps / sizeof fac_hwcaps[0]; ++i) {
- vg_assert(fac_hwcaps[i].facility_bit <= 191); // for now
dw_number = fac_hwcaps[i].facility_bit / 64;
fac_bit = fac_hwcaps[i].facility_bit % 64;
if (hoststfle[dw_number] & (1ULL << (63 - fac_bit))) {
#include <stdio.h>
+#include <assert.h>
-/* Number of double words needed to store all facility bits. */
-#define S390_NUM_FACILITY_DW 4
+/* Return the number of double words needed to store all facility bits */
+static unsigned get_num_facility_dw(void)
+{
+ unsigned long long dummy[1];
+ register unsigned long long r0 asm("0") = 0;
+ asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
+ : "=Q" (dummy), "+d"(r0)
+ :
+ : "cc", "memory");
+ return r0 + 1;
+}
unsigned long long stfle(unsigned long dw, unsigned bit_to_test)
{
- unsigned long long hoststfle[S390_NUM_FACILITY_DW];
+ unsigned long long hoststfle[dw];
register unsigned long long __nr asm("0") = dw - 1;
int cc;
: "=Q" (*hoststfle), "+d" (__nr), "=d" (cc) : : "cc", "memory");
printf("the value of cc is %d and #double words is %llu\n", cc, __nr + 1);
- if (bit_to_test < 64)
- return (hoststfle[0] & (1ULL << (63 - bit_to_test)));
- else if (bit_to_test < 128)
- return (hoststfle[1] & (1ULL << (63 - bit_to_test)));
- else if (bit_to_test < 192)
- return (hoststfle[2] & (1ULL << (63 - bit_to_test)));
-
- printf("code needs to be updated\n");
- return 0;
+
+ for (unsigned i = 0; i < dw; ++i) {
+ if (bit_to_test < (i + 1) * 64) {
+ bit_to_test -= i * 64;
+ return (hoststfle[i] & (1ULL << (63 - bit_to_test)));
+ }
+ }
+ assert(0);
}
-int main()
+int main(void)
{
- int dw = S390_NUM_FACILITY_DW;
+ int dw = get_num_facility_dw();
/* Test #1: Make sure STFLE returns sensible values. z/Arch facilities
must be present. */
else
printf("STFLE facility is not installed\n");
+ /* Test #2.1: Test facility 77 which is installed for z196 and later */
+ if (stfle(dw, 77))
+ printf("Facility 77 is installed\n");
+ else
+ printf("Facility 77 is not installed\n");
+
/* Test #3: Tell STFLE to only write 1 DW of facility bits. Expected condition
code should be 3 because this test is run on those machines only
that need 3 do double words to store facility bits. */
The z/Architecture architectural mode is installed and active
the value of cc is 0 and #double words is 3
STFLE facility is installed
+the value of cc is 0 and #double words is 3
+Facility 77 is installed
the value of cc is 3 and #double words is 3
the value of cc is 3 and #double words is 3
The z/Architecture architectural mode is installed and active
The z/Architecture architectural mode is installed and active
the value of cc is 0 and #double words is 4
STFLE facility is installed
+the value of cc is 0 and #double words is 4
+Facility 77 is installed
the value of cc is 3 and #double words is 4
the value of cc is 3 and #double words is 4
The z/Architecture architectural mode is installed and active
#define GET_HWCAP() 0UL
#endif
-/* Number of double words needed to store all facility bits. */
-#define S390_NUM_FACILITY_DW 3
+/* Return the number of double words needed to store all facility bits */
+static unsigned get_num_facility_dw(void)
+{
+ unsigned long long facilities[1];
-static void clear_facilities(unsigned long long *ret)
+ register unsigned long long r0 asm("0") = 0;
+ asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
+ : "=Q" (facilities), "+d"(r0)
+ :
+ : "cc", "memory");
+ return r0 + 1;
+}
+
+static void clear_facilities(unsigned long long *ret, unsigned num_dw)
{
unsigned int index;
- for(index = 0; index < S390_NUM_FACILITY_DW; index++)
+ for(index = 0; index < num_dw; index++)
{
ret[index] = 0ULL;
}
}
-void stfle(unsigned long long *ret)
+void stfle(unsigned long long *ret, unsigned num_dw)
{
- register unsigned long long r0 asm("0") = S390_NUM_FACILITY_DW - 1;
+ register unsigned long long r0 asm("0") = num_dw - 1;
asm volatile(".insn s,0xb2b00000,%0\n" /* stfle */
- : "=m" (*ret), "+d"(r0) :: "cc", "memory");
+ : "=Q" (*ret), "+d"(r0) :: "cc", "memory");
}
static int go(char *feature, char *cpu)
{
- unsigned long long facilities[S390_NUM_FACILITY_DW];
unsigned long long match;
model_info *host, *from, *to, *p;
char *colon;
- clear_facilities(facilities);
- stfle(facilities);
+ unsigned num_dw = get_num_facility_dw();
+ unsigned long long facilities[num_dw];
+
+ clear_facilities(facilities, num_dw);
+ stfle(facilities, num_dw);
if (strcmp(feature, "s390x-vx") == 0 ) {
/* VX needs kernel support; thus check the appropriate HWCAP bit. */