blob: a063579d641152c68ebbf9f41746c2af89a881b1 [file] [log] [blame]
Martin Roth9b1b3352016-02-24 12:27:06 -08001/* error.c - MemTest-86 Version 4.1
2 *
3 * Released under version 2 of the Gnu Public License.
4 * By Chris Brady
5 */
6#include "stddef.h"
7#include "stdint.h"
8#include "test.h"
9#include "config.h"
10#include "cpuid.h"
11#include "smp.h"
12#include "dmi.h"
13#include "controller.h"
14
15extern int dmi_err_cnts[MAX_DMI_MEMDEVS];
16extern int beepmode;
17extern short dmi_initialized;
18extern struct cpu_ident cpu_id;
19extern struct barrier_s *barr;
20extern int test_ticks, nticks;
21extern struct tseq tseq[];
22extern volatile int test;
23void poll_errors();
24extern int num_cpus;
25
26static void update_err_counts(void);
27static void print_err_counts(void);
Martin Rothf7b770a2016-03-27 21:06:05 -060028static void common_err(ulong *adr, ulong good, ulong bad, ulong xor, int type);
Martin Roth9b1b3352016-02-24 12:27:06 -080029static int syn, chan, len=1;
30
31/*
32 * Display data error message. Don't display duplicate errors.
33 */
34void error(ulong *adr, ulong good, ulong bad)
35{
Martin Roth9b1b3352016-02-24 12:27:06 -080036 ulong xor;
37
Martin Roth9b1b3352016-02-24 12:27:06 -080038 xor = good ^ bad;
39
40#ifdef USB_WAR
41 /* Skip any errrors that appear to be due to the BIOS using location
42 * 0x4e0 for USB keyboard support. This often happens with Intel
Ben Gardner90f7d112016-03-15 15:25:22 -050043 * 810, 815 and 820 chipsets. It is possible that we will skip
Martin Roth9b1b3352016-02-24 12:27:06 -080044 * a real error but the odds are very low.
45 */
46 if ((ulong)adr == 0x4e0 || (ulong)adr == 0x410) {
47 return;
48 }
49#endif
50
51 /* A sporadic bug exists in test #6, with SMP enabled, that
52 * reports false positives on < 65K-0.5MB range. I was
53 * not able to solve this. After investigations, it seems
Martin Roth4dcd13d2016-02-24 13:53:07 -080054 * related to a BIOS issue similiar to the one solved by
Martin Roth9b1b3352016-02-24 12:27:06 -080055 * USB_WAR, but for MP Table.
56 */
Martin Roth4dcd13d2016-02-24 13:53:07 -080057 /* Solved
58 if (test == 6 && (ulong)adr <= 0x07FFFF && num_cpus > 1)
Martin Roth9b1b3352016-02-24 12:27:06 -080059 {
60 cprint(6,78,"-"); // Debug
61 return;
62 }
63 */
Martin Roth4dcd13d2016-02-24 13:53:07 -080064
Ben Gardnerd23ce492016-03-30 14:59:47 -050065 spin_lock(&barr->mutex);
Martin Roth9b1b3352016-02-24 12:27:06 -080066 common_err(adr, good, bad, xor, 0);
67 spin_unlock(&barr->mutex);
68}
69
70
71
72/*
73 * Display address error message.
74 * Since this is strictly an address test, trying to create BadRAM
75 * patterns does not make sense. Just report the error.
76 */
77void ad_err1(ulong *adr1, ulong *mask, ulong bad, ulong good)
78{
79 spin_lock(&barr->mutex);
80 common_err(adr1, good, bad, (ulong)mask, 1);
81 spin_unlock(&barr->mutex);
82}
83
84/*
85 * Display address error message.
86 * Since this type of address error can also report data errors go
87 * ahead and generate BadRAM patterns.
88 */
89void ad_err2(ulong *adr, ulong bad)
90{
91 spin_lock(&barr->mutex);
92 common_err(adr, (ulong)adr, bad, ((ulong)adr) ^ bad, 0);
93 spin_unlock(&barr->mutex);
94}
95
96static void update_err_counts(void)
97{
Ben Gardner90f7d112016-03-15 15:25:22 -050098 if (beepmode) {
Martin Roth9b1b3352016-02-24 12:27:06 -080099 beep(600);
100 beep(1000);
101 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800102
Martin Roth9b1b3352016-02-24 12:27:06 -0800103 if (v->pass && v->ecount == 0) {
104 cprint(LINE_MSG, COL_MSG,
Ben Gardner90f7d112016-03-15 15:25:22 -0500105 " ");
Martin Roth9b1b3352016-02-24 12:27:06 -0800106 }
107 ++(v->ecount);
108 tseq[test].errors++;
Martin Roth9b1b3352016-02-24 12:27:06 -0800109}
110
111static void print_err_counts(void)
112{
113 int i;
114 char *pp;
115
116 if ((v->ecount > 4096) && (v->ecount % 256 != 0)) return;
117
118 dprint(LINE_INFO, 72, v->ecount, 6, 0);
119/*
120 dprint(LINE_INFO, 56, v->ecc_ecount, 6, 0);
121*/
122
123 /* Paint the error messages on the screen red to provide a vivid */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800124 /* indicator that an error has occured */
Martin Roth9b1b3352016-02-24 12:27:06 -0800125 if ((v->printmode == PRINTMODE_ADDRESSES ||
Ben Gardner90f7d112016-03-15 15:25:22 -0500126 v->printmode == PRINTMODE_PATTERNS) &&
127 v->msg_line < 24) {
128 for (i=0, pp=(char *)((SCREEN_ADR+v->msg_line*160+1));
129 i<76; i++, pp+=2) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800130 *pp = 0x47;
131 }
132 }
133}
134
135/*
136 * Print an individual error
137 */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800138void common_err( ulong *adr, ulong good, ulong bad, ulong xor, int type)
Martin Roth9b1b3352016-02-24 12:27:06 -0800139{
140 int i, j, n, x, flag=0;
141 ulong page, offset;
142 int patnchg;
143 ulong mb;
144
145 update_err_counts();
146
Ben Gardner90f7d112016-03-15 15:25:22 -0500147 switch (v->printmode) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800148 case PRINTMODE_SUMMARY:
149 /* Don't do anything for a parity error. */
150 if (type == 3) {
151 return;
152 }
153
154 /* Address error */
155 if (type == 1) {
156 xor = good ^ bad;
157 }
158
159 /* Ecc correctable errors */
160 if (type == 2) {
161 /* the bad value is the corrected flag */
162 if (bad) {
163 v->erri.cor_err++;
164 }
165 page = (ulong)adr;
166 offset = good;
167 } else {
168 page = page_of(adr);
169 offset = (ulong)adr & 0xFFF;
170 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800171
Martin Roth9b1b3352016-02-24 12:27:06 -0800172 /* Calc upper and lower error addresses */
173 if (v->erri.low_addr.page > page) {
174 v->erri.low_addr.page = page;
175 v->erri.low_addr.offset = offset;
176 flag++;
177 } else if (v->erri.low_addr.page == page &&
Ben Gardner90f7d112016-03-15 15:25:22 -0500178 v->erri.low_addr.offset > offset) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800179 v->erri.low_addr.offset = offset;
180 v->erri.high_addr.offset = offset;
181 flag++;
182 } else if (v->erri.high_addr.page < page) {
183 v->erri.high_addr.page = page;
184 flag++;
185 }
186 if (v->erri.high_addr.page == page &&
Ben Gardner90f7d112016-03-15 15:25:22 -0500187 v->erri.high_addr.offset < offset) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800188 v->erri.high_addr.offset = offset;
189 flag++;
190 }
191
192 /* Calc bits in error */
193 for (i=0, n=0; i<32; i++) {
194 if (xor>>i & 1) {
195 n++;
196 }
197 }
198 v->erri.tbits += n;
199 if (n > v->erri.max_bits) {
200 v->erri.max_bits = n;
201 flag++;
202 }
203 if (n < v->erri.min_bits) {
204 v->erri.min_bits = n;
205 flag++;
206 }
207 if (v->erri.ebits ^ xor) {
208 flag++;
209 }
210 v->erri.ebits |= xor;
211
Ben Gardner90f7d112016-03-15 15:25:22 -0500212 /* Calc max contig errors */
Martin Roth9b1b3352016-02-24 12:27:06 -0800213 len = 1;
214 if ((ulong)adr == (ulong)v->erri.eadr+4 ||
Ben Gardner90f7d112016-03-15 15:25:22 -0500215 (ulong)adr == (ulong)v->erri.eadr-4) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800216 len++;
217 }
218 if (len > v->erri.maxl) {
219 v->erri.maxl = len;
220 flag++;
221 }
222 v->erri.eadr = (ulong)adr;
223
224 if (v->erri.hdr_flag == 0) {
225 clear_scroll();
226 cprint(LINE_HEADER+0, 1, "Error Confidence Value:");
227 cprint(LINE_HEADER+1, 1, " Lowest Error Address:");
228 cprint(LINE_HEADER+2, 1, " Highest Error Address:");
229 cprint(LINE_HEADER+3, 1, " Bits in Error Mask:");
230 cprint(LINE_HEADER+4, 1, " Bits in Error - Total:");
231 cprint(LINE_HEADER+4, 29, "Min: Max: Avg:");
232 cprint(LINE_HEADER+5, 1, " Max Contiguous Errors:");
233 x = 24;
234 if (dmi_initialized) {
Ben Gardner90f7d112016-03-15 15:25:22 -0500235 for (i=0; i < MAX_DMI_MEMDEVS; ) {
236 n = LINE_HEADER+7;
237 for (j=0; j<4; j++) {
238 if (dmi_err_cnts[i] >= 0) {
239 dprint(n, x, i, 2, 0);
240 cprint(n, x+2, ": 0");
241 }
242 i++;
243 n++;
244 }
245 x += 10;
Martin Roth9b1b3352016-02-24 12:27:06 -0800246 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800247 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800248
Martin Roth9b1b3352016-02-24 12:27:06 -0800249 cprint(LINE_HEADER+0, 64, "Test Errors");
250 v->erri.hdr_flag++;
251 }
252 if (flag) {
Ben Gardner90f7d112016-03-15 15:25:22 -0500253 /* Calc bits in error */
254 for (i=0, n=0; i<32; i++) {
255 if (v->erri.ebits>>i & 1) {
256 n++;
Martin Roth9b1b3352016-02-24 12:27:06 -0800257 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800258 }
Ben Gardner90f7d112016-03-15 15:25:22 -0500259 page = v->erri.low_addr.page;
260 offset = v->erri.low_addr.offset;
261 mb = page >> 8;
262 hprint(LINE_HEADER+1, 25, page);
263 hprint2(LINE_HEADER+1, 33, offset, 3);
264 cprint(LINE_HEADER+1, 36, " - . MB");
265 dprint(LINE_HEADER+1, 39, mb, 5, 0);
266 dprint(LINE_HEADER+1, 45, ((page & 0xF)*10)/16, 1, 0);
267 page = v->erri.high_addr.page;
268 offset = v->erri.high_addr.offset;
269 mb = page >> 8;
270 hprint(LINE_HEADER+2, 25, page);
271 hprint2(LINE_HEADER+2, 33, offset, 3);
272 cprint(LINE_HEADER+2, 36, " - . MB");
273 dprint(LINE_HEADER+2, 39, mb, 5, 0);
274 dprint(LINE_HEADER+2, 45, ((page & 0xF)*10)/16, 1, 0);
275 hprint(LINE_HEADER+3, 25, v->erri.ebits);
276 dprint(LINE_HEADER+4, 25, n, 2, 1);
277 dprint(LINE_HEADER+4, 34, v->erri.min_bits, 2, 1);
278 dprint(LINE_HEADER+4, 42, v->erri.max_bits, 2, 1);
279 dprint(LINE_HEADER+4, 50, v->erri.tbits/v->ecount, 2, 1);
280 dprint(LINE_HEADER+5, 25, v->erri.maxl, 7, 1);
281 x = 28;
282 for (i=0; i < MAX_DMI_MEMDEVS; ) {
283 n = LINE_HEADER+7;
284 for (j=0; j<4; j++) {
285 if (dmi_err_cnts[i] > 0) {
286 dprint (n, x, dmi_err_cnts[i], 7, 1);
287 }
288 i++;
289 n++;
290 }
291 x += 10;
292 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800293
Ben Gardner90f7d112016-03-15 15:25:22 -0500294 for (i=0; tseq[i].msg != NULL; i++) {
295 dprint(LINE_HEADER+1+i, 66, i, 2, 0);
296 dprint(LINE_HEADER+1+i, 68, tseq[i].errors, 8, 0);
297 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800298 }
299 if (v->erri.cor_err) {
Ben Gardner90f7d112016-03-15 15:25:22 -0500300 dprint(LINE_HEADER+6, 25, v->erri.cor_err, 8, 1);
Martin Roth9b1b3352016-02-24 12:27:06 -0800301 }
302 break;
303
304 case PRINTMODE_ADDRESSES:
305 /* Don't display duplicate errors */
306 if ((ulong)adr == (ulong)v->erri.eadr &&
Ben Gardner90f7d112016-03-15 15:25:22 -0500307 xor == v->erri.exor) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800308 return;
309 }
310 if (v->erri.hdr_flag == 0) {
311 clear_scroll();
312 cprint(LINE_HEADER, 0,
313"Tst Pass Failing Address Good Bad Err-Bits Count CPU");
314 cprint(LINE_HEADER+1, 0,
315"--- ---- ----------------------- -------- -------- -------- ----- ----");
316 v->erri.hdr_flag++;
317 }
318 /* Check for keyboard input */
319 check_input();
320 scroll();
Martin Roth4dcd13d2016-02-24 13:53:07 -0800321
Ben Gardner90f7d112016-03-15 15:25:22 -0500322 if (type == 2 || type == 3) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800323 page = (ulong)adr;
324 offset = good;
325 } else {
326 page = page_of(adr);
327 offset = ((unsigned long)adr) & 0xFFF;
328 }
329 mb = page >> 8;
330 dprint(v->msg_line, 0, test+1, 3, 0);
331 dprint(v->msg_line, 4, v->pass, 5, 0);
332 hprint(v->msg_line, 11, page);
333 hprint2(v->msg_line, 19, offset, 3);
334 cprint(v->msg_line, 22, " - . MB");
335 dprint(v->msg_line, 25, mb, 5, 0);
336 dprint(v->msg_line, 31, ((page & 0xF)*10)/16, 1, 0);
337
338 if (type == 3) {
339 /* ECC error */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800340 cprint(v->msg_line, 36,
Ben Gardner90f7d112016-03-15 15:25:22 -0500341 bad ? "corrected " : "uncorrected ");
Martin Roth9b1b3352016-02-24 12:27:06 -0800342 hprint2(v->msg_line, 60, syn, 4);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800343 cprint(v->msg_line, 68, "ECC");
Martin Roth9b1b3352016-02-24 12:27:06 -0800344 dprint(v->msg_line, 74, chan, 2, 0);
345 } else if (type == 2) {
346 cprint(v->msg_line, 36, "Parity error detected ");
347 } else {
348 hprint(v->msg_line, 36, good);
349 hprint(v->msg_line, 46, bad);
350 hprint(v->msg_line, 56, xor);
351 dprint(v->msg_line, 66, v->ecount, 5, 0);
Ben Gardner90f7d112016-03-15 15:25:22 -0500352 dprint(v->msg_line, 74, smp_my_cpu_num(), 2, 1);
Martin Roth9b1b3352016-02-24 12:27:06 -0800353 v->erri.exor = xor;
354 }
355 v->erri.eadr = (ulong)adr;
356 print_err_counts();
357 break;
358
359 case PRINTMODE_PATTERNS:
360 if (v->erri.hdr_flag == 0) {
361 clear_scroll();
362 v->erri.hdr_flag++;
363 }
364 /* Do not do badram patterns from test 0 or 5 */
365 if (test == 0 || test == 5) {
366 return;
367 }
368 /* Only do patterns for data errors */
Ben Gardner90f7d112016-03-15 15:25:22 -0500369 if (type != 0) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800370 return;
371 }
372 /* Process the address in the pattern administration */
373 patnchg=insertaddress ((ulong) adr);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800374 if (patnchg) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800375 printpatn();
376 }
377 break;
378
379 case PRINTMODE_NONE:
380 if (v->erri.hdr_flag == 0) {
381 clear_scroll();
382 v->erri.hdr_flag++;
383 }
384 break;
385 }
386}
387
388/*
389 * Print an ecc error
390 */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800391void print_ecc_err(unsigned long page, unsigned long offset,
Ben Gardner90f7d112016-03-15 15:25:22 -0500392 int corrected, unsigned short syndrome, int channel)
Martin Roth9b1b3352016-02-24 12:27:06 -0800393{
394 ++(v->ecc_ecount);
395 syn = syndrome;
396 chan = channel;
397 common_err((ulong *)page, offset, corrected, 0, 2);
398}
399
400#ifdef PARITY_MEM
401/*
402 * Print a parity error message
403 */
Martin Roth4dcd13d2016-02-24 13:53:07 -0800404void parity_err( unsigned long edi, unsigned long esi)
Martin Roth9b1b3352016-02-24 12:27:06 -0800405{
406 unsigned long addr;
407
408 if (test == 5) {
409 addr = esi;
410 } else {
411 addr = edi;
412 }
413 common_err((ulong *)addr, addr & 0xFFF, 0, 0, 3);
414}
415#endif
416
417/*
418 * Print the pattern array as a LILO boot option addressing BadRAM support.
419 */
420void printpatn (void)
421{
Ben Gardner90f7d112016-03-15 15:25:22 -0500422 int idx=0;
423 int x;
Martin Roth9b1b3352016-02-24 12:27:06 -0800424
425 /* Check for keyboard input */
426 check_input();
427
Ben Gardner90f7d112016-03-15 15:25:22 -0500428 if (v->numpatn == 0)
429 return;
Martin Roth9b1b3352016-02-24 12:27:06 -0800430
Ben Gardner90f7d112016-03-15 15:25:22 -0500431 scroll();
Martin Roth9b1b3352016-02-24 12:27:06 -0800432
Ben Gardner90f7d112016-03-15 15:25:22 -0500433 cprint (v->msg_line, 0, "badram=");
434 x=7;
Martin Roth9b1b3352016-02-24 12:27:06 -0800435
Ben Gardner90f7d112016-03-15 15:25:22 -0500436 for (idx = 0; idx < v->numpatn; idx++) {
437 if (x > 80-22) {
438 scroll();
439 x=7;
440 }
441 cprint (v->msg_line, x, "0x");
442 hprint (v->msg_line, x+2, v->patn[idx].adr );
443 cprint (v->msg_line, x+10, ",0x");
444 hprint (v->msg_line, x+13, v->patn[idx].mask);
445 if (idx+1 < v->numpatn)
446 cprint (v->msg_line, x+21, ",");
447 x+=22;
448 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800449}
Martin Roth4dcd13d2016-02-24 13:53:07 -0800450
Martin Roth9b1b3352016-02-24 12:27:06 -0800451/*
452 * Show progress by displaying elapsed time and update bar graphs
453 */
454short spin_idx[MAX_CPUS];
Ben Gardner90f7d112016-03-15 15:25:22 -0500455char spin[4] = {'|', '/', '-', '\\'};
Martin Roth9b1b3352016-02-24 12:27:06 -0800456
457void do_tick(int me)
458{
459 int i, j, pct;
460 ulong h, l, n, t;
461 extern int mstr_cpu;
462
463 if (++spin_idx[me] > 3) {
464 spin_idx[me] = 0;
465 }
466 cplace(8, me+7, spin[spin_idx[me]]);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800467
468
Martin Roth9b1b3352016-02-24 12:27:06 -0800469 /* Check for keyboard input */
470 if (me == mstr_cpu) {
471 check_input();
472 }
473 /* A barrier here holds the other CPUs until the configuration
474 * changes are done */
475 s_barrier();
476
477 /* Only the first selected CPU does the update */
478 if (me != mstr_cpu) {
479 return;
480 }
481
482 /* FIXME only print serial error messages from the tick handler */
483 if (v->ecount) {
484 print_err_counts();
485 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800486
Martin Roth9b1b3352016-02-24 12:27:06 -0800487 nticks++;
488 v->total_ticks++;
489
490 if (test_ticks) {
491 pct = 100*nticks/test_ticks;
492 if (pct > 100) {
493 pct = 100;
494 }
495 } else {
496 pct = 0;
497 }
498 dprint(2, COL_MID+4, pct, 3, 0);
499 i = (BAR_SIZE * pct) / 100;
500 while (i > v->tptr) {
501 if (v->tptr >= BAR_SIZE) {
502 break;
503 }
504 cprint(2, COL_MID+9+v->tptr, "#");
505 v->tptr++;
506 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800507
Martin Roth9b1b3352016-02-24 12:27:06 -0800508 if (v->pass_ticks) {
509 pct = 100*v->total_ticks/v->pass_ticks;
510 if (pct > 100) {
511 pct = 100;
512 }
513 } else {
514 pct = 0;
Ben Gardner90f7d112016-03-15 15:25:22 -0500515 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800516 dprint(1, COL_MID+4, pct, 3, 0);
517 i = (BAR_SIZE * pct) / 100;
518 while (i > v->pptr) {
519 if (v->pptr >= BAR_SIZE) {
520 break;
521 }
522 cprint(1, COL_MID+9+v->pptr, "#");
523 v->pptr++;
524 }
525
526 if (v->ecount && v->printmode == PRINTMODE_SUMMARY) {
527 /* Compute confidence score */
528 pct = 0;
529
530 /* If there are no errors within 1mb of start - end addresses */
531 h = v->pmap[v->msegs - 1].end - 0x100;
532 if (v->erri.low_addr.page > 0x100 &&
Ben Gardner90f7d112016-03-15 15:25:22 -0500533 v->erri.high_addr.page < h) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800534 pct += 8;
535 }
536
537 /* Errors for only some tests */
538 if (v->pass) {
539 for (i=0, n=0; tseq[i].msg != NULL; i++) {
540 if (tseq[i].errors == 0) {
541 n++;
542 }
543 }
544 pct += n*3;
545 } else {
546 for (i=0, n=0; i<test; i++) {
547 if (tseq[i].errors == 0) {
548 n++;
549 }
550 }
551 pct += n*2;
Martin Roth9b1b3352016-02-24 12:27:06 -0800552 }
553
554 /* Only some bits in error */
555 n = 0;
556 if (v->erri.ebits & 0xf) n++;
557 if (v->erri.ebits & 0xf0) n++;
558 if (v->erri.ebits & 0xf00) n++;
559 if (v->erri.ebits & 0xf000) n++;
560 if (v->erri.ebits & 0xf0000) n++;
561 if (v->erri.ebits & 0xf00000) n++;
562 if (v->erri.ebits & 0xf000000) n++;
563 if (v->erri.ebits & 0xf0000000) n++;
564 pct += (8-n)*2;
565
566 /* Adjust the score */
567 pct = pct*100/22;
568/*
569 if (pct > 100) {
570 pct = 100;
571 }
572*/
573 dprint(LINE_HEADER+0, 25, pct, 3, 1);
574 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800575
Martin Roth9b1b3352016-02-24 12:27:06 -0800576
577 /* We can't do the elapsed time unless the rdtsc instruction
578 * is supported
579 */
580 if (cpu_id.fid.bits.rdtsc) {
Ben Gardner90f7d112016-03-15 15:25:22 -0500581 asm __volatile__ (
582 "rdtsc" : "=a" (l), "=d" (h));
Martin Roth9b1b3352016-02-24 12:27:06 -0800583 asm __volatile__ (
584 "subl %2,%0\n\t"
585 "sbbl %3,%1"
Ben Gardner90f7d112016-03-15 15:25:22 -0500586 : "=a" (l), "=d" (h)
587 : "g" (v->startl), "g" (v->starth),
588 "0" (l), "1" (h));
Martin Roth9b1b3352016-02-24 12:27:06 -0800589 t = h * ((unsigned)0xffffffff / v->clks_msec) / 1000;
590 t += (l / v->clks_msec) / 1000;
591 i = t % 60;
592 j = i % 10;
Martin Roth4dcd13d2016-02-24 13:53:07 -0800593
Ben Gardner90f7d112016-03-15 15:25:22 -0500594 if (j != v->each_sec) {
Martin Roth9b1b3352016-02-24 12:27:06 -0800595 dprint(LINE_TIME, COL_TIME+9, i % 10, 1, 0);
596 dprint(LINE_TIME, COL_TIME+8, i / 10, 1, 0);
597 t /= 60;
598 i = t % 60;
599 dprint(LINE_TIME, COL_TIME+6, i % 10, 1, 0);
600 dprint(LINE_TIME, COL_TIME+5, i / 10, 1, 0);
601 t /= 60;
602 dprint(LINE_TIME, COL_TIME, t, 4, 0);
Martin Roth4dcd13d2016-02-24 13:53:07 -0800603
Ben Gardner90f7d112016-03-15 15:25:22 -0500604 if (v->check_temp > 0 && !(v->fail_safe & 4)) {
605 coretemp();
606 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800607 v->each_sec = j;
Martin Roth9b1b3352016-02-24 12:27:06 -0800608 }
Martin Roth9b1b3352016-02-24 12:27:06 -0800609 }
Martin Roth4dcd13d2016-02-24 13:53:07 -0800610
Martin Roth9b1b3352016-02-24 12:27:06 -0800611
612
613 /* Poll for ECC errors */
614/*
615 poll_errors();
616*/
617}