Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Denys Vlasenko and committed by
Ingo Molnar
a58e2ecd 9a9d8642

+138 -1
+1 -1
tools/testing/selftests/x86/Makefile
··· 6 6 7 7 TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs ldt_gdt syscall_nt 8 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 11 TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY) 12 12 BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
+137
tools/testing/selftests/x86/test_FISTTP.c
··· 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 + }