VirtualBox

Changeset 53063 in vbox


Ignore:
Timestamp:
Oct 15, 2014 12:41:35 PM (10 years ago)
Author:
vboxsync
Message:

HostDrivers/Support: Add TSC-delta measurement ioctl interface, fixed spinning on concurrent measurements.

Location:
trunk
Files:
4 edited

Legend:

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

    r52618 r53063  
    14341434SUPR3DECL(int) SUPR3ResumeSuspendedKeyboards(void);
    14351435
     1436
     1437/**
     1438 * Measure the TSC-delta for the specified CPU.
     1439 *
     1440 * @returns VBox status code.
     1441 * @param   idCpu               The CPU to measure the TSC-delta for.
     1442 * @param   fAsync              Whether the measurement is asynchronous, returns
     1443 *                              immediately after signalling a measurement
     1444 *                              request.
     1445 * @param   fForce              Whether to perform a measurement even if the
     1446 *                              specified CPU has a (possibly) valid TSC delta.
     1447 * @param   cRetries            Number of times to retry failed delta
     1448 *                              measurements.
     1449 */
     1450SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries);
     1451
    14361452/** @} */
    14371453#endif /* IN_RING3 */
  • trunk/src/VBox/HostDrivers/Support/SUPDrv.c

    r53058 r53063  
    154154static int                  supdrvIOCtl_LoggerSettings(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLOGGERSETTINGS pReq);
    155155static int                  supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq);
     156static int                  supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPTSCDELTAMEASURE pReq);
    156157static int                  supdrvGipCreate(PSUPDRVDEVEXT pDevExt);
    157158static void                 supdrvGipDestroy(PSUPDRVDEVEXT pDevExt);
     
    22422243        }
    22432244
     2245        case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_TSC_DELTA_MEASURE):
     2246        {
     2247            /* validate */
     2248            PSUPTSCDELTAMEASURE pReq = (PSUPTSCDELTAMEASURE)pReqHdr;
     2249            REQ_CHECK_SIZES(SUP_IOCTL_TSC_DELTA_MEASURE);
     2250
     2251            pReqHdr->rc = supdrvIOCtl_TscDeltaMeasure(pDevExt, pReq);
     2252            return 0;
     2253        }
     2254
    22442255        default:
    22452256            Log(("Unknown IOCTL %#lx\n", (long)uIOCtl));
     
    66426653static int supdrvMeasureTscDeltaOne(PSUPDRVDEVEXT pDevExt, uint32_t idxWorker)
    66436654{
    6644     PSUPGLOBALINFOPAGE pGip  = pDevExt->pGip;
    6645     RTCPUID    idMaster      = pDevExt->idGipMaster;
    6646     uint32_t   idxMaster     = supdrvGipCpuIndexFromCpuId(pGip, idMaster);
    6647     PSUPGIPCPU pGipCpuWorker = &pGip->aCPUs[idxWorker];
    6648     int        rc            = VERR_CPU_OFFLINE;
    6649 
    6650     if (idxWorker == idxMaster)
     6655    int rc;
     6656    PSUPGLOBALINFOPAGE pGip;
     6657    PSUPGIPCPU pGipCpuWorker;
     6658    RTCPUID idMaster;
     6659
     6660    AssertReturn(pDevExt, VERR_INVALID_PARAMETER);
     6661    AssertReturn(pDevExt->pGip, VERR_INVALID_PARAMETER);
     6662
     6663    pGip          = pDevExt->pGip;
     6664    idMaster      = pDevExt->idGipMaster;
     6665    pGipCpuWorker = &pGip->aCPUs[idxWorker];
     6666
     6667    if (pGipCpuWorker->idCpu == idMaster)
    66516668    {
    66526669        ASMAtomicWriteS64(&pGipCpuWorker->i64TSCDelta, 0);
     
    66566673    /* Set the master TSC as the initiator. */
    66576674    while (ASMAtomicCmpXchgU32(&g_idTscDeltaInitiator, idMaster, NIL_RTCPUID) == false)
    6658         ASMNopPause();
     6675    {
     6676        /*
     6677         * Sleep here rather than spin as there is a parallel measurement
     6678         * being executed and that can take a good while to be done.
     6679         */
     6680        RTThreadSleep(1);
     6681    }
    66596682
    66606683    if (RTCpuSetIsMember(&pGip->OnlineCpuSet, pGipCpuWorker->idCpu))
     
    66706693        }
    66716694    }
     6695    else
     6696        rc = VERR_CPU_OFFLINE;
    66726697
    66736698    ASMAtomicWriteU32(&g_idTscDeltaInitiator, NIL_RTCPUID);
     
    73147339}
    73157340
     7341
    73167342/**
    73177343 * Resume built-in keyboard on MacBook Air and Pro hosts.
     
    73297355}
    73307356
     7357
     7358/**
     7359 * Service a TSC-delta measurement request.
     7360 *
     7361 * @returns VBox status code.
     7362 * @param   pDevExt             Pointer to the device instance data.
     7363 * @param   pReq                Pointer to the TSC-delta measurement request.
     7364 */
     7365static int supdrvIOCtl_TscDeltaMeasure(PSUPDRVDEVEXT pDevExt, PSUPTSCDELTAMEASURE pReq)
     7366{
     7367    PSUPGLOBALINFOPAGE pGip;
     7368    RTCPUID            idCpuWorker;
     7369    int                rc = VERR_CPU_NOT_FOUND;
     7370    int16_t            cTries;
     7371    RTMSINTERVAL       cMsWaitRetry;
     7372    uint16_t           iCpu;
     7373
     7374    /*
     7375     * Validate.
     7376     */
     7377    AssertReturn(pDevExt, VERR_INVALID_PARAMETER);
     7378    AssertReturn(pReq, VERR_INVALID_PARAMETER);
     7379    AssertReturn(pDevExt->pGip, VERR_INVALID_PARAMETER);
     7380    idCpuWorker = pReq->u.In.idCpu;
     7381    if (idCpuWorker == NIL_RTCPUID)
     7382        return VERR_INVALID_CPU_ID;
     7383
     7384#ifdef SUPDRV_USE_TSC_DELTA_THREAD
     7385    if (pReq->u.In.fAsync)
     7386    {
     7387        /** @todo Async. doesn't implement options like retries, waiting. We'll need
     7388         *        to pass those options to the thread somehow and implement it in the
     7389         *        thread. Check if anyone uses/needs fAsync before implementing this. */
     7390        RTCpuSetAdd(&pDevExt->TscDeltaCpuSet, idCpu);
     7391        RTSpinlockAcquire(pDevExt->hTscDeltaSpinlock);
     7392        if (   pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Listening
     7393            || pDevExt->enmTscDeltaState == kSupDrvTscDeltaState_Measuring)
     7394        {
     7395            pDevExt->enmTscDeltaState = kSupDrvTscDeltaState_WaitAndMeasure;
     7396        }
     7397        RTSpinlockRelease(pDevExt->hTscDeltaSpinlock);
     7398        RTThreadUserSignal(pDevExt->hTscDeltaThread);
     7399        return VINF_SUCCESS;
     7400    }
     7401#endif
     7402
     7403    cTries       = RT_MAX(pReq->u.In.cRetries + 1, 10);
     7404    cMsWaitRetry = RT_MAX(pReq->u.In.cMsWaitRetry, 5);
     7405    pGip = pDevExt->pGip;
     7406    for (iCpu = 0; iCpu < pGip->cCpus; iCpu++)
     7407    {
     7408        PSUPGIPCPU pGipCpuWorker = &pGip->aCPUs[iCpu];
     7409        if (pGipCpuWorker->idCpu == idCpuWorker)
     7410        {
     7411            if (   pGipCpuWorker->i64TSCDelta != INT64_MAX
     7412                && !pReq->u.In.fForce)
     7413                return VINF_SUCCESS;
     7414
     7415            while (!cTries--)
     7416            {
     7417                rc = supdrvMeasureTscDeltaOne(pDevExt, iCpu);
     7418                if (RT_SUCCESS(rc))
     7419                {
     7420                    Assert(pGipCpuWorker->i64TSCDelta != INT64_MAX);
     7421                    break;
     7422                }
     7423
     7424                if (cMsWaitRetry)
     7425                    RTThreadSleep(cMsWaitRetry);
     7426            }
     7427
     7428            break;
     7429        }
     7430    }
     7431    return rc;
     7432}
     7433
  • trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h

    r53002 r53063  
    215215 *          - (none).
    216216 */
    217 #define SUPDRV_IOC_VERSION                              0x001b0000
     217#define SUPDRV_IOC_VERSION                              0x001b0001
    218218
    219219/** SUP_IOCTL_COOKIE. */
     
    14711471
    14721472
     1473/** @name SUP_IOCTL_TSC_DELTA_MEASURE
     1474 * Measure the TSC-delta between the specified CPU and the master TSC.
     1475 *
     1476 * @{
     1477 */
     1478#define SUP_IOCTL_TSC_DELTA_MEASURE                     SUP_CTL_CODE_SIZE(36, SUP_IOCTL_TSC_DELTA_MEASURE_SIZE)
     1479#define SUP_IOCTL_TSC_DELTA_MEASURE_SIZE                sizeof(SUPTSCDELTAMEASURE)
     1480#define SUP_IOCTL_TSC_DELTA_MEASURE_SIZE_IN             sizeof(SUPTSCDELTAMEASURE)
     1481#define SUP_IOCTL_TSC_DELTA_MEASURE_SIZE_OUT            sizeof(SUPREQHDR)
     1482typedef struct SUPTSCDELTAMEASURE
     1483{
     1484    /** The header. */
     1485    SUPREQHDR               Hdr;
     1486
     1487    /** Input/output union. */
     1488    union
     1489    {
     1490        struct
     1491        {
     1492            /** Which CPU to take the TSC-delta measurement for. */
     1493            RTCPUID         idCpu;
     1494            /** Number of times to retry on failure (specify 0 for default). */
     1495            uint8_t         cRetries;
     1496            /** Number of milliseconds to wait before each retry. */
     1497            uint8_t         cMsWaitRetry;
     1498            /** Whether to force taking a measurement if one exists already. */
     1499            bool            fForce;
     1500            /** Whether to do the measurement asynchronously (if possible). */
     1501            bool            fAsync;
     1502            /** Padding for future. */
     1503            uint64_t        auPadding[3];
     1504        } In;
     1505    } u;
     1506} SUPTSCDELTAMEASURE, *PSUPTSCDELTAMEASURE;
     1507AssertCompileMemberAlignment(SUPTSCDELTAMEASURE, u, 8);
     1508/** @} */
     1509
     1510
    14731511#pragma pack()                          /* paranoia */
    14741512
  • trunk/src/VBox/HostDrivers/Support/SUPLib.cpp

    r53059 r53063  
    280280        CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;
    281281        const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001b0000
    282                                    ? 0x001b0000
     282                                   ? 0x001b0001
    283283                                   : SUPDRV_IOC_VERSION & 0xffff0000;
    284284        CookieReq.u.In.u32MinVersion = uMinVersion;
     
    21762176}
    21772177
     2178
     2179SUPR3DECL(int) SUPR3TscDeltaMeasure(RTCPUID idCpu, bool fAsync, bool fForce, uint8_t cRetries, uint8_t cMsWaitRetry)
     2180{
     2181    SUPTSCDELTAMEASURE Req;
     2182    Req.Hdr.u32Cookie        = g_u32Cookie;
     2183    Req.Hdr.u32SessionCookie = g_u32SessionCookie;
     2184    Req.Hdr.cbIn             = SUP_IOCTL_TSC_DELTA_MEASURE_SIZE_IN;
     2185    Req.Hdr.cbOut            = SUP_IOCTL_TSC_DELTA_MEASURE_SIZE_OUT;
     2186    Req.Hdr.fFlags           = SUPREQHDR_FLAGS_DEFAULT;
     2187    Req.Hdr.rc               = VERR_INTERNAL_ERROR;
     2188
     2189    Req.u.In.cRetries     = cRetries;
     2190    Req.u.In.fAsync       = fAsync;
     2191    Req.u.In.fForce       = fForce;
     2192    Req.u.In.idCpu        = idCpu;
     2193    Req.u.In.cMsWaitRetry = cMsWaitRetry;
     2194
     2195    int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TSC_DELTA_MEASURE, &Req, SUP_IOCTL_TSC_DELTA_MEASURE_SIZE);
     2196    if (RT_SUCCESS(rc))
     2197        rc = Req.Hdr.rc;
     2198    return rc;
     2199}
     2200
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