pci_emul.c revision 234761
1/*- 2 * Copyright (c) 2011 NetApp, Inc. 3 * All rights reserved. 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted provided that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY NETAPP, INC ``AS IS'' AND 15 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL NETAPP, INC OR CONTRIBUTORS BE LIABLE 18 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * SUCH DAMAGE. 25 * 26 * $FreeBSD$ 27 */ 28 29#include <sys/cdefs.h> 30__FBSDID("$FreeBSD$"); 31 32#include <sys/param.h> 33#include <sys/linker_set.h> 34 35#include <ctype.h> 36#include <stdio.h> 37#include <stdlib.h> 38#include <string.h> 39#include <strings.h> 40#include <assert.h> 41 42#include <machine/vmm.h> 43#include <vmmapi.h> 44 45#include "fbsdrun.h" 46#include "inout.h" 47#include "pci_emul.h" 48#include "instruction_emul.h" 49 50#define CONF1_ADDR_PORT 0x0cf8 51#define CONF1_DATA_PORT 0x0cfc 52 53#define CFGWRITE(pi,off,val,b) \ 54do { \ 55 if ((b) == 1) { \ 56 pci_set_cfgdata8((pi),(off),(val)); \ 57 } else if ((b) == 2) { \ 58 pci_set_cfgdata16((pi),(off),(val)); \ 59 } else { \ 60 pci_set_cfgdata32((pi),(off),(val)); \ 61 } \ 62} while (0) 63 64#define MAXSLOTS 32 65 66static struct slotinfo { 67 char *si_name; 68 char *si_param; 69 struct pci_devinst *si_devi; 70 int si_titled; 71 int si_pslot; 72 char si_prefix; 73 char si_suffix; 74} pci_slotinfo[MAXSLOTS]; 75 76/* 77 * NetApp specific: 78 * struct used to build an in-core OEM table to supply device names 79 * to driver instances 80 */ 81static struct mptable_pci_devnames { 82#define MPT_HDR_BASE 0 83#define MPT_HDR_NAME 2 84 uint16_t md_hdrtype; 85 uint16_t md_entries; 86 uint16_t md_cksum; 87 uint16_t md_pad; 88#define MPT_NTAP_SIG \ 89 ((uint32_t)(('P' << 24) | ('A' << 16) | ('T' << 8) | 'N')) 90 uint32_t md_sig; 91 uint32_t md_rsvd; 92 struct mptable_pci_slotinfo { 93 uint16_t mds_type; 94 uint16_t mds_phys_slot; 95 uint8_t mds_bus; 96 uint8_t mds_slot; 97 uint8_t mds_func; 98 uint8_t mds_pad; 99 uint16_t mds_vid; 100 uint16_t mds_did; 101 uint8_t mds_suffix[4]; 102 uint8_t mds_prefix[4]; 103 uint32_t mds_rsvd[3]; 104 } md_slotinfo[MAXSLOTS]; 105} pci_devnames; 106 107SET_DECLARE(pci_devemu_set, struct pci_devemu); 108 109static uint64_t pci_emul_iobase; 110static uint64_t pci_emul_membase32; 111static uint64_t pci_emul_membase64; 112 113#define PCI_EMUL_IOBASE 0x2000 114#define PCI_EMUL_IOLIMIT 0x10000 115 116#define PCI_EMUL_MEMBASE32 (lomem_sz) 117#define PCI_EMUL_MEMLIMIT32 0xE0000000 /* 3.5GB */ 118 119#define PCI_EMUL_MEMBASE64 0xD000000000UL 120#define PCI_EMUL_MEMLIMIT64 0xFD00000000UL 121 122static int pci_emul_devices; 123static int devname_elems; 124 125/* 126 * I/O access 127 */ 128 129/* 130 * Slot options are in the form: 131 * 132 * <slot>,<emul>[,<config>] 133 * 134 * slot is 0..31 135 * emul is a string describing the type of PCI device e.g. virtio-net 136 * config is an optional string, depending on the device, that can be 137 * used for configuration. 138 * Examples are: 139 * 1,virtio-net,tap0 140 * 3,dummy 141 */ 142static void 143pci_parse_slot_usage(char *aopt) 144{ 145 printf("Invalid PCI slot info field \"%s\"\n", aopt); 146 free(aopt); 147} 148 149void 150pci_parse_slot(char *opt) 151{ 152 char *slot, *emul, *config; 153 char *str, *cpy; 154 int snum; 155 156 str = cpy = strdup(opt); 157 config = NULL; 158 159 slot = strsep(&str, ","); 160 emul = strsep(&str, ","); 161 if (str != NULL) { 162 config = strsep(&str, ","); 163 } 164 165 if (emul == NULL) { 166 pci_parse_slot_usage(cpy); 167 return; 168 } 169 170 snum = 255; 171 snum = atoi(slot); 172 if (snum < 0 || snum >= MAXSLOTS) { 173 pci_parse_slot_usage(cpy); 174 } else { 175 pci_slotinfo[snum].si_name = emul; 176 pci_slotinfo[snum].si_param = config; 177 } 178} 179 180 181/* 182 * 183 * PCI MPTable names are of the form: 184 * 185 * <slot>,[prefix]<digit><suffix> 186 * 187 * .. with <prefix> an alphabetic char, <digit> a 1 or 2-digit string, 188 * and <suffix> a single char. 189 * 190 * Examples: 191 * 1,e0c 192 * 4,e0P 193 * 6,43a 194 * 7,0f 195 * 10,1 196 * 12,e0M 197 * 2,12a 198 * 199 * Note that this is NetApp-specific, but is ignored on other o/s's. 200 */ 201static void 202pci_parse_name_usage(char *aopt) 203{ 204 printf("Invalid PCI slot name field \"%s\"\n", aopt); 205} 206 207void 208pci_parse_name(char *opt) 209{ 210 char csnum[4]; 211 char *namestr; 212 char *slotend; 213 char prefix, suffix; 214 int i; 215 int pslot; 216 int snum; 217 218 pslot = -1; 219 prefix = suffix = 0; 220 slotend = strchr(opt, ','); 221 222 /* 223 * A comma must be present, and can't be the first character 224 * or no slot would be present. Also, the slot number can't be 225 * more than 2 characters. 226 */ 227 if (slotend == NULL || slotend == opt || (slotend - opt > 2)) { 228 pci_parse_name_usage(opt); 229 return; 230 } 231 232 for (i = 0; i < (slotend - opt); i++) { 233 csnum[i] = opt[i]; 234 } 235 csnum[i] = '\0'; 236 237 snum = 255; 238 snum = atoi(csnum); 239 if (snum < 0 || snum >= MAXSLOTS) { 240 pci_parse_name_usage(opt); 241 return; 242 } 243 244 namestr = slotend + 1; 245 246 if (strlen(namestr) > 3) { 247 pci_parse_name_usage(opt); 248 return; 249 } 250 251 if (isalpha(*namestr)) { 252 prefix = *namestr++; 253 } 254 255 if (!isdigit(*namestr)) { 256 pci_parse_name_usage(opt); 257 } else { 258 pslot = *namestr++ - '0'; 259 if (isnumber(*namestr)) { 260 pslot = 10*pslot + *namestr++ - '0'; 261 262 } 263 if (isalpha(*namestr) && *(namestr + 1) == 0) { 264 suffix = *namestr; 265 pci_slotinfo[snum].si_titled = 1; 266 pci_slotinfo[snum].si_pslot = pslot; 267 pci_slotinfo[snum].si_prefix = prefix; 268 pci_slotinfo[snum].si_suffix = suffix; 269 270 } else { 271 pci_parse_name_usage(opt); 272 } 273 } 274} 275 276static void 277pci_add_mptable_name(struct slotinfo *si) 278{ 279 struct mptable_pci_slotinfo *ms; 280 281 /* 282 * If naming information has been supplied for this slot, populate 283 * the next available mptable OEM entry 284 */ 285 if (si->si_titled) { 286 ms = &pci_devnames.md_slotinfo[devname_elems]; 287 288 ms->mds_type = MPT_HDR_NAME; 289 ms->mds_phys_slot = si->si_pslot; 290 ms->mds_bus = si->si_devi->pi_bus; 291 ms->mds_slot = si->si_devi->pi_slot; 292 ms->mds_func = si->si_devi->pi_func; 293 ms->mds_vid = pci_get_cfgdata16(si->si_devi, PCIR_VENDOR); 294 ms->mds_did = pci_get_cfgdata16(si->si_devi, PCIR_DEVICE); 295 ms->mds_suffix[0] = si->si_suffix; 296 ms->mds_prefix[0] = si->si_prefix; 297 298 devname_elems++; 299 } 300} 301 302static void 303pci_finish_mptable_names(void) 304{ 305 int size; 306 307 if (devname_elems) { 308 pci_devnames.md_hdrtype = MPT_HDR_BASE; 309 pci_devnames.md_entries = devname_elems; 310 pci_devnames.md_cksum = 0; /* XXX */ 311 pci_devnames.md_sig = MPT_NTAP_SIG; 312 313 size = (uintptr_t)&pci_devnames.md_slotinfo[devname_elems] - 314 (uintptr_t)&pci_devnames; 315 316 fbsdrun_add_oemtbl(&pci_devnames, size); 317 } 318} 319 320static int 321pci_emul_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 322 uint32_t *eax, void *arg) 323{ 324 struct pci_devinst *pdi = arg; 325 struct pci_devemu *pe = pdi->pi_d; 326 int offset, i; 327 328 for (i = 0; i <= PCI_BARMAX; i++) { 329 if (pdi->pi_bar[i].type == PCIBAR_IO && 330 port >= pdi->pi_bar[i].addr && 331 port + bytes <= pdi->pi_bar[i].addr + pdi->pi_bar[i].size) { 332 offset = port - pdi->pi_bar[i].addr; 333 if (in) 334 *eax = (*pe->pe_ior)(pdi, i, offset, bytes); 335 else 336 (*pe->pe_iow)(pdi, i, offset, bytes, *eax); 337 return (0); 338 } 339 } 340 return (-1); 341} 342 343static int 344pci_emul_alloc_resource(uint64_t *baseptr, uint64_t limit, uint64_t size, 345 uint64_t *addr) 346{ 347 uint64_t base; 348 349 assert((size & (size - 1)) == 0); /* must be a power of 2 */ 350 351 base = roundup2(*baseptr, size); 352 353 if (base + size <= limit) { 354 *addr = base; 355 *baseptr = base + size; 356 return (0); 357 } else 358 return (-1); 359} 360 361int 362pci_emul_alloc_bar(struct pci_devinst *pdi, int idx, uint64_t hostbase, 363 enum pcibar_type type, uint64_t size) 364{ 365 int i, error; 366 uint64_t *baseptr, limit, addr, mask, lobits, bar; 367 struct inout_port iop; 368 369 assert(idx >= 0 && idx <= PCI_BARMAX); 370 371 if ((size & (size - 1)) != 0) 372 size = 1UL << flsl(size); /* round up to a power of 2 */ 373 374 switch (type) { 375 case PCIBAR_NONE: 376 baseptr = NULL; 377 addr = mask = lobits = 0; 378 break; 379 case PCIBAR_IO: 380 baseptr = &pci_emul_iobase; 381 limit = PCI_EMUL_IOLIMIT; 382 mask = PCIM_BAR_IO_BASE; 383 lobits = PCIM_BAR_IO_SPACE; 384 break; 385 case PCIBAR_MEM64: 386 /* 387 * XXX 388 * Some drivers do not work well if the 64-bit BAR is allocated 389 * above 4GB. Allow for this by allocating small requests under 390 * 4GB unless then allocation size is larger than some arbitrary 391 * number (32MB currently). 392 */ 393 if (size > 32 * 1024 * 1024) { 394 /* 395 * XXX special case for device requiring peer-peer DMA 396 */ 397 if (size == 0x100000000UL) 398 baseptr = &hostbase; 399 else 400 baseptr = &pci_emul_membase64; 401 limit = PCI_EMUL_MEMLIMIT64; 402 mask = PCIM_BAR_MEM_BASE; 403 lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 | 404 PCIM_BAR_MEM_PREFETCH; 405 break; 406 } 407 /* fallthrough */ 408 case PCIBAR_MEM32: 409 baseptr = &pci_emul_membase32; 410 limit = PCI_EMUL_MEMLIMIT32; 411 mask = PCIM_BAR_MEM_BASE; 412 lobits = PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; 413 break; 414 default: 415 printf("pci_emul_alloc_base: invalid bar type %d\n", type); 416 assert(0); 417 } 418 419 if (baseptr != NULL) { 420 error = pci_emul_alloc_resource(baseptr, limit, size, &addr); 421 if (error != 0) 422 return (error); 423 } 424 425 pdi->pi_bar[idx].type = type; 426 pdi->pi_bar[idx].addr = addr; 427 pdi->pi_bar[idx].size = size; 428 429 /* Initialize the BAR register in config space */ 430 bar = (addr & mask) | lobits; 431 pci_set_cfgdata32(pdi, PCIR_BAR(idx), bar); 432 433 if (type == PCIBAR_MEM64) { 434 assert(idx + 1 <= PCI_BARMAX); 435 pdi->pi_bar[idx + 1].type = PCIBAR_MEMHI64; 436 pci_set_cfgdata32(pdi, PCIR_BAR(idx + 1), bar >> 32); 437 } 438 439 /* add a handler to intercept accesses to the I/O bar */ 440 if (type == PCIBAR_IO) { 441 iop.name = pdi->pi_name; 442 iop.flags = IOPORT_F_INOUT; 443 iop.handler = pci_emul_handler; 444 iop.arg = pdi; 445 446 for (i = 0; i < size; i++) { 447 iop.port = addr + i; 448 register_inout(&iop); 449 } 450 } 451 452 return (0); 453} 454 455#define CAP_START_OFFSET 0x40 456static int 457pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen) 458{ 459 int i, capoff, capid, reallen; 460 uint16_t sts; 461 462 static u_char endofcap[4] = { 463 PCIY_RESERVED, 0, 0, 0 464 }; 465 466 assert(caplen > 0 && capdata[0] != PCIY_RESERVED); 467 468 reallen = roundup2(caplen, 4); /* dword aligned */ 469 470 sts = pci_get_cfgdata16(pi, PCIR_STATUS); 471 if ((sts & PCIM_STATUS_CAPPRESENT) == 0) { 472 capoff = CAP_START_OFFSET; 473 pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff); 474 pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT); 475 } else { 476 capoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR); 477 while (1) { 478 assert((capoff & 0x3) == 0); 479 capid = pci_get_cfgdata8(pi, capoff); 480 if (capid == PCIY_RESERVED) 481 break; 482 capoff = pci_get_cfgdata8(pi, capoff + 1); 483 } 484 } 485 486 /* Check if we have enough space */ 487 if (capoff + reallen + sizeof(endofcap) > PCI_REGMAX + 1) 488 return (-1); 489 490 /* Copy the capability */ 491 for (i = 0; i < caplen; i++) 492 pci_set_cfgdata8(pi, capoff + i, capdata[i]); 493 494 /* Set the next capability pointer */ 495 pci_set_cfgdata8(pi, capoff + 1, capoff + reallen); 496 497 /* Copy of the reserved capability which serves as the end marker */ 498 for (i = 0; i < sizeof(endofcap); i++) 499 pci_set_cfgdata8(pi, capoff + reallen + i, endofcap[i]); 500 501 return (0); 502} 503 504static struct pci_devemu * 505pci_emul_finddev(char *name) 506{ 507 struct pci_devemu **pdpp, *pdp; 508 509 SET_FOREACH(pdpp, pci_devemu_set) { 510 pdp = *pdpp; 511 if (!strcmp(pdp->pe_emu, name)) { 512 return (pdp); 513 } 514 } 515 516 return (NULL); 517} 518 519static void 520pci_emul_init(struct vmctx *ctx, struct pci_devemu *pde, int slot, char *params) 521{ 522 struct pci_devinst *pdi; 523 pdi = malloc(sizeof(struct pci_devinst)); 524 bzero(pdi, sizeof(*pdi)); 525 526 pdi->pi_vmctx = ctx; 527 pdi->pi_bus = 0; 528 pdi->pi_slot = slot; 529 pdi->pi_func = 0; 530 pdi->pi_d = pde; 531 snprintf(pdi->pi_name, PI_NAMESZ, "%s-pci-%d", pde->pe_emu, slot); 532 533 /* Disable legacy interrupts */ 534 pci_set_cfgdata8(pdi, PCIR_INTLINE, 255); 535 pci_set_cfgdata8(pdi, PCIR_INTPIN, 0); 536 537 pci_set_cfgdata8(pdi, PCIR_COMMAND, 538 PCIM_CMD_PORTEN | PCIM_CMD_MEMEN | PCIM_CMD_BUSMASTEREN); 539 540 if ((*pde->pe_init)(ctx, pdi, params) != 0) { 541 free(pdi); 542 } else { 543 pci_emul_devices++; 544 pci_slotinfo[slot].si_devi = pdi; 545 } 546} 547 548void 549pci_populate_msicap(struct msicap *msicap, int msgnum, int nextptr) 550{ 551 int mmc; 552 553 CTASSERT(sizeof(struct msicap) == 14); 554 555 /* Number of msi messages must be a power of 2 between 1 and 32 */ 556 assert((msgnum & (msgnum - 1)) == 0 && msgnum >= 1 && msgnum <= 32); 557 mmc = ffs(msgnum) - 1; 558 559 bzero(msicap, sizeof(struct msicap)); 560 msicap->capid = PCIY_MSI; 561 msicap->nextptr = nextptr; 562 msicap->msgctrl = PCIM_MSICTRL_64BIT | (mmc << 1); 563} 564 565int 566pci_emul_add_msicap(struct pci_devinst *pi, int msgnum) 567{ 568 struct msicap msicap; 569 570 pci_populate_msicap(&msicap, msgnum, 0); 571 572 return (pci_emul_add_capability(pi, (u_char *)&msicap, sizeof(msicap))); 573} 574 575void 576msixcap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 577 int bytes, uint32_t val) 578{ 579 uint16_t msgctrl, rwmask; 580 int off, table_bar; 581 582 off = offset - capoff; 583 table_bar = pi->pi_msix.table_bar; 584 /* Message Control Register */ 585 if (off == 2 && bytes == 2) { 586 rwmask = PCIM_MSIXCTRL_MSIX_ENABLE | PCIM_MSIXCTRL_FUNCTION_MASK; 587 msgctrl = pci_get_cfgdata16(pi, offset); 588 msgctrl &= ~rwmask; 589 msgctrl |= val & rwmask; 590 val = msgctrl; 591 592 pi->pi_msix.enabled = val & PCIM_MSIXCTRL_MSIX_ENABLE; 593 } 594 595 CFGWRITE(pi, offset, val, bytes); 596} 597 598void 599msicap_cfgwrite(struct pci_devinst *pi, int capoff, int offset, 600 int bytes, uint32_t val) 601{ 602 uint16_t msgctrl, rwmask, msgdata, mme; 603 uint32_t addrlo; 604 605 /* 606 * If guest is writing to the message control register make sure 607 * we do not overwrite read-only fields. 608 */ 609 if ((offset - capoff) == 2 && bytes == 2) { 610 rwmask = PCIM_MSICTRL_MME_MASK | PCIM_MSICTRL_MSI_ENABLE; 611 msgctrl = pci_get_cfgdata16(pi, offset); 612 msgctrl &= ~rwmask; 613 msgctrl |= val & rwmask; 614 val = msgctrl; 615 616 addrlo = pci_get_cfgdata32(pi, capoff + 4); 617 if (msgctrl & PCIM_MSICTRL_64BIT) 618 msgdata = pci_get_cfgdata16(pi, capoff + 12); 619 else 620 msgdata = pci_get_cfgdata16(pi, capoff + 8); 621 622 /* 623 * XXX check delivery mode, destination mode etc 624 */ 625 mme = msgctrl & PCIM_MSICTRL_MME_MASK; 626 pi->pi_msi.enabled = msgctrl & PCIM_MSICTRL_MSI_ENABLE ? 1 : 0; 627 if (pi->pi_msi.enabled) { 628 pi->pi_msi.cpu = (addrlo >> 12) & 0xff; 629 pi->pi_msi.vector = msgdata & 0xff; 630 pi->pi_msi.msgnum = 1 << (mme >> 4); 631 } else { 632 pi->pi_msi.cpu = 0; 633 pi->pi_msi.vector = 0; 634 pi->pi_msi.msgnum = 0; 635 } 636 } 637 638 CFGWRITE(pi, offset, val, bytes); 639} 640 641/* 642 * This function assumes that 'coff' is in the capabilities region of the 643 * config space. 644 */ 645static void 646pci_emul_capwrite(struct pci_devinst *pi, int offset, int bytes, uint32_t val) 647{ 648 int capid; 649 uint8_t capoff, nextoff; 650 651 /* Do not allow un-aligned writes */ 652 if ((offset & (bytes - 1)) != 0) 653 return; 654 655 /* Find the capability that we want to update */ 656 capoff = CAP_START_OFFSET; 657 while (1) { 658 capid = pci_get_cfgdata8(pi, capoff); 659 if (capid == PCIY_RESERVED) 660 break; 661 662 nextoff = pci_get_cfgdata8(pi, capoff + 1); 663 if (offset >= capoff && offset < nextoff) 664 break; 665 666 capoff = nextoff; 667 } 668 assert(offset >= capoff); 669 670 /* 671 * Capability ID and Next Capability Pointer are readonly 672 */ 673 if (offset == capoff || offset == capoff + 1) 674 return; 675 676 switch (capid) { 677 case PCIY_MSI: 678 msicap_cfgwrite(pi, capoff, offset, bytes, val); 679 break; 680 default: 681 break; 682 } 683} 684 685static int 686pci_emul_iscap(struct pci_devinst *pi, int offset) 687{ 688 int found; 689 uint16_t sts; 690 uint8_t capid, lastoff; 691 692 found = 0; 693 sts = pci_get_cfgdata16(pi, PCIR_STATUS); 694 if ((sts & PCIM_STATUS_CAPPRESENT) != 0) { 695 lastoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR); 696 while (1) { 697 assert((lastoff & 0x3) == 0); 698 capid = pci_get_cfgdata8(pi, lastoff); 699 if (capid == PCIY_RESERVED) 700 break; 701 lastoff = pci_get_cfgdata8(pi, lastoff + 1); 702 } 703 if (offset >= CAP_START_OFFSET && offset <= lastoff) 704 found = 1; 705 } 706 return (found); 707} 708 709void 710init_pci(struct vmctx *ctx) 711{ 712 struct pci_devemu *pde; 713 struct slotinfo *si; 714 int i; 715 716 pci_emul_iobase = PCI_EMUL_IOBASE; 717 pci_emul_membase32 = PCI_EMUL_MEMBASE32; 718 pci_emul_membase64 = PCI_EMUL_MEMBASE64; 719 720 si = pci_slotinfo; 721 722 for (i = 0; i < MAXSLOTS; i++, si++) { 723 if (si->si_name != NULL) { 724 pde = pci_emul_finddev(si->si_name); 725 if (pde != NULL) { 726 pci_emul_init(ctx, pde, i, si->si_param); 727 pci_add_mptable_name(si); 728 } 729 } 730 } 731 pci_finish_mptable_names(); 732} 733 734int 735pci_msi_enabled(struct pci_devinst *pi) 736{ 737 return (pi->pi_msi.enabled); 738} 739 740int 741pci_msi_msgnum(struct pci_devinst *pi) 742{ 743 if (pi->pi_msi.enabled) 744 return (pi->pi_msi.msgnum); 745 else 746 return (0); 747} 748 749void 750pci_generate_msi(struct pci_devinst *pi, int msg) 751{ 752 753 if (pci_msi_enabled(pi) && msg < pci_msi_msgnum(pi)) { 754 vm_lapic_irq(pi->pi_vmctx, 755 pi->pi_msi.cpu, 756 pi->pi_msi.vector + msg); 757 } 758} 759 760static int cfgbus, cfgslot, cfgfunc, cfgoff; 761 762static int 763pci_emul_cfgaddr(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 764 uint32_t *eax, void *arg) 765{ 766 uint32_t x; 767 768 assert(!in); 769 770 if (bytes != 4) 771 return (-1); 772 773 x = *eax; 774 cfgoff = x & PCI_REGMAX; 775 cfgfunc = (x >> 8) & PCI_FUNCMAX; 776 cfgslot = (x >> 11) & PCI_SLOTMAX; 777 cfgbus = (x >> 16) & PCI_BUSMAX; 778 779 return (0); 780} 781INOUT_PORT(pci_cfgaddr, CONF1_ADDR_PORT, IOPORT_F_OUT, pci_emul_cfgaddr); 782 783static int 784pci_emul_cfgdata(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 785 uint32_t *eax, void *arg) 786{ 787 struct pci_devinst *pi; 788 struct pci_devemu *pe; 789 int coff, idx; 790 uint64_t mask, bar; 791 792 assert(bytes == 1 || bytes == 2 || bytes == 4); 793 794 pi = pci_slotinfo[cfgslot].si_devi; 795 coff = cfgoff + (port - CONF1_DATA_PORT); 796 797#if 0 798 printf("pcicfg-%s from 0x%0x of %d bytes (%d/%d/%d)\n\r", 799 in ? "read" : "write", coff, bytes, cfgbus, cfgslot, cfgfunc); 800#endif 801 802 if (pi == NULL || cfgfunc != 0) { 803 if (in) 804 *eax = 0xffffffff; 805 return (0); 806 } 807 808 pe = pi->pi_d; 809 810 /* 811 * Config read 812 */ 813 if (in) { 814 /* Let the device emulation override the default handler */ 815 if (pe->pe_cfgread != NULL && 816 (*pe->pe_cfgread)(ctx, vcpu, pi, coff, bytes, eax) == 0) 817 return (0); 818 819 if (bytes == 1) 820 *eax = pci_get_cfgdata8(pi, coff); 821 else if (bytes == 2) 822 *eax = pci_get_cfgdata16(pi, coff); 823 else 824 *eax = pci_get_cfgdata32(pi, coff); 825 } else { 826 /* Let the device emulation override the default handler */ 827 if (pe->pe_cfgwrite != NULL && 828 (*pe->pe_cfgwrite)(ctx, vcpu, pi, coff, bytes, *eax) == 0) 829 return (0); 830 831 /* 832 * Special handling for write to BAR registers 833 */ 834 if (coff >= PCIR_BAR(0) && coff < PCIR_BAR(PCI_BARMAX + 1)) { 835 /* 836 * Ignore writes to BAR registers that are not 837 * 4-byte aligned. 838 */ 839 if (bytes != 4 || (coff & 0x3) != 0) 840 return (0); 841 idx = (coff - PCIR_BAR(0)) / 4; 842 switch (pi->pi_bar[idx].type) { 843 case PCIBAR_NONE: 844 bar = 0; 845 break; 846 case PCIBAR_IO: 847 mask = ~(pi->pi_bar[idx].size - 1); 848 mask &= PCIM_BAR_IO_BASE; 849 bar = (*eax & mask) | PCIM_BAR_IO_SPACE; 850 break; 851 case PCIBAR_MEM32: 852 mask = ~(pi->pi_bar[idx].size - 1); 853 mask &= PCIM_BAR_MEM_BASE; 854 bar = *eax & mask; 855 bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_32; 856 break; 857 case PCIBAR_MEM64: 858 mask = ~(pi->pi_bar[idx].size - 1); 859 mask &= PCIM_BAR_MEM_BASE; 860 bar = *eax & mask; 861 bar |= PCIM_BAR_MEM_SPACE | PCIM_BAR_MEM_64 | 862 PCIM_BAR_MEM_PREFETCH; 863 break; 864 case PCIBAR_MEMHI64: 865 mask = ~(pi->pi_bar[idx - 1].size - 1); 866 mask &= PCIM_BAR_MEM_BASE; 867 bar = ((uint64_t)*eax << 32) & mask; 868 bar = bar >> 32; 869 break; 870 default: 871 assert(0); 872 } 873 pci_set_cfgdata32(pi, coff, bar); 874 875 if (pi->pi_bar[idx].handler) { 876 pi->pi_bar[idx].handler(pi, idx, bar); 877 } 878 879 } else if (pci_emul_iscap(pi, coff)) { 880 pci_emul_capwrite(pi, coff, bytes, *eax); 881 } else { 882 CFGWRITE(pi, coff, *eax, bytes); 883 } 884 } 885 886 return (0); 887} 888 889INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+0, IOPORT_F_INOUT, pci_emul_cfgdata); 890INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+1, IOPORT_F_INOUT, pci_emul_cfgdata); 891INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+2, IOPORT_F_INOUT, pci_emul_cfgdata); 892INOUT_PORT(pci_cfgdata, CONF1_DATA_PORT+3, IOPORT_F_INOUT, pci_emul_cfgdata); 893 894/* 895 * I/O ports to configure PCI IRQ routing. We ignore all writes to it. 896 */ 897static int 898pci_irq_port_handler(struct vmctx *ctx, int vcpu, int in, int port, int bytes, 899 uint32_t *eax, void *arg) 900{ 901 assert(in == 0); 902 return (0); 903} 904INOUT_PORT(pci_irq, 0xC00, IOPORT_F_OUT, pci_irq_port_handler); 905INOUT_PORT(pci_irq, 0xC01, IOPORT_F_OUT, pci_irq_port_handler); 906 907#define PCI_EMUL_TEST 908#ifdef PCI_EMUL_TEST 909/* 910 * Define a dummy test device 911 */ 912#define DREGSZ 20 913struct pci_emul_dsoftc { 914 uint8_t regs[DREGSZ]; 915}; 916 917#define PCI_EMUL_MSGS 4 918 919static int 920pci_emul_dinit(struct vmctx *ctx, struct pci_devinst *pi, char *opts) 921{ 922 int error; 923 struct pci_emul_dsoftc *sc; 924 925 sc = malloc(sizeof(struct pci_emul_dsoftc)); 926 memset(sc, 0, sizeof(struct pci_emul_dsoftc)); 927 928 pi->pi_arg = sc; 929 930 pci_set_cfgdata16(pi, PCIR_DEVICE, 0x0001); 931 pci_set_cfgdata16(pi, PCIR_VENDOR, 0x10DD); 932 pci_set_cfgdata8(pi, PCIR_CLASS, 0x02); 933 934 error = pci_emul_alloc_bar(pi, 0, 0, PCIBAR_IO, DREGSZ); 935 assert(error == 0); 936 937 error = pci_emul_add_msicap(pi, PCI_EMUL_MSGS); 938 assert(error == 0); 939 940 return (0); 941} 942 943static void 944pci_emul_diow(struct pci_devinst *pi, int baridx, int offset, int size, 945 uint32_t value) 946{ 947 int i; 948 struct pci_emul_dsoftc *sc = pi->pi_arg; 949 950 if (offset + size > DREGSZ) { 951 printf("diow: too large, offset %d size %d\n", offset, size); 952 return; 953 } 954 955 if (size == 1) { 956 sc->regs[offset] = value & 0xff; 957 } else if (size == 2) { 958 *(uint16_t *)&sc->regs[offset] = value & 0xffff; 959 } else { 960 *(uint32_t *)&sc->regs[offset] = value; 961 } 962 963 /* 964 * Special magic value to generate an interrupt 965 */ 966 if (offset == 4 && size == 4 && pci_msi_enabled(pi)) 967 pci_generate_msi(pi, value % pci_msi_msgnum(pi)); 968 969 if (value == 0xabcdef) { 970 for (i = 0; i < pci_msi_msgnum(pi); i++) 971 pci_generate_msi(pi, i); 972 } 973} 974 975static uint32_t 976pci_emul_dior(struct pci_devinst *pi, int baridx, int offset, int size) 977{ 978 struct pci_emul_dsoftc *sc = pi->pi_arg; 979 uint32_t value; 980 981 if (offset + size > DREGSZ) { 982 printf("dior: too large, offset %d size %d\n", offset, size); 983 return (0); 984 } 985 986 if (size == 1) { 987 value = sc->regs[offset]; 988 } else if (size == 2) { 989 value = *(uint16_t *) &sc->regs[offset]; 990 } else { 991 value = *(uint32_t *) &sc->regs[offset]; 992 } 993 994 return (value); 995} 996 997struct pci_devemu pci_dummy = { 998 .pe_emu = "dummy", 999 .pe_init = pci_emul_dinit, 1000 .pe_iow = pci_emul_diow, 1001 .pe_ior = pci_emul_dior 1002}; 1003PCI_EMUL_SET(pci_dummy); 1004 1005#endif /* PCI_EMUL_TEST */ 1006