- Timestamp:
- Nov 22, 2013 6:11:29 PM (11 years ago)
- svn:sync-xref-src-repo-rev:
- 90859
- Location:
- trunk/src/VBox
- Files:
-
- 13 edited
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/HostDrivers/Support/Makefile.kmk
r48677 r49634 83 83 SUPR3_SOURCES = \ 84 84 SUPLib.cpp \ 85 SUPLibLdr.cpp \ 85 86 SUPLibSem.cpp \ 86 87 SUPLibTracerA.asm \ -
trunk/src/VBox/HostDrivers/Support/SUPDrv.c
r49622 r49634 125 125 static int supdrvIOCtl_CallServiceModule(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPCALLSERVICE pReq); 126 126 static int supdrvIOCtl_LoggerSettings(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, PSUPLOGGERSETTINGS pReq); 127 static int supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq); 127 128 static int supdrvGipCreate(PSUPDRVDEVEXT pDevExt); 128 129 static void supdrvGipDestroy(PSUPDRVDEVEXT pDevExt); … … 1891 1892 } 1892 1893 1894 case SUP_CTL_CODE_NO_SIZE(SUP_IOCTL_MSR_PROBER): 1895 { 1896 /* validate */ 1897 PSUPMSRPROBER pReq = (PSUPMSRPROBER)pReqHdr; 1898 REQ_CHECK_SIZES(SUP_IOCTL_MSR_PROBER); 1899 REQ_CHECK_EXPR(SUP_IOCTL_MSR_PROBER, 1900 pReq->u.In.enmOp > SUPMSRPROBEROP_INVALID && pReq->u.In.enmOp < SUPMSRPROBEROP_END); 1901 1902 pReqHdr->rc = supdrvIOCtl_MsrProber(pDevExt, pReq); 1903 return 0; 1904 } 1905 1906 1893 1907 default: 1894 1908 Log(("Unknown IOCTL %#lx\n", (long)uIOCtl)); … … 5137 5151 5138 5152 /** 5153 * Implements the MSR prober operations. 5154 * 5155 * @returns VBox status code. 5156 * @param pDevExt The device extension. 5157 * @param pReq The request. 5158 */ 5159 static int supdrvIOCtl_MsrProber(PSUPDRVDEVEXT pDevExt, PSUPMSRPROBER pReq) 5160 { 5161 #ifdef SUPDRV_WITH_MSR_PROBER 5162 RTCPUID const idCpu = pReq->u.In.idCpu == UINT32_MAX ? NIL_RTCPUID : pReq->u.In.idCpu; 5163 int rc; 5164 5165 switch (pReq->u.In.enmOp) 5166 { 5167 case SUPMSRPROBEROP_READ: 5168 { 5169 uint64_t uValue; 5170 rc = supdrvOSMsrProberRead(pReq->u.In.uMsr, idCpu, &uValue); 5171 if (RT_SUCCESS(rc)) 5172 { 5173 pReq->u.Out.uResults.Read.uValue = uValue; 5174 pReq->u.Out.uResults.Read.fGp = false; 5175 } 5176 else if (rc == VERR_ACCESS_DENIED) 5177 { 5178 pReq->u.Out.uResults.Read.uValue = 0; 5179 pReq->u.Out.uResults.Read.fGp = true; 5180 rc = VINF_SUCCESS; 5181 } 5182 break; 5183 } 5184 5185 case SUPMSRPROBEROP_WRITE: 5186 rc = supdrvOSMsrProberWrite(pReq->u.In.uMsr, idCpu, pReq->u.In.uArgs.Write.uToWrite); 5187 if (RT_SUCCESS(rc)) 5188 pReq->u.Out.uResults.Write.fGp = false; 5189 else if (rc == VERR_ACCESS_DENIED) 5190 { 5191 pReq->u.Out.uResults.Read.fGp = true; 5192 rc = VINF_SUCCESS; 5193 } 5194 break; 5195 5196 case SUPMSRPROBEROP_MODIFY: 5197 case SUPMSRPROBEROP_MODIFY_FASTER: 5198 rc = supdrvOSMsrProberModify(idCpu, pReq); 5199 break; 5200 5201 default: 5202 return VERR_INVALID_FUNCTION; 5203 } 5204 return rc; 5205 #else 5206 return VERR_NOT_IMPLEMENTED; 5207 #endif 5208 } 5209 5210 5211 5212 /** 5139 5213 * Creates the GIP. 5140 5214 * -
trunk/src/VBox/HostDrivers/Support/SUPDrvIOC.h
r44528 r49634 102 102 #define SUP_IOCTL_FAST_DO_RAW_RUN SUP_CTL_CODE_FAST(64) 103 103 /** Fast path IOCtl: VMMR0_DO_HM_RUN */ 104 #define SUP_IOCTL_FAST_DO_HM_RUN SUP_CTL_CODE_FAST(65)104 #define SUP_IOCTL_FAST_DO_HM_RUN SUP_CTL_CODE_FAST(65) 105 105 /** Just a NOP call for profiling the latency of a fast ioctl call to VMMR0. */ 106 106 #define SUP_IOCTL_FAST_DO_NOP SUP_CTL_CODE_FAST(66) … … 194 194 * - Remove RTSpinlockReleaseNoInts. 195 195 */ 196 #define SUPDRV_IOC_VERSION 0x001a000 5196 #define SUPDRV_IOC_VERSION 0x001a0006 197 197 198 198 /** SUP_IOCTL_COOKIE. */ … … 1333 1333 1334 1334 1335 /** @name SUP_IOCTL_MSR_PROBER 1336 * MSR probing interface, not available in normal builds. 1337 * 1338 * @{ 1339 */ 1340 #define SUP_IOCTL_MSR_PROBER SUP_CTL_CODE_SIZE(34, SUP_IOCTL_MSR_PROBER_SIZE) 1341 #define SUP_IOCTL_MSR_PROBER_SIZE sizeof(SUPMSRPROBER) 1342 #define SUP_IOCTL_MSR_PROBER_SIZE_IN sizeof(SUPMSRPROBER) 1343 #define SUP_IOCTL_MSR_PROBER_SIZE_OUT sizeof(SUPMSRPROBER) 1344 1345 typedef enum SUPMSRPROBEROP 1346 { 1347 SUPMSRPROBEROP_INVALID = 0, /**< The customary invalid zero value. */ 1348 SUPMSRPROBEROP_READ, /**< Read an MSR. */ 1349 SUPMSRPROBEROP_WRITE, /**< Write a value to an MSR (use with care!). */ 1350 SUPMSRPROBEROP_MODIFY, /**< Read-modify-restore-flushall. */ 1351 SUPMSRPROBEROP_MODIFY_FASTER, /**< Read-modify-restore, skip the flushing. */ 1352 SUPMSRPROBEROP_END, /**< End of valid values. */ 1353 SUPMSRPROBEROP_32BIT_HACK = 0x7fffffff /**< The customary 32-bit type hack. */ 1354 } SUPMSRPROBEROP; 1355 1356 typedef struct SUPMSRPROBER 1357 { 1358 /** The header. */ 1359 SUPREQHDR Hdr; 1360 1361 /** Input/output union. */ 1362 union 1363 { 1364 /** Inputs. */ 1365 struct 1366 { 1367 /** The operation. */ 1368 SUPMSRPROBEROP enmOp; 1369 /** The MSR to test. */ 1370 uint32_t uMsr; 1371 /** The CPU to perform the operation on. 1372 * Use UINT32_MAX to indicate that any CPU will do. */ 1373 uint32_t idCpu; 1374 /** Alignment padding. */ 1375 uint32_t u32Padding; 1376 /** Operation specific arguments. */ 1377 union 1378 { 1379 /* SUPMSRPROBEROP_READ takes no extra arguments. */ 1380 1381 /** For SUPMSRPROBEROP_WRITE. */ 1382 struct 1383 { 1384 /** The value to write. */ 1385 uint64_t uToWrite; 1386 } Write; 1387 1388 /** For SUPMSRPROBEROP_MODIFY and SUPMSRPROBEROP_MODIFY_FASTER. */ 1389 struct 1390 { 1391 /** The value to AND the current MSR value with to construct the value to 1392 * write. This applied first. */ 1393 uint64_t fAndMask; 1394 /** The value to OR the result of the above mentioned AND operation with 1395 * attempting to modify the MSR. */ 1396 uint64_t fOrMask; 1397 } Modify; 1398 1399 /** Reserve space for the future.. */ 1400 uint64_t auPadding[3]; 1401 } uArgs; 1402 } In; 1403 1404 /** Outputs. */ 1405 struct 1406 { 1407 /** Operation specific results. */ 1408 union 1409 { 1410 /** For SUPMSRPROBEROP_READ. */ 1411 struct 1412 { 1413 /** The value we've read. */ 1414 uint64_t uValue; 1415 /** Set if we GPed while reading it. */ 1416 bool fGp; 1417 } Read; 1418 1419 /** For SUPMSRPROBEROP_WRITE. */ 1420 struct 1421 { 1422 /** Set if we GPed while writing it. */ 1423 bool fGp; 1424 } Write; 1425 1426 /** For SUPMSRPROBEROP_MODIFY and SUPMSRPROBEROP_MODIFY_FASTER. */ 1427 SUPMSRPROBERMODIFYRESULT Modify; 1428 1429 /** Size padding/aligning. */ 1430 uint64_t auPadding[5]; 1431 } uResults; 1432 } Out; 1433 } u; 1434 } SUPMSRPROBER, *PSUPMSRPROBER; 1435 AssertCompileMemberAlignment(SUPMSRPROBER, u, 8); 1436 AssertCompileMemberAlignment(SUPMSRPROBER, u.In.uArgs, 8); 1437 AssertCompileMembersSameSizeAndOffset(SUPMSRPROBER, u.In, SUPMSRPROBER, u.Out); 1438 /** @} */ 1439 1440 1335 1441 #pragma pack() /* paranoia */ 1336 1442 -
trunk/src/VBox/HostDrivers/Support/SUPDrvInternal.h
r47537 r49634 209 209 ( VALID_PTR(pDevExt)\ 210 210 && pDevExt->u32Cookie == BIRD) 211 212 213 /** @def SUPDRV_WITH_MSR_PROBER 214 * Enables the SUP_IOCTL_MSR_PROBER function. 215 * By default, only enabled in DEBUG builds as it's a sensitive feature. 216 */ 217 #if defined(DEBUG) && !defined(SUPDRV_WITH_MSR_PROBER) && !defined(SUPDRV_WITHOUT_MSR_PROBER) 218 # define SUPDRV_WITH_MSR_PROBER 219 #endif 220 221 /** @def SUPDRV_WITHOUT_MSR_PROBER 222 * Executive overide for disabling the SUP_IOCTL_MSR_PROBER function. 223 */ 224 #ifdef SUPDRV_WITHOUT_MSR_PROBER 225 # undef SUPDRV_WITH_MSR_PROBER 226 #endif 211 227 212 228 … … 685 701 686 702 703 #ifdef SUPDRV_WITH_MSR_PROBER 704 705 /** 706 * Tries to read an MSR. 707 * 708 * @returns One of the listed VBox status codes. 709 * @retval VINF_SUCCESS if read successfully, value in *puValue. 710 * @retval VERR_ACCESS_DENIED if we couldn't read it (GP). 711 * @retval VERR_NOT_SUPPORTED if not supported. 712 * 713 * @param uMsr The MSR to read from. 714 * @param idCpu The CPU to read the MSR on. NIL_RTCPUID 715 * indicates any suitable CPU. 716 * @param puValue Where to return the value. 717 */ 718 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue); 719 720 /** 721 * Tries to write an MSR. 722 * 723 * @returns One of the listed VBox status codes. 724 * @retval VINF_SUCCESS if written successfully. 725 * @retval VERR_ACCESS_DENIED if we couldn't write the value to it (GP). 726 * @retval VERR_NOT_SUPPORTED if not supported. 727 * 728 * @param uMsr The MSR to write to. 729 * @param idCpu The CPU to write the MSR on. NIL_RTCPUID 730 * indicates any suitable CPU. 731 * @param uValue The value to write. 732 */ 733 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue); 734 735 /** 736 * Tries to modify an MSR value. 737 * 738 * @returns One of the listed VBox status codes. 739 * @retval VINF_SUCCESS if succeeded. 740 * @retval VERR_NOT_SUPPORTED if not supported. 741 * 742 * @param idCpu The CPU to modify the MSR on. NIL_RTCPUID 743 * indicates any suitable CPU. 744 * @param pReq The request packet with input arguments and 745 * where to store the results. 746 */ 747 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq); 748 749 #endif /* SUPDRV_WITH_MSR_PROBER */ 750 751 687 752 /******************************************************************************* 688 753 * Shared Functions * -
trunk/src/VBox/HostDrivers/Support/SUPLib.cpp
r49039 r49634 68 68 #include <iprt/x86.h> 69 69 70 #include "SUPDrvIOC.h" 70 71 #include "SUPLibInternal.h" 71 #include "SUPDrvIOC.h"72 72 73 73 … … 117 117 DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage; 118 118 /** Address of the ring-0 mapping of the GIP. */ 119 static PSUPGLOBALINFOPAGEg_pSUPGlobalInfoPageR0;119 PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPageR0; 120 120 /** The physical address of the GIP. */ 121 121 static RTHCPHYS g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS; … … 128 128 PSUPDRVSESSION g_pSession; 129 129 /** R0 SUP Functions used for resolving referenced to the SUPR0 module. */ 130 static PSUPQUERYFUNCS g_pFunctions;130 PSUPQUERYFUNCS g_pSupFunctions; 131 131 132 132 /** VMMR0 Load Address. */ … … 135 135 static bool g_fSupportsPageAllocNoKernel = true; 136 136 /** Fake mode indicator. (~0 at first, 0 or 1 after first test) */ 137 static uint32_t g_u32FakeMode = ~0;137 uint32_t g_uSupFakeMode = ~0; 138 138 139 139 … … 248 248 * we haven't ported the support driver to. 249 249 */ 250 if (g_u 32FakeMode == ~0U)250 if (g_uSupFakeMode == ~0U) 251 251 { 252 252 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE"); 253 253 if (psz && !strcmp(psz, "fake")) 254 ASMAtomicCmpXchgU32(&g_u 32FakeMode, 1, ~0U);254 ASMAtomicCmpXchgU32(&g_uSupFakeMode, 1, ~0U); 255 255 else 256 ASMAtomicCmpXchgU32(&g_u 32FakeMode, 0, ~0U);257 } 258 if (RT_UNLIKELY(g_u 32FakeMode))256 ASMAtomicCmpXchgU32(&g_uSupFakeMode, 0, ~0U); 257 } 258 if (RT_UNLIKELY(g_uSupFakeMode)) 259 259 return supInitFake(ppSession); 260 260 … … 353 353 g_u32SessionCookie = CookieReq.u.Out.u32SessionCookie; 354 354 g_pSession = CookieReq.u.Out.pSession; 355 g_p Functions= pFuncsReq;355 g_pSupFunctions = pFuncsReq; 356 356 if (ppSession) 357 357 *ppSession = CookieReq.u.Out.pSession; … … 505 505 506 506 /* fake r0 functions. */ 507 g_p Functions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));508 if (g_p Functions)509 { 510 g_p Functions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);511 memcpy(&g_p Functions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));512 g_pSession = (PSUPDRVSESSION)(void *)g_p Functions;507 g_pSupFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions))); 508 if (g_pSupFunctions) 509 { 510 g_pSupFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions); 511 memcpy(&g_pSupFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions)); 512 g_pSession = (PSUPDRVSESSION)(void *)g_pSupFunctions; 513 513 if (ppSession) 514 514 *ppSession = g_pSession; … … 524 524 } 525 525 526 RTMemFree(g_p Functions);527 g_p Functions = NULL;526 RTMemFree(g_pSupFunctions); 527 g_pSupFunctions = NULL; 528 528 } 529 529 return VERR_NO_MEMORY; … … 574 574 { 575 575 /* fake */ 576 if (RT_UNLIKELY(g_u 32FakeMode))576 if (RT_UNLIKELY(g_uSupFakeMode)) 577 577 #ifdef RT_ARCH_AMD64 578 578 return SUPPAGINGMODE_AMD64_GLOBAL_NX; … … 640 640 641 641 /* fake */ 642 if (RT_UNLIKELY(g_u 32FakeMode))642 if (RT_UNLIKELY(g_uSupFakeMode)) 643 643 return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr); 644 644 … … 731 731 SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0) 732 732 { 733 if (RT_UNLIKELY(g_u 32FakeMode))733 if (RT_UNLIKELY(g_uSupFakeMode)) 734 734 return VINF_SUCCESS; 735 735 … … 755 755 756 756 /* fake */ 757 if (RT_UNLIKELY(g_u 32FakeMode))757 if (RT_UNLIKELY(g_uSupFakeMode)) 758 758 return VERR_NOT_SUPPORTED; 759 759 … … 956 956 957 957 /* fake */ 958 if (RT_UNLIKELY(g_u 32FakeMode))958 if (RT_UNLIKELY(g_uSupFakeMode)) 959 959 { 960 960 RTHCPHYS Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024; … … 1017 1017 1018 1018 /* fake */ 1019 if (RT_UNLIKELY(g_u 32FakeMode))1019 if (RT_UNLIKELY(g_uSupFakeMode)) 1020 1020 return VINF_SUCCESS; 1021 1021 … … 1072 1072 1073 1073 /* fake */ 1074 if (RT_UNLIKELY(g_u 32FakeMode))1074 if (RT_UNLIKELY(g_uSupFakeMode)) 1075 1075 { 1076 1076 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE); … … 1165 1165 1166 1166 /* fake */ 1167 if (RT_UNLIKELY(g_u 32FakeMode))1167 if (RT_UNLIKELY(g_uSupFakeMode)) 1168 1168 return VERR_NOT_SUPPORTED; 1169 1169 … … 1202 1202 1203 1203 /* fake */ 1204 if (RT_UNLIKELY(g_u 32FakeMode))1204 if (RT_UNLIKELY(g_uSupFakeMode)) 1205 1205 return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt); 1206 1206 … … 1242 1242 1243 1243 /* fake */ 1244 if (RT_UNLIKELY(g_u 32FakeMode))1244 if (RT_UNLIKELY(g_uSupFakeMode)) 1245 1245 { 1246 1246 RTMemPageFree(pvPages, cPages * PAGE_SIZE); … … 1291 1291 1292 1292 /* fake */ 1293 if (RT_UNLIKELY(g_u 32FakeMode))1293 if (RT_UNLIKELY(g_uSupFakeMode)) 1294 1294 { 1295 1295 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE); … … 1340 1340 1341 1341 /* fake */ 1342 if (RT_UNLIKELY(g_u 32FakeMode))1342 if (RT_UNLIKELY(g_uSupFakeMode)) 1343 1343 { 1344 1344 RTMemPageFree(pv, cPages * PAGE_SIZE); … … 1375 1375 1376 1376 /* fake */ 1377 if (RT_UNLIKELY(g_u 32FakeMode))1377 if (RT_UNLIKELY(g_uSupFakeMode)) 1378 1378 { 1379 1379 *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE); … … 1443 1443 1444 1444 /* fake */ 1445 if (RT_UNLIKELY(g_u 32FakeMode))1445 if (RT_UNLIKELY(g_uSupFakeMode)) 1446 1446 { 1447 1447 RTMemPageFree(pv, cPages * PAGE_SIZE); … … 1596 1596 1597 1597 1598 SUPR3DECL(int) SUPR3LoadModule(const char *pszFilename, const char *pszModule, void **ppvImageBase, PRTERRINFO pErrInfo)1599 {1600 /*1601 * Check that the module can be trusted.1602 */1603 int rc = SUPR3HardenedVerifyPlugIn(pszFilename, pErrInfo);1604 if (RT_SUCCESS(rc))1605 {1606 rc = supLoadModule(pszFilename, pszModule, NULL, ppvImageBase);1607 if (RT_FAILURE(rc))1608 RTErrInfoSetF(pErrInfo, rc, "SUPR3LoadModule: supLoadModule returned %Rrc", rc);1609 }1610 return rc;1611 }1612 1613 1614 SUPR3DECL(int) SUPR3LoadServiceModule(const char *pszFilename, const char *pszModule,1615 const char *pszSrvReqHandler, void **ppvImageBase)1616 {1617 AssertPtrReturn(pszSrvReqHandler, VERR_INVALID_PARAMETER);1618 1619 /*1620 * Check that the module can be trusted.1621 */1622 int rc = SUPR3HardenedVerifyPlugIn(pszFilename, NULL /*pErrInfo*/);1623 if (RT_SUCCESS(rc))1624 rc = supLoadModule(pszFilename, pszModule, pszSrvReqHandler, ppvImageBase);1625 else1626 LogRel(("SUPR3LoadServiceModule: Verification of \"%s\" failed, rc=%Rrc\n", rc));1627 return rc;1628 }1629 1630 1631 /**1632 * Resolve an external symbol during RTLdrGetBits().1633 *1634 * @returns VBox status code.1635 * @param hLdrMod The loader module handle.1636 * @param pszModule Module name.1637 * @param pszSymbol Symbol name, NULL if uSymbol should be used.1638 * @param uSymbol Symbol ordinal, ~0 if pszSymbol should be used.1639 * @param pValue Where to store the symbol value (address).1640 * @param pvUser User argument.1641 */1642 static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule,1643 const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)1644 {1645 NOREF(hLdrMod); NOREF(pvUser); NOREF(uSymbol);1646 AssertPtr(pValue);1647 AssertPtr(pvUser);1648 1649 /*1650 * Only SUPR0 and VMMR0.r01651 */1652 if ( pszModule1653 && *pszModule1654 && strcmp(pszModule, "VBoxDrv.sys")1655 && strcmp(pszModule, "VMMR0.r0"))1656 {1657 AssertMsgFailed(("%s is importing from %s! (expected 'SUPR0.dll' or 'VMMR0.r0', case-sensitive)\n", pvUser, pszModule));1658 return VERR_SYMBOL_NOT_FOUND;1659 }1660 1661 /*1662 * No ordinals.1663 */1664 if (pszSymbol < (const char*)0x10000)1665 {1666 AssertMsgFailed(("%s is importing by ordinal (ord=%d)\n", pvUser, (int)(uintptr_t)pszSymbol));1667 return VERR_SYMBOL_NOT_FOUND;1668 }1669 1670 /*1671 * Lookup symbol.1672 */1673 /** @todo is this actually used??? */1674 /* skip the 64-bit ELF import prefix first. */1675 if (!strncmp(pszSymbol, RT_STR_TUPLE("SUPR0$")))1676 pszSymbol += sizeof("SUPR0$") - 1;1677 1678 /*1679 * Check the VMMR0.r0 module if loaded.1680 */1681 /** @todo call the SUPR3LoadModule caller.... */1682 /** @todo proper reference counting and such. */1683 if (g_pvVMMR0 != NIL_RTR0PTR)1684 {1685 void *pvValue;1686 if (!SUPR3GetSymbolR0((void *)g_pvVMMR0, pszSymbol, &pvValue))1687 {1688 *pValue = (uintptr_t)pvValue;1689 return VINF_SUCCESS;1690 }1691 }1692 1693 /* iterate the function table. */1694 int c = g_pFunctions->u.Out.cFunctions;1695 PSUPFUNC pFunc = &g_pFunctions->u.Out.aFunctions[0];1696 while (c-- > 0)1697 {1698 if (!strcmp(pFunc->szName, pszSymbol))1699 {1700 *pValue = (uintptr_t)pFunc->pfn;1701 return VINF_SUCCESS;1702 }1703 pFunc++;1704 }1705 1706 /*1707 * The GIP.1708 */1709 if ( pszSymbol1710 && g_pSUPGlobalInfoPage1711 && g_pSUPGlobalInfoPageR01712 && !strcmp(pszSymbol, "g_SUPGlobalInfoPage")1713 )1714 {1715 *pValue = (uintptr_t)g_pSUPGlobalInfoPageR0;1716 return VINF_SUCCESS;1717 }1718 1719 /*1720 * Symbols that are undefined by convention.1721 */1722 #ifdef RT_OS_SOLARIS1723 static const char * const s_apszConvSyms[] =1724 {1725 "", "mod_getctl",1726 "", "mod_install",1727 "", "mod_remove",1728 "", "mod_info",1729 "", "mod_miscops",1730 };1731 for (unsigned i = 0; i < RT_ELEMENTS(s_apszConvSyms); i += 2)1732 {1733 if ( !RTStrCmp(s_apszConvSyms[i], pszModule)1734 && !RTStrCmp(s_apszConvSyms[i + 1], pszSymbol))1735 {1736 *pValue = ~(uintptr_t)0;1737 return VINF_SUCCESS;1738 }1739 }1740 #endif1741 1742 /*1743 * Despair.1744 */1745 c = g_pFunctions->u.Out.cFunctions;1746 pFunc = &g_pFunctions->u.Out.aFunctions[0];1747 while (c-- > 0)1748 {1749 RTAssertMsg2Weak("%d: %s\n", g_pFunctions->u.Out.cFunctions - c, pFunc->szName);1750 pFunc++;1751 }1752 1753 AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol));1754 if (g_u32FakeMode)1755 {1756 *pValue = 0xdeadbeef;1757 return VINF_SUCCESS;1758 }1759 return VERR_SYMBOL_NOT_FOUND;1760 }1761 1762 1763 /** Argument package for supLoadModuleCalcSizeCB. */1764 typedef struct SUPLDRCALCSIZEARGS1765 {1766 size_t cbStrings;1767 uint32_t cSymbols;1768 size_t cbImage;1769 } SUPLDRCALCSIZEARGS, *PSUPLDRCALCSIZEARGS;1770 1771 /**1772 * Callback used to calculate the image size.1773 * @return VINF_SUCCESS1774 */1775 static DECLCALLBACK(int) supLoadModuleCalcSizeCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)1776 {1777 PSUPLDRCALCSIZEARGS pArgs = (PSUPLDRCALCSIZEARGS)pvUser;1778 if ( pszSymbol != NULL1779 && *pszSymbol1780 && Value <= pArgs->cbImage)1781 {1782 pArgs->cSymbols++;1783 pArgs->cbStrings += strlen(pszSymbol) + 1;1784 }1785 NOREF(hLdrMod); NOREF(uSymbol);1786 return VINF_SUCCESS;1787 }1788 1789 1790 /** Argument package for supLoadModuleCreateTabsCB. */1791 typedef struct SUPLDRCREATETABSARGS1792 {1793 size_t cbImage;1794 PSUPLDRSYM pSym;1795 char *pszBase;1796 char *psz;1797 } SUPLDRCREATETABSARGS, *PSUPLDRCREATETABSARGS;1798 1799 /**1800 * Callback used to calculate the image size.1801 * @return VINF_SUCCESS1802 */1803 static DECLCALLBACK(int) supLoadModuleCreateTabsCB(RTLDRMOD hLdrMod, const char *pszSymbol, unsigned uSymbol, RTUINTPTR Value, void *pvUser)1804 {1805 PSUPLDRCREATETABSARGS pArgs = (PSUPLDRCREATETABSARGS)pvUser;1806 if ( pszSymbol != NULL1807 && *pszSymbol1808 && Value <= pArgs->cbImage)1809 {1810 pArgs->pSym->offSymbol = (uint32_t)Value;1811 pArgs->pSym->offName = pArgs->psz - pArgs->pszBase;1812 pArgs->pSym++;1813 1814 size_t cbCopy = strlen(pszSymbol) + 1;1815 memcpy(pArgs->psz, pszSymbol, cbCopy);1816 pArgs->psz += cbCopy;1817 }1818 NOREF(hLdrMod); NOREF(uSymbol);1819 return VINF_SUCCESS;1820 }1821 1822 1823 /**1824 * Worker for SUPR3LoadModule().1825 *1826 * @returns VBox status code.1827 * @param pszFilename Name of the VMMR0 image file1828 */1829 static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase)1830 {1831 int rc;1832 1833 /*1834 * Validate input.1835 */1836 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);1837 AssertPtrReturn(pszModule, VERR_INVALID_PARAMETER);1838 AssertPtrReturn(ppvImageBase, VERR_INVALID_PARAMETER);1839 AssertReturn(strlen(pszModule) < RT_SIZEOFMEMB(SUPLDROPEN, u.In.szName), VERR_FILENAME_TOO_LONG);1840 char szAbsFilename[RT_SIZEOFMEMB(SUPLDROPEN, u.In.szFilename)];1841 rc = RTPathAbs(pszFilename, szAbsFilename, sizeof(szAbsFilename));1842 if (RT_FAILURE(rc))1843 return rc;1844 pszFilename = szAbsFilename;1845 1846 const bool fIsVMMR0 = !strcmp(pszModule, "VMMR0.r0");1847 AssertReturn(!pszSrvReqHandler || !fIsVMMR0, VERR_INTERNAL_ERROR);1848 *ppvImageBase = NULL;1849 1850 /*1851 * Open image file and figure its size.1852 */1853 RTLDRMOD hLdrMod;1854 rc = RTLdrOpen(pszFilename, 0, RTLDRARCH_HOST, &hLdrMod);1855 if (!RT_SUCCESS(rc))1856 {1857 LogRel(("SUP: RTLdrOpen failed for %s (%s)\n", pszModule, pszFilename, rc));1858 return rc;1859 }1860 1861 SUPLDRCALCSIZEARGS CalcArgs;1862 CalcArgs.cbStrings = 0;1863 CalcArgs.cSymbols = 0;1864 CalcArgs.cbImage = RTLdrSize(hLdrMod);1865 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCalcSizeCB, &CalcArgs);1866 if (RT_SUCCESS(rc))1867 {1868 const uint32_t offSymTab = RT_ALIGN_32(CalcArgs.cbImage, 8);1869 const uint32_t offStrTab = offSymTab + CalcArgs.cSymbols * sizeof(SUPLDRSYM);1870 const uint32_t cbImageWithTabs = RT_ALIGN_32(offStrTab + CalcArgs.cbStrings, 8);1871 1872 /*1873 * Open the R0 image.1874 */1875 SUPLDROPEN OpenReq;1876 OpenReq.Hdr.u32Cookie = g_u32Cookie;1877 OpenReq.Hdr.u32SessionCookie = g_u32SessionCookie;1878 OpenReq.Hdr.cbIn = SUP_IOCTL_LDR_OPEN_SIZE_IN;1879 OpenReq.Hdr.cbOut = SUP_IOCTL_LDR_OPEN_SIZE_OUT;1880 OpenReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1881 OpenReq.Hdr.rc = VERR_INTERNAL_ERROR;1882 OpenReq.u.In.cbImageWithTabs = cbImageWithTabs;1883 OpenReq.u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;1884 strcpy(OpenReq.u.In.szName, pszModule);1885 strcpy(OpenReq.u.In.szFilename, pszFilename);1886 if (!g_u32FakeMode)1887 {1888 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE);1889 if (RT_SUCCESS(rc))1890 rc = OpenReq.Hdr.rc;1891 }1892 else1893 {1894 OpenReq.u.Out.fNeedsLoading = true;1895 OpenReq.u.Out.pvImageBase = 0xef423420;1896 }1897 *ppvImageBase = (void *)OpenReq.u.Out.pvImageBase;1898 if ( RT_SUCCESS(rc)1899 && OpenReq.u.Out.fNeedsLoading)1900 {1901 /*1902 * We need to load it.1903 * Allocate memory for the image bits.1904 */1905 PSUPLDRLOAD pLoadReq = (PSUPLDRLOAD)RTMemTmpAlloc(SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));1906 if (pLoadReq)1907 {1908 /*1909 * Get the image bits.1910 */1911 rc = RTLdrGetBits(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase,1912 supLoadModuleResolveImport, (void *)pszModule);1913 1914 if (RT_SUCCESS(rc))1915 {1916 /*1917 * Get the entry points.1918 */1919 RTUINTPTR VMMR0EntryInt = 0;1920 RTUINTPTR VMMR0EntryFast = 0;1921 RTUINTPTR VMMR0EntryEx = 0;1922 RTUINTPTR SrvReqHandler = 0;1923 RTUINTPTR ModuleInit = 0;1924 RTUINTPTR ModuleTerm = 0;1925 if (fIsVMMR0)1926 {1927 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryInt", &VMMR0EntryInt);1928 if (RT_SUCCESS(rc))1929 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryFast", &VMMR0EntryFast);1930 if (RT_SUCCESS(rc))1931 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "VMMR0EntryEx", &VMMR0EntryEx);1932 }1933 else if (pszSrvReqHandler)1934 rc = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, pszSrvReqHandler, &SrvReqHandler);1935 if (RT_SUCCESS(rc))1936 {1937 int rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleInit", &ModuleInit);1938 if (RT_FAILURE(rc2))1939 ModuleInit = 0;1940 1941 rc2 = RTLdrGetSymbolEx(hLdrMod, &pLoadReq->u.In.abImage[0], (uintptr_t)OpenReq.u.Out.pvImageBase, "ModuleTerm", &ModuleTerm);1942 if (RT_FAILURE(rc2))1943 ModuleTerm = 0;1944 }1945 if (RT_SUCCESS(rc))1946 {1947 /*1948 * Create the symbol and string tables.1949 */1950 SUPLDRCREATETABSARGS CreateArgs;1951 CreateArgs.cbImage = CalcArgs.cbImage;1952 CreateArgs.pSym = (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab];1953 CreateArgs.pszBase = (char *)&pLoadReq->u.In.abImage[offStrTab];1954 CreateArgs.psz = CreateArgs.pszBase;1955 rc = RTLdrEnumSymbols(hLdrMod, 0, NULL, 0, supLoadModuleCreateTabsCB, &CreateArgs);1956 if (RT_SUCCESS(rc))1957 {1958 AssertRelease((size_t)(CreateArgs.psz - CreateArgs.pszBase) <= CalcArgs.cbStrings);1959 AssertRelease((size_t)(CreateArgs.pSym - (PSUPLDRSYM)&pLoadReq->u.In.abImage[offSymTab]) <= CalcArgs.cSymbols);1960 1961 /*1962 * Upload the image.1963 */1964 pLoadReq->Hdr.u32Cookie = g_u32Cookie;1965 pLoadReq->Hdr.u32SessionCookie = g_u32SessionCookie;1966 pLoadReq->Hdr.cbIn = SUP_IOCTL_LDR_LOAD_SIZE_IN(cbImageWithTabs);1967 pLoadReq->Hdr.cbOut = SUP_IOCTL_LDR_LOAD_SIZE_OUT;1968 pLoadReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_IN;1969 pLoadReq->Hdr.rc = VERR_INTERNAL_ERROR;1970 1971 pLoadReq->u.In.pfnModuleInit = (RTR0PTR)ModuleInit;1972 pLoadReq->u.In.pfnModuleTerm = (RTR0PTR)ModuleTerm;1973 if (fIsVMMR0)1974 {1975 pLoadReq->u.In.eEPType = SUPLDRLOADEP_VMMR0;1976 pLoadReq->u.In.EP.VMMR0.pvVMMR0 = OpenReq.u.Out.pvImageBase;1977 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryInt = (RTR0PTR)VMMR0EntryInt;1978 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryFast= (RTR0PTR)VMMR0EntryFast;1979 pLoadReq->u.In.EP.VMMR0.pvVMMR0EntryEx = (RTR0PTR)VMMR0EntryEx;1980 }1981 else if (pszSrvReqHandler)1982 {1983 pLoadReq->u.In.eEPType = SUPLDRLOADEP_SERVICE;1984 pLoadReq->u.In.EP.Service.pfnServiceReq = (RTR0PTR)SrvReqHandler;1985 pLoadReq->u.In.EP.Service.apvReserved[0] = NIL_RTR0PTR;1986 pLoadReq->u.In.EP.Service.apvReserved[1] = NIL_RTR0PTR;1987 pLoadReq->u.In.EP.Service.apvReserved[2] = NIL_RTR0PTR;1988 }1989 else1990 pLoadReq->u.In.eEPType = SUPLDRLOADEP_NOTHING;1991 pLoadReq->u.In.offStrTab = offStrTab;1992 pLoadReq->u.In.cbStrTab = (uint32_t)CalcArgs.cbStrings;1993 AssertRelease(pLoadReq->u.In.cbStrTab == CalcArgs.cbStrings);1994 pLoadReq->u.In.cbImageBits = (uint32_t)CalcArgs.cbImage;1995 pLoadReq->u.In.offSymbols = offSymTab;1996 pLoadReq->u.In.cSymbols = CalcArgs.cSymbols;1997 pLoadReq->u.In.cbImageWithTabs = cbImageWithTabs;1998 pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase;1999 if (!g_u32FakeMode)2000 {2001 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs));2002 if (RT_SUCCESS(rc))2003 rc = pLoadReq->Hdr.rc;2004 else2005 LogRel(("SUP: SUP_IOCTL_LDR_LOAD ioctl for %s (%s) failed rc=%Rrc\n", pszModule, pszFilename, rc));2006 }2007 else2008 rc = VINF_SUCCESS;2009 if ( RT_SUCCESS(rc)2010 || rc == VERR_ALREADY_LOADED /* A competing process. */2011 )2012 {2013 LogRel(("SUP: Loaded %s (%s) at %#p - ModuleInit at %RTptr and ModuleTerm at %RTptr%s\n",2014 pszModule, pszFilename, OpenReq.u.Out.pvImageBase, ModuleInit, ModuleTerm,2015 OpenReq.u.Out.fNativeLoader ? " using the native ring-0 loader" : ""));2016 if (fIsVMMR0)2017 {2018 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;2019 LogRel(("SUP: VMMR0EntryEx located at %RTptr, VMMR0EntryFast at %RTptr and VMMR0EntryInt at %RTptr\n",2020 VMMR0EntryEx, VMMR0EntryFast, VMMR0EntryInt));2021 }2022 #ifdef RT_OS_WINDOWS2023 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));2024 #endif2025 2026 RTMemTmpFree(pLoadReq);2027 RTLdrClose(hLdrMod);2028 return VINF_SUCCESS;2029 }2030 else2031 LogRel(("SUP: Loading failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));2032 }2033 else2034 LogRel(("SUP: RTLdrEnumSymbols failed for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));2035 }2036 else2037 LogRel(("SUP: Failed to get entry points for %s (%s) rc=%Rrc\n", pszModule, pszFilename, rc));2038 }2039 else2040 LogRel(("SUP: RTLdrGetBits failed for %s (%s). rc=%Rrc\n", pszModule, pszFilename, rc));2041 RTMemTmpFree(pLoadReq);2042 }2043 else2044 {2045 AssertMsgFailed(("failed to allocated %u bytes for SUPLDRLOAD_IN structure!\n", SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)));2046 rc = VERR_NO_TMP_MEMORY;2047 }2048 }2049 else if (RT_SUCCESS(rc))2050 {2051 if (fIsVMMR0)2052 g_pvVMMR0 = OpenReq.u.Out.pvImageBase;2053 LogRel(("SUP: Opened %s (%s) at %#p.\n", pszModule, pszFilename, OpenReq.u.Out.pvImageBase,2054 OpenReq.u.Out.fNativeLoader ? " loaded by the native ring-0 loader" : ""));2055 #ifdef RT_OS_WINDOWS2056 LogRel(("SUP: windbg> .reload /f %s=%#p\n", pszFilename, OpenReq.u.Out.pvImageBase));2057 #endif2058 }2059 }2060 RTLdrClose(hLdrMod);2061 return rc;2062 }2063 2064 2065 SUPR3DECL(int) SUPR3FreeModule(void *pvImageBase)2066 {2067 /* fake */2068 if (RT_UNLIKELY(g_u32FakeMode))2069 {2070 g_pvVMMR0 = NIL_RTR0PTR;2071 return VINF_SUCCESS;2072 }2073 2074 /*2075 * Free the requested module.2076 */2077 SUPLDRFREE Req;2078 Req.Hdr.u32Cookie = g_u32Cookie;2079 Req.Hdr.u32SessionCookie = g_u32SessionCookie;2080 Req.Hdr.cbIn = SUP_IOCTL_LDR_FREE_SIZE_IN;2081 Req.Hdr.cbOut = SUP_IOCTL_LDR_FREE_SIZE_OUT;2082 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2083 Req.Hdr.rc = VERR_INTERNAL_ERROR;2084 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;2085 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_FREE, &Req, SUP_IOCTL_LDR_FREE_SIZE);2086 if (RT_SUCCESS(rc))2087 rc = Req.Hdr.rc;2088 if ( RT_SUCCESS(rc)2089 && (RTR0PTR)pvImageBase == g_pvVMMR0)2090 g_pvVMMR0 = NIL_RTR0PTR;2091 return rc;2092 }2093 2094 2095 SUPR3DECL(int) SUPR3GetSymbolR0(void *pvImageBase, const char *pszSymbol, void **ppvValue)2096 {2097 *ppvValue = NULL;2098 2099 /* fake */2100 if (RT_UNLIKELY(g_u32FakeMode))2101 {2102 *ppvValue = (void *)(uintptr_t)0xdeadf00d;2103 return VINF_SUCCESS;2104 }2105 2106 /*2107 * Do ioctl.2108 */2109 SUPLDRGETSYMBOL Req;2110 Req.Hdr.u32Cookie = g_u32Cookie;2111 Req.Hdr.u32SessionCookie = g_u32SessionCookie;2112 Req.Hdr.cbIn = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_IN;2113 Req.Hdr.cbOut = SUP_IOCTL_LDR_GET_SYMBOL_SIZE_OUT;2114 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2115 Req.Hdr.rc = VERR_INTERNAL_ERROR;2116 Req.u.In.pvImageBase = (RTR0PTR)pvImageBase;2117 size_t cchSymbol = strlen(pszSymbol);2118 if (cchSymbol >= sizeof(Req.u.In.szSymbol))2119 return VERR_SYMBOL_NOT_FOUND;2120 memcpy(Req.u.In.szSymbol, pszSymbol, cchSymbol + 1);2121 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_GET_SYMBOL, &Req, SUP_IOCTL_LDR_GET_SYMBOL_SIZE);2122 if (RT_SUCCESS(rc))2123 rc = Req.Hdr.rc;2124 if (RT_SUCCESS(rc))2125 *ppvValue = (void *)Req.u.Out.pvSymbol;2126 return rc;2127 }2128 2129 2130 SUPR3DECL(int) SUPR3LoadVMM(const char *pszFilename)2131 {2132 void *pvImageBase;2133 return SUPR3LoadModule(pszFilename, "VMMR0.r0", &pvImageBase, NULL /*pErrInfo*/);2134 }2135 2136 2137 SUPR3DECL(int) SUPR3UnloadVMM(void)2138 {2139 return SUPR3FreeModule((void*)g_pvVMMR0);2140 }2141 2142 2143 1598 SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys) 2144 1599 { … … 2150 1605 *pHCPhys = NIL_RTHCPHYS; 2151 1606 return VERR_WRONG_ORDER; 2152 }2153 2154 2155 /**2156 * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv.2157 *2158 * @returns iprt status code.2159 * @param pszFilename The full file name.2160 * @param phLdrMod Where to store the handle to the loaded module.2161 * @param fFlags See RTLDFLAGS_.2162 * @param pErrInfo Where to return extended error information.2163 * Optional.2164 *2165 */2166 static int supR3HardenedLdrLoadIt(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)2167 {2168 #ifdef VBOX_WITH_HARDENING2169 /*2170 * Verify the image file.2171 */2172 int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);2173 if (RT_FAILURE(rc))2174 {2175 LogRel(("supR3HardenedLdrLoadIt: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));2176 return RTErrInfoSet(pErrInfo, rc, "supR3HardenedVerifyFixedFile failed");2177 }2178 #endif2179 2180 /*2181 * Try load it.2182 */2183 return RTLdrLoadEx(pszFilename, phLdrMod, fFlags, pErrInfo);2184 }2185 2186 2187 SUPR3DECL(int) SUPR3HardenedLdrLoad(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)2188 {2189 /*2190 * Validate input.2191 */2192 RTErrInfoClear(pErrInfo);2193 AssertPtrReturn(pszFilename, VERR_INVALID_POINTER);2194 AssertPtrReturn(phLdrMod, VERR_INVALID_POINTER);2195 *phLdrMod = NIL_RTLDRMOD;2196 AssertReturn(RTPathHavePath(pszFilename), VERR_INVALID_PARAMETER);2197 2198 /*2199 * Add the default extension if it's missing.2200 */2201 if (!RTPathHasSuffix(pszFilename))2202 {2203 const char *pszSuff = RTLdrGetSuff();2204 size_t cchSuff = strlen(pszSuff);2205 size_t cchFilename = strlen(pszFilename);2206 char *psz = (char *)alloca(cchFilename + cchSuff + 1);2207 AssertReturn(psz, VERR_NO_TMP_MEMORY);2208 memcpy(psz, pszFilename, cchFilename);2209 memcpy(psz + cchFilename, pszSuff, cchSuff + 1);2210 pszFilename = psz;2211 }2212 2213 /*2214 * Pass it on to the common library loader.2215 */2216 return supR3HardenedLdrLoadIt(pszFilename, phLdrMod, fFlags, pErrInfo);2217 }2218 2219 2220 SUPR3DECL(int) SUPR3HardenedLdrLoadAppPriv(const char *pszFilename, PRTLDRMOD phLdrMod, uint32_t fFlags, PRTERRINFO pErrInfo)2221 {2222 LogFlow(("SUPR3HardenedLdrLoadAppPriv: pszFilename=%p:{%s} phLdrMod=%p fFlags=%08x pErrInfo=%p\n", pszFilename, pszFilename, phLdrMod, fFlags, pErrInfo));2223 2224 /*2225 * Validate input.2226 */2227 RTErrInfoClear(pErrInfo);2228 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);2229 *phLdrMod = NIL_RTLDRMOD;2230 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);2231 AssertMsgReturn(!RTPathHavePath(pszFilename), ("%s\n", pszFilename), VERR_INVALID_PARAMETER);2232 2233 /*2234 * Check the filename.2235 */2236 size_t cchFilename = strlen(pszFilename);2237 AssertMsgReturn(cchFilename < (RTPATH_MAX / 4) * 3, ("%zu\n", cchFilename), VERR_INVALID_PARAMETER);2238 2239 const char *pszExt = "";2240 size_t cchExt = 0;2241 if (!RTPathHasSuffix(pszFilename))2242 {2243 pszExt = RTLdrGetSuff();2244 cchExt = strlen(pszExt);2245 }2246 2247 /*2248 * Construct the private arch path and check if the file exists.2249 */2250 char szPath[RTPATH_MAX];2251 int rc = RTPathAppPrivateArch(szPath, sizeof(szPath) - 1 - cchExt - cchFilename);2252 AssertRCReturn(rc, rc);2253 2254 char *psz = strchr(szPath, '\0');2255 *psz++ = RTPATH_SLASH;2256 memcpy(psz, pszFilename, cchFilename);2257 psz += cchFilename;2258 memcpy(psz, pszExt, cchExt + 1);2259 2260 if (!RTPathExists(szPath))2261 {2262 LogRel(("SUPR3HardenedLdrLoadAppPriv: \"%s\" not found\n", szPath));2263 return VERR_FILE_NOT_FOUND;2264 }2265 2266 /*2267 * Pass it on to SUPR3HardenedLdrLoad.2268 */2269 rc = SUPR3HardenedLdrLoad(szPath, phLdrMod, fFlags, pErrInfo);2270 2271 LogFlow(("SUPR3HardenedLdrLoadAppPriv: returns %Rrc\n", rc));2272 return rc;2273 }2274 2275 2276 SUPR3DECL(int) SUPR3HardenedLdrLoadPlugIn(const char *pszFilename, PRTLDRMOD phLdrMod, PRTERRINFO pErrInfo)2277 {2278 /*2279 * Validate input.2280 */2281 RTErrInfoClear(pErrInfo);2282 AssertPtrReturn(phLdrMod, VERR_INVALID_PARAMETER);2283 *phLdrMod = NIL_RTLDRMOD;2284 AssertPtrReturn(pszFilename, VERR_INVALID_PARAMETER);2285 AssertReturn(RTPathStartsWithRoot(pszFilename), VERR_INVALID_PARAMETER);2286 2287 #ifdef VBOX_WITH_HARDENING2288 /*2289 * Verify the image file.2290 */2291 int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);2292 if (RT_FAILURE(rc))2293 {2294 if (!RTErrInfoIsSet(pErrInfo))2295 LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));2296 return rc;2297 }2298 #endif2299 2300 /*2301 * Try load it.2302 */2303 return RTLdrLoadEx(pszFilename, phLdrMod, RTLDRLOAD_FLAGS_LOCAL, pErrInfo);2304 1607 } 2305 1608 … … 2322 1625 2323 1626 /* fake */ 2324 if (RT_UNLIKELY(g_u 32FakeMode))1627 if (RT_UNLIKELY(g_uSupFakeMode)) 2325 1628 return VINF_SUCCESS; 2326 1629 … … 2350 1653 { 2351 1654 /* fake */ 2352 if (RT_UNLIKELY(g_u 32FakeMode))1655 if (RT_UNLIKELY(g_uSupFakeMode)) 2353 1656 return VINF_SUCCESS; 2354 1657 … … 2375 1678 { 2376 1679 /* fake */ 2377 if (RT_UNLIKELY(g_u 32FakeMode))1680 if (RT_UNLIKELY(g_uSupFakeMode)) 2378 1681 return VINF_SUCCESS; 2379 1682 … … 2398 1701 { 2399 1702 /* fake */ 2400 if (RT_UNLIKELY(g_u 32FakeMode))1703 if (RT_UNLIKELY(g_uSupFakeMode)) 2401 1704 { 2402 1705 *piRetVal = -1; … … 2624 1927 * Fake out. 2625 1928 */ 2626 if (RT_UNLIKELY(g_u 32FakeMode))1929 if (RT_UNLIKELY(g_uSupFakeMode)) 2627 1930 return VINF_SUCCESS; 2628 1931 … … 2708 2011 * Fake out. 2709 2012 */ 2710 if (RT_UNLIKELY(g_u 32FakeMode))2013 if (RT_UNLIKELY(g_uSupFakeMode)) 2711 2014 return VINF_SUCCESS; 2712 2015 … … 2742 2045 } 2743 2046 2047 2048 SUPR3DECL(int) SUPR3MsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue, bool *pfGp) 2049 { 2050 SUPMSRPROBER Req; 2051 Req.Hdr.u32Cookie = g_u32Cookie; 2052 Req.Hdr.u32SessionCookie = g_u32SessionCookie; 2053 Req.Hdr.cbIn = SUP_IOCTL_MSR_PROBER_SIZE_IN; 2054 Req.Hdr.cbOut = SUP_IOCTL_MSR_PROBER_SIZE_OUT; 2055 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2056 Req.Hdr.rc = VERR_INTERNAL_ERROR; 2057 2058 Req.u.In.enmOp = SUPMSRPROBEROP_READ; 2059 Req.u.In.uMsr = uMsr; 2060 Req.u.In.idCpu = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu; 2061 2062 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE); 2063 if (RT_SUCCESS(rc)) 2064 rc = Req.Hdr.rc; 2065 if (RT_SUCCESS(rc)) 2066 { 2067 if (puValue) 2068 *puValue = Req.u.Out.uResults.Read.uValue; 2069 if (pfGp) 2070 *pfGp = Req.u.Out.uResults.Read.fGp; 2071 } 2072 2073 return rc; 2074 } 2075 2076 2077 SUPR3DECL(int) SUPR3MsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue, bool *pfGp) 2078 { 2079 SUPMSRPROBER Req; 2080 Req.Hdr.u32Cookie = g_u32Cookie; 2081 Req.Hdr.u32SessionCookie = g_u32SessionCookie; 2082 Req.Hdr.cbIn = SUP_IOCTL_MSR_PROBER_SIZE_IN; 2083 Req.Hdr.cbOut = SUP_IOCTL_MSR_PROBER_SIZE_OUT; 2084 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2085 Req.Hdr.rc = VERR_INTERNAL_ERROR; 2086 2087 Req.u.In.enmOp = SUPMSRPROBEROP_WRITE; 2088 Req.u.In.uMsr = uMsr; 2089 Req.u.In.idCpu = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu; 2090 Req.u.In.uArgs.Write.uToWrite = uValue; 2091 2092 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE); 2093 if (RT_SUCCESS(rc)) 2094 rc = Req.Hdr.rc; 2095 if (RT_SUCCESS(rc) && pfGp) 2096 *pfGp = Req.u.Out.uResults.Write.fGp; 2097 2098 return rc; 2099 } 2100 2101 2102 SUPR3DECL(int) SUPR3MsrProberModify(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, 2103 PSUPMSRPROBERMODIFYRESULT pResult) 2104 { 2105 return SUPR3MsrProberModifyEx(uMsr, idCpu, fAndMask, fOrMask, false /*fFaster*/, pResult); 2106 } 2107 2108 2109 SUPR3DECL(int) SUPR3MsrProberModifyEx(uint32_t uMsr, RTCPUID idCpu, uint64_t fAndMask, uint64_t fOrMask, bool fFaster, 2110 PSUPMSRPROBERMODIFYRESULT pResult) 2111 { 2112 SUPMSRPROBER Req; 2113 Req.Hdr.u32Cookie = g_u32Cookie; 2114 Req.Hdr.u32SessionCookie = g_u32SessionCookie; 2115 Req.Hdr.cbIn = SUP_IOCTL_MSR_PROBER_SIZE_IN; 2116 Req.Hdr.cbOut = SUP_IOCTL_MSR_PROBER_SIZE_OUT; 2117 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT; 2118 Req.Hdr.rc = VERR_INTERNAL_ERROR; 2119 2120 Req.u.In.enmOp = fFaster ? SUPMSRPROBEROP_MODIFY_FASTER : SUPMSRPROBEROP_MODIFY; 2121 Req.u.In.uMsr = uMsr; 2122 Req.u.In.idCpu = idCpu == NIL_RTCPUID ? UINT32_MAX : idCpu; 2123 Req.u.In.uArgs.Modify.fAndMask = fAndMask; 2124 Req.u.In.uArgs.Modify.fOrMask = fOrMask; 2125 2126 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_MSR_PROBER, &Req, SUP_IOCTL_MSR_PROBER_SIZE); 2127 if (RT_SUCCESS(rc)) 2128 rc = Req.Hdr.rc; 2129 if (RT_SUCCESS(rc)) 2130 *pResult = Req.u.Out.uResults.Modify; 2131 2132 return rc; 2133 } 2134 -
trunk/src/VBox/HostDrivers/Support/SUPLibInternal.h
r49211 r49634 280 280 * Global Variables * 281 281 *******************************************************************************/ 282 extern DECLHIDDEN(uint32_t) g_u32Cookie; 283 extern DECLHIDDEN(uint32_t) g_u32SessionCookie; 284 extern DECLHIDDEN(SUPLIBDATA) g_supLibData; 282 extern DECLHIDDEN(uint32_t) g_u32Cookie; 283 extern DECLHIDDEN(uint32_t) g_u32SessionCookie; 284 extern DECLHIDDEN(SUPLIBDATA) g_supLibData; 285 extern DECLHIDDEN(uint32_t) g_uSupFakeMode; 286 extern DECLHIDDEN(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPageR0; 287 #ifdef ___SUPDrvIOC_h___ 288 extern DECLHIDDEN(PSUPQUERYFUNCS) g_pSupFunctions; 289 #endif 285 290 286 291 -
trunk/src/VBox/HostDrivers/Support/SUPLibLdr.cpp
r49620 r49634 1 1 /* $Id$ */ 2 2 /** @file 3 * VirtualBox Support Library - Common code.3 * VirtualBox Support Library - Loader related bits. 4 4 */ 5 5 … … 68 68 #include <iprt/x86.h> 69 69 70 #include "SUPDrvIOC.h" 70 71 #include "SUPLibInternal.h" 71 #include "SUPDrvIOC.h"72 72 73 73 … … 89 89 * Global Variables * 90 90 *******************************************************************************/ 91 /** Init counter. */92 static uint32_t g_cInits = 0;93 /** Whether we've been preinitied. */94 static bool g_fPreInited = false;95 /** The SUPLib instance data.96 * Well, at least parts of it, specifically the parts that are being handed over97 * via the pre-init mechanism from the hardened executable stub. */98 SUPLIBDATA g_supLibData =99 {100 /*.hDevice = */ SUP_HDEVICE_NIL,101 /*.fUnrestricted = */ true102 #if defined(RT_OS_DARWIN)103 ,/* .uConnection = */ NULL104 #elif defined(RT_OS_LINUX)105 ,/* .fSysMadviseWorks = */ false106 #endif107 };108 109 /** Pointer to the Global Information Page.110 *111 * This pointer is valid as long as SUPLib has a open session. Anyone using112 * the page must treat this pointer as highly volatile and not trust it beyond113 * one transaction.114 *115 * @todo This will probably deserve it's own session or some other good solution...116 */117 DECLEXPORT(PSUPGLOBALINFOPAGE) g_pSUPGlobalInfoPage;118 /** Address of the ring-0 mapping of the GIP. */119 static PSUPGLOBALINFOPAGE g_pSUPGlobalInfoPageR0;120 /** The physical address of the GIP. */121 static RTHCPHYS g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS;122 123 /** The negotiated cookie. */124 uint32_t g_u32Cookie = 0;125 /** The negotiated session cookie. */126 uint32_t g_u32SessionCookie;127 /** Session handle. */128 PSUPDRVSESSION g_pSession;129 /** R0 SUP Functions used for resolving referenced to the SUPR0 module. */130 static PSUPQUERYFUNCS g_pFunctions;131 132 91 /** VMMR0 Load Address. */ 133 92 static RTR0PTR g_pvVMMR0 = NIL_RTR0PTR; 134 /** PAGE_ALLOC_EX sans kernel mapping support indicator. */135 static bool g_fSupportsPageAllocNoKernel = true;136 /** Fake mode indicator. (~0 at first, 0 or 1 after first test) */137 static uint32_t g_u32FakeMode = ~0;138 93 139 94 … … 141 96 * Internal Functions * 142 97 *******************************************************************************/ 143 static int supInitFake(PSUPDRVSESSION *ppSession);144 98 static int supLoadModule(const char *pszFilename, const char *pszModule, const char *pszSrvReqHandler, void **ppvImageBase); 145 99 static DECLCALLBACK(int) supLoadModuleResolveImport(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser); 146 147 148 /** Touch a range of pages. */149 DECLINLINE(void) supR3TouchPages(void *pv, size_t cPages)150 {151 uint32_t volatile *pu32 = (uint32_t volatile *)pv;152 while (cPages-- > 0)153 {154 ASMAtomicCmpXchgU32(pu32, 0, 0);155 pu32 += PAGE_SIZE / sizeof(uint32_t);156 }157 }158 159 160 SUPR3DECL(int) SUPR3Install(void)161 {162 return suplibOsInstall();163 }164 165 166 SUPR3DECL(int) SUPR3Uninstall(void)167 {168 return suplibOsUninstall();169 }170 171 172 DECLEXPORT(int) supR3PreInit(PSUPPREINITDATA pPreInitData, uint32_t fFlags)173 {174 /*175 * The caller is kind of trustworthy, just perform some basic checks.176 *177 * Note! Do not do any fancy stuff here because IPRT has NOT been178 * initialized at this point.179 */180 if (!VALID_PTR(pPreInitData))181 return VERR_INVALID_POINTER;182 if (g_fPreInited || g_cInits > 0)183 return VERR_WRONG_ORDER;184 185 if ( pPreInitData->u32Magic != SUPPREINITDATA_MAGIC186 || pPreInitData->u32EndMagic != SUPPREINITDATA_MAGIC)187 return VERR_INVALID_MAGIC;188 if ( !(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)189 && pPreInitData->Data.hDevice == SUP_HDEVICE_NIL)190 return VERR_INVALID_HANDLE;191 if ( (fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV)192 && pPreInitData->Data.hDevice != SUP_HDEVICE_NIL)193 return VERR_INVALID_PARAMETER;194 195 /*196 * Hand out the data.197 */198 int rc = supR3HardenedRecvPreInitData(pPreInitData);199 if (RT_FAILURE(rc))200 return rc;201 202 /** @todo This may need some small restructuring later, it doesn't quite work with a root service flag... */203 if (!(fFlags & SUPSECMAIN_FLAGS_DONT_OPEN_DEV))204 {205 g_supLibData = pPreInitData->Data;206 g_fPreInited = true;207 }208 209 return VINF_SUCCESS;210 }211 212 213 SUPR3DECL(int) SUPR3InitEx(bool fUnrestricted, PSUPDRVSESSION *ppSession)214 {215 /*216 * Perform some sanity checks.217 * (Got some trouble with compile time member alignment assertions.)218 */219 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, u64NanoTSLastUpdateHz) & 0x7));220 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs) & 0x1f));221 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[1]) & 0x1f));222 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64NanoTS) & 0x7));223 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64TSC) & 0x7));224 Assert(!(RT_OFFSETOF(SUPGLOBALINFOPAGE, aCPUs[0].u64CpuHz) & 0x7));225 226 /*227 * Check if already initialized.228 */229 if (ppSession)230 *ppSession = g_pSession;231 if (g_cInits++ > 0)232 {233 if (fUnrestricted && !g_supLibData.fUnrestricted)234 {235 g_cInits--;236 if (ppSession)237 *ppSession = NIL_RTR0PTR;238 return VERR_VM_DRIVER_NOT_ACCESSIBLE; /** @todo different status code? */239 }240 return VINF_SUCCESS;241 }242 243 /*244 * Check for fake mode.245 *246 * Fake mode is used when we're doing smoke testing and debugging.247 * It's also useful on platforms where we haven't root access or which248 * we haven't ported the support driver to.249 */250 if (g_u32FakeMode == ~0U)251 {252 const char *psz = RTEnvGet("VBOX_SUPLIB_FAKE");253 if (psz && !strcmp(psz, "fake"))254 ASMAtomicCmpXchgU32(&g_u32FakeMode, 1, ~0U);255 else256 ASMAtomicCmpXchgU32(&g_u32FakeMode, 0, ~0U);257 }258 if (RT_UNLIKELY(g_u32FakeMode))259 return supInitFake(ppSession);260 261 /*262 * Open the support driver.263 */264 int rc = suplibOsInit(&g_supLibData, g_fPreInited, fUnrestricted);265 if (RT_SUCCESS(rc))266 {267 /*268 * Negotiate the cookie.269 */270 SUPCOOKIE CookieReq;271 memset(&CookieReq, 0xff, sizeof(CookieReq));272 CookieReq.Hdr.u32Cookie = SUPCOOKIE_INITIAL_COOKIE;273 CookieReq.Hdr.u32SessionCookie = RTRandU32();274 CookieReq.Hdr.cbIn = SUP_IOCTL_COOKIE_SIZE_IN;275 CookieReq.Hdr.cbOut = SUP_IOCTL_COOKIE_SIZE_OUT;276 CookieReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;277 CookieReq.Hdr.rc = VERR_INTERNAL_ERROR;278 strcpy(CookieReq.u.In.szMagic, SUPCOOKIE_MAGIC);279 CookieReq.u.In.u32ReqVersion = SUPDRV_IOC_VERSION;280 const uint32_t uMinVersion = (SUPDRV_IOC_VERSION & 0xffff0000) == 0x001a0000281 ? 0x001a0005282 : SUPDRV_IOC_VERSION & 0xffff0000;283 CookieReq.u.In.u32MinVersion = uMinVersion;284 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_COOKIE, &CookieReq, SUP_IOCTL_COOKIE_SIZE);285 if ( RT_SUCCESS(rc)286 && RT_SUCCESS(CookieReq.Hdr.rc))287 {288 if ( (CookieReq.u.Out.u32SessionVersion & 0xffff0000) == (SUPDRV_IOC_VERSION & 0xffff0000)289 && CookieReq.u.Out.u32SessionVersion >= uMinVersion)290 {291 /*292 * Query the functions.293 */294 PSUPQUERYFUNCS pFuncsReq = NULL;295 if (g_supLibData.fUnrestricted)296 {297 pFuncsReq = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));298 if (pFuncsReq)299 {300 pFuncsReq->Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;301 pFuncsReq->Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;302 pFuncsReq->Hdr.cbIn = SUP_IOCTL_QUERY_FUNCS_SIZE_IN;303 pFuncsReq->Hdr.cbOut = SUP_IOCTL_QUERY_FUNCS_SIZE_OUT(CookieReq.u.Out.cFunctions);304 pFuncsReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;305 pFuncsReq->Hdr.rc = VERR_INTERNAL_ERROR;306 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_QUERY_FUNCS(CookieReq.u.Out.cFunctions), pFuncsReq,307 SUP_IOCTL_QUERY_FUNCS_SIZE(CookieReq.u.Out.cFunctions));308 if (RT_SUCCESS(rc))309 rc = pFuncsReq->Hdr.rc;310 if (RT_SUCCESS(rc))311 {312 /*313 * Map the GIP into userspace.314 */315 Assert(!g_pSUPGlobalInfoPage);316 SUPGIPMAP GipMapReq;317 GipMapReq.Hdr.u32Cookie = CookieReq.u.Out.u32Cookie;318 GipMapReq.Hdr.u32SessionCookie = CookieReq.u.Out.u32SessionCookie;319 GipMapReq.Hdr.cbIn = SUP_IOCTL_GIP_MAP_SIZE_IN;320 GipMapReq.Hdr.cbOut = SUP_IOCTL_GIP_MAP_SIZE_OUT;321 GipMapReq.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;322 GipMapReq.Hdr.rc = VERR_INTERNAL_ERROR;323 GipMapReq.u.Out.HCPhysGip = NIL_RTHCPHYS;324 GipMapReq.u.Out.pGipR0 = NIL_RTR0PTR;325 GipMapReq.u.Out.pGipR3 = NULL;326 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GIP_MAP, &GipMapReq, SUP_IOCTL_GIP_MAP_SIZE);327 if (RT_SUCCESS(rc))328 rc = GipMapReq.Hdr.rc;329 if (RT_SUCCESS(rc))330 {331 /*332 * Set the GIP globals.333 */334 AssertRelease(GipMapReq.u.Out.pGipR3->u32Magic == SUPGLOBALINFOPAGE_MAGIC);335 AssertRelease(GipMapReq.u.Out.pGipR3->u32Version >= SUPGLOBALINFOPAGE_VERSION);336 337 ASMAtomicXchgSize(&g_HCPhysSUPGlobalInfoPage, GipMapReq.u.Out.HCPhysGip);338 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPage, GipMapReq.u.Out.pGipR3, NULL);339 ASMAtomicCmpXchgPtr((void * volatile *)&g_pSUPGlobalInfoPageR0, (void *)GipMapReq.u.Out.pGipR0, NULL);340 }341 }342 }343 else344 rc = VERR_NO_MEMORY;345 }346 347 if (RT_SUCCESS(rc))348 {349 /*350 * Set the globals and return success.351 */352 g_u32Cookie = CookieReq.u.Out.u32Cookie;353 g_u32SessionCookie = CookieReq.u.Out.u32SessionCookie;354 g_pSession = CookieReq.u.Out.pSession;355 g_pFunctions = pFuncsReq;356 if (ppSession)357 *ppSession = CookieReq.u.Out.pSession;358 return VINF_SUCCESS;359 }360 361 /* bailout */362 RTMemFree(pFuncsReq);363 }364 else365 {366 LogRel(("Support driver version mismatch: SessionVersion=%#x DriverVersion=%#x ClientVersion=%#x MinVersion=%#x\n",367 CookieReq.u.Out.u32SessionVersion, CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, uMinVersion));368 rc = VERR_VM_DRIVER_VERSION_MISMATCH;369 }370 }371 else372 {373 if (RT_SUCCESS(rc))374 {375 rc = CookieReq.Hdr.rc;376 LogRel(("Support driver version mismatch: DriverVersion=%#x ClientVersion=%#x rc=%Rrc\n",377 CookieReq.u.Out.u32DriverVersion, SUPDRV_IOC_VERSION, rc));378 if (rc != VERR_VM_DRIVER_VERSION_MISMATCH)379 rc = VERR_VM_DRIVER_VERSION_MISMATCH;380 }381 else382 {383 /* for pre 0x00060000 drivers */384 LogRel(("Support driver version mismatch: DriverVersion=too-old ClientVersion=%#x\n", SUPDRV_IOC_VERSION));385 rc = VERR_VM_DRIVER_VERSION_MISMATCH;386 }387 }388 389 suplibOsTerm(&g_supLibData);390 }391 g_cInits--;392 393 return rc;394 }395 396 397 SUPR3DECL(int) SUPR3Init(PSUPDRVSESSION *ppSession)398 {399 return SUPR3InitEx(true, ppSession);400 }401 402 /**403 * Fake mode init.404 */405 static int supInitFake(PSUPDRVSESSION *ppSession)406 {407 Log(("SUP: Fake mode!\n"));408 static const SUPFUNC s_aFakeFunctions[] =409 {410 /* name function */411 { "SUPR0AbsIs64bit", 0 },412 { "SUPR0Abs64bitKernelCS", 0 },413 { "SUPR0Abs64bitKernelSS", 0 },414 { "SUPR0Abs64bitKernelDS", 0 },415 { "SUPR0AbsKernelCS", 8 },416 { "SUPR0AbsKernelSS", 16 },417 { "SUPR0AbsKernelDS", 16 },418 { "SUPR0AbsKernelES", 16 },419 { "SUPR0AbsKernelFS", 24 },420 { "SUPR0AbsKernelGS", 32 },421 { "SUPR0ComponentRegisterFactory", 0xefeefffd },422 { "SUPR0ComponentDeregisterFactory", 0xefeefffe },423 { "SUPR0ComponentQueryFactory", 0xefeeffff },424 { "SUPR0ObjRegister", 0xefef0000 },425 { "SUPR0ObjAddRef", 0xefef0001 },426 { "SUPR0ObjAddRefEx", 0xefef0001 },427 { "SUPR0ObjRelease", 0xefef0002 },428 { "SUPR0ObjVerifyAccess", 0xefef0003 },429 { "SUPR0LockMem", 0xefef0004 },430 { "SUPR0UnlockMem", 0xefef0005 },431 { "SUPR0ContAlloc", 0xefef0006 },432 { "SUPR0ContFree", 0xefef0007 },433 { "SUPR0MemAlloc", 0xefef0008 },434 { "SUPR0MemGetPhys", 0xefef0009 },435 { "SUPR0MemFree", 0xefef000a },436 { "SUPR0Printf", 0xefef000b },437 { "SUPR0GetPagingMode", 0xefef000c },438 { "SUPR0EnableVTx", 0xefef000e },439 { "RTMemAlloc", 0xefef000f },440 { "RTMemAllocZ", 0xefef0010 },441 { "RTMemFree", 0xefef0011 },442 { "RTR0MemObjAddress", 0xefef0012 },443 { "RTR0MemObjAddressR3", 0xefef0013 },444 { "RTR0MemObjAllocPage", 0xefef0014 },445 { "RTR0MemObjAllocPhysNC", 0xefef0015 },446 { "RTR0MemObjAllocLow", 0xefef0016 },447 { "RTR0MemObjEnterPhys", 0xefef0017 },448 { "RTR0MemObjFree", 0xefef0018 },449 { "RTR0MemObjGetPagePhysAddr", 0xefef0019 },450 { "RTR0MemObjMapUser", 0xefef001a },451 { "RTR0MemObjMapKernel", 0xefef001b },452 { "RTR0MemObjMapKernelEx", 0xefef001c },453 { "RTMpGetArraySize", 0xefef001c },454 { "RTProcSelf", 0xefef001d },455 { "RTR0ProcHandleSelf", 0xefef001e },456 { "RTSemEventCreate", 0xefef001f },457 { "RTSemEventSignal", 0xefef0020 },458 { "RTSemEventWait", 0xefef0021 },459 { "RTSemEventWaitNoResume", 0xefef0022 },460 { "RTSemEventDestroy", 0xefef0023 },461 { "RTSemEventMultiCreate", 0xefef0024 },462 { "RTSemEventMultiSignal", 0xefef0025 },463 { "RTSemEventMultiReset", 0xefef0026 },464 { "RTSemEventMultiWait", 0xefef0027 },465 { "RTSemEventMultiWaitNoResume", 0xefef0028 },466 { "RTSemEventMultiDestroy", 0xefef0029 },467 { "RTSemFastMutexCreate", 0xefef002a },468 { "RTSemFastMutexDestroy", 0xefef002b },469 { "RTSemFastMutexRequest", 0xefef002c },470 { "RTSemFastMutexRelease", 0xefef002d },471 { "RTSpinlockCreate", 0xefef002e },472 { "RTSpinlockDestroy", 0xefef002f },473 { "RTSpinlockAcquire", 0xefef0030 },474 { "RTSpinlockRelease", 0xefef0031 },475 { "RTSpinlockAcquireNoInts", 0xefef0032 },476 { "RTSpinlockReleaseNoInts", 0xefef0033 },477 { "RTTimeNanoTS", 0xefef0034 },478 { "RTTimeMillieTS", 0xefef0035 },479 { "RTTimeSystemNanoTS", 0xefef0036 },480 { "RTTimeSystemMillieTS", 0xefef0037 },481 { "RTThreadNativeSelf", 0xefef0038 },482 { "RTThreadSleep", 0xefef0039 },483 { "RTThreadYield", 0xefef003a },484 { "RTTimerCreate", 0xefef003a },485 { "RTTimerCreateEx", 0xefef003a },486 { "RTTimerDestroy", 0xefef003a },487 { "RTTimerStart", 0xefef003a },488 { "RTTimerStop", 0xefef003a },489 { "RTTimerChangeInterval", 0xefef003a },490 { "RTTimerGetSystemGranularity", 0xefef003a },491 { "RTTimerRequestSystemGranularity", 0xefef003a },492 { "RTTimerReleaseSystemGranularity", 0xefef003a },493 { "RTTimerCanDoHighResolution", 0xefef003a },494 { "RTLogDefaultInstance", 0xefef003b },495 { "RTLogRelDefaultInstance", 0xefef003c },496 { "RTLogSetDefaultInstanceThread", 0xefef003d },497 { "RTLogLogger", 0xefef003e },498 { "RTLogLoggerEx", 0xefef003f },499 { "RTLogLoggerExV", 0xefef0040 },500 { "RTAssertMsg1", 0xefef0041 },501 { "RTAssertMsg2", 0xefef0042 },502 { "RTAssertMsg2V", 0xefef0043 },503 { "SUPR0QueryVTCaps", 0xefef0044 },504 };505 506 /* fake r0 functions. */507 g_pFunctions = (PSUPQUERYFUNCS)RTMemAllocZ(SUP_IOCTL_QUERY_FUNCS_SIZE(RT_ELEMENTS(s_aFakeFunctions)));508 if (g_pFunctions)509 {510 g_pFunctions->u.Out.cFunctions = RT_ELEMENTS(s_aFakeFunctions);511 memcpy(&g_pFunctions->u.Out.aFunctions[0], &s_aFakeFunctions[0], sizeof(s_aFakeFunctions));512 g_pSession = (PSUPDRVSESSION)(void *)g_pFunctions;513 if (ppSession)514 *ppSession = g_pSession;515 516 /* fake the GIP. */517 g_pSUPGlobalInfoPage = (PSUPGLOBALINFOPAGE)RTMemPageAllocZ(PAGE_SIZE);518 if (g_pSUPGlobalInfoPage)519 {520 g_pSUPGlobalInfoPageR0 = g_pSUPGlobalInfoPage;521 g_HCPhysSUPGlobalInfoPage = NIL_RTHCPHYS & ~(RTHCPHYS)PAGE_OFFSET_MASK;522 /* the page is supposed to be invalid, so don't set the magic. */523 return VINF_SUCCESS;524 }525 526 RTMemFree(g_pFunctions);527 g_pFunctions = NULL;528 }529 return VERR_NO_MEMORY;530 }531 532 533 SUPR3DECL(int) SUPR3Term(bool fForced)534 {535 /*536 * Verify state.537 */538 AssertMsg(g_cInits > 0, ("SUPR3Term() is called before SUPR3Init()!\n"));539 if (g_cInits == 0)540 return VERR_WRONG_ORDER;541 if (g_cInits == 1 || fForced)542 {543 /*544 * NULL the GIP pointer.545 */546 if (g_pSUPGlobalInfoPage)547 {548 ASMAtomicWriteNullPtr((void * volatile *)&g_pSUPGlobalInfoPage);549 ASMAtomicWriteNullPtr((void * volatile *)&g_pSUPGlobalInfoPageR0);550 ASMAtomicWriteSize(&g_HCPhysSUPGlobalInfoPage, NIL_RTHCPHYS);551 /* just a little safe guard against threads using the page. */552 RTThreadSleep(50);553 }554 555 /*556 * Close the support driver.557 */558 int rc = suplibOsTerm(&g_supLibData);559 if (rc)560 return rc;561 562 g_u32Cookie = 0;563 g_u32SessionCookie = 0;564 g_cInits = 0;565 }566 else567 g_cInits--;568 569 return 0;570 }571 572 573 SUPR3DECL(SUPPAGINGMODE) SUPR3GetPagingMode(void)574 {575 /* fake */576 if (RT_UNLIKELY(g_u32FakeMode))577 #ifdef RT_ARCH_AMD64578 return SUPPAGINGMODE_AMD64_GLOBAL_NX;579 #else580 return SUPPAGINGMODE_32_BIT_GLOBAL;581 #endif582 583 /*584 * Issue IOCtl to the SUPDRV kernel module.585 */586 SUPGETPAGINGMODE Req;587 Req.Hdr.u32Cookie = g_u32Cookie;588 Req.Hdr.u32SessionCookie = g_u32SessionCookie;589 Req.Hdr.cbIn = SUP_IOCTL_GET_PAGING_MODE_SIZE_IN;590 Req.Hdr.cbOut = SUP_IOCTL_GET_PAGING_MODE_SIZE_OUT;591 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;592 Req.Hdr.rc = VERR_INTERNAL_ERROR;593 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_GET_PAGING_MODE, &Req, SUP_IOCTL_GET_PAGING_MODE_SIZE);594 if ( RT_FAILURE(rc)595 || RT_FAILURE(Req.Hdr.rc))596 {597 LogRel(("SUPR3GetPagingMode: %Rrc %Rrc\n", rc, Req.Hdr.rc));598 Req.u.Out.enmMode = SUPPAGINGMODE_INVALID;599 }600 601 return Req.u.Out.enmMode;602 }603 604 605 /**606 * For later.607 */608 static int supCallVMMR0ExFake(PVMR0 pVMR0, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)609 {610 AssertMsgFailed(("%d\n", uOperation)); NOREF(pVMR0); NOREF(uOperation); NOREF(u64Arg); NOREF(pReqHdr);611 return VERR_NOT_SUPPORTED;612 }613 614 615 SUPR3DECL(int) SUPR3CallVMMR0Fast(PVMR0 pVMR0, unsigned uOperation, VMCPUID idCpu)616 {617 NOREF(pVMR0);618 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_RAW_RUN))619 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_RAW_RUN, idCpu);620 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_HM_RUN))621 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_HM_RUN, idCpu);622 if (RT_LIKELY(uOperation == SUP_VMMR0_DO_NOP))623 return suplibOsIOCtlFast(&g_supLibData, SUP_IOCTL_FAST_DO_NOP, idCpu);624 625 AssertMsgFailed(("%#x\n", uOperation));626 return VERR_INTERNAL_ERROR;627 }628 629 630 SUPR3DECL(int) SUPR3CallVMMR0Ex(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, uint64_t u64Arg, PSUPVMMR0REQHDR pReqHdr)631 {632 /*633 * The following operations don't belong here.634 */635 AssertMsgReturn( uOperation != SUP_VMMR0_DO_RAW_RUN636 && uOperation != SUP_VMMR0_DO_HM_RUN637 && uOperation != SUP_VMMR0_DO_NOP,638 ("%#x\n", uOperation),639 VERR_INTERNAL_ERROR);640 641 /* fake */642 if (RT_UNLIKELY(g_u32FakeMode))643 return supCallVMMR0ExFake(pVMR0, uOperation, u64Arg, pReqHdr);644 645 int rc;646 if (!pReqHdr)647 {648 /* no data. */649 SUPCALLVMMR0 Req;650 Req.Hdr.u32Cookie = g_u32Cookie;651 Req.Hdr.u32SessionCookie = g_u32SessionCookie;652 Req.Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(0);653 Req.Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(0);654 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;655 Req.Hdr.rc = VERR_INTERNAL_ERROR;656 Req.u.In.pVMR0 = pVMR0;657 Req.u.In.idCpu = idCpu;658 Req.u.In.uOperation = uOperation;659 Req.u.In.u64Arg = u64Arg;660 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(0), &Req, SUP_IOCTL_CALL_VMMR0_SIZE(0));661 if (RT_SUCCESS(rc))662 rc = Req.Hdr.rc;663 }664 else if (SUP_IOCTL_CALL_VMMR0_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */665 {666 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);667 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);668 const size_t cbReq = pReqHdr->cbReq;669 670 PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)alloca(SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));671 pReq->Hdr.u32Cookie = g_u32Cookie;672 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;673 pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_SIZE_IN(cbReq);674 pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_SIZE_OUT(cbReq);675 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;676 pReq->Hdr.rc = VERR_INTERNAL_ERROR;677 pReq->u.In.pVMR0 = pVMR0;678 pReq->u.In.idCpu = idCpu;679 pReq->u.In.uOperation = uOperation;680 pReq->u.In.u64Arg = u64Arg;681 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);682 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0(cbReq), pReq, SUP_IOCTL_CALL_VMMR0_SIZE(cbReq));683 if (RT_SUCCESS(rc))684 rc = pReq->Hdr.rc;685 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);686 }687 else if (pReqHdr->cbReq <= _512K)688 {689 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);690 AssertReturn(pReqHdr->u32Magic == SUPVMMR0REQHDR_MAGIC, VERR_INVALID_MAGIC);691 const size_t cbReq = pReqHdr->cbReq;692 693 PSUPCALLVMMR0 pReq = (PSUPCALLVMMR0)RTMemTmpAlloc(SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));694 pReq->Hdr.u32Cookie = g_u32Cookie;695 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;696 pReq->Hdr.cbIn = SUP_IOCTL_CALL_VMMR0_BIG_SIZE_IN(cbReq);697 pReq->Hdr.cbOut = SUP_IOCTL_CALL_VMMR0_BIG_SIZE_OUT(cbReq);698 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;699 pReq->Hdr.rc = VERR_INTERNAL_ERROR;700 pReq->u.In.pVMR0 = pVMR0;701 pReq->u.In.idCpu = idCpu;702 pReq->u.In.uOperation = uOperation;703 pReq->u.In.u64Arg = u64Arg;704 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);705 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_VMMR0_BIG, pReq, SUP_IOCTL_CALL_VMMR0_BIG_SIZE(cbReq));706 if (RT_SUCCESS(rc))707 rc = pReq->Hdr.rc;708 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);709 RTMemTmpFree(pReq);710 }711 else712 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_OUT_OF_RANGE);713 return rc;714 }715 716 717 SUPR3DECL(int) SUPR3CallVMMR0(PVMR0 pVMR0, VMCPUID idCpu, unsigned uOperation, void *pvArg)718 {719 /*720 * The following operations don't belong here.721 */722 AssertMsgReturn( uOperation != SUP_VMMR0_DO_RAW_RUN723 && uOperation != SUP_VMMR0_DO_HM_RUN724 && uOperation != SUP_VMMR0_DO_NOP,725 ("%#x\n", uOperation),726 VERR_INTERNAL_ERROR);727 return SUPR3CallVMMR0Ex(pVMR0, idCpu, uOperation, (uintptr_t)pvArg, NULL);728 }729 730 731 SUPR3DECL(int) SUPR3SetVMForFastIOCtl(PVMR0 pVMR0)732 {733 if (RT_UNLIKELY(g_u32FakeMode))734 return VINF_SUCCESS;735 736 SUPSETVMFORFAST Req;737 Req.Hdr.u32Cookie = g_u32Cookie;738 Req.Hdr.u32SessionCookie = g_u32SessionCookie;739 Req.Hdr.cbIn = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_IN;740 Req.Hdr.cbOut = SUP_IOCTL_SET_VM_FOR_FAST_SIZE_OUT;741 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;742 Req.Hdr.rc = VERR_INTERNAL_ERROR;743 Req.u.In.pVMR0 = pVMR0;744 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_SET_VM_FOR_FAST, &Req, SUP_IOCTL_SET_VM_FOR_FAST_SIZE);745 if (RT_SUCCESS(rc))746 rc = Req.Hdr.rc;747 return rc;748 }749 750 751 SUPR3DECL(int) SUPR3CallR0Service(const char *pszService, size_t cchService, uint32_t uOperation, uint64_t u64Arg, PSUPR0SERVICEREQHDR pReqHdr)752 {753 AssertReturn(cchService < RT_SIZEOFMEMB(SUPCALLSERVICE, u.In.szName), VERR_INVALID_PARAMETER);754 Assert(strlen(pszService) == cchService);755 756 /* fake */757 if (RT_UNLIKELY(g_u32FakeMode))758 return VERR_NOT_SUPPORTED;759 760 int rc;761 if (!pReqHdr)762 {763 /* no data. */764 SUPCALLSERVICE Req;765 Req.Hdr.u32Cookie = g_u32Cookie;766 Req.Hdr.u32SessionCookie = g_u32SessionCookie;767 Req.Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(0);768 Req.Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(0);769 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;770 Req.Hdr.rc = VERR_INTERNAL_ERROR;771 memcpy(Req.u.In.szName, pszService, cchService);772 Req.u.In.szName[cchService] = '\0';773 Req.u.In.uOperation = uOperation;774 Req.u.In.u64Arg = u64Arg;775 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(0), &Req, SUP_IOCTL_CALL_SERVICE_SIZE(0));776 if (RT_SUCCESS(rc))777 rc = Req.Hdr.rc;778 }779 else if (SUP_IOCTL_CALL_SERVICE_SIZE(pReqHdr->cbReq) < _4K) /* FreeBSD won't copy more than 4K. */780 {781 AssertPtrReturn(pReqHdr, VERR_INVALID_POINTER);782 AssertReturn(pReqHdr->u32Magic == SUPR0SERVICEREQHDR_MAGIC, VERR_INVALID_MAGIC);783 const size_t cbReq = pReqHdr->cbReq;784 785 PSUPCALLSERVICE pReq = (PSUPCALLSERVICE)alloca(SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));786 pReq->Hdr.u32Cookie = g_u32Cookie;787 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;788 pReq->Hdr.cbIn = SUP_IOCTL_CALL_SERVICE_SIZE_IN(cbReq);789 pReq->Hdr.cbOut = SUP_IOCTL_CALL_SERVICE_SIZE_OUT(cbReq);790 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;791 pReq->Hdr.rc = VERR_INTERNAL_ERROR;792 memcpy(pReq->u.In.szName, pszService, cchService);793 pReq->u.In.szName[cchService] = '\0';794 pReq->u.In.uOperation = uOperation;795 pReq->u.In.u64Arg = u64Arg;796 memcpy(&pReq->abReqPkt[0], pReqHdr, cbReq);797 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CALL_SERVICE(cbReq), pReq, SUP_IOCTL_CALL_SERVICE_SIZE(cbReq));798 if (RT_SUCCESS(rc))799 rc = pReq->Hdr.rc;800 memcpy(pReqHdr, &pReq->abReqPkt[0], cbReq);801 }802 else /** @todo may have to remove the size limits one this request... */803 AssertMsgFailedReturn(("cbReq=%#x\n", pReqHdr->cbReq), VERR_INTERNAL_ERROR);804 return rc;805 }806 807 808 /**809 * Worker for the SUPR3Logger* APIs.810 *811 * @returns VBox status code.812 * @param enmWhich Which logger.813 * @param fWhat What to do with the logger.814 * @param pszFlags The flags settings.815 * @param pszGroups The groups settings.816 * @param pszDest The destination specificier.817 */818 static int supR3LoggerSettings(SUPLOGGER enmWhich, uint32_t fWhat, const char *pszFlags, const char *pszGroups, const char *pszDest)819 {820 uint32_t const cchFlags = pszFlags ? (uint32_t)strlen(pszFlags) : 0;821 uint32_t const cchGroups = pszGroups ? (uint32_t)strlen(pszGroups) : 0;822 uint32_t const cchDest = pszDest ? (uint32_t)strlen(pszDest) : 0;823 uint32_t const cbStrTab = cchFlags + !!cchFlags824 + cchGroups + !!cchGroups825 + cchDest + !!cchDest826 + (!cchFlags && !cchGroups && !cchDest);827 828 PSUPLOGGERSETTINGS pReq = (PSUPLOGGERSETTINGS)alloca(SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));829 pReq->Hdr.u32Cookie = g_u32Cookie;830 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;831 pReq->Hdr.cbIn = SUP_IOCTL_LOGGER_SETTINGS_SIZE_IN(cbStrTab);832 pReq->Hdr.cbOut = SUP_IOCTL_LOGGER_SETTINGS_SIZE_OUT;833 pReq->Hdr.fFlags= SUPREQHDR_FLAGS_DEFAULT;834 pReq->Hdr.rc = VERR_INTERNAL_ERROR;835 switch (enmWhich)836 {837 case SUPLOGGER_DEBUG: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_DEBUG; break;838 case SUPLOGGER_RELEASE: pReq->u.In.fWhich = SUPLOGGERSETTINGS_WHICH_RELEASE; break;839 default:840 return VERR_INVALID_PARAMETER;841 }842 pReq->u.In.fWhat = fWhat;843 844 uint32_t off = 0;845 if (cchFlags)846 {847 pReq->u.In.offFlags = off;848 memcpy(&pReq->u.In.szStrings[off], pszFlags, cchFlags + 1);849 off += cchFlags + 1;850 }851 else852 pReq->u.In.offFlags = cbStrTab - 1;853 854 if (cchGroups)855 {856 pReq->u.In.offGroups = off;857 memcpy(&pReq->u.In.szStrings[off], pszGroups, cchGroups + 1);858 off += cchGroups + 1;859 }860 else861 pReq->u.In.offGroups = cbStrTab - 1;862 863 if (cchDest)864 {865 pReq->u.In.offDestination = off;866 memcpy(&pReq->u.In.szStrings[off], pszDest, cchDest + 1);867 off += cchDest + 1;868 }869 else870 pReq->u.In.offDestination = cbStrTab - 1;871 872 if (!off)873 {874 pReq->u.In.szStrings[0] = '\0';875 off++;876 }877 Assert(off == cbStrTab);878 Assert(pReq->u.In.szStrings[cbStrTab - 1] == '\0');879 880 881 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOGGER_SETTINGS(cbStrTab), pReq, SUP_IOCTL_LOGGER_SETTINGS_SIZE(cbStrTab));882 if (RT_SUCCESS(rc))883 rc = pReq->Hdr.rc;884 return rc;885 }886 887 888 SUPR3DECL(int) SUPR3LoggerSettings(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)889 {890 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_SETTINGS, pszFlags, pszGroups, pszDest);891 }892 893 894 SUPR3DECL(int) SUPR3LoggerCreate(SUPLOGGER enmWhich, const char *pszFlags, const char *pszGroups, const char *pszDest)895 {896 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_CREATE, pszFlags, pszGroups, pszDest);897 }898 899 900 SUPR3DECL(int) SUPR3LoggerDestroy(SUPLOGGER enmWhich)901 {902 return supR3LoggerSettings(enmWhich, SUPLOGGERSETTINGS_WHAT_DESTROY, NULL, NULL, NULL);903 }904 905 906 SUPR3DECL(int) SUPR3PageAlloc(size_t cPages, void **ppvPages)907 {908 /*909 * Validate.910 */911 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);912 *ppvPages = NULL;913 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);914 915 /*916 * Call OS specific worker.917 */918 return suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);919 }920 921 922 SUPR3DECL(int) SUPR3PageFree(void *pvPages, size_t cPages)923 {924 /*925 * Validate.926 */927 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);928 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);929 930 /*931 * Call OS specific worker.932 */933 return suplibOsPageFree(&g_supLibData, pvPages, cPages);934 }935 936 937 /**938 * Locks down the physical memory backing a virtual memory939 * range in the current process.940 *941 * @returns VBox status code.942 * @param pvStart Start of virtual memory range.943 * Must be page aligned.944 * @param cPages Number of pages.945 * @param paPages Where to store the physical page addresses returned.946 * On entry this will point to an array of with cbMemory >> PAGE_SHIFT entries.947 */948 SUPR3DECL(int) supR3PageLock(void *pvStart, size_t cPages, PSUPPAGE paPages)949 {950 /*951 * Validate.952 */953 AssertPtr(pvStart);954 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));955 AssertPtr(paPages);956 957 /* fake */958 if (RT_UNLIKELY(g_u32FakeMode))959 {960 RTHCPHYS Phys = (uintptr_t)pvStart + PAGE_SIZE * 1024;961 size_t iPage = cPages;962 while (iPage-- > 0)963 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);964 return VINF_SUCCESS;965 }966 967 /*968 * Issue IOCtl to the SUPDRV kernel module.969 */970 int rc;971 PSUPPAGELOCK pReq = (PSUPPAGELOCK)RTMemTmpAllocZ(SUP_IOCTL_PAGE_LOCK_SIZE(cPages));972 if (RT_LIKELY(pReq))973 {974 pReq->Hdr.u32Cookie = g_u32Cookie;975 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;976 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_LOCK_SIZE_IN;977 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_LOCK_SIZE_OUT(cPages);978 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;979 pReq->Hdr.rc = VERR_INTERNAL_ERROR;980 pReq->u.In.pvR3 = pvStart;981 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);982 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_LOCK, pReq, SUP_IOCTL_PAGE_LOCK_SIZE(cPages));983 if (RT_SUCCESS(rc))984 rc = pReq->Hdr.rc;985 if (RT_SUCCESS(rc))986 {987 for (uint32_t iPage = 0; iPage < cPages; iPage++)988 {989 paPages[iPage].uReserved = 0;990 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];991 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));992 }993 }994 RTMemTmpFree(pReq);995 }996 else997 rc = VERR_NO_TMP_MEMORY;998 999 return rc;1000 }1001 1002 1003 /**1004 * Releases locked down pages.1005 *1006 * @returns VBox status code.1007 * @param pvStart Start of virtual memory range previously locked1008 * down by SUPPageLock().1009 */1010 SUPR3DECL(int) supR3PageUnlock(void *pvStart)1011 {1012 /*1013 * Validate.1014 */1015 AssertPtr(pvStart);1016 AssertMsg(RT_ALIGN_P(pvStart, PAGE_SIZE) == pvStart, ("pvStart (%p) must be page aligned\n", pvStart));1017 1018 /* fake */1019 if (RT_UNLIKELY(g_u32FakeMode))1020 return VINF_SUCCESS;1021 1022 /*1023 * Issue IOCtl to the SUPDRV kernel module.1024 */1025 SUPPAGEUNLOCK Req;1026 Req.Hdr.u32Cookie = g_u32Cookie;1027 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1028 Req.Hdr.cbIn = SUP_IOCTL_PAGE_UNLOCK_SIZE_IN;1029 Req.Hdr.cbOut = SUP_IOCTL_PAGE_UNLOCK_SIZE_OUT;1030 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1031 Req.Hdr.rc = VERR_INTERNAL_ERROR;1032 Req.u.In.pvR3 = pvStart;1033 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_UNLOCK, &Req, SUP_IOCTL_PAGE_UNLOCK_SIZE);1034 if (RT_SUCCESS(rc))1035 rc = Req.Hdr.rc;1036 return rc;1037 }1038 1039 1040 /**1041 * Fallback for SUPR3PageAllocEx on systems where RTR0MemObjPhysAllocNC isn't1042 * supported.1043 */1044 static int supPagePageAllocNoKernelFallback(size_t cPages, void **ppvPages, PSUPPAGE paPages)1045 {1046 int rc = suplibOsPageAlloc(&g_supLibData, cPages, ppvPages);1047 if (RT_SUCCESS(rc))1048 {1049 if (!paPages)1050 paPages = (PSUPPAGE)alloca(sizeof(paPages[0]) * cPages);1051 rc = supR3PageLock(*ppvPages, cPages, paPages);1052 if (RT_FAILURE(rc))1053 suplibOsPageFree(&g_supLibData, *ppvPages, cPages);1054 }1055 return rc;1056 }1057 1058 1059 SUPR3DECL(int) SUPR3PageAllocEx(size_t cPages, uint32_t fFlags, void **ppvPages, PRTR0PTR pR0Ptr, PSUPPAGE paPages)1060 {1061 /*1062 * Validate.1063 */1064 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);1065 *ppvPages = NULL;1066 AssertPtrNullReturn(pR0Ptr, VERR_INVALID_POINTER);1067 if (pR0Ptr)1068 *pR0Ptr = NIL_RTR0PTR;1069 AssertPtrNullReturn(paPages, VERR_INVALID_POINTER);1070 AssertMsgReturn(cPages > 0 && cPages <= VBOX_MAX_ALLOC_PAGE_COUNT, ("cPages=%zu\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);1071 AssertReturn(!fFlags, VERR_INVALID_PARAMETER);1072 1073 /* fake */1074 if (RT_UNLIKELY(g_u32FakeMode))1075 {1076 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);1077 if (!pv)1078 return VERR_NO_MEMORY;1079 *ppvPages = pv;1080 if (pR0Ptr)1081 *pR0Ptr = (RTR0PTR)pv;1082 if (paPages)1083 for (size_t iPage = 0; iPage < cPages; iPage++)1084 {1085 paPages[iPage].uReserved = 0;1086 paPages[iPage].Phys = (iPage + 4321) << PAGE_SHIFT;1087 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));1088 }1089 return VINF_SUCCESS;1090 }1091 1092 /*1093 * Use fallback for non-R0 mapping?1094 */1095 if ( !pR0Ptr1096 && !g_fSupportsPageAllocNoKernel)1097 return supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);1098 1099 /*1100 * Issue IOCtl to the SUPDRV kernel module.1101 */1102 int rc;1103 PSUPPAGEALLOCEX pReq = (PSUPPAGEALLOCEX)RTMemTmpAllocZ(SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));1104 if (pReq)1105 {1106 pReq->Hdr.u32Cookie = g_u32Cookie;1107 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;1108 pReq->Hdr.cbIn = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_IN;1109 pReq->Hdr.cbOut = SUP_IOCTL_PAGE_ALLOC_EX_SIZE_OUT(cPages);1110 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;1111 pReq->Hdr.rc = VERR_INTERNAL_ERROR;1112 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);1113 pReq->u.In.fKernelMapping = pR0Ptr != NULL;1114 pReq->u.In.fUserMapping = true;1115 pReq->u.In.fReserved0 = false;1116 pReq->u.In.fReserved1 = false;1117 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_ALLOC_EX, pReq, SUP_IOCTL_PAGE_ALLOC_EX_SIZE(cPages));1118 if (RT_SUCCESS(rc))1119 {1120 rc = pReq->Hdr.rc;1121 if (RT_SUCCESS(rc))1122 {1123 *ppvPages = pReq->u.Out.pvR3;1124 if (pR0Ptr)1125 *pR0Ptr = pReq->u.Out.pvR0;1126 if (paPages)1127 for (size_t iPage = 0; iPage < cPages; iPage++)1128 {1129 paPages[iPage].uReserved = 0;1130 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];1131 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));1132 }1133 #ifdef RT_OS_DARWIN /* HACK ALERT! */1134 supR3TouchPages(pReq->u.Out.pvR3, cPages);1135 #endif1136 }1137 else if ( rc == VERR_NOT_SUPPORTED1138 && !pR0Ptr)1139 {1140 g_fSupportsPageAllocNoKernel = false;1141 rc = supPagePageAllocNoKernelFallback(cPages, ppvPages, paPages);1142 }1143 }1144 1145 RTMemTmpFree(pReq);1146 }1147 else1148 rc = VERR_NO_TMP_MEMORY;1149 return rc;1150 1151 }1152 1153 1154 SUPR3DECL(int) SUPR3PageMapKernel(void *pvR3, uint32_t off, uint32_t cb, uint32_t fFlags, PRTR0PTR pR0Ptr)1155 {1156 /*1157 * Validate.1158 */1159 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);1160 AssertPtrReturn(pR0Ptr, VERR_INVALID_POINTER);1161 Assert(!(off & PAGE_OFFSET_MASK));1162 Assert(!(cb & PAGE_OFFSET_MASK) && cb);1163 Assert(!fFlags);1164 *pR0Ptr = NIL_RTR0PTR;1165 1166 /* fake */1167 if (RT_UNLIKELY(g_u32FakeMode))1168 return VERR_NOT_SUPPORTED;1169 1170 /*1171 * Issue IOCtl to the SUPDRV kernel module.1172 */1173 SUPPAGEMAPKERNEL Req;1174 Req.Hdr.u32Cookie = g_u32Cookie;1175 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1176 Req.Hdr.cbIn = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_IN;1177 Req.Hdr.cbOut = SUP_IOCTL_PAGE_MAP_KERNEL_SIZE_OUT;1178 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1179 Req.Hdr.rc = VERR_INTERNAL_ERROR;1180 Req.u.In.pvR3 = pvR3;1181 Req.u.In.offSub = off;1182 Req.u.In.cbSub = cb;1183 Req.u.In.fFlags = fFlags;1184 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_MAP_KERNEL, &Req, SUP_IOCTL_PAGE_MAP_KERNEL_SIZE);1185 if (RT_SUCCESS(rc))1186 rc = Req.Hdr.rc;1187 if (RT_SUCCESS(rc))1188 *pR0Ptr = Req.u.Out.pvR0;1189 return rc;1190 }1191 1192 1193 SUPR3DECL(int) SUPR3PageProtect(void *pvR3, RTR0PTR R0Ptr, uint32_t off, uint32_t cb, uint32_t fProt)1194 {1195 /*1196 * Validate.1197 */1198 AssertPtrReturn(pvR3, VERR_INVALID_POINTER);1199 Assert(!(off & PAGE_OFFSET_MASK));1200 Assert(!(cb & PAGE_OFFSET_MASK) && cb);1201 AssertReturn(!(fProt & ~(RTMEM_PROT_NONE | RTMEM_PROT_READ | RTMEM_PROT_WRITE | RTMEM_PROT_EXEC)), VERR_INVALID_PARAMETER);1202 1203 /* fake */1204 if (RT_UNLIKELY(g_u32FakeMode))1205 return RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);1206 1207 /*1208 * Some OSes can do this from ring-3, so try that before we1209 * issue the IOCtl to the SUPDRV kernel module.1210 * (Yea, this isn't very nice, but just try get the job done for now.)1211 */1212 #if !defined(RT_OS_SOLARIS)1213 RTMemProtect((uint8_t *)pvR3 + off, cb, fProt);1214 #endif1215 1216 SUPPAGEPROTECT Req;1217 Req.Hdr.u32Cookie = g_u32Cookie;1218 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1219 Req.Hdr.cbIn = SUP_IOCTL_PAGE_PROTECT_SIZE_IN;1220 Req.Hdr.cbOut = SUP_IOCTL_PAGE_PROTECT_SIZE_OUT;1221 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1222 Req.Hdr.rc = VERR_INTERNAL_ERROR;1223 Req.u.In.pvR3 = pvR3;1224 Req.u.In.pvR0 = R0Ptr;1225 Req.u.In.offSub = off;1226 Req.u.In.cbSub = cb;1227 Req.u.In.fProt = fProt;1228 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_PROTECT, &Req, SUP_IOCTL_PAGE_PROTECT_SIZE);1229 if (RT_SUCCESS(rc))1230 rc = Req.Hdr.rc;1231 return rc;1232 }1233 1234 1235 SUPR3DECL(int) SUPR3PageFreeEx(void *pvPages, size_t cPages)1236 {1237 /*1238 * Validate.1239 */1240 AssertPtrReturn(pvPages, VERR_INVALID_POINTER);1241 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);1242 1243 /* fake */1244 if (RT_UNLIKELY(g_u32FakeMode))1245 {1246 RTMemPageFree(pvPages, cPages * PAGE_SIZE);1247 return VINF_SUCCESS;1248 }1249 1250 /*1251 * Try normal free first, then if it fails check if we're using the fallback1252 * for the allocations without kernel mappings and attempt unlocking it.1253 */1254 NOREF(cPages);1255 SUPPAGEFREE Req;1256 Req.Hdr.u32Cookie = g_u32Cookie;1257 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1258 Req.Hdr.cbIn = SUP_IOCTL_PAGE_FREE_SIZE_IN;1259 Req.Hdr.cbOut = SUP_IOCTL_PAGE_FREE_SIZE_OUT;1260 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1261 Req.Hdr.rc = VERR_INTERNAL_ERROR;1262 Req.u.In.pvR3 = pvPages;1263 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_PAGE_FREE, &Req, SUP_IOCTL_PAGE_FREE_SIZE);1264 if (RT_SUCCESS(rc))1265 {1266 rc = Req.Hdr.rc;1267 if ( rc == VERR_INVALID_PARAMETER1268 && !g_fSupportsPageAllocNoKernel)1269 {1270 int rc2 = supR3PageUnlock(pvPages);1271 if (RT_SUCCESS(rc2))1272 rc = suplibOsPageFree(&g_supLibData, pvPages, cPages);1273 }1274 }1275 return rc;1276 }1277 1278 1279 SUPR3DECL(void *) SUPR3ContAlloc(size_t cPages, PRTR0PTR pR0Ptr, PRTHCPHYS pHCPhys)1280 {1281 /*1282 * Validate.1283 */1284 AssertPtrReturn(pHCPhys, NULL);1285 *pHCPhys = NIL_RTHCPHYS;1286 AssertPtrNullReturn(pR0Ptr, NULL);1287 if (pR0Ptr)1288 *pR0Ptr = NIL_RTR0PTR;1289 AssertPtrNullReturn(pHCPhys, NULL);1290 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), NULL);1291 1292 /* fake */1293 if (RT_UNLIKELY(g_u32FakeMode))1294 {1295 void *pv = RTMemPageAllocZ(cPages * PAGE_SIZE);1296 if (pR0Ptr)1297 *pR0Ptr = (RTR0PTR)pv;1298 if (pHCPhys)1299 *pHCPhys = (uintptr_t)pv + (PAGE_SHIFT * 1024);1300 return pv;1301 }1302 1303 /*1304 * Issue IOCtl to the SUPDRV kernel module.1305 */1306 SUPCONTALLOC Req;1307 Req.Hdr.u32Cookie = g_u32Cookie;1308 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1309 Req.Hdr.cbIn = SUP_IOCTL_CONT_ALLOC_SIZE_IN;1310 Req.Hdr.cbOut = SUP_IOCTL_CONT_ALLOC_SIZE_OUT;1311 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1312 Req.Hdr.rc = VERR_INTERNAL_ERROR;1313 Req.u.In.cPages = (uint32_t)cPages;1314 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_ALLOC, &Req, SUP_IOCTL_CONT_ALLOC_SIZE);1315 if ( RT_SUCCESS(rc)1316 && RT_SUCCESS(Req.Hdr.rc))1317 {1318 *pHCPhys = Req.u.Out.HCPhys;1319 if (pR0Ptr)1320 *pR0Ptr = Req.u.Out.pvR0;1321 #ifdef RT_OS_DARWIN /* HACK ALERT! */1322 supR3TouchPages(Req.u.Out.pvR3, cPages);1323 #endif1324 return Req.u.Out.pvR3;1325 }1326 1327 return NULL;1328 }1329 1330 1331 SUPR3DECL(int) SUPR3ContFree(void *pv, size_t cPages)1332 {1333 /*1334 * Validate.1335 */1336 if (!pv)1337 return VINF_SUCCESS;1338 AssertPtrReturn(pv, VERR_INVALID_POINTER);1339 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);1340 1341 /* fake */1342 if (RT_UNLIKELY(g_u32FakeMode))1343 {1344 RTMemPageFree(pv, cPages * PAGE_SIZE);1345 return VINF_SUCCESS;1346 }1347 1348 /*1349 * Issue IOCtl to the SUPDRV kernel module.1350 */1351 SUPCONTFREE Req;1352 Req.Hdr.u32Cookie = g_u32Cookie;1353 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1354 Req.Hdr.cbIn = SUP_IOCTL_CONT_FREE_SIZE_IN;1355 Req.Hdr.cbOut = SUP_IOCTL_CONT_FREE_SIZE_OUT;1356 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1357 Req.Hdr.rc = VERR_INTERNAL_ERROR;1358 Req.u.In.pvR3 = pv;1359 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_CONT_FREE, &Req, SUP_IOCTL_CONT_FREE_SIZE);1360 if (RT_SUCCESS(rc))1361 rc = Req.Hdr.rc;1362 return rc;1363 }1364 1365 1366 SUPR3DECL(int) SUPR3LowAlloc(size_t cPages, void **ppvPages, PRTR0PTR ppvPagesR0, PSUPPAGE paPages)1367 {1368 /*1369 * Validate.1370 */1371 AssertPtrReturn(ppvPages, VERR_INVALID_POINTER);1372 *ppvPages = NULL;1373 AssertPtrReturn(paPages, VERR_INVALID_POINTER);1374 AssertMsgReturn(cPages > 0 && cPages < 256, ("cPages=%d must be > 0 and < 256\n", cPages), VERR_PAGE_COUNT_OUT_OF_RANGE);1375 1376 /* fake */1377 if (RT_UNLIKELY(g_u32FakeMode))1378 {1379 *ppvPages = RTMemPageAllocZ((size_t)cPages * PAGE_SIZE);1380 if (!*ppvPages)1381 return VERR_NO_LOW_MEMORY;1382 1383 /* fake physical addresses. */1384 RTHCPHYS Phys = (uintptr_t)*ppvPages + PAGE_SIZE * 1024;1385 size_t iPage = cPages;1386 while (iPage-- > 0)1387 paPages[iPage].Phys = Phys + (iPage << PAGE_SHIFT);1388 return VINF_SUCCESS;1389 }1390 1391 /*1392 * Issue IOCtl to the SUPDRV kernel module.1393 */1394 int rc;1395 PSUPLOWALLOC pReq = (PSUPLOWALLOC)RTMemTmpAllocZ(SUP_IOCTL_LOW_ALLOC_SIZE(cPages));1396 if (pReq)1397 {1398 pReq->Hdr.u32Cookie = g_u32Cookie;1399 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;1400 pReq->Hdr.cbIn = SUP_IOCTL_LOW_ALLOC_SIZE_IN;1401 pReq->Hdr.cbOut = SUP_IOCTL_LOW_ALLOC_SIZE_OUT(cPages);1402 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_MAGIC | SUPREQHDR_FLAGS_EXTRA_OUT;1403 pReq->Hdr.rc = VERR_INTERNAL_ERROR;1404 pReq->u.In.cPages = (uint32_t)cPages; AssertRelease(pReq->u.In.cPages == cPages);1405 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_ALLOC, pReq, SUP_IOCTL_LOW_ALLOC_SIZE(cPages));1406 if (RT_SUCCESS(rc))1407 rc = pReq->Hdr.rc;1408 if (RT_SUCCESS(rc))1409 {1410 *ppvPages = pReq->u.Out.pvR3;1411 if (ppvPagesR0)1412 *ppvPagesR0 = pReq->u.Out.pvR0;1413 if (paPages)1414 for (size_t iPage = 0; iPage < cPages; iPage++)1415 {1416 paPages[iPage].uReserved = 0;1417 paPages[iPage].Phys = pReq->u.Out.aPages[iPage];1418 Assert(!(paPages[iPage].Phys & ~X86_PTE_PAE_PG_MASK));1419 Assert(paPages[iPage].Phys <= UINT32_C(0xfffff000));1420 }1421 #ifdef RT_OS_DARWIN /* HACK ALERT! */1422 supR3TouchPages(pReq->u.Out.pvR3, cPages);1423 #endif1424 }1425 RTMemTmpFree(pReq);1426 }1427 else1428 rc = VERR_NO_TMP_MEMORY;1429 1430 return rc;1431 }1432 1433 1434 SUPR3DECL(int) SUPR3LowFree(void *pv, size_t cPages)1435 {1436 /*1437 * Validate.1438 */1439 if (!pv)1440 return VINF_SUCCESS;1441 AssertPtrReturn(pv, VERR_INVALID_POINTER);1442 AssertReturn(cPages > 0, VERR_PAGE_COUNT_OUT_OF_RANGE);1443 1444 /* fake */1445 if (RT_UNLIKELY(g_u32FakeMode))1446 {1447 RTMemPageFree(pv, cPages * PAGE_SIZE);1448 return VINF_SUCCESS;1449 }1450 1451 /*1452 * Issue IOCtl to the SUPDRV kernel module.1453 */1454 SUPCONTFREE Req;1455 Req.Hdr.u32Cookie = g_u32Cookie;1456 Req.Hdr.u32SessionCookie = g_u32SessionCookie;1457 Req.Hdr.cbIn = SUP_IOCTL_LOW_FREE_SIZE_IN;1458 Req.Hdr.cbOut = SUP_IOCTL_LOW_FREE_SIZE_OUT;1459 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;1460 Req.Hdr.rc = VERR_INTERNAL_ERROR;1461 Req.u.In.pvR3 = pv;1462 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LOW_FREE, &Req, SUP_IOCTL_LOW_FREE_SIZE);1463 if (RT_SUCCESS(rc))1464 rc = Req.Hdr.rc;1465 return rc;1466 }1467 1468 1469 SUPR3DECL(int) SUPR3HardenedVerifyFile(const char *pszFilename, const char *pszMsg, PRTFILE phFile)1470 {1471 /*1472 * Quick input validation.1473 */1474 AssertPtr(pszFilename);1475 AssertPtr(pszMsg);1476 AssertReturn(!phFile, VERR_NOT_IMPLEMENTED); /** @todo Implement this. The deal is that we make sure the1477 file is the same we verified after opening it. */1478 1479 /*1480 * Only do the actual check in hardened builds.1481 */1482 #ifdef VBOX_WITH_HARDENING1483 int rc = supR3HardenedVerifyFixedFile(pszFilename, false /* fFatal */);1484 if (RT_FAILURE(rc))1485 LogRel(("SUPR3HardenedVerifyFile: %s: Verification of \"%s\" failed, rc=%Rrc\n", pszMsg, pszFilename, rc));1486 return rc;1487 #else1488 return VINF_SUCCESS;1489 #endif1490 }1491 1492 1493 SUPR3DECL(int) SUPR3HardenedVerifySelf(const char *pszArgv0, bool fInternal, PRTERRINFO pErrInfo)1494 {1495 /*1496 * Quick input validation.1497 */1498 AssertPtr(pszArgv0);1499 RTErrInfoClear(pErrInfo);1500 1501 /*1502 * Get the executable image path as we need it for all the tests here.1503 */1504 char szExecPath[RTPATH_MAX];1505 if (!RTProcGetExecutablePath(szExecPath, sizeof(szExecPath)))1506 return RTErrInfoSet(pErrInfo, VERR_INTERNAL_ERROR_2, "RTProcGetExecutablePath failed");1507 1508 int rc;1509 if (fInternal)1510 {1511 /*1512 * Internal applications must be launched directly without any PATH1513 * searching involved.1514 */1515 if (RTPathCompare(pszArgv0, szExecPath) != 0)1516 return RTErrInfoSetF(pErrInfo, VERR_SUPLIB_INVALID_ARGV0_INTERNAL,1517 "argv[0] does not match the executable image path: '%s' != '%s'", pszArgv0, szExecPath);1518 1519 /*1520 * Internal applications must reside in or under the1521 * RTPathAppPrivateArch directory.1522 */1523 char szAppPrivateArch[RTPATH_MAX];1524 rc = RTPathAppPrivateArch(szAppPrivateArch, sizeof(szAppPrivateArch));1525 if (RT_FAILURE(rc))1526 return RTErrInfoSetF(pErrInfo, VERR_SUPLIB_INVALID_ARGV0_INTERNAL,1527 "RTPathAppPrivateArch failed with rc=%Rrc", rc);1528 size_t cchAppPrivateArch = strlen(szAppPrivateArch);1529 if ( cchAppPrivateArch >= strlen(szExecPath)1530 || !RTPATH_IS_SLASH(szExecPath[cchAppPrivateArch]))1531 return RTErrInfoSet(pErrInfo, VERR_SUPLIB_INVALID_INTERNAL_APP_DIR,1532 "Internal executable does reside under RTPathAppPrivateArch");1533 szExecPath[cchAppPrivateArch] = '\0';1534 if (RTPathCompare(szExecPath, szAppPrivateArch) != 0)1535 return RTErrInfoSet(pErrInfo, VERR_SUPLIB_INVALID_INTERNAL_APP_DIR,1536 "Internal executable does reside under RTPathAppPrivateArch");1537 szExecPath[cchAppPrivateArch] = RTPATH_SLASH;1538 }1539 1540 #ifdef VBOX_WITH_HARDENING1541 /*1542 * Verify that the image file and parent directories are sane.1543 */1544 rc = supR3HardenedVerifyFile(szExecPath, RTHCUINTPTR_MAX, pErrInfo);1545 if (RT_FAILURE(rc))1546 return rc;1547 #endif1548 1549 return VINF_SUCCESS;1550 }1551 1552 1553 SUPR3DECL(int) SUPR3HardenedVerifyDir(const char *pszDirPath, bool fRecursive, bool fCheckFiles, PRTERRINFO pErrInfo)1554 {1555 /*1556 * Quick input validation1557 */1558 AssertPtr(pszDirPath);1559 RTErrInfoClear(pErrInfo);1560 1561 /*1562 * Only do the actual check in hardened builds.1563 */1564 #ifdef VBOX_WITH_HARDENING1565 int rc = supR3HardenedVerifyDir(pszDirPath, fRecursive, fCheckFiles, pErrInfo);1566 if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))1567 LogRel(("supR3HardenedVerifyDir: Verification of \"%s\" failed, rc=%Rrc\n", pszDirPath, rc));1568 return rc;1569 #else1570 NOREF(pszDirPath); NOREF(fRecursive); NOREF(fCheckFiles);1571 return VINF_SUCCESS;1572 #endif1573 }1574 1575 1576 SUPR3DECL(int) SUPR3HardenedVerifyPlugIn(const char *pszFilename, PRTERRINFO pErrInfo)1577 {1578 /*1579 * Quick input validation1580 */1581 AssertPtr(pszFilename);1582 RTErrInfoClear(pErrInfo);1583 1584 /*1585 * Only do the actual check in hardened builds.1586 */1587 #ifdef VBOX_WITH_HARDENING1588 int rc = supR3HardenedVerifyFile(pszFilename, RTHCUINTPTR_MAX, pErrInfo);1589 if (RT_FAILURE(rc) && !RTErrInfoIsSet(pErrInfo))1590 LogRel(("supR3HardenedVerifyFile: Verification of \"%s\" failed, rc=%Rrc\n", pszFilename, rc));1591 return rc;1592 #else1593 return VINF_SUCCESS;1594 #endif1595 }1596 100 1597 101 … … 1692 196 1693 197 /* iterate the function table. */ 1694 int c = g_p Functions->u.Out.cFunctions;1695 PSUPFUNC pFunc = &g_p Functions->u.Out.aFunctions[0];198 int c = g_pSupFunctions->u.Out.cFunctions; 199 PSUPFUNC pFunc = &g_pSupFunctions->u.Out.aFunctions[0]; 1696 200 while (c-- > 0) 1697 201 { … … 1743 247 * Despair. 1744 248 */ 1745 c = g_p Functions->u.Out.cFunctions;1746 pFunc = &g_p Functions->u.Out.aFunctions[0];249 c = g_pSupFunctions->u.Out.cFunctions; 250 pFunc = &g_pSupFunctions->u.Out.aFunctions[0]; 1747 251 while (c-- > 0) 1748 252 { 1749 RTAssertMsg2Weak("%d: %s\n", g_p Functions->u.Out.cFunctions - c, pFunc->szName);253 RTAssertMsg2Weak("%d: %s\n", g_pSupFunctions->u.Out.cFunctions - c, pFunc->szName); 1750 254 pFunc++; 1751 255 } 1752 256 1753 257 AssertLogRelMsgFailed(("%s is importing %s which we couldn't find\n", pvUser, pszSymbol)); 1754 if (g_u 32FakeMode)258 if (g_uSupFakeMode) 1755 259 { 1756 260 *pValue = 0xdeadbeef; … … 1884 388 strcpy(OpenReq.u.In.szName, pszModule); 1885 389 strcpy(OpenReq.u.In.szFilename, pszFilename); 1886 if (!g_u 32FakeMode)390 if (!g_uSupFakeMode) 1887 391 { 1888 392 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_OPEN, &OpenReq, SUP_IOCTL_LDR_OPEN_SIZE); … … 1997 501 pLoadReq->u.In.cbImageWithTabs = cbImageWithTabs; 1998 502 pLoadReq->u.In.pvImageBase = OpenReq.u.Out.pvImageBase; 1999 if (!g_u 32FakeMode)503 if (!g_uSupFakeMode) 2000 504 { 2001 505 rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_LDR_LOAD, pLoadReq, SUP_IOCTL_LDR_LOAD_SIZE(cbImageWithTabs)); … … 2066 570 { 2067 571 /* fake */ 2068 if (RT_UNLIKELY(g_u 32FakeMode))572 if (RT_UNLIKELY(g_uSupFakeMode)) 2069 573 { 2070 574 g_pvVMMR0 = NIL_RTR0PTR; … … 2098 602 2099 603 /* fake */ 2100 if (RT_UNLIKELY(g_u 32FakeMode))604 if (RT_UNLIKELY(g_uSupFakeMode)) 2101 605 { 2102 606 *ppvValue = (void *)(uintptr_t)0xdeadf00d; … … 2141 645 2142 646 2143 SUPR3DECL(int) SUPR3GipGetPhys(PRTHCPHYS pHCPhys)2144 {2145 if (g_pSUPGlobalInfoPage)2146 {2147 *pHCPhys = g_HCPhysSUPGlobalInfoPage;2148 return VINF_SUCCESS;2149 }2150 *pHCPhys = NIL_RTHCPHYS;2151 return VERR_WRONG_ORDER;2152 }2153 2154 2155 647 /** 2156 648 * Worker for SUPR3HardenedLdrLoad and SUPR3HardenedLdrLoadAppPriv. … … 2305 797 2306 798 2307 SUPR3DECL(int) SUPR3QueryVTxSupported(void)2308 {2309 #ifdef RT_OS_LINUX2310 return suplibOsQueryVTxSupported();2311 #else2312 return VINF_SUCCESS;2313 #endif2314 }2315 2316 2317 SUPR3DECL(int) SUPR3QueryVTCaps(uint32_t *pfCaps)2318 {2319 AssertPtrReturn(pfCaps, VERR_INVALID_POINTER);2320 2321 *pfCaps = 0;2322 2323 /* fake */2324 if (RT_UNLIKELY(g_u32FakeMode))2325 return VINF_SUCCESS;2326 2327 /*2328 * Issue IOCtl to the SUPDRV kernel module.2329 */2330 SUPVTCAPS Req;2331 Req.Hdr.u32Cookie = g_u32Cookie;2332 Req.Hdr.u32SessionCookie = g_u32SessionCookie;2333 Req.Hdr.cbIn = SUP_IOCTL_VT_CAPS_SIZE_IN;2334 Req.Hdr.cbOut = SUP_IOCTL_VT_CAPS_SIZE_OUT;2335 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2336 Req.Hdr.rc = VERR_INTERNAL_ERROR;2337 Req.u.Out.Caps = 0;2338 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_VT_CAPS, &Req, SUP_IOCTL_VT_CAPS_SIZE);2339 if (RT_SUCCESS(rc))2340 {2341 rc = Req.Hdr.rc;2342 if (RT_SUCCESS(rc))2343 *pfCaps = Req.u.Out.Caps;2344 }2345 return rc;2346 }2347 2348 2349 SUPR3DECL(int) SUPR3TracerOpen(uint32_t uCookie, uintptr_t uArg)2350 {2351 /* fake */2352 if (RT_UNLIKELY(g_u32FakeMode))2353 return VINF_SUCCESS;2354 2355 /*2356 * Issue IOCtl to the SUPDRV kernel module.2357 */2358 SUPTRACEROPEN Req;2359 Req.Hdr.u32Cookie = g_u32Cookie;2360 Req.Hdr.u32SessionCookie= g_u32SessionCookie;2361 Req.Hdr.cbIn = SUP_IOCTL_TRACER_OPEN_SIZE_IN;2362 Req.Hdr.cbOut = SUP_IOCTL_TRACER_OPEN_SIZE_OUT;2363 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2364 Req.Hdr.rc = VERR_INTERNAL_ERROR;2365 Req.u.In.uCookie = uCookie;2366 Req.u.In.uArg = uArg;2367 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_OPEN, &Req, SUP_IOCTL_TRACER_OPEN_SIZE);2368 if (RT_SUCCESS(rc))2369 rc = Req.Hdr.rc;2370 return rc;2371 }2372 2373 2374 SUPR3DECL(int) SUPR3TracerClose(void)2375 {2376 /* fake */2377 if (RT_UNLIKELY(g_u32FakeMode))2378 return VINF_SUCCESS;2379 2380 /*2381 * Issue IOCtl to the SUPDRV kernel module.2382 */2383 SUPREQHDR Req;2384 Req.u32Cookie = g_u32Cookie;2385 Req.u32SessionCookie= g_u32SessionCookie;2386 Req.cbIn = SUP_IOCTL_TRACER_OPEN_SIZE_IN;2387 Req.cbOut = SUP_IOCTL_TRACER_OPEN_SIZE_OUT;2388 Req.fFlags = SUPREQHDR_FLAGS_DEFAULT;2389 Req.rc = VERR_INTERNAL_ERROR;2390 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_CLOSE, &Req, SUP_IOCTL_TRACER_CLOSE_SIZE);2391 if (RT_SUCCESS(rc))2392 rc = Req.rc;2393 return rc;2394 }2395 2396 2397 SUPR3DECL(int) SUPR3TracerIoCtl(uintptr_t uCmd, uintptr_t uArg, int32_t *piRetVal)2398 {2399 /* fake */2400 if (RT_UNLIKELY(g_u32FakeMode))2401 {2402 *piRetVal = -1;2403 return VERR_NOT_SUPPORTED;2404 }2405 2406 /*2407 * Issue IOCtl to the SUPDRV kernel module.2408 */2409 SUPTRACERIOCTL Req;2410 Req.Hdr.u32Cookie = g_u32Cookie;2411 Req.Hdr.u32SessionCookie= g_u32SessionCookie;2412 Req.Hdr.cbIn = SUP_IOCTL_TRACER_IOCTL_SIZE_IN;2413 Req.Hdr.cbOut = SUP_IOCTL_TRACER_IOCTL_SIZE_OUT;2414 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2415 Req.Hdr.rc = VERR_INTERNAL_ERROR;2416 Req.u.In.uCmd = uCmd;2417 Req.u.In.uArg = uArg;2418 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_IOCTL, &Req, SUP_IOCTL_TRACER_IOCTL_SIZE);2419 if (RT_SUCCESS(rc))2420 {2421 rc = Req.Hdr.rc;2422 *piRetVal = Req.u.Out.iRetVal;2423 }2424 return rc;2425 }2426 2427 2428 2429 typedef struct SUPDRVTRACERSTRTAB2430 {2431 /** Pointer to the string table. */2432 char *pchStrTab;2433 /** The actual string table size. */2434 uint32_t cbStrTab;2435 /** The original string pointers. */2436 RTUINTPTR apszOrgFunctions[1];2437 } SUPDRVTRACERSTRTAB, *PSUPDRVTRACERSTRTAB;2438 2439 2440 /**2441 * Destroys a string table, restoring the original pszFunction member valus.2442 *2443 * @param pThis The string table structure.2444 * @param paProbLocs The probe location array.2445 * @param cProbLocs The number of probe locations.2446 */2447 static void supr3TracerDestroyStrTab(PSUPDRVTRACERSTRTAB pThis, PVTGPROBELOC32 paProbeLocs32, PVTGPROBELOC64 paProbeLocs64,2448 uint32_t cProbeLocs, bool f32Bit)2449 {2450 /* Restore. */2451 size_t i = cProbeLocs;2452 if (f32Bit)2453 while (i--)2454 paProbeLocs32[i].pszFunction = (uint32_t)pThis->apszOrgFunctions[i];2455 else2456 while (i--)2457 paProbeLocs64[i].pszFunction = pThis->apszOrgFunctions[i];2458 2459 /* Free. */2460 RTMemFree(pThis->pchStrTab);2461 RTMemFree(pThis);2462 }2463 2464 2465 /**2466 * Creates a string table for the pszFunction members in the probe location2467 * array.2468 *2469 * This will save and replace the pszFunction members with offsets.2470 *2471 * @returns Pointer to a string table structure. NULL on failure.2472 * @param paProbLocs The probe location array.2473 * @param cProbLocs The number of elements in the array.2474 * @param cBits2475 */2476 static PSUPDRVTRACERSTRTAB supr3TracerCreateStrTab(PVTGPROBELOC32 paProbeLocs32,2477 PVTGPROBELOC64 paProbeLocs64,2478 uint32_t cProbeLocs,2479 RTUINTPTR offDelta,2480 bool f32Bit)2481 {2482 if (cProbeLocs > _128K)2483 return NULL;2484 2485 /*2486 * Allocate the string table structures.2487 */2488 size_t cbThis = RT_OFFSETOF(SUPDRVTRACERSTRTAB, apszOrgFunctions[cProbeLocs]);2489 PSUPDRVTRACERSTRTAB pThis = (PSUPDRVTRACERSTRTAB)RTMemAlloc(cbThis);2490 if (!pThis)2491 return NULL;2492 2493 uint32_t const cHashBits = cProbeLocs * 2 - 1;2494 uint32_t *pbmHash = (uint32_t *)RTMemAllocZ(RT_ALIGN_32(cHashBits, 64) / 8 );2495 if (!pbmHash)2496 {2497 RTMemFree(pThis);2498 return NULL;2499 }2500 2501 /*2502 * Calc the max string table size and save the orignal pointers so we can2503 * replace them later.2504 */2505 size_t cbMax = 1;2506 for (uint32_t i = 0; i < cProbeLocs; i++)2507 {2508 pThis->apszOrgFunctions[i] = f32Bit ? paProbeLocs32[i].pszFunction : paProbeLocs64[i].pszFunction;2509 const char *pszFunction = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);2510 size_t cch = strlen(pszFunction);2511 if (cch > _1K)2512 {2513 cbMax = 0;2514 break;2515 }2516 cbMax += cch + 1;2517 }2518 2519 /* Alloc space for it. */2520 if (cbMax > 0)2521 pThis->pchStrTab = (char *)RTMemAlloc(cbMax);2522 else2523 pThis->pchStrTab = NULL;2524 if (!pThis->pchStrTab)2525 {2526 RTMemFree(pbmHash);2527 RTMemFree(pThis);2528 return NULL;2529 }2530 2531 /*2532 * Create the string table.2533 */2534 uint32_t off = 0;2535 uint32_t offPrev = 0;2536 2537 for (uint32_t i = 0; i < cProbeLocs; i++)2538 {2539 const char * const psz = (const char *)(uintptr_t)(pThis->apszOrgFunctions[i] + offDelta);2540 size_t const cch = strlen(psz);2541 uint32_t const iHashBit = RTStrHash1(psz) % cHashBits;2542 if (ASMBitTestAndSet(pbmHash, iHashBit))2543 {2544 /* Often it's the most recent string. */2545 if ( off - offPrev < cch + 12546 || memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))2547 {2548 /* It wasn't, search the entire string table. (lazy bird) */2549 offPrev = 0;2550 while (offPrev < off)2551 {2552 size_t cchCur = strlen(&pThis->pchStrTab[offPrev]);2553 if ( cchCur == cch2554 && !memcmp(&pThis->pchStrTab[offPrev], psz, cch + 1))2555 break;2556 offPrev += (uint32_t)cchCur + 1;2557 }2558 }2559 }2560 else2561 offPrev = off;2562 2563 /* Add the string to the table. */2564 if (offPrev >= off)2565 {2566 memcpy(&pThis->pchStrTab[off], psz, cch + 1);2567 offPrev = off;2568 off += (uint32_t)cch + 1;2569 }2570 2571 /* Update the entry */2572 if (f32Bit)2573 paProbeLocs32[i].pszFunction = offPrev;2574 else2575 paProbeLocs64[i].pszFunction = offPrev;2576 }2577 2578 pThis->cbStrTab = off;2579 RTMemFree(pbmHash);2580 return pThis;2581 }2582 2583 2584 2585 SUPR3DECL(int) SUPR3TracerRegisterModule(uintptr_t hModNative, const char *pszModule, struct VTGOBJHDR *pVtgHdr,2586 RTUINTPTR uVtgHdrAddr, uint32_t fFlags)2587 {2588 /* Validate input. */2589 NOREF(hModNative);2590 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);2591 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);2592 AssertPtrReturn(pszModule, VERR_INVALID_POINTER);2593 size_t cchModule = strlen(pszModule);2594 AssertReturn(cchModule < RT_SIZEOFMEMB(SUPTRACERUMODREG, u.In.szName), VERR_FILENAME_TOO_LONG);2595 AssertReturn(!RTPathHavePath(pszModule), VERR_INVALID_PARAMETER);2596 AssertReturn(fFlags == SUP_TRACER_UMOD_FLAGS_EXE || fFlags == SUP_TRACER_UMOD_FLAGS_SHARED, VERR_INVALID_PARAMETER);2597 2598 /*2599 * Set the probe location array offset and size members. If the size is2600 * zero, don't bother ring-0 with it.2601 */2602 if (!pVtgHdr->offProbeLocs)2603 {2604 uint64_t u64Tmp = pVtgHdr->uProbeLocsEnd.u64 - pVtgHdr->uProbeLocs.u64;2605 if (u64Tmp >= UINT32_MAX)2606 return VERR_SUPDRV_VTG_BAD_HDR_TOO_MUCH;2607 pVtgHdr->cbProbeLocs = (uint32_t)u64Tmp;2608 2609 u64Tmp = pVtgHdr->uProbeLocs.u64 - uVtgHdrAddr;2610 if ((int64_t)u64Tmp != (int32_t)u64Tmp)2611 {2612 LogRel(("SUPR3TracerRegisterModule: VERR_SUPDRV_VTG_BAD_HDR_PTR - u64Tmp=%#llx uProbeLocs=%#llx uVtgHdrAddr=%RTptr\n",2613 u64Tmp, pVtgHdr->uProbeLocs.u64, uVtgHdrAddr));2614 return VERR_SUPDRV_VTG_BAD_HDR_PTR;2615 }2616 pVtgHdr->offProbeLocs = (int32_t)u64Tmp;2617 }2618 2619 if ( !pVtgHdr->cbProbeLocs2620 || !pVtgHdr->cbProbes)2621 return VINF_SUCCESS;2622 2623 /*2624 * Fake out.2625 */2626 if (RT_UNLIKELY(g_u32FakeMode))2627 return VINF_SUCCESS;2628 2629 /*2630 * Create a string table for the function names in the location array.2631 * It's somewhat easier to do that here than from ring-0.2632 */2633 size_t const cProbeLocs = pVtgHdr->cbProbeLocs2634 / (pVtgHdr->cBits == 32 ? sizeof(VTGPROBELOC32) : sizeof(VTGPROBELOC64));2635 PVTGPROBELOC paProbeLocs = (PVTGPROBELOC)((uintptr_t)pVtgHdr + pVtgHdr->offProbeLocs);2636 PSUPDRVTRACERSTRTAB pStrTab = supr3TracerCreateStrTab((PVTGPROBELOC32)paProbeLocs,2637 (PVTGPROBELOC64)paProbeLocs,2638 cProbeLocs, (uintptr_t)pVtgHdr - uVtgHdrAddr,2639 pVtgHdr->cBits == 32);2640 if (!pStrTab)2641 return VERR_NO_MEMORY;2642 2643 2644 /*2645 * Issue IOCtl to the SUPDRV kernel module.2646 */2647 SUPTRACERUMODREG Req;2648 Req.Hdr.u32Cookie = g_u32Cookie;2649 Req.Hdr.u32SessionCookie= g_u32SessionCookie;2650 Req.Hdr.cbIn = SUP_IOCTL_TRACER_UMOD_REG_SIZE_IN;2651 Req.Hdr.cbOut = SUP_IOCTL_TRACER_UMOD_REG_SIZE_OUT;2652 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2653 Req.Hdr.rc = VERR_INTERNAL_ERROR;2654 Req.u.In.uVtgHdrAddr = uVtgHdrAddr;2655 Req.u.In.R3PtrVtgHdr = pVtgHdr;2656 Req.u.In.R3PtrStrTab = pStrTab->pchStrTab;2657 Req.u.In.cbStrTab = pStrTab->cbStrTab;2658 Req.u.In.fFlags = fFlags;2659 2660 memcpy(Req.u.In.szName, pszModule, cchModule + 1);2661 if (!RTPathHasSuffix(Req.u.In.szName))2662 {2663 /* Add the default suffix if none is given. */2664 switch (fFlags & SUP_TRACER_UMOD_FLAGS_TYPE_MASK)2665 {2666 #if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)2667 case SUP_TRACER_UMOD_FLAGS_EXE:2668 if (cchModule + sizeof(".exe") <= sizeof(Req.u.In.szName))2669 strcpy(&Req.u.In.szName[cchModule], ".exe");2670 break;2671 #endif2672 2673 case SUP_TRACER_UMOD_FLAGS_SHARED:2674 {2675 const char *pszSuff = RTLdrGetSuff();2676 size_t cchSuff = strlen(pszSuff);2677 if (cchModule + cchSuff < sizeof(Req.u.In.szName))2678 memcpy(&Req.u.In.szName[cchModule], pszSuff, cchSuff + 1);2679 break;2680 }2681 }2682 }2683 2684 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_REG, &Req, SUP_IOCTL_TRACER_UMOD_REG_SIZE);2685 if (RT_SUCCESS(rc))2686 rc = Req.Hdr.rc;2687 2688 supr3TracerDestroyStrTab(pStrTab, (PVTGPROBELOC32)paProbeLocs, (PVTGPROBELOC64)paProbeLocs,2689 cProbeLocs, pVtgHdr->cBits == 32);2690 return rc;2691 }2692 2693 2694 SUPR3DECL(int) SUPR3TracerDeregisterModule(struct VTGOBJHDR *pVtgHdr)2695 {2696 /* Validate input. */2697 AssertPtrReturn(pVtgHdr, VERR_INVALID_POINTER);2698 AssertReturn(!memcmp(pVtgHdr->szMagic, VTGOBJHDR_MAGIC, sizeof(pVtgHdr->szMagic)), VERR_SUPDRV_VTG_MAGIC);2699 2700 /*2701 * Don't bother if the object is empty.2702 */2703 if ( !pVtgHdr->cbProbeLocs2704 || !pVtgHdr->cbProbes)2705 return VINF_SUCCESS;2706 2707 /*2708 * Fake out.2709 */2710 if (RT_UNLIKELY(g_u32FakeMode))2711 return VINF_SUCCESS;2712 2713 /*2714 * Issue IOCtl to the SUPDRV kernel module.2715 */2716 SUPTRACERUMODDEREG Req;2717 Req.Hdr.u32Cookie = g_u32Cookie;2718 Req.Hdr.u32SessionCookie= g_u32SessionCookie;2719 Req.Hdr.cbIn = SUP_IOCTL_TRACER_UMOD_REG_SIZE_IN;2720 Req.Hdr.cbOut = SUP_IOCTL_TRACER_UMOD_REG_SIZE_OUT;2721 Req.Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2722 Req.Hdr.rc = VERR_INTERNAL_ERROR;2723 Req.u.In.pVtgHdr = pVtgHdr;2724 2725 int rc = suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_DEREG, &Req, SUP_IOCTL_TRACER_UMOD_DEREG_SIZE);2726 if (RT_SUCCESS(rc))2727 rc = Req.Hdr.rc;2728 return rc;2729 }2730 2731 2732 DECLASM(void) suplibTracerFireProbe(PVTGPROBELOC pProbeLoc, PSUPTRACERUMODFIREPROBE pReq)2733 {2734 pReq->Hdr.u32Cookie = g_u32Cookie;2735 pReq->Hdr.u32SessionCookie = g_u32SessionCookie;2736 Assert(pReq->Hdr.cbIn == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_IN);2737 Assert(pReq->Hdr.cbOut == SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE_OUT);2738 pReq->Hdr.fFlags = SUPREQHDR_FLAGS_DEFAULT;2739 pReq->Hdr.rc = VINF_SUCCESS;2740 2741 suplibOsIOCtl(&g_supLibData, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE, pReq, SUP_IOCTL_TRACER_UMOD_FIRE_PROBE_SIZE);2742 }2743 -
trunk/src/VBox/HostDrivers/Support/darwin/SUPDrv-darwin.cpp
r47537 r49634 943 943 944 944 945 #ifdef SUPDRV_WITH_MSR_PROBER 946 947 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) 948 { 949 NOREF(uMsr); NOREF(idCpu); NOREF(puValue); 950 return VERR_NOT_SUPPORTED; 951 } 952 953 954 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) 955 { 956 NOREF(uMsr); NOREF(idCpu); NOREF(uValue); 957 return VERR_NOT_SUPPORTED; 958 } 959 960 961 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) 962 { 963 NOREF(idCpu); NOREF(pReq); 964 return VERR_NOT_SUPPORTED; 965 } 966 967 #endif /* SUPDRV_WITH_MSR_PROBER */ 968 969 970 945 971 /** 946 972 * Converts an IPRT error code to a darwin error code. -
trunk/src/VBox/HostDrivers/Support/freebsd/SUPDrv-freebsd.c
r47537 r49634 552 552 553 553 554 #ifdef SUPDRV_WITH_MSR_PROBER 555 556 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) 557 { 558 NOREF(uMsr); NOREF(idCpu); NOREF(puValue); 559 return VERR_NOT_SUPPORTED; 560 } 561 562 563 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) 564 { 565 NOREF(uMsr); NOREF(idCpu); NOREF(uValue); 566 return VERR_NOT_SUPPORTED; 567 } 568 569 570 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) 571 { 572 NOREF(idCpu); NOREF(pReq); 573 return VERR_NOT_SUPPORTED; 574 } 575 576 #endif /* SUPDRV_WITH_MSR_PROBER */ 577 578 554 579 SUPR0DECL(int) SUPR0Printf(const char *pszFormat, ...) 555 580 { -
trunk/src/VBox/HostDrivers/Support/linux/SUPDrv-linux.c
r47537 r49634 60 60 # include <linux/platform_device.h> 61 61 #endif 62 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 28)) && defined(SUPDRV_WITH_MSR_PROBER) 63 # define SUPDRV_LINUX_HAS_SAFE_MSR_API 64 # include <asm/msr.h> 65 # include <iprt/asm-amd64-x86.h> 66 #endif 67 62 68 63 69 … … 853 859 854 860 861 #ifdef SUPDRV_WITH_MSR_PROBER 862 863 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) 864 { 865 # ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API 866 uint32_t u32Low, u32High; 867 int rc; 868 869 if (idCpu == NIL_RTCPUID) 870 idCpu = RTMpCpuId(); 871 else if (!RTMpIsCpuOnline(idCpu)) 872 return VERR_CPU_OFFLINE; 873 rc = rdmsr_safe_on_cpu(idCpu, uMsr, &u32Low, &u32High); 874 if (rc >= 0) 875 { 876 *puValue = RT_MAKE_U64(u32Low, u32High); 877 return VINF_SUCCESS; 878 } 879 return VERR_ACCESS_DENIED; 880 # else 881 return VERR_NOT_SUPPORTED; 882 # endif 883 } 884 885 886 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) 887 { 888 # ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API 889 int rc; 890 891 if (idCpu == NIL_RTCPUID) 892 idCpu = RTMpCpuId(); 893 else if (!RTMpIsCpuOnline(idCpu)) 894 return VERR_CPU_OFFLINE; 895 rc = wrmsr_safe_on_cpu(idCpu, uMsr, RT_LODWORD(uValue), RT_HIDWORD(uValue)); 896 if (rc >= 0) 897 return VINF_SUCCESS; 898 return VERR_ACCESS_DENIED; 899 # else 900 return VERR_NOT_SUPPORTED; 901 # endif 902 } 903 904 # ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API 905 /** 906 * Worker for supdrvOSMsrProberModify. 907 */ 908 static DECLCALLBACK(void) supdrvOsMsrProberModifyOnCpu(RTCPUID idCpu, void *pvUser1, void *pvUser2) 909 { 910 PSUPMSRPROBER pReq = (PSUPMSRPROBER)pvUser1; 911 register uint32_t uMsr = pReq->u.In.uMsr; 912 bool const fFaster = pReq->u.In.enmOp == SUPMSRPROBEROP_MODIFY_FASTER; 913 uint64_t uBefore; 914 uint64_t uWritten; 915 uint64_t uAfter; 916 int rcBefore, rcWrite, rcAfter, rcRestore; 917 RTCCUINTREG fOldFlags; 918 919 /* Initialize result variables. */ 920 uBefore = uWritten = uAfter = 0; 921 rcWrite = rcAfter = rcRestore = -EIO; 922 923 /* 924 * Do the job. 925 */ 926 fOldFlags = ASMIntDisableFlags(); 927 ASMCompilerBarrier(); /* paranoia */ 928 if (!fFaster) 929 ASMWriteBackAndInvalidateCaches(); 930 931 rcBefore = rdmsrl_safe(uMsr, &uBefore); 932 if (rcBefore >= 0) 933 { 934 register uint64_t uRestore = uBefore; 935 uWritten = uRestore; 936 uWritten &= pReq->u.In.uArgs.Modify.fAndMask; 937 uWritten |= pReq->u.In.uArgs.Modify.fOrMask; 938 939 rcWrite = wrmsr_safe(uMsr, RT_LODWORD(uWritten), RT_HIDWORD(uWritten)); 940 rcAfter = rdmsrl_safe(uMsr, &uAfter); 941 rcRestore = wrmsr_safe(uMsr, RT_LODWORD(uRestore), RT_HIDWORD(uRestore)); 942 943 if (!fFaster) 944 { 945 ASMWriteBackAndInvalidateCaches(); 946 ASMReloadCR3(); 947 ASMNopPause(); 948 } 949 } 950 951 ASMCompilerBarrier(); /* paranoia */ 952 ASMSetFlags(fOldFlags); 953 954 /* 955 * Write out the results. 956 */ 957 pReq->u.Out.uResults.Modify.uBefore = uBefore; 958 pReq->u.Out.uResults.Modify.uWritten = uWritten; 959 pReq->u.Out.uResults.Modify.uAfter = uAfter; 960 pReq->u.Out.uResults.Modify.fBeforeGp = rcBefore < 0; 961 pReq->u.Out.uResults.Modify.fModifyGp = rcWrite < 0; 962 pReq->u.Out.uResults.Modify.fAfterGp = rcAfter < 0; 963 pReq->u.Out.uResults.Modify.fRestoreGp = rcRestore < 0; 964 RT_ZERO(pReq->u.Out.uResults.Modify.afReserved); 965 } 966 967 # endif 968 969 970 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) 971 { 972 # ifdef SUPDRV_LINUX_HAS_SAFE_MSR_API 973 if (idCpu == NIL_RTCPUID) 974 idCpu = RTMpCpuId(); 975 else if (!RTMpIsCpuOnline(idCpu)) 976 return VERR_CPU_OFFLINE; 977 return RTMpOnSpecific(idCpu, supdrvOsMsrProberModifyOnCpu, pReq, NULL); 978 # else 979 return VERR_NOT_SUPPORTED; 980 # endif 981 } 982 983 #endif /* SUPDRV_WITH_MSR_PROBER */ 984 985 855 986 /** 856 987 * Converts a supdrv error code to an linux error code. -
trunk/src/VBox/HostDrivers/Support/os2/SUPDrv-os2.cpp
r47537 r49634 421 421 422 422 423 #ifdef SUPDRV_WITH_MSR_PROBER 424 425 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) 426 { 427 NOREF(uMsr); NOREF(idCpu); NOREF(puValue); 428 return VERR_NOT_SUPPORTED; 429 } 430 431 432 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) 433 { 434 NOREF(uMsr); NOREF(idCpu); NOREF(uValue); 435 return VERR_NOT_SUPPORTED; 436 } 437 438 439 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) 440 { 441 NOREF(idCpu); NOREF(pReq); 442 return VERR_NOT_SUPPORTED; 443 } 444 445 #endif /* SUPDRV_WITH_MSR_PROBER */ 446 447 423 448 /** 424 449 * Callback for writing to the log buffer. -
trunk/src/VBox/HostDrivers/Support/solaris/SUPDrv-solaris.c
r48952 r49634 1189 1189 1190 1190 1191 #ifdef SUPDRV_WITH_MSR_PROBER 1192 1193 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) 1194 { 1195 NOREF(uMsr); NOREF(idCpu); NOREF(puValue); 1196 return VERR_NOT_SUPPORTED; 1197 } 1198 1199 1200 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) 1201 { 1202 NOREF(uMsr); NOREF(idCpu); NOREF(uValue); 1203 return VERR_NOT_SUPPORTED; 1204 } 1205 1206 1207 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) 1208 { 1209 NOREF(idCpu); NOREF(pReq); 1210 return VERR_NOT_SUPPORTED; 1211 } 1212 1213 #endif /* SUPDRV_WITH_MSR_PROBER */ 1214 1215 1191 1216 RTDECL(int) SUPR0Printf(const char *pszFormat, ...) 1192 1217 { -
trunk/src/VBox/HostDrivers/Support/win/SUPDrv-win.cpp
r48132 r49634 1035 1035 1036 1036 1037 #ifdef SUPDRV_WITH_MSR_PROBER 1038 1039 int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue) 1040 { 1041 NOREF(uMsr); NOREF(idCpu); NOREF(puValue); 1042 return VERR_NOT_SUPPORTED; 1043 } 1044 1045 1046 int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue) 1047 { 1048 NOREF(uMsr); NOREF(idCpu); NOREF(uValue); 1049 return VERR_NOT_SUPPORTED; 1050 } 1051 1052 1053 int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq) 1054 { 1055 NOREF(idCpu); NOREF(pReq); 1056 return VERR_NOT_SUPPORTED; 1057 } 1058 1059 #endif /* SUPDRV_WITH_MSR_PROBER */ 1060 1061 1037 1062 /** 1038 1063 * Converts an IPRT error code to an nt status code. -
trunk/src/VBox/Runtime/VBox/VBoxRTDeps.cpp
r48935 r49634 55 55 (PFNRT)SUPR3Init, 56 56 (PFNRT)SUPR3PageAllocEx, 57 (PFNRT)SUPR3LoadVMM, 57 58 (PFNRT)SUPSemEventCreate, 58 59 (PFNRT)SUPTracerFireProbe,
Note:
See TracChangeset
for help on using the changeset viewer.