From bb9b6dd4e04e671c065090a1ccaebe67f7950cda Mon Sep 17 00:00:00 2001 From: YouMin Chen Date: Sun, 22 Oct 2023 18:37:09 +0800 Subject: [PATCH] memtester: some changes for the Rockchip platform 20231020 base on: memtester-4.5.1 merge from rockchip develop branch: commit 2d622bb314fa2ed60a818c4bb6e920babe606d78 Signed-off-by: YouMin Chen --- Makefile | 17 +- cache.c | 28 +++ cache.h | 12 ++ io_map.c | 321 ++++++++++++++++++++++++++++++ io_map.h | 19 ++ memtester.c | 155 +++++++++++++-- sizes.h | 25 +-- tests.c | 548 +++++++++++++++++++++++++++++++++++++++------------- tests.h | 37 ++-- types.h | 6 +- va_2_pa.c | 76 ++++++++ va_2_pa.h | 15 ++ 12 files changed, 1069 insertions(+), 190 deletions(-) create mode 100644 cache.c create mode 100644 cache.h create mode 100644 io_map.c create mode 100644 io_map.h create mode 100644 va_2_pa.c create mode 100644 va_2_pa.h diff --git a/Makefile b/Makefile index 123f7bc..272fd35 100644 --- a/Makefile +++ b/Makefile @@ -13,7 +13,7 @@ CC = $(shell head -n 1 conf-cc) LD = $(shell head -n 1 conf-ld) -SOURCES = memtester.c tests.c +SOURCES = memtester.c tests.c io_map.c va_2_pa.c cache.c OBJECTS = $(SOURCES:.c=.o) HEADERS = memtester.h TARGETS = *.o compile load auto-ccld.sh find-systype make-compile make-load systype extra-libs @@ -75,11 +75,18 @@ clean: rm -f memtester $(TARGETS) $(OBJECTS) core memtester: \ -$(OBJECTS) memtester.c tests.h tests.c tests.h conf-cc Makefile load extra-libs - ./load memtester tests.o `cat extra-libs` +$(OBJECTS) memtester.c tests.h tests.c tests.h io_map.c io_map.h va_2_pa.c va_2_pa.h cache.c cache.h conf-cc Makefile load extra-libs + ./load memtester tests.o io_map.o va_2_pa.o cache.o `cat extra-libs` -memtester.o: memtester.c tests.h conf-cc Makefile compile +memtester.o: memtester.c tests.h io_map.h va_2_pa.h cache.h conf-cc Makefile compile ./compile memtester.c -tests.o: tests.c tests.h conf-cc Makefile compile +tests.o: tests.c tests.h io_map.h va_2_pa.h cache.h conf-cc Makefile compile ./compile tests.c +io_map.o: io_map.c io_map.h conf-cc Makefile compile + ./compile io_map.c +va_2_pa.o: va_2_pa.c va_2_pa.h conf-cc Makefile compile + ./compile va_2_pa.c + +cache.o: cache.c cache.h conf-cc Makefile compile + ./compile cache.c diff --git a/cache.c b/cache.c new file mode 100644 index 0000000..66230a3 --- /dev/null +++ b/cache.c @@ -0,0 +1,28 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd. + */ + +#include +#include "types.h" +#include "cache.h" +#include + +void dcacheflush(ul start, ul end) +{ +#if defined (__aarch64__) + ul cache_line; + + __asm("mrs %0, ctr_el0":"+r" (cache_line):); + cache_line = 4 << ((cache_line >> 16) & 0xf); + printf("cache line:%u\n", cache_line); + start &= ~(cache_line - 1); + + for (; start < end; start += cache_line) { + __asm("dc civac, %0":"+r" (start):); + } +#else + printf("flush cache\n"); + syscall(__ARM_NR_cacheflush, start, end, 0); +#endif +} diff --git a/cache.h b/cache.h new file mode 100644 index 0000000..5532bc0 --- /dev/null +++ b/cache.h @@ -0,0 +1,12 @@ +/* + * Copyright (C) 2019 Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CMD_MEMTESTER_CACHE_H +#define _CMD_MEMTESTER_CACHE_H + +void dcacheflush(ul start, ul end); + +#endif /* _CMD_MEMTESTER_CACHE_H */ diff --git a/io_map.c b/io_map.c new file mode 100644 index 0000000..836ea74 --- /dev/null +++ b/io_map.c @@ -0,0 +1,321 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "types.h" +#include "io_map.h" + +#define IO_TYPE_1_1_16 0 +#define IO_TYPE_1_1_32 1 +#define IO_TYPE_1_2 2 +#define IO_TYPE_2 3 + +#define SYS_REG_DEC_BW(n, ch) (2 >> (((n) >> (2 + 16 * (ch))) & 0x3)) + +static u32 io_type; + +u32 io_bw; + +struct chip_info { + char chip_name[10]; + uint32_t osreg_addr; +}; + +struct chip_info chip_info[] = { + { .chip_name = "rv1106", + .osreg_addr = 0xff020208 + }, + { .chip_name = "rv1108", + .osreg_addr = 0x10300588 + }, + { .chip_name = "rv1109", + .osreg_addr = 0xfe020208 + }, + { .chip_name = "rv1126", + .osreg_addr = 0xfe020208 + }, + { .chip_name = "rk1808", + .osreg_addr = 0xfe020208 + }, + { .chip_name = "rk3036", + .osreg_addr = 0x200081cc + }, + { .chip_name = "rk3126b", + .osreg_addr = 0x200081cc + }, + { .chip_name = "rk3126c", + .osreg_addr = 0x200081cc + }, + { .chip_name = "rk3126", + .osreg_addr = 0x200081cc + }, + { .chip_name = "rk3128", + .osreg_addr = 0x200081cc + }, + { .chip_name = "rk3188", + .osreg_addr = 0x20004048 + }, + { .chip_name = "rk3228h", + .osreg_addr = 0xff1005d0 + }, + { .chip_name = "rk3228", + .osreg_addr = 0x110005d0 + }, + { .chip_name = "rk3229", + .osreg_addr = 0x110005d0 + }, + { .chip_name = "rk3288", + .osreg_addr = 0xff73009c + }, + { .chip_name = "rk3308", + .osreg_addr = 0xff000208 + }, + { .chip_name = "rk3326", + .osreg_addr = 0xff010208 + }, + { .chip_name = "px30", + .osreg_addr = 0xff010208 + }, + { .chip_name = "rk3328", + .osreg_addr = 0xff1005d0 + }, + { .chip_name = "rk3368", + .osreg_addr = 0xff738208 + }, + { .chip_name = "rk3399", + .osreg_addr = 0xff320308 + }, + { .chip_name = "rk3528", + .osreg_addr = 0xff370248 + }, + { .chip_name = "rk3562", + .osreg_addr = 0xff010208 + }, + { .chip_name = "rk3566", + .osreg_addr = 0xfdc20208 + }, + { .chip_name = "rk3568", + .osreg_addr = 0xfdc20208 + }, + { .chip_name = "rk3588", + .osreg_addr = 0xfd58a208 + } +}; + +char* try_get_chip_name(void) +{ + FILE * file; + char *chip_name = NULL; + char buffer[100], buffer_new[100]; + int i, j, bytes; + + file = fopen("/proc/device-tree/compatible", "r"); + if (file == NULL) { + printf("Failed to open /proc/device-tree/compatible\n"); + goto out; + } + + bytes = fread(buffer, sizeof(char), sizeof(buffer), file); + if (ferror(file)) { + printf("Failed to read /proc/device-tree/compatible.\n"); + fclose(file); + goto out; + } + fclose(file); + + for (i = 0, j = 0; i < bytes; i++) { + if ((buffer[i] == '\0') && (i < (bytes - 1))) + continue; + else + buffer_new[j++] = buffer[i]; + } + + for (i = 0; i < (sizeof(chip_info) / sizeof(chip_info[0])); i++) { + if (strstr(buffer_new, chip_info[i].chip_name) != NULL) { + chip_name = chip_info[i].chip_name; + break; + } + } + +out: + printf("get chip name: %s\n", chip_name); + return chip_name; +} + +char* try_get_ddr_bw(char *chip_name) +{ + ull page_size; + char *ddr_bw = NULL; + int fd; + uint32_t reg_addr = 0, reg_val = 0; + uint32_t i, bw; + + if (chip_name == NULL) + goto out; + + for (i = 0; i < (sizeof(chip_info) / sizeof(chip_info[0])); i++) { + if (!strcasecmp(chip_name, chip_info[i].chip_name)) { + reg_addr = chip_info[i].osreg_addr; + break; + } + } + + if (reg_addr == 0) + goto out; + + page_size = getpagesize(); + + fd = open("/dev/mem", O_RDWR); + if (fd < 0) { + printf("Failed to open /dev/mem\n"); + goto out; + } + + void *map_base = mmap(NULL, page_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, + reg_addr & ~(page_size - 1)); + if (map_base == (void*)-1) { + printf("Failed to mmap /dev/mem\n"); + close(fd); + goto out; + } + + reg_val = (uint32_t)*(uint32_t *)(map_base + reg_addr % page_size); + if (munmap(map_base, page_size) == -1) { + printf("Failed to munmap /dev/mem"); + close(fd); + goto out; + } + close(fd); + + bw = 8 << SYS_REG_DEC_BW(reg_val, 0); + if (bw == 8) + ddr_bw = "bw_x8"; + else if (bw == 16) + ddr_bw = "bw_x16"; + else if (bw == 32) + ddr_bw = "bw_x32"; + +out: + printf("get ddr bw: %s\n", ddr_bw); + return ddr_bw; +} + +/* len should be 16byte align */ +int data_cpu_2_io(void *p, u32 len) +{ + uchar *val = p; + uchar buf[16]; + u32 i, j; + + if ((len % sizeof(buf)) || !len) + return -1; + + if (io_type == IO_TYPE_1_2) { + len /= sizeof(buf); + for (j = 0; j < len; j++) { + memset(buf, 0, sizeof(buf)); + for (i = 0; i < sizeof(buf); i++) + buf[i] = val[(i % 4) * 4 + i / 4 + j * sizeof(buf)]; + memcpy(&val[j * sizeof(buf)], buf, sizeof(buf)); + } + } else if (io_type == IO_TYPE_1_1_32) { + len /= 8; + for (j = 0; j < len; j++) { + memset(buf, 0, sizeof(buf)); + for (i = 0; i < 8; i++) + buf[i] = val[(i % 4) * 2 + i / 4 + j * 8]; + memcpy(&val[j * 8], buf, 8); + } + } + /* IO_TYPE_2 and IO_TYPE_1_1_16 do nothing*/ + return 0; +} + +void data_cpu_2_io_init(char *chip, char *ddr_bw) +{ + u32 osreg = 0; + u32 bw; + + io_bw = IO_BW_32; + io_type = IO_TYPE_2; + + if (chip == NULL) { + chip = try_get_chip_name(); + if (chip == NULL) + goto bw_type; + } + + if (!strcasecmp(chip, "rk3036") || + !strcasecmp(chip, "rk3126") || + !strcasecmp(chip, "rk3126b") || + !strcasecmp(chip, "rk3126c")) { + io_type = IO_TYPE_1_1_16; + } else if (!strcasecmp(chip, "rk3228") || + !strcasecmp(chip, "rk3229") || + !strcasecmp(chip, "rk3368")) { + io_type = IO_TYPE_1_2; + } else if (!strcasecmp(chip, "rv1108") || + !strcasecmp(chip, "rk3308")) { + io_type = IO_TYPE_1_2; + io_bw = IO_BW_16; + } else if (!strcasecmp(chip, "rk3128")) { + osreg = 0x200081cc; + } else if (!strcasecmp(chip, "rk3288")) { + osreg = 0xff73009c; + } else if (!strcasecmp(chip, "rk3188")) { + osreg = 0x20004048; + } else if (!strcasecmp(chip, "rk3328") || + !strcasecmp(chip, "rk3228h")|| + !strcasecmp(chip, "px30")|| + !strcasecmp(chip, "rk3326")|| + !strcasecmp(chip, "rk1808")|| + !strcasecmp(chip, "rv1126")|| + !strcasecmp(chip, "rv1109")) { + io_type = IO_TYPE_2; + } else { + /* default IO_TYPE_2 */ + printf("no available chip info, using default maping\n"); + io_type = IO_TYPE_2; + } + + if (osreg) { + bw = (2 >> ((osreg >> 2) & 0x3)); + if (bw == 2) + io_type = IO_TYPE_1_1_32; + else + io_type = IO_TYPE_1_1_16; + } + +bw_type: + if (ddr_bw == NULL) { + ddr_bw = try_get_ddr_bw(chip); + if (ddr_bw == NULL) + goto out; + } + + if (!strcasecmp(ddr_bw, "bw_x32")) { + io_bw = IO_BW_32; + } else if (!strcasecmp(ddr_bw, "bw_x16")) { + io_bw = IO_BW_16; + } else if (!strcasecmp(ddr_bw, "bw_x8")) { + io_bw = IO_BW_8; + } + +out: + if (io_bw == IO_BW_32) + printf("io bw x32\n"); + else if (io_bw == IO_BW_16) + printf("io bw x16\n"); + else if (io_bw == IO_BW_8) + printf("io bw x8\n"); +} + diff --git a/io_map.h b/io_map.h new file mode 100644 index 0000000..317b5bd --- /dev/null +++ b/io_map.h @@ -0,0 +1,19 @@ +/* + * Copyright (C) 2019 Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _CMD_MEMTESTER_IO_MAP_H +#define _CMD_MEMTESTER_IO_MAP_H + +#define IO_BW_32 0 +#define IO_BW_16 1 +#define IO_BW_8 2 + +extern u32 io_bw; + +int data_cpu_2_io(void *p, u32 len); +void data_cpu_2_io_init(char *chip, char *ddr_bw); + +#endif /* _CMD_MEMTESTER_IO_MAP_H */ diff --git a/memtester.c b/memtester.c index 44d331e..a867443 100644 --- a/memtester.c +++ b/memtester.c @@ -12,7 +12,7 @@ * */ -#define __version__ "4.5.1" +#define __version__ "4.5.1_20231020" #include #include @@ -24,15 +24,22 @@ #include #include #include +#include #include "types.h" #include "sizes.h" #include "tests.h" +#include "io_map.h" +#include "va_2_pa.h" +#include "cache.h" #define EXIT_FAIL_NONSTARTER 0x01 #define EXIT_FAIL_ADDRESSLINES 0x02 #define EXIT_FAIL_OTHERTEST 0x04 +void sighandler(int); +int exit_code = 0; + struct test tests[] = { { "Random Value", test_random_value }, { "Compare XOR", test_xor_comparison }, @@ -102,7 +109,41 @@ off_t physaddrbase = 0; /* Function definitions */ void usage(char *me) { fprintf(stderr, "\n" - "Usage: %s [-p physaddrbase [-d device]] [B|K|M|G] [loops]\n", + "Usage: %s [-p physaddrbase [-d device]] [-e exit_when_error]" + "[-t test_pattern] [-c chip name][B|K|M|G] [loops]\n" + "-p testing phys address\n" + "-e if not 0, exit immediately when test fail\n" + "-f fixed bit to a exact level, 1: high, 0: low, which bits are depend on level(-l) bits\n" + "-b fix bits, 1: fix bit level, 0: do not fix level\n" + " example: -f 0x1 -b 0x1000: fix cpu bit 12 to high\n" + " -f 0x0 -b 0x1000: fix cpu bit 12 to low\n" + " when doing bitflip, bitspread, walkbits1,\n" + " walkbits0, blockseq, checkerboard and solidbits tests.\n" + "-t testing pattern mask, if null or 0 enable all test pattern\n" + " bit0: Random Value\n" + " bit1: Compare XOR\n" + " bit2: Compare SUB\n" + " bit3: Compare MUL\n" + " bit4: Compare DIV\n" + " bit5: Compare OR\n" + " bit6: Compare AND\n" + " bit7: Sequential Increment\n" + " bit8: Solid Bits\n" + " bit9: Block Sequential\n" + " bit10: Checkerboard\n" + " bit11: Bit Spread\n" + " bit12: Bit Flip\n" + " bit13: Walking Ones\n" + " bit14: Walking Zeroes\n" + " bit15: 8-bit Writes\n" + " bit16: 16-bit Writes\n" + " example: -t 0x1000,enable Bit Flip only\n" + "-c chip name include:\n" + " rk3036, rk3126, rk3228, rk3229, rv1108, rk3368, rk3128," + " rk3188, rk3288, rk3228h, rk3328, rk3326, px30, rk1808, rv1109," + " rv1126, rk3308\n" + "-w ddr bus width, include:\n" + " bw_x8, bw_x16, bw_x32\n", me); exit(EXIT_FAIL_NONSTARTER); } @@ -112,11 +153,15 @@ int main(int argc, char **argv) { size_t pagesize, wantraw, wantmb, wantbytes, wantbytes_orig, bufsize, halflen, count; char *memsuffix, *addrsuffix, *loopsuffix; + char *chip_name = NULL; + char *ddr_bw = NULL; ptrdiff_t pagesizemask; void volatile *buf, *aligned; - ulv *bufa, *bufb; + u32v *bufa, *bufb; int do_mlock = 1, done_mem = 0; - int exit_code = 0; + ul error_exit = 0; + ul test_pattern = 0; + ul stuck_addr = 1; int memfd, opt, memshift; size_t maxbytes = -1; /* addressable memory, in bytes */ size_t maxmb = (maxbytes >> 20) + 1; /* addressable memory, in MB */ @@ -126,6 +171,7 @@ int main(int argc, char **argv) { int device_specified = 0; char *env_testmask = 0; ul testmask = 0; + u32 fix_level = 0, fix_bit = 0; printf("memtester version " __version__ " (%d-bit)\n", UL_LEN); printf("Copyright (C) 2001-2020 Charles Cazabon.\n"); @@ -150,7 +196,7 @@ int main(int argc, char **argv) { printf("using testmask 0x%lx\n", testmask); } - while ((opt = getopt(argc, argv, "p:d:")) != -1) { + while ((opt = getopt(argc, argv, "p:d:e:f:b:t:c:w:")) != -1) { switch (opt) { case 'p': errno = 0; @@ -192,7 +238,54 @@ int main(int argc, char **argv) { device_specified = 1; } } - break; + break; + case 'e': + errno = 0; + error_exit = strtoull(optarg, NULL, 0); + if (errno != 0) { + fprintf(stderr, + "failed to parse exit_when_error arg;\n"); + usage(argv[0]); /* doesn't return */ + } + break; + case 'f': + errno = 0; + fix_level = strtoull(optarg, NULL, 0); + if (errno != 0) { + fprintf(stderr, + "failed to parse test_pattern arg;\n"); + usage(argv[0]); /* doesn't return */ + } + break; + case 'b': + errno = 0; + fix_bit = strtoull(optarg, NULL, 0); + if (errno != 0) { + fprintf(stderr, + "failed to parse test_pattern arg;\n"); + usage(argv[0]); /* doesn't return */ + } + break; + case 't': + errno = 0; + test_pattern = strtoull(optarg, NULL, 0); + if (errno != 0) { + fprintf(stderr, + "failed to parse test_pattern arg;\n"); + usage(argv[0]); /* doesn't return */ + } + /* must add random value first */ + if (test_pattern & 0x7e) + test_pattern |= 0x1; + if (test_pattern) + stuck_addr = 0; + break; + case 'c': + chip_name = optarg; + break; + case 'w': + ddr_bw = optarg; + break; default: /* '?' */ usage(argv[0]); /* doesn't return */ } @@ -372,10 +465,16 @@ int main(int argc, char **argv) { aligned = buf; } + if (!use_phys) + printf("testing from phyaddress:0x%lx\n", read_pagemap((ul)aligned)); + + data_cpu_2_io_init(chip_name, ddr_bw); halflen = bufsize / 2; - count = halflen / sizeof(ul); - bufa = (ulv *) aligned; - bufb = (ulv *) ((size_t) aligned + halflen); + count = halflen / sizeof(u32); + bufa = (u32v *) aligned; + bufb = (u32v *) ((size_t) aligned + halflen); + + signal(SIGINT, sighandler); for(loop=1; ((!loops) || loop <= loops); loop++) { printf("Loop %lu", loop); @@ -383,12 +482,19 @@ int main(int argc, char **argv) { printf("/%lu", loops); } printf(":\n"); - printf(" %-20s: ", "Stuck Address"); - fflush(stdout); - if (!test_stuck_address(aligned, bufsize / sizeof(ul))) { - printf("ok\n"); - } else { - exit_code |= EXIT_FAIL_ADDRESSLINES; + if (stuck_addr != 0) { + printf(" %-20s: ", "Stuck Address"); + fflush(stdout); + if (!test_stuck_address(aligned, bufsize / sizeof(u32))) { + printf("ok\n"); + } else { + exit_code |= EXIT_FAIL_ADDRESSLINES; + if (error_exit) { + printf("EXIT_FAIL_ADDRESSLINES\n"); + fflush(stdout); + exit(exit_code); + } + } } for (i=0;;i++) { if (!tests[i].name) break; @@ -398,11 +504,17 @@ int main(int argc, char **argv) { if (testmask && (!((1 << i) & testmask))) { continue; } + if (test_pattern && (!((1 << i) & test_pattern))) + continue; printf(" %-20s: ", tests[i].name); - if (!tests[i].fp(bufa, bufb, count)) { + if (!tests[i].fp(bufa, bufb, count, fix_bit, fix_level)) { printf("ok\n"); } else { exit_code |= EXIT_FAIL_OTHERTEST; + if (error_exit) { + printf("EXIT_FAIL_OTHERTEST\n"); + goto out; + } } fflush(stdout); /* clear buffer */ @@ -412,7 +524,14 @@ int main(int argc, char **argv) { fflush(stdout); } if (do_mlock) munlock((void *) aligned, bufsize); - printf("Done.\n"); +out: fflush(stdout); - exit(exit_code); + exit_result(exit_code); } + +void sighandler(int signum) +{ + fflush(stdout); + exit_result(exit_code); +} + diff --git a/sizes.h b/sizes.h index cd1c3ad..5a4a994 100644 --- a/sizes.h +++ b/sizes.h @@ -16,23 +16,10 @@ #define rand32() ((unsigned int) rand() | ( (unsigned int) rand() << 16)) -#if (ULONG_MAX == 4294967295UL) - #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 (ULONG_MAX == 18446744073709551615ULL) - #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 - +#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)) diff --git a/tests.c b/tests.c index 4970350..8cbcaaf 100644 --- a/tests.c +++ b/tests.c @@ -21,6 +21,9 @@ #include "types.h" #include "sizes.h" #include "memtester.h" +#include "io_map.h" +#include "va_2_pa.h" +#include "cache.h" char progress[] = "-\\|/"; #define PROGRESSLEN 4 @@ -29,45 +32,67 @@ char progress[] = "-\\|/"; union { unsigned char bytes[UL_LEN/8]; - ul val; + u32 val; } mword8; union { unsigned short u16s[UL_LEN/16]; - ul val; + u32 val; } mword16; +u32 fault_cnt = 0; /* Function definitions. */ -int compare_regions(ulv *bufa, ulv *bufb, size_t count) { +__attribute__((weak)) void dcacheflush(ul start, ul end) +{ + return; +} + +int compare_regions(u32v *bufa, u32v *bufb, size_t count) { int r = 0; size_t i; - ulv *p1 = bufa; - ulv *p2 = bufb; + u32v *p1 = bufa; + u32v *p2 = bufb; + u32 read[2]; + u32 reread[2]; off_t physaddr; for (i = 0; i < count; i++, p1++, p2++) { - if (*p1 != *p2) { + read[0] = *p1; + read[1] = *p2; + if (read[0] != read[1]) { + dcacheflush((ul)p1, (ul)p1 + 4); + dcacheflush((ul)p2, (ul)p2 + 4); + reread[0] = *p1; + reread[1] = *p2; if (use_phys) { - physaddr = physaddrbase + (i * sizeof(ul)); - fprintf(stderr, - "FAILURE: 0x%08lx != 0x%08lx at physical address " - "0x%08lx.\n", - (ul) *p1, (ul) *p2, physaddr); + physaddr = physaddrbase + (i * sizeof(u32v)); + fprintf(stdout, + "FAILURE: 0x%08x != 0x%08x (readA^readB:0x%08x) at physical address " + "0x%08lx, reread:0x%08x, 0x%08x (rereadA^readA:0x%08x, rereadB^readB:0x%08x).\n", + read[0], read[1], read[0] ^ read[1], physaddr, + reread[0], reread[1], reread[0] ^ read[0], reread[1] ^ read[1]); } else { - fprintf(stderr, - "FAILURE: 0x%08lx != 0x%08lx at offset 0x%08lx.\n", - (ul) *p1, (ul) *p2, (ul) (i * sizeof(ul))); + fprintf(stdout, + "FAILURE: 0x%08x != 0x%08x (readA^readB:0x%08x) at offset 0x%08lx.\n" + "physical address: 0x%08lx, 0x%08lx, " + "reread:0x%08x, 0x%08x (rereadA^readA:0x%08x, rereadB^readB:0x%08x).\n", + read[0], read[1], read[0] ^ read[1], (ul) (i * sizeof(u32v)), + read_pagemap((ul)p1), read_pagemap((ul)p2), + reread[0], reread[1], reread[0] ^ read[0], reread[1] ^ read[1]); } /* printf("Skipping to next test..."); */ r = -1; + fault_cnt++; } } return r; } -int test_stuck_address(ulv *bufa, size_t count) { - ulv *p1 = bufa; +int test_stuck_address(u32v *bufa, size_t count) { + u32v *p1 = bufa; + u32 read, expect; + u32 reread; unsigned int j; size_t i; off_t physaddr; @@ -76,33 +101,41 @@ int test_stuck_address(ulv *bufa, size_t count) { fflush(stdout); for (j = 0; j < 16; j++) { printf("\b\b\b\b\b\b\b\b\b\b\b"); - p1 = (ulv *) bufa; + p1 = (u32v *) bufa; printf("setting %3u", j); fflush(stdout); for (i = 0; i < count; i++) { - *p1 = ((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1); + *p1 = ((j + i) % 2) == 0 ? (u32)(ul) p1 : ~((u32)(ul) p1); *p1++; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); fflush(stdout); - p1 = (ulv *) bufa; + p1 = (u32v *) bufa; for (i = 0; i < count; i++, p1++) { - if (*p1 != (((j + i) % 2) == 0 ? (ul) p1 : ~((ul) p1))) { + read = *p1; + expect = ((j + i) % 2) == 0 ? (u32)(ul) p1 : ~((u32)(ul) p1); + if (read != expect) { + dcacheflush((ul)p1, (ul)p1 + 4); + reread = *p1; if (use_phys) { - physaddr = physaddrbase + (i * sizeof(ul)); - fprintf(stderr, + physaddr = physaddrbase + (i * sizeof(u32)); + fprintf(stdout, "FAILURE: possible bad address line at physical " - "address 0x%08lx.\n", - physaddr); + "address 0x%08lx:0x%08x != 0x%08x (0x%08x), reread:0x%08x(reread^read:0x%08x).\n", + physaddr, read, expect, read ^ expect, reread, reread ^ read); } else { - fprintf(stderr, + fprintf(stdout, "FAILURE: possible bad address line at offset " - "0x%08lx.\n", - (ul) (i * sizeof(ul))); + "0x%08lx.\n" + "physical address 0x%08lx:0x%08x != 0x%08x (0x%08x)," + "reread:0x%08x(reread^read:0x%08x).\n", + (ul) (i * sizeof(u32)), read_pagemap((ul)p1), + read, expect, read ^ expect, reread, reread ^ read); } printf("Skipping to next test...\n"); fflush(stdout); + fault_cnt++; return -1; } } @@ -112,9 +145,9 @@ int test_stuck_address(ulv *bufa, size_t count) { return 0; } -int test_random_value(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_random_value(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; ul j = 0; size_t i; @@ -133,11 +166,11 @@ int test_random_value(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_xor_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { *p1++ ^= q; @@ -146,11 +179,11 @@ int test_xor_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_sub_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { *p1++ -= q; @@ -159,11 +192,11 @@ int test_sub_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_mul_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { *p1++ *= q; @@ -172,11 +205,11 @@ int test_mul_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_div_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { if (!q) { @@ -188,11 +221,11 @@ int test_div_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_or_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { *p1++ |= q; @@ -201,11 +234,11 @@ int test_or_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_and_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { *p1++ &= q; @@ -214,11 +247,11 @@ int test_and_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_seqinc_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; size_t i; - ul q = rand_ul(); + u32 q = rand_ul(); for (i = 0; i < count; i++) { *p1++ = *p2++ = (i + q); @@ -226,24 +259,55 @@ int test_seqinc_comparison(ulv *bufa, ulv *bufb, size_t count) { return compare_regions(bufa, bufb, count); } -int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_solidbits_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j; - ul q; + u32 q; + u32 data[4]; size_t i; printf(" "); fflush(stdout); 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; + if (io_bw == IO_BW_32) { + q = (j % 2) == 0 ? UL_ONEBITS : 0; + if (fix_level) + q |= fix_bit; + else + q &= ~fix_bit; + } else if (io_bw == IO_BW_16) { + q = (j % 2) == 0 ? (UL_ONEBITS & 0x0000ffff) : (0 & 0xffff0000); + if (fix_level) + q |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + else + q &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + q = (j % 2) == 0 ? (UL_ONEBITS & 0x00ff00ff) : (0 & 0xff00ff00); + if (fix_level) + q |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + else + q &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } + + data[0] = data[2] = q; + if (io_bw == IO_BW_32) { + if (fix_level) { + data[1] = data[3] = (~q) | fix_bit; + } else { + data[1] = data[3] = (~q) & (~fix_bit); + } + } else { + data[1] = data[3] = q; + } + data_cpu_2_io(data, sizeof(data)); printf("setting %3u", j); fflush(stdout); - p1 = (ulv *) bufa; - p2 = (ulv *) bufb; + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; for (i = 0; i < count; i++) { - *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); @@ -257,24 +321,54 @@ int test_solidbits_comparison(ulv *bufa, ulv *bufb, size_t count) { return 0; } -int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_checkerboard_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j; - ul q; + u32 q; + u32 data[4]; size_t i; printf(" "); fflush(stdout); for (j = 0; j < 64; j++) { printf("\b\b\b\b\b\b\b\b\b\b\b"); - q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; + if (io_bw == IO_BW_32) { + q = (j % 2) == 0 ? CHECKERBOARD1 : CHECKERBOARD2; + if (fix_level) + q |= fix_bit; + else + q &= ~fix_bit; + } else if (io_bw == IO_BW_16) { + q = ((CHECKERBOARD1 & 0x0000ffff) | (CHECKERBOARD2 & 0xffff0000)); + if (fix_level) + q |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + else + q &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + q = ((CHECKERBOARD1 & 0x00ff00ff) | (CHECKERBOARD2 & 0xff00ff00)); + if (fix_level) + q |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + else + q &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } + data[0] = data[2] = q; + if (io_bw == IO_BW_32) { + if (fix_level) { + data[1] = data[3] = (~q) | fix_bit; + } else { + data[1] = data[3] = (~q) & (~fix_bit); + } + } else { + data[1] = data[3] = q; + } + data_cpu_2_io(data, sizeof(data)); printf("setting %3u", j); fflush(stdout); - p1 = (ulv *) bufa; - p2 = (ulv *) bufb; + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; for (i = 0; i < count; i++) { - *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); @@ -288,22 +382,48 @@ int test_checkerboard_comparison(ulv *bufa, ulv *bufb, size_t count) { return 0; } -int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_blockseq_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j; + u32 data[4]; + u32 q; size_t i; printf(" "); fflush(stdout); for (j = 0; j < 256; j++) { printf("\b\b\b\b\b\b\b\b\b\b\b"); - p1 = (ulv *) bufa; - p2 = (ulv *) bufb; + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; printf("setting %3u", j); fflush(stdout); + q = (u32)UL_BYTE(j); + + if (io_bw == IO_BW_32) { + if (fix_level) + q |= fix_bit; + else + q &= ~fix_bit; + } else if (io_bw == IO_BW_16) { + if (fix_level) + q |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + else + q &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + if (fix_level) + q |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + else + q &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } + + data[0] = q; + data[1] = q; + data[2] = q; + data[3] = q; + data_cpu_2_io(data, sizeof(data)); for (i = 0; i < count; i++) { - *p1++ = *p2++ = (ul) UL_BYTE(j); + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); @@ -317,26 +437,53 @@ int test_blockseq_comparison(ulv *bufa, ulv *bufb, size_t count) { return 0; } -int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_walkbits0_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j; + u32 data[4]; + u32 q; size_t i; printf(" "); fflush(stdout); 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; + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; printf("setting %3u", j); fflush(stdout); + if (j < UL_LEN) + q = ONE << j; + else + q = ONE << (UL_LEN * 2 - j - 1); + + if (io_bw == IO_BW_32) { + if (fix_level) + q |= fix_bit; + else + q &= ~fix_bit; + } else if (io_bw == IO_BW_16) { + if (fix_level) + q |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + else + q &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + if (fix_level) + q |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + else + q &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } + + data[0] = q; + data[1] = q; + data[2] = q; + data[3] = q; + + data_cpu_2_io(data, sizeof(data)); + 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); - } + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); @@ -350,26 +497,55 @@ int test_walkbits0_comparison(ulv *bufa, ulv *bufb, size_t count) { return 0; } -int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_walkbits1_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j; + u32 data[4]; + u32 q; size_t i; printf(" "); fflush(stdout); + 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; + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; printf("setting %3u", j); + + if (j < UL_LEN) + q = UL_ONEBITS ^ (ONE << j); + else + q = UL_ONEBITS ^ (ONE << (UL_LEN * 2 - j - 1)); + + if (io_bw == IO_BW_32) { + if (fix_level) + q |= fix_bit; + else + q &= ~fix_bit; + } else if (io_bw == IO_BW_16) { + if (fix_level) + q |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + else + q &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + if (fix_level) + q |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + else + q &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } + + data[0] = q; + data[1] = q; + data[2] = q; + data[3] = q; + + data_cpu_2_io(data, sizeof(data)); + fflush(stdout); 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)); - } + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); @@ -383,32 +559,80 @@ int test_walkbits1_comparison(ulv *bufa, ulv *bufb, size_t count) { return 0; } -int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_bitspread_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j; + u32 data[4]; size_t i; + u32 length; printf(" "); fflush(stdout); + + if (io_bw == IO_BW_32) { + length = UL_LEN; + } else if (io_bw == IO_BW_16) { + length = UL_LEN / 2; + } else { + length = UL_LEN / 4; + } + 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; + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; printf("setting %3u", j); + + if (j < length) { + data[0] = (ONE << j) | (ONE << (j + 2)); + data[1] = UL_ONEBITS ^ ((ONE << j) | (ONE << (j + 2))); + } else { + data[0] = (ONE << (length * 2 - 1 - j)) | + (ONE << (length * 2 + 1 - j)); + data[1] = UL_ONEBITS ^ (ONE << (length * 2 - 1 - j) + | (ONE << (length * 2 + 1 - j))); + } + if (io_bw == IO_BW_16) { + data[1] = data[0] = (data[0] & 0x0000ffff) | ((data[1] & 0x0000ffff) << 16); + } else if (io_bw == IO_BW_8) { + data[1] = data[0] = (data[0] & 0x000000ff) | ((data[1] & 0x000000ff) << 8) | + ((data[0] & 0x000000ff) << 16) | ((data[1] & 0x000000ff) << 24); + } + if (fix_level) { + if (io_bw == IO_BW_32) { + data[0] |= fix_bit; + data[1] |= fix_bit; + } else if (io_bw == IO_BW_16) { + data[0] |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + data[1] |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + } else { + data[0] |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | + ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + data[1] |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | + ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + } + } else { + if (io_bw == IO_BW_32) { + data[0] &= ~fix_bit; + data[1] &= ~fix_bit; + } else if (io_bw == IO_BW_16) { + data[0] &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + data[1] &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + data[0] &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | + ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + data[1] &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | + ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } + } + data[2] = data[0]; + data[3] = data[1]; + data_cpu_2_io(data, sizeof(data)); + fflush(stdout); 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))); - } + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", j); @@ -422,26 +646,64 @@ int test_bitspread_comparison(ulv *bufa, ulv *bufb, size_t count) { return 0; } -int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) { - ulv *p1 = bufa; - ulv *p2 = bufb; +int test_bitflip_comparison(u32v *bufa, u32v *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { + u32v *p1 = bufa; + u32v *p2 = bufb; unsigned int j, k; - ul q; + u32 q; + u32 data[4]; size_t i; printf(" "); fflush(stdout); for (k = 0; k < UL_LEN; k++) { - q = ONE << k; + if (io_bw == IO_BW_32) + q = ONE << k; + else if (io_bw == IO_BW_16) + q = ONE << (k % 16); + else + q = ONE << (k % 8); for (j = 0; j < 8; j++) { printf("\b\b\b\b\b\b\b\b\b\b\b"); - q = ~q; + if (io_bw == IO_BW_32) { + if (fix_level) { + q = (~q) | fix_bit; + } else { + q = (~q) & (~fix_bit); + } + } else if (io_bw == IO_BW_16) { + q = (q & 0x0000ffff) | ((~q & 0x0000ffff) << 16); + if (fix_level) + q |= (fix_bit & 0x0000ffff) | ((fix_bit & 0x0000ffff) << 16); + else + q &= (~fix_bit & 0x0000ffff) | ((~fix_bit & 0x0000ffff) << 16); + } else { + q = (q & 0x000000ff) | ((~q & 0x000000ff) << 8) | + ((q & 0x000000ff) << 16) | ((~q & 0x000000ff) << 24); + if (fix_level) + q |= (fix_bit & 0x000000ff) | ((fix_bit & 0x000000ff) << 8) | + ((fix_bit & 0x000000ff) << 16) | ((fix_bit & 0x000000ff) << 24); + else + q &= (~fix_bit & 0x000000ff) | ((~fix_bit & 0x000000ff) << 8) | + ((~fix_bit & 0x000000ff) << 16) | ((~fix_bit & 0x000000ff) << 24); + } printf("setting %3u", k * 8 + j); fflush(stdout); - p1 = (ulv *) bufa; - p2 = (ulv *) bufb; + data[0] = data[2] = q; + if (io_bw == IO_BW_32) { + if (fix_level) { + data[1] = data[3] = (~q) | fix_bit; + } else { + data[1] = data[3] = (~q) & (~fix_bit); + } + } else { + data[1] = data[3] = q; + } + data_cpu_2_io(data, sizeof(data)); + p1 = (u32v *) bufa; + p2 = (u32v *) bufb; for (i = 0; i < count; i++) { - *p1++ = *p2++ = (i % 2) == 0 ? q : ~q; + *p1++ = *p2++ = data[i & 3]; } printf("\b\b\b\b\b\b\b\b\b\b\b"); printf("testing %3u", k * 8 + j); @@ -457,9 +719,9 @@ int test_bitflip_comparison(ulv *bufa, ulv *bufb, size_t count) { } #ifdef TEST_NARROW_WRITES -int test_8bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { +int test_8bit_wide_random(u32v* bufa, u32v* bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { u8v *p1, *t; - ulv *p2; + u32v *p2; int attempt; unsigned int b, j = 0; size_t i; @@ -495,9 +757,9 @@ int test_8bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { return 0; } -int test_16bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { +int test_16bit_wide_random(u32v* bufa, u32v* bufb, size_t count, unsigned int fix_bit, unsigned int fix_level) { u16v *p1, *t; - ulv *p2; + u32v *p2; int attempt; unsigned int b, j = 0; size_t i; @@ -533,3 +795,31 @@ int test_16bit_wide_random(ulv* bufa, ulv* bufb, size_t count) { return 0; } #endif + +void exit_result(int exit_code) +{ + printf("\n*************************************************************\n"); + printf("memtester result:\n"); + printf("Log: had found %u failures.\n", fault_cnt); + printf("\nStatus: "); + if (!fault_cnt) { + printf("PASS.\n"); + } else { + printf("FAIL - "); + switch (exit_code) { + EXIT_FAIL_NONSTARTER: + printf("EXIT_FAIL_NONSTARTER\n"); + break; + EXIT_FAIL_ADDRESSLINES: + printf("EXIT_FAIL_ADDRESSLINES\n"); + break; + EXIT_FAIL_OTHERTEST: + default: + printf("EXIT_FAIL_OTHERTEST\n"); + break; + } + } + printf("\n*************************************************************\n"); + exit(exit_code); +} + diff --git a/tests.h b/tests.h index e8b2f5f..1559065 100644 --- a/tests.h +++ b/tests.h @@ -16,24 +16,25 @@ /* 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_stuck_address(unsigned int volatile *bufa, size_t count); +int test_random_value(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_xor_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_sub_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_mul_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_div_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_or_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_and_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_seqinc_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_solidbits_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_checkerboard_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_blockseq_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_walkbits0_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_walkbits1_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_bitspread_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_bitflip_comparison(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); #ifdef TEST_NARROW_WRITES -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); +int test_8bit_wide_random(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); +int test_16bit_wide_random(unsigned int volatile *bufa, unsigned int volatile *bufb, size_t count, unsigned int fix_bit, unsigned int fix_level); #endif +void exit_result(int exit_code); diff --git a/types.h b/types.h index 4cb41c3..e2d86f0 100644 --- a/types.h +++ b/types.h @@ -14,9 +14,12 @@ #include "sizes.h" +typedef unsigned char uchar; +typedef unsigned int u32; typedef unsigned long ul; typedef unsigned long long ull; -typedef unsigned long volatile ulv; +/* for all rk chip, dram bandwidth both 32bit */ +typedef unsigned int volatile u32v; typedef unsigned char volatile u8v; typedef unsigned short volatile u16v; @@ -24,3 +27,4 @@ struct test { char *name; int (*fp)(); }; + diff --git a/va_2_pa.c b/va_2_pa.c new file mode 100644 index 0000000..5c42f42 --- /dev/null +++ b/va_2_pa.c @@ -0,0 +1,76 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * (C) Copyright 2019 Rockchip Electronics Co., Ltd. + */ + +#include +#include +#include +#include +#include +#include +#include +#include "types.h" +#include "va_2_pa.h" + +#define PAGEMAP_ENTRY 8 +#define GET_BIT(X,Y) (X & ((unsigned long long)1<> Y +#define GET_PFN(X) X & 0x7FFFFFFFFFFFFF + +const int __endian_bit = 1; +#define is_bigendian() ( (*(char*)&__endian_bit) == 0 ) + +unsigned long read_pagemap(unsigned long virt_addr) +{ + FILE * f; + unsigned char c_buf[PAGEMAP_ENTRY]; + unsigned int status, i, c; + ull page_size, file_offset; + unsigned long phy_addr = 0, page; + + f = fopen("/proc/self/pagemap", "rb"); + if (!f) { + printf("Error! Cannot open /proc/self/pagemap\n"); + return -1; + } + page_size = getpagesize(); + + file_offset = virt_addr / page_size * PAGEMAP_ENTRY; + //printf("Vaddr: 0x%lx, Page_size: %lld, Entry_size: %d\n", virt_addr, page_size, PAGEMAP_ENTRY); + ///printf("Reading %s at 0x%llx\n", "/proc/self/pagemap", (unsigned long long)file_offset); + status = fseek(f, file_offset, SEEK_SET); + if (status) { + perror("Failed to do fseek for get physical address!\n"); + return -1; + } + errno = 0; + page = 0; + for(i=0; i < PAGEMAP_ENTRY; i++){ + c = getc(f); + if (c==EOF) { + printf("\nReached end of the file\n"); + return -1; + } + if (is_bigendian()) + c_buf[i] = c; + else + c_buf[PAGEMAP_ENTRY - i - 1] = c; + //printf("[%d]0x%x ", i, c); + } + for(i=0; i < PAGEMAP_ENTRY; i++){ + //printf("%d ",c_buf[i]); + page = (page << 8) + c_buf[i]; + } + //printf("Result: 0x%llx\n", (unsigned long long) page); + if(GET_BIT(page, 63)) { + uint64_t pfn = GET_PFN(page); + phy_addr = pfn * page_size + virt_addr % page_size; + //printf("PFN: 0x%llx (0x%llx)\n", pfn, phy_addr); + } else { + printf("Page not present\n"); + } + if(GET_BIT(page, 62)) + printf("Page swapped\n"); + fclose(f); + return phy_addr; +} diff --git a/va_2_pa.h b/va_2_pa.h new file mode 100644 index 0000000..dab38e9 --- /dev/null +++ b/va_2_pa.h @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2019 Rockchip Electronics Co., Ltd. + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +#ifndef _VA_2_PA_H +#define _VA_2_PA_H + +int data_cpu_2_io(void *p, u32 len); +void data_cpu_2_io_init(char *chip, char *ddr_bw); + +unsigned long read_pagemap(unsigned long virt_addr); + +#endif /* _VA_2_PA_H */ -- 2.38.0