/** * Initialize the configuration of halt method 1 & 2. * * @return VBox status code. Failure on invalid CFGM data. * @param pVM Pointer to the VM. */ static int vmR3HaltMethod12ReadConfigU(PUVM pUVM) { /* * The defaults. */ #if 1 /* DEBUGGING STUFF - REMOVE LATER */ pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4; pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = 2*1000000; pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = 75*1000000; pUVM->vm.s.Halt.Method12.u32StartSpinningCfg = 30*1000000; pUVM->vm.s.Halt.Method12.u32StopSpinningCfg = 20*1000000; #else pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4; pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = 5*1000000; pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = 200*1000000; pUVM->vm.s.Halt.Method12.u32StartSpinningCfg = 20*1000000; pUVM->vm.s.Halt.Method12.u32StopSpinningCfg = 2*1000000; #endif /* * Query overrides. * * I don't have time to bother with niceties such as invalid value checks * here right now. sorry. */ PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pUVM->pVM), "/VMM/HaltedMethod1"); if (pCfg) { uint32_t u32; if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "LagBlockIntervalDivisor", &u32))) pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = u32; if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "MinBlockInterval", &u32))) pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = u32; if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "MaxBlockInterval", &u32))) pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = u32; if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "StartSpinning", &u32))) pUVM->vm.s.Halt.Method12.u32StartSpinningCfg = u32; if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "StopSpinning", &u32))) pUVM->vm.s.Halt.Method12.u32StopSpinningCfg = u32; LogRel(("HaltedMethod1 config: %d/%d/%d/%d/%d\n", pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg, pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg, pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg, pUVM->vm.s.Halt.Method12.u32StartSpinningCfg, pUVM->vm.s.Halt.Method12.u32StopSpinningCfg)); } return VINF_SUCCESS; }
/** * Initialize the global 1 halt method. * * @return VBox status code. * @param pUVM Pointer to the user mode VM structure. */ static DECLCALLBACK(int) vmR3HaltGlobal1Init(PUVM pUVM) { /* * The defaults. */ uint32_t cNsResolution = SUPSemEventMultiGetResolution(pUVM->vm.s.pSession); if (cNsResolution > 5*RT_NS_100US) pUVM->vm.s.Halt.Global1.cNsSpinBlockThresholdCfg = 50000; else if (cNsResolution > RT_NS_100US) pUVM->vm.s.Halt.Global1.cNsSpinBlockThresholdCfg = cNsResolution / 4; else pUVM->vm.s.Halt.Global1.cNsSpinBlockThresholdCfg = 2000; /* * Query overrides. * * I don't have time to bother with niceties such as invalid value checks * here right now. sorry. */ PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pUVM->pVM), "/VMM/HaltedGlobal1"); if (pCfg) { uint32_t u32; if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "SpinBlockThreshold", &u32))) pUVM->vm.s.Halt.Global1.cNsSpinBlockThresholdCfg = u32; } LogRel(("HaltedGlobal1 config: cNsSpinBlockThresholdCfg=%u\n", pUVM->vm.s.Halt.Global1.cNsSpinBlockThresholdCfg)); return VINF_SUCCESS; }
/** * Changes the halt method. * * @returns VBox status code. * @param pUVM Pointer to the user mode VM structure. * @param enmHaltMethod The new halt method. * @thread EMT. */ int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod) { PVM pVM = pUVM->pVM; Assert(pVM); VM_ASSERT_EMT(pVM); AssertReturn(enmHaltMethod > VMHALTMETHOD_INVALID && enmHaltMethod < VMHALTMETHOD_END, VERR_INVALID_PARAMETER); /* * Resolve default (can be overridden in the configuration). */ if (enmHaltMethod == VMHALTMETHOD_DEFAULT) { uint32_t u32; int rc = CFGMR3QueryU32(CFGMR3GetChild(CFGMR3GetRoot(pVM), "VM"), "HaltMethod", &u32); if (RT_SUCCESS(rc)) { enmHaltMethod = (VMHALTMETHOD)u32; if (enmHaltMethod <= VMHALTMETHOD_INVALID || enmHaltMethod >= VMHALTMETHOD_END) return VMSetError(pVM, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("Invalid VM/HaltMethod value %d"), enmHaltMethod); } else if (rc == VERR_CFGM_VALUE_NOT_FOUND || rc == VERR_CFGM_CHILD_NOT_FOUND) return VMSetError(pVM, rc, RT_SRC_POS, N_("Failed to Query VM/HaltMethod as uint32_t")); else enmHaltMethod = VMHALTMETHOD_GLOBAL_1; //enmHaltMethod = VMHALTMETHOD_1; //enmHaltMethod = VMHALTMETHOD_OLD; } LogRel(("VM: Halt method %s (%d)\n", vmR3GetHaltMethodName(enmHaltMethod), enmHaltMethod)); /* * Find the descriptor. */ unsigned i = 0; while ( i < RT_ELEMENTS(g_aHaltMethods) && g_aHaltMethods[i].enmHaltMethod != enmHaltMethod) i++; AssertReturn(i < RT_ELEMENTS(g_aHaltMethods), VERR_INVALID_PARAMETER); /* * This needs to be done while the other EMTs are not sleeping or otherwise messing around. */ return VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_ONCE, vmR3SetHaltMethodCallback, (void *)(uintptr_t)i); }
/** * Construct a keyboard driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ static DECLCALLBACK(int) drvKbdQueueConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVKBDQUEUE pDrv = PDMINS_2_DATA(pDrvIns, PDRVKBDQUEUE); LogFlow(("drvKbdQueueConstruct: iInstance=%d\n", pDrvIns->iInstance)); PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns); /* * Validate configuration. */ if (!CFGMR3AreValuesValid(pCfg, "QueueSize\0Interval\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; /* * Init basic data members and interfaces. */ pDrv->fInactive = true; pDrv->fSuspended = false; pDrv->XlatState = SS_IDLE; /* IBase. */ pDrvIns->IBase.pfnQueryInterface = drvKbdQueueQueryInterface; /* IKeyboardConnector. */ pDrv->IConnector.pfnLedStatusChange = drvKbdPassThruLedsChange; pDrv->IConnector.pfnSetActive = drvKbdPassThruSetActive; pDrv->IConnector.pfnFlushQueue = drvKbdFlushQueue; /* IKeyboardPort. */ pDrv->IPort.pfnPutEventScan = drvKbdQueuePutEventScan; /* * Get the IKeyboardPort interface of the above driver/device. */ pDrv->pUpPort = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMIKEYBOARDPORT); if (!pDrv->pUpPort) { AssertMsgFailed(("Configuration error: No keyboard port interface above!\n")); return VERR_PDM_MISSING_INTERFACE_ABOVE; } /* * Attach driver below and query it's connector interface. */ PPDMIBASE pDownBase; int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pDownBase); if (RT_FAILURE(rc)) { AssertMsgFailed(("Failed to attach driver below us! rc=%Rra\n", rc)); return rc; } pDrv->pDownConnector = PDMIBASE_QUERY_INTERFACE(pDownBase, PDMIKEYBOARDCONNECTOR); if (!pDrv->pDownConnector) { AssertMsgFailed(("Configuration error: No keyboard connector interface below!\n")); return VERR_PDM_MISSING_INTERFACE_BELOW; } /* * Create the queue. */ uint32_t cMilliesInterval = 0; rc = CFGMR3QueryU32(pCfg, "Interval", &cMilliesInterval); if (rc == VERR_CFGM_VALUE_NOT_FOUND) cMilliesInterval = 0; else if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: 32-bit \"Interval\" -> rc=%Rrc\n", rc)); return rc; } uint32_t cItems = 0; rc = CFGMR3QueryU32(pCfg, "QueueSize", &cItems); if (rc == VERR_CFGM_VALUE_NOT_FOUND) cItems = 128; else if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: 32-bit \"QueueSize\" -> rc=%Rrc\n", rc)); return rc; } rc = PDMDrvHlpQueueCreate(pDrvIns, sizeof(DRVKBDQUEUEITEM), cItems, cMilliesInterval, drvKbdQueueConsumer, "Keyboard", &pDrv->pQueue); if (RT_FAILURE(rc)) { AssertMsgFailed(("Failed to create driver: cItems=%d cMilliesInterval=%d rc=%Rrc\n", cItems, cMilliesInterval, rc)); return rc; } return VINF_SUCCESS; }
/** * Construct a status driver instance. * * @copydoc FNPDMDRVCONSTRUCT */ DECLCALLBACK(int) VMStatus::drvConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags) { PDRVMAINSTATUS pData = PDMINS_2_DATA(pDrvIns, PDRVMAINSTATUS); LogFlow(("VMStatus::drvConstruct: iInstance=%d\n", pDrvIns->iInstance)); /* * Validate configuration. */ if (!CFGMR3AreValuesValid(pCfg, "papLeds\0First\0Last\0")) return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; AssertMsgReturn(PDMDrvHlpNoAttach(pDrvIns) == VERR_PDM_NO_ATTACHED_DRIVER, ("Configuration error: Not possible to attach anything to this driver!\n"), VERR_PDM_DRVINS_NO_ATTACH); /* * Data. */ pDrvIns->IBase.pfnQueryInterface = VMStatus::drvQueryInterface; pData->ILedConnectors.pfnUnitChanged = VMStatus::drvUnitChanged; /* * Read config. */ int rc = CFGMR3QueryPtr(pCfg, "papLeds", (void **)&pData->papLeds); if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: Failed to query the \"papLeds\" value! rc=%Rrc\n", rc)); return rc; } rc = CFGMR3QueryU32(pCfg, "First", &pData->iFirstLUN); if (rc == VERR_CFGM_VALUE_NOT_FOUND) pData->iFirstLUN = 0; else if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: Failed to query the \"First\" value! rc=%Rrc\n", rc)); return rc; } rc = CFGMR3QueryU32(pCfg, "Last", &pData->iLastLUN); if (rc == VERR_CFGM_VALUE_NOT_FOUND) pData->iLastLUN = 0; else if (RT_FAILURE(rc)) { AssertMsgFailed(("Configuration error: Failed to query the \"Last\" value! rc=%Rrc\n", rc)); return rc; } if (pData->iFirstLUN > pData->iLastLUN) { AssertMsgFailed(("Configuration error: Invalid unit range %u-%u\n", pData->iFirstLUN, pData->iLastLUN)); return VERR_GENERAL_FAILURE; } /* * Get the ILedPorts interface of the above driver/device and * query the LEDs we want. */ pData->pLedPorts = PDMIBASE_QUERY_INTERFACE(pDrvIns->pUpBase, PDMILEDPORTS); AssertMsgReturn(pData->pLedPorts, ("Configuration error: No led ports interface above!\n"), VERR_PDM_MISSING_INTERFACE_ABOVE); for (unsigned i = pData->iFirstLUN; i <= pData->iLastLUN; i++) VMStatus::drvUnitChanged(&pData->ILedConnectors, i); return VINF_SUCCESS; }