Changeset 64281 in vbox for trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
- Timestamp:
- Oct 15, 2016 4:46:29 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 111296
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/SUPDrvGip.cpp
r64260 r64281 1320 1320 pGip->aCPUs[i].iCpuGroupMember = iCpuSet; 1321 1321 #ifdef RT_OS_WINDOWS 1322 pGip->aCPUs[i].iCpuGroup = supdrvOSGipGetGroupFromCpu(pDevExt, idCpu, &pGip->aCPUs[i].iCpuGroupMember);1322 supdrvOSGipInitGroupBitsForCpu(pDevExt, pGip, &pGip->aCPUs[i]); 1323 1323 #endif 1324 1324 … … 1744 1744 * Initializes the GIP data. 1745 1745 * 1746 * @returns VBox status code. 1746 1747 * @param pDevExt Pointer to the device instance data. 1747 1748 * @param pGip Pointer to the read-write kernel mapping of the GIP. … … 1751 1752 * @param uUpdateIntervalNS The update interval in nanoseconds. 1752 1753 * @param cCpus The CPU count. 1753 */ 1754 static void supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, 1755 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned uUpdateIntervalNS, unsigned cCpus) 1756 { 1757 size_t const cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), PAGE_SIZE); 1758 unsigned i; 1754 * @param cbGipCpuGroups The supdrvOSGipGetGroupTableSize return value we 1755 * used when allocating the GIP structure. 1756 */ 1757 static int supdrvGipInit(PSUPDRVDEVEXT pDevExt, PSUPGLOBALINFOPAGE pGip, RTHCPHYS HCPhys, 1758 uint64_t u64NanoTS, unsigned uUpdateHz, unsigned uUpdateIntervalNS, 1759 unsigned cCpus, size_t cbGipCpuGroups) 1760 { 1761 size_t const cbGip = RT_ALIGN_Z(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]) + cbGipCpuGroups, PAGE_SIZE); 1762 unsigned i; 1759 1763 #ifdef DEBUG_DARWIN_GIP 1760 1764 OSDBGPRINT(("supdrvGipInit: pGip=%p HCPhys=%lx u64NanoTS=%llu uUpdateHz=%d cCpus=%u\n", pGip, (long)HCPhys, u64NanoTS, uUpdateHz, cCpus)); … … 1794 1798 for (i = 0; i < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx); i++) 1795 1799 pGip->aiCpuFromCpuSetIdx[i] = UINT16_MAX; 1796 pGip->aiFirstCpuSetIdxFromCpuGroup[0] = 0; 1797 for (i = 1; i < RT_ELEMENTS(pGip->aiFirstCpuSetIdxFromCpuGroup); i++) 1798 pGip->aiFirstCpuSetIdxFromCpuGroup[i] = UINT16_MAX; 1799 #ifdef RT_OS_WINDOWS 1800 supdrvOSInitGipGroupTable(pDevExt, pGip); 1801 #endif 1800 for (i = 0; i < RT_ELEMENTS(pGip->aoffCpuGroup); i++) 1801 pGip->aoffCpuGroup[i] = UINT16_MAX; 1802 1802 for (i = 0; i < cCpus; i++) 1803 1803 supdrvGipInitCpu(pGip, &pGip->aCPUs[i], u64NanoTS, 0 /*uCpuHz*/); 1804 #ifdef RT_OS_WINDOWS 1805 int rc = supdrvOSInitGipGroupTable(pDevExt, pGip, cbGipCpuGroups); 1806 AssertRCReturn(rc, rc); 1807 #endif 1804 1808 1805 1809 /* … … 1809 1813 pDevExt->HCPhysGip = HCPhys; 1810 1814 pDevExt->cGipUsers = 0; 1815 1816 return VINF_SUCCESS; 1811 1817 } 1812 1818 … … 1821 1827 { 1822 1828 PSUPGLOBALINFOPAGE pGip; 1829 size_t cbGip; 1830 size_t cbGipCpuGroups; 1823 1831 RTHCPHYS HCPhysGip; 1824 1832 uint32_t u32SystemResolution; … … 1862 1870 * Allocate a contiguous set of pages with a default kernel mapping. 1863 1871 */ 1864 rc = RTR0MemObjAllocCont(&pDevExt->GipMemObj, RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]), false /*fExecutable*/); 1872 cbGipCpuGroups = supdrvOSGipGetGroupTableSize(pDevExt); 1873 cbGip = RT_UOFFSETOF(SUPGLOBALINFOPAGE, aCPUs[cCpus]) + cbGipCpuGroups; 1874 rc = RTR0MemObjAllocCont(&pDevExt->GipMemObj, cbGip, false /*fExecutable*/); 1865 1875 if (RT_FAILURE(rc)) 1866 1876 { … … 1884 1894 u32Interval += u32SystemResolution - uMod; 1885 1895 1886 supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval, cCpus); 1887 1888 /* 1889 * Important sanity check... 1896 rc = supdrvGipInit(pDevExt, pGip, HCPhysGip, RTTimeSystemNanoTS(), RT_NS_1SEC / u32Interval /*=Hz*/, u32Interval, 1897 cCpus, cbGipCpuGroups); 1898 1899 /* 1900 * Important sanity check... (Sets rc) 1890 1901 */ 1891 1902 if (RT_UNLIKELY( pGip->enmUseTscDelta == SUPGIPUSETSCDELTA_ZERO_CLAIMED … … 1894 1905 { 1895 1906 OSDBGPRINT(("supdrvGipCreate: Host-OS/user claims the TSC-deltas are zero but we detected async. TSC! Bad.\n")); 1896 r eturnVERR_INTERNAL_ERROR_2;1907 rc = VERR_INTERNAL_ERROR_2; 1897 1908 } 1898 1909 1899 1910 /* It doesn't make sense to do TSC-delta detection on systems we detect as async. */ 1900 AssertReturn( pGip->u32Mode != SUPGIPMODE_ASYNC_TSC 1901 || pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED, VERR_INTERNAL_ERROR_3); 1911 AssertStmt( pGip->u32Mode != SUPGIPMODE_ASYNC_TSC 1912 || pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ZERO_CLAIMED, 1913 rc = VERR_INTERNAL_ERROR_3); 1902 1914 1903 1915 /* … … 1912 1924 * array with more reasonable values. 1913 1925 */ 1914 if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC)1915 {1916 rc = supdrvGipInitMeasureTscFreq(pGip, true /*fRough*/); /* cannot fail */1917 supdrvGipInitStartTimerForRefiningInvariantTscFreq(pDevExt);1918 }1919 else1920 rc = supdrvGipInitMeasureTscFreq(pGip, false /*fRough*/);1921 1926 if (RT_SUCCESS(rc)) 1922 1927 { 1923 /* 1924 * Start TSC-delta measurement thread before we start getting MP 1925 * events that will try kick it into action (includes the 1926 * RTMpOnAll/supdrvGipInitOnCpu call below). 1927 */ 1928 RTCpuSetEmpty(&pDevExt->TscDeltaCpuSet); 1929 RTCpuSetEmpty(&pDevExt->TscDeltaObtainedCpuSet); 1930 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 1931 if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED) 1932 rc = supdrvTscDeltaThreadInit(pDevExt); 1933 #endif 1928 if (pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC) 1929 { 1930 rc = supdrvGipInitMeasureTscFreq(pGip, true /*fRough*/); /* cannot fail */ 1931 supdrvGipInitStartTimerForRefiningInvariantTscFreq(pDevExt); 1932 } 1933 else 1934 rc = supdrvGipInitMeasureTscFreq(pGip, false /*fRough*/); 1934 1935 if (RT_SUCCESS(rc)) 1935 1936 { 1936 rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt); 1937 /* 1938 * Start TSC-delta measurement thread before we start getting MP 1939 * events that will try kick it into action (includes the 1940 * RTMpOnAll/supdrvGipInitOnCpu call below). 1941 */ 1942 RTCpuSetEmpty(&pDevExt->TscDeltaCpuSet); 1943 RTCpuSetEmpty(&pDevExt->TscDeltaObtainedCpuSet); 1944 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 1945 if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED) 1946 rc = supdrvTscDeltaThreadInit(pDevExt); 1947 #endif 1937 1948 if (RT_SUCCESS(rc)) 1938 1949 { 1939 /* 1940 * Do GIP initialization on all online CPUs. Wake up the 1941 * TSC-delta thread afterwards. 1942 */ 1943 rc = RTMpOnAll(supdrvGipInitOnCpu, pDevExt, pGip); 1950 rc = RTMpNotificationRegister(supdrvGipMpEvent, pDevExt); 1944 1951 if (RT_SUCCESS(rc)) 1945 1952 { 1946 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 1947 supdrvTscDeltaThreadStartMeasurement(pDevExt, true /* fForceAll */); 1948 #else 1949 uint16_t iCpu; 1950 if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED) 1953 /* 1954 * Do GIP initialization on all online CPUs. Wake up the 1955 * TSC-delta thread afterwards. 1956 */ 1957 rc = RTMpOnAll(supdrvGipInitOnCpu, pDevExt, pGip); 1958 if (RT_SUCCESS(rc)) 1951 1959 { 1952 /*1953 * Measure the TSC deltas now that we have MP notifications.1954 */1955 int cTries = 5;1956 do1960 #ifdef SUPDRV_USE_TSC_DELTA_THREAD 1961 supdrvTscDeltaThreadStartMeasurement(pDevExt, true /* fForceAll */); 1962 #else 1963 uint16_t iCpu; 1964 if (pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_ZERO_CLAIMED) 1957 1965 { 1958 rc = supdrvTscMeasureInitialDeltas(pDevExt); 1959 if ( rc != VERR_TRY_AGAIN 1960 && rc != VERR_CPU_OFFLINE) 1961 break; 1962 } while (--cTries > 0); 1963 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 1964 Log(("supdrvTscDeltaInit: cpu[%u] delta %lld\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta)); 1966 /* 1967 * Measure the TSC deltas now that we have MP notifications. 1968 */ 1969 int cTries = 5; 1970 do 1971 { 1972 rc = supdrvTscMeasureInitialDeltas(pDevExt); 1973 if ( rc != VERR_TRY_AGAIN 1974 && rc != VERR_CPU_OFFLINE) 1975 break; 1976 } while (--cTries > 0); 1977 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 1978 Log(("supdrvTscDeltaInit: cpu[%u] delta %lld\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta)); 1979 } 1980 else 1981 { 1982 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 1983 AssertMsg(!pGip->aCPUs[iCpu].i64TSCDelta, ("iCpu=%u %lld mode=%d\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta, pGip->u32Mode)); 1984 } 1985 if (RT_SUCCESS(rc)) 1986 #endif 1987 { 1988 /* 1989 * Create the timer. 1990 * If CPU_ALL isn't supported we'll have to fall back to synchronous mode. 1991 */ 1992 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 1993 { 1994 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, RTTIMER_FLAGS_CPU_ALL, 1995 supdrvGipAsyncTimer, pDevExt); 1996 if (rc == VERR_NOT_SUPPORTED) 1997 { 1998 OSDBGPRINT(("supdrvGipCreate: omni timer not supported, falling back to synchronous mode\n")); 1999 pGip->u32Mode = SUPGIPMODE_SYNC_TSC; 2000 } 2001 } 2002 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC) 2003 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0 /* fFlags */, 2004 supdrvGipSyncAndInvariantTimer, pDevExt); 2005 if (RT_SUCCESS(rc)) 2006 { 2007 /* 2008 * We're good. 2009 */ 2010 Log(("supdrvGipCreate: %u ns interval.\n", u32Interval)); 2011 supdrvGipReleaseHigherTimerFrequencyFromSystem(pDevExt); 2012 2013 g_pSUPGlobalInfoPage = pGip; 2014 return VINF_SUCCESS; 2015 } 2016 2017 OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %u ns interval. rc=%Rrc\n", u32Interval, rc)); 2018 Assert(!pDevExt->pGipTimer); 2019 } 1965 2020 } 1966 2021 else 1967 { 1968 for (iCpu = 0; iCpu < pGip->cCpus; iCpu++) 1969 AssertMsg(!pGip->aCPUs[iCpu].i64TSCDelta, ("iCpu=%u %lld mode=%d\n", iCpu, pGip->aCPUs[iCpu].i64TSCDelta, pGip->u32Mode)); 1970 } 1971 if (RT_SUCCESS(rc)) 1972 #endif 1973 { 1974 /* 1975 * Create the timer. 1976 * If CPU_ALL isn't supported we'll have to fall back to synchronous mode. 1977 */ 1978 if (pGip->u32Mode == SUPGIPMODE_ASYNC_TSC) 1979 { 1980 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, RTTIMER_FLAGS_CPU_ALL, 1981 supdrvGipAsyncTimer, pDevExt); 1982 if (rc == VERR_NOT_SUPPORTED) 1983 { 1984 OSDBGPRINT(("supdrvGipCreate: omni timer not supported, falling back to synchronous mode\n")); 1985 pGip->u32Mode = SUPGIPMODE_SYNC_TSC; 1986 } 1987 } 1988 if (pGip->u32Mode != SUPGIPMODE_ASYNC_TSC) 1989 rc = RTTimerCreateEx(&pDevExt->pGipTimer, u32Interval, 0 /* fFlags */, 1990 supdrvGipSyncAndInvariantTimer, pDevExt); 1991 if (RT_SUCCESS(rc)) 1992 { 1993 /* 1994 * We're good. 1995 */ 1996 Log(("supdrvGipCreate: %u ns interval.\n", u32Interval)); 1997 supdrvGipReleaseHigherTimerFrequencyFromSystem(pDevExt); 1998 1999 g_pSUPGlobalInfoPage = pGip; 2000 return VINF_SUCCESS; 2001 } 2002 2003 OSDBGPRINT(("supdrvGipCreate: failed create GIP timer at %u ns interval. rc=%Rrc\n", u32Interval, rc)); 2004 Assert(!pDevExt->pGipTimer); 2005 } 2022 OSDBGPRINT(("supdrvGipCreate: RTMpOnAll failed. rc=%Rrc\n", rc)); 2006 2023 } 2007 2024 else 2008 OSDBGPRINT(("supdrvGipCreate: RTMpOnAll failed. rc=%Rrc\n", rc));2025 OSDBGPRINT(("supdrvGipCreate: failed to register MP event notfication. rc=%Rrc\n", rc)); 2009 2026 } 2010 2027 else 2011 OSDBGPRINT(("supdrvGipCreate: failed to register MP event notfication. rc=%Rrc\n", rc));2028 OSDBGPRINT(("supdrvGipCreate: supdrvTscDeltaInit failed. rc=%Rrc\n", rc)); 2012 2029 } 2013 2030 else 2014 OSDBGPRINT(("supdrvGipCreate: supdrvTscDeltaInit failed. rc=%Rrc\n", rc)); 2015 } 2016 else 2017 OSDBGPRINT(("supdrvGipCreate: supdrvTscMeasureInitialDeltas failed. rc=%Rrc\n", rc)); 2031 OSDBGPRINT(("supdrvGipCreate: supdrvTscMeasureInitialDeltas failed. rc=%Rrc\n", rc)); 2032 } 2018 2033 2019 2034 /* Releases timer frequency increase too. */
Note:
See TracChangeset
for help on using the changeset viewer.