Changeset 65489 in vbox
- Timestamp:
- Jan 27, 2017 4:12:00 PM (8 years ago)
- svn:sync-xref-src-repo-rev:
- 113119
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Devices/Bus/DevPciIch9.cpp
r65324 r65489 98 98 DECLINLINE(PPDMPCIDEV) ich9pciFindBridge(PDEVPCIBUS pBus, uint8_t uBus); 99 99 static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus); 100 static bool ich9pciBiosInitAllDevicesPrefetchableOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus, bool fUse64Bit, bool fDryrun); 100 101 #endif 101 102 … … 1624 1625 } 1625 1626 1626 static void ich9pciBiosInitDeviceBARs(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn)1627 static int ichpciBiosInitDeviceGetRegions(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn) 1627 1628 { 1628 1629 uint8_t uHeaderType = ich9pciBiosInitReadConfig(pPciRoot, uBus, uDevFn, VBOX_PCI_HEADER_TYPE, 1) & 0x7f; 1629 int cRegions = 0;1630 1630 if (uHeaderType == 0x00) 1631 1631 /* 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; 1633 1633 else if (uHeaderType == 0x01) 1634 1634 /* 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 1643 static void ich9pciBiosInitDeviceBARs(PDEVPCIROOT pPciRoot, uint8_t uBus, uint8_t uDevFn) 1644 { 1645 int cRegions = ichpciBiosInitDeviceGetRegions(pPciRoot, uBus, uDevFn); 1637 1646 bool fSuppressMem = false; 1638 1647 bool fActiveMemRegion = false; … … 1773 1782 } 1774 1783 1784 static 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 1886 static 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 1929 static 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 1775 1974 static void ich9pciBiosInitAllDevicesOnBus(PDEVPCIROOT pPciRoot, uint8_t uBus) 1776 1975 { … … 1878 2077 Log(("BIOS init bridge: %02x:%02x.%d\n", uBus, uDevFn >> 3, uDevFn & 7)); 1879 2078 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 } 1880 2117 } 1881 2118 } … … 2623 2860 (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_MEMORY_LIMIT) & 0xfff0) << 16 | 0xfffff); 2624 2861 devpciR3InfoIndent(pHlp, iIndentLvl); 2625 pHlp->pfnPrintf(pHlp, "behind bridge: prefetch memory %#018 x..%#018x\n",2862 pHlp->pfnPrintf(pHlp, "behind bridge: prefetch memory %#018llx..%#018llx\n", 2626 2863 ( ((uint64_t)ich9pciGetDWord(&pBusSub->PciDev, VBOX_PCI_PREF_BASE_UPPER32) << 32) 2627 2864 | (ich9pciGetWord(&pBusSub->PciDev, VBOX_PCI_PREF_MEMORY_BASE) & 0xfff0) << 16), 2628 2865 ( ((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) 2630 2867 | 0xfffff); 2631 2868 devpciR3InfoPciBus(pBusSub, pHlp, iIndentLvl + 1, fRegisters);
Note:
See TracChangeset
for help on using the changeset viewer.