--- //depot/vendor/freebsd/src/usr.sbin/bhyve/pci_emul.c +++ //depot/user/jhb/bhyve/usr.sbin/bhyve/pci_emul.c @@ -604,48 +604,39 @@ static int pci_emul_add_capability(struct pci_devinst *pi, u_char *capdata, int caplen) { - int i, capoff, capid, reallen; + int i, capoff, reallen; uint16_t sts; - static u_char endofcap[4] = { - PCIY_RESERVED, 0, 0, 0 - }; - - assert(caplen > 0 && capdata[0] != PCIY_RESERVED); + assert(caplen > 0); reallen = roundup2(caplen, 4); /* dword aligned */ sts = pci_get_cfgdata16(pi, PCIR_STATUS); - if ((sts & PCIM_STATUS_CAPPRESENT) == 0) { + if ((sts & PCIM_STATUS_CAPPRESENT) == 0) capoff = CAP_START_OFFSET; - pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff); - pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT); - } else { - capoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR); - while (1) { - assert((capoff & 0x3) == 0); - capid = pci_get_cfgdata8(pi, capoff); - if (capid == PCIY_RESERVED) - break; - capoff = pci_get_cfgdata8(pi, capoff + 1); - } - } + else + capoff = pi->pi_capend + 1; /* Check if we have enough space */ - if (capoff + reallen + sizeof(endofcap) > PCI_REGMAX + 1) + if (capoff + reallen > PCI_REGMAX + 1) return (-1); + /* Set the previous capability pointer */ + if ((sts & PCIM_STATUS_CAPPRESENT) == 0) { + pci_set_cfgdata8(pi, PCIR_CAP_PTR, capoff); + pci_set_cfgdata16(pi, PCIR_STATUS, sts|PCIM_STATUS_CAPPRESENT); + } else + pci_set_cfgdata8(pi, pi->pi_prevcap + 1, capoff); + /* Copy the capability */ for (i = 0; i < caplen; i++) pci_set_cfgdata8(pi, capoff + i, capdata[i]); /* Set the next capability pointer */ - pci_set_cfgdata8(pi, capoff + 1, capoff + reallen); + pci_set_cfgdata8(pi, capoff + 1, 0); - /* Copy of the reserved capability which serves as the end marker */ - for (i = 0; i < sizeof(endofcap); i++) - pci_set_cfgdata8(pi, capoff + reallen + i, endofcap[i]); - + pi->pi_prevcap = capoff; + pi->pi_capend = capoff + reallen - 1; return (0); } @@ -732,7 +723,7 @@ static void pci_populate_msixcap(struct msixcap *msixcap, int msgnum, int barnum, - uint32_t msix_tab_size, int nextptr) + uint32_t msix_tab_size) { CTASSERT(sizeof(struct msixcap) == 12); @@ -740,7 +731,6 @@ bzero(msixcap, sizeof(struct msixcap)); msixcap->capid = PCIY_MSIX; - msixcap->nextptr = nextptr; /* * Message Control Register, all fields set to @@ -802,7 +792,7 @@ pci_msix_table_init(pi, msgnum); - pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size, 0); + pci_populate_msixcap(&msixcap, msgnum, barnum, tab_size); /* allocate memory for MSI-X Table and PBA */ pci_emul_alloc_bar(pi, barnum, PCIBAR_MEM32, @@ -925,11 +915,9 @@ /* Find the capability that we want to update */ capoff = CAP_START_OFFSET; while (1) { - capid = pci_get_cfgdata8(pi, capoff); - if (capid == PCIY_RESERVED) + nextoff = pci_get_cfgdata8(pi, capoff + 1); + if (nextoff == 0) break; - - nextoff = pci_get_cfgdata8(pi, capoff + 1); if (offset >= capoff && offset < nextoff) break; @@ -952,6 +940,7 @@ return; } + capid = pci_get_cfgdata8(pi, capoff); switch (capid) { case PCIY_MSI: msicap_cfgwrite(pi, capoff, offset, bytes, val); @@ -970,25 +959,14 @@ static int pci_emul_iscap(struct pci_devinst *pi, int offset) { - int found; uint16_t sts; - uint8_t capid, lastoff; - found = 0; sts = pci_get_cfgdata16(pi, PCIR_STATUS); if ((sts & PCIM_STATUS_CAPPRESENT) != 0) { - lastoff = pci_get_cfgdata8(pi, PCIR_CAP_PTR); - while (1) { - assert((lastoff & 0x3) == 0); - capid = pci_get_cfgdata8(pi, lastoff); - if (capid == PCIY_RESERVED) - break; - lastoff = pci_get_cfgdata8(pi, lastoff + 1); - } - if (offset >= CAP_START_OFFSET && offset <= lastoff) - found = 1; + if (offset >= CAP_START_OFFSET && offset <= pi->pi_capend) + return (1); } - return (found); + return (0); } static int --- //depot/vendor/freebsd/src/usr.sbin/bhyve/pci_emul.h +++ //depot/user/jhb/bhyve/usr.sbin/bhyve/pci_emul.h @@ -39,7 +39,6 @@ #include #define PCI_BARMAX PCIR_MAX_BAR_0 /* BAR registers in a Type 0 header */ -#define PCIY_RESERVED 0x00 struct vmctx; struct pci_devinst; @@ -115,6 +114,8 @@ uint8_t pi_bus, pi_slot, pi_func; char pi_name[PI_NAMESZ]; int pi_bar_getsize; + int pi_prevcap; + int pi_capend; struct { int8_t pin;