/** * Signal a fatal wait error. * * @returns Fatal error code to be propagated up the call stack. * @param pUVCpu The user mode per CPU structure of the calling * EMT. * @param pszFmt The error format with a single %Rrc in it. * @param rcFmt The status code to format. */ static int vmR3FatalWaitError(PUVMCPU pUVCpu, const char *pszFmt, int rcFmt) { /** @todo This is wrong ... raise a fatal error / guru meditation * instead. */ AssertLogRelMsgFailed((pszFmt, rcFmt)); ASMAtomicUoWriteBool(&pUVCpu->pUVM->vm.s.fTerminateEMT, true); if (pUVCpu->pVM) VM_FF_SET(pUVCpu->pVM, VM_FF_CHECK_VM_STATE); return VERR_VM_FATAL_WAIT_ERROR; }
/** * Insert pending notification * * @param pVM Pointer to the VM. * @param pRec Notification record to insert */ static void remNotifyHandlerInsert(PVM pVM, PREMHANDLERNOTIFICATION pRec) { /* * Fetch a free record. */ uint32_t cFlushes = 0; uint32_t idxFree; PREMHANDLERNOTIFICATION pFree; do { idxFree = ASMAtomicUoReadU32(&pVM->rem.s.idxFreeList); if (idxFree == UINT32_MAX) { do { cFlushes++; Assert(cFlushes != 128); AssertFatal(cFlushes < _1M); VMMRZCallRing3NoCpu(pVM, VMMCALLRING3_REM_REPLAY_HANDLER_NOTIFICATIONS, 0); idxFree = ASMAtomicUoReadU32(&pVM->rem.s.idxFreeList); } while (idxFree == UINT32_MAX); } pFree = &pVM->rem.s.aHandlerNotifications[idxFree]; } while (!ASMAtomicCmpXchgU32(&pVM->rem.s.idxFreeList, pFree->idxNext, idxFree)); /* * Copy the record. */ pFree->enmKind = pRec->enmKind; pFree->u = pRec->u; /* * Insert it into the pending list. */ uint32_t idxNext; do { idxNext = ASMAtomicUoReadU32(&pVM->rem.s.idxPendingList); ASMAtomicWriteU32(&pFree->idxNext, idxNext); ASMCompilerBarrier(); } while (!ASMAtomicCmpXchgU32(&pVM->rem.s.idxPendingList, idxFree, idxNext)); VM_FF_SET(pVM, VM_FF_REM_HANDLER_NOTIFY); }
/** * Sets the VMM Debug Command variable. * * @returns Previous command. * @param pVM Pointer to the VM. * @param enmCmd The command. */ DECLINLINE(DBGFCMD) dbgfR3SetCmd(PVM pVM, DBGFCMD enmCmd) { DBGFCMD rc; if (enmCmd == DBGFCMD_NO_COMMAND) { Log2(("DBGF: Setting command to %d (DBGFCMD_NO_COMMAND)\n", enmCmd)); rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd); VM_FF_CLEAR(pVM, VM_FF_DBGF); } else { Log2(("DBGF: Setting command to %d\n", enmCmd)); AssertMsg(pVM->dbgf.s.enmVMMCmd == DBGFCMD_NO_COMMAND, ("enmCmd=%d enmVMMCmd=%d\n", enmCmd, pVM->dbgf.s.enmVMMCmd)); rc = (DBGFCMD)ASMAtomicXchgU32((uint32_t volatile *)(void *)&pVM->dbgf.s.enmVMMCmd, enmCmd); VM_FF_SET(pVM, VM_FF_DBGF); VMR3NotifyGlobalFFU(pVM->pUVM, 0 /* didn't notify REM */); } return rc; }
/** * Queue an item. * The item must have been obtained using PDMQueueAlloc(). Once the item * have been passed to this function it must not be touched! * * @param pQueue The queue handle. * @param pItem The item to insert. * @thread Any thread. */ VMMDECL(void) PDMQueueInsert(PPDMQUEUE pQueue, PPDMQUEUEITEMCORE pItem) { Assert(VALID_PTR(pQueue) && pQueue->CTX_SUFF(pVM)); Assert(VALID_PTR(pItem)); #if 0 /* the paranoid android version: */ void *pvNext; do { pvNext = ASMAtomicUoReadPtr((void * volatile *)&pQueue->CTX_SUFF(pPending)); ASMAtomicUoWritePtr((void * volatile *)&pItem->CTX_SUFF(pNext), pvNext); } while (!ASMAtomicCmpXchgPtr(&pQueue->CTX_SUFF(pPending), pItem, pvNext)); #else PPDMQUEUEITEMCORE pNext; do { pNext = pQueue->CTX_SUFF(pPending); pItem->CTX_SUFF(pNext) = pNext; } while (!ASMAtomicCmpXchgPtr(&pQueue->CTX_SUFF(pPending), pItem, pNext)); #endif if (!pQueue->pTimer) { PVM pVM = pQueue->CTX_SUFF(pVM); Log2(("PDMQueueInsert: VM_FF_PDM_QUEUES %d -> 1\n", VM_FF_ISSET(pVM, VM_FF_PDM_QUEUES))); VM_FF_SET(pVM, VM_FF_PDM_QUEUES); ASMAtomicBitSet(&pVM->pdm.s.fQueueFlushing, PDM_QUEUE_FLUSH_FLAG_PENDING_BIT); #ifdef IN_RING3 # ifdef VBOX_WITH_REM REMR3NotifyQueuePending(pVM); /** @todo r=bird: we can remove REMR3NotifyQueuePending and let VMR3NotifyFF do the work. */ # endif VMR3NotifyGlobalFFU(pVM->pUVM, VMNOTIFYFF_FLAGS_DONE_REM); #endif } STAM_REL_COUNTER_INC(&pQueue->StatInsert); STAM_STATS({ ASMAtomicIncU32(&pQueue->cStatPending); });
/** * Interface that PDM the helper asynchronous notification completed methods * uses for EMT0 when it is waiting inside VMR3AsyncPdmNotificationWaitU(). * * @param pUVM Pointer to the user mode VM structure. */ VMMR3_INT_DECL(void) VMR3AsyncPdmNotificationWakeupU(PUVM pUVM) { LogFlow(("VMR3AsyncPdmNotificationWakeupU:\n")); VM_FF_SET(pUVM->pVM, VM_FF_REQUEST); /* this will have to do for now. */ g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnNotifyCpuFF(&pUVM->aCpus[0], 0 /*fFlags*/); }