VirtualBox

Changeset 54308 in vbox


Ignore:
Timestamp:
Feb 19, 2015 7:43:51 PM (10 years ago)
Author:
vboxsync
Message:

VMM,SUP: Apply the tsc delta where it matters. Made sense out of the paravirt-tsc-mode enable/disable code.

Location:
trunk
Files:
18 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/sup.h

    r54286 r54308  
    455455 *          as volatile. Thus, there is no PCSUPGLOBALINFOPAGE type.
    456456 */
    457 #if defined(IN_SUP_R0) || defined(IN_SUP_R3) || defined(IN_SUP_RC)
     457#ifdef IN_SUP_R3
    458458extern DECLEXPORT(PSUPGLOBALINFOPAGE)   g_pSUPGlobalInfoPage;
    459459
     
    489489SUPDECL(PSUPGLOBALINFOPAGE)             SUPGetGIP(void);
    490490
    491 /** Whether the application of TSC-deltas is required. */
    492 #define GIP_ARE_TSC_DELTAS_APPLICABLE(a_pGip)  ((a_pGip)->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO)
    493 
    494 
    495 #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86)
     491
     492/** @internal  */
     493SUPDECL(uint64_t) SUPGetCpuHzFromGipForAsyncMode(PSUPGLOBALINFOPAGE pGip);
     494
    496495/**
    497496 * Gets the TSC frequency of the calling CPU.
     
    500499 * @param   pGip        The GIP pointer.
    501500 */
    502 DECLINLINE(uint64_t) SUPGetCpuHzFromGIP(PSUPGLOBALINFOPAGE pGip)
    503 {
    504     unsigned iCpu;
    505 
    506     if (RT_UNLIKELY(!pGip || pGip->u32Magic != SUPGLOBALINFOPAGE_MAGIC || !pGip->u64CpuHz))
    507         return UINT64_MAX;
    508 
    509     if (   pGip->u32Mode == SUPGIPMODE_INVARIANT_TSC
    510         || pGip->u32Mode == SUPGIPMODE_SYNC_TSC)
    511         iCpu = 0;
    512     else
     501DECLINLINE(uint64_t) SUPGetCpuHzFromGip(PSUPGLOBALINFOPAGE pGip)
     502{
     503    if (RT_LIKELY(   pGip
     504                  && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
     505                  && pGip->u64CpuHz))
    513506    {
    514         Assert(pGip->u32Mode == SUPGIPMODE_ASYNC_TSC);
    515         iCpu = pGip->aiCpuFromApicId[ASMGetApicId()];
    516         if (RT_UNLIKELY(iCpu >= pGip->cCpus))
    517             return UINT64_MAX;
     507        switch (pGip->u32Mode)
     508        {
     509            case SUPGIPMODE_INVARIANT_TSC:
     510            case SUPGIPMODE_SYNC_TSC:
     511                return pGip->aCPUs[0].u64CpuHz;
     512            case SUPGIPMODE_ASYNC_TSC:
     513                return SUPGetCpuHzFromGipForAsyncMode(pGip);
     514            default: break; /* shut up gcc */
     515        }
    518516    }
    519 
    520     return pGip->aCPUs[iCpu].u64CpuHz;
     517    AssertFailed();
     518    return UINT64_MAX;
    521519}
    522 #endif /* X86 || AMD64 */
    523 
    524 /**
    525  * Request for generic VMMR0Entry calls.
    526  */
    527 typedef struct SUPVMMR0REQHDR
    528 {
    529     /** The magic. (SUPVMMR0REQHDR_MAGIC) */
    530     uint32_t    u32Magic;
    531     /** The size of the request. */
    532     uint32_t    cbReq;
    533 } SUPVMMR0REQHDR;
    534 /** Pointer to a ring-0 request header. */
    535 typedef SUPVMMR0REQHDR *PSUPVMMR0REQHDR;
    536 /** the SUPVMMR0REQHDR::u32Magic value (Ethan Iverson - The Bad Plus). */
    537 #define SUPVMMR0REQHDR_MAGIC        UINT32_C(0x19730211)
    538 
    539 
    540 /** For the fast ioctl path.
    541  * @{
    542  */
    543 /** @see VMMR0_DO_RAW_RUN. */
    544 #define SUP_VMMR0_DO_RAW_RUN    0
    545 /** @see VMMR0_DO_HM_RUN. */
    546 #define SUP_VMMR0_DO_HM_RUN     1
    547 /** @see VMMR0_DO_NOP */
    548 #define SUP_VMMR0_DO_NOP        2
    549 /** @} */
    550 
    551 /** SUPR3QueryVTCaps capability flags
    552  * @{
    553  */
    554 #define SUPVTCAPS_AMD_V             RT_BIT(0)
    555 #define SUPVTCAPS_VT_X              RT_BIT(1)
    556 #define SUPVTCAPS_NESTED_PAGING     RT_BIT(2)
    557 /** @} */
    558 
    559 /**
    560  * Request for generic FNSUPR0SERVICEREQHANDLER calls.
    561  */
    562 typedef struct SUPR0SERVICEREQHDR
    563 {
    564     /** The magic. (SUPR0SERVICEREQHDR_MAGIC) */
    565     uint32_t    u32Magic;
    566     /** The size of the request. */
    567     uint32_t    cbReq;
    568 } SUPR0SERVICEREQHDR;
    569 /** Pointer to a ring-0 service request header. */
    570 typedef SUPR0SERVICEREQHDR *PSUPR0SERVICEREQHDR;
    571 /** the SUPVMMR0REQHDR::u32Magic value (Esbjoern Svensson - E.S.P.).  */
    572 #define SUPR0SERVICEREQHDR_MAGIC    UINT32_C(0x19640416)
    573 
    574 
    575 /** Event semaphore handle. Ring-0 / ring-3. */
    576 typedef R0PTRTYPE(struct SUPSEMEVENTHANDLE *) SUPSEMEVENT;
    577 /** Pointer to an event semaphore handle. */
    578 typedef SUPSEMEVENT *PSUPSEMEVENT;
    579 /** Nil event semaphore handle. */
    580 #define NIL_SUPSEMEVENT         ((SUPSEMEVENT)0)
    581 
    582 /**
    583  * Creates a single release event semaphore.
    584  *
    585  * @returns VBox status code.
    586  * @param   pSession        The session handle of the caller.
    587  * @param   phEvent         Where to return the handle to the event semaphore.
    588  */
    589 SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent);
    590 
    591 /**
    592  * Closes a single release event semaphore handle.
    593  *
    594  * @returns VBox status code.
    595  * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
    596  * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
    597  *          object remained alive because of other references.
    598  *
    599  * @param   pSession            The session handle of the caller.
    600  * @param   hEvent              The handle. Nil is quietly ignored.
    601  */
    602 SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
    603 
    604 /**
    605  * Signals a single release event semaphore.
    606  *
    607  * @returns VBox status code.
    608  * @param   pSession            The session handle of the caller.
    609  * @param   hEvent              The semaphore handle.
    610  */
    611 SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
    612 
    613 #ifdef IN_RING0
    614 /**
    615  * Waits on a single release event semaphore, not interruptible.
    616  *
    617  * @returns VBox status code.
    618  * @param   pSession            The session handle of the caller.
    619  * @param   hEvent              The semaphore handle.
    620  * @param   cMillies            The number of milliseconds to wait.
    621  * @remarks Not available in ring-3.
    622  */
    623 SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
    624 #endif
    625 
    626 /**
    627  * Waits on a single release event semaphore, interruptible.
    628  *
    629  * @returns VBox status code.
    630  * @param   pSession            The session handle of the caller.
    631  * @param   hEvent              The semaphore handle.
    632  * @param   cMillies            The number of milliseconds to wait.
    633  */
    634 SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
    635 
    636 /**
    637  * Waits on a single release event semaphore, interruptible.
    638  *
    639  * @returns VBox status code.
    640  * @param   pSession            The session handle of the caller.
    641  * @param   hEvent              The semaphore handle.
    642  * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
    643  */
    644 SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout);
    645 
    646 /**
    647  * Waits on a single release event semaphore, interruptible.
    648  *
    649  * @returns VBox status code.
    650  * @param   pSession            The session handle of the caller.
    651  * @param   hEvent              The semaphore handle.
    652  * @param   cNsTimeout          The number of nanoseconds to wait.
    653  */
    654 SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout);
    655 
    656 /**
    657  * Gets the best timeout resolution that SUPSemEventWaitNsAbsIntr and
    658  * SUPSemEventWaitNsAbsIntr can do.
    659  *
    660  * @returns The resolution in nanoseconds.
    661  * @param   pSession            The session handle of the caller.
    662  */
    663 SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession);
    664 
    665 
    666 /** Multiple release event semaphore handle. Ring-0 / ring-3. */
    667 typedef R0PTRTYPE(struct SUPSEMEVENTMULTIHANDLE *)  SUPSEMEVENTMULTI;
    668 /** Pointer to an multiple release event semaphore handle. */
    669 typedef SUPSEMEVENTMULTI                           *PSUPSEMEVENTMULTI;
    670 /** Nil multiple release event semaphore handle. */
    671 #define NIL_SUPSEMEVENTMULTI                        ((SUPSEMEVENTMULTI)0)
    672 
    673 /**
    674  * Creates a multiple release event semaphore.
    675  *
    676  * @returns VBox status code.
    677  * @param   pSession        The session handle of the caller.
    678  * @param   phEventMulti    Where to return the handle to the event semaphore.
    679  */
    680 SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti);
    681 
    682 /**
    683  * Closes a multiple release event semaphore handle.
    684  *
    685  * @returns VBox status code.
    686  * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
    687  * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
    688  *          object remained alive because of other references.
    689  *
    690  * @param   pSession            The session handle of the caller.
    691  * @param   hEventMulti         The handle. Nil is quietly ignored.
    692  */
    693 SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
    694 
    695 /**
    696  * Signals a multiple release event semaphore.
    697  *
    698  * @returns VBox status code.
    699  * @param   pSession            The session handle of the caller.
    700  * @param   hEventMulti         The semaphore handle.
    701  */
    702 SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
    703 
    704 /**
    705  * Resets a multiple release event semaphore.
    706  *
    707  * @returns VBox status code.
    708  * @param   pSession            The session handle of the caller.
    709  * @param   hEventMulti         The semaphore handle.
    710  */
    711 SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
    712 
    713 #ifdef IN_RING0
    714 /**
    715  * Waits on a multiple release event semaphore, not interruptible.
    716  *
    717  * @returns VBox status code.
    718  * @param   pSession            The session handle of the caller.
    719  * @param   hEventMulti         The semaphore handle.
    720  * @param   cMillies            The number of milliseconds to wait.
    721  * @remarks Not available in ring-3.
    722  */
    723 SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
    724 #endif
    725 
    726 /**
    727  * Waits on a multiple release event semaphore, interruptible.
    728  *
    729  * @returns VBox status code.
    730  * @param   pSession            The session handle of the caller.
    731  * @param   hEventMulti         The semaphore handle.
    732  * @param   cMillies            The number of milliseconds to wait.
    733  */
    734 SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
    735 
    736 /**
    737  * Waits on a multiple release event semaphore, interruptible.
    738  *
    739  * @returns VBox status code.
    740  * @param   pSession            The session handle of the caller.
    741  * @param   hEventMulti         The semaphore handle.
    742  * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
    743  */
    744 SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout);
    745 
    746 /**
    747  * Waits on a multiple release event semaphore, interruptible.
    748  *
    749  * @returns VBox status code.
    750  * @param   pSession            The session handle of the caller.
    751  * @param   hEventMulti         The semaphore handle.
    752  * @param   cNsTimeout          The number of nanoseconds to wait.
    753  */
    754 SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout);
    755 
    756 /**
    757  * Gets the best timeout resolution that SUPSemEventMultiWaitNsAbsIntr and
    758  * SUPSemEventMultiWaitNsRelIntr can do.
    759  *
    760  * @returns The resolution in nanoseconds.
    761  * @param   pSession            The session handle of the caller.
    762  */
    763 SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession);
    764 
    765 
    766 #ifdef IN_RING3
    767 
    768 /** @defgroup   grp_sup_r3     SUP Host Context Ring-3 API
    769  * @{
    770  */
    771 
    772 /**
    773  * Installs the support library.
    774  *
    775  * @returns VBox status code.
    776  */
    777 SUPR3DECL(int) SUPR3Install(void);
    778 
    779 /**
    780  * Uninstalls the support library.
    781  *
    782  * @returns VBox status code.
    783  */
    784 SUPR3DECL(int) SUPR3Uninstall(void);
    785 
    786 /**
    787  * Trusted main entry point.
    788  *
    789  * This is exported as "TrustedMain" by the dynamic libraries which contains the
    790  * "real" application binary for which the hardened stub is built.  The entry
    791  * point is invoked upon successful initialization of the support library and
    792  * runtime.
    793  *
    794  * @returns main kind of exit code.
    795  * @param   argc            The argument count.
    796  * @param   argv            The argument vector.
    797  * @param   envp            The environment vector.
    798  */
    799 typedef DECLCALLBACK(int) FNSUPTRUSTEDMAIN(int argc, char **argv, char **envp);
    800 /** Pointer to FNSUPTRUSTEDMAIN(). */
    801 typedef FNSUPTRUSTEDMAIN *PFNSUPTRUSTEDMAIN;
    802 
    803 /** Which operation failed. */
    804 typedef enum SUPINITOP
    805 {
    806     /** Invalid. */
    807     kSupInitOp_Invalid = 0,
    808     /** Installation integrity error. */
    809     kSupInitOp_Integrity,
    810     /** Setuid related. */
    811     kSupInitOp_RootCheck,
    812     /** Driver related. */
    813     kSupInitOp_Driver,
    814     /** IPRT init related. */
    815     kSupInitOp_IPRT,
    816     /** Miscellaneous. */
    817     kSupInitOp_Misc,
    818     /** Place holder. */
    819     kSupInitOp_End
    820 } SUPINITOP;
    821 
    822 /**
    823  * Trusted error entry point, optional.
    824  *
    825  * This is exported as "TrustedError" by the dynamic libraries which contains
    826  * the "real" application binary for which the hardened stub is built. The
    827  * hardened main() must specify SUPSECMAIN_FLAGS_TRUSTED_ERROR when calling
    828  * SUPR3HardenedMain.
    829  *
    830  * @param   pszWhere        Where the error occurred (function name).
    831  * @param   enmWhat         Which operation went wrong.
    832  * @param   rc              The status code.
    833  * @param   pszMsgFmt       Error message format string.
    834  * @param   va              The message format arguments.
    835  */
    836 typedef DECLCALLBACK(void) FNSUPTRUSTEDERROR(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va);
    837 /** Pointer to FNSUPTRUSTEDERROR. */
    838 typedef FNSUPTRUSTEDERROR *PFNSUPTRUSTEDERROR;
    839 
    840 /**
    841  * Secure main.
    842  *
    843  * This is used for the set-user-ID-on-execute binaries on unixy systems
    844  * and when using the open-vboxdrv-via-root-service setup on Windows.
    845  *
    846  * This function will perform the integrity checks of the VirtualBox
    847  * installation, open the support driver, open the root service (later),
    848  * and load the DLL corresponding to \a pszProgName and execute its main
    849  * function.
    850  *
    851  * @returns Return code appropriate for main().
    852  *
    853  * @param   pszProgName     The program name. This will be used to figure out which
    854  *                          DLL/SO/DYLIB to load and execute.
    855  * @param   fFlags          Flags.
    856  * @param   argc            The argument count.
    857  * @param   argv            The argument vector.
    858  * @param   envp            The environment vector.
    859  */
    860 DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp);
    861 
    862 /** @name SUPR3HardenedMain flags.
    863  * @{ */
    864 /** Don't open the device. (Intended for VirtualBox without -startvm.) */
    865 #define SUPSECMAIN_FLAGS_DONT_OPEN_DEV      RT_BIT_32(0)
    866 /** The hardened DLL has a "TrustedError" function (see FNSUPTRUSTEDERROR). */
    867 #define SUPSECMAIN_FLAGS_TRUSTED_ERROR      RT_BIT_32(1)
    868 /** @} */
    869 
    870 /**
    871  * Initializes the support library.
    872  *
    873  * Each successful call to SUPR3Init() or SUPR3InitEx must be countered by a
    874  * call to SUPR3Term(false).
    875  *
    876  * @returns VBox status code.
    877  * @param   ppSession       Where to store the session handle. Defaults to NULL.
    878  */
    879 SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession);
    880 
    881 
    882 /**
    883  * Initializes the support library, extended version.
    884  *
    885  * Each successful call to SUPR3Init() or SUPR3InitEx must be countered by a
    886  * call to SUPR3Term(false).
    887  *
    888  * @returns VBox status code.
    889  * @param   fUnrestricted   The desired access.
    890  * @param   ppSession       Where to store the session handle. Defaults to NULL.
    891  */
    892 SUPR3DECL(int) SUPR3InitEx(bool fUnrestricted, PSUPDRVSESSION *ppSession);
    893 
    894 /**
    895  * Terminates the support library.
    896  *
    897  * @returns VBox status code.
    898  * @param   fForced     Forced termination. This means to ignore the
    899  *                      init call count and just terminated.
    900  */
    901 #ifdef __cplusplus
    902 SUPR3DECL(int) SUPR3Term(bool fForced = false);
    903 #else
    904 SUPR3DECL(int) SUPR3Term(int fForced);
    905 #endif
    906 
    907 /**
    908  * Sets the ring-0 VM handle for use with fast IOCtls.
    909  *
    910  * @returns VBox status code.
    911  * @param   pVMR0       The ring-0 VM handle.
    912  *                      NIL_RTR0PTR can be used to unset the handle when the
    913  *                      VM is about to be destroyed.
    914  */
    915 SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0);
    916 
    917 /**
    918  * Calls the HC R0 VMM entry point.
    919  * See VMMR0Entry() for more details.
    920  *
    921  * @returns error code specific to uFunction.
    922  * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
    923  * @param   idCpu       The virtual CPU ID.
    924  * @param   uOperation  Operation to execute.
    925  * @param   pvArg       Argument.
    926  */
    927 SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg);
    928 
    929 /**
    930  * Variant of SUPR3CallVMMR0, except that this takes the fast ioclt path
    931  * regardsless of compile-time defaults.
    932  *
    933  * @returns VBox status code.
    934  * @param   pVMR0       The ring-0 VM handle.
    935  * @param   uOperation  The operation; only the SUP_VMMR0_DO_* ones are valid.
    936  * @param   idCpu       The virtual CPU ID.
    937  */
    938 SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu);
    939 
    940 /**
    941  * Calls the HC R0 VMM entry point, in a safer but slower manner than
    942  * SUPR3CallVMMR0. When entering using this call the R0 components can call
    943  * into the host kernel (i.e. use the SUPR0 and RT APIs).
    944  *
    945  * See VMMR0Entry() for more details.
    946  *
    947  * @returns error code specific to uFunction.
    948  * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
    949  * @param   idCpu       The virtual CPU ID.
    950  * @param   uOperation  Operation to execute.
    951  * @param   u64Arg      Constant argument.
    952  * @param   pReqHdr     Pointer to a request header. Optional.
    953  *                      This will be copied in and out of kernel space. There currently is a size
    954  *                      limit on this, just below 4KB.
    955  */
    956 SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
    957 
    958 /**
    959  * Calls a ring-0 service.
    960  *
    961  * The operation and the request packet is specific to the service.
    962  *
    963  * @returns error code specific to uFunction.
    964  * @param   pszService  The service name.
    965  * @param   cchService  The length of the service name.
    966  * @param   uReq        The request number.
    967  * @param   u64Arg      Constant argument.
    968  * @param   pReqHdr     Pointer to a request header. Optional.
    969  *                      This will be copied in and out of kernel space. There currently is a size
    970  *                      limit on this, just below 4KB.
    971  */
    972 SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr);
    973 
    974 /** Which logger. */
    975 typedef enum SUPLOGGER
    976 {
    977     SUPLOGGER_DEBUG = 1,
    978     SUPLOGGER_RELEASE
    979 } SUPLOGGER;
    980 
    981 /**
    982  * Changes the settings of the specified ring-0 logger.
    983  *
    984  * @returns VBox status code.
    985  * @param   enmWhich    Which logger.
    986  * @param   pszFlags    The flags settings.
    987  * @param   pszGroups   The groups settings.
    988  * @param   pszDest     The destination specificier.
    989  */
    990 SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
    991 
    992 /**
    993  * Creates a ring-0 logger instance.
    994  *
    995  * @returns VBox status code.
    996  * @param   enmWhich    Which logger to create.
    997  * @param   pszFlags    The flags settings.
    998  * @param   pszGroups   The groups settings.
    999  * @param   pszDest     The destination specificier.
    1000  */
    1001 SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
    1002 
    1003 /**
    1004  * Destroys a ring-0 logger instance.
    1005  *
    1006  * @returns VBox status code.
    1007  * @param   enmWhich    Which logger.
    1008  */
    1009 SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich);
    1010 
    1011 /**
    1012  * Queries the paging mode of the host OS.
    1013  *
    1014  * @returns The paging mode.
    1015  */
    1016 SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void);
    1017 
    1018 /**
    1019  * Allocate zero-filled pages.
    1020  *
    1021  * Use this to allocate a number of pages suitable for seeding / locking.
    1022  * Call SUPR3PageFree() to free the pages once done with them.
    1023  *
    1024  * @returns VBox status.
    1025  * @param   cPages          Number of pages to allocate.
    1026  * @param   ppvPages        Where to store the base pointer to the allocated pages.
    1027  */
    1028 SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages);
    1029 
    1030 /**
    1031  * Frees pages allocated with SUPR3PageAlloc().
    1032  *
    1033  * @returns VBox status.
    1034  * @param   pvPages         Pointer returned by SUPR3PageAlloc().
    1035  * @param   cPages          Number of pages that was allocated.
    1036  */
    1037 SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages);
    1038 
    1039 /**
    1040  * Allocate non-zeroed, locked, pages with user and, optionally, kernel
    1041  * mappings.
    1042  *
    1043  * Use SUPR3PageFreeEx() to free memory allocated with this function.
    1044  *
    1045  * @returns VBox status code.
    1046  * @param   cPages          The number of pages to allocate.
    1047  * @param   fFlags          Flags, reserved. Must be zero.
    1048  * @param   ppvPages        Where to store the address of the user mapping.
    1049  * @param   pR0Ptr          Where to store the address of the kernel mapping.
    1050  *                          NULL if no kernel mapping is desired.
    1051  * @param   paPages         Where to store the physical addresses of each page.
    1052  *                          Optional.
    1053  */
    1054 SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages);
    1055 
    1056 /**
    1057  * Maps a portion of a ring-3 only allocation into kernel space.
    1058  *
    1059  * @returns VBox status code.
    1060  *
    1061  * @param   pvR3            The address SUPR3PageAllocEx return.
    1062  * @param   off             Offset to start mapping at. Must be page aligned.
    1063  * @param   cb              Number of bytes to map. Must be page aligned.
    1064  * @param   fFlags          Flags, must be zero.
    1065  * @param   pR0Ptr          Where to store the address on success.
    1066  *
    1067  */
    1068 SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr);
    1069 
    1070 /**
    1071  * Changes the protection of
    1072  *
    1073  * @returns VBox status code.
    1074  * @retval  VERR_NOT_SUPPORTED if the OS doesn't allow us to change page level
    1075  *          protection. See also RTR0MemObjProtect.
    1076  *
    1077  * @param   pvR3            The ring-3 address SUPR3PageAllocEx returned.
    1078  * @param   R0Ptr           The ring-0 address SUPR3PageAllocEx returned if it
    1079  *                          is desired that the corresponding ring-0 page
    1080  *                          mappings should change protection as well. Pass
    1081  *                          NIL_RTR0PTR if the ring-0 pages should remain
    1082  *                          unaffected.
    1083  * @param   off             Offset to start at which to start chagning the page
    1084  *                          level protection. Must be page aligned.
    1085  * @param   cb              Number of bytes to change. Must be page aligned.
    1086  * @param   fProt           The new page level protection, either a combination
    1087  *                          of RTMEM_PROT_READ, RTMEM_PROT_WRITE and
    1088  *                          RTMEM_PROT_EXEC, or just RTMEM_PROT_NONE.
    1089  */
    1090 SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt);
    1091 
    1092 /**
    1093  * Free pages allocated by SUPR3PageAllocEx.
    1094  *
    1095  * @returns VBox status code.
    1096  * @param   pvPages         The address of the user mapping.
    1097  * @param   cPages          The number of pages.
    1098  */
    1099 SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages);
    1100 
    1101 /**
    1102  * Allocated memory with page aligned memory with a contiguous and locked physical
    1103  * memory backing below 4GB.
    1104  *
    1105  * @returns Pointer to the allocated memory (virtual address).
    1106  *          *pHCPhys is set to the physical address of the memory.
    1107  *          If ppvR0 isn't NULL, *ppvR0 is set to the ring-0 mapping.
    1108  *          The returned memory must be freed using SUPR3ContFree().
    1109  * @returns NULL on failure.
    1110  * @param   cPages      Number of pages to allocate.
    1111  * @param   pR0Ptr      Where to store the ring-0 mapping of the allocation. (optional)
    1112  * @param   pHCPhys     Where to store the physical address of the memory block.
    1113  *
    1114  * @remark  This 2nd version of this API exists because we're not able to map the
    1115  *          ring-3 mapping executable on WIN64. This is a serious problem in regard to
    1116  *          the world switchers.
    1117  */
    1118 SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys);
    1119 
    1120 /**
    1121  * Frees memory allocated with SUPR3ContAlloc().
    1122  *
    1123  * @returns VBox status code.
    1124  * @param   pv          Pointer to the memory block which should be freed.
    1125  * @param   cPages      Number of pages to be freed.
    1126  */
    1127 SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages);
    1128 
    1129 /**
    1130  * Allocated non contiguous physical memory below 4GB.
    1131  *
    1132  * The memory isn't zeroed.
    1133  *
    1134  * @returns VBox status code.
    1135  * @returns NULL on failure.
    1136  * @param   cPages      Number of pages to allocate.
    1137  * @param   ppvPages    Where to store the pointer to the allocated memory.
    1138  *                      The pointer stored here on success must be passed to
    1139  *                      SUPR3LowFree when the memory should be released.
    1140  * @param   ppvPagesR0  Where to store the ring-0 pointer to the allocated memory. optional.
    1141  * @param   paPages     Where to store the physical addresses of the individual pages.
    1142  */
    1143 SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages);
    1144 
    1145 /**
    1146  * Frees memory allocated with SUPR3LowAlloc().
    1147  *
    1148  * @returns VBox status code.
    1149  * @param   pv          Pointer to the memory block which should be freed.
    1150  * @param   cPages      Number of pages that was allocated.
    1151  */
    1152 SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages);
    1153 
    1154 /**
    1155  * Load a module into R0 HC.
    1156  *
    1157  * This will verify the file integrity in a similar manner as
    1158  * SUPR3HardenedVerifyFile before loading it.
    1159  *
    1160  * @returns VBox status code.
    1161  * @param   pszFilename     The path to the image file.
    1162  * @param   pszModule       The module name. Max 32 bytes.
    1163  * @param   ppvImageBase    Where to store the image address.
    1164  * @param   pErrInfo        Where to return extended error information.
    1165  *                          Optional.
    1166  */
    1167 SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo);
    1168 
    1169 /**
    1170  * Load a module into R0 HC.
    1171  *
    1172  * This will verify the file integrity in a similar manner as
    1173  * SUPR3HardenedVerifyFile before loading it.
    1174  *
    1175  * @returns VBox status code.
    1176  * @param   pszFilename         The path to the image file.
    1177  * @param   pszModule           The module name. Max 32 bytes.
    1178  * @param   pszSrvReqHandler    The name of the service request handler entry
    1179  *                              point. See FNSUPR0SERVICEREQHANDLER.
    1180  * @param   ppvImageBase        Where to store the image address.
    1181  */
    1182 SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
    1183                                       const char *pszSrvReqHandler, void **ppvImageBase);
    1184 
    1185 /**
    1186  * Frees a R0 HC module.
    1187  *
    1188  * @returns VBox status code.
    1189  * @param   pszModule       The module to free.
    1190  * @remark  This will not actually 'free' the module, there are of course usage counting.
    1191  */
    1192 SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase);
    1193 
    1194 /**
    1195  * Lock down the module loader interface.
    1196  *
    1197  * This will lock down the module loader interface. No new modules can be
    1198  * loaded and all loaded modules can no longer be freed.
    1199  *
    1200  * @returns VBox status code.
    1201  * @param   pErrInfo        Where to return extended error information.
    1202  *                          Optional.
    1203  */
    1204 SUPR3DECL(int) SUPR3LockDownLoader(PRTERRINFO pErrInfo);
    1205 
    1206 /**
    1207  * Get the address of a symbol in a ring-0 module.
    1208  *
    1209  * @returns VBox status code.
    1210  * @param   pszModule       The module name.
    1211  * @param   pszSymbol       Symbol name. If it's value is less than 64k it's treated like a
    1212  *                          ordinal value rather than a string pointer.
    1213  * @param   ppvValue        Where to store the symbol value.
    1214  */
    1215 SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue);
    1216 
    1217 /**
    1218  * Load R0 HC VMM code.
    1219  *
    1220  * @returns VBox status code.
    1221  * @deprecated  Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
    1222  */
    1223 SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename);
    1224 
    1225 /**
    1226  * Unloads R0 HC VMM code.
    1227  *
    1228  * @returns VBox status code.
    1229  * @deprecated  Use SUPR3FreeModule().
    1230  */
    1231 SUPR3DECL(int) SUPR3UnloadVMM(void);
    1232 
    1233 /**
    1234  * Get the physical address of the GIP.
    1235  *
    1236  * @returns VBox status code.
    1237  * @param   pHCPhys     Where to store the physical address of the GIP.
    1238  */
    1239 SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys);
    1240 
    1241 /**
    1242  * Initializes only the bits relevant for the SUPR3HardenedVerify* APIs.
    1243  *
    1244  * This is for users that don't necessarily need to initialize the whole of
    1245  * SUPLib.  There is no harm in calling this one more time.
    1246  *
    1247  * @returns VBox status code.
    1248  * @remarks Currently not counted, so only call once.
    1249  */
    1250 SUPR3DECL(int) SUPR3HardenedVerifyInit(void);
    1251 
    1252 /**
    1253  * Reverses the effect of SUPR3HardenedVerifyInit if SUPR3InitEx hasn't been
    1254  * called.
    1255  *
    1256  * Ignored if the support library was initialized using SUPR3Init or
    1257  * SUPR3InitEx.
    1258  *
    1259  * @returns VBox status code.
    1260  */
    1261 SUPR3DECL(int) SUPR3HardenedVerifyTerm(void);
    1262 
    1263 /**
    1264  * Verifies the integrity of a file, and optionally opens it.
    1265  *
    1266  * The integrity check is for whether the file is suitable for loading into
    1267  * the hypervisor or VM process. The integrity check may include verifying
    1268  * the authenticode/elfsign/whatever signature of the file, which can take
    1269  * a little while.
    1270  *
    1271  * @returns VBox status code. On failure it will have printed a LogRel message.
    1272  *
    1273  * @param   pszFilename     The file.
    1274  * @param   pszWhat         For the LogRel on failure.
    1275  * @param   phFile          Where to store the handle to the opened file. This is optional, pass NULL
    1276  *                          if the file should not be opened.
    1277  * @deprecated Write a new one.
    1278  */
    1279 SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszWhat, PRTFILE phFile);
    1280 
    1281 /**
    1282  * Verifies the integrity of a the current process, including the image
    1283  * location and that the invocation was absolute.
    1284  *
    1285  * This must currently be called after initializing the runtime.  The intended
    1286  * audience is set-uid-to-root applications, root services and similar.
    1287  *
    1288  * @returns VBox status code.  On failure
    1289  *          message.
    1290  * @param   pszArgv0        The first argument to main().
    1291  * @param   fInternal       Set this to @c true if this is an internal
    1292  *                          VirtualBox application.  Otherwise pass @c false.
    1293  * @param   pErrInfo        Where to return extended error information.
    1294  */
    1295 SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo);
    1296 
    1297 /**
    1298  * Verifies the integrity of an installation directory.
    1299  *
    1300  * The integrity check verifies that the directory cannot be tampered with by
    1301  * normal users on the system.  On Unix this translates to root ownership and
    1302  * no symbolic linking.
    1303  *
    1304  * @returns VBox status code. On failure a message will be stored in @a pszErr.
    1305  *
    1306  * @param   pszDirPath      The directory path.
    1307  * @param   fRecursive      Whether the check should be recursive or
    1308  *                          not.  When set, all sub-directores will be checked,
    1309  *                          including files (@a fCheckFiles is ignored).
    1310  * @param   fCheckFiles     Whether to apply the same basic integrity check to
    1311  *                          the files in the directory as the directory itself.
    1312  * @param   pErrInfo        Where to return extended error information.
    1313  *                          Optional.
    1314  */
    1315 SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo);
    1316 
    1317 /**
    1318  * Verifies the integrity of a plug-in module.
    1319  *
    1320  * This is similar to SUPR3HardenedLdrLoad, except it does not load the module
    1321  * and that the module does not have to be shipped with VirtualBox.
    1322  *
    1323  * @returns VBox status code. On failure a message will be stored in @a pszErr.
    1324  *
    1325  * @param   pszFilename     The filename of the plug-in module (nothing can be
    1326  *                          omitted here).
    1327  * @param   pErrInfo        Where to return extended error information.
    1328  *                          Optional.
    1329  */
    1330 SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo);
    1331 
    1332 /**
    1333  * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
    1334  *
    1335  * Will add dll suffix if missing and try load the file.
    1336  *
    1337  * @returns iprt status code.
    1338  * @param   pszFilename     Image filename. This must have a path.
    1339  * @param   phLdrMod        Where to store the handle to the loaded module.
    1340  * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
    1341  * @param   pErrInfo        Where to return extended error information.
    1342  *                          Optional.
    1343  */
    1344 SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
    1345 
    1346 /**
    1347  * Same as RTLdrLoadAppPriv() but it will verify the files it loads (hardened
    1348  * builds).
    1349  *
    1350  * Will add dll suffix to the file if missing, then look for it in the
    1351  * architecture dependent application directory.
    1352  *
    1353  * @returns iprt status code.
    1354  * @param   pszFilename     Image filename.
    1355  * @param   phLdrMod        Where to store the handle to the loaded module.
    1356  * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
    1357  * @param   pErrInfo        Where to return extended error information.
    1358  *                          Optional.
    1359  */
    1360 SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
    1361 
    1362 /**
    1363  * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
    1364  *
    1365  * This differs from SUPR3HardenedLdrLoad() in that it can load modules from
    1366  * extension packs and anything else safely installed on the system, provided
    1367  * they pass the hardening tests.
    1368  *
    1369  * @returns iprt status code.
    1370  * @param   pszFilename     The full path to the module, with extension.
    1371  * @param   phLdrMod        Where to store the handle to the loaded module.
    1372  * @param   pErrInfo        Where to return extended error information.
    1373  *                          Optional.
    1374  */
    1375 SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
    1376 
    1377 /**
    1378  * Check if the host kernel can run in VMX root mode.
    1379  *
    1380  * @returns VINF_SUCCESS if supported, error code indicating why if not.
    1381  */
    1382 SUPR3DECL(int) SUPR3QueryVTxSupported(void);
    1383 
    1384 /**
    1385  * Return VT-x/AMD-V capabilities.
    1386  *
    1387  * @returns VINF_SUCCESS if supported, error code indicating why if not.
    1388  * @param   pfCaps      Pointer to capability dword (out).
    1389  * @todo Intended for main, which means we need to relax the privilege requires
    1390  *       when accessing certain vboxdrv functions.
    1391  */
    1392 SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps);
    1393 
    1394 /**
    1395  * Open the tracer.
    1396  *
    1397  * @returns VBox status code.
    1398  * @param   uCookie         Cookie identifying the tracer we expect to talk to.
    1399  * @param   uArg            Tracer specific open argument.
    1400  */
    1401 SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg);
    1402 
    1403 /**
    1404  * Closes the tracer.
    1405  *
    1406  * @returns VBox status code.
    1407  */
    1408 SUPR3DECL(int) SUPR3TracerClose(void);
    1409 
    1410 /**
    1411  * Perform an I/O request on the tracer.
    1412  *
    1413  * @returns VBox status.
    1414  * @param   uCmd                The tracer command.
    1415  * @param   uArg                The argument.
    1416  * @param   piRetVal            Where to store the tracer return value.
    1417  */
    1418 SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal);
    1419 
    1420 /**
    1421  * Registers the user module with the tracer.
    1422  *
    1423  * @returns VBox status code.
    1424  * @param   hModNative          Native module handle.  Pass ~(uintptr_t)0 if not
    1425  *                              at hand.
    1426  * @param   pszModule           The module name.
    1427  * @param   pVtgHdr             The VTG header.
    1428  * @param   uVtgHdrAddr         The address to which the VTG header is loaded
    1429  *                              in the relevant execution context.
    1430  * @param   fFlags              See SUP_TRACER_UMOD_FLAGS_XXX
    1431  */
    1432 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
    1433                                          RTUINTPTR uVtgHdrAddr, uint32_t fFlags);
    1434 
    1435 /**
    1436  * Deregisters the user module.
    1437  *
    1438  * @returns VBox status code.
    1439  * @param   pVtgHdr             The VTG header.
    1440  */
    1441 SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr);
    1442 
    1443 /**
    1444  * Fire the probe.
    1445  *
    1446  * @param   pVtgProbeLoc        The probe location record.
    1447  * @param   uArg0               Raw probe argument 0.
    1448  * @param   uArg1               Raw probe argument 1.
    1449  * @param   uArg2               Raw probe argument 2.
    1450  * @param   uArg3               Raw probe argument 3.
    1451  * @param   uArg4               Raw probe argument 4.
    1452  */
    1453 SUPDECL(void)  SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
    1454                                   uintptr_t uArg3, uintptr_t uArg4);
    1455 
    1456 
    1457 /**
    1458  * Attempts to read the value of an MSR.
    1459  *
    1460  * @returns VBox status code.
    1461  * @param   uMsr                The MSR to read.
    1462  * @param   idCpu               The CPU to read it on, NIL_RTCPUID if it doesn't
    1463  *                              matter which CPU.
    1464  * @param   puValue             Where to return the value.
    1465  * @param   pfGp                Where to store the \#GP indicator for the read
    1466  *                              operation.
    1467  */
    1468 SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp);
    1469 
    1470 /**
    1471  * Attempts to write to an MSR.
    1472  *
    1473  * @returns VBox status code.
    1474  * @param   uMsr                The MSR to write to.
    1475  * @param   idCpu               The CPU to wrtie it on, NIL_RTCPUID if it
    1476  *                              doesn't matter which CPU.
    1477  * @param   uValue              The value to write.
    1478  * @param   pfGp                Where to store the \#GP indicator for the write
    1479  *                              operation.
    1480  */
    1481 SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp);
    1482 
    1483 /**
    1484  * Attempts to modify the value of an MSR.
    1485  *
    1486  * @returns VBox status code.
    1487  * @param   uMsr                The MSR to modify.
    1488  * @param   idCpu               The CPU to modify it on, NIL_RTCPUID if it
    1489  *                              doesn't matter which CPU.
    1490  * @param   fAndMask            The bits to keep in the current MSR value.
    1491  * @param   fOrMask             The bits to set before writing.
    1492  * @param   pResult             The result buffer.
    1493  */
    1494 SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
    1495                                     PSUPMSRPROBERMODIFYRESULT pResult);
    1496 
    1497 /**
    1498  * Attempts to modify the value of an MSR, extended version.
    1499  *
    1500  * @returns VBox status code.
    1501  * @param   uMsr                The MSR to modify.
    1502  * @param   idCpu               The CPU to modify it on, NIL_RTCPUID if it
    1503  *                              doesn't matter which CPU.
    1504  * @param   fAndMask            The bits to keep in the current MSR value.
    1505  * @param   fOrMask             The bits to set before writing.
    1506  * @param   fFaster             If set to @c true some cache/tlb invalidation is
    1507  *                              skipped, otherwise behave like
    1508  *                              SUPR3MsrProberModify.
    1509  * @param   pResult             The result buffer.
    1510  */
    1511 SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
    1512                                       PSUPMSRPROBERMODIFYRESULT pResult);
    1513 
    1514 /**
    1515  * Resume built-in keyboard on MacBook Air and Pro hosts.
    1516  *
    1517  * @returns VBox status code.
    1518  */
    1519 SUPR3DECL(int) SUPR3ResumeSuspendedKeyboards(void);
    1520 
    1521 
    1522 /**
    1523  * Measure the TSC-delta for the specified CPU.
    1524  *
    1525  * @returns VBox status code.
    1526  * @param   idCpu               The CPU to measure the TSC-delta for.
    1527  * @param   fAsync              Whether the measurement is asynchronous, returns
    1528  *                              immediately after signalling a measurement
    1529  *                              request.
    1530  * @param   fForce              Whether to perform a measurement even if the
    1531  *                              specified CPU has a (possibly) valid TSC delta.
    1532  * @param   cRetries            Number of times to retry failed delta
    1533  *                              measurements.
    1534  * @param   cMsWaitRetry        Number of milliseconds to wait between retries.
    1535  */
    1536 SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry);
    1537 
    1538 /**
    1539  * Reads the delta-adjust TSC value.
    1540  *
    1541  * @returns VBox status code.
    1542  * @param   puTsc           Where to store the read TSC value.
    1543  * @param   pidApic         Where to store the APIC ID of the CPU where the TSC
    1544  *                          was read (optional, can be NULL).
    1545  */
    1546 SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic);
    1547 
    1548 /** @} */
    1549 #endif /* IN_RING3 */
    1550 
    1551 
    1552 /**
    1553  * Gets the descriptive GIP mode name.
    1554  *
    1555  * @returns The name.
    1556  * @param   pGip      Pointer to the GIP.
    1557  */
    1558 DECLINLINE(const char *) SUPGetGIPModeName(PSUPGLOBALINFOPAGE pGip)
    1559 {
    1560     AssertReturn(pGip, NULL);
    1561     switch (pGip->u32Mode)
     520
     521
     522/**
     523 * Gets the TSC frequency of the specified CPU.
     524 *
     525 * @returns TSC frequency, UINT64_MAX on failure.
     526 * @param   pGip        The GIP pointer.
     527 * @param   iCpuSet     The CPU set index of the CPU in question.
     528 */
     529DECLINLINE(uint64_t) SUPGetCpuHzFromGipBySetIndex(PSUPGLOBALINFOPAGE pGip, uint32_t iCpuSet)
     530{
     531    if (RT_LIKELY(   pGip
     532                  && pGip->u32Magic == SUPGLOBALINFOPAGE_MAGIC
     533                  && pGip->u64CpuHz))
    1562534    {
    1563         case SUPGIPMODE_INVARIANT_TSC:  return "Invariant";
    1564         case SUPGIPMODE_SYNC_TSC:       return "Synchronous";
    1565         case SUPGIPMODE_ASYNC_TSC:      return "Asynchronous";
    1566         case SUPGIPMODE_INVALID:        return "Invalid";
    1567         default:                        return "???";
     535        switch (pGip->u32Mode)
     536        {
     537            case SUPGIPMODE_INVARIANT_TSC:
     538            case SUPGIPMODE_SYNC_TSC:
     539                return pGip->aCPUs[0].u64CpuHz;
     540            case SUPGIPMODE_ASYNC_TSC:
     541                if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     542                {
     543                    uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     544                    if (RT_LIKELY(iCpu < pGip->cCpus))
     545                        return pGip->aCPUs[iCpu].u64CpuHz;
     546                }
     547                break;
     548            default: break; /* shut up gcc */
     549        }
    1568550    }
     551    AssertFailed();
     552    return UINT64_MAX;
    1569553}
    1570554
     
    1600584
    1601585/** @internal */
    1602 SUPDECL(uint64_t) SUPReadTscWithDelta(void);
    1603 
    1604 /**
    1605  * Reads the host TSC value.
    1606  *
    1607  * If applicable, normalizes the host TSC value with intercpu TSC deltas.
     586SUPDECL(uint64_t) SUPReadTscWithDelta(PSUPGLOBALINFOPAGE pGip);
     587
     588/**
     589 * Read the host TSC value and applies the TSC delta if appropriate.
    1608590 *
    1609591 * @returns the TSC value.
    1610  *
    1611  * @remarks Requires GIP to be initialized.
     592 * @remarks Requires GIP to be initialized and valid.
    1612593 */
    1613594DECLINLINE(uint64_t) SUPReadTsc(void)
    1614595{
    1615     if (g_pSUPGlobalInfoPage->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
     596    PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
     597    if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
    1616598        return ASMReadTSC();
    1617     return SUPReadTscWithDelta();
     599    return SUPReadTscWithDelta(pGip);
    1618600}
    1619601
    1620602#endif /* X86 || AMD64 */
     603
     604/** @internal */
     605SUPDECL(uint64_t) SUPGetTscDeltaSlow(PSUPGLOBALINFOPAGE pGip);
     606
     607/**
     608 * Gets the TSC delta for the current CPU.
     609 *
     610 * @returns The TSC delta value (will not return the special INT64_MAX value).
     611 * @remarks Requires GIP to be initialized and valid.
     612 */
     613DECLINLINE(int64_t) SUPGetTscDelta(void)
     614{
     615    PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
     616    if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
     617        return 0;
     618    return SUPGetTscDeltaSlow(pGip);
     619}
     620
     621
     622/**
     623 * Gets the TSC delta for a given CPU.
     624 *
     625 * @returns The TSC delta value (will not return the special INT64_MAX value).
     626 * @param   iCpuSet         The CPU set index of the CPU which TSC delta we want.
     627 * @remarks Requires GIP to be initialized and valid.
     628 */
     629DECLINLINE(int64_t) SUPGetTscDeltaByCpuSetIndex(uint32_t iCpuSet)
     630{
     631    PSUPGLOBALINFOPAGE pGip = g_pSUPGlobalInfoPage;
     632    if (pGip->enmUseTscDelta <= SUPGIPUSETSCDELTA_ROUGHLY_ZERO)
     633        return 0;
     634    if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     635    {
     636        uint16_t iCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     637        if (RT_LIKELY(iCpu < pGip->cCpus))
     638        {
     639            int64_t iTscDelta = pGip->aCPUs[iCpu].i64TSCDelta;
     640            if (iTscDelta != INT64_MAX)
     641                return iTscDelta;
     642        }
     643    }
     644    AssertFailed();
     645    return 0;
     646}
     647
     648
     649/**
     650 * Gets the descriptive GIP mode name.
     651 *
     652 * @returns The name.
     653 * @param   pGip      Pointer to the GIP.
     654 */
     655DECLINLINE(const char *) SUPGetGIPModeName(PSUPGLOBALINFOPAGE pGip)
     656{
     657    AssertReturn(pGip, NULL);
     658    switch (pGip->u32Mode)
     659    {
     660        case SUPGIPMODE_INVARIANT_TSC:  return "Invariant";
     661        case SUPGIPMODE_SYNC_TSC:       return "Synchronous";
     662        case SUPGIPMODE_ASYNC_TSC:      return "Asynchronous";
     663        case SUPGIPMODE_INVALID:        return "Invalid";
     664        default:                        return "???";
     665    }
     666}
     667
     668
     669/**
     670 * Request for generic VMMR0Entry calls.
     671 */
     672typedef struct SUPVMMR0REQHDR
     673{
     674    /** The magic. (SUPVMMR0REQHDR_MAGIC) */
     675    uint32_t    u32Magic;
     676    /** The size of the request. */
     677    uint32_t    cbReq;
     678} SUPVMMR0REQHDR;
     679/** Pointer to a ring-0 request header. */
     680typedef SUPVMMR0REQHDR *PSUPVMMR0REQHDR;
     681/** the SUPVMMR0REQHDR::u32Magic value (Ethan Iverson - The Bad Plus). */
     682#define SUPVMMR0REQHDR_MAGIC        UINT32_C(0x19730211)
     683
     684
     685/** For the fast ioctl path.
     686 * @{
     687 */
     688/** @see VMMR0_DO_RAW_RUN. */
     689#define SUP_VMMR0_DO_RAW_RUN    0
     690/** @see VMMR0_DO_HM_RUN. */
     691#define SUP_VMMR0_DO_HM_RUN     1
     692/** @see VMMR0_DO_NOP */
     693#define SUP_VMMR0_DO_NOP        2
     694/** @} */
     695
     696/** SUPR3QueryVTCaps capability flags
     697 * @{
     698 */
     699#define SUPVTCAPS_AMD_V             RT_BIT(0)
     700#define SUPVTCAPS_VT_X              RT_BIT(1)
     701#define SUPVTCAPS_NESTED_PAGING     RT_BIT(2)
     702/** @} */
     703
     704/**
     705 * Request for generic FNSUPR0SERVICEREQHANDLER calls.
     706 */
     707typedef struct SUPR0SERVICEREQHDR
     708{
     709    /** The magic. (SUPR0SERVICEREQHDR_MAGIC) */
     710    uint32_t    u32Magic;
     711    /** The size of the request. */
     712    uint32_t    cbReq;
     713} SUPR0SERVICEREQHDR;
     714/** Pointer to a ring-0 service request header. */
     715typedef SUPR0SERVICEREQHDR *PSUPR0SERVICEREQHDR;
     716/** the SUPVMMR0REQHDR::u32Magic value (Esbjoern Svensson - E.S.P.).  */
     717#define SUPR0SERVICEREQHDR_MAGIC    UINT32_C(0x19640416)
     718
     719
     720/** Event semaphore handle. Ring-0 / ring-3. */
     721typedef R0PTRTYPE(struct SUPSEMEVENTHANDLE *) SUPSEMEVENT;
     722/** Pointer to an event semaphore handle. */
     723typedef SUPSEMEVENT *PSUPSEMEVENT;
     724/** Nil event semaphore handle. */
     725#define NIL_SUPSEMEVENT         ((SUPSEMEVENT)0)
     726
     727/**
     728 * Creates a single release event semaphore.
     729 *
     730 * @returns VBox status code.
     731 * @param   pSession        The session handle of the caller.
     732 * @param   phEvent         Where to return the handle to the event semaphore.
     733 */
     734SUPDECL(int) SUPSemEventCreate(PSUPDRVSESSION pSession, PSUPSEMEVENT phEvent);
     735
     736/**
     737 * Closes a single release event semaphore handle.
     738 *
     739 * @returns VBox status code.
     740 * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
     741 * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
     742 *          object remained alive because of other references.
     743 *
     744 * @param   pSession            The session handle of the caller.
     745 * @param   hEvent              The handle. Nil is quietly ignored.
     746 */
     747SUPDECL(int) SUPSemEventClose(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
     748
     749/**
     750 * Signals a single release event semaphore.
     751 *
     752 * @returns VBox status code.
     753 * @param   pSession            The session handle of the caller.
     754 * @param   hEvent              The semaphore handle.
     755 */
     756SUPDECL(int) SUPSemEventSignal(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent);
     757
     758#ifdef IN_RING0
     759/**
     760 * Waits on a single release event semaphore, not interruptible.
     761 *
     762 * @returns VBox status code.
     763 * @param   pSession            The session handle of the caller.
     764 * @param   hEvent              The semaphore handle.
     765 * @param   cMillies            The number of milliseconds to wait.
     766 * @remarks Not available in ring-3.
     767 */
     768SUPDECL(int) SUPSemEventWait(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
     769#endif
     770
     771/**
     772 * Waits on a single release event semaphore, interruptible.
     773 *
     774 * @returns VBox status code.
     775 * @param   pSession            The session handle of the caller.
     776 * @param   hEvent              The semaphore handle.
     777 * @param   cMillies            The number of milliseconds to wait.
     778 */
     779SUPDECL(int) SUPSemEventWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint32_t cMillies);
     780
     781/**
     782 * Waits on a single release event semaphore, interruptible.
     783 *
     784 * @returns VBox status code.
     785 * @param   pSession            The session handle of the caller.
     786 * @param   hEvent              The semaphore handle.
     787 * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
     788 */
     789SUPDECL(int) SUPSemEventWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t uNsTimeout);
     790
     791/**
     792 * Waits on a single release event semaphore, interruptible.
     793 *
     794 * @returns VBox status code.
     795 * @param   pSession            The session handle of the caller.
     796 * @param   hEvent              The semaphore handle.
     797 * @param   cNsTimeout          The number of nanoseconds to wait.
     798 */
     799SUPDECL(int) SUPSemEventWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENT hEvent, uint64_t cNsTimeout);
     800
     801/**
     802 * Gets the best timeout resolution that SUPSemEventWaitNsAbsIntr and
     803 * SUPSemEventWaitNsAbsIntr can do.
     804 *
     805 * @returns The resolution in nanoseconds.
     806 * @param   pSession            The session handle of the caller.
     807 */
     808SUPDECL(uint32_t) SUPSemEventGetResolution(PSUPDRVSESSION pSession);
     809
     810
     811/** Multiple release event semaphore handle. Ring-0 / ring-3. */
     812typedef R0PTRTYPE(struct SUPSEMEVENTMULTIHANDLE *)  SUPSEMEVENTMULTI;
     813/** Pointer to an multiple release event semaphore handle. */
     814typedef SUPSEMEVENTMULTI                           *PSUPSEMEVENTMULTI;
     815/** Nil multiple release event semaphore handle. */
     816#define NIL_SUPSEMEVENTMULTI                        ((SUPSEMEVENTMULTI)0)
     817
     818/**
     819 * Creates a multiple release event semaphore.
     820 *
     821 * @returns VBox status code.
     822 * @param   pSession        The session handle of the caller.
     823 * @param   phEventMulti    Where to return the handle to the event semaphore.
     824 */
     825SUPDECL(int) SUPSemEventMultiCreate(PSUPDRVSESSION pSession, PSUPSEMEVENTMULTI phEventMulti);
     826
     827/**
     828 * Closes a multiple release event semaphore handle.
     829 *
     830 * @returns VBox status code.
     831 * @retval  VINF_OBJECT_DESTROYED if the semaphore was destroyed.
     832 * @retval  VINF_SUCCESS if the handle was successfully closed but the semaphore
     833 *          object remained alive because of other references.
     834 *
     835 * @param   pSession            The session handle of the caller.
     836 * @param   hEventMulti         The handle. Nil is quietly ignored.
     837 */
     838SUPDECL(int) SUPSemEventMultiClose(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
     839
     840/**
     841 * Signals a multiple release event semaphore.
     842 *
     843 * @returns VBox status code.
     844 * @param   pSession            The session handle of the caller.
     845 * @param   hEventMulti         The semaphore handle.
     846 */
     847SUPDECL(int) SUPSemEventMultiSignal(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
     848
     849/**
     850 * Resets a multiple release event semaphore.
     851 *
     852 * @returns VBox status code.
     853 * @param   pSession            The session handle of the caller.
     854 * @param   hEventMulti         The semaphore handle.
     855 */
     856SUPDECL(int) SUPSemEventMultiReset(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti);
     857
     858#ifdef IN_RING0
     859/**
     860 * Waits on a multiple release event semaphore, not interruptible.
     861 *
     862 * @returns VBox status code.
     863 * @param   pSession            The session handle of the caller.
     864 * @param   hEventMulti         The semaphore handle.
     865 * @param   cMillies            The number of milliseconds to wait.
     866 * @remarks Not available in ring-3.
     867 */
     868SUPDECL(int) SUPSemEventMultiWait(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
     869#endif
     870
     871/**
     872 * Waits on a multiple release event semaphore, interruptible.
     873 *
     874 * @returns VBox status code.
     875 * @param   pSession            The session handle of the caller.
     876 * @param   hEventMulti         The semaphore handle.
     877 * @param   cMillies            The number of milliseconds to wait.
     878 */
     879SUPDECL(int) SUPSemEventMultiWaitNoResume(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint32_t cMillies);
     880
     881/**
     882 * Waits on a multiple release event semaphore, interruptible.
     883 *
     884 * @returns VBox status code.
     885 * @param   pSession            The session handle of the caller.
     886 * @param   hEventMulti         The semaphore handle.
     887 * @param   uNsTimeout          The deadline given on the RTTimeNanoTS() clock.
     888 */
     889SUPDECL(int) SUPSemEventMultiWaitNsAbsIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t uNsTimeout);
     890
     891/**
     892 * Waits on a multiple release event semaphore, interruptible.
     893 *
     894 * @returns VBox status code.
     895 * @param   pSession            The session handle of the caller.
     896 * @param   hEventMulti         The semaphore handle.
     897 * @param   cNsTimeout          The number of nanoseconds to wait.
     898 */
     899SUPDECL(int) SUPSemEventMultiWaitNsRelIntr(PSUPDRVSESSION pSession, SUPSEMEVENTMULTI hEventMulti, uint64_t cNsTimeout);
     900
     901/**
     902 * Gets the best timeout resolution that SUPSemEventMultiWaitNsAbsIntr and
     903 * SUPSemEventMultiWaitNsRelIntr can do.
     904 *
     905 * @returns The resolution in nanoseconds.
     906 * @param   pSession            The session handle of the caller.
     907 */
     908SUPDECL(uint32_t) SUPSemEventMultiGetResolution(PSUPDRVSESSION pSession);
     909
     910
     911#ifdef IN_RING3
     912
     913/** @defgroup   grp_sup_r3     SUP Host Context Ring-3 API
     914 * @{
     915 */
     916
     917/**
     918 * Installs the support library.
     919 *
     920 * @returns VBox status code.
     921 */
     922SUPR3DECL(int) SUPR3Install(void);
     923
     924/**
     925 * Uninstalls the support library.
     926 *
     927 * @returns VBox status code.
     928 */
     929SUPR3DECL(int) SUPR3Uninstall(void);
     930
     931/**
     932 * Trusted main entry point.
     933 *
     934 * This is exported as "TrustedMain" by the dynamic libraries which contains the
     935 * "real" application binary for which the hardened stub is built.  The entry
     936 * point is invoked upon successful initialization of the support library and
     937 * runtime.
     938 *
     939 * @returns main kind of exit code.
     940 * @param   argc            The argument count.
     941 * @param   argv            The argument vector.
     942 * @param   envp            The environment vector.
     943 */
     944typedef DECLCALLBACK(int) FNSUPTRUSTEDMAIN(int argc, char **argv, char **envp);
     945/** Pointer to FNSUPTRUSTEDMAIN(). */
     946typedef FNSUPTRUSTEDMAIN *PFNSUPTRUSTEDMAIN;
     947
     948/** Which operation failed. */
     949typedef enum SUPINITOP
     950{
     951    /** Invalid. */
     952    kSupInitOp_Invalid = 0,
     953    /** Installation integrity error. */
     954    kSupInitOp_Integrity,
     955    /** Setuid related. */
     956    kSupInitOp_RootCheck,
     957    /** Driver related. */
     958    kSupInitOp_Driver,
     959    /** IPRT init related. */
     960    kSupInitOp_IPRT,
     961    /** Miscellaneous. */
     962    kSupInitOp_Misc,
     963    /** Place holder. */
     964    kSupInitOp_End
     965} SUPINITOP;
     966
     967/**
     968 * Trusted error entry point, optional.
     969 *
     970 * This is exported as "TrustedError" by the dynamic libraries which contains
     971 * the "real" application binary for which the hardened stub is built. The
     972 * hardened main() must specify SUPSECMAIN_FLAGS_TRUSTED_ERROR when calling
     973 * SUPR3HardenedMain.
     974 *
     975 * @param   pszWhere        Where the error occurred (function name).
     976 * @param   enmWhat         Which operation went wrong.
     977 * @param   rc              The status code.
     978 * @param   pszMsgFmt       Error message format string.
     979 * @param   va              The message format arguments.
     980 */
     981typedef DECLCALLBACK(void) FNSUPTRUSTEDERROR(const char *pszWhere, SUPINITOP enmWhat, int rc, const char *pszMsgFmt, va_list va);
     982/** Pointer to FNSUPTRUSTEDERROR. */
     983typedef FNSUPTRUSTEDERROR *PFNSUPTRUSTEDERROR;
     984
     985/**
     986 * Secure main.
     987 *
     988 * This is used for the set-user-ID-on-execute binaries on unixy systems
     989 * and when using the open-vboxdrv-via-root-service setup on Windows.
     990 *
     991 * This function will perform the integrity checks of the VirtualBox
     992 * installation, open the support driver, open the root service (later),
     993 * and load the DLL corresponding to \a pszProgName and execute its main
     994 * function.
     995 *
     996 * @returns Return code appropriate for main().
     997 *
     998 * @param   pszProgName     The program name. This will be used to figure out which
     999 *                          DLL/SO/DYLIB to load and execute.
     1000 * @param   fFlags          Flags.
     1001 * @param   argc            The argument count.
     1002 * @param   argv            The argument vector.
     1003 * @param   envp            The environment vector.
     1004 */
     1005DECLHIDDEN(int) SUPR3HardenedMain(const char *pszProgName, uint32_t fFlags, int argc, char **argv, char **envp);
     1006
     1007/** @name SUPR3HardenedMain flags.
     1008 * @{ */
     1009/** Don't open the device. (Intended for VirtualBox without -startvm.) */
     1010#define SUPSECMAIN_FLAGS_DONT_OPEN_DEV      RT_BIT_32(0)
     1011/** The hardened DLL has a "TrustedError" function (see FNSUPTRUSTEDERROR). */
     1012#define SUPSECMAIN_FLAGS_TRUSTED_ERROR      RT_BIT_32(1)
     1013/** @} */
     1014
     1015/**
     1016 * Initializes the support library.
     1017 *
     1018 * Each successful call to SUPR3Init() or SUPR3InitEx must be countered by a
     1019 * call to SUPR3Term(false).
     1020 *
     1021 * @returns VBox status code.
     1022 * @param   ppSession       Where to store the session handle. Defaults to NULL.
     1023 */
     1024SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession);
     1025
     1026
     1027/**
     1028 * Initializes the support library, extended version.
     1029 *
     1030 * Each successful call to SUPR3Init() or SUPR3InitEx must be countered by a
     1031 * call to SUPR3Term(false).
     1032 *
     1033 * @returns VBox status code.
     1034 * @param   fUnrestricted   The desired access.
     1035 * @param   ppSession       Where to store the session handle. Defaults to NULL.
     1036 */
     1037SUPR3DECL(int) SUPR3InitEx(bool fUnrestricted, PSUPDRVSESSION *ppSession);
     1038
     1039/**
     1040 * Terminates the support library.
     1041 *
     1042 * @returns VBox status code.
     1043 * @param   fForced     Forced termination. This means to ignore the
     1044 *                      init call count and just terminated.
     1045 */
     1046#ifdef __cplusplus
     1047SUPR3DECL(int) SUPR3Term(bool fForced = false);
     1048#else
     1049SUPR3DECL(int) SUPR3Term(int fForced);
     1050#endif
     1051
     1052/**
     1053 * Sets the ring-0 VM handle for use with fast IOCtls.
     1054 *
     1055 * @returns VBox status code.
     1056 * @param   pVMR0       The ring-0 VM handle.
     1057 *                      NIL_RTR0PTR can be used to unset the handle when the
     1058 *                      VM is about to be destroyed.
     1059 */
     1060SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0);
     1061
     1062/**
     1063 * Calls the HC R0 VMM entry point.
     1064 * See VMMR0Entry() for more details.
     1065 *
     1066 * @returns error code specific to uFunction.
     1067 * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
     1068 * @param   idCpu       The virtual CPU ID.
     1069 * @param   uOperation  Operation to execute.
     1070 * @param   pvArg       Argument.
     1071 */
     1072SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg);
     1073
     1074/**
     1075 * Variant of SUPR3CallVMMR0, except that this takes the fast ioclt path
     1076 * regardsless of compile-time defaults.
     1077 *
     1078 * @returns VBox status code.
     1079 * @param   pVMR0       The ring-0 VM handle.
     1080 * @param   uOperation  The operation; only the SUP_VMMR0_DO_* ones are valid.
     1081 * @param   idCpu       The virtual CPU ID.
     1082 */
     1083SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu);
     1084
     1085/**
     1086 * Calls the HC R0 VMM entry point, in a safer but slower manner than
     1087 * SUPR3CallVMMR0. When entering using this call the R0 components can call
     1088 * into the host kernel (i.e. use the SUPR0 and RT APIs).
     1089 *
     1090 * See VMMR0Entry() for more details.
     1091 *
     1092 * @returns error code specific to uFunction.
     1093 * @param   pVMR0       Pointer to the Ring-0 (Host Context) mapping of the VM structure.
     1094 * @param   idCpu       The virtual CPU ID.
     1095 * @param   uOperation  Operation to execute.
     1096 * @param   u64Arg      Constant argument.
     1097 * @param   pReqHdr     Pointer to a request header. Optional.
     1098 *                      This will be copied in and out of kernel space. There currently is a size
     1099 *                      limit on this, just below 4KB.
     1100 */
     1101SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr);
     1102
     1103/**
     1104 * Calls a ring-0 service.
     1105 *
     1106 * The operation and the request packet is specific to the service.
     1107 *
     1108 * @returns error code specific to uFunction.
     1109 * @param   pszService  The service name.
     1110 * @param   cchService  The length of the service name.
     1111 * @param   uReq        The request number.
     1112 * @param   u64Arg      Constant argument.
     1113 * @param   pReqHdr     Pointer to a request header. Optional.
     1114 *                      This will be copied in and out of kernel space. There currently is a size
     1115 *                      limit on this, just below 4KB.
     1116 */
     1117SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr);
     1118
     1119/** Which logger. */
     1120typedef enum SUPLOGGER
     1121{
     1122    SUPLOGGER_DEBUG = 1,
     1123    SUPLOGGER_RELEASE
     1124} SUPLOGGER;
     1125
     1126/**
     1127 * Changes the settings of the specified ring-0 logger.
     1128 *
     1129 * @returns VBox status code.
     1130 * @param   enmWhich    Which logger.
     1131 * @param   pszFlags    The flags settings.
     1132 * @param   pszGroups   The groups settings.
     1133 * @param   pszDest     The destination specificier.
     1134 */
     1135SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
     1136
     1137/**
     1138 * Creates a ring-0 logger instance.
     1139 *
     1140 * @returns VBox status code.
     1141 * @param   enmWhich    Which logger to create.
     1142 * @param   pszFlags    The flags settings.
     1143 * @param   pszGroups   The groups settings.
     1144 * @param   pszDest     The destination specificier.
     1145 */
     1146SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest);
     1147
     1148/**
     1149 * Destroys a ring-0 logger instance.
     1150 *
     1151 * @returns VBox status code.
     1152 * @param   enmWhich    Which logger.
     1153 */
     1154SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich);
     1155
     1156/**
     1157 * Queries the paging mode of the host OS.
     1158 *
     1159 * @returns The paging mode.
     1160 */
     1161SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void);
     1162
     1163/**
     1164 * Allocate zero-filled pages.
     1165 *
     1166 * Use this to allocate a number of pages suitable for seeding / locking.
     1167 * Call SUPR3PageFree() to free the pages once done with them.
     1168 *
     1169 * @returns VBox status.
     1170 * @param   cPages          Number of pages to allocate.
     1171 * @param   ppvPages        Where to store the base pointer to the allocated pages.
     1172 */
     1173SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages);
     1174
     1175/**
     1176 * Frees pages allocated with SUPR3PageAlloc().
     1177 *
     1178 * @returns VBox status.
     1179 * @param   pvPages         Pointer returned by SUPR3PageAlloc().
     1180 * @param   cPages          Number of pages that was allocated.
     1181 */
     1182SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages);
     1183
     1184/**
     1185 * Allocate non-zeroed, locked, pages with user and, optionally, kernel
     1186 * mappings.
     1187 *
     1188 * Use SUPR3PageFreeEx() to free memory allocated with this function.
     1189 *
     1190 * @returns VBox status code.
     1191 * @param   cPages          The number of pages to allocate.
     1192 * @param   fFlags          Flags, reserved. Must be zero.
     1193 * @param   ppvPages        Where to store the address of the user mapping.
     1194 * @param   pR0Ptr          Where to store the address of the kernel mapping.
     1195 *                          NULL if no kernel mapping is desired.
     1196 * @param   paPages         Where to store the physical addresses of each page.
     1197 *                          Optional.
     1198 */
     1199SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages);
     1200
     1201/**
     1202 * Maps a portion of a ring-3 only allocation into kernel space.
     1203 *
     1204 * @returns VBox status code.
     1205 *
     1206 * @param   pvR3            The address SUPR3PageAllocEx return.
     1207 * @param   off             Offset to start mapping at. Must be page aligned.
     1208 * @param   cb              Number of bytes to map. Must be page aligned.
     1209 * @param   fFlags          Flags, must be zero.
     1210 * @param   pR0Ptr          Where to store the address on success.
     1211 *
     1212 */
     1213SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr);
     1214
     1215/**
     1216 * Changes the protection of
     1217 *
     1218 * @returns VBox status code.
     1219 * @retval  VERR_NOT_SUPPORTED if the OS doesn't allow us to change page level
     1220 *          protection. See also RTR0MemObjProtect.
     1221 *
     1222 * @param   pvR3            The ring-3 address SUPR3PageAllocEx returned.
     1223 * @param   R0Ptr           The ring-0 address SUPR3PageAllocEx returned if it
     1224 *                          is desired that the corresponding ring-0 page
     1225 *                          mappings should change protection as well. Pass
     1226 *                          NIL_RTR0PTR if the ring-0 pages should remain
     1227 *                          unaffected.
     1228 * @param   off             Offset to start at which to start chagning the page
     1229 *                          level protection. Must be page aligned.
     1230 * @param   cb              Number of bytes to change. Must be page aligned.
     1231 * @param   fProt           The new page level protection, either a combination
     1232 *                          of RTMEM_PROT_READ, RTMEM_PROT_WRITE and
     1233 *                          RTMEM_PROT_EXEC, or just RTMEM_PROT_NONE.
     1234 */
     1235SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt);
     1236
     1237/**
     1238 * Free pages allocated by SUPR3PageAllocEx.
     1239 *
     1240 * @returns VBox status code.
     1241 * @param   pvPages         The address of the user mapping.
     1242 * @param   cPages          The number of pages.
     1243 */
     1244SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages);
     1245
     1246/**
     1247 * Allocated memory with page aligned memory with a contiguous and locked physical
     1248 * memory backing below 4GB.
     1249 *
     1250 * @returns Pointer to the allocated memory (virtual address).
     1251 *          *pHCPhys is set to the physical address of the memory.
     1252 *          If ppvR0 isn't NULL, *ppvR0 is set to the ring-0 mapping.
     1253 *          The returned memory must be freed using SUPR3ContFree().
     1254 * @returns NULL on failure.
     1255 * @param   cPages      Number of pages to allocate.
     1256 * @param   pR0Ptr      Where to store the ring-0 mapping of the allocation. (optional)
     1257 * @param   pHCPhys     Where to store the physical address of the memory block.
     1258 *
     1259 * @remark  This 2nd version of this API exists because we're not able to map the
     1260 *          ring-3 mapping executable on WIN64. This is a serious problem in regard to
     1261 *          the world switchers.
     1262 */
     1263SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys);
     1264
     1265/**
     1266 * Frees memory allocated with SUPR3ContAlloc().
     1267 *
     1268 * @returns VBox status code.
     1269 * @param   pv          Pointer to the memory block which should be freed.
     1270 * @param   cPages      Number of pages to be freed.
     1271 */
     1272SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages);
     1273
     1274/**
     1275 * Allocated non contiguous physical memory below 4GB.
     1276 *
     1277 * The memory isn't zeroed.
     1278 *
     1279 * @returns VBox status code.
     1280 * @returns NULL on failure.
     1281 * @param   cPages      Number of pages to allocate.
     1282 * @param   ppvPages    Where to store the pointer to the allocated memory.
     1283 *                      The pointer stored here on success must be passed to
     1284 *                      SUPR3LowFree when the memory should be released.
     1285 * @param   ppvPagesR0  Where to store the ring-0 pointer to the allocated memory. optional.
     1286 * @param   paPages     Where to store the physical addresses of the individual pages.
     1287 */
     1288SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages);
     1289
     1290/**
     1291 * Frees memory allocated with SUPR3LowAlloc().
     1292 *
     1293 * @returns VBox status code.
     1294 * @param   pv          Pointer to the memory block which should be freed.
     1295 * @param   cPages      Number of pages that was allocated.
     1296 */
     1297SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages);
     1298
     1299/**
     1300 * Load a module into R0 HC.
     1301 *
     1302 * This will verify the file integrity in a similar manner as
     1303 * SUPR3HardenedVerifyFile before loading it.
     1304 *
     1305 * @returns VBox status code.
     1306 * @param   pszFilename     The path to the image file.
     1307 * @param   pszModule       The module name. Max 32 bytes.
     1308 * @param   ppvImageBase    Where to store the image address.
     1309 * @param   pErrInfo        Where to return extended error information.
     1310 *                          Optional.
     1311 */
     1312SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo);
     1313
     1314/**
     1315 * Load a module into R0 HC.
     1316 *
     1317 * This will verify the file integrity in a similar manner as
     1318 * SUPR3HardenedVerifyFile before loading it.
     1319 *
     1320 * @returns VBox status code.
     1321 * @param   pszFilename         The path to the image file.
     1322 * @param   pszModule           The module name. Max 32 bytes.
     1323 * @param   pszSrvReqHandler    The name of the service request handler entry
     1324 *                              point. See FNSUPR0SERVICEREQHANDLER.
     1325 * @param   ppvImageBase        Where to store the image address.
     1326 */
     1327SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,
     1328                                      const char *pszSrvReqHandler, void **ppvImageBase);
     1329
     1330/**
     1331 * Frees a R0 HC module.
     1332 *
     1333 * @returns VBox status code.
     1334 * @param   pszModule       The module to free.
     1335 * @remark  This will not actually 'free' the module, there are of course usage counting.
     1336 */
     1337SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase);
     1338
     1339/**
     1340 * Lock down the module loader interface.
     1341 *
     1342 * This will lock down the module loader interface. No new modules can be
     1343 * loaded and all loaded modules can no longer be freed.
     1344 *
     1345 * @returns VBox status code.
     1346 * @param   pErrInfo        Where to return extended error information.
     1347 *                          Optional.
     1348 */
     1349SUPR3DECL(int) SUPR3LockDownLoader(PRTERRINFO pErrInfo);
     1350
     1351/**
     1352 * Get the address of a symbol in a ring-0 module.
     1353 *
     1354 * @returns VBox status code.
     1355 * @param   pszModule       The module name.
     1356 * @param   pszSymbol       Symbol name. If it's value is less than 64k it's treated like a
     1357 *                          ordinal value rather than a string pointer.
     1358 * @param   ppvValue        Where to store the symbol value.
     1359 */
     1360SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue);
     1361
     1362/**
     1363 * Load R0 HC VMM code.
     1364 *
     1365 * @returns VBox status code.
     1366 * @deprecated  Use SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase)
     1367 */
     1368SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename);
     1369
     1370/**
     1371 * Unloads R0 HC VMM code.
     1372 *
     1373 * @returns VBox status code.
     1374 * @deprecated  Use SUPR3FreeModule().
     1375 */
     1376SUPR3DECL(int) SUPR3UnloadVMM(void);
     1377
     1378/**
     1379 * Get the physical address of the GIP.
     1380 *
     1381 * @returns VBox status code.
     1382 * @param   pHCPhys     Where to store the physical address of the GIP.
     1383 */
     1384SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys);
     1385
     1386/**
     1387 * Initializes only the bits relevant for the SUPR3HardenedVerify* APIs.
     1388 *
     1389 * This is for users that don't necessarily need to initialize the whole of
     1390 * SUPLib.  There is no harm in calling this one more time.
     1391 *
     1392 * @returns VBox status code.
     1393 * @remarks Currently not counted, so only call once.
     1394 */
     1395SUPR3DECL(int) SUPR3HardenedVerifyInit(void);
     1396
     1397/**
     1398 * Reverses the effect of SUPR3HardenedVerifyInit if SUPR3InitEx hasn't been
     1399 * called.
     1400 *
     1401 * Ignored if the support library was initialized using SUPR3Init or
     1402 * SUPR3InitEx.
     1403 *
     1404 * @returns VBox status code.
     1405 */
     1406SUPR3DECL(int) SUPR3HardenedVerifyTerm(void);
     1407
     1408/**
     1409 * Verifies the integrity of a file, and optionally opens it.
     1410 *
     1411 * The integrity check is for whether the file is suitable for loading into
     1412 * the hypervisor or VM process. The integrity check may include verifying
     1413 * the authenticode/elfsign/whatever signature of the file, which can take
     1414 * a little while.
     1415 *
     1416 * @returns VBox status code. On failure it will have printed a LogRel message.
     1417 *
     1418 * @param   pszFilename     The file.
     1419 * @param   pszWhat         For the LogRel on failure.
     1420 * @param   phFile          Where to store the handle to the opened file. This is optional, pass NULL
     1421 *                          if the file should not be opened.
     1422 * @deprecated Write a new one.
     1423 */
     1424SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszWhat, PRTFILE phFile);
     1425
     1426/**
     1427 * Verifies the integrity of a the current process, including the image
     1428 * location and that the invocation was absolute.
     1429 *
     1430 * This must currently be called after initializing the runtime.  The intended
     1431 * audience is set-uid-to-root applications, root services and similar.
     1432 *
     1433 * @returns VBox status code.  On failure
     1434 *          message.
     1435 * @param   pszArgv0        The first argument to main().
     1436 * @param   fInternal       Set this to @c true if this is an internal
     1437 *                          VirtualBox application.  Otherwise pass @c false.
     1438 * @param   pErrInfo        Where to return extended error information.
     1439 */
     1440SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo);
     1441
     1442/**
     1443 * Verifies the integrity of an installation directory.
     1444 *
     1445 * The integrity check verifies that the directory cannot be tampered with by
     1446 * normal users on the system.  On Unix this translates to root ownership and
     1447 * no symbolic linking.
     1448 *
     1449 * @returns VBox status code. On failure a message will be stored in @a pszErr.
     1450 *
     1451 * @param   pszDirPath      The directory path.
     1452 * @param   fRecursive      Whether the check should be recursive or
     1453 *                          not.  When set, all sub-directores will be checked,
     1454 *                          including files (@a fCheckFiles is ignored).
     1455 * @param   fCheckFiles     Whether to apply the same basic integrity check to
     1456 *                          the files in the directory as the directory itself.
     1457 * @param   pErrInfo        Where to return extended error information.
     1458 *                          Optional.
     1459 */
     1460SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo);
     1461
     1462/**
     1463 * Verifies the integrity of a plug-in module.
     1464 *
     1465 * This is similar to SUPR3HardenedLdrLoad, except it does not load the module
     1466 * and that the module does not have to be shipped with VirtualBox.
     1467 *
     1468 * @returns VBox status code. On failure a message will be stored in @a pszErr.
     1469 *
     1470 * @param   pszFilename     The filename of the plug-in module (nothing can be
     1471 *                          omitted here).
     1472 * @param   pErrInfo        Where to return extended error information.
     1473 *                          Optional.
     1474 */
     1475SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo);
     1476
     1477/**
     1478 * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
     1479 *
     1480 * Will add dll suffix if missing and try load the file.
     1481 *
     1482 * @returns iprt status code.
     1483 * @param   pszFilename     Image filename. This must have a path.
     1484 * @param   phLdrMod        Where to store the handle to the loaded module.
     1485 * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
     1486 * @param   pErrInfo        Where to return extended error information.
     1487 *                          Optional.
     1488 */
     1489SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
     1490
     1491/**
     1492 * Same as RTLdrLoadAppPriv() but it will verify the files it loads (hardened
     1493 * builds).
     1494 *
     1495 * Will add dll suffix to the file if missing, then look for it in the
     1496 * architecture dependent application directory.
     1497 *
     1498 * @returns iprt status code.
     1499 * @param   pszFilename     Image filename.
     1500 * @param   phLdrMod        Where to store the handle to the loaded module.
     1501 * @param   fFlags          See RTLDRLOAD_FLAGS_XXX.
     1502 * @param   pErrInfo        Where to return extended error information.
     1503 *                          Optional.
     1504 */
     1505SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo);
     1506
     1507/**
     1508 * Same as RTLdrLoad() but will verify the files it loads (hardened builds).
     1509 *
     1510 * This differs from SUPR3HardenedLdrLoad() in that it can load modules from
     1511 * extension packs and anything else safely installed on the system, provided
     1512 * they pass the hardening tests.
     1513 *
     1514 * @returns iprt status code.
     1515 * @param   pszFilename     The full path to the module, with extension.
     1516 * @param   phLdrMod        Where to store the handle to the loaded module.
     1517 * @param   pErrInfo        Where to return extended error information.
     1518 *                          Optional.
     1519 */
     1520SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo);
     1521
     1522/**
     1523 * Check if the host kernel can run in VMX root mode.
     1524 *
     1525 * @returns VINF_SUCCESS if supported, error code indicating why if not.
     1526 */
     1527SUPR3DECL(int) SUPR3QueryVTxSupported(void);
     1528
     1529/**
     1530 * Return VT-x/AMD-V capabilities.
     1531 *
     1532 * @returns VINF_SUCCESS if supported, error code indicating why if not.
     1533 * @param   pfCaps      Pointer to capability dword (out).
     1534 * @todo Intended for main, which means we need to relax the privilege requires
     1535 *       when accessing certain vboxdrv functions.
     1536 */
     1537SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps);
     1538
     1539/**
     1540 * Open the tracer.
     1541 *
     1542 * @returns VBox status code.
     1543 * @param   uCookie         Cookie identifying the tracer we expect to talk to.
     1544 * @param   uArg            Tracer specific open argument.
     1545 */
     1546SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg);
     1547
     1548/**
     1549 * Closes the tracer.
     1550 *
     1551 * @returns VBox status code.
     1552 */
     1553SUPR3DECL(int) SUPR3TracerClose(void);
     1554
     1555/**
     1556 * Perform an I/O request on the tracer.
     1557 *
     1558 * @returns VBox status.
     1559 * @param   uCmd                The tracer command.
     1560 * @param   uArg                The argument.
     1561 * @param   piRetVal            Where to store the tracer return value.
     1562 */
     1563SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal);
     1564
     1565/**
     1566 * Registers the user module with the tracer.
     1567 *
     1568 * @returns VBox status code.
     1569 * @param   hModNative          Native module handle.  Pass ~(uintptr_t)0 if not
     1570 *                              at hand.
     1571 * @param   pszModule           The module name.
     1572 * @param   pVtgHdr             The VTG header.
     1573 * @param   uVtgHdrAddr         The address to which the VTG header is loaded
     1574 *                              in the relevant execution context.
     1575 * @param   fFlags              See SUP_TRACER_UMOD_FLAGS_XXX
     1576 */
     1577SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,
     1578                                         RTUINTPTR uVtgHdrAddr, uint32_t fFlags);
     1579
     1580/**
     1581 * Deregisters the user module.
     1582 *
     1583 * @returns VBox status code.
     1584 * @param   pVtgHdr             The VTG header.
     1585 */
     1586SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr);
     1587
     1588/**
     1589 * Fire the probe.
     1590 *
     1591 * @param   pVtgProbeLoc        The probe location record.
     1592 * @param   uArg0               Raw probe argument 0.
     1593 * @param   uArg1               Raw probe argument 1.
     1594 * @param   uArg2               Raw probe argument 2.
     1595 * @param   uArg3               Raw probe argument 3.
     1596 * @param   uArg4               Raw probe argument 4.
     1597 */
     1598SUPDECL(void)  SUPTracerFireProbe(struct VTGPROBELOC *pVtgProbeLoc, uintptr_t uArg0, uintptr_t uArg1, uintptr_t uArg2,
     1599                                  uintptr_t uArg3, uintptr_t uArg4);
     1600
     1601
     1602/**
     1603 * Attempts to read the value of an MSR.
     1604 *
     1605 * @returns VBox status code.
     1606 * @param   uMsr                The MSR to read.
     1607 * @param   idCpu               The CPU to read it on, NIL_RTCPUID if it doesn't
     1608 *                              matter which CPU.
     1609 * @param   puValue             Where to return the value.
     1610 * @param   pfGp                Where to store the \#GP indicator for the read
     1611 *                              operation.
     1612 */
     1613SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp);
     1614
     1615/**
     1616 * Attempts to write to an MSR.
     1617 *
     1618 * @returns VBox status code.
     1619 * @param   uMsr                The MSR to write to.
     1620 * @param   idCpu               The CPU to wrtie it on, NIL_RTCPUID if it
     1621 *                              doesn't matter which CPU.
     1622 * @param   uValue              The value to write.
     1623 * @param   pfGp                Where to store the \#GP indicator for the write
     1624 *                              operation.
     1625 */
     1626SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp);
     1627
     1628/**
     1629 * Attempts to modify the value of an MSR.
     1630 *
     1631 * @returns VBox status code.
     1632 * @param   uMsr                The MSR to modify.
     1633 * @param   idCpu               The CPU to modify it on, NIL_RTCPUID if it
     1634 *                              doesn't matter which CPU.
     1635 * @param   fAndMask            The bits to keep in the current MSR value.
     1636 * @param   fOrMask             The bits to set before writing.
     1637 * @param   pResult             The result buffer.
     1638 */
     1639SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask,
     1640                                    PSUPMSRPROBERMODIFYRESULT pResult);
     1641
     1642/**
     1643 * Attempts to modify the value of an MSR, extended version.
     1644 *
     1645 * @returns VBox status code.
     1646 * @param   uMsr                The MSR to modify.
     1647 * @param   idCpu               The CPU to modify it on, NIL_RTCPUID if it
     1648 *                              doesn't matter which CPU.
     1649 * @param   fAndMask            The bits to keep in the current MSR value.
     1650 * @param   fOrMask             The bits to set before writing.
     1651 * @param   fFaster             If set to @c true some cache/tlb invalidation is
     1652 *                              skipped, otherwise behave like
     1653 *                              SUPR3MsrProberModify.
     1654 * @param   pResult             The result buffer.
     1655 */
     1656SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster,
     1657                                      PSUPMSRPROBERMODIFYRESULT pResult);
     1658
     1659/**
     1660 * Resume built-in keyboard on MacBook Air and Pro hosts.
     1661 *
     1662 * @returns VBox status code.
     1663 */
     1664SUPR3DECL(int) SUPR3ResumeSuspendedKeyboards(void);
     1665
     1666
     1667/**
     1668 * Measure the TSC-delta for the specified CPU.
     1669 *
     1670 * @returns VBox status code.
     1671 * @param   idCpu               The CPU to measure the TSC-delta for.
     1672 * @param   fAsync              Whether the measurement is asynchronous, returns
     1673 *                              immediately after signalling a measurement
     1674 *                              request.
     1675 * @param   fForce              Whether to perform a measurement even if the
     1676 *                              specified CPU has a (possibly) valid TSC delta.
     1677 * @param   cRetries            Number of times to retry failed delta
     1678 *                              measurements.
     1679 * @param   cMsWaitRetry        Number of milliseconds to wait between retries.
     1680 */
     1681SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry);
     1682
     1683/**
     1684 * Reads the delta-adjust TSC value.
     1685 *
     1686 * @returns VBox status code.
     1687 * @param   puTsc           Where to store the read TSC value.
     1688 * @param   pidApic         Where to store the APIC ID of the CPU where the TSC
     1689 *                          was read (optional, can be NULL).
     1690 */
     1691SUPR3DECL(int) SUPR3ReadTsc(uint64_t *puTsc, uint16_t *pidApic);
     1692
     1693/** @} */
     1694#endif /* IN_RING3 */
    16211695
    16221696
  • trunk/include/VBox/vmm/tm.h

    r54065 r54308  
    133133VMMDECL(uint64_t)       TMCpuTickGet(PVMCPU pVCpu);
    134134VMM_INT_DECL(uint64_t)  TMCpuTickGetNoCheck(PVMCPU pVCpu);
    135 VMM_INT_DECL(bool)      TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfParavirtTsc);
    136 VMM_INT_DECL(uint64_t)  TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfOffsettedTsc, bool *pfParavirtTsc);
     135VMM_INT_DECL(bool)      TMCpuTickCanUseRealTSC(PVM pVM, PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfParavirtTsc);
     136VMM_INT_DECL(uint64_t)  TMCpuTickGetDeadlineAndTscOffset(PVM pVM, PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfOffsettedTsc, bool *pfParavirtTsc);
    137137VMM_INT_DECL(int)       TMCpuTickSet(PVM pVM, PVMCPU pVCpu, uint64_t u64Tick);
    138138VMM_INT_DECL(int)       TMCpuTickSetLastSeen(PVMCPU pVCpu, uint64_t u64LastSeenTick);
  • trunk/src/VBox/HostDrivers/Support/Makefile.kmk

    r54227 r54308  
    467467#
    468468SUPRC_TEMPLATE := VBoxRc
    469 SUPRC_DEFS     := IN_SUP_RC
     469SUPRC_DEFS     := IN_SUP_RC IN_RT_RC IN_VMM_RC
    470470SUPRC_SOURCES  := SUPLibAll.cpp
    471471
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r54307 r54308  
    215215    { "g_pSUPGlobalInfoPage",                   (void *)&g_pSUPGlobalInfoPage },            /* SED: DATA */
    216216    { "SUPGetGIP",                              (void *)SUPGetGIP },
     217    { "SUPReadTscWithDelta",                    (void *)SUPReadTscWithDelta },
     218    { "SUPGetTscDeltaSlow",                     (void *)SUPGetTscDeltaSlow },
     219    { "SUPGetCpuHzFromGipForAsyncMode",         (void *)SUPGetCpuHzFromGipForAsyncMode },
    217220    { "SUPR0ComponentDeregisterFactory",        (void *)SUPR0ComponentDeregisterFactory },
    218221    { "SUPR0ComponentQueryFactory",             (void *)SUPR0ComponentQueryFactory },
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r54252 r54308  
    215215 *          - Fix SUPTSCREAD padding (#if 0 -> #if 1).
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x001f0000
     217#define SUPDRV_IOC_VERSION                              0x001f0001
    218218
    219219/** SUP_IOCTL_COOKIE. */
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r54249 r54308  
    279279        strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);
    280280        CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
    281         const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001d0000
    282                                    ? 0x001d0002
     281        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001f0000
     282                                   ? 0x001f0001
    283283                                   : SUPDRV_IOC_VERSION & 0xffff0000;
    284284        CookieReq.u.In.u32MinVersion = uMinVersion;
  • trunk/src/VBox/HostDrivers/Support/SUPLibAll.cpp

    r54259 r54308  
    5050 *
    5151 * @returns TSC with delta applied.
     52 * @param   pGip        Pointer to the GIP.
    5253 *
    5354 * @remarks May be called with interrupts disabled in ring-0!  This is why the
     
    5657 * @internal
    5758 */
    58 SUPDECL(uint64_t) SUPReadTscWithDelta(void)
    59 {
    60     PSUPGLOBALINFOPAGE  pGip = g_pSUPGlobalInfoPage;
     59SUPDECL(uint64_t) SUPReadTscWithDelta(PSUPGLOBALINFOPAGE  pGip)
     60{
    6161    uint64_t            uTsc;
    6262    uint16_t            iGipCpu;
    6363    AssertCompile(RT_IS_POWER_OF_TWO(RTCPUSET_MAX_CPUS));
    6464    AssertCompile(RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx) >= RTCPUSET_MAX_CPUS);
    65     Assert(GIP_ARE_TSC_DELTAS_APPLICABLE(pGip));
     65    Assert(pGip->enmUseTscDelta > SUPGIPUSETSCDELTA_PRACTICALLY_ZERO);
    6666
    6767    /*
    6868     * Read the TSC and get the corresponding aCPUs index.
    6969     */
     70#ifdef IN_RING3
    7071    if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
    7172    {
     
    7677        iGipCpu   = pGip->aiCpuFromCpuSetIdx[iCpuSet];
    7778    }
    78 # ifndef IN_RING0
    7979    else if (pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS)
    8080    {
     
    100100        }
    101101    }
    102 # endif /* !IN_RING0 */
    103     else
    104     {
    105 # ifdef IN_RING3
    106         /* Ring-3: Get APIC ID via the slow CPUID instruction, requires looping. */
     102    else
     103    {
     104        /* Get APIC ID via the slow CPUID instruction, requires looping. */
    107105        uint32_t cTries = 0;
    108106        for (;;)
     
    122120            cTries++;
    123121        }
    124 
    125 # elif defined(IN_RING0)
    126         /* Ring-0: Use use RTMpCpuId(), no loops. */
    127         RTCCUINTREG uFlags  = ASMIntDisableFlags();
    128         int         iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId());
    129         if (RT_LIKELY((unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
    130             iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
    131         else
    132             iGipCpu = UINT16_MAX;
    133         uTsc = ASMReadTSC();
    134         ASMSetFlags(uFlags);
     122    }
     123#elif defined(IN_RING0)
     124    /* Ring-0: Use use RTMpCpuId(), no loops. */
     125    RTCCUINTREG uFlags  = ASMIntDisableFlags();
     126    int         iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId());
     127    if (RT_LIKELY((unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     128        iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     129    else
     130        iGipCpu = UINT16_MAX;
     131    uTsc = ASMReadTSC();
     132    ASMSetFlags(uFlags);
    135133
    136134# elif defined(IN_RC)
    137         /* Raw-mode context: We can get the host CPU set index via VMCPU, no loops. */
    138         RTCCUINTREG uFlags  = ASMIntDisableFlags(); /* Are already disable, but play safe. */
    139         uint32_t    iCpuSet = VMMGetCpu(&g_VM)->iHostCpuSet;
    140         if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
    141             iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
    142         else
    143             iGipCpu = UINT16_MAX;
    144         uTsc = ASMReadTSC();
    145         ASMSetFlags(uFlags);
    146 # else
    147 #  error "IN_RING3, IN_RC or IN_RING0 must be defined!"
    148 # endif
    149     }
     135    /* Raw-mode context: We can get the host CPU set index via VMCPU, no loops. */
     136    RTCCUINTREG uFlags  = ASMIntDisableFlags(); /* Are already disable, but play safe. */
     137    uint32_t    iCpuSet = VMMGetCpu(&g_VM)->iHostCpuSet;
     138    if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     139        iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     140    else
     141        iGipCpu = UINT16_MAX;
     142    uTsc = ASMReadTSC();
     143    ASMSetFlags(uFlags);
     144#else
     145# error "IN_RING3, IN_RC or IN_RING0 must be defined!"
     146#endif
    150147
    151148    /*
     
    178175}
    179176
     177
     178/**
     179 * Internal worker for getting the GIP CPU array index for the calling CPU.
     180 *
     181 * @returns Index into SUPGLOBALINFOPAGE::aCPUs or UINT16_MAX.
     182 * @param   pGip    The GIP.
     183 */
     184DECLINLINE(uint16_t) supGetGipCpuIndex(PSUPGLOBALINFOPAGE pGip)
     185{
     186    uint16_t iGipCpu;
     187#ifdef IN_RING3
     188    if (pGip->fGetGipCpu & SUPGIPGETCPU_IDTR_LIMIT_MASK_MAX_SET_CPUS)
     189    {
     190        /* Storing the IDTR is normally very fast. */
     191        uint16_t cbLim = ASMGetIdtrLimit();
     192        uint16_t iCpuSet = cbLim - 256 * (ARCH_BITS == 64 ? 16 : 8);
     193        iCpuSet  &= RTCPUSET_MAX_CPUS - 1;
     194        iGipCpu   = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     195    }
     196    else if (pGip->fGetGipCpu & SUPGIPGETCPU_RDTSCP_MASK_MAX_SET_CPUS)
     197    {
     198        /* RDTSCP gives us what need need and more. */
     199        uint32_t iCpuSet;
     200        ASMReadTscWithAux(&iCpuSet);
     201        iCpuSet  &= RTCPUSET_MAX_CPUS - 1;
     202        iGipCpu   = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     203    }
     204    else
     205    {
     206        /* Get APIC ID via the slow CPUID instruction. */
     207        uint8_t idApic = ASMGetApicId();
     208        iGipCpu = pGip->aiCpuFromApicId[idApic];
     209    }
     210#elif defined(IN_RING0)
     211    /* Ring-0: Use use RTMpCpuId() (disables cli to avoid host OS assertions about unsafe CPU number usage). */
     212    RTCCUINTREG uFlags  = ASMIntDisableFlags();
     213    int         iCpuSet = RTMpCpuIdToSetIndex(RTMpCpuId());
     214    if (RT_LIKELY((unsigned)iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     215        iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     216    else
     217        iGipCpu = UINT16_MAX;
     218    ASMSetFlags(uFlags);
     219
     220# elif defined(IN_RC)
     221    /* Raw-mode context: We can get the host CPU set index via VMCPU. */
     222    uint32_t    iCpuSet = VMMGetCpu(&g_VM)->iHostCpuSet;
     223    if (RT_LIKELY(iCpuSet < RT_ELEMENTS(pGip->aiCpuFromCpuSetIdx)))
     224        iGipCpu = pGip->aiCpuFromCpuSetIdx[iCpuSet];
     225    else
     226        iGipCpu = UINT16_MAX;
     227#else
     228# error "IN_RING3, IN_RC or IN_RING0 must be defined!"
     229#endif
     230    return iGipCpu;
     231}
     232
     233
     234/**
     235 * Slow path in SUPGetTscDelta, don't call directly.
     236 *
     237 * @returns See SUPGetTscDelta.
     238 * @param   pGip        The GIP.
     239 * @internal
     240 */
     241SUPDECL(uint64_t) SUPGetTscDeltaSlow(PSUPGLOBALINFOPAGE pGip)
     242{
     243    uint16_t iGipCpu = supGetGipCpuIndex(pGip);
     244    if (RT_LIKELY(iGipCpu < pGip->cCpus))
     245    {
     246        int64_t iTscDelta = pGip->aCPUs[iGipCpu].i64TSCDelta;
     247        if (iTscDelta != INT64_MAX)
     248            return iTscDelta;
     249    }
     250    AssertFailed();
     251    return 0;
     252}
     253
     254
     255/**
     256 * Slow path in SUPGetCpuHzFromGip, don't call directly.
     257 *
     258 * @returns See SUPGetCpuHzFromGip.
     259 * @param   pGip        The GIP.
     260 * @internal
     261 */
     262SUPDECL(uint64_t) SUPGetCpuHzFromGipForAsyncMode(PSUPGLOBALINFOPAGE pGip)
     263{
     264    uint16_t iGipCpu = supGetGipCpuIndex(pGip);
     265    if (RT_LIKELY(iGipCpu < pGip->cCpus))
     266        return pGip->aCPUs[iGipCpu].u64CpuHz;
     267    AssertFailed();
     268    return pGip->u64CpuHz;
     269}
     270
     271
    180272#endif /* RT_ARCH_AMD64 || RT_ARCH_X86 */
    181273
  • trunk/src/VBox/Runtime/Makefile.kmk

    r54254 r54308  
    22622262 #
    22632263 RuntimeRC_TEMPLATE      = VBoxRc
    2264  RuntimeRC_DEFS          = IN_RT_RC RT_WITH_VBOX
     2264 RuntimeRC_DEFS          = IN_RT_RC RT_WITH_VBOX IN_SUP_R0 IN_VMM_RC
    22652265 RuntimeRC_INCS          = include
    22662266 RuntimeRC_SOURCES      := \
  • trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp

    r52144 r54308  
    55
    66/*
    7  * Copyright (C) 2006-2014 Oracle Corporation
     7 * Copyright (C) 2006-2015 Oracle Corporation
    88 *
    99 * This file is part of VirtualBox Open Source Edition (OSE), as
     
    5858    (PFNRT)SUPSemEventCreate,
    5959    (PFNRT)SUPTracerFireProbe,
     60    (PFNRT)SUPGetTscDeltaSlow,
    6061#endif
    6162    (PFNRT)xmlLoadCatalogs,
  • trunk/src/VBox/VMM/Makefile.kmk

    r53781 r54308  
    404404 VMMRC_SYSSUFF   = .gc
    405405
    406  VMMRC_DEFS      = IN_VMM_RC IN_RT_RC IN_DIS DIS_CORE_ONLY VBOX_WITH_RAW_MODE VBOX_WITH_RAW_MODE_NOT_R0 $(VMM_COMMON_DEFS)
     406 VMMRC_DEFS      = IN_VMM_RC IN_RT_RC IN_DIS DIS_CORE_ONLY VBOX_WITH_RAW_MODE VBOX_WITH_RAW_MODE_NOT_R0 IN_SUP_RC \
     407        $(VMM_COMMON_DEFS)
    407408 ifdef VBOX_WITH_VMM_R0_SWITCH_STACK
    408409  VMMRC_DEFS    += VMM_R0_SWITCH_STACK
     
    422423 VMMRC_LIBS      = \
    423424        $(PATH_STAGE_LIB)/DisasmRC$(VBOX_SUFF_LIB) \
    424         $(PATH_STAGE_LIB)/RuntimeRC$(VBOX_SUFF_LIB)
     425        $(PATH_STAGE_LIB)/RuntimeRC$(VBOX_SUFF_LIB) \
     426        $(PATH_STAGE_LIB)/SUPRC$(VBOX_SUFF_LIB)
    425427 ifneq ($(filter pe lx,$(VBOX_LDR_FMT32)),)
    426428  VMMRC_LIBS    += \
  • trunk/src/VBox/VMM/VMMAll/TMAllCpu.cpp

    r54065 r54308  
    5151
    5252
     53#ifdef IN_RING3
     54/**
     55 * Used by tmR3CpuTickParavirtEnable and tmR3CpuTickParavirtDisable.
     56 */
     57uint64_t tmR3CpuTickGetRawVirtualNoCheck(PVM pVM)
     58{
     59    return tmCpuTickGetRawVirtual(pVM, false /*fCheckTimers*/);
     60}
     61#endif
     62
     63
    5364/**
    5465 * Resumes the CPU timestamp counter ticking.
     
    6879         *        unpaused before the virtual time and stopped after it. */
    6980        if (pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET)
    70             pVCpu->tm.s.offTSCRawSrc = ASMReadTSC() - pVCpu->tm.s.u64TSC;
     81            pVCpu->tm.s.offTSCRawSrc = SUPReadTsc() - pVCpu->tm.s.u64TSC;
    7182        else
    7283            pVCpu->tm.s.offTSCRawSrc = tmCpuTickGetRawVirtual(pVM, false /* don't check for pending timers */)
     
    103114            /* When resuming, use the TSC value of the last stopped VCPU to avoid the TSC going back. */
    104115            if (pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET)
    105                 pVCpu->tm.s.offTSCRawSrc = ASMReadTSC() - pVM->tm.s.u64LastPausedTSC;
     116                pVCpu->tm.s.offTSCRawSrc = SUPReadTsc() - pVM->tm.s.u64LastPausedTSC;
    106117            else
    107118                pVCpu->tm.s.offTSCRawSrc = tmCpuTickGetRawVirtual(pVM, false /* don't check for pending timers */)
     
    211222 *
    212223 * @returns true/false accordingly.
     224 * @param   pVM             Pointer to the cross context VM structure.
    213225 * @param   pVCpu           Pointer to the VMCPU.
    214  * @param   poffRealTSC     The offset against the TSC of the current CPU.
    215  * @param   pfParavirtTsc   Where to store whether paravirt. TSC is enabled.
     226 * @param   poffRealTsc     The offset against the TSC of the current host CPU,
     227 *                          if pfOffsettedTsc is set to true.
     228 * @param   pfParavirtTsc   Where to return whether paravirt TSC is enabled.
    216229 *
    217230 * @thread  EMT(pVCpu).
    218231 * @see     TMCpuTickGetDeadlineAndTscOffset().
    219232 */
    220 VMM_INT_DECL(bool) TMCpuTickCanUseRealTSC(PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfParavirtTsc)
    221 {
    222     PVM pVM = pVCpu->CTX_SUFF(pVM);
    223     bool fOffsettedTsc = false;
     233VMM_INT_DECL(bool) TMCpuTickCanUseRealTSC(PVM pVM, PVMCPU pVCpu, uint64_t *poffRealTsc, bool *pfParavirtTsc)
     234{
     235    Assert(pVCpu->tm.s.fTSCTicking);
     236
     237    *pfParavirtTsc = pVM->tm.s.fParavirtTscEnabled;
     238
     239    /*
     240     * In real TSC mode it's easy, we just need the delta & offTscRawSrc and
     241     * the CPU will add them to RDTSC and RDTSCP at runtime.
     242     *
     243     * In tmCpuTickGetInternal we do:
     244     *          SUPReadTsc() - pVCpu->tm.s.offTSCRawSrc;
     245     * Where SUPReadTsc() does:
     246     *          ASMReadTSC() - pGipCpu->i64TscDelta;
     247     * Which means tmCpuTickGetInternal actually does:
     248     *          ASMReadTSC() - pGipCpu->i64TscDelta - pVCpu->tm.s.offTSCRawSrc;
     249     * So, the offset to be ADDED to RDTSC[P] is:
     250     *          offRealTsc = -(pGipCpu->i64TscDelta + pVCpu->tm.s.offTSCRawSrc)
     251     */
     252    if (pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET)
     253    {
     254        /** @todo We should negate both deltas!  It's soo weird that we do the
     255         *        exact opposite of what the hardware implements. */
     256#ifdef IN_RING3
     257        *poffRealTsc = 0 - pVCpu->tm.s.offTSCRawSrc - SUPGetTscDelta();
     258#else
     259        *poffRealTsc = 0 - pVCpu->tm.s.offTSCRawSrc - SUPGetTscDeltaByCpuSetIndex(pVCpu->iHostCpuSet);
     260#endif
     261        return true;
     262    }
    224263
    225264    /*
     
    232271     *          c) we're not using warp drive (accelerated virtual guest time).
    233272     */
    234     Assert(pVCpu->tm.s.fTSCTicking);
    235     *pfParavirtTsc = pVM->tm.s.fParavirtTscEnabled;
    236 
    237     if (pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET)
    238     {
    239         /* The source is the real TSC. */
    240         *poffRealTSC = 0 - pVCpu->tm.s.offTSCRawSrc;
    241         return true;    /** @todo count this? */
    242     }
    243 
    244273    if (   pVM->tm.s.enmTSCMode == TMTSCMODE_DYNAMIC
    245274        && !pVM->tm.s.fVirtualSyncCatchUp
     
    254283         * timer timeout. If it's lower than the avg. length, we should trap rdtsc to increase
    255284         * the chance that we'll get interrupted right after the timer expired. */
    256         uint64_t u64TSC = ASMReadTSC();     /** @todo should be replaced with SUPReadTSC() eventually. */
    257         *poffRealTSC = u64Now - u64TSC;
    258         fOffsettedTsc = u64Now >= pVCpu->tm.s.u64TSCLastSeen;
    259         return true;    /** @todo count this? */
     285        if (u64Now >= pVCpu->tm.s.u64TSCLastSeen)
     286        {
     287            *poffRealTsc = u64Now - ASMReadTSC();
     288            return true;    /** @todo count this? */
     289        }
    260290    }
    261291
     
    274304 *
    275305 * @returns The number of host cpu ticks to the next deadline.  Max one second.
    276  * @param   cNsToDeadline       The number of nano seconds to the next virtual
    277  *                              sync deadline.
    278  */
    279 DECLINLINE(uint64_t) tmCpuCalcTicksToDeadline(uint64_t cNsToDeadline)
     306 * @param   pVCpu           The current CPU.
     307 * @param   cNsToDeadline   The number of nano seconds to the next virtual
     308 *                          sync deadline.
     309 */
     310DECLINLINE(uint64_t) tmCpuCalcTicksToDeadline(PVMCPU pVCpu, uint64_t cNsToDeadline)
    280311{
    281312    AssertCompile(TMCLOCK_FREQ_VIRTUAL <= _4G);
     313#ifdef IN_RING3
     314    uint64_t uCpuHz = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage);
     315#else
     316    uint64_t uCpuHz = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
     317#endif
    282318    if (RT_UNLIKELY(cNsToDeadline >= TMCLOCK_FREQ_VIRTUAL))
    283         return SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
    284     uint64_t cTicks = ASMMultU64ByU32DivByU32(SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage),
    285                                               cNsToDeadline,
    286                                               TMCLOCK_FREQ_VIRTUAL);
     319        return uCpuHz;
     320    uint64_t cTicks = ASMMultU64ByU32DivByU32(uCpuHz, cNsToDeadline, TMCLOCK_FREQ_VIRTUAL);
    287321    if (cTicks > 4000)
    288322        cTicks -= 4000; /* fudge to account for overhead */
     
    298332 *
    299333 * @returns The number of host CPU clock ticks to the next timer deadline.
     334 * @param   pVM             Pointer to the cross context VM structure.
    300335 * @param   pVCpu           The current CPU.
    301  * @param   poffRealTSC     The offset against the TSC of the current CPU.
    302  * @param   pfOffsettedTsc  Where to store whether TSC offsetting can be used.
    303  * @param   pfParavirtTsc   Where to store whether paravirt. TSC is enabled.
     336 * @param   poffRealTsc     The offset against the TSC of the current host CPU,
     337 *                          if pfOffsettedTsc is set to true.
     338 * @param   pfOffsettedTsc  Where to return whether TSC offsetting can be used.
     339 * @param   pfParavirtTsc   Where to return whether paravirt TSC is enabled.
    304340 *
    305341 * @thread  EMT(pVCpu).
    306342 * @see     TMCpuTickCanUseRealTSC().
    307343 */
    308 VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVMCPU pVCpu, uint64_t *poffRealTSC, bool *pfOffsettedTsc,
    309                                                         bool *pfParavirtTsc)
    310 {
    311     PVM      pVM = pVCpu->CTX_SUFF(pVM);
    312     uint64_t cTicksToDeadline;
     344VMM_INT_DECL(uint64_t) TMCpuTickGetDeadlineAndTscOffset(PVM pVM, PVMCPU pVCpu, uint64_t *poffRealTsc,
     345                                                        bool *pfOffsettedTsc, bool *pfParavirtTsc)
     346{
     347    Assert(pVCpu->tm.s.fTSCTicking);
     348
     349    *pfParavirtTsc = pVM->tm.s.fParavirtTscEnabled;
    313350
    314351    /*
    315      * We require:
    316      *     1. A fixed TSC, this is checked at init time.
    317      *     2. That the TSC is ticking (we shouldn't be here if it isn't)
    318      *     3. Either that we're using the real TSC as time source or
    319      *          a) we don't have any lag to catch up, and
    320      *          b) the virtual sync clock hasn't been halted by an expired timer, and
    321      *          c) we're not using warp drive (accelerated virtual guest time).
     352     * Same logic as in TMCpuTickCanUseRealTSC.
    322353     */
    323     Assert(pVCpu->tm.s.fTSCTicking);
    324     *pfParavirtTsc = pVM->tm.s.fParavirtTscEnabled;
    325 
    326354    if (pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET)
    327355    {
    328         /* The source is the real TSC. */
    329         *poffRealTSC    = 0 - pVCpu->tm.s.offTSCRawSrc;
    330         *pfOffsettedTsc = true;
    331         cTicksToDeadline = tmCpuCalcTicksToDeadline(TMVirtualSyncGetNsToDeadline(pVM));
    332         return cTicksToDeadline;
    333     }
    334 
     356        /** @todo We should negate both deltas!  It's soo weird that we do the
     357         *        exact opposite of what the hardware implements. */
     358#ifdef IN_RING3
     359        *poffRealTsc     = 0 - pVCpu->tm.s.offTSCRawSrc - SUPGetTscDelta();
     360#else
     361        *poffRealTsc     = 0 - pVCpu->tm.s.offTSCRawSrc - SUPGetTscDeltaByCpuSetIndex(pVCpu->iHostCpuSet);
     362#endif
     363        *pfOffsettedTsc  = true;
     364        return tmCpuCalcTicksToDeadline(pVCpu, TMVirtualSyncGetNsToDeadline(pVM));
     365    }
     366
     367    /*
     368     * Same logic as in TMCpuTickCanUseRealTSC.
     369     */
    335370    if (   pVM->tm.s.enmTSCMode == TMTSCMODE_DYNAMIC
    336371        && !pVM->tm.s.fVirtualSyncCatchUp
     
    345380                        : u64NowVirtSync;
    346381        u64Now -= pVCpu->tm.s.offTSCRawSrc;
    347         *poffRealTSC     = u64Now - ASMReadTSC();        /** @todo replace with SUPReadTSC() eventually. */
     382        *poffRealTsc     = u64Now - ASMReadTSC();
    348383        *pfOffsettedTsc  = u64Now >= pVCpu->tm.s.u64TSCLastSeen;
    349         cTicksToDeadline = tmCpuCalcTicksToDeadline(cNsToDeadline);
    350         return cTicksToDeadline;
     384        return tmCpuCalcTicksToDeadline(pVCpu, cNsToDeadline);
    351385    }
    352386
     
    355389#endif
    356390    *pfOffsettedTsc  = false;
    357     *poffRealTSC     = 0;
    358     cTicksToDeadline = tmCpuCalcTicksToDeadline(TMVirtualSyncGetNsToDeadline(pVM));
    359     return cTicksToDeadline;
     391    *poffRealTsc     = 0;
     392    return tmCpuCalcTicksToDeadline(pVCpu, TMVirtualSyncGetNsToDeadline(pVM));
    360393}
    361394
     
    375408        PVM pVM = pVCpu->CTX_SUFF(pVM);
    376409        if (pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET)
    377             u64 = ASMReadTSC();
     410            u64 = SUPReadTsc();
    378411        else
    379412            u64 = tmCpuTickGetRawVirtual(pVM, fCheckTimers);
     
    497530        && g_pSUPGlobalInfoPage->u32Mode != SUPGIPMODE_INVARIANT_TSC)
    498531    {
    499         uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     532#ifdef IN_RING3
     533        uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage);
     534#elif defined(IN_RING0)
     535        uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, RTMpCpuIdToSetIndex(RTMpCpuId()));
     536#else
     537        uint64_t cTSCTicksPerSecond = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, VMMGetCpu(pVM)->iHostCpuSet);
     538#endif
    500539        if (RT_LIKELY(cTSCTicksPerSecond != ~(uint64_t)0))
    501540            return cTSCTicksPerSecond;
  • trunk/src/VBox/VMM/VMMR0/HMR0.cpp

    r54277 r54308  
    14031403
    14041404    /* Clear the VCPU <-> host CPU mapping as we've left HM context. */
    1405     ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID);
     1405    ASMAtomicWriteU32(&pVCpu->idHostCpu, NIL_RTCPUID); /** @todo r=bird: This is VMMR0.cpp's job, isn't it? */
    14061406
    14071407    return VINF_SUCCESS;
  • trunk/src/VBox/VMM/VMMR0/HMSVMR0.cpp

    r54196 r54308  
    22512251 * intercepts.
    22522252 *
     2253 * @param   pVM         The shared VM handle.
    22532254 * @param   pVCpu       Pointer to the VMCPU.
    22542255 *
    22552256 * @remarks No-long-jump zone!!!
    22562257 */
    2257 static void hmR0SvmUpdateTscOffsetting(PVMCPU pVCpu)
    2258 {
    2259     bool fParavirtTsc;
    2260     bool fCanUseRealTsc;
     2258static void hmR0SvmUpdateTscOffsetting(PVM pVM, PVMCPU pVCpu)
     2259{
     2260    bool     fParavirtTsc;
    22612261    PSVMVMCB pVmcb = (PSVMVMCB)pVCpu->hm.s.svm.pvVmcb;
    2262     fCanUseRealTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVmcb->ctrl.u64TSCOffset, &fParavirtTsc);
     2262    bool fCanUseRealTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &pVmcb->ctrl.u64TSCOffset, &fParavirtTsc);
    22632263    if (fCanUseRealTsc)
    22642264    {
     
    22792279    if (fParavirtTsc)
    22802280    {
    2281         int rc = GIMR0UpdateParavirtTsc(pVCpu->CTX_SUFF(pVM), 0 /* u64Offset */);
     2281        int rc = GIMR0UpdateParavirtTsc(pVM, 0 /* u64Offset */);
    22822282        AssertRC(rc);
    22832283        STAM_COUNTER_INC(&pVCpu->hm.s.StatTscParavirt);
     
    30683068        || idCurrentCpu != pVCpu->hm.s.idLastCpu)
    30693069    {
    3070         hmR0SvmUpdateTscOffsetting(pVCpu);
     3070        hmR0SvmUpdateTscOffsetting(pVM, pVCpu);
    30713071        pSvmTransient->fUpdateTscOffsetting = false;
    30723072    }
     
    31903190
    31913191    if (!(pVmcb->ctrl.u32InterceptCtrl1 & SVM_CTRL1_INTERCEPT_RDTSC))
    3192         TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVmcb->ctrl.u64TSCOffset);     /** @todo use SUPReadTSC() eventually. */
     3192        TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVmcb->ctrl.u64TSCOffset);
    31933193
    31943194    STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatExit1, x);
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r54196 r54308  
    56035603 *
    56045604 * @returns VBox status code.
     5605 * @param   pVM             Pointer to the cross context VM structure.
    56055606 * @param   pVCpu           Pointer to the VMCPU.
    56065607 *
    56075608 * @remarks No-long-jump zone!!!
    56085609 */
    5609 static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVMCPU pVCpu)
    5610 {
    5611     int  rc            = VERR_INTERNAL_ERROR_5;
    5612     bool fOffsettedTsc = false;
    5613     bool fParavirtTsc  = false;
    5614     PVM pVM            = pVCpu->CTX_SUFF(pVM);
     5610static void hmR0VmxUpdateTscOffsettingAndPreemptTimer(PVM pVM, PVMCPU pVCpu)
     5611{
     5612    int  rc;
     5613    bool fOffsettedTsc;
     5614    bool fParavirtTsc;
    56155615    if (pVM->hm.s.vmx.fUsePreemptTimer)
    56165616    {
    5617         uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset, &fOffsettedTsc,
    5618                                                                      &fParavirtTsc);
     5617        uint64_t cTicksToDeadline = TMCpuTickGetDeadlineAndTscOffset(pVM, pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset,
     5618                                                                     &fOffsettedTsc, &fParavirtTsc);
    56195619
    56205620        /* Make sure the returned values have sane upper and lower boundaries. */
    5621         uint64_t u64CpuHz  = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     5621        uint64_t u64CpuHz  = SUPGetCpuHzFromGipBySetIndex(g_pSUPGlobalInfoPage, pVCpu->iHostCpuSet);
    56225622        cTicksToDeadline   = RT_MIN(cTicksToDeadline, u64CpuHz / 64);      /* 1/64th of a second */
    56235623        cTicksToDeadline   = RT_MAX(cTicksToDeadline, u64CpuHz / 2048);    /* 1/2048th of a second */
     
    56285628    }
    56295629    else
    5630         fOffsettedTsc = TMCpuTickCanUseRealTSC(pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset, &fParavirtTsc);
     5630        fOffsettedTsc = TMCpuTickCanUseRealTSC(pVM, pVCpu, &pVCpu->hm.s.vmx.u64TSCOffset, &fParavirtTsc);
    56315631
    56325632    /** @todo later optimize this to be done elsewhere and not before every
     
    86378637        || idCurrentCpu != pVCpu->hm.s.idLastCpu)
    86388638    {
    8639         hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVCpu);
     8639        hmR0VmxUpdateTscOffsettingAndPreemptTimer(pVM, pVCpu);
    86408640        pVmxTransient->fUpdateTscOffsettingAndPreemptTimer = false;
    86418641    }
     
    87188718
    87198719    if (!(pVCpu->hm.s.vmx.u32ProcCtls & VMX_VMCS_CTRL_PROC_EXEC_RDTSC_EXIT))
    8720         TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVCpu->hm.s.vmx.u64TSCOffset);     /** @todo use SUPReadTSC() eventually. */
     8720        TMCpuTickSetLastSeen(pVCpu, ASMReadTSC() + pVCpu->hm.s.vmx.u64TSCOffset);
    87218721
    87228722    STAM_PROFILE_ADV_STOP_START(&pVCpu->hm.s.StatInGC, &pVCpu->hm.s.StatExit1, x);
  • trunk/src/VBox/VMM/VMMR3/TM.cpp

    r54292 r54308  
    182182static DECLCALLBACK(void)   tmR3TimerInfoActive(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    183183static DECLCALLBACK(void)   tmR3InfoClocks(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);
    184 static DECLCALLBACK(VBOXSTRICTRC) tmR3CpuTickParavirtToggle(PVM pVM, PVMCPU pVCpu, void *pvData);
     184static DECLCALLBACK(VBOXSTRICTRC) tmR3CpuTickParavirtDisable(PVM pVM, PVMCPU pVCpu, void *pvData);
    185185
    186186
     
    934934     * Use GIP when available.
    935935     */
    936     uint64_t u64Hz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     936    uint64_t u64Hz = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage);
    937937    if (g_pSUPGlobalInfoPage->u32Mode == SUPGIPMODE_INVARIANT_TSC)
    938938    {
     
    954954        }
    955955
    956         u64Hz = SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage);
     956        u64Hz = SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage);
    957957        if (u64Hz != UINT64_MAX)
    958958            return u64Hz;
     
    11821182    {
    11831183        bool fParavirtTSC = false;
    1184         tmR3CpuTickParavirtToggle(pVM, NULL /* pVCpuEmt */, &fParavirtTSC);
     1184        tmR3CpuTickParavirtDisable(pVM, NULL, NULL);
    11851185    }
    11861186    Assert(!GIMIsParavirtTscEnabled(pVM));
     
    30933093
    30943094/**
    3095  * Switch TM TSC mode to the most appropriate/efficient one.
    3096  *
    3097  * @returns strict VBox status code.
    3098  * @param   pVM         Pointer to the VM.
    3099  * @param   pVCpuEmt    Pointer to the VMCPU it's called on, can be NULL.
    3100  * @param   pvData      Opaque pointer to whether usage of paravirt. TSC is
    3101  *                      enabled or disabled by the guest OS.
    3102  *
    3103  * @thread  EMT.
    3104  * @remarks Must only be called during an EMTs rendezvous.
    3105  */
    3106 static DECLCALLBACK(VBOXSTRICTRC) tmR3CpuTickParavirtToggle(PVM pVM, PVMCPU pVCpuEmt, void *pvData)
    3107 {
    3108     Assert(pVM);
    3109     Assert(pvData);
    3110     Assert(pVM->tm.s.fTSCModeSwitchAllowed);
    3111     NOREF(pVCpuEmt);
    3112 
    3113     bool *pfEnable = (bool *)pvData;
    3114     if (*pfEnable)
    3115     {
    3116         if (pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET)
     3095 * @callback_method_impl{PFNVMMEMTRENDEZVOUS,
     3096 *      Worker for TMR3CpuTickParavirtEnable}
     3097 */
     3098static DECLCALLBACK(VBOXSTRICTRC) tmR3CpuTickParavirtEnable(PVM pVM, PVMCPU pVCpuEmt, void *pvData)
     3099{
     3100    AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt); NOREF(pvData);
     3101    Assert(pVCpuEmt->tm.s.fTSCTicking);
     3102
     3103    if (pVM->tm.s.enmTSCMode != TMTSCMODE_REAL_TSC_OFFSET)
     3104    {
     3105        if (tmR3HasFixedTSC(pVM))
    31173106        {
    3118             if (tmR3HasFixedTSC(pVM))
    3119             {
    3120                 uint64_t u64NowVirtSync = TMVirtualSyncGetNoCheck(pVM);
    3121                 uint64_t u64Now = ASMMultU64ByU32DivByU32(u64NowVirtSync, pVM->tm.s.cTSCTicksPerSecond, TMCLOCK_FREQ_VIRTUAL);
    3122                 uint32_t cCpus  = pVM->cCpus;
    3123                 uint64_t u64RealTSC = ASMReadTSC();     /** @todo should use SUPReadTsc() */
    3124                 for (uint32_t i = 0; i < cCpus; i++)
    3125                 {
    3126                     PVMCPU   pVCpu = &pVM->aCpus[i];
    3127                     uint64_t u64TickOld = u64Now - pVCpu->tm.s.offTSCRawSrc;
    3128 
    3129                     /*
    3130                      * The return value of TMCpuTickGet() and the guest's TSC value (u64Tick) must
    3131                      * remain constant across the TM TSC mode-switch.
    3132                      * OldTick = VrSync - CurOff
    3133                      * NewTick = RealTsc - NewOff
    3134                      * NewTick = OldTick
    3135                      *  => RealTsc - NewOff = VrSync - CurOff
    3136                      *  => NewOff = CurOff + RealTsc - VrSync
    3137                      */
    3138                     pVCpu->tm.s.offTSCRawSrc = pVCpu->tm.s.offTSCRawSrc + u64RealTSC  - u64Now;
    3139 
    3140                     /* If the new offset results in the TSC going backwards, re-adjust the offset. */
    3141                     if (u64RealTSC - pVCpu->tm.s.offTSCRawSrc < u64TickOld)
    3142                         pVCpu->tm.s.offTSCRawSrc += u64TickOld - u64RealTSC;
    3143                     Assert(u64RealTSC - pVCpu->tm.s.offTSCRawSrc >= u64TickOld);
    3144                 }
    3145                 pVM->tm.s.enmTSCMode = TMTSCMODE_REAL_TSC_OFFSET;
    3146                 LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
    3147             }
    3148             else
    3149                 LogRel(("TM: Host is not suitable for using TSC mode (%d - %s). Request to change TSC mode ignored.\n",
    3150                         TMTSCMODE_REAL_TSC_OFFSET, tmR3GetTSCModeNameEx(TMTSCMODE_REAL_TSC_OFFSET)));
    3151         }
    3152     }
    3153     else
    3154     {
    3155         if (   pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET
    3156             && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode)
    3157         {
    3158             uint64_t u64NowVirtSync = TMVirtualSyncGetNoCheck(pVM);
    3159             uint64_t u64Now     = ASMMultU64ByU32DivByU32(u64NowVirtSync, pVM->tm.s.cTSCTicksPerSecond, TMCLOCK_FREQ_VIRTUAL);
    3160             uint64_t u64RealTSC = ASMReadTSC();          /** @todo replace with SUPReadTSC() eventually. */
    3161             uint32_t cCpus      = pVM->cCpus;
     3107            /*
     3108             * The return value of TMCpuTickGet() and the guest's TSC value for each
     3109             * CPU must remain constant across the TM TSC mode-switch.  Thus we have
     3110             * the following equation (new/old signifies the new/old tsc modes):
     3111             *      uNewTsc = uOldTsc
     3112             *
     3113             * Where (see tmCpuTickGetInternal):
     3114             *      uOldTsc = uRawOldTsc - offTscRawSrcOld
     3115             *      uNewTsc = uRawNewTsc - offTscRawSrcNew
     3116             *
     3117             * Solve it for offTscRawSrcNew without replacing uOldTsc:
     3118             *     uRawNewTsc - offTscRawSrcNew = uOldTsc
     3119             *  => -offTscRawSrcNew = uOldTsc - uRawNewTsc
     3120             *  => offTscRawSrcNew  = uRawNewTsc - uOldTsc
     3121             */
     3122            uint64_t uRawOldTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM);
     3123            uint64_t uRawNewTsc = SUPReadTsc();
     3124            uint32_t cCpus = pVM->cCpus;
    31623125            for (uint32_t i = 0; i < cCpus; i++)
    31633126            {
    3164                 PVMCPU   pVCpu      = &pVM->aCpus[i];
    3165                 uint64_t u64TickOld = u64RealTSC - pVCpu->tm.s.offTSCRawSrc;
    3166 
    3167                 /* Update the last-seen tick here as we havent't been updating it (as we don't
    3168                    need it) while in pure TSC-offsetting mode. */
    3169                 pVCpu->tm.s.u64TSCLastSeen = pVCpu->tm.s.u64TSC;
    3170 
    3171                 /*
    3172                  * The return value of TMCpuTickGet() and the guest's TSC value (u64Tick) must
    3173                  * remain constant across the TM TSC mode-switch.
    3174                  * OldTick = RealTsc - CurOff
    3175                  * NewTick = VrSync - NewOff
    3176                  * NewTick = OldTick
    3177                  *  => VrSync - NewOff = RealTsc - CurOff
    3178                  *  => NewOff = CurOff + VrSync - RealTsc
    3179                  */
    3180                 pVCpu->tm.s.offTSCRawSrc = pVCpu->tm.s.offTSCRawSrc + u64Now - u64RealTSC;
    3181 
    3182                 /* If the new offset results in the TSC going backwards, re-adjust the offset. */
    3183                 if (u64Now - pVCpu->tm.s.offTSCRawSrc < u64TickOld)
    3184                     pVCpu->tm.s.offTSCRawSrc += u64TickOld - u64Now;
    3185                 Assert(u64Now - pVCpu->tm.s.offTSCRawSrc >= u64TickOld);
     3127                PVMCPU   pVCpu   = &pVM->aCpus[i];
     3128                uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc;
     3129                pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc;
     3130                Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */
    31863131            }
    3187             pVM->tm.s.enmTSCMode = pVM->tm.s.enmOriginalTSCMode;
     3132
     3133            pVM->tm.s.enmTSCMode = TMTSCMODE_REAL_TSC_OFFSET;
    31883134            LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
    31893135        }
     3136        else
     3137            LogRel(("TM: Host is not suitable for using TSC mode (%d - %s). Request to change TSC mode ignored.\n",
     3138                    TMTSCMODE_REAL_TSC_OFFSET, tmR3GetTSCModeNameEx(TMTSCMODE_REAL_TSC_OFFSET)));
    31903139    }
    31913140    return VINF_SUCCESS;
     
    31953144/**
    31963145 * Notify TM that the guest has enabled usage of a paravirtualized TSC.
     3146 *
     3147 * This may perform a EMT rendezvous and change the TSC virtualization mode.
    31973148 *
    31983149 * @returns VBox status code.
     
    32033154    int rc = VINF_SUCCESS;
    32043155    if (pVM->tm.s.fTSCModeSwitchAllowed)
    3205     {
    3206         bool fEnable = true;
    3207         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtToggle, (void *)&fEnable);
    3208     }
     3156        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtEnable, NULL);
    32093157    pVM->tm.s.fParavirtTscEnabled = true;
    32103158    return rc;
     
    32133161
    32143162/**
     3163 * @callback_method_impl{PFNVMMEMTRENDEZVOUS,
     3164 *      Worker for TMR3CpuTickParavirtDisable}
     3165 */
     3166static DECLCALLBACK(VBOXSTRICTRC) tmR3CpuTickParavirtDisable(PVM pVM, PVMCPU pVCpuEmt, void *pvData)
     3167{
     3168    AssertPtr(pVM); Assert(pVM->tm.s.fTSCModeSwitchAllowed); NOREF(pVCpuEmt);
     3169    Assert(pVCpuEmt->tm.s.fTSCTicking);
     3170
     3171    if (   pVM->tm.s.enmTSCMode == TMTSCMODE_REAL_TSC_OFFSET
     3172        && pVM->tm.s.enmTSCMode != pVM->tm.s.enmOriginalTSCMode)
     3173    {
     3174        /*
     3175         * See tmR3CpuTickParavirtEnable for an explanation of the conversion math.
     3176         */
     3177        uint64_t uRawOldTsc = SUPReadTsc();
     3178        uint64_t uRawNewTsc = tmR3CpuTickGetRawVirtualNoCheck(pVM);
     3179        uint32_t cCpus = pVM->cCpus;
     3180        for (uint32_t i = 0; i < cCpus; i++)
     3181        {
     3182            PVMCPU   pVCpu   = &pVM->aCpus[i];
     3183            uint64_t uOldTsc = uRawOldTsc - pVCpu->tm.s.offTSCRawSrc;
     3184            pVCpu->tm.s.offTSCRawSrc = uRawNewTsc - uOldTsc;
     3185            Assert(uRawNewTsc - pVCpu->tm.s.offTSCRawSrc >= uOldTsc); /* paranoia^256 */
     3186
     3187            /* Update the last-seen tick here as we havent't been updating it (as we don't
     3188               need it) while in pure TSC-offsetting mode. */
     3189#if 0 /** @todo r=bird: Why use the TSC value from the last time we paused the TSC? Makes more sense to use uOldTsc doesn't it? */
     3190            pVCpu->tm.s.u64TSCLastSeen = pVCpu->tm.s.u64TSC;
     3191#else
     3192            pVCpu->tm.s.u64TSCLastSeen = uOldTsc;
     3193#endif
     3194        }
     3195        pVM->tm.s.enmTSCMode = pVM->tm.s.enmOriginalTSCMode;
     3196        LogRel(("TM: Switched TSC mode. New enmTSCMode=%d (%s)\n", pVM->tm.s.enmTSCMode, tmR3GetTSCModeName(pVM)));
     3197    }
     3198    return VINF_SUCCESS;
     3199}
     3200
     3201
     3202/**
    32153203 * Notify TM that the guest has disabled usage of a paravirtualized TSC.
     3204 *
     3205 * If TMR3CpuTickParavirtEnable changed the TSC virtualization mode, this will
     3206 * perform an EMT  rendezvous to revert those changes.
    32163207 *
    32173208 * @returns VBox status code.
     
    32223213    int rc = VINF_SUCCESS;
    32233214    if (pVM->tm.s.fTSCModeSwitchAllowed)
    3224     {
    3225         bool fEnable = false;
    3226         rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtToggle, (void *)&fEnable);
    3227     }
     3215        rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, tmR3CpuTickParavirtDisable, NULL);
    32283216    pVM->tm.s.fParavirtTscEnabled = false;
    32293217    return rc;
  • trunk/src/VBox/VMM/VMMR3/VMMTests.cpp

    r50115 r54308  
    495495            }
    496496            uint64_t Ticks = ASMReadTSC() - StartTick;
    497             if (Ticks < (SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage) / 10000))
    498                 RTPrintf("Warning: Ticks=%RU64 (< %RU64)\n", Ticks, SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage) / 10000);
     497            if (Ticks < (SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) / 10000))
     498                RTPrintf("Warning: Ticks=%RU64 (< %RU64)\n", Ticks, SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) / 10000);
    499499        }
    500500
  • trunk/src/VBox/VMM/VMMRC/VMMRC.cpp

    r49893 r54308  
    136136        case VMMGC_DO_TESTCASE_INTERRUPT_MASKING:
    137137        {
    138             uint64_t u64MaxTicks = (SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage) != ~(uint64_t)0
    139                                     ? SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage)
     138            uint64_t u64MaxTicks = (SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) != ~(uint64_t)0
     139                                    ? SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage)
    140140                                    : _2G)
    141141                                   / 10000;
  • trunk/src/VBox/VMM/include/TMInternal.h

    r54270 r54308  
    759759#endif
    760760
     761uint64_t                tmR3CpuTickGetRawVirtualNoCheck(PVM pVM);
    761762int                     tmCpuTickPause(PVMCPU pVCpu);
    762763int                     tmCpuTickPauseLocked(PVM pVM, PVMCPU pVCpu);
Note: See TracChangeset for help on using the changeset viewer.

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