1 // Copyright 2006 Google Inc. All Rights Reserved.
2 /* Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14
15 /* This is stressapptest for Rockchip platform in U-Boot, the design idea and
16 * the patterns are from code.google.com/p/stressapptest.
17 */
18
19 #include <common.h>
20 #include <amp.h>
21 #include <div64.h>
22 #include <malloc.h>
23 #include <asm/arch/rockchip_smccc.h>
24 #include "stressapptest.h"
25 #include "../ddr_tool_common.h"
26
27 #define __version__ "v1.3.0 20230713"
28
29 #if defined(CONFIG_ARM64)
30 /* Float operation in TOOLCHAIN_ARM32 will cause the compile error */
31 #define WARM_CPU
32 #endif
33
34 #define PAT_NUM 26
35 #define PATTERN_LIST_SIZE (PAT_NUM * 2 * 4)
36
37 #define CPU_NUM_MAX 16
38
39 static u32 walking_1_data[] = {
40 0x00000001, 0x00000002, 0x00000004, 0x00000008,
41 0x00000010, 0x00000020, 0x00000040, 0x00000080,
42 0x00000100, 0x00000200, 0x00000400, 0x00000800,
43 0x00001000, 0x00002000, 0x00004000, 0x00008000,
44 0x00010000, 0x00020000, 0x00040000, 0x00080000,
45 0x00100000, 0x00200000, 0x00400000, 0x00800000,
46 0x01000000, 0x02000000, 0x04000000, 0x08000000,
47 0x10000000, 0x20000000, 0x40000000, 0x80000000,
48 0x40000000, 0x20000000, 0x10000000, 0x08000000,
49 0x04000000, 0x02000000, 0x01000000, 0x00800000,
50 0x00400000, 0x00200000, 0x00100000, 0x00080000,
51 0x00040000, 0x00020000, 0x00010000, 0x00008000,
52 0x00004000, 0x00002000, 0x00001000, 0x00000800,
53 0x00000400, 0x00000200, 0x00000100, 0x00000080,
54 0x00000040, 0x00000020, 0x00000010, 0x00000008,
55 0x00000004, 0x00000002, 0x00000001, 0x00000000
56 };
57
58 static struct pat walking_1 = {
59 "walking_1",
60 walking_1_data,
61 ARRAY_SIZE(walking_1_data) - 1, /* mask */
62 {1, 1, 2, 1} /* weight */
63 };
64
65 static u32 walking_1_x16_data[] = {
66 0x00020001, 0x00080004, 0x00200010, 0x00800040,
67 0x02000100, 0x08000400, 0x20001000, 0x80004000,
68 0x20004000, 0x08001000, 0x02000400, 0x00800100,
69 0x00200040, 0x00080010, 0x00020004, 0x00000001
70 };
71
72 static struct pat walking_1_x16 = {
73 "walking_1_x16",
74 walking_1_x16_data,
75 ARRAY_SIZE(walking_1_x16_data) - 1, /* mask */
76 {2, 0, 0, 0} /* Weight for choosing 32/64/128/256 bit wide of this pattern */
77 /* Reuse for walking_0_x16, because of invert */
78 };
79
80 static u32 walking_1_x16_repeat_data[] = {
81 0x00010001, 0x00020002, 0x00040004, 0x00080008,
82 0x00100010, 0x00200020, 0x00400040, 0x00800080,
83 0x01000100, 0x02000200, 0x04000400, 0x08000800,
84 0x10001000, 0x20002000, 0x40004000, 0x80008000,
85 0x40004000, 0x20002000, 0x10001000, 0x08000800,
86 0x04000400, 0x02000200, 0x01000100, 0x00800080,
87 0x00400040, 0x00200020, 0x00100010, 0x00080008,
88 0x00040004, 0x00020002, 0x00010001, 0x00000000
89 };
90
91 static struct pat walking_1_x16_repeat = {
92 "walking_1_x16_repeat",
93 walking_1_x16_repeat_data,
94 ARRAY_SIZE(walking_1_x16_repeat_data) - 1, /* mask */
95 {2, 4, 2, 0} /* Weight for choosing 32/64/128/256 bit wide of this pattern */
96 /* Reuse for walking_0_x16_repeat, because of invert */
97 };
98
99 static u32 walking_inv_1_data[] = {
100 0x00000001, 0xfffffffe, 0x00000002, 0xfffffffd,
101 0x00000004, 0xfffffffb, 0x00000008, 0xfffffff7,
102 0x00000010, 0xffffffef, 0x00000020, 0xffffffdf,
103 0x00000040, 0xffffffbf, 0x00000080, 0xffffff7f,
104 0x00000100, 0xfffffeff, 0x00000200, 0xfffffdff,
105 0x00000400, 0xfffffbff, 0x00000800, 0xfffff7ff,
106 0x00001000, 0xffffefff, 0x00002000, 0xffffdfff,
107 0x00004000, 0xffffbfff, 0x00008000, 0xffff7fff,
108 0x00010000, 0xfffeffff, 0x00020000, 0xfffdffff,
109 0x00040000, 0xfffbffff, 0x00080000, 0xfff7ffff,
110 0x00100000, 0xffefffff, 0x00200000, 0xffdfffff,
111 0x00400000, 0xffbfffff, 0x00800000, 0xff7fffff,
112 0x01000000, 0xfeffffff, 0x02000000, 0xfdffffff,
113 0x04000000, 0xfbffffff, 0x08000000, 0xf7ffffff,
114 0x10000000, 0xefffffff, 0x20000000, 0xdfffffff,
115 0x40000000, 0xbfffffff, 0x80000000, 0x7fffffff,
116 0x40000000, 0xbfffffff, 0x20000000, 0xdfffffff,
117 0x10000000, 0xefffffff, 0x08000000, 0xf7ffffff,
118 0x04000000, 0xfbffffff, 0x02000000, 0xfdffffff,
119 0x01000000, 0xfeffffff, 0x00800000, 0xff7fffff,
120 0x00400000, 0xffbfffff, 0x00200000, 0xffdfffff,
121 0x00100000, 0xffefffff, 0x00080000, 0xfff7ffff,
122 0x00040000, 0xfffbffff, 0x00020000, 0xfffdffff,
123 0x00010000, 0xfffeffff, 0x00008000, 0xffff7fff,
124 0x00004000, 0xffffbfff, 0x00002000, 0xffffdfff,
125 0x00001000, 0xffffefff, 0x00000800, 0xfffff7ff,
126 0x00000400, 0xfffffbff, 0x00000200, 0xfffffdff,
127 0x00000100, 0xfffffeff, 0x00000080, 0xffffff7f,
128 0x00000040, 0xffffffbf, 0x00000020, 0xffffffdf,
129 0x00000010, 0xffffffef, 0x00000008, 0xfffffff7,
130 0x00000004, 0xfffffffb, 0x00000002, 0xfffffffd,
131 0x00000001, 0xfffffffe, 0x00000000, 0xffffffff
132 };
133
134 static struct pat walking_inv_1 = {
135 "walking_inv_1",
136 walking_inv_1_data,
137 ARRAY_SIZE(walking_inv_1_data) - 1, /* mask */
138 {2, 2, 5, 5} /* weight */
139 };
140
141 static u32 walking_inv_1_x16_data[] = {
142 0xfffe0001, 0xfffd0002, 0xfffb0004, 0xfff70008,
143 0xffef0010, 0xffdf0020, 0xffbf0040, 0xff7f0080,
144 0xfeff0100, 0xfdff0200, 0xfbff0400, 0xf7ff0800,
145 0xefff1000, 0xdfff2000, 0xbfff4000, 0x7fff8000,
146 0xbfff4000, 0xdfff2000, 0xefff1000, 0xf7ff0800,
147 0xfbff0400, 0xfdff0200, 0xfeff0100, 0xff7f0080,
148 0xffbf0040, 0xffdf0020, 0xffef0010, 0xfff70008,
149 0xfffb0004, 0xfffd0002, 0xfffe0001, 0xffff0000
150 };
151
152 static struct pat walking_inv_1_x16 = {
153 "walking_inv_1_x16",
154 walking_inv_1_x16_data,
155 ARRAY_SIZE(walking_inv_1_x16_data) - 1, /* mask */
156 {2, 0, 0, 0} /* weight */
157 };
158
159 static u32 walking_inv_1_x16_repeat_data[] = {
160 0x00010001, 0xfffefffe, 0x00020002, 0xfffdfffd,
161 0x00040004, 0xfffbfffb, 0x00080008, 0xfff7fff7,
162 0x00100010, 0xffefffef, 0x00200020, 0xffdfffdf,
163 0x00400040, 0xffbfffbf, 0x00800080, 0xff7fff7f,
164 0x01000100, 0xfefffeff, 0x02000200, 0xfdfffdff,
165 0x04000400, 0xfbfffbff, 0x08000800, 0xf7fff7ff,
166 0x10001000, 0xefffefff, 0x20002000, 0xdfffdfff,
167 0x40004000, 0xbfffbfff, 0x80008000, 0x7fff7fff,
168 0x40004000, 0xbfffbfff, 0x20002000, 0xdfffdfff,
169 0x10001000, 0xefffefff, 0x08000800, 0xf7fff7ff,
170 0x04000400, 0xfbfffbff, 0x02000200, 0xfdfffdff,
171 0x01000100, 0xfefffeff, 0x00800080, 0xff7fff7f,
172 0x00400040, 0xffbfffbf, 0x00200020, 0xffdfffdf,
173 0x00100010, 0xffefffef, 0x00080008, 0xfff7fff7,
174 0x00040004, 0xfffbfffb, 0x00020002, 0xfffdfffd,
175 0x00010001, 0xfffefffe, 0x00000000, 0xffffffff
176 };
177
178 static struct pat walking_inv_1_x16_repeat = {
179 "walking_inv_1_x16_repeat",
180 walking_inv_1_x16_repeat_data,
181 ARRAY_SIZE(walking_inv_1_x16_repeat_data) - 1, /* mask */
182 {2, 5, 5, 0} /* weight */
183 };
184
185 static u32 walking_0_data[] = {
186 0xfffffffe, 0xfffffffd, 0xfffffffb, 0xfffffff7,
187 0xffffffef, 0xffffffdf, 0xffffffbf, 0xffffff7f,
188 0xfffffeff, 0xfffffdff, 0xfffffbff, 0xfffff7ff,
189 0xffffefff, 0xffffdfff, 0xffffbfff, 0xffff7fff,
190 0xfffeffff, 0xfffdffff, 0xfffbffff, 0xfff7ffff,
191 0xffefffff, 0xffdfffff, 0xffbfffff, 0xff7fffff,
192 0xfeffffff, 0xfdffffff, 0xfbffffff, 0xf7ffffff,
193 0xefffffff, 0xdfffffff, 0xbfffffff, 0x7fffffff,
194 0xbfffffff, 0xdfffffff, 0xefffffff, 0xf7ffffff,
195 0xfbffffff, 0xfdffffff, 0xfeffffff, 0xff7fffff,
196 0xffbfffff, 0xffdfffff, 0xffefffff, 0xfff7ffff,
197 0xfffbffff, 0xfffdffff, 0xfffeffff, 0xffff7fff,
198 0xffffbfff, 0xffffdfff, 0xffffefff, 0xfffff7ff,
199 0xfffffbff, 0xfffffdff, 0xfffffeff, 0xffffff7f,
200 0xffffffbf, 0xffffffdf, 0xffffffef, 0xfffffff7,
201 0xfffffffb, 0xfffffffd, 0xfffffffe, 0xffffffff
202 };
203
204 static struct pat walking_0 = {
205 "walking_0",
206 walking_0_data,
207 ARRAY_SIZE(walking_0_data) - 1, /* mask */
208 {1, 1, 2, 1} /* weight */
209 };
210
211 static u32 one_zero_data[] = {0x00000000, 0xffffffff};
212
213 static struct pat one_zero = {
214 "one_zero",
215 one_zero_data,
216 ARRAY_SIZE(one_zero_data) - 1, /* mask */
217 {5, 5, 15, 5} /* weight */
218 };
219
220 static unsigned int one_zero_x16_data[] = {0x0000ffff, 0x0000ffff};
221
222 static struct pat one_zero_x16 = {
223 "one_zero_x16",
224 one_zero_x16_data,
225 ARRAY_SIZE(one_zero_x16_data) - 1, /* mask */
226 {5, 0, 0, 0} /* weight */
227 };
228
229 static u32 just_0_data[] = {0x00000000, 0x00000000};
230
231 static struct pat just_0 = {
232 "just_0",
233 just_0_data,
234 ARRAY_SIZE(just_0_data) - 1, /* mask */
235 {2, 0, 0, 0} /* weight */
236 };
237
238 static u32 just_1_data[] = {0xffffffff, 0xffffffff};
239
240 static struct pat just_1 = {
241 "just_1",
242 just_1_data,
243 ARRAY_SIZE(just_1_data) - 1, /* mask */
244 {2, 0, 0, 0} /* weight */
245 };
246
247 static u32 just_5_data[] = {0x55555555, 0x55555555};
248
249 static struct pat just_5 = {
250 "just_5",
251 just_5_data,
252 ARRAY_SIZE(just_5_data) - 1, /* mask */
253 {2, 0, 0, 0} /* weight */
254 };
255
256 static u32 just_a_data[] = {0xaaaaaaaa, 0xaaaaaaaa};
257
258 static struct pat just_a = {
259 "just_a",
260 just_a_data,
261 ARRAY_SIZE(just_a_data) - 1, /* mask */
262 {2, 0, 0, 0} /* weight */
263 };
264
265 static u32 five_a_data[] = {0x55555555, 0xaaaaaaaa};
266
267 static struct pat five_a = {
268 "five_a",
269 five_a_data,
270 ARRAY_SIZE(five_a_data) - 1, /* mask */
271 {1, 1, 1, 1} /* weight */
272 };
273
274 static unsigned int five_a_x16_data[] = {0x5555aaaa, 0x5555aaaa};
275
276 static struct pat five_a_x16 = {
277 "five_a_x16",
278 five_a_x16_data,
279 ARRAY_SIZE(five_a_x16_data) - 1, /* mask */
280 {1, 0, 0, 0} /* weight */
281 };
282
283 static u32 five_a8_data[] = {
284 0x5aa5a55a, 0xa55a5aa5, 0xa55a5aa5, 0x5aa5a55a
285 };
286
287 static struct pat five_a8 = {
288 "five_a8",
289 five_a8_data,
290 ARRAY_SIZE(five_a8_data) - 1, /* mask */
291 {1, 1, 1, 1} /* weight */
292 };
293
294 static u32 five_a8_x16_data[] = {0x5aa5a55a, 0xa55a5aa5};
295
296 static struct pat five_a8_x16 = {
297 "five_a8_x16",
298 five_a8_x16_data,
299 ARRAY_SIZE(five_a8_x16_data) - 1, /* mask */
300 {1, 0, 0, 0} /* weight */
301 };
302
303 static unsigned int five_a8_x16_repeat_data[] = {
304 0x5aa55aa5, 0xa55aa55a, 0xa55aa55a, 0x5aa55aa5
305 };
306
307 static struct pat five_a8_x16_repeat = {
308 "five_a8_x16_repeat",
309 five_a8_x16_repeat_data,
310 ARRAY_SIZE(five_a8_x16_repeat_data) - 1, /* mask */
311 {1, 1, 1, 0} /* weight */
312 };
313
314 static u32 long_8b10b_data[] = {0x16161616, 0x16161616};
315
316 static struct pat long_8b10b = {
317 "long_8b10b",
318 long_8b10b_data,
319 ARRAY_SIZE(long_8b10b_data) - 1, /* mask */
320 {2, 0, 0, 0} /* weight */
321 };
322
323 static u32 short_8b10b_data[] = {0xb5b5b5b5, 0xb5b5b5b5};
324
325 static struct pat short_8b10b = {
326 "short_8b10b",
327 short_8b10b_data,
328 ARRAY_SIZE(short_8b10b_data) - 1, /* mask */
329 {2, 0, 0, 0} /* weight */
330 };
331
332 static u32 checker_8b10b_data[] = {0xb5b5b5b5, 0x4a4a4a4a};
333
334 static struct pat checker_8b10b = {
335 "checker_8b10b",
336 checker_8b10b_data,
337 ARRAY_SIZE(checker_8b10b_data) - 1, /* mask */
338 {1, 0, 1, 1} /* weight */
339 };
340
341 static u32 checker_8b10b_x16_data[] = {0xb5b54a4a, 0xb5b54a4a};
342
343 static struct pat checker_8b10b_x16 = {
344 "checker_8b10b_x16",
345 checker_8b10b_x16_data,
346 ARRAY_SIZE(checker_8b10b_x16_data) - 1, /* mask */
347 {1, 0, 0, 0} /* weight */
348 };
349
350 static u32 five_7_data[] = {0x55555557, 0x55575555};
351
352 static struct pat five_7 = {
353 "five_7",
354 five_7_data,
355 ARRAY_SIZE(five_7_data) - 1, /* mask */
356 {0, 2, 0, 0} /* weight */
357 };
358
359 static u32 five_7_x16_data[] = {0x55575557, 0x57555755};
360
361 static struct pat five_7_x16 = {
362 "five_7_x16",
363 five_7_x16_data,
364 ARRAY_SIZE(five_7_x16_data) - 1, /* mask */
365 {2, 0, 0, 0} /* weight */
366 };
367
368 static u32 zero2_fd_data[] = {0x00020002, 0xfffdfffd};
369
370 static struct pat zero2_fd = {
371 "zero2_fd",
372 zero2_fd_data,
373 ARRAY_SIZE(zero2_fd_data) - 1, /* mask */
374 {0, 2, 0, 0} /* weight */
375 };
376
377 static u32 zero2_fd_x16_data[] = {0x02020202, 0xfdfdfdfd};
378
379 static struct pat zero2_fd_x16 = {
380 "zero2_fd_x16",
381 zero2_fd_x16_data,
382 ARRAY_SIZE(zero2_fd_x16_data) - 1, /* mask */
383 {2, 0, 0, 0} /* weight */
384 };
385
386 static struct pat *pat_array[] = {
387 &walking_1,
388 &walking_1_x16,
389 &walking_1_x16_repeat,
390 &walking_inv_1,
391 &walking_inv_1_x16,
392 &walking_inv_1_x16_repeat,
393 &walking_0,
394 &one_zero,
395 &one_zero_x16,
396 &just_0,
397 &just_1,
398 &just_5,
399 &just_a,
400 &five_a,
401 &five_a_x16,
402 &five_a8,
403 &five_a8_x16,
404 &five_a8_x16_repeat,
405 &long_8b10b,
406 &short_8b10b,
407 &checker_8b10b,
408 &checker_8b10b_x16,
409 &five_7,
410 &five_7_x16,
411 &zero2_fd,
412 &zero2_fd_x16
413 };
414
415 static u32 cpu_copy_err[CPU_NUM_MAX];
416 static u32 cpu_inv_err[CPU_NUM_MAX];
417
418 static u64 start_time_us;
419 static u64 test_time_us;
420
421 static bool cpu_init_finish[CPU_NUM_MAX];
422 static bool cpu_test_finish[CPU_NUM_MAX];
423 static bool pattern_page_init_finish;
424
425 #if (CPU_NUM_MAX > 1)
426 static ulong test_count = 0;
427 static ulong __gd; /* set r9/x18 of secondary cpu to gd addr */
428 #endif
429 ulong __sp; /* set sp of secondary cpu */
430
431 u32 print_mutex; /* 0: unlock, 1: lock */
432
get_time_us(void)433 static u64 get_time_us(void)
434 {
435 return lldiv(get_ticks(), gd->arch.timer_rate_hz / 1000000);
436 }
437
run_time_us(void)438 static u64 run_time_us(void)
439 {
440 return get_time_us() - start_time_us;
441 }
442
print_time_stamp(void)443 static void print_time_stamp(void)
444 {
445 u64 time_us;
446
447 time_us = run_time_us();
448
449 printf("[%5d.%06d] ", (u32)(time_us / 1000000), (u32)(time_us % 1000000));
450 }
451
pattern_get(struct pattern * pattern,u32 offset)452 static u32 pattern_get(struct pattern *pattern, u32 offset)
453 {
454 u32 ret;
455
456 ret = pattern->pat->data_array[(offset >> pattern->repeat) &
457 pattern->pat->mask];
458
459 return pattern->inv ? ~ret : ret;
460 }
461
pattern_adler_sum_calc(struct pattern * pattern,struct stressapptest_params * sat)462 static void pattern_adler_sum_calc(struct pattern *pattern,
463 struct stressapptest_params *sat)
464 {
465 int i = 0;
466 u64 a1 = 1;
467 u64 b1 = 0;
468 u64 a2 = 1;
469 u64 b2 = 0;
470
471 while (i < sat->block_size_byte / sizeof(u32)) {
472 a1 += (u64)pattern_get(pattern, i++);
473 b1 += a1;
474 a1 += pattern_get(pattern, i++);
475 b1 += a1;
476
477 a2 += (u64)pattern_get(pattern, i++);
478 b2 += a2;
479 a2 += pattern_get(pattern, i++);
480 b2 += a2;
481 }
482
483 pattern->adler_sum.a1 = a1;
484 pattern->adler_sum.b1 = b1;
485 pattern->adler_sum.a2 = a2;
486 pattern->adler_sum.b2 = b2;
487 }
488
pattern_list_init(struct pattern * pattern_list,struct stressapptest_params * sat)489 static void pattern_list_init(struct pattern *pattern_list,
490 struct stressapptest_params *sat)
491 {
492 u32 weight_count = 0;
493 int k = 0;
494
495 for (int i = 0; i < PAT_NUM; i++) {
496 for (int j = 0; j < 8; j++) {
497 pattern_list[k].pat = pat_array[i];
498 pattern_list[k].inv = j % 2;
499 pattern_list[k].repeat = j / 2;
500 pattern_list[k].weight = pattern_list[k].pat->weight[j / 2];
501 pattern_adler_sum_calc(&pattern_list[k], sat);
502 weight_count += pattern_list[k].weight;
503 k++;
504 }
505 }
506
507 sat->weight_count = weight_count;
508 }
509
get_max_page_num(ulong page_size_byte)510 static u32 get_max_page_num(ulong page_size_byte)
511 {
512 ulong start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
513 u32 page_num = 0;
514
515 get_print_available_addr(start_adr, length, 0);
516
517 page_num = 0;
518 for (int i = 0; i < ARRAY_SIZE(start_adr) || i < ARRAY_SIZE(length); i++) {
519 if ((start_adr[i] == 0 && length[i] == 0))
520 break;
521 page_num += (u32)(length[i] / page_size_byte);
522 }
523
524 return page_num;
525 }
526
get_page_addr(struct page * page_list,struct stressapptest_params * sat)527 static int get_page_addr(struct page *page_list,
528 struct stressapptest_params *sat)
529 {
530 ulong start_adr[CONFIG_NR_DRAM_BANKS], length[CONFIG_NR_DRAM_BANKS];
531 ulong used_length;
532 u32 page = 0;
533
534 get_print_available_addr(start_adr, length, 0);
535
536 printf("Address for test:\n Start End Length\n");
537 for (int i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
538 if ((start_adr[i] == 0 && length[i] == 0) || page >= sat->page_num)
539 break;
540 if (start_adr[i] + length[i] < sat->total_start_addr)
541 continue;
542 if (start_adr[i] < sat->total_start_addr) {
543 length[i] -= sat->total_start_addr - start_adr[i];
544 start_adr[i] = sat->total_start_addr;
545 }
546
547 used_length = 0;
548 while (page < sat->page_num &&
549 length[i] >= used_length + sat->page_size_byte) {
550 page_list[page].base_addr = (void *)(start_adr[i] + used_length);
551 used_length += sat->page_size_byte;
552 page++;
553 }
554 printf(" 0x%09lx - 0x%09lx 0x%09lx\n",
555 start_adr[i], start_adr[i] + used_length, used_length);
556 }
557
558 printf("page_num = %d, page_size = 0x%lx, total_test_size = 0x%lx\n",
559 page, sat->page_size_byte, sat->page_size_byte * page);
560
561 if (sat->total_test_size_mb == 0) {
562 /* No arg for total_test_size_mb, test all available space by default. */
563 sat->page_num = page;
564 } else if (page < sat->page_num || page < sat->cpu_num * 4) {
565 printf("ERROR: Cannot get enough pages to test.\n");
566 printf("Please decrease page_size or test_size\n");
567
568 return -1;
569 }
570
571 return 0;
572 }
573
page_init_valid(struct page * page,struct pattern * pattern_list,struct stressapptest_params * sat)574 static void page_init_valid(struct page *page, struct pattern *pattern_list,
575 struct stressapptest_params *sat)
576 {
577 int target;
578 int i = 0;
579 u64 *mem;
580
581 target = (rand() % sat->weight_count) + 1;
582 do {
583 target -= pattern_list[i++].weight;
584 if (target <= 0)
585 break;
586 } while (i < PATTERN_LIST_SIZE);
587 page->pattern = &pattern_list[--i];
588 page->valid = 1;
589
590 mem = (u64 *)page->base_addr;
591 for (i = 0; i < sat->page_size_byte / sizeof(u64); i++)
592 mem[i] = (u64)pattern_get(page->pattern, i * 2) |
593 (u64)pattern_get(page->pattern, i * 2 + 1) << 32;
594 }
595
page_init_empty(struct page * page)596 static void page_init_empty(struct page *page)
597 {
598 page->valid = 0;
599 }
600
page_init(struct pattern * pattern_list,struct stressapptest_params * sat)601 static void page_init(struct pattern *pattern_list,
602 struct stressapptest_params *sat)
603 {
604 int i, cpu;
605 u32 empty_page_num;
606
607 for (cpu = 0; cpu < sat->cpu_num; cpu++) {
608 empty_page_num = 0;
609 for (i = cpu; i < sat->page_num; i += sat->cpu_num) {
610 if (rand() % 5 < 3) {
611 page_list[i].valid = 1;
612 } else {
613 page_list[i].valid = 0;
614 empty_page_num++;
615 }
616 }
617 while (empty_page_num >= sat->page_num / sat->cpu_num / 2 && i > 0) {
618 i -= sat->cpu_num;
619 if (page_list[i].valid == 0) {
620 page_list[i].valid = 1;
621 empty_page_num--;
622 }
623 }
624 i = cpu;
625 while (empty_page_num < 2 && i < sat->page_num) {
626 if (page_list[i].valid == 1) {
627 page_list[i].valid = 0;
628 empty_page_num++;
629 }
630 i += sat->cpu_num;
631 }
632 }
633
634 for (i = 0; i < sat->page_num; i++) {
635 if (page_list[i].valid == 1)
636 page_init_valid(&page_list[i], pattern_list, sat);
637 else
638 page_init_empty(&page_list[i]);
639 }
640 flush_dcache_all();
641 }
642
page_rand_pick(struct page * page_list,bool valid,struct stressapptest_params * sat,u8 cpu_id)643 static u32 page_rand_pick(struct page *page_list, bool valid,
644 struct stressapptest_params *sat, u8 cpu_id)
645 {
646 u32 pick;
647
648 pick = rand() % sat->page_num;
649 pick = pick / sat->cpu_num * sat->cpu_num + cpu_id;
650 if (pick >= sat->page_num)
651 pick = cpu_id;
652
653 while (page_list[pick].valid != valid) {
654 pick += sat->cpu_num;
655 if (pick >= sat->page_num)
656 pick = cpu_id;
657 }
658
659 return pick;
660 }
661
block_mis_search(void * dst_addr,struct pattern * src_pattern,char * item,struct stressapptest_params * sat,u8 cpu_id)662 static u32 block_mis_search(void *dst_addr, struct pattern *src_pattern, char *item,
663 struct stressapptest_params *sat, u8 cpu_id)
664 {
665 u32 *dst_mem;
666 u32 read, reread, expected;
667 u32 err = 0;
668 u32 *print_addr;
669 int i, j;
670
671 dst_mem = (u32 *)dst_addr;
672
673 for (i = 0; i < sat->block_size_byte / sizeof(u32); i++) {
674 read = dst_mem[i];
675 expected = pattern_get(src_pattern, i);
676
677 if (read != expected) {
678 flush_dcache_range((ulong)&dst_mem[i], (ulong)&dst_mem[i + 1]);
679 reread = dst_mem[i];
680
681 lock_byte_mutex(&print_mutex);
682
683 print_time_stamp();
684 printf("%s Hardware Error: miscompare on CPU %d at 0x%lx:\n",
685 item, cpu_id, (ulong)&dst_mem[i]);
686 printf(" read: 0x%08x\n", read);
687 printf(" reread: 0x%08x(reread^read:0x%08x)\n",
688 reread, reread ^ read);
689 printf(" expected:0x%08x(expected^read:0x%08x)\n",
690 expected, expected ^ read);
691 printf(" \'%s%s%d\'", src_pattern->pat->name,
692 src_pattern->inv ? "~" : "",
693 32 << src_pattern->repeat);
694 if (reread == expected)
695 printf(" read error");
696 printf("\n");
697
698 /* Dump data around the error address */
699 print_addr = &dst_mem[i] - 64;
700 for (j = 0; j < 128; j += 8)
701 printf(" [0x%010lx] 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x, 0x%08x\n",
702 (ulong)(print_addr + j),
703 *(print_addr + j), *(print_addr + j + 1),
704 *(print_addr + j + 2), *(print_addr + j + 3),
705 *(print_addr + j + 4), *(print_addr + j + 5),
706 *(print_addr + j + 6), *(print_addr + j + 7));
707
708 unlock_byte_mutex(&print_mutex);
709
710 /* fix the error */
711 dst_mem[i] = expected;
712 err++;
713 flush_dcache_range((ulong)&dst_mem[i], (ulong)&dst_mem[i + 1]);
714 }
715 }
716
717 if (err == 0) {
718 lock_byte_mutex(&print_mutex);
719 printf("%s ERROR detected but cannot find mismatch data (maybe read error).\n", item);
720 unlock_byte_mutex(&print_mutex);
721 }
722
723 return err;
724 }
725
block_inv_check(void * dst_addr,struct pattern * src_pattern,struct stressapptest_params * sat,u8 cpu_id)726 static u32 block_inv_check(void *dst_addr, struct pattern *src_pattern,
727 struct stressapptest_params *sat, u8 cpu_id)
728 {
729 u32 *dst_mem;
730 u32 err = 0;
731 int i = 0;
732 #if defined(WARM_CPU)
733 double a, b, c, d;
734 #endif
735
736 struct adler_sum adler_sum = {
737 1, 0, 1, 0
738 };
739
740 dst_mem = (u32 *)dst_addr;
741
742 #if defined(WARM_CPU)
743 a = 2.0 * dst_mem[0];
744 b = 5.0 * dst_mem[0];
745 c = 7.0 * dst_mem[0];
746 d = 9.0 * dst_mem[0];
747 #endif
748
749 while (i < sat->block_size_byte / sizeof(u32)) {
750 adler_sum.a1 += dst_mem[i++];
751 adler_sum.b1 += adler_sum.a1;
752 adler_sum.a1 += dst_mem[i++];
753 adler_sum.b1 += adler_sum.a1;
754
755 #if defined(WARM_CPU)
756 a = a * b;
757 b = b + c;
758 #endif
759
760 adler_sum.a2 += dst_mem[i++];
761 adler_sum.b2 += adler_sum.a2;
762 adler_sum.a2 += dst_mem[i++];
763 adler_sum.b2 += adler_sum.a2;
764 #if defined(WARM_CPU)
765 c = c * d;
766 d = d + d;
767 #endif
768 }
769
770 #if defined(WARM_CPU)
771 d = a + b + c + d;
772 if (d == 1.0)
773 /* Reference the result so that it can't be discarded by the compiler. */
774 printf("This will probably never happen.\n");
775 #endif
776
777 if (adler_sum.a1 != src_pattern->adler_sum.a1 ||
778 adler_sum.b1 != src_pattern->adler_sum.b1 ||
779 adler_sum.a2 != src_pattern->adler_sum.a2 ||
780 adler_sum.b2 != src_pattern->adler_sum.b2)
781 err = block_mis_search(dst_addr, src_pattern, "Inv", sat, cpu_id);
782
783 return err;
784 }
785
page_inv_up(void * src_addr,struct stressapptest_params * sat)786 static void page_inv_up(void *src_addr, struct stressapptest_params *sat)
787 {
788 void *dst_addr = src_addr;
789 uint data;
790 uint *dst_mem;
791
792 for (int i = 0; i < sat->block_num; i++) {
793 dst_mem = (uint *)dst_addr;
794 for (int j = 0; j < sat->block_size_byte / sizeof(uint); j += 32) {
795 for (int k = j; k < j + 32; k++) {
796 data = dst_mem[k];
797 dst_mem[k] = ~data;
798 }
799 flush_dcache_range((ulong)&dst_mem[j], (ulong)&dst_mem[j + 1]);
800 }
801 dst_addr += sat->block_size_byte;
802 }
803 }
804
page_inv_down(void * src_addr,struct stressapptest_params * sat)805 static void page_inv_down(void *src_addr, struct stressapptest_params *sat)
806 {
807 void *dst_addr = src_addr;
808 uint data;
809 uint *dst_mem;
810
811 dst_addr += sat->block_size_byte * (sat->block_num - 1);
812
813 for (int i = sat->block_num - 1; i >= 0; i--) {
814 dst_mem = (uint *)dst_addr;
815 for (int j = sat->block_size_byte / sizeof(uint) - 32; j >= 0; j -= 32) {
816 for (int k = j + 31; k >= j; k--) {
817 data = dst_mem[k];
818 dst_mem[k] = ~data;
819 }
820 flush_dcache_range((ulong)&dst_mem[j], (ulong)&dst_mem[j + 1]);
821 }
822 dst_addr -= sat->block_size_byte;
823 }
824 }
825
page_inv(struct stressapptest_params * sat,u8 cpu_id)826 static u32 page_inv(struct stressapptest_params *sat, u8 cpu_id)
827 {
828 u32 src;
829 void *dst_block_addr;
830 u32 err = 0;
831
832 src = page_rand_pick(page_list, 1, sat, cpu_id); /* pick a valid page */
833 dst_block_addr = page_list[src].base_addr;
834
835 for (int i = 0; i < 4; i++) {
836 if (rand() % 2 == 0)
837 page_inv_up(page_list[src].base_addr, sat);
838 else
839 page_inv_down(page_list[src].base_addr, sat);
840 }
841
842 for (int i = 0; i < sat->block_num; i++) {
843 err += block_inv_check(dst_block_addr, page_list[src].pattern, sat, cpu_id);
844 dst_block_addr += sat->block_size_byte;
845 }
846
847 return err;
848 }
849
block_copy_check(void * dst_addr,struct adler_sum * adler_sum,struct pattern * src_pattern,struct stressapptest_params * sat,u8 cpu_id)850 static u32 block_copy_check(void *dst_addr, struct adler_sum *adler_sum,
851 struct pattern *src_pattern, struct stressapptest_params *sat,
852 u8 cpu_id)
853 {
854 u32 err = 0;
855
856 if (adler_sum->a1 != src_pattern->adler_sum.a1 ||
857 adler_sum->b1 != src_pattern->adler_sum.b1 ||
858 adler_sum->a2 != src_pattern->adler_sum.a2 ||
859 adler_sum->b2 != src_pattern->adler_sum.b2)
860 err = block_mis_search(dst_addr, src_pattern, "Copy", sat, cpu_id);
861
862 return err;
863 }
864
block_copy(void * dst_addr,void * src_addr,struct pattern * src_pattern,struct stressapptest_params * sat,u8 cpu_id)865 static u32 block_copy(void *dst_addr, void *src_addr,
866 struct pattern *src_pattern,
867 struct stressapptest_params *sat, u8 cpu_id)
868 {
869 u64 *dst_mem;
870 u64 *src_mem;
871 u64 data;
872 int i = 0;
873 #if defined(WARM_CPU)
874 double a, b, c, d;
875 #endif
876
877 struct adler_sum adler_sum = {
878 1, 0, 1, 0
879 };
880
881 dst_mem = (u64 *)dst_addr;
882 src_mem = (u64 *)src_addr;
883
884 #if defined(WARM_CPU)
885 a = 2.0 * src_mem[0];
886 b = 5.0 * src_mem[0];
887 c = 7.0 * src_mem[0];
888 d = 9.0 * src_mem[0];
889 #endif
890
891 while (i < sat->block_size_byte / sizeof(u64)) {
892 data = src_mem[i];
893 adler_sum.a1 += data & 0xffffffff;
894 adler_sum.b1 += adler_sum.a1;
895 adler_sum.a1 += data >> 32;
896 adler_sum.b1 += adler_sum.a1;
897 dst_mem[i] = data;
898 i++;
899
900 #if defined(WARM_CPU)
901 a = a * b;
902 b = b + c;
903 #endif
904
905 data = src_mem[i];
906 adler_sum.a2 += data & 0xffffffff;
907 adler_sum.b2 += adler_sum.a2;
908 adler_sum.a2 += data >> 32;
909 adler_sum.b2 += adler_sum.a2;
910 dst_mem[i] = data;
911 i++;
912
913 #if defined(WARM_CPU)
914 c = c * d;
915 d = d + d;
916 #endif
917 }
918
919 #if defined(WARM_CPU)
920 d = a + b + c + d;
921 if (d == 1.0)
922 /* Reference the result so that it can't be discarded by the compiler. */
923 printf("This will probably never happen.\n");
924 #endif
925
926 return block_copy_check(dst_addr, &adler_sum, src_pattern, sat, cpu_id);
927 }
928
page_copy(struct stressapptest_params * sat,u8 cpu_id)929 static u32 page_copy(struct stressapptest_params *sat, u8 cpu_id)
930 {
931 u32 dst;
932 u32 src;
933 void *dst_block_addr;
934 void *src_block_addr;
935 u32 err = 0;
936
937 dst = page_rand_pick(page_list, 0, sat, cpu_id); /* pick a empty page */
938 dst_block_addr = page_list[dst].base_addr;
939 src = page_rand_pick(page_list, 1, sat, cpu_id); /* pick a valid page */
940 src_block_addr = page_list[src].base_addr;
941
942 for (int i = 0; i < sat->block_num; i++) {
943 err += block_copy(dst_block_addr, src_block_addr,
944 page_list[src].pattern, sat, cpu_id);
945 dst_block_addr += sat->block_size_byte;
946 src_block_addr += sat->block_size_byte;
947 }
948
949 page_list[dst].pattern = page_list[src].pattern;
950 page_list[dst].valid = 1;
951 page_list[src].valid = 0;
952 flush_dcache_range((ulong)&page_list[src], (ulong)&page_list[src + 1]);
953 flush_dcache_range((ulong)&page_list[dst], (ulong)&page_list[dst + 1]);
954
955 return err;
956 }
957
secondary_main(void)958 void secondary_main(void)
959 {
960 #if (CPU_NUM_MAX > 1)
961 u8 cpu_id;
962 ulong test = 0;
963
964 #ifndef CONFIG_ARM64
965 asm volatile("mov r9, %0" : : "r" (__gd)); /* set r9 to gd addr */
966 #else
967 asm volatile("mov x18, %0" : : "r" (__gd)); /* set x18 to gd addr */
968 #endif
969 dcache_enable();
970 icache_enable();
971
972 udelay(100);
973
974 flush_dcache_all();
975
976 cpu_id = sat.cpu_num;
977 cpu_init_finish[cpu_id] = 1;
978 printf("CPU%d start OK.\n", cpu_id);
979
980 while (pattern_page_init_finish == 0) {
981 udelay(100);
982 flush_dcache_all();
983 }
984
985 while (1) {
986 udelay(100);
987 flush_dcache_all();
988 while (test < test_count) {
989 cpu_test_finish[cpu_id] = 0;
990 flush_dcache_all();
991 while (run_time_us() < test_time_us) {
992 if (rand() % 2 == 0)
993 cpu_copy_err[cpu_id] += page_copy(&sat, cpu_id);
994 else
995 cpu_inv_err[cpu_id] += page_inv(&sat, cpu_id);
996 }
997 test++;
998 cpu_test_finish[cpu_id] = 1;
999 flush_dcache_range((ulong)&cpu_test_finish[cpu_id],
1000 (ulong)&cpu_test_finish[cpu_id + 1]);
1001 flush_dcache_range((ulong)&cpu_copy_err[cpu_id],
1002 (ulong)&cpu_copy_err[cpu_id + 1]);
1003 flush_dcache_range((ulong)&cpu_inv_err[cpu_id],
1004 (ulong)&cpu_inv_err[cpu_id + 1]);
1005 }
1006 }
1007 #else
1008 return;
1009 #endif
1010 }
1011
doing_stressapptest(void)1012 static int doing_stressapptest(void)
1013 {
1014 int i;
1015 u32 pre_10s;
1016 u32 now_10s;
1017
1018 struct pattern pattern_list[PATTERN_LIST_SIZE];
1019 void *page_info;
1020
1021 u32 all_copy_err = 0;
1022 u32 all_inv_err = 0;
1023 u32 cpu_no_response_err = 0;
1024
1025 int ret = CMD_RET_SUCCESS;
1026
1027 for (i = 0; i < CPU_NUM_MAX; i++) {
1028 cpu_copy_err[i] = 0;
1029 cpu_inv_err[i] = 0;
1030 cpu_init_finish[i] = 0;
1031 cpu_test_finish[i] = 0;
1032 }
1033 pattern_page_init_finish = 0;
1034 print_mutex = 0;
1035 asm volatile("clrex");
1036
1037 #if (CPU_NUM_MAX > 1)
1038 if (test_count == 0) {
1039 __gd = (ulong)gd;
1040 asm volatile("mov %0, sp" : "=r" (__sp));
1041 printf("CPU0 sp is at 0x%lx now.\n", __sp);
1042 __sp &= ~(ulong)0xffff;
1043 for (sat.cpu_num = 1; sat.cpu_num < CPU_NUM_MAX; sat.cpu_num++) {
1044 __sp -= 0x10000;
1045 flush_dcache_all();
1046 if (psci_cpu_on(sat.cpu_num, (ulong)secondary_init) == 0) {
1047 mdelay(10);
1048 printf("Calling CPU%d, sp = 0x%lx\n", sat.cpu_num, __sp);
1049 } else {
1050 break;
1051 }
1052 while (cpu_init_finish[sat.cpu_num] == 0) {
1053 udelay(1000);
1054 flush_dcache_all();
1055 }
1056 }
1057 }
1058 #else
1059 sat.cpu_num = 1;
1060 #endif
1061
1062 if (sat.total_test_size_mb == 0)
1063 sat.page_num = get_max_page_num(sat.page_size_byte);
1064 else
1065 sat.page_num = (sat.total_test_size_mb << 20) / sat.page_size_byte;
1066 sat.block_num = sat.page_size_byte / sat.block_size_byte;
1067
1068 udelay(100);
1069
1070 page_info = malloc(sizeof(struct page) * sat.page_num);
1071 if (page_info == 0) {
1072 printf("ERROR: StressAppTest fail to malloc.\n");
1073 printf("Please try increasing CONFIG_SYS_MALLOC_LEN in include/configs/rxxxxx_common.h.\n");
1074 ret = CMD_RET_FAILURE;
1075 goto out;
1076 }
1077 page_list = (struct page *)page_info;
1078
1079 if (get_page_addr(page_list, &sat) < 0) {
1080 ret = CMD_RET_FAILURE;
1081 goto out;
1082 }
1083
1084 pattern_list_init(pattern_list, &sat);
1085 page_init(pattern_list, &sat);
1086
1087 #if (CPU_NUM_MAX > 1)
1088 if (sat.cpu_num > 1) {
1089 pattern_page_init_finish = 1;
1090 test_count++;
1091 flush_dcache_all();
1092 }
1093 #endif
1094
1095 pre_10s = (u32)(run_time_us() / 1000000 / 10);
1096 lock_byte_mutex(&print_mutex);
1097 print_time_stamp();
1098 printf("Start StressAppTest in U-Boot:\n");
1099 unlock_byte_mutex(&print_mutex);
1100
1101 while (run_time_us() < test_time_us) {
1102 if (rand() % 2 == 0)
1103 cpu_copy_err[0] += page_copy(&sat, 0);
1104 else
1105 cpu_inv_err[0] += page_inv(&sat, 0);
1106
1107 /* Print every 10 seconds */
1108 now_10s = (u32)(run_time_us() / 1000000 / 10);
1109 if (now_10s > pre_10s) {
1110 pre_10s = now_10s;
1111 lock_byte_mutex(&print_mutex);
1112 print_time_stamp();
1113 printf("Seconds remaining: %d\n", (u32)(test_time_us / 1000000 - now_10s * 10));
1114 unlock_byte_mutex(&print_mutex);
1115 }
1116 }
1117
1118 #if (CPU_NUM_MAX > 1)
1119 for (i = 1; i < sat.cpu_num; i++) {
1120 while (cpu_test_finish[i] == 0) {
1121 if ((u32)(run_time_us() / 1000000 / 10) > pre_10s + 6) {
1122 /* wait for secondary CPU in 60s */
1123 lock_byte_mutex(&print_mutex);
1124 print_time_stamp();
1125 printf("ERROR: Cannot wait for CPU%d to finish!\n", i);
1126 unlock_byte_mutex(&print_mutex);
1127 cpu_no_response_err++;
1128 break;
1129 }
1130 mdelay(1);
1131 flush_dcache_range((ulong)&cpu_test_finish[i],
1132 (ulong)&cpu_test_finish[i + 1]);
1133 }
1134 }
1135 flush_dcache_all();
1136 #endif
1137
1138 for (i = 0; i < sat.cpu_num; i++) {
1139 all_copy_err += cpu_copy_err[i];
1140 all_inv_err += cpu_inv_err[i];
1141 }
1142 print_time_stamp();
1143 printf("StressAppTest Result: ");
1144 if (all_copy_err == 0 && all_inv_err == 0 && cpu_no_response_err == 0)
1145 printf("Pass.\n");
1146 else
1147 printf("FAIL!\nStressAppTest detects %d copy errors, %d inv errors.\n",
1148 all_copy_err, all_inv_err);
1149
1150 out:
1151 free(page_info);
1152
1153 return ret;
1154 }
1155
do_stressapptest(cmd_tbl_t * cmdtp,int flag,int argc,char * const argv[])1156 static int do_stressapptest(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
1157 {
1158 ulong test_time_sec = 20;
1159 ulong page_size_kb = 1024;
1160
1161 sat.total_test_size_mb = 0;
1162 sat.block_size_byte = 4096;
1163 sat.total_start_addr = 0x0;
1164
1165 printf("StressAppTest in U-Boot, " __version__ "\n");
1166
1167 if (argc > 1) {
1168 if (strict_strtoul(argv[1], 0, &test_time_sec) < 0)
1169 return CMD_RET_USAGE;
1170 if (test_time_sec < 1)
1171 test_time_sec = 20;
1172 }
1173 if (argc > 2) {
1174 if (strict_strtoul(argv[2], 0, &sat.total_test_size_mb) < 0)
1175 return CMD_RET_USAGE;
1176 if (sat.total_test_size_mb < 1)
1177 sat.total_test_size_mb = 0;
1178 }
1179 if (argc > 3) {
1180 if (strict_strtoul(argv[3], 0, &sat.total_start_addr) < 0)
1181 return CMD_RET_USAGE;
1182 if (sat.total_start_addr < 0x1)
1183 sat.total_start_addr = 0x0;
1184 }
1185 if (argc > 4) {
1186 if (strict_strtoul(argv[4], 0, &page_size_kb) < 0)
1187 return CMD_RET_USAGE;
1188 if (page_size_kb < 1)
1189 page_size_kb = 1024;
1190 }
1191
1192 sat.page_size_byte = page_size_kb << 10;
1193
1194 start_time_us = get_time_us();
1195 test_time_us = (u64)test_time_sec * 1000000;
1196
1197 /* Change rand seed. If not do this, rand() would be same after boot.*/
1198 srand((unsigned int)(start_time_us & 0xffffffff));
1199
1200 return doing_stressapptest();
1201 }
1202
1203 U_BOOT_CMD(stressapptest, 5, 1, do_stressapptest,
1204 "StressAppTest for Rockchip\n",
1205 "\narg1: test time in second, default value is 20s.\n"
1206 "arg2: test size in MB, default value is all available space.\n"
1207 "arg3: start addr for test.\n"
1208 "arg4: test page size in kB, default value is 1024kB(1MB).\n"
1209 "example:\n"
1210 " stressapptest: test for 20s, test size is all available space, each page size is 1MB.\n"
1211 " stressapptest 43200 64: test for 12h, test size is 64MB, each page size is 1MB (64 pages).\n"
1212 " stressapptest 86400 1024 0x80000000: test for 24h, test size is 1024MB, start addr for test is 0x80000000, each page size is 1MB (1024 pages).\n"
1213 " stressapptest 43200 16 0x40000000 512: test for 12h, test size is 16MB, start addr for test is 0x40000000, each page size is 512kB (32 pages).\n"
1214 );
1215