]>
git.proxmox.com Git - mirror_qemu.git/blob - tests/tcg/multiarch/system/memory.c
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 endian handling.
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))
52 #error Unsupported __BYTE_ORDER__
56 * Fill the data with ascending (for little-endian) or descending (for
57 * big-endian) value bytes.
60 static void init_test_data_u8(int unused_offset
)
62 uint8_t count
= 0, *ptr
= &test_data
[0];
64 (void)(unused_offset
);
66 ml_printf("Filling test area with u8:");
67 for (i
= 0; i
< TEST_SIZE
; i
++) {
68 *ptr
++ = BYTE_NEXT(count
);
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.
80 static inline uint8_t get_byte(int index
, bool neg
)
82 return neg
? (0xff << (index
% 7)) : (0xff >> ((index
% 6) + 1));
85 static void init_test_data_s8(bool neg_first
)
87 uint8_t top
, bottom
, *ptr
= &test_data
[0];
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
);
101 * Zero the first few bytes of the test data in preparation for
104 static void reset_start_data(int offset
)
106 uint32_t *ptr
= (uint32_t *) &test_data
[0];
108 for (i
= 0; i
< offset
; i
++) {
113 static void init_test_data_u16(int offset
)
116 uint16_t word
, *ptr
= (uint16_t *) &test_data
[offset
];
117 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
120 ml_printf("Filling test area with u16 (offset %d, %p):", offset
, ptr
);
122 reset_start_data(offset
);
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);
130 ml_printf("done @ %p\n", ptr
);
133 static void init_test_data_u32(int offset
)
136 uint32_t word
, *ptr
= (uint32_t *) &test_data
[offset
];
137 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
140 ml_printf("Filling test area with u32 (offset %d, %p):", offset
, ptr
);
142 reset_start_data(offset
);
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) |
152 ml_printf("done @ %p\n", ptr
);
155 static void init_test_data_u64(int offset
)
158 uint64_t word
, *ptr
= (uint64_t *) &test_data
[offset
];
159 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
162 ml_printf("Filling test area with u64 (offset %d, %p):", offset
, ptr
);
164 reset_start_data(offset
);
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);
177 ml_printf("done @ %p\n", ptr
);
180 static bool read_test_data_u16(int offset
)
182 uint16_t word
, *ptr
= (uint16_t *)&test_data
[offset
];
184 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
186 ml_printf("Reading u16 from %#lx (offset %d):", ptr
, offset
);
188 for (i
= 0; i
< max
; i
++) {
191 high
= (word
>> 8) & 0xff;
193 if (high
< low
&& high
!= 0) {
194 ml_printf("Error %d < %d\n", high
, low
);
201 ml_printf("done @ %p\n", ptr
);
205 static bool read_test_data_u32(int offset
)
207 uint32_t word
, *ptr
= (uint32_t *)&test_data
[offset
];
209 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
211 ml_printf("Reading u32 from %#lx (offset %d):", ptr
, offset
);
213 for (i
= 0; i
< max
; i
++) {
214 uint8_t b1
, b2
, b3
, b4
;
218 b1
= word
>> 24 & 0xff;
219 b2
= word
>> 16 & 0xff;
220 b3
= word
>> 8 & 0xff;
223 zeros
+= (b1
== 0 ? 1 : 0);
224 zeros
+= (b2
== 0 ? 1 : 0);
225 zeros
+= (b3
== 0 ? 1 : 0);
226 zeros
+= (b4
== 0 ? 1 : 0);
228 ml_printf("Error @ %p, more zeros than expected: %d, %d, %d, %d",
229 ptr
- 1, b1
, b2
, b3
, b4
);
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
);
242 ml_printf("done @ %p\n", ptr
);
246 static bool read_test_data_u64(int offset
)
248 uint64_t word
, *ptr
= (uint64_t *)&test_data
[offset
];
250 const int max
= (TEST_SIZE
- offset
) / sizeof(word
);
252 ml_printf("Reading u64 from %#lx (offset %d):", ptr
, offset
);
254 for (i
= 0; i
< max
; i
++) {
255 uint8_t b1
, b2
, b3
, b4
, b5
, b6
, b7
, b8
;
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;
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);
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
);
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
);
296 ml_printf("done @ %p\n", ptr
);
300 /* Read the test data and verify at various offsets */
301 read_ufn read_ufns
[] = { read_test_data_u16
,
303 read_test_data_u64
};
305 bool do_unsigned_reads(int start_off
)
310 for (i
= 0; i
< ARRAY_SIZE(read_ufns
) && ok
; i
++) {
313 for (off
= start_off
; off
< 8 && ok
; off
++) {
314 ok
= read_ufns
[i
](off
);
317 ok
= read_ufns
[i
](start_off
);
324 static bool do_unsigned_test(init_ufn fn
)
329 for (i
= 0; i
< 8 && ok
; i
++) {
331 ok
= do_unsigned_reads(i
);
336 return do_unsigned_reads(0);
341 * We need to ensure signed data is read into a larger data type to
342 * ensure that sign extension is working properly.
345 static bool read_test_data_s8(int offset
, bool neg_first
)
347 int8_t *ptr
= (int8_t *)&test_data
[offset
];
349 const int max
= (TEST_SIZE
- offset
) / 2;
351 ml_printf("Reading s8 pairs from %#lx (offset %d):", ptr
, offset
);
353 for (i
= 0; i
< max
; i
++) {
354 int16_t first
, second
;
359 if (neg_first
&& first
< 0 && second
> 0) {
361 } else if (!neg_first
&& first
> 0 && second
< 0) {
364 ml_printf("Error %d %c %d\n", first
, neg_first
? '<' : '>', second
);
368 ml_printf("done @ %p\n", ptr
);
372 static bool read_test_data_s16(int offset
, bool neg_first
)
374 int16_t *ptr
= (int16_t *)&test_data
[offset
];
376 const int max
= (TEST_SIZE
- offset
) / (sizeof(*ptr
));
378 ml_printf("Reading s16 from %#lx (offset %d, %s):", ptr
,
379 offset
, neg_first
? "neg" : "pos");
382 * If the first byte is negative, then the last byte is positive.
383 * Therefore the logic below must be flipped for big-endian.
385 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
386 neg_first
= !neg_first
;
389 for (i
= 0; i
< max
; i
++) {
390 int32_t data
= *ptr
++;
392 if (neg_first
&& data
< 0) {
394 } else if (!neg_first
&& data
> 0) {
397 ml_printf("Error %d %c 0\n", data
, neg_first
? '<' : '>');
401 ml_printf("done @ %p\n", ptr
);
405 static bool read_test_data_s32(int offset
, bool neg_first
)
407 int32_t *ptr
= (int32_t *)&test_data
[offset
];
409 const int max
= (TEST_SIZE
- offset
) / (sizeof(int32_t));
411 ml_printf("Reading s32 from %#lx (offset %d, %s):",
412 ptr
, offset
, neg_first
? "neg" : "pos");
415 * If the first byte is negative, then the last byte is positive.
416 * Therefore the logic below must be flipped for big-endian.
418 #if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
419 neg_first
= !neg_first
;
422 for (i
= 0; i
< max
; i
++) {
423 int64_t data
= *ptr
++;
425 if (neg_first
&& data
< 0) {
427 } else if (!neg_first
&& data
> 0) {
430 ml_printf("Error %d %c 0\n", data
, neg_first
? '<' : '>');
434 ml_printf("done @ %p\n", ptr
);
439 * Read the test data and verify at various offsets
441 * For everything except bytes all our reads should be either positive
442 * or negative depending on what offset we are reading from.
444 read_sfn read_sfns
[] = { read_test_data_s8
,
446 read_test_data_s32
};
448 bool do_signed_reads(bool neg_first
)
453 for (i
= 0; i
< ARRAY_SIZE(read_sfns
) && ok
; i
++) {
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
);
461 ok
= read_sfns
[i
](0, i
== 0 ? neg_first
: !neg_first
);
468 init_ufn init_ufns
[] = { init_test_data_u8
,
471 init_test_data_u64
};
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
]);
484 init_test_data_s8(false);
485 ok
= do_signed_reads(false);
489 init_test_data_s8(true);
490 ok
= do_signed_reads(true);
493 ml_printf("Test complete: %s\n", ok
? "PASSED" : "FAILED");