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
19 #ifndef CHECK_UNALIGNED
20 # error "Target does not specify CHECK_UNALIGNED"
23 #define PAGE_SIZE 4096 /* nominal 4k "pages" */
24 #define TEST_SIZE (PAGE_SIZE * 4) /* 4 pages */
26 #define ARRAY_SIZE(x) ((sizeof(x) / sizeof((x)[0])))
28 __attribute__((aligned(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) {
43 * Helper macros for shift/extract so we can keep our endian handling
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];
61 (void)(unused_offset
);
63 ml_printf("Filling test area with u8:");
64 for (i
= 0; i
< TEST_SIZE
; i
++) {
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];
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
);
98 * Zero the first few bytes of the test data in preparation for
101 static void reset_start_data(int offset
)
103 uint32_t *ptr
= (uint32_t *) &test_data
[0];
105 for (i
= 0; i
< offset
; i
++) {
110 static void init_test_data_u16(int offset
)
113 uint16_t word
, *ptr
= (uint16_t *) &test_data
[offset
];
114 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
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);
127 ml_printf("done @ %p\n", ptr
);
130 static void init_test_data_u32(int offset
)
133 uint32_t word
, *ptr
= (uint32_t *) &test_data
[offset
];
134 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
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
;
148 ml_printf("done @ %p\n", ptr
);
151 static void init_test_data_u64(int offset
)
154 uint64_t word
, *ptr
= (uint64_t *) &test_data
[offset
];
155 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
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
;
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
];
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
++) {
187 high
= (word
>> 8) & 0xff;
189 if (high
< low
&& high
!= 0) {
190 ml_printf("Error %d < %d\n", high
, low
);
197 ml_printf("done @ %p\n", ptr
);
201 static bool read_test_data_u32(int offset
)
203 uint32_t word
, *ptr
= (uint32_t *)&test_data
[offset
];
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
;
214 b1
= word
>> 24 & 0xff;
215 b2
= word
>> 16 & 0xff;
216 b3
= word
>> 8 & 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);
224 ml_printf("Error @ %p, more zeros than expected: %d, %d, %d, %d",
225 ptr
- 1, b1
, b2
, b3
, b4
);
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
);
238 ml_printf("done @ %p\n", ptr
);
242 static bool read_test_data_u64(int offset
)
244 uint64_t word
, *ptr
= (uint64_t *)&test_data
[offset
];
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
;
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);
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
);
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
);
292 ml_printf("done @ %p\n", ptr
);
296 /* Read the test data and verify at various offsets */
297 read_ufn read_ufns
[] = { read_test_data_u16
,
299 read_test_data_u64
};
301 bool do_unsigned_reads(int start_off
)
306 for (i
= 0; i
< ARRAY_SIZE(read_ufns
) && ok
; i
++) {
309 for (off
= start_off
; off
< 8 && ok
; off
++) {
310 ok
= read_ufns
[i
](off
);
313 ok
= read_ufns
[i
](start_off
);
320 static bool do_unsigned_test(init_ufn fn
)
325 for (i
= 0; i
< 8 && ok
; i
++) {
327 ok
= do_unsigned_reads(i
);
331 return do_unsigned_reads(0);
336 * We need to ensure signed data is read into a larger data type to
337 * ensure that sign extension is working properly.
340 static bool read_test_data_s8(int offset
, bool neg_first
)
342 int8_t *ptr
= (int8_t *)&test_data
[offset
];
344 const int max
= (TEST_SIZE
- offset
) / 2;
346 ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr
, offset
);
348 for (i
= 0; i
< max
; i
++) {
349 int16_t first
, second
;
354 if (neg_first
&& first
< 0 && second
> 0) {
356 } else if (!neg_first
&& first
> 0 && second
< 0) {
359 ml_printf("Error %d %c %d\n", first
, neg_first
? '<' : '>', second
);
363 ml_printf("done @ %p\n", ptr
);
367 static bool read_test_data_s16(int offset
, bool neg_first
)
369 int16_t *ptr
= (int16_t *)&test_data
[offset
];
371 const int max
= (TEST_SIZE
- offset
) / (sizeof(*ptr
));
373 ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr
,
374 offset
, neg_first
? "neg" : "pos");
376 for (i
= 0; i
< max
; i
++) {
377 int32_t data
= *ptr
++;
379 if (neg_first
&& data
< 0) {
381 } else if (data
> 0) {
384 ml_printf("Error %d %c 0\n", data
, neg_first
? '<' : '>');
388 ml_printf("done @ %p\n", ptr
);
392 static bool read_test_data_s32(int offset
, bool neg_first
)
394 int32_t *ptr
= (int32_t *)&test_data
[offset
];
396 const int max
= (TEST_SIZE
- offset
) / (sizeof(int32_t));
398 ml_printf("Reading s32 from %#lx (offset %d, %s):",
399 ptr
, offset
, neg_first
? "neg" : "pos");
401 for (i
= 0; i
< max
; i
++) {
402 int64_t data
= *ptr
++;
404 if (neg_first
&& data
< 0) {
406 } else if (data
> 0) {
409 ml_printf("Error %d %c 0\n", data
, neg_first
? '<' : '>');
413 ml_printf("done @ %p\n", ptr
);
418 * Read the test data and verify at various offsets
420 * For everything except bytes all our reads should be either positive
421 * or negative depending on what offset we are reading from. Currently
422 * we only handle LE systems.
424 read_sfn read_sfns
[] = { read_test_data_s8
,
426 read_test_data_s32
};
428 bool do_signed_reads(bool neg_first
)
433 for (i
= 0; i
< ARRAY_SIZE(read_sfns
) && ok
; i
++) {
436 for (off
= 0; off
< 8 && ok
; off
++) {
437 bool nf
= i
== 0 ? neg_first
^ (off
& 1) : !(neg_first
^ (off
& 1));
438 ok
= read_sfns
[i
](off
, nf
);
441 ok
= read_sfns
[i
](0, i
== 0 ? neg_first
: !neg_first
);
448 init_ufn init_ufns
[] = { init_test_data_u8
,
451 init_test_data_u64
};
458 /* Run through the unsigned tests first */
459 for (i
= 0; i
< ARRAY_SIZE(init_ufns
) && ok
; i
++) {
460 ok
= do_unsigned_test(init_ufns
[i
]);
464 init_test_data_s8(false);
465 ok
= do_signed_reads(false);
469 init_test_data_s8(true);
470 ok
= do_signed_reads(true);
473 ml_printf("Test complete: %s\n", ok
? "PASSED" : "FAILED");