1 // SPDX-License-Identifier: GPL-2.0
11 #define ITERATIONS 10000
13 #define LARGE_SIZE (5 * 1024)
14 #define LARGE_ITERATIONS 1000
15 #define LARGE_MAX_OFFSET 32
16 #define LARGE_SIZE_START 4096
18 /* This is big enough to fit LARGE_SIZE and works on 4K & 64K kernels */
19 #define MAP_SIZE (64 * 1024)
21 #define MAX_OFFSET_DIFF_S1_S2 48
24 int enter_vmx_ops(void)
30 void exit_vmx_ops(void)
34 int test_memcmp(const void *s1
, const void *s2
, size_t n
);
36 /* test all offsets and lengths */
37 static void test_one(char *s1
, char *s2
, unsigned long max_offset
,
38 unsigned long size_start
, unsigned long max_size
)
40 unsigned long offset
, size
;
42 for (offset
= 0; offset
< max_offset
; offset
++) {
43 for (size
= size_start
; size
< (max_size
- offset
); size
++) {
47 y
= memcmp(s1
+offset
, s2
+offset
, size
);
48 x
= test_memcmp(s1
+offset
, s2
+offset
, size
);
50 if (((x
^ y
) < 0) && /* Trick to compare sign */
51 ((x
| y
) != 0)) { /* check for zero */
52 printf("memcmp returned %d, should have returned %d (offset %ld size %ld)\n", x
, y
, offset
, size
);
54 for (i
= offset
; i
< offset
+size
; i
++)
55 printf("%02x ", s1
[i
]);
58 for (i
= offset
; i
< offset
+size
; i
++)
59 printf("%02x ", s2
[i
]);
65 printf("vmx enter/exit not paired.(offset:%ld size:%ld s1:%p s2:%p vc:%d\n",
66 offset
, size
, s1
, s2
, vmx_count
);
74 static int testcase(bool islarge
)
76 unsigned long i
, comp_size
, alloc_size
;
80 comp_size
= (islarge
? LARGE_SIZE
: SIZE
);
81 alloc_size
= comp_size
+ MAX_OFFSET_DIFF_S1_S2
;
82 iterations
= islarge
? LARGE_ITERATIONS
: ITERATIONS
;
84 p
= mmap(NULL
, 4 * MAP_SIZE
, PROT_READ
| PROT_WRITE
,
85 MAP_ANONYMOUS
| MAP_PRIVATE
, -1, 0);
86 FAIL_IF(p
== MAP_FAILED
);
88 /* Put s1/s2 at the end of a page */
89 s1
= p
+ MAP_SIZE
- alloc_size
;
90 s2
= p
+ 3 * MAP_SIZE
- alloc_size
;
92 /* And unmap the subsequent page to force a fault if we overread */
93 munmap(p
+ MAP_SIZE
, MAP_SIZE
);
94 munmap(p
+ 3 * MAP_SIZE
, MAP_SIZE
);
98 for (i
= 0; i
< iterations
; i
++) {
100 unsigned long change
;
104 for (j
= 0; j
< alloc_size
; j
++)
107 rand_s1
+= random() % MAX_OFFSET_DIFF_S1_S2
;
108 rand_s2
+= random() % MAX_OFFSET_DIFF_S1_S2
;
109 memcpy(rand_s2
, rand_s1
, comp_size
);
111 /* change one byte */
112 change
= random() % comp_size
;
113 rand_s2
[change
] = random() & 0xff;
116 test_one(rand_s1
, rand_s2
, LARGE_MAX_OFFSET
,
117 LARGE_SIZE_START
, comp_size
);
119 test_one(rand_s1
, rand_s2
, SIZE
, 0, comp_size
);
124 for (i
= 0; i
< iterations
; i
++) {
126 unsigned long change
;
130 for (j
= 0; j
< alloc_size
; j
++)
133 rand_s1
+= random() % MAX_OFFSET_DIFF_S1_S2
;
134 rand_s2
+= random() % MAX_OFFSET_DIFF_S1_S2
;
135 memcpy(rand_s2
, rand_s1
, comp_size
);
137 /* change multiple bytes, 1/8 of total */
138 for (j
= 0; j
< comp_size
/ 8; j
++) {
139 change
= random() % comp_size
;
140 s2
[change
] = random() & 0xff;
144 test_one(rand_s1
, rand_s2
, LARGE_MAX_OFFSET
,
145 LARGE_SIZE_START
, comp_size
);
147 test_one(rand_s1
, rand_s2
, SIZE
, 0, comp_size
);
153 static int testcases(void)
156 // vcmpequd used in memcmp_64.S is v2.07
157 SKIP_IF(!have_hwcap2(PPC_FEATURE2_ARCH_2_07
));
167 test_harness_set_timeout(300);
168 return test_harness(testcases
, "memcmp");