xref: /linux/tools/testing/selftests/powerpc/copyloops/validate.c (revision 4f3df2e5ea69f5717d2721922aff263c31957548)
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