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
22 /*
23 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26 #pragma ident "%Z%%M% %I% %E% SMI"
27
28 #include <sys/mdb_modapi.h>
29 #include <sys/types.h>
30 #include <sys/dditypes.h>
31 #include <sys/fcode.h>
32 #include <sys/machcpuvar.h>
33 #include <sys/opl.h>
34 #include <sys/opl_cfg.h>
35
36 static uintptr_t tmptr;
37
38 /*
39 * print hardware descriptor
40 */
41
42 /* Verbosity bits */
43 #define DUMP_HDR 0x00001 /* Header */
44 #define DUMP_SB_STAT 0x00002 /* System Board Status */
45 #define DUMP_DINFO 0x00004 /* Domain Information */
46 #define DUMP_SB_INFO 0x00008 /* System Board Information */
47 #define DUMP_CMU_CHAN 0x00010 /* CPU/Memory Channel */
48 #define DUMP_CHIPS 0x00020 /* Phyiscal CPUs */
49 #define DUMP_MEM 0x00040 /* Memory Information */
50 #define DUMP_PCI_CH 0x00080 /* PCI Channel */
51 #define DUMP_MEM_BANKS 0x00100 /* Memory Banks */
52 #define DUMP_MEM_CHUNKS 0x00200 /* Memory Chunks */
53 #define DUMP_MEM_DIMMS 0x00400 /* Memory DIMMS */
54 #define DUMP_MEM_CS 0x00800 /* Memory CS */
55 #define DUMP_CORES 0x01000 /* CPU Cores Information */
56 #define DUMP_SCS 0x02000 /* SC Information */
57 #define DUMP_MISSING 0x10000 /* Miscellenous Information */
58 #define DUMP_COMP_NAME 0x20000 /* Component Name */
59
60
61 /* A nice mix of most of what you want */
62 #define DUMP_ALL (DUMP_HDR | DUMP_SB_STAT | DUMP_DINFO | \
63 DUMP_SB_INFO | DUMP_CMU_CHAN | DUMP_CHIPS | \
64 DUMP_MEM | DUMP_PCI_CH | DUMP_MEM_BANKS | \
65 DUMP_CORES | DUMP_SCS)
66
67
68 #define DUMP_VERBOSE (DUMP_ALL | DUMP_MEM_CHUNKS | DUMP_MEM_CS)
69 #define DUMP_FULL (DUMP_VERBOSE | DUMP_MISSING | DUMP_COMP_NAME)
70
71
72 #define MIA(stat) ((stat) == HWD_STAT_MISS)
73 #define DONT_BOTHER(stat, v) (MIA(stat) && (v != HWD_STAT_PRESENT))
74
hwd_stat_decode(int stat)75 static char *hwd_stat_decode(int stat)
76 {
77 switch (stat) {
78 case HWD_STAT_UNKNOWN:
79 return ("UNKNOWN");
80 case HWD_STAT_PRESENT:
81 return ("PRESENT");
82 case HWD_STAT_MISS:
83 return ("MISS");
84 case HWD_STAT_MISCONFIG:
85 return ("MISCONFIG");
86 case HWD_STAT_PASS:
87 return ("PASS");
88 case HWD_STAT_FAIL:
89 return ("FAIL_XSCF");
90 case HWD_STAT_FAIL_OBP:
91 return ("FAIL_OBP");
92 case HWD_STAT_FAIL_OS:
93 return ("FAIL_OS");
94 default:
95 return ("?");
96 }
97 }
98
99 static void
dumpmemhwd(hwd_memory_t * memp,int v,int mv)100 dumpmemhwd(hwd_memory_t *memp, int v, int mv)
101 {
102 int i, j;
103
104 mdb_printf("\nMemory:\tstart\t0x%llx\tsize\t0x%llx\tmirror mode %d\n",
105 memp->mem_start_address, memp->mem_size, memp->mem_mirror_mode);
106 mdb_printf("\tdivision mode\t0x%x\tpiece number\t0x%llx",
107 memp->mem_division_mode, memp->mem_piece_number);
108 mdb_printf("\tcs interleave %d\n", memp->mem_cs_interleave);
109
110 /* banks */
111 for (i = 0; i < HWD_BANKS_PER_CMU; i++) {
112 if (DONT_BOTHER(memp->mem_banks[i].bank_status, mv)) {
113 mdb_printf("\tBank %d\tstatus\t0x%x (%s)\n",
114 i, memp->mem_banks[i].bank_status,
115 hwd_stat_decode(memp->mem_banks[i].bank_status));
116 continue;
117 }
118 mdb_printf("\tBank %d\tstatus\t0x%x (%s)\treg addr\t0x%llx\n",
119 i, memp->mem_banks[i].bank_status,
120 hwd_stat_decode(memp->mem_banks[i].bank_status),
121 memp->mem_banks[i].bank_register_address);
122 if (v & DUMP_MEM_BANKS) {
123 mdb_printf("\t\tcs status\t0x%x 0x%x\n",
124 memp->mem_banks[i].bank_cs_status[0],
125 memp->mem_banks[i].bank_cs_status[1]);
126 mdb_printf("\t\tMAC OCD\tDIMM OCDs\n");
127 mdb_printf("\t\t%x\t%x %x %x %x %x %x %x %x\n",
128 memp->mem_banks[i].bank_mac_ocd,
129 memp->mem_banks[i].bank_dimm_ocd[0][0],
130 memp->mem_banks[i].bank_dimm_ocd[0][1],
131 memp->mem_banks[i].bank_dimm_ocd[1][0],
132 memp->mem_banks[i].bank_dimm_ocd[1][1],
133 memp->mem_banks[i].bank_dimm_ocd[2][0],
134 memp->mem_banks[i].bank_dimm_ocd[2][1],
135 memp->mem_banks[i].bank_dimm_ocd[3][0],
136 memp->mem_banks[i].bank_dimm_ocd[3][1]);
137 }
138 }
139 /* chunks */
140 for (i = 0; i < HWD_MAX_MEM_CHUNKS; i++) {
141 if ((memp->mem_chunks[i].chnk_start_address == 0) && (mv != 1))
142 continue;
143 mdb_printf("\tchunk %d\tstart\t0x%llx\tsize\t0x%llx\n",
144 i, memp->mem_chunks[i].chnk_start_address,
145 memp->mem_chunks[i].chnk_size);
146 }
147 /* dimms */
148 for (i = 0; i < HWD_DIMMS_PER_CMU; i++) {
149 if (DONT_BOTHER(memp->mem_dimms[i].dimm_status, mv)) {
150 if (v & DUMP_MEM_DIMMS)
151 mdb_printf("\tDIMM %d\tstatus\t0x%x (%s)\n",
152 i, memp->mem_dimms[i].dimm_status,
153 hwd_stat_decode(
154 memp->mem_dimms[i].dimm_status));
155 continue;
156 }
157 mdb_printf("\tDIMM %d\tstatus\t0x%x (%s)\tcapacity\t0x%llx\n",
158 i, memp->mem_dimms[i].dimm_status,
159 hwd_stat_decode(memp->mem_dimms[i].dimm_status),
160 memp->mem_dimms[i].dimm_capacity);
161 mdb_printf("\t\trank\t%x\tavailable capacity\t0x%llx\n",
162 memp->mem_dimms[i].dimm_rank,
163 memp->mem_dimms[i].dimm_available_capacity);
164 }
165 /* cs */
166 for (i = 0; i < 2; i++) {
167 if (DONT_BOTHER(memp->mem_cs[i].cs_status, mv)) {
168 mdb_printf("\tCS %d:\tstatus\t0x%x (%s)\n",
169 i, memp->mem_cs[i].cs_status,
170 hwd_stat_decode(memp->mem_cs[i].cs_status));
171 continue;
172 }
173 mdb_printf("\tCS %d:\tstatus\t0x%x (%s)\tavailable\t0x%llx\n",
174 i, memp->mem_cs[i].cs_status,
175 hwd_stat_decode(memp->mem_cs[i].cs_status),
176 memp->mem_cs[i].cs_available_capacity);
177 mdb_printf("\t\tno of dimms\t%x\tdimm capacity\t0x%llx\n",
178 memp->mem_cs[i].cs_number_of_dimms,
179 memp->mem_cs[i].cs_dimm_capacity);
180 mdb_printf("\t\tPA <-> MAC conversion\n\t\t");
181 for (j = 0; j < 20; j++)
182 mdb_printf("%02x ", memp->mem_cs[i].cs_pa_mac_table[j]);
183 mdb_printf("\n\t\t");
184 for (j = 20; j < 40; j++)
185 mdb_printf("%02x ", memp->mem_cs[i].cs_pa_mac_table[j]);
186 mdb_printf("\n\t\t");
187 for (j = 40; j < 60; j++)
188 mdb_printf("%02x ", memp->mem_cs[i].cs_pa_mac_table[j]);
189 mdb_printf("\n\t\t");
190 for (j = 60; j < 64; j++)
191 mdb_printf("%02x ", memp->mem_cs[i].cs_pa_mac_table[j]);
192 mdb_printf("\n");
193 }
194 }
195
196 /* ARGSUSED */
197 static void
dumpchiphwd(hwd_cpu_chip_t * chipp,int ch,int v,int mv)198 dumpchiphwd(hwd_cpu_chip_t *chipp, int ch, int v, int mv)
199 {
200 int cp, co;
201 hwd_cpu_t *cpup;
202 hwd_core_t *corep;
203
204 mdb_printf("\nChip %d:\tstatus\t0x%x (%s)\tportid\t%x\n",
205 ch, chipp->chip_status, hwd_stat_decode(chipp->chip_status),
206 chipp->chip_portid);
207
208 if (MIA(chipp->chip_status))
209 return;
210
211 for (co = 0; co < HWD_CORES_PER_CPU_CHIP; co++) {
212 corep = &chipp->chip_cores[co];
213
214 mdb_printf("\tCore %d:\tstatus\t0x%x (%s)\tconfig\t0x%llx\n",
215 co, corep->core_status,
216 hwd_stat_decode(corep->core_status),
217 corep->core_config);
218
219 if (MIA(corep->core_status))
220 continue;
221
222 if (v & DUMP_CORES) {
223 mdb_printf("\t\tfrequency\t0x%llx\tversion\t0x%llx\n",
224 corep->core_frequency, corep->core_version);
225 mdb_printf("\t\t(manuf/impl/mask: %x/%x/%x)\n",
226 corep->core_manufacturer,
227 corep->core_implementation, corep->core_mask);
228 mdb_printf("\t\t\tSize\tLinesize\tAssoc\n");
229 mdb_printf("\t\tL1I$\t%x\t%x\t\t%x\n",
230 corep->core_l1_icache_size,
231 corep->core_l1_icache_line_size,
232 corep->core_l1_icache_associativity);
233 mdb_printf("\t\tL1D$\t%x\t%x\t\t%x\n",
234 corep->core_l1_dcache_size,
235 corep->core_l1_dcache_line_size,
236 corep->core_l1_dcache_associativity);
237 mdb_printf("\t\tL2$\t%x\t%x\t\t%x",
238 corep->core_l2_cache_size,
239 corep->core_l2_cache_line_size,
240 corep->core_l2_cache_associativity);
241 mdb_printf("\tsharing\t%x\n",
242 corep->core_l2_cache_sharing);
243 mdb_printf("\t\tITLB entries\t0x%x\tDTLB entries "
244 "0x%x\n", corep->core_num_itlb_entries,
245 corep->core_num_dtlb_entries);
246 }
247
248 for (cp = 0; cp < HWD_CPUS_PER_CORE; cp++) {
249 cpup = &corep->core_cpus[cp];
250 mdb_printf("\t\tCPU %d:\tstatus\t0x%x (%s)\tcpuid"
251 " = 0x%x\n", cp, cpup->cpu_status,
252 hwd_stat_decode(cpup->cpu_status),
253 cpup->cpu_cpuid);
254 if (v & DUMP_COMP_NAME)
255 mdb_printf("\t\t\tcomponent name:%s\n",
256 cpup->cpu_component_name);
257 }
258 }
259 }
260
261 /* ARGSUSED */
262 static void
dumppcihwd(hwd_pci_ch_t * pcip,int ch,int v,int mv)263 dumppcihwd(hwd_pci_ch_t *pcip, int ch, int v, int mv)
264 {
265 int lf;
266 hwd_leaf_t *leafp;
267
268 mdb_printf("\nPCI CH %d:\tstatus\t0x%x (%s)\n",
269 ch, pcip->pci_status, hwd_stat_decode(pcip->pci_status));
270
271 for (lf = 0; lf < HWD_LEAVES_PER_PCI_CHANNEL; lf++) {
272 leafp = &pcip->pci_leaf[lf];
273
274 if (DONT_BOTHER(leafp->leaf_status, mv)) {
275 mdb_printf("\tleaf %d:\tstatus\t0x%x (%s)\n",
276 lf, leafp->leaf_status,
277 hwd_stat_decode(leafp->leaf_status));
278 continue;
279 }
280 mdb_printf("\tleaf %d:\tstatus\t0x%x (%s)\tportid 0x%x",
281 lf, leafp->leaf_status,
282 hwd_stat_decode(leafp->leaf_status), leafp->leaf_port_id);
283 mdb_printf("\ttype0x%x\n)",
284 leafp->leaf_slot_type);
285 mdb_printf("\t\t\tOffset\t\tSize\n");
286 mdb_printf("\t\tcfgio\t0x%llx\t0x%llx\t\t%x\n",
287 leafp->leaf_cfgio_offset,
288 leafp->leaf_cfgio_size);
289 mdb_printf("\t\tmem32\t0x%llx\t0x%llx\t\t%x\n",
290 leafp->leaf_mem32_offset,
291 leafp->leaf_mem32_size);
292 mdb_printf("\t\tmem64\t0x%llx\t0x%llx\t\t%x\n",
293 leafp->leaf_mem64_offset,
294 leafp->leaf_mem64_size);
295 }
296 }
297
298 /* ARGSUSED */
299 static void
dumpahwd(int bd,int v)300 dumpahwd(int bd, int v)
301 {
302 opl_board_cfg_t boardcfg;
303 hwd_header_t hwd_hdr;
304 hwd_sb_status_t hwd_sb_status;
305 hwd_domain_info_t hwd_dinfo;
306 hwd_sb_t hwd_sb;
307 caddr_t statusp, dinfop, sbp = NULL;
308
309 /* A flag for whether or not to dump stuff that is missing */
310 int mv = 0;
311
312 if (v & DUMP_MISSING)
313 mv = 1;
314
315 bzero(&boardcfg, sizeof (opl_board_cfg_t));
316 bzero(&hwd_hdr, sizeof (hwd_header_t));
317 bzero(&hwd_sb_status, sizeof (hwd_sb_status_t));
318 bzero(&hwd_dinfo, sizeof (hwd_domain_info_t));
319 bzero(&hwd_sb, sizeof (hwd_sb_t));
320
321
322 if (mdb_vread(&boardcfg, sizeof (opl_board_cfg_t),
323 tmptr + (bd * sizeof (opl_board_cfg_t))) == -1) {
324 mdb_warn("failed to read opl_board_cfg at %p",
325 (tmptr + (bd * sizeof (opl_board_cfg_t))));
326 return;
327 }
328
329 if (boardcfg.cfg_hwd == NULL) {
330 mdb_printf("Board %d has no HWD info\n", bd);
331 return;
332 }
333
334 mdb_printf("Board %d:\thwd pointer\t%8llx\n", bd, boardcfg.cfg_hwd);
335
336 /* We always need the header, for offsets */
337 if (mdb_vread(&hwd_hdr, sizeof (hwd_header_t),
338 (uintptr_t)boardcfg.cfg_hwd) == -1) {
339 mdb_warn("failed to read hwd_header_t at %p\n",
340 boardcfg.cfg_hwd);
341 return;
342 }
343
344 /* Figure out the inside pointers, in case we need them... */
345 statusp = (caddr_t)boardcfg.cfg_hwd + hwd_hdr.hdr_sb_status_offset;
346 dinfop = (caddr_t)boardcfg.cfg_hwd + hwd_hdr.hdr_domain_info_offset;
347 sbp = (caddr_t)boardcfg.cfg_hwd + hwd_hdr.hdr_sb_info_offset;
348
349 /* The sb data is what we will surely be dumping */
350 if (mdb_vread(&hwd_sb, sizeof (hwd_sb_t), (uintptr_t)sbp) == -1) {
351 mdb_warn("failed to read hwd_sb_t at %p\n", sbp);
352 return;
353 }
354
355 if (v & DUMP_HDR) {
356 /* Print the interesting stuff from the header */
357 mdb_printf("\t\tversion\t%x.%x\tDID\t%x\tmagic\t0x%x\n\n",
358 hwd_hdr.hdr_version.major, hwd_hdr.hdr_version.minor,
359 hwd_hdr.hdr_domain_id, hwd_hdr.hdr_magic);
360 mdb_printf("\tstatus offset = 0x%x\t(addr=%llx)\n",
361 hwd_hdr.hdr_sb_status_offset, statusp);
362 mdb_printf("\tdomain offset = 0x%x\t(addr=%llx)\n",
363 hwd_hdr.hdr_domain_info_offset, dinfop);
364 mdb_printf("\tboard offset = 0x%x\t(addr=%llx)\n",
365 hwd_hdr.hdr_sb_info_offset, sbp);
366 }
367
368 if (v & DUMP_SB_STAT) {
369 int i;
370 if (mdb_vread(&hwd_sb_status, sizeof (hwd_sb_status_t),
371 (uintptr_t)statusp) == -1) {
372 mdb_warn("failed to read hwd_sb_status_t at %p\n",
373 statusp);
374 return;
375 }
376 mdb_printf("\nSTATUS:\tBoard\tStatus\n");
377 for (i = 0; i < HWD_SBS_PER_DOMAIN; i++) {
378 if (DONT_BOTHER(hwd_sb_status.sb_status[i], mv))
379 continue;
380 mdb_printf("\t%d\t0x%x (%s)\n", i,
381 hwd_sb_status.sb_status[i],
382 hwd_stat_decode(hwd_sb_status.sb_status[i]));
383 }
384 }
385
386 /* Domain Info */
387 if (v & DUMP_DINFO) {
388 if (mdb_vread(&hwd_dinfo, sizeof (hwd_domain_info_t),
389 (uintptr_t)dinfop) == -1) {
390 mdb_warn("failed to read hwd_domain_info_t at %p\n",
391 dinfop);
392 return;
393 }
394 mdb_printf("\nDomain info:\tReset reason\t0x%x",
395 hwd_dinfo.dinf_reset_factor);
396 mdb_printf("\tHost ID 0x%x\n", hwd_dinfo.dinf_host_id);
397 mdb_printf("\tSystem freq\t0x%llx\tStick freq\t0x%llx\n",
398 hwd_dinfo.dinf_system_frequency,
399 hwd_dinfo.dinf_stick_frequency);
400 mdb_printf("\tSCF timeout \t0x%x\tModel info\t%x",
401 hwd_dinfo.dinf_scf_command_timeout,
402 hwd_dinfo.dinf_model_info);
403 if (hwd_dinfo.dinf_dr_status == 0)
404 mdb_printf("\tDR capable\n");
405 else
406 mdb_printf("\tNOT DR capable (%x)\n",
407 hwd_dinfo.dinf_dr_status);
408 mdb_printf("\tMAC address\t%02x.%02x.%02x.%02x.%02x.%02x",
409 hwd_dinfo.dinf_mac_address[0],
410 hwd_dinfo.dinf_mac_address[1],
411 hwd_dinfo.dinf_mac_address[2],
412 hwd_dinfo.dinf_mac_address[3],
413 hwd_dinfo.dinf_mac_address[4],
414 hwd_dinfo.dinf_mac_address[5]);
415 mdb_printf("\tcpu_start_time\t0x%llx\n",
416 hwd_dinfo.dinf_cpu_start_time);
417 mdb_printf("\tcfg policy\t%x\tdiag lvl\t%x\tboot mode\t%x\n",
418 hwd_dinfo.dinf_config_policy, hwd_dinfo.dinf_diag_level,
419 hwd_dinfo.dinf_boot_mode);
420 mdb_printf("\tBanner name\t%s\n",
421 hwd_dinfo.dinf_banner_name);
422 mdb_printf("\tPlatform token\t%s\n",
423 hwd_dinfo.dinf_platform_token);
424 mdb_printf("\tFloating bd bitmap\t%04x\n",
425 hwd_dinfo.dinf_floating_board_bitmap);
426 mdb_printf("\tChassis Serial#\t%s\n",
427 hwd_dinfo.dinf_chassis_sn);
428 mdb_printf("\tBrand Control\t%d\n",
429 hwd_dinfo.dinf_brand_control);
430
431 }
432
433 /* SB info */
434 if (v & DUMP_SB_INFO) {
435 mdb_printf("\nBoard:\tstatus =0x%x (%s)\tmode =0x%x (%s)\
436 \tPSB =0x%x\n", hwd_sb.sb_status,
437 hwd_stat_decode(hwd_sb.sb_status),
438 hwd_sb.sb_mode, (hwd_sb.sb_mode == 0 ? "PSB" : "XSB"),
439 hwd_sb.sb_psb_number);
440 }
441
442 /* CMU Chan info */
443 if (v & DUMP_CMU_CHAN) {
444 hwd_cmu_chan_t *cmup;
445 cmup = &hwd_sb.sb_cmu.cmu_ch;
446
447 mdb_printf("\nCMU CH: status\t0x%x (%s)\tportid=0x%x"
448 " LSB = 0x%x\n",
449 cmup->chan_status, hwd_stat_decode(cmup->chan_status),
450 cmup->chan_portid, ((cmup->chan_portid) >> 4));
451
452 if (v & DUMP_COMP_NAME)
453 mdb_printf("\tcomponent name:%s\n",
454 cmup->chan_component_name);
455
456 /* scf_interface */
457 mdb_printf("\tscf:\tstatus\t0x%x (%s)\n",
458 cmup->chan_scf_interface.scf_status,
459 hwd_stat_decode(cmup->chan_scf_interface.scf_status));
460 if (v & DUMP_COMP_NAME)
461 mdb_printf("\t\tcomponent name:%s\n",
462 cmup->chan_scf_interface.scf_component_name);
463
464 /* serial */
465 mdb_printf("\tserial:\tstatus\t0x%x (%s)\n",
466 cmup->chan_serial.tty_status,
467 hwd_stat_decode(cmup->chan_serial.tty_status));
468 if (v & DUMP_COMP_NAME)
469 mdb_printf("\t\tcomponent name:%s\n",
470 cmup->chan_serial.tty_component_name);
471
472 /* fmem */
473 mdb_printf("\tfmem[0]\tstatus\t0x%x (%s)",
474 cmup->chan_fmem[0].fmem_status,
475 hwd_stat_decode(cmup->chan_fmem[0].fmem_status));
476 mdb_printf("\tused %x\tversion %x.%x.%x\n",
477 cmup->chan_fmem[0].fmem_used,
478 cmup->chan_fmem[0].fmem_version.fver_major,
479 cmup->chan_fmem[0].fmem_version.fver_minor,
480 cmup->chan_fmem[0].fmem_version.fver_local);
481 if (v & DUMP_COMP_NAME)
482 mdb_printf("\t\tcomponent name:%s\n",
483 cmup->chan_fmem[0].fmem_component_name);
484 mdb_printf("\tfmem[1]\tstatus\t0x%x (%s)",
485 cmup->chan_fmem[1].fmem_status,
486 hwd_stat_decode(cmup->chan_fmem[1].fmem_status));
487 mdb_printf("\tused %x\tversion %x.%x.%x\n",
488 cmup->chan_fmem[1].fmem_used,
489 cmup->chan_fmem[1].fmem_version.fver_major,
490 cmup->chan_fmem[1].fmem_version.fver_minor,
491 cmup->chan_fmem[1].fmem_version.fver_local);
492 if (v & DUMP_COMP_NAME)
493 mdb_printf("\t\tcomponent name:%s\n",
494 cmup->chan_fmem[1].fmem_component_name);
495
496 }
497
498 /* CMU SC info */
499 if (v & DUMP_SCS) {
500 hwd_sc_t *scp;
501 int sc;
502
503 for (sc = 0; sc < HWD_SCS_PER_CMU; sc++) {
504
505 scp = &hwd_sb.sb_cmu.cmu_scs[sc];
506
507 if (DONT_BOTHER(scp->sc_status, mv))
508 mdb_printf("\nSC %d:\tstatus\t0x%x (%s)\n",
509 sc, scp->sc_status,
510 hwd_stat_decode(scp->sc_status));
511 else {
512 mdb_printf("\nSC %d:\tstatus\t0x%x (%s)\t",
513 sc, scp->sc_status,
514 hwd_stat_decode(scp->sc_status));
515 mdb_printf("register addr\t0x%llx\n",
516 scp->sc_register_address);
517 }
518 }
519
520 }
521
522 if (v & DUMP_MEM)
523 dumpmemhwd(&hwd_sb.sb_cmu.cmu_memory, v, mv);
524
525 if (v & DUMP_CHIPS) {
526 int ch;
527 for (ch = 0; ch < HWD_CPU_CHIPS_PER_CMU; ch++) {
528 if (MIA(hwd_sb.sb_cmu.cmu_cpu_chips[ch].chip_status)) {
529 mdb_printf("\nChip %d: status\t0x%x (%s)\n",
530 ch,
531 hwd_sb.sb_cmu.cmu_cpu_chips[ch].chip_status,
532 "MISS");
533 continue;
534 }
535 dumpchiphwd(&hwd_sb.sb_cmu.cmu_cpu_chips[ch], ch, v,
536 mv);
537 }
538 }
539
540 if (v & DUMP_PCI_CH) {
541 int ch;
542 for (ch = 0; ch < HWD_CPU_CHIPS_PER_CMU; ch++) {
543 if (MIA(hwd_sb.sb_pci_ch[ch].pci_status)) {
544 mdb_printf("\nPCI CH %d:\tstatus\t0x%x (%s)\n",
545 ch, hwd_sb.sb_pci_ch[ch].pci_status,
546 "MISS");
547 continue;
548 }
549 dumppcihwd(&hwd_sb.sb_pci_ch[ch], ch, v, mv);
550 }
551 }
552 }
553
554 /*
555 * oplhwd dcmd - Print out the per-board HWD, nicely formatted.
556 */
557 /*ARGSUSED*/
558 static int
oplhwd(uintptr_t addr,uint_t flags,int argc,const mdb_arg_t * argv)559 oplhwd(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
560 {
561 int bdi;
562 uint64_t v_mode = DUMP_HDR;
563 uint_t obits = 0;
564 GElf_Sym tmsym;
565 uint64_t bdo;
566
567 /*
568 * Either use the board number, or get an arg for it, or
569 * show all of them.
570 */
571
572 if (flags & DCMD_ADDRSPEC) {
573 bdi = addr;
574 } else {
575 bdi = -1;
576 }
577
578 bdo = bdi;
579 if (mdb_getopts(argc, argv,
580 'a', MDB_OPT_SETBITS, DUMP_FULL, &obits, /* All possible info */
581 'b', MDB_OPT_UINT64, &bdo, /* board number */
582 'd', MDB_OPT_SETBITS, DUMP_DINFO, &obits, /* domain info */
583 's', MDB_OPT_SETBITS, DUMP_SB_STAT, &obits, /* SB status */
584 'i', MDB_OPT_SETBITS, DUMP_SB_INFO, &obits, /* SB info */
585 'c', MDB_OPT_SETBITS, DUMP_CMU_CHAN, &obits, /* CMU chan */
586 'h', MDB_OPT_SETBITS, DUMP_CHIPS, &obits, /* chips */
587 'm', MDB_OPT_SETBITS, DUMP_MEM, &obits, /* memory */
588 'p', MDB_OPT_SETBITS, DUMP_PCI_CH, &obits, /* PCI chans */
589 'k', MDB_OPT_SETBITS, DUMP_MEM_BANKS, &obits, /* banks */
590 'o', MDB_OPT_SETBITS, DUMP_CORES, &obits, /* core details */
591 'r', MDB_OPT_SETBITS, DUMP_SCS, &obits, /* SC info */
592 'C', MDB_OPT_SETBITS, DUMP_COMP_NAME, &obits, /* SC info */
593 'v', MDB_OPT_SETBITS, DUMP_VERBOSE, &obits, /* all of the above */
594 NULL) != argc)
595 return (DCMD_USAGE);
596 bdi = bdo;
597 v_mode |= obits;
598
599 if (mdb_lookup_by_obj("opl_cfg", "opl_boards", &tmsym) == -1) {
600 mdb_warn("unable to reference opl_boards\n");
601 return (DCMD_ERR);
602 }
603
604 tmptr = (uintptr_t)tmsym.st_value;
605 mdb_printf("Board %d:\tboardcfg \t%8llx\n", 0, tmptr);
606
607 if (bdi < 0) {
608 /* get active boards */
609 for (bdi = 0; bdi < OPL_MAX_BOARDS; bdi++)
610 dumpahwd(bdi, v_mode);
611 } else {
612 dumpahwd(bdi, v_mode);
613 }
614 return (DCMD_OK);
615 }
616
617 /*
618 * ::oplhwd help
619 */
620 static void
oplhwd_help(void)621 oplhwd_help(void)
622 {
623 mdb_printf("oplhwd will dump HWD only for a particular board"
624 " on which,");
625 mdb_printf("an earlier DR operation has been executed.\n");
626 mdb_printf("-b NUM \tlist oplhwd entry for a board\n"
627 "-s \t\tlist oplhwd entry with SB status\n"
628 "-d \t\tlist oplhwd entry with Domain info.\n"
629 "-i \t\tlist oplhwd entry with SB info.\n"
630 "-h \t\tlist oplhwd entry with Chips details\n"
631 "-o \t\tlist oplhwd entry with Core details\n"
632 "-m \t\tlist oplhwd entry with Memory info.\n"
633 "-k \t\tlist oplhwd entry with Memory Bank info.\n"
634 "-r \t\tlist oplhwd entry with SC info.\n"
635 "-c \t\tlist oplhwd entry with CMU channels\n"
636 "-p \t\tlist oplhwd entry with PCI channels\n"
637 "-a \t\tlist oplhwd entry with all possible info.\n"
638 "-C \t\tlist oplhwd entry with component names\n"
639 "-v \t\tlist oplhwd entry in verbose mode\n");
640 }
641
642 /*
643 * MDB module linkage information:
644 *
645 * We declare a list of structures describing our dcmds, and a function
646 * named _mdb_init to return a pointer to our module information.
647 */
648
649 static const mdb_dcmd_t dcmds[] = {
650 { "oplhwd", "?[ -b NUM ] [ -sdihomkrcp ] [ -a ] [ -C ] [ -v ]",
651 "dump hardware descriptor for SUNW,SPARC-Enterprise",
652 oplhwd, oplhwd_help },
653 { NULL }
654 };
655
656 static const mdb_modinfo_t modinfo = {
657 MDB_API_VERSION, dcmds, NULL
658 };
659
660 const mdb_modinfo_t *
_mdb_init(void)661 _mdb_init(void)
662 {
663 return (&modinfo);
664 }
665