aboutsummaryrefslogtreecommitdiffstats
path: root/tools
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2015-09-20 10:03:10 -0400
committerIngo Molnar <mingo@kernel.org>2015-09-20 10:19:01 -0400
commita58e2ecd019d9ffb9f1813faf6151716fdecbae5 (patch)
tree0e586e76d7d5047d185c77b81168a94f2b94a88d /tools
parent9a9d8642d03a7512f78cbe7ed6a2011fad3cbca3 (diff)
x86/fpu/math-emu, selftests: Add test for FISTTP instructions
$ ./test_FISTTP_32 [RUN] Testing fisttp instructions [OK] fisttp Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Kees Cook <keescook@chromium.org> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Shuah Khan <shuahkh@osg.samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: linux-kernel@vger.kernel.org Link: http://lkml.kernel.org/r/1442757790-27233-1-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
Diffstat (limited to 'tools')
-rw-r--r--tools/testing/selftests/x86/Makefile2
-rw-r--r--tools/testing/selftests/x86/test_FISTTP.c137
2 files changed, 138 insertions, 1 deletions
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index c4c9b9088998..7145b3d9030c 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -6,7 +6,7 @@ include ../lib.mk
6 6
7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt 7TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt
8TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \ 8TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \
9 test_FCMOV test_FCOMI 9 test_FCMOV test_FCOMI test_FISTTP
10 10
11TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 11TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
12BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) 12BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
diff --git a/tools/testing/selftests/x86/test_FISTTP.c b/tools/testing/selftests/x86/test_FISTTP.c
new file mode 100644
index 000000000000..b8e61a047f6b
--- /dev/null
+++ b/tools/testing/selftests/x86/test_FISTTP.c
@@ -0,0 +1,137 @@
1#undef _GNU_SOURCE
2#define _GNU_SOURCE 1
3#undef __USE_GNU
4#define __USE_GNU 1
5#include <unistd.h>
6#include <stdlib.h>
7#include <string.h>
8#include <stdio.h>
9#include <signal.h>
10#include <sys/types.h>
11#include <sys/select.h>
12#include <sys/time.h>
13#include <sys/wait.h>
14#include <fenv.h>
15
16unsigned long long res64 = -1;
17unsigned int res32 = -1;
18unsigned short res16 = -1;
19
20int test(void)
21{
22 int ex;
23
24 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
25 asm volatile ("\n"
26 " fld1""\n"
27 " fisttp res16""\n"
28 " fld1""\n"
29 " fisttpl res32""\n"
30 " fld1""\n"
31 " fisttpll res64""\n"
32 : : : "memory"
33 );
34 if (res16 != 1 || res32 != 1 || res64 != 1) {
35 printf("[BAD]\tfisttp 1\n");
36 return 1;
37 }
38 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
39 if (ex != 0) {
40 printf("[BAD]\tfisttp 1: wrong exception state\n");
41 return 1;
42 }
43
44 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
45 asm volatile ("\n"
46 " fldpi""\n"
47 " fisttp res16""\n"
48 " fldpi""\n"
49 " fisttpl res32""\n"
50 " fldpi""\n"
51 " fisttpll res64""\n"
52 : : : "memory"
53 );
54 if (res16 != 3 || res32 != 3 || res64 != 3) {
55 printf("[BAD]\tfisttp pi\n");
56 return 1;
57 }
58 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
59 if (ex != FE_INEXACT) {
60 printf("[BAD]\tfisttp pi: wrong exception state\n");
61 return 1;
62 }
63
64 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
65 asm volatile ("\n"
66 " fldpi""\n"
67 " fchs""\n"
68 " fisttp res16""\n"
69 " fldpi""\n"
70 " fchs""\n"
71 " fisttpl res32""\n"
72 " fldpi""\n"
73 " fchs""\n"
74 " fisttpll res64""\n"
75 : : : "memory"
76 );
77 if (res16 != 0xfffd || res32 != 0xfffffffd || res64 != 0xfffffffffffffffdULL) {
78 printf("[BAD]\tfisttp -pi\n");
79 return 1;
80 }
81 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
82 if (ex != FE_INEXACT) {
83 printf("[BAD]\tfisttp -pi: wrong exception state\n");
84 return 1;
85 }
86
87 feclearexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
88 asm volatile ("\n"
89 " fldln2""\n"
90 " fisttp res16""\n"
91 " fldln2""\n"
92 " fisttpl res32""\n"
93 " fldln2""\n"
94 " fisttpll res64""\n"
95 : : : "memory"
96 );
97 /* Test truncation to zero (round-to-nearest would give 1 here) */
98 if (res16 != 0 || res32 != 0 || res64 != 0) {
99 printf("[BAD]\tfisttp ln2\n");
100 return 1;
101 }
102 ex = fetestexcept(FE_DIVBYZERO|FE_INEXACT|FE_INVALID|FE_OVERFLOW|FE_UNDERFLOW);
103 if (ex != FE_INEXACT) {
104 printf("[BAD]\tfisttp ln2: wrong exception state\n");
105 return 1;
106 }
107
108 return 0;
109}
110
111void sighandler(int sig)
112{
113 printf("[FAIL]\tGot signal %d, exiting\n", sig);
114 exit(1);
115}
116
117int main(int argc, char **argv, char **envp)
118{
119 int err = 0;
120
121 /* SIGILL triggers on 32-bit kernels w/o fisttp emulation
122 * when run with "no387 nofxsr". Other signals are caught
123 * just in case.
124 */
125 signal(SIGILL, sighandler);
126 signal(SIGFPE, sighandler);
127 signal(SIGSEGV, sighandler);
128
129 printf("[RUN]\tTesting fisttp instructions\n");
130 err |= test();
131 if (!err)
132 printf("[OK]\tfisttp\n");
133 else
134 printf("[FAIL]\tfisttp errors: %d\n", err);
135
136 return err;
137}