1 /* SPDX-License-Identifier: GPL-2.0 */ 2 /* 3 * Very simple but very effective user-space memory tester. 4 * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> 5 * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> 6 * Version 3 not publicly released. 7 * Version 4 rewrite: 8 * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca> 9 * Licensed under the terms of the GNU General Public License version 2 (only). 10 * See the file COPYING for details. 11 * 12 * This file contains the functions for the actual tests, called from the 13 * main routine in memtester.c. See other comments in that file. 14 * 15 */ 16 17 #include "memtester.h" 18 #include "sizes.h" 19 #include "types.h" 20 #include "../io_map.h" 21 22 union { 23 unsigned char bytes[UL_LEN / 8]; 24 u32 val; 25 } mword8; 26 27 union { 28 unsigned short u16s[UL_LEN / 16]; 29 u32 val; 30 } mword16; 31 32 char progress[] = "-\\|/"; 33 #define PROGRESSLEN 4 34 #define PROGRESSOFTEN 2500 35 #define ONE 0x00000001L 36 37 #define fflush(n) 38 39 /* Function definitions. */ 40 int compare_regions(u32v *bufa, u32v *bufb, size_t count) 41 { 42 int r = 0; 43 size_t i; 44 u32v *p1 = bufa; 45 u32v *p2 = bufb; 46 off_t physaddr; 47 48 for (i = 0; i < count; i++, p1++, p2++) { 49 if (*p1 != *p2) { 50 if (use_phys) { 51 physaddr = physaddrbase + (i * sizeof(u32v)); 52 fprintf(stderr, 53 "FAILURE: 0x%08lx != 0x%08lx at physical address " 54 "0x%08lx.\n", 55 (ul)*p1, (ul)*p2, physaddr); 56 } else { 57 fprintf(stderr, 58 "FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", 59 (ul)*p1, (ul)*p2, 60 (ul)(i * sizeof(u32v))); 61 } 62 /* printf("Skipping to next test..."); */ 63 r = -1; 64 } 65 } 66 return r; 67 } 68 69 int test_stuck_address(u32v *bufa, size_t count) 70 { 71 u32v *p1 = bufa; 72 unsigned int j; 73 size_t i; 74 off_t physaddr; 75 76 printf(" "); 77 fflush(stdout); 78 for (j = 0; j < 16; j++) { 79 printf("\b\b\b\b\b\b\b\b\b\b\b"); 80 p1 = (u32v *)bufa; 81 printf("setting %3u", j); 82 fflush(stdout); 83 for (i = 0; i < count; i++) { 84 *p1 = ((j + i) % 2) == 0 ? (u32)(ul)p1 : ~((u32)(ul)p1); 85 *p1++; 86 } 87 printf("\b\b\b\b\b\b\b\b\b\b\b"); 88 printf("testing %3u", j); 89 fflush(stdout); 90 p1 = (u32v *)bufa; 91 for (i = 0; i < count; i++, p1++) { 92 if (*p1 != (((j + i) % 2) == 0 ? 93 (u32)(ul)p1 : ~((u32)(ul)p1))) { 94 if (use_phys) { 95 physaddr = 96 physaddrbase + (i * sizeof(u32v)); 97 fprintf(stderr, 98 "FAILURE: possible bad address line at physical " 99 "address 0x%08lx.\n", physaddr); 100 } else { 101 fprintf(stderr, 102 "FAILURE: possible bad address line at offset " 103 "0x%08lx.\n", 104 (ul)(i * sizeof(u32v))); 105 } 106 printf("Skipping to next test...\n"); 107 fflush(stdout); 108 return -1; 109 } 110 } 111 } 112 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 113 fflush(stdout); 114 return 0; 115 } 116 117 int test_random_value(u32v *bufa, u32v *bufb, size_t count, 118 ul fix_bit, ul fix_level) 119 { 120 u32v *p1 = bufa; 121 u32v *p2 = bufb; 122 ul j = 0; 123 size_t i; 124 125 putc(' '); 126 fflush(stdout); 127 for (i = 0; i < count; i++) { 128 *p1++ = *p2++ = rand_ul(); 129 if (!(i % PROGRESSOFTEN)) { 130 putc('\b'); 131 putc(progress[++j % PROGRESSLEN]); 132 fflush(stdout); 133 } 134 } 135 printf("\b \b"); 136 fflush(stdout); 137 return compare_regions(bufa, bufb, count); 138 } 139 140 int test_xor_comparison(u32v *bufa, u32v *bufb, size_t count, 141 ul fix_bit, ul fix_level) 142 143 { 144 u32v *p1 = bufa; 145 u32v *p2 = bufb; 146 size_t i; 147 u32 q = rand_ul(); 148 149 for (i = 0; i < count; i++) { 150 *p1++ ^= q; 151 *p2++ ^= q; 152 } 153 return compare_regions(bufa, bufb, count); 154 } 155 156 int test_sub_comparison(u32v *bufa, u32v *bufb, size_t count, 157 ul fix_bit, ul fix_level) 158 { 159 u32v *p1 = bufa; 160 u32v *p2 = bufb; 161 size_t i; 162 u32 q = rand_ul(); 163 164 for (i = 0; i < count; i++) { 165 *p1++ -= q; 166 *p2++ -= q; 167 } 168 return compare_regions(bufa, bufb, count); 169 } 170 171 int test_mul_comparison(u32v *bufa, u32v *bufb, size_t count, 172 ul fix_bit, ul fix_level) 173 { 174 u32v *p1 = bufa; 175 u32v *p2 = bufb; 176 size_t i; 177 u32 q = rand_ul(); 178 179 for (i = 0; i < count; i++) { 180 *p1++ *= q; 181 *p2++ *= q; 182 } 183 return compare_regions(bufa, bufb, count); 184 } 185 186 int test_div_comparison(u32v *bufa, u32v *bufb, size_t count, 187 ul fix_bit, ul fix_level) 188 { 189 u32v *p1 = bufa; 190 u32v *p2 = bufb; 191 size_t i; 192 u32 q = rand_ul(); 193 194 for (i = 0; i < count; i++) { 195 if (!q) 196 q++; 197 *p1++ /= q; 198 *p2++ /= q; 199 } 200 return compare_regions(bufa, bufb, count); 201 } 202 203 int test_or_comparison(u32v *bufa, u32v *bufb, size_t count, 204 ul fix_bit, ul fix_level) 205 { 206 u32v *p1 = bufa; 207 u32v *p2 = bufb; 208 size_t i; 209 u32 q = rand_ul(); 210 211 for (i = 0; i < count; i++) { 212 *p1++ |= q; 213 *p2++ |= q; 214 } 215 return compare_regions(bufa, bufb, count); 216 } 217 218 int test_and_comparison(u32v *bufa, u32v *bufb, size_t count, 219 ul fix_bit, ul fix_level) 220 { 221 u32v *p1 = bufa; 222 u32v *p2 = bufb; 223 size_t i; 224 u32 q = rand_ul(); 225 226 for (i = 0; i < count; i++) { 227 *p1++ &= q; 228 *p2++ &= q; 229 } 230 return compare_regions(bufa, bufb, count); 231 } 232 233 int test_seqinc_comparison(u32v *bufa, u32v *bufb, size_t count, 234 ul fix_bit, ul fix_level) 235 { 236 u32v *p1 = bufa; 237 u32v *p2 = bufb; 238 size_t i; 239 u32 q = rand_ul(); 240 241 for (i = 0; i < count; i++) 242 *p1++ = *p2++ = (i + q); 243 return compare_regions(bufa, bufb, count); 244 } 245 246 int test_solidbits_comparison(u32v *bufa, u32v *bufb, size_t count, 247 ul fix_bit, ul fix_level) 248 { 249 u32v *p1 = bufa; 250 u32v *p2 = bufb; 251 unsigned int j; 252 u32 q; 253 u32 data[4]; 254 size_t i; 255 256 printf(" "); 257 fflush(stdout); 258 for (j = 0; j < 64; j++) { 259 printf("\b\b\b\b\b\b\b\b\b\b\b"); 260 q = (j % 2) == 0 ? UL_ONEBITS : 0; 261 if (fix_level) 262 q |= fix_bit; 263 else 264 q &= ~fix_bit; 265 data[0] = data[2] = q; 266 data[1] = data[3] = ~q; 267 data_cpu_2_io(data, sizeof(data)); 268 printf("setting %3u", j); 269 fflush(stdout); 270 p1 = (u32v *)bufa; 271 p2 = (u32v *)bufb; 272 for (i = 0; i < count; i++) 273 *p1++ = *p2++ = data[i & 3]; 274 printf("\b\b\b\b\b\b\b\b\b\b\b"); 275 printf("testing %3u", j); 276 fflush(stdout); 277 if (compare_regions(bufa, bufb, count)) 278 return -1; 279 } 280 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 281 fflush(stdout); 282 return 0; 283 } 284 285 int test_checkerboard_comparison(u32v *bufa, u32v *bufb, size_t count, 286 ul fix_bit, ul fix_level) 287 { 288 u32v *p1 = bufa; 289 u32v *p2 = bufb; 290 unsigned int j; 291 u32 q; 292 u32 data[4]; 293 size_t i; 294 295 printf(" "); 296 fflush(stdout); 297 for (j = 0; j < 64; j++) { 298 printf("\b\b\b\b\b\b\b\b\b\b\b"); 299 q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; 300 if (fix_level) 301 q |= fix_bit; 302 else 303 q &= ~fix_bit; 304 305 data[0] = data[2] = q; 306 data[1] = data[3] = ~q; 307 data_cpu_2_io(data, sizeof(data)); 308 printf("setting %3u", j); 309 fflush(stdout); 310 p1 = (u32v *)bufa; 311 p2 = (u32v *)bufb; 312 for (i = 0; i < count; i++) 313 *p1++ = *p2++ = data[i & 3]; 314 printf("\b\b\b\b\b\b\b\b\b\b\b"); 315 printf("testing %3u", j); 316 fflush(stdout); 317 if (compare_regions(bufa, bufb, count)) 318 return -1; 319 } 320 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 321 fflush(stdout); 322 return 0; 323 } 324 325 int test_blockseq_comparison(u32v *bufa, u32v *bufb, size_t count, 326 ul fix_bit, ul fix_level) 327 { 328 u32v *p1 = bufa; 329 u32v *p2 = bufb; 330 unsigned int j; 331 u32 data[4]; 332 u32 q; 333 size_t i; 334 335 printf(" "); 336 fflush(stdout); 337 for (j = 0; j < 256; j++) { 338 printf("\b\b\b\b\b\b\b\b\b\b\b"); 339 p1 = (u32v *)bufa; 340 p2 = (u32v *)bufb; 341 printf("setting %3u", j); 342 fflush(stdout); 343 q = (u32)UL_BYTE(j); 344 if (fix_level) 345 q |= fix_bit; 346 else 347 q &= ~fix_bit; 348 349 data[0] = q; 350 data[1] = q; 351 data[2] = q; 352 data[3] = q; 353 354 data_cpu_2_io(data, sizeof(data)); 355 356 for (i = 0; i < count; i++) 357 *p1++ = *p2++ = data[i & 3]; 358 printf("\b\b\b\b\b\b\b\b\b\b\b"); 359 printf("testing %3u", j); 360 fflush(stdout); 361 if (compare_regions(bufa, bufb, count)) 362 return -1; 363 } 364 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 365 fflush(stdout); 366 return 0; 367 } 368 369 int test_walkbits0_comparison(u32v *bufa, u32v *bufb, size_t count, 370 ul fix_bit, ul fix_level) 371 { 372 u32v *p1 = bufa; 373 u32v *p2 = bufb; 374 unsigned int j; 375 u32 data[4]; 376 u32 q; 377 size_t i; 378 379 printf(" "); 380 fflush(stdout); 381 for (j = 0; j < UL_LEN * 2; j++) { 382 printf("\b\b\b\b\b\b\b\b\b\b\b"); 383 p1 = (u32v *)bufa; 384 p2 = (u32v *)bufb; 385 printf("setting %3u", j); 386 fflush(stdout); 387 if (j < UL_LEN) 388 q = ONE << j; 389 else 390 q = ONE << (UL_LEN * 2 - j - 1); 391 392 if (fix_level) 393 q |= fix_bit; 394 else 395 q &= ~fix_bit; 396 397 data[0] = q; 398 data[1] = q; 399 data[2] = q; 400 data[3] = q; 401 data_cpu_2_io(data, sizeof(data)); 402 403 for (i = 0; i < count; i++) { 404 *p1++ = *p2++ = data[i & 3]; 405 } 406 printf("\b\b\b\b\b\b\b\b\b\b\b"); 407 printf("testing %3u", j); 408 fflush(stdout); 409 if (compare_regions(bufa, bufb, count)) 410 return -1; 411 } 412 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 413 fflush(stdout); 414 return 0; 415 } 416 417 int test_walkbits1_comparison(u32v *bufa, u32v *bufb, size_t count, 418 ul fix_bit, ul fix_level) 419 { 420 u32v *p1 = bufa; 421 u32v *p2 = bufb; 422 unsigned int j; 423 u32 data[4]; 424 u32 q; 425 size_t i; 426 427 printf(" "); 428 fflush(stdout); 429 for (j = 0; j < UL_LEN * 2; j++) { 430 printf("\b\b\b\b\b\b\b\b\b\b\b"); 431 p1 = (u32v *)bufa; 432 p2 = (u32v *)bufb; 433 printf("setting %3u", j); 434 fflush(stdout); 435 if (j < UL_LEN) 436 q = UL_ONEBITS ^ (ONE << j); 437 else 438 q = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1)); 439 if (fix_level) 440 q |= fix_bit; 441 else 442 q &= ~fix_bit; 443 444 data[0] = q; 445 data[1] = q; 446 data[2] = q; 447 data[3] = q; 448 data_cpu_2_io(data, sizeof(data)); 449 450 for (i = 0; i < count; i++) { 451 *p1++ = *p2++ = data[i & 3]; 452 } 453 printf("\b\b\b\b\b\b\b\b\b\b\b"); 454 printf("testing %3u", j); 455 fflush(stdout); 456 if (compare_regions(bufa, bufb, count)) 457 return -1; 458 } 459 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 460 fflush(stdout); 461 return 0; 462 } 463 464 int test_bitspread_comparison(u32v *bufa, u32v *bufb, size_t count, 465 ul fix_bit, ul fix_level) 466 { 467 u32v *p1 = bufa; 468 u32v *p2 = bufb; 469 unsigned int j; 470 u32 data[4]; 471 size_t i; 472 473 printf(" "); 474 fflush(stdout); 475 for (j = 0; j < UL_LEN * 2; j++) { 476 printf("\b\b\b\b\b\b\b\b\b\b\b"); 477 p1 = (u32v *)bufa; 478 p2 = (u32v *)bufb; 479 printf("setting %3u", j); 480 fflush(stdout); 481 if (j < UL_LEN) { 482 data[0] = (ONE << j) | (ONE << (j + 2)); 483 data[1] = UL_ONEBITS ^ ((ONE << j) | (ONE << (j + 2))); 484 } else { 485 data[0] = (ONE << (UL_LEN * 2 - 1 - j)) | 486 (ONE << (UL_LEN * 2 + 1 - j)); 487 data[1] = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j) 488 | (ONE << (UL_LEN * 2 + 1 - j))); 489 } 490 if (fix_level) { 491 data[0] |= fix_bit; 492 data[1] |= fix_bit; 493 } else { 494 data[0] &= ~fix_bit; 495 data[1] &= ~fix_bit; 496 } 497 data[2] = data[0]; 498 data[3] = data[1]; 499 data_cpu_2_io(data, sizeof(data)); 500 501 for (i = 0; i < count; i++) { 502 *p1++ = *p2++ = data[i & 3]; 503 } 504 printf("\b\b\b\b\b\b\b\b\b\b\b"); 505 printf("testing %3u", j); 506 fflush(stdout); 507 if (compare_regions(bufa, bufb, count)) 508 return -1; 509 } 510 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 511 fflush(stdout); 512 return 0; 513 } 514 515 int test_bitflip_comparison(u32v *bufa, u32v *bufb, size_t count, 516 ul fix_bit, ul fix_level) 517 { 518 u32v *p1 = bufa; 519 u32v *p2 = bufb; 520 unsigned int j, k; 521 u32 q; 522 u32 data[4]; 523 size_t i; 524 525 printf(" "); 526 fflush(stdout); 527 for (k = 0; k < UL_LEN; k++) { 528 q = ONE << k; 529 for (j = 0; j < 8; j++) { 530 printf("\b\b\b\b\b\b\b\b\b\b\b"); 531 q = ~q; 532 printf("setting %3u", k * 8 + j); 533 fflush(stdout); 534 if (fix_level) 535 q |= fix_bit; 536 else 537 q &= ~fix_bit; 538 539 data[0] = data[2] = q; 540 data[1] = data[3] = ~q; 541 data_cpu_2_io(data, sizeof(data)); 542 p1 = (u32v *)bufa; 543 p2 = (u32v *)bufb; 544 for (i = 0; i < count; i++) 545 *p1++ = *p2++ = data[i & 3]; 546 printf("\b\b\b\b\b\b\b\b\b\b\b"); 547 printf("testing %3u", k * 8 + j); 548 fflush(stdout); 549 if (compare_regions(bufa, bufb, count)) 550 return -1; 551 } 552 } 553 printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); 554 fflush(stdout); 555 return 0; 556 } 557 558 #ifdef TEST_NARROW_WRITES 559 int test_8bit_wide_random(u32v *bufa, u32v *bufb, size_t count, 560 ul fix_bit, ul fix_level) 561 { 562 u8v *p1, *t; 563 u32v *p2; 564 int attempt; 565 unsigned int b, j = 0; 566 size_t i; 567 568 putc(' '); 569 fflush(stdout); 570 for (attempt = 0; attempt < 2; attempt++) { 571 if (attempt & 1) { 572 p1 = (u8v *)bufa; 573 p2 = bufb; 574 } else { 575 p1 = (u8v *)bufb; 576 p2 = bufa; 577 } 578 for (i = 0; i < count; i++) { 579 t = mword8.bytes; 580 *p2++ = mword8.val = rand_ul(); 581 for (b = 0; b < UL_LEN / 8; b++) 582 *p1++ = *t++; 583 if (!(i % PROGRESSOFTEN)) { 584 putc('\b'); 585 putc(progress[++j % PROGRESSLEN]); 586 fflush(stdout); 587 } 588 } 589 if (compare_regions(bufa, bufb, count)) 590 return -1; 591 } 592 printf("\b \b"); 593 fflush(stdout); 594 return 0; 595 } 596 597 int test_16bit_wide_random(u32v *bufa, u32v *bufb, size_t count, 598 ul fix_bit, ul fix_level) 599 { 600 u16v *p1, *t; 601 u32v *p2; 602 int attempt; 603 unsigned int b, j = 0; 604 size_t i; 605 606 putc(' '); 607 fflush(stdout); 608 for (attempt = 0; attempt < 2; attempt++) { 609 if (attempt & 1) { 610 p1 = (u16v *)bufa; 611 p2 = bufb; 612 } else { 613 p1 = (u16v *)bufb; 614 p2 = bufa; 615 } 616 for (i = 0; i < count; i++) { 617 t = mword16.u16s; 618 *p2++ = mword16.val = rand_ul(); 619 for (b = 0; b < UL_LEN / 16; b++) 620 *p1++ = *t++; 621 if (!(i % PROGRESSOFTEN)) { 622 putc('\b'); 623 putc(progress[++j % PROGRESSLEN]); 624 fflush(stdout); 625 } 626 } 627 if (compare_regions(bufa, bufb, count)) 628 return -1; 629 } 630 printf("\b \b"); 631 fflush(stdout); 632 return 0; 633 } 634 #endif 635