Module Name: xsrc Committed By: jmcneill Date: Thu Oct 8 23:04:34 UTC 2020
Modified Files: xsrc/external/mit/libpciaccess/dist/src: netbsd_pci.c Log Message: Fix crash when more than 32 pci(4) devices are attached. To generate a diff of this commit: cvs rdiff -u -r1.18 -r1.19 \ xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c diff -u xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c:1.18 xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c:1.19 --- xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c:1.18 Fri Oct 26 11:17:33 2018 +++ xsrc/external/mit/libpciaccess/dist/src/netbsd_pci.c Thu Oct 8 23:04:34 2020 @@ -66,7 +66,7 @@ typedef struct _pcibus { int maxdevs; /* maximum number of devices */ } PciBus; -static PciBus buses[32]; /* indexed by pci_device.domain */ +static PciBus *buses = NULL; /* indexed by pci_device.domain */ static int nbuses = 0; /* number of buses found */ /* @@ -99,7 +99,7 @@ pci_read(int domain, int bus, int dev, i { uint32_t rval; - if ((domain < 0) || (domain > nbuses)) + if ((domain < 0) || (domain >= nbuses)) return -1; if (pcibus_conf_read(buses[domain].fd, (unsigned int)bus, @@ -115,7 +115,7 @@ static int pci_write(int domain, int bus, int dev, int func, uint32_t reg, uint32_t val) { - if ((domain < 0) || (domain > nbuses)) + if ((domain < 0) || (domain >= nbuses)) return -1; return pcibus_conf_write(buses[domain].fd, (unsigned int)bus, @@ -127,7 +127,7 @@ pci_nfuncs(int domain, int bus, int dev) { uint32_t hdr; - if ((domain < 0) || (domain > nbuses)) + if ((domain < 0) || (domain >= nbuses)) return -1; if (pci_read(domain, bus, dev, 0, PCI_BHLC_REG, &hdr) != 0) @@ -907,13 +907,42 @@ static const struct pci_system_methods n .has_kernel_driver = pci_device_netbsd_has_kernel_driver, }; +static int +pci_system_netbsd_open_device(int unit) +{ + char netbsd_devname[32]; + int pcifd; + + snprintf(netbsd_devname, 32, "/dev/pci%d", unit); + pcifd = open(netbsd_devname, O_RDWR | O_CLOEXEC); + if (pcifd == -1) + pcifd = open(netbsd_devname, O_RDONLY | O_CLOEXEC); + + return pcifd; +} + +static int +pci_system_netbsd_count_buses(void) +{ + int pcifd, nbuses; + + do { + pcifd = pci_system_netbsd_open_device(nbuses); + if (pcifd != -1) { + close(pcifd); + nbuses++; + } + } while (pcifd != -1); + + return nbuses; +} + int pci_system_netbsd_create(void) { struct pci_device_private *device; - int bus, dev, func, ndevs, nfuncs, domain, pcifd; + int bus, dev, func, ndevs, nfuncs, domain, pcifd, n; uint32_t reg; - char netbsd_devname[32]; struct pciio_businfo businfo; pci_sys = calloc(1, sizeof(struct pci_system)); @@ -921,19 +950,18 @@ pci_system_netbsd_create(void) pci_sys->methods = &netbsd_pci_methods; ndevs = 0; - nbuses = 0; - snprintf(netbsd_devname, 32, "/dev/pci%d", nbuses); - pcifd = open(netbsd_devname, O_RDWR | O_CLOEXEC); - if (pcifd == -1) - pcifd = open(netbsd_devname, O_RDONLY | O_CLOEXEC); + nbuses = pci_system_netbsd_count_buses(); + if (nbuses > 0) + buses = calloc(nbuses, sizeof(PciBus)); + + for (n = 0; n < nbuses; n++) { + pcifd = pci_system_netbsd_open_device(n); - while (pcifd > 0) { ioctl(pcifd, PCI_IOC_BUSINFO, &businfo); - buses[nbuses].fd = pcifd; - buses[nbuses].num = bus = businfo.busno; - buses[nbuses].maxdevs = businfo.maxdevs; - domain = nbuses; - nbuses++; + buses[n].fd = pcifd; + buses[n].num = bus = businfo.busno; + buses[n].maxdevs = businfo.maxdevs; + domain = n; for (dev = 0; dev < businfo.maxdevs; dev++) { nfuncs = pci_nfuncs(domain, bus, dev); for (func = 0; func < nfuncs; func++) { @@ -947,10 +975,6 @@ pci_system_netbsd_create(void) ndevs++; } } - snprintf(netbsd_devname, 32, "/dev/pci%d", nbuses); - pcifd = open(netbsd_devname, O_RDWR); - if (pcifd == -1) - pcifd = open(netbsd_devname, O_RDONLY | O_CLOEXEC); } pci_sys->num_devices = ndevs;