16429Svs195195 /*
26429Svs195195 * CDDL HEADER START
36429Svs195195 *
46429Svs195195 * The contents of this file are subject to the terms of the
56429Svs195195 * Common Development and Distribution License (the "License").
66429Svs195195 * You may not use this file except in compliance with the License.
76429Svs195195 *
86429Svs195195 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96429Svs195195 * or http://www.opensolaris.org/os/licensing.
106429Svs195195 * See the License for the specific language governing permissions
116429Svs195195 * and limitations under the License.
126429Svs195195 *
136429Svs195195 * When distributing Covered Code, include this CDDL HEADER in each
146429Svs195195 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156429Svs195195 * If applicable, add the following below this CDDL HEADER, with the
166429Svs195195 * fields enclosed by brackets "[]" replaced with your own identifying
176429Svs195195 * information: Portions Copyright [yyyy] [name of copyright owner]
186429Svs195195 *
196429Svs195195 * CDDL HEADER END
206429Svs195195 */
216429Svs195195
226429Svs195195 /*
236491Sia112686 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
246429Svs195195 * Use is subject to license terms.
256429Svs195195 */
266429Svs195195
276429Svs195195 #pragma ident "%Z%%M% %I% %E% SMI"
286429Svs195195
296429Svs195195 #include <stdio.h>
306429Svs195195 #include <unistd.h>
316429Svs195195 #include <fps_ereport.h>
326429Svs195195
336429Svs195195 extern void iflush(void);
346429Svs195195 extern int g1(unsigned long, unsigned long *, unsigned long *);
356429Svs195195 extern int g2(unsigned long, unsigned long *, unsigned long *);
366429Svs195195 extern int g3(unsigned long, unsigned long *, unsigned long *);
376429Svs195195 extern int g4(unsigned long, unsigned long *, unsigned long *);
386429Svs195195 extern int l0(unsigned long, unsigned long *, unsigned long *);
396429Svs195195 extern int l1(unsigned long, unsigned long *, unsigned long *);
406429Svs195195 extern int l2(unsigned long, unsigned long *, unsigned long *);
416429Svs195195 extern int l3(unsigned long, unsigned long *, unsigned long *);
426429Svs195195 extern int l4(unsigned long, unsigned long *, unsigned long *);
436429Svs195195 extern int l5(unsigned long, unsigned long *, unsigned long *);
446429Svs195195 extern int l6(unsigned long, unsigned long *, unsigned long *);
456429Svs195195 extern int l7(unsigned long, unsigned long *, unsigned long *);
466429Svs195195 extern int o0(unsigned long, unsigned long *, unsigned long *);
476429Svs195195 extern int o1(unsigned long, unsigned long *, unsigned long *);
486429Svs195195 extern int o2(unsigned long, unsigned long *, unsigned long *);
496429Svs195195 extern int o3(unsigned long, unsigned long *, unsigned long *);
506429Svs195195 extern int o4(unsigned long, unsigned long *, unsigned long *);
516429Svs195195 extern int o5(unsigned long, unsigned long *, unsigned long *);
526429Svs195195 extern int o7(unsigned long, unsigned long *, unsigned long *);
536429Svs195195
546429Svs195195 typedef struct {
556429Svs195195 char *reg;
566429Svs195195 int (*test_func) (unsigned long, unsigned long *,\
576429Svs195195 unsigned long *);
586429Svs195195 }reg_info;
596429Svs195195
606429Svs195195 /* Registers to be tested and the functions to be used for it. */
616429Svs195195 static
626429Svs195195 reg_info reg_func[] =
636429Svs195195 {
646429Svs195195 {"g1", g1},
656429Svs195195 {"g2", g2},
666429Svs195195 {"g3", g3},
676429Svs195195 {"g4", g4},
686429Svs195195 {"l0", l0},
696429Svs195195 {"l1", l1},
706429Svs195195 {"l2", l2},
716429Svs195195 {"l3", l3},
726429Svs195195 {"l4", l4},
736429Svs195195 {"l5", l5},
746429Svs195195 {"l6", l6},
756429Svs195195 {"l7", l7},
766429Svs195195 {"o0", o0},
776429Svs195195 {"o1", o1},
786429Svs195195 {"o2", o2},
796429Svs195195 {"o3", o3},
806429Svs195195 {"o4", o4},
816429Svs195195 {"o5", o5},
826429Svs195195 /* %o6 is not tested as it is the %sp */
836429Svs195195 {"o7", o7}
846429Svs195195 };
856429Svs195195
866429Svs195195 #define N_REGS (sizeof (reg_func)/sizeof (*reg_func))
876429Svs195195
886429Svs195195 /*
896429Svs195195 * cheetah_sdc_test(int limit, int unit, struct fps_test_ereport *report)
906429Svs195195 * tests for silent data corruption first unearthed in a 750 Mhz Cheetah
916429Svs195195 * (Toshiba). Returns if successful or not. If an error, relevant data
926429Svs195195 * is stored in report. The test calls an assembly routine with
936429Svs195195 * different target registers but essentially the same code sequence
946429Svs195195 */
956429Svs195195 int
cheetah_sdc_test(int limit,struct fps_test_ereport * report)966429Svs195195 cheetah_sdc_test(int limit, struct fps_test_ereport *report)
976429Svs195195 {
986429Svs195195 char err_data[MAX_INFO_SIZE];
996429Svs195195 int iter;
1006429Svs195195 int regs;
1016429Svs195195 int rval;
1026429Svs195195 uint64_t expect;
1036429Svs195195 uint64_t observe;
1046429Svs195195 unsigned long tmp1 = 0;
1056429Svs195195 unsigned long tmp2 = 0;
1066429Svs195195
1076429Svs195195 unsigned long pattern = 0xDEADDEADDEADDEAD;
1086429Svs195195
1096429Svs195195 for (regs = 0; regs < N_REGS; regs++) {
1106429Svs195195 for (iter = 0; iter < limit; iter++) {
1116429Svs195195 iflush();
1126429Svs195195 rval = reg_func[regs].test_func(pattern, &tmp1, &tmp2);
1136429Svs195195
1146429Svs195195 if (rval != 0) {
115*7186Skk158166 (void) snprintf(err_data, sizeof (err_data),
1166429Svs195195 "Test:%d, reg:%s", iter,
1176429Svs195195 reg_func[regs].reg);
1186429Svs195195 expect = (uint64_t)0;
1196429Svs195195 observe = (uint64_t)rval;
1206429Svs195195 setup_fps_test_struct(IS_EREPORT_INFO,
1216429Svs195195 report, 6357, &observe,
1226429Svs195195 &expect, 1, 1, err_data);
1236429Svs195195
1246429Svs195195 return (-1);
1256429Svs195195 }
1266429Svs195195 }
1276429Svs195195 }
1286429Svs195195
1296429Svs195195 return (0);
1306429Svs195195 }
131