From: Andi Kleen <andi@firstfloor.org>
To: x86@kernel.org
Cc: luto@amacapital.net, linux-kernel@vger.kernel.org,
Andi Kleen <ak@linux.intel.com>
Subject: [PATCH 7/9] x86: Add self test code for fsgsbase
Date: Mon, 21 Mar 2016 09:16:07 -0700 [thread overview]
Message-ID: <1458576969-13309-8-git-send-email-andi@firstfloor.org> (raw)
In-Reply-To: <1458576969-13309-1-git-send-email-andi@firstfloor.org>
From: Andi Kleen <ak@linux.intel.com>
Add a simple tester. By default it runs 10000 iterations,
but can also run forever with tfsgs_64 0
Signed-off-by: Andi Kleen <ak@linux.intel.com>
---
tools/testing/selftests/x86/Makefile | 3 +-
tools/testing/selftests/x86/tfsgs.c | 151 +++++++++++++++++++++++++++++++++++
2 files changed, 153 insertions(+), 1 deletion(-)
create mode 100644 tools/testing/selftests/x86/tfsgs.c
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index d5ce7d7..e4a3ef9 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -9,11 +9,12 @@ TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_sysc
TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \
test_FCMOV test_FCOMI test_FISTTP \
vdso_restorer
+TARGETS_C_64BIT_ONLY := tfsgs
TARGETS_C_32BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_32BIT_ONLY)
TARGETS_C_64BIT_ALL := $(TARGETS_C_BOTHBITS) $(TARGETS_C_64BIT_ONLY)
BINARIES_32 := $(TARGETS_C_32BIT_ALL:%=%_32)
-BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64)
+BINARIES_64 := $(TARGETS_C_64BIT_ALL:%=%_64) $(TARGETS_C_64BIT_ONLY:%=%_64)
CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
diff --git a/tools/testing/selftests/x86/tfsgs.c b/tools/testing/selftests/x86/tfsgs.c
new file mode 100644
index 0000000..15bb472
--- /dev/null
+++ b/tools/testing/selftests/x86/tfsgs.c
@@ -0,0 +1,151 @@
+/* Test kernel RD/WR FS/GS BASE support
+ * Run tfsgs 0 to run forever, otherwise iterations (default 10000)
+ * For stress testing run many in parallel to test context switching too
+ *
+ * This program destroys TLS, which means most of normal glibc
+ * doesn't work. So it uses its own libc replacement.
+ *
+ * It also breaks some versions of gdb
+ * (workaround available in https://sourceware.org/bugzilla/show_bug.cgi?id=19684)
+ */
+#include <stdlib.h>
+#include <assert.h>
+#include <asm/prctl.h>
+#include <asm/unistd.h>
+#include <cpuid.h>
+#include <sys/auxv.h>
+#include <elf.h>
+
+#ifndef __always_inline
+#define __always_inline inline __attribute__((always_inline))
+#endif
+
+static __always_inline unsigned long rdgsbase(void)
+{
+ unsigned long gs;
+ asm volatile(".byte 0xf3,0x48,0x0f,0xae,0xc8 # rdgsbaseq %%rax"
+ : "=a" (gs)
+ :: "memory");
+ return gs;
+}
+
+static __always_inline unsigned long rdfsbase(void)
+{
+ unsigned long fs;
+ asm volatile(".byte 0xf3,0x48,0x0f,0xae,0xc0 # rdfsbaseq %%rax"
+ : "=a" (fs)
+ :: "memory");
+ return fs;
+}
+
+static __always_inline void wrgsbase(unsigned long gs)
+{
+ asm volatile(".byte 0xf3,0x48,0x0f,0xae,0xd8 # wrgsbaseq %%rax"
+ :: "a" (gs)
+ : "memory");
+}
+
+static __always_inline void wrfsbase(unsigned long fs)
+{
+ asm volatile(".byte 0xf3,0x48,0x0f,0xae,0xd0 # wrfsbaseq %%rax"
+ :: "a" (fs)
+ : "memory");
+}
+
+/* Custom assert because we can't access errno with changed fs */
+
+int my_strlen(char *s)
+{
+ int len = 0;
+ while (*s++)
+ len++;
+ return len;
+}
+
+int arch_prctl(int cmd, unsigned long arg)
+{
+ int ret;
+ asm volatile("syscall" : "=a" (ret)
+ : "0" (__NR_arch_prctl), "D" (cmd), "S" (arg)
+ : "memory", "rcx", "r11");
+ return ret;
+}
+
+__attribute__((noinline)) void my_assert(int flag, char *msg)
+{
+ if (!flag) {
+ int ret;
+ asm volatile("syscall"
+ : "=a" (ret)
+ : "0" (__NR_write),
+ "D" (2), "S" (msg),
+ "d" (my_strlen(msg))
+ : "memory", "rcx", "r11");
+ *(int *)0 = 0;
+ }
+}
+
+long iter = 10000;
+
+#ifndef bit_FSGSBASE
+#define bit_FSGSBASE 1
+#endif
+
+/* Will be eventually in asm/hwcap.h */
+#define HWCAP2_FSGSBASE (1 << 0)
+
+unsigned long nfs, ngs, x;
+
+int main(int ac, char **av)
+{
+ long i;
+ unsigned a, b, c, d;
+
+ if (__get_cpuid_max(0, NULL) < 7)
+ exit(0);
+ __cpuid_count(7, 0, a, b, c, d);
+ if (!(b & bit_FSGSBASE))
+ exit(0);
+
+ /* Kernel support? */
+ if (!(getauxval(AT_HWCAP2) & HWCAP2_FSGSBASE))
+ exit(0);
+
+ if (av[1])
+ iter = strtoul(av[1], NULL, 0);
+
+ srandom(1);
+ unsigned long count = random();
+ unsigned long orig_fs = rdfsbase();
+ for (i = 0; i < iter || iter == 0; i++) {
+ unsigned long x = count++;
+ x = ((long)(x << 16)) >> 16; /* sign extend 48->64 */
+
+ wrgsbase(x);
+ wrfsbase(x);
+
+ int i;
+ for (i = 0; i < 1000; i++)
+ asm volatile("pause" ::: "memory");
+
+ ngs = rdgsbase();
+ nfs = rdfsbase();
+
+ my_assert(ngs == x, "gs check 1 failed\n");
+ my_assert(nfs == x, "fs check 1 failed\n");
+
+ unsigned long n;
+ const unsigned long MASK = 0x7fffffffffff;
+ arch_prctl(ARCH_SET_FS, (x + 1) & MASK);
+ arch_prctl(ARCH_SET_GS, (x - 1) & MASK);
+ n = rdfsbase();
+ my_assert(n == ((x + 1) & MASK), "fs check 2 failed\n");
+
+ for (i = 0; i < 1000; i++)
+ asm volatile("pause" ::: "memory");
+
+ n = rdgsbase();
+ my_assert(n == ((x - 1) & MASK), "gs check 2 failed\n");
+ }
+ wrfsbase(orig_fs);
+}
--
2.5.5
next prev parent reply other threads:[~2016-03-21 16:16 UTC|newest]
Thread overview: 39+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-03-21 16:16 Updated version of RD/WR FS/GS BASE patchkit Andi Kleen
2016-03-21 16:16 ` [PATCH 1/9] x86: Add intrinsics/macros for new rd/wr fs/gs base instructions Andi Kleen
2016-03-21 18:14 ` Andy Lutomirski
2016-03-21 16:16 ` [PATCH 2/9] x86: Add support for rd/wr fs/gs base Andi Kleen
2016-03-21 18:13 ` Andy Lutomirski
2016-03-21 19:05 ` Andi Kleen
2016-03-21 19:22 ` Andy Lutomirski
2016-03-21 22:05 ` Andi Kleen
2016-03-21 22:08 ` Andy Lutomirski
2016-03-21 22:15 ` Andi Kleen
2016-03-22 8:36 ` Thomas Gleixner
2016-03-22 14:40 ` Brian Gerst
2016-04-15 0:06 ` Andy Lutomirski
2016-03-21 16:16 ` [PATCH 3/9] x86: Make old K8 swapgs workaround conditional Andi Kleen
2016-03-21 16:16 ` [PATCH 4/9] x86: Enumerate kernel FSGS capability in AT_HWCAP2 Andi Kleen
2016-03-21 18:49 ` Brian Gerst
2016-03-21 18:54 ` Andi Kleen
2016-03-21 19:32 ` Brian Gerst
2016-03-21 19:43 ` Andi Kleen
2016-03-21 22:10 ` Andy Lutomirski
2016-03-21 16:16 ` [PATCH 5/9] x86: Add documentation for rd/wr fs/gs base Andi Kleen
2016-03-23 19:14 ` Valdis.Kletnieks
2016-03-21 16:16 ` [PATCH 6/9] x86: Use rd/wr fs/gs base in arch_prctl Andi Kleen
2016-03-21 18:17 ` Andy Lutomirski
2016-03-21 16:16 ` Andi Kleen [this message]
2016-03-21 16:16 ` [PATCH 8/9] x86: Support arbitrary fs/gs base in getregs Andi Kleen
2016-03-21 16:16 ` [PATCH 9/9] x86: Save FS/GS base in core dump Andi Kleen
2016-03-21 18:39 ` Updated version of RD/WR FS/GS BASE patchkit Andy Lutomirski
2016-03-21 19:03 ` Andi Kleen
2016-03-21 19:23 ` Andy Lutomirski
2016-03-21 19:40 ` Andi Kleen
2016-03-21 22:05 ` Andy Lutomirski
2016-03-21 22:11 ` Andi Kleen
2016-03-21 22:27 ` Andy Lutomirski
2016-03-21 22:41 ` Andi Kleen
2016-03-21 22:47 ` Andy Lutomirski
2016-03-21 22:52 ` Andi Kleen
2016-03-21 22:57 ` Andy Lutomirski
2016-03-21 23:02 ` Andi Kleen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1458576969-13309-8-git-send-email-andi@firstfloor.org \
--to=andi@firstfloor.org \
--cc=ak@linux.intel.com \
--cc=linux-kernel@vger.kernel.org \
--cc=luto@amacapital.net \
--cc=x86@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox