r3 release
[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 #include <sys/ioctl.h>
15 #include <sys/mman.h>
16 #include <sys/types.h>
17 #include <sys/stat.h>
18 #include <fcntl.h>
19 #include <linux/fb.h>
20
21 #if 1
22 #include "warm.h"
23 #else
24 #define warm_init(...) 0
25 #define warm_finish(...)
26 #define warm_cache_op_range(...)
27 #define warm_change_cb_range(...)
28 #endif
29
30 typedef unsigned long long u64;
31 static u64 start_time, end_time;
32
33 static unsigned char buff[2 * 1024 * 1024] __attribute__((aligned(32)));
34 static unsigned char *buff_mid = &buff[sizeof(buff) / 2];
35
36 #define REP 32
37
38 static u64 xtime(void)
39 {
40         struct timeval tv;
41         gettimeofday(&tv, NULL);
42         return (u64)tv.tv_sec * 1000000 + tv.tv_usec;
43 }
44
45 static void test_start(void)
46 {
47         start_time = xtime();
48 }
49
50 static void test_end(void)
51 {
52         end_time = xtime();
53 }
54
55 static void show_result(const char *name, int bytes)
56 {
57         double secs = (end_time - start_time) / 1000000.0;
58         printf("%-16s: %4.1fs, %5.1f MB/s\n", name, secs, bytes / secs / 1048576);
59 }
60
61 static void do_memset(void)
62 {
63         memset(buff, 0, sizeof(buff));
64 }
65
66 static void byte_fill(void)
67 {
68         char *p = (void *)buff;
69         int i;
70         for (i = sizeof(buff); i > 0; i--)
71                 *p++ = 0;
72 }
73
74 static void word_fill(void)
75 {
76         long *p = (void *)buff;
77         int i;
78         for (i = sizeof(buff) / sizeof(*p); i > 0; i--)
79                 *p++ = 0;
80 }
81
82 static void cached_byte_fill(void)
83 {
84         char *p = (void *)buff;
85         int i, j, v;
86
87         for (i = sizeof(buff) / 32; i > 0; i--) {
88                 v += *p;
89                 for (j = 32; j > 0; j--)
90                         *p++ = v;
91         }
92 }
93
94 static void do_memcpy(void)
95 {
96         memcpy(buff, buff_mid, sizeof(buff) / 2);
97 }
98
99 static void byte_cpy(void)
100 {
101         char *d = (void *)buff;
102         char *s = (void *)buff_mid;
103         int i;
104         for (i = sizeof(buff) / sizeof(*d) / 2; i > 0; i--)
105                 *d++ = *s++;
106 }
107
108 static void word_cpy(void)
109 {
110         long *d = (void *)buff;
111         long *s = (void *)buff_mid;
112         int i;
113         for (i = sizeof(buff) / sizeof(*d) / 2; i > 0; i--)
114                 *d++ = *s++;
115 }
116
117 static void word_inc(void)
118 {
119         long *p = (void *)buff;
120         int i;
121
122         for (i = sizeof(buff) / sizeof(*p); i > 0; i--) {
123                 (*p)++;
124                 p++;
125         }
126 }
127
128 #define TEST_PAGE 4096
129
130 static void page_writes_ref(void *buf)
131 {
132         long *d = buf;
133         int i, j;
134
135         for (j = 0; j < 0x100000 / TEST_PAGE; j++)
136                 for (i = 0; i < TEST_PAGE / 4; i++)
137                         d[j * TEST_PAGE / 4 + i] = 0;
138 }
139
140 static void page_inc_ref(void *buf)
141 {
142         long *d = buf;
143         int i, j;
144
145         for (j = 0; j < 0x100000 / TEST_PAGE; j++)
146                 for (i = 0; i < TEST_PAGE / 4; i++)
147                         d[j * TEST_PAGE / 4 + i]++;
148 }
149
150 static void page_writes(void *buf)
151 {
152         long *d = buf;
153         int i, j;
154
155         for (i = 0; i < TEST_PAGE / 4; i++)
156                 for (j = 0; j < 0x100000 / TEST_PAGE; j++)
157                         d[j * TEST_PAGE / 4 + i] = 0;
158 }
159
160 static void page_inc(void *buf)
161 {
162         long *d = buf;
163         int i, j;
164
165         for (i = 0; i < TEST_PAGE / 4; i++)
166                 for (j = 0; j < 0x100000 / TEST_PAGE; j++)
167                         d[j * TEST_PAGE / 4 + i]++;
168 }
169
170 #define ONE_TEST(count, func) \
171         test_start(); \
172         for (i = count; i > 0; i--) \
173                 func; \
174         test_end()
175
176 static void tests(void)
177 {
178         int i;
179
180         ONE_TEST(REP, do_memset());
181         show_result("memset", sizeof(buff) * REP);
182
183         ONE_TEST(REP, byte_fill());
184         show_result("byte fill", sizeof(buff) * REP);
185
186         ONE_TEST(REP, word_fill());
187         show_result("word fill", sizeof(buff) * REP);
188
189         ONE_TEST(REP, cached_byte_fill());
190         show_result("c. byte fill", sizeof(buff) * REP);
191
192         ONE_TEST(REP * 2, do_memcpy());
193         show_result("memcpy", sizeof(buff) * REP);
194
195         ONE_TEST(REP * 2, byte_cpy());
196         show_result("byte copy", sizeof(buff) * REP);
197
198         ONE_TEST(REP * 2, word_cpy());
199         show_result("word copy", sizeof(buff) * REP);
200
201         ONE_TEST(REP, word_inc());
202         show_result("word inc", sizeof(buff) * REP);
203
204         usleep(200000);
205 }
206
207 static void page_tests(void *buf)
208 {
209         int i;
210
211         ONE_TEST(REP, page_writes(buf));
212         show_result("page_writes", 0x100000 * REP);
213
214         ONE_TEST(REP, page_inc(buf));
215         show_result("page_inc", 0x100000 * REP);
216 }
217
218 #if 1
219 #include <sys/types.h>
220 #include <sys/stat.h>
221 #include <fcntl.h>
222 #include <sys/mman.h>
223
224 void coherency_test(void)
225 {
226         volatile unsigned char *buff_mapped;
227         volatile unsigned char *buff_vol;
228         unsigned long buff_phys, mapped_phys, align;
229         unsigned char buff_mapped_vals[6];
230         unsigned char buff_vals[5];
231         int random_offs;
232         int memdev;
233
234         srand(time(NULL));
235
236         buff_phys = warm_virt2phys(buff_mid);
237         align = buff_phys & 0xfff;
238
239         memdev = open("/dev/mem", O_RDONLY | O_SYNC);
240         if (memdev < 0) {
241                 perror("open /dev/mem");
242                 return;
243         }
244
245         /* the mapping is valid for 1 page only.
246          * Also it doesn't work for GP2X F100 (2.4 kernels?),
247          * only upper mem maps correctly there. */
248         buff_mapped = mmap(NULL, 0x1000, PROT_READ,
249                         MAP_SHARED, memdev, buff_phys & ~0xfff);
250         if (buff_mapped == MAP_FAILED) {
251                 perror("mmap buff");
252                 return;
253         }
254         buff_mapped += align;
255
256         buff_mapped_vals[5] = buff_mapped[0];   /* touch */
257         mapped_phys = warm_virt2phys((void *)buff_mapped);
258         if (buff_phys != mapped_phys)
259                 printf("warning: mmap requested %08lx, got %08lx\n", buff_phys, mapped_phys);
260
261         random_offs = rand() % (0x1000 - align);
262
263         buff_vol = (volatile void *)buff_mid;
264         buff_vals[0] = buff_vol[random_offs]; buff_mapped_vals[0] = buff_mapped[random_offs];
265
266         /* incremented: */
267         buff_vol[random_offs]++;
268         buff_vals[1] = buff_vol[random_offs]; buff_mapped_vals[1] = buff_mapped[random_offs];
269
270         /* cleaned: */
271         warm_cache_op_range(WOP_D_CLEAN, (char *)buff_vol + random_offs, 32);
272         buff_vals[2] = buff_vol[random_offs]; buff_mapped_vals[2] = buff_mapped[random_offs];
273
274         /* incremented: */
275         buff_vol[random_offs]++;
276         buff_vals[3] = buff_vol[random_offs]; buff_mapped_vals[3] = buff_mapped[random_offs];
277
278         /* invalidated: */
279         warm_cache_op_range(WOP_D_INVALIDATE, (char *)buff_vol + random_offs, 32);
280         buff_vals[4] = buff_vol[random_offs]; buff_mapped_vals[4] = buff_mapped[random_offs];
281
282         printf("buff is @ %p -> %lx, mapped %p, random offset %x\n", buff_vol, buff_phys,
283                 buff_mapped, random_offs);
284         printf("val: %02x, mmaped: %02x\n", buff_vals[0], buff_mapped_vals[0]);
285
286         printf("incremented:\n");
287         printf("val: %02x, mmaped: %02x\n", buff_vals[1], buff_mapped_vals[1]);
288
289         printf("cleaned:\n");
290         printf("val: %02x, mmaped: %02x\n", buff_vals[2], buff_mapped_vals[2]);
291
292         printf("incremented:\n");
293         printf("val: %02x, mmaped: %02x\n", buff_vals[3], buff_mapped_vals[3]);
294
295         printf("invalidated:\n");
296         printf("val: %02x, mmaped: %02x\n", buff_vals[4], buff_mapped_vals[4]);
297 }
298 #else
299 #define coherency_test()
300 #endif
301
302 int main()
303 {
304         struct fb_fix_screeninfo fbfix;
305         void *mmap_mem;
306         void *section_mem;
307         int fbdev;
308         int i, ret;
309
310         ret = warm_init();
311         if (ret != 0)
312         {
313                 printf("init failed.\n");
314                 return 1;
315         }
316
317         printf("buff: %p - %p\n", buff, buff + sizeof(buff) - 1);
318
319         // prefault
320         do_memset();
321
322         printf("-- default --\n");
323         tests();
324
325         printf("-- ncnb --\n");
326         warm_change_cb_range(WCB_C_BIT|WCB_B_BIT, 0, buff, sizeof(buff));
327         tests();
328
329         printf("-- nc b --\n");
330         warm_change_cb_range(WCB_B_BIT, 1, buff, sizeof(buff));
331         tests();
332
333         printf("--  cnb --\n");
334         warm_change_cb_range(WCB_C_BIT, 1, buff, sizeof(buff));
335         warm_change_cb_range(WCB_B_BIT, 0, buff, sizeof(buff));
336         tests();
337
338         //printf("--  c b --\n");
339         warm_change_cb_range(WCB_C_BIT|WCB_B_BIT, 1, buff, sizeof(buff));
340         //tests();
341
342         coherency_test();
343
344         mmap_mem = mmap((void *)0x60000000, 0x100000, PROT_READ | PROT_WRITE,
345                         MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
346
347         // find safe location for section map, we'll use fb
348         fbdev = open("/dev/fb0", O_RDWR);
349         if (fbdev == -1) {
350                 perror("fb open");
351                 goto out;
352         }
353
354         ret = ioctl(fbdev, FBIOGET_FSCREENINFO, &fbfix);
355         if (ret == -1) {
356                 perror("ioctl(fbdev)");
357                 goto out;
358         }
359
360         section_mem = (void *)0x70000000;
361         ret = warm_mmap_section(section_mem, fbfix.smem_start, 0x100000,
362                                 WCB_C_BIT|WCB_B_BIT);
363         if (ret != 0) {
364                 fprintf(stderr, "section map failed\n");
365                 goto out;
366         }
367
368         // prefault
369         memset(mmap_mem, 0, 0x100000);
370         memset(section_mem, 0, 0x100000);
371
372         ONE_TEST(REP, page_writes_ref(mmap_mem));
373         show_result("page_wr_ref_m", 0x100000 * REP);
374
375         ONE_TEST(REP, page_inc_ref(mmap_mem));
376         show_result("page_inc_ref_m", 0x100000 * REP);
377
378         ONE_TEST(REP, page_writes_ref(section_mem));
379         show_result("page_wr_ref_s", 0x100000 * REP);
380
381         ONE_TEST(REP, page_inc_ref(section_mem));
382         show_result("page_inc_ref_s", 0x100000 * REP);
383
384         printf("== pages ==\n");
385         page_tests(mmap_mem);
386
387         printf("== section ==\n");
388         printf("-- default --\n");
389         page_tests(section_mem);
390
391         printf("-- ncnb --\n");
392         warm_change_cb_range(WCB_C_BIT|WCB_B_BIT, 0, section_mem, 0x100000);
393         page_tests(section_mem);
394
395         printf("-- nc b --\n");
396         warm_change_cb_range(WCB_B_BIT, 1, section_mem, 0x100000);
397         page_tests(section_mem);
398
399         printf("--  cnb --\n");
400         warm_change_cb_range(WCB_C_BIT, 1, section_mem, 0x100000);
401         warm_change_cb_range(WCB_B_BIT, 0, section_mem, 0x100000);
402         page_tests(section_mem);
403
404         warm_munmap_section(section_mem, 0x100000);
405
406 out:
407         warm_finish();
408
409         return 0;
410 }
411