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 2010 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 * Copyright (c) 2018, Joyent, Inc. 26 */ 27 28 /* 29 * Public interface to routines implemented by CPU modules 30 */ 31 32 #include <sys/types.h> 33 #include <sys/atomic.h> 34 #include <sys/x86_archext.h> 35 #include <sys/cpu_module_impl.h> 36 #include <sys/cpu_module_ms.h> 37 #include <sys/fm/util.h> 38 #include <sys/reboot.h> 39 #include <sys/modctl.h> 40 #include <sys/param.h> 41 #include <sys/cmn_err.h> 42 #include <sys/systm.h> 43 #include <sys/fm/protocol.h> 44 #include <sys/pcb.h> 45 #include <sys/ontrap.h> 46 #include <sys/psw.h> 47 #include <sys/privregs.h> 48 #include <sys/machsystm.h> 49 50 /* 51 * Set to force cmi_init to fail. 52 */ 53 int cmi_no_init = 0; 54 55 /* 56 * Set to avoid MCA initialization. 57 */ 58 int cmi_no_mca_init = 0; 59 60 /* 61 * If cleared for debugging we will not attempt to load a model-specific 62 * cpu module but will load the generic cpu module instead. 63 */ 64 int cmi_force_generic = 0; 65 66 /* 67 * If cleared for debugging, we will suppress panicking on fatal hardware 68 * errors. This should *only* be used for debugging; it use can and will 69 * cause data corruption if actual hardware errors are detected by the system. 70 */ 71 int cmi_panic_on_uncorrectable_error = 1; 72 73 #ifndef __xpv 74 /* 75 * Set to indicate whether we are able to enable cmci interrupt. 76 */ 77 int cmi_enable_cmci = 0; 78 #endif 79 80 /* 81 * Subdirectory (relative to the module search path) in which we will 82 * look for cpu modules. 83 */ 84 #define CPUMOD_SUBDIR "cpu" 85 86 /* 87 * CPU modules have a filenames such as "cpu.AuthenticAMD.15" and 88 * "cpu.generic" - the "cpu" prefix is specified by the following. 89 */ 90 #define CPUMOD_PREFIX "cpu" 91 92 /* 93 * Structure used to keep track of cpu modules we have loaded and their ops 94 */ 95 typedef struct cmi { 96 struct cmi *cmi_next; 97 struct cmi *cmi_prev; 98 const cmi_ops_t *cmi_ops; 99 struct modctl *cmi_modp; 100 uint_t cmi_refcnt; 101 } cmi_t; 102 103 static cmi_t *cmi_list; 104 static const cmi_mc_ops_t *cmi_mc_global_ops; 105 static void *cmi_mc_global_data; 106 static kmutex_t cmi_load_lock; 107 108 /* 109 * Functions we need from cmi_hw.c that are not part of the cpu_module.h 110 * interface. 111 */ 112 extern cmi_hdl_t cmi_hdl_create(enum cmi_hdl_class, uint_t, uint_t, uint_t); 113 extern void cmi_hdl_destroy(cmi_hdl_t ophdl); 114 extern void cmi_hdl_setcmi(cmi_hdl_t, void *, void *); 115 extern void *cmi_hdl_getcmi(cmi_hdl_t); 116 extern void cmi_hdl_setmc(cmi_hdl_t, const struct cmi_mc_ops *, void *); 117 extern void cmi_hdl_inj_begin(cmi_hdl_t); 118 extern void cmi_hdl_inj_end(cmi_hdl_t); 119 extern void cmi_read_smbios(cmi_hdl_t); 120 121 #define HDL2CMI(hdl) cmi_hdl_getcmi(hdl) 122 123 #define CMI_OPS(cmi) (cmi)->cmi_ops 124 #define CMI_OP_PRESENT(cmi, op) ((cmi) && CMI_OPS(cmi)->op != NULL) 125 126 #define CMI_MATCH_VENDOR 0 /* Just match on vendor */ 127 #define CMI_MATCH_FAMILY 1 /* Match down to family */ 128 #define CMI_MATCH_MODEL 2 /* Match down to model */ 129 #define CMI_MATCH_STEPPING 3 /* Match down to stepping */ 130 131 static void 132 cmi_link(cmi_t *cmi) 133 { 134 ASSERT(MUTEX_HELD(&cmi_load_lock)); 135 136 cmi->cmi_prev = NULL; 137 cmi->cmi_next = cmi_list; 138 if (cmi_list != NULL) 139 cmi_list->cmi_prev = cmi; 140 cmi_list = cmi; 141 } 142 143 static void 144 cmi_unlink(cmi_t *cmi) 145 { 146 ASSERT(MUTEX_HELD(&cmi_load_lock)); 147 ASSERT(cmi->cmi_refcnt == 0); 148 149 if (cmi->cmi_prev != NULL) 150 cmi->cmi_prev = cmi->cmi_next; 151 152 if (cmi->cmi_next != NULL) 153 cmi->cmi_next->cmi_prev = cmi->cmi_prev; 154 155 if (cmi_list == cmi) 156 cmi_list = cmi->cmi_next; 157 } 158 159 /* 160 * Hold the module in memory. We call to CPU modules without using the 161 * stubs mechanism, so these modules must be manually held in memory. 162 * The mod_ref acts as if another loaded module has a dependency on us. 163 */ 164 static void 165 cmi_hold(cmi_t *cmi) 166 { 167 ASSERT(MUTEX_HELD(&cmi_load_lock)); 168 169 mutex_enter(&mod_lock); 170 cmi->cmi_modp->mod_ref++; 171 mutex_exit(&mod_lock); 172 cmi->cmi_refcnt++; 173 } 174 175 static void 176 cmi_rele(cmi_t *cmi) 177 { 178 ASSERT(MUTEX_HELD(&cmi_load_lock)); 179 180 mutex_enter(&mod_lock); 181 cmi->cmi_modp->mod_ref--; 182 mutex_exit(&mod_lock); 183 184 if (--cmi->cmi_refcnt == 0) { 185 cmi_unlink(cmi); 186 kmem_free(cmi, sizeof (cmi_t)); 187 } 188 } 189 190 static cmi_ops_t * 191 cmi_getops(modctl_t *modp) 192 { 193 cmi_ops_t *ops; 194 195 if ((ops = (cmi_ops_t *)modlookup_by_modctl(modp, "_cmi_ops")) == 196 NULL) { 197 cmn_err(CE_WARN, "cpu module '%s' is invalid: no _cmi_ops " 198 "found", modp->mod_modname); 199 return (NULL); 200 } 201 202 if (ops->cmi_init == NULL) { 203 cmn_err(CE_WARN, "cpu module '%s' is invalid: no cmi_init " 204 "entry point", modp->mod_modname); 205 return (NULL); 206 } 207 208 return (ops); 209 } 210 211 static cmi_t * 212 cmi_load_modctl(modctl_t *modp) 213 { 214 cmi_ops_t *ops; 215 uintptr_t ver; 216 cmi_t *cmi; 217 cmi_api_ver_t apiver; 218 219 ASSERT(MUTEX_HELD(&cmi_load_lock)); 220 221 for (cmi = cmi_list; cmi != NULL; cmi = cmi->cmi_next) { 222 if (cmi->cmi_modp == modp) 223 return (cmi); 224 } 225 226 if ((ver = modlookup_by_modctl(modp, "_cmi_api_version")) == NULL) { 227 /* 228 * Apparently a cpu module before versioning was introduced - 229 * we call this version 0. 230 */ 231 apiver = CMI_API_VERSION_0; 232 } else { 233 apiver = *((cmi_api_ver_t *)ver); 234 if (!CMI_API_VERSION_CHKMAGIC(apiver)) { 235 cmn_err(CE_WARN, "cpu module '%s' is invalid: " 236 "_cmi_api_version 0x%x has bad magic", 237 modp->mod_modname, apiver); 238 return (NULL); 239 } 240 } 241 242 if (apiver != CMI_API_VERSION) { 243 cmn_err(CE_WARN, "cpu module '%s' has API version %d, " 244 "kernel requires API version %d", modp->mod_modname, 245 CMI_API_VERSION_TOPRINT(apiver), 246 CMI_API_VERSION_TOPRINT(CMI_API_VERSION)); 247 return (NULL); 248 } 249 250 if ((ops = cmi_getops(modp)) == NULL) 251 return (NULL); 252 253 cmi = kmem_zalloc(sizeof (*cmi), KM_SLEEP); 254 cmi->cmi_ops = ops; 255 cmi->cmi_modp = modp; 256 257 cmi_link(cmi); 258 259 return (cmi); 260 } 261 262 static int 263 cmi_cpu_match(cmi_hdl_t hdl1, cmi_hdl_t hdl2, int match) 264 { 265 if (match >= CMI_MATCH_VENDOR && 266 cmi_hdl_vendor(hdl1) != cmi_hdl_vendor(hdl2)) 267 return (0); 268 269 if (match >= CMI_MATCH_FAMILY && 270 cmi_hdl_family(hdl1) != cmi_hdl_family(hdl2)) 271 return (0); 272 273 if (match >= CMI_MATCH_MODEL && 274 cmi_hdl_model(hdl1) != cmi_hdl_model(hdl2)) 275 return (0); 276 277 if (match >= CMI_MATCH_STEPPING && 278 cmi_hdl_stepping(hdl1) != cmi_hdl_stepping(hdl2)) 279 return (0); 280 281 return (1); 282 } 283 284 static int 285 cmi_search_list_cb(cmi_hdl_t whdl, void *arg1, void *arg2, void *arg3) 286 { 287 cmi_hdl_t thdl = (cmi_hdl_t)arg1; 288 int match = *((int *)arg2); 289 cmi_hdl_t *rsltp = (cmi_hdl_t *)arg3; 290 291 if (cmi_cpu_match(thdl, whdl, match)) { 292 cmi_hdl_hold(whdl); /* short-term hold */ 293 *rsltp = whdl; 294 return (CMI_HDL_WALK_DONE); 295 } else { 296 return (CMI_HDL_WALK_NEXT); 297 } 298 } 299 300 static cmi_t * 301 cmi_search_list(cmi_hdl_t hdl, int match) 302 { 303 cmi_hdl_t dhdl = NULL; 304 cmi_t *cmi = NULL; 305 306 ASSERT(MUTEX_HELD(&cmi_load_lock)); 307 308 cmi_hdl_walk(cmi_search_list_cb, (void *)hdl, (void *)&match, &dhdl); 309 if (dhdl) { 310 cmi = HDL2CMI(dhdl); 311 cmi_hdl_rele(dhdl); /* held in cmi_search_list_cb */ 312 } 313 314 return (cmi); 315 } 316 317 static cmi_t * 318 cmi_load_module(cmi_hdl_t hdl, int match, int *chosenp) 319 { 320 modctl_t *modp; 321 cmi_t *cmi; 322 int modid; 323 uint_t s[3]; 324 325 ASSERT(MUTEX_HELD(&cmi_load_lock)); 326 ASSERT(match == CMI_MATCH_STEPPING || match == CMI_MATCH_MODEL || 327 match == CMI_MATCH_FAMILY || match == CMI_MATCH_VENDOR); 328 329 /* 330 * Have we already loaded a module for a cpu with the same 331 * vendor/family/model/stepping? 332 */ 333 if ((cmi = cmi_search_list(hdl, match)) != NULL) { 334 cmi_hold(cmi); 335 return (cmi); 336 } 337 338 s[0] = cmi_hdl_family(hdl); 339 s[1] = cmi_hdl_model(hdl); 340 s[2] = cmi_hdl_stepping(hdl); 341 modid = modload_qualified(CPUMOD_SUBDIR, CPUMOD_PREFIX, 342 cmi_hdl_vendorstr(hdl), ".", s, match, chosenp); 343 344 if (modid == -1) 345 return (NULL); 346 347 modp = mod_hold_by_id(modid); 348 cmi = cmi_load_modctl(modp); 349 if (cmi) 350 cmi_hold(cmi); 351 mod_release_mod(modp); 352 353 return (cmi); 354 } 355 356 /* 357 * Try to load a cpu module with specific support for this chip type. 358 */ 359 static cmi_t * 360 cmi_load_specific(cmi_hdl_t hdl, void **datap) 361 { 362 cmi_t *cmi; 363 int err; 364 int i; 365 366 ASSERT(MUTEX_HELD(&cmi_load_lock)); 367 368 for (i = CMI_MATCH_STEPPING; i >= CMI_MATCH_VENDOR; i--) { 369 int suffixlevel; 370 371 if ((cmi = cmi_load_module(hdl, i, &suffixlevel)) == NULL) 372 return (NULL); 373 374 /* 375 * A module has loaded and has a _cmi_ops structure, and the 376 * module has been held for this instance. Call its cmi_init 377 * entry point - we expect success (0) or ENOTSUP. 378 */ 379 if ((err = cmi->cmi_ops->cmi_init(hdl, datap)) == 0) { 380 if (boothowto & RB_VERBOSE) { 381 printf("initialized cpu module '%s' on " 382 "chip %d core %d strand %d\n", 383 cmi->cmi_modp->mod_modname, 384 cmi_hdl_chipid(hdl), cmi_hdl_coreid(hdl), 385 cmi_hdl_strandid(hdl)); 386 } 387 return (cmi); 388 } else if (err != ENOTSUP) { 389 cmn_err(CE_WARN, "failed to init cpu module '%s' on " 390 "chip %d core %d strand %d: err=%d\n", 391 cmi->cmi_modp->mod_modname, 392 cmi_hdl_chipid(hdl), cmi_hdl_coreid(hdl), 393 cmi_hdl_strandid(hdl), err); 394 } 395 396 /* 397 * The module failed or declined to init, so release 398 * it and update i to be equal to the number 399 * of suffices actually used in the last module path. 400 */ 401 cmi_rele(cmi); 402 i = suffixlevel; 403 } 404 405 return (NULL); 406 } 407 408 /* 409 * Load the generic IA32 MCA cpu module, which may still supplement 410 * itself with model-specific support through cpu model-specific modules. 411 */ 412 static cmi_t * 413 cmi_load_generic(cmi_hdl_t hdl, void **datap) 414 { 415 modctl_t *modp; 416 cmi_t *cmi; 417 int modid; 418 int err; 419 420 ASSERT(MUTEX_HELD(&cmi_load_lock)); 421 422 if ((modid = modload(CPUMOD_SUBDIR, CPUMOD_PREFIX ".generic")) == -1) 423 return (NULL); 424 425 modp = mod_hold_by_id(modid); 426 cmi = cmi_load_modctl(modp); 427 if (cmi) 428 cmi_hold(cmi); 429 mod_release_mod(modp); 430 431 if (cmi == NULL) 432 return (NULL); 433 434 if ((err = cmi->cmi_ops->cmi_init(hdl, datap)) != 0) { 435 if (err != ENOTSUP) 436 cmn_err(CE_WARN, CPUMOD_PREFIX ".generic failed to " 437 "init: err=%d", err); 438 cmi_rele(cmi); 439 return (NULL); 440 } 441 442 return (cmi); 443 } 444 445 cmi_hdl_t 446 cmi_init(enum cmi_hdl_class class, uint_t chipid, uint_t coreid, 447 uint_t strandid) 448 { 449 cmi_t *cmi = NULL; 450 cmi_hdl_t hdl; 451 void *data; 452 453 if (cmi_no_init) { 454 cmi_no_mca_init = 1; 455 return (NULL); 456 } 457 458 mutex_enter(&cmi_load_lock); 459 460 if ((hdl = cmi_hdl_create(class, chipid, coreid, strandid)) == NULL) { 461 mutex_exit(&cmi_load_lock); 462 cmn_err(CE_WARN, "There will be no MCA support on chip %d " 463 "core %d strand %d (cmi_hdl_create returned NULL)\n", 464 chipid, coreid, strandid); 465 return (NULL); 466 } 467 468 if (!cmi_force_generic) 469 cmi = cmi_load_specific(hdl, &data); 470 471 if (cmi == NULL && (cmi = cmi_load_generic(hdl, &data)) == NULL) { 472 cmn_err(CE_WARN, "There will be no MCA support on chip %d " 473 "core %d strand %d\n", chipid, coreid, strandid); 474 cmi_hdl_rele(hdl); 475 mutex_exit(&cmi_load_lock); 476 return (NULL); 477 } 478 479 cmi_hdl_setcmi(hdl, cmi, data); 480 481 cms_init(hdl); 482 483 cmi_read_smbios(hdl); 484 485 mutex_exit(&cmi_load_lock); 486 487 return (hdl); 488 } 489 490 /* 491 * cmi_fini is called on DR deconfigure of a cpu resource. 492 * It should not be called at simple offline of a cpu. 493 */ 494 void 495 cmi_fini(cmi_hdl_t hdl) 496 { 497 cmi_t *cmi = HDL2CMI(hdl); 498 499 if (cms_present(hdl)) 500 cms_fini(hdl); 501 502 if (CMI_OP_PRESENT(cmi, cmi_fini)) 503 CMI_OPS(cmi)->cmi_fini(hdl); 504 505 cmi_hdl_destroy(hdl); 506 } 507 508 /* 509 * cmi_post_startup is called from post_startup for the boot cpu only (no 510 * other cpus are started yet). 511 */ 512 void 513 cmi_post_startup(void) 514 { 515 cmi_hdl_t hdl; 516 cmi_t *cmi; 517 518 if (cmi_no_mca_init != 0 || 519 (hdl = cmi_hdl_any()) == NULL) /* short-term hold */ 520 return; 521 522 cmi = HDL2CMI(hdl); 523 524 if (CMI_OP_PRESENT(cmi, cmi_post_startup)) 525 CMI_OPS(cmi)->cmi_post_startup(hdl); 526 527 cmi_hdl_rele(hdl); 528 } 529 530 /* 531 * Called just once from start_other_cpus when all processors are started. 532 * This will not be called for each cpu, so the registered op must not 533 * assume it is called as such. We are not necessarily executing on 534 * the boot cpu. 535 */ 536 void 537 cmi_post_mpstartup(void) 538 { 539 cmi_hdl_t hdl; 540 cmi_t *cmi; 541 542 if (cmi_no_mca_init != 0 || 543 (hdl = cmi_hdl_any()) == NULL) /* short-term hold */ 544 return; 545 546 cmi = HDL2CMI(hdl); 547 548 if (CMI_OP_PRESENT(cmi, cmi_post_mpstartup)) 549 CMI_OPS(cmi)->cmi_post_mpstartup(hdl); 550 551 cmi_hdl_rele(hdl); 552 } 553 554 void 555 cmi_faulted_enter(cmi_hdl_t hdl) 556 { 557 cmi_t *cmi = HDL2CMI(hdl); 558 559 if (cmi_no_mca_init != 0) 560 return; 561 562 if (CMI_OP_PRESENT(cmi, cmi_faulted_enter)) 563 CMI_OPS(cmi)->cmi_faulted_enter(hdl); 564 } 565 566 void 567 cmi_faulted_exit(cmi_hdl_t hdl) 568 { 569 cmi_t *cmi = HDL2CMI(hdl); 570 571 if (cmi_no_mca_init != 0) 572 return; 573 574 if (CMI_OP_PRESENT(cmi, cmi_faulted_exit)) 575 CMI_OPS(cmi)->cmi_faulted_exit(hdl); 576 } 577 578 void 579 cmi_mca_init(cmi_hdl_t hdl) 580 { 581 cmi_t *cmi; 582 583 if (cmi_no_mca_init != 0) 584 return; 585 586 cmi = HDL2CMI(hdl); 587 588 if (CMI_OP_PRESENT(cmi, cmi_mca_init)) 589 CMI_OPS(cmi)->cmi_mca_init(hdl); 590 } 591 592 #define CMI_RESPONSE_PANIC 0x0 /* panic must have value 0 */ 593 #define CMI_RESPONSE_NONE 0x1 594 #define CMI_RESPONSE_CKILL 0x2 595 #define CMI_RESPONSE_REBOOT 0x3 /* not implemented */ 596 #define CMI_RESPONSE_ONTRAP_PROT 0x4 597 #define CMI_RESPONSE_LOFAULT_PROT 0x5 598 599 /* 600 * Return 0 if we will panic in response to this machine check, otherwise 601 * non-zero. If the caller is cmi_mca_trap in this file then the nonzero 602 * return values are to be interpreted from CMI_RESPONSE_* above. 603 * 604 * This function must just return what will be done without actually 605 * doing anything; this includes not changing the regs. 606 */ 607 int 608 cmi_mce_response(struct regs *rp, uint64_t disp) 609 { 610 int panicrsp = cmi_panic_on_uncorrectable_error ? CMI_RESPONSE_PANIC : 611 CMI_RESPONSE_NONE; 612 on_trap_data_t *otp; 613 614 ASSERT(rp != NULL); /* don't call for polling, only on #MC */ 615 616 /* 617 * If no bits are set in the disposition then there is nothing to 618 * worry about and we do not need to trampoline to ontrap or 619 * lofault handlers. 620 */ 621 if (disp == 0) 622 return (CMI_RESPONSE_NONE); 623 624 /* 625 * Unconstrained errors cannot be forgiven, even by ontrap or 626 * lofault protection. The data is not poisoned and may not 627 * even belong to the trapped context - eg a writeback of 628 * data that is found to be bad. 629 */ 630 if (disp & CMI_ERRDISP_UC_UNCONSTRAINED) 631 return (panicrsp); 632 633 /* 634 * ontrap OT_DATA_EC and lofault protection forgive any disposition 635 * other than unconstrained, even those normally forced fatal. 636 */ 637 if ((otp = curthread->t_ontrap) != NULL && otp->ot_prot & OT_DATA_EC) 638 return (CMI_RESPONSE_ONTRAP_PROT); 639 else if (curthread->t_lofault) 640 return (CMI_RESPONSE_LOFAULT_PROT); 641 642 /* 643 * Forced-fatal errors are terminal even in user mode. 644 */ 645 if (disp & CMI_ERRDISP_FORCEFATAL) 646 return (panicrsp); 647 648 /* 649 * If the trapped context is corrupt or we have no instruction pointer 650 * to resume at (and aren't trampolining to a fault handler) 651 * then in the kernel case we must panic and in usermode we 652 * kill the affected contract. 653 */ 654 if (disp & (CMI_ERRDISP_CURCTXBAD | CMI_ERRDISP_RIPV_INVALID)) 655 return (USERMODE(rp->r_cs) ? CMI_RESPONSE_CKILL : panicrsp); 656 657 /* 658 * Anything else is harmless 659 */ 660 return (CMI_RESPONSE_NONE); 661 } 662 663 int cma_mca_trap_panic_suppressed = 0; 664 665 static void 666 cmi_mca_panic(void) 667 { 668 if (cmi_panic_on_uncorrectable_error) { 669 fm_panic("Unrecoverable Machine-Check Exception"); 670 } else { 671 cmn_err(CE_WARN, "suppressing panic from fatal #mc"); 672 cma_mca_trap_panic_suppressed++; 673 } 674 } 675 676 677 int cma_mca_trap_contract_kills = 0; 678 int cma_mca_trap_ontrap_forgiven = 0; 679 int cma_mca_trap_lofault_forgiven = 0; 680 681 /* 682 * Native #MC handler - we branch to here from mcetrap 683 */ 684 /*ARGSUSED*/ 685 void 686 cmi_mca_trap(struct regs *rp) 687 { 688 #ifndef __xpv 689 cmi_hdl_t hdl = NULL; 690 uint64_t disp; 691 cmi_t *cmi; 692 int s; 693 694 if (cmi_no_mca_init != 0) 695 return; 696 697 /* 698 * This function can call cmn_err, and the cpu module cmi_mca_trap 699 * entry point may also elect to call cmn_err (e.g., if it can't 700 * log the error onto an errorq, say very early in boot). 701 * We need to let cprintf know that we must not block. 702 */ 703 s = spl8(); 704 705 if ((hdl = cmi_hdl_lookup(CMI_HDL_NATIVE, cmi_ntv_hwchipid(CPU), 706 cmi_ntv_hwcoreid(CPU), cmi_ntv_hwstrandid(CPU))) == NULL || 707 (cmi = HDL2CMI(hdl)) == NULL || 708 !CMI_OP_PRESENT(cmi, cmi_mca_trap)) { 709 710 cmn_err(CE_WARN, "#MC exception on cpuid %d: %s", 711 CPU->cpu_id, 712 hdl ? "handle lookup ok but no #MC handler found" : 713 "handle lookup failed"); 714 715 if (hdl != NULL) 716 cmi_hdl_rele(hdl); 717 718 splx(s); 719 return; 720 } 721 722 disp = CMI_OPS(cmi)->cmi_mca_trap(hdl, rp); 723 724 switch (cmi_mce_response(rp, disp)) { 725 default: 726 cmn_err(CE_WARN, "Invalid response from cmi_mce_response"); 727 /*FALLTHRU*/ 728 729 case CMI_RESPONSE_PANIC: 730 cmi_mca_panic(); 731 break; 732 733 case CMI_RESPONSE_NONE: 734 break; 735 736 case CMI_RESPONSE_CKILL: 737 ttolwp(curthread)->lwp_pcb.pcb_flags |= ASYNC_HWERR; 738 aston(curthread); 739 cma_mca_trap_contract_kills++; 740 break; 741 742 case CMI_RESPONSE_ONTRAP_PROT: { 743 on_trap_data_t *otp = curthread->t_ontrap; 744 otp->ot_trap = OT_DATA_EC; 745 rp->r_pc = otp->ot_trampoline; 746 cma_mca_trap_ontrap_forgiven++; 747 break; 748 } 749 750 case CMI_RESPONSE_LOFAULT_PROT: 751 rp->r_r0 = EFAULT; 752 rp->r_pc = curthread->t_lofault; 753 cma_mca_trap_lofault_forgiven++; 754 break; 755 } 756 757 cmi_hdl_rele(hdl); 758 splx(s); 759 #endif /* __xpv */ 760 } 761 762 void 763 cmi_hdl_poke(cmi_hdl_t hdl) 764 { 765 cmi_t *cmi = HDL2CMI(hdl); 766 767 if (!CMI_OP_PRESENT(cmi, cmi_hdl_poke)) 768 return; 769 770 CMI_OPS(cmi)->cmi_hdl_poke(hdl); 771 } 772 773 #ifndef __xpv 774 void 775 cmi_cmci_trap() 776 { 777 cmi_hdl_t hdl = NULL; 778 cmi_t *cmi; 779 780 if (cmi_no_mca_init != 0) 781 return; 782 783 if ((hdl = cmi_hdl_lookup(CMI_HDL_NATIVE, cmi_ntv_hwchipid(CPU), 784 cmi_ntv_hwcoreid(CPU), cmi_ntv_hwstrandid(CPU))) == NULL || 785 (cmi = HDL2CMI(hdl)) == NULL || 786 !CMI_OP_PRESENT(cmi, cmi_cmci_trap)) { 787 788 cmn_err(CE_WARN, "CMCI interrupt on cpuid %d: %s", 789 CPU->cpu_id, 790 hdl ? "handle lookup ok but no CMCI handler found" : 791 "handle lookup failed"); 792 793 if (hdl != NULL) 794 cmi_hdl_rele(hdl); 795 796 return; 797 } 798 799 CMI_OPS(cmi)->cmi_cmci_trap(hdl); 800 801 cmi_hdl_rele(hdl); 802 } 803 #endif /* __xpv */ 804 805 void 806 cmi_mc_register(cmi_hdl_t hdl, const cmi_mc_ops_t *mcops, void *mcdata) 807 { 808 if (!cmi_no_mca_init) 809 cmi_hdl_setmc(hdl, mcops, mcdata); 810 } 811 812 cmi_errno_t 813 cmi_mc_register_global(const cmi_mc_ops_t *mcops, void *mcdata) 814 { 815 if (!cmi_no_mca_init) { 816 if (cmi_mc_global_ops != NULL || cmi_mc_global_data != NULL || 817 mcops == NULL || mcops->cmi_mc_patounum == NULL || 818 mcops->cmi_mc_unumtopa == NULL) { 819 return (CMIERR_UNKNOWN); 820 } 821 cmi_mc_global_data = mcdata; 822 cmi_mc_global_ops = mcops; 823 } 824 return (CMI_SUCCESS); 825 } 826 827 void 828 cmi_mc_sw_memscrub_disable(void) 829 { 830 memscrub_disable(); 831 } 832 833 cmi_errno_t 834 cmi_mc_patounum(uint64_t pa, uint8_t valid_hi, uint8_t valid_lo, uint32_t synd, 835 int syndtype, mc_unum_t *up) 836 { 837 const struct cmi_mc_ops *mcops; 838 cmi_hdl_t hdl; 839 cmi_errno_t rv; 840 841 if (cmi_no_mca_init) 842 return (CMIERR_MC_ABSENT); 843 844 if (cmi_mc_global_ops != NULL) { 845 if (cmi_mc_global_ops->cmi_mc_patounum == NULL) 846 return (CMIERR_MC_NOTSUP); 847 return (cmi_mc_global_ops->cmi_mc_patounum(cmi_mc_global_data, 848 pa, valid_hi, valid_lo, synd, syndtype, up)); 849 } 850 851 if ((hdl = cmi_hdl_any()) == NULL) /* short-term hold */ 852 return (CMIERR_MC_ABSENT); 853 854 if ((mcops = cmi_hdl_getmcops(hdl)) == NULL || 855 mcops->cmi_mc_patounum == NULL) { 856 cmi_hdl_rele(hdl); 857 return (CMIERR_MC_NOTSUP); 858 } 859 860 rv = mcops->cmi_mc_patounum(cmi_hdl_getmcdata(hdl), pa, valid_hi, 861 valid_lo, synd, syndtype, up); 862 863 cmi_hdl_rele(hdl); 864 865 return (rv); 866 } 867 868 cmi_errno_t 869 cmi_mc_unumtopa(mc_unum_t *up, nvlist_t *nvl, uint64_t *pap) 870 { 871 const struct cmi_mc_ops *mcops; 872 cmi_hdl_t hdl; 873 cmi_errno_t rv; 874 nvlist_t *hcsp; 875 876 if (up != NULL && nvl != NULL) 877 return (CMIERR_API); /* convert from just one form */ 878 879 if (cmi_no_mca_init) 880 return (CMIERR_MC_ABSENT); 881 882 if (cmi_mc_global_ops != NULL) { 883 if (cmi_mc_global_ops->cmi_mc_unumtopa == NULL) 884 return (CMIERR_MC_NOTSUP); 885 return (cmi_mc_global_ops->cmi_mc_unumtopa(cmi_mc_global_data, 886 up, nvl, pap)); 887 } 888 889 if ((hdl = cmi_hdl_any()) == NULL) /* short-term hold */ 890 return (CMIERR_MC_ABSENT); 891 892 if ((mcops = cmi_hdl_getmcops(hdl)) == NULL || 893 mcops->cmi_mc_unumtopa == NULL) { 894 cmi_hdl_rele(hdl); 895 896 if (nvl != NULL && nvlist_lookup_nvlist(nvl, 897 FM_FMRI_HC_SPECIFIC, &hcsp) == 0 && 898 (nvlist_lookup_uint64(hcsp, 899 "asru-" FM_FMRI_HC_SPECIFIC_PHYSADDR, pap) == 0 || 900 nvlist_lookup_uint64(hcsp, FM_FMRI_HC_SPECIFIC_PHYSADDR, 901 pap) == 0)) { 902 return (CMIERR_MC_PARTIALUNUMTOPA); 903 } else { 904 return (mcops && mcops->cmi_mc_unumtopa == NULL ? 905 CMIERR_MC_NOTSUP : CMIERR_MC_ABSENT); 906 } 907 } 908 909 rv = mcops->cmi_mc_unumtopa(cmi_hdl_getmcdata(hdl), up, nvl, pap); 910 911 cmi_hdl_rele(hdl); 912 913 return (rv); 914 } 915 916 void 917 cmi_mc_logout(cmi_hdl_t hdl, boolean_t ismc, boolean_t sync) 918 { 919 const struct cmi_mc_ops *mcops; 920 921 if (cmi_no_mca_init) 922 return; 923 924 if (cmi_mc_global_ops != NULL) 925 mcops = cmi_mc_global_ops; 926 else 927 mcops = cmi_hdl_getmcops(hdl); 928 929 if (mcops != NULL && mcops->cmi_mc_logout != NULL) 930 mcops->cmi_mc_logout(hdl, ismc, sync); 931 } 932 933 cmi_errno_t 934 cmi_hdl_msrinject(cmi_hdl_t hdl, cmi_mca_regs_t *regs, uint_t nregs, 935 int force) 936 { 937 cmi_t *cmi = cmi_hdl_getcmi(hdl); 938 cmi_errno_t rc; 939 940 if (!CMI_OP_PRESENT(cmi, cmi_msrinject)) 941 return (CMIERR_NOTSUP); 942 943 cmi_hdl_inj_begin(hdl); 944 rc = CMI_OPS(cmi)->cmi_msrinject(hdl, regs, nregs, force); 945 cmi_hdl_inj_end(hdl); 946 947 return (rc); 948 } 949 950 boolean_t 951 cmi_panic_on_ue(void) 952 { 953 return (cmi_panic_on_uncorrectable_error ? B_TRUE : B_FALSE); 954 } 955 956 void 957 cmi_panic_callback(void) 958 { 959 cmi_hdl_t hdl; 960 cmi_t *cmi; 961 962 if (cmi_no_mca_init || (hdl = cmi_hdl_any()) == NULL) 963 return; 964 965 cmi = cmi_hdl_getcmi(hdl); 966 if (CMI_OP_PRESENT(cmi, cmi_panic_callback)) 967 CMI_OPS(cmi)->cmi_panic_callback(); 968 969 cmi_hdl_rele(hdl); 970 } 971 972 973 const char * 974 cmi_hdl_chipident(cmi_hdl_t hdl) 975 { 976 cmi_t *cmi = cmi_hdl_getcmi(hdl); 977 978 if (!CMI_OP_PRESENT(cmi, cmi_ident)) 979 return (NULL); 980 981 return (CMI_OPS(cmi)->cmi_ident(hdl)); 982 } 983