xref: /openbmc/qemu/tests/tcg/multiarch/system/memory.c (revision 67f3da9d)
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:
9 
10  *
11  */
12 
13 #include <inttypes.h>
14 #include <minilib.h>
15 
16 #define TEST_SIZE (4096 * 4)  /* 4 pages */
17 
18 static uint8_t test_data[TEST_SIZE];
19 
20 static void pdot(int count)
21 {
22     if (count % 128 == 0) {
23         ml_printf(".");
24     }
25 }
26 
27 
28 /*
29  * Fill the data with ascending value bytes. As x86 is a LE machine we
30  * write in ascending order and then read and high byte should either
31  * be zero or higher than the lower bytes.
32  */
33 
34 static void init_test_data_u8(void)
35 {
36     uint8_t count = 0, *ptr = &test_data[0];
37     int i;
38 
39     ml_printf("Filling test area with u8:");
40     for (i = 0; i < TEST_SIZE; i++) {
41         *ptr++ = count++;
42         pdot(i);
43     }
44     ml_printf("done\n");
45 }
46 
47 static void init_test_data_u16(int offset)
48 {
49     uint8_t count = 0;
50     uint16_t word, *ptr = (uint16_t *) &test_data[0];
51     const int max = (TEST_SIZE - offset) / sizeof(word);
52     int i;
53 
54     ml_printf("Filling test area with u16 (offset %d):", offset);
55 
56     /* Leading zeros */
57     for (i = 0; i < offset; i++) {
58         *ptr = 0;
59     }
60 
61     ptr = (uint16_t *) &test_data[offset];
62     for (i = 0; i < max; i++) {
63         uint8_t high, low;
64         low = count++;
65         high = count++;
66         word = (high << 8) | low;
67         *ptr++ = word;
68         pdot(i);
69     }
70     ml_printf("done\n");
71 }
72 
73 static void init_test_data_u32(int offset)
74 {
75     uint8_t count = 0;
76     uint32_t word, *ptr = (uint32_t *) &test_data[0];
77     const int max = (TEST_SIZE - offset) / sizeof(word);
78     int i;
79 
80     ml_printf("Filling test area with u32 (offset %d):", offset);
81 
82     /* Leading zeros */
83     for (i = 0; i < offset; i++) {
84         *ptr = 0;
85     }
86 
87     ptr = (uint32_t *) &test_data[offset];
88     for (i = 0; i < max; i++) {
89         uint8_t b1, b2, b3, b4;
90         b4 = count++;
91         b3 = count++;
92         b2 = count++;
93         b1 = count++;
94         word = (b1 << 24) | (b2 << 16) | (b3 << 8) | b4;
95         *ptr++ = word;
96         pdot(i);
97     }
98     ml_printf("done\n");
99 }
100 
101 
102 static int read_test_data_u16(int offset)
103 {
104     uint16_t word, *ptr = (uint16_t *)&test_data[offset];
105     int i;
106     const int max = (TEST_SIZE - offset) / sizeof(word);
107 
108     ml_printf("Reading u16 from %#lx (offset %d):", ptr, offset);
109 
110     for (i = 0; i < max; i++) {
111         uint8_t high, low;
112         word = *ptr++;
113         high = (word >> 8) & 0xff;
114         low = word & 0xff;
115         if (high < low && high != 0) {
116             ml_printf("Error %d < %d\n", high, low);
117             return 1;
118         } else {
119             pdot(i);
120         }
121 
122     }
123     ml_printf("done\n");
124     return 0;
125 }
126 
127 static int read_test_data_u32(int offset)
128 {
129     uint32_t word, *ptr = (uint32_t *)&test_data[offset];
130     int i;
131     const int max = (TEST_SIZE - offset) / sizeof(word);
132 
133     ml_printf("Reading u32 from %#lx (offset %d):", ptr, offset);
134 
135     for (i = 0; i < max; i++) {
136         uint8_t b1, b2, b3, b4;
137         word = *ptr++;
138 
139         b1 = word >> 24 & 0xff;
140         b2 = word >> 16 & 0xff;
141         b3 = word >> 8 & 0xff;
142         b4 = word & 0xff;
143 
144         if ((b1 < b2 && b1 != 0) ||
145             (b2 < b3 && b2 != 0) ||
146             (b3 < b4 && b3 != 0)) {
147             ml_printf("Error %d, %d, %d, %d", b1, b2, b3, b4);
148             return 2;
149         } else {
150             pdot(i);
151         }
152     }
153     ml_printf("done\n");
154     return 0;
155 }
156 
157 static int read_test_data_u64(int offset)
158 {
159     uint64_t word, *ptr = (uint64_t *)&test_data[offset];
160     int i;
161     const int max = (TEST_SIZE - offset) / sizeof(word);
162 
163     ml_printf("Reading u64 from %#lx (offset %d):", ptr, offset);
164 
165     for (i = 0; i < max; i++) {
166         uint8_t b1, b2, b3, b4, b5, b6, b7, b8;
167         word = *ptr++;
168 
169         b1 = ((uint64_t) (word >> 56)) & 0xff;
170         b2 = ((uint64_t) (word >> 48)) & 0xff;
171         b3 = ((uint64_t) (word >> 40)) & 0xff;
172         b4 = (word >> 32) & 0xff;
173         b5 = (word >> 24) & 0xff;
174         b6 = (word >> 16) & 0xff;
175         b7 = (word >> 8)  & 0xff;
176         b8 = (word >> 0)  & 0xff;
177 
178         if ((b1 < b2 && b1 != 0) ||
179             (b2 < b3 && b2 != 0) ||
180             (b3 < b4 && b3 != 0) ||
181             (b4 < b5 && b4 != 0) ||
182             (b5 < b6 && b5 != 0) ||
183             (b6 < b7 && b6 != 0) ||
184             (b7 < b8 && b7 != 0)) {
185             ml_printf("Error %d, %d, %d, %d, %d, %d, %d, %d",
186                       b1, b2, b3, b4, b5, b6, b7, b8);
187             return 2;
188         } else {
189             pdot(i);
190         }
191     }
192     ml_printf("done\n");
193     return 0;
194 }
195 
196 /* Read the test data and verify at various offsets */
197 int do_reads(void)
198 {
199     int r = 0;
200     int off = 0;
201 
202     while (r == 0 && off < 8) {
203         r = read_test_data_u16(off);
204         r |= read_test_data_u32(off);
205         r |= read_test_data_u64(off);
206         off++;
207     }
208 
209     return r;
210 }
211 
212 int main(void)
213 {
214     int i, r = 0;
215 
216 
217     init_test_data_u8();
218     r = do_reads();
219     if (r) {
220         return r;
221     }
222 
223     for (i = 0; i < 8; i++) {
224         init_test_data_u16(i);
225 
226         r = do_reads();
227         if (r) {
228             return r;
229         }
230     }
231 
232     for (i = 0; i < 8; i++) {
233         init_test_data_u32(i);
234 
235         r = do_reads();
236         if (r) {
237             return r;
238         }
239     }
240 
241     ml_printf("Test complete: %s\n", r == 0 ? "PASSED" : "FAILED");
242     return r;
243 }
244