Skip to content

Commit

Permalink
selftests/x86: Consolidate and fix get/set_eflags() helpers
Browse files Browse the repository at this point in the history
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
  • Loading branch information
amluto authored and KAGA-KOKO committed Jul 1, 2020
1 parent a61fa27 commit cced0b2
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 90 deletions.
4 changes: 2 additions & 2 deletions tools/testing/selftests/x86/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,10 @@ all_64: $(BINARIES_64)

EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64)

$(BINARIES_32): $(OUTPUT)/%_32: %.c
$(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h
$(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm

$(BINARIES_64): $(OUTPUT)/%_64: %.c
$(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h
$(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl

# x86_64 users should be encouraged to install 32-bit libraries
Expand Down
41 changes: 41 additions & 0 deletions tools/testing/selftests/x86/helpers.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
// SPDX-License-Identifier: GPL-2.0-only
#ifndef __SELFTESTS_X86_HELPERS_H
#define __SELFTESTS_X86_HELPERS_H

#include <asm/processor-flags.h>

static inline unsigned long get_eflags(void)
{
unsigned long eflags;

asm volatile (
#ifdef __x86_64__
"subq $128, %%rsp\n\t"
"pushfq\n\t"
"popq %0\n\t"
"addq $128, %%rsp"
#else
"pushfl\n\t"
"popl %0"
#endif
: "=r" (eflags) :: "memory");

return eflags;
}

static inline void set_eflags(unsigned long eflags)
{
asm volatile (
#ifdef __x86_64__
"subq $128, %%rsp\n\t"
"pushq %0\n\t"
"popfq\n\t"
"addq $128, %%rsp"
#else
"pushl %0\n\t"
"popfl"
#endif
:: "r" (eflags) : "flags", "memory");
}

#endif /* __SELFTESTS_X86_HELPERS_H */
17 changes: 2 additions & 15 deletions tools/testing/selftests/x86/single_step_syscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include <sys/ptrace.h>
#include <sys/user.h>

#include "helpers.h"

static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
int flags)
{
Expand Down Expand Up @@ -67,21 +69,6 @@ static unsigned char altstack_data[SIGSTKSZ];
# define INT80_CLOBBERS
#endif

static unsigned long get_eflags(void)
{
unsigned long eflags;
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
return eflags;
}

static void set_eflags(unsigned long eflags)
{
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
: : "rm" (eflags) : "flags");
}

#define X86_EFLAGS_TF (1UL << 8)

static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
{
ucontext_t *ctx = (ucontext_t*)ctx_void;
Expand Down
21 changes: 1 addition & 20 deletions tools/testing/selftests/x86/syscall_arg_fault.c
Original file line number Diff line number Diff line change
Expand Up @@ -15,30 +15,11 @@
#include <setjmp.h>
#include <errno.h>

#ifdef __x86_64__
# define WIDTH "q"
#else
# define WIDTH "l"
#endif
#include "helpers.h"

/* Our sigaltstack scratch space. */
static unsigned char altstack_data[SIGSTKSZ];

static unsigned long get_eflags(void)
{
unsigned long eflags;
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
return eflags;
}

static void set_eflags(unsigned long eflags)
{
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
: : "rm" (eflags) : "flags");
}

#define X86_EFLAGS_TF (1UL << 8)

static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
int flags)
{
Expand Down
20 changes: 1 addition & 19 deletions tools/testing/selftests/x86/syscall_nt.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,29 +13,11 @@
#include <signal.h>
#include <err.h>
#include <sys/syscall.h>
#include <asm/processor-flags.h>

#ifdef __x86_64__
# define WIDTH "q"
#else
# define WIDTH "l"
#endif
#include "helpers.h"

static unsigned int nerrs;

static unsigned long get_eflags(void)
{
unsigned long eflags;
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
return eflags;
}

static void set_eflags(unsigned long eflags)
{
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
: : "rm" (eflags) : "flags");
}

static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
int flags)
{
Expand Down
15 changes: 2 additions & 13 deletions tools/testing/selftests/x86/test_vsyscall.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
#include <setjmp.h>
#include <sys/uio.h>

#include "helpers.h"

#ifdef __x86_64__
# define VSYS(x) (x)
#else
Expand Down Expand Up @@ -493,21 +495,8 @@ static int test_process_vm_readv(void)
}

#ifdef __x86_64__
#define X86_EFLAGS_TF (1UL << 8)
static volatile sig_atomic_t num_vsyscall_traps;

static unsigned long get_eflags(void)
{
unsigned long eflags;
asm volatile ("pushfq\n\tpopq %0" : "=rm" (eflags));
return eflags;
}

static void set_eflags(unsigned long eflags)
{
asm volatile ("pushq %0\n\tpopfq" : : "rm" (eflags) : "flags");
}

static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
{
ucontext_t *ctx = (ucontext_t *)ctx_void;
Expand Down
23 changes: 2 additions & 21 deletions tools/testing/selftests/x86/unwind_vdso.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
#include <features.h>
#include <stdio.h>

#include "helpers.h"

#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16

int main()
Expand Down Expand Up @@ -53,27 +55,6 @@ static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
err(1, "sigaction");
}

#ifdef __x86_64__
# define WIDTH "q"
#else
# define WIDTH "l"
#endif

static unsigned long get_eflags(void)
{
unsigned long eflags;
asm volatile ("pushf" WIDTH "\n\tpop" WIDTH " %0" : "=rm" (eflags));
return eflags;
}

static void set_eflags(unsigned long eflags)
{
asm volatile ("push" WIDTH " %0\n\tpopf" WIDTH
: : "rm" (eflags) : "flags");
}

#define X86_EFLAGS_TF (1UL << 8)

static volatile sig_atomic_t nerrs;
static unsigned long sysinfo;
static bool got_sysinfo = false;
Expand Down

0 comments on commit cced0b2

Please sign in to comment.