📄 ui_memtest.c
字号:
/* ********************************************************************* * Broadcom Common Firmware Environment (CFE) * * Test commands File: ui_memtest.c * * A simple memory test * * Author: Mitch Lichtenberg * ********************************************************************* * * Copyright 2000,2001,2002,2003 * Broadcom Corporation. All rights reserved. * * This software is furnished under license and may be used and * copied only in accordance with the following terms and * conditions. Subject to these conditions, you may download, * copy, install, use, modify and distribute modified or unmodified * copies of this software in source and/or binary form. No title * or ownership is transferred hereby. * * 1) Any source code used, modified or distributed must reproduce * and retain this copyright notice and list of conditions * as they appear in the source file. * * 2) No right is granted to use any trade name, trademark, or * logo of Broadcom Corporation. The "Broadcom Corporation" * name may not be used to endorse or promote products derived * from this software without the prior written permission of * Broadcom Corporation. * * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF * THE POSSIBILITY OF SUCH DAMAGE. ********************************************************************* */#include "cfe.h"#include "sbmips.h"#include "ui_command.h"#include "cfe_mem.h"#include "lib_hssubr.h"#include "exception.h"#ifdef _BIGSUR_#include "bcm1480_regs.h"#include "bcm1480_scd.h"#endifstatic int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]);#ifndef BCM47XXstatic int ui_cmd_randmemtest(ui_cmdline_t *cmd,int argc,char *argv[]);#endif#ifndef _SB_MAKE64#define _SB_MAKE64(x) ((uint64_t)(x))#endif#ifndef _SB_MAKEMASK#define _SB_MAKEMASK(v,n) (_SB_MAKE64((_SB_MAKE64(1)<<(v))-1) << _SB_MAKE64(n))#endif#ifndef _SB_MAKEMASK1#define _SB_MAKEMASK1(n) (_SB_MAKE64(1) << _SB_MAKE64(n))#endifint ui_init_memtestcmds(void);int ui_init_memtestcmds(void){ cmd_addcmd("memorytest", ui_cmd_memorytest, NULL, "Tests all available memory", "", "-loop;Loop forever or until keypress|" "-stoponerror;Stop if error occurs while looping|" "-cca=*;Use specified cacheability attribute|" "-arena=*;Test only specified arena index");#ifndef BCM47XX cmd_addcmd("randmemtest", ui_cmd_randmemtest, NULL, "Tests memory using random access pattern", "randmemtest [num_mb]", "-loop;Loop forever or until keypress|" "-stoponerror;Stop if error occurs while looping|" "-cca=*;Use specified cacheability attribute|" "-ignoreerror;Ignore errors, don't print anything|" "-arena=*;Test only specified arena index");#endif /* BCM47XX */ return 0;}/* extensive memory tests */static void inline uacwrite(volatile uint64_t *srcadr,hsaddr_t dstadr) {__asm __volatile ("ld $8, 0(%0) ; " "ld $9, 8(%0) ; " "ld $10, 16(%0) ; " "ld $11, 24(%0) ; " "sync ; " ".align 4 ; " "sd $8, 0(%1) ; " "sd $9, 8(%1) ; " "sd $10, 16(%1) ; " "sd $11, 24(%1) ; " "sync" :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11");}static void inline readline(hsaddr_t srcadr,volatile uint64_t *dstadr) {__asm __volatile ("ld $8, 0(%0) ; " "ld $9, 8(%0) ; " "ld $10, 16(%0) ; " "ld $11, 24(%0) ; " "sd $8, 0(%1) ; " "sd $9, 8(%1) ; " "sd $10, 16(%1) ; " "sd $11, 24(%1) ; " :: "r"(srcadr),"r"(dstadr) : "$8","$9","$10","$11");}#define TEST_DATA_LEN 4#define CACHE_LINE_LEN 32static int test_arena(hsaddr_t arena_start,hsaddr_t arena_size,int cca,int stoponerror);static int ui_cmd_memorytest(ui_cmdline_t *cmd,int argc,char *argv[]){ int arena; int error; int arena_type; uint64_t arena_start, arena_size; int forever; int passcnt; int stoponerr = 0; hsaddr_t phys_addr; hsaddr_t mem_base; int cca = K_CALG_UNCACHED_ACCEL; int arenanum = -1; char *x; int res; forever = cmd_sw_isset(cmd,"-loop"); stoponerr = cmd_sw_isset(cmd,"-stoponerror"); if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x); if (cmd_sw_value(cmd,"-arena",&x)) arenanum = atoi(x); printf("Available memory arenas:\n"); arena = 0; while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) { phys_addr = arena_start; /* actual physical address */#if CPUCFG_REGS64 mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */#else mem_base = PHYS_TO_K1(phys_addr); /* virtual address */#endif xprintf("phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size); arena++; } passcnt = 0; res = 0; printf("\nTesting memory.\n"); do { passcnt++; if (forever) { if (console_status()) break; printf("***** Iteration %d *****\n",passcnt); } arena = 0; error = 0; while (cfe_arena_enum(arena, &arena_type, &arena_start, &arena_size, FALSE) == 0) { /* * See if we were asked to do just one part of memory. */ if ((arenanum >= 0) && (arena != arenanum)) { arena++; continue; } /* * If we enumerated the locore area, avoid it. */ if (arena_start == 0) { arena_start += CFE_LOCORE_GLOBAL_END; arena_size -= CFE_LOCORE_GLOBAL_END; } res = test_arena(arena_start,arena_size,cca,stoponerr); if (stoponerr && (res < 0)) { forever = 0; break; } arena++; } } while (forever); return res;}static int test_arena(hsaddr_t arena_start,hsaddr_t arena_size,int cca,int stoponerr){ static volatile uint64_t test_data[TEST_DATA_LEN] = { 0xaaaaaaaaaaaaaaaaULL, 0x5555555555555555ULL, 0xccccccccccccccccULL, 0x3333333333333333ULL, /* one cache line */ }; static volatile uint64_t check_data[TEST_DATA_LEN]; int exitLoop; int error; hsaddr_t phys_addr; long offset; hsaddr_t mem_base; long i; hsaddr_t dst_adr, cache_dst_adr; long cda,tda; test_data[0] = 0xAAAAAAAAAAAAAAAAULL; test_data[1] = 0x5555555555555555ULL; test_data[2] = 0xCCCCCCCCCCCCCCCCULL; test_data[3] = 0x3333333333333333ULL; phys_addr = arena_start; /* actual physical address */#if CPUCFG_REGS64 mem_base = PHYS_TO_XKPHYS(cca, phys_addr); /* virtual address */#else mem_base = PHYS_TO_K1(phys_addr); /* virtual address */#endif xprintf("\n"); xprintf("Testing: phys = %016llX, virt = %016llX, size = %016llX\n", phys_addr, mem_base, arena_size); xprintf("Writing: a/5/c/3\n"); for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { dst_adr = (mem_base+offset); uacwrite(test_data, dst_adr); } xprintf("Reading: a/5/c/3\n"); error = 0; for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { dst_adr = (mem_base+offset); cache_dst_adr = (mem_base+offset); readline(cache_dst_adr,check_data); for (i = 0; i < TEST_DATA_LEN; i++) { cda = check_data[i]; tda = test_data[i]; if (cda != tda) { xprintf("mem[%016llX] %016llX != %016llX\n", mem_base+offset+(i*8), cda, tda); error++; } } if (error) break; } if (error) return -1; xprintf("Writing: address|5555/inv/aaaa|address\n"); exitLoop = 0; for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { dst_adr = (mem_base+offset); test_data[0] = ((uint64_t)dst_adr<<32)|0x55555555; test_data[1] = ~test_data[0]; test_data[2] = 0xaaaaaaaa00000000ULL|(dst_adr & 0xffffffff); test_data[3] = ~test_data[2]; uacwrite(test_data, dst_adr); } xprintf("Reading: address|5555/inv/aaaa|address\n"); error = 0; for (offset = 0; (offset < arena_size); offset += CACHE_LINE_LEN) { dst_adr = (mem_base+offset); test_data[0] = ((uint64_t)dst_adr<<32)|0x55555555; test_data[1] = ~test_data[0]; test_data[2] = 0xaaaaaaaa00000000ULL|(dst_adr & 0xffffffff); test_data[3] = ~test_data[2]; cache_dst_adr = (mem_base+offset); readline(cache_dst_adr,check_data); for (i = 0; i < TEST_DATA_LEN; i++) { cda = check_data[i]; tda = test_data[i]; if (cda != tda) { xprintf("mem[%016llX] %016llX != %016llX\n", mem_base+offset+(i*8),cda,tda); error++; } } if (error) break; } return error ? -1 : 0;}#define LFSR_M 22#define LFSR_TAP 21//#define LFSR_PERIOD 0x3fff80#define LFSR_PERIOD 0x3ffffstatic inline unsigned long nextval(unsigned long regval){ unsigned long newbit; newbit = (regval & 1) ^ ((regval & (1<<(LFSR_M - LFSR_TAP))) != 0); regval = (regval >> 1) | (newbit << (LFSR_M-1)); return regval;}#ifndef BCM47XX#define START_PHYS 0x1000static int randmemtest(int num_mb,int high_mb,int cca,int stoponerr,int ignoreerr){#if CPUCFG_REGS64 hsaddr_t membase = PHYS_TO_XKPHYS(cca,START_PHYS);#else hsaddr_t membase = PHYS_TO_K1(START_PHYS); /* UNCACHED virtual address */#endif unsigned long lfsr; uint64_t idx; uint64_t maxidx; uint64_t highlfsr; int error = 0; register uint64_t pattern0,pattern1,pattern2,pattern3,x; highlfsr = (high_mb << 15); if (highlfsr == 0) highlfsr = 0x3fff80; maxidx = (uint64_t) ((num_mb << 15)-1); printf("Highest physaddr is %016llX\n",highlfsr<<5); printf("Writing (memory base %016llX)\n",membase); lfsr = (1<<LFSR_M)-1; for (idx = 0; idx < maxidx; idx++) { pattern0 = 0x5555555555555555ULL ^ (lfsr | (lfsr << LFSR_M)); pattern1 = ~pattern0; pattern3 = 0xaaaaaaaaaaaaaaaaULL ^ (idx | (idx << LFSR_M)) ; pattern2 = ~pattern3; if (lfsr < highlfsr) { __asm __volatile ( " .align 4 ; " " sd %0,0(%4) ; " " sd %1,8(%4) ; " " sd %2,16(%4) ; " " sd %3,24(%4) ; " : : "r"(pattern0),"r"(pattern1),"r"(pattern2),"r"(pattern3), "r"(membase+(hsaddr_t)(lfsr << 5))); } lfsr = nextval(lfsr); } printf("Reading.\n"); lfsr = (1<<LFSR_M)-1; for (idx = 0; idx < maxidx; idx++) { if (lfsr < highlfsr) { /* stay within 128MB */ hsaddr_t addr = (membase + (hsaddr_t)(lfsr<<5)); __asm __volatile ( " ld %0,0(%4) ; " " ld %1,8(%4) ; " " ld %2,16(%4) ; " " ld %3,24(%4)" : "=r"(pattern0),"=r"(pattern1),"=r"(pattern2),"=r"(pattern3) : "r"(addr)); if (!ignoreerr) { x = 0x5555555555555555ULL ^ (lfsr | (lfsr << LFSR_M)); if (pattern0 != x) { printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr,pattern0,x,pattern0^x); error++; if (console_status()) break; } x = ~x; if (pattern1 != x) { printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr+8,pattern1,x,pattern1^x); error++; if (console_status()) break; } x = 0xaaaaaaaaaaaaaaaaULL ^ (idx | (idx << LFSR_M)); if (pattern3 != x) { printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr+24,pattern3,x,pattern3^x); error++; if (console_status()) break; } x = ~x; if (pattern2 != x) { printf("mem[%016llX] %016llX should be %016llX (%016llX)\n",addr+16,pattern2,x,pattern2^x); error++; if (console_status()) break; } } if (error && stoponerr) break; } lfsr = nextval(lfsr); } return error;}static int ui_cmd_randmemtest(ui_cmdline_t *cmd,int argc,char *argv[]){ int stoponerr = 1; int ignoreerr = 0; char *x; int cca = K_CALG_UNCACHED_ACCEL; int forever; int error = 0; int res; int num_mb = 128; int high_mb = 128; ignoreerr = cmd_sw_isset(cmd,"-ignoreerror"); stoponerr = cmd_sw_isset(cmd,"-stoponerror"); if (cmd_sw_value(cmd,"-cca",&x)) cca = atoi(x); forever = cmd_sw_isset(cmd,"-loop"); if ((x = cmd_getarg(cmd,0))) num_mb = atoi(x); if (num_mb > 128) num_mb = 128; if ((x = cmd_getarg(cmd,1))) high_mb = atoi(x); if (high_mb > 128) high_mb = 128; do {#ifdef _BIGSUR_ SBWRITECSR(A_BUS_L2_ERRORS,0); SBWRITECSR(A_BUS_MEM_IO_ERRORS,0);#endif res = randmemtest(num_mb,high_mb,cca,stoponerr,ignoreerr); if (res != 0) error = -1; if ((res != 0) && stoponerr) break;#ifdef _BIGSUR_ do { uint64_t l2reg,memreg; l2reg = SBREADCSR(A_BUS_L2_ERRORS); memreg = SBREADCSR(A_BUS_MEM_IO_ERRORS); printf("L2: CorrECC=%d BadECC=%d Mem: CorrECC=%d BadECC=%d\n", (int)G_SCD_L2ECC_CORR_D(l2reg),(int)G_SCD_L2ECC_BAD_D(l2reg), (int)G_SCD_MEM_ECC_CORR(memreg),(int)G_SCD_MEM_ECC_BAD(memreg)); } while (0);#endif } while (forever && !console_status()); return error;}#endif /* !BCM47XX */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -