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