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