55dfe7bf2d851362b74a395b2d8d9ede4b049014
[warm.git] / test.c
1 /*
2  * wARM functionality test
3  *
4  * written by GraÅžvydas "notaz" Ignotas
5  *
6  * see warm.c for license info
7  */
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/time.h>
12 #include <time.h>
13 #include <unistd.h>
14
15 #if 1
16 #include "warm.h"
17 #else
18 #define warm_init(...) 0
19 #define warm_finish(...)
20 #define warm_cache_op_range(...)
21 #define warm_change_cb_range(...)
22 #endif
23
24 typedef unsigned long long u64;
25 static u64 start_time, end_time;
26
27 static unsigned char buff[8 * 1024 * 1024] __attribute__((aligned(32)));
28 static unsigned char *buff_mid = &buff[8 * 1024 * 1024 / 2];
29
30 static u64 xtime(void)
31 {
32         struct timeval tv;
33         gettimeofday(&tv, NULL);
34         return (u64)tv.tv_sec * 1000000 + tv.tv_usec;
35 }
36
37 static void test_start(void)
38 {
39         start_time = xtime();
40 }
41
42 static void test_end(void)
43 {
44         end_time = xtime();
45 }
46
47 static void show_result(const char *name, int bytes)
48 {
49         double secs = (end_time - start_time) / 1000000.0;
50         printf("%-16s: %4.1fs, %5.1f MB/s\n", name, secs, bytes / secs / 1048576);
51 }
52
53 static void do_memset(void)
54 {
55         memset(buff, 0, sizeof(buff));
56 }
57
58 static void byte_fill(void)
59 {
60         char *p = (void *)buff;
61         int i;
62         for (i = sizeof(buff); i > 0; i--)
63                 *p++ = 0;
64 }
65
66 static void word_fill(void)
67 {
68         long *p = (void *)buff;
69         int i;
70         for (i = sizeof(buff) / sizeof(*p); i > 0; i--)
71                 *p++ = 0;
72 }
73
74 static void do_memcpy(void)
75 {
76         memcpy(buff, buff_mid, sizeof(buff) / 2);
77 }
78
79 static void byte_cpy(void)
80 {
81         char *d = (void *)buff;
82         char *s = (void *)buff_mid;
83         int i;
84         for (i = sizeof(buff) / sizeof(*d) / 2; i > 0; i--)
85                 *d++ = *s++;
86 }
87
88 static void word_cpy(void)
89 {
90         long *d = (void *)buff;
91         long *s = (void *)buff_mid;
92         int i;
93         for (i = sizeof(buff) / sizeof(*d) / 2; i > 0; i--)
94                 *d++ = *s++;
95 }
96
97 static void word_inc(void)
98 {
99         long *p = (void *)buff;
100         int i;
101
102         for (i = sizeof(buff) / sizeof(*p); i > 0; i--) {
103                 (*p)++;
104                 p++;
105         }
106 }
107
108 #define ONE_TEST(count, func) \
109         test_start(); \
110         for (i = count; i > 0; i--) \
111                 func(); \
112         test_end()
113
114 static void tests(void)
115 {
116         int i;
117
118         ONE_TEST(64, do_memset);
119         show_result("memset", sizeof(buff) * 64);
120
121         ONE_TEST(64, byte_fill);
122         show_result("byte fill", sizeof(buff) * 64);
123
124         ONE_TEST(64, word_fill);
125         show_result("word fill", sizeof(buff) * 64);
126
127         ONE_TEST(128, do_memcpy);
128         show_result("memcpy", sizeof(buff) * 128 / 2);
129
130         ONE_TEST(128, byte_cpy);
131         show_result("byte copy", sizeof(buff) * 128 / 2);
132
133         ONE_TEST(128, word_cpy);
134         show_result("word copy", sizeof(buff) * 128 / 2);
135
136         ONE_TEST(64, word_inc);
137         show_result("word inc", sizeof(buff) * 64);
138
139         usleep(200000);
140 }
141
142 #if 1
143 #include <sys/types.h>
144 #include <sys/stat.h>
145 #include <fcntl.h>
146 #include <sys/mman.h>
147
148 void coherency_test(void)
149 {
150         volatile unsigned char *buff_mapped;
151         volatile unsigned char *buff_vol;
152         unsigned long buff_phys, mapped_phys, align;
153         unsigned char buff_mapped_vals[6];
154         unsigned char buff_vals[5];
155         int random_offs;
156         int memdev;
157
158         srand(time(NULL));
159
160         buff_phys = warm_virt2phys(buff_mid);
161         align = buff_phys & 0xfff;
162
163         memdev = open("/dev/mem", O_RDONLY | O_SYNC);
164         if (memdev < 0) {
165                 perror("open /dev/mem");
166                 return;
167         }
168
169         /* the mapping is valid for 1 page only.
170          * Also it doesn't work for GP2X F100 (2.4 kernels?),
171          * only upper mem maps correctly there. */
172         buff_mapped = mmap(NULL, 0x1000, PROT_READ,
173                         MAP_SHARED, memdev, buff_phys & ~0xfff);
174         if (buff_mapped == MAP_FAILED) {
175                 perror("mmap buff");
176                 return;
177         }
178         buff_mapped += align;
179
180         buff_mapped_vals[5] = buff_mapped[0];   /* touch */
181         mapped_phys = warm_virt2phys((void *)buff_mapped);
182         if (buff_phys != mapped_phys)
183                 printf("warning: mmap requested %08lx, got %08lx\n", buff_phys, mapped_phys);
184
185         random_offs = rand() % (0x1000 - align);
186
187         buff_vol = (volatile void *)buff_mid;
188         buff_vals[0] = buff_vol[random_offs]; buff_mapped_vals[0] = buff_mapped[random_offs];
189
190         /* incremented: */
191         buff_vol[random_offs]++;
192         buff_vals[1] = buff_vol[random_offs]; buff_mapped_vals[1] = buff_mapped[random_offs];
193
194         /* cleaned: */
195         warm_cache_op_range(WOP_D_CLEAN, (char *)buff_vol + random_offs, 32);
196         buff_vals[2] = buff_vol[random_offs]; buff_mapped_vals[2] = buff_mapped[random_offs];
197
198         /* incremented: */
199         buff_vol[random_offs]++;
200         buff_vals[3] = buff_vol[random_offs]; buff_mapped_vals[3] = buff_mapped[random_offs];
201
202         /* invalidated: */
203         warm_cache_op_range(WOP_D_INVALIDATE, (char *)buff_vol + random_offs, 32);
204         buff_vals[4] = buff_vol[random_offs]; buff_mapped_vals[4] = buff_mapped[random_offs];
205
206         printf("buff is @ %p -> %lx, mapped %p, random offset %x\n", buff_vol, buff_phys,
207                 buff_mapped, random_offs);
208         printf("val: %02x, mmaped: %02x\n", buff_vals[0], buff_mapped_vals[0]);
209
210         printf("incremented:\n");
211         printf("val: %02x, mmaped: %02x\n", buff_vals[1], buff_mapped_vals[1]);
212
213         printf("cleaned:\n");
214         printf("val: %02x, mmaped: %02x\n", buff_vals[2], buff_mapped_vals[2]);
215
216         printf("incremented:\n");
217         printf("val: %02x, mmaped: %02x\n", buff_vals[3], buff_mapped_vals[3]);
218
219         printf("invalidated:\n");
220         printf("val: %02x, mmaped: %02x\n", buff_vals[4], buff_mapped_vals[4]);
221 }
222 #else
223 #define coherency_test()
224 #endif
225
226 int main()
227 {
228         int ret;
229
230         ret = warm_init();
231         if (ret != 0)
232         {
233                 printf("init failed.\n");
234                 return 1;
235         }
236
237         printf("buff: %p - %p\n", buff, buff + sizeof(buff) - 1);
238
239         printf("-- default --\n");
240         tests();
241
242         printf("-- ncnb --\n");
243         warm_change_cb_range(WCB_C_BIT|WCB_B_BIT, 0, buff, sizeof(buff));
244         tests();
245
246         printf("-- nc b --\n");
247         warm_change_cb_range(WCB_B_BIT, 1, buff, sizeof(buff));
248         tests();
249
250         printf("--  cnb --\n");
251         warm_change_cb_range(WCB_C_BIT, 1, buff, sizeof(buff));
252         warm_change_cb_range(WCB_B_BIT, 0, buff, sizeof(buff));
253         tests();
254
255         warm_change_cb_range(WCB_C_BIT|WCB_B_BIT, 1, buff, sizeof(buff));
256         coherency_test();
257
258         warm_finish();
259
260         return 0;
261 }
262