Merge remote-tracking branch 'remotes/dgilbert-gitlab/tags/pull-migration-20210726a...
[qemu/armbru.git] / tests / tcg / multiarch / system / memory.c
blob41c7f66e2ed90ee3c8fa8f037b7f852e0ac19e21
1 /*
2 * Memory Test
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:
10 * - unaligned at various sizes (if -DCHECK_UNALIGNED set)
11 * - spanning a (softmmu) page
12 * - sign extension when loading
15 #include <inttypes.h>
16 #include <stdbool.h>
17 #include <minilib.h>
19 #ifndef CHECK_UNALIGNED
20 # error "Target does not specify CHECK_UNALIGNED"
21 #endif
23 #define MEM_PAGE_SIZE 4096 /* nominal 4k "pages" */
24 #define TEST_SIZE (MEM_PAGE_SIZE * 4) /* 4 pages */
26 #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])))
28 __attribute__((aligned(MEM_PAGE_SIZE)))
29 static uint8_t test_data[TEST_SIZE];
31 typedef void (*init_ufn) (int offset);
32 typedef bool (*read_ufn) (int offset);
33 typedef bool (*read_sfn) (int offset, bool nf);
35 static void pdot(int count)
37 if (count % 128 == 0) {
38 ml_printf(".");
43 * Helper macros for shift/extract so we can keep our endian handling
44 * in one place.
46 #define BYTE_SHIFT(b, pos) ((uint64_t)b << (pos * 8))
47 #define BYTE_EXTRACT(b, pos) ((b >> (pos * 8)) & 0xff)
50 * Fill the data with ascending value bytes.
52 * Currently we only support Little Endian machines so write in
53 * ascending address order. When we read higher address bytes should
54 * either be zero or higher than the lower bytes.
57 static void init_test_data_u8(int unused_offset)
59 uint8_t count = 0, *ptr = &test_data[0];
60 int i;
61 (void)(unused_offset);
63 ml_printf("Filling test area with u8:");
64 for (i = 0; i < TEST_SIZE; i++) {
65 *ptr++ = count++;
66 pdot(i);
68 ml_printf("done\n");
72 * Full the data with alternating positive and negative bytes. This
73 * should mean for reads larger than a byte all subsequent reads will
74 * stay either negative or positive. We never write 0.
77 static inline uint8_t get_byte(int index, bool neg)
79 return neg ? (0xff << (index % 7)) : (0xff >> ((index % 6) + 1));
82 static void init_test_data_s8(bool neg_first)
84 uint8_t top, bottom, *ptr = &test_data[0];
85 int i;
87 ml_printf("Filling test area with s8 pairs (%s):",
88 neg_first ? "neg first" : "pos first");
89 for (i = 0; i < TEST_SIZE / 2; i++) {
90 *ptr++ = get_byte(i, neg_first);
91 *ptr++ = get_byte(i, !neg_first);
92 pdot(i);
94 ml_printf("done\n");
98 * Zero the first few bytes of the test data in preparation for
99 * new offset values.
101 static void reset_start_data(int offset)
103 uint32_t *ptr = (uint32_t *) &test_data[0];
104 int i;
105 for (i = 0; i < offset; i++) {
106 *ptr++ = 0;
110 static void init_test_data_u16(int offset)
112 uint8_t count = 0;
113 uint16_t word, *ptr = (uint16_t *) &test_data[offset];
114 const int max = (TEST_SIZE - offset) / sizeof(word);
115 int i;
117 ml_printf("Filling test area with u16 (offset %d, %p):", offset, ptr);
119 reset_start_data(offset);
121 for (i = 0; i < max; i++) {
122 uint8_t low = count++, high = count++;
123 word = BYTE_SHIFT(high, 1) | BYTE_SHIFT(low, 0);
124 *ptr++ = word;
125 pdot(i);
127 ml_printf("done @ %p\n", ptr);
130 static void init_test_data_u32(int offset)
132 uint8_t count = 0;
133 uint32_t word, *ptr = (uint32_t *) &test_data[offset];
134 const int max = (TEST_SIZE - offset) / sizeof(word);
135 int i;
137 ml_printf("Filling test area with u32 (offset %d, %p):", offset, ptr);
139 reset_start_data(offset);
141 for (i = 0; i < max; i++) {
142 uint8_t b4 = count++, b3 = count++;
143 uint8_t b2 = count++, b1 = count++;
144 word = BYTE_SHIFT(b1, 3) | BYTE_SHIFT(b2, 2) | BYTE_SHIFT(b3, 1) | b4;
145 *ptr++ = word;
146 pdot(i);
148 ml_printf("done @ %p\n", ptr);
151 static void init_test_data_u64(int offset)
153 uint8_t count = 0;
154 uint64_t word, *ptr = (uint64_t *) &test_data[offset];
155 const int max = (TEST_SIZE - offset) / sizeof(word);
156 int i;
158 ml_printf("Filling test area with u64 (offset %d, %p):", offset, ptr);
160 reset_start_data(offset);
162 for (i = 0; i < max; i++) {
163 uint8_t b8 = count++, b7 = count++;
164 uint8_t b6 = count++, b5 = count++;
165 uint8_t b4 = count++, b3 = count++;
166 uint8_t b2 = count++, b1 = count++;
167 word = BYTE_SHIFT(b1, 7) | BYTE_SHIFT(b2, 6) | BYTE_SHIFT(b3, 5) |
168 BYTE_SHIFT(b4, 4) | BYTE_SHIFT(b5, 3) | BYTE_SHIFT(b6, 2) |
169 BYTE_SHIFT(b7, 1) | b8;
170 *ptr++ = word;
171 pdot(i);
173 ml_printf("done @ %p\n", ptr);
176 static bool read_test_data_u16(int offset)
178 uint16_t word, *ptr = (uint16_t *)&test_data[offset];
179 int i;
180 const int max = (TEST_SIZE - offset) / sizeof(word);
182 ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
184 for (i = 0; i < max; i++) {
185 uint8_t high, low;
186 word = *ptr++;
187 high = (word >> 8) & 0xff;
188 low = word & 0xff;
189 if (high < low && high != 0) {
190 ml_printf("Error %d < %d\n", high, low);
191 return false;
192 } else {
193 pdot(i);
197 ml_printf("done @ %p\n", ptr);
198 return true;
201 static bool read_test_data_u32(int offset)
203 uint32_t word, *ptr = (uint32_t *)&test_data[offset];
204 int i;
205 const int max = (TEST_SIZE - offset) / sizeof(word);
207 ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
209 for (i = 0; i < max; i++) {
210 uint8_t b1, b2, b3, b4;
211 int zeros = 0;
212 word = *ptr++;
214 b1 = word >> 24 & 0xff;
215 b2 = word >> 16 & 0xff;
216 b3 = word >> 8 & 0xff;
217 b4 = word & 0xff;
219 zeros += (b1 == 0 ? 1 : 0);
220 zeros += (b2 == 0 ? 1 : 0);
221 zeros += (b3 == 0 ? 1 : 0);
222 zeros += (b4 == 0 ? 1 : 0);
223 if (zeros > 1) {
224 ml_printf("Error @ %p, more zeros than expected: %d, %d, %d, %d",
225 ptr - 1, b1, b2, b3, b4);
226 return false;
229 if ((b1 < b2 && b1 != 0) ||
230 (b2 < b3 && b2 != 0) ||
231 (b3 < b4 && b3 != 0)) {
232 ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
233 return false;
234 } else {
235 pdot(i);
238 ml_printf("done @ %p\n", ptr);
239 return true;
242 static bool read_test_data_u64(int offset)
244 uint64_t word, *ptr = (uint64_t *)&test_data[offset];
245 int i;
246 const int max = (TEST_SIZE - offset) / sizeof(word);
248 ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
250 for (i = 0; i < max; i++) {
251 uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
252 int zeros = 0;
253 word = *ptr++;
255 b1 = ((uint64_t) (word >> 56)) & 0xff;
256 b2 = ((uint64_t) (word >> 48)) & 0xff;
257 b3 = ((uint64_t) (word >> 40)) & 0xff;
258 b4 = (word >> 32) & 0xff;
259 b5 = (word >> 24) & 0xff;
260 b6 = (word >> 16) & 0xff;
261 b7 = (word >> 8) & 0xff;
262 b8 = (word >> 0) & 0xff;
264 zeros += (b1 == 0 ? 1 : 0);
265 zeros += (b2 == 0 ? 1 : 0);
266 zeros += (b3 == 0 ? 1 : 0);
267 zeros += (b4 == 0 ? 1 : 0);
268 zeros += (b5 == 0 ? 1 : 0);
269 zeros += (b6 == 0 ? 1 : 0);
270 zeros += (b7 == 0 ? 1 : 0);
271 zeros += (b8 == 0 ? 1 : 0);
272 if (zeros > 1) {
273 ml_printf("Error @ %p, more zeros than expected: %d, %d, %d, %d, %d, %d, %d, %d",
274 ptr - 1, b1, b2, b3, b4, b5, b6, b7, b8);
275 return false;
278 if ((b1 < b2 && b1 != 0) ||
279 (b2 < b3 && b2 != 0) ||
280 (b3 < b4 && b3 != 0) ||
281 (b4 < b5 && b4 != 0) ||
282 (b5 < b6 && b5 != 0) ||
283 (b6 < b7 && b6 != 0) ||
284 (b7 < b8 && b7 != 0)) {
285 ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
286 b1, b2, b3, b4, b5, b6, b7, b8);
287 return false;
288 } else {
289 pdot(i);
292 ml_printf("done @ %p\n", ptr);
293 return true;
296 /* Read the test data and verify at various offsets */
297 read_ufn read_ufns[] = { read_test_data_u16,
298 read_test_data_u32,
299 read_test_data_u64 };
301 bool do_unsigned_reads(int start_off)
303 int i;
304 bool ok = true;
306 for (i = 0; i < ARRAY_SIZE(read_ufns) && ok; i++) {
307 #if CHECK_UNALIGNED
308 int off;
309 for (off = start_off; off < 8 && ok; off++) {
310 ok = read_ufns[i](off);
312 #else
313 ok = read_ufns[i](start_off);
314 #endif
317 return ok;
320 static bool do_unsigned_test(init_ufn fn)
322 #if CHECK_UNALIGNED
323 bool ok = true;
324 int i;
325 for (i = 0; i < 8 && ok; i++) {
326 fn(i);
327 ok = do_unsigned_reads(i);
329 return ok;
330 #else
331 fn(0);
332 return do_unsigned_reads(0);
333 #endif
337 * We need to ensure signed data is read into a larger data type to
338 * ensure that sign extension is working properly.
341 static bool read_test_data_s8(int offset, bool neg_first)
343 int8_t *ptr = (int8_t *)&test_data[offset];
344 int i;
345 const int max = (TEST_SIZE - offset) / 2;
347 ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr, offset);
349 for (i = 0; i < max; i++) {
350 int16_t first, second;
351 bool ok;
352 first = *ptr++;
353 second = *ptr++;
355 if (neg_first && first < 0 && second > 0) {
356 pdot(i);
357 } else if (!neg_first && first > 0 && second < 0) {
358 pdot(i);
359 } else {
360 ml_printf("Error %d %c %d\n", first, neg_first ? '<' : '>', second);
361 return false;
364 ml_printf("done @ %p\n", ptr);
365 return true;
368 static bool read_test_data_s16(int offset, bool neg_first)
370 int16_t *ptr = (int16_t *)&test_data[offset];
371 int i;
372 const int max = (TEST_SIZE - offset) / (sizeof(*ptr));
374 ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr,
375 offset, neg_first ? "neg" : "pos");
377 for (i = 0; i < max; i++) {
378 int32_t data = *ptr++;
380 if (neg_first && data < 0) {
381 pdot(i);
382 } else if (data > 0) {
383 pdot(i);
384 } else {
385 ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
386 return false;
389 ml_printf("done @ %p\n", ptr);
390 return true;
393 static bool read_test_data_s32(int offset, bool neg_first)
395 int32_t *ptr = (int32_t *)&test_data[offset];
396 int i;
397 const int max = (TEST_SIZE - offset) / (sizeof(int32_t));
399 ml_printf("Reading s32 from %#lx (offset %d, %s):",
400 ptr, offset, neg_first ? "neg" : "pos");
402 for (i = 0; i < max; i++) {
403 int64_t data = *ptr++;
405 if (neg_first && data < 0) {
406 pdot(i);
407 } else if (data > 0) {
408 pdot(i);
409 } else {
410 ml_printf("Error %d %c 0\n", data, neg_first ? '<' : '>');
411 return false;
414 ml_printf("done @ %p\n", ptr);
415 return true;
419 * Read the test data and verify at various offsets
421 * For everything except bytes all our reads should be either positive
422 * or negative depending on what offset we are reading from. Currently
423 * we only handle LE systems.
425 read_sfn read_sfns[] = { read_test_data_s8,
426 read_test_data_s16,
427 read_test_data_s32 };
429 bool do_signed_reads(bool neg_first)
431 int i;
432 bool ok = true;
434 for (i = 0; i < ARRAY_SIZE(read_sfns) && ok; i++) {
435 #if CHECK_UNALIGNED
436 int off;
437 for (off = 0; off < 8 && ok; off++) {
438 bool nf = i == 0 ? neg_first ^ (off & 1) : !(neg_first ^ (off & 1));
439 ok = read_sfns[i](off, nf);
441 #else
442 ok = read_sfns[i](0, i == 0 ? neg_first : !neg_first);
443 #endif
446 return ok;
449 init_ufn init_ufns[] = { init_test_data_u8,
450 init_test_data_u16,
451 init_test_data_u32,
452 init_test_data_u64 };
454 int main(void)
456 int i;
457 bool ok = true;
459 /* Run through the unsigned tests first */
460 for (i = 0; i < ARRAY_SIZE(init_ufns) && ok; i++) {
461 ok = do_unsigned_test(init_ufns[i]);
464 if (ok) {
465 init_test_data_s8(false);
466 ok = do_signed_reads(false);
469 if (ok) {
470 init_test_data_s8(true);
471 ok = do_signed_reads(true);
474 ml_printf("Test complete: %s\n", ok ? "PASSED" : "FAILED");
475 return ok ? 0 : -1;