00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include <agnix/agnix.h>
00015 #include <agnix/init.h>
00016 #include <agnix/memory.h>
00017 #include <agnix/linkage.h>
00018 #include <asm/memtests.h>
00019 #include <agnix/console.h>
00020
00021 #define MOD_NAME "MEMTEST: "
00022
00023 extern struct main_memory_s main_memory;
00024
00025 u32 memaddr_next_1(u32 addr)
00026 {
00027 return addr + 16;
00028 }
00029
00030 u32 memdata_next_1(u32 data)
00031 {
00032 return 0xA5A5A5A5;
00033 }
00034
00035 int memcheck_type_1(u32 addr_check, u32 data_check)
00036 {
00037 __asm__ __volatile (
00038 "movl (%%edi), %%eax\n\t"
00039 "subl %%ebx, %%eax"
00040 :
00041 :"D"(addr_check), "b"(data_check)
00042 );
00043
00044
00045 }
00046
00047 struct memtest_addr_pattern_s memaddr_patterns[MEMTEST_MAX_ADDR_PATTERNS] = {
00048 {
00049 .memtest_addr_pattern_type = MEMTEST_ADDR_PATTERN_ALL,
00050 .next_addr = memaddr_next_1
00051 },
00052 { 0 }
00053 };
00054
00055 struct memtest_data_pattern_s memdata_patterns[MEMTEST_MAX_DATA_PATTERNS] = {
00056 {
00057 .memtest_data_pattern_type = MEMTEST_DATA_PATTERN_BINARY,
00058 .next_data = memdata_next_1
00059 },
00060 { 0 }
00061 };
00062
00063 struct memtest_check_type_s memcheck_types[MEMTEST_MAX_CHECK_TYPES] = {
00064 {
00065 .memtest_check_type = MEMTEST_CHECK_RW,
00066 .check_mem = memcheck_type_1
00067 },
00068 { 0 }
00069 };
00070
00071 int memtests_init(void)
00072 {
00073 printk(MOD_NAME "initializing memory tests\n");
00074
00075 return 0;
00076 }
00077
00078 u32 do_memtest_next_addr(u32 addr_cur, int memaddr_pattern_type)
00079 {
00080 u32 addr_next = addr_cur;
00081 int i;
00082
00083 for (i = 0; i < MEMTEST_MAX_ADDR_PATTERNS; i++) {
00084 if (!memaddr_patterns[i].memtest_addr_pattern_type)
00085 return addr_next;
00086
00087 if (!(memaddr_patterns[i].memtest_addr_pattern_type & memaddr_pattern_type))
00088 continue;
00089
00090 addr_next = memaddr_patterns[i].next_addr(addr_next);
00091 }
00092
00093 return addr_next;
00094 }
00095
00096 u32 do_memtest_next_data(u32 data_cur, int memdata_pattern_type)
00097 {
00098 u32 data_next = data_cur;
00099 int i;
00100
00101 for (i = 0; i < MEMTEST_MAX_DATA_PATTERNS; i++) {
00102 if (!memdata_patterns[i].memtest_data_pattern_type)
00103 return data_next;
00104
00105 if (!(memdata_patterns[i].memtest_data_pattern_type & memdata_pattern_type))
00106 continue;
00107
00108 data_next = memdata_patterns[i].next_data(data_next);
00109 }
00110
00111 return data_next;
00112 }
00113
00114 int do_memtest_checks(u32 addr_check, u32 data_check, int memtest_check_type)
00115 {
00116 int i;
00117 int check_ret;
00118
00119 for (i = 0; i < MEMTEST_MAX_CHECK_TYPES; i++) {
00120 if (!memcheck_types[i].memtest_check_type)
00121 return 0;
00122
00123 if (!(memcheck_types[i].memtest_check_type & memtest_check_type))
00124 continue;
00125
00126 if ((check_ret = memcheck_types[i].check_mem(addr_check, data_check)) < 0)
00127 return check_ret;
00128 }
00129
00130 return 0;
00131 }
00132
00133 int do_memtest_check(u32 addr_start, u32 addr_end, u32 data_start,
00134 int memaddr_pattern_type, int memdata_pattern_type, int memtest_check_type)
00135 {
00136 u32 addr_check_cur = addr_start;
00137 u32 data_check_cur = data_start;
00138
00139 do {
00140
00141 if (addr_check_cur == do_memtest_checks(addr_check_cur, data_check_cur, memtest_check_type) < 0) {
00142 printk(MOD_NAME "check failed at address %08x with data %08x\n", addr_check_cur, data_check_cur);
00143 return -1;
00144 }
00145
00146 __asm__ __volatile (
00147 "movl %%eax, (%%edi)"
00148 :
00149 :"D"(addr_check_cur), "a"(0)
00150 );
00151
00152 addr_check_cur = do_memtest_next_addr(addr_check_cur, memaddr_pattern_type);
00153 data_check_cur = do_memtest_next_data(data_check_cur, memdata_pattern_type);
00154
00155 } while(addr_check_cur < addr_end);
00156
00157 return 0;
00158 }
00159
00160 int do_memtest(u32 addr_start, u32 addr_end, int memaddr_pattern_type, int memdata_pattern_type, int memtest_check_type, int check_rate)
00161 {
00162 u32 addr_cur = addr_start;
00163 u32 data_cur = 0xA5A5A5A5;
00164 u32 addr_last_check = addr_cur;
00165 u32 data_last_check = data_cur;
00166 int check_rate_cur = 0;
00167 int check_ret = 0;
00168 int bar_progress = 0;
00169 int bar_next_progress;
00170 u32 bar_max_progress = (addr_end - addr_start);
00171 int i;
00172
00173 do {
00174
00175 check_rate_cur++;
00176
00177 if (check_rate == check_rate_cur) {
00178 check_rate_cur = 0;
00179 check_ret = do_memtest_check(addr_last_check, addr_cur, data_last_check,
00180 memaddr_pattern_type, memdata_pattern_type, memtest_check_type);
00181
00182 if (check_ret < 0) {
00183 printk(" failed\n");
00184 return check_ret;
00185 }
00186
00187 addr_last_check = addr_cur;
00188 data_last_check = data_cur;
00189
00190 bar_next_progress = ((addr_cur - addr_start) * 10) / bar_max_progress;
00191 if (bar_next_progress != bar_progress) {
00192 for (i = bar_progress; i < bar_next_progress; i++) {
00193 printk(".");
00194 }
00195 bar_progress = bar_next_progress;
00196 }
00197 }
00198
00199 __asm__ __volatile (
00200 "movl %%eax, (%%edi)"
00201 :
00202 :"D"(addr_cur), "a"(data_cur)
00203 );
00204
00205 addr_cur = do_memtest_next_addr(addr_cur, memaddr_pattern_type);
00206 data_cur = do_memtest_next_data(data_cur, memdata_pattern_type);
00207
00208 } while (addr_cur < addr_end);
00209
00210 printk(" ok\n");
00211
00212 return 0;
00213 }
00214
00215 int do_memtests(void)
00216 {
00217 printk(MOD_NAME "upper memory tests....\n");
00218
00219 printk(MOD_NAME "RW test (from 0xc0200000 to 0x%08x) ", 0xc0000000 + (main_memory.mem_size << 10));
00220
00221 do_memtest(0xc0200000, 0xc0000000 + (main_memory.mem_size << 10), MEMTEST_ADDR_PATTERN_ALL,
00222 MEMTEST_DATA_PATTERN_BINARY, MEMTEST_CHECK_RW, 32);
00223
00224 return 0;
00225 }