diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-12 16:49:57 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2016-12-12 16:49:57 -0500 |
commit | 5645688f9d0d5a32f030f9c5429e1a58bedca23b (patch) | |
tree | 0b576ba953fb26d521c6b8c3364848acb00ceef3 /tools | |
parent | 4ade5b2268b9ff05e48a9cb99689c4fd15fbe9c3 (diff) | |
parent | 53938ee427bf27525a63721b7e25d86b8f31f161 (diff) |
Merge branch 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull x86 asm updates from Ingo Molnar:
"The main changes in this development cycle were:
- a large number of call stack dumping/printing improvements: higher
robustness, better cross-context dumping, improved output, etc.
(Josh Poimboeuf)
- vDSO getcpu() performance improvement for future Intel CPUs with
the RDPID instruction (Andy Lutomirski)
- add two new Intel AVX512 features and the CPUID support
infrastructure for it: AVX512IFMA and AVX512VBMI. (Gayatri Kammela,
He Chen)
- more copy-user unification (Borislav Petkov)
- entry code assembly macro simplifications (Alexander Kuleshov)
- vDSO C/R support improvements (Dmitry Safonov)
- misc fixes and cleanups (Borislav Petkov, Paul Bolle)"
* 'x86-asm-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (40 commits)
scripts/decode_stacktrace.sh: Fix address line detection on x86
x86/boot/64: Use defines for page size
x86/dumpstack: Make stack name tags more comprehensible
selftests/x86: Add test_vdso to test getcpu()
x86/vdso: Use RDPID in preference to LSL when available
x86/dumpstack: Handle NULL stack pointer in show_trace_log_lvl()
x86/cpufeatures: Enable new AVX512 cpu features
x86/cpuid: Provide get_scattered_cpuid_leaf()
x86/cpuid: Cleanup cpuid_regs definitions
x86/copy_user: Unify the code by removing the 64-bit asm _copy_*_user() variants
x86/unwind: Ensure stack grows down
x86/vdso: Set vDSO pointer only after success
x86/prctl/uapi: Remove #ifdef for CHECKPOINT_RESTORE
x86/unwind: Detect bad stack return address
x86/dumpstack: Warn on stack recursion
x86/unwind: Warn on bad frame pointer
x86/decoder: Use stderr if insn sanity test fails
x86/decoder: Use stdout if insn decoder test is successful
mm/page_alloc: Remove kernel address exposure in free_reserved_area()
x86/dumpstack: Remove raw stack dump
...
Diffstat (limited to 'tools')
-rw-r--r-- | tools/testing/selftests/x86/Makefile | 2 | ||||
-rw-r--r-- | tools/testing/selftests/x86/test_vdso.c | 123 |
2 files changed, 124 insertions, 1 deletions
diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile index a89f80a5b711..8c1cb423cfe6 100644 --- a/tools/testing/selftests/x86/Makefile +++ b/tools/testing/selftests/x86/Makefile | |||
@@ -6,7 +6,7 @@ include ../lib.mk | |||
6 | 6 | ||
7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \ | 7 | TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt ptrace_syscall test_mremap_vdso \ |
8 | check_initial_reg_state sigreturn ldt_gdt iopl \ | 8 | check_initial_reg_state sigreturn ldt_gdt iopl \ |
9 | protection_keys | 9 | protection_keys test_vdso |
10 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ | 10 | TARGETS_C_32BIT_ONLY := entry_from_vm86 syscall_arg_fault test_syscall_vdso unwind_vdso \ |
11 | test_FCMOV test_FCOMI test_FISTTP \ | 11 | test_FCMOV test_FCOMI test_FISTTP \ |
12 | vdso_restorer | 12 | vdso_restorer |
diff --git a/tools/testing/selftests/x86/test_vdso.c b/tools/testing/selftests/x86/test_vdso.c new file mode 100644 index 000000000000..65d7a2bf7e14 --- /dev/null +++ b/tools/testing/selftests/x86/test_vdso.c | |||
@@ -0,0 +1,123 @@ | |||
1 | /* | ||
2 | * ldt_gdt.c - Test cases for LDT and GDT access | ||
3 | * Copyright (c) 2011-2015 Andrew Lutomirski | ||
4 | */ | ||
5 | |||
6 | #define _GNU_SOURCE | ||
7 | |||
8 | #include <stdio.h> | ||
9 | #include <sys/time.h> | ||
10 | #include <time.h> | ||
11 | #include <stdlib.h> | ||
12 | #include <unistd.h> | ||
13 | #include <sys/syscall.h> | ||
14 | #include <dlfcn.h> | ||
15 | #include <string.h> | ||
16 | #include <errno.h> | ||
17 | #include <sched.h> | ||
18 | #include <stdbool.h> | ||
19 | |||
20 | #ifndef SYS_getcpu | ||
21 | # ifdef __x86_64__ | ||
22 | # define SYS_getcpu 309 | ||
23 | # else | ||
24 | # define SYS_getcpu 318 | ||
25 | # endif | ||
26 | #endif | ||
27 | |||
28 | int nerrs = 0; | ||
29 | |||
30 | #ifdef __x86_64__ | ||
31 | # define VSYS(x) (x) | ||
32 | #else | ||
33 | # define VSYS(x) 0 | ||
34 | #endif | ||
35 | |||
36 | typedef long (*getcpu_t)(unsigned *, unsigned *, void *); | ||
37 | |||
38 | const getcpu_t vgetcpu = (getcpu_t)VSYS(0xffffffffff600800); | ||
39 | getcpu_t vdso_getcpu; | ||
40 | |||
41 | void fill_function_pointers() | ||
42 | { | ||
43 | void *vdso = dlopen("linux-vdso.so.1", | ||
44 | RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); | ||
45 | if (!vdso) | ||
46 | vdso = dlopen("linux-gate.so.1", | ||
47 | RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD); | ||
48 | if (!vdso) { | ||
49 | printf("[WARN]\tfailed to find vDSO\n"); | ||
50 | return; | ||
51 | } | ||
52 | |||
53 | vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu"); | ||
54 | if (!vdso_getcpu) | ||
55 | printf("Warning: failed to find getcpu in vDSO\n"); | ||
56 | } | ||
57 | |||
58 | static long sys_getcpu(unsigned * cpu, unsigned * node, | ||
59 | void* cache) | ||
60 | { | ||
61 | return syscall(__NR_getcpu, cpu, node, cache); | ||
62 | } | ||
63 | |||
64 | static void test_getcpu(void) | ||
65 | { | ||
66 | printf("[RUN]\tTesting getcpu...\n"); | ||
67 | |||
68 | for (int cpu = 0; ; cpu++) { | ||
69 | cpu_set_t cpuset; | ||
70 | CPU_ZERO(&cpuset); | ||
71 | CPU_SET(cpu, &cpuset); | ||
72 | if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0) | ||
73 | return; | ||
74 | |||
75 | unsigned cpu_sys, cpu_vdso, cpu_vsys, | ||
76 | node_sys, node_vdso, node_vsys; | ||
77 | long ret_sys, ret_vdso = 1, ret_vsys = 1; | ||
78 | unsigned node; | ||
79 | |||
80 | ret_sys = sys_getcpu(&cpu_sys, &node_sys, 0); | ||
81 | if (vdso_getcpu) | ||
82 | ret_vdso = vdso_getcpu(&cpu_vdso, &node_vdso, 0); | ||
83 | if (vgetcpu) | ||
84 | ret_vsys = vgetcpu(&cpu_vsys, &node_vsys, 0); | ||
85 | |||
86 | if (!ret_sys) | ||
87 | node = node_sys; | ||
88 | else if (!ret_vdso) | ||
89 | node = node_vdso; | ||
90 | else if (!ret_vsys) | ||
91 | node = node_vsys; | ||
92 | |||
93 | bool ok = true; | ||
94 | if (!ret_sys && (cpu_sys != cpu || node_sys != node)) | ||
95 | ok = false; | ||
96 | if (!ret_vdso && (cpu_vdso != cpu || node_vdso != node)) | ||
97 | ok = false; | ||
98 | if (!ret_vsys && (cpu_vsys != cpu || node_vsys != node)) | ||
99 | ok = false; | ||
100 | |||
101 | printf("[%s]\tCPU %u:", ok ? "OK" : "FAIL", cpu); | ||
102 | if (!ret_sys) | ||
103 | printf(" syscall: cpu %u, node %u", cpu_sys, node_sys); | ||
104 | if (!ret_vdso) | ||
105 | printf(" vdso: cpu %u, node %u", cpu_vdso, node_vdso); | ||
106 | if (!ret_vsys) | ||
107 | printf(" vsyscall: cpu %u, node %u", cpu_vsys, | ||
108 | node_vsys); | ||
109 | printf("\n"); | ||
110 | |||
111 | if (!ok) | ||
112 | nerrs++; | ||
113 | } | ||
114 | } | ||
115 | |||
116 | int main(int argc, char **argv) | ||
117 | { | ||
118 | fill_function_pointers(); | ||
119 | |||
120 | test_getcpu(); | ||
121 | |||
122 | return nerrs ? 1 : 0; | ||
123 | } | ||