1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 *
21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
22 * Use is subject to license terms.
23 */
24
25 #include <mdb/mdb_modapi.h>
26 #include <amd_opteron/ao.h>
27
28 #define ALLBITS (u_longlong_t)-1
29
30 static const mdb_bitmask_t ao_nbcfg_bits[] = {
31 { "SyncOnDramAdrParErrEn", ALLBITS, AMD_NB_CFG_SYNCONDRAMADRPARERREN },
32 { "NbMcaToMstCpuEn", ALLBITS, AMD_NB_CFG_NBMCATOMSTCPUEN },
33 { "ReservedBit26", ALLBITS, 0x4000000 },
34 { "DisPciCfgCpuErrRsp", ALLBITS, AMD_NB_CFG_DISPCICFGCPUERRRSP },
35 { "IoRdDatErrEn", ALLBITS, AMD_NB_CFG_IORDDATERREN },
36 { "ChipKillEccEn", ALLBITS, AMD_NB_CFG_CHIPKILLECCEN },
37 { "EccEn", ALLBITS, AMD_NB_CFG_ECCEN },
38 { "SyncOnAnyErrEn", ALLBITS, AMD_NB_CFG_SYNCONANYERREN },
39 { "SyncOnWdogEn", ALLBITS, AMD_NB_CFG_SYNCONWDOGEN },
40 { "GenCrcErrByte1", ALLBITS, AMD_NB_CFG_GENCRCERRBYTE1 },
41 { "GenCrcErrByte0", ALLBITS, AMD_NB_CFG_GENCRCERRBYTE0 },
42 /* LdtLinkSel handled separately */
43 /* WdogTmrBaseSel handled separately */
44 /* WdogTmrCntSel handled separately */
45 /* WdogTmrDis handled separately */
46 { "IoErrDis", ALLBITS, AMD_NB_CFG_IOERRDIS },
47 { "CpuErrDis", ALLBITS, AMD_NB_CFG_CPUERRDIS },
48 { "IoMstAbortDis", ALLBITS, AMD_NB_CFG_IOMSTABORTDIS },
49 { "SyncPktPropDis", ALLBITS, AMD_NB_CFG_SYNCPKTPROPDIS },
50 { "SyncPktGenDis", ALLBITS, AMD_NB_CFG_SYNCPKTGENDIS },
51 { "SyncOnUcEccEn", ALLBITS, AMD_NB_CFG_SYNCONUCECCEN },
52 { "CpuRdDatErrEn", ALLBITS, AMD_NB_CFG_CPURDDATERREN }
53 };
54
55 /*ARGSUSED*/
56 static int
ao_nbcfg_describe(uintptr_t val,uint_t flags,int argc,const mdb_arg_t * argv)57 ao_nbcfg_describe(uintptr_t val, uint_t flags, int argc, const mdb_arg_t *argv)
58 {
59 const mdb_bitmask_t *bm;
60 uintptr_t field;
61 int nbits, i;
62
63 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
64 return (DCMD_USAGE);
65
66 for (nbits = 0, bm = ao_nbcfg_bits, i = 0;
67 i < sizeof (ao_nbcfg_bits) / sizeof (mdb_bitmask_t); i++, bm++) {
68 if (!(val & bm->bm_bits))
69 continue;
70
71 mdb_printf("\t0x%08x %s\n", bm->bm_bits, bm->bm_name);
72
73 val &= ~bm->bm_bits;
74 nbits++;
75 }
76
77 if ((field = (val & AMD_NB_CFG_LDTLINKSEL_MASK)) != 0) {
78 mdb_printf("\tLdtLinkSel = %d", field >>
79 AMD_NB_CFG_LDTLINKSEL_SHIFT);
80 }
81
82 if (val & AMD_NB_CFG_WDOGTMRDIS) {
83 mdb_printf("\t0x%08x %s\n", AMD_NB_CFG_WDOGTMRDIS,
84 "WdogTmrDis");
85 } else {
86 static const uint_t wdogcounts[] = {
87 4095, 2047, 1023, 511, 255, 127, 63, 31
88 };
89
90 uintptr_t cntfld = (val & AMD_NB_CFG_WDOGTMRCNTSEL_MASK);
91 uintptr_t basefld = (val & AMD_NB_CFG_WDOGTMRBASESEL_MASK);
92 uintptr_t count;
93 int valid = 1;
94 const char *units;
95
96 if (cntfld < sizeof (wdogcounts) / sizeof (uint_t))
97 count = wdogcounts[cntfld];
98 else
99 valid = 0;
100
101 switch (basefld) {
102 case AMD_NB_CFG_WDOGTMRBASESEL_1MS:
103 units = "ms";
104 break;
105 case AMD_NB_CFG_WDOGTMRBASESEL_1US:
106 units = "us";
107 break;
108 case AMD_NB_CFG_WDOGTMRBASESEL_5NS:
109 count *= 5;
110 units = "ns";
111 break;
112 default:
113 units = " (unknown units)";
114 break;
115 }
116
117 if (valid) {
118 mdb_printf("\tWatchdog timeout: %u%s\n", count,
119 units);
120 } else {
121 mdb_printf("\tInvalid Watchdog: Count %u, Base %u\n",
122 cntfld, basefld);
123 }
124 }
125
126 return (DCMD_OK);
127 }
128
129 static const char *ao_scrub_rate[] = {
130 "Do not scrub", /* 0b00000 */
131 "40.0 nanosec", /* 0b00001 */
132 "80.0 nanosec", /* 0b00010 */
133 "160.0 nanosec", /* 0b00011 */
134 "320.0 nanosec", /* 0b00100 */
135 "640.0 nanosec", /* 0b00101 */
136 "1.28 microsec", /* 0b00110 */
137 "2.56 microsec", /* 0b00111 */
138 "5.12 microsec", /* 0b01000 */
139 "10.2 microsec", /* 0b01001 */
140 "20.5 microsec", /* 0b01010 */
141 "41.0 microsec", /* 0b01011 */
142 "81.9 microsec", /* 0b01100 */
143 "163.8 microsec", /* 0b01101 */
144 "327.7 microsec", /* 0b01110 */
145 "655.4 microsec", /* 0b01111 */
146 "1.31 millsec", /* 0b10000 */
147 "2.62 millsec", /* 0b10001 */
148 "5.24 millsec", /* 0b10010 */
149 "10.49 millsec", /* 0b10011 */
150 "20.97 millsec", /* 0b10100 */
151 "42.00 millsec", /* 0b10101 */
152 "84.00 millsec", /* 0b10110 */
153 };
154
155 #define SCRUBCODE(val, low) ((val) >> low & 0x1f)
156
157 #define SCRUBSTR(val, low) \
158 (SCRUBCODE(val, low) < sizeof (ao_scrub_rate) / sizeof (char *) ? \
159 ao_scrub_rate[SCRUBCODE(val, low)] : "reserved value!")
160
161 /*ARGSUSED*/
162 static int
ao_scrubctl_describe(uintptr_t val,uint_t flags,int argc,const mdb_arg_t * argv)163 ao_scrubctl_describe(uintptr_t val, uint_t flags, int argc,
164 const mdb_arg_t *argv)
165 {
166 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
167 return (DCMD_USAGE);
168
169 mdb_printf("\tDcacheScrub: %s\n\t L2Scrub: %s\n\t DramScrub: %s\n",
170 SCRUBSTR(val, 16), SCRUBSTR(val, 8), SCRUBSTR(val, 0));
171
172 return (DCMD_OK);
173 }
174
175 /*ARGSUSED*/
176 static int
ao_sparectl_describe(uintptr_t val,uint_t flags,int argc,const mdb_arg_t * argv)177 ao_sparectl_describe(uintptr_t val, uint_t flags, int argc,
178 const mdb_arg_t *argv)
179 {
180 const char *itypes[] = {
181 "No Interrupt", /* 0b00 */
182 "Reserved", /* 0b01 */
183 "SMI", /* 0b10 */
184 "Reserved", /* 0b11 */
185 };
186
187 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
188 return (DCMD_USAGE);
189
190 mdb_printf(
191 "\t EccErrInt: %s\n"
192 "\tSwapDoneInt: %s\n"
193 "\t BadDramCs: %d\n"
194 "\t SwapDone: %s\n"
195 "\t SwapEn: %s\n",
196 itypes[val >> 14 & 0x3],
197 itypes[val >> 12 & 0x3],
198 val >> 4 & 0x7,
199 val & 0x2 ? "Yes" : "No",
200 val & 0x1 ? "Yes" : "No");
201
202 return (DCMD_OK);
203 }
204
205 static const char *ao_mcactl_dc[] = {
206 "ECCI (Single-bit ECC Data Errors)",
207 "ECCM (Multi-bit ECC Data Errors)",
208 "DECC (Data Array ECC Errors)",
209 "DMTP (Main Tag Array Parity Errors)",
210 "DSTP (Snoop Tag Array Parity Errors)",
211 "L1TP (L1 TLB Parity Errors)",
212 "L2TP (L2 TLB Parity Errors)",
213 };
214
215 static const char *ao_mcactl_ic[] = {
216 "ECCI (Single-bit ECC data errors)",
217 "ECCM (Multi-bit ECC data errors)",
218 "IDP (Data array parity errors)",
219 "IMTP (Main tag array parity errors)",
220 "ISTP (Snoop tag array parity errors)",
221 "L1TP (L1 TLB Parity Errors)",
222 "L2TP (L2 TLB Parity Errors)",
223 NULL, /* reserved */
224 NULL, /* reserved */
225 "RDDE (Read Data Errors)",
226 };
227
228 static const char *ao_mcactl_bu[] = {
229 "S_RDE_HP (System read data hardware prefetch)",
230 "S_RDE_TLB (System read data TLB reload)",
231 "S_RDE_ALL (All system read data)",
232 "S_ECC1_TLB (System data 1-bit ECC TLB reload)",
233 "S_ECC1_HP (System data 1-bit ECC hardware prefetch)",
234 "S_ECCM_TLB (System data multi-bit ECC TLB reload)",
235 "S_ECCM_HP (System data multi-bit ECC hardware prefetch)",
236 "L2T_PAR_ICDC (L2 tag array parity IC or DC fetch)",
237 "L2T_PAR_TLB (L2 tag array parity TLB reload)",
238 "L2T_PAR_SNP (L2 tag array parity snoop)",
239 "L2T_PAR_CPB (L2 tag array parity copyback)",
240 "L2T_PAR_SCR (L2 tag array parity scrub)",
241 "L2D_ECC1_TLB (L2 data array 1-bit ECC TLB reload)",
242 "L2D_ECC1_SNP (L2 data array 1-bit ECC snoop)",
243 "L2D_ECC1_CPB (L2 data array 1-bit ECC copyback)",
244 "L2D_ECCM_TLB (L2 data array multi-bit ECC TLB reload)",
245 "L2D_ECCM_SNP (L2 data array multi-bit ECC snoop)",
246 "L2D_ECCM_CPB (L2 data array multi-bit ECC copyback)",
247 "L2T_ECC1_SCR (L2 tag array 1-bit ECC Scrub)",
248 "L2T_ECCM_SCR (L2 tag array multi-bit ECC Scrub)",
249 };
250
251 static const char *ao_mcactl_ls[] = {
252 "S_RDE_L (Read Data Errors on Load)",
253 "S_RDE_S (Read Data Errors on Store)",
254 };
255
256 static const char *ao_mcactl_nb[] = {
257 "CorrEccEn (Correctable ECC Error Reporting Enable)",
258 "UnCorrEccEn (Uncorrectable ECC Error Reporting Enable)",
259 "CrcErr0En (HT Link 0 CRC Error Reporting Enable)",
260 "CrcErr1En (HT Link 1 CRC Error Reporting Enable)",
261 "CrcErr2En (HT Link 2 CRC Error Reporting Enable)",
262 "SyncPkt0En (HT Link 0 Sync Packet Error Reporting Enable)",
263 "SyncPkt1En (HT Link 1 Sync Packet Error Reporting Enable)",
264 "SyncPkt2En (HT Link 2 Sync Packet Error Reporting Enable)",
265 "MstrAbrtEn (Master Abort Error Reporting Enable)",
266 "TgtAbrtEn (Target Abort Error Reporting Enable)",
267 "GartTblWkEn (GART Table Walk Error Reporting Enable)",
268 "AtomicRMWEn (Atomic Read-Modify-Write Error Reporting Enable)",
269 "WchDogTmrEn (Watchdog Timer Error Reporting Enable)",
270 NULL, /* reserved */
271 NULL, /* reserved */
272 NULL, /* reserved */
273 NULL, /* reserved */
274 NULL, /* reserved */
275 "DramParEn (DRAM Parity Error Reporting enable)",
276 };
277
278 static const struct ao_mcactl {
279 const char *bank_name;
280 const char **bank_ctlbits;
281 int bank_tblsz;
282 } ao_mcactls[] = {
283 { "dc", &ao_mcactl_dc[0], sizeof (ao_mcactl_dc) / sizeof (char *) },
284 { "ic", &ao_mcactl_ic[0], sizeof (ao_mcactl_ic) / sizeof (char *) },
285 { "bu", &ao_mcactl_bu[0], sizeof (ao_mcactl_bu) / sizeof (char *) },
286 { "ls", &ao_mcactl_ls[0], sizeof (ao_mcactl_ls) / sizeof (char *) },
287 { "nb", &ao_mcactl_nb[0], sizeof (ao_mcactl_nb) / sizeof (char *) }
288 };
289
290 #define AO_MCI_CTL 0x0
291 #define AO_MCI_MASK 0x1
292
293 static int
ao_mci_ctlmask_common(uintptr_t val,uint_t flags,int argc,const mdb_arg_t * argv,int which)294 ao_mci_ctlmask_common(uintptr_t val, uint_t flags, int argc,
295 const mdb_arg_t *argv, int which)
296 {
297 uint64_t bank;
298 const char *bankname = NULL;
299 int i;
300
301 if (argc != 2 || !(flags & DCMD_ADDRSPEC))
302 return (DCMD_USAGE);
303
304 if (mdb_getopts(argc, argv,
305 't', MDB_OPT_STR, &bankname, NULL) != 2)
306 return (DCMD_USAGE);
307
308 for (i = 0; i < AMD_MCA_BANK_COUNT; i++) {
309 if (strncmp(bankname, ao_mcactls[i].bank_name,
310 2) == 0) {
311 bank = i;
312 break;
313 }
314 }
315
316 if (i == AMD_MCA_BANK_COUNT) {
317 mdb_warn("Valid bank names: dc, ic, bu, ls, nb\n");
318 return (DCMD_ERR);
319 }
320
321 mdb_printf("Reporting %s for %s:\n", which == AO_MCI_CTL ? "enables" :
322 "masks", ao_mcactls[bank].bank_name);
323 mdb_printf("%3s %4s %s\n", "Bit", "Set?", "Description");
324
325 for (i = 0; i < 63; i++) {
326 int set = val & 0x1ULL << i;
327 int inrange = i < ao_mcactls[bank].bank_tblsz;
328 const char *desc = ao_mcactls[bank].bank_ctlbits[i];
329
330 if (inrange) {
331 int known = desc != NULL;
332
333 mdb_printf("%2d %4s ", i, set ? "Yes" : "- ");
334 if (known)
335 mdb_printf("%s\n", desc);
336 else
337 mdb_printf("reserved%s\n",
338 set ? " - but set!" : "");
339 } else if (set) {
340 mdb_printf("%2d %4s Reserved - but set!\n",
341 i, "Yes");
342 }
343 }
344
345 return (DCMD_OK);
346 }
347
348 /*ARGSUSED3*/
349 static int
ao_mci_ctl(uintptr_t val,uint_t flags,int argc,const mdb_arg_t * argv)350 ao_mci_ctl(uintptr_t val, uint_t flags, int argc, const mdb_arg_t *argv)
351 {
352 return (ao_mci_ctlmask_common(val, flags, argc, argv, AO_MCI_CTL));
353 }
354
355 /*ARGSUSED3*/
356 static int
ao_mci_mask(uintptr_t val,uint_t flags,int argc,const mdb_arg_t * argv)357 ao_mci_mask(uintptr_t val, uint_t flags, int argc, const mdb_arg_t *argv)
358 {
359 return (ao_mci_ctlmask_common(val, flags, argc, argv, AO_MCI_MASK));
360 }
361
362 static const mdb_dcmd_t dcmds[] = {
363 { "ao_nbcfg", ":", "decode Northbridge config bits",
364 ao_nbcfg_describe },
365 { "ao_scrubctl", ":", "decode Scrub Control Register",
366 ao_scrubctl_describe },
367 { "ao_sparectl", ":", "decode Online Spare Control Register",
368 ao_sparectl_describe },
369 { "ao_mci_ctl", ": -t <dc|ic|bu|ls|nb>",
370 "decode MCi_CTL", ao_mci_ctl },
371 { "ao_mci_mask", ": -t <dc|ic|bu|ls|nb>",
372 "decode MCi_MASK", ao_mci_mask },
373 { NULL }
374 };
375
376 static const mdb_walker_t walkers[] = {
377 { NULL }
378 };
379
380 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
381
382 const mdb_modinfo_t *
_mdb_init(void)383 _mdb_init(void)
384 {
385 return (&modinfo);
386 }
387