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