]> git.proxmox.com Git - mirror_qemu.git/blob - tests/tcg/multiarch/system/memory.c
Merge tag 'q800-for-8.2-pull-request' of https://github.com/vivier/qemu-m68k into...
[mirror_qemu.git] / tests / tcg / multiarch / system / memory.c
1 /*
2 * Memory Test
3 *
4 * This is intended to test the softmmu code and ensure we properly
5 * behave across normal and unaligned accesses across several pages.
6 * We are not replicating memory tests for stuck bits and other
7 * hardware level failures but looking for issues with different size
8 * accesses when access is:
9 *
10 * - unaligned at various sizes (if -DCHECK_UNALIGNED set)
11 * - spanning a (softmmu) page
12 * - sign extension when loading
13 */
14
15 #include <stdint.h>
16 #include <stdbool.h>
17 #include <minilib.h>
18
19 #ifndef CHECK_UNALIGNED
20 # error "Target does not specify CHECK_UNALIGNED"
21 #endif
22
23 #define MEM_PAGE_SIZE 4096 /* nominal 4k "pages" */
24 #define TEST_SIZE (MEM_PAGE_SIZE * 4) /* 4 pages */
25
26 #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])))
27
28 __attribute__((aligned(MEM_PAGE_SIZE)))
29 static uint8_t test_data[TEST_SIZE];
30
31 typedef void (*init_ufn) (int offset);
32 typedef bool (*read_ufn) (int offset);
33 typedef bool (*read_sfn) (int offset, bool nf);
34
35 static void pdot(int count)
36 {
37 if (count % 128 == 0) {
38 ml_printf(".");
39 }
40 }
41
42 /*
43 * Helper macros for endian handling.
44 */
45 #if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__
46 #define BYTE_SHIFT(b, pos) (b << (pos * 8))
47 #define BYTE_NEXT(b) ((b)++)
48 #elif __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
49 #define BYTE_SHIFT(b, pos) (b << ((sizeof(b) - 1 - (pos)) * 8))
50 #define BYTE_NEXT(b) (--(b))
51 #else
52 #error Unsupported __BYTE_ORDER__
53 #endif
54
55 /*
56 * Fill the data with ascending (for little-endian) or descending (for
57 * big-endian) value bytes.
58 */
59
60 static void init_test_data_u8(int unused_offset)
61 {
62 uint8_t count = 0, *ptr = &test_data[0];
63 int i;
64 (void)(unused_offset);
65
66 ml_printf("Filling test area with u8:");
67 for (i = 0; i < TEST_SIZE; i++) {
68 *ptr++ = BYTE_NEXT(count);
69 pdot(i);
70 }
71 ml_printf("done\n");
72 }
73
74 /*
75 * Fill the data with alternating positive and negative bytes. This
76 * should mean for reads larger than a byte all subsequent reads will
77 * stay either negative or positive. We never write 0.
78 */
79
80 static inline uint8_t get_byte(int index, bool neg)
81 {
82 return neg ? (0xff << (index % 7)) : (0xff >> ((index % 6) + 1));
83 }
84
85 static void init_test_data_s8(bool neg_first)
86 {
87 uint8_t top, bottom, *ptr = &test_data[0];
88 int i;
89
90 ml_printf("Filling test area with s8 pairs (%s):",
91 neg_first ? "neg first" : "pos first");
92 for (i = 0; i < TEST_SIZE / 2; i++) {
93 *ptr++ = get_byte(i, neg_first);
94 *ptr++ = get_byte(i, !neg_first);
95 pdot(i);
96 }
97 ml_printf("done\n");
98 }
99
100 /*
101 * Zero the first few bytes of the test data in preparation for
102 * new offset values.
103 */
104 static void reset_start_data(int offset)
105 {
106 uint32_t *ptr = (uint32_t *) &test_data[0];
107 int i;
108 for (i = 0; i < offset; i++) {
109 *ptr++ = 0;
110 }
111 }
112
113 static void init_test_data_u16(int offset)
114 {
115 uint8_t count = 0;
116 uint16_t word, *ptr = (uint16_t *) &test_data[offset];
117 const int max = (TEST_SIZE - offset) / sizeof(word);
118 int i;
119
120 ml_printf("Filling test area with u16 (offset %d, %p):", offset, ptr);
121
122 reset_start_data(offset);
123
124 for (i = 0; i < max; i++) {
125 uint16_t low = BYTE_NEXT(count), high = BYTE_NEXT(count);
126 word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
127 *ptr++ = word;
128 pdot(i);
129 }
130 ml_printf("done @ %p\n", ptr);
131 }
132
133 static void init_test_data_u32(int offset)
134 {
135 uint8_t count = 0;
136 uint32_t word, *ptr = (uint32_t *) &test_data[offset];
137 const int max = (TEST_SIZE - offset) / sizeof(word);
138 int i;
139
140 ml_printf("Filling test area with u32 (offset %d, %p):", offset, ptr);
141
142 reset_start_data(offset);
143
144 for (i = 0; i < max; i++) {
145 uint32_t b4 = BYTE_NEXT(count), b3 = BYTE_NEXT(count);
146 uint32_t b2 = BYTE_NEXT(count), b1 = BYTE_NEXT(count);
147 word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) |
148 BYTE_SHIFT(b4, 0);
149 *ptr++ = word;
150 pdot(i);
151 }
152 ml_printf("done @ %p\n", ptr);
153 }
154
155 static void init_test_data_u64(int offset)
156 {
157 uint8_t count = 0;
158 uint64_t word, *ptr = (uint64_t *) &test_data[offset];
159 const int max = (TEST_SIZE - offset) / sizeof(word);
160 int i;
161
162 ml_printf("Filling test area with u64 (offset %d, %p):", offset, ptr);
163
164 reset_start_data(offset);
165
166 for (i = 0; i < max; i++) {
167 uint64_t b8 = BYTE_NEXT(count), b7 = BYTE_NEXT(count);
168 uint64_t b6 = BYTE_NEXT(count), b5 = BYTE_NEXT(count);
169 uint64_t b4 = BYTE_NEXT(count), b3 = BYTE_NEXT(count);
170 uint64_t b2 = BYTE_NEXT(count), b1 = BYTE_NEXT(count);
171 word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
172 BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
173 BYTE_SHIFT(b7, 1) | BYTE_SHIFT(b8, 0);
174 *ptr++ = word;
175 pdot(i);
176 }
177 ml_printf("done @ %p\n", ptr);
178 }
179
180 static bool read_test_data_u16(int offset)
181 {
182 uint16_t word, *ptr = (uint16_t *)&test_data[offset];
183 int i;
184 const int max = (TEST_SIZE - offset) / sizeof(word);
185
186 ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
187
188 for (i = 0; i < max; i++) {
189 uint8_t high, low;
190 word = *ptr++;
191 high = (word >> 8) & 0xff;
192 low = word & 0xff;
193 if (high < low && high != 0) {
194 ml_printf("Error %d < %d\n", high, low);
195 return false;
196 } else {
197 pdot(i);
198 }
199
200 }
201 ml_printf("done @ %p\n", ptr);
202 return true;
203 }
204
205 static bool read_test_data_u32(int offset)
206 {
207 uint32_t word, *ptr = (uint32_t *)&test_data[offset];
208 int i;
209 const int max = (TEST_SIZE - offset) / sizeof(word);
210
211 ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
212
213 for (i = 0; i < max; i++) {
214 uint8_t b1, b2, b3, b4;
215 int zeros = 0;
216 word = *ptr++;
217
218 b1 = word >> 24 & 0xff;
219 b2 = word >> 16 & 0xff;
220 b3 = word >> 8 & 0xff;
221 b4 = word & 0xff;
222
223 zeros += (b1 == 0 ? 1 : 0);
224 zeros += (b2 == 0 ? 1 : 0);
225 zeros += (b3 == 0 ? 1 : 0);
226 zeros += (b4 == 0 ? 1 : 0);
227 if (zeros > 1) {
228 ml_printf("Error @ %p, more zeros than expected: %d, %d, %d, %d",
229 ptr - 1, b1, b2, b3, b4);
230 return false;
231 }
232
233 if ((b1 < b2 && b1 != 0) ||
234 (b2 < b3 && b2 != 0) ||
235 (b3 < b4 && b3 != 0)) {
236 ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
237 return false;
238 } else {
239 pdot(i);
240 }
241 }
242 ml_printf("done @ %p\n", ptr);
243 return true;
244 }
245
246 static bool read_test_data_u64(int offset)
247 {
248 uint64_t word, *ptr = (uint64_t *)&test_data[offset];
249 int i;
250 const int max = (TEST_SIZE - offset) / sizeof(word);
251
252 ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
253
254 for (i = 0; i < max; i++) {
255 uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
256 int zeros = 0;
257 word = *ptr++;
258
259 b1 = ((uint64_t) (word >> 56)) & 0xff;
260 b2 = ((uint64_t) (word >> 48)) & 0xff;
261 b3 = ((uint64_t) (word >> 40)) & 0xff;
262 b4 = (word >> 32) & 0xff;
263 b5 = (word >> 24) & 0xff;
264 b6 = (word >> 16) & 0xff;
265 b7 = (word >> 8) & 0xff;
266 b8 = (word >> 0) & 0xff;
267
268 zeros += (b1 == 0 ? 1 : 0);
269 zeros += (b2 == 0 ? 1 : 0);
270 zeros += (b3 == 0 ? 1 : 0);
271 zeros += (b4 == 0 ? 1 : 0);
272 zeros += (b5 == 0 ? 1 : 0);
273 zeros += (b6 == 0 ? 1 : 0);
274 zeros += (b7 == 0 ? 1 : 0);
275 zeros += (b8 == 0 ? 1 : 0);
276 if (zeros > 1) {
277 ml_printf("Error @ %p, more zeros than expected: %d, %d, %d, %d, %d, %d, %d, %d",
278 ptr - 1, b1, b2, b3, b4, b5, b6, b7, b8);
279 return false;
280 }
281
282 if ((b1 < b2 && b1 != 0) ||
283 (b2 < b3 && b2 != 0) ||
284 (b3 < b4 && b3 != 0) ||
285 (b4 < b5 && b4 != 0) ||
286 (b5 < b6 && b5 != 0) ||
287 (b6 < b7 && b6 != 0) ||
288 (b7 < b8 && b7 != 0)) {
289 ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
290 b1, b2, b3, b4, b5, b6, b7, b8);
291 return false;
292 } else {
293 pdot(i);
294 }
295 }
296 ml_printf("done @ %p\n", ptr);
297 return true;
298 }
299
300 /* Read the test data and verify at various offsets */
301 read_ufn read_ufns[] = { read_test_data_u16,
302 read_test_data_u32,
303 read_test_data_u64 };
304
305 bool do_unsigned_reads(int start_off)
306 {
307 int i;
308 bool ok = true;
309
310 for (i = 0; i < ARRAY_SIZE(read_ufns) && ok; i++) {
311 #if CHECK_UNALIGNED
312 int off;
313 for (off = start_off; off < 8 && ok; off++) {
314 ok = read_ufns[i](off);
315 }
316 #else
317 ok = read_ufns[i](start_off);
318 #endif
319 }
320
321 return ok;
322 }
323
324 static bool do_unsigned_test(init_ufn fn)
325 {
326 #if CHECK_UNALIGNED
327 bool ok = true;
328 int i;
329 for (i = 0; i < 8 && ok; i++) {
330 fn(i);
331 ok = do_unsigned_reads(i);
332 }
333 return ok;
334 #else
335 fn(0);
336 return do_unsigned_reads(0);
337 #endif
338 }
339
340 /*
341 * We need to ensure signed data is read into a larger data type to
342 * ensure that sign extension is working properly.
343 */
344
345 static bool read_test_data_s8(int offset, bool neg_first)
346 {
347 int8_t *ptr = (int8_t *)&test_data[offset];
348 int i;
349 const int max = (TEST_SIZE - offset) / 2;
350
351 ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr, offset);
352
353 for (i = 0; i < max; i++) {
354 int16_t first, second;
355 bool ok;
356 first = *ptr++;
357 second = *ptr++;
358
359 if (neg_first && first < 0 && second > 0) {
360 pdot(i);
361 } else if (!neg_first && first > 0 && second < 0) {
362 pdot(i);
363 } else {
364 ml_printf("Error %d %c %d\n", first, neg_first ? '<' : '>', second);
365 return false;
366 }
367 }
368 ml_printf("done @ %p\n", ptr);
369 return true;
370 }
371
372 static bool read_test_data_s16(int offset, bool neg_first)
373 {
374 int16_t *ptr = (int16_t *)&test_data[offset];
375 int i;
376 const int max = (TEST_SIZE - offset) / (sizeof(*ptr));
377
378 ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr,
379 offset, neg_first ? "neg" : "pos");
380
381 /*
382 * If the first byte is negative, then the last byte is positive.
383 * Therefore the logic below must be flipped for big-endian.
384 */
385 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
386 neg_first = !neg_first;
387 #endif
388
389 for (i = 0; i < max; i++) {
390 int32_t data = *ptr++;
391
392 if (neg_first && data < 0) {
393 pdot(i);
394 } else if (!neg_first && data > 0) {
395 pdot(i);
396 } else {
397 ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
398 return false;
399 }
400 }
401 ml_printf("done @ %p\n", ptr);
402 return true;
403 }
404
405 static bool read_test_data_s32(int offset, bool neg_first)
406 {
407 int32_t *ptr = (int32_t *)&test_data[offset];
408 int i;
409 const int max = (TEST_SIZE - offset) / (sizeof(int32_t));
410
411 ml_printf("Reading s32 from %#lx (offset %d, %s):",
412 ptr, offset, neg_first ? "neg" : "pos");
413
414 /*
415 * If the first byte is negative, then the last byte is positive.
416 * Therefore the logic below must be flipped for big-endian.
417 */
418 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
419 neg_first = !neg_first;
420 #endif
421
422 for (i = 0; i < max; i++) {
423 int64_t data = *ptr++;
424
425 if (neg_first && data < 0) {
426 pdot(i);
427 } else if (!neg_first && data > 0) {
428 pdot(i);
429 } else {
430 ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
431 return false;
432 }
433 }
434 ml_printf("done @ %p\n", ptr);
435 return true;
436 }
437
438 /*
439 * Read the test data and verify at various offsets
440 *
441 * For everything except bytes all our reads should be either positive
442 * or negative depending on what offset we are reading from.
443 */
444 read_sfn read_sfns[] = { read_test_data_s8,
445 read_test_data_s16,
446 read_test_data_s32 };
447
448 bool do_signed_reads(bool neg_first)
449 {
450 int i;
451 bool ok = true;
452
453 for (i = 0; i < ARRAY_SIZE(read_sfns) && ok; i++) {
454 #if CHECK_UNALIGNED
455 int off;
456 for (off = 0; off < 8 && ok; off++) {
457 bool nf = i == 0 ? neg_first ^ (off & 1) : !(neg_first ^ (off & 1));
458 ok = read_sfns[i](off, nf);
459 }
460 #else
461 ok = read_sfns[i](0, i == 0 ? neg_first : !neg_first);
462 #endif
463 }
464
465 return ok;
466 }
467
468 init_ufn init_ufns[] = { init_test_data_u8,
469 init_test_data_u16,
470 init_test_data_u32,
471 init_test_data_u64 };
472
473 int main(void)
474 {
475 int i;
476 bool ok = true;
477
478 /* Run through the unsigned tests first */
479 for (i = 0; i < ARRAY_SIZE(init_ufns) && ok; i++) {
480 ok = do_unsigned_test(init_ufns[i]);
481 }
482
483 if (ok) {
484 init_test_data_s8(false);
485 ok = do_signed_reads(false);
486 }
487
488 if (ok) {
489 init_test_data_s8(true);
490 ok = do_signed_reads(true);
491 }
492
493 ml_printf("Test complete: %s\n", ok ? "PASSED" : "FAILED");
494 return ok ? 0 : -1;
495 }