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
This commit is contained in:
Родитель
a61fa2799e
Коммит
cced0b24bb
|
@ -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
|
||||
|
|
|
@ -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 */
|
|
@ -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)
|
||||
{
|
||||
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -20,6 +20,8 @@
|
|||
#include <setjmp.h>
|
||||
#include <sys/uio.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#ifdef __x86_64__
|
||||
# define VSYS(x) (x)
|
||||
#else
|
||||
|
@ -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;
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
#include <features.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "helpers.h"
|
||||
|
||||
#if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 16
|
||||
|
||||
int main()
|
||||
|
@ -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;
|
||||
|
|
Загрузка…
Ссылка в новой задаче