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 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) {
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
);
332 return do_unsigned_reads(0);
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
];
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
;
355 if (neg_first
&& first
< 0 && second
> 0) {
357 } else if (!neg_first
&& first
> 0 && second
< 0) {
360 ml_printf("Error %d %c %d\n", first
, neg_first
? '<' : '>', second
);
364 ml_printf("done @ %p\n", ptr
);
368 static bool read_test_data_s16(int offset
, bool neg_first
)
370 int16_t *ptr
= (int16_t *)&test_data
[offset
];
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) {
382 } else if (data
> 0) {
385 ml_printf("Error %d %c 0\n", data
, neg_first
? '<' : '>');
389 ml_printf("done @ %p\n", ptr
);
393 static bool read_test_data_s32(int offset
, bool neg_first
)
395 int32_t *ptr
= (int32_t *)&test_data
[offset
];
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) {
407 } else if (data
> 0) {
410 ml_printf("Error %d %c 0\n", data
, neg_first
? '<' : '>');
414 ml_printf("done @ %p\n", ptr
);
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
,
427 read_test_data_s32
};
429 bool do_signed_reads(bool neg_first
)
434 for (i
= 0; i
< ARRAY_SIZE(read_sfns
) && ok
; i
++) {
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
);
442 ok
= read_sfns
[i
](0, i
== 0 ? neg_first
: !neg_first
);
449 init_ufn init_ufns
[] = { init_test_data_u8
,
452 init_test_data_u64
};
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
]);
465 init_test_data_s8(false);
466 ok
= do_signed_reads(false);
470 init_test_data_s8(true);
471 ok
= do_signed_reads(true);
474 ml_printf("Test complete: %s\n", ok
? "PASSED" : "FAILED");