Commit cced0b24 authored by Andy Lutomirski's avatar Andy Lutomirski Committed by Thomas Gleixner
Browse files

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: default avatarAndy Lutomirski <luto@kernel.org>
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
Link: https://lkml.kernel.org/r/982ce58ae8dea2f1e57093ee894760e35267e751.1593191971.git.luto@kernel.org
parent a61fa279
Loading
Loading
Loading
Loading
+2 −2
Original line number Original line Diff line number Diff line
@@ -70,10 +70,10 @@ all_64: $(BINARIES_64)


EXTRA_CLEAN := $(BINARIES_32) $(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
	$(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
	$(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl


# x86_64 users should be encouraged to install 32-bit libraries
# x86_64 users should be encouraged to install 32-bit libraries
+41 −0
Original line number Original line Diff line number Diff line
// 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 */
+2 −15
Original line number Original line Diff line number Diff line
@@ -31,6 +31,8 @@
#include <sys/ptrace.h>
#include <sys/ptrace.h>
#include <sys/user.h>
#include <sys/user.h>


#include "helpers.h"

static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
		       int flags)
		       int flags)
{
{
@@ -67,21 +69,6 @@ static unsigned char altstack_data[SIGSTKSZ];
# define INT80_CLOBBERS
# define INT80_CLOBBERS
#endif
#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)
static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
{
{
	ucontext_t *ctx = (ucontext_t*)ctx_void;
	ucontext_t *ctx = (ucontext_t*)ctx_void;
+1 −20
Original line number Original line Diff line number Diff line
@@ -15,30 +15,11 @@
#include <setjmp.h>
#include <setjmp.h>
#include <errno.h>
#include <errno.h>


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


/* Our sigaltstack scratch space. */
/* Our sigaltstack scratch space. */
static unsigned char altstack_data[SIGSTKSZ];
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 *),
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
		       int flags)
		       int flags)
{
{
+1 −19
Original line number Original line Diff line number Diff line
@@ -13,29 +13,11 @@
#include <signal.h>
#include <signal.h>
#include <err.h>
#include <err.h>
#include <sys/syscall.h>
#include <sys/syscall.h>
#include <asm/processor-flags.h>


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


static unsigned int nerrs;
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 *),
static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
		       int flags)
		       int flags)
{
{
Loading