1 #include <stdlib.h>
2 #include <signal.h>
3 #include <unistd.h>
4 #include <linux/compiler.h>
5 #include "../tests.h"
6 
7 typedef struct _buf {
8 	char data1;
9 	char reserved[55];
10 	char data2;
11 } buf __attribute__((aligned(64)));
12 
13 /* volatile to try to avoid the compiler seeing reserved as unused. */
14 static volatile buf workload_datasym_buf1 = {
15 	/* to have this in the data section */
16 	.reserved[0] = 1,
17 };
18 
19 static volatile sig_atomic_t done;
20 
sighandler(int sig __maybe_unused)21 static void sighandler(int sig __maybe_unused)
22 {
23 	done = 1;
24 }
25 
datasym(int argc,const char ** argv)26 static int datasym(int argc, const char **argv)
27 {
28 	int sec = 1;
29 
30 	if (argc > 0)
31 		sec = atoi(argv[0]);
32 
33 	signal(SIGINT, sighandler);
34 	signal(SIGALRM, sighandler);
35 	alarm(sec);
36 
37 	while (!done) {
38 		workload_datasym_buf1.data1++;
39 		if (workload_datasym_buf1.data1 == 123) {
40 			/*
41 			 * Add some 'noise' in the loop to work around errata
42 			 * 1694299 on Arm N1.
43 			 *
44 			 * Bias exists in SPE sampling which can cause the load
45 			 * and store instructions to be skipped entirely. This
46 			 * comes and goes randomly depending on the offset the
47 			 * linker places the datasym loop at in the Perf binary.
48 			 * With an extra branch in the middle of the loop that
49 			 * isn't always taken, the instruction stream is no
50 			 * longer a continuous repeating pattern that interacts
51 			 * badly with the bias.
52 			 */
53 			workload_datasym_buf1.data1++;
54 		}
55 		workload_datasym_buf1.data2 += workload_datasym_buf1.data1;
56 	}
57 	return 0;
58 }
59 
60 DEFINE_WORKLOAD(datasym);
61