void testCreateFileSimple(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; SHFLCREATERESULT Result; int rc; RTTestSub(hTest, "Create file simple"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, NULL, &Result); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, !strcmp(testRTFileOpenName, "/test/mapping/test/file"), (hTest, "pszFilename=%s\n", testRTFileOpenName)); RTTEST_CHECK_MSG(hTest, testRTFileOpenFlags == 0x181, (hTest, "fOpen=%llu\n", LLUIFY(testRTFileOpenFlags))); RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED, (hTest, "Result=%d\n", (int) Result)); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); }
void testFSInfoQuerySetEndOfFile(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; const RTFOFF cbNew = 50000; SHFLFSOBJINFO Info; SHFLHANDLE Handle; int rc; RTTestSub(hTest, "Set end of file position"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); RT_ZERO(Info); Info.cbObject = cbNew; rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_SIZE, sizeof(Info), &Info); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, testRTFileSetSizeFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileSetSizeFile))); RTTEST_CHECK_MSG(hTest, testRTFileSetSizeSize == cbNew, (hTest, "Size=%llu\n", LLUIFY(testRTFileSetSizeSize))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); }
void testReadFileSimple(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; SHFLHANDLE Handle; const char *pcszReadData = "Data to read"; char acBuf[sizeof(pcszReadData) + 10]; uint32_t cbRead; int rc; RTTestSub(hTest, "Read file simple"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); testRTFileReadData = pcszReadData; rc = readFile(&svcTable, Root, Handle, 0, strlen(pcszReadData) + 1, &cbRead, acBuf, (uint32_t)sizeof(acBuf)); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, !strncmp(acBuf, pcszReadData, sizeof(acBuf)), (hTest, "pvBuf=%.*s\n", sizeof(acBuf), acBuf)); RTTEST_CHECK_MSG(hTest, cbRead == strlen(pcszReadData) + 1, (hTest, "cbRead=%llu\n", LLUIFY(cbRead))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); }
/* Event rate throttling timer to emulate the auxiliary device sampling rate. */ static DECLCALLBACK(void) ps2mThrottleTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) { PPS2M pThis = (PS2M *)pvUser; NOREF(pDevIns); uint32_t uHaveEvents; /* Grab the lock to avoid races with PutEvent(). */ int rc = PDMCritSectEnter(pThis->pCritSectR3, VERR_SEM_BUSY); AssertReleaseRC(rc); #if 0 /* If the input queue is not empty, restart the timer. */ #else /* If more movement is accumulated, report it and restart the timer. */ uHaveEvents = pThis->iAccumX | pThis->iAccumY | pThis->iAccumZ | pThis->fAccumB; LogFlowFunc(("Have%s events\n", uHaveEvents ? "" : " no")); if (uHaveEvents) #endif { ps2mReportAccumulatedEvents(pThis); TMTimerSetMillies(pThis->CTX_SUFF(pThrottleTimer), pThis->uThrottleDelay); } else pThis->fThrottleActive = false; PDMCritSectLeave(pThis->pCritSectR3); }
void testWriteFileSimple(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; SHFLHANDLE Handle; const char *pcszWrittenData = "Data to write"; uint32_t cbToWrite = (uint32_t)strlen(pcszWrittenData) + 1; uint32_t cbWritten; int rc; RTTestSub(hTest, "Write file simple"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); rc = writeFile(&svcTable, Root, Handle, 0, cbToWrite, &cbWritten, pcszWrittenData, cbToWrite); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, !strcmp(testRTFileWriteData, pcszWrittenData), (hTest, "pvBuf=%s\n", testRTFileWriteData)); RTTEST_CHECK_MSG(hTest, cbWritten == cbToWrite, (hTest, "cbWritten=%llu\n", LLUIFY(cbWritten))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); }
void testFlushFileSimple(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; SHFLHANDLE Handle; int rc; RTTestSub(hTest, "Flush file simple"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); rc = flushFile(&svcTable, Root, Handle); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, testRTFileFlushFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileFlushFile))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); }
/* Event rate throttling timer to emulate the auxiliary device sampling rate. */ static DECLCALLBACK(void) ps2mThrottleTimer(PPDMDEVINS pDevIns, PTMTIMER pTimer, void *pvUser) { RT_NOREF2(pDevIns, pTimer); PPS2M pThis = (PS2M *)pvUser; uint32_t uHaveEvents; /* Grab the lock to avoid races with PutEvent(). */ int rc = PDMCritSectEnter(pThis->pCritSectR3, VERR_SEM_BUSY); AssertReleaseRC(rc); #if 0 /* If the input queue is not empty, restart the timer. */ #else /* If more movement is accumulated, report it and restart the timer. */ uHaveEvents = pThis->iAccumX | pThis->iAccumY | pThis->iAccumZ | (pThis->fCurrB != pThis->fReportedB); LogFlowFunc(("Have%s events\n", uHaveEvents ? "" : " no")); if (uHaveEvents) #endif { /* Report accumulated data, poke the KBC, and start the timer. */ ps2mReportAccumulatedEvents(pThis, (GeneriQ *)&pThis->evtQ, true); KBCUpdateInterrupts(pThis->pParent); TMTimerSetMillies(pThis->CTX_SUFF(pThrottleTimer), pThis->uThrottleDelay); } else pThis->fThrottleActive = false; PDMCritSectLeave(pThis->pCritSectR3); }
void testDirListEmpty(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; PRTDIR pcDir = (PRTDIR)0x10000; SHFLHANDLE Handle; SHFLDIRINFO DirInfo; uint32_t cFiles; int rc; RTTestSub(hTest, "List empty directory"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTDirOpenpDir = pcDir; rc = createFile(&svcTable, Root, "test/dir", SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); rc = listDir(&svcTable, Root, Handle, 0, sizeof (SHFLDIRINFO), NULL, &DirInfo, sizeof(DirInfo), 0, &cFiles); RTTEST_CHECK_RC(hTest, rc, VERR_NO_MORE_FILES); RTTEST_CHECK_MSG(hTest, testRTDirReadExDir == pcDir, (hTest, "Dir=%llu\n", LLUIFY(testRTDirReadExDir))); RTTEST_CHECK_MSG(hTest, cFiles == 0, (hTest, "cFiles=%llu\n", LLUIFY(cFiles))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTDirClosepDir == pcDir, (hTest, "pDir=%llu\n", LLUIFY(testRTDirClosepDir))); }
DECLINLINE(void) rtThreadLockRD(void) { if (g_ThreadRWSem == NIL_RTSEMRW) rtThreadInit(); int rc = RTSemRWRequestRead(g_ThreadRWSem, RT_INDEFINITE_WAIT); AssertReleaseRC(rc); }
void testCreateDirSimple(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; PRTDIR pcDir = (PRTDIR)0x10000; SHFLCREATERESULT Result; int rc; RTTestSub(hTest, "Create directory simple"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTDirOpenpDir = pcDir; rc = createFile(&svcTable, Root, "test/dir", SHFL_CF_DIRECTORY | SHFL_CF_ACCESS_READ, NULL, &Result); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, !strcmp(testRTDirCreatePath, "/test/mapping/test/dir"), (hTest, "pszPath=%s\n", testRTDirCreatePath)); RTTEST_CHECK_MSG(hTest, !strcmp(testRTDirOpenName, "/test/mapping/test/dir"), (hTest, "pszFilename=%s\n", testRTDirOpenName)); RTTEST_CHECK_MSG(hTest, Result == SHFL_FILE_CREATED, (hTest, "Result=%d\n", (int) Result)); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTDirClosepDir == pcDir, (hTest, "pDir=%llu\n", LLUIFY(testRTDirClosepDir))); }
/** @todo Mappings should be automatically removed by unloading the service, * but unloading is currently a no-op! */ static void unmapAndRemoveMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable, SHFLROOT root, const char *pcszFolderName) { VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_UNMAP_FOLDER, SHFL_CPARMS_REMOVE_MAPPING)]; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; struct TESTSHFLSTRING FolderName; int rc; aParms[0].setUInt32(root); psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_UNMAP_FOLDER, SHFL_CPARMS_UNMAP_FOLDER, aParms); AssertReleaseRC(callHandle.rc); fillTestShflString(&FolderName, pcszFolderName); aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String) + FolderName.string.u16Size); rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_REMOVE_MAPPING, SHFL_CPARMS_REMOVE_MAPPING, aParms); AssertReleaseRC(rc); }
/** @interface_method_impl{PDMPCIRAWHLPR3,pfnGetR0Helpers} */ static DECLCALLBACK(PCPDMPCIRAWHLPR0) pdmR3PciRawHlp_GetR0Helpers(PPDMDEVINS pDevIns) { PDMDEV_ASSERT_DEVINS(pDevIns); VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3); PCPDMHPETHLPR0 pR0Helpers = NIL_RTR0PTR; int rc = PDMR3LdrGetSymbolR0(pDevIns->Internal.s.pVMR3, NULL, "g_pdmR0PciRawHlp", &pR0Helpers); AssertReleaseRC(rc); AssertRelease(pR0Helpers); LogFlow(("pdmR3PciRawHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers)); return pR0Helpers; }
/** @interface_method_impl{PDMHPETHLPR3,pfnGetRCHelpers} */ static DECLCALLBACK(PCPDMHPETHLPRC) pdmR3HpetHlp_GetRCHelpers(PPDMDEVINS pDevIns) { PDMDEV_ASSERT_DEVINS(pDevIns); VM_ASSERT_EMT(pDevIns->Internal.s.pVMR3); RTRCPTR pRCHelpers = 0; int rc = PDMR3LdrGetSymbolRC(pDevIns->Internal.s.pVMR3, NULL, "g_pdmRCHpetHlp", &pRCHelpers); AssertReleaseRC(rc); AssertRelease(pRCHelpers); LogFlow(("pdmR3HpetHlp_GetGCHelpers: caller='%s'/%d: returns %RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers)); return pRCHelpers; }
/** @interface_method_impl{PDMIOAPICHLPR3,pfnGetR0Helpers} */ static DECLCALLBACK(PCPDMIOAPICHLPR0) pdmR3IoApicHlp_GetR0Helpers(PPDMDEVINS pDevIns) { PDMDEV_ASSERT_DEVINS(pDevIns); PVM pVM = pDevIns->Internal.s.pVMR3; VM_ASSERT_EMT(pVM); PCPDMIOAPICHLPR0 pR0Helpers = 0; int rc = PDMR3LdrGetSymbolR0(pVM, NULL, "g_pdmR0IoApicHlp", &pR0Helpers); AssertReleaseRC(rc); AssertRelease(pR0Helpers); LogFlow(("pdmR3IoApicHlp_GetR0Helpers: caller='%s'/%d: returns %RHv\n", pDevIns->pReg->szName, pDevIns->iInstance, pR0Helpers)); return pR0Helpers; }
static SHFLROOT initWithWritableMapping(RTTEST hTest, VBOXHGCMSVCFNTABLE *psvcTable, VBOXHGCMSVCHELPERS *psvcHelpers, const char *pcszFolderName, const char *pcszMapping) { VBOXHGCMSVCPARM aParms[RT_MAX(SHFL_CPARMS_ADD_MAPPING, SHFL_CPARMS_MAP_FOLDER)]; struct TESTSHFLSTRING FolderName; struct TESTSHFLSTRING Mapping; VBOXHGCMCALLHANDLE_TYPEDEF callHandle = { VINF_SUCCESS }; int rc; initTable(psvcTable, psvcHelpers); AssertReleaseRC(VBoxHGCMSvcLoad(psvcTable)); AssertRelease( psvcTable->pvService = RTTestGuardedAllocTail(hTest, psvcTable->cbClient)); RT_BZERO(psvcTable->pvService, psvcTable->cbClient); fillTestShflString(&FolderName, pcszFolderName); fillTestShflString(&Mapping, pcszMapping); aParms[0].setPointer(&FolderName, RT_UOFFSETOF(SHFLSTRING, String) + FolderName.string.u16Size); aParms[1].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String) + Mapping.string.u16Size); aParms[2].setUInt32(1); rc = psvcTable->pfnHostCall(psvcTable->pvService, SHFL_FN_ADD_MAPPING, SHFL_CPARMS_ADD_MAPPING, aParms); AssertReleaseRC(rc); aParms[0].setPointer(&Mapping, RT_UOFFSETOF(SHFLSTRING, String) + Mapping.string.u16Size); aParms[1].setUInt32(0); /* root */ aParms[2].setUInt32('/'); /* delimiter */ aParms[3].setUInt32(1); /* case sensitive */ psvcTable->pfnCall(psvcTable->pvService, &callHandle, 0, psvcTable->pvService, SHFL_FN_MAP_FOLDER, SHFL_CPARMS_MAP_FOLDER, aParms); AssertReleaseRC(callHandle.rc); return aParms[1].u.uint32; }
/** * @interface_method_impl{PDMIMOUSEPORT, pfnPutEvent} */ static DECLCALLBACK(int) ps2mPutEvent(PPDMIMOUSEPORT pInterface, int32_t dx, int32_t dy, int32_t dz, int32_t dw, uint32_t fButtons) { PPS2M pThis = RT_FROM_MEMBER(pInterface, PS2M, Mouse.IPort); int rc = PDMCritSectEnter(pThis->pCritSectR3, VERR_SEM_BUSY); AssertReleaseRC(rc); LogFlowFunc(("dX=%d dY=%d dZ=%d dW=%d buttons=%02X\n", dx, dy, dz, dw, fButtons)); /* NB: The PS/2 Y axis direction is inverted relative to ours. */ ps2mPutEventWorker(pThis, dx, -dy, dz, dw, fButtons); PDMCritSectLeave(pThis->pCritSectR3); return VINF_SUCCESS; }
void testLockFileSimple(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; const int64_t offLock = 50000; const uint64_t cbLock = 4000; SHFLHANDLE Handle; int rc; RTTestSub(hTest, "Simple file lock and unlock"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_SHARED); RTTEST_CHECK_RC_OK(hTest, rc); #ifdef RT_OS_WINDOWS /* Locking is a no-op elsewhere. */ RTTEST_CHECK_MSG(hTest, testRTFileLockFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileLockFile))); RTTEST_CHECK_MSG(hTest, testRTFileLockfLock == 0, (hTest, "fLock=%u\n", testRTFileLockfLock)); RTTEST_CHECK_MSG(hTest, testRTFileLockOffset == offLock, (hTest, "Offs=%llu\n", (long long) testRTFileLockOffset)); RTTEST_CHECK_MSG(hTest, testRTFileLockSize == cbLock, (hTest, "Size=%llu\n", LLUIFY(testRTFileLockSize))); #endif rc = lockFile(&svcTable, Root, Handle, offLock, cbLock, SHFL_LOCK_CANCEL); RTTEST_CHECK_RC_OK(hTest, rc); #ifdef RT_OS_WINDOWS RTTEST_CHECK_MSG(hTest, testRTFileUnlockFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileUnlockFile))); RTTEST_CHECK_MSG(hTest, testRTFileUnlockOffset == offLock, (hTest, "Offs=%llu\n", (long long) testRTFileUnlockOffset)); RTTEST_CHECK_MSG(hTest, testRTFileUnlockSize == cbLock, (hTest, "Size=%llu\n", LLUIFY(testRTFileUnlockSize))); #endif unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); }
/** @interface_method_impl{PDMPICHLPR3,pfnGetRCHelpers} */ static DECLCALLBACK(PCPDMPICHLPRC) pdmR3PicHlp_GetRCHelpers(PPDMDEVINS pDevIns) { PDMDEV_ASSERT_DEVINS(pDevIns); PVM pVM = pDevIns->Internal.s.pVMR3; VM_ASSERT_EMT(pVM); RTRCPTR pRCHelpers = NIL_RTRCPTR; if (!HMIsEnabled(pVM)) { int rc = PDMR3LdrGetSymbolRC(pVM, NULL, "g_pdmRCPicHlp", &pRCHelpers); AssertReleaseRC(rc); AssertRelease(pRCHelpers); } LogFlow(("pdmR3PicHlp_GetRCHelpers: caller='%s'/%d: returns %RRv\n", pDevIns->pReg->szName, pDevIns->iInstance, pRCHelpers)); return pRCHelpers; }
void testFSInfoQuerySetFileATime(RTTEST hTest) { VBOXHGCMSVCFNTABLE svcTable; VBOXHGCMSVCHELPERS svcHelpers; SHFLROOT Root; const RTFILE hcFile = (RTFILE) 0x10000; const int64_t ccAtimeNano = 100000; SHFLFSOBJINFO Info; SHFLHANDLE Handle; int rc; RTTestSub(hTest, "Query and set file atime"); Root = initWithWritableMapping(hTest, &svcTable, &svcHelpers, "/test/mapping", "testname"); testRTFileOpenpFile = hcFile; rc = createFile(&svcTable, Root, "/test/file", SHFL_CF_ACCESS_READ, &Handle, NULL); RTTEST_CHECK_RC_OK(hTest, rc); RT_ZERO(Info); RTTimeSpecSetNano(&testRTFileQueryInfoATime, ccAtimeNano); rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_FILE, sizeof(Info), &Info); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, testRTFileQueryInfoFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileQueryInfoFile))); RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&Info.AccessTime) == ccAtimeNano, (hTest, "ATime=%llu\n", LLUIFY(RTTimeSpecGetNano(&Info.AccessTime)))); RT_ZERO(Info); RTTimeSpecSetNano(&Info.AccessTime, ccAtimeNano); rc = sfInformation(&svcTable, Root, Handle, SHFL_INFO_SET | SHFL_INFO_FILE, sizeof(Info), &Info); RTTEST_CHECK_RC_OK(hTest, rc); RTTEST_CHECK_MSG(hTest, RTTimeSpecGetNano(&testRTFileSetTimesATime) == ccAtimeNano, (hTest, "ATime=%llu\n", LLUIFY(RTTimeSpecGetNano(&testRTFileSetTimesATime)))); unmapAndRemoveMapping(hTest, &svcTable, Root, "testname"); AssertReleaseRC(svcTable.pfnDisconnect(NULL, 0, svcTable.pvService)); RTTestGuardedFree(hTest, svcTable.pvService); RTTEST_CHECK_MSG(hTest, testRTFileCloseFile == hcFile, (hTest, "File=%llu\n", LLUIFY(testRTFileCloseFile))); }
/** * Create a new thread. * * @returns iprt status code. * @param pThread Where to store the thread handle to the new thread. (optional) * @param pfnThread The thread function. * @param pvUser User argument. * @param cbStack The size of the stack for the new thread. * Use 0 for the default stack size. * @param enmType The thread type. Used for deciding scheduling attributes * of the thread. * @param fFlags Flags of the RTTHREADFLAGS type (ORed together). * @param pszName Thread name. */ RTDECL(int) RTThreadCreate(PRTTHREAD pThread, PFNRTTHREAD pfnThread, void *pvUser, size_t cbStack, RTTHREADTYPE enmType, unsigned fFlags, const char *pszName) { int rc; PRTTHREADINT pThreadInt; LogFlow(("RTThreadCreate: pThread=%p pfnThread=%p pvUser=%p cbStack=%#x enmType=%d fFlags=%#x pszName=%p:{%s}\n", pThread, pfnThread, pvUser, cbStack, enmType, fFlags, pszName, pszName)); /* * Validate input. */ if (!VALID_PTR(pThread) && pThread) { Assert(VALID_PTR(pThread)); return VERR_INVALID_PARAMETER; } if (!VALID_PTR(pfnThread)) { Assert(VALID_PTR(pfnThread)); return VERR_INVALID_PARAMETER; } if (!pszName || !*pszName || strlen(pszName) >= RTTHREAD_NAME_LEN) { AssertMsgFailed(("pszName=%s (max len is %d because of logging)\n", pszName, RTTHREAD_NAME_LEN - 1)); return VERR_INVALID_PARAMETER; } if (fFlags & ~RTTHREADFLAGS_MASK) { AssertMsgFailed(("fFlags=%#x\n", fFlags)); return VERR_INVALID_PARAMETER; } /* * Allocate thread argument. */ pThreadInt = rtThreadAlloc(enmType, fFlags, 0, pszName); if (pThreadInt) { RTNATIVETHREAD NativeThread; pThreadInt->pfnThread = pfnThread; pThreadInt->pvUser = pvUser; pThreadInt->cbStack = cbStack; rc = rtThreadNativeCreate(pThreadInt, &NativeThread); if (RT_SUCCESS(rc)) { rtThreadInsert(pThreadInt, NativeThread); rtThreadRelease(pThreadInt); Log(("RTThreadCreate: Created thread %p (%p) %s\n", pThreadInt, NativeThread, pszName)); if (pThread) *pThread = pThreadInt; return VINF_SUCCESS; } pThreadInt->cRefs = 1; rtThreadRelease(pThreadInt); } else rc = VERR_NO_TMP_MEMORY; LogFlow(("RTThreadCreate: Failed to create thread, rc=%Rrc\n", rc)); AssertReleaseRC(rc); return rc; }
DECLINLINE(void) rtThreadUnLockRD(void) { int rc = RTSemRWReleaseRead(g_ThreadRWSem); AssertReleaseRC(rc); }
int main(int argc, char **argv) { int rcRet = 1; int rc; RTR3InitAndSUPLib(); /* * Parse input. */ if (argc <= 1) { syntax(); return 1; } bool fPowerOn = false; uint32_t u32WarpDrive = 100; /* % */ uint64_t cbMem = ~0ULL; const char *pszSavedState = NULL; const char *pszRawMem = NULL; uint64_t offRawMem = 0; const char *pszScript = NULL; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-') { /* check that it's on short form */ if (argv[i][2]) { if ( strcmp(argv[i], "--help") && strcmp(argv[i], "-help")) RTPrintf("tstAnimate: Syntax error: Unknown argument '%s'.\n", argv[i]); else syntax(); return 1; } /* check for 2nd argument */ switch (argv[i][1]) { case 'r': case 'o': case 'c': case 'm': case 'w': case 'z': if (i + 1 < argc) break; RTPrintf("tstAnimate: Syntax error: '%s' takes a 2nd argument.\n", argv[i]); return 1; } /* process argument */ switch (argv[i][1]) { case 'r': pszRawMem = argv[++i]; break; case 'z': pszSavedState = argv[++i]; break; case 'o': { rc = RTStrToUInt64Ex(argv[++i], NULL, 0, &offRawMem); if (RT_FAILURE(rc)) { RTPrintf("tstAnimate: Syntax error: Invalid offset given to -o.\n"); return 1; } break; } case 'm': { char *pszNext; rc = RTStrToUInt64Ex(argv[++i], &pszNext, 0, &cbMem); if (RT_FAILURE(rc)) { RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n"); return 1; } switch (*pszNext) { case 'G': cbMem *= _1G; pszNext++; break; case 'M': cbMem *= _1M; pszNext++; break; case 'K': cbMem *= _1K; pszNext++; break; case '\0': break; default: RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n"); return 1; } if (*pszNext) { RTPrintf("tstAnimate: Syntax error: Invalid memory size given to -m.\n"); return 1; } break; } case 's': pszScript = argv[++i]; break; case 'p': fPowerOn = true; break; case 'w': { rc = RTStrToUInt32Ex(argv[++i], NULL, 0, &u32WarpDrive); if (RT_FAILURE(rc)) { RTPrintf("tstAnimate: Syntax error: Invalid number given to -w.\n"); return 1; } break; } case 'h': case 'H': case '?': syntax(); return 1; default: RTPrintf("tstAnimate: Syntax error: Unknown argument '%s'.\n", argv[i]); return 1; } } else { RTPrintf("tstAnimate: Syntax error at arg no. %d '%s'.\n", i, argv[i]); syntax(); return 1; } } /* * Check that the basic requirements are met. */ if (pszRawMem && pszSavedState) { RTPrintf("tstAnimate: Syntax error: Either -z or -r, not both.\n"); return 1; } if (!pszRawMem && !pszSavedState) { RTPrintf("tstAnimate: Syntax error: The -r argument is compulsory.\n"); return 1; } /* * Open the files. */ RTFILE FileRawMem = NIL_RTFILE; if (pszRawMem) { rc = RTFileOpen(&FileRawMem, pszRawMem, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) { RTPrintf("tstAnimate: error: Failed to open '%s': %Rrc\n", pszRawMem, rc); return 1; } } RTFILE FileScript = NIL_RTFILE; if (pszScript) { rc = RTFileOpen(&FileScript, pszScript, RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); if (RT_FAILURE(rc)) { RTPrintf("tstAnimate: error: Failed to open '%s': %Rrc\n", pszScript, rc); return 1; } } /* * Figure the memsize if not specified. */ if (cbMem == ~0ULL) { if (FileRawMem != NIL_RTFILE) { rc = RTFileGetSize(FileRawMem, &cbMem); AssertReleaseRC(rc); cbMem -= offRawMem; cbMem &= ~(PAGE_SIZE - 1); } else { RTPrintf("tstAnimate: error: too lazy to figure out the memsize in a saved state.\n"); return 1; } } RTPrintf("tstAnimate: info: cbMem=0x%llx bytes\n", cbMem); /* * Open a release log. */ static const char * const s_apszGroups[] = VBOX_LOGGROUP_NAMES; PRTLOGGER pRelLogger; rc = RTLogCreate(&pRelLogger, RTLOGFLAGS_PREFIX_TIME_PROG, "all", "VBOX_RELEASE_LOG", RT_ELEMENTS(s_apszGroups), s_apszGroups, RTLOGDEST_FILE, "./tstAnimate.log"); if (RT_SUCCESS(rc)) RTLogRelSetDefaultInstance(pRelLogger); else RTPrintf("tstAnimate: rtLogCreateEx failed - %Rrc\n", rc); /* * Create empty VM. */ PVM pVM; rc = VMR3Create(1, NULL, NULL, NULL, cfgmR3CreateDefault, &cbMem, &pVM); if (RT_SUCCESS(rc)) { /* * Load memory. */ if (FileRawMem != NIL_RTFILE) rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)loadMem, 3, pVM, FileRawMem, &offRawMem); else rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)SSMR3Load, 7, pVM, pszSavedState, (uintptr_t)NULL /*pStreamOps*/, (uintptr_t)NULL /*pvUser*/, SSMAFTER_DEBUG_IT, (uintptr_t)NULL /*pfnProgress*/, (uintptr_t)NULL /*pvProgressUser*/); if (RT_SUCCESS(rc)) { /* * Load register script. */ if (FileScript != NIL_RTFILE) rc = VMR3ReqCallWait(pVM, VMCPUID_ANY, (PFNRT)scriptRun, 2, pVM, FileScript); if (RT_SUCCESS(rc)) { if (fPowerOn) { /* * Adjust warpspeed? */ if (u32WarpDrive != 100) { rc = TMR3SetWarpDrive(pVM, u32WarpDrive); if (RT_FAILURE(rc)) RTPrintf("warning: TMVirtualSetWarpDrive(,%u) -> %Rrc\n", u32WarpDrive, rc); } /* * Start the thing with single stepping and stuff enabled. * (Try make sure we don't execute anything in raw mode.) */ RTPrintf("info: powering on the VM...\n"); RTLogGroupSettings(NULL, "+REM_DISAS.e.l.f"); rc = REMR3DisasEnableStepping(pVM, true); if (RT_SUCCESS(rc)) { rc = EMR3SetExecutionPolicy(pVM, EMEXECPOLICY_RECOMPILE_RING0, true); AssertReleaseRC(rc); rc = EMR3SetExecutionPolicy(pVM, EMEXECPOLICY_RECOMPILE_RING3, true); AssertReleaseRC(rc); DBGFR3Info(pVM, "cpumguest", "verbose", NULL); if (fPowerOn) rc = VMR3PowerOn(pVM); if (RT_SUCCESS(rc)) { RTPrintf("info: VM is running\n"); signal(SIGINT, SigInterrupt); while (!g_fSignaled) RTThreadSleep(1000); } else RTPrintf("error: Failed to power on the VM: %Rrc\n", rc); } else RTPrintf("error: Failed to enabled singlestepping: %Rrc\n", rc); } else { /* * Don't start it, just enter the debugger. */ RTPrintf("info: entering debugger...\n"); DBGFR3Info(pVM, "cpumguest", "verbose", NULL); signal(SIGINT, SigInterrupt); while (!g_fSignaled) RTThreadSleep(1000); } RTPrintf("info: shutting down the VM...\n"); } /* execScript complains */ } else if (FileRawMem == NIL_RTFILE) /* loadMem complains, SSMR3Load doesn't */ RTPrintf("tstAnimate: error: SSMR3Load failed: rc=%Rrc\n", rc); rcRet = RT_SUCCESS(rc) ? 0 : 1; /* * Cleanup. */ rc = VMR3Destroy(pVM); if (!RT_SUCCESS(rc)) { RTPrintf("tstAnimate: error: failed to destroy vm! rc=%Rrc\n", rc); rcRet++; } } else { RTPrintf("tstAnimate: fatal error: failed to create vm! rc=%Rrc\n", rc); rcRet++; } return rcRet; }
/* execute the switch. */ VMMR3DECL(int) VMMDoTest(PVM pVM) { #if 1 PVMCPU pVCpu = &pVM->aCpus[0]; #ifdef NO_SUPCALLR0VMM RTPrintf("NO_SUPCALLR0VMM\n"); return VINF_SUCCESS; #endif /* * Setup stack for calling VMMGCEntry(). */ RTRCPTR RCPtrEP; int rc = PDMR3LdrGetSymbolRC(pVM, VMMGC_MAIN_MODULE_NAME, "VMMGCEntry", &RCPtrEP); if (RT_SUCCESS(rc)) { RTPrintf("VMM: VMMGCEntry=%RRv\n", RCPtrEP); /* * Test various crashes which we must be able to recover from. */ vmmR3DoTrapTest(pVM, 0x3, 0, VINF_EM_DBG_HYPER_ASSERTION, 0xf0f0f0f0, "vmmGCTestTrap3_FaultEIP", "int3"); vmmR3DoTrapTest(pVM, 0x3, 1, VINF_EM_DBG_HYPER_ASSERTION, 0xf0f0f0f0, "vmmGCTestTrap3_FaultEIP", "int3 WP"); #if defined(DEBUG_bird) /* guess most people would like to skip these since they write to com1. */ vmmR3DoTrapTest(pVM, 0x8, 0, VERR_TRPM_PANIC, 0x00000000, "vmmGCTestTrap8_FaultEIP", "#DF [#PG]"); SELMR3Relocate(pVM); /* this resets the busy flag of the Trap 08 TSS */ bool f; rc = CFGMR3QueryBool(CFGMR3GetRoot(pVM), "DoubleFault", &f); #if !defined(DEBUG_bird) if (RT_SUCCESS(rc) && f) #endif { /* see triple fault warnings in SELM and VMMGC.cpp. */ vmmR3DoTrapTest(pVM, 0x8, 1, VERR_TRPM_PANIC, 0x00000000, "vmmGCTestTrap8_FaultEIP", "#DF [#PG] WP"); SELMR3Relocate(pVM); /* this resets the busy flag of the Trap 08 TSS */ } #endif vmmR3DoTrapTest(pVM, 0xd, 0, VERR_TRPM_DONT_PANIC, 0xf0f0f0f0, "vmmGCTestTrap0d_FaultEIP", "ltr #GP"); ///@todo find a better \#GP case, on intel ltr will \#PF (busy update?) and not \#GP. //vmmR3DoTrapTest(pVM, 0xd, 1, VERR_TRPM_DONT_PANIC, 0xf0f0f0f0, "vmmGCTestTrap0d_FaultEIP", "ltr #GP WP"); vmmR3DoTrapTest(pVM, 0xe, 0, VERR_TRPM_DONT_PANIC, 0x00000000, "vmmGCTestTrap0e_FaultEIP", "#PF (NULL)"); vmmR3DoTrapTest(pVM, 0xe, 1, VERR_TRPM_DONT_PANIC, 0x00000000, "vmmGCTestTrap0e_FaultEIP", "#PF (NULL) WP"); vmmR3DoTrapTest(pVM, 0xe, 2, VINF_SUCCESS, 0x00000000, NULL, "#PF w/Tmp Handler"); /* This test is no longer relevant as fs and gs are loaded with NULL selectors and we will always return to HC if a #GP occurs while returning to guest code. vmmR3DoTrapTest(pVM, 0xe, 4, VINF_SUCCESS, 0x00000000, NULL, "#PF w/Tmp Handler and bad fs"); */ /* * Set a debug register and perform a context switch. */ rc = vmmR3DoGCTest(pVM, VMMGC_DO_TESTCASE_NOP, 0); if (rc != VINF_SUCCESS) { RTPrintf("VMM: Nop test failed, rc=%Rrc not VINF_SUCCESS\n", rc); return rc; } /* a harmless breakpoint */ RTPrintf("VMM: testing hardware bp at 0x10000 (not hit)\n"); DBGFADDRESS Addr; DBGFR3AddrFromFlat(pVM, &Addr, 0x10000); RTUINT iBp0; rc = DBGFR3BpSetReg(pVM, &Addr, 0, ~(uint64_t)0, X86_DR7_RW_EO, 1, &iBp0); AssertReleaseRC(rc); rc = vmmR3DoGCTest(pVM, VMMGC_DO_TESTCASE_NOP, 0); if (rc != VINF_SUCCESS) { RTPrintf("VMM: DR0=0x10000 test failed with rc=%Rrc!\n", rc); return rc; } /* a bad one at VMMGCEntry */ RTPrintf("VMM: testing hardware bp at VMMGCEntry (hit)\n"); DBGFR3AddrFromFlat(pVM, &Addr, RCPtrEP); RTUINT iBp1; rc = DBGFR3BpSetReg(pVM, &Addr, 0, ~(uint64_t)0, X86_DR7_RW_EO, 1, &iBp1); AssertReleaseRC(rc); rc = vmmR3DoGCTest(pVM, VMMGC_DO_TESTCASE_NOP, 0); if (rc != VINF_EM_DBG_HYPER_BREAKPOINT) { RTPrintf("VMM: DR1=VMMGCEntry test failed with rc=%Rrc! expected VINF_EM_RAW_BREAKPOINT_HYPER\n", rc); return rc; } /* resume the breakpoint */ RTPrintf("VMM: resuming hyper after breakpoint\n"); CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_RF); rc = VMMR3ResumeHyper(pVM, pVCpu); if (rc != VINF_SUCCESS) { RTPrintf("VMM: failed to resume on hyper breakpoint, rc=%Rrc = KNOWN BUG\n", rc); /** @todo fix VMMR3ResumeHyper */ return rc; } /* engage the breakpoint again and try single stepping. */ RTPrintf("VMM: testing hardware bp at VMMGCEntry + stepping\n"); rc = vmmR3DoGCTest(pVM, VMMGC_DO_TESTCASE_NOP, 0); if (rc != VINF_EM_DBG_HYPER_BREAKPOINT) { RTPrintf("VMM: DR1=VMMGCEntry test failed with rc=%Rrc! expected VINF_EM_RAW_BREAKPOINT_HYPER\n", rc); return rc; } RTGCUINTREG OldPc = CPUMGetHyperEIP(pVCpu); RTPrintf("%RGr=>", OldPc); unsigned i; for (i = 0; i < 8; i++) { CPUMSetHyperEFlags(pVCpu, CPUMGetHyperEFlags(pVCpu) | X86_EFL_TF | X86_EFL_RF); rc = VMMR3ResumeHyper(pVM, pVCpu); if (rc != VINF_EM_DBG_HYPER_STEPPED) { RTPrintf("\nVMM: failed to step on hyper breakpoint, rc=%Rrc\n", rc); return rc; } RTGCUINTREG Pc = CPUMGetHyperEIP(pVCpu); RTPrintf("%RGr=>", Pc); if (Pc == OldPc) { RTPrintf("\nVMM: step failed, PC: %RGr -> %RGr\n", OldPc, Pc); return VERR_GENERAL_FAILURE; } OldPc = Pc; } RTPrintf("ok\n"); /* done, clear it */ if ( RT_FAILURE(DBGFR3BpClear(pVM, iBp0)) || RT_FAILURE(DBGFR3BpClear(pVM, iBp1))) { RTPrintf("VMM: Failed to clear breakpoints!\n"); return VERR_GENERAL_FAILURE; } rc = vmmR3DoGCTest(pVM, VMMGC_DO_TESTCASE_NOP, 0); if (rc != VINF_SUCCESS) { RTPrintf("VMM: NOP failed, rc=%Rrc\n", rc); return rc; } /* * Interrupt masking. */ RTPrintf("VMM: interrupt masking...\n"); RTStrmFlush(g_pStdOut); RTThreadSleep(250); for (i = 0; i < 10000; i++) { uint64_t StartTick = ASMReadTSC(); rc = vmmR3DoGCTest(pVM, VMMGC_DO_TESTCASE_INTERRUPT_MASKING, 0); if (rc != VINF_SUCCESS) { RTPrintf("VMM: Interrupt masking failed: rc=%Rrc\n", rc); return rc; } uint64_t Ticks = ASMReadTSC() - StartTick; if (Ticks < (SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage) / 10000)) RTPrintf("Warning: Ticks=%RU64 (< %RU64)\n", Ticks, SUPGetCpuHzFromGIP(g_pSUPGlobalInfoPage) / 10000); } /* * Interrupt forwarding. */ CPUMSetHyperState(pVCpu, pVM->vmm.s.pfnCallTrampolineRC, pVCpu->vmm.s.pbEMTStackBottomRC, 0, 0); CPUMPushHyper(pVCpu, 0); CPUMPushHyper(pVCpu, VMMGC_DO_TESTCASE_HYPER_INTERRUPT); CPUMPushHyper(pVCpu, pVM->pVMRC); CPUMPushHyper(pVCpu, 3 * sizeof(RTRCPTR)); /* stack frame size */ CPUMPushHyper(pVCpu, RCPtrEP); /* what to call */ Log(("trampoline=%x\n", pVM->vmm.s.pfnCallTrampolineRC)); /* * Switch and do da thing. */ RTPrintf("VMM: interrupt forwarding...\n"); RTStrmFlush(g_pStdOut); RTThreadSleep(250); i = 0; uint64_t tsBegin = RTTimeNanoTS(); uint64_t TickStart = ASMReadTSC(); Assert(CPUMGetHyperCR3(pVCpu) && CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu)); do { rc = SUPR3CallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN, 0); if (RT_LIKELY(rc == VINF_SUCCESS)) rc = pVCpu->vmm.s.iLastGZRc; if (RT_FAILURE(rc)) { Log(("VMM: GC returned fatal %Rra in iteration %d\n", rc, i)); VMMR3FatalDump(pVM, pVCpu, rc); return rc; } i++; if (!(i % 32)) Log(("VMM: iteration %d, esi=%08x edi=%08x ebx=%08x\n", i, CPUMGetHyperESI(pVCpu), CPUMGetHyperEDI(pVCpu), CPUMGetHyperEBX(pVCpu))); } while (rc == VINF_EM_RAW_INTERRUPT_HYPER); uint64_t TickEnd = ASMReadTSC(); uint64_t tsEnd = RTTimeNanoTS(); uint64_t Elapsed = tsEnd - tsBegin; uint64_t PerIteration = Elapsed / (uint64_t)i; uint64_t cTicksElapsed = TickEnd - TickStart; uint64_t cTicksPerIteration = cTicksElapsed / (uint64_t)i; RTPrintf("VMM: %8d interrupts in %11llu ns (%11llu ticks), %10llu ns/iteration (%11llu ticks)\n", i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration); Log(("VMM: %8d interrupts in %11llu ns (%11llu ticks), %10llu ns/iteration (%11llu ticks)\n", i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration)); /* * These forced actions are not necessary for the test and trigger breakpoints too. */ VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_TRPM_SYNC_IDT); VMCPU_FF_CLEAR(pVCpu, VMCPU_FF_SELM_SYNC_TSS); /* * Profile switching. */ RTPrintf("VMM: profiling switcher...\n"); Log(("VMM: profiling switcher...\n")); uint64_t TickMin = ~0; tsBegin = RTTimeNanoTS(); TickStart = ASMReadTSC(); Assert(CPUMGetHyperCR3(pVCpu) && CPUMGetHyperCR3(pVCpu) == PGMGetHyperCR3(pVCpu)); for (i = 0; i < 1000000; i++) { CPUMSetHyperState(pVCpu, pVM->vmm.s.pfnCallTrampolineRC, pVCpu->vmm.s.pbEMTStackBottomRC, 0, 0); CPUMPushHyper(pVCpu, 0); CPUMPushHyper(pVCpu, VMMGC_DO_TESTCASE_NOP); CPUMPushHyper(pVCpu, pVM->pVMRC); CPUMPushHyper(pVCpu, 3 * sizeof(RTRCPTR)); /* stack frame size */ CPUMPushHyper(pVCpu, RCPtrEP); /* what to call */ uint64_t TickThisStart = ASMReadTSC(); rc = SUPR3CallVMMR0Fast(pVM->pVMR0, VMMR0_DO_RAW_RUN, 0); if (RT_LIKELY(rc == VINF_SUCCESS)) rc = pVCpu->vmm.s.iLastGZRc; uint64_t TickThisElapsed = ASMReadTSC() - TickThisStart; if (RT_FAILURE(rc)) { Log(("VMM: GC returned fatal %Rra in iteration %d\n", rc, i)); VMMR3FatalDump(pVM, pVCpu, rc); return rc; } if (TickThisElapsed < TickMin) TickMin = TickThisElapsed; } TickEnd = ASMReadTSC(); tsEnd = RTTimeNanoTS(); Elapsed = tsEnd - tsBegin; PerIteration = Elapsed / (uint64_t)i; cTicksElapsed = TickEnd - TickStart; cTicksPerIteration = cTicksElapsed / (uint64_t)i; RTPrintf("VMM: %8d cycles in %11llu ns (%11lld ticks), %10llu ns/iteration (%11lld ticks) Min %11lld ticks\n", i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration, TickMin); Log(("VMM: %8d cycles in %11llu ns (%11lld ticks), %10llu ns/iteration (%11lld ticks) Min %11lld ticks\n", i, Elapsed, cTicksElapsed, PerIteration, cTicksPerIteration, TickMin)); rc = VINF_SUCCESS; } else AssertMsgFailed(("Failed to resolved VMMGC.gc::VMMGCEntry(), rc=%Rrc\n", rc)); #endif return rc; }