VirtualBox

Changeset 24730 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Nov 17, 2009 4:51:03 PM (15 years ago)
Author:
vboxsync
Message:

PDM: Implemented making device/driver/usb-device suspend and poweroff notifications asynchronous when needed. Also prepped the way for failing poweron and resume.

Location:
trunk/src/VBox/VMM
Files:
7 edited

Legend:

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

    r24692 r24730  
    912912
    913913/**
     914 * Worker for PDMR3PowerOn that deals with one driver.
     915 *
     916 * @param   pDrvIns             The driver instance.
     917 * @param   pszDeviceName       The parent device name.
     918 * @param   iDevInstance        The parent device instance number.
     919 * @param   iLun                The parent LUN number.
     920 */
     921DECLINLINE(bool) pdmR3PowerOnDrv(PPDMDRVINS pDrvIns, const char *pszDeviceName, uint32_t iDevInstance, uint32_t iLun)
     922{
     923    Assert(pDrvIns->Internal.s.fVMSuspended);
     924    if (pDrvIns->pDrvReg->pfnPowerOn)
     925    {
     926        LogFlow(("PDMR3PowerOn: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
     927                 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
     928        int rc = VINF_SUCCESS; pDrvIns->pDrvReg->pfnPowerOn(pDrvIns);
     929        if (RT_FAILURE(rc))
     930        {
     931            LogRel(("PDMR3PowerOn: driver '%s'/%d on LUN#%d of device '%s'/%d -> %Rrc\n",
     932                    pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance, rc));
     933            return rc;
     934        }
     935    }
     936    pDrvIns->Internal.s.fVMSuspended = false;
     937    return VINF_SUCCESS;
     938}
     939
     940
     941/**
     942 * Worker for PDMR3PowerOn that deals with one USB device instance.
     943 *
     944 * @returns VBox status code.
     945 * @param   pUsbIns             The USB device instance.
     946 */
     947DECLINLINE(int) pdmR3PowerOnUsb(PPDMUSBINS pUsbIns)
     948{
     949    Assert(pUsbIns->Internal.s.fVMSuspended);
     950    if (pUsbIns->pUsbReg->pfnVMPowerOn)
     951    {
     952        LogFlow(("PDMR3PowerOn: Notifying - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
     953        int rc = VINF_SUCCESS; pUsbIns->pUsbReg->pfnVMPowerOn(pUsbIns);
     954        if (RT_FAILURE(rc))
     955        {
     956            LogRel(("PDMR3PowerOn: device '%s'/%d -> %Rrc\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, rc));
     957            return rc;
     958        }
     959    }
     960    pUsbIns->Internal.s.fVMSuspended = false;
     961    return VINF_SUCCESS;
     962}
     963
     964
     965/**
     966 * Worker for PDMR3PowerOn that deals with one device instance.
     967 *
     968 * @returns VBox status code.
     969 * @param   pDevIns             The device instance.
     970 */
     971DECLINLINE(int) pdmR3PowerOnDev(PPDMDEVINS pDevIns)
     972{
     973    Assert(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_SUSPENDED);
     974    if (pDevIns->pDevReg->pfnPowerOn)
     975    {
     976        LogFlow(("PDMR3PowerOn: Notifying - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     977        int rc = VINF_SUCCESS; pDevIns->pDevReg->pfnPowerOn(pDevIns);
     978        if (RT_FAILURE(rc))
     979        {
     980            LogRel(("PDMR3PowerOn: device '%s'/%d -> %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     981            return rc;
     982        }
     983    }
     984    pDevIns->Internal.s.fIntFlags &= ~PDMDEVINSINT_FLAGS_SUSPENDED;
     985    return VINF_SUCCESS;
     986}
     987
     988
     989/**
    914990 * This function will notify all the devices and their
    915991 * attached drivers about the VM now being powered on.
     
    922998
    923999    /*
    924      * Iterate the device instances.
    925      * The attached drivers are processed first.
    926      */
    927     for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
    928     {
    929         for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
    930             /** @todo Inverse the order here? */
    931             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    932                 if (pDrvIns->pDrvReg->pfnPowerOn)
    933                 {
    934                     LogFlow(("PDMR3PowerOn: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
    935                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    936                     pDrvIns->pDrvReg->pfnPowerOn(pDrvIns);
    937                 }
    938 
    939         if (pDevIns->pDevReg->pfnPowerOn)
    940         {
    941             LogFlow(("PDMR3PowerOn: Notifying - device '%s'/%d\n",
    942                      pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    943             pDevIns->pDevReg->pfnPowerOn(pDevIns);
    944         }
     1000     * Iterate thru the device instances and USB device instances,
     1001     * processing the drivers associated with those.
     1002     */
     1003    int rc = VINF_SUCCESS;
     1004    for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances;  pDevIns && RT_SUCCESS(rc);  pDevIns = pDevIns->Internal.s.pNextR3)
     1005    {
     1006        for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;  pLun && RT_SUCCESS(rc);  pLun = pLun->pNext)
     1007            for (PPDMDRVINS pDrvIns = pLun->pTop;  pDrvIns && RT_SUCCESS(rc);  pDrvIns = pDrvIns->Internal.s.pDown)
     1008                rc = pdmR3PowerOnDrv(pDrvIns, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pLun->iLun);
     1009        if (RT_SUCCESS(rc))
     1010            rc = pdmR3PowerOnDev(pDevIns);
    9451011    }
    9461012
    9471013#ifdef VBOX_WITH_USB
    948     for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
    949     {
    950         for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
    951             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    952                 if (pDrvIns->pDrvReg->pfnPowerOn)
    953                 {
    954                     LogFlow(("PDMR3PowerOn: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
    955                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    956                     pDrvIns->pDrvReg->pfnPowerOn(pDrvIns);
    957                 }
    958 
    959         if (pUsbIns->pUsbReg->pfnVMPowerOn)
    960         {
    961             LogFlow(("PDMR3PowerOn: Notifying - device '%s'/%d\n",
    962                      pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    963             pUsbIns->pUsbReg->pfnVMPowerOn(pUsbIns);
    964         }
     1014    for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances;  pUsbIns && RT_SUCCESS(rc);  pUsbIns = pUsbIns->Internal.s.pNext)
     1015    {
     1016        for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns;  pLun && RT_SUCCESS(rc);  pLun = pLun->pNext)
     1017            for (PPDMDRVINS pDrvIns = pLun->pTop;  pDrvIns && RT_SUCCESS(rc);  pDrvIns = pDrvIns->Internal.s.pDown)
     1018                rc = pdmR3PowerOnDrv(pDrvIns, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, pLun->iLun);
     1019        if (RT_SUCCESS(rc))
     1020            rc = pdmR3PowerOnUsb(pUsbIns);
    9651021    }
    9661022#endif
     
    9691025     * Resume all threads.
    9701026     */
    971     pdmR3ThreadResumeAll(pVM);
    972 
    973     LogFlow(("PDMR3PowerOn: returns void\n"));
     1027    if (RT_SUCCESS(rc))
     1028        pdmR3ThreadResumeAll(pVM);
     1029
     1030    /*
     1031     * On failure, clean up via PDMR3Suspend.
     1032     */
     1033    if (RT_FAILURE(rc))
     1034        PDMR3Suspend(pVM);
     1035
     1036    LogFlow(("PDMR3PowerOn: returns %Rrc\n", rc));
     1037    return /*rc*/;
    9741038}
    9751039
     
    10501114
    10511115/**
    1052  * This function will notify all the devices and their
    1053  * attached drivers about the VM now being suspended.
    1054  *
    1055  * @param   pVM     VM Handle.
     1116 * Worker for PDMR3Suspend that deals with one driver.
     1117 *
     1118 * @param   pDrvIns             The driver instance.
     1119 * @param   pcAsync             The asynchronous suspend notification counter.
     1120 * @param   pszDeviceName       The parent device name.
     1121 * @param   iDevInstance        The parent device instance number.
     1122 * @param   iLun                The parent LUN number.
     1123 */
     1124DECLINLINE(bool) pdmR3SuspendDrv(PPDMDRVINS pDrvIns, unsigned *pcAsync,
     1125                                 const char *pszDeviceName, uint32_t iDevInstance, uint32_t iLun)
     1126{
     1127    if (!pDrvIns->Internal.s.fVMSuspended)
     1128    {
     1129        pDrvIns->Internal.s.fVMSuspended = true;
     1130        if (pDrvIns->pDrvReg->pfnSuspend)
     1131        {
     1132            if (!pDrvIns->Internal.s.pfnAsyncNotify)
     1133            {
     1134                LogFlow(("PDMR3Suspend: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
     1135                         pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
     1136                pDrvIns->pDrvReg->pfnSuspend(pDrvIns);
     1137            }
     1138            else if (pDrvIns->Internal.s.pfnAsyncNotify(pDrvIns))
     1139            {
     1140                pDrvIns->Internal.s.pfnAsyncNotify = false;
     1141                LogFlow(("PDMR3Suspend: Async notification completed - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
     1142                         pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
     1143            }
     1144            if (pDrvIns->Internal.s.pfnAsyncNotify)
     1145            {
     1146                pDrvIns->Internal.s.fVMSuspended = false;
     1147                (*pcAsync)++;
     1148                return false;
     1149            }
     1150        }
     1151    }
     1152    return true;
     1153}
     1154
     1155
     1156/**
     1157 * Worker for PDMR3Suspend that deals with one USB device instance.
     1158 *
     1159 * @param   pUsbIns             The USB device instance.
     1160 * @param   pcAsync             The asynchronous suspend notification counter.
     1161 */
     1162DECLINLINE(void) pdmR3SuspendUsb(PPDMUSBINS pUsbIns, unsigned *pcAsync)
     1163{
     1164    if (!pUsbIns->Internal.s.fVMSuspended)
     1165    {
     1166        pUsbIns->Internal.s.fVMSuspended = true;
     1167        if (pUsbIns->pUsbReg->pfnVMSuspend)
     1168        {
     1169            if (!pUsbIns->Internal.s.pfnAsyncNotify)
     1170            {
     1171                LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
     1172                pUsbIns->pUsbReg->pfnVMSuspend(pUsbIns);
     1173            }
     1174            else if (pUsbIns->Internal.s.pfnAsyncNotify(pUsbIns))
     1175            {
     1176                LogFlow(("PDMR3Suspend: Async notification completed - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
     1177                pUsbIns->Internal.s.pfnAsyncNotify = NULL;
     1178            }
     1179            if (pUsbIns->Internal.s.pfnAsyncNotify)
     1180            {
     1181                pUsbIns->Internal.s.fVMSuspended = false;
     1182                (*pcAsync)++;
     1183            }
     1184        }
     1185    }
     1186}
     1187
     1188
     1189/**
     1190 * Worker for PDMR3Suspend that deals with one device instance.
     1191 *
     1192 * @param   pDevIns             The device instance.
     1193 * @param   pcAsync             The asynchronous suspend notification counter.
     1194 */
     1195DECLINLINE(void) pdmR3SuspendDev(PPDMDEVINS pDevIns, unsigned *pcAsync)
     1196{
     1197    if (!(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_SUSPENDED))
     1198    {
     1199        pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_SUSPENDED;
     1200        if (pDevIns->pDevReg->pfnSuspend)
     1201        {
     1202            if (!pDevIns->Internal.s.pfnAsyncNotify)
     1203            {
     1204                LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1205                pDevIns->pDevReg->pfnSuspend(pDevIns);
     1206            }
     1207            else if (pDevIns->Internal.s.pfnAsyncNotify(pDevIns))
     1208            {
     1209                LogFlow(("PDMR3Suspend: Async notification completed - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1210                pDevIns->Internal.s.pfnAsyncNotify = NULL;
     1211            }
     1212            if (pDevIns->Internal.s.pfnAsyncNotify)
     1213            {
     1214                pDevIns->Internal.s.fIntFlags &= ~PDMDEVINSINT_FLAGS_SUSPENDED;
     1215                (*pcAsync)++;
     1216            }
     1217        }
     1218    }
     1219}
     1220
     1221
     1222/**
     1223 * This function will notify all the devices and their attached drivers about
     1224 * the VM now being suspended.
     1225 *
     1226 * @param   pVM     The VM Handle.
    10561227 * @thread  EMT(0)
    10571228 */
     
    10621233
    10631234    /*
    1064      * Iterate the device instances.
    1065      * The attached drivers are processed first.
    1066      */
    1067     for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
     1235     * The outer loop repeats until there are no more async requests.
     1236     *
     1237     * Note! We depend on the suspended indicators to be in the desired state
     1238     *       and we do not reset them before starting because this allows
     1239     *       PDMR3PowerOn and PDMR3Resume to use PDMR3Suspend for cleaning up
     1240     *       on failure.
     1241     */
     1242    unsigned cAsync;
     1243    for (;;)
    10681244    {
    10691245        /*
    1070          * Some devices need to be notified first that the VM is suspended to ensure that that there are no pending
    1071          * requests from the guest which are still processed. Calling the drivers before these requests are finished
    1072          * might lead to errors otherwise. One example is the SATA controller which might still have I/O requests
    1073          * pending. But DrvVD sets the files into readonly mode and every request will fail then.
     1246         * Iterate thru the device instances and USB device instances,
     1247         * processing the drivers associated with those.
     1248         *
     1249         * The attached drivers are normally processed first.  Some devices
     1250         * (like DevAHCI) though needs to be notified before the drivers so
     1251         * that it doesn't kick off any new requests after the drivers stopped
     1252         * taking any. (DrvVD changes to read-only in this particular case.)
    10741253         */
    1075         if (pDevIns->pDevReg->pfnSuspend && (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION))
    1076         {
    1077             LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n",
    1078                      pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1079             pDevIns->pDevReg->pfnSuspend(pDevIns);
    1080         }
    1081 
    1082         for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
    1083             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    1084                 if (pDrvIns->pDrvReg->pfnSuspend)
    1085                 {
    1086                     LogFlow(("PDMR3Suspend: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
    1087                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1088                     pDrvIns->pDrvReg->pfnSuspend(pDrvIns);
    1089                 }
    1090 
    1091         /* Don't call the suspend notification again if it was already called. */
    1092         if (pDevIns->pDevReg->pfnSuspend && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION))
    1093         {
    1094             LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n",
    1095                      pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1096             pDevIns->pDevReg->pfnSuspend(pDevIns);
    1097         }
    1098     }
     1254        cAsync = 0;
     1255        for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
     1256        {
     1257            unsigned const cAsyncStart = cAsync;
     1258
     1259            if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION)
     1260                pdmR3SuspendDev(pDevIns, &cAsync);
     1261
     1262            if (cAsync == cAsyncStart)
     1263                for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
     1264                    for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
     1265                        if (!pdmR3SuspendDrv(pDrvIns, &cAsync, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pLun->iLun))
     1266                            break;
     1267
     1268            if (    cAsync == cAsyncStart
     1269                && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_SUSPEND_NOTIFICATION))
     1270                pdmR3SuspendDev(pDevIns, &cAsync);
     1271        }
    10991272
    11001273#ifdef VBOX_WITH_USB
    1101     for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
    1102     {
    1103         for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
    1104             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    1105                 if (pDrvIns->pDrvReg->pfnSuspend)
    1106                 {
    1107                     LogFlow(("PDMR3Suspend: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
    1108                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    1109                     pDrvIns->pDrvReg->pfnSuspend(pDrvIns);
    1110                 }
    1111 
    1112         if (pUsbIns->pUsbReg->pfnVMSuspend)
    1113         {
    1114             LogFlow(("PDMR3Suspend: Notifying - device '%s'/%d\n",
    1115                      pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    1116             pUsbIns->pUsbReg->pfnVMSuspend(pUsbIns);
    1117         }
    1118     }
     1274        for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
     1275        {
     1276            unsigned const cAsyncStart = cAsync;
     1277
     1278            for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
     1279                for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
     1280                    if (!pdmR3SuspendDrv(pDrvIns, &cAsync, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, pLun->iLun))
     1281                        break;
     1282
     1283            if (cAsync == cAsyncStart)
     1284                pdmR3SuspendUsb(pUsbIns, &cAsync);
     1285        }
    11191286#endif
     1287        if (!cAsync)
     1288            break;
     1289
     1290        /*
     1291         * Process requests.
     1292         */
     1293        /** @todo This is utterly nuts and completely unsafe... will get back to it in a
     1294         *        bit I hope... */
     1295        int rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY);
     1296        AssertReleaseRC(rc == VINF_SUCCESS);
     1297    }
    11201298
    11211299    /*
     
    11251303
    11261304    LogFlow(("PDMR3Suspend: returns void\n"));
     1305}
     1306
     1307
     1308/**
     1309 * Worker for PDMR3Resume that deals with one driver.
     1310 *
     1311 * @param   pDrvIns             The driver instance.
     1312 * @param   pszDeviceName       The parent device name.
     1313 * @param   iDevInstance        The parent device instance number.
     1314 * @param   iLun                The parent LUN number.
     1315 */
     1316DECLINLINE(bool) pdmR3ResumeDrv(PPDMDRVINS pDrvIns, const char *pszDeviceName, uint32_t iDevInstance, uint32_t iLun)
     1317{
     1318    Assert(pDrvIns->Internal.s.fVMSuspended);
     1319    if (pDrvIns->pDrvReg->pfnResume)
     1320    {
     1321        LogFlow(("PDMR3Resume: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
     1322                 pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
     1323        int rc = VINF_SUCCESS; pDrvIns->pDrvReg->pfnResume(pDrvIns);
     1324        if (RT_FAILURE(rc))
     1325        {
     1326            LogRel(("PDMR3Resume: driver '%s'/%d on LUN#%d of device '%s'/%d -> %Rrc\n",
     1327                    pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance, rc));
     1328            return rc;
     1329        }
     1330    }
     1331    pDrvIns->Internal.s.fVMSuspended = false;
     1332    return VINF_SUCCESS;
     1333}
     1334
     1335
     1336/**
     1337 * Worker for PDMR3Resume that deals with one USB device instance.
     1338 *
     1339 * @returns VBox status code.
     1340 * @param   pUsbIns             The USB device instance.
     1341 */
     1342DECLINLINE(int) pdmR3ResumeUsb(PPDMUSBINS pUsbIns)
     1343{
     1344    Assert(pUsbIns->Internal.s.fVMSuspended);
     1345    if (pUsbIns->pUsbReg->pfnVMResume)
     1346    {
     1347        LogFlow(("PDMR3Resume: Notifying - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
     1348        int rc = VINF_SUCCESS; pUsbIns->pUsbReg->pfnVMResume(pUsbIns);
     1349        if (RT_FAILURE(rc))
     1350        {
     1351            LogRel(("PDMR3Resume: device '%s'/%d -> %Rrc\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, rc));
     1352            return rc;
     1353        }
     1354    }
     1355    pUsbIns->Internal.s.fVMSuspended = false;
     1356    return VINF_SUCCESS;
     1357}
     1358
     1359
     1360/**
     1361 * Worker for PDMR3Resume that deals with one device instance.
     1362 *
     1363 * @returns VBox status code.
     1364 * @param   pDevIns             The device instance.
     1365 */
     1366DECLINLINE(int) pdmR3ResumeDev(PPDMDEVINS pDevIns)
     1367{
     1368    Assert(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_SUSPENDED);
     1369    if (pDevIns->pDevReg->pfnResume)
     1370    {
     1371        LogFlow(("PDMR3Resume: Notifying - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1372        int rc = VINF_SUCCESS; pDevIns->pDevReg->pfnResume(pDevIns);
     1373        if (RT_FAILURE(rc))
     1374        {
     1375            LogRel(("PDMR3Resume: device '%s'/%d -> %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
     1376            return rc;
     1377        }
     1378    }
     1379    pDevIns->Internal.s.fIntFlags &= ~PDMDEVINSINT_FLAGS_SUSPENDED;
     1380    return VINF_SUCCESS;
    11271381}
    11281382
     
    11391393
    11401394    /*
    1141      * Iterate the device instances.
    1142      * The attached drivers are processed first.
    1143      */
    1144     for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
    1145     {
    1146         for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
    1147             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    1148                 if (pDrvIns->pDrvReg->pfnResume)
    1149                 {
    1150                     LogFlow(("PDMR3Resume: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
    1151                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1152                     pDrvIns->pDrvReg->pfnResume(pDrvIns);
    1153                 }
    1154 
    1155         if (pDevIns->pDevReg->pfnResume)
    1156         {
    1157             LogFlow(("PDMR3Resume: Notifying - device '%s'/%d\n",
    1158                      pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1159             pDevIns->pDevReg->pfnResume(pDevIns);
    1160         }
     1395     * Iterate thru the device instances and USB device instances,
     1396     * processing the drivers associated with those.
     1397     */
     1398    int rc = VINF_SUCCESS;
     1399    for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances;  pDevIns && RT_SUCCESS(rc);  pDevIns = pDevIns->Internal.s.pNextR3)
     1400    {
     1401        for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3;  pLun && RT_SUCCESS(rc);  pLun    = pLun->pNext)
     1402            for (PPDMDRVINS pDrvIns = pLun->pTop;  pDrvIns && RT_SUCCESS(rc);  pDrvIns = pDrvIns->Internal.s.pDown)
     1403                rc = pdmR3ResumeDrv(pDrvIns, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pLun->iLun);
     1404        if (RT_SUCCESS(rc))
     1405            rc = pdmR3ResumeDev(pDevIns);
    11611406    }
    11621407
    11631408#ifdef VBOX_WITH_USB
    1164     for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
    1165     {
    1166         for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
    1167             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    1168                 if (pDrvIns->pDrvReg->pfnResume)
    1169                 {
    1170                     LogFlow(("PDMR3Resume: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
    1171                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    1172                     pDrvIns->pDrvReg->pfnResume(pDrvIns);
    1173                 }
    1174 
    1175         if (pUsbIns->pUsbReg->pfnVMResume)
    1176         {
    1177             LogFlow(("PDMR3Resume: Notifying - device '%s'/%d\n",
    1178                      pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    1179             pUsbIns->pUsbReg->pfnVMResume(pUsbIns);
    1180         }
     1409    for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances;  pUsbIns && RT_SUCCESS(rc);  pUsbIns = pUsbIns->Internal.s.pNext)
     1410    {
     1411        for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns;  pLun && RT_SUCCESS(rc);  pLun = pLun->pNext)
     1412            for (PPDMDRVINS pDrvIns = pLun->pTop;  pDrvIns && RT_SUCCESS(rc);  pDrvIns = pDrvIns->Internal.s.pDown)
     1413                rc = pdmR3ResumeDrv(pDrvIns, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, pLun->iLun);
     1414        if (RT_SUCCESS(rc))
     1415            rc = pdmR3ResumeUsb(pUsbIns);
    11811416    }
    11821417#endif
     
    11851420     * Resume all threads.
    11861421     */
    1187     pdmR3ThreadResumeAll(pVM);
    1188 
    1189     LogFlow(("PDMR3Resume: returns void\n"));
     1422    if (RT_SUCCESS(rc))
     1423        pdmR3ThreadResumeAll(pVM);
     1424
     1425    /*
     1426     * On failure, clean up via PDMR3Suspend.
     1427     */
     1428    if (RT_FAILURE(rc))
     1429        PDMR3Suspend(pVM);
     1430
     1431    LogFlow(("PDMR3Resume: returns %Rrc\n", rc));
     1432    return /*rc*/;
     1433}
     1434
     1435
     1436/**
     1437 * Worker for PDMR3PowerOff that deals with one driver.
     1438 *
     1439 * @param   pDrvIns             The driver instance.
     1440 * @param   pcAsync             The asynchronous power off notification counter.
     1441 * @param   pszDeviceName       The parent device name.
     1442 * @param   iDevInstance        The parent device instance number.
     1443 * @param   iLun                The parent LUN number.
     1444 */
     1445DECLINLINE(bool) pdmR3PowerOffDrv(PPDMDRVINS pDrvIns, unsigned *pcAsync,
     1446                                  const char *pszDeviceName, uint32_t iDevInstance, uint32_t iLun)
     1447{
     1448    if (!pDrvIns->Internal.s.fVMSuspended)
     1449    {
     1450        pDrvIns->Internal.s.fVMSuspended = true;
     1451        if (pDrvIns->pDrvReg->pfnSuspend)
     1452        {
     1453            if (!pDrvIns->Internal.s.pfnAsyncNotify)
     1454            {
     1455                LogFlow(("PDMR3PowerOff: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
     1456                         pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
     1457                pDrvIns->pDrvReg->pfnPowerOff(pDrvIns);
     1458            }
     1459            else if (pDrvIns->Internal.s.pfnAsyncNotify(pDrvIns))
     1460            {
     1461                pDrvIns->Internal.s.pfnAsyncNotify = false;
     1462                LogFlow(("PDMR3PowerOff: Async notification completed - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
     1463                         pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, iLun, pszDeviceName, iDevInstance));
     1464            }
     1465            if (pDrvIns->Internal.s.pfnAsyncNotify)
     1466            {
     1467                pDrvIns->Internal.s.fVMSuspended = false;
     1468                (*pcAsync)++;
     1469                return false;
     1470            }
     1471        }
     1472    }
     1473    return true;
     1474}
     1475
     1476
     1477/**
     1478 * Worker for PDMR3PowerOff that deals with one USB device instance.
     1479 *
     1480 * @param   pUsbIns             The USB device instance.
     1481 * @param   pcAsync             The asynchronous power off notification counter.
     1482 */
     1483DECLINLINE(void) pdmR3PowerOffUsb(PPDMUSBINS pUsbIns, unsigned *pcAsync)
     1484{
     1485    if (!pUsbIns->Internal.s.fVMSuspended)
     1486    {
     1487        pUsbIns->Internal.s.fVMSuspended = true;
     1488        if (pUsbIns->pUsbReg->pfnVMPowerOff)
     1489        {
     1490            if (!pUsbIns->Internal.s.pfnAsyncNotify)
     1491            {
     1492                LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
     1493                pUsbIns->pUsbReg->pfnVMPowerOff(pUsbIns);
     1494            }
     1495            else if (pUsbIns->Internal.s.pfnAsyncNotify(pUsbIns))
     1496            {
     1497                LogFlow(("PDMR3PowerOff: Async notification completed - device '%s'/%d\n", pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
     1498                pUsbIns->Internal.s.pfnAsyncNotify = NULL;
     1499            }
     1500            if (pUsbIns->Internal.s.pfnAsyncNotify)
     1501            {
     1502                pUsbIns->Internal.s.fVMSuspended = false;
     1503                (*pcAsync)++;
     1504            }
     1505        }
     1506    }
     1507}
     1508
     1509
     1510/**
     1511 * Worker for PDMR3PowerOff that deals with one device instance.
     1512 *
     1513 * @param   pDevIns             The device instance.
     1514 * @param   pcAsync             The asynchronous power off notification counter.
     1515 */
     1516DECLINLINE(void) pdmR3PowerOffDev(PPDMDEVINS pDevIns, unsigned *pcAsync)
     1517{
     1518    if (!(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_SUSPENDED))
     1519    {
     1520        pDevIns->Internal.s.fIntFlags |= PDMDEVINSINT_FLAGS_SUSPENDED;
     1521        if (pDevIns->pDevReg->pfnSuspend)
     1522        {
     1523            if (!pDevIns->Internal.s.pfnAsyncNotify)
     1524            {
     1525                LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1526                pDevIns->pDevReg->pfnPowerOff(pDevIns);
     1527            }
     1528            else if (pDevIns->Internal.s.pfnAsyncNotify(pDevIns))
     1529            {
     1530                LogFlow(("PDMR3PowerOff: Async notification completed - device '%s'/%d\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
     1531                pDevIns->Internal.s.pfnAsyncNotify = NULL;
     1532            }
     1533            if (pDevIns->Internal.s.pfnAsyncNotify)
     1534            {
     1535                pDevIns->Internal.s.fIntFlags &= ~PDMDEVINSINT_FLAGS_SUSPENDED;
     1536                (*pcAsync)++;
     1537            }
     1538        }
     1539    }
    11901540}
    11911541
     
    12021552
    12031553    /*
    1204      * Iterate the device instances.
    1205      * The attached drivers are processed first.
    1206      */
    1207     for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
    1208     {
    1209 
    1210         if (pDevIns->pDevReg->pfnPowerOff && (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION))
    1211         {
    1212             LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n",
    1213                      pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1214             pDevIns->pDevReg->pfnPowerOff(pDevIns);
    1215         }
    1216 
    1217         for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
    1218             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    1219                 if (pDrvIns->pDrvReg->pfnPowerOff)
    1220                 {
    1221                     LogFlow(("PDMR3PowerOff: Notifying - driver '%s'/%d on LUN#%d of device '%s'/%d\n",
    1222                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1223                     pDrvIns->pDrvReg->pfnPowerOff(pDrvIns);
    1224                 }
    1225 
    1226         if (pDevIns->pDevReg->pfnPowerOff && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION))
    1227         {
    1228             LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n",
    1229                      pDevIns->pDevReg->szDeviceName, pDevIns->iInstance));
    1230             pDevIns->pDevReg->pfnPowerOff(pDevIns);
    1231         }
    1232     }
     1554     * The outer loop repeats until there are no more async requests.
     1555     */
     1556    unsigned cAsync;
     1557    for (;;)
     1558    {
     1559        /*
     1560         * Iterate thru the device instances and USB device instances,
     1561         * processing the drivers associated with those.
     1562         *
     1563         * The attached drivers are normally processed first.  Some devices
     1564         * (like DevAHCI) though needs to be notified before the drivers so
     1565         * that it doesn't kick off any new requests after the drivers stopped
     1566         * taking any. (DrvVD changes to read-only in this particular case.)
     1567         */
     1568        cAsync = 0;
     1569        for (PPDMDEVINS pDevIns = pVM->pdm.s.pDevInstances; pDevIns; pDevIns = pDevIns->Internal.s.pNextR3)
     1570        {
     1571            unsigned const cAsyncStart = cAsync;
     1572
     1573            if (pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION)
     1574                pdmR3PowerOffDev(pDevIns, &cAsync);
     1575
     1576            if (cAsync == cAsyncStart)
     1577                for (PPDMLUN pLun = pDevIns->Internal.s.pLunsR3; pLun; pLun = pLun->pNext)
     1578                    for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
     1579                        if (!pdmR3PowerOffDrv(pDrvIns, &cAsync, pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pLun->iLun))
     1580                            break;
     1581
     1582            if (    cAsync == cAsyncStart
     1583                && !(pDevIns->pDevReg->fFlags & PDM_DEVREG_FLAGS_FIRST_POWEROFF_NOTIFICATION))
     1584                pdmR3PowerOffDev(pDevIns, &cAsync);
     1585        }
    12331586
    12341587#ifdef VBOX_WITH_USB
    1235     for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
    1236     {
    1237         for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
    1238             for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
    1239                 if (pDrvIns->pDrvReg->pfnPowerOff)
    1240                 {
    1241                     LogFlow(("PDMR3PowerOff: Notifying - driver '%s'/%d on LUN#%d of usb device '%s'/%d\n",
    1242                              pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pLun->iLun, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    1243                     pDrvIns->pDrvReg->pfnPowerOff(pDrvIns);
    1244                 }
    1245 
    1246         if (pUsbIns->pUsbReg->pfnVMPowerOff)
    1247         {
    1248             LogFlow(("PDMR3PowerOff: Notifying - device '%s'/%d\n",
    1249                      pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance));
    1250             pUsbIns->pUsbReg->pfnVMPowerOff(pUsbIns);
    1251         }
    1252     }
     1588        for (PPDMUSBINS pUsbIns = pVM->pdm.s.pUsbInstances; pUsbIns; pUsbIns = pUsbIns->Internal.s.pNext)
     1589        {
     1590            unsigned const cAsyncStart = cAsync;
     1591
     1592            for (PPDMLUN pLun = pUsbIns->Internal.s.pLuns; pLun; pLun = pLun->pNext)
     1593                for (PPDMDRVINS pDrvIns = pLun->pTop; pDrvIns; pDrvIns = pDrvIns->Internal.s.pDown)
     1594                    if (!pdmR3PowerOffDrv(pDrvIns, &cAsync, pUsbIns->pUsbReg->szDeviceName, pUsbIns->iInstance, pLun->iLun))
     1595                        break;
     1596
     1597            if (cAsync == cAsyncStart)
     1598                pdmR3PowerOffUsb(pUsbIns, &cAsync);
     1599        }
    12531600#endif
     1601        if (!cAsync)
     1602            break;
     1603
     1604        /*
     1605         * Process requests.
     1606         */
     1607        /** @todo This is utterly nuts and completely unsafe... will get back to it in a
     1608         *        bit I hope... */
     1609        int rc = VMR3ReqProcessU(pVM->pUVM, VMCPUID_ANY);
     1610        AssertReleaseRC(rc == VINF_SUCCESS);
     1611    }
    12541612
    12551613    /*
  • trunk/src/VBox/VMM/PDMDevHlp.cpp

    r24632 r24730  
    887887                        pNew->Internal.s.pVM            = pVM;
    888888                        //pNew->Internal.s.fDetaching     = false;
     889                        pNew->Internal.s.fVMSuspended   = true;
     890                        //pNew->Internal.s.pfnAsyncNotify = NULL;
    889891                        pNew->Internal.s.pCfgHandle     = pNode;
    890892                        pNew->pDrvHlp                   = &g_pdmR3DrvHlp;
     
    23242326    LogFlow(("pdmR3DevHlp_PhysGCPtr2GCPhys: caller='%s'/%d: returns %Rrc *pGCPhys=%RGp\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc, *pGCPhys));
    23252327
     2328    return rc;
     2329}
     2330
     2331
     2332/** @copydoc PDMDEVHLPR3::pfnSetAsyncNotification */
     2333static DECLCALLBACK(int) pdmR3DevHlp_SetAsyncNotification(PPDMDEVINS pDevIns, PFNPDMDEVASYNCNOTIFY pfnAsyncNotify)
     2334{
     2335    PDMDEV_ASSERT_DEVINS(pDevIns);
     2336    VM_ASSERT_EMT0(pDevIns->Internal.s.pVMR3);
     2337    LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, pfnAsyncNotify));
     2338
     2339    int rc = VINF_SUCCESS;
     2340    AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
     2341    AssertStmt(!pDevIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
     2342    AssertStmt(pDevIns->Internal.s.fIntFlags & PDMDEVINSINT_FLAGS_SUSPENDED, rc = VERR_WRONG_ORDER);
     2343    VMSTATE enmVMState = VMR3GetState(pDevIns->Internal.s.pVMR3);
     2344    AssertStmt(   enmVMState == VMSTATE_SUSPENDING
     2345               || enmVMState == VMSTATE_SUSPENDING_EXT_LS
     2346               || enmVMState == VMSTATE_SUSPENDING_LS
     2347               || enmVMState == VMSTATE_POWERING_OFF
     2348               || enmVMState == VMSTATE_POWERING_OFF_LS,
     2349               rc = VERR_INVALID_STATE);
     2350
     2351    if (RT_SUCCESS(rc))
     2352        pDevIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
     2353
     2354    LogFlow(("pdmR3DevHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDevIns->pDevReg->szDeviceName, pDevIns->iInstance, rc));
    23262355    return rc;
    23272356}
     
    28362865    pdmR3DevHlp_PDMThreadCreate,
    28372866    pdmR3DevHlp_PhysGCPtr2GCPhys,
     2867    pdmR3DevHlp_SetAsyncNotification,
    28382868    0,
    28392869    0,
     
    33013331    pdmR3DevHlp_PDMThreadCreate,
    33023332    pdmR3DevHlp_PhysGCPtr2GCPhys,
     3333    pdmR3DevHlp_SetAsyncNotification,
    33033334    0,
    33043335    0,
  • trunk/src/VBox/VMM/PDMDevice.cpp

    r24272 r24730  
    325325        //pDevIns->Internal.s.pPciDeviceRC        = 0;
    326326        //pDevIns->Internal.s.pPciBusRC           = 0;
     327        pDevIns->Internal.s.fIntFlags           = PDMDEVINSINT_FLAGS_SUSPENDED;
    327328        pDevIns->pDevHlpR3                      = fTrusted ? &g_pdmR3DevHlpTrusted : &g_pdmR3DevHlpUnTrusted;
    328329        pDevIns->pDevHlpRC                      = pDevHlpRC;
  • trunk/src/VBox/VMM/PDMDriver.cpp

    r24282 r24730  
    536536                            pNew->Internal.s.pVM            = pVM;
    537537                            pNew->Internal.s.fDetaching     = false;
     538                            pNew->Internal.s.fVMSuspended   = true;
     539                            pNew->Internal.s.pfnAsyncNotify = NULL;
    538540                            pNew->Internal.s.pCfgHandle     = pNode;
    539541                            pNew->pDrvHlp                   = &g_pdmR3DrvHlp;
     
    10171019
    10181020
     1021/** @copydoc PDMDRVHLP::pfnSetAsyncNotification */
     1022static DECLCALLBACK(int) pdmR3DrvHlp_SetAsyncNotification(PPDMDRVINS pDrvIns, PFNPDMDRVASYNCNOTIFY pfnAsyncNotify)
     1023{
     1024    PDMDRV_ASSERT_DRVINS(pDrvIns);
     1025    VM_ASSERT_EMT0(pDrvIns->Internal.s.pVM);
     1026    LogFlow(("pdmR3DrvHlp_SetAsyncNotification: caller='%s'/%d: pfnAsyncNotify=%p\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pfnAsyncNotify));
     1027
     1028    int rc = VINF_SUCCESS;
     1029    AssertStmt(pfnAsyncNotify, rc = VERR_INVALID_PARAMETER);
     1030    AssertStmt(!pDrvIns->Internal.s.pfnAsyncNotify, rc = VERR_WRONG_ORDER);
     1031    AssertStmt(pDrvIns->Internal.s.fVMSuspended, rc = VERR_WRONG_ORDER);
     1032    VMSTATE enmVMState = VMR3GetState(pDrvIns->Internal.s.pVM);
     1033    AssertStmt(   enmVMState == VMSTATE_SUSPENDING
     1034               || enmVMState == VMSTATE_SUSPENDING_EXT_LS
     1035               || enmVMState == VMSTATE_SUSPENDING_LS
     1036               || enmVMState == VMSTATE_POWERING_OFF
     1037               || enmVMState == VMSTATE_POWERING_OFF_LS,
     1038               rc = VERR_INVALID_STATE);
     1039
     1040    if (RT_SUCCESS(rc))
     1041        pDrvIns->Internal.s.pfnAsyncNotify = pfnAsyncNotify;
     1042
     1043    LogFlow(("pdmR3DrvHlp_SetAsyncNotification: caller='%s'/%d: returns %Rrc\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc));
     1044    return rc;
     1045}
     1046
     1047
    10191048/** @copydoc PDMDRVHLP::pfnPDMThreadCreate */
    10201049static DECLCALLBACK(int) pdmR3DrvHlp_PDMThreadCreate(PPDMDRVINS pDrvIns, PPPDMTHREAD ppThread, void *pvUser, PFNPDMTHREADDRV pfnThread,
     
    10841113    pdmR3DrvHlp_SUPCallVMMR0Ex,
    10851114    pdmR3DrvHlp_USBRegisterHub,
     1115    pdmR3DrvHlp_SetAsyncNotification,
    10861116    pdmR3DrvHlp_PDMThreadCreate,
    10871117#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
  • trunk/src/VBox/VMM/PDMInternal.h

    r24127 r24730  
    2323#define ___PDMInternal_h
    2424
    25 #include <VBox/cdefs.h>
    2625#include <VBox/types.h>
    2726#include <VBox/param.h>
     
    3029#include <VBox/vusb.h>
    3130#include <VBox/pdmasynccompletion.h>
     31#include <VBox/pdmcommon.h>
    3232#include <iprt/assert.h>
    3333#include <iprt/critsect.h>
     
    101101    /** Pointer to the list of logical units associated with the device. (FIFO) */
    102102    R3PTRTYPE(PPDMLUN)              pLunsR3;
     103    /** Pointer to the asynchronous notification callback set while in
     104     * FNPDMDEVSUSPEND or FNPDMDEVPOWEROFF. */
     105    R3PTRTYPE(PFNPDMDEVASYNCNOTIFY) pfnAsyncNotify;
    103106    /** Configuration handle to the instance node. */
    104107    R3PTRTYPE(PCFGMNODE)            pCfgHandle;
     
    117120    /** R0 pointer to associated PCI bus structure. */
    118121    R0PTRTYPE(PPDMPCIBUS)           pPciBusR0;
    119     /** Alignment padding. */
    120     RTR0PTR                         Alignment0;
    121122
    122123    /** RC pointer to the VM this instance was created for. */
     
    135136/** Used by pdmR3Load to mark device instances it found in the saved state. */
    136137#define PDMDEVINSINT_FLAGS_FOUND         RT_BIT_32(0)
     138/** Indicates that the device hasn't been powered on or resumed.
     139 * This is used by PDMR3PowerOn, PDMR3Resume, PDMR3Suspend and PDMR3PowerOff
     140 * to make sure each device gets exactly one notification for each of those
     141 * events.  PDMR3Resume and PDMR3PowerOn also makes use of it to bail out on
     142 * a failure (already resumed/powered-on devices are suspended). */
     143#define PDMDEVINSINT_FLAGS_SUSPENDED     RT_BIT_32(1)
    137144/** @} */
    138145
     
    171178    /** The port number that we're connected to. */
    172179    uint32_t                        iPort;
    173 #if HC_ARCH_BITS == 64
    174     uint32_t                        Alignment0;
    175 #endif
     180    /** Indicates that the driver hasn't been powered on or resumed.
     181     * See PDMDEVINSINT_FLAGS_SUSPENDED. */
     182    bool                            fVMSuspended;
     183    /** Pointer to the asynchronous notification callback set while in
     184     * FNPDMDEVSUSPEND or FNPDMDEVPOWEROFF. */
     185    R3PTRTYPE(PFNPDMUSBASYNCNOTIFY) pfnAsyncNotify;
    176186} PDMUSBINSINT;
    177187
     
    197207     * (Helps detect potential recursive detaching.) */
    198208    bool                            fDetaching;
     209    /** Indicates that the driver hasn't been powered on or resumed.
     210     * See PDMDEVINSINT_FLAGS_SUSPENDED. */
     211    bool                            fVMSuspended;
     212    /** Pointer to the asynchronous notification callback set while in
     213     * PDMUSBREG::pfnVMSuspend or PDMUSBREG::pfnVMPowerOff. */
     214    R3PTRTYPE(PFNPDMDRVASYNCNOTIFY) pfnAsyncNotify;
    199215    /** Configuration handle to the instance node. */
    200216    PCFGMNODE                       pCfgHandle;
  • trunk/src/VBox/VMM/VM.cpp

    r24567 r24730  
    12101210    int rc = VMMR3EmtRendezvous(pVM, VMMEMTRENDEZVOUS_FLAGS_TYPE_DESCENDING | VMMEMTRENDEZVOUS_FLAGS_STOP_ON_ERROR,
    12111211                                vmR3PowerOn, NULL);
    1212     LogFlow(("VMR3Suspend: returns %Rrc\n", rc));
     1212    LogFlow(("VMR3PowerOn: returns %Rrc\n", rc));
    12131213    return rc;
    12141214}
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r24582 r24730  
    356356    GEN_CHECK_OFF(PDMDEVINSINT, pVMRC);
    357357    GEN_CHECK_OFF(PDMDEVINSINT, pLunsR3);
     358    GEN_CHECK_OFF(PDMDEVINSINT, pfnAsyncNotify);
    358359    GEN_CHECK_OFF(PDMDEVINSINT, pCfgHandle);
    359360    GEN_CHECK_OFF(PDMDEVINSINT, pPciDeviceR3);
     
    363364    GEN_CHECK_OFF(PDMDEVINSINT, pPciBusR0);
    364365    GEN_CHECK_OFF(PDMDEVINSINT, pPciBusRC);
     366    GEN_CHECK_OFF(PDMDEVINSINT, fIntFlags);
     367    GEN_CHECK_OFF(PDMDEVINS, u32Version);
     368    GEN_CHECK_OFF(PDMDEVINS, iInstance);
     369    GEN_CHECK_OFF(PDMDEVINS, pDevHlpRC);
     370    GEN_CHECK_OFF(PDMDEVINS, pvInstanceDataRC);
     371    GEN_CHECK_OFF(PDMDEVINS, pDevHlpR0);
     372    GEN_CHECK_OFF(PDMDEVINS, pvInstanceDataR0);
     373    GEN_CHECK_OFF(PDMDEVINS, pDevHlpR3);
     374    GEN_CHECK_OFF(PDMDEVINS, pvInstanceDataR3);
     375    GEN_CHECK_OFF(PDMDEVINS, pDevReg);
     376    GEN_CHECK_OFF(PDMDEVINS, pCfgHandle);
     377    GEN_CHECK_OFF(PDMDEVINS, IBase);
     378    GEN_CHECK_OFF(PDMDEVINS, Internal);
     379    GEN_CHECK_OFF(PDMDEVINS, achInstanceData);
    365380    GEN_CHECK_SIZE(PDMCRITSECTINT);
    366381    GEN_CHECK_OFF(PDMCRITSECTINT, Core);
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