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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 23 /* 24 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 25 * Use is subject to license terms. 26 */ 27 28 #pragma ident "%Z%%M% %I% %E% SMI" 29 30 #include <sys/types.h> 31 #include <sys/regset.h> 32 #include <sys/privregs.h> 33 #include <sys/pci_impl.h> 34 #include <sys/cpuvar.h> 35 #include <sys/x86_archext.h> 36 #include <sys/cmn_err.h> 37 #include <sys/systm.h> 38 #include <sys/sysmacros.h> 39 #include <sys/chip.h> 40 #include <sys/cyclic.h> 41 #include <sys/cpu_module_impl.h> 42 #include <sys/pci_cfgspace_impl.h> 43 #include <sys/sysevent.h> 44 #include <sys/smbios.h> 45 #include <sys/mca_x86.h> 46 #include <sys/mca_amd.h> 47 #include <sys/mc.h> 48 #include <sys/psw.h> 49 #include <sys/ddi.h> 50 #include <sys/sunddi.h> 51 #include <sys/sdt.h> 52 #include <sys/fm/util.h> 53 #include <sys/fm/protocol.h> 54 #include <sys/fm/cpu/AMD.h> 55 56 #include "ao.h" 57 #include "ao_mca_disp.h" 58 59 errorq_t *ao_mca_queue; /* machine-check ereport queue */ 60 int ao_mca_stack_flag = 0; /* record stack trace in ereports */ 61 int ao_mca_smi_disable = 1; /* attempt to disable SMI polling */ 62 63 ao_bank_regs_t ao_bank_regs[AMD_MCA_BANK_COUNT] = { 64 { AMD_MSR_DC_STATUS, AMD_MSR_DC_ADDR }, 65 { AMD_MSR_IC_STATUS, AMD_MSR_IC_ADDR }, 66 { AMD_MSR_BU_STATUS, AMD_MSR_BU_ADDR }, 67 { AMD_MSR_LS_STATUS, AMD_MSR_LS_ADDR }, 68 { AMD_MSR_NB_STATUS, AMD_MSR_NB_ADDR } 69 }; 70 71 typedef struct ao_bank_cfg { 72 uint_t bank_ctl; 73 uint_t bank_ctl_mask; 74 uint64_t bank_ctl_init; 75 uint_t bank_status; 76 uint_t bank_addr; 77 } ao_bank_cfg_t; 78 79 static const ao_bank_cfg_t ao_bank_cfgs[] = { 80 { AMD_MSR_DC_CTL, AMD_MSR_DC_MASK, AMD_DC_CTL_INIT, AMD_MSR_DC_STATUS, 81 AMD_MSR_DC_ADDR }, 82 { AMD_MSR_IC_CTL, AMD_MSR_IC_MASK, AMD_IC_CTL_INIT, AMD_MSR_IC_STATUS, 83 AMD_MSR_IC_ADDR }, 84 { AMD_MSR_BU_CTL, AMD_MSR_BU_MASK, AMD_BU_CTL_INIT, AMD_MSR_BU_STATUS, 85 AMD_MSR_BU_ADDR }, 86 { AMD_MSR_LS_CTL, AMD_MSR_LS_MASK, AMD_LS_CTL_INIT, AMD_MSR_LS_STATUS, 87 AMD_MSR_LS_ADDR }, 88 { AMD_MSR_NB_CTL, AMD_MSR_NB_MASK, AMD_NB_CTL_INIT, AMD_MSR_NB_STATUS, 89 AMD_MSR_NB_ADDR } 90 }; 91 92 static const ao_error_disp_t ao_disp_unknown = { 93 FM_EREPORT_CPU_AMD_UNKNOWN, 94 FM_EREPORT_PAYLOAD_FLAGS_CPU_AMD_UNKNOWN 95 }; 96 97 /* 98 * This is quite awful but necessary to work around x86 system vendor's view of 99 * the world. Other operating systems (you know who you are) don't understand 100 * Opteron-specific error handling, so BIOS and system vendors often hide these 101 * conditions from them by using SMI polling to copy out any errors from the 102 * machine-check registers. When Solaris runs on a system with this feature, 103 * we want to disable the SMI polling so we can use FMA instead. Sadly, there 104 * isn't even a standard self-describing way to express the whole situation, 105 * so we have to resort to hard-coded values. This should all be changed to 106 * be a self-describing vendor-specific SMBIOS structure in the future. 107 */ 108 static const struct ao_smi_disable { 109 const char *asd_sys_vendor; /* SMB_TYPE_SYSTEM vendor prefix */ 110 const char *asd_bios_vendor; /* SMB_TYPE_BIOS vendor prefix */ 111 uint32_t asd_port; /* output port for SMI disable */ 112 uint32_t asd_code; /* output code for SMI disable */ 113 } ao_smi_disable[] = { 114 { "Sun Microsystems", "American Megatrends", 0x502F, 0x59 }, 115 { NULL, NULL, 0, 0 } 116 }; 117 118 static int 119 ao_disp_match_r4(uint16_t ref, uint8_t r4) 120 { 121 static const uint16_t ao_r4_map[] = { 122 AO_MCA_R4_BIT_GEN, /* AMD_ERRCODE_R4_GEN */ 123 AO_MCA_R4_BIT_RD, /* AMD_ERRCODE_R4_RD */ 124 AO_MCA_R4_BIT_WR, /* AMD_ERRCODE_R4_WR */ 125 AO_MCA_R4_BIT_DRD, /* AMD_ERRCODE_R4_DRD */ 126 AO_MCA_R4_BIT_DWR, /* AMD_ERRCODE_R4_DWR */ 127 AO_MCA_R4_BIT_IRD, /* AMD_ERRCODE_R4_IRD */ 128 AO_MCA_R4_BIT_PREFETCH, /* AMD_ERRCODE_R4_PREFETCH */ 129 AO_MCA_R4_BIT_EVICT, /* AMD_ERRCODE_R4_EVICT */ 130 AO_MCA_R4_BIT_SNOOP /* AMD_ERRCODE_R4_SNOOP */ 131 }; 132 133 ASSERT(r4 < sizeof (ao_r4_map) / sizeof (uint16_t)); 134 135 return ((ref & ao_r4_map[r4]) != 0); 136 } 137 138 static int 139 ao_disp_match_pp(uint8_t ref, uint8_t pp) 140 { 141 static const uint8_t ao_pp_map[] = { 142 AO_MCA_PP_BIT_SRC, /* AMD_ERRCODE_PP_SRC */ 143 AO_MCA_PP_BIT_RSP, /* AMD_ERRCODE_PP_RSP */ 144 AO_MCA_PP_BIT_OBS, /* AMD_ERRCODE_PP_OBS */ 145 AO_MCA_PP_BIT_GEN /* AMD_ERRCODE_PP_GEN */ 146 }; 147 148 ASSERT(pp < sizeof (ao_pp_map) / sizeof (uint8_t)); 149 150 return ((ref & ao_pp_map[pp]) != 0); 151 } 152 153 static int 154 ao_disp_match_ii(uint8_t ref, uint8_t ii) 155 { 156 static const uint8_t ao_ii_map[] = { 157 AO_MCA_II_BIT_MEM, /* AMD_ERRCODE_II_MEM */ 158 0, 159 AO_MCA_II_BIT_IO, /* AMD_ERRCODE_II_IO */ 160 AO_MCA_II_BIT_GEN /* AMD_ERRCODE_II_GEN */ 161 }; 162 163 ASSERT(ii < sizeof (ao_ii_map) / sizeof (uint8_t)); 164 165 return ((ref & ao_ii_map[ii]) != 0); 166 } 167 168 static uint8_t 169 bit_strip(uint16_t *codep, uint16_t mask, uint16_t shift) 170 { 171 uint8_t val = (*codep & mask) >> shift; 172 *codep &= ~mask; 173 return (val); 174 } 175 176 #define BIT_STRIP(codep, name) \ 177 bit_strip(codep, AMD_ERRCODE_##name##_MASK, AMD_ERRCODE_##name##_SHIFT) 178 179 static int 180 ao_disp_match_one(const ao_error_disp_t *aed, uint64_t status) 181 { 182 uint16_t code = status & AMD_ERRCODE_MASK; 183 uint8_t extcode = (status & AMD_ERREXT_MASK) >> AMD_ERREXT_SHIFT; 184 uint64_t stat_mask = aed->aed_stat_mask; 185 uint64_t stat_mask_res = aed->aed_stat_mask_res; 186 187 /* 188 * If the bank's status register indicates overflow, then we can no 189 * longer rely on the value of CECC: our experience with actual fault 190 * injection has shown that multiple CE's overwriting each other shows 191 * AMD_BANK_STAT_CECC and AMD_BANK_STAT_UECC both set to zero. This 192 * should be clarified in a future BKDG or by the Revision Guide. 193 */ 194 if (status & AMD_BANK_STAT_OVER) { 195 stat_mask &= ~AMD_BANK_STAT_CECC; 196 stat_mask_res &= ~AMD_BANK_STAT_CECC; 197 } 198 199 if ((status & stat_mask) != stat_mask_res) 200 return (0); 201 202 /* 203 * r4 and pp bits are stored separately, so we mask off and compare them 204 * for the code types that use them. Once we've taken the r4 and pp 205 * bits out of the equation, we can directly compare the resulting code 206 * with the one stored in the ao_error_disp_t. 207 */ 208 if (AMD_ERRCODE_ISMEM(code)) { 209 uint8_t r4 = BIT_STRIP(&code, R4); 210 211 if (!ao_disp_match_r4(aed->aed_stat_r4_bits, r4)) 212 return (0); 213 214 } else if (AMD_ERRCODE_ISBUS(code)) { 215 uint8_t r4 = BIT_STRIP(&code, R4); 216 uint8_t pp = BIT_STRIP(&code, PP); 217 uint8_t ii = BIT_STRIP(&code, II); 218 219 if (!ao_disp_match_r4(aed->aed_stat_r4_bits, r4) || 220 !ao_disp_match_pp(aed->aed_stat_pp_bits, pp) || 221 !ao_disp_match_ii(aed->aed_stat_ii_bits, ii)) 222 return (0); 223 } 224 225 return (code == aed->aed_stat_code && extcode == aed->aed_stat_extcode); 226 } 227 228 static const ao_error_disp_t * 229 ao_disp_match(uint_t bankno, uint64_t status) 230 { 231 const ao_error_disp_t *aed; 232 233 for (aed = ao_error_disp[bankno]; aed->aed_stat_mask != 0; aed++) { 234 if (ao_disp_match_one(aed, status)) 235 return (aed); 236 } 237 238 return (&ao_disp_unknown); 239 } 240 241 void 242 ao_pcicfg_write(uint_t chipid, uint_t func, uint_t reg, uint32_t val) 243 { 244 ASSERT(chipid + 24 <= 31); 245 ASSERT((func & 7) == func); 246 ASSERT((reg & 3) == 0 && reg < 256); 247 248 pci_mech1_putl(0, chipid + 24, func, reg, val); 249 } 250 251 uint32_t 252 ao_pcicfg_read(uint_t chipid, uint_t func, uint_t reg) 253 { 254 ASSERT(chipid + 24 <= 31); 255 ASSERT((func & 7) == func); 256 ASSERT((reg & 3) == 0 && reg < 256); 257 258 return (pci_mech1_getl(0, chipid + 24, func, reg)); 259 } 260 261 /* 262 * Setup individual bank detectors after stashing their bios settings. 263 */ 264 static void 265 ao_bank_cfg(ao_mca_t *mca) 266 { 267 ao_bios_cfg_t *bioscfg = &mca->ao_mca_bios_cfg; 268 const ao_bank_cfg_t *bankcfg = ao_bank_cfgs; 269 int i; 270 271 for (i = 0; i < AMD_MCA_BANK_COUNT; i++, bankcfg++) { 272 bioscfg->bcfg_bank_ctl[i] = rdmsr(bankcfg->bank_ctl); 273 bioscfg->bcfg_bank_mask[i] = rdmsr(bankcfg->bank_ctl_mask); 274 wrmsr(bankcfg->bank_ctl, bankcfg->bank_ctl_init); 275 } 276 } 277 278 /* 279 * Bits to be added to the NorthBridge (NB) configuration register. 280 * See BKDG 3.29 Section 3.6.4.2 for more information. 281 */ 282 uint32_t ao_nb_cfg_add = 283 AMD_NB_CFG_NBMCATOMSTCPUEN | 284 AMD_NB_CFG_DISPCICFGCPUERRRSP | 285 AMD_NB_CFG_SYNCONUCECCEN | 286 AMD_NB_CFG_CPUECCERREN; 287 288 /* 289 * Bits to be cleared from the NorthBridge (NB) configuration register. 290 * See BKDG 3.29 Section 3.6.4.2 for more information. 291 */ 292 uint32_t ao_nb_cfg_remove = 293 AMD_NB_CFG_IORDDATERREN | 294 AMD_NB_CFG_SYNCONANYERREN | 295 AMD_NB_CFG_SYNCONWDOGEN | 296 AMD_NB_CFG_IOERRDIS | 297 AMD_NB_CFG_IOMSTABORTDIS | 298 AMD_NB_CFG_SYNCPKTPROPDIS | 299 AMD_NB_CFG_SYNCPKTGENDIS; 300 301 /* 302 * Bits to be used if we configure the NorthBridge (NB) Watchdog. The watchdog 303 * triggers a machine check exception when no response to an NB system access 304 * occurs within a specified time interval. If the BIOS (i.e. platform design) 305 * has enabled the watchdog, we leave its rate alone. If the BIOS has not 306 * enabled the watchdog, we enable it and set the rate to one specified below. 307 * To disable the watchdog, add the AMD_NB_CFG_WDOGTMRDIS bit to ao_nb_cfg_add. 308 */ 309 uint32_t ao_nb_cfg_wdog = 310 AMD_NB_CFG_WDOGTMRCNTSEL_4095 | 311 AMD_NB_CFG_WDOGTMRBASESEL_1MS; 312 313 static void 314 ao_nb_cfg(ao_mca_t *mca) 315 { 316 uint_t chipid = chip_plat_get_chipid(CPU); 317 uint32_t val; 318 319 if (chip_plat_get_clogid(CPU) != 0) 320 return; /* only configure NB once per CPU */ 321 322 /* 323 * Read the NorthBridge (NB) configuration register in PCI space, 324 * modify the settings accordingly, and store the new value back. 325 */ 326 mca->ao_mca_bios_cfg.bcfg_nb_cfg = val = 327 ao_pcicfg_read(chipid, AMD_NB_FUNC, AMD_NB_REG_CFG); 328 329 /* 330 * If the watchdog was disabled, enable it according to the policy 331 * described above. Then apply the ao_nb_cfg_[add|remove] masks. 332 */ 333 if (val & AMD_NB_CFG_WDOGTMRDIS) { 334 val &= ~AMD_NB_CFG_WDOGTMRBASESEL_MASK; 335 val &= ~AMD_NB_CFG_WDOGTMRCNTSEL_MASK; 336 val &= ~AMD_NB_CFG_WDOGTMRDIS; 337 val |= ao_nb_cfg_wdog; 338 } 339 340 val &= ~ao_nb_cfg_remove; 341 val |= ao_nb_cfg_add; 342 343 ao_pcicfg_write(chipid, AMD_NB_FUNC, AMD_NB_REG_CFG, val); 344 } 345 346 /* 347 * Capture the machine-check exception state into our per-CPU logout area, and 348 * dispatch a copy of the logout area to our error queue for ereport creation. 349 * If 'rp' is non-NULL, we're being called from trap context; otherwise we're 350 * being polled or poked by the injector. We return the number of errors 351 * found through 'np', and a boolean indicating whether the error is fatal. 352 * The caller is expected to call fm_panic() if we return fatal (non-zero). 353 */ 354 int 355 ao_mca_logout(ao_cpu_logout_t *acl, struct regs *rp, int *np) 356 { 357 int i, fatal, n = 0; 358 359 acl->acl_timestamp = gethrtime_waitfree(); 360 acl->acl_mcg_status = rdmsr(IA32_MSR_MCG_STATUS); 361 acl->acl_ip = rp ? rp->r_pc : 0; 362 acl->acl_flags = 0; 363 364 /* 365 * Iterate over the banks of machine-check registers, read the address 366 * and status registers into the logout area, and clear them as we go. 367 */ 368 for (i = 0; i < AMD_MCA_BANK_COUNT; i++) { 369 ao_bank_logout_t *abl = &acl->acl_banks[i]; 370 371 abl->abl_addr = rdmsr(ao_bank_regs[i].abr_addr); 372 abl->abl_status = rdmsr(ao_bank_regs[i].abr_status); 373 374 if (abl->abl_status & AMD_BANK_STAT_VALID) 375 wrmsr(ao_bank_regs[i].abr_status, 0); 376 } 377 378 if (rp == NULL || !USERMODE(rp->r_cs)) 379 acl->acl_flags |= AO_ACL_F_PRIV; 380 381 if (ao_mca_stack_flag) 382 acl->acl_stackdepth = getpcstack(acl->acl_stack, FM_STK_DEPTH); 383 else 384 acl->acl_stackdepth = 0; 385 386 /* 387 * Clear MCG_STATUS, indicating that machine-check trap processing is 388 * complete. Once we do this, another machine-check trap can occur. 389 */ 390 wrmsr(IA32_MSR_MCG_STATUS, 0); 391 392 /* 393 * If we took a machine-check trap, then the error is fatal if the 394 * return instruction pointer is not valid in the global register. 395 */ 396 fatal = rp != NULL && !(acl->acl_mcg_status & MCG_STATUS_RIPV); 397 398 /* 399 * Now iterate over the saved logout area, determining whether the 400 * error that we saw is fatal or not based upon our dispositions 401 * and the hardware's indicators of whether or not we can resume. 402 */ 403 for (i = 0; i < AMD_MCA_BANK_COUNT; i++) { 404 ao_bank_logout_t *abl = &acl->acl_banks[i]; 405 const ao_error_disp_t *aed; 406 407 if (!(abl->abl_status & AMD_BANK_STAT_VALID)) 408 continue; 409 410 aed = ao_disp_match(i, abl->abl_status); 411 fatal |= (aed->aed_panic_when != AO_AED_PANIC_NEVER); 412 413 /* 414 * If we are taking a machine-check exception and the overflow 415 * bit is set or our context is corrupt, then we must die. 416 * NOTE: This code assumes that if the overflow bit is set and 417 * we didn't take a #mc exception (i.e. the poller found it), 418 * then multiple correctable errors overwrote each other. 419 * This will need to change if we eventually use the Opteron 420 * Rev E exception mechanism for detecting correctable errors. 421 */ 422 if (rp != NULL && (abl->abl_status & 423 (AMD_BANK_STAT_OVER | AMD_BANK_STAT_PCC))) 424 fatal = 1; 425 426 /* 427 * If we are taking a machine-check exception and we don't 428 * recognize the error case at all, then assume it's fatal. 429 * This will need to change if we eventually use the Opteron 430 * Rev E exception mechanism for detecting correctable errors. 431 */ 432 if (rp != NULL && aed == &ao_disp_unknown) 433 fatal = 1; 434 435 n++; 436 } 437 438 if (n > 0) { 439 errorq_dispatch(ao_mca_queue, acl, sizeof (ao_cpu_logout_t), 440 fatal && cmi_panic_on_uncorrectable_error ? 441 ERRORQ_SYNC : ERRORQ_ASYNC); 442 } 443 444 if (np != NULL) 445 *np = n; /* return number of errors found to caller */ 446 447 return (fatal); 448 } 449 450 static uint_t 451 ao_ereport_synd(ao_mca_t *mca, 452 const ao_bank_logout_t *abl, uint_t *typep, int is_nb) 453 { 454 if (is_nb) { 455 if ((mca->ao_mca_bios_cfg.bcfg_nb_cfg & 456 AMD_NB_CFG_CHIPKILLECCEN) != 0) { 457 *typep = AMD_SYNDTYPE_CHIPKILL; 458 return (AMD_NB_STAT_CKSYND(abl->abl_status)); 459 } else { 460 *typep = AMD_SYNDTYPE_ECC; 461 return (AMD_BANK_SYND(abl->abl_status)); 462 } 463 } else { 464 *typep = AMD_SYNDTYPE_ECC; 465 return (AMD_BANK_SYND(abl->abl_status)); 466 } 467 } 468 469 static void 470 ao_ereport_create_resource_elem(nvlist_t **nvlp, nv_alloc_t *nva, 471 mc_unum_t *unump, int dimmnum) 472 { 473 nvlist_t *snvl; 474 *nvlp = fm_nvlist_create(nva); /* freed by caller */ 475 476 snvl = fm_nvlist_create(nva); 477 478 (void) nvlist_add_uint64(snvl, FM_FMRI_HC_SPECIFIC_OFFSET, 479 unump->unum_offset); 480 481 fm_fmri_hc_set(*nvlp, FM_HC_SCHEME_VERSION, NULL, snvl, 4, 482 "motherboard", unump->unum_board, 483 "chip", unump->unum_chip, 484 "memory-controller", unump->unum_mc, 485 "dimm", unump->unum_dimms[dimmnum]); 486 487 fm_nvlist_destroy(snvl, FM_NVA_FREE); 488 } 489 490 static void 491 ao_ereport_add_resource(nvlist_t *payload, nv_alloc_t *nva, mc_unum_t *unump) 492 { 493 494 nvlist_t *elems[MC_UNUM_NDIMM]; 495 int nelems = 0; 496 int i; 497 498 for (i = 0; i < MC_UNUM_NDIMM; i++) { 499 if (unump->unum_dimms[i] == -1) 500 break; 501 ao_ereport_create_resource_elem(&elems[nelems++], nva, 502 unump, i); 503 } 504 505 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_RESOURCE, 506 DATA_TYPE_NVLIST_ARRAY, nelems, elems); 507 508 for (i = 0; i < nelems; i++) 509 fm_nvlist_destroy(elems[i], FM_NVA_FREE); 510 } 511 512 static void 513 ao_ereport_add_logout(ao_data_t *ao, nvlist_t *payload, nv_alloc_t *nva, 514 const ao_cpu_logout_t *acl, uint_t bankno, const ao_error_disp_t *aed) 515 { 516 uint64_t members = aed->aed_ereport_members; 517 ao_mca_t *mca = &ao->ao_mca; 518 const ao_bank_logout_t *abl = &acl->acl_banks[bankno]; 519 uint_t synd, syndtype; 520 521 synd = ao_ereport_synd(mca, abl, &syndtype, bankno == AMD_MCA_BANK_NB); 522 523 if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_STAT) { 524 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_STAT, 525 DATA_TYPE_UINT64, abl->abl_status, NULL); 526 } 527 528 if (members & FM_EREPORT_PAYLOAD_FLAG_BANK_NUM) { 529 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_BANK_NUM, 530 DATA_TYPE_UINT8, bankno, NULL); 531 } 532 533 if (members & FM_EREPORT_PAYLOAD_FLAG_ADDR) { 534 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ADDR, 535 DATA_TYPE_UINT64, abl->abl_addr, NULL); 536 } 537 538 if (members & FM_EREPORT_PAYLOAD_FLAG_ADDR_VALID) { 539 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_ADDR_VALID, 540 DATA_TYPE_BOOLEAN_VALUE, (abl->abl_status & 541 AMD_BANK_STAT_ADDRV) ? B_TRUE : B_FALSE); 542 } 543 544 if (members & FM_EREPORT_PAYLOAD_FLAG_SYND) { 545 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SYND, 546 DATA_TYPE_UINT16, synd, NULL); 547 } 548 549 if (members & FM_EREPORT_PAYLOAD_FLAG_SYND_TYPE) { 550 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_SYND_TYPE, 551 DATA_TYPE_STRING, (syndtype == AMD_SYNDTYPE_CHIPKILL ? 552 "C" : "E"), NULL); 553 } 554 555 if (members & FM_EREPORT_PAYLOAD_FLAG_IP) { 556 uint64_t ip = (acl->acl_mcg_status & MCG_STATUS_EIPV) ? 557 acl->acl_ip : 0; 558 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_IP, 559 DATA_TYPE_UINT64, ip, NULL); 560 } 561 562 if (members & FM_EREPORT_PAYLOAD_FLAG_PRIV) { 563 fm_payload_set(payload, FM_EREPORT_PAYLOAD_NAME_PRIV, 564 DATA_TYPE_BOOLEAN_VALUE, (acl->acl_flags & AO_ACL_F_PRIV) ? 565 B_TRUE : B_FALSE, NULL); 566 } 567 568 if (members & FM_EREPORT_PAYLOAD_FLAG_RESOURCE) { 569 mc_unum_t unum; 570 int addrvalid; 571 572 addrvalid = (members & FM_EREPORT_PAYLOAD_FLAG_ADDR) && 573 (members & FM_EREPORT_PAYLOAD_FLAG_ADDR_VALID) && 574 (abl->abl_status & AMD_BANK_STAT_ADDRV); 575 576 if (addrvalid && ao_mc_patounum(ao, abl->abl_addr, synd, 577 syndtype, &unum)) 578 ao_ereport_add_resource(payload, nva, &unum); 579 } 580 581 if (ao_mca_stack_flag && members & FM_EREPORT_PAYLOAD_FLAG_STACK) { 582 fm_payload_stack_add(payload, acl->acl_stack, 583 acl->acl_stackdepth); 584 } 585 } 586 587 static void 588 ao_ereport_post(const ao_cpu_logout_t *acl, 589 int bankno, const ao_error_disp_t *aed) 590 { 591 ao_data_t *ao = acl->acl_ao; 592 errorq_elem_t *eqep; 593 nvlist_t *ereport, *detector; 594 nv_alloc_t *nva = NULL; 595 char buf[FM_MAX_CLASS]; 596 597 if (panicstr) { 598 if ((eqep = errorq_reserve(ereport_errorq)) == NULL) 599 return; 600 ereport = errorq_elem_nvl(ereport_errorq, eqep); 601 nva = errorq_elem_nva(ereport_errorq, eqep); 602 } else { 603 ereport = fm_nvlist_create(nva); 604 } 605 606 /* 607 * Create the scheme "cpu" FMRI 608 */ 609 detector = ao_fmri_create(ao, nva); 610 611 /* 612 * Encode all the common data into the ereport. 613 */ 614 (void) snprintf(buf, FM_MAX_CLASS, "%s.%s.%s", 615 FM_ERROR_CPU, "amd", aed->aed_class); 616 617 fm_ereport_set(ereport, FM_EREPORT_VERSION, buf, 618 fm_ena_generate_cpu(acl->acl_timestamp, ao->ao_cpu->cpu_id, 619 FM_ENA_FMT1), detector, NULL); 620 621 /* 622 * Encode the error-specific data that was saved in the logout area. 623 */ 624 ao_ereport_add_logout(ao, ereport, nva, acl, bankno, aed); 625 626 if (panicstr) { 627 errorq_commit(ereport_errorq, eqep, ERRORQ_SYNC); 628 } else { 629 (void) fm_ereport_post(ereport, EVCH_TRYHARD); 630 fm_nvlist_destroy(ereport, FM_NVA_FREE); 631 fm_nvlist_destroy(detector, FM_NVA_FREE); 632 } 633 } 634 635 /*ARGSUSED*/ 636 void 637 ao_mca_drain(void *ignored, const void *data, const errorq_elem_t *eqe) 638 { 639 const ao_cpu_logout_t *acl = data; 640 int i; 641 642 for (i = 0; i < AMD_MCA_BANK_COUNT; i++) { 643 const ao_bank_logout_t *abl = &acl->acl_banks[i]; 644 const ao_error_disp_t *aed; 645 646 if (abl->abl_status & AMD_BANK_STAT_VALID) { 647 aed = ao_disp_match(i, abl->abl_status); 648 ao_ereport_post(acl, i, aed); 649 } 650 } 651 } 652 653 int 654 ao_mca_trap(void *data, struct regs *rp) 655 { 656 ao_data_t *ao = data; 657 ao_mca_t *mca = &ao->ao_mca; 658 ao_cpu_logout_t *acl = &mca->ao_mca_logout[AO_MCA_LOGOUT_EXCEPTION]; 659 return (ao_mca_logout(acl, rp, NULL)); 660 } 661 662 /*ARGSUSED*/ 663 int 664 ao_mca_inject(void *data, cmi_mca_regs_t *regs, uint_t nregs) 665 { 666 uint64_t hwcr, oldhwcr; 667 int i; 668 669 oldhwcr = rdmsr(MSR_AMD_HWCR); 670 hwcr = oldhwcr | AMD_HWCR_MCI_STATUS_WREN; 671 wrmsr(MSR_AMD_HWCR, hwcr); 672 673 for (i = 0; i < nregs; i++) 674 wrmsr(regs[i].cmr_msrnum, regs[i].cmr_msrval); 675 676 wrmsr(MSR_AMD_HWCR, oldhwcr); 677 return (0); 678 } 679 680 void 681 ao_mca_init(void *data) 682 { 683 ao_data_t *ao = data; 684 ao_mca_t *mca = &ao->ao_mca; 685 uint64_t cap; 686 int i; 687 688 ao_mca_poll_init(mca); 689 690 ASSERT(x86_feature & X86_MCA); 691 cap = rdmsr(IA32_MSR_MCG_CAP); 692 ASSERT(cap & MCG_CAP_CTL_P); 693 694 /* 695 * If the hardware's bank count is different than what we expect, then 696 * we're running on some Opteron variant that we don't understand yet. 697 */ 698 if ((cap & MCG_CAP_COUNT_MASK) != AMD_MCA_BANK_COUNT) { 699 cmn_err(CE_WARN, "CPU %d has %llu MCA banks; expected %u: " 700 "disabling MCA on this CPU", ao->ao_cpu->cpu_id, 701 (u_longlong_t)cap & MCG_CAP_COUNT_MASK, AMD_MCA_BANK_COUNT); 702 return; 703 } 704 705 /* 706 * Configure the logout areas. We preset every logout area's acl_ao 707 * pointer to refer back to our per-CPU state for errorq drain usage. 708 */ 709 for (i = 0; i < AO_MCA_LOGOUT_NUM; i++) 710 mca->ao_mca_logout[i].acl_ao = ao; 711 712 ao_bank_cfg(mca); 713 ao_nb_cfg(mca); 714 715 wrmsr(IA32_MSR_MCG_CTL, AMD_MCG_EN_ALL); 716 717 /* 718 * Throw away all existing bank state. We do this because some BIOSes, 719 * perhaps during POST, do things to the machine that cause MCA state 720 * to be updated. If we interpret this state as an actual error, we 721 * may end up indicting something that's not actually broken. 722 */ 723 for (i = 0; i < sizeof (ao_bank_cfgs) / sizeof (ao_bank_cfg_t); i++) 724 wrmsr(ao_bank_cfgs[i].bank_status, 0ULL); 725 726 wrmsr(IA32_MSR_MCG_STATUS, 0ULL); 727 membar_producer(); 728 729 setcr4(getcr4() | CR4_MCE); /* enable #mc exceptions */ 730 } 731 732 /*ARGSUSED*/ 733 void 734 ao_mca_post_init(void *data) 735 { 736 const struct ao_smi_disable *asd; 737 id_t id; 738 739 smbios_system_t sy; 740 smbios_bios_t sb; 741 smbios_info_t si; 742 743 /* 744 * Fetch the System and BIOS vendor strings from SMBIOS and see if they 745 * match a value in our table. If so, disable SMI error polling. This 746 * is grotesque and should be replaced by self-describing vendor- 747 * specific SMBIOS data or a specification enhancement instead. 748 */ 749 if (ao_mca_smi_disable && ksmbios != NULL && 750 smbios_info_bios(ksmbios, &sb) != SMB_ERR && 751 (id = smbios_info_system(ksmbios, &sy)) != SMB_ERR && 752 smbios_info_common(ksmbios, id, &si) != SMB_ERR) { 753 754 for (asd = ao_smi_disable; asd->asd_sys_vendor != NULL; asd++) { 755 if (strncmp(asd->asd_sys_vendor, si.smbi_manufacturer, 756 strlen(asd->asd_sys_vendor)) != 0 || 757 strncmp(asd->asd_bios_vendor, sb.smbb_vendor, 758 strlen(asd->asd_bios_vendor)) != 0) 759 continue; 760 761 cmn_err(CE_CONT, "?SMI polling disabled in favor of " 762 "Solaris Fault Management for AMD Processors"); 763 764 outl(asd->asd_port, asd->asd_code); 765 break; 766 } 767 } 768 769 ao_mca_poll_start(); 770 } 771 772 /* 773 * Called after a CPU has been marked with CPU_FAULTED. Not called on the 774 * faulted CPU. cpu_lock is held. 775 */ 776 /*ARGSUSED*/ 777 void 778 ao_faulted_enter(void *data) 779 { 780 /* 781 * Nothing to do here. We'd like to turn off the faulted CPU's 782 * correctable error detectors, but that can only be done by the 783 * faulted CPU itself. cpu_get_state() will now return P_FAULTED, 784 * allowing the poller to skip this CPU until it is re-enabled. 785 */ 786 } 787 788 /* 789 * Called after the CPU_FAULTED bit has been cleared from a previously-faulted 790 * CPU. Not called on the faulted CPU. cpu_lock is held. 791 */ 792 void 793 ao_faulted_exit(void *data) 794 { 795 ao_data_t *ao = data; 796 797 /* 798 * We'd like to clear the faulted CPU's MCi_STATUS registers so as to 799 * avoid generating ereports for errors which occurred while the CPU was 800 * officially faulted. Unfortunately, those registers can only be 801 * cleared by the CPU itself, so we can't do it here. 802 * 803 * We're going to set the UNFAULTING bit on the formerly-faulted CPU's 804 * MCA state. This will tell the poller that the MCi_STATUS registers 805 * can't yet be trusted. The poller, which is the first thing we 806 * control that'll execute on that CPU, will clear the registers, and 807 * will then clear the bit. 808 */ 809 810 ao->ao_mca.ao_mca_flags |= AO_MCA_F_UNFAULTING; 811 } 812