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

selftests/x86: Consolidate and fix get/set_eflags() helpers

There are several copies of get_eflags() and set_eflags() and they all are
buggy. Consolidate them and fix them. The fixes are:

Add memory clobbers. These are probably unnecessary but they make sure
that the compiler doesn't move something past one of these calls when it
shouldn't.

Respect the redzone on x86_64. There has no failure been observed related
to this, but it's definitely a bug.

Signed-off-by: Andy Lutomirski <luto@kernel.org>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/982ce58ae8dea2f1e57093ee894760e35267e751.1593191971.git.luto@kernel.org

authored by

Andy Lutomirski and committed by
Thomas Gleixner
cced0b24 a61fa279

+51 -90
+2 -2
tools/testing/selftests/x86/Makefile
··· 70 70 71 71 EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64) 72 72 73 - $(BINARIES_32): $(OUTPUT)/%_32: %.c 73 + $(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h 74 74 $(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm 75 75 76 - $(BINARIES_64): $(OUTPUT)/%_64: %.c 76 + $(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h 77 77 $(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl 78 78 79 79 # x86_64 users should be encouraged to install 32-bit libraries
+41
tools/testing/selftests/x86/helpers.h
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + #ifndef __SELFTESTS_X86_HELPERS_H 3 + #define __SELFTESTS_X86_HELPERS_H 4 + 5 + #include <asm/processor-flags.h> 6 + 7 + static inline unsigned long get_eflags(void) 8 + { 9 + unsigned long eflags; 10 + 11 + asm volatile ( 12 + #ifdef __x86_64__ 13 + "subq $128, %%rsp\n\t" 14 + "pushfq\n\t" 15 + "popq %0\n\t" 16 + "addq $128, %%rsp" 17 + #else 18 + "pushfl\n\t" 19 + "popl %0" 20 + #endif 21 + : "=r" (eflags) :: "memory"); 22 + 23 + return eflags; 24 + } 25 + 26 + static inline void set_eflags(unsigned long eflags) 27 + { 28 + asm volatile ( 29 + #ifdef __x86_64__ 30 + "subq $128, %%rsp\n\t" 31 + "pushq %0\n\t" 32 + "popfq\n\t" 33 + "addq $128, %%rsp" 34 + #else 35 + "pushl %0\n\t" 36 + "popfl" 37 + #endif 38 + :: "r" (eflags) : "flags", "memory"); 39 + } 40 + 41 + #endif /* __SELFTESTS_X86_HELPERS_H */
+2 -15
tools/testing/selftests/x86/single_step_syscall.c
··· 31 31 #include <sys/ptrace.h> 32 32 #include <sys/user.h> 33 33 34 + #include "helpers.h" 35 + 34 36 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 35 37 int flags) 36 38 { ··· 68 66 # define WIDTH "l" 69 67 # define INT80_CLOBBERS 70 68 #endif 71 - 72 - static unsigned long get_eflags(void) 73 - { 74 - unsigned long eflags; 75 - asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags)); 76 - return eflags; 77 - } 78 - 79 - static void set_eflags(unsigned long eflags) 80 - { 81 - asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH 82 - : : "rm" (eflags) : "flags"); 83 - } 84 - 85 - #define X86_EFLAGS_TF (1UL << 8) 86 69 87 70 static void sigtrap(int sig, siginfo_t *info, void *ctx_void) 88 71 {
+1 -20
tools/testing/selftests/x86/syscall_arg_fault.c
··· 15 15 #include <setjmp.h> 16 16 #include <errno.h> 17 17 18 - #ifdef __x86_64__ 19 - # define WIDTH "q" 20 - #else 21 - # define WIDTH "l" 22 - #endif 18 + #include "helpers.h" 23 19 24 20 /* Our sigaltstack scratch space. */ 25 21 static unsigned char altstack_data[SIGSTKSZ]; 26 - 27 - static unsigned long get_eflags(void) 28 - { 29 - unsigned long eflags; 30 - asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags)); 31 - return eflags; 32 - } 33 - 34 - static void set_eflags(unsigned long eflags) 35 - { 36 - asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH 37 - : : "rm" (eflags) : "flags"); 38 - } 39 - 40 - #define X86_EFLAGS_TF (1UL << 8) 41 22 42 23 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 43 24 int flags)
+1 -19
tools/testing/selftests/x86/syscall_nt.c
··· 13 13 #include <signal.h> 14 14 #include <err.h> 15 15 #include <sys/syscall.h> 16 - #include <asm/processor-flags.h> 17 16 18 - #ifdef __x86_64__ 19 - # define WIDTH "q" 20 - #else 21 - # define WIDTH "l" 22 - #endif 17 + #include "helpers.h" 23 18 24 19 static unsigned int nerrs; 25 - 26 - static unsigned long get_eflags(void) 27 - { 28 - unsigned long eflags; 29 - asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags)); 30 - return eflags; 31 - } 32 - 33 - static void set_eflags(unsigned long eflags) 34 - { 35 - asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH 36 - : : "rm" (eflags) : "flags"); 37 - } 38 20 39 21 static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *), 40 22 int flags)
+2 -13
tools/testing/selftests/x86/test_vsyscall.c
··· 20 20 #include <setjmp.h> 21 21 #include <sys/uio.h> 22 22 23 + #include "helpers.h" 24 + 23 25 #ifdef __x86_64__ 24 26 # define VSYS(x) (x) 25 27 #else ··· 495 493 } 496 494 497 495 #ifdef __x86_64__ 498 - #define X86_EFLAGS_TF (1UL << 8) 499 496 static volatile sig_atomic_t num_vsyscall_traps; 500 - 501 - static unsigned long get_eflags(void) 502 - { 503 - unsigned long eflags; 504 - asm volatile ("pushfq\n\tpopq %0" : "=rm" (eflags)); 505 - return eflags; 506 - } 507 - 508 - static void set_eflags(unsigned long eflags) 509 - { 510 - asm volatile ("pushq %0\n\tpopfq" : : "rm" (eflags) : "flags"); 511 - } 512 497 513 498 static void sigtrap(int sig, siginfo_t *info, void *ctx_void) 514 499 {
+2 -21
tools/testing/selftests/x86/unwind_vdso.c
··· 11 11 #include <features.h> 12 12 #include <stdio.h> 13 13 14 + #include "helpers.h" 15 + 14 16 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16 15 17 16 18 int main() ··· 54 52 if (sigaction(sig, &sa, 0)) 55 53 err(1, "sigaction"); 56 54 } 57 - 58 - #ifdef __x86_64__ 59 - # define WIDTH "q" 60 - #else 61 - # define WIDTH "l" 62 - #endif 63 - 64 - static unsigned long get_eflags(void) 65 - { 66 - unsigned long eflags; 67 - asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags)); 68 - return eflags; 69 - } 70 - 71 - static void set_eflags(unsigned long eflags) 72 - { 73 - asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH 74 - : : "rm" (eflags) : "flags"); 75 - } 76 - 77 - #define X86_EFLAGS_TF (1UL << 8) 78 55 79 56 static volatile sig_atomic_t nerrs; 80 57 static unsigned long sysinfo;