1 // SPDX-License-Identifier: GPL-2.0
2 #include <malloc.h>
3 #include <string.h>
4 #include <stdlib.h>
5 #include <stdbool.h>
6
7 #include "utils.h"
8
9 #define MAX_LEN 8192
10 #define MAX_OFFSET 16
11 #define MIN_REDZONE 128
12 #define BUFLEN (MAX_LEN+MAX_OFFSET+2*MIN_REDZONE)
13 #define POISON 0xa5
14
15 #ifdef VMX_TEST
16 #define VMX_COPY_THRESHOLD 3328
17 #endif
18
19 unsigned long COPY_LOOP(void *to, const void *from, unsigned long size);
20
do_one(char * src,char * dst,unsigned long src_off,unsigned long dst_off,unsigned long len,void * redzone,void * fill)21 static void do_one(char *src, char *dst, unsigned long src_off,
22 unsigned long dst_off, unsigned long len, void *redzone,
23 void *fill)
24 {
25 char *srcp, *dstp;
26 unsigned long ret;
27 unsigned long i;
28
29 srcp = src + MIN_REDZONE + src_off;
30 dstp = dst + MIN_REDZONE + dst_off;
31
32 memset(src, POISON, BUFLEN);
33 memset(dst, POISON, BUFLEN);
34 memcpy(srcp, fill, len);
35
36 ret = COPY_LOOP(dstp, srcp, len);
37 if (ret && ret != (unsigned long)dstp) {
38 printf("(%p,%p,%ld) returned %ld\n", dstp, srcp, len, ret);
39 abort();
40 }
41
42 if (memcmp(dstp, srcp, len)) {
43 printf("(%p,%p,%ld) miscompare\n", dstp, srcp, len);
44 printf("src: ");
45 for (i = 0; i < len; i++)
46 printf("%02x ", srcp[i]);
47 printf("\ndst: ");
48 for (i = 0; i < len; i++)
49 printf("%02x ", dstp[i]);
50 printf("\n");
51 abort();
52 }
53
54 if (memcmp(dst, redzone, dstp - dst)) {
55 printf("(%p,%p,%ld) redzone before corrupted\n",
56 dstp, srcp, len);
57 abort();
58 }
59
60 if (memcmp(dstp+len, redzone, dst+BUFLEN-(dstp+len))) {
61 printf("(%p,%p,%ld) redzone after corrupted\n",
62 dstp, srcp, len);
63 abort();
64 }
65 }
66
test_copy_loop(void)67 int test_copy_loop(void)
68 {
69 char *src, *dst, *redzone, *fill;
70 unsigned long len, src_off, dst_off;
71 unsigned long i;
72
73 src = memalign(BUFLEN, BUFLEN);
74 dst = memalign(BUFLEN, BUFLEN);
75 redzone = malloc(BUFLEN);
76 fill = malloc(BUFLEN);
77
78 if (!src || !dst || !redzone || !fill) {
79 fprintf(stderr, "malloc failed\n");
80 exit(1);
81 }
82
83 memset(redzone, POISON, BUFLEN);
84
85 /* Fill with sequential bytes */
86 for (i = 0; i < BUFLEN; i++)
87 fill[i] = i & 0xff;
88 #ifdef VMX_TEST
89 /* Force sizes above kernel VMX threshold (3328) */
90 for (len = VMX_COPY_THRESHOLD + 1; len < MAX_LEN; len++) {
91 #else
92 for (len = 1; len < MAX_LEN; len++) {
93 #endif
94 for (src_off = 0; src_off < MAX_OFFSET; src_off++) {
95 for (dst_off = 0; dst_off < MAX_OFFSET; dst_off++) {
96 do_one(src, dst, src_off, dst_off, len,
97 redzone, fill);
98 }
99 }
100 }
101
102 return 0;
103 }
104
105 int main(void)
106 {
107 #ifdef VMX_TEST
108 /* Skip if Altivec not present */
109 SKIP_IF_MSG(!have_hwcap(PPC_FEATURE_HAS_ALTIVEC), "ALTIVEC not supported");
110 #endif
111
112 return test_harness(test_copy_loop, str(COPY_LOOP));
113 }
114