| 1 | #include <qi.h> |
| 2 | #include <string.h> |
| 3 | |
| 4 | int memory_test_const32(void * start, unsigned int length, u32 value) |
| 5 | { |
| 6 | int errors = 0; |
| 7 | u32 * p = (u32 *)start; |
| 8 | u32 * pend = (u32 *)(start + length); |
| 9 | int count = length >> 2; |
| 10 | |
| 11 | puts("."); |
| 12 | |
| 13 | while (p < pend) |
| 14 | *p++ = value; |
| 15 | |
| 16 | p = (u32 *)start; |
| 17 | count = length >> 2; |
| 18 | |
| 19 | while (count--) |
| 20 | if (*p++ != value) { |
| 21 | puts("*** Error "); |
| 22 | print32((long)p - 4); |
| 23 | errors++; |
| 24 | } |
| 25 | |
| 26 | return errors; |
| 27 | } |
| 28 | |
| 29 | int memory_test_ads(void * start, unsigned int length, u32 mask) |
| 30 | { |
| 31 | int errors = 0; |
| 32 | u32 * p = (u32 *)start; |
| 33 | u32 * pend = (u32 *)(start + length); |
| 34 | |
| 35 | puts("."); |
| 36 | |
| 37 | while (p < pend) |
| 38 | if ((u32)p & mask) |
| 39 | *p++ = 0xffffffff; |
| 40 | else |
| 41 | *p++ = 0; |
| 42 | |
| 43 | p = (u32 *)start; |
| 44 | |
| 45 | while (p < pend) { |
| 46 | if ((u32)p & mask) { |
| 47 | if (*p++ != 0xffffffff) { |
| 48 | puts("*** Error "); |
| 49 | print32((long)p - 4); |
| 50 | errors++; |
| 51 | } |
| 52 | } else { |
| 53 | if (*p++) { |
| 54 | puts("*** Error "); |
| 55 | print32((long)p - 4); |
| 56 | errors++; |
| 57 | } |
| 58 | } |
| 59 | } |
| 60 | return errors; |
| 61 | } |
| 62 | |
| 63 | int memory_test_walking1(void * start, unsigned int length) |
| 64 | { |
| 65 | int errors = 0; |
| 66 | u32 value = 1; |
| 67 | |
| 68 | while (value) { |
| 69 | errors += memory_test_const32(start, length, value); |
| 70 | value <<= 1; |
| 71 | } |
| 72 | |
| 73 | return errors; |
| 74 | } |
| 75 | |
| 76 | /* negative runs == run forever */ |
| 77 | |
| 78 | void __memory_test(void * start, unsigned int length) |
| 79 | { |
| 80 | int errors = 0; |
| 81 | int series = 0; |
| 82 | int mask; |
| 83 | |
| 84 | puts("\nMemory Testing 0x"); |
| 85 | print32((u32)start); |
| 86 | puts(" length "); |
| 87 | printdec(length >> 20); |
| 88 | puts(" MB\n"); |
| 89 | |
| 90 | while (1) { |
| 91 | puts(" Test series "); |
| 92 | printdec(series + 1); |
| 93 | puts(" "); |
| 94 | |
| 95 | /* these are looking at data issues, they flood the whole |
| 96 | * array with the same data |
| 97 | */ |
| 98 | |
| 99 | errors += memory_test_const32(start, length, 0x55555555); |
| 100 | errors += memory_test_const32(start, length, 0xaaaaaaaa); |
| 101 | errors += memory_test_const32(start, length, 0x55aa55aa); |
| 102 | errors += memory_test_const32(start, length, 0xaa55aa55); |
| 103 | errors += memory_test_const32(start, length, 0x00ff00ff); |
| 104 | errors += memory_test_const32(start, length, 0xff00ff00); |
| 105 | errors += memory_test_walking1(start, length); |
| 106 | |
| 107 | /* this is looking at addressing issues, it floods only |
| 108 | * addresses meeting a walking mask with 0xffffffff (the rest |
| 109 | * is zeroed), and makes sure all the bits are only seen where |
| 110 | * they were placed |
| 111 | */ |
| 112 | |
| 113 | mask = 1; |
| 114 | while (! (length & mask)) { |
| 115 | errors += memory_test_ads(start, length, mask); |
| 116 | mask = mask << 1; |
| 117 | } |
| 118 | |
| 119 | puts(" Total errors: "); |
| 120 | printdec(errors); |
| 121 | puts("\n"); |
| 122 | |
| 123 | series++; |
| 124 | } |
| 125 | } |
| 126 | |
| 127 | |
| 128 | void memory_test(void * start, unsigned int length) |
| 129 | { |
| 130 | /* it's a small steppingstone stack from start.S */ |
| 131 | extern int _ss_stack; |
| 132 | |
| 133 | /* |
| 134 | * we won't be coming back from this, so just force our local stack to |
| 135 | * steppingstone out of the way of main memory test action |
| 136 | * |
| 137 | * then jump into the actual test |
| 138 | */ |
| 139 | asm volatile ( |
| 140 | "mov sp, %0\n" |
| 141 | : : "r" (&_ss_stack) |
| 142 | ); |
| 143 | |
| 144 | __memory_test(start, length); |
| 145 | } |
| 146 | |