/** * Initalizes the triple fault / boot hack. * * Always call vmmR0TripleFaultHackTerm to clean up, even when this call fails. * * @returns VBox status code. */ int vmmR0TripleFaultHackInit(void) { /* * Map the first page. */ int rc = RTR0MemObjEnterPhys(&g_hMemPage0, 0, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE); AssertRCReturn(rc, rc); rc = RTR0MemObjMapKernel(&g_hMapPage0, g_hMemPage0, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); AssertRCReturn(rc, rc); g_pbPage0 = (uint8_t *)RTR0MemObjAddress(g_hMapPage0); LogRel(("0040:0067 = %04x:%04x\n", RT_MAKE_U16(g_pbPage0[0x467+2], g_pbPage0[0x467+3]), RT_MAKE_U16(g_pbPage0[0x467+0], g_pbPage0[0x467+1]) )); /* * Allocate some "low core" memory. If that fails, just grab some memory. */ //rc = RTR0MemObjAllocPhys(&g_hMemLowCore, PAGE_SIZE, _1M - 1); //__debugbreak(); rc = RTR0MemObjEnterPhys(&g_hMemLowCore, 0x7000, PAGE_SIZE, RTMEM_CACHE_POLICY_DONT_CARE); AssertRCReturn(rc, rc); rc = RTR0MemObjMapKernel(&g_hMapLowCore, g_hMemLowCore, (void *)-1, 0, RTMEM_PROT_READ | RTMEM_PROT_WRITE); AssertRCReturn(rc, rc); g_pbLowCore = (uint8_t *)RTR0MemObjAddress(g_hMapLowCore); g_HCPhysLowCore = RTR0MemObjGetPagePhysAddr(g_hMapLowCore, 0); LogRel(("Low core at %RHp mapped at %p\n", g_HCPhysLowCore, g_pbLowCore)); /* * Save memory we'll be overwriting. */ g_pvSavedLowCore = RTMemAlloc(PAGE_SIZE); AssertReturn(g_pvSavedLowCore, VERR_NO_MEMORY); memcpy(g_pvSavedLowCore, g_pbLowCore, PAGE_SIZE); g_u32SavedVector = RT_MAKE_U32_FROM_U8(g_pbPage0[0x467], g_pbPage0[0x467+1], g_pbPage0[0x467+2], g_pbPage0[0x467+3]); g_u16SavedCadIndicator = RT_MAKE_U16(g_pbPage0[0x472], g_pbPage0[0x472+1]); /* * Install the code. */ size_t cbCode = (uintptr_t)&vmmR0TripleFaultHackEnd - (uintptr_t)&vmmR0TripleFaultHackStart; AssertLogRelReturn(cbCode <= PAGE_SIZE, VERR_OUT_OF_RANGE); memcpy(g_pbLowCore, &vmmR0TripleFaultHackStart, cbCode); g_pbPage0[0x467+0] = 0x00; g_pbPage0[0x467+1] = 0x70; g_pbPage0[0x467+2] = 0x00; g_pbPage0[0x467+3] = 0x00; g_pbPage0[0x472+0] = 0x34; g_pbPage0[0x472+1] = 0x12; /* * Configure the status port and cmos shutdown command. */ uint32_t fSaved = ASMIntDisableFlags(); ASMOutU8(0x70, 0x0f); ASMOutU8(0x71, 0x0a); ASMOutU8(0x70, 0x05); ASMInU8(0x71); ASMReloadCR3(); ASMWriteBackAndInvalidateCaches(); ASMSetFlags(fSaved); #if 1 /* For testing & debugging. */ vmmR0TripleFaultHackTripleFault(); #endif return VINF_SUCCESS; }
RTDECL(int) RTSemRWReleaseWrite(RTSEMRW hRWSem) { /* * Validate handle. */ struct RTSEMRWINTERNAL *pThis = hRWSem; AssertPtrReturn(pThis, VERR_INVALID_HANDLE); AssertReturn(pThis->u32Magic == RTSEMRW_MAGIC, VERR_INVALID_HANDLE); /* * Take critsect. */ int rc = RTCritSectEnter(&pThis->CritSect); AssertRCReturn(rc, rc); /* * Check if owner. */ RTNATIVETHREAD hNativeSelf = pThis->CritSect.NativeThreadOwner; if (pThis->hWriter != hNativeSelf) { RTCritSectLeave(&pThis->CritSect); AssertMsgFailed(("Not read-write owner of rwsem %p.\n", hRWSem)); return VERR_NOT_OWNER; } #ifdef RTSEMRW_STRICT if (pThis->cWrites > 1 || !pThis->cWriterReads) /* don't check+release if VERR_WRONG_ORDER */ { int rc9 = RTLockValidatorRecExclReleaseOwner(&pThis->ValidatorWrite, pThis->cWrites == 1); if (RT_FAILURE(rc9)) { RTCritSectLeave(&pThis->CritSect); return rc9; } } #endif /* * Release ownership and remove ourselves from the writers count. */ Assert(pThis->cWrites > 0); pThis->cWrites--; if (!pThis->cWrites) { if (RT_UNLIKELY(pThis->cWriterReads > 0)) { pThis->cWrites++; RTCritSectLeave(&pThis->CritSect); AssertMsgFailed(("All recursive read locks need to be released prior to the final write lock! (%p)n\n", pThis)); return VERR_WRONG_ORDER; } pThis->hWriter = NIL_RTNATIVETHREAD; } /* * Release the readers if no more writers waiting, otherwise the writers. */ if (!pThis->cWritesWaiting) { rc = RTSemEventMultiSignal(pThis->ReadEvent); AssertMsgRC(rc, ("RTSemEventMultiSignal failed for rwsem %p, rc=%Rrc.\n", hRWSem, rc)); pThis->fNeedResetReadEvent = true; } else { rc = RTSemEventSignal(pThis->WriteEvent); AssertMsgRC(rc, ("Failed to signal writers on rwsem %p, rc=%Rrc\n", hRWSem, rc)); } RTCritSectLeave(&pThis->CritSect); return rc; }
/** * The GC entry point. * * @returns VBox status code. * @param pVM Pointer to the VM. * @param uOperation Which operation to execute (VMMGCOPERATION). * @param uArg Argument to that operation. */ VMMRCDECL(int) VMMGCEntry(PVM pVM, unsigned uOperation, unsigned uArg, ...) { /* todo */ switch (uOperation) { /* * Init RC modules. */ case VMMGC_DO_VMMGC_INIT: { /* * Validate the svn revision (uArg) and build type (ellipsis). */ if (uArg != VMMGetSvnRev()) return VERR_VMM_RC_VERSION_MISMATCH; va_list va; va_start(va, uArg); uint32_t uBuildType = va_arg(va, uint32_t); if (uBuildType != vmmGetBuildType()) return VERR_VMM_RC_VERSION_MISMATCH; /* * Initialize the runtime. */ uint64_t u64TS = va_arg(va, uint64_t); va_end(va); int rc = RTRCInit(u64TS); Log(("VMMGCEntry: VMMGC_DO_VMMGC_INIT - uArg=%u (svn revision) u64TS=%RX64; rc=%Rrc\n", uArg, u64TS, rc)); AssertRCReturn(rc, rc); rc = PGMRegisterStringFormatTypes(); AssertRCReturn(rc, rc); rc = PGMRCDynMapInit(pVM); AssertRCReturn(rc, rc); return VINF_SUCCESS; } /* * Testcase which is used to test interrupt forwarding. * It spins for a while with interrupts enabled. */ case VMMGC_DO_TESTCASE_HYPER_INTERRUPT: { uint32_t volatile i = 0; ASMIntEnable(); while (i < _2G32) i++; ASMIntDisable(); return 0; } /* * Testcase which simply returns, this is used for * profiling of the switcher. */ case VMMGC_DO_TESTCASE_NOP: return 0; /* * Testcase executes a privileged instruction to force a world switch. (in both SVM & VMX) */ case VMMGC_DO_TESTCASE_HM_NOP: ASMRdMsr_Low(MSR_IA32_SYSENTER_CS); return 0; /* * Delay for ~100us. */ case VMMGC_DO_TESTCASE_INTERRUPT_MASKING: { uint64_t u64MaxTicks = (SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) != ~(uint64_t)0 ? SUPGetCpuHzFromGip(g_pSUPGlobalInfoPage) : _2G) / 10000; uint64_t u64StartTSC = ASMReadTSC(); uint64_t u64TicksNow; uint32_t volatile i = 0; do { /* waste some time and protect against getting stuck. */ for (uint32_t volatile j = 0; j < 1000; j++, i++) if (i > _2G32) return VERR_GENERAL_FAILURE; /* check if we're done.*/ u64TicksNow = ASMReadTSC() - u64StartTSC; } while (u64TicksNow < u64MaxTicks); return VINF_SUCCESS; } /* * Trap testcases and unknown operations. */ default: if ( uOperation >= VMMGC_DO_TESTCASE_TRAP_FIRST && uOperation < VMMGC_DO_TESTCASE_TRAP_LAST) return vmmGCTest(pVM, uOperation, uArg); return VERR_INVALID_PARAMETER; } }
VBOXDDU_DECL(int) VDDbgIoLogStartDiscard(VDIOLOGGER hIoLogger, bool fAsync, PCRTRANGE paRanges, unsigned cRanges, PVDIOLOGENT phIoLogEntry) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; PVDIOLOGENTINT pIoLogEntry = NULL; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries); if (pIoLogEntry) { IoLogEntryStart Entry; pIoLogEntry->idStart = pIoLogger->idNext++; Entry.u32Type = VDIOLOG_EVENT_START; Entry.u8AsyncIo = fAsync ? 1 : 0; Entry.u32ReqType = VDDBGIOLOGREQ_DISCARD; Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart); Entry.Discard.cRanges = RT_H2LE_U32(cRanges); /* Write new entry. */ rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { pIoLogger->offWriteNext += sizeof(Entry); IoLogEntryDiscard DiscardRange; for (unsigned i = 0; i < cRanges; i++) { DiscardRange.u64Off = RT_H2LE_U64(paRanges[i].offStart); DiscardRange.u32Discard = RT_H2LE_U32((uint32_t)paRanges[i].cbRange); rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext + i*sizeof(DiscardRange), &DiscardRange, sizeof(DiscardRange), NULL); if (RT_FAILURE(rc)) break; } if (RT_FAILURE(rc)) { pIoLogger->offWriteNext -= sizeof(Entry); rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext); } else pIoLogger->offWriteNext += cRanges * sizeof(DiscardRange); } if (RT_SUCCESS(rc)) { pIoLogEntry->tsStart = RTTimeProgramMilliTS(); pIoLogEntry->cbIo = 0; *phIoLogEntry = pIoLogEntry; } else { pIoLogger->idNext--; RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry); } } else rc = VERR_NO_MEMORY; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
VBOXDDU_DECL(int) VDDbgIoLogEventGetStartDiscard(VDIOLOGGER hIoLogger, uint64_t *pidEvent, bool *pfAsync, PRTRANGE *ppaRanges, unsigned *pcRanges) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(pidEvent, VERR_INVALID_POINTER); AssertPtrReturn(pfAsync, VERR_INVALID_POINTER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); if ( pIoLogger->u32EventTypeNext == VDIOLOG_EVENT_START && pIoLogger->enmReqTypeNext == VDDBGIOLOGREQ_DISCARD) { IoLogEntryStart Entry; rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { PRTRANGE paRanges = NULL; IoLogEntryDiscard DiscardRange; pIoLogger->offReadNext += sizeof(Entry); *pfAsync = RT_BOOL(Entry.u8AsyncIo); *pidEvent = RT_LE2H_U64(Entry.u64Id); *pcRanges = RT_LE2H_U32(Entry.Discard.cRanges); paRanges = (PRTRANGE)RTMemAllocZ(*pcRanges * sizeof(RTRANGE)); if (paRanges) { for (unsigned i = 0; i < *pcRanges; i++) { rc = RTFileReadAt(pIoLogger->hFile, pIoLogger->offReadNext + i*sizeof(DiscardRange), &DiscardRange, sizeof(DiscardRange), NULL); if (RT_FAILURE(rc)) break; paRanges[i].offStart = RT_LE2H_U64(DiscardRange.u64Off); paRanges[i].cbRange = RT_LE2H_U32(DiscardRange.u32Discard); } if (RT_SUCCESS(rc)) { pIoLogger->offReadNext += *pcRanges * sizeof(DiscardRange); *ppaRanges = paRanges; } else pIoLogger->offReadNext -= sizeof(Entry); } else rc = VERR_NO_MEMORY; } } else rc = VERR_INVALID_STATE; if (RT_SUCCESS(rc)) pIoLogger->u32EventTypeNext = 0; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
/** * @interface_method_impl{Construct a NAT network transport driver instance, * PDMDRVREG,pfnDestruct} */ static DECLCALLBACK(int) drvR3NetShaperConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVNETSHAPER pThis = PDMINS_2_DATA(pDrvIns, PDRVNETSHAPER); LogFlow(("drvNetShaperConstruct:\n")); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Init the static parts. */ pThis->pDrvInsR3 = pDrvIns; pThis->pDrvInsR0 = PDMDRVINS_2_R0PTR(pDrvIns); /* IBase */ pDrvIns->IBase.pfnQueryInterface = drvR3NetShaperIBase_QueryInterface; pThis->IBaseR0.pfnQueryInterface = drvR3NetShaperIBaseR0_QueryInterface; pThis->IBaseRC.pfnQueryInterface = drvR3NetShaperIBaseRC_QueryInterface; /* INetworkUp */ pThis->INetworkUpR3.pfnBeginXmit = drvNetShaperUp_BeginXmit; pThis->INetworkUpR3.pfnAllocBuf = drvNetShaperUp_AllocBuf; pThis->INetworkUpR3.pfnFreeBuf = drvNetShaperUp_FreeBuf; pThis->INetworkUpR3.pfnSendBuf = drvNetShaperUp_SendBuf; pThis->INetworkUpR3.pfnEndXmit = drvNetShaperUp_EndXmit; pThis->INetworkUpR3.pfnSetPromiscuousMode = drvNetShaperUp_SetPromiscuousMode; pThis->INetworkUpR3.pfnNotifyLinkChanged = drvR3NetShaperUp_NotifyLinkChanged; /* Resolve the ring-0 context interface addresses. */ int rc = pDrvIns->pHlpR3->pfnLdrGetR0InterfaceSymbols(pDrvIns, &pThis->INetworkUpR0, sizeof(pThis->INetworkUpR0), "drvNetShaperUp_", PDMINETWORKUP_SYM_LIST); AssertLogRelRCReturn(rc, rc); /* INetworkDown */ pThis->INetworkDown.pfnWaitReceiveAvail = drvR3NetShaperDown_WaitReceiveAvail; pThis->INetworkDown.pfnReceive = drvR3NetShaperDown_Receive; pThis->INetworkDown.pfnReceiveGso = drvR3NetShaperDown_ReceiveGso; pThis->INetworkDown.pfnXmitPending = drvR3NetShaperDown_XmitPending; /* INetworkConfig */ pThis->INetworkConfig.pfnGetMac = drvR3NetShaperDownCfg_GetMac; pThis->INetworkConfig.pfnGetLinkState = drvR3NetShaperDownCfg_GetLinkState; pThis->INetworkConfig.pfnSetLinkState = drvR3NetShaperDownCfg_SetLinkState; /* * Create the locks. */ rc = PDMDrvHlpCritSectInit(pDrvIns, &pThis->XmitLock, RT_SRC_POS, "NetShaper"); AssertRCReturn(rc, rc); /* * Validate the config. */ if (!CFGMR3AreValuesValid(pCfg, "BwGroup\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; /* * Find the bandwidth group we have to attach to. */ rc = CFGMR3QueryStringAlloc(pCfg, "BwGroup", &pThis->pszBwGroup); if (RT_FAILURE(rc) && rc != VERR_CFGM_VALUE_NOT_FOUND) { rc = PDMDRV_SET_ERROR(pDrvIns, rc, N_("DrvNetShaper: Configuration error: Querying \"BwGroup\" as string failed")); return rc; } else rc = VINF_SUCCESS; pThis->Filter.pIDrvNetR3 = &pThis->INetworkDown; rc = PDMDrvHlpNetShaperAttach(pDrvIns, pThis->pszBwGroup, &pThis->Filter); if (RT_FAILURE(rc)) { rc = PDMDRV_SET_ERROR(pDrvIns, rc, N_("DrvNetShaper: Configuration error: Failed to attach to bandwidth group")); return rc; } /* * Query the network port interface. */ pThis->pIAboveNet = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKDOWN); if (!pThis->pIAboveNet) { AssertMsgFailed(("Configuration error: the above device/driver didn't export the network port interface!\n")); return VERR_PDM_MISSING_INTERFACE_ABOVE; } /* * Query the network config interface. */ pThis->pIAboveConfig = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMINETWORKCONFIG); if (!pThis->pIAboveConfig) { AssertMsgFailed(("Configuration error: the above device/driver didn't export the network config interface!\n")); return VERR_PDM_MISSING_INTERFACE_ABOVE; } /* * Query the network connector interface. */ PPDMIBASE pBaseDown; rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBaseDown); if ( rc == VERR_PDM_NO_ATTACHED_DRIVER || rc == VERR_PDM_CFG_MISSING_DRIVER_NAME) { pThis->pIBelowNetR3 = NULL; pThis->pIBelowNetR0 = NIL_RTR0PTR; } else if (RT_SUCCESS(rc)) { pThis->pIBelowNetR3 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMINETWORKUP); if (!pThis->pIBelowNetR3) { AssertMsgFailed(("Configuration error: the driver below didn't export the network connector interface!\n")); return VERR_PDM_MISSING_INTERFACE_BELOW; } PPDMIBASER0 pBaseR0 = PDMIBASE_QUERY_INTERFACE(pBaseDown, PDMIBASER0); pThis->pIBelowNetR0 = pBaseR0 ? pBaseR0->pfnQueryInterface(pBaseR0, PDMINETWORKUP_IID) : NIL_RTR0PTR; } else { AssertMsgFailed(("Failed to attach to driver below! rc=%Rrc\n", rc)); return rc; } /* * Register statistics. */ PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesRequested, "Bytes/Tx/Requested", STAMUNIT_BYTES, "Number of requested TX bytes."); PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesDenied, "Bytes/Tx/Denied", STAMUNIT_BYTES, "Number of denied TX bytes."); PDMDrvHlpSTAMRegCounterEx(pDrvIns, &pThis->StatXmitBytesGranted, "Bytes/Tx/Granted", STAMUNIT_BYTES, "Number of granted TX bytes."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsRequested, "Packets/Tx/Requested", "Number of requested TX packets."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsDenied, "Packets/Tx/Denied", "Number of denied TX packets."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPktsGranted, "Packets/Tx/Granted", "Number of granted TX packets."); PDMDrvHlpSTAMRegCounter(pDrvIns, &pThis->StatXmitPendingCalled, "Tx/WakeUp", "Number of wakeup TX calls."); return VINF_SUCCESS; }
VBOXDDU_DECL(int) VDDbgIoLogStart(VDIOLOGGER hIoLogger, bool fAsync, VDDBGIOLOGREQ enmTxDir, uint64_t off, size_t cbIo, PCRTSGBUF pSgBuf, PVDIOLOGENT phIoLogEntry) { int rc = VINF_SUCCESS; PVDIOLOGGERINT pIoLogger = hIoLogger; PVDIOLOGENTINT pIoLogEntry = NULL; AssertPtrReturn(pIoLogger, VERR_INVALID_HANDLE); AssertPtrReturn(phIoLogEntry, VERR_INVALID_POINTER); AssertReturn(enmTxDir > VDDBGIOLOGREQ_INVALID && enmTxDir <= VDDBGIOLOGREQ_FLUSH, VERR_INVALID_PARAMETER); rc = RTSemFastMutexRequest(pIoLogger->hMtx); AssertRCReturn(rc, rc); pIoLogEntry = (PVDIOLOGENTINT)RTMemCacheAlloc(pIoLogger->hMemCacheIoLogEntries); if (pIoLogEntry) { IoLogEntryStart Entry; pIoLogEntry->idStart = pIoLogger->idNext++; Entry.u32Type = VDIOLOG_EVENT_START; Entry.u8AsyncIo = fAsync ? 1 : 0; Entry.u32ReqType = enmTxDir; Entry.u64Id = RT_H2LE_U64(pIoLogEntry->idStart); Entry.Io.u64Off = RT_H2LE_U64(off); Entry.Io.u64IoSize = RT_H2LE_U64(cbIo); /* Write new entry. */ rc = RTFileWriteAt(pIoLogger->hFile, pIoLogger->offWriteNext, &Entry, sizeof(Entry), NULL); if (RT_SUCCESS(rc)) { pIoLogger->offWriteNext += sizeof(Entry); if ( enmTxDir == VDDBGIOLOGREQ_WRITE && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_WRITTEN)) { /* Write data. */ rc = vddbgIoLogWriteSgBuf(pIoLogger, pIoLogger->offWriteNext, pSgBuf, cbIo); if (RT_FAILURE(rc)) { pIoLogger->offWriteNext -= sizeof(Entry); rc = RTFileSetSize(pIoLogger->hFile, pIoLogger->offWriteNext); } else pIoLogger->offWriteNext += cbIo; } } if (RT_SUCCESS(rc)) { pIoLogEntry->tsStart = RTTimeProgramMilliTS(); if ( enmTxDir == VDDBGIOLOGREQ_READ && (pIoLogger->fFlags & VDDBG_IOLOG_LOG_DATA_READ)) pIoLogEntry->cbIo = cbIo; else pIoLogEntry->cbIo = 0; *phIoLogEntry = pIoLogEntry; } else { pIoLogger->idNext--; RTMemCacheFree(pIoLogger->hMemCacheIoLogEntries, pIoLogEntry); } } else rc = VERR_NO_MEMORY; RTSemFastMutexRelease(pIoLogger->hMtx); return rc; }
/** * Handles the getregisters sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. */ static RTEXITCODE handleDebugVM_GetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) { /* * We take a list of register names (case insensitive). If 'all' is * encountered we'll dump all registers. */ ULONG idCpu = 0; unsigned cRegisters = 0; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; static const RTGETOPTDEF s_aOptions[] = { { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case 'c': idCpu = ValueUnion.u32; break; case VINF_GETOPT_NOT_OPTION: if (!RTStrICmp(ValueUnion.psz, "all")) { com::SafeArray<BSTR> aBstrNames; com::SafeArray<BSTR> aBstrValues; CHECK_ERROR2I_RET(pDebugger, GetRegisters(idCpu, ComSafeArrayAsOutParam(aBstrNames), ComSafeArrayAsOutParam(aBstrValues)), RTEXITCODE_FAILURE); Assert(aBstrNames.size() == aBstrValues.size()); size_t cchMaxName = 8; for (size_t i = 0; i < aBstrNames.size(); i++) { size_t cchName = RTUtf16Len(aBstrNames[i]); if (cchName > cchMaxName) cchMaxName = cchName; } for (size_t i = 0; i < aBstrNames.size(); i++) RTPrintf("%-*ls = %ls\n", cchMaxName, aBstrNames[i], aBstrValues[i]); } else { com::Bstr bstrName = ValueUnion.psz; com::Bstr bstrValue; CHECK_ERROR2I_RET(pDebugger, GetRegister(idCpu, bstrName.raw(), bstrValue.asOutParam()), RTEXITCODE_FAILURE); RTPrintf("%s = %ls\n", ValueUnion.psz, bstrValue.raw()); } cRegisters++; break; default: return errorGetOpt(rc, &ValueUnion); } } if (!cRegisters) return errorSyntax("The getregisters sub-command takes at least one register name"); return RTEXITCODE_SUCCESS; }
/** * Handles the show sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. */ static RTEXITCODE handleDebugVM_Show(HandlerArg *pArgs, IMachineDebugger *pDebugger) { /* * Parse arguments and what to show. Order dependent. */ uint32_t fFlags = DEBUGVM_SHOW_FLAGS_HUMAN_READABLE; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; static const RTGETOPTDEF s_aOptions[] = { { "--human-readable", 'H', RTGETOPT_REQ_NOTHING }, { "--sh-export", 'e', RTGETOPT_REQ_NOTHING }, { "--sh-eval", 'E', RTGETOPT_REQ_NOTHING }, { "--cmd-set", 's', RTGETOPT_REQ_NOTHING }, }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case 'H': fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_HUMAN_READABLE; break; case 'e': fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_SH_EXPORT; break; case 'E': fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_SH_EVAL; break; case 's': fFlags = (fFlags & ~DEBUGVM_SHOW_FLAGS_FMT_MASK) | DEBUGVM_SHOW_FLAGS_CMD_SET; break; case VINF_GETOPT_NOT_OPTION: { RTEXITCODE rcExit; if (!strcmp(ValueUnion.psz, "log-settings")) { rcExit = handleDebugVM_Show_LogDbgSettings(pDebugger, fFlags); if (rcExit == RTEXITCODE_SUCCESS) rcExit = handleDebugVM_Show_LogRelSettings(pDebugger, fFlags); } else if (!strcmp(ValueUnion.psz, "logdbg-settings")) rcExit = handleDebugVM_Show_LogDbgSettings(pDebugger, fFlags); else if (!strcmp(ValueUnion.psz, "logrel-settings")) rcExit = handleDebugVM_Show_LogRelSettings(pDebugger, fFlags); else rcExit = errorSyntax("The show sub-command has no idea what '%s' might be", ValueUnion.psz); if (rcExit != RTEXITCODE_SUCCESS) return rcExit; break; } default: return errorGetOpt(rc, &ValueUnion); } } return RTEXITCODE_SUCCESS; }
/** * Handles the log sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. * @param pszSubCmd The sub command. */ static RTEXITCODE handleDebugVM_LogXXXX(HandlerArg *pArgs, IMachineDebugger *pDebugger, const char *pszSubCmd) { /* * Parse arguments. */ bool fRelease = false; com::Utf8Str strSettings; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; /* * NB: don't use short options to prevent log specifications like * "-drv_foo" from being interpreted as options. */ # define DEBUGVM_LOG_DEBUG (VINF_GETOPT_NOT_OPTION + 'd') # define DEBUGVM_LOG_RELEASE (VINF_GETOPT_NOT_OPTION + 'r') static const RTGETOPTDEF s_aOptions[] = { { "--debug", DEBUGVM_LOG_DEBUG, RTGETOPT_REQ_NOTHING }, { "--release", DEBUGVM_LOG_RELEASE, RTGETOPT_REQ_NOTHING } }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, /* * Note: RTGETOPTINIT_FLAGS_NO_STD_OPTS is needed to not get into an infinite hang in the following * while-loop when processing log groups starting with "h", * e.g. "VBoxManage debugvm <VM Name> log --debug -hex". */ RTGETOPTINIT_FLAGS_OPTS_FIRST | RTGETOPTINIT_FLAGS_NO_STD_OPTS); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case DEBUGVM_LOG_RELEASE: fRelease = true; break; case DEBUGVM_LOG_DEBUG: fRelease = false; break; /* Because log strings can start with "-" (like "-all+dev_foo") * we have to take everything we got as a setting and apply it. * IPRT will take care of the validation afterwards. */ default: if (strSettings.length() == 0) strSettings = ValueUnion.psz; else { strSettings.append(' '); strSettings.append(ValueUnion.psz); } break; } } if (fRelease) { com::Utf8Str strTmp(strSettings); strSettings = "release:"; strSettings.append(strTmp); } com::Bstr bstrSettings(strSettings); if (!strcmp(pszSubCmd, "log")) CHECK_ERROR2I_RET(pDebugger, ModifyLogGroups(bstrSettings.raw()), RTEXITCODE_FAILURE); else if (!strcmp(pszSubCmd, "logdest")) CHECK_ERROR2I_RET(pDebugger, ModifyLogDestinations(bstrSettings.raw()), RTEXITCODE_FAILURE); else if (!strcmp(pszSubCmd, "logflags")) CHECK_ERROR2I_RET(pDebugger, ModifyLogFlags(bstrSettings.raw()), RTEXITCODE_FAILURE); else AssertFailedReturn(RTEXITCODE_FAILURE); return RTEXITCODE_SUCCESS; }
/** * Handles the setregisters sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. */ static RTEXITCODE handleDebugVM_SetRegisters(HandlerArg *pArgs, IMachineDebugger *pDebugger) { /* * We take a list of register assignments, that is register=value. */ ULONG idCpu = 0; com::SafeArray<IN_BSTR> aBstrNames; com::SafeArray<IN_BSTR> aBstrValues; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; static const RTGETOPTDEF s_aOptions[] = { { "--cpu", 'c', RTGETOPT_REQ_UINT32 }, }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, RTGETOPTINIT_FLAGS_OPTS_FIRST); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case 'c': idCpu = ValueUnion.u32; break; case VINF_GETOPT_NOT_OPTION: { const char *pszEqual = strchr(ValueUnion.psz, '='); if (!pszEqual) return errorSyntax("setregisters expects input on the form 'register=value' got '%s'", ValueUnion.psz); try { com::Bstr bstrName(ValueUnion.psz, pszEqual - ValueUnion.psz); com::Bstr bstrValue(pszEqual + 1); if ( !aBstrNames.push_back(bstrName.raw()) || !aBstrValues.push_back(bstrValue.raw())) throw std::bad_alloc(); } catch (std::bad_alloc) { RTMsgError("Out of memory\n"); return RTEXITCODE_FAILURE; } break; } default: return errorGetOpt(rc, &ValueUnion); } } if (!aBstrNames.size()) return errorSyntax("The setregisters sub-command takes at least one register name"); /* * If it is only one register, use the single register method just so * we expose it and can test it from the command line. */ if (aBstrNames.size() == 1) { CHECK_ERROR2I_RET(pDebugger, SetRegister(idCpu, aBstrNames[0], aBstrValues[0]), RTEXITCODE_FAILURE); RTPrintf("Successfully set %ls\n", aBstrNames[0]); } else { CHECK_ERROR2I_RET(pDebugger, SetRegisters(idCpu, ComSafeArrayAsInParam(aBstrNames), ComSafeArrayAsInParam(aBstrValues)), RTEXITCODE_FAILURE); RTPrintf("Successfully set %u registers\n", aBstrNames.size()); } return RTEXITCODE_SUCCESS; }
/** * Filter a the filename in the against a filter. * * The rules are as follows: * '?' Matches exactly one char. * '*' Matches zero or more chars. * '<' The dos star, matches zero or more chars except the DOS dot. * '>' The dos question mark, matches one char, but dots and end-of-name eats them. * '"' The dos dot, matches a dot or end-of-name. * * @returns true if the name matches the filter. * @returns false if the name doesn't match filter. * @param iDepth The recursion depth. * @param pszName The path to match to the filter. * @param puszFilter The filter string. */ static bool rtDirFilterWinNtMatchBase(unsigned iDepth, const char *pszName, PCRTUNICP puszFilter) { AssertReturn(iDepth++ < 256, false); /* * Walk the string and match it up char by char. */ RTUNICP uc; do { RTUNICP ucFilter = *puszFilter++; int rc = RTStrGetCpEx(&pszName, &uc); AssertRCReturn(rc, false); switch (ucFilter) { /* Exactly one char. */ case '?': if (!uc) return false; break; /* One char, but the dos dot and end-of-name eats '>' and '<'. */ case '>': /* dos ? */ if (!uc) return rtDirFilterWinNtMatchEon(puszFilter); if (uc == '.') { while ((ucFilter = *puszFilter) == '>' || ucFilter == '<') puszFilter++; if (ucFilter == '"' || ucFilter == '.') /* not 100% sure about the last dot */ ++puszFilter; else /* the does question mark doesn't match '.'s, so backtrack. */ pszName = RTStrPrevCp(NULL, pszName); } break; /* Match a dot or the end-of-name. */ case '"': /* dos '.' */ if (uc != '.') { if (uc) return false; return rtDirFilterWinNtMatchEon(puszFilter); } break; /* zero or more */ case '*': return rtDirFilterWinNtMatchStar(iDepth, uc, pszName, puszFilter); case '<': /* dos '*' */ return rtDirFilterWinNtMatchDosStar(iDepth, uc, pszName, puszFilter); /* uppercased match */ default: { if (RTUniCpToUpper(uc) != ucFilter) return false; break; } } } while (uc); return true; }
/** * Recursive star matching. * * @returns true on match. * @returns false on miss. */ static bool rtDirFilterWinNtMatchStar(unsigned iDepth, RTUNICP uc, const char *pszNext, PCRTUNICP puszFilter) { AssertReturn(iDepth++ < 256, false); /* * Inspect the next filter char(s) until we find something to work on. */ for (;;) { RTUNICP ucFilter = *puszFilter++; switch (ucFilter) { /* * The star expression is the last in the pattern. * Cool, that means we're done! */ case '\0': return true; /* * Just in case (doubt we ever get here), just merge it with the current one. */ case '*': break; /* * Skip a fixed number of chars. * Figure out how many by walking the filter ignoring '*'s. */ case '?': { unsigned cQms = 1; while ((ucFilter = *puszFilter) == '*' || ucFilter == '?') { cQms += ucFilter == '?'; puszFilter++; } do { if (!uc) return false; int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false); } while (--cQms > 0); /* done? */ if (!ucFilter) return true; break; } /* * The simple way is to try char by char and match the remaining * expression. If it's trailing we're done. */ case '>': /* dos question mark */ { if (rtDirFilterWinNtMatchEon(puszFilter)) return true; const char *pszStart = pszNext; do { if (rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter)) return true; int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false); } while (uc); /* backtrack and do the current char. */ pszNext = RTStrPrevCp(NULL, pszStart); AssertReturn(pszNext, false); return rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter); } /* * This bugger is interesting. * Time for brute force. Iterate the name char by char. */ case '<': { do { if (rtDirFilterWinNtMatchDosStar(iDepth, uc, pszNext, puszFilter)) return true; int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false); } while (uc); return false; } /* * This guy matches a '.' or the end of the name. * It's very simple if the rest of the filter expression also matches eon. */ case '"': if (rtDirFilterWinNtMatchEon(puszFilter)) return true; ucFilter = '.'; /* fall thru */ /* * Ok, we've got zero or more characters. * We'll try match starting at each occurrence of this character. */ default: { do { if ( RTUniCpToUpper(uc) == ucFilter && rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter)) return true; int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false); } while (uc); return false; } } } /* for (;;) */ /* won't ever get here! */ }
/** * Recursive star matching. * Practically the same as normal star, except that the dos star stops * when hitting the last dot. * * @returns true on match. * @returns false on miss. */ static bool rtDirFilterWinNtMatchDosStar(unsigned iDepth, RTUNICP uc, const char *pszNext, PCRTUNICP puszFilter) { AssertReturn(iDepth++ < 256, false); /* * If there is no dos star, we should work just like the NT star. * Since that's generally faster algorithms, we jump down to there if we can. */ const char *pszDosDot = strrchr(pszNext, '.'); if (!pszDosDot && uc == '.') pszDosDot = pszNext - 1; if (!pszDosDot) return rtDirFilterWinNtMatchStar(iDepth, uc, pszNext, puszFilter); /* * Inspect the next filter char(s) until we find something to work on. */ RTUNICP ucFilter = *puszFilter++; switch (ucFilter) { /* * The star expression is the last in the pattern. * We're fine if the name ends with a dot. */ case '\0': return !pszDosDot[1]; /* * Simplified by brute force. */ case '>': /* dos question mark */ case '?': case '*': case '<': /* dos star */ case '"': /* dos dot */ { puszFilter--; const char *pszStart = pszNext; do { if (rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter)) return true; int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false); } while ((intptr_t)pszDosDot - (intptr_t)pszNext >= -1); /* backtrack and do the current char. */ pszNext = RTStrPrevCp(NULL, pszStart); AssertReturn(pszNext, false); return rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter); } /* * Ok, we've got zero or more characters. * We'll try match starting at each occurrence of this character. */ default: { if ( RTUniCpToUpper(uc) == ucFilter && rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter)) return true; do { int rc = RTStrGetCpEx(&pszNext, &uc); AssertRCReturn(rc, false); if ( RTUniCpToUpper(uc) == ucFilter && rtDirFilterWinNtMatchBase(iDepth, pszNext, puszFilter)) return true; } while ((intptr_t)pszDosDot - (intptr_t)pszNext >= -1); return false; } } /* won't ever get here! */ }
/** * Parse the arguments. * * @returns 0 on success, fully bitched exit code on failure. * * @param argc Argument count. * @param argv Argument vector. */ int VBoxNetBaseService::parseArgs(int argc, char **argv) { RTGETOPTSTATE State; PRTGETOPTDEF paOptionArray = getOptionsPtr(); int rc = RTGetOptInit(&State, argc, argv, paOptionArray, m_vecOptionDefs.size(), 0, 0 /*fFlags*/); AssertRCReturn(rc, 49); #if 0 /* default initialization */ m_enmTrunkType = kIntNetTrunkType_WhateverNone; #endif Log2(("BaseService: parseArgs enter\n")); for (;;) { RTGETOPTUNION Val; rc = RTGetOpt(&State, &Val); if (!rc) break; switch (rc) { case 'N': m_Name = Val.psz; break; case 'n': m_Network = Val.psz; break; case 't': m_TrunkName = Val.psz; break; case 'T': if (!strcmp(Val.psz, "none")) m_enmTrunkType = kIntNetTrunkType_None; else if (!strcmp(Val.psz, "whatever")) m_enmTrunkType = kIntNetTrunkType_WhateverNone; else if (!strcmp(Val.psz, "netflt")) m_enmTrunkType = kIntNetTrunkType_NetFlt; else if (!strcmp(Val.psz, "netadp")) m_enmTrunkType = kIntNetTrunkType_NetAdp; else if (!strcmp(Val.psz, "srvnat")) m_enmTrunkType = kIntNetTrunkType_SrvNat; else { RTStrmPrintf(g_pStdErr, "Invalid trunk type '%s'\n", Val.psz); return 1; } break; case 'a': m_MacAddress = Val.MacAddr; break; case 'i': m_Ipv4Address = Val.IPv4Addr; break; case 'm': m_Ipv4Netmask = Val.IPv4Addr; break; case 'v': m_cVerbosity++; break; case 'V': RTPrintf("%sr%u\n", RTBldCfgVersion(), RTBldCfgRevision()); return 1; case 'h': RTPrintf("VBoxNetDHCP Version %s\n" "(C) 2009-" VBOX_C_YEAR " " VBOX_VENDOR "\n" "All rights reserved.\n" "\n" "Usage: VBoxNetDHCP <options>\n" "\n" "Options:\n", RTBldCfgVersion()); for (unsigned int i = 0; i < m_vecOptionDefs.size(); i++) RTPrintf(" -%c, %s\n", m_vecOptionDefs[i]->iShort, m_vecOptionDefs[i]->pszLong); usage(); /* to print Service Specific usage */ return 1; default: int rc1 = parseOpt(rc, Val); if (RT_FAILURE(rc1)) { rc = RTGetOptPrintError(rc, &Val); RTPrintf("Use --help for more information.\n"); return rc; } } } RTMemFree(paOptionArray); return rc; }
/** * Handles the statistics sub-command. * * @returns Suitable exit code. * @param pArgs The handler arguments. * @param pDebugger Pointer to the debugger interface. */ static RTEXITCODE handleDebugVM_Statistics(HandlerArg *pArgs, IMachineDebugger *pDebugger) { /* * Parse arguments. */ bool fWithDescriptions = false; const char *pszPattern = NULL; /* all */ bool fReset = false; RTGETOPTSTATE GetState; RTGETOPTUNION ValueUnion; static const RTGETOPTDEF s_aOptions[] = { { "--descriptions", 'd', RTGETOPT_REQ_NOTHING }, { "--pattern", 'p', RTGETOPT_REQ_STRING }, { "--reset", 'r', RTGETOPT_REQ_NOTHING }, }; int rc = RTGetOptInit(&GetState, pArgs->argc, pArgs->argv, s_aOptions, RT_ELEMENTS(s_aOptions), 2, 0 /*fFlags*/); AssertRCReturn(rc, RTEXITCODE_FAILURE); while ((rc = RTGetOpt(&GetState, &ValueUnion)) != 0) { switch (rc) { case 'd': fWithDescriptions = true; break; case 'p': if (pszPattern) return errorSyntax("Multiple --pattern options are not permitted"); pszPattern = ValueUnion.psz; break; case 'r': fReset = true; break; default: return errorGetOpt(rc, &ValueUnion); } } if (fReset && fWithDescriptions) return errorSyntax("The --reset and --descriptions options does not mix"); /* * Execute the order. */ com::Bstr bstrPattern(pszPattern); if (fReset) CHECK_ERROR2I_RET(pDebugger, ResetStats(bstrPattern.raw()), RTEXITCODE_FAILURE); else { com::Bstr bstrStats; CHECK_ERROR2I_RET(pDebugger, GetStats(bstrPattern.raw(), fWithDescriptions, bstrStats.asOutParam()), RTEXITCODE_FAILURE); /* if (fFormatted) { big mess } else */ RTPrintf("%ls\n", bstrStats.raw()); } return RTEXITCODE_SUCCESS; }
STDMETHODIMP Guest::InternalGetStatistics(ULONG *aCpuUser, ULONG *aCpuKernel, ULONG *aCpuIdle, ULONG *aMemTotal, ULONG *aMemFree, ULONG *aMemBalloon, ULONG *aMemShared, ULONG *aMemCache, ULONG *aPageTotal, ULONG *aMemAllocTotal, ULONG *aMemFreeTotal, ULONG *aMemBalloonTotal, ULONG *aMemSharedTotal) { CheckComArgOutPointerValid(aCpuUser); CheckComArgOutPointerValid(aCpuKernel); CheckComArgOutPointerValid(aCpuIdle); CheckComArgOutPointerValid(aMemTotal); CheckComArgOutPointerValid(aMemFree); CheckComArgOutPointerValid(aMemBalloon); CheckComArgOutPointerValid(aMemShared); CheckComArgOutPointerValid(aMemCache); CheckComArgOutPointerValid(aPageTotal); CheckComArgOutPointerValid(aMemAllocTotal); CheckComArgOutPointerValid(aMemFreeTotal); CheckComArgOutPointerValid(aMemBalloonTotal); CheckComArgOutPointerValid(aMemSharedTotal); AutoCaller autoCaller(this); if (FAILED(autoCaller.rc())) return autoCaller.rc(); AutoReadLock alock(this COMMA_LOCKVAL_SRC_POS); *aCpuUser = mCurrentGuestStat[GUESTSTATTYPE_CPUUSER]; *aCpuKernel = mCurrentGuestStat[GUESTSTATTYPE_CPUKERNEL]; *aCpuIdle = mCurrentGuestStat[GUESTSTATTYPE_CPUIDLE]; *aMemTotal = mCurrentGuestStat[GUESTSTATTYPE_MEMTOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemFree = mCurrentGuestStat[GUESTSTATTYPE_MEMFREE] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemBalloon = mCurrentGuestStat[GUESTSTATTYPE_MEMBALLOON] * (_4K/_1K); /* page (4K) -> 1KB units */ *aMemCache = mCurrentGuestStat[GUESTSTATTYPE_MEMCACHE] * (_4K/_1K); /* page (4K) -> 1KB units */ *aPageTotal = mCurrentGuestStat[GUESTSTATTYPE_PAGETOTAL] * (_4K/_1K); /* page (4K) -> 1KB units */ /* Play safe or smth? */ *aMemAllocTotal = 0; *aMemFreeTotal = 0; *aMemBalloonTotal = 0; *aMemSharedTotal = 0; *aMemShared = 0; /* MUST release all locks before calling any PGM statistics queries, * as they are executed by EMT and that might deadlock us by VMM device * activity which waits for the Guest object lock. */ alock.release(); Console::SafeVMPtr ptrVM(mParent); if (!ptrVM.isOk()) return E_FAIL; uint64_t cbFreeTotal, cbAllocTotal, cbBalloonedTotal, cbSharedTotal; int rc = PGMR3QueryGlobalMemoryStats(ptrVM.rawUVM(), &cbAllocTotal, &cbFreeTotal, &cbBalloonedTotal, &cbSharedTotal); AssertRCReturn(rc, E_FAIL); *aMemAllocTotal = (ULONG)(cbAllocTotal / _1K); /* bytes -> KB */ *aMemFreeTotal = (ULONG)(cbFreeTotal / _1K); *aMemBalloonTotal = (ULONG)(cbBalloonedTotal / _1K); *aMemSharedTotal = (ULONG)(cbSharedTotal / _1K); /* Query the missing per-VM memory statistics. */ uint64_t cbTotalMemIgn, cbPrivateMemIgn, cbSharedMem, cbZeroMemIgn; rc = PGMR3QueryMemoryStats(ptrVM.rawUVM(), &cbTotalMemIgn, &cbPrivateMemIgn, &cbSharedMem, &cbZeroMemIgn); AssertRCReturn(rc, E_FAIL); *aMemShared = (ULONG)(cbSharedMem / _1K); return S_OK; }
DECLINLINE(int) tftpSessionOptionParse(PTFTPSESSION pTftpSession, PCTFTPIPHDR pcTftpIpHeader) { int rc = VINF_SUCCESS; char *pszTftpRRQRaw; size_t idxTftpRRQRaw = 0; int cbTftpRRQRaw = 0; int fWithArg = 0; int idxOptionArg = 0; AssertPtrReturn(pTftpSession, VERR_INVALID_PARAMETER); AssertPtrReturn(pcTftpIpHeader, VERR_INVALID_PARAMETER); AssertReturn(RT_N2H_U16(pcTftpIpHeader->u16TftpOpType) == TFTP_RRQ, VERR_INVALID_PARAMETER); LogFlowFunc(("pTftpSession:%p, pcTftpIpHeader:%p\n", pTftpSession, pcTftpIpHeader)); pszTftpRRQRaw = (char *)&pcTftpIpHeader->Core; cbTftpRRQRaw = RT_H2N_U16(pcTftpIpHeader->UdpHdr.uh_ulen) + sizeof(struct ip) - RT_OFFSETOF(TFTPIPHDR, Core); while(cbTftpRRQRaw) { idxTftpRRQRaw = RTStrNLen(pszTftpRRQRaw, 512 - idxTftpRRQRaw) + 1; if (RTStrNLen((char *)pTftpSession->pszFilename, TFTP_FILENAME_MAX) == 0) { rc = RTStrCopy((char *)pTftpSession->pszFilename, TFTP_FILENAME_MAX, pszTftpRRQRaw); if (RT_FAILURE(rc)) { LogFlowFuncLeaveRC(rc); AssertRCReturn(rc,rc); } } else if (pTftpSession->enmTftpFmt == TFTPFMT_NONE) { int idxFmt = 0; rc = tftpFindTransferFormatIdxbyName(&idxFmt, pszTftpRRQRaw); if (RT_FAILURE(rc)) { LogFlowFuncLeaveRC(VERR_INTERNAL_ERROR); return VERR_INTERNAL_ERROR; } AssertReturn( g_TftpTransferFmtDesc[idxFmt].enmType != TFTPFMT_NONE && g_TftpTransferFmtDesc[idxFmt].enmType != TFTPFMT_NOT_FMT, VERR_INTERNAL_ERROR); pTftpSession->enmTftpFmt = g_TftpTransferFmtDesc[idxFmt].enmType; } else if (fWithArg) { if (!RTStrICmp("blksize", g_TftpDesc[idxOptionArg].pszName)) { rc = tftpSessionParseAndMarkOption(pszTftpRRQRaw, &pTftpSession->OptionBlkSize); if (pTftpSession->OptionBlkSize.u64Value > UINT16_MAX) rc = VERR_INVALID_PARAMETER; } if ( RT_SUCCESS(rc) && !RTStrICmp("tsize", g_TftpDesc[idxOptionArg].pszName)) rc = tftpSessionParseAndMarkOption(pszTftpRRQRaw, &pTftpSession->OptionTSize); /* @todo: we don't use timeout, but its value in the range 0-255 */ if ( RT_SUCCESS(rc) && !RTStrICmp("timeout", g_TftpDesc[idxOptionArg].pszName)) rc = tftpSessionParseAndMarkOption(pszTftpRRQRaw, &pTftpSession->OptionTimeout); /* @todo: unknown option detection */ if (RT_FAILURE(rc)) { LogFlowFuncLeaveRC(rc); AssertRCReturn(rc,rc); } fWithArg = 0; idxOptionArg = 0; } else { rc = tftpFindOptionIdxbyName(&idxOptionArg, pszTftpRRQRaw); if (RT_SUCCESS(rc)) fWithArg = 1; else { LogFlowFuncLeaveRC(rc); AssertRCReturn(rc,rc); } } pszTftpRRQRaw += idxTftpRRQRaw; cbTftpRRQRaw -= idxTftpRRQRaw; } LogFlowFuncLeaveRC(rc); return rc; }