VirtualBox

Changeset 23148 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 18, 2009 9:53:15 PM (15 years ago)
Author:
vboxsync
Message:

VM.cpp: converted VMR3PowerOn and VMR3Resume to use VMMR3EmtRendezvous; Cleanups.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VM.cpp

    r23146 r23148  
    11301130
    11311131/**
    1132  * Power on the virtual machine.
    1133  *
    1134  * @returns 0 on success.
    1135  * @returns VBox error code on failure.
    1136  * @param   pVM         VM to power on.
    1137  * @thread  EMT
    1138  */
    1139 static DECLCALLBACK(int) vmR3PowerOn(PVM pVM)
    1140 {
    1141     LogFlow(("vmR3PowerOn: pVM=%p\n", pVM));
    1142 
    1143     /*
    1144      * EMT(0) does the actual power on work *before* the other EMTs
    1145      * get here, they just need to set their state to STARTED so they
    1146      * get out of the EMT loop and into EM.
    1147      */
    1148     PVMCPU pVCpu = VMMGetCpu(pVM);
     1132 * EMT rendezvous worker for VMR3PowerOn.
     1133 *
     1134 * @returns VERR_VM_INVALID_VM_STATE or VINF_SUCCESS. (This is a strict return
     1135 *          code, see FNVMMEMTRENDEZVOUS.)
     1136 *
     1137 * @param   pVM             The VM handle.
     1138 * @param   pVCpu           The VMCPU handle of the EMT.
     1139 * @param   pvUser          Ignored.
     1140 */
     1141static DECLCALLBACK(VBOXSTRICTRC) vmR3PowerOn(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1142{
     1143    LogFlow(("vmR3PowerOn: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
     1144    Assert(!pvUser); NOREF(pvUser);
     1145
     1146    /*
     1147     * The first thread thru here tries to change the state.  We shouldn't be
     1148     * called again if this fails.
     1149     */
     1150    if (pVCpu->idCpu == pVM->cCpus - 1)
     1151    {
     1152        int rc = vmR3TrySetState(pVM, "VMR3PowerOn", 1, VMSTATE_POWERING_ON, VMSTATE_CREATED);
     1153        if (RT_FAILURE(rc))
     1154            return rc;
     1155    }
     1156
     1157    VMSTATE enmVMState = VMR3GetState(pVM);
     1158    AssertMsgReturn(enmVMState == VMSTATE_POWERING_ON,
     1159                    ("%s\n", VMR3GetStateName(enmVMState)),
     1160                    VERR_INTERNAL_ERROR_4);
     1161
     1162    /*
     1163     * All EMTs changes their state to started.
     1164     */
    11491165    VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
    1150     if (pVCpu->idCpu != 0)
    1151         return VINF_SUCCESS;
    1152 
    1153     /*
    1154      * Try change the state.
    1155      */
    1156     int rc = vmR3TrySetState(pVM, "VMR3PowerOff", 1, VMSTATE_POWERING_ON, VMSTATE_CREATED);
    1157     if (RT_FAILURE(rc))
    1158         return rc;
    1159 
    1160     /*
    1161      * Change the state, notify the components and resume the execution.
    1162      */
    1163     PDMR3PowerOn(pVM);
    1164     vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_POWERING_ON);
     1166
     1167    /*
     1168     * EMT(0) is last thru here and it will make the notification calls
     1169     * and advance the state.
     1170     */
     1171    if (pVCpu->idCpu == 0)
     1172    {
     1173        PDMR3PowerOn(pVM);
     1174        vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_POWERING_ON);
     1175    }
    11651176
    11661177    return VINF_SUCCESS;
     
    11771188 * @thread      Any thread.
    11781189 * @vmstate     Created
    1179  * @vmstateto   PoweringOn, Running
     1190 * @vmstateto   PoweringOn+Running
    11801191 */
    11811192VMMR3DECL(int) VMR3PowerOn(PVM pVM)
     
    11851196
    11861197    /*
    1187      * Forward the request to the EMTs (EMT(0) first as it does all the
    1188      * work upfront).
    1189      */
    1190     int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL, (PFNRT)vmR3PowerOn, 1, pVM);
    1191     LogFlow(("VMR3PowerOn: returns %Rrc\n", rc));
     1198     * Gather all the EMTs to reduce the init TSC drift and keep                                      .
     1199     * the state changing APIs a bit uniform.
     1200     */
     1201    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
     1202                                vmR3PowerOn, NULL);
     1203    LogFlow(("VMR3Suspend: returns %Rrc\n", rc));
    11921204    return rc;
    11931205}
     
    12071219
    12081220/**
    1209  * EMT worker for VMR3Suspend.
    1210  *
    1211  * @returns VBox strict status code.
    1212  * @retval  VINF_EM_SUSPEND.
    1213  * @retval  VERR_VM_INVALID_VM_STATE.
    1214  *
    1215  * @param   pVM             The VM to suspend.
    1216  * @param   pvUser          Our fFatal flag.
    1217  *
    1218  * @thread  EMT
     1221 * EMT rendezvous worker for VMR3Suspend.
     1222 *
     1223 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_SUSPEND. (This is a strict
     1224 *          return code, see FNVMMEMTRENDEZVOUS.)
     1225 *
     1226 * @param   pVM             The VM handle.
     1227 * @param   pVCpu           The VMCPU handle of the EMT.
     1228 * @param   pvUser          Ignored.
    12191229 */
    12201230static DECLCALLBACK(VBOXSTRICTRC) vmR3Suspend(PVM pVM, PVMCPU pVCpu, void *pvUser)
    12211231{
    1222 #if 0
    1223     if (!pVCpu) pVCpu = VMMGetCpu(pVM);
    1224 #endif
    12251232    LogFlow(("vmR3Suspend: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
    1226     Assert(!pvUser);
    1227     Assert(pVCpu);
     1233    Assert(!pvUser); NOREF(pvUser);
    12281234
    12291235    /*
     
    12831289    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    12841290
    1285 #if 0 /* if the code below screws up, this should still work */
    1286     /*
    1287      * Forward the operation to EMT in reverse order so EMT(0) can do the
    1288      * actual suspending after the other ones have stopped running guest code.
    1289      */
    1290     int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL_REVERSE,
    1291                               (PFNRT)vmR3Suspend, 3, pVM, NULL, NULL);
    1292 #else
    12931291    /*
    12941292     * Gather all the EMTs to make sure there are no races before
     
    12971295    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
    12981296                                vmR3Suspend, NULL);
    1299 #endif
    1300 
    13011297    LogFlow(("VMR3Suspend: returns %Rrc\n", rc));
    13021298    return rc;
     
    13051301
    13061302/**
    1307  * Resume VM execution.
    1308  *
    1309  * @returns 0 on success.
    1310  * @returns VBox error code on failure.
    1311  * @param   pVM         The VM to resume.
    1312  * @thread  EMT
    1313  */
    1314 static DECLCALLBACK(int) vmR3Resume(PVM pVM)
    1315 {
    1316     LogFlow(("vmR3Resume: pVM=%p\n", pVM));
    1317 
    1318     /*
    1319      * EMT(0) does all the work *before* the others wake up.
    1320      */
    1321     PVMCPU pVCpu = VMMGetCpu(pVM);
    1322     if (pVCpu->idCpu == 0)
     1303 * EMT rendezvous worker for VMR3Resume.
     1304 *
     1305 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_RESUME. (This is a strict
     1306 *          return code, see FNVMMEMTRENDEZVOUS.)
     1307 *
     1308 * @param   pVM             The VM handle.
     1309 * @param   pVCpu           The VMCPU handle of the EMT.
     1310 * @param   pvUser          Ignored.
     1311 */
     1312static DECLCALLBACK(VBOXSTRICTRC) vmR3Resume(PVM pVM, PVMCPU pVCpu, void *pvUser)
     1313{
     1314    LogFlow(("vmR3Resume: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
     1315    Assert(!pvUser); NOREF(pvUser);
     1316
     1317    /*
     1318     * The first thread thru here tries to change the state.  We shouldn't be
     1319     * called again if this fails.
     1320     */
     1321    if (pVCpu->idCpu == pVM->cCpus - 1)
    13231322    {
    13241323        int rc = vmR3TrySetState(pVM, "VMR3Resume", 1, VMSTATE_RESUMING, VMSTATE_SUSPENDED);
    13251324        if (RT_FAILURE(rc))
    13261325            return rc;
    1327 
    1328         /* Perform resume notifications. */
     1326    }
     1327
     1328    VMSTATE enmVMState = VMR3GetState(pVM);
     1329    AssertMsgReturn(enmVMState == VMSTATE_RESUMING,
     1330                    ("%s\n", VMR3GetStateName(enmVMState)),
     1331                    VERR_INTERNAL_ERROR_4);
     1332
     1333#if 0
     1334    /*
     1335     * All EMTs changes their state to started.
     1336     */
     1337    VMCPU_SET_STATE(pVCpu, VMCPUSTATE_STARTED);
     1338#endif
     1339
     1340    /*
     1341     * EMT(0) is last thru here and it will make the notification calls
     1342     * and advance the state.
     1343     */
     1344    if (pVCpu->idCpu == 0)
     1345    {
    13291346        PDMR3Resume(pVM);
    1330 
    1331         /* Advance to the final state. */
    13321347        vmR3SetState(pVM, VMSTATE_RUNNING, VMSTATE_RESUMING);
    13331348    }
    13341349
    1335     /** @todo there is a race here: Someone could suspend, power off, raise a fatal
    1336      *        error (both kinds), save the vm, or start a live save operation before
    1337      *        we get here on all CPUs. Only safe way is a cross call, or to make
    1338      *        the last thread flip the state from Resuming to Running. While the
    1339      *        latter seems easy and perhaps more attractive, the former might be
    1340      *        better wrt TSC/TM... */
    1341     AssertMsgReturn(VMR3GetState(pVM) == VMSTATE_RUNNING, ("%s\n", VMR3GetStateName(VMR3GetState(pVM))), VERR_VM_INVALID_VM_STATE);
    13421350    return VINF_EM_RESUME;
    13431351}
    1344 
    1345 
    13461352
    13471353
     
    13641370
    13651371    /*
    1366      * Forward the request to the EMTs (EMT(0) first as it does all the
    1367      * work upfront).
    1368      */
    1369     int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL, (PFNRT)vmR3Resume, 1, pVM);
     1372     * Gather all the EMTs to make sure there are no races before
     1373     * changing the VM state.
     1374     */
     1375    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
     1376                                vmR3Resume, NULL);
    13701377    LogFlow(("VMR3Resume: returns %Rrc\n", rc));
    13711378    return rc;
     
    16921699
    16931700    /*
    1694      * Forward the request to EMT(0).
     1701     * Forward the request to EMT(0).  No need to setup a rendezvous here
     1702     * since there is no execution taking place when this call is allowed.
    16951703     */
    16961704    int rc = VMR3ReqCallWaitU(pVM->pUVM, 0 /*idDstCpu*/,
     
    17021710
    17031711/**
    1704  * Worker for VMR3PowerOff that does the actually powering off on EMT(0) after
    1705  * cycling thru the other EMTs first.
    1706  *
    1707  * @returns VBox strict status code.
    1708  *
    1709  * @param   pVM     The VM handle.
    1710  * @param   pVCpu   The VMCPU of the EMT.
    1711  * @param   pvUser  Unused user argument.
    1712  *
    1713  * @thread      EMT.
     1712 * EMT rendezvous worker for VMR3PowerOff.
     1713 *
     1714 * @returns VERR_VM_INVALID_VM_STATE or VINF_EM_OFF. (This is a strict
     1715 *          return code, see FNVMMEMTRENDEZVOUS.)
     1716 *
     1717 * @param   pVM             The VM handle.
     1718 * @param   pVCpu           The VMCPU handle of the EMT.
     1719 * @param   pvUser          Ignored.
    17141720 */
    17151721static DECLCALLBACK(VBOXSTRICTRC) vmR3PowerOff(PVM pVM, PVMCPU pVCpu, void *pvUser)
    17161722{
    1717 #if 0
    1718     pVCpu = VMMGetCpu(pVM);
    1719 #endif
    17201723    LogFlow(("vmR3PowerOff: pVM=%p pVCpu=%p/#%u\n", pVM, pVCpu, pVCpu->idCpu));
    1721     NOREF(pvUser);
     1724    Assert(!pvUser); NOREF(pvUser);
    17221725
    17231726    /*
     
    18531856    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    18541857
    1855 #if 0
    1856     /*
    1857      * Forward the request to the EMTs in reverse order, making all the other
    1858      * EMTs stop working before EMT(0) comes and does the actual powering off.
    1859      */
    1860     int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL_REVERSE, (PFNRT)vmR3PowerOff, 3, pVM, NULL, NULL);
    1861 #else
    18621858    /*
    18631859     * Gather all the EMTs to make sure there are no races before
     
    18661862    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
    18671863                                vmR3PowerOff, NULL);
    1868 
    1869 #endif
    18701864    LogFlow(("VMR3PowerOff: returns %Rrc\n", rc));
    18711865    return rc;
     
    23912385
    23922386/**
    2393  * Reset request processor.
    2394  *
    2395  * This is called by the emulation threads as a response to the
    2396  * reset request issued by VMR3Reset().
    2397  *
    2398  * @returns VBox strict status code.
    2399  * @param   pVM     The VM to reset.
    2400  * @param   pVCpu   The VMCPU of the EMT.
    2401  * @param   pvUser  Unused argument.
     2387 * EMT rendezvous worker for VMR3Reset.
     2388 *
     2389 * This is called by the emulation threads as a response to the reset request
     2390 * issued by VMR3Reset().
     2391 *
     2392 * @returns VERR_VM_INVALID_VM_STATE, VINF_EM_RESET or VINF_EM_SUSPEND. (This
     2393 *          is a strict return code, see FNVMMEMTRENDEZVOUS.)
     2394 *
     2395 * @param   pVM             The VM handle.
     2396 * @param   pVCpu           The VMCPU handle of the EMT.
     2397 * @param   pvUser          Ignored.
    24022398 */
    24032399static DECLCALLBACK(VBOXSTRICTRC) vmR3Reset(PVM pVM, PVMCPU pVCpu, void *pvUser)
    24042400{
    2405 #if 0
    2406     pVCpu = VMMGetCpu(pVM);
    2407 #endif
    2408     Assert(!pvUser);
    2409     NOREF(pvUser);
     2401    Assert(!pvUser); NOREF(pvUser);
    24102402
    24112403    /*
     
    25292521    VM_ASSERT_VALID_EXT_RETURN(pVM, VERR_INVALID_VM_HANDLE);
    25302522
    2531 #if 0
    2532     /*
    2533      * Forward the query to the EMTs in reverse order, so all the other EMT are
    2534      * dosile when EMT(0) does the actual resetting.
    2535      */
    2536     int rc = VMR3ReqCallWaitU(pVM->pUVM, VMCPUID_ALL_REVERSE, (PFNRT)vmR3Reset, 3, pVM, NULL, NULL);
    2537 #else
    25382523    /*
    25392524     * Gather all the EMTs to make sure there are no races before
     
    25422527    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
    25432528                                vmR3Reset, NULL);
    2544 #endif
    25452529    LogFlow(("VMR3Reset: returns %Rrc\n", rc));
    25462530    return rc;
     
    26422626        case VMSTATE_POWERING_ON:
    26432627            AssertMsgReturn(   enmStateNew == VMSTATE_RUNNING
    2644                             || enmStateNew == VMSTATE_FATAL_ERROR /*?*/
     2628                            /*|| enmStateNew == VMSTATE_FATAL_ERROR ?*/
    26452629                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
    26462630            break;
     
    26482632        case VMSTATE_RESUMING:
    26492633            AssertMsgReturn(   enmStateNew == VMSTATE_RUNNING
    2650                             || enmStateNew == VMSTATE_FATAL_ERROR /*?*/
     2634                            /*|| enmStateNew == VMSTATE_FATAL_ERROR ?*/
    26512635                            , ("%s -> %s\n", VMR3GetStateName(enmStateOld), VMR3GetStateName(enmStateNew)), false);
    26522636            break;
     
    34713455 *          code, see FNVMMEMTRENDEZVOUS.)
    34723456 *
    3473  * @param   pVM                 The VM handle.
    3474  * @param   pVCpu               The VMCPU handle of the EMT.
    3475  * @param   pvUser              Unused user argument.
     3457 * @param   pVM             The VM handle.
     3458 * @param   pVCpu           The VMCPU handle of the EMT.
     3459 * @param   pvUser          Ignored.
    34763460 */
    34773461static DECLCALLBACK(VBOXSTRICTRC) vmR3SetRuntimeErrorChangeState(PVM pVM, PVMCPU pVCpu, void *pvUser)
    34783462{
    34793463    NOREF(pVCpu);
    3480     NOREF(pvUser);
     3464    Assert(!pvUser); NOREF(pvUser);
     3465
    34813466    int rc = vmR3TrySetState(pVM, "VMSetRuntimeError", 2,
    34823467                             VMSTATE_FATAL_ERROR,    VMSTATE_RUNNING,
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette