diff options
author | Andy Lutomirski <luto@kernel.org> | 2016-11-16 13:23:28 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@kernel.org> | 2016-11-17 02:31:22 -0500 |
commit | 3200ca806942d3d8f78d0d0c822e345dfb8789e7 (patch) | |
tree | a04e19e941ea8461cefffb8ced7a099774179de2 /tools | |
parent | a582c540ac1b10f0a7d37415e04c4af42409fd08 (diff) |
selftests/x86: Add test_vdso to test getcpu()
I'll eventually add tests for more vDSO functions here.
Signed-off-by: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Megha <megha.dey@intel.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Link: http://lkml.kernel.org/r/945cd29901a62a3cc6ea7d6ee5e389ab1ec1ac0c.1479320367.git.luto@kernel.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>
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 | } | ||