Changeset 54224 in vbox for trunk/include/VBox
- Timestamp:
- Feb 16, 2015 10:41:32 PM (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/sup.h
r54222 r54224 240 240 /** Current CPU Frequency. */ 241 241 volatile uint64_t u64CpuHz; 242 /** The TSC delta with reference to the master TSC . */242 /** The TSC delta with reference to the master TSC, subtract from RDTSC. */ 243 243 volatile int64_t i64TSCDelta; 244 244 /** Number of errors during updating. … … 439 439 ((a_pGip)->u32Mode == SUPGIPMODE_INVARIANT_TSC && !((a_pGip)->fOsTscDeltasInSync)) 440 440 441 /** Whether the application of TSC-deltas are worth it (performance matters). */442 #define GIP_TSC_DELTAS_ROUGHLY_IN_SYNC(a_pGip) ((a_pGip)->fTscDeltasRoughlyInSync)443 441 444 442 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) … … 1547 1545 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) 1548 1546 1549 /** 1550 * Applies the TSC delta to the supplied raw TSC value. 1551 * 1552 * @returns VBox status code. 1553 * @param pGip Pointer to the GIP. 1554 * @param puTsc Pointer to a valid TSC value before the TSC delta has been applied. 1555 * @param idApic The APIC ID of the CPU @c puTsc corresponds to. 1556 * @param fDeltaApplied Where to store whether the TSC delta was succesfully 1557 * applied or not (optional, can be NULL). 1558 * 1559 * @remarks Maybe called with interrupts disabled in ring-0! 1560 * 1561 * @note If you change the delta calculation made here, make sure to update 1562 * the assembly version in sup.mac! Also update supdrvGipMpEvent() 1563 * while re-adjusting deltas while choosing a new GIP master. 1564 */ 1565 DECLINLINE(int) SUPTscDeltaApply(PSUPGLOBALINFOPAGE pGip, uint64_t *puTsc, uint16_t idApic, bool *pfDeltaApplied) 1566 { 1567 PSUPGIPCPU pGipCpu; 1568 uint16_t iCpu; 1569 1570 /* Validate. */ 1571 Assert(puTsc); 1572 Assert(pGip); 1573 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip)); 1574 1575 /** @todo convert these to AssertMsg() after sufficient testing before public 1576 * release. */ 1577 AssertMsgReturn(idApic < RT_ELEMENTS(pGip->aiCpuFromApicId), ("idApic=%u\n", idApic), VERR_INVALID_CPU_ID); 1578 iCpu = pGip->aiCpuFromApicId[idApic]; 1579 AssertMsgReturn(iCpu < pGip->cCpus, ("iCpu=%u cCpus=%u\n", iCpu, pGip->cCpus), VERR_INVALID_CPU_INDEX); 1580 pGipCpu = &pGip->aCPUs[iCpu]; 1581 Assert(pGipCpu); 1582 1583 if (RT_LIKELY(pGipCpu->i64TSCDelta != INT64_MAX)) 1584 { 1585 *puTsc -= pGipCpu->i64TSCDelta; 1586 if (pfDeltaApplied) 1587 *pfDeltaApplied = true; 1588 } 1589 else if (pfDeltaApplied) 1590 *pfDeltaApplied = false; 1591 1592 return VINF_SUCCESS; 1593 } 1594 1595 1596 /** 1597 * Gets the delta-adjusted TSC. 1598 * 1599 * Must only be called when GIP mode is invariant (i.e. when TSC deltas are 1600 * likely to be computed and available). In other GIP modes, like async, we 1601 * don't bother with computing TSC deltas and therefore it is meaningless to 1602 * call this function, use SUPReadTSC() instead. 1603 * 1604 * @returns VBox status code. 1605 * @param puTsc Where to store the normalized TSC value. 1606 * @param pidApic Where to store the APIC ID of the CPU where the TSC 1607 * was read (optional, can be NULL). This is updated 1608 * even if the function fails with 1609 * VERR_SUPDRV_TSC_READ_FAILED. Not guaranteed to be 1610 * updated for other failures. 1611 * 1612 * @remarks May be called with interrupts disabled in ring-0! 1613 */ 1614 DECLINLINE(int) SUPGetTsc(uint64_t *puTsc, uint16_t *pidApic) 1615 { 1616 # ifdef IN_RING3 1617 1618 /** @todo Use rdtscp after figuring out what the host OS has stuffed into the 1619 * TSC_AUX msr, otherwise use the fallback below. */ 1620 int cTries = 10; 1621 Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(g_pSUPGlobalInfoPage)); 1622 do 1623 { 1624 uint16_t idApicBefore; 1625 uint16_t idApicAfter; 1626 1627 /* The chance of getting preempted twice here is rather low, hence we 1628 take this approach. Performance matters, see @bugref{6710} comment #24. */ 1629 idApicBefore = ASMGetApicId(); 1630 *puTsc = ASMReadTSC(); 1631 idApicAfter = ASMGetApicId(); 1632 if (RT_LIKELY(idApicBefore == idApicAfter)) 1633 { 1634 SUPTscDeltaApply(g_pSUPGlobalInfoPage, puTsc, idApicBefore, NULL); 1635 if (pidApic) 1636 *pidApic = idApicBefore; 1637 return VINF_SUCCESS; 1638 } 1639 } while (cTries-- > 0); 1640 *puTsc = 0; 1641 return VERR_SUPDRV_TSC_READ_FAILED; 1642 1643 /** @todo get rid of SUPR3ReadTsc(). */ 1644 //return SUPR3ReadTsc(puTsc, pidApic); 1645 # else 1646 RTCCUINTREG uFlags; 1647 uint16_t idApic; 1648 bool fDeltaApplied; 1649 int rc; 1650 1651 /** @todo Use rdtscp after figuring out what the host OS has stuffed into the 1652 * TSC_AUX msr, otherwise use the fallback below. */ 1653 1654 /* Validate. */ 1655 Assert(puTsc); 1656 1657 uFlags = ASMIntDisableFlags(); 1658 idApic = ASMGetApicId(); /* Doubles as serialization. */ 1659 *puTsc = ASMReadTSC(); 1660 ASMSetFlags(uFlags); 1661 1662 if (pidApic) 1663 *pidApic = idApic; 1664 1665 rc = SUPTscDeltaApply(g_pSUPGlobalInfoPage, puTsc, idApic, &fDeltaApplied); 1666 AssertRC(rc); 1667 return fDeltaApplied ? VINF_SUCCESS : VERR_SUPDRV_TSC_READ_FAILED; 1668 # endif 1669 } 1670 1547 /** @internal */ 1548 SUPDECL(uint64_t) SUPReadTscWithDelta(void); 1671 1549 1672 1550 /** … … 1682 1560 { 1683 1561 if ( GIP_ARE_TSC_DELTAS_APPLICABLE(g_pSUPGlobalInfoPage) 1684 && !GIP_TSC_DELTAS_ROUGHLY_IN_SYNC(g_pSUPGlobalInfoPage)) 1685 { 1686 uint64_t u64Tsc = UINT64_MAX; 1687 int rc = SUPGetTsc(&u64Tsc, NULL /* pidApic */); 1688 NOREF(rc); 1689 #ifdef DEBUG_ramshankar 1690 AssertRC(rc); 1691 #endif 1692 return u64Tsc; 1693 } 1562 && !g_pSUPGlobalInfoPage->fTscDeltasRoughlyInSync) 1563 return SUPReadTscWithDelta(); 1694 1564 return ASMReadTSC(); 1695 1565 }
Note:
See TracChangeset
for help on using the changeset viewer.