Print this page
5083 avoid undefined order of operations in assignments
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c
+++ new/usr/src/cmd/mdb/intel/modules/generic_cpu/gcpu.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
24 24 */
25 25
26 26 #include <mdb/mdb_modapi.h>
27 27 #include <generic_cpu/gcpu.h>
28 28 #include <sys/cpu_module_impl.h>
29 29 #include <sys/cpu_module_ms_impl.h>
30 30
31 31 typedef struct cmi_hdl_impl {
32 32 enum cmi_hdl_class cmih_class; /* Handle nature */
33 33 struct cmi_hdl_ops *cmih_ops; /* Operations vector */
34 34 uint_t cmih_chipid; /* Chipid of cpu resource */
35 35 uint_t cmih_procnodeid; /* Nodeid of cpu resource */
36 36 uint_t cmih_coreid; /* Core within die */
37 37 uint_t cmih_strandid; /* Thread within core */
38 38 uint_t cmih_procnodes_per_pkg; /* Nodes in a processor */
39 39 boolean_t cmih_mstrand; /* cores are multithreaded */
40 40 volatile uint32_t *cmih_refcntp; /* Reference count pointer */
41 41 uint64_t cmih_msrsrc; /* MSR data source flags */
42 42 void *cmih_hdlpriv; /* cmi_hw.c private data */
43 43 void *cmih_spec; /* cmi_hdl_{set,get}_specific */
44 44 void *cmih_cmi; /* cpu mod control structure */
45 45 void *cmih_cmidata; /* cpu mod private data */
46 46 const struct cmi_mc_ops *cmih_mcops; /* Memory-controller ops */
47 47 void *cmih_mcdata; /* Memory-controller data */
48 48 uint64_t cmih_flags;
49 49 uint16_t cmih_smbiosid; /* SMBIOS Type 4 struct ID */
50 50 uint_t cmih_smb_chipid; /* smbios chipid */
51 51 nvlist_t *cmih_smb_bboard; /* smbios bboard */
52 52 } cmi_hdl_impl_t;
53 53
54 54 typedef struct cmi_hdl_ent {
55 55 volatile uint32_t cmae_refcnt;
56 56 cmi_hdl_impl_t *cmae_hdlp;
57 57 } cmi_hdl_ent_t;
58 58
59 59 typedef struct cmi {
60 60 struct cmi *cmi_next;
61 61 struct cmi *cmi_prev;
62 62 const cmi_ops_t *cmi_ops;
63 63 struct modctl *cmi_modp;
64 64 uint_t cmi_refcnt;
65 65 } cmi_t;
66 66
67 67 typedef struct cms {
68 68 struct cms *cms_next;
69 69 struct cms *cms_prev;
70 70 const cms_ops_t *cms_ops;
71 71 struct modctl *cms_modp;
72 72 uint_t cms_refcnt;
73 73 } cms_t;
74 74
75 75 struct cms_ctl {
76 76 cms_t *cs_cms;
77 77 void *cs_cmsdata;
78 78 };
79 79
80 80 #define CMI_MAX_CHIPID_NBITS 6 /* max chipid of 63 */
81 81
82 82 #define CMI_MAX_CHIPID ((1 << (CMI_MAX_CHIPID_NBITS)) - 1)
83 83 #define CMI_MAX_CORES_PER_CHIP(cbits) (1 << (cbits))
84 84 #define CMI_MAX_COREID(cbits) ((1 << (cbits)) - 1)
85 85 #define CMI_MAX_STRANDS_PER_CORE(sbits) (1 << (sbits))
86 86 #define CMI_MAX_STRANDID(sbits) ((1 << (sbits)) - 1)
87 87 #define CMI_MAX_STRANDS_PER_CHIP(cbits, sbits) \
88 88 (CMI_MAX_CORES_PER_CHIP(cbits) * CMI_MAX_STRANDS_PER_CORE(sbits))
89 89
90 90 #define CMI_CHIPID_ARR_SZ (1 << CMI_MAX_CHIPID_NBITS)
91 91
92 92 struct cmih_walk_state {
93 93 int chipid, coreid, strandid; /* currently visited cpu */
94 94 cmi_hdl_ent_t *chip_tab[CMI_CHIPID_ARR_SZ];
95 95 uint_t core_nbits;
96 96 uint_t strand_nbits;
97 97 };
98 98
99 99 /*
100 100 * Advance the <chipid,coreid,strandid> tuple to the next strand entry
101 101 * Return true upon sucessful result. Otherwise return false if already reach
102 102 * the highest strand.
103 103 */
104 104 static boolean_t
105 105 cmih_ent_next(struct cmih_walk_state *wsp)
106 106 {
107 107 uint_t carry = 0;
108 108
109 109 /* Check for end of the table */
110 110 if (wsp->chipid >= CMI_MAX_CHIPID &&
111 111 wsp->coreid >= CMI_MAX_COREID(wsp->core_nbits) &&
112 112 wsp->strandid >= CMI_MAX_STRANDID(wsp->strand_nbits))
113 113 return (B_FALSE);
114 114
115 115 /* increment the strand id */
116 116 wsp->strandid++;
117 117 carry = wsp->strandid >> wsp->strand_nbits;
118 118 wsp->strandid = wsp->strandid & CMI_MAX_STRANDID(wsp->strand_nbits);
119 119 if (carry == 0)
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
120 120 return (B_TRUE);
121 121
122 122 /* increment the core id */
123 123 wsp->coreid++;
124 124 carry = wsp->coreid >> wsp->core_nbits;
125 125 wsp->coreid = wsp->coreid & CMI_MAX_COREID(wsp->core_nbits);
126 126 if (carry == 0)
127 127 return (B_TRUE);
128 128
129 129 /* increment the chip id */
130 - wsp->chipid = ++wsp->chipid & (CMI_MAX_CHIPID);
130 + wsp->chipid = (wsp->chipid + 1) & (CMI_MAX_CHIPID);
131 131
132 132 return (B_TRUE);
133 133 }
134 134
135 135 /*
136 136 * Lookup for the hdl entry of a given <chip,core,strand> tuple
137 137 */
138 138 static cmi_hdl_ent_t *
139 139 cmih_ent_lookup(struct cmih_walk_state *wsp)
140 140 {
141 141 if (wsp == NULL || wsp->chip_tab[wsp->chipid] == NULL)
142 142 return (NULL); /* chip is not present */
143 143
144 144 return (wsp->chip_tab[wsp->chipid] +
145 145 (((wsp->coreid & CMI_MAX_COREID(wsp->core_nbits)) <<
146 146 wsp->strand_nbits) |
147 147 ((wsp->strandid) & CMI_MAX_STRANDID(wsp->strand_nbits))));
148 148 }
149 149
150 150 /* forward decls */
151 151 static void
152 152 cmih_walk_fini(mdb_walk_state_t *wsp);
153 153
154 154 static int
155 155 cmih_walk_init(mdb_walk_state_t *wsp)
156 156 {
157 157 int i;
158 158 ssize_t sz;
159 159 struct cmih_walk_state *awsp;
160 160 void *pg;
161 161 cmi_hdl_ent_t *ent;
162 162
163 163 if (wsp->walk_addr != NULL) {
164 164 mdb_warn("cmihdl is a global walker\n");
165 165 return (WALK_ERR);
166 166 }
167 167
168 168 wsp->walk_data = awsp =
169 169 mdb_zalloc(sizeof (struct cmih_walk_state), UM_SLEEP);
170 170
171 171 /* read the number of core bits and strand bits */
172 172 if (mdb_readvar(&awsp->core_nbits, "cmi_core_nbits") == -1) {
173 173 mdb_warn("read of cmi_core_nbits failed");
174 174 mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
175 175 wsp->walk_data = NULL;
176 176 return (WALK_ERR);
177 177 }
178 178 if (mdb_readvar(&awsp->strand_nbits, "cmi_strand_nbits") == -1) {
179 179 mdb_warn("read of cmi_strand_nbits failed");
180 180 mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
181 181 wsp->walk_data = NULL;
182 182 return (WALK_ERR);
183 183 }
184 184
185 185 /* table of chipid entries */
186 186 if ((sz = mdb_readvar(&awsp->chip_tab, "cmi_chip_tab")) == -1) {
187 187 mdb_warn("read of cmi_chip_tab failed");
188 188 mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
189 189 wsp->walk_data = NULL;
190 190 return (WALK_ERR);
191 191 } else if (sz < sizeof (awsp->chip_tab)) {
192 192 mdb_warn("Unexpected cmi_chip_tab size (exp=%ld, actual=%ld)",
193 193 sizeof (awsp->chip_tab), sz);
194 194 mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
195 195 wsp->walk_data = NULL;
196 196 return (WALK_ERR);
197 197 }
198 198
199 199 /* read the per-chip table that contains all strands of the chip */
200 200 sz = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits, awsp->strand_nbits) *
201 201 sizeof (cmi_hdl_ent_t);
202 202 for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
203 203 if (awsp->chip_tab[i] == NULL)
204 204 continue; /* this chip(i) is not present */
205 205 pg = mdb_alloc(sz, UM_SLEEP);
206 206 if (mdb_vread(pg, sz, (uintptr_t)awsp->chip_tab[i]) != sz) {
207 207 mdb_warn("read of cmi_hdl(%i) array at 0x%p failed",
208 208 i, awsp->chip_tab[i]);
209 209 mdb_free(pg, sz);
210 210 cmih_walk_fini(wsp);
211 211 return (WALK_ERR);
212 212 }
213 213 awsp->chip_tab[i] = pg;
214 214 }
215 215
216 216 /* Look up the hdl of the first strand <0,0,0> */
217 217 wsp->walk_addr = NULL;
218 218 if ((ent = cmih_ent_lookup(awsp)) != NULL)
219 219 wsp->walk_addr = (uintptr_t)ent->cmae_hdlp;
220 220
221 221 return (WALK_NEXT);
222 222 }
223 223
224 224 static int
225 225 cmih_walk_step(mdb_walk_state_t *wsp)
226 226 {
227 227 struct cmih_walk_state *awsp = wsp->walk_data;
228 228 uintptr_t addr = NULL;
229 229 cmi_hdl_impl_t hdl;
230 230 cmi_hdl_ent_t *ent;
231 231 int rv;
232 232
233 233 if ((ent = cmih_ent_lookup(awsp)) != NULL)
234 234 addr = (uintptr_t)ent->cmae_hdlp;
235 235 if (wsp->walk_addr == NULL || addr == NULL)
236 236 return (cmih_ent_next(awsp) ? WALK_NEXT : WALK_DONE);
237 237
238 238 if (mdb_vread(&hdl, sizeof (hdl), addr) != sizeof (hdl)) {
239 239 mdb_warn("read of handle at 0x%p failed", addr);
240 240 return (WALK_DONE);
241 241 }
242 242
243 243 if ((rv = wsp->walk_callback(addr, (void *)&hdl,
244 244 wsp->walk_cbdata)) != WALK_NEXT)
245 245 return (rv);
246 246
247 247 return (cmih_ent_next(awsp) ? WALK_NEXT : WALK_DONE);
248 248 }
249 249
250 250 static void
251 251 cmih_walk_fini(mdb_walk_state_t *wsp)
252 252 {
253 253 struct cmih_walk_state *awsp = wsp->walk_data;
254 254
255 255 if (awsp != NULL) {
256 256 int i;
257 257 int max_strands = CMI_MAX_STRANDS_PER_CHIP(awsp->core_nbits,
258 258 awsp->strand_nbits);
259 259 for (i = 0; i < CMI_CHIPID_ARR_SZ; i++) {
260 260 /* free the per-chip table */
261 261 if (awsp->chip_tab[i] != NULL) {
262 262 mdb_free((void *)awsp->chip_tab[i],
263 263 max_strands * sizeof (cmi_hdl_ent_t));
264 264 awsp->chip_tab[i] = NULL;
265 265 }
266 266 }
267 267 mdb_free(wsp->walk_data, sizeof (struct cmih_walk_state));
268 268 wsp->walk_data = NULL;
269 269 }
270 270 }
271 271
272 272 struct cmihdl_cb {
273 273 int mod_cpuid;
274 274 int mod_chipid;
275 275 int mod_coreid;
276 276 int mod_strandid;
277 277 uintptr_t mod_hdladdr;
278 278 };
279 279
280 280 static int
281 281 cmihdl_cb(uintptr_t addr, const void *arg, void *data)
282 282 {
283 283 cmi_hdl_impl_t *hdl = (cmi_hdl_impl_t *)arg;
284 284 struct cmihdl_cb *cbp = data;
285 285 cpu_t *cp;
286 286 int rv;
287 287
288 288 if (cbp->mod_cpuid != -1) {
289 289 cp = mdb_alloc(sizeof (cpu_t), UM_SLEEP);
290 290 if (mdb_vread(cp, sizeof (cpu_t),
291 291 (uintptr_t)hdl->cmih_hdlpriv) != sizeof (cpu_t)) {
292 292 mdb_warn("Read of cpu_t at 0x%p failed",
293 293 hdl->cmih_hdlpriv);
294 294 mdb_free(cp, sizeof (cpu_t));
295 295 return (WALK_ERR);
296 296 }
297 297
298 298 if (cp->cpu_id == cbp->mod_cpuid) {
299 299 cbp->mod_hdladdr = addr;
300 300 rv = WALK_DONE;
301 301 } else {
302 302 rv = WALK_NEXT;
303 303 }
304 304
305 305 mdb_free(cp, sizeof (cpu_t));
306 306 return (rv);
307 307 } else {
308 308 if (hdl->cmih_chipid == cbp->mod_chipid &&
309 309 hdl->cmih_coreid == cbp->mod_coreid &&
310 310 hdl->cmih_strandid == cbp->mod_strandid) {
311 311 cbp->mod_hdladdr = addr;
312 312 return (WALK_DONE);
313 313 } else {
314 314 return (WALK_NEXT);
315 315 }
316 316 }
317 317 }
318 318
319 319 static int
320 320 cmihdl_disp(uintptr_t addr, cmi_hdl_impl_t *hdl)
321 321 {
322 322 struct cms_ctl cmsctl; /* 16 bytes max */
323 323 struct modctl cmimodc, cmsmodc; /* 288 bytes max */
324 324 cmi_t cmi; /* 40 bytes max */
325 325 cms_t cms; /* 40 bytes max */
326 326 cpu_t *cp;
327 327 char cmimodnm[25], cmsmodnm[25]; /* 50 bytes */
328 328 char cpuidstr[4], hwidstr[16];
329 329 int native = hdl->cmih_class == CMI_HDL_NATIVE;
330 330 uint32_t refcnt;
331 331
332 332 cmimodnm[0] = cmsmodnm[0] = '-';
333 333 cmimodnm[1] = cmsmodnm[1] = '\0';
334 334
335 335 if (hdl->cmih_cmi != NULL) {
336 336 if (mdb_vread(&cmi, sizeof (cmi_t),
337 337 (uintptr_t)hdl->cmih_cmi) != sizeof (cmi)) {
338 338 mdb_warn("Read of cmi_t at 0x%p failed",
339 339 hdl->cmih_cmi);
340 340 return (0);
341 341 }
342 342
343 343 if (cmi.cmi_modp != NULL) {
344 344 if (mdb_vread(&cmimodc, sizeof (struct modctl),
345 345 (uintptr_t)cmi.cmi_modp) != sizeof (cmimodc)) {
346 346 mdb_warn("Read of modctl at 0x%p failed",
347 347 cmi.cmi_modp);
348 348 return (0);
349 349 }
350 350
351 351 if (mdb_readstr(cmimodnm, sizeof (cmimodnm),
352 352 (uintptr_t)cmimodc.mod_modname) == -1) {
353 353 mdb_warn("Read of cmi module name at 0x%p "
354 354 "failed", cmimodc.mod_modname);
355 355 return (0);
356 356 }
357 357 }
358 358 }
359 359
360 360 if (hdl->cmih_spec != NULL) {
361 361 if (mdb_vread(&cmsctl, sizeof (struct cms_ctl),
362 362 (uintptr_t)hdl->cmih_spec) != sizeof (cmsctl)) {
363 363 mdb_warn("Read of struct cms_ctl at 0x%p failed",
364 364 hdl->cmih_spec);
365 365 return (0);
366 366 }
367 367
368 368 if (mdb_vread(&cms, sizeof (cms_t),
369 369 (uintptr_t)cmsctl.cs_cms) != sizeof (cms)) {
370 370 mdb_warn("Read of cms_t at 0x%p failed", cmsctl.cs_cms);
371 371 return (0);
372 372 }
373 373
374 374 if (cms.cms_modp != NULL) {
375 375 if (mdb_vread(&cmsmodc, sizeof (struct modctl),
376 376 (uintptr_t)cms.cms_modp) != sizeof (cmsmodc)) {
377 377 mdb_warn("Read of modctl at 0x%p failed",
378 378 cms.cms_modp);
379 379 return (0);
380 380 }
381 381
382 382 if (mdb_readstr(cmsmodnm, sizeof (cmsmodnm),
383 383 (uintptr_t)cmsmodc.mod_modname) == -1) {
384 384 mdb_warn("Read of cms module name at 0x%p "
385 385 "failed", cmsmodc.mod_modname);
386 386 return (0);
387 387 }
388 388 }
389 389 }
390 390
391 391 if (mdb_vread(&refcnt, sizeof (uint32_t),
392 392 (uintptr_t)hdl->cmih_refcntp) != sizeof (uint32_t)) {
393 393 mdb_warn("Read of reference count for hdl 0x%p failed", hdl);
394 394 return (0);
395 395 }
396 396
397 397 if (native) {
398 398 cp = mdb_alloc(sizeof (cpu_t), UM_SLEEP);
399 399
400 400 if (mdb_vread(cp, sizeof (cpu_t),
401 401 (uintptr_t)hdl->cmih_hdlpriv) != sizeof (cpu_t)) {
402 402 mdb_free(cp, sizeof (cpu_t));
403 403 mdb_warn("Read of cpu_t at 0x%p failed",
404 404 hdl->cmih_hdlpriv);
405 405 return (0);
406 406 }
407 407 }
408 408
409 409 if (native) {
410 410 (void) mdb_snprintf(cpuidstr, sizeof (cpuidstr), "%d",
411 411 cp->cpu_id);
412 412 } else {
413 413 (void) mdb_snprintf(cpuidstr, sizeof (cpuidstr), "-");
414 414 }
415 415
416 416 (void) mdb_snprintf(hwidstr, sizeof (hwidstr), "%d/%d/%d",
417 417 hdl->cmih_chipid, hdl->cmih_coreid, hdl->cmih_strandid);
418 418
419 419 mdb_printf("%16lx %3d %3s %8s %3s %2s %-13s %-24s\n", addr,
420 420 refcnt, cpuidstr, hwidstr, hdl->cmih_mstrand ? "M" : "S",
421 421 hdl->cmih_mcops ? "Y" : "N", cmimodnm, cmsmodnm);
422 422
423 423 if (native)
424 424 mdb_free(cp, sizeof (cpu_t));
425 425
426 426 return (1);
427 427 }
428 428
429 429 #define HDRFMT "%-16s %3s %3s %8s %3s %2s %-13s %-24s\n"
430 430
431 431 static int
432 432 cmihdl(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
433 433 {
434 434 struct cmihdl_cb cb;
435 435 cmi_hdl_impl_t *hdl;
436 436
437 437 /*
438 438 * If an address is given it must be that of a cmi handle.
439 439 * Otherwise if the user has specified -c <cpuid> or
440 440 * -c <chipid/coreid/strandid> we will lookup a matching handle.
441 441 * Otherwise we'll walk and callback to this dcmd.
442 442 */
443 443 if (!(flags & DCMD_ADDRSPEC)) {
444 444 char *p, *buf;
445 445 int len;
446 446
447 447 if (argc == 0)
448 448 return (mdb_walk_dcmd("cmihdl", "cmihdl", argc,
449 449 argv) == 0 ? DCMD_OK : DCMD_ERR);
450 450
451 451
452 452 if (mdb_getopts(argc, argv,
453 453 'c', MDB_OPT_STR, &p,
454 454 NULL) != argc)
455 455 return (DCMD_USAGE);
456 456
457 457 if ((len = strlen(p)) == 0) {
458 458 return (DCMD_USAGE);
459 459 } else {
460 460 buf = mdb_alloc(len + 1, UM_SLEEP);
461 461 strcpy(buf, p);
462 462 }
463 463
464 464 cb.mod_cpuid = cb.mod_chipid = cb.mod_coreid =
465 465 cb.mod_strandid = -1;
466 466
467 467 if ((p = strchr(buf, '/')) == NULL) {
468 468 /* Native cpuid */
469 469 cb.mod_cpuid = (int)mdb_strtoull(buf);
470 470 } else {
471 471 /* Comma-separated triplet chip,core,strand. */
472 472 char *q = buf;
473 473
474 474 *p = '\0';
475 475 cb.mod_chipid = (int)mdb_strtoull(q);
476 476
477 477 if ((q = p + 1) >= buf + len ||
478 478 (p = strchr(q, '/')) == NULL) {
479 479 mdb_free(buf, len);
480 480 return (DCMD_USAGE);
481 481 }
482 482
483 483 *p = '\0';
484 484 cb.mod_coreid = (int)mdb_strtoull(q);
485 485
486 486 if ((q = p + 1) >= buf + len) {
487 487 mdb_free(buf, len);
488 488 return (DCMD_USAGE);
489 489 }
490 490
491 491 cb.mod_strandid = (int)mdb_strtoull(q);
492 492 }
493 493
494 494 mdb_free(buf, len);
495 495
496 496 cb.mod_hdladdr = NULL;
497 497 if (mdb_walk("cmihdl", cmihdl_cb, &cb) == -1) {
498 498 mdb_warn("cmi_hdl walk failed\n");
499 499 return (DCMD_ERR);
500 500 }
501 501
502 502 if (cb.mod_hdladdr == NULL) {
503 503 if (cb.mod_cpuid != -1) {
504 504 mdb_warn("No handle found for cpuid %d\n",
505 505 cb.mod_cpuid);
506 506 } else {
507 507
508 508 mdb_warn("No handle found for chip %d "
509 509 "core %d strand %d\n", cb.mod_chipid,
510 510 cb.mod_coreid, cb.mod_strandid);
511 511 }
512 512 return (DCMD_ERR);
513 513 }
514 514
515 515 addr = cb.mod_hdladdr;
516 516 }
517 517
518 518 if (DCMD_HDRSPEC(flags)) {
519 519 char ul[] = "----------------------------";
520 520 char *p = ul + sizeof (ul) - 1;
521 521
522 522 mdb_printf(HDRFMT HDRFMT,
523 523 "HANDLE", "REF", "CPU", "CH/CR/ST", "CMT", "MC",
524 524 "MODULE", "MODEL-SPECIFIC",
525 525 p - 16, p - 3, p - 3, p - 8, p - 3, p - 2, p - 13, p - 24);
526 526 }
527 527
528 528 hdl = mdb_alloc(sizeof (cmi_hdl_impl_t), UM_SLEEP);
529 529
530 530 if (mdb_vread(hdl, sizeof (cmi_hdl_impl_t), addr) !=
531 531 sizeof (cmi_hdl_impl_t)) {
532 532 mdb_free(hdl, sizeof (cmi_hdl_impl_t));
533 533 mdb_warn("Read of cmi handle at 0x%p failed", addr);
534 534 return (DCMD_ERR);
535 535 }
536 536
537 537 if (!cmihdl_disp(addr, hdl)) {
538 538 mdb_free(hdl, sizeof (cmi_hdl_impl_t));
539 539 return (DCMD_ERR);
540 540 }
541 541
542 542 mdb_free(hdl, sizeof (cmi_hdl_impl_t));
543 543
544 544 return (DCMD_OK);
545 545 }
546 546
547 547 /*ARGSUSED*/
548 548 static int
549 549 gcpu_mpt_dump(uintptr_t addr, uint_t flags, int argc, const mdb_arg_t *argv)
550 550 {
551 551 static const char *const whatstrs[] = {
552 552 "ntv-cyc-poll", /* GCPU_MPT_WHAT_CYC_ERR */
553 553 "poll-poked", /* GCPU_MPT_WHAT_POKE_ERR */
554 554 "unfaulting", /* GCPU_MPT_WHAT_UNFAULTING */
555 555 "#MC", /* GCPU_MPT_WHAT_MC_ERR */
556 556 "CMCI-int", /* GCPU_MPT_WHAT_CMCI_ERR */
557 557 "xpv-virq-nrec", /* GCPU_MPT_WHAT_XPV_VIRQ */
558 558 "xpv-virq-lgout", /* GCPU_MPT_WHAT_XPV_VIRQ_LOGOUT */
559 559 };
560 560
561 561 gcpu_poll_trace_t mpt;
562 562 const char *what;
563 563
564 564 if (argc != 0 || !(flags & DCMD_ADDRSPEC))
565 565 return (DCMD_USAGE);
566 566
567 567 if (mdb_vread(&mpt, sizeof (mpt), addr) != sizeof (mpt)) {
568 568 mdb_warn("failed to read gcpu_poll_trace_t at 0x%p", addr);
569 569 return (DCMD_ERR);
570 570 }
571 571
572 572 if (DCMD_HDRSPEC(flags)) {
573 573 mdb_printf("%<u>%?s%</u> %<u>%?s%</u> %<u>%15s%</u> "
574 574 "%<u>%4s%</u>\n", "ADDR", "WHEN", "WHAT", "NERR");
575 575 }
576 576
577 577 if (mpt.mpt_what < sizeof (whatstrs) / sizeof (char *))
578 578 what = whatstrs[mpt.mpt_what];
579 579 else
580 580 what = "???";
581 581
582 582 mdb_printf("%?p %?p %15s %4u\n", addr, mpt.mpt_when, what,
583 583 mpt.mpt_nerr);
584 584
585 585 return (DCMD_OK);
586 586 }
587 587
588 588 typedef struct mptwalk_data {
589 589 uintptr_t mw_traceaddr;
590 590 gcpu_poll_trace_t *mw_trace;
591 591 size_t mw_tracesz;
592 592 uint_t mw_tracenent;
593 593 uint_t mw_curtrace;
594 594 } mptwalk_data_t;
595 595
596 596 static int
597 597 gcpu_mptwalk_init(mdb_walk_state_t *wsp)
598 598 {
599 599 gcpu_poll_trace_t *mpt;
600 600 mptwalk_data_t *mw;
601 601 GElf_Sym sym;
602 602 uint_t nent, i;
603 603 hrtime_t latest;
604 604
605 605 if (wsp->walk_addr == NULL) {
606 606 mdb_warn("the address of a poll trace array must be "
607 607 "specified\n");
608 608 return (WALK_ERR);
609 609 }
610 610
611 611 if (mdb_lookup_by_name("gcpu_poll_trace_nent", &sym) < 0 ||
612 612 sym.st_size != sizeof (uint_t) || mdb_vread(&nent, sizeof (uint_t),
613 613 sym.st_value) != sizeof (uint_t)) {
614 614 mdb_warn("failed to read gcpu_poll_trace_nent from kernel");
615 615 return (WALK_ERR);
616 616 }
617 617
618 618 mw = mdb_alloc(sizeof (mptwalk_data_t), UM_SLEEP);
619 619 mw->mw_traceaddr = wsp->walk_addr;
620 620 mw->mw_tracenent = nent;
621 621 mw->mw_tracesz = nent * sizeof (gcpu_poll_trace_t);
622 622 mw->mw_trace = mdb_alloc(mw->mw_tracesz, UM_SLEEP);
623 623
624 624 if (mdb_vread(mw->mw_trace, mw->mw_tracesz, wsp->walk_addr) !=
625 625 mw->mw_tracesz) {
626 626 mdb_free(mw->mw_trace, mw->mw_tracesz);
627 627 mdb_free(mw, sizeof (mptwalk_data_t));
628 628 mdb_warn("failed to read poll trace array from kernel");
629 629 return (WALK_ERR);
630 630 }
631 631
632 632 latest = 0;
633 633 mw->mw_curtrace = 0;
634 634 for (mpt = mw->mw_trace, i = 0; i < mw->mw_tracenent; i++, mpt++) {
635 635 if (mpt->mpt_when > latest) {
636 636 latest = mpt->mpt_when;
637 637 mw->mw_curtrace = i;
638 638 }
639 639 }
640 640
641 641 if (latest == 0) {
642 642 mdb_free(mw->mw_trace, mw->mw_tracesz);
643 643 mdb_free(mw, sizeof (mptwalk_data_t));
644 644 return (WALK_DONE); /* trace array is empty */
645 645 }
646 646
647 647 wsp->walk_data = mw;
648 648
649 649 return (WALK_NEXT);
650 650 }
651 651
652 652 static int
653 653 gcpu_mptwalk_step(mdb_walk_state_t *wsp)
654 654 {
655 655 mptwalk_data_t *mw = wsp->walk_data;
656 656 gcpu_poll_trace_t *thismpt, *prevmpt;
657 657 int prev, rv;
658 658
659 659 thismpt = &mw->mw_trace[mw->mw_curtrace];
660 660
661 661 rv = wsp->walk_callback(mw->mw_traceaddr + (mw->mw_curtrace *
662 662 sizeof (gcpu_poll_trace_t)), thismpt, wsp->walk_cbdata);
663 663
664 664 if (rv != WALK_NEXT)
665 665 return (rv);
666 666
667 667 prev = (mw->mw_curtrace - 1) % mw->mw_tracenent;
668 668 prevmpt = &mw->mw_trace[prev];
669 669
670 670 if (prevmpt->mpt_when == 0 || prevmpt->mpt_when > thismpt->mpt_when)
671 671 return (WALK_DONE);
672 672
673 673 mw->mw_curtrace = prev;
674 674
675 675 return (WALK_NEXT);
676 676 }
677 677
678 678 static void
679 679 gcpu_mptwalk_fini(mdb_walk_state_t *wsp)
680 680 {
681 681 mptwalk_data_t *mw = wsp->walk_data;
682 682
683 683 mdb_free(mw->mw_trace, mw->mw_tracesz);
684 684 mdb_free(mw, sizeof (mptwalk_data_t));
685 685 }
686 686
687 687 static const mdb_dcmd_t dcmds[] = {
688 688 { "cmihdl", ": -c <cpuid>|<chip,core,strand> ",
689 689 "dump a cmi_handle_t", cmihdl },
690 690 { "gcpu_poll_trace", ":", "dump a poll trace buffer", gcpu_mpt_dump },
691 691 { NULL }
692 692 };
693 693
694 694 static const mdb_walker_t walkers[] = {
695 695 { "cmihdl", "walks cpu module interface handle list",
696 696 cmih_walk_init, cmih_walk_step, cmih_walk_fini, NULL },
697 697 { "gcpu_poll_trace", "walks poll trace buffers in reverse "
698 698 "chronological order", gcpu_mptwalk_init, gcpu_mptwalk_step,
699 699 gcpu_mptwalk_fini, NULL },
700 700 { NULL }
701 701 };
702 702
703 703 static const mdb_modinfo_t modinfo = { MDB_API_VERSION, dcmds, walkers };
704 704
705 705 const mdb_modinfo_t *
706 706 _mdb_init(void)
707 707 {
708 708 return (&modinfo);
709 709 }
↓ open down ↓ |
569 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX