|
From: <sv...@va...> - 2011-05-17 16:20:01
|
Author: sewardj
Date: 2011-05-17 17:19:53 +0100 (Tue, 17 May 2011)
New Revision: 11766
Log:
s390x: add test cases for STCK{,E,F} instructions. See #271779.
(Christian Borntraeger <bor...@de...> and Divya Vyas)
Added:
trunk/none/tests/s390x/stck.c
trunk/none/tests/s390x/stck.stderr.exp
trunk/none/tests/s390x/stck.stdout.exp
trunk/none/tests/s390x/stck.vgtest
trunk/none/tests/s390x/stcke.c
trunk/none/tests/s390x/stcke.stderr.exp
trunk/none/tests/s390x/stcke.stdout.exp
trunk/none/tests/s390x/stcke.vgtest
trunk/none/tests/s390x/stckf.c
trunk/none/tests/s390x/stckf.stderr.exp
trunk/none/tests/s390x/stckf.stdout.exp
trunk/none/tests/s390x/stckf.vgtest
trunk/tests/s390x_features.c
Modified:
trunk/none/tests/s390x/Makefile.am
trunk/tests/Makefile.am
Modified: trunk/none/tests/s390x/Makefile.am
===================================================================
--- trunk/none/tests/s390x/Makefile.am 2011-05-17 16:07:33 UTC (rev 11765)
+++ trunk/none/tests/s390x/Makefile.am 2011-05-17 16:19:53 UTC (rev 11766)
@@ -5,7 +5,7 @@
INSN_TESTS = clc clcle cvb cvd icm lpr tcxb lam_stam xc mvst add sub mul \
and or xor insert div srst fold_And16 flogr sub_EI add_EI \
and_EI or_EI xor_EI insert_EI mul_GE add_GE condloadstore \
- op_exception fgx
+ op_exception fgx stck stckf stcke
check_PROGRAMS = $(INSN_TESTS) \
ex_sig \
Added: trunk/none/tests/s390x/stck.c
===================================================================
--- trunk/none/tests/s390x/stck.c (rev 0)
+++ trunk/none/tests/s390x/stck.c 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,41 @@
+#include<stdio.h>
+#include<time.h>
+#include<stdlib.h>
+#include<unistd.h>
+
+int stck(unsigned long *addr)
+{
+ int cc;
+ asm volatile ( "stck %0\n"
+ "ipm %1\n"
+ "srl %1,28\n"
+ :"=Q" (*addr), "=d"(cc)::"memory", "cc");
+ return cc;
+}
+
+unsigned long clockticks_in_msec(unsigned long b, unsigned long a)
+{
+ return (b - a) / 4096000UL;
+}
+
+int main()
+{
+
+ int cc;
+ unsigned long start, end, diff;
+
+ cc = stck(&start);
+ if (cc)
+ printf("cc != 0!\n");
+ sleep(1);
+ cc = stck(&end);
+ if (cc)
+ printf("cc != 0!\n");
+ diff = clockticks_in_msec(end, start);
+ if (diff >= 1000 && diff < 1500)
+ printf("OK.....Testcase passed\n");
+ else
+ printf("FAILED.....Testcase failed\n");
+ return 0;
+
+}
Added: trunk/none/tests/s390x/stck.stderr.exp
===================================================================
--- trunk/none/tests/s390x/stck.stderr.exp (rev 0)
+++ trunk/none/tests/s390x/stck.stderr.exp 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,2 @@
+
+
Added: trunk/none/tests/s390x/stck.stdout.exp
===================================================================
--- trunk/none/tests/s390x/stck.stdout.exp (rev 0)
+++ trunk/none/tests/s390x/stck.stdout.exp 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1 @@
+OK.....Testcase passed
Added: trunk/none/tests/s390x/stck.vgtest
===================================================================
--- trunk/none/tests/s390x/stck.vgtest (rev 0)
+++ trunk/none/tests/s390x/stck.vgtest 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1 @@
+prog:stck
Added: trunk/none/tests/s390x/stcke.c
===================================================================
--- trunk/none/tests/s390x/stcke.c (rev 0)
+++ trunk/none/tests/s390x/stcke.c 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,56 @@
+#include <stdio.h>
+#include<stdlib.h>
+#include<unistd.h>
+
+union stcke {
+ unsigned long buffer[2];
+ struct reader {
+ char pad;
+ unsigned long long time;
+ int time2;
+ short program;
+ } __attribute__ ((packed)) reader;
+};
+
+int stcke(unsigned long *addr)
+{
+
+ int cc;
+ asm volatile ( "stcke %0\n"
+ "ipm %1\n"
+ "srl %1, 28\n"
+ :"+Q" (*addr), "=d"(cc)::"cc");
+
+ return cc;
+}
+
+unsigned long clockticks_in_msec(unsigned long b, unsigned long a)
+{
+ return (b -a ) / 4096000UL;
+}
+
+int main()
+{
+ union stcke start, end;
+ int cc;
+
+ cc = stcke(start.buffer);
+ if (cc)
+ printf("cc != 0!\n");
+
+ sleep(1);
+ cc = stcke(end.buffer);
+ if (cc)
+ printf("cc != 0!\n");
+
+ unsigned long c = clockticks_in_msec(end.reader.time,
+ start.reader.time);
+
+ if (c >= 1000 && c < 1500)
+ printf("OK.....Testcase passed\n");
+ else
+ printf("FAILED.....Testcase failed\n");
+
+ return 0;
+
+}
Added: trunk/none/tests/s390x/stcke.stderr.exp
===================================================================
--- trunk/none/tests/s390x/stcke.stderr.exp (rev 0)
+++ trunk/none/tests/s390x/stcke.stderr.exp 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,2 @@
+
+
Added: trunk/none/tests/s390x/stcke.stdout.exp
===================================================================
--- trunk/none/tests/s390x/stcke.stdout.exp (rev 0)
+++ trunk/none/tests/s390x/stcke.stdout.exp 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1 @@
+OK.....Testcase passed
Added: trunk/none/tests/s390x/stcke.vgtest
===================================================================
--- trunk/none/tests/s390x/stcke.vgtest (rev 0)
+++ trunk/none/tests/s390x/stcke.vgtest 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1 @@
+prog:stcke
Added: trunk/none/tests/s390x/stckf.c
===================================================================
--- trunk/none/tests/s390x/stckf.c (rev 0)
+++ trunk/none/tests/s390x/stckf.c 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,42 @@
+#include<stdio.h>
+#include<time.h>
+#include<stdlib.h>
+#include<unistd.h>
+
+int stckf(unsigned long *addr)
+{
+ int cc;
+ asm volatile ( ".insn s,0xb27c0000,%0\n"
+ "ipm %1\n"
+ "srl %1,28\n"
+ :"=Q" (*addr), "=d"(cc)::"memory", "cc");
+ return cc;
+}
+
+unsigned long clockticks_in_msec(unsigned long b, unsigned long a)
+{
+ return (b - a) / 4096000UL;
+}
+
+int main()
+{
+
+ int cc;
+ unsigned long start, end, diff;
+
+ cc = stckf(&start);
+ if (cc)
+ printf("cc != 0!\n");
+ sleep(1);
+ cc = stckf(&end);
+ if (cc)
+ printf("cc != 0!\n");
+
+ diff = clockticks_in_msec(end, start);
+ if (diff >= 1000 && diff < 1500)
+ printf("OK.....Testcase passed\n");
+ else
+ printf("FAILED.....Testcase failed\n");
+ return 0;
+
+}
Added: trunk/none/tests/s390x/stckf.stderr.exp
===================================================================
--- trunk/none/tests/s390x/stckf.stderr.exp (rev 0)
+++ trunk/none/tests/s390x/stckf.stderr.exp 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,2 @@
+
+
Added: trunk/none/tests/s390x/stckf.stdout.exp
===================================================================
--- trunk/none/tests/s390x/stckf.stdout.exp (rev 0)
+++ trunk/none/tests/s390x/stckf.stdout.exp 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1 @@
+OK.....Testcase passed
Added: trunk/none/tests/s390x/stckf.vgtest
===================================================================
--- trunk/none/tests/s390x/stckf.vgtest (rev 0)
+++ trunk/none/tests/s390x/stckf.vgtest 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,2 @@
+prog:stckf
+prereq: ../../../tests/s390x_features s390x-stckf
Modified: trunk/tests/Makefile.am
===================================================================
--- trunk/tests/Makefile.am 2011-05-17 16:07:33 UTC (rev 11765)
+++ trunk/tests/Makefile.am 2011-05-17 16:19:53 UTC (rev 11766)
@@ -21,7 +21,8 @@
arch_test \
os_test \
true \
- x86_amd64_features
+ x86_amd64_features \
+ s390x_features
AM_CFLAGS += $(AM_FLAG_M3264_PRI)
AM_CXXFLAGS += $(AM_FLAG_M3264_PRI)
Added: trunk/tests/s390x_features.c
===================================================================
--- trunk/tests/s390x_features.c (rev 0)
+++ trunk/tests/s390x_features.c 2011-05-17 16:19:53 UTC (rev 11766)
@@ -0,0 +1,93 @@
+#include <setjmp.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+// This file determines s390x features a processor supports.
+//
+// We return:
+// - 0 if the machine matches the asked-for feature.
+// - 1 if the machine does not.
+// - 2 if the asked-for feature isn't recognised (this will be the case for
+// any feature if run on a non-s390x machine).
+// - 3 if there was a usage error (it also prints an error message).
+
+jmp_buf env;
+
+#if defined(VGA_s390x)
+
+void handle_sigill(int signum)
+{
+ longjmp(env, 1);
+}
+
+unsigned long long stfle(void)
+{
+
+ unsigned long long ret;
+
+ signal(SIGILL, handle_sigill);
+ if (setjmp(env)) {
+ /* stfle not available: assume no facilities */
+ return 0;
+ } else {
+ asm volatile("lghi 0, 0\n"
+ ".insn s,0xb2b00000,%0\n" /* stfle */
+ : "=Q" (ret)::"0", "cc");
+ return ret;
+ }
+}
+
+static int go(char* cpu)
+{
+ unsigned long long facilities;
+ unsigned long long match;
+
+ facilities = stfle();
+
+ if (strcmp(cpu, "s390x-zarch") == 0 ) {
+ match = (facilities & (1ULL << 62) && (facilities & (1ULL << 61)));
+ } else if (strcmp(cpu, "s390x-n3") == 0 ) {
+ match = (facilities & (1ULL << 63));
+ } else if (strcmp(cpu, "s390x-stfle") == 0 ) {
+ match = (facilities & (1ULL << 56));
+ } else if (strcmp(cpu, "s390x-ldisp") == 0 ) {
+ match = (facilities & (1ULL << 45) && (facilities & (1ULL << 44)));
+ } else if (strcmp(cpu, "s390x-eimm") == 0 ) {
+ match = (facilities & (1ULL << 42));
+ } else if (strcmp(cpu, "s390x-stckf") == 0 ) {
+ match = (facilities & (1ULL << 38));
+ } else if (strcmp(cpu, "s390x-genins") == 0 ) {
+ match = (facilities & (1ULL << 29));
+ } else if (strcmp(cpu, "s390x-exrl") == 0 ) {
+ match = (facilities & (1ULL << 28));
+ } else {
+ return 2; // Unrecognised feature.
+ }
+
+ return match == 0;
+}
+
+#else
+
+static int go(char* cpu)
+{
+ return 2; // Feature not recognised (non-s390x machine!)
+}
+
+#endif
+
+
+//---------------------------------------------------------------------------
+// main
+//---------------------------------------------------------------------------
+int main(int argc, char **argv)
+{
+ if ( argc != 2 ) {
+ fprintf( stderr, "usage: s390x_features <feature>\n" );
+ exit(3); // Usage error.
+ }
+ return go(argv[1]);
+}
|