1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2013 Neel Natu <neel@freebsd.org> 5 * Copyright (c) 2013 Tycho Nightingale <tycho.nightingale@pluribusnetworks.com> 6 * All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in the 15 * documentation and/or other materials provided with the distribution. 16 * 17 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27 * SUCH DAMAGE. 28 */ 29 30 /* 31 * Copyright 2018 Joyent, Inc. 32 */ 33 34 #include <sys/cdefs.h> 35 36 #include <sys/types.h> 37 #include <machine/vmm.h> 38 39 #include <err.h> 40 #include <stdio.h> 41 #include <stdlib.h> 42 #include <string.h> 43 44 #include <vmmapi.h> 45 46 #include "acpi.h" 47 #include "debug.h" 48 #include "bootrom.h" 49 #include "config.h" 50 #include "inout.h" 51 #include "pci_emul.h" 52 #include "pci_irq.h" 53 #include "pci_lpc.h" 54 #include "pci_passthru.h" 55 #include "pctestdev.h" 56 #include "tpm_device.h" 57 #include "uart_emul.h" 58 59 #define IO_ICU1 0x20 60 #define IO_ICU2 0xA0 61 62 SET_DECLARE(lpc_dsdt_set, struct lpc_dsdt); 63 SET_DECLARE(lpc_sysres_set, struct lpc_sysres); 64 65 #define ELCR_PORT 0x4d0 66 SYSRES_IO(ELCR_PORT, 2); 67 68 #define IO_TIMER1_PORT 0x40 69 70 #define NMISC_PORT 0x61 71 SYSRES_IO(NMISC_PORT, 1); 72 73 static struct pci_devinst *lpc_bridge; 74 75 #define LPC_UART_NUM 4 76 static struct lpc_uart_softc { 77 struct uart_softc *uart_softc; 78 int iobase; 79 int irq; 80 int enabled; 81 } lpc_uart_softc[LPC_UART_NUM]; 82 83 static const char *lpc_uart_names[LPC_UART_NUM] = { 84 "com1", "com2", "com3", "com4" 85 }; 86 87 static const char *lpc_uart_acpi_names[LPC_UART_NUM] = { 88 "COM1", "COM2", "COM3", "COM4" 89 }; 90 91 /* 92 * LPC device configuration is in the following form: 93 * <lpc_device_name>[,<options>] 94 * For e.g. "com1,stdio" or "bootrom,/var/romfile" 95 */ 96 int 97 lpc_device_parse(const char *opts) 98 { 99 int unit, error; 100 char *str, *cpy, *lpcdev, *node_name; 101 const char *romfile, *varfile, *tpm_type, *tpm_path; 102 103 error = -1; 104 str = cpy = strdup(opts); 105 lpcdev = strsep(&str, ","); 106 if (lpcdev != NULL) { 107 if (strcasecmp(lpcdev, "bootrom") == 0) { 108 romfile = strsep(&str, ","); 109 if (romfile == NULL) { 110 errx(4, "invalid bootrom option \"%s\"", opts); 111 } 112 set_config_value("lpc.bootrom", romfile); 113 114 varfile = strsep(&str, ","); 115 if (varfile == NULL) { 116 error = 0; 117 goto done; 118 } 119 if (strchr(varfile, '=') == NULL) { 120 set_config_value("lpc.bootvars", varfile); 121 } else { 122 /* varfile doesn't exist, it's another config 123 * option */ 124 pci_parse_legacy_config(find_config_node("lpc"), 125 varfile); 126 } 127 128 pci_parse_legacy_config(find_config_node("lpc"), str); 129 error = 0; 130 goto done; 131 } 132 if (strcasecmp(lpcdev, "tpm") == 0) { 133 nvlist_t *nvl = create_config_node("tpm"); 134 135 tpm_type = strsep(&str, ","); 136 if (tpm_type == NULL) { 137 errx(4, "invalid tpm type \"%s\"", opts); 138 } 139 set_config_value_node(nvl, "type", tpm_type); 140 141 tpm_path = strsep(&str, ","); 142 if (tpm_path == NULL) { 143 errx(4, "invalid tpm path \"%s\"", opts); 144 } 145 set_config_value_node(nvl, "path", tpm_path); 146 147 pci_parse_legacy_config(find_config_node("tpm"), str); 148 149 set_config_value_node_if_unset(nvl, "version", "2.0"); 150 error = 0; 151 goto done; 152 } 153 for (unit = 0; unit < LPC_UART_NUM; unit++) { 154 if (strcasecmp(lpcdev, lpc_uart_names[unit]) == 0) { 155 asprintf(&node_name, "lpc.%s.path", 156 lpc_uart_names[unit]); 157 set_config_value(node_name, str); 158 free(node_name); 159 error = 0; 160 goto done; 161 } 162 } 163 if (strcasecmp(lpcdev, pctestdev_getname()) == 0) { 164 asprintf(&node_name, "lpc.%s", pctestdev_getname()); 165 set_config_bool(node_name, true); 166 free(node_name); 167 error = 0; 168 goto done; 169 } 170 } 171 172 done: 173 free(cpy); 174 175 return (error); 176 } 177 178 void 179 lpc_print_supported_devices(void) 180 { 181 size_t i; 182 183 printf("bootrom\n"); 184 for (i = 0; i < LPC_UART_NUM; i++) 185 printf("%s\n", lpc_uart_names[i]); 186 printf("tpm\n"); 187 printf("%s\n", pctestdev_getname()); 188 } 189 190 const char * 191 lpc_bootrom(void) 192 { 193 194 return (get_config_value("lpc.bootrom")); 195 } 196 197 const char * 198 lpc_fwcfg(void) 199 { 200 return (get_config_value("lpc.fwcfg")); 201 } 202 203 static void 204 lpc_uart_intr_assert(void *arg) 205 { 206 struct lpc_uart_softc *sc = arg; 207 208 assert(sc->irq >= 0); 209 210 vm_isa_pulse_irq(lpc_bridge->pi_vmctx, sc->irq, sc->irq); 211 } 212 213 static void 214 lpc_uart_intr_deassert(void *arg __unused) 215 { 216 /* 217 * The COM devices on the LPC bus generate edge triggered interrupts, 218 * so nothing more to do here. 219 */ 220 } 221 222 static int 223 lpc_uart_io_handler(struct vmctx *ctx __unused, int in, 224 int port, int bytes, uint32_t *eax, void *arg) 225 { 226 int offset; 227 struct lpc_uart_softc *sc = arg; 228 229 offset = port - sc->iobase; 230 231 switch (bytes) { 232 case 1: 233 if (in) 234 *eax = uart_read(sc->uart_softc, offset); 235 else 236 uart_write(sc->uart_softc, offset, *eax); 237 break; 238 case 2: 239 if (in) { 240 *eax = uart_read(sc->uart_softc, offset); 241 *eax |= uart_read(sc->uart_softc, offset + 1) << 8; 242 } else { 243 uart_write(sc->uart_softc, offset, *eax); 244 uart_write(sc->uart_softc, offset + 1, *eax >> 8); 245 } 246 break; 247 #ifndef __FreeBSD__ 248 case 4: 249 if (in) { 250 *eax = uart_read(sc->uart_softc, offset); 251 *eax |= uart_read(sc->uart_softc, offset + 1) << 8; 252 *eax |= uart_read(sc->uart_softc, offset + 2) << 16; 253 *eax |= uart_read(sc->uart_softc, offset + 3) << 24; 254 } else { 255 uart_write(sc->uart_softc, offset, *eax); 256 uart_write(sc->uart_softc, offset + 1, *eax >> 8); 257 uart_write(sc->uart_softc, offset + 2, *eax >> 16); 258 uart_write(sc->uart_softc, offset + 3, *eax >> 24); 259 } 260 break; 261 #endif 262 default: 263 return (-1); 264 } 265 266 return (0); 267 } 268 269 static int 270 lpc_init(struct vmctx *ctx) 271 { 272 struct lpc_uart_softc *sc; 273 struct inout_port iop; 274 const char *backend, *name; 275 char *node_name; 276 int unit, error; 277 const nvlist_t *nvl; 278 279 nvl = find_config_node("lpc"); 280 #ifndef __FreeBSD__ 281 if (nvl != NULL && nvlist_exists((nvlist_t *)nvl, "bootrom")) { 282 error = bootrom_loadrom(ctx, nvl); 283 if (error) 284 return (error); 285 } 286 #else 287 if (nvl != NULL && nvlist_exists(nvl, "bootrom")) { 288 error = bootrom_loadrom(ctx, nvl); 289 if (error) 290 return (error); 291 } 292 #endif 293 294 /* COM1 and COM2 */ 295 for (unit = 0; unit < LPC_UART_NUM; unit++) { 296 sc = &lpc_uart_softc[unit]; 297 name = lpc_uart_names[unit]; 298 299 if (uart_legacy_alloc(unit, &sc->iobase, &sc->irq) != 0) { 300 EPRINTLN("Unable to allocate resources for " 301 "LPC device %s", name); 302 return (-1); 303 } 304 pci_irq_reserve(sc->irq); 305 306 sc->uart_softc = uart_init(lpc_uart_intr_assert, 307 lpc_uart_intr_deassert, sc); 308 309 asprintf(&node_name, "lpc.%s.path", name); 310 backend = get_config_value(node_name); 311 free(node_name); 312 if (uart_set_backend(sc->uart_softc, backend) != 0) { 313 EPRINTLN("Unable to initialize backend '%s' " 314 "for LPC device %s", backend, name); 315 return (-1); 316 } 317 318 bzero(&iop, sizeof(struct inout_port)); 319 iop.name = name; 320 iop.port = sc->iobase; 321 iop.size = UART_IO_BAR_SIZE; 322 iop.flags = IOPORT_F_INOUT; 323 iop.handler = lpc_uart_io_handler; 324 iop.arg = sc; 325 326 error = register_inout(&iop); 327 assert(error == 0); 328 sc->enabled = 1; 329 } 330 331 /* pc-testdev */ 332 asprintf(&node_name, "lpc.%s", pctestdev_getname()); 333 if (get_config_bool_default(node_name, false)) { 334 error = pctestdev_init(ctx); 335 if (error) 336 return (error); 337 } 338 free(node_name); 339 340 return (0); 341 } 342 343 static void 344 pci_lpc_write_dsdt(struct pci_devinst *pi) 345 { 346 struct lpc_dsdt **ldpp, *ldp; 347 348 dsdt_line(""); 349 dsdt_line("Device (ISA)"); 350 dsdt_line("{"); 351 dsdt_line(" Name (_ADR, 0x%04X%04X)", pi->pi_slot, pi->pi_func); 352 dsdt_line(" OperationRegion (LPCR, PCI_Config, 0x00, 0x100)"); 353 dsdt_line(" Field (LPCR, AnyAcc, NoLock, Preserve)"); 354 dsdt_line(" {"); 355 dsdt_line(" Offset (0x60),"); 356 dsdt_line(" PIRA, 8,"); 357 dsdt_line(" PIRB, 8,"); 358 dsdt_line(" PIRC, 8,"); 359 dsdt_line(" PIRD, 8,"); 360 dsdt_line(" Offset (0x68),"); 361 dsdt_line(" PIRE, 8,"); 362 dsdt_line(" PIRF, 8,"); 363 dsdt_line(" PIRG, 8,"); 364 dsdt_line(" PIRH, 8"); 365 dsdt_line(" }"); 366 dsdt_line(""); 367 368 dsdt_indent(1); 369 SET_FOREACH(ldpp, lpc_dsdt_set) { 370 ldp = *ldpp; 371 ldp->handler(); 372 } 373 374 dsdt_line(""); 375 dsdt_line("Device (PIC)"); 376 dsdt_line("{"); 377 dsdt_line(" Name (_HID, EisaId (\"PNP0000\"))"); 378 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 379 dsdt_line(" {"); 380 dsdt_indent(2); 381 dsdt_fixed_ioport(IO_ICU1, 2); 382 dsdt_fixed_ioport(IO_ICU2, 2); 383 dsdt_fixed_irq(2); 384 dsdt_unindent(2); 385 dsdt_line(" })"); 386 dsdt_line("}"); 387 388 dsdt_line(""); 389 dsdt_line("Device (TIMR)"); 390 dsdt_line("{"); 391 dsdt_line(" Name (_HID, EisaId (\"PNP0100\"))"); 392 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 393 dsdt_line(" {"); 394 dsdt_indent(2); 395 dsdt_fixed_ioport(IO_TIMER1_PORT, 4); 396 dsdt_fixed_irq(0); 397 dsdt_unindent(2); 398 dsdt_line(" })"); 399 dsdt_line("}"); 400 dsdt_unindent(1); 401 402 dsdt_line("}"); 403 } 404 405 static void 406 pci_lpc_sysres_dsdt(void) 407 { 408 struct lpc_sysres **lspp, *lsp; 409 410 dsdt_line(""); 411 dsdt_line("Device (SIO)"); 412 dsdt_line("{"); 413 dsdt_line(" Name (_HID, EisaId (\"PNP0C02\"))"); 414 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 415 dsdt_line(" {"); 416 417 dsdt_indent(2); 418 SET_FOREACH(lspp, lpc_sysres_set) { 419 lsp = *lspp; 420 switch (lsp->type) { 421 case LPC_SYSRES_IO: 422 dsdt_fixed_ioport(lsp->base, lsp->length); 423 break; 424 case LPC_SYSRES_MEM: 425 dsdt_fixed_mem32(lsp->base, lsp->length); 426 break; 427 } 428 } 429 dsdt_unindent(2); 430 431 dsdt_line(" })"); 432 dsdt_line("}"); 433 } 434 LPC_DSDT(pci_lpc_sysres_dsdt); 435 436 static void 437 pci_lpc_uart_dsdt(void) 438 { 439 struct lpc_uart_softc *sc; 440 int unit; 441 442 for (unit = 0; unit < LPC_UART_NUM; unit++) { 443 sc = &lpc_uart_softc[unit]; 444 if (!sc->enabled) 445 continue; 446 dsdt_line(""); 447 dsdt_line("Device (%s)", lpc_uart_acpi_names[unit]); 448 dsdt_line("{"); 449 dsdt_line(" Name (_HID, EisaId (\"PNP0501\"))"); 450 dsdt_line(" Name (_UID, %d)", unit + 1); 451 dsdt_line(" Name (_CRS, ResourceTemplate ()"); 452 dsdt_line(" {"); 453 dsdt_indent(2); 454 dsdt_fixed_ioport(sc->iobase, UART_IO_BAR_SIZE); 455 dsdt_fixed_irq(sc->irq); 456 dsdt_unindent(2); 457 dsdt_line(" })"); 458 dsdt_line("}"); 459 } 460 } 461 LPC_DSDT(pci_lpc_uart_dsdt); 462 463 static int 464 pci_lpc_cfgwrite(struct pci_devinst *pi, int coff, int bytes, uint32_t val) 465 { 466 int pirq_pin; 467 468 if (bytes == 1) { 469 pirq_pin = 0; 470 if (coff >= 0x60 && coff <= 0x63) 471 pirq_pin = coff - 0x60 + 1; 472 if (coff >= 0x68 && coff <= 0x6b) 473 pirq_pin = coff - 0x68 + 5; 474 if (pirq_pin != 0) { 475 pirq_write(pi->pi_vmctx, pirq_pin, val); 476 pci_set_cfgdata8(pi, coff, pirq_read(pirq_pin)); 477 return (0); 478 } 479 } 480 return (-1); 481 } 482 483 static void 484 pci_lpc_write(struct pci_devinst *pi __unused, int baridx __unused, 485 uint64_t offset __unused, int size __unused, uint64_t value __unused) 486 { 487 } 488 489 static uint64_t 490 pci_lpc_read(struct pci_devinst *pi __unused, int baridx __unused, 491 uint64_t offset __unused, int size __unused) 492 { 493 return (0); 494 } 495 496 #define LPC_DEV 0x7000 497 #define LPC_VENDOR 0x8086 498 #define LPC_REVID 0x00 499 #define LPC_SUBVEND_0 0x0000 500 #define LPC_SUBDEV_0 0x0000 501 502 #ifdef __FreeBSD__ 503 static int 504 pci_lpc_get_sel(struct pcisel *const sel) 505 { 506 assert(sel != NULL); 507 508 memset(sel, 0, sizeof(*sel)); 509 510 for (uint8_t slot = 0; slot <= PCI_SLOTMAX; ++slot) { 511 uint8_t max_func = 0; 512 513 sel->pc_dev = slot; 514 sel->pc_func = 0; 515 516 if (read_config(sel, PCIR_HDRTYPE, 1) & PCIM_MFDEV) 517 max_func = PCI_FUNCMAX; 518 519 for (uint8_t func = 0; func <= max_func; ++func) { 520 sel->pc_func = func; 521 522 if ((read_config(sel, PCIR_CLASS, 1) == PCIC_BRIDGE) && 523 (read_config(sel, PCIR_SUBCLASS, 1) == 524 PCIS_BRIDGE_ISA)) { 525 return (0); 526 } 527 } 528 } 529 530 warnx("%s: Unable to find host selector of LPC bridge.", __func__); 531 532 return (-1); 533 } 534 #else 535 /* 536 * This function is used to find the PCI selector for the host's LPC so that 537 * its various IDs can be used to configure the guest LPC with the same values 538 * when the `host` keyword is used in the configuration. 539 * On illumos we always just report that we cannot find the host LPC. This is 540 * likely to be true in the case that we're running in a zone anyway. 541 */ 542 static int 543 pci_lpc_get_sel(struct pcisel *const sel __unused) 544 { 545 return (-1); 546 } 547 #endif 548 549 static int 550 pci_lpc_init(struct pci_devinst *pi, nvlist_t *nvl) 551 { 552 struct pcisel sel = { 0 }; 553 struct pcisel *selp = NULL; 554 uint16_t device, subdevice, subvendor, vendor; 555 uint8_t revid; 556 557 /* 558 * Do not allow more than one LPC bridge to be configured. 559 */ 560 if (lpc_bridge != NULL) { 561 EPRINTLN("Only one LPC bridge is allowed."); 562 return (-1); 563 } 564 565 /* 566 * Enforce that the LPC can only be configured on bus 0. This 567 * simplifies the ACPI DSDT because it can provide a decode for 568 * all legacy i/o ports behind bus 0. 569 */ 570 if (pi->pi_bus != 0) { 571 EPRINTLN("LPC bridge can be present only on bus 0."); 572 return (-1); 573 } 574 575 if (lpc_init(pi->pi_vmctx) != 0) 576 return (-1); 577 578 if (pci_lpc_get_sel(&sel) == 0) 579 selp = &sel; 580 581 vendor = pci_config_read_reg(selp, nvl, PCIR_VENDOR, 2, LPC_VENDOR); 582 device = pci_config_read_reg(selp, nvl, PCIR_DEVICE, 2, LPC_DEV); 583 revid = pci_config_read_reg(selp, nvl, PCIR_REVID, 1, LPC_REVID); 584 subvendor = pci_config_read_reg(selp, nvl, PCIR_SUBVEND_0, 2, 585 LPC_SUBVEND_0); 586 subdevice = pci_config_read_reg(selp, nvl, PCIR_SUBDEV_0, 2, 587 LPC_SUBDEV_0); 588 589 /* initialize config space */ 590 pci_set_cfgdata16(pi, PCIR_VENDOR, vendor); 591 pci_set_cfgdata16(pi, PCIR_DEVICE, device); 592 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_BRIDGE); 593 pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_BRIDGE_ISA); 594 pci_set_cfgdata8(pi, PCIR_REVID, revid); 595 pci_set_cfgdata16(pi, PCIR_SUBVEND_0, subvendor); 596 pci_set_cfgdata16(pi, PCIR_SUBDEV_0, subdevice); 597 598 lpc_bridge = pi; 599 600 return (0); 601 } 602 603 char * 604 lpc_pirq_name(int pin) 605 { 606 char *name; 607 608 if (lpc_bridge == NULL) 609 return (NULL); 610 asprintf(&name, "\\_SB.PC00.ISA.LNK%c,", 'A' + pin - 1); 611 return (name); 612 } 613 614 void 615 lpc_pirq_routed(void) 616 { 617 int pin; 618 619 if (lpc_bridge == NULL) 620 return; 621 622 for (pin = 0; pin < 4; pin++) 623 pci_set_cfgdata8(lpc_bridge, 0x60 + pin, pirq_read(pin + 1)); 624 for (pin = 0; pin < 4; pin++) 625 pci_set_cfgdata8(lpc_bridge, 0x68 + pin, pirq_read(pin + 5)); 626 } 627 628 static const struct pci_devemu pci_de_lpc = { 629 .pe_emu = "lpc", 630 .pe_init = pci_lpc_init, 631 .pe_write_dsdt = pci_lpc_write_dsdt, 632 .pe_cfgwrite = pci_lpc_cfgwrite, 633 .pe_barwrite = pci_lpc_write, 634 .pe_barread = pci_lpc_read 635 }; 636 PCI_EMUL_SET(pci_de_lpc); 637