Author: wmb Date: Sat Jun 4 22:25:49 2011 New Revision: 2245 URL: http://tracker.coreboot.org/trac/openfirmware/changeset/2245
Log: OLPC XO-1.75 trac #10883 - Integrated memory test suite into XO-1.75 build and added a random address and data memory test based on a linear feedback shift register sequence generator. To use, "test /memory", or "memtest" for a multi-pass test.
Modified: cpu/arm/memtest.fth cpu/arm/mmp2/mmuon.fth cpu/arm/olpc/1.75/addrs.fth cpu/arm/olpc/1.75/devices.fth cpu/arm/olpc/1.75/probemem.fth cpu/arm/olpc/initmmu.fth cpu/arm/scc.fth ofw/fcode/memtest.fth
Modified: cpu/arm/memtest.fth ============================================================================== --- cpu/arm/memtest.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/memtest.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -7,7 +7,10 @@
\ Report the progress through low-level tests 0 0 2value test-name -: show-status ( adr len -- ) to test-name ; +: (quiet-show-status) ( adr len -- ) to test-name ; + +defer show-status +' type to show-status
code lfill ( adr len l -- ) \ tos: pattern @@ -86,6 +89,160 @@
2dup afill mask @ masked-atest ; +code random-fill ( adr len data index polynomial -- ) + ldmia sp!,{r1,r2,r3,r4} \ tos:poly r1:index r2:data r3:len r4:adr + + movs r3,r3,lsr #2 \ Convert to longword count + nxteq + + sub r0,r3,#1 \ r0:remaining count + + \ r3:address-lfsr r4:data-lfsr r5:data-poly + set r5,#0x80200003 \ 32-bit polynomial + + begin + \ Compute new data value with an LFSR step + movs r2,r2,lsr #1 + eorcs r2,r2,r5 + + \ Compute new address index, discarding values >= len + begin + movs r1,r1,lsr #1 + eorcs r1,r1,tos + cmp r1,r3 + u< until + + \ Write the "random" value to the "random" address (adr[index]) + str r2,[r4,r1,lsl #2] + + decs r0,#1 + 0= until + + pop tos,sp +c; +code random-check ( adr len data index remain polynomial -- false | adr len data index remain true ) + ldmia sp!,{r0,r1,r2,r3,r4} \ tos:poly r0:remain r1:index r2:data r3:len r4:adr + + cmp r0,#0 + moveq tos,#0 \ Return false + nxteq + + mov r7,r3,lsr #2 \ Convert to longword count + + set r5,#0x80200003 \ 32-bit polynomial + + begin + \ Compute new data value with an LFSR step + movs r2,r2,lsr #1 + eorcs r2,r2,r5 + + \ Compute new address index, discarding values >= len + begin + movs r1,r1,lsr #1 + eorcs r1,r1,tos + cmp r1,r7 + u< until + + \ Read the value at the "random" address (adr[index]) + ldr r6,[r4,r1,lsl #2] + + \ Compare it to the calculated value + cmp r6,r2 + + decne r0,#1 + stmnedb sp!,{r0,r1,r2,r3,r4} \ Push results + mvnne tos,#0 \ True on top of stack + nxtne + + decs r0,#1 + 0= until + + mov tos,#0 +c; +\ Polynomials for maximal length LFSRs for different bit lengths +\ The values come from the Wikipedia article for Linear Feedback Shift Register and from +\ http://www.xilinx.com/support/documentation/application_notes/xapp052.pdf +create polynomials \ #bits period +h# 0 , \ 0 0 +h# 1 , \ 1 1 +h# 3 , \ 2 3 +h# 6 , \ 3 7 +h# c , \ 4 f +h# 14 , \ 5 1f +h# 30 , \ 6 3f +h# 60 , \ 7 7f +h# b8 , \ 8 ff +h# 110 , \ 9 1ff +h# 240 , \ 10 3ff +h# 500 , \ 11 7ff +h# e08 , \ 12 fff +h# 1c80 , \ 13 1fff +h# 3802 , \ 14 3fff +h# 6000 , \ 15 7fff +h# b400 , \ 16 ffff +h# 12000 , \ 17 1ffff +h# 20400 , \ 18 3ffff +h# 72000 , \ 19 7ffff +h# 90000 , \ 20 fffff +h# 140000 , \ 21 1fffff +h# 300000 , \ 22 3fffff +h# 420000 , \ 23 7fffff +h# e10000 , \ 24 ffffff +h# 1200000 , \ 25 1ffffff +h# 2000023 , \ 26 3ffffff +h# 4000013 , \ 27 7ffffff +h# 9000000 , \ 28 fffffff +h# 14000000 , \ 29 1fffffff +h# 20000029 , \ 30 3fffffff +h# 48000000 , \ 31 7fffffff +h# 80200003 , \ 32 ffffffff + +: round-up-log2 ( n -- log2 ) + dup log2 ( n log2 ) + tuck 1 swap lshift ( log2 n 2^log2 ) + > - ( log2' ) +; + +defer .lfsr-mem-error +: (.lfsr-mem-error) ( adr len data index remain -- adr len data index remain ) + push-hex + ." Error at address " 4 pick 2 pick la+ dup 8 u.r ( adr len data index remain err-adr ) + ." - expected " 3 pick 8 u.r ( adr len data index remain err-adr ) + ." got " l@ 8 u.r cr + pop-base +; +' (.lfsr-mem-error) to .lfsr-mem-error +: throw-lfsr-error ( adr len data index remain -- <thrown> ) + (.lfsr-mem-error) -1 throw +; + +: (random-test) ( adr len -- ) + dup /l <= if 2drop exit then ( adr len #bits ) + dup /l / round-up-log2 ( adr len #bits ) + polynomials swap la+ l@ ( adr len polynomial ) + + 3dup 1 1 rot random-fill ( adr len polynomial ) + + >r ( adr len r: polynomial ) + 1 1 2 pick /l / 1- ( adr len data index remain r: polynomial ) + begin ( adr len data index remain r: polynomial ) + r@ random-check ( false | adr len data index remain true r: polynomial ) + while ( adr len data index remain r: polynomial ) + .lfsr-mem-error ( adr len data index remain r: polynomial ) + repeat ( r: polynomial ) + r> drop +; +\ Not truly random - uses LFSR sequences +: random-test ( adr len -- error? ) + " Random address and data test" show-status + + ['] throw-lfsr-error to .lfsr-mem-error + ['] (random-test) catch if + 2drop true + else + false + then +;
\ LICENSE_BEGIN \ Copyright (c) 1997 FirmWorks
Modified: cpu/arm/mmp2/mmuon.fth ============================================================================== --- cpu/arm/mmp2/mmuon.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/mmp2/mmuon.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -25,7 +25,7 @@ : ofw-sections ( -- ) h# 0000.0000 h# c0e over dma-base map-sections \ Cache and write bufferable dma-base h# c02 over dma-size map-sections \ Non-cacheable DMA space - extra-mem-base h# c0e over extra-mem-size map-sections \ Cache and write bufferable + extra-mem-pa h# c0e over /extra-mem map-sections \ Cache and write bufferable fw-pa h# c0e over /fw-ram map-sections \ Cache and write bufferable fb-pa h# c06 over fb-size map-sections \ Write bufferable \ h# d100.0000 h# c0e over h# 0030.0000 map-sections \ Cache and write bufferable (SRAM)
Modified: cpu/arm/olpc/1.75/addrs.fth ============================================================================== --- cpu/arm/olpc/1.75/addrs.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/olpc/1.75/addrs.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -29,8 +29,8 @@ h# 1f00.0000 constant dma-base h# 80.0000 constant dma-size
-h# 1f80.0000 constant extra-mem-base -h# 20.0000 constant extra-mem-size +h# 1f80.0000 constant extra-mem-pa +h# 20.0000 constant /extra-mem
[ifdef] virtual-mode h# f700.0000 constant fw-virt-base
Modified: cpu/arm/olpc/1.75/devices.fth ============================================================================== --- cpu/arm/olpc/1.75/devices.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/olpc/1.75/devices.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -373,7 +373,7 @@ warning !
stand-init: More memory - extra-mem-base extra-mem-size add-memory + extra-mem-pa /extra-mem add-memory ;
\ LICENSE_BEGIN
Modified: cpu/arm/olpc/1.75/probemem.fth ============================================================================== --- cpu/arm/olpc/1.75/probemem.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/olpc/1.75/probemem.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -17,7 +17,6 @@ headers : probe ( -- ) 0 available-ram-size log&release -\ h# 2000.0000 h# 1000.0000 log&release
0 0 encode-bytes ( adr 0 ) physavail ['] make-phys-memlist find-node ( adr len prev 0 ) @@ -25,7 +24,95 @@
\ Claim the memory used by OFW fw-pa /fw-ram 0 claim drop -\ high h# 10.0000 - h# 10.0000 0 claim drop + extra-mem-pa /extra-mem 0 claim drop + + 0 pagesize 0 claim drop \ Vector table +; + +\ The parameters depend on CPU-specific cache parameters +: flush-entire-dcache ( -- ) + \ Flush L1 dcache + + h# 1000 0 do \ Loop over sets - h# 1000 is L1 #sets + 0 0 do \ Loop over ways + i j + clean&flush-d$-entry-way \ Operate on L1 cache + h# 2000.0000 +loop \ h# 2000.0000 depends on L1 #ways + h# 20 +loop \ h# 20 is L1 line size + + h# 10000 0 do \ Loop over sets - h# 10000 is L2 #sets + 0 0 do \ Loop over ways + i j + 2+ clean&flush-d$-entry-way \ Operate on L2 cache (2+) + h# 2000.0000 +loop \ h# 2000.0000 depends on L2 #ways + h# 20 +loop \ h# 20 is L2 line size +; +' flush-entire-dcache to memtest-flush-cache + +0 value p-adr +0 value v-adr + +false value mem-fail? + +: show-line ( adr len -- ) (cr type 3 spaces kill-line ; +' show-line to show-status + +: test-mem ( adr len -- ) \ Test a chunk 'o memory + ." Testing address 0x" over .x ." length 0x" dup .x cr + + 2>r + 2r@ 0 mem-claim to p-adr ( ) ( r: adr len ) +[ifdef] virtual-mode + 2r@ nip 1 mmu-claim to v-adr ( ) ( r: adr len ) + 2r@ v-adr swap h# c00 mmu-map ( ) ( r: adr len ) \ c00 = non-cached + v-adr ( adr ) +[else] + p-adr ( adr ) +[then] + + 2r@ nip memory-test-suite ( status ) ( r: adr len ) + 0<> if true to mem-fail? then + +[ifdef] virtual-mode + v-adr 2r@ nip mmu-unmap ( ) ( r: adr len ) + v-adr 2r@ nip mmu-release ( ) ( r: adr len ) +[then] + p-adr 2r> nip mem-release ( ) + + mem-fail? if ( ) + " !!Failed!!" show-status cr ( ) + else ( ) + " Succeeded" show-status cr ( ) + then ( ) +; + +: selftest ( -- error? ) + + false to mem-fail? + + " available" get-my-property if + ." No available property in memory node" cr + true exit + then ( adr len ) + + begin dup while ( adr len ) + decode-int >r decode-int ( adr len this-len r: this-padr ) + r> swap test-mem ( adr len ) + mem-fail? if ( adr len ) + 2drop true exit ( -- error ) + then ( adr len ) + repeat ( adr len ) + 2drop ( ) + + mem-fail? ;
device-end + +: memtest ( -- ) + true to diag-switch? + 1 begin ( pass# ) + ." Pass " dup .d cr 1+ ( pass# ) + " /memory" test-dev ( pass# ) + key? until ( pass# ) + key drop ( pass# ) + drop ( ) +;
Modified: cpu/arm/olpc/initmmu.fth ============================================================================== --- cpu/arm/olpc/initmmu.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/olpc/initmmu.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -215,8 +215,8 @@ set r3,#0xc02 \ No caching or write buffering bl `map-sections-v=p`
- set r1,`extra-mem-base #` \ Address of additional allocatable memory - set r2,`extra-mem-size #` \ Size of additional allocatable memory + set r1,`extra-mem-pa #` \ Address of additional allocatable memory + set r2,`/extra-mem #` \ Size of additional allocatable memory set r3,#0xc0e \ Write bufferable bl `map-sections-v=p`
Modified: cpu/arm/scc.fth ============================================================================== --- cpu/arm/scc.fth Sat Jun 4 08:48:27 2011 (r2244) +++ cpu/arm/scc.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -119,6 +119,13 @@ code disable-mclk ( -- ) mcr p15,0,r0,cr15,cr4,2 c; code wait-for-interrupt ( -- ) mcr p15,0,r0,cr15,cr8,2 c;
+code cache-level@ ( -- level ) psh tos,sp mrc p15,2,tos,cr0,cr0,0 c; +code cache-level! ( level -- ) mcr p15,2,tos,cr0,cr0,0 pop tos,sp c; +code cache-size-id@ ( -- n ) psh tos,sp mrc p15,1,tos,cr0,cr0,0 c; +code cache-level-id@ ( -- n ) psh tos,sp mrc p15,1,tos,cr0,cr0,1 c; + +code silicon-id@ ( -- id ) psh tos,sp mrc p15,1,tos,cr0,cr0,7 c; + : ttbase ( -- n ) ttbase@ h# 3ff invert and ;
: .control ( -- ) control@ " i..rsb...wcam" show-bits ;
Modified: ofw/fcode/memtest.fth ============================================================================== --- ofw/fcode/memtest.fth Sat Jun 4 08:48:27 2011 (r2244) +++ ofw/fcode/memtest.fth Sat Jun 4 22:25:49 2011 (r2245) @@ -127,6 +127,8 @@ hex
headers +defer memtest-flush-cache ' noop to memtest-flush-cache + defer meml! defer meml@ defer memw! @@ -203,6 +205,7 @@ \ First we write all zeroes to the top and bottom memory locations 0 add-base @ meml! 0 add-top @ meml!
+ memtest-flush-cache \ Now we write all ones to 2 locations: the location whose address \ differs from the bottom address only by the address line under test, \ and the location whose address differs from the top address only by @@ -212,6 +215,7 @@ add-base @ over + ffffffff swap meml! \ store ones at "base + [1 << addr#]" add-top @ over - ffffffff swap meml! \ store ones at "top - [1 << addr#]" ( addr# offset ) + memtest-flush-cache
\ Now we check to see if either of the top or bottom locations got \ clobbered when we wrote the other two locations. This tests for @@ -234,6 +238,8 @@ add-base @ over + 0 swap meml! \ store 0 at location "base + [ 1 << addr#]" add-top @ over - 0 swap meml! \ store 0 at location "top - [ 1 << addr#]"
+ memtest-flush-cache + ffffffff add-base @ mem-test ffffffff add-top @ mem-test ( addr# offset ) @@ -290,6 +296,8 @@ temp-buf w@ over memw! temp-buf wa1+ w@ over wa1+ memw! ( membase )
+ memtest-flush-cache + h# 12345678 over mem-test ( membase )
\ write data in byte size @@ -298,6 +306,7 @@ temp-buf 2 ca+ c@ over 2 ca+ memc! temp-buf 3 ca+ c@ over 3 ca+ memc! ( membase )
+ memtest-flush-cache h# 12345678 over mem-test ( membase ) drop failed @ \ place failed flag on stack @@ -311,12 +320,14 @@ ( membase ) d# 32 0 do \ loop over all 32 data lines 1 i << over meml! ( membase ) + memtest-flush-cache 1 i << over mem-test ( membase ) loop ( membase )
\ Walking zeroes d# 32 0 do \ loop over all 32 data lines 1 i << invert over meml! ( membase ) + memtest-flush-cache 1 i << invert over mem-test ( membase ) /l + loop ( membase )
@@ -330,8 +341,8 @@ failed off \ set failed flag to false
bounds ( memtop membase ) - 2dup ?do h# ffffffff i 2dup meml! mem-test /l +loop \ stuck at 0 test - ?do h# 00000000 i 2dup meml! mem-test /l +loop \ stuck at 1 test + 2dup ?do h# ffffffff i 2dup meml! memtest-flush-cache mem-test /l +loop \ stuck at 0 test + ?do h# 00000000 i 2dup meml! memtest-flush-cache mem-test /l +loop \ stuck at 1 test
failed @ \ put failed flag onto the stack ; @@ -343,6 +354,8 @@
bounds 2dup do i i meml! /l +loop ( memtop membase )
+ memtest-flush-cache + failed off do i i mem-test /l +loop failed @ \ return failed flag on stack @@ -365,6 +378,8 @@ i 2 la+ meml! /l 3 * +loop
+ memtest-flush-cache + failed off ( memtop membase ) do mats-pattern @ @@ -394,7 +409,10 @@ 2dup address=data-test ?suite-failed ( membase memsize ) \ Don't do the mats test, because I'm not convinced that it is useful \ 2dup h# a5a5a5a5 mats-test ?suite-failed ( membase memsize ) - then +[ifdef] random-test + 2dup random-test ?suite-failed ( membase memsize ) +[then] + then ( membase memsize ) 2drop
suite-failed @