VirtualBox

Changeset 65489 in vbox


Ignore:
Timestamp:
Jan 27, 2017 4:12:00 PM (8 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
113119
Message:

DevPciIch9.cpp: implement init of prefetchable BARs

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Devices/Bus/DevPciIch9.cpp

    r65324 r65489  
    9898DECLINLINE(PPDMPCIDEV) ich9pciFindBridge(PDEVPCIBUS pBus, uint8_t uBus);
    9999static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus);
     100static bool ich9pciBiosInitAllDevicesPrefetchableOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus, bool fUse64Bit, bool fDryrun);
    100101#endif
    101102
     
    16241625}
    16251626
    1626 static void ich9pciBiosInitDeviceBARs(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn)
     1627static int ichpciBiosInitDeviceGetRegions(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn)
    16271628{
    16281629    uint8_t uHeaderType = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_HEADER_TYPE, 1) & 0x7f;
    1629     int cRegions = 0;
    16301630    if (uHeaderType == 0x00)
    16311631        /* Ignore ROM region here, which is included in VBOX_PCI_NUM_REGIONS. */
    1632         cRegions = VBOX_PCI_NUM_REGIONS - 1;
     1632        return VBOX_PCI_NUM_REGIONS - 1;
    16331633    else if (uHeaderType == 0x01)
    16341634        /* PCI bridges have 2 BARs. */
    1635         cRegions = 2;
    1636 
     1635        return 2;
     1636    else
     1637    {
     1638        AssertMsgFailed(("invalid header type %#x\n", uHeaderType));
     1639        return 0;
     1640    }
     1641}
     1642
     1643static void ich9pciBiosInitDeviceBARs(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn)
     1644{
     1645    int cRegions = ichpciBiosInitDeviceGetRegions(pPciRoot, uBus, uDevFn);
    16371646    bool fSuppressMem = false;
    16381647    bool fActiveMemRegion = false;
     
    17731782}
    17741783
     1784static bool ich9pciBiosInitDevicePrefetchableBARs(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn, bool fUse64Bit, bool fDryrun)
     1785{
     1786    int cRegions = ichpciBiosInitDeviceGetRegions(pPciRoot, uBus, uDevFn);
     1787    bool fActiveMemRegion = false;
     1788    for (int iRegion = 0; iRegion < cRegions; iRegion++)
     1789    {
     1790        uint32_t u32Address = ich9pciGetRegionReg(iRegion);
     1791        uint8_t u8ResourceType = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, u32Address, 1);
     1792        bool fPrefetch =    (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_MEM_PREFETCH | PCI_ADDRESS_SPACE_IO)))
     1793                      == PCI_ADDRESS_SPACE_MEM_PREFETCH;
     1794        bool f64Bit =    (u8ResourceType & ((uint8_t)(PCI_ADDRESS_SPACE_BAR64 | PCI_ADDRESS_SPACE_IO)))
     1795                      == PCI_ADDRESS_SPACE_BAR64;
     1796        uint64_t cbRegSize64 = 0;
     1797
     1798        /* Everything besides prefetchable regions has been set up already. */
     1799        if (!fPrefetch)
     1800            continue;
     1801
     1802        if (f64Bit)
     1803        {
     1804            ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, u32Address,   UINT32_C(0xffffffff), 4);
     1805            ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, u32Address+4, UINT32_C(0xffffffff), 4);
     1806            cbRegSize64  =            ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, u32Address,   4);
     1807            cbRegSize64 |= ((uint64_t)ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, u32Address+4, 4) << 32);
     1808            cbRegSize64 &= ~UINT64_C(0x0f);
     1809            cbRegSize64 = (~cbRegSize64) + 1;
     1810        }
     1811        else
     1812        {
     1813            uint32_t cbRegSize32;
     1814            ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, u32Address, UINT32_C(0xffffffff), 4);
     1815            cbRegSize32 = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, u32Address, 4);
     1816            cbRegSize32 &= ~UINT32_C(0x0f);
     1817            cbRegSize32 = (~cbRegSize32) + 1;
     1818
     1819            cbRegSize64 = cbRegSize32;
     1820        }
     1821        Log2(("%s: Size of region %u for device %d on bus %d is %lld\n", __FUNCTION__, iRegion, uDevFn, uBus, cbRegSize64));
     1822
     1823        if (cbRegSize64)
     1824        {
     1825            uint64_t uNew;
     1826            if (!fUse64Bit)
     1827            {
     1828                uNew = pPciRoot->uPciBiosMmio;
     1829                /* Align starting address to region size. */
     1830                uNew = (uNew + cbRegSize64 - 1) & ~(cbRegSize64 - 1);
     1831                /* Unconditionally exclude I/O-APIC/HPET/ROM. Pessimistic, but better than causing a mess. */
     1832                if (   !uNew
     1833                    || (uNew <= UINT32_C(0xffffffff) && uNew + cbRegSize64 - 1 >= UINT32_C(0xfec00000))
     1834                    || uNew >= _4G)
     1835                {
     1836                    Assert(fDryrun);
     1837                    return true;
     1838                }
     1839                if (!fDryrun)
     1840                {
     1841                    LogFunc(("Start address of MMIO region %u is %#x\n", iRegion, uNew));
     1842                    ich9pciBiosInitSetRegionAddress(pPciRoot, uBus, uDevFn, iRegion, uNew);
     1843                    fActiveMemRegion = true;
     1844                }
     1845                pPciRoot->uPciBiosMmio = uNew + cbRegSize64;
     1846            }
     1847            else
     1848            {
     1849                /* Can't handle 32-bit BARs when forcing 64-bit allocs. */
     1850                if (!f64Bit)
     1851                {
     1852                    Assert(fDryrun);
     1853                    return true;
     1854                }
     1855                uNew = pPciRoot->uPciBiosMmio64;
     1856                /* Align starting address to region size. */
     1857                uNew = (uNew + cbRegSize64 - 1) & ~(cbRegSize64 - 1);
     1858                pPciRoot->uPciBiosMmio64 = uNew + cbRegSize64;
     1859                if (!fDryrun)
     1860                {
     1861                    LogFunc(("Start address of 64-bit MMIO region %u/%u is %#llx\n", iRegion, iRegion + 1, uNew));
     1862                    ich9pciBiosInitSetRegionAddress(pPciRoot, uBus, uDevFn, iRegion, uNew);
     1863                    fActiveMemRegion = true;
     1864                }
     1865            }
     1866
     1867            if (f64Bit)
     1868                iRegion++; /* skip next region */
     1869        }
     1870    }
     1871
     1872    if (!fDryrun)
     1873    {
     1874        /* Update the command word appropriately. */
     1875        uint8_t uCmd = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_COMMAND, 2);
     1876        if (fActiveMemRegion)
     1877            uCmd |= VBOX_PCI_COMMAND_MEMORY; /* Enable MMIO access. */
     1878        ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_COMMAND, uCmd, 2);
     1879    }
     1880    else
     1881        Assert(!fActiveMemRegion);
     1882
     1883    return false;
     1884}
     1885
     1886static bool ich9pciBiosInitBridgePrefetchable(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn, bool fUse64Bit, bool fDryrun)
     1887{
     1888    Log(("BIOS init bridge (prefetch): %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
     1889
     1890    pPciRoot->uPciBiosMmio = RT_ALIGN_32(pPciRoot->uPciBiosMmio, 1024*1024);
     1891    pPciRoot->uPciBiosMmio64 = RT_ALIGN_64(pPciRoot->uPciBiosMmio64, 1024*1024);
     1892
     1893    /* Save values to compare later to. */
     1894    uint32_t u32MMIOAddressBase = pPciRoot->uPciBiosMmio;
     1895    uint64_t u64MMIOAddressBase = pPciRoot->uPciBiosMmio64;
     1896
     1897    uint8_t uBridgeBus = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_SECONDARY_BUS, 1);
     1898
     1899    /* Init all devices behind the bridge (recursing to further buses). */
     1900    bool fRes = ich9pciBiosInitAllDevicesPrefetchableOnBus(pPciRoot, uBridgeBus, fUse64Bit, fDryrun);
     1901    if (fDryrun)
     1902        return fRes;
     1903    Assert(!fRes);
     1904
     1905    /* Set prefetchable MMIO limit register with 1MB boundary. */
     1906    uint64_t uBase, uLimit;
     1907    if (fUse64Bit)
     1908    {
     1909        if (u64MMIOAddressBase == pPciRoot->uPciBiosMmio64)
     1910            return false;
     1911        uBase = u64MMIOAddressBase;
     1912        uLimit = RT_ALIGN_64(pPciRoot->uPciBiosMmio64, 1024*1024) - 1;
     1913    }
     1914    else
     1915    {
     1916        if (u32MMIOAddressBase == pPciRoot->uPciBiosMmio)
     1917            return false;
     1918        uBase = u32MMIOAddressBase;
     1919        uLimit = RT_ALIGN_32(pPciRoot->uPciBiosMmio, 1024*1024) - 1;
     1920    }
     1921    ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_BASE_UPPER32, uBase >> 32, 4);
     1922    ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_BASE, (uint32_t)(uBase >> 16) & UINT32_C(0xfff0), 2);
     1923    ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_LIMIT_UPPER32, uLimit >> 32, 4);
     1924    ich9pciBiosInitWriteConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_PREF_MEMORY_LIMIT, (uint32_t)(uLimit >> 16) & UINT32_C(0xfff0), 2);
     1925
     1926    return false;
     1927}
     1928
     1929static bool ich9pciBiosInitAllDevicesPrefetchableOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus, bool fUse64Bit, bool fDryrun)
     1930{
     1931    /* First pass: assign resources to all devices. */
     1932    for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
     1933    {
     1934        /* check if device is present */
     1935        uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
     1936        if (uVendor == 0xffff)
     1937            continue;
     1938
     1939        Log(("BIOS init device (prefetch): %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
     1940
     1941        /* prefetchable memory mappings */
     1942        bool fRes = ich9pciBiosInitDevicePrefetchableBARs(pPciRoot, uBus, uDevFn, fUse64Bit, fDryrun);
     1943        if (fRes)
     1944        {
     1945            Assert(fDryrun);
     1946            return fRes;
     1947        }
     1948    }
     1949
     1950    /* Second pass: handle bridges recursively. */
     1951    for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
     1952    {
     1953        /* check if device is present */
     1954        uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
     1955        if (uVendor == 0xffff)
     1956            continue;
     1957
     1958        /* only handle PCI-to-PCI bridges */
     1959        uint16_t uDevClass = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
     1960        if (uDevClass != 0x0604)
     1961            continue;
     1962
     1963        Log(("BIOS init bridge (prefetch): %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
     1964        bool fRes = ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, fUse64Bit, fDryrun);
     1965        if (fRes)
     1966        {
     1967            Assert(fDryrun);
     1968            return fRes;
     1969        }
     1970    }
     1971    return false;
     1972}
     1973
    17751974static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus)
    17761975{
     
    18782077        Log(("BIOS init bridge: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
    18792078        ich9pciBiosInitBridge(pPciRoot, uBus, uDevFn);
     2079    }
     2080
     2081    /* Third pass (only for bus 0): set up prefetchable bars recursively. */
     2082    if (uBus == 0)
     2083    {
     2084        for (uint32_t uDevFn = 0; uDevFn < 256; uDevFn++)
     2085        {
     2086            /* check if device is present */
     2087            uint16_t uVendor = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_VENDOR_ID, 2);
     2088            if (uVendor == 0xffff)
     2089                continue;
     2090
     2091            /* only handle PCI-to-PCI bridges */
     2092            uint16_t uDevClass = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_CLASS_DEVICE, 2);
     2093            if (uDevClass != 0x0604)
     2094                continue;
     2095
     2096            Log(("BIOS init prefetchable memory behind bridge: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
     2097            /* Save values for the prefetchable dryruns. */
     2098            uint32_t u32MMIOAddressBase = pPciRoot->uPciBiosMmio;
     2099            uint64_t u64MMIOAddressBase = pPciRoot->uPciBiosMmio64;
     2100
     2101            bool fProbe = ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, false /* fUse64Bit */, true /* fDryrun */);
     2102            pPciRoot->uPciBiosMmio = u32MMIOAddressBase;
     2103            pPciRoot->uPciBiosMmio64 = u64MMIOAddressBase;
     2104            if (fProbe)
     2105            {
     2106                fProbe = ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, true /* fUse64Bit */, true /* fDryrun */);
     2107                pPciRoot->uPciBiosMmio = u32MMIOAddressBase;
     2108                pPciRoot->uPciBiosMmio64 = u64MMIOAddressBase;
     2109                if (fProbe)
     2110                    LogRel(("PCI: unresolvable prefetchable memory behind bridge %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7));
     2111                else
     2112                    ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, true /* fUse64Bit */, false /* fDryrun */);
     2113            }
     2114            else
     2115                ich9pciBiosInitBridgePrefetchable(pPciRoot, uBus, uDevFn, false /* fUse64Bit */, false /* fDryrun */);
     2116        }
    18802117    }
    18812118}
     
    26232860                            (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_MEMORY_LIMIT) & 0xfff0) << 16 | 0xfffff);
    26242861            devpciR3InfoIndent(pHlp, iIndentLvl);
    2625             pHlp->pfnPrintf(pHlp, "behind bridge: prefetch memory %#018x..%#018x\n",
     2862            pHlp->pfnPrintf(pHlp, "behind bridge: prefetch memory %#018llx..%#018llx\n",
    26262863                            (  ((uint64_t)ich9pciGetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_BASE_UPPER32) << 32)
    26272864                             | (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_BASE) & 0xfff0) << 16),
    26282865                            (  ((uint64_t)ich9pciGetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_LIMIT_UPPER32) << 32)
    2629                              | (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_LIMIT) & 0xfff0) << 16)
     2866                             | (uint32_t)(ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_LIMIT) & 0xfff0) << 16)
    26302867                             | 0xfffff);
    26312868            devpciR3InfoPciBus(pBusSub, pHlp, iIndentLvl + 1, fRegisters);
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette