diff options
author | Denys Vlasenko <dvlasenk@redhat.com> | 2015-09-20 10:03:10 -0400 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2015-09-20 10:19:01 -0400 |
commit | a58e2ecd019d9ffb9f1813faf6151716fdecbae5 (patch) | |
tree | 0e586e76d7d5047d185c77b81168a94f2b94a88d /tools | |
parent | 9a9d8642d03a7512f78cbe7ed6a2011fad3cbca3 (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/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/x86/test_FISTTP.c | 137 |
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 | ||
7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt | 7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt |
8 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \ | 8 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault sigreturn \ |
9 | test_FCMOV test_FCOMI | 9 | test_FCMOV test_FCOMI test_FISTTP |
10 | 10 | ||
11 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) | 11 | TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) |
12 | BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32) | 12 | BINARIES_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 | |||
16 | unsigned long long res64 = -1; | ||
17 | unsigned int res32 = -1; | ||
18 | unsigned short res16 = -1; | ||
19 | |||
20 | int 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 | |||
111 | void sighandler(int sig) | ||
112 | { | ||
113 | printf("[FAIL]\tGot signal %d, exiting\n", sig); | ||
114 | exit(1); | ||
115 | } | ||
116 | |||
117 | int 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 | } | ||