Skip to contentSkip to conversation

commands: import memtester 4.3.0 from Debian GNU/Linux

PATCH Superseded Peter Mamonov 2 participants 4 messages Oct 23, 2020 – Oct 30, 2020

v2 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

PATCH v2 1/1 commands: import memtester 4.3.0 from Debian GNU/Linux

Memtester is an utility for testing the memory subsystem for faults. For hardware developers, memtester can be told to test memory starting at a particular physical address.

This port is based on the sources from Debian GNU/Linux. Debian package meta data is as follows:

	Package: memtester
	Version: 4.3.0-5
	Homepage: http://pyropus.ca/software/memtester/
	APT-Sources: http://ftp.ru.debian.org/debian testing/main amd64 Packages

Dissected version of this patch can be found at
https://github.com/pmamonov/barebox/commits/memtester

Changes since v1:

1acbafe7a2 init global vars on start 7664692fd4 use proper return value a10eba5b49 use strtoull_suffix() to parse memory size 001b623c16 add option to set TESTMASK 3acfe07d56 make tests[] static
528360ebd7 fix license

---
 commands/Kconfig               |   8 +
 commands/Makefile              |   1 +
 commands/memtester/Makefile    |   1 +
 commands/memtester/memtester.c | 295 ++++++++++++++++++
 commands/memtester/memtester.h |  21 ++
 commands/memtester/sizes.h     |  37 +++
 commands/memtester/tests.c     | 537 +++++++++++++++++++++++++++++++++
 commands/memtester/tests.h     |  36 +++
 commands/memtester/types.h     |  35 +++
 9 files changed, 971 insertions(+)
 create mode 100644 commands/memtester/Makefile
 create mode 100644 commands/memtester/memtester.c
 create mode 100644 commands/memtester/memtester.h
 create mode 100644 commands/memtester/sizes.h
 create mode 100644 commands/memtester/tests.c
 create mode 100644 commands/memtester/tests.h
 create mode 100644 commands/memtester/types.h
commands/Kconfig +8 -0
index df18715f20..960d3608c7 100644
@@ -1611,6 +1611,14 @@ config CMD_MEMTEST
 		  -i ITERATIONS	perform number of iterations (default 1, 0 is endless)
 		  -b	perform only a test on bus lines
 
+config CMD_MEMTESTER
+	tristate
+	prompt "memtester"
+	help
+	  Utility for testing the memory subsystem.
+
+	  Homepage: http://pyropus.ca/software/memtester/
+
 config CMD_MM
 	tristate
 	select DEV_MEM
commands/Makefile +1 -0
index 6cc4997cc5..dc285cd00e 100644
@@ -49,6 +49,7 @@ obj-$(CONFIG_CMD_LOADENV)	+= loadenv.o
 obj-$(CONFIG_CMD_NAND)		+= nand.o
 obj-$(CONFIG_CMD_NANDTEST)	+= nandtest.o
 obj-$(CONFIG_CMD_MEMTEST)	+= memtest.o
+obj-$(CONFIG_CMD_MEMTESTER)	+= memtester/
 obj-$(CONFIG_CMD_TRUE)		+= true.o
 obj-$(CONFIG_CMD_FALSE)		+= false.o
 obj-$(CONFIG_CMD_VERSION)	+= version.o
commands/memtester/Makefile new file +1 -0
new file mode 100644
index 0000000000..17a2429276
@@ -0,0 +1 @@
+obj-y += tests.o memtester.o
commands/memtester/memtester.c new file +295 -0

295 lines not on this page · raw message

commands/memtester/memtester.h new file +21 -0
new file mode 100644
index 0000000000..008af0351a
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple (yet, for some reason, very effective) memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ * This file contains the declarations for external variables from the main file.
+ * See other comments in that file.
+ *
+ */
+
+#include <types.h>
+
+/* extern declarations. */
+
+extern int use_phys;
+extern off_t physaddrbase;
+
commands/memtester/sizes.h new file +37 -0
new file mode 100644
index 0000000000..d57f74f8ba
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ * This file contains some macro definitions for handling 32/64 bit platforms.
+ *
+ */
+
+#include <linux/limits.h>
+
+#define rand32() ((unsigned int) rand() | ( (unsigned int) rand() << 16))
+
+#if defined(CONFIG_32BIT)
+    #define rand_ul() rand32()
+    #define UL_ONEBITS 0xffffffff
+    #define UL_LEN 32
+    #define CHECKERBOARD1 0x55555555
+    #define CHECKERBOARD2 0xaaaaaaaa
+    #define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24))
+#elif defined(CONFIG_64BIT)
+    #define rand64() (((ul) rand32()) << 32 | ((ul) rand32()))
+    #define rand_ul() rand64()
+    #define UL_ONEBITS 0xffffffffffffffffUL
+    #define UL_LEN 64
+    #define CHECKERBOARD1 0x5555555555555555
+    #define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa
+    #define UL_BYTE(x) (((ul)x | (ul)x<<8 | (ul)x<<16 | (ul)x<<24 | (ul)x<<32 | (ul)x<<40 | (ul)x<<48 | (ul)x<<56))
+#else
+    #error long on this platform is not 32 or 64 bits
+#endif
+
+
commands/memtester/tests.c new file +537 -0

537 lines not on this page · raw message

commands/memtester/tests.h new file +36 -0
new file mode 100644
index 0000000000..86ef72509c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple yet very effective memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ * This file contains the declarations for the functions for the actual tests,
+ * called from the main routine in memtester.c.  See other comments in that 
+ * file.
+ *
+ */
+
+/* Function declaration. */
+
+int test_stuck_address(unsigned long volatile *bufa, size_t count);
+int test_random_value(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_xor_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_sub_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_mul_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_div_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_or_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_and_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_seqinc_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_solidbits_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_checkerboard_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_blockseq_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_walkbits0_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_walkbits1_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_bitspread_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_bitflip_comparison(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_8bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+int test_16bit_wide_random(unsigned long volatile *bufa, unsigned long volatile *bufb, size_t count);
+
commands/memtester/types.h new file +35 -0
new file mode 100644
index 0000000000..0291610d2c
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2010 Charles Cazabon <[email protected]>
+ *
+ * This file contains typedefs, structure, and union definitions.
+ *
+ */
+
+#include "sizes.h"
+
+typedef unsigned long ul;
+typedef unsigned long long ull;
+typedef unsigned long volatile ulv;
+typedef unsigned char volatile u8v;
+typedef unsigned short volatile u16v;
+
+struct test {
+    char *name;
+    int (*fp)(ulv *, ulv *, size_t);
+};
+
+typedef union {
+    unsigned char bytes[UL_LEN/8];
+    ul val;
+} mword8_t;
+
+typedef union {
+    unsigned short u16s[UL_LEN/16];
+    ul val;
+} mword16_t;
Signature · 7 lines
2.20.1


_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox
#1 lore raw

Hi Peter,

There are a few more things to fix. I just saw I never answered to your last mail.

Quoted 1 line

Do you prefer this two step version to be submitted?

No, it's ok as a singe patch.

Quoted 141 lines · Peter Mamonov

Memtester is an utility for testing the memory subsystem for faults. For hardware developers, memtester can be told to test memory starting at a particular physical address.

This port is based on the sources from Debian GNU/Linux. Debian package meta data is as follows:

	Package: memtester
	Version: 4.3.0-5
	Homepage: http://pyropus.ca/software/memtester/
	APT-Sources: http://ftp.ru.debian.org/debian testing/main amd64 Packages

Dissected version of this patch can be found at
https://github.com/pmamonov/barebox/commits/memtester

Changes since v1:

1acbafe7a2 init global vars on start 7664692fd4 use proper return value a10eba5b49 use strtoull_suffix() to parse memory size 001b623c16 add option to set TESTMASK 3acfe07d56 make tests[] static
528360ebd7 fix license

---
 commands/Kconfig               |   8 +
 commands/Makefile              |   1 +
 commands/memtester/Makefile    |   1 +
 commands/memtester/memtester.c | 295 ++++++++++++++++++
 commands/memtester/memtester.h |  21 ++
 commands/memtester/sizes.h     |  37 +++
 commands/memtester/tests.c     | 537 +++++++++++++++++++++++++++++++++
 commands/memtester/tests.h     |  36 +++
 commands/memtester/types.h     |  35 +++
 9 files changed, 971 insertions(+)
 create mode 100644 commands/memtester/Makefile
 create mode 100644 commands/memtester/memtester.c
 create mode 100644 commands/memtester/memtester.h
 create mode 100644 commands/memtester/sizes.h
 create mode 100644 commands/memtester/tests.c
 create mode 100644 commands/memtester/tests.h
 create mode 100644 commands/memtester/types.h
commands/Kconfig +8 -0
index df18715f20..960d3608c7 100644
@@ -1611,6 +1611,14 @@ config CMD_MEMTEST
 		  -i ITERATIONS	perform number of iterations (default 1, 0 is endless)
 		  -b	perform only a test on bus lines
 
+config CMD_MEMTESTER
+	tristate
+	prompt "memtester"
+	help
+	  Utility for testing the memory subsystem.
+
+	  Homepage: http://pyropus.ca/software/memtester/
+
 config CMD_MM
 	tristate
 	select DEV_MEM
commands/Makefile +1 -0
index 6cc4997cc5..dc285cd00e 100644
@@ -49,6 +49,7 @@ obj-$(CONFIG_CMD_LOADENV)	+= loadenv.o
 obj-$(CONFIG_CMD_NAND)		+= nand.o
 obj-$(CONFIG_CMD_NANDTEST)	+= nandtest.o
 obj-$(CONFIG_CMD_MEMTEST)	+= memtest.o
+obj-$(CONFIG_CMD_MEMTESTER)	+= memtester/
 obj-$(CONFIG_CMD_TRUE)		+= true.o
 obj-$(CONFIG_CMD_FALSE)		+= false.o
 obj-$(CONFIG_CMD_VERSION)	+= version.o
commands/memtester/Makefile new file +1 -0
new file mode 100644
index 0000000000..17a2429276
@@ -0,0 +1 @@
+obj-y += tests.o memtester.o
commands/memtester/memtester.c new file +53 -0
new file mode 100644
index 0000000000..8342eabfb1
@@ -0,0 +1,295 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * memtester version 4
+ *
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ */
+
+#define __version__ "4.3.0"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <errno.h>
+#include <getopt.h>
+#include <common.h>
+#include <command.h>
+#include <environment.h>
+#include <fs.h>
+
+#include "types.h"
+#include "sizes.h"
+#include "tests.h"
+
+#define EXIT_FAIL_NONSTARTER    COMMAND_ERROR
+#define EXIT_FAIL_ADDRESSLINES  0x02
+#define EXIT_FAIL_OTHERTEST     0x04
+
+static struct test tests[] = {
+    { "Random Value", test_random_value },
+    { "Compare XOR", test_xor_comparison },
+    { "Compare SUB", test_sub_comparison },
+    { "Compare MUL", test_mul_comparison },
+    { "Compare DIV",test_div_comparison },
+    { "Compare OR", test_or_comparison },
+    { "Compare AND", test_and_comparison },
+    { "Sequential Increment", test_seqinc_comparison },
+    { "Solid Bits", test_solidbits_comparison },
+    { "Block Sequential", test_blockseq_comparison },
+    { "Checkerboard", test_checkerboard_comparison },
+    { "Bit Spread", test_bitspread_comparison },
+    { "Bit Flip", test_bitflip_comparison },
+    { "Walking Ones", test_walkbits1_comparison },
+    { "Walking Zeroes", test_walkbits0_comparison },

commands/memtester/memtester.c line 63

Quoted 10 lines
commands/memtester/memtester.c new file +10 -0
+    { "8-bit Writes", test_8bit_wide_random },
+    { "16-bit Writes", test_16bit_wide_random },
+    { NULL, NULL }
+};
+
+/* Function declarations */
+
+/* Global vars - so tests have access to this information */
+int use_phys;
+off_t physaddrbase;

These names are too generic for global variables. Please add a memtester_ prefix.

commands/memtester/memtester.c line 70

Quoted 7 lines
commands/memtester/memtester.c new file +7 -0
+
+static int do_memtester(int argc, char **argv) {
+    ul loops, loop, i;
+    size_t wantmb, wantbytes, bufsize,
+         halflen, count;
+    char *addrsuffix, *loopsuffix;
+    void volatile *buf, *aligned;

You can drop this 'volatile' here - it's the functions you call with this buf that need it. Also you can drop the casts when using this buf.

Quoted 74 lines
commands/memtester/memtester.c new file +74 -0
+    ulv *bufa, *bufb;
+    int exit_code = 0, ret;
+    int memfd = 0, opt;
+    size_t maxbytes = -1; /* addressable memory, in bytes */
+    size_t maxmb = (maxbytes >> 20) + 1; /* addressable memory, in MB */
+    /* Device to mmap memory from with -p, default is normal core */
+    char *device_name = "/dev/mem";
+    struct stat statbuf;
+    int device_specified = 0;
+    ul testmask = 0;
+
+    use_phys = 0;
+    physaddrbase = 0;
+
+    printf("memtester version " __version__ " (%d-bit)\n", UL_LEN);
+    printf("Copyright (C) 2001-2012 Charles Cazabon.\n");
+    printf("Licensed under the GNU General Public License version 2 (only).\n");
+    printf("\n");
+
+    while ((opt = getopt(argc, argv, "p:d:m:")) != -1) {
+        switch (opt) {
+            case 'm':
+                errno = 0;
+                testmask = simple_strtoul(optarg, 0, 0);
+                if (errno) {
+                    printf("error parsing MEMTESTER_TEST_MASK %s: %s\n",
+                            optarg, strerror(errno));
+                    return COMMAND_ERROR_USAGE;
+                }
+                printf("using testmask 0x%lx\n", testmask);
+                break;
+            case 'p':
+                errno = 0;
+                physaddrbase = (off_t) simple_strtoull(optarg, &addrsuffix, 16);
+                if (errno != 0) {
+                    printf("failed to parse physaddrbase arg; should be hex "
+                           "address (0x123...)\n");
+                    return COMMAND_ERROR_USAGE;
+                }
+                if (*addrsuffix != '\0') {
+                    /* got an invalid character in the address */
+                    printf("failed to parse physaddrbase arg; should be hex "
+                           "address (0x123...)\n");
+                    return COMMAND_ERROR_USAGE;
+                }
+                /* okay, got address */
+                use_phys = 1;
+                break;
+            case 'd':
+                if (stat(optarg,&statbuf)) {
+                    printf("can not use %s as device: %s\n", optarg,
+                            strerror(errno));
+                    return COMMAND_ERROR_USAGE;
+                } else {
+                    if (!S_ISCHR(statbuf.st_mode)) {
+                        printf("can not mmap non-char device %s\n",
+                                optarg);
+                        return COMMAND_ERROR_USAGE;
+                    } else {
+                        device_name = optarg;
+                        device_specified = 1;
+                    }
+                }
+                break;
+            default: /* '?' */
+                return COMMAND_ERROR_USAGE;
+        }
+    }
+    if (device_specified && !use_phys) {
+        printf("for mem device, physaddrbase (-p) must be specified\n");
+        return COMMAND_ERROR_USAGE;
+    }
+
+    if (optind >= argc) {

commands/memtester/memtester.c line 154

Quoted 10 lines
commands/memtester/memtester.c new file +10 -0
+        printf("need memory argument, in MB\n");
+        return COMMAND_ERROR_USAGE;
+    }
+
+    errno = 0;
+    wantbytes = (size_t) strtoull_suffix(argv[optind], 0, 0);
+    if (errno != 0) {
+        printf("failed to parse memory argument");
+        return COMMAND_ERROR_USAGE;
+    }

strtoull_suffix() doesn't set errno. There is currently no way to detect an error from strtoull_suffix().

Quoted 6 lines
commands/memtester/memtester.c new file +6 -0
+    wantmb = (wantbytes >> 20);
+    optind++;
+    if (wantmb > maxmb) {
+        printf("This system can only address %llu MB.\n", (ull) maxmb);
+        return EXIT_FAIL_NONSTARTER;
+    }

commands/memtester/memtester.c line 170

Quoted 10 lines
commands/memtester/memtester.c new file +10 -0
+
+    if (optind >= argc) {
+        loops = 0;
+    } else {
+        errno = 0;
+        loops = simple_strtoul(argv[optind], &loopsuffix, 0);
+        if (errno != 0) {
+            printf("failed to parse number of loops");
+            return COMMAND_ERROR_USAGE;
+        }

same here. You can use kstrtoul instead which allows checking for errors. Another option would be to change simple_strtoul() to set errno.

Quoted 13 lines
commands/memtester/memtester.c new file +13 -0
+        if (*loopsuffix != '\0') {
+            printf("loop suffix %c\n", *loopsuffix);
+            return COMMAND_ERROR_USAGE;
+        }
+    }
+
+    printf("want %lluMB (%llu bytes)\n", (ull) wantmb, (ull) wantbytes);
+    buf = NULL;
+
+    if (use_phys) {
+        memfd = open(device_name, O_RDWR);
+        if (memfd == -1) {
+            printf("failed to open %s for physical memory: %s\n",

commands/memtester/memtester.c line 193

Quoted 10 lines
commands/memtester/memtester.c new file +10 -0
+                    device_name, strerror(errno));
+            return EXIT_FAIL_NONSTARTER;
+        }
+        buf = (void volatile *) memmap(memfd, PROT_READ | PROT_WRITE) +
+                                       physaddrbase;
+        if (buf == MAP_FAILED) {
+            printf("failed to mmap %s for physical memory: %s\n",
+                    device_name, strerror(errno));
+            return EXIT_FAIL_NONSTARTER;
+        }

memfd is not closed in this error path.

Quoted 19 lines
commands/memtester/memtester.c new file +19 -0
+
+        bufsize = wantbytes; /* accept no less */
+    } else {
+        buf = (void volatile *) malloc(wantbytes);
+        if (!buf) {
+            printf("malloc failed\n");
+            return ENOMEM;
+        }
+        printf("got  %lluMB (%llu bytes)\n", (ull) wantbytes >> 20,
+               (ull) wantbytes);
+    }
+    bufsize = wantbytes;
+    aligned = buf;
+
+    printf("buffer @ 0x%p\n", buf);
+
+    halflen = bufsize / 2;
+    count = halflen / sizeof(ul);
+    bufa = (ulv *) aligned;

commands/memtester/memtester.c line 222

Quoted 10 lines
commands/memtester/memtester.c new file +10 -0
+    bufb = (ulv *) ((size_t) aligned + halflen);
+
+    for(loop=1; ((!loops) || loop <= loops); loop++) {
+        printf("Loop %lu", loop);
+        if (loops) {
+            printf("/%lu", loops);
+        }
+        printf(":\n");
+        printf("  %-20s: ", "Stuck Address");
+        console_flush();

Why did you add all these console_flush() throughout the code?

Quoted 112 lines
commands/memtester/memtester.c new file +73 -0
+        ret = test_stuck_address(aligned, bufsize / sizeof(ul));
+        if (!ret) {
+             printf("ok\n");
+        } else if (ret == -EINTR) {
+            goto out;
+        } else {
+            exit_code |= EXIT_FAIL_ADDRESSLINES;
+        }
+        for (i=0;;i++) {
+            if (!tests[i].name) break;
+            /* If using a custom testmask, only run this test if the
+               bit corresponding to this test was set by the user.
+             */
+            if (testmask && (!((1 << i) & testmask))) {
+                continue;
+            }
+            printf("  %-20s: ", tests[i].name);
+            ret = tests[i].fp(bufa, bufb, count);
+            if (!ret) {
+                printf("ok\n");
+            } else if (ret == -EINTR) {
+                goto out;
+            } else {
+                exit_code |= EXIT_FAIL_OTHERTEST;
+            }
+            console_flush();
+        }
+        printf("\n");
+        console_flush();
+    }
+out:
+    if (use_phys)
+        close(memfd);
+    else
+        free((void *)buf);
+    printf("Done.\n");
+    console_flush();
+    if (!exit_code)
+        return 0;
+    printf("%s FAILED: 0x%x\n", argv[0], exit_code);
+    return COMMAND_ERROR;
+}
+
+BAREBOX_CMD_HELP_START(memtester)
+BAREBOX_CMD_HELP_TEXT("Options:")
+BAREBOX_CMD_HELP_TEXT("-p PHYSADDR")
+BAREBOX_CMD_HELP_TEXT("        tells memtester to test a specific region of memory starting at physical")
+BAREBOX_CMD_HELP_TEXT("        address PHYSADDR (given in hex), by mmaping a device specified by the -d")
+BAREBOX_CMD_HELP_TEXT("        option (below, or  /dev/mem  by  default).")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("-d DEVICE")
+BAREBOX_CMD_HELP_TEXT("        a device to mmap")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("-m TESTMASK")
+BAREBOX_CMD_HELP_TEXT("        bitmask to select desired tests")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("MEMORY ")
+BAREBOX_CMD_HELP_TEXT("        the amount of memory to allocate and test in bytes. You")
+BAREBOX_CMD_HELP_TEXT("        can include a suffix of K, M, or G to indicate kilobytes, ")
+BAREBOX_CMD_HELP_TEXT("        megabytes, or gigabytes respectively.")
+BAREBOX_CMD_HELP_TEXT("")
+BAREBOX_CMD_HELP_TEXT("ITERATIONS")
+BAREBOX_CMD_HELP_TEXT("        (optional) number of loops to iterate through.  Default is infinite.")
+BAREBOX_CMD_HELP_END
+
+BAREBOX_CMD_START(memtester)
+	.cmd		= do_memtester,
+	BAREBOX_CMD_DESC("memory stress-testing")
+	BAREBOX_CMD_OPTS("[-p PHYSADDR [-d DEVICE]] [-m TESTMASK] <MEMORY>[k|M|G] [ITERATIONS]")
+	BAREBOX_CMD_GROUP(CMD_GRP_MEM)
+	BAREBOX_CMD_HELP(cmd_memtester_help)
+BAREBOX_CMD_END
commands/memtester/memtester.h new file +21 -0
new file mode 100644
index 0000000000..008af0351a
@@ -0,0 +1,21 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple (yet, for some reason, very effective) memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ * This file contains the declarations for external variables from the main file.
+ * See other comments in that file.
+ *
+ */
+
+#include <types.h>
+
+/* extern declarations. */
+
+extern int use_phys;
+extern off_t physaddrbase;
+
commands/memtester/sizes.h new file +6 -0
new file mode 100644
index 0000000000..d57f74f8ba
@@ -0,0 +1,37 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.

commands/memtester/sizes.h line 16

Quoted 10 lines
commands/memtester/sizes.h new file +10 -0
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ * This file contains some macro definitions for handling 32/64 bit platforms.
+ *
+ */
+
+#include <linux/limits.h>
+
+#define rand32() ((unsigned int) rand() | ( (unsigned int) rand() << 16))

For some historic reason RAND_MAX in barebox is defined as 32768, so rand() returns only 15bit. While I am sure that this can and should be changed we also have random32() which does what you want here.

Quoted 49 lines
commands/memtester/sizes.h new file +21 -0
+
+#if defined(CONFIG_32BIT)
+    #define rand_ul() rand32()
+    #define UL_ONEBITS 0xffffffff
+    #define UL_LEN 32
+    #define CHECKERBOARD1 0x55555555
+    #define CHECKERBOARD2 0xaaaaaaaa
+    #define UL_BYTE(x) ((x | x << 8 | x << 16 | x << 24))
+#elif defined(CONFIG_64BIT)
+    #define rand64() (((ul) rand32()) << 32 | ((ul) rand32()))
+    #define rand_ul() rand64()
+    #define UL_ONEBITS 0xffffffffffffffffUL
+    #define UL_LEN 64
+    #define CHECKERBOARD1 0x5555555555555555
+    #define CHECKERBOARD2 0xaaaaaaaaaaaaaaaa
+    #define UL_BYTE(x) (((ul)x | (ul)x<<8 | (ul)x<<16 | (ul)x<<24 | (ul)x<<32 | (ul)x<<40 | (ul)x<<48 | (ul)x<<56))
+#else
+    #error long on this platform is not 32 or 64 bits
+#endif
+
+
commands/memtester/tests.c new file +22 -0
new file mode 100644
index 0000000000..4411573ba4
@@ -0,0 +1,537 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Very simple but very effective user-space memory tester.
+ * Originally by Simon Kirby <[email protected]> <[email protected]>
+ * Version 2 by Charles Cazabon <[email protected]>
+ * Version 3 not publicly released.
+ * Version 4 rewrite:
+ * Copyright (C) 2004-2012 Charles Cazabon <[email protected]>
+ *
+ * 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"

commands/memtester/tests.c line 32

Quoted 10 lines
commands/memtester/tests.c new file +10 -0
+#include "memtester.h"
+#include "tests.h"
+
+char progress[] = "-\\|/";
+#define PROGRESSLEN 4
+#define PROGRESSOFTEN 2500
+#define ONE 0x00000001L
+
+mword8_t  mword8;
+mword16_t mword16;

These should be static.

Sascha

Signature · 9 lines
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox
#2 lore raw

Hi, Sascha,

Quoted 14 lines · Sascha Hauer

Hi Peter,

There are a few more things to fix. I just saw I never answered to your last mail.

[...]

commands/memtester/memtester.c line 154

Quoted 6 lines
commands/memtester/memtester.c new file +6 -0
+    errno = 0;
+    wantbytes = (size_t) strtoull_suffix(argv[optind], 0, 0);
+    if (errno != 0) {
+        printf("failed to parse memory argument");
+        return COMMAND_ERROR_USAGE;
+    }
Quoted 2 lines

strtoull_suffix() doesn't set errno. There is currently no way to detect an error from strtoull_suffix().

errno is checked throughout the original code, including this slightly modified piece. Should I remove those checks or keep them for the sake of future errno support?

Quoted 6 lines

[...]

Review

Quoted 2 lines
(quoted diff) +2 -0
+        printf("  %-20s: ", "Stuck Address");
+        console_flush();

Why did you add all these console_flush() throughout the code?

I've merely replaced fflush(stdout) with console_flush() (see the original:
https://github.com/pmamonov/barebox/blob/31fd9d18f37ed58e5e559fe2ad6686066966f86e/commands/memtester/memtester.c#L374).
I choosed to keep all those (excessive) flushes as is, since most of the output is a progress indicator which should be displayed immediately and I wasn't sure that some type of barebox console won't cache the output.

PS Will address other comments in the next patch.

Peter

_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox

#3 lore raw
Quoted 17 lines · Peter Mamonov

Hi, Sascha,

Quoted 14 lines · Sascha Hauer

Hi Peter,

There are a few more things to fix. I just saw I never answered to your last mail.

[...]

Quoted 6 lines
commands/memtester/memtester.c new file +6 -0
+    errno = 0;
+    wantbytes = (size_t) strtoull_suffix(argv[optind], 0, 0);
+    if (errno != 0) {
+        printf("failed to parse memory argument");
+        return COMMAND_ERROR_USAGE;
+    }
Quoted 6 lines
Quoted 2 lines

strtoull_suffix() doesn't set errno. There is currently no way to detect an error from strtoull_suffix().

errno is checked throughout the original code, including this slightly modified piece. Should I remove those checks or keep them for the sake of future errno support?

I'd say it's not worth it to keep compatibility to the original code in this file. There are many small things that could/should be done differently, so just drop errno from the code, use kstrtoul where appropriate (unlike simple_strtoul kstrto* return an error).

Quoted 6 lines
Quoted 6 lines

[...]

Quoted 2 lines
(quoted diff) +2 -0
+        printf("  %-20s: ", "Stuck Address");
+        console_flush();
Quoted 8 lines
Quoted 1 line

Why did you add all these console_flush() throughout the code?

I've merely replaced fflush(stdout) with console_flush() (see the original:
https://github.com/pmamonov/barebox/blob/31fd9d18f37ed58e5e559fe2ad6686066966f86e/commands/memtester/memtester.c#L374).
I choosed to keep all those (excessive) flushes as is, since most of the output is a progress indicator which should be displayed immediately and I wasn't sure that some type of barebox console won't cache the output.

barebox doesn't cache anything in the console layer. Only the UART drivers do in their FIFOs, so console_flush() merely waits until the hardware FIFOs are drained. Normally there is no reason to use console_flush(), it's mainly useful to call it right before resetting the board, before booting Linux, or before switching the baudrate.

Sascha

Signature · 9 lines
Pengutronix e.K.                           |                             |
Steuerwalder Str. 21                       | http://www.pengutronix.de/  |
31137 Hildesheim, Germany                  | Phone: +49-5121-206917-0    |
Amtsgericht Hildesheim, HRA 2686           | Fax:   +49-5121-206917-5555 |

_______________________________________________
barebox mailing list
[email protected]
http://lists.infradead.org/mailman/listinfo/barebox