diff options
Diffstat (limited to 'commands/memtester/tests.c')
-rw-r--r-- | commands/memtester/tests.c | 495 |
1 files changed, 495 insertions, 0 deletions
diff --git a/commands/memtester/tests.c b/commands/memtester/tests.c new file mode 100644 index 0000000000..ca83c4a764 --- /dev/null +++ b/commands/memtester/tests.c @@ -0,0 +1,495 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * Very simple but very effective user-space memory tester. + * Originally by Simon Kirby <sim@stormix.com> <sim@neato.org> + * Version 2 by Charles Cazabon <charlesc-memtester@pyropus.ca> + * Version 3 not publicly released. + * Version 4 rewrite: + * Copyright (C) 2004-2012 Charles Cazabon <charlesc-memtester@pyropus.ca> + * + * This file contains the functions for the actual tests, called from the + * main routine in memtester.c. See other comments in that file. + * + */ + +#include <common.h> +#include <types.h> +#include <stdio.h> +#include <stdlib.h> +#include <linux/limits.h> + +#include "types.h" +#include "sizes.h" +#include "memtester.h" +#include "tests.h" + +static char progress[] = "-\\|/"; +#define PROGRESSLEN 4 +#define PROGRESSOFTEN 2500 +#define ONE 0x00000001L + +static mword8_t mword8; +static mword16_t mword16; + +/* Function definitions. */ + +static int compare_regions(ulv *bufa, ulv *bufb, size_t count) { + int r = 0; + size_t i; + ulv *p1 = bufa; + ulv *p2 = bufb; + off_t physaddr; + + if (ctrlc()) + return -EINTR; + + for (i = 0; i < count; i++, p1++, p2++) { + if (*p1 != *p2) { + if (memtester_use_phys) { + physaddr = memtester_physaddrbase + (i * sizeof(ul)); + printf("FAILURE: 0x%08lx != 0x%08lx at physical address " + "0x%08lx.\n", + (ul) *p1, (ul) *p2, physaddr); + } else { + printf("FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", + (ul) *p1, (ul) *p2, (ul) (i * sizeof(ul))); + } + /* printf("Skipping to next test..."); */ + r = -1; + } + } + return r; +} + +int test_stuck_address(ulv *bufa, size_t count) { + ulv *p1 = bufa; + unsigned int j; + size_t i; + off_t physaddr; + + printf(" "); + for (j = 0; j < 16; j++) { + if (ctrlc()) + return -EINTR; + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + printf("setting %3u", j); + for (i = 0; i < count; i++) { + *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1); + *p1++; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + p1 = (ulv *) bufa; + for (i = 0; i < count; i++, p1++) { + if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) { + if (memtester_use_phys) { + physaddr = memtester_physaddrbase + (i * sizeof(ul)); + printf("FAILURE: possible bad address line at physical " + "address 0x%08lx.\n", + physaddr); + } else { + printf("FAILURE: possible bad address line at offset " + "0x%08lx.\n", + (ul) (i * sizeof(ul))); + } + printf("Skipping to next test...\n"); + return -1; + } + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_random_value(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + ul j = 0; + size_t i; + + putchar(' '); + for (i = 0; i < count; i++) { + *p1++ = *p2++ = rand_ul(); + if (!(i % PROGRESSOFTEN)) { + putchar('\b'); + putchar(progress[++j % PROGRESSLEN]); + } + } + printf("\b \b"); + return compare_regions(bufa, bufb, count); +} + +int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ ^= q; + *p2++ ^= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ -= q; + *p2++ -= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ *= q; + *p2++ *= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + if (!q) { + q++; + } + *p1++ /= q; + *p2++ /= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ |= q; + *p2++ |= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ &= q; + *p2++ &= q; + } + return compare_regions(bufa, bufb, count); +} + +int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + size_t i; + ul q = rand_ul(); + + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i + q); + } + return compare_regions(bufa, bufb, count); +} + +int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + ul q; + size_t i; + int ret; + + printf(" "); + for (j = 0; j < 64; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + q = (j % 2) == 0 ? UL_ONEBITS : 0; + printf("setting %3u", j); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + ul q; + size_t i; + int ret; + + printf(" "); + for (j = 0; j < 64; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; + printf("setting %3u", j); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + int ret; + + printf(" "); + for (j = 0; j < 256; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (ul) UL_BYTE(j); + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + int ret; + + printf(" "); + for (j = 0; j < UL_LEN * 2; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + *p1++ = *p2++ = ONE << j; + } else { /* Walk it back down. */ + *p1++ = *p2++ = ONE << (UL_LEN * 2 - j - 1); + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + int ret; + + printf(" "); + for (j = 0; j < UL_LEN * 2; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + *p1++ = *p2++ = UL_ONEBITS ^ (ONE << j); + } else { /* Walk it back down. */ + *p1++ = *p2++ = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1)); + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j; + size_t i; + int ret; + + printf(" "); + for (j = 0; j < UL_LEN * 2; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + printf("setting %3u", j); + for (i = 0; i < count; i++) { + if (j < UL_LEN) { /* Walk it up. */ + *p1++ = *p2++ = (i % 2 == 0) + ? (ONE << j) | (ONE << (j + 2)) + : UL_ONEBITS ^ ((ONE << j) + | (ONE << (j + 2))); + } else { /* Walk it back down. */ + *p1++ = *p2++ = (i % 2 == 0) + ? (ONE << (UL_LEN * 2 - 1 - j)) | (ONE << (UL_LEN * 2 + 1 - j)) + : UL_ONEBITS ^ (ONE << (UL_LEN * 2 - 1 - j) + | (ONE << (UL_LEN * 2 + 1 - j))); + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) { + ulv *p1 = bufa; + ulv *p2 = bufb; + unsigned int j, k; + ul q; + size_t i; + int ret; + + printf(" "); + for (k = 0; k < UL_LEN; k++) { + q = ONE << k; + for (j = 0; j < 8; j++) { + printf("\b\b\b\b\b\b\b\b\b\b\b"); + q = ~q; + printf("setting %3u", k * 8 + j); + p1 = (ulv *) bufa; + p2 = (ulv *) bufb; + for (i = 0; i < count; i++) { + *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + } + printf("\b\b\b\b\b\b\b\b\b\b\b"); + printf("testing %3u", k * 8 + j); + ret = compare_regions(bufa, bufb, count); + if (ret) + return -1; + } + } + printf("\b\b\b\b\b\b\b\b\b\b\b \b\b\b\b\b\b\b\b\b\b\b"); + return 0; +} + +int test_8bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { + u8v *p1, *t; + ulv *p2; + int attempt; + unsigned int b, j = 0; + size_t i; + int ret; + + putchar(' '); + for (attempt = 0; attempt < 2; attempt++) { + if (attempt & 1) { + p1 = (u8v *) bufa; + p2 = bufb; + } else { + p1 = (u8v *) bufb; + p2 = bufa; + } + for (i = 0; i < count; i++) { + t = mword8.bytes; + *p2++ = mword8.val = rand_ul(); + for (b=0; b < UL_LEN/8; b++) { + *p1++ = *t++; + } + if (!(i % PROGRESSOFTEN)) { + putchar('\b'); + putchar(progress[++j % PROGRESSLEN]); + } + } + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b \b"); + return 0; +} + +int test_16bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { + u16v *p1, *t; + ulv *p2; + int attempt; + unsigned int b, j = 0; + size_t i; + int ret; + + putchar( ' ' ); + for (attempt = 0; attempt < 2; attempt++) { + if (attempt & 1) { + p1 = (u16v *) bufa; + p2 = bufb; + } else { + p1 = (u16v *) bufb; + p2 = bufa; + } + for (i = 0; i < count; i++) { + t = mword16.u16s; + *p2++ = mword16.val = rand_ul(); + for (b = 0; b < UL_LEN/16; b++) { + *p1++ = *t++; + } + if (!(i % PROGRESSOFTEN)) { + putchar('\b'); + putchar(progress[++j % PROGRESSLEN]); + } + } + ret = compare_regions(bufa, bufb, count); + if (ret) + return ret; + } + printf("\b \b"); + return 0; +} |