1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD 3 * 4 * Copyright (c) 2020 Alexander Motin <mav@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/cdefs.h> 29 __FBSDID("$FreeBSD$"); 30 31 #include "opt_acpi.h" 32 #include "opt_pci.h" 33 34 #include <sys/param.h> 35 #include <sys/systm.h> 36 #include <sys/bus.h> 37 #include <sys/callout.h> 38 #include <sys/interrupt.h> 39 #include <sys/kernel.h> 40 #include <sys/malloc.h> 41 #include <sys/module.h> 42 #include <sys/queue.h> 43 #include <sys/rman.h> 44 #include <vm/vm.h> 45 #include <vm/pmap.h> 46 47 #include <contrib/dev/acpica/include/acpi.h> 48 #include <contrib/dev/acpica/include/accommon.h> 49 #include <contrib/dev/acpica/include/aclocal.h> 50 #include <contrib/dev/acpica/include/actables.h> 51 52 #include <dev/acpica/acpivar.h> 53 #include <dev/pci/pcireg.h> 54 #include <dev/pci/pcivar.h> 55 56 struct apei_ge { 57 union { 58 ACPI_HEST_GENERIC v1; 59 ACPI_HEST_GENERIC_V2 v2; 60 }; 61 int res_type; 62 int res_rid; 63 struct resource *res; 64 int res2_type; 65 int res2_rid; 66 struct resource *res2; 67 uint8_t *buf, *copybuf; 68 TAILQ_ENTRY(apei_ge) link; 69 TAILQ_ENTRY(apei_ge) nlink; 70 }; 71 72 /* NMI */ 73 struct apei_nges { 74 void *swi_ih; 75 TAILQ_HEAD(, apei_ge) ges; 76 } *apei_nmi_nges; 77 78 /* Interrupt */ 79 struct apei_iges { 80 TAILQ_HEAD(, apei_ge) ges; 81 }; 82 83 /* Polling */ 84 struct apei_pges { 85 sbintime_t interval; 86 struct callout poll; 87 TAILQ_HEAD(, apei_ge) ges; 88 }; 89 90 struct apei_softc { 91 ACPI_TABLE_HEST *hest; 92 TAILQ_HEAD(, apei_ge) ges; 93 struct apei_nges nges; 94 struct apei_iges iges; 95 struct apei_pges pges[32]; 96 }; 97 98 struct apei_mem_error { 99 uint64_t ValidationBits; 100 uint64_t ErrorStatus; 101 uint64_t PhysicalAddress; 102 uint64_t PhysicalAddressMask; 103 uint16_t Node; 104 uint16_t Card; 105 uint16_t Module; 106 uint16_t Bank; 107 uint16_t Device; 108 uint16_t Row; 109 uint16_t Column; 110 uint16_t BitPosition; 111 uint64_t RequesterID; 112 uint64_t ResponderID; 113 uint64_t TargetID; 114 uint8_t MemoryErrorType; 115 uint8_t Extended; 116 uint16_t RankNumber; 117 uint16_t CardHandle; 118 uint16_t ModuleHandle; 119 }; 120 121 struct apei_pcie_error { 122 uint64_t ValidationBits; 123 uint32_t PortType; 124 uint32_t Version; 125 uint32_t CommandStatus; 126 uint32_t Reserved; 127 uint8_t DeviceID[16]; 128 uint8_t DeviceSerialNumber[8]; 129 uint8_t BridgeControlStatus[4]; 130 uint8_t CapabilityStructure[60]; 131 uint8_t AERInfo[96]; 132 }; 133 134 #ifdef __i386__ 135 static __inline uint64_t 136 apei_bus_read_8(struct resource *res, bus_size_t offset) 137 { 138 return (bus_read_4(res, offset) | 139 ((uint64_t)bus_read_4(res, offset + 4)) << 32); 140 } 141 static __inline void 142 apei_bus_write_8(struct resource *res, bus_size_t offset, uint64_t val) 143 { 144 bus_write_4(res, offset, val); 145 bus_write_4(res, offset + 4, val >> 32); 146 } 147 #define READ8(r, o) apei_bus_read_8((r), (o)) 148 #define WRITE8(r, o, v) apei_bus_write_8((r), (o), (v)) 149 #else 150 #define READ8(r, o) bus_read_8((r), (o)) 151 #define WRITE8(r, o, v) bus_write_8((r), (o), (v)) 152 #endif 153 154 #define GED_SIZE(ged) ((ged)->Revision >= 0x300 ? \ 155 sizeof(ACPI_HEST_GENERIC_DATA_V300) : sizeof(ACPI_HEST_GENERIC_DATA)) 156 #define GED_DATA(ged) ((uint8_t *)(ged) + GED_SIZE(ged)) 157 158 #define PGE_ID(ge) (fls(MAX(1, (ge)->v1.Notify.PollInterval)) - 1) 159 160 int apei_nmi_handler(void); 161 162 static const char * 163 apei_severity(uint32_t s) 164 { 165 switch (s) { 166 case ACPI_HEST_GEN_ERROR_RECOVERABLE: 167 return ("Recoverable"); 168 case ACPI_HEST_GEN_ERROR_FATAL: 169 return ("Fatal"); 170 case ACPI_HEST_GEN_ERROR_CORRECTED: 171 return ("Corrected"); 172 case ACPI_HEST_GEN_ERROR_NONE: 173 return ("Informational"); 174 } 175 return ("???"); 176 } 177 178 static int 179 apei_mem_handler(ACPI_HEST_GENERIC_DATA *ged) 180 { 181 struct apei_mem_error *p = (struct apei_mem_error *)GED_DATA(ged); 182 183 printf("APEI %s Memory Error:\n", apei_severity(ged->ErrorSeverity)); 184 if (p->ValidationBits & 0x01) 185 printf(" Error Status: 0x%jx\n", p->ErrorStatus); 186 if (p->ValidationBits & 0x02) 187 printf(" Physical Address: 0x%jx\n", p->PhysicalAddress); 188 if (p->ValidationBits & 0x04) 189 printf(" Physical Address Mask: 0x%jx\n", p->PhysicalAddressMask); 190 if (p->ValidationBits & 0x08) 191 printf(" Node: %u\n", p->Node); 192 if (p->ValidationBits & 0x10) 193 printf(" Card: %u\n", p->Card); 194 if (p->ValidationBits & 0x20) 195 printf(" Module: %u\n", p->Module); 196 if (p->ValidationBits & 0x40) 197 printf(" Bank: %u\n", p->Bank); 198 if (p->ValidationBits & 0x80) 199 printf(" Device: %u\n", p->Device); 200 if (p->ValidationBits & 0x100) 201 printf(" Row: %u\n", p->Row); 202 if (p->ValidationBits & 0x200) 203 printf(" Column: %u\n", p->Column); 204 if (p->ValidationBits & 0x400) 205 printf(" Bit Position: %u\n", p->BitPosition); 206 if (p->ValidationBits & 0x800) 207 printf(" Requester ID: 0x%jx\n", p->RequesterID); 208 if (p->ValidationBits & 0x1000) 209 printf(" Responder ID: 0x%jx\n", p->ResponderID); 210 if (p->ValidationBits & 0x2000) 211 printf(" Target ID: 0x%jx\n", p->TargetID); 212 if (p->ValidationBits & 0x4000) 213 printf(" Memory Error Type: %u\n", p->MemoryErrorType); 214 if (p->ValidationBits & 0x8000) 215 printf(" Rank Number: %u\n", p->RankNumber); 216 if (p->ValidationBits & 0x10000) 217 printf(" Card Handle: 0x%x\n", p->CardHandle); 218 if (p->ValidationBits & 0x20000) 219 printf(" Module Handle: 0x%x\n", p->ModuleHandle); 220 if (p->ValidationBits & 0x40000) 221 printf(" Extended Row: %u\n", 222 (uint32_t)(p->Extended & 0x3) << 16 | p->Row); 223 if (p->ValidationBits & 0x80000) 224 printf(" Bank Group: %u\n", p->Bank >> 8); 225 if (p->ValidationBits & 0x100000) 226 printf(" Bank Address: %u\n", p->Bank & 0xff); 227 if (p->ValidationBits & 0x200000) 228 printf(" Chip Identification: %u\n", (p->Extended >> 5) & 0x7); 229 230 return (0); 231 } 232 233 static int 234 apei_pcie_handler(ACPI_HEST_GENERIC_DATA *ged) 235 { 236 struct apei_pcie_error *p = (struct apei_pcie_error *)GED_DATA(ged); 237 int h = 0, off; 238 #ifdef DEV_PCI 239 device_t dev; 240 int sev; 241 242 if ((p->ValidationBits & 0x8) == 0x8) { 243 mtx_lock(&Giant); 244 dev = pci_find_dbsf((uint32_t)p->DeviceID[10] << 8 | 245 p->DeviceID[9], p->DeviceID[11], p->DeviceID[8], 246 p->DeviceID[7]); 247 if (dev != NULL) { 248 switch (ged->ErrorSeverity) { 249 case ACPI_HEST_GEN_ERROR_FATAL: 250 sev = PCIEM_STA_FATAL_ERROR; 251 break; 252 case ACPI_HEST_GEN_ERROR_RECOVERABLE: 253 sev = PCIEM_STA_NON_FATAL_ERROR; 254 break; 255 default: 256 sev = PCIEM_STA_CORRECTABLE_ERROR; 257 break; 258 } 259 pcie_apei_error(dev, sev, 260 (p->ValidationBits & 0x80) ? p->AERInfo : NULL); 261 h = 1; 262 } 263 mtx_unlock(&Giant); 264 } 265 if (h) 266 return (h); 267 #endif 268 269 printf("APEI %s PCIe Error:\n", apei_severity(ged->ErrorSeverity)); 270 if (p->ValidationBits & 0x01) 271 printf(" Port Type: %u\n", p->PortType); 272 if (p->ValidationBits & 0x02) 273 printf(" Version: %x\n", p->Version); 274 if (p->ValidationBits & 0x04) 275 printf(" Command Status: 0x%08x\n", p->CommandStatus); 276 if (p->ValidationBits & 0x08) { 277 printf(" DeviceID:"); 278 for (off = 0; off < sizeof(p->DeviceID); off++) 279 printf(" %02x", p->DeviceID[off]); 280 printf("\n"); 281 } 282 if (p->ValidationBits & 0x10) { 283 printf(" Device Serial Number:"); 284 for (off = 0; off < sizeof(p->DeviceSerialNumber); off++) 285 printf(" %02x", p->DeviceSerialNumber[off]); 286 printf("\n"); 287 } 288 if (p->ValidationBits & 0x20) { 289 printf(" Bridge Control Status:"); 290 for (off = 0; off < sizeof(p->BridgeControlStatus); off++) 291 printf(" %02x", p->BridgeControlStatus[off]); 292 printf("\n"); 293 } 294 if (p->ValidationBits & 0x40) { 295 printf(" Capability Structure:\n"); 296 for (off = 0; off < sizeof(p->CapabilityStructure); off++) { 297 printf(" %02x", p->CapabilityStructure[off]); 298 if ((off % 16) == 15 || 299 off + 1 == sizeof(p->CapabilityStructure)) 300 printf("\n"); 301 } 302 } 303 if (p->ValidationBits & 0x80) { 304 printf(" AER Info:\n"); 305 for (off = 0; off < sizeof(p->AERInfo); off++) { 306 printf(" %02x", p->AERInfo[off]); 307 if ((off % 16) == 15 || off + 1 == sizeof(p->AERInfo)) 308 printf("\n"); 309 } 310 } 311 return (h); 312 } 313 314 static void 315 apei_ged_handler(ACPI_HEST_GENERIC_DATA *ged) 316 { 317 ACPI_HEST_GENERIC_DATA_V300 *ged3 = (ACPI_HEST_GENERIC_DATA_V300 *)ged; 318 /* A5BC1114-6F64-4EDE-B863-3E83ED7C83B1 */ 319 static uint8_t mem_uuid[ACPI_UUID_LENGTH] = { 320 0x14, 0x11, 0xBC, 0xA5, 0x64, 0x6F, 0xDE, 0x4E, 321 0xB8, 0x63, 0x3E, 0x83, 0xED, 0x7C, 0x83, 0xB1 322 }; 323 /* D995E954-BBC1-430F-AD91-B44DCB3C6F35 */ 324 static uint8_t pcie_uuid[ACPI_UUID_LENGTH] = { 325 0x54, 0xE9, 0x95, 0xD9, 0xC1, 0xBB, 0x0F, 0x43, 326 0xAD, 0x91, 0xB4, 0x4D, 0xCB, 0x3C, 0x6F, 0x35 327 }; 328 uint8_t *t; 329 int h = 0, off; 330 331 if (memcmp(mem_uuid, ged->SectionType, ACPI_UUID_LENGTH) == 0) { 332 h = apei_mem_handler(ged); 333 } else if (memcmp(pcie_uuid, ged->SectionType, ACPI_UUID_LENGTH) == 0) { 334 h = apei_pcie_handler(ged); 335 } else { 336 t = ged->SectionType; 337 printf("APEI %s Error %02x%02x%02x%02x-%02x%02x-" 338 "%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x:\n", 339 apei_severity(ged->ErrorSeverity), 340 t[3], t[2], t[1], t[0], t[5], t[4], t[7], t[6], 341 t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); 342 printf(" Error Data:\n"); 343 t = (uint8_t *)GED_DATA(ged); 344 for (off = 0; off < ged->ErrorDataLength; off++) { 345 printf(" %02x", t[off]); 346 if ((off % 16) == 15 || off + 1 == ged->ErrorDataLength) 347 printf("\n"); 348 } 349 } 350 if (h) 351 return; 352 353 printf(" Flags: 0x%x\n", ged->Flags); 354 if (ged->ValidationBits & ACPI_HEST_GEN_VALID_FRU_ID) { 355 t = ged->FruId; 356 printf(" FRU Id: %02x%02x%02x%02x-%02x%02x-%02x%02x-" 357 "%02x%02x-%02x%02x%02x%02x%02x%02x\n", 358 t[3], t[2], t[1], t[0], t[5], t[4], t[7], t[6], 359 t[8], t[9], t[10], t[11], t[12], t[13], t[14], t[15]); 360 } 361 if (ged->ValidationBits & ACPI_HEST_GEN_VALID_FRU_STRING) 362 printf(" FRU Text: %.20s\n", ged->FruText); 363 if (ged->Revision >= 0x300 && 364 ged->ValidationBits & ACPI_HEST_GEN_VALID_TIMESTAMP) 365 printf(" Timestamp: %016jx\n", ged3->TimeStamp); 366 } 367 368 static int 369 apei_ge_handler(struct apei_ge *ge, bool copy) 370 { 371 uint8_t *buf = copy ? ge->copybuf : ge->buf; 372 ACPI_HEST_GENERIC_STATUS *ges = (ACPI_HEST_GENERIC_STATUS *)buf; 373 ACPI_HEST_GENERIC_DATA *ged; 374 uint32_t sev; 375 int i, c, off; 376 377 if (ges == NULL || ges->BlockStatus == 0) 378 return (0); 379 380 c = (ges->BlockStatus >> 4) & 0x3ff; 381 sev = ges->ErrorSeverity; 382 383 /* Process error entries. */ 384 for (off = i = 0; i < c && off + sizeof(*ged) <= ges->DataLength; i++) { 385 ged = (ACPI_HEST_GENERIC_DATA *)&buf[sizeof(*ges) + off]; 386 apei_ged_handler(ged); 387 off += GED_SIZE(ged) + ged->ErrorDataLength; 388 } 389 390 /* Acknowledge the error has been processed. */ 391 ges->BlockStatus = 0; 392 if (!copy && ge->v1.Header.Type == ACPI_HEST_TYPE_GENERIC_ERROR_V2 && 393 ge->res2) { 394 uint64_t val = READ8(ge->res2, 0); 395 val &= ge->v2.ReadAckPreserve; 396 val |= ge->v2.ReadAckWrite; 397 WRITE8(ge->res2, 0, val); 398 } 399 400 /* If ACPI told the error is fatal -- make it so. */ 401 if (sev == ACPI_HEST_GEN_ERROR_FATAL) 402 panic("APEI Fatal Hardware Error!"); 403 404 return (1); 405 } 406 407 static void 408 apei_nmi_swi(void *arg) 409 { 410 struct apei_nges *nges = arg; 411 struct apei_ge *ge; 412 413 TAILQ_FOREACH(ge, &nges->ges, nlink) 414 apei_ge_handler(ge, true); 415 } 416 417 int 418 apei_nmi_handler(void) 419 { 420 struct apei_nges *nges = apei_nmi_nges; 421 struct apei_ge *ge; 422 ACPI_HEST_GENERIC_STATUS *ges, *gesc; 423 int handled = 0; 424 425 if (nges == NULL) 426 return (0); 427 428 TAILQ_FOREACH(ge, &nges->ges, nlink) { 429 ges = (ACPI_HEST_GENERIC_STATUS *)ge->buf; 430 if (ges == NULL || ges->BlockStatus == 0) 431 continue; 432 433 /* If ACPI told the error is fatal -- make it so. */ 434 if (ges->ErrorSeverity == ACPI_HEST_GEN_ERROR_FATAL) 435 panic("APEI Fatal Hardware Error!"); 436 437 /* Copy the buffer for later processing. */ 438 gesc = (ACPI_HEST_GENERIC_STATUS *)ge->copybuf; 439 if (gesc->BlockStatus == 0) 440 memcpy(ge->copybuf, ge->buf, ge->v1.ErrorBlockLength); 441 442 /* Acknowledge the error has been processed. */ 443 ges->BlockStatus = 0; 444 if (ge->v1.Header.Type == ACPI_HEST_TYPE_GENERIC_ERROR_V2 && 445 ge->res2) { 446 uint64_t val = READ8(ge->res2, 0); 447 val &= ge->v2.ReadAckPreserve; 448 val |= ge->v2.ReadAckWrite; 449 WRITE8(ge->res2, 0, val); 450 } 451 handled = 1; 452 } 453 454 /* Schedule SWI for real handling. */ 455 if (handled) 456 swi_sched(nges->swi_ih, SWI_FROMNMI); 457 458 return (handled); 459 } 460 461 static void 462 apei_callout_handler(void *context) 463 { 464 struct apei_pges *pges = context; 465 struct apei_ge *ge; 466 467 TAILQ_FOREACH(ge, &pges->ges, nlink) 468 apei_ge_handler(ge, false); 469 callout_schedule_sbt(&pges->poll, pges->interval, pges->interval, 0); 470 } 471 472 static void 473 apei_notify_handler(ACPI_HANDLE h, UINT32 notify, void *context) 474 { 475 device_t dev = context; 476 struct apei_softc *sc = device_get_softc(dev); 477 struct apei_ge *ge; 478 479 TAILQ_FOREACH(ge, &sc->iges.ges, nlink) 480 apei_ge_handler(ge, false); 481 } 482 483 static int 484 hest_parse_structure(struct apei_softc *sc, void *addr, int remaining) 485 { 486 ACPI_HEST_HEADER *hdr = addr; 487 struct apei_ge *ge; 488 489 if (remaining < (int)sizeof(ACPI_HEST_HEADER)) 490 return (-1); 491 492 switch (hdr->Type) { 493 case ACPI_HEST_TYPE_IA32_CHECK: { 494 ACPI_HEST_IA_MACHINE_CHECK *s = addr; 495 return (sizeof(*s) + s->NumHardwareBanks * 496 sizeof(ACPI_HEST_IA_ERROR_BANK)); 497 } 498 case ACPI_HEST_TYPE_IA32_CORRECTED_CHECK: { 499 ACPI_HEST_IA_CORRECTED *s = addr; 500 return (sizeof(*s) + s->NumHardwareBanks * 501 sizeof(ACPI_HEST_IA_ERROR_BANK)); 502 } 503 case ACPI_HEST_TYPE_IA32_NMI: { 504 ACPI_HEST_IA_NMI *s = addr; 505 return (sizeof(*s)); 506 } 507 case ACPI_HEST_TYPE_AER_ROOT_PORT: { 508 ACPI_HEST_AER_ROOT *s = addr; 509 return (sizeof(*s)); 510 } 511 case ACPI_HEST_TYPE_AER_ENDPOINT: { 512 ACPI_HEST_AER *s = addr; 513 return (sizeof(*s)); 514 } 515 case ACPI_HEST_TYPE_AER_BRIDGE: { 516 ACPI_HEST_AER_BRIDGE *s = addr; 517 return (sizeof(*s)); 518 } 519 case ACPI_HEST_TYPE_GENERIC_ERROR: { 520 ACPI_HEST_GENERIC *s = addr; 521 ge = malloc(sizeof(*ge), M_DEVBUF, M_WAITOK | M_ZERO); 522 ge->v1 = *s; 523 TAILQ_INSERT_TAIL(&sc->ges, ge, link); 524 return (sizeof(*s)); 525 } 526 case ACPI_HEST_TYPE_GENERIC_ERROR_V2: { 527 ACPI_HEST_GENERIC_V2 *s = addr; 528 ge = malloc(sizeof(*ge), M_DEVBUF, M_WAITOK | M_ZERO); 529 ge->v2 = *s; 530 TAILQ_INSERT_TAIL(&sc->ges, ge, link); 531 return (sizeof(*s)); 532 } 533 case ACPI_HEST_TYPE_IA32_DEFERRED_CHECK: { 534 ACPI_HEST_IA_DEFERRED_CHECK *s = addr; 535 return (sizeof(*s) + s->NumHardwareBanks * 536 sizeof(ACPI_HEST_IA_ERROR_BANK)); 537 } 538 default: 539 return (-1); 540 } 541 } 542 543 static void 544 hest_parse_table(struct apei_softc *sc) 545 { 546 ACPI_TABLE_HEST *hest = sc->hest; 547 char *cp; 548 int remaining, consumed; 549 550 remaining = hest->Header.Length - sizeof(ACPI_TABLE_HEST); 551 while (remaining > 0) { 552 cp = (char *)hest + hest->Header.Length - remaining; 553 consumed = hest_parse_structure(sc, cp, remaining); 554 if (consumed <= 0) 555 break; 556 else 557 remaining -= consumed; 558 } 559 } 560 561 static char *apei_ids[] = { "PNP0C33", NULL }; 562 static devclass_t apei_devclass; 563 564 static ACPI_STATUS 565 apei_find(ACPI_HANDLE handle, UINT32 level, void *context, 566 void **status) 567 { 568 int *found = (int *)status; 569 char **ids; 570 571 for (ids = apei_ids; *ids != NULL; ids++) { 572 if (acpi_MatchHid(handle, *ids)) { 573 *found = 1; 574 break; 575 } 576 } 577 return (AE_OK); 578 } 579 580 static void 581 apei_identify(driver_t *driver, device_t parent) 582 { 583 device_t child; 584 int found; 585 ACPI_TABLE_HEADER *hest; 586 ACPI_STATUS status; 587 588 if (acpi_disabled("apei")) 589 return; 590 591 /* Without HEST table we have nothing to do. */ 592 status = AcpiGetTable(ACPI_SIG_HEST, 0, &hest); 593 if (ACPI_FAILURE(status)) 594 return; 595 AcpiPutTable(hest); 596 597 /* Only one APEI device can exist. */ 598 if (devclass_get_device(apei_devclass, 0)) 599 return; 600 601 /* Search for ACPI error device to be used. */ 602 found = 0; 603 AcpiWalkNamespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 604 100, apei_find, NULL, NULL, (void *)&found); 605 if (found) 606 return; 607 608 /* If not found - create a fake one. */ 609 child = BUS_ADD_CHILD(parent, 2, "apei", 0); 610 if (child == NULL) 611 printf("%s: can't add child\n", __func__); 612 } 613 614 static int 615 apei_probe(device_t dev) 616 { 617 ACPI_TABLE_HEADER *hest; 618 ACPI_STATUS status; 619 int rv; 620 621 if (acpi_disabled("apei")) 622 return (ENXIO); 623 624 if (acpi_get_handle(dev) != NULL) { 625 rv = ACPI_ID_PROBE(device_get_parent(dev), dev, apei_ids, NULL); 626 if (rv > 0) 627 return (rv); 628 } else 629 rv = 0; 630 631 /* Without HEST table we have nothing to do. */ 632 status = AcpiGetTable(ACPI_SIG_HEST, 0, &hest); 633 if (ACPI_FAILURE(status)) 634 return (ENXIO); 635 AcpiPutTable(hest); 636 637 device_set_desc(dev, "ACPI Platform Error Interface"); 638 return (rv); 639 } 640 641 static int 642 apei_attach(device_t dev) 643 { 644 struct apei_softc *sc = device_get_softc(dev); 645 struct apei_pges *pges; 646 struct apei_ge *ge; 647 ACPI_STATUS status; 648 int rid; 649 650 TAILQ_INIT(&sc->ges); 651 TAILQ_INIT(&sc->nges.ges); 652 TAILQ_INIT(&sc->iges.ges); 653 for (int i = 0; i < nitems(sc->pges); i++) { 654 pges = &sc->pges[i]; 655 pges->interval = SBT_1MS << i; 656 callout_init(&pges->poll, 1); 657 TAILQ_INIT(&pges->ges); 658 } 659 660 /* Search and parse HEST table. */ 661 status = AcpiGetTable(ACPI_SIG_HEST, 0, (ACPI_TABLE_HEADER **)&sc->hest); 662 if (ACPI_FAILURE(status)) 663 return (ENXIO); 664 hest_parse_table(sc); 665 AcpiPutTable((ACPI_TABLE_HEADER *)sc->hest); 666 667 rid = 0; 668 TAILQ_FOREACH(ge, &sc->ges, link) { 669 ge->res_rid = rid++; 670 acpi_bus_alloc_gas(dev, &ge->res_type, &ge->res_rid, 671 &ge->v1.ErrorStatusAddress, &ge->res, 0); 672 if (ge->res) { 673 ge->buf = pmap_mapdev_attr(READ8(ge->res, 0), 674 ge->v1.ErrorBlockLength, VM_MEMATTR_WRITE_COMBINING); 675 } else { 676 device_printf(dev, "Can't allocate status resource.\n"); 677 } 678 if (ge->v1.Header.Type == ACPI_HEST_TYPE_GENERIC_ERROR_V2) { 679 ge->res2_rid = rid++; 680 acpi_bus_alloc_gas(dev, &ge->res2_type, &ge->res2_rid, 681 &ge->v2.ReadAckRegister, &ge->res2, 0); 682 if (ge->res2 == NULL) 683 device_printf(dev, "Can't allocate ack resource.\n"); 684 } 685 if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_POLLED) { 686 pges = &sc->pges[PGE_ID(ge)]; 687 TAILQ_INSERT_TAIL(&sc->pges[PGE_ID(ge)].ges, ge, nlink); 688 callout_reset_sbt(&pges->poll, pges->interval, pges->interval, 689 apei_callout_handler, pges, 0); 690 } else if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_SCI || 691 ge->v1.Notify.Type == ACPI_HEST_NOTIFY_GPIO || 692 ge->v1.Notify.Type == ACPI_HEST_NOTIFY_GSIV) { 693 TAILQ_INSERT_TAIL(&sc->iges.ges, ge, nlink); 694 } else if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_NMI) { 695 ge->copybuf = malloc(ge->v1.ErrorBlockLength, 696 M_DEVBUF, M_WAITOK | M_ZERO); 697 TAILQ_INSERT_TAIL(&sc->nges.ges, ge, nlink); 698 if (sc->nges.swi_ih == NULL) { 699 swi_add(&clk_intr_event, "apei", apei_nmi_swi, 700 &sc->nges, SWI_CLOCK, INTR_MPSAFE, 701 &sc->nges.swi_ih); 702 apei_nmi_nges = &sc->nges; 703 apei_nmi = apei_nmi_handler; 704 } 705 } 706 } 707 708 if (acpi_get_handle(dev) != NULL) { 709 AcpiInstallNotifyHandler(acpi_get_handle(dev), 710 ACPI_DEVICE_NOTIFY, apei_notify_handler, dev); 711 } 712 return (0); 713 } 714 715 static int 716 apei_detach(device_t dev) 717 { 718 struct apei_softc *sc = device_get_softc(dev); 719 struct apei_ge *ge; 720 721 apei_nmi = NULL; 722 apei_nmi_nges = NULL; 723 if (sc->nges.swi_ih != NULL) { 724 swi_remove(&sc->nges.swi_ih); 725 sc->nges.swi_ih = NULL; 726 } 727 if (acpi_get_handle(dev) != NULL) { 728 AcpiRemoveNotifyHandler(acpi_get_handle(dev), 729 ACPI_DEVICE_NOTIFY, apei_notify_handler); 730 } 731 for (int i = 0; i < nitems(sc->pges); i++) 732 callout_drain(&sc->pges[i].poll); 733 734 while ((ge = TAILQ_FIRST(&sc->ges)) != NULL) { 735 TAILQ_REMOVE(&sc->ges, ge, link); 736 if (ge->res) { 737 bus_release_resource(dev, ge->res_type, 738 ge->res_rid, ge->res); 739 } 740 if (ge->res2) { 741 bus_release_resource(dev, ge->res2_type, 742 ge->res2_rid, ge->res2); 743 } 744 if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_POLLED) { 745 TAILQ_REMOVE(&sc->pges[PGE_ID(ge)].ges, ge, nlink); 746 } else if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_SCI || 747 ge->v1.Notify.Type == ACPI_HEST_NOTIFY_GPIO || 748 ge->v1.Notify.Type == ACPI_HEST_NOTIFY_GSIV) { 749 TAILQ_REMOVE(&sc->iges.ges, ge, nlink); 750 } else if (ge->v1.Notify.Type == ACPI_HEST_NOTIFY_NMI) { 751 TAILQ_REMOVE(&sc->nges.ges, ge, nlink); 752 free(ge->copybuf, M_DEVBUF); 753 } 754 if (ge->buf) { 755 pmap_unmapdev((vm_offset_t)ge->buf, 756 ge->v1.ErrorBlockLength); 757 } 758 free(ge, M_DEVBUF); 759 } 760 return (0); 761 } 762 763 static device_method_t apei_methods[] = { 764 /* Device interface */ 765 DEVMETHOD(device_identify, apei_identify), 766 DEVMETHOD(device_probe, apei_probe), 767 DEVMETHOD(device_attach, apei_attach), 768 DEVMETHOD(device_detach, apei_detach), 769 DEVMETHOD_END 770 }; 771 772 static driver_t apei_driver = { 773 "apei", 774 apei_methods, 775 sizeof(struct apei_softc), 776 }; 777 778 DRIVER_MODULE(apei, acpi, apei_driver, apei_devclass, 0, 0); 779 MODULE_DEPEND(apei, acpi, 1, 1, 1); 780