VirtualBox

Changeset 6796 in vbox


Ignore:
Timestamp:
Feb 4, 2008 6:19:58 PM (17 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
27892
Message:

Fixed init problems wrt. VM ownership by implementing the UVM structure (U = user mode) and moving problematic ring-3 stuff over there (emt+reqs, r3heap, stam, loader[VMMR0.r0]). Big change, but it works fine here... :-)

Location:
trunk
Files:
1 added
30 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/mm.h

    r6626 r6796  
    340340 */
    341341
     342MMR3DECL(int)       MMR3InitUVM(PUVM pUVM);
    342343MMR3DECL(int)       MMR3Init(PVM pVM);
    343344MMR3DECL(int)       MMR3InitPaging(PVM pVM);
    344345MMR3DECL(int)       MMR3HyperInitFinalize(PVM pVM);
    345346MMR3DECL(int)       MMR3Term(PVM pVM);
     347MMR3DECL(void)      MMR3TermUVM(PUVM pUVM);
    346348MMR3DECL(void)      MMR3Reset(PVM pVM);
    347349MMR3DECL(int)       MMR3IncreaseBaseReservation(PVM pVM, uint64_t cAddBasePages);
    348 MMR3DECL(int)       MMR3IncreateFixedReservation(PVM pVM, uint32_t cAddFixedPages);
     350MMR3DECL(int)       MMR3IncreaseFixedReservation(PVM pVM, uint32_t cAddFixedPages);
    349351MMR3DECL(int)       MMR3UpdateShadowReservation(PVM pVM, uint32_t cShadowPages);
    350352
     
    404406 * @{ */
    405407MMR3DECL(void *)    MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize);
     408MMR3DECL(void *)    MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize);
    406409MMR3DECL(int)       MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv);
     410MMR3DECL(int)       MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv);
    407411MMR3DECL(void *)    MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize);
     412MMR3DECL(void *)    MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize);
    408413MMR3DECL(int)       MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv);
     414MMR3DECL(int)       MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv);
    409415MMR3DECL(void *)    MMR3HeapRealloc(void *pv, size_t cbNewSize);
    410416MMR3DECL(char *)    MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz);
     417MMR3DECL(char *)    MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz);
    411418MMR3DECL(void)      MMR3HeapFree(void *pv);
    412419/** @} */
  • trunk/include/VBox/pdmapi.h

    r5999 r6796  
    111111 */
    112112
    113 PDMR3DECL(int)  PDMR3LdrLoadVMMR0(void **ppvOpaque);
    114 PDMR3DECL(void) PDMR3LdrLoadVMMR0Part2(PVM pVM, void *pvOpaque);
     113PDMR3DECL(int) PDMR3InitUVM(PUVM pUVM);
     114PDMR3DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM);
    115115
    116116/**
     
    169169 * process so that components can resolve GC symbols during relocation.
    170170 *
    171  * @param   pVM         VM handle.
     171 * @param   pUVM            Pointer to the user mode VM structure.
    172172 * @param   offDelta    Relocation delta relative to old location.
    173173 */
    174 PDMR3DECL(void) PDMR3LdrRelocate(PVM pVM, RTGCINTPTR offDelta);
     174PDMR3DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta);
    175175
    176176/**
     
    194194 */
    195195PDMR3DECL(int) PDMR3Term(PVM pVM);
     196PDMR3DECL(void) PDMR3TermUVM(PUVM pUVM);
    196197
    197198
  • trunk/include/VBox/stam.h

    r5999 r6796  
    955955 */
    956956
    957 /**
    958  * Initializes the STAM.
    959  *
    960  * @returns VBox status code.
    961  * @param   pVM         The VM to operate on.
    962  */
    963 STAMR3DECL(int) STAMR3Init(PVM pVM);
    964 
    965 /**
    966  * Applies relocations to data and code managed by this
    967  * component. This function will be called at init and
    968  * whenever the VMM need to relocate it self inside the GC.
    969  *
    970  * @param   pVM     The VM.
    971  */
    972 STAMR3DECL(void) STAMR3Relocate(PVM pVM);
    973 
    974 /**
    975  * Terminates the STAM.
    976  *
    977  * Termination means cleaning up and freeing all resources,
    978  * the VM it self is at this point powered off or suspended.
    979  *
    980  * @returns VBox status code.
    981  * @param   pVM         The VM to operate on.
    982  */
    983 STAMR3DECL(int) STAMR3Term(PVM pVM);
    984 
    985 /**
    986  * Registers a sample with the statistics mamanger.
    987  *
    988  * Statistics are maintained on a per VM basis and should therefore
    989  * be registered during the VM init stage. However, there is not problem
    990  * registering temporary samples or samples for hotpluggable devices. Samples
    991  * can be deregisterd using the STAMR3Deregister() function, but note that
    992  * this is only necessary for temporary samples or hotpluggable devices.
    993  *
    994  * It is not possible to register the same sample twice.
    995  *
    996  * @returns VBox status.
    997  * @param   pVM         The VM handle.
    998  * @param   pvSample    Pointer to the sample.
    999  * @param   enmType     Sample type. This indicates what pvSample is pointing at.
    1000  * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
    1001  * @param   pszName     Sample name. The name is on this form "/<component>/<sample>".
    1002  *                      Further nesting is possible.
    1003  * @param   enmUnit     Sample unit.
    1004  * @param   pszDesc     Sample description.
    1005  */
    1006 STAMR3DECL(int)  STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
     957STAMR3DECL(int) STAMR3InitUVM(PUVM pUVM);
     958STAMR3DECL(void) STAMR3TermUVM(PUVM pUVM);
     959STAMR3DECL(int) STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
    1007960                                const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
     961STAMR3DECL(int) STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility,
     962                               const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
    1008963
    1009964/** @def STAM_REL_REG
     
    10631018    STAM_STATS({ STAM_REL_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc); })
    10641019
    1065 /**
    1066  * Same as STAMR3Register except that the name is specified in a
    1067  * RTStrPrintf like fashion.
    1068  *
    1069  * @returns VBox status.
    1070  * @param   pVM         The VM handle.
    1071  * @param   pvSample    Pointer to the sample.
    1072  * @param   enmType     Sample type. This indicates what pvSample is pointing at.
    1073  * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
    1074  * @param   enmUnit     Sample unit.
    1075  * @param   pszDesc     Sample description.
    1076  * @param   pszName     The sample name format string.
    1077  * @param   ...         Arguments to the format string.
    1078  */
     1020STAMR3DECL(int)  STAMR3RegisterFU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     1021                                  const char *pszDesc, const char *pszName, ...);
    10791022STAMR3DECL(int)  STAMR3RegisterF(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
    10801023                                 const char *pszDesc, const char *pszName, ...);
    1081 
    1082 /**
    1083  * Same as STAMR3Register except that the name is specified in a
    1084  * RTStrPrintfV like fashion.
    1085  *
    1086  * @returns VBox status.
    1087  * @param   pVM         The VM handle.
    1088  * @param   pvSample    Pointer to the sample.
    1089  * @param   enmType     Sample type. This indicates what pvSample is pointing at.
    1090  * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
    1091  * @param   enmUnit     Sample unit.
    1092  * @param   pszDesc     Sample description.
    1093  * @param   pszName     The sample name format string.
    1094  * @param   args        Arguments to the format string.
    1095  */
     1024STAMR3DECL(int)  STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     1025                                  const char *pszDesc, const char *pszName, va_list args);
    10961026STAMR3DECL(int)  STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
    10971027                                 const char *pszDesc, const char *pszName, va_list args);
     
    11181048typedef FNSTAMR3CALLBACKPRINT *PFNSTAMR3CALLBACKPRINT;
    11191049
    1120 /**
    1121  * Similar to STAMR3Register except for the two callbacks, the implied type (STAMTYPE_CALLBACK),
    1122  * and name given in an RTStrPrintf like fashion.
    1123  *
    1124  * @returns VBox status.
    1125  * @param   pVM         The VM handle.
    1126  * @param   pvSample    Pointer to the sample.
    1127  * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
    1128  * @param   enmUnit     Sample unit.
    1129  * @param   pfnReset    Callback for resetting the sample. NULL should be used if the sample can't be reset.
    1130  * @param   pfnPrint    Print the sample.
    1131  * @param   pszDesc     Sample description.
    1132  * @param   pszName     The sample name format string.
    1133  * @param   ...         Arguments to the format string.
    1134  * @remark  There is currently no device or driver variant of this API. Add one if it should become necessary!
    1135  */
    11361050STAMR3DECL(int)  STAMR3RegisterCallback(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
    11371051                                        PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    11381052                                        const char *pszDesc, const char *pszName, ...);
    1139 
    1140 /**
    1141  * Same as STAMR3RegisterCallback() except for the ellipsis which is a va_list here.
    1142  *
    1143  * @returns VBox status.
    1144  * @param   pVM         The VM handle.
    1145  * @param   pvSample    Pointer to the sample.
    1146  * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
    1147  * @param   enmUnit     Sample unit.
    1148  * @param   pfnReset    Callback for resetting the sample. NULL should be used if the sample can't be reset.
    1149  * @param   pfnPrint    Print the sample.
    1150  * @param   pszDesc     Sample description.
    1151  * @param   pszName     The sample name format string.
    1152  * @param   args        Arguments to the format string.
    1153  * @remark  There is currently no device or driver variant of this API. Add one if it should become necessary!
    1154  */
    11551053STAMR3DECL(int)  STAMR3RegisterCallbackV(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
    11561054                                         PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    11571055                                         const char *pszDesc, const char *pszName, va_list args);
    1158 
    1159 /**
    1160  * Deregisters all samples previously registered by STAMR3Register(),
    1161  * STAMR3RegisterF(), STAMR3RegisterV() or STAMR3RegisterCallback().
    1162  *
    1163  * This is intended used for devices which can be unplugged and for
    1164  * temporary samples.
    1165  *
    1166  * @returns VBox status.
    1167  * @param   pVM         The VM handle.
    1168  * @param   pvSample    Pointer to the register sample.
    1169  */
     1056STAMR3DECL(int)  STAMR3DeregisterU(PUVM pUVM, void *pvSample);
    11701057STAMR3DECL(int)  STAMR3Deregister(PVM pVM, void *pvSample);
    11711058
     
    11871074    STAM_STATS({ STAM_REL_DEREG(pVM, pvSample); })
    11881075
    1189 /**
    1190  * Resets statistics for the specified VM.
    1191  * It's possible to select a subset of the samples.
    1192  *
    1193  * @returns VBox status. (Basically, it cannot fail.)
    1194  * @param   pVM         The VM handle.
    1195  * @param   pszPat      The name matching pattern. See somewhere_where_this_is_described_in_detail.
    1196  *                      If NULL all samples are reset.
    1197  */
    1198 STAMR3DECL(int)  STAMR3Reset(PVM pVM, const char *pszPat);
    1199 
    1200 /**
    1201  * Get a snapshot of the statistics.
    1202  * It's possible to select a subset of the samples.
    1203  *
    1204  * @returns VBox status. (Basically, it cannot fail.)
    1205  * @param   pVM             The VM handle.
    1206  * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
    1207  *                          If NULL all samples are reset.
    1208  * @param   fWithDesc       Whether to include the descriptions.
    1209  * @param   ppszSnapshot    Where to store the pointer to the snapshot data.
    1210  *                          The format of the snapshot should be XML, but that will have to be discussed
    1211  *                          when this function is implemented.
    1212  *                          The returned pointer must be freed by calling STAMR3SnapshotFree().
    1213  * @param   pcchSnapshot    Where to store the size of the snapshot data. (Excluding the trailing '\0')
    1214  */
     1076STAMR3DECL(int) STAMR3ResetU(PUVM pUVM, const char *pszPat);
     1077STAMR3DECL(int) STAMR3Reset(PVM pVM, const char *pszPat);
     1078STAMR3DECL(int) STAMR3SnapshotU(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc);
    12151079STAMR3DECL(int) STAMR3Snapshot(PVM pVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc);
    1216 
    1217 /**
    1218  * Releases a statistics snapshot returned by STAMR3Snapshot().
    1219  *
    1220  * @returns VBox status.
    1221  * @param   pVM             The VM handle.
    1222  * @param   pszSnapshot     The snapshot data pointer returned by STAMR3Snapshot().
    1223  *                          NULL is allowed.
    1224  */
    1225 STAMR3DECL(int)  STAMR3SnapshotFree(PVM pVM, char *pszSnapshot);
    1226 
    1227 /**
    1228  * Dumps the selected statistics to the log.
    1229  *
    1230  * @returns VBox status.
    1231  * @param   pVM             The VM handle.
    1232  * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
    1233  *                          If NULL all samples are reset.
    1234  */
    1235 STAMR3DECL(int)  STAMR3Dump(PVM pVM, const char *pszPat);
    1236 
    1237 /**
    1238  * Dumps the selected statistics to the release log.
    1239  *
    1240  * @returns VBox status.
    1241  * @param   pVM             The VM handle.
    1242  * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
    1243  *                          If NULL all samples are written to the log.
    1244  */
    1245 STAMR3DECL(int)  STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat);
    1246 
    1247 /**
    1248  * Prints the selected statistics to standard out.
    1249  *
    1250  * @returns VBox status.
    1251  * @param   pVM             The VM handle.
    1252  * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
    1253  *                          If NULL all samples are reset.
    1254  */
    1255 STAMR3DECL(int)  STAMR3Print(PVM pVM, const char *pszPat);
     1080STAMR3DECL(int) STAMR3SnapshotFreeU(PUVM pUVM, char *pszSnapshot);
     1081STAMR3DECL(int) STAMR3SnapshotFree(PVM pVM, char *pszSnapshot);
     1082STAMR3DECL(int) STAMR3DumpU(PUVM pUVM, const char *pszPat);
     1083STAMR3DECL(int) STAMR3Dump(PVM pVM, const char *pszPat);
     1084STAMR3DECL(int) STAMR3DumpToReleaseLogU(PUVM pUVM, const char *pszPat);
     1085STAMR3DECL(int) STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat);
     1086STAMR3DECL(int) STAMR3PrintU(PUVM pUVM, const char *pszPat);
     1087STAMR3DECL(int) STAMR3Print(PVM pVM, const char *pszPat);
    12561088
    12571089/**
     
    12731105typedef FNSTAMR3ENUM *PFNSTAMR3ENUM;
    12741106
    1275 /**
    1276  * Enumerate the statistics by the means of a callback function.
    1277  *
    1278  * @returns Whatever the callback returns.
    1279  *
    1280  * @param   pVM         The VM handle.
    1281  * @param   pszPat      The pattern to match samples.
    1282  * @param   pfnEnum     The callback function.
    1283  * @param   pvUser      The pvUser argument of the callback function.
    1284  */
     1107STAMR3DECL(int) STAMR3EnumU(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser);
    12851108STAMR3DECL(int) STAMR3Enum(PVM pVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser);
    1286 
    1287 /**
    1288  * Get the unit string.
    1289  *
    1290  * @returns Pointer to read only unit string.
    1291  * @param   enmUnit     The unit.
    1292  */
    12931109STAMR3DECL(const char *) STAMR3GetUnit(STAMUNIT enmUnit);
    12941110
  • trunk/include/VBox/types.h

    r5999 r6796  
    9090typedef GCPTRTYPE(struct VM *)  PVMGC;
    9191
    92 /** Pointer to a the ring-0 (global) VM structure. */
     92/** Pointer to a ring-0 (global) VM structure. */
    9393typedef R0PTRTYPE(struct GVM *) PGVM;
     94
     95/** Pointer to a ring-3 (user mode) VM structure. */
     96typedef R3PTRTYPE(struct UVM *) PUVM;
    9497
    9598
  • trunk/include/VBox/vm.h

    r5999 r6796  
    239239    /** Session handle. For use when calling SUPR0 APIs. */
    240240    PSUPDRVSESSION              pSession;
    241     /** Pointer to the next VM.
    242      * We keep a per process list of VM for the event that a process could
    243      * contain more than one VM.
    244      */
    245     R3PTRTYPE(struct VM *)      pNext;
     241    /** Pointer to the ring-3 VM structure. */
     242    PUVM                        pUVM;
    246243    /** Ring-3 Host Context VM Pointer. */
    247244    R3PTRTYPE(struct VM *)      pVMR3;
     
    498495    } dbgf;
    499496
    500     /** STAM part. */
    501     union
    502     {
    503 #ifdef ___STAMInternal_h
    504         struct STAM s;
    505 #endif
    506         char        padding[256];       /* multiple of 32 */
    507     } stam;
    508 
    509497    /** SSM part. */
    510498    union
  • trunk/include/VBox/vm.mac

    r5999 r6796  
    4646    .fForcedActions     resd 1
    4747    .paVMPagesR3        RTR3PTR_RES 1
    48     .pSession           RTR3PTR_RES 1
    49     .pNext              RTHCPTR_RES 1
     48    .pSession           RTR0PTR_RES 1
     49    .pUVM               RTR3PTR_RES 1
    5050    .pVMR3              RTR3PTR_RES 1
    5151    .pVMR0              RTR0PTR_RES 1
  • trunk/include/VBox/vmapi.h

    r5999 r6796  
    5555#else
    5656# define VM_GUEST_ADDR(pVM, pvInVM)     ( (RTGCPTR)(pvInVM) )
    57 #endif 
     57#endif
    5858
    5959/** @def VM_R3_ADDR
     
    7171#else
    7272# define VM_R3_ADDR(pVM, pvInVM)       ( (RTR3PTR)(pvInVM) )
    73 #endif 
     73#endif
    7474
    7575
     
    8888#else
    8989# define VM_R0_ADDR(pVM, pvInVM)       ( (RTR0PTR)(pvInVM) )
    90 #endif 
     90#endif
    9191
    9292/** @def VM_HOST_ADDR
     
    118118typedef FNVMATERROR *PFNVMATERROR;
    119119
    120 /**
    121  * Sets the error message.
    122  *
    123  * @returns rc. Meaning you can do:
    124  *    @code
    125  *    return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
    126  *    @endcode
    127  * @param   pVM             VM handle. Must be non-NULL.
    128  * @param   rc              VBox status code.
    129  * @param   RT_SRC_POS_DECL Use RT_SRC_POS.
    130  * @param   pszFormat       Error message format string.
    131  * @param   ...             Error message arguments.
    132  * @thread  Any
    133  */
    134120VMDECL(int) VMSetError(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
    135 
    136 /**
    137  * Sets the error message.
    138  *
    139  * @returns rc. Meaning you can do:
    140  *    @code
    141  *    return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");
    142  *    @endcode
    143  * @param   pVM             VM handle. Must be non-NULL.
    144  * @param   rc              VBox status code.
    145  * @param   RT_SRC_POS_DECL Use RT_SRC_POS.
    146  * @param   pszFormat       Error message format string.
    147  * @param   args            Error message arguments.
    148  * @thread  Any
    149  */
    150121VMDECL(int) VMSetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
    151122
     
    183154typedef FNVMATRUNTIMEERROR *PFNVMATRUNTIMEERROR;
    184155
    185 /**
    186  * Sets the runtime error message.
    187  * As opposed VMSetError(), this method is intended to inform the VM user about
    188  * errors and error-like conditions that happen at an arbitrary point during VM
    189  * execution (like "host memory low" or "out of host disk space").
    190  *
    191  * The @a fFatal parameter defines whether the error is fatal or not. If it is
    192  * true, then it is expected that the caller has already paused the VM execution
    193  * before calling this method. The VM user is supposed to power off the VM
    194  * immediately after it has received the runtime error notification via the
    195  * FNVMATRUNTIMEERROR callback.
    196  *
    197  * If @a fFatal is false, then the paused state of the VM defines the kind of
    198  * the error. If the VM is paused before calling this method, it means that
    199  * the VM user may try to fix the error condition (i.e. free more host memory)
    200  * and then resume the VM execution. If the VM is not paused before calling
    201  * this method, it means that the given error is a warning about an error
    202  * condition that may happen soon but that doesn't directly affect the
    203  * VM execution by the time of the call.
    204  *
    205  * The @a pszErrorID parameter defines an unique error identificator.
    206  * It is used by the front-ends to show a proper message to the end user
    207  * containig possible actions (for example, Retry/Ignore). For this reason,
    208  * an error ID assigned once to some particular error condition should not
    209  * change in the future. The format of this parameter is "SomeErrorCondition".
    210  *
    211  * @param   pVM             VM handle. Must be non-NULL.
    212  * @param   fFatal          Whether it is a fatal error or not.
    213  * @param   pszErrorID      Error ID string.
    214  * @param   pszFormat       Error message format string.
    215  * @param   ...             Error message arguments.
    216  *
    217  * @return  VBox status code (whether the error has been successfully set
    218  *          and delivered to callbacks or not).
    219  *
    220  * @thread  Any
    221  */
    222 VMDECL(int) VMSetRuntimeError(PVM pVM, bool fFatal, const char *pszErrorID,
    223                               const char *pszFormat, ...);
    224 
    225 /**
    226  * va_list version of VMSetRuntimeError.
    227  *
    228  * @param   pVM             VM handle. Must be non-NULL.
    229  * @param   fFatal          Whether it is a fatal error or not.
    230  * @param   pszErrorID      Error ID string.
    231  * @param   pszFormat       Error message format string.
    232  * @param   args            Error message arguments.
    233  *
    234  * @return  VBox status code (whether the error has been successfully set
    235  *          and delivered to callbacks or not).
    236  *
    237  * @thread  Any
    238  */
    239 VMDECL(int) VMSetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID,
    240                                const char *pszFormat, va_list args);
     156VMDECL(int) VMSetRuntimeError(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, ...);
     157VMDECL(int) VMSetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list args);
    241158
    242159
     
    347264    /** Pointer to the next request in the chain. */
    348265    struct VMREQ * volatile pNext;
    349     /** Pointer to the VM this packet belongs to. */
    350     PVM                     pVM;
     266    /** Pointer to ring-3 VM structure which this request belongs to. */
     267    PUVM                    pUVM;
    351268    /** Request state. */
    352269    volatile VMREQSTATE     enmState;
     
    414331
    415332
    416 /**
    417  * Creates a virtual machine by calling the supplied configuration constructor.
    418  *
    419  * On successful return the VM is powered off, i.e. VMR3PowerOn() should be
    420  * called to start the execution.
    421  *
    422  * @returns 0 on success.
    423  * @returns VBox error code on failure.
    424  * @param   pfnVMAtError        Pointer to callback function for setting VM errors.
    425  *                              This is called in the EM.
    426  * @param   pvUserVM            The user argument passed to pfnVMAtError.
    427  * @param   pfnCFGMConstructor  Pointer to callback function for constructing the VM configuration tree.
    428  *                              This is called in the EM.
    429  * @param   pvUserCFGM          The user argument passed to pfnCFGMConstructor.
    430  * @param   ppVM                Where to store the 'handle' of the created VM.
    431  * @thread      Any thread.
    432  * @vmstate     N/A
    433  * @vmstateto   Created
    434  */
    435333VMR3DECL(int)   VMR3Create(PFNVMATERROR pfnVMAtError, void *pvUserVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM, PVM *ppVM);
    436 
    437 /**
    438  * Power on a virtual machine.
    439  *
    440  * @returns 0 on success.
    441  * @returns VBox error code on failure.
    442  * @param   pVM         VM to power on.
    443  * @thread      Any thread.
    444  * @vmstate     Created
    445  * @vmstateto   Running
    446  */
    447334VMR3DECL(int)   VMR3PowerOn(PVM pVM);
    448 
    449 /**
    450  * Suspend a running VM.
    451  *
    452  * @returns VBox status.
    453  * @param   pVM     VM to suspend.
    454  * @thread      Any thread.
    455  * @vmstate     Running
    456  * @vmstateto   Suspended
    457  */
    458335VMR3DECL(int)   VMR3Suspend(PVM pVM);
    459 
    460 /**
    461  * Suspends a running VM and prevent state saving until the VM is resumed or stopped.
    462  *
    463  * @returns 0 on success.
    464  * @returns VBox error code on failure.
    465  * @param   pVM     VM to suspend.
    466  * @thread      Any thread.
    467  * @vmstate     Running
    468  * @vmstateto   Suspended
    469  */
    470 VMR3DECL(int) VMR3SuspendNoSave(PVM pVM);
    471 
    472 /**
    473  * Resume VM execution.
    474  *
    475  * @returns VBox status.
    476  * @param   pVM         The VM to resume.
    477  * @thread      Any thread.
    478  * @vmstate     Suspended
    479  * @vmstateto   Running
    480  */
     336VMR3DECL(int)   VMR3SuspendNoSave(PVM pVM);
    481337VMR3DECL(int)   VMR3Resume(PVM pVM);
    482 
    483 /**
    484  * Reset the current VM.
    485  *
    486  * @returns VBox status code.
    487  * @param   pVM     VM to reset.
    488  * @thread      Any thread.
    489  * @vmstate     Suspended, Running
    490  * @vmstateto   Unchanged state.
    491  */
    492338VMR3DECL(int)   VMR3Reset(PVM pVM);
    493339
     
    506352typedef FNVMPROGRESS *PFNVMPROGRESS;
    507353
    508 /**
    509  * Save current VM state.
    510  *
    511  * To save and terminate the VM, the VM must be suspended before the call.
    512  *
    513  * @returns 0 on success.
    514  * @returns VBox error code on failure.
    515  * @param   pVM             VM which state should be saved.
    516  * @param   pszFilename     Name of the save state file.
    517  * @param   pfnProgress     Progress callback. Optional.
    518  * @param   pvUser          User argument for the progress callback.
    519  * @thread      Any thread.
    520  * @vmstate     Suspended
    521  * @vmstateto   Unchanged state.
    522  */
    523354VMR3DECL(int)   VMR3Save(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
    524 
    525 /**
    526  * Load a new VM state.
    527  *
    528  * To restore a saved state on VM startup, call this function and then
    529  * resume the VM instead of powering it on.
    530  *
    531  * @returns 0 on success.
    532  * @returns VBox error code on failure.
    533  * @param   pVM             VM which state should be saved.
    534  * @param   pszFilename     Name of the save state file.
    535  * @param   pfnProgress     Progress callback. Optional.
    536  * @param   pvUser          User argument for the progress callback.
    537  * @thread      Any thread.
    538  * @vmstate     Created, Suspended
    539  * @vmstateto   Suspended
    540  */
    541355VMR3DECL(int)   VMR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
    542 
    543 /**
    544  * Power off a VM.
    545  *
    546  * @returns 0 on success.
    547  * @returns VBox error code on failure.
    548  * @param   pVM     VM which should be destroyed.
    549  * @thread      Any thread.
    550  * @vmstate     Suspended, Running, Guru Mediation, Load Failure
    551  * @vmstateto   Off
    552  */
    553356VMR3DECL(int)   VMR3PowerOff(PVM pVM);
    554 
    555 /**
    556  * Destroy a VM.
    557  * The VM must be powered off (or never really powered on) to call this function.
    558  * The VM handle is destroyed and can no longer be used up successful return.
    559  *
    560  * @returns 0 on success.
    561  * @returns VBox error code on failure.
    562  * @param   pVM     VM which should be destroyed.
    563  * @thread      Any thread but the emulation thread.
    564  * @vmstate     Off, Created
    565  * @vmstateto   N/A
    566  */
    567357VMR3DECL(int)   VMR3Destroy(PVM pVM);
    568 
    569 /**
    570  * Calls the relocation functions for all VMM components so they can update
    571  * any GC pointers. When this function is called all the basic VM members
    572  * have been updated  and the actual memory relocation have been done
    573  * by the PGM/MM.
    574  *
    575  * This is used both on init and on runtime relocations.
    576  *
    577  * @param   pVM         VM handle.
    578  * @param   offDelta    Relocation delta relative to old location.
    579  * @thread  The emulation thread.
    580  */
    581 VMR3DECL(void)   VMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
    582 
    583 /**
    584  * Enumerates the VMs in this process.
    585  *
    586  * @returns Pointer to the next VM.
    587  * @returns NULL when no more VMs.
    588  * @param   pVMPrev     The previous VM
    589  *                      Use NULL to start the enumeration.
    590  */
     358VMR3DECL(void)  VMR3Relocate(PVM pVM, RTGCINTPTR offDelta);
    591359VMR3DECL(PVM)   VMR3EnumVMs(PVM pVMPrev);
    592 
    593 /**
    594  * Wait for VM to be resumed. Handle events like vmR3EmulationThread does.
    595  * In case the VM is stopped, clean up and long jump to the main EMT loop.
    596  *
    597  * @returns VINF_SUCCESS or doesn't return
    598  * @param   pVM             VM handle.
    599  */
    600 VMR3DECL(int) VMR3WaitForResume(PVM pVM);
    601 
     360VMR3DECL(int)   VMR3WaitForResume(PVM pVM);
    602361
    603362/**
     
    610369typedef FNVMATDTOR *PFNVMATDTOR;
    611370
    612 /**
    613  * Registers an at VM destruction callback.
    614  *
    615  * @returns VBox status code.
    616  * @param   pfnAtDtor       Pointer to callback.
    617  * @param   pvUser          User argument.
    618  */
    619371VMR3DECL(int)   VMR3AtDtorRegister(PFNVMATDTOR pfnAtDtor, void *pvUser);
    620 
    621 /**
    622  * Deregisters an at VM destruction callback.
    623  *
    624  * @returns VBox status code.
    625  * @param   pfnAtDtor       Pointer to callback.
    626  */
    627372VMR3DECL(int)   VMR3AtDtorDeregister(PFNVMATDTOR pfnAtDtor);
    628 
    629 
    630 /**
    631  * Registers an at VM reset callback.
    632  *
    633  * @returns VBox status code.
    634  * @param   pVM             The VM.
    635  * @param   pDevInst        Device instance.
    636  * @param   pfnCallback     Callback function.
    637  * @param   pvUser          User argument.
    638  * @param   pszDesc         Description (optional).
    639  */
    640373VMR3DECL(int)   VMR3AtResetRegister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback, void *pvUser, const char *pszDesc);
    641 
    642 /**
    643  * Registers an at VM reset internal callback.
    644  *
    645  * @returns VBox status code.
    646  * @param   pVM             The VM.
    647  * @param   pfnCallback     Callback function.
    648  * @param   pvUser          User argument.
    649  * @param   pszDesc         Description (optional).
    650  */
    651374VMR3DECL(int)   VMR3AtResetRegisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback, void *pvUser, const char *pszDesc);
    652 
    653 /**
    654  * Registers an at VM reset external callback.
    655  *
    656  * @returns VBox status code.
    657  * @param   pVM             The VM.
    658  * @param   pfnCallback     Callback function.
    659  * @param   pvUser          User argument.
    660  * @param   pszDesc         Description (optional).
    661  */
    662375VMR3DECL(int)   VMR3AtResetRegisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback, void *pvUser, const char *pszDesc);
    663 
    664 
    665 /**
    666  * Deregisters an at VM reset callback.
    667  *
    668  * @returns VBox status code.
    669  * @param   pVM             The VM.
    670  * @param   pDevInst        Device instance.
    671  * @param   pfnCallback     Callback function.
    672  */
    673376VMR3DECL(int)   VMR3AtResetDeregister(PVM pVM, PPDMDEVINS pDevInst, PFNVMATRESET pfnCallback);
    674 
    675 /**
    676  * Deregisters an at VM reset internal callback.
    677  *
    678  * @returns VBox status code.
    679  * @param   pVM             The VM.
    680  * @param   pfnCallback     Callback function.
    681  */
    682377VMR3DECL(int)   VMR3AtResetDeregisterInternal(PVM pVM, PFNVMATRESETINT pfnCallback);
    683 
    684 /**
    685  * Deregisters an at VM reset external callback.
    686  *
    687  * @returns VBox status code.
    688  * @param   pVM             The VM.
    689  * @param   pfnCallback     Callback function.
    690  */
    691378VMR3DECL(int)   VMR3AtResetDeregisterExternal(PVM pVM, PFNVMATRESETEXT pfnCallback);
    692 
    693 
    694 /**
    695  * Registers a VM state change callback.
    696  *
    697  * You are not allowed to call any function which changes the VM state from a
    698  * state callback, except VMR3Destroy().
    699  *
    700  * @returns VBox status code.
    701  * @param   pVM             VM handle.
    702  * @param   pfnAtState      Pointer to callback.
    703  * @param   pvUser          User argument.
    704  * @thread  Any.
    705  */
    706379VMR3DECL(int)   VMR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser);
    707 
    708 /**
    709  * Deregisters a VM state change callback.
    710  *
    711  * @returns VBox status code.
    712  * @param   pVM             The VM handle.
    713  * @param   pfnAtState      Pointer to callback.
    714  * @param   pvUser          User argument.
    715  * @thread  Any.
    716  */
    717380VMR3DECL(int)   VMR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser);
    718 
    719 /**
    720  * Gets the current VM state.
    721  *
    722  * @returns The current VM state.
    723  * @param   pVM             The VM handle.
    724  * @thread  Any
    725  */
    726381VMR3DECL(VMSTATE) VMR3GetState(PVM pVM);
    727 
    728 /**
    729  * Gets the state name string for a VM state.
    730  *
    731  * @returns Pointer to the state name. (readonly)
    732  * @param   enmState        The state.
    733  */
    734382VMR3DECL(const char *) VMR3GetStateName(VMSTATE enmState);
    735 
    736 /**
    737  * Registers a VM error callback.
    738  *
    739  * @returns VBox status code.
    740  * @param   pVM             The VM handle.
    741  * @param   pfnAtError      Pointer to callback.
    742  * @param   pvUser          User argument.
    743  * @thread  Any.
    744  */
    745383VMR3DECL(int)   VMR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
    746 
    747 /**
    748  * Deregisters a VM error callback.
    749  *
    750  * @returns VBox status code.
    751  * @param   pVM             The VM handle.
    752  * @param   pfnAtError      Pointer to callback.
    753  * @param   pvUser          User argument.
    754  * @thread  Any.
    755  */
     384VMR3DECL(int)   VMR3AtErrorRegisterU(PUVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
    756385VMR3DECL(int)   VMR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
    757 
    758 /**
    759  * This is a worker function for GC and Ring-0 calls to VMSetError and VMSetErrorV.
    760  * The message is found in VMINT.
    761  *
    762  * @param   pVM             The VM handle.
    763  * @thread  EMT.
    764  */
    765 VMR3DECL(void) VMR3SetErrorWorker(PVM pVM);
    766 
    767 /**
    768  * Registers a VM runtime error callback.
    769  *
    770  * @returns VBox status code.
    771  * @param   pVM                 The VM handle.
    772  * @param   pfnAtRuntimeError   Pointer to callback.
    773  * @param   pvUser              User argument.
    774  * @thread  Any.
    775  */
     386VMR3DECL(void)  VMR3SetErrorWorker(PVM pVM);
    776387VMR3DECL(int)   VMR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
    777 
    778 /**
    779  * Deregisters a VM runtime error callback.
    780  *
    781  * @returns VBox status code.
    782  * @param   pVM                 The VM handle.
    783  * @param   pfnAtRuntimeError   Pointer to callback.
    784  * @param   pvUser              User argument.
    785  * @thread  Any.
    786  */
    787388VMR3DECL(int)   VMR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
    788 
    789 /**
    790  * This is a worker function for GC and Ring-0 calls to VMSetRuntimeError and VMSetRuntimeErrorV.
    791  * The message is found in VMINT.
    792  *
    793  * @param   pVM             The VM handle.
    794  * @thread  EMT.
    795  */
    796 VMR3DECL(void) VMR3SetRuntimeErrorWorker(PVM pVM);
    797 
    798 
    799 /**
    800  * Allocate and queue a call request.
    801  *
    802  * If it's desired to poll on the completion of the request set cMillies
    803  * to 0 and use VMR3ReqWait() to check for completation. In the other case
    804  * use RT_INDEFINITE_WAIT.
    805  * The returned request packet must be freed using VMR3ReqFree().
    806  *
    807  * @returns VBox status code.
    808  *          Will not return VERR_INTERRUPTED.
    809  * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    810  *
    811  * @param   pVM             The VM handle.
    812  * @param   ppReq           Where to store the pointer to the request.
    813  *                          This will be NULL or a valid request pointer not matter what happends.
    814  * @param   cMillies        Number of milliseconds to wait for the request to
    815  *                          be completed. Use RT_INDEFINITE_WAIT to only
    816  *                          wait till it's completed.
    817  * @param   pfnFunction     Pointer to the function to call.
    818  * @param   cArgs           Number of arguments following in the ellipsis.
    819  *                          Not possible to pass 64-bit arguments!
    820  * @param   ...             Function arguments.
    821  */
    822 VMR3DECL(int) VMR3ReqCall(PVM pVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
    823 
    824 /**
    825  * Allocate and queue a call request to a void function.
    826  *
    827  * If it's desired to poll on the completion of the request set cMillies
    828  * to 0 and use VMR3ReqWait() to check for completation. In the other case
    829  * use RT_INDEFINITE_WAIT.
    830  * The returned request packet must be freed using VMR3ReqFree().
    831  *
    832  * @returns VBox status code.
    833  *          Will not return VERR_INTERRUPTED.
    834  * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    835  *
    836  * @param   pVM             The VM handle.
    837  * @param   ppReq           Where to store the pointer to the request.
    838  *                          This will be NULL or a valid request pointer not matter what happends.
    839  * @param   cMillies        Number of milliseconds to wait for the request to
    840  *                          be completed. Use RT_INDEFINITE_WAIT to only
    841  *                          wait till it's completed.
    842  * @param   pfnFunction     Pointer to the function to call.
    843  * @param   cArgs           Number of arguments following in the ellipsis.
    844  *                          Not possible to pass 64-bit arguments!
    845  * @param   ...             Function arguments.
    846  */
    847 VMR3DECL(int) VMR3ReqCallVoid(PVM pVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
    848 
    849 /**
    850  * Allocate and queue a call request to a void function.
    851  *
    852  * If it's desired to poll on the completion of the request set cMillies
    853  * to 0 and use VMR3ReqWait() to check for completation. In the other case
    854  * use RT_INDEFINITE_WAIT.
    855  * The returned request packet must be freed using VMR3ReqFree().
    856  *
    857  * @returns VBox status code.
    858  *          Will not return VERR_INTERRUPTED.
    859  * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    860  *
    861  * @param   pVM             The VM handle.
    862  * @param   ppReq           Where to store the pointer to the request.
    863  *                          This will be NULL or a valid request pointer not matter what happends, unless fFlags
    864  *                          contains VMREQFLAGS_NO_WAIT when it will be optional and always NULL.
    865  * @param   cMillies        Number of milliseconds to wait for the request to
    866  *                          be completed. Use RT_INDEFINITE_WAIT to only
    867  *                          wait till it's completed.
    868  * @param   fFlags          A combination of the VMREQFLAGS values.
    869  * @param   pfnFunction     Pointer to the function to call.
    870  * @param   cArgs           Number of arguments following in the ellipsis.
    871  *                          Not possible to pass 64-bit arguments!
    872  * @param   ...             Function arguments.
    873  */
    874 VMR3DECL(int) VMR3ReqCallEx(PVM pVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
    875 
    876 /**
    877  * Allocate and queue a call request.
    878  *
    879  * If it's desired to poll on the completion of the request set cMillies
    880  * to 0 and use VMR3ReqWait() to check for completation. In the other case
    881  * use RT_INDEFINITE_WAIT.
    882  * The returned request packet must be freed using VMR3ReqFree().
    883  *
    884  * @returns VBox status code.
    885  *          Will not return VERR_INTERRUPTED.
    886  * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    887  *
    888  * @param   pVM             The VM handle.
    889  * @param   ppReq           Where to store the pointer to the request.
    890  *                          This will be NULL or a valid request pointer not matter what happends, unless fFlags
    891  *                          contains VMREQFLAGS_NO_WAIT when it will be optional and always NULL.
    892  * @param   cMillies        Number of milliseconds to wait for the request to
    893  *                          be completed. Use RT_INDEFINITE_WAIT to only
    894  *                          wait till it's completed.
    895  * @param   fFlags          A combination of the VMREQFLAGS values.
    896  * @param   pfnFunction     Pointer to the function to call.
    897  * @param   cArgs           Number of arguments following in the ellipsis.
    898  *                          Not possible to pass 64-bit arguments!
    899  * @param   pvArgs          Pointer to function arguments.
    900  */
    901 VMR3DECL(int) VMR3ReqCallV(PVM pVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
    902 
    903 /**
    904  * Allocates a request packet.
    905  *
    906  * The caller allocates a request packet, fills in the request data
    907  * union and queues the request.
    908  *
    909  * @returns VBox status code.
    910  *
    911  * @param   pVM             VM handle.
    912  * @param   ppReq           Where to store the pointer to the allocated packet.
    913  * @param   enmType         Package type.
    914  */
    915 VMR3DECL(int) VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType);
    916 
    917 /**
    918  * Free a request packet.
    919  *
    920  * @returns VBox status code.
    921  *
    922  * @param   pReq            Package to free.
    923  * @remark  The request packet must be in allocated or completed state!
    924  */
    925 VMR3DECL(int) VMR3ReqFree(PVMREQ pReq);
    926 
    927 /**
    928  * Queue a request.
    929  *
    930  * The quest must be allocated using VMR3ReqAlloc() and contain
    931  * all the required data.
    932  * If it's disired to poll on the completion of the request set cMillies
    933  * to 0 and use VMR3ReqWait() to check for completation. In the other case
    934  * use RT_INDEFINITE_WAIT.
    935  *
    936  * @returns VBox status code.
    937  *          Will not return VERR_INTERRUPTED.
    938  * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    939  *
    940  * @param   pReq            The request to queue.
    941  * @param   cMillies        Number of milliseconds to wait for the request to
    942  *                          be completed. Use RT_INDEFINITE_WAIT to only
    943  *                          wait till it's completed.
    944  */
    945 VMR3DECL(int) VMR3ReqQueue(PVMREQ pReq, unsigned cMillies);
    946 
    947 /**
    948  * Wait for a request to be completed.
    949  *
    950  * @returns VBox status code.
    951  *          Will not return VERR_INTERRUPTED.
    952  * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    953  *
    954  * @param   pReq            The request to wait for.
    955  * @param   cMillies        Number of milliseconds to wait.
    956  *                          Use RT_INDEFINITE_WAIT to only wait till it's completed.
    957  */
    958 VMR3DECL(int) VMR3ReqWait(PVMREQ pReq, unsigned cMillies);
    959 
    960 
    961 
    962 /**
    963  * Process pending request(s).
    964  *
    965  * This function is called from a forced action handler in
    966  * the EMT.
    967  *
    968  * @returns VBox status code.
    969  *
    970  * @param   pVM         VM handle.
    971  */
    972 VMR3DECL(int) VMR3ReqProcess(PVM pVM);
    973 
    974 
    975 /**
    976  * Notify the emulation thread (EMT) about pending Forced Action (FF).
    977  *
    978  * This function is called by thread other than EMT to make
    979  * sure EMT wakes up and promptly service a FF request.
    980  *
    981  * @param   pVM             VM handle.
    982  * @param   fNotifiedREM    Set if REM have already been notified. If clear the
    983  *                          generic REMR3NotifyFF() method is called.
    984  */
    985 VMR3DECL(void) VMR3NotifyFF(PVM pVM, bool fNotifiedREM);
    986 
    987 /**
    988  * Halted VM Wait.
    989  * Any external event will unblock the thread.
    990  *
    991  * @returns VINF_SUCCESS unless a fatal error occured. In the latter
    992  *          case an appropriate status code is returned.
    993  * @param   pVM                 VM handle.
    994  * @param   fIgnoreInterrupts   If set the VM_FF_INTERRUPT flags is ignored.
    995  * @thread  The emulation thread.
    996  */
    997 VMR3DECL(int) VMR3WaitHalted(PVM pVM, bool fIgnoreInterrupts);
    998 
    999 /**
    1000  * Suspended VM Wait.
    1001  * Only a handful of forced actions will cause the function to
    1002  * return to the caller.
    1003  *
    1004  * @returns VINF_SUCCESS unless a fatal error occured. In the latter
    1005  *          case an appropriate status code is returned.
    1006  * @param   pVM         VM handle.
    1007  * @thread  The emulation thread.
    1008  */
    1009 VMR3DECL(int) VMR3Wait(PVM pVM);
     389VMR3DECL(void)  VMR3SetRuntimeErrorWorker(PVM pVM);
     390VMR3DECL(int)   VMR3ReqCall(PVM pVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
     391VMR3DECL(int)   VMR3ReqCallVoidU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
     392VMR3DECL(int)   VMR3ReqCallVoid(PVM pVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...);
     393VMR3DECL(int)   VMR3ReqCallEx(PVM pVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
     394VMR3DECL(int)   VMR3ReqCallU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...);
     395VMR3DECL(int)   VMR3ReqCallVU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args);
     396VMR3DECL(int)   VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType);
     397VMR3DECL(int)   VMR3ReqAllocU(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType);
     398VMR3DECL(int)   VMR3ReqFree(PVMREQ pReq);
     399VMR3DECL(int)   VMR3ReqQueue(PVMREQ pReq, unsigned cMillies);
     400VMR3DECL(int)   VMR3ReqWait(PVMREQ pReq, unsigned cMillies);
     401VMR3DECL(int)   VMR3ReqProcessU(PUVM pUVM);
     402VMR3DECL(void)  VMR3NotifyFF(PVM pVM, bool fNotifiedREM);
     403VMR3DECL(void)  VMR3NotifyFFU(PUVM pUVM, bool fNotifiedREM);
     404VMR3DECL(int)   VMR3WaitHalted(PVM pVM, bool fIgnoreInterrupts);
     405VMR3DECL(int)   VMR3WaitU(PUVM pUVM);
    1010406
    1011407/** @} */
  • trunk/src/VBox/VMM/DBGF.cpp

    r5999 r6796  
    604604            {
    605605                LogFlow(("dbgfr3VMMWait: Processes requests...\n"));
    606                 rc = VMR3ReqProcess(pVM);
     606                rc = VMR3ReqProcessU(pVM->pUVM);
    607607                LogFlow(("dbgfr3VMMWait: VMR3ReqProcess -> %Vrc rcRet=%Vrc\n", rc, rcRet));
    608608                if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST)
  • trunk/src/VBox/VMM/EM.cpp

    r5999 r6796  
    29842984        if (VM_FF_ISSET(pVM, VM_FF_REQUEST))
    29852985        {
    2986             rc2 = VMR3ReqProcess(pVM);
     2986            rc2 = VMR3ReqProcessU(pVM->pUVM);
    29872987            if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE)
    29882988            {
  • trunk/src/VBox/VMM/MM.cpp

    r6634 r6796  
    8888#include "MMInternal.h"
    8989#include <VBox/vm.h>
     90#include <VBox/uvm.h>
    9091#include <VBox/err.h>
    9192#include <VBox/param.h>
     
    107108*   Internal Functions                                                         *
    108109*******************************************************************************/
    109 static int mmR3Term(PVM pVM, bool fKeepTheHeap);
    110110static DECLCALLBACK(int) mmR3Save(PVM pVM, PSSMHANDLE pSSM);
    111111static DECLCALLBACK(int) mmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version);
    112112
     113
     114/**
     115 * Initializes the MM members of the UVM.
     116 *
     117 * This is currently only the ring-3 heap.
     118 *
     119 * @returns VBox status code.
     120 * @param   pUVM    Pointer to the user mode VM structure.
     121 */
     122MMR3DECL(int) MMR3InitUVM(PUVM pUVM)
     123{
     124    /*
     125     * Assert sizes and order.
     126     */
     127    AssertCompile(sizeof(pUVM->mm.s) <= sizeof(pUVM->mm.padding));
     128    AssertRelease(sizeof(pUVM->mm.s) <= sizeof(pUVM->mm.padding));
     129    Assert(!pUVM->mm.s.pHeap);
     130
     131    /*
     132     * Init the heap.
     133     */
     134    return mmR3HeapCreateU(pUVM, &pUVM->mm.s.pHeap);
     135}
    113136
    114137
     
    147170    pVM->mm.s.offVM = RT_OFFSETOF(VM, mm);
    148171    pVM->mm.s.offLookupHyper = NIL_OFFSET;
    149 
    150     /*
    151      * Init the heap (may already be initialized already if someone used it).
    152      */
    153     if (!pVM->mm.s.pHeap)
    154     {
    155         int rc = mmR3HeapCreate(pVM, &pVM->mm.s.pHeap);
    156         if (!VBOX_SUCCESS(rc))
    157             return rc;
    158     }
    159172
    160173    /*
     
    182195        }
    183196    }
    184     mmR3Term(pVM, true /* keep the heap */);
     197    MMR3Term(pVM);
    185198    return rc;
    186199}
     
    346359 */
    347360MMR3DECL(int) MMR3Term(PVM pVM)
    348 {
    349     return mmR3Term(pVM, false /* free the heap */);
    350 }
    351 
    352 
    353 /**
    354  * Worker for MMR3Term and MMR3Init.
    355  *
    356  * The tricky bit here is that we must not destroy the heap if we're
    357  * called from MMR3Init, otherwise we'll get into trouble when
    358  * CFGMR3Term is called later in the bailout process.
    359  *
    360  * @returns VBox status code.
    361  * @param   pVM             The VM to operate on.
    362  * @param   fKeepTheHeap    Whether or not to keep the heap.
    363  */
    364 static int mmR3Term(PVM pVM, bool fKeepTheHeap)
    365361{
    366362    /*
     
    395391
    396392    /*
    397      * Destroy the heap if requested.
    398      */
    399     if (!fKeepTheHeap)
    400     {
    401         mmR3HeapDestroy(pVM->mm.s.pHeap);
    402         pVM->mm.s.pHeap = NULL;
    403     }
    404 
    405     /*
    406393     * Zero stuff to detect after termination use of the MM interface
    407394     */
     
    413400
    414401    return 0;
     402}
     403
     404
     405/**
     406 * Terminates the UVM part of MM.
     407 *
     408 * Termination means cleaning up and freeing all resources,
     409 * the VM it self is at this point powered off or suspended.
     410 *
     411 * @returns VBox status code.
     412 * @param   pUVM        Pointer to the user mode VM structure.
     413 */
     414MMR3DECL(void) MMR3TermUVM(PUVM pUVM)
     415{
     416    /*
     417     * Destroy the heap.
     418     */
     419    mmR3HeapDestroy(pUVM->mm.s.pHeap);
     420    pUVM->mm.s.pHeap = NULL;
    415421}
    416422
  • trunk/src/VBox/VMM/MMHeap.cpp

    r6529 r6796  
    2222#define LOG_GROUP LOG_GROUP_MM_HEAP
    2323#include <VBox/mm.h>
     24#include <VBox/stam.h>
    2425#include <VBox/pgm.h>
    2526#include "MMInternal.h"
    2627#include <VBox/vm.h>
     28#include <VBox/uvm.h>
    2729#include <VBox/err.h>
    2830#include <VBox/param.h>
     
    4850 * @param   ppHeap  Where to store the heap pointer.
    4951 */
    50 int mmR3HeapCreate(PVM pVM, PMMHEAP *ppHeap)
     52int mmR3HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap)
    5153{
    5254    PMMHEAP pHeap = (PMMHEAP)RTMemAllocZ(sizeof(MMHEAP) + sizeof(MMHEAPSTAT));
     
    5961             * Initialize the global stat record.
    6062             */
    61             pHeap->pVM   = pVM;
    62 
     63            pHeap->pUVM = pUVM;
    6364            pHeap->Stat.pHeap = pHeap;
    6465#ifdef MMR3HEAP_WITH_STATISTICS
    6566            PMMHEAPSTAT pStat = &pHeap->Stat;
    66             STAMR3Register(pVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cAllocations",     STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
    67             STAMR3Register(pVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cReallocations",   STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
    68             STAMR3Register(pVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFrees",           STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
    69             STAMR3Register(pVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFailures",        STAMUNIT_COUNT, "Number of failures.");
    70             STAMR3Register(pVM, &pStat->cbCurAllocated, sizeof(pStat->cbCurAllocated) == sizeof(uint32_t) ? STAMTYPE_U32 : STAMTYPE_U64,
    71                                                                       STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbCurAllocated",   STAMUNIT_BYTES, "Number of bytes currently allocated.");
    72             STAMR3Register(pVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbAllocated",      STAMUNIT_BYTES, "Total number of bytes allocated.");
    73             STAMR3Register(pVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbFreed",          STAMUNIT_BYTES, "Total number of bytes freed.");
     67            STAMR3RegisterU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cAllocations",     STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
     68            STAMR3RegisterU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cReallocations",   STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
     69            STAMR3RegisterU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFrees",           STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
     70            STAMR3RegisterU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cFailures",        STAMUNIT_COUNT, "Number of failures.");
     71            STAMR3RegisterU(pUVM, &pStat->cbCurAllocated, sizeof(pStat->cbCurAllocated) == sizeof(uint32_t) ? STAMTYPE_U32 : STAMTYPE_U64,
     72                                                                        STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbCurAllocated",   STAMUNIT_BYTES, "Number of bytes currently allocated.");
     73            STAMR3RegisterU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbAllocated",      STAMUNIT_BYTES, "Total number of bytes allocated.");
     74            STAMR3RegisterU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS, "/MM/R3Heap/cbFreed",          STAMUNIT_BYTES, "Total number of bytes freed.");
    7475#endif
    7576            *ppHeap = pHeap;
     
    121122 * The memory will be allocated from the default heap but a header
    122123 * is added in which we keep track of which VM it belongs to and chain
    123  * all the allocations together so they can be freed in a one go.
     124 * all the allocations together so they can be freed in one go.
    124125 *
    125126 * This interface is typically used for memory block which will not be
     
    127128 *
    128129 * @returns Pointer to allocated memory.
     130 * @param   pUVM        Pointer to the user mode VM structure.
     131 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     132 *                      basis in addition to a global one. Thus we can easily
     133 *                      identify how memory is used by the VM.
     134 * @param   cbSize      Size of the block.
     135 */
     136MMR3DECL(void *) MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
     137{
     138    Assert(pUVM->mm.s.pHeap);
     139    return mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, false);
     140}
     141
     142
     143/**
     144 * Allocate memory associating it with the VM for collective cleanup.
     145 *
     146 * The memory will be allocated from the default heap but a header
     147 * is added in which we keep track of which VM it belongs to and chain
     148 * all the allocations together so they can be freed in one go.
     149 *
     150 * This interface is typically used for memory block which will not be
     151 * freed during the life of the VM.
     152 *
     153 * @returns Pointer to allocated memory.
    129154 * @param   pVM         VM handle.
    130155 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     
    135160MMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize)
    136161{
    137     if (!pVM->mm.s.pHeap)
    138     {
    139         int rc = mmR3HeapCreate(pVM, &pVM->mm.s.pHeap);
    140         if (VBOX_FAILURE(rc))
    141             return NULL;
    142     }
    143     return mmR3HeapAlloc(pVM->mm.s.pHeap, enmTag, cbSize, false);
    144 }
    145 
    146 
    147 /**
    148  * Same as MMR3HeapAlloc().
    149  *
    150  *
    151  * @returns Pointer to allocated memory.
    152  * @param   pVM         VM handle.
     162    return mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false);
     163}
     164
     165
     166/**
     167 * Same as MMR3HeapAllocU().
     168 *
     169 * @returns Pointer to allocated memory.
     170 * @param   pUVM        Pointer to the user mode VM structure.
    153171 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    154172 *                      basis in addition to a global one. Thus we can easily
     
    157175 * @param   ppv         Where to store the pointer to the allocated memory on success.
    158176 */
    159 MMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
    160 {
    161     if (!pVM->mm.s.pHeap)
    162     {
    163         int rc = mmR3HeapCreate(pVM, &pVM->mm.s.pHeap);
    164         if (VBOX_FAILURE(rc))
    165             return rc;
    166     }
    167     void *pv = mmR3HeapAlloc(pVM->mm.s.pHeap, enmTag, cbSize, false);
     177MMR3DECL(int) MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv)
     178{
     179    Assert(pUVM->mm.s.pHeap);
     180    void *pv = mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, false);
    168181    if (pv)
    169182    {
     
    176189
    177190/**
    178  * Same as MMR3HeapAlloc() only the memory is zeroed.
    179  *
     191 * Same as MMR3HeapAlloc().
    180192 *
    181193 * @returns Pointer to allocated memory.
     
    185197 *                      identify how memory is used by the VM.
    186198 * @param   cbSize      Size of the block.
    187  */
    188 MMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize)
    189 {
    190     if (!pVM->mm.s.pHeap)
    191     {
    192         int rc = mmR3HeapCreate(pVM, &pVM->mm.s.pHeap);
    193         if (VBOX_FAILURE(rc))
    194             return NULL;
    195     }
    196     return mmR3HeapAlloc(pVM->mm.s.pHeap, enmTag, cbSize, true);
    197 }
    198 
    199 
    200 /**
    201  * Same as MMR3HeapAllocZ().
    202  *
    203  *
    204  * @returns Pointer to allocated memory.
    205  * @param   pVM         VM handle.
    206  * @param   enmTag      Statistics tag. Statistics are collected on a per tag
    207  *                      basis in addition to a global one. Thus we can easily
    208  *                      identify how memory is used by the VM.
    209  * @param   cbSize      Size of the block.
    210199 * @param   ppv         Where to store the pointer to the allocated memory on success.
    211200 */
    212 MMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
    213 {
    214     if (!pVM->mm.s.pHeap)
    215     {
    216         int rc = mmR3HeapCreate(pVM, &pVM->mm.s.pHeap);
    217         if (VBOX_FAILURE(rc))
    218             return rc;
    219     }
    220     void *pv = mmR3HeapAlloc(pVM->mm.s.pHeap, enmTag, cbSize, true);
     201MMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
     202{
     203    void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false);
    221204    if (pv)
    222205    {
     
    229212
    230213/**
     214 * Same as MMR3HeapAlloc() only the memory is zeroed.
     215 *
     216 * @returns Pointer to allocated memory.
     217 * @param   pUVM        Pointer to the user mode VM structure.
     218 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     219 *                      basis in addition to a global one. Thus we can easily
     220 *                      identify how memory is used by the VM.
     221 * @param   cbSize      Size of the block.
     222 */
     223MMR3DECL(void *) MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize)
     224{
     225    return mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, true);
     226}
     227
     228
     229/**
     230 * Same as MMR3HeapAlloc() only the memory is zeroed.
     231 *
     232 * @returns Pointer to allocated memory.
     233 * @param   pVM         VM handle.
     234 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     235 *                      basis in addition to a global one. Thus we can easily
     236 *                      identify how memory is used by the VM.
     237 * @param   cbSize      Size of the block.
     238 */
     239MMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize)
     240{
     241    return mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, true);
     242}
     243
     244
     245/**
     246 * Same as MMR3HeapAllocZ().
     247 *
     248 * @returns Pointer to allocated memory.
     249 * @param   pUVM        Pointer to the user mode VM structure.
     250 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     251 *                      basis in addition to a global one. Thus we can easily
     252 *                      identify how memory is used by the VM.
     253 * @param   cbSize      Size of the block.
     254 * @param   ppv         Where to store the pointer to the allocated memory on success.
     255 */
     256MMR3DECL(int) MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv)
     257{
     258    Assert(pUVM->mm.s.pHeap);
     259    void *pv = mmR3HeapAlloc(pUVM->mm.s.pHeap, enmTag, cbSize, true);
     260    if (pv)
     261    {
     262        *ppv = pv;
     263        return VINF_SUCCESS;
     264    }
     265    return VERR_NO_MEMORY;
     266}
     267
     268
     269/**
     270 * Same as MMR3HeapAllocZ().
     271 *
     272 * @returns Pointer to allocated memory.
     273 * @param   pVM         VM handle.
     274 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     275 *                      basis in addition to a global one. Thus we can easily
     276 *                      identify how memory is used by the VM.
     277 * @param   cbSize      Size of the block.
     278 * @param   ppv         Where to store the pointer to the allocated memory on success.
     279 */
     280MMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv)
     281{
     282    void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, true);
     283    if (pv)
     284    {
     285        *ppv = pv;
     286        return VINF_SUCCESS;
     287    }
     288    return VERR_NO_MEMORY;
     289}
     290
     291
     292/**
    231293 * Allocate memory from the heap.
    232294 *
     
    239301 * @param   fZero       Whether or not to zero the memory block.
    240302 */
    241 void * mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero)
     303void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero)
    242304{
    243305#ifdef MMR3HEAP_WITH_STATISTICS
     
    273335
    274336        /* register the statistics */
    275         PVM pVM = pHeap->pVM;
     337        PUVM pUVM = pHeap->pUVM;
    276338        char szName[80];
    277339        const char *pszTag = mmR3GetTagName(enmTag);
    278340        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cAllocations", pszTag);
    279         STAMR3Register(pVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
     341        STAMR3RegisterU(pUVM, &pStat->cAllocations,   STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_CALLS, "Number or MMR3HeapAlloc() calls.");
    280342
    281343        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cReallocations", pszTag);
    282         STAMR3Register(pVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
     344        STAMR3RegisterU(pUVM, &pStat->cReallocations, STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_CALLS, "Number of MMR3HeapRealloc() calls.");
    283345
    284346        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cFrees", pszTag);
    285         STAMR3Register(pVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
     347        STAMR3RegisterU(pUVM, &pStat->cFrees,         STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_CALLS, "Number of MMR3HeapFree() calls.");
    286348
    287349        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cFailures", pszTag);
    288         STAMR3Register(pVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_COUNT, "Number of failures.");
     350        STAMR3RegisterU(pUVM, &pStat->cFailures,      STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_COUNT, "Number of failures.");
    289351
    290352        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cbCurAllocated", pszTag);
    291         STAMR3Register(pVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_BYTES, "Number of bytes currently allocated.");
     353        STAMR3RegisterU(pUVM, &pStat->cbCurAllocated, STAMTYPE_U32, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_BYTES, "Number of bytes currently allocated.");
    292354
    293355        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cbAllocated", pszTag);
    294         STAMR3Register(pVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_BYTES, "Total number of bytes allocated.");
     356        STAMR3RegisterU(pUVM, &pStat->cbAllocated,    STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_BYTES, "Total number of bytes allocated.");
    295357
    296358        RTStrPrintf(szName, sizeof(szName), "/MM/R3Heap/%s/cbFreed", pszTag);
    297         STAMR3Register(pVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_BYTES, "Total number of bytes freed.");
     359        STAMR3RegisterU(pUVM, &pStat->cbFreed,        STAMTYPE_U64, STAMVISIBILITY_ALWAYS, szName,  STAMUNIT_BYTES, "Total number of bytes freed.");
    298360    }
    299361#endif
     
    452514    RTCritSectEnter(&pHeap->Lock);
    453515    pHdrNew->pStat->cbAllocated += cbNewSize - pHdrNew->cbSize;
    454     pHeap->Stat.cbAllocated   += cbNewSize - pHdrNew->cbSize;
     516    pHeap->Stat.cbAllocated += cbNewSize - pHdrNew->cbSize;
    455517    RTCritSectLeave(&pHeap->Lock);
    456518#endif
     
    459521
    460522    return pHdrNew + 1;
     523}
     524
     525
     526/**
     527 * Duplicates the specified string.
     528 *
     529 * @returns Pointer to the duplicate.
     530 * @returns NULL on failure or when input NULL.
     531 * @param   pUVM        Pointer to the user mode VM structure.
     532 * @param   enmTag      Statistics tag. Statistics are collected on a per tag
     533 *                      basis in addition to a global one. Thus we can easily
     534 *                      identify how memory is used by the VM.
     535 * @param   psz         The string to duplicate. NULL is allowed.
     536 */
     537MMR3DECL(char *) MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz)
     538{
     539    if (!psz)
     540        return NULL;
     541    AssertPtr(psz);
     542
     543    size_t cch = strlen(psz) + 1;
     544    char *pszDup = (char *)MMR3HeapAllocU(pUVM, enmTag, cch);
     545    if (pszDup)
     546        memcpy(pszDup, psz, cch);
     547    return pszDup;
    461548}
    462549
     
    475562MMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz)
    476563{
    477     if (!psz)
    478         return NULL;
    479     Assert(VALID_PTR(psz));
    480     size_t cch = strlen(psz) + 1;
    481     char *pszDup = (char *)MMR3HeapAlloc(pVM, enmTag, cch);
    482     if (pszDup)
    483         memcpy(pszDup, psz, cch);
    484     return pszDup;
     564    return MMR3HeapStrDupU(pVM->pUVM, enmTag, psz);
    485565}
    486566
  • trunk/src/VBox/VMM/MMInternal.h

    r6627 r6796  
    117117    PAVLULNODECORE      pStatTree;
    118118    /** The VM handle. */
    119     PVM                 pVM;
     119    PUVM                pUVM;
    120120    /** Heap global statistics. */
    121121    MMHEAPSTAT          Stat;
     
    675675    /** The head of the ROM ranges. */
    676676    R3PTRTYPE(PMMROMRANGE)      pRomHead;
    677 
    678     /** Pointer to the MM R3 Heap. */
    679     R3PTRTYPE(PMMHEAP)          pHeap;
    680 
    681677} MM;
    682678/** Pointer to MM Data (part of VM). */
    683679typedef MM *PMM;
    684680
     681
     682/**
     683 * MM data kept in the UVM.
     684 */
     685typedef struct MMUSERPERVM
     686{
     687    /** Pointer to the MM R3 Heap. */
     688    R3PTRTYPE(PMMHEAP)          pHeap;
     689} MMUSERPERVM;
     690/** Pointer to the MM data kept in the UVM. */
     691typedef MMUSERPERVM *PMMUSERPERVM;
     692
     693
    685694__BEGIN_DECLS
    686695
     
    691700void mmR3PagePoolTerm(PVM pVM);
    692701
    693 int  mmR3HeapCreate(PVM pVM, PMMHEAP *ppHeap);
     702int  mmR3HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap);
    694703void mmR3HeapDestroy(PMMHEAP pHeap);
    695704
  • trunk/src/VBox/VMM/PDM.cpp

    r5999 r6796  
    109109#include <VBox/ssm.h>
    110110#include <VBox/vm.h>
     111#include <VBox/uvm.h>
    111112#include <VBox/vmm.h>
    112113#include <VBox/param.h>
     
    141142
    142143/**
     144 * Initializes the PDM part of the UVM.
     145 *
     146 * This doesn't really do much right now but has to be here for the sake
     147 * of completeness.
     148 *
     149 * @returns VBox status code.
     150 * @param   pUVM        Pointer to the user mode VM structure.
     151 */
     152PDMR3DECL(int) PDMR3InitUVM(PUVM pUVM)
     153{
     154    AssertCompile(sizeof(pUVM->pdm.s) <= sizeof(pUVM->pdm.padding));
     155    AssertRelease(sizeof(pUVM->pdm.s) <= sizeof(pUVM->pdm.padding));
     156    pUVM->pdm.s.pModules = NULL;
     157    return VINF_SUCCESS;
     158}
     159
     160
     161/**
    143162 * Initializes the PDM.
    144163 *
     
    174193        if (VBOX_SUCCESS(rc))
    175194#endif
    176             rc = pdmR3LdrInit(pVM);
     195            rc = pdmR3LdrInitU(pVM->pUVM);
    177196        if (VBOX_SUCCESS(rc))
    178197        {
     
    426445     * Free modules.
    427446     */
    428     pdmR3LdrTerm(pVM);
     447    pdmR3LdrTermU(pVM->pUVM);
    429448
    430449#ifdef VBOX_WITH_PDM_LOCK
     
    438457    return VINF_SUCCESS;
    439458}
     459
     460
     461/**
     462 * Terminates the PDM part of the UVM.
     463 *
     464 * This will unload any modules left behind.
     465 *
     466 * @param   pUVM        Pointer to the user mode VM structure.
     467 */
     468PDMR3DECL(void) PDMR3TermUVM(PUVM pUVM)
     469{
     470    /*
     471     * In the normal cause of events we will now call pdmR3LdrTermU for
     472     * the second time. In the case of init failure however, this might
     473     * the first time, which is why we do it.
     474     */
     475    pdmR3LdrTermU(pUVM);
     476}
     477
     478
     479
    440480
    441481
  • trunk/src/VBox/VMM/PDMDevice.cpp

    r6475 r6796  
    994994     * Load it.
    995995     */
    996     int rc = pdmR3LoadR3(pVM, pszFilename, pszName);
     996    int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
    997997    if (VBOX_SUCCESS(rc))
    998998    {
  • trunk/src/VBox/VMM/PDMDriver.cpp

    r6221 r6796  
    9595
    9696#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
    97 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 
     97static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
    9898                                                                      PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc);
    9999#endif
     
    303303     * Load it.
    304304     */
    305     int rc = pdmR3LoadR3(pVM, pszFilename, pszName);
     305    int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName);
    306306    if (VBOX_SUCCESS(rc))
    307307    {
     
    10751075
    10761076#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
    1077 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 
     1077static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate,
    10781078                                                                      PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc)
    10791079{
     
    10851085    int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pszDesc);
    10861086
    1087     LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Vrc *ppThread=%p\n", pDrvIns->pDrvReg->szDriverName, 
     1087    LogFlow(("pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate: caller='%s'/%d: returns %Vrc *ppThread=%p\n", pDrvIns->pDrvReg->szDriverName,
    10881088             pDrvIns->iInstance, rc, *ppTemplate));
    10891089    return rc;
  • trunk/src/VBox/VMM/PDMInternal.h

    r5999 r6796  
    776776    RTUINT                          uPadding0; /**< Alignment padding.*/
    777777
    778     /** Pointer to list of loaded modules. This is HC only! */
    779     R3PTRTYPE(PPDMMOD)              pModules;
    780 
    781778    /** List of registered devices. (FIFO) */
    782779    R3PTRTYPE(PPDMDEV)              pDevs;
     
    867864
    868865
     866/**
     867 * PDM data kept in the UVM.
     868 */
     869typedef struct PDMUSERPERVM
     870{
     871    /** Pointer to list of loaded modules. */
     872    PPDMMOD                         pModules;
     873    /** @todo move more stuff over here. */
     874} PDMUSERPERVM;
     875/** Pointer to the PDM data kept in the UVM. */
     876typedef PDMUSERPERVM *PPDMUSERPERVM;
     877
     878
    869879
    870880/*******************************************************************************
     
    902912PPDMDRV     pdmR3DrvLookup(PVM pVM, const char *pszName);
    903913
    904 int         pdmR3LdrInit(PVM pVM);
    905 void        pdmR3LdrTerm(PVM pVM);
     914int         pdmR3LdrInitU(PUVM pUVM);
     915void        pdmR3LdrTermU(PUVM pUVM);
    906916char *      pdmR3FileR3(const char *pszFile, bool fShared = false);
    907 int         pdmR3LoadR3(PVM pVM, const char *pszFilename, const char *pszName);
     917int         pdmR3LoadR3U(PUVM pUVM, const char *pszFilename, const char *pszName);
    908918
    909919void        pdmR3QueueRelocate(PVM pVM, RTGCINTPTR offDelta);
  • trunk/src/VBox/VMM/PDMLdr.cpp

    r5999 r6796  
    2727#include <VBox/vmm.h>
    2828#include <VBox/vm.h>
     29#include <VBox/uvm.h>
    2930#include <VBox/sup.h>
    3031#include <VBox/param.h>
     
    5960*   Internal Functions                                                         *
    6061*******************************************************************************/
    61 static DECLCALLBACK(int) pdmr3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
    62 static int      pdmR3LoadR0(PVM pVM, const char *pszFilename, const char *pszName);
     62static DECLCALLBACK(int) pdmR3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser);
     63static int      pdmR3LoadR0U(PUVM pUVM, const char *pszFilename, const char *pszName);
    6364static char *   pdmR3FileGC(const char *pszFile);
    6465static char *   pdmR3FileR0(const char *pszFile);
     
    6970
    7071/**
    71  * Loads the VMMR0.r0 module before the VM is created.
    72  *
    73  * The opqaue VMMR0 module pointer is passed on to PDMR3Init later in
    74  * the init process or PDMR3LdrUnloadVMMR0 in case of some init failure before PDMR3Init.
     72 * Loads the VMMR0.r0 module early in the init process.
    7573 *
    7674 * @returns VBox status code.
    77  * @param   ppvOpaque       Where to return the opaque VMMR0.r0 module handle one success.
    78  *
    79  * @remarks Yes, this is a kind of hacky and should go away. See @todo in VMR3Create.
    80  */
    81 PDMR3DECL(int) PDMR3LdrLoadVMMR0(void **ppvOpaque)
    82 {
    83     *ppvOpaque = NULL;
    84 
    85     /*
    86      * Resolve the filename and allocate the module list node.
    87      */
    88     char *pszFilename = pdmR3FileR0(VMMR0_MAIN_MODULE_NAME);
    89     PPDMMOD pModule = (PPDMMOD)RTMemAllocZ(sizeof(*pModule) + strlen(pszFilename));
    90     if (!pModule)
    91     {
    92         RTMemTmpFree(pszFilename);
    93         return VERR_NO_MEMORY;
    94     }
    95     strcpy(pModule->szName, VMMR0_MAIN_MODULE_NAME);
    96     pModule->eType = PDMMOD_TYPE_R0;
    97     strcpy(pModule->szFilename, pszFilename);
    98     RTMemTmpFree(pszFilename);
    99 
    100     /*
    101      * Ask the support library to load it.
    102      */
    103     void *pvImageBase;
    104     int rc = SUPLoadModule(pModule->szFilename, pModule->szName, &pvImageBase);
    105     if (RT_SUCCESS(rc))
    106     {
    107         pModule->hLdrMod = NIL_RTLDRMOD;
    108         pModule->ImageBase = (uintptr_t)pvImageBase;
    109         *ppvOpaque = pModule;
    110 
    111         Log(("PDMR3LdrLoadVMMR0: Loaded %s at %VGvx (%s)\n", pModule->szName, (RTGCPTR)pModule->ImageBase, pModule->szFilename));
    112         return VINF_SUCCESS;
    113     }
    114 
    115     LogRel(("PDMR3LdrLoadVMMR0: rc=%Vrc szName=%s szFilename=%s\n", rc, pModule->szName, pModule->szFilename));
    116     RTMemFree(pModule);
    117     return rc;
    118 }
    119 
    120 
    121 /**
    122  * Register the VMMR0.r0 module with the created VM or unload it if
    123  * we failed to create the VM (pVM == NULL).
    124  *
    125  * @param   pVM         The VM pointer. NULL if we failed to create the VM and
    126  *                      the module should be unloaded and freed.
    127  * @param   pvOpaque    The value returned by PDMR3LDrLoadVMMR0().
    128  *
    129  * @remarks Yes, this is a kind of hacky and should go away. See @todo in VMR3Create.
    130  */
    131 PDMR3DECL(void) PDMR3LdrLoadVMMR0Part2(PVM pVM, void *pvOpaque)
    132 {
    133     PPDMMOD pModule = (PPDMMOD)pvOpaque;
    134     AssertPtrReturnVoid(pModule);
    135 
    136     if (pVM)
    137     {
    138         /*
    139          * Register the R0 module loaded by PDMR3LdrLoadVMMR0
    140          */
    141         Assert(!pVM->pdm.s.pModules);
    142         pModule->pNext = pVM->pdm.s.pModules;
    143         pVM->pdm.s.pModules = pModule;
    144     }
    145     else
    146     {
    147         /*
    148          * Failed, unload the module.
    149          */
    150         int rc2 = SUPFreeModule((void *)(uintptr_t)pModule->ImageBase);
    151         AssertRC(rc2);
    152         pModule->ImageBase = 0;
    153         RTMemFree(pvOpaque);
    154     }
     75 * @param   pUVM            Pointer to the user mode VM structure.
     76 */
     77PDMR3DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM)
     78{
     79    return pdmR3LoadR0U(pUVM, NULL, VMMR0_MAIN_MODULE_NAME);
    15580}
    15681
     
    16388 *
    16489 * @returns VBox stutus code.
    165  * @param   pVM         VM handle.
     90 * @param   pUVM        Pointer to the user mode VM structure.
    16691 * @param   pvVMMR0Mod  The opqaue returned by PDMR3LdrLoadVMMR0.
    16792 */
    168 int pdmR3LdrInit(PVM pVM)
     93int pdmR3LdrInitU(PUVM pUVM)
    16994{
    17095#ifdef PDMLDR_FAKE_MODE
     
    176101     * Load the mandatory GC module, the VMMR0.r0 is loaded before VM creation.
    177102     */
    178     return PDMR3LoadGC(pVM, NULL, VMMGC_MAIN_MODULE_NAME);
     103    return PDMR3LoadGC(pUVM->pVM, NULL, VMMGC_MAIN_MODULE_NAME);
    179104#endif
    180105}
     
    187112 *
    188113 * @param   pVM         The VM handle.
    189  */
    190 void pdmR3LdrTerm(PVM pVM)
     114 *
     115 * @remarks This is normally called twice during termination.
     116 */
     117void pdmR3LdrTermU(PUVM pUVM)
    191118{
    192119    /*
    193120     * Free the modules.
    194121     */
    195     PPDMMOD pModule = pVM->pdm.s.pModules;
     122    PPDMMOD pModule = pUVM->pdm.s.pModules;
     123    pUVM->pdm.s.pModules = NULL;
    196124    while (pModule)
    197125    {
     
    240168 * process so that components can resolve GC symbols during relocation.
    241169 *
    242  * @param   pVM         VM handle.
     170 * @param   pUVM        Pointer to the user mode VM structure.
    243171 * @param   offDelta    Relocation delta relative to old location.
    244172 */
    245 PDMR3DECL(void) PDMR3LdrRelocate(PVM pVM, RTGCINTPTR offDelta)
     173PDMR3DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta)
    246174{
    247175    LogFlow(("PDMR3LdrRelocate: offDelta=%VGv\n", offDelta));
     
    250178     * GC Modules.
    251179     */
    252     if (pVM->pdm.s.pModules)
     180    if (pUVM->pdm.s.pModules)
    253181    {
    254182        /*
     
    260188        /* pass 1 */
    261189        PPDMMOD pCur;
    262         for (pCur = pVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
     190        for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
    263191        {
    264192            if (pCur->eType == PDMMOD_TYPE_GC)
    265193            {
    266194                pCur->OldImageBase = pCur->ImageBase;
    267                 pCur->ImageBase = MMHyperHC2GC(pVM, pCur->pvBits);
     195                pCur->ImageBase = MMHyperHC2GC(pUVM->pVM, pCur->pvBits);
    268196            }
    269197        }
    270198
    271199        /* pass 2 */
    272         for (pCur = pVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
     200        for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
    273201        {
    274202            if (pCur->eType == PDMMOD_TYPE_GC)
    275203            {
    276204                PDMGETIMPORTARGS Args;
    277                 Args.pVM = pVM;
     205                Args.pVM = pUVM->pVM;
    278206                Args.pModule = pCur;
    279207                int rc = RTLdrRelocate(pCur->hLdrMod, pCur->pvBits, pCur->ImageBase, pCur->OldImageBase,
    280                                        pdmr3GetImportGC, &Args);
     208                                       pdmR3GetImportGC, &Args);
    281209                AssertFatalMsgRC(rc, ("RTLdrRelocate failed, rc=%d\n", rc));
    282                 DBGFR3ModuleRelocate(pVM, pCur->OldImageBase, pCur->ImageBase, RTLdrSize(pCur->hLdrMod),
     210                DBGFR3ModuleRelocate(pUVM->pVM, pCur->OldImageBase, pCur->ImageBase, RTLdrSize(pCur->hLdrMod),
    283211                                     pCur->szFilename, pCur->szName);
    284212            }
     
    301229 *
    302230 * @returns VBox status code.
    303  * @param   pVM             The VM to load it into.
     231 * @param   pUVM            Pointer to the user mode VM structure.
    304232 * @param   pszFilename     Filename of the module binary.
    305233 * @param   pszName         Module name. Case sensitive and the length is limited!
    306234 */
    307 int pdmR3LoadR3(PVM pVM, const char *pszFilename, const char *pszName)
     235int pdmR3LoadR3U(PUVM pUVM, const char *pszFilename, const char *pszName)
    308236{
    309237    /*
    310238     * Validate input.
    311239     */
    312     AssertMsg(pVM->pdm.s.offVM, ("bad init order!\n"));
     240    AssertMsg(pUVM->pVM->pdm.s.offVM, ("bad init order!\n"));
    313241    Assert(pszFilename);
    314242    size_t cchFilename = strlen(pszFilename);
     
    325253     * Try lookup the name and see if the module exists.
    326254     */
    327     for (pCur = pVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
     255    for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
    328256    {
    329257        if (!strcmp(pCur->szName, pszName))
     
    353281    if (VBOX_SUCCESS(rc))
    354282    {
    355         pModule->pNext = pVM->pdm.s.pModules;
    356         pVM->pdm.s.pModules = pModule;
     283        pModule->pNext = pUVM->pdm.s.pModules;
     284        pUVM->pdm.s.pModules = pModule;
    357285        return rc;
    358286    }
     
    360288    /* Something went wrong, most likely module not found. Don't consider other unlikely errors */
    361289    RTMemFree(pModule);
    362     return VMSetError(pVM, rc, RT_SRC_POS, N_("Unable to load R3 module %s"), pszFilename);
     290    return VMSetError(pUVM->pVM, rc, RT_SRC_POS, N_("Unable to load R3 module %s"), pszFilename);
    363291}
    364292
     
    375303 * @param   pvUser          User argument.
    376304 */
    377 static DECLCALLBACK(int) pdmr3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
     305static DECLCALLBACK(int) pdmR3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)
    378306{
    379307    PVM         pVM = ((PPDMGETIMPORTARGS)pvUser)->pVM;
     
    427355     * Search for module.
    428356     */
    429     PPDMMOD  pCur = pVM->pdm.s.pModules;
     357    PPDMMOD  pCur = pVM->pUVM->pdm.s.pModules;
    430358    while (pCur)
    431359    {
     
    478406     */
    479407    AssertMsg(pVM->pdm.s.offVM, ("bad init order!\n"));
    480     PPDMMOD  pCur = pVM->pdm.s.pModules;
     408    PPDMMOD  pCur = pVM->pUVM->pdm.s.pModules;
    481409    while (pCur)
    482410    {
     
    541469                Args.pVM = pVM;
    542470                Args.pModule = pModule;
    543                 rc = RTLdrGetBits(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, pdmr3GetImportGC, &Args);
     471                rc = RTLdrGetBits(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, pdmR3GetImportGC, &Args);
    544472                if (VBOX_SUCCESS(rc))
    545473                {
     
    547475                     * Insert the module.
    548476                     */
    549                     if (pVM->pdm.s.pModules)
     477                    PUVM pUVM = pVM->pUVM;
     478                    if (pUVM->pdm.s.pModules)
    550479                    {
    551480                        /* we don't expect this list to be very long, so rather save the tail pointer. */
    552                         PPDMMOD pCur = pVM->pdm.s.pModules;
     481                        PPDMMOD pCur = pUVM->pdm.s.pModules;
    553482                        while (pCur->pNext)
    554483                            pCur = pCur->pNext;
     
    556485                    }
    557486                    else
    558                         pVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */
     487                        pUVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */
    559488                    Log(("PDM: GC Module at %VGvx %s (%s)\n", (RTGCPTR)pModule->ImageBase, pszName, pszFilename));
    560489                    RTMemTmpFree(pszFile);
     
    587516 *
    588517 * @returns VBox status code.
    589  * @param   pVM             The VM to load it into.
     518 * @param   pUVM            Pointer to the user mode VM structure.
    590519 * @param   pszFilename     Filename of the module binary.
    591520 * @param   pszName         Module name. Case sensitive and the length is limited!
    592521 */
    593 static int pdmR3LoadR0(PVM pVM, const char *pszFilename, const char *pszName)
     522static int pdmR3LoadR0U(PUVM pUVM, const char *pszFilename, const char *pszName)
    594523{
    595524    /*
    596525     * Validate input.
    597526     */
    598     AssertMsg(pVM->pdm.s.offVM, ("bad init order!\n"));
    599     PPDMMOD  pCur = pVM->pdm.s.pModules;
     527    PPDMMOD  pCur = pUVM->pdm.s.pModules;
    600528    while (pCur)
    601529    {
     
    608536        pCur = pCur->pNext;
    609537    }
    610     AssertReturn(strcmp(pszName, VMMR0_MAIN_MODULE_NAME), VERR_INTERNAL_ERROR);
    611538
    612539    /*
     
    645572         * Insert the module.
    646573         */
    647         if (pVM->pdm.s.pModules)
     574        if (pUVM->pdm.s.pModules)
    648575        {
    649576            /* we don't expect this list to be very long, so rather save the tail pointer. */
    650             PPDMMOD pCur = pVM->pdm.s.pModules;
     577            PPDMMOD pCur = pUVM->pdm.s.pModules;
    651578            while (pCur->pNext)
    652579                pCur = pCur->pNext;
     
    654581        }
    655582        else
    656             pVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */
     583            pUVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */
    657584        Log(("PDM: GC Module at %VGvx %s (%s)\n", (RTGCPTR)pModule->ImageBase, pszName, pszFilename));
    658585        RTMemTmpFree(pszFile);
     
    662589    RTMemFree(pModule);
    663590    RTMemTmpFree(pszFile);
    664     LogRel(("pdmR3LoadR0: pszName=\"%s\" rc=%Vrc\n", pszName, rc));
     591    LogRel(("pdmR3LoadR0U: pszName=\"%s\" rc=%Vrc\n", pszName, rc));
    665592
    666593    /* Don't consider VERR_PDM_MODULE_NAME_CLASH and VERR_NO_MEMORY above as these are very unlikely. */
    667     if (VBOX_FAILURE(rc))
    668         return VMSetError(pVM, rc, RT_SRC_POS, N_("Cannot load R0 module %s"), pszFilename);
     594    if (VBOX_FAILURE(rc) && pUVM->pVM) /** @todo VMR3SetErrorU. */
     595        return VMSetError(pUVM->pVM, rc, RT_SRC_POS, N_("Cannot load R0 module %s"), pszFilename);
    669596    return rc;
    670597}
     
    692619     * Find the module.
    693620     */
    694     for (PPDMMOD pModule = pVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
     621    for (PPDMMOD pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
    695622    {
    696623        if (    pModule->eType == PDMMOD_TYPE_R3
     
    747674     * Find the module.
    748675     */
    749     for (PPDMMOD pModule = pVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
     676    for (PPDMMOD pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
    750677    {
    751678        if (    pModule->eType == PDMMOD_TYPE_R0
     
    794721        AssertMsgReturn(!strpbrk(pszModule, "/\\:\n\r\t"), ("pszModule=%s\n", pszModule), VERR_INVALID_PARAMETER);
    795722        PPDMMOD pModule;
    796         for (pModule = pVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
     723        for (pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
    797724            if (    pModule->eType == PDMMOD_TYPE_R0
    798725                &&  !strcmp(pModule->szName, pszModule))
     
    800727        if (!pModule)
    801728        {
    802             int rc = pdmR3LoadR0(pVM, NULL, pszModule);
     729            int rc = pdmR3LoadR0U(pVM->pUVM, NULL, pszModule);
    803730            AssertMsgRCReturn(rc, ("pszModule=%s rc=%Vrc\n", pszModule, rc), VERR_MODULE_NOT_FOUND);
    804731        }
     
    836763     * Find the module.
    837764     */
    838     for (PPDMMOD pModule = pVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
     765    for (PPDMMOD pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
    839766    {
    840767        if (    pModule->eType == PDMMOD_TYPE_GC
     
    891818        AssertMsgReturn(!strpbrk(pszModule, "/\\:\n\r\t"), ("pszModule=%s\n", pszModule), VERR_INVALID_PARAMETER);
    892819        PPDMMOD pModule;
    893         for (pModule = pVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
     820        for (pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext)
    894821            if (    pModule->eType == PDMMOD_TYPE_GC
    895822                &&  !strcmp(pModule->szName, pszModule))
     
    10781005    int     rc = VERR_MODULE_NOT_FOUND;
    10791006    PPDMMOD pCur;
    1080     for (pCur = pVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
     1007    for (pCur = pVM->pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
    10811008    {
    10821009        /* Skip anything which isn't in GC. */
     
    11951122{
    11961123    PPDMMOD pCur;
    1197     for (pCur = pVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
     1124    for (pCur = pVM->pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext)
    11981125    {
    11991126        int rc = pfnCallback(pVM,
  • trunk/src/VBox/VMM/STAM.cpp

    r6617 r6796  
    2424#include "STAMInternal.h"
    2525#include <VBox/vm.h>
     26#include <VBox/uvm.h>
    2627#include <VBox/err.h>
    2728#include <VBox/dbg.h>
     
    7273    /** Pointer to the current buffer position. */
    7374    char           *psz;
    74     /** The VM handle (just in case). */
     75    /** The VM handle. */
    7576    PVM             pVM;
    7677    /** The number of bytes allocated. */
     
    104105*   Internal Functions                                                         *
    105106*******************************************************************************/
    106 static int stamR3Register(PVM pVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    107                           STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
     107static int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
     108                           STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc);
    108109static int stamR3ResetOne(PSTAMDESC pDesc, void *pvArg);
    109110static DECLCALLBACK(void) stamR3EnumLogPrintf(PSTAMR3PRINTONEARGS pvArg, const char *pszFormat, ...);
     
    116117static bool stamR3MultiMatch(const char * const *papszExpressions, unsigned cExpressions, unsigned *piExpression, const char *pszName);
    117118static char **stamR3SplitPattern(const char *pszPat, unsigned *pcExpressions, char **ppszCopy);
    118 static int stamR3Enum(PVM pVM, const char *pszPat, bool fUpdateRing0, int (pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg);
    119 static void stamR3Ring0StatsRegister(PVM pVM);
    120 static void stamR3Ring0StatsUpdate(PVM pVM, const char *pszPat);
    121 static void stamR3Ring0StatsUpdateMulti(PVM pVM, const char * const *papszExpressions, unsigned cExpressions);
     119static int stamR3EnumU(PUVM pUVM, const char *pszPat, bool fUpdateRing0, int (pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg);
     120static void stamR3Ring0StatsRegisterU(PUVM pUVM);
     121static void stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat);
     122static void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions);
    122123
    123124#ifdef VBOX_WITH_DEBUGGER
     
    188189 * @param   pVM         The VM to operate on.
    189190 */
    190 STAMR3DECL(int) STAMR3Init(PVM pVM)
     191STAMR3DECL(int) STAMR3InitUVM(PUVM pUVM)
    191192{
    192193    LogFlow(("STAMR3Init\n"));
     
    195196     * Assert alignment and sizes.
    196197     */
    197     AssertRelease(!(RT_OFFSETOF(VM, stam.s) & 31));
    198     AssertRelease(sizeof(pVM->stam.s) <= sizeof(pVM->stam.padding));
     198    AssertCompile(sizeof(pUVM->stam.s) <= sizeof(pUVM->stam.padding));
     199    AssertRelease(sizeof(pUVM->stam.s) <= sizeof(pUVM->stam.padding));
    199200
    200201    /*
    201202     * Setup any fixed pointers and offsets.
    202203     */
    203     pVM->stam.s.offVM = RT_OFFSETOF(VM, stam);
    204     int rc = RTSemRWCreate(&pVM->stam.s.RWSem);
    205     AssertRC(rc);
    206     if (VBOX_FAILURE(rc))
    207         return rc;
     204    int rc = RTSemRWCreate(&pUVM->stam.s.RWSem);
     205    AssertRCReturn(rc, rc);
    208206
    209207    /*
    210208     * Register the ring-0 statistics (GVMM/GMM).
    211209     */
    212     stamR3Ring0StatsRegister(pVM);
     210    stamR3Ring0StatsRegisterU(pUVM);
    213211
    214212#ifdef VBOX_WITH_DEBUGGER
     
    230228
    231229/**
    232  * Applies relocations to data and code managed by this
    233  * component. This function will be called at init and
    234  * whenever the VMM need to relocate it self inside the GC.
    235  *
    236  * @param   pVM     The VM.
    237  */
    238 STAMR3DECL(void) STAMR3Relocate(PVM pVM)
    239 {
    240     LogFlow(("STAMR3Relocate\n"));
    241     NOREF(pVM);
    242 }
    243 
    244 
    245 /**
    246230 * Terminates the STAM.
    247231 *
    248  * Termination means cleaning up and freeing all resources,
    249  * the VM it self is at this point powered off or suspended.
    250  *
    251  * @returns VBox status code.
    252  * @param   pVM         The VM to operate on.
    253  */
    254 STAMR3DECL(int) STAMR3Term(PVM pVM)
     232 * @param   pUVM        Pointer to the user mode VM structure.
     233 */
     234STAMR3DECL(void) STAMR3TermUVM(PUVM pUVM)
    255235{
    256236    /*
    257237     * Free used memory and the RWLock.
    258238     */
    259     PSTAMDESC   pCur = pVM->stam.s.pHead;
     239    PSTAMDESC pCur = pUVM->stam.s.pHead;
    260240    while (pCur)
    261241    {
     
    264244        RTMemFree(pvFree);
    265245    }
    266     pVM->stam.s.pHead = NULL;
    267 
    268     /* careful here as we might be called twice in on some failure paths (?) */
    269     if (pVM->stam.s.RWSem != NIL_RTSEMRW)
    270         RTSemRWDestroy(pVM->stam.s.RWSem);
    271     pVM->stam.s.RWSem = NIL_RTSEMRW;
    272     return VINF_SUCCESS;
    273 }
    274 
    275 
     246    pUVM->stam.s.pHead = NULL;
     247
     248    Assert(pUVM->stam.s.RWSem != NIL_RTSEMRW);
     249    RTSemRWDestroy(pUVM->stam.s.RWSem);
     250    pUVM->stam.s.RWSem = NIL_RTSEMRW;
     251}
    276252
    277253
     
    279255 * Registers a sample with the statistics mamanger.
    280256 *
    281  * Statistics are maintained on a per VM basis and should therefore
    282  * be registered during the VM init stage. However, there is not problem
    283  * registering temporary samples or samples for hotpluggable devices. Samples
    284  * can be deregisterd using the STAMR3Deregister() function, but note that
    285  * this is only necessary for temporary samples or hotpluggable devices.
     257 * Statistics are maintained on a per VM basis and is normally registered
     258 * during the VM init stage, but there is nothing preventing you from
     259 * register them at runtime.
     260 *
     261 * Use STAMR3Deregister() to deregister statistics at runtime, however do
     262 * not bother calling at termination time.
     263 *
     264 * It is not possible to register the same sample twice.
     265 *
     266 * @returns VBox status.
     267 * @param   pUVM        Pointer to the user mode VM structure.
     268 * @param   pvSample    Pointer to the sample.
     269 * @param   enmType     Sample type. This indicates what pvSample is pointing at.
     270 * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
     271 * @param   pszName     Sample name. The name is on this form "/<component>/<sample>".
     272 *                      Further nesting is possible.
     273 * @param   enmUnit     Sample unit.
     274 * @param   pszDesc     Sample description.
     275 */
     276STAMR3DECL(int)  STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
     277{
     278    AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER);
     279    return stamR3RegisterU(pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
     280}
     281
     282
     283/**
     284 * Registers a sample with the statistics mamanger.
     285 *
     286 * Statistics are maintained on a per VM basis and is normally registered
     287 * during the VM init stage, but there is nothing preventing you from
     288 * register them at runtime.
     289 *
     290 * Use STAMR3Deregister() to deregister statistics at runtime, however do
     291 * not bother calling at termination time.
    286292 *
    287293 * It is not possible to register the same sample twice.
     
    300306{
    301307    AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER);
    302     return stamR3Register(pVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
     308    return stamR3RegisterU(pVM->pUVM, pvSample, NULL, NULL, enmType, enmVisibility, pszName, enmUnit, pszDesc);
     309}
     310
     311
     312/**
     313 * Same as STAMR3RegisterU except that the name is specified in a
     314 * RTStrPrintf like fashion.
     315 *
     316 * @returns VBox status.
     317 * @param   pUVM        Pointer to the user mode VM structure.
     318 * @param   pvSample    Pointer to the sample.
     319 * @param   enmType     Sample type. This indicates what pvSample is pointing at.
     320 * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
     321 * @param   enmUnit     Sample unit.
     322 * @param   pszDesc     Sample description.
     323 * @param   pszName     The sample name format string.
     324 * @param   ...         Arguments to the format string.
     325 */
     326STAMR3DECL(int)  STAMR3RegisterFU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     327                                  const char *pszDesc, const char *pszName, ...)
     328{
     329    va_list args;
     330    va_start(args, pszName);
     331    int rc = STAMR3RegisterVU(pUVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
     332    va_end(args);
     333    return rc;
    303334}
    304335
     
    323354    va_list args;
    324355    va_start(args, pszName);
    325     int rc = STAMR3RegisterV(pVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
     356    int rc = STAMR3RegisterVU(pVM->pUVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    326357    va_end(args);
    327358    return rc;
     
    343374 * @param   args        Arguments to the format string.
    344375 */
    345 STAMR3DECL(int)  STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
    346                                  const char *pszDesc, const char *pszName, va_list args)
     376STAMR3DECL(int)  STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     377                                  const char *pszDesc, const char *pszName, va_list args)
    347378{
    348379    AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER);
     
    353384        return VERR_NO_MEMORY;
    354385
    355     int rc = STAMR3Register(pVM, pvSample, enmType, enmVisibility, pszFormattedName, enmUnit, pszDesc);
     386    int rc = STAMR3RegisterU(pUVM, pvSample, enmType, enmVisibility, pszFormattedName, enmUnit, pszDesc);
    356387    RTStrFree(pszFormattedName);
    357388    return rc;
     389}
     390
     391
     392/**
     393 * Same as STAMR3Register except that the name is specified in a
     394 * RTStrPrintfV like fashion.
     395 *
     396 * @returns VBox status.
     397 * @param   pVM         The VM handle.
     398 * @param   pvSample    Pointer to the sample.
     399 * @param   enmType     Sample type. This indicates what pvSample is pointing at.
     400 * @param   enmVisibility  Visibility type specifying whether unused statistics should be visible or not.
     401 * @param   enmUnit     Sample unit.
     402 * @param   pszDesc     Sample description.
     403 * @param   pszName     The sample name format string.
     404 * @param   args        Arguments to the format string.
     405 */
     406STAMR3DECL(int)  STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,
     407                                 const char *pszDesc, const char *pszName, va_list args)
     408{
     409    return STAMR3RegisterVU(pVM->pUVM, pvSample, enmType, enmVisibility, enmUnit, pszDesc, pszName, args);
    358410}
    359411
     
    411463        return VERR_NO_MEMORY;
    412464
    413     int rc = stamR3Register(pVM, pvSample, pfnReset, pfnPrint, STAMTYPE_CALLBACK, enmVisibility, pszFormattedName, enmUnit, pszDesc);
     465    int rc = stamR3RegisterU(pVM->pUVM, pvSample, pfnReset, pfnPrint, STAMTYPE_CALLBACK, enmVisibility, pszFormattedName, enmUnit, pszDesc);
    414466    RTStrFree(pszFormattedName);
    415467    return rc;
     
    421473 *
    422474 * @returns VBox status.
    423  * @param   pVM         The VM handle.
     475 * @param   pUVM        Pointer to the user mode VM structure.
    424476 * @param   pvSample    Pointer to the sample.
    425477 * @param   pfnReset    Callback for resetting the sample. NULL should be used if the sample can't be reset.
     
    433485 * @remark  There is currently no device or driver variant of this API. Add one if it should become necessary!
    434486 */
    435 static int stamR3Register(PVM pVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
    436                           STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
    437 {
    438     STAM_LOCK_WR(pVM);
     487static int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint,
     488                           STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc)
     489{
     490    STAM_LOCK_WR(pUVM);
    439491
    440492    /*
     
    442494     */
    443495    PSTAMDESC   pPrev = NULL;
    444     PSTAMDESC   pCur = pVM->stam.s.pHead;
     496    PSTAMDESC   pCur = pUVM->stam.s.pHead;
    445497    while (pCur)
    446498    {
     
    452504        if (!iDiff)
    453505        {
    454             STAM_UNLOCK_WR(pVM);
     506            STAM_UNLOCK_WR(pUVM);
    455507            AssertMsgFailed(("Duplicate sample name: %s\n", pszName));
    456508            return VERR_ALREADY_EXISTS;
     
    491543            pPrev->pNext    = pNew;
    492544        else
    493             pVM->stam.s.pHead = pNew;
    494 
    495         stamR3ResetOne(pNew, pVM);
     545            pUVM->stam.s.pHead = pNew;
     546
     547        stamR3ResetOne(pNew, pUVM->pVM);
    496548        rc = VINF_SUCCESS;
    497549    }
     
    499551        rc = VERR_NO_MEMORY;
    500552
    501     STAM_UNLOCK_WR(pVM);
     553    STAM_UNLOCK_WR(pUVM);
    502554    return rc;
    503555}
     
    511563 *
    512564 * @returns VBox status.
    513  * @param   pVM         The VM handle.
     565 * @param   pUVM        Pointer to the user mode VM structure.
    514566 * @param   pvSample    Pointer to the sample registered with STAMR3Register().
    515567 */
    516 STAMR3DECL(int)  STAMR3Deregister(PVM pVM, void *pvSample)
    517 {
    518     STAM_LOCK_WR(pVM);
     568STAMR3DECL(int)  STAMR3DeregisterU(PUVM pUVM, void *pvSample)
     569{
     570    STAM_LOCK_WR(pUVM);
    519571
    520572    /*
     
    523575    int         rc = VERR_INVALID_HANDLE;
    524576    PSTAMDESC   pPrev = NULL;
    525     PSTAMDESC   pCur = pVM->stam.s.pHead;
     577    PSTAMDESC   pCur = pUVM->stam.s.pHead;
    526578    while (pCur)
    527579    {
     
    533585                pPrev->pNext = pCur;
    534586            else
    535                 pVM->stam.s.pHead = pCur;
     587                pUVM->stam.s.pHead = pCur;
    536588
    537589            RTMemFree(pvFree);
     
    545597    }
    546598
    547     STAM_UNLOCK_WR(pVM);
     599    STAM_UNLOCK_WR(pUVM);
    548600    return rc;
     601}
     602
     603
     604/**
     605 * Deregisters a sample previously registered by STAR3Register().
     606 *
     607 * This is intended used for devices which can be unplugged and for
     608 * temporary samples.
     609 *
     610 * @returns VBox status.
     611 * @param   pVM         The VM handle.
     612 * @param   pvSample    Pointer to the sample registered with STAMR3Register().
     613 */
     614STAMR3DECL(int)  STAMR3Deregister(PVM pVM, void *pvSample)
     615{
     616    return STAMR3DeregisterU(pVM->pUVM, pvSample);
    549617}
    550618
     
    560628 * @remarks Don't confuse this with the other 'XYZR3Reset' methods, it's not called at VM reset.
    561629 */
    562 STAMR3DECL(int)  STAMR3Reset(PVM pVM, const char *pszPat)
     630STAMR3DECL(int)  STAMR3ResetU(PUVM pUVM, const char *pszPat)
    563631{
    564632    int rc = VINF_SUCCESS;
     
    601669    }
    602670
    603     STAM_LOCK_WR(pVM);
     671    STAM_LOCK_WR(pUVM);
    604672    if (fGVMMMatched)
    605673    {
     674        PVM pVM = pUVM->pVM;
    606675        GVMMReq.Hdr.cbReq = sizeof(GVMMReq);
    607676        GVMMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     
    612681//    if (fGMMMatched)
    613682//    {
     683//        PVM pVM = pUVM->pVM;
    614684//        GMMReq.Hdr.cbReq = sizeof(Req);
    615685//        GMMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     
    619689
    620690    /* and the reset */
    621     stamR3Enum(pVM, pszPat, false /* fUpdateRing0 */, stamR3ResetOne, pVM);
    622 
    623     STAM_UNLOCK_WR(pVM);
     691    stamR3EnumU(pUVM, pszPat, false /* fUpdateRing0 */, stamR3ResetOne, pUVM->pVM);
     692
     693    STAM_UNLOCK_WR(pUVM);
    624694    return rc;
    625695}
    626696
     697/**
     698 * Resets statistics for the specified VM.
     699 * It's possible to select a subset of the samples.
     700 *
     701 * @returns VBox status. (Basically, it cannot fail.)
     702 * @param   pVM         The VM handle.
     703 * @param   pszPat      The name matching pattern. See somewhere_where_this_is_described_in_detail.
     704 *                      If NULL all samples are reset.
     705 * @remarks Don't confuse this with the other 'XYZR3Reset' methods, it's not called at VM reset.
     706 */
     707STAMR3DECL(int)  STAMR3Reset(PVM pVM, const char *pszPat)
     708{
     709    return STAMR3ResetU(pVM->pUVM, pszPat);
     710}
     711
     712
    627713
    628714/**
    629715 * Resets one statistics sample.
    630  * Callback for stamR3Enum().
     716 * Callback for stamR3EnumU().
    631717 *
    632718 * @returns VINF_SUCCESS
     
    706792 *
    707793 * @returns VBox status. (Basically, it cannot fail.)
     794 * @param   pUVM            Pointer to the user mode VM structure.
     795 * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
     796 *                          If NULL all samples are reset.
     797 * @param   fWithDesc       Whether to include the descriptions.
     798 * @param   ppszSnapshot    Where to store the pointer to the snapshot data.
     799 *                          The format of the snapshot should be XML, but that will have to be discussed
     800 *                          when this function is implemented.
     801 *                          The returned pointer must be freed by calling STAMR3SnapshotFree().
     802 * @param   pcchSnapshot    Where to store the size of the snapshot data. (Excluding the trailing '\0')
     803 */
     804STAMR3DECL(int) STAMR3SnapshotU(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc)
     805{
     806    STAMR3SNAPSHOTONE State = { NULL, NULL, NULL, pUVM->pVM, 0, VINF_SUCCESS, fWithDesc };
     807
     808    /*
     809     * Write the XML header.
     810     */
     811    /** @todo Make this proper & valid XML. */
     812    stamR3SnapshotPrintf(&State, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
     813
     814    /*
     815     * Write the content.
     816     */
     817    stamR3SnapshotPrintf(&State, "<Statistics>\n");
     818    STAM_LOCK_RD(pUVM);
     819    int rc = stamR3EnumU(pUVM, pszPat, true /* fUpdateRing0 */, stamR3SnapshotOne, &State);
     820    STAM_UNLOCK_RD(pUVM);
     821    stamR3SnapshotPrintf(&State, "</Statistics>\n");
     822
     823    if (VBOX_SUCCESS(rc))
     824        rc = State.rc;
     825    else
     826    {
     827        RTMemFree(State.pszStart);
     828        State.pszStart = State.pszEnd = State.psz = NULL;
     829        State.cbAllocated = 0;
     830    }
     831
     832    /*
     833     * Done.
     834     */
     835    *ppszSnapshot = State.pszStart;
     836    if (pcchSnapshot)
     837        *pcchSnapshot = State.psz - State.pszStart;
     838    return rc;
     839}
     840
     841
     842/**
     843 * Get a snapshot of the statistics.
     844 * It's possible to select a subset of the samples.
     845 *
     846 * @returns VBox status. (Basically, it cannot fail.)
    708847 * @param   pVM             The VM handle.
    709848 * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
     
    718857STAMR3DECL(int) STAMR3Snapshot(PVM pVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc)
    719858{
    720     STAMR3SNAPSHOTONE State = { NULL, NULL, NULL, pVM, 0, VINF_SUCCESS, fWithDesc };
    721 
    722     /*
    723      * Write the XML header.
    724      */
    725     /** @todo Make this proper & valid XML. */
    726     stamR3SnapshotPrintf(&State, "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n");
    727 
    728     /*
    729      * Write the content.
    730      */
    731     stamR3SnapshotPrintf(&State, "<Statistics>\n");
    732     STAM_LOCK_RD(pVM);
    733     int rc = stamR3Enum(pVM, pszPat, true /* fUpdateRing0 */, stamR3SnapshotOne, &State);
    734     STAM_UNLOCK_RD(pVM);
    735     stamR3SnapshotPrintf(&State, "</Statistics>\n");
    736 
    737     if (VBOX_SUCCESS(rc))
    738         rc = State.rc;
    739     else
    740     {
    741         RTMemFree(State.pszStart);
    742         State.pszStart = State.pszEnd = State.psz = NULL;
    743         State.cbAllocated = 0;
    744     }
    745 
    746     /*
    747      * Done.
    748      */
    749     *ppszSnapshot = State.pszStart;
    750     if (pcchSnapshot)
    751         *pcchSnapshot = State.psz - State.pszStart;
    752     return rc;
    753 }
    754 
    755 
    756 /**
    757  * stamR3Enum callback employed by STAMR3Snapshot.
     859    return STAMR3SnapshotU(pVM->pUVM, pszPat, ppszSnapshot, pcchSnapshot, fWithDesc);
     860}
     861
     862
     863/**
     864 * stamR3EnumU callback employed by STAMR3Snapshot.
    758865 *
    759866 * @returns VBox status code, but it's interpreted as 0 == success / !0 == failure by enmR3Enum.
     
    9861093 *
    9871094 * @returns VBox status.
     1095 * @param   pUVM        Pointer to the user mode VM structure.
     1096 * @param   pszSnapshot     The snapshot data pointer returned by STAMR3Snapshot().
     1097 *                          NULL is allowed.
     1098 */
     1099STAMR3DECL(int)  STAMR3SnapshotFreeU(PUVM pUVM, char *pszSnapshot)
     1100{
     1101    if (!pszSnapshot)
     1102        RTMemFree(pszSnapshot);
     1103    return VINF_SUCCESS;
     1104}
     1105
     1106
     1107/**
     1108 * Releases a statistics snapshot returned by STAMR3Snapshot().
     1109 *
     1110 * @returns VBox status.
    9881111 * @param   pVM             The VM handle.
    9891112 * @param   pszSnapshot     The snapshot data pointer returned by STAMR3Snapshot().
     
    9921115STAMR3DECL(int)  STAMR3SnapshotFree(PVM pVM, char *pszSnapshot)
    9931116{
    994     if (!pszSnapshot)
    995         RTMemFree(pszSnapshot);
     1117    return STAMR3SnapshotFreeU(pVM->pUVM, pszSnapshot);
     1118}
     1119
     1120
     1121/**
     1122 * Dumps the selected statistics to the log.
     1123 *
     1124 * @returns VBox status.
     1125 * @param   pUVM            Pointer to the user mode VM structure.
     1126 * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
     1127 *                          If NULL all samples are written to the log.
     1128 */
     1129STAMR3DECL(int)  STAMR3DumpU(PUVM pUVM, const char *pszPat)
     1130{
     1131    STAMR3PRINTONEARGS Args;
     1132    Args.pVM = pUVM->pVM;
     1133    Args.pvArg = NULL;
     1134    Args.pfnPrintf = stamR3EnumLogPrintf;
     1135
     1136    STAM_LOCK_RD(pUVM);
     1137    stamR3EnumU(pUVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
     1138    STAM_UNLOCK_RD(pUVM);
    9961139    return VINF_SUCCESS;
    9971140}
     
    10081151STAMR3DECL(int)  STAMR3Dump(PVM pVM, const char *pszPat)
    10091152{
    1010     STAMR3PRINTONEARGS Args;
    1011     Args.pVM = pVM;
    1012     Args.pvArg = NULL;
    1013     Args.pfnPrintf = stamR3EnumLogPrintf;
    1014 
    1015     STAM_LOCK_RD(pVM);
    1016     stamR3Enum(pVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
    1017     STAM_UNLOCK_RD(pVM);
    1018     return VINF_SUCCESS;
     1153    return STAMR3DumpU(pVM->pUVM, pszPat);
    10191154}
    10201155
     
    10411176 *
    10421177 * @returns VBox status.
     1178 * @param   pUVM            Pointer to the user mode VM structure.
     1179 * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
     1180 *                          If NULL all samples are written to the log.
     1181 */
     1182STAMR3DECL(int)  STAMR3DumpToReleaseLogU(PUVM pUVM, const char *pszPat)
     1183{
     1184    STAMR3PRINTONEARGS Args;
     1185    Args.pVM = pUVM->pVM;
     1186    Args.pvArg = NULL;
     1187    Args.pfnPrintf = stamR3EnumRelLogPrintf;
     1188
     1189    STAM_LOCK_RD(pUVM);
     1190    stamR3EnumU(pUVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
     1191    STAM_UNLOCK_RD(pUVM);
     1192    return VINF_SUCCESS;
     1193}
     1194
     1195
     1196/**
     1197 * Dumps the selected statistics to the release log.
     1198 *
     1199 * @returns VBox status.
    10431200 * @param   pVM             The VM handle.
    10441201 * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
     
    10471204STAMR3DECL(int)  STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat)
    10481205{
    1049     STAMR3PRINTONEARGS Args;
    1050     Args.pVM = pVM;
    1051     Args.pvArg = NULL;
    1052     Args.pfnPrintf = stamR3EnumRelLogPrintf;
    1053 
    1054     STAM_LOCK_RD(pVM);
    1055     stamR3Enum(pVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
    1056     STAM_UNLOCK_RD(pVM);
    1057     return VINF_SUCCESS;
     1206    return STAMR3DumpToReleaseLogU(pVM->pUVM, pszPat);
    10581207}
    10591208
     
    10841233 *                          If NULL all samples are reset.
    10851234 */
    1086 STAMR3DECL(int)  STAMR3Print(PVM pVM, const char *pszPat)
     1235STAMR3DECL(int)  STAMR3PrintU(PUVM pUVM, const char *pszPat)
    10871236{
    10881237    STAMR3PRINTONEARGS Args;
    1089     Args.pVM = pVM;
     1238    Args.pVM = pUVM->pVM;
    10901239    Args.pvArg = NULL;
    10911240    Args.pfnPrintf = stamR3EnumPrintf;
    10921241
    1093     STAM_LOCK_RD(pVM);
    1094     stamR3Enum(pVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
    1095     STAM_UNLOCK_RD(pVM);
     1242    STAM_LOCK_RD(pUVM);
     1243    stamR3EnumU(pUVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
     1244    STAM_UNLOCK_RD(pUVM);
    10961245    return VINF_SUCCESS;
     1246}
     1247
     1248
     1249/**
     1250 * Prints the selected statistics to standard out.
     1251 *
     1252 * @returns VBox status.
     1253 * @param   pVM             The VM handle.
     1254 * @param   pszPat          The name matching pattern. See somewhere_where_this_is_described_in_detail.
     1255 *                          If NULL all samples are reset.
     1256 */
     1257STAMR3DECL(int)  STAMR3Print(PVM pVM, const char *pszPat)
     1258{
     1259    return STAMR3PrintU(pVM->pUVM, pszPat);
    10971260}
    10981261
     
    11171280/**
    11181281 * Prints one sample.
    1119  * Callback for stamR3Enum().
     1282 * Callback for stamR3EnumU().
    11201283 *
    11211284 * @returns VINF_SUCCESS
     
    12351398 * @returns Whatever the callback returns.
    12361399 *
     1400 * @param   pUVM        Pointer to the user mode VM structure.
     1401 * @param   pszPat      The pattern to match samples.
     1402 * @param   pfnEnum     The callback function.
     1403 * @param   pvUser      The pvUser argument of the callback function.
     1404 */
     1405STAMR3DECL(int) STAMR3EnumU(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser)
     1406{
     1407    STAMR3ENUMONEARGS Args;
     1408    Args.pVM     = pUVM->pVM;
     1409    Args.pfnEnum = pfnEnum;
     1410    Args.pvUser  = pvUser;
     1411
     1412    STAM_LOCK_RD(pUVM);
     1413    int rc = stamR3EnumU(pUVM, pszPat, true /* fUpdateRing0 */, stamR3EnumOne, &Args);
     1414    STAM_UNLOCK_RD(pUVM);
     1415    return rc;
     1416}
     1417
     1418
     1419/**
     1420 * Enumerate the statistics by the means of a callback function.
     1421 *
     1422 * @returns Whatever the callback returns.
     1423 *
    12371424 * @param   pVM         The VM handle.
    12381425 * @param   pszPat      The pattern to match samples.
     
    12421429STAMR3DECL(int) STAMR3Enum(PVM pVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser)
    12431430{
    1244     STAMR3ENUMONEARGS Args;
    1245     Args.pVM     = pVM;
    1246     Args.pfnEnum = pfnEnum;
    1247     Args.pvUser  = pvUser;
    1248 
    1249     STAM_LOCK_RD(pVM);
    1250     int rc = stamR3Enum(pVM, pszPat, true /* fUpdateRing0 */, stamR3EnumOne, &Args);
    1251     STAM_UNLOCK_RD(pVM);
    1252     return rc;
     1431    return STAMR3EnumU(pVM->pUVM, pszPat, pfnEnum, pvUser);
    12531432}
    12541433
     
    14191598 *
    14201599 * @returns The rc from the callback.
    1421  * @param   pVM             VM handle
     1600 * @param   pUVM        Pointer to the user mode VM structure.
    14221601 * @param   pszPat          Pattern.
    14231602 * @param   fUpdateRing0    Update the ring-0 .
     
    14271606 * @param   pvArg           User parameter for the callback.
    14281607 */
    1429 static int stamR3Enum(PVM pVM, const char *pszPat, bool fUpdateRing0, int (*pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg)
     1608static int stamR3EnumU(PUVM pUVM, const char *pszPat, bool fUpdateRing0, int (*pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg)
    14301609{
    14311610    int rc = VINF_SUCCESS;
     
    14371616    {
    14381617        if (fUpdateRing0)
    1439             stamR3Ring0StatsUpdate(pVM, "*");
    1440 
    1441         PSTAMDESC   pCur = pVM->stam.s.pHead;
     1618            stamR3Ring0StatsUpdateU(pUVM, "*");
     1619
     1620        PSTAMDESC   pCur = pUVM->stam.s.pHead;
    14421621        while (pCur)
    14431622        {
     
    14571636    {
    14581637        if (fUpdateRing0)
    1459             stamR3Ring0StatsUpdate(pVM, pszPat);
     1638            stamR3Ring0StatsUpdateU(pUVM, pszPat);
    14601639
    14611640        /** @todo This needs to be optimized since the GUI is using this path for the VM info dialog.
    14621641         * Note that it's doing exact matching. Organizing the samples in a tree would speed up thing
    14631642         * no end (at least for debug and profile builds). */
    1464         for (PSTAMDESC pCur = pVM->stam.s.pHead; pCur; pCur = pCur->pNext)
     1643        for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext)
    14651644            if (stamR3Match(pszPat, pCur->pszName))
    14661645            {
     
    14891668         */
    14901669        if (fUpdateRing0)
    1491             stamR3Ring0StatsUpdateMulti(pVM, papszExpressions, cExpressions);
     1670            stamR3Ring0StatsUpdateMultiU(pUVM, papszExpressions, cExpressions);
    14921671
    14931672        unsigned iExpression = 0;
    1494         for (PSTAMDESC pCur = pVM->stam.s.pHead; pCur; pCur = pCur->pNext)
     1673        for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext)
    14951674            if (stamR3MultiMatch(papszExpressions, cExpressions, &iExpression, pCur->pszName))
    14961675            {
     
    15111690 * Registers the ring-0 statistics.
    15121691 *
    1513  * @param   pVM         Pointer to the shared VM structure.
    1514  */
    1515 static void stamR3Ring0StatsRegister(PVM pVM)
     1692 * @param   pUVM        Pointer to the user mode VM structure.
     1693 */
     1694static void stamR3Ring0StatsRegisterU(PUVM pUVM)
    15161695{
    15171696    /* GVMM */
    15181697    for (unsigned i = 0; i < RT_ELEMENTS(g_aGVMMStats); i++)
    1519         stamR3Register(pVM, (uint8_t *)&pVM->stam.s.GVMMStats + g_aGVMMStats[i].offVar, NULL, NULL,
    1520                        g_aGVMMStats[i].enmType, STAMVISIBILITY_ALWAYS, g_aGVMMStats[i].pszName,
    1521                        g_aGVMMStats[i].enmUnit, g_aGVMMStats[i].pszDesc);
     1698        stamR3RegisterU(pUVM, (uint8_t *)&pUVM->stam.s.GVMMStats + g_aGVMMStats[i].offVar, NULL, NULL,
     1699                        g_aGVMMStats[i].enmType, STAMVISIBILITY_ALWAYS, g_aGVMMStats[i].pszName,
     1700                        g_aGVMMStats[i].enmUnit, g_aGVMMStats[i].pszDesc);
    15221701}
    15231702
     
    15261705 * Updates the ring-0 statistics (the copy).
    15271706 *
    1528  * @param   pVM         Pointer to the shared VM structure.
     1707 * @param   pUVM        Pointer to the user mode VM structure.
    15291708 * @param   pszPat      The pattern.
    15301709 */
    1531 static void stamR3Ring0StatsUpdate(PVM pVM, const char *pszPat)
    1532 {
    1533     stamR3Ring0StatsUpdateMulti(pVM, &pszPat, 1);
     1710static void stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat)
     1711{
     1712    stamR3Ring0StatsUpdateMultiU(pUVM, &pszPat, 1);
    15341713}
    15351714
     
    15411720 * must be copied when needed.
    15421721 *
    1543  * @param   pVM         Pointer to the shared VM structure.
     1722 * @param   pUVM        Pointer to the user mode VM structure.
    15441723 * @param   pszPat      The pattern (for knowing when to skip).
    15451724 */
    1546 static void stamR3Ring0StatsUpdateMulti(PVM pVM, const char * const *papszExpressions, unsigned cExpressions)
    1547 {
    1548     if (!pVM->pSession)
     1725static void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions)
     1726{
     1727    PVM pVM = pUVM->pVM;
     1728    if (!pVM || !pVM->pSession)
    15491729        return;
    15501730
     
    15651745        int rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_QUERY_STATISTICS, 0, &Req.Hdr);
    15661746        if (RT_SUCCESS(rc))
    1567             pVM->stam.s.GVMMStats = Req.Stats;
     1747            pUVM->stam.s.GVMMStats = Req.Stats;
    15681748    }
    15691749}
     
    16221802    if (!pVM)
    16231803        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires VM to be selected.\n");
    1624     if (!pVM->stam.s.pHead)
     1804    PUVM pUVM = pVM->pUVM;
     1805    if (!pUVM->stam.s.pHead)
    16251806        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Sorry, no statistics present.\n");
    16261807
     
    16331814    Args.pfnPrintf = stamR3EnumDbgfPrintf;
    16341815
    1635     STAM_LOCK_RD(pVM);
    1636     int rc = stamR3Enum(pVM, cArgs ? paArgs[0].u.pszString : NULL, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
    1637     STAM_UNLOCK_RD(pVM);
     1816    STAM_LOCK_RD(pUVM);
     1817    int rc = stamR3EnumU(pUVM, cArgs ? paArgs[0].u.pszString : NULL, true /* fUpdateRing0 */, stamR3PrintOne, &Args);
     1818    STAM_UNLOCK_RD(pUVM);
    16381819
    16391820    return rc;
     
    16771858    if (!pVM)
    16781859        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "error: The command requires VM to be selected.\n");
    1679     if (!pVM->stam.s.pHead)
     1860    PUVM pUVM = pVM->pUVM;
     1861    if (!pUVM->stam.s.pHead)
    16801862        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Sorry, no statistics present.\n");
    16811863
     
    16831865     * Execute reset.
    16841866     */
    1685     int rc = STAMR3Reset(pVM, cArgs ? paArgs[0].u.pszString : NULL);
     1867    int rc = STAMR3ResetU(pUVM, cArgs ? paArgs[0].u.pszString : NULL);
    16861868    if (VBOX_SUCCESS(rc))
    16871869        return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "info: Statistics reset.\n");
  • trunk/src/VBox/VMM/STAMInternal.h

    r5999 r6796  
    9595
    9696/**
    97  * Converts a STAM pointer into a VM pointer.
    98  * @returns Pointer to the VM structure the STAM is part of.
    99  * @param   pSTAM   Pointer to STAM instance data.
     97 * STAM data kept in the UVM.
    10098 */
    101 #define STAM2VM(pSTAM)  ( (PVM)((char*)pSTAM - pSTAM->offVM) )
    102 
    103 
    104 /**
    105  * The stam data in the VM.
    106  */
    107 struct STAM
     99typedef struct STAMUSERPERVM
    108100{
    109     /** Offset to the VM structure.
    110      * See STAM2VM(). */
    111     RTINT                   offVM;
    112     /** Alignment padding. */
    113     RTUINT                  uPadding;
    114101    /** Pointer to the first sample. */
    115102    R3PTRTYPE(PSTAMDESC)    pHead;
     
    119106    /** The copy of the GVMM statistics. */
    120107    GVMMSTATS               GVMMStats;
    121 };
     108} STAMUSERPERVM;
     109/** Pointer to the STAM data kept in the UVM. */
     110typedef STAMUSERPERVM *PSTAMUSERPERVM;
     111
    122112
    123113/** Locks the sample descriptors for reading. */
    124 #define STAM_LOCK_RD(pVM)       do { int rcSem = RTSemRWRequestRead(pVM->stam.s.RWSem, RT_INDEFINITE_WAIT);  AssertRC(rcSem); } while (0)
     114#define STAM_LOCK_RD(pUVM)      do { int rcSem = RTSemRWRequestRead(pUVM->stam.s.RWSem, RT_INDEFINITE_WAIT);  AssertRC(rcSem); } while (0)
    125115/** Locks the sample descriptors for writing. */
    126 #define STAM_LOCK_WR(pVM)       do { int rcSem = RTSemRWRequestWrite(pVM->stam.s.RWSem, RT_INDEFINITE_WAIT); AssertRC(rcSem); } while (0)
     116#define STAM_LOCK_WR(pUVM)      do { int rcSem = RTSemRWRequestWrite(pUVM->stam.s.RWSem, RT_INDEFINITE_WAIT); AssertRC(rcSem); } while (0)
    127117/** UnLocks the sample descriptors after reading. */
    128 #define STAM_UNLOCK_RD(pVM)     do { int rcSem = RTSemRWReleaseRead(pVM->stam.s.RWSem);  AssertRC(rcSem); } while (0)
     118#define STAM_UNLOCK_RD(pUVM)    do { int rcSem = RTSemRWReleaseRead(pUVM->stam.s.RWSem);  AssertRC(rcSem); } while (0)
    129119/** UnLocks the sample descriptors after writing. */
    130 #define STAM_UNLOCK_WR(pVM)     do { int rcSem = RTSemRWReleaseWrite(pVM->stam.s.RWSem); AssertRC(rcSem); } while (0)
     120#define STAM_UNLOCK_WR(pUVM)    do { int rcSem = RTSemRWReleaseWrite(pUVM->stam.s.RWSem); AssertRC(rcSem); } while (0)
    131121
    132122/** @} */
  • trunk/src/VBox/VMM/VM.cpp

    r6633 r6796  
    4343#include "VMInternal.h"
    4444#include <VBox/vm.h>
     45#include <VBox/uvm.h>
    4546
    4647#include <VBox/sup.h>
     
    8283*******************************************************************************/
    8384/** Pointer to the list of VMs. */
    84 static PVM          g_pVMsHead;
     85static PUVM         g_pUVMsHead = NULL;
    8586
    8687/** Pointer to the list of at VM destruction callbacks. */
    87 static PVMATDTOR    g_pVMAtDtorHead;
     88static PVMATDTOR    g_pVMAtDtorHead = NULL;
    8889/** Lock the g_pVMAtDtorHead list. */
    8990#define VM_ATDTOR_LOCK() do { } while (0)
     
    9192#define VM_ATDTOR_UNLOCK() do { } while (0)
    9293
     94
    9395/*******************************************************************************
    9496*   Internal Functions                                                         *
    9597*******************************************************************************/
    96 static int  vmR3Create(PVM pVM, PFNVMATERROR pfnVMAtError, void *pvUserVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM);
    97 static void vmR3CallVMAtError(PFNVMATERROR pfnVMAtError, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, ...);
    98 static int  vmR3InitRing3(PVM pVM);
     98static int  vmR3CreateUVM(PUVM *ppUVM);
     99static int  vmR3CreateU(PUVM pUVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM);
     100static int  vmR3InitRing3(PVM pVM, PUVM pUVM);
    99101static int  vmR3InitRing0(PVM pVM);
    100102static int  vmR3InitGC(PVM pVM);
     
    106108static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser);
    107109static DECLCALLBACK(int) vmR3PowerOff(PVM pVM);
     110static void vmR3DestroyUVM(PUVM pUVM);
    108111static void vmR3AtDtor(PVM pVM);
    109 static int  vmR3AtReset(PVM pVM);
     112static int  vmR3AtResetU(PUVM pUVM);
    110113static DECLCALLBACK(int) vmR3Reset(PVM pVM);
    111 static DECLCALLBACK(int) vmR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser);
    112 static DECLCALLBACK(int) vmR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser);
    113 static DECLCALLBACK(int) vmR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
    114 static DECLCALLBACK(int) vmR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser);
    115 static DECLCALLBACK(int) vmR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
    116 static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
     114static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
     115static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser);
     116static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
     117static DECLCALLBACK(int) vmR3AtErrorDeregisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser);
     118static int               vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...);
     119static DECLCALLBACK(int) vmR3AtRuntimeErrorRegisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
     120static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser);
    117121
    118122
     
    127131     * Only once.
    128132     */
    129     static bool fDone = false;
    130     if (fDone)
     133    static bool volatile s_fDone = false;
     134    if (s_fDone)
    131135        return VINF_SUCCESS;
    132136
     
    134138     * We're done.
    135139     */
    136     fDone = true;
     140    s_fDone = true;
    137141    return VINF_SUCCESS;
    138142}
     
    175179
    176180    /*
    177      * Init support library and load the VMMR0.r0 module.
    178      */
    179     PSUPDRVSESSION pSession = 0;
    180     int rc = SUPInit(&pSession, 0);
    181     if (VBOX_SUCCESS(rc))
    182     {
    183         /** @todo This is isn't very nice, it would be preferrable to move the loader bits
    184          * out of the VM structure and into a ring-3 only thing. There's a big deal of the
    185          * error path that we now won't unload the VMMR0.r0 module in. This isn't such a
    186          * big deal right now, but I'll have to get back to this later. UVM (bird) */
    187         void *pvVMMR0Opaque;
    188         rc = PDMR3LdrLoadVMMR0(&pvVMMR0Opaque);
     181     * Create the UVM so we can register the at-error callback
     182     * and consoliate a bit of cleanup code.
     183     */
     184    PUVM pUVM;
     185    int rc = vmR3CreateUVM(&pUVM);
     186    if (RT_FAILURE(rc))
     187        return rc;
     188    if (pfnVMAtError)
     189        rc = VMR3AtErrorRegisterU(pUVM, pfnVMAtError, pvUserVM);
     190    if (RT_SUCCESS(rc))
     191    {
     192        /*
     193         * Initialize the support library creating the session for this v
     194         */
     195        rc = SUPInit(&pUVM->vm.s.pSession, 0);
    189196        if (RT_SUCCESS(rc))
    190197        {
    191198            /*
    192              * Request GVMM to create a new VM for us.
     199             * Call vmR3CreateU in the EMT thread and wait for it to finish.
    193200             */
    194             GVMMCREATEVMREQ CreateVMReq;
    195             CreateVMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
    196             CreateVMReq.Hdr.cbReq = sizeof(CreateVMReq);
    197             CreateVMReq.pSession = pSession;
    198             CreateVMReq.pVMR0 = NIL_RTR0PTR;
    199             CreateVMReq.pVMR3 = NULL;
    200             rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
     201            PVMREQ pReq;
     202            rc = VMR3ReqCallU(pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3CreateU,
     203                              3, pUVM, pfnCFGMConstructor, pvUserCFGM);
    201204            if (RT_SUCCESS(rc))
    202205            {
    203                 PVM pVM = CreateVMReq.pVMR3;
    204                 AssertRelease(VALID_PTR(pVM));
    205                 Log(("VMR3Create: Created pVM=%p pVMR0=%p\n", pVM, pVM->pVMR0));
    206                 PDMR3LdrLoadVMMR0Part2(pVM, pvVMMR0Opaque);
    207 
    208                 /*
    209                  * Do basic init of the VM structure.
    210                  */
    211                 pVM->vm.s.offVM = RT_OFFSETOF(VM, vm.s);
    212                 pVM->vm.s.ppAtResetNext = &pVM->vm.s.pAtReset;
    213                 pVM->vm.s.ppAtStateNext = &pVM->vm.s.pAtState;
    214                 pVM->vm.s.ppAtErrorNext = &pVM->vm.s.pAtError;
    215                 pVM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;
    216                 pVM->vm.s.enmHaltMethod = VMHALTMETHOD_1;
    217                 rc = RTSemEventCreate(&pVM->vm.s.EventSemWait);
     206                rc = pReq->iStatus;
     207                VMR3ReqFree(pReq);
    218208                if (RT_SUCCESS(rc))
    219209                {
    220210                    /*
    221                      * Initialize STAM.
     211                     * Success!
    222212                     */
    223                     rc = STAMR3Init(pVM);
    224                     if (VBOX_SUCCESS(rc))
    225                     {
    226                         /*
    227                          * Create the EMT thread, it will start up and wait for requests to process.
    228                          */
    229                         VMEMULATIONTHREADARGS Args;
    230                         Args.pVM = pVM;
    231                         rc = RTThreadCreate(&pVM->ThreadEMT, vmR3EmulationThread, &Args, _1M,
    232                                             RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "EMT");
    233                         if (VBOX_SUCCESS(rc))
    234                         {
    235                             /*
    236                              * Issue a VM Create request and wait for it to complete.
    237                              */
    238                             PVMREQ pReq;
    239                             rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3Create, 5,
    240                                              pVM, pfnVMAtError, pvUserVM, pfnCFGMConstructor, pvUserCFGM);
    241                             if (VBOX_SUCCESS(rc))
    242                             {
    243                                 rc = pReq->iStatus;
    244                                 VMR3ReqFree(pReq);
    245                                 if (VBOX_SUCCESS(rc))
    246                                 {
    247                                     *ppVM = pVM;
    248                                     LogFlow(("VMR3Create: returns VINF_SUCCESS *ppVM=%p\n", pVM));
    249                                     return VINF_SUCCESS;
    250                                 }
    251 
    252                                 NoDmik(AssertMsgFailed(("vmR3Create failed rc=%Vrc\n", rc)));
    253                             }
    254                             else
    255                                 AssertMsgFailed(("VMR3ReqCall failed rc=%Vrc\n", rc));
    256 
    257                             /*
    258                              * An error occurred during VM creation. Set the error message directly
    259                              * using the initial callback, as the callback list doesn't exist yet.
    260                              */
    261                             const char *pszError = NULL;
    262                             switch (rc)
    263                             {
    264                                 case VERR_VMX_IN_VMX_ROOT_MODE:
    265 #ifdef RT_OS_LINUX
    266                                     pszError = N_("VirtualBox can't operate in VMX root mode. "
    267                                                   "Please disable the KVM kernel extension, recompile your kernel and reboot");
    268 #else
    269                                     pszError = N_("VirtualBox can't operate in VMX root mode");
    270 #endif
    271                                     break;
    272                                 default:
    273                                     /* XXX check if there was already an error message set! */
    274                                     pszError = N_("Unknown error creating VM");
    275                                     NoDmik(AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc)));
    276                             }
    277                             if (pszError)
    278                                 vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, pszError, rc);
    279 
    280                             /* Forcefully terminate the emulation thread. */
    281                             VM_FF_SET(pVM, VM_FF_TERMINATE);
    282                             VMR3NotifyFF(pVM, false);
    283                             RTThreadWait(pVM->ThreadEMT, 1000, NULL);
    284                         }
    285 
    286                         int rc2 = STAMR3Term(pVM);
    287                         AssertRC(rc2);
    288                     }
    289 
    290                     RTSemEventDestroy(pVM->vm.s.EventSemWait);
     213                    *ppVM = pUVM->pVM;
     214                    LogFlow(("VMR3Create: returns VINF_SUCCESS *ppVM=%p\n", *ppVM));
     215                    return VINF_SUCCESS;
    291216                }
    292                 /* cleanup the heap. */
    293                 int rc2 = MMR3Term(pVM);
    294                 AssertRC(rc2);
    295 
    296                 /* Tell GVMM that it can destroy the VM now. */
    297                 rc2 = SUPCallVMMR0Ex(CreateVMReq.pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
    298                 AssertRC(rc2);
    299217            }
    300218            else
     219                AssertMsgFailed(("VMR3ReqCall failed rc=%Vrc\n", rc));
     220
     221            /*
     222             * An error occurred during VM creation. Set the error message directly
     223             * using the initial callback, as the callback list doesn't exist yet.
     224             */
     225            const char *pszError = NULL;
     226            switch (rc)
    301227            {
    302                 PDMR3LdrLoadVMMR0Part2(NULL, pvVMMR0Opaque);
    303                 vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, N_("VM creation failed"));
    304                 AssertMsgFailed(("GMMR0CreateVMReq returned %Rrc\n", rc));
     228                case VERR_VMX_IN_VMX_ROOT_MODE:
     229#ifdef RT_OS_LINUX
     230                    pszError = N_("VirtualBox can't operate in VMX root mode. "
     231                                  "Please disable the KVM kernel extension, recompile your kernel and reboot");
     232#else
     233                    pszError = N_("VirtualBox can't operate in VMX root mode");
     234#endif
     235                    break;
     236
     237                default:
     238                    pszError = N_("Unknown error creating VM");
     239                    NoDmik(AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc)));
     240                    break;
    305241            }
     242            vmR3SetErrorU(pUVM, rc, RT_SRC_POS, pszError, rc);
    306243        }
    307244        else
    308245        {
    309             vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, N_("Failed to load VMMR0.r0"));
    310             AssertMsgFailed(("PDMR3LdrLoadVMMR0 returned %Rrc\n", rc));
     246            /*
     247             * An error occurred at support library initialization time (before the
     248             * VM could be created). Set the error message directly using the
     249             * initial callback, as the callback list doesn't exist yet.
     250             */
     251            const char *pszError;
     252            switch (rc)
     253            {
     254                case VERR_VM_DRIVER_LOAD_ERROR:
     255#ifdef RT_OS_LINUX
     256                    pszError = N_("VirtualBox kernel driver not loaded. The vboxdrv kernel module "
     257                                  "was either not loaded or /dev/vboxdrv is not set up properly. "
     258                                  "Re-setup the kernel module by executing "
     259                                  "'/etc/init.d/vboxdrv setup' as root");
     260#else
     261                    pszError = N_("VirtualBox kernel driver not loaded");
     262#endif
     263                    break;
     264                case VERR_VM_DRIVER_OPEN_ERROR:
     265                    pszError = N_("VirtualBox kernel driver cannot be opened");
     266                    break;
     267                case VERR_VM_DRIVER_NOT_ACCESSIBLE:
     268#ifdef RT_OS_LINUX
     269                    pszError = N_("The VirtualBox kernel driver is not accessible to the current "
     270                                  "user. Make sure that the user has write permissions for "
     271                                  "/dev/vboxdrv by adding them to the vboxusers groups. You "
     272                                  "will need to logout for the change to take effect.");
     273#else
     274                    pszError = N_("VirtualBox kernel driver not accessible, permission problem");
     275#endif
     276                    break;
     277                case VERR_VM_DRIVER_NOT_INSTALLED:
     278#ifdef RT_OS_LINUX
     279                    pszError = N_("VirtualBox kernel driver not installed. The vboxdrv kernel module "
     280                                  "was either not loaded or /dev/vboxdrv was not created for some "
     281                                  "reason. Re-setup the kernel module by executing "
     282                                  "'/etc/init.d/vboxdrv setup' as root");
     283#else
     284                    pszError = N_("VirtualBox kernel driver not installed");
     285#endif
     286                    break;
     287                case VERR_NO_MEMORY:
     288                    pszError = N_("VirtualBox support library out of memory");
     289                    break;
     290                case VERR_VERSION_MISMATCH:
     291                case VERR_VM_DRIVER_VERSION_MISMATCH:
     292                    pszError = N_("The VirtualBox support driver which is running is from a different "
     293                                  "version of VirtualBox.  You can correct this by stopping all "
     294                                  "running instances of VirtualBox and reinstalling the software.");
     295                    break;
     296                default:
     297                    pszError = N_("Unknown error initializing kernel driver");
     298                    AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc));
     299            }
     300            vmR3SetErrorU(pUVM, rc, RT_SRC_POS, pszError, rc);
    311301        }
    312 
    313         /* terminate SUPLib */
    314         int rc2 = SUPTerm(false);
    315         AssertRC(rc2);
    316     }
    317     else
    318     {
    319         /*
    320          * An error occurred at support library initialization time (before the
    321          * VM could be created). Set the error message directly using the
    322          * initial callback, as the callback list doesn't exist yet.
    323          */
    324         const char *pszError;
    325         switch (rc)
    326         {
    327             case VERR_VM_DRIVER_LOAD_ERROR:
    328 #ifdef RT_OS_LINUX
    329                 pszError = N_("VirtualBox kernel driver not loaded. The vboxdrv kernel module "
    330                               "was either not loaded or /dev/vboxdrv is not set up properly. "
    331                               "Re-setup the kernel module by executing "
    332                               "'/etc/init.d/vboxdrv setup' as root");
    333 #else
    334                 pszError = N_("VirtualBox kernel driver not loaded");
    335 #endif
    336                 break;
    337             case VERR_VM_DRIVER_OPEN_ERROR:
    338                 pszError = N_("VirtualBox kernel driver cannot be opened");
    339                 break;
    340             case VERR_VM_DRIVER_NOT_ACCESSIBLE:
    341 #ifdef RT_OS_LINUX
    342                 pszError = N_("The VirtualBox kernel driver is not accessible to the current "
    343                               "user. Make sure that the user has write permissions for "
    344                               "/dev/vboxdrv by adding them to the vboxusers groups. You "
    345                               "will need to logout for the change to take effect.");
    346 #else
    347                 pszError = N_("VirtualBox kernel driver not accessible, permission problem");
    348 #endif
    349                 break;
    350             case VERR_VM_DRIVER_NOT_INSTALLED:
    351 #ifdef RT_OS_LINUX
    352                 pszError = N_("VirtualBox kernel driver not installed. The vboxdrv kernel module "
    353                               "was either not loaded or /dev/vboxdrv was not created for some "
    354                               "reason. Re-setup the kernel module by executing "
    355                               "'/etc/init.d/vboxdrv setup' as root");
    356 #else
    357                 pszError = N_("VirtualBox kernel driver not installed");
    358 #endif
    359                 break;
    360             case VERR_NO_MEMORY:
    361                 pszError = N_("VirtualBox support library out of memory");
    362                 break;
    363             case VERR_VERSION_MISMATCH:
    364             case VERR_VM_DRIVER_VERSION_MISMATCH:
    365                 pszError = N_("The VirtualBox support driver which is running is from a different "
    366                               "version of VirtualBox.  You can correct this by stopping all "
    367                               "running instances of VirtualBox and reinstalling the software.");
    368                 break;
    369             default:
    370                 pszError = N_("Unknown error initializing kernel driver");
    371                 AssertMsgFailed(("Add error message for rc=%d (%Vrc)\n", rc, rc));
    372         }
    373         vmR3CallVMAtError(pfnVMAtError, pvUserVM, rc, RT_SRC_POS, pszError, rc);
    374     }
    375 
     302    }
     303
     304    /* cleanup */
     305    vmR3DestroyUVM(pUVM);
    376306    LogFlow(("VMR3Create: returns %Vrc\n", rc));
    377307    return rc;
     
    380310
    381311/**
    382  * Wrapper for getting a correct va_list.
    383  */
    384 static void vmR3CallVMAtError(PFNVMATERROR pfnVMAtError, void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszError, ...)
    385 {
    386     if (!pfnVMAtError)
    387         return;
    388     va_list va;
    389     va_start(va, pszError);
    390     pfnVMAtError(NULL, pvUser, rc, RT_SRC_POS_ARGS, pszError, va);
    391     va_end(va);
    392 }
    393 
    394 
    395 /**
    396  * Initializes the VM.
    397  */
    398 static int vmR3Create(PVM pVM, PFNVMATERROR pfnVMAtError, void *pvUserVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM)
     312 * Creates the UVM.
     313 *
     314 * This will not initialize the support library even if vmR3DestroyUVM
     315 * will terminate that.
     316 *
     317 * @returns VBox status code.
     318 * @param   ppUVM   Where to store the UVM pointer.
     319 */
     320static int vmR3CreateUVM(PUVM *ppUVM)
     321{
     322    /*
     323     * Create the UVM, initialize the fundamental stuff (VM+MMR3Heap+STAM)
     324     * and start the emulation thread (EMT).
     325     */
     326    PUVM pUVM = (PUVM)RTMemAllocZ(sizeof(*pUVM));
     327    AssertReturn(pUVM, VERR_NO_MEMORY);
     328    pUVM->u32Magic = UVM_MAGIC;
     329
     330    AssertCompile(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding));
     331    AssertRelease(sizeof(pUVM->vm.s) <= sizeof(pUVM->vm.padding));
     332
     333    pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset;
     334    pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState;
     335    pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError;
     336    pUVM->vm.s.ppAtRuntimeErrorNext = &pUVM->vm.s.pAtRuntimeError;
     337    pUVM->vm.s.enmHaltMethod = VMHALTMETHOD_BOOTSTRAP;
     338    int rc = RTSemEventCreate(&pUVM->vm.s.EventSemWait);
     339    if (RT_SUCCESS(rc))
     340    {
     341        rc = STAMR3InitUVM(pUVM);
     342        if (RT_SUCCESS(rc))
     343        {
     344            rc = MMR3InitUVM(pUVM);
     345            if (RT_SUCCESS(rc))
     346            {
     347                rc = PDMR3InitUVM(pUVM);
     348                if (RT_SUCCESS(rc))
     349                {
     350
     351                    rc = RTThreadCreate(&pUVM->vm.s.ThreadEMT, vmR3EmulationThread, pUVM, _1M,
     352                                        RTTHREADTYPE_EMULATION, RTTHREADFLAGS_WAITABLE, "EMT");
     353                    if (RT_SUCCESS(rc))
     354                    {
     355                        *ppUVM = pUVM;
     356                        return VINF_SUCCESS;
     357                    }
     358
     359                    /* bail out. */
     360                    PDMR3TermUVM(pUVM);
     361                }
     362                MMR3TermUVM(pUVM);
     363            }
     364            STAMR3TermUVM(pUVM);
     365        }
     366        RTSemEventDestroy(pUVM->vm.s.EventSemWait);
     367    }
     368    RTMemFree(pUVM);
     369    return rc;
     370}
     371
     372
     373/**
     374 * Creates and initializes the VM.
     375 *
     376 * @thread EMT
     377 */
     378static int vmR3CreateU(PUVM pUVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM)
    399379{
    400380    int rc = VINF_SUCCESS;
    401381
    402     /* Register error callback if specified. */
    403     if (pfnVMAtError)
    404         rc = VMR3AtErrorRegister(pVM, pfnVMAtError, pvUserVM);
    405     if (VBOX_SUCCESS(rc))
    406     {
     382    /*
     383     * Load the VMMR0.r0 module so that we can call GVMMR0CreateVM.
     384     */
     385    rc = PDMR3LdrLoadVMMR0U(pUVM);
     386    if (RT_FAILURE(rc))
     387        return vmR3SetErrorU(pUVM, rc, RT_SRC_POS, N_("Failed to load VMMR0.r0"));
     388
     389    /*
     390     * Request GVMM to create a new VM for us.
     391     */
     392    GVMMCREATEVMREQ CreateVMReq;
     393    CreateVMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC;
     394    CreateVMReq.Hdr.cbReq = sizeof(CreateVMReq);
     395    CreateVMReq.pSession = pUVM->vm.s.pSession;
     396    CreateVMReq.pVMR0 = NIL_RTR0PTR;
     397    CreateVMReq.pVMR3 = NULL;
     398    rc = SUPCallVMMR0Ex(NIL_RTR0PTR, VMMR0_DO_GVMM_CREATE_VM, 0, &CreateVMReq.Hdr);
     399    if (RT_SUCCESS(rc))
     400    {
     401        PVM pVM = pUVM->pVM = CreateVMReq.pVMR3;
     402        AssertRelease(VALID_PTR(pVM));
     403        AssertRelease(pVM->pVMR0 == CreateVMReq.pVMR0);
     404        AssertRelease(pVM->pSession == pUVM->vm.s.pSession);
     405
     406        Log(("VMR3Create: Created pUVM=%p pVM=%p pVMR0=%p hSelf=%#x \n", pUVM, pVM, pVM->pVMR0, pVM->hSelf));
     407
     408        /*
     409         * Initialize the VM structure and our internal data (VMINT).
     410         */
     411        pVM->pUVM = pUVM;
     412        pVM->ThreadEMT = pUVM->vm.s.ThreadEMT;
     413        pVM->NativeThreadEMT = pUVM->vm.s.NativeThreadEMT;
     414
     415        pVM->vm.s.offVM = RT_OFFSETOF(VM, vm.s);
     416
    407417        /*
    408418         * Init the configuration.
     
    424434
    425435            /*
    426              * Check if the required minimum of resources are available.
     436             * Init the Ring-3 components and do a round of relocations with 0 delta.
    427437             */
    428             /** @todo Check if the required minimum of resources are available. */
     438            rc = vmR3InitRing3(pVM, pUVM);
    429439            if (VBOX_SUCCESS(rc))
    430440            {
     441                VMR3Relocate(pVM, 0);
     442                LogFlow(("Ring-3 init succeeded\n"));
     443
    431444                /*
    432                  * Init the Ring-3 components and do a round of relocations with 0 delta.
     445                 * Init the Ring-0 components.
    433446                 */
    434                 rc = vmR3InitRing3(pVM);
     447                rc = vmR3InitRing0(pVM);
    435448                if (VBOX_SUCCESS(rc))
    436449                {
     450                    /* Relocate again, because some switcher fixups depends on R0 init results. */
    437451                    VMR3Relocate(pVM, 0);
    438                     LogFlow(("Ring-3 init succeeded\n"));
    439 
     452
     453#ifdef VBOX_WITH_DEBUGGER
    440454                    /*
    441                      * Init the Ring-0 components.
     455                     * Init the tcp debugger console if we're building
     456                     * with debugger support.
    442457                     */
    443                     rc = vmR3InitRing0(pVM);
    444                     if (VBOX_SUCCESS(rc))
     458                    void *pvUser = NULL;
     459                    rc = DBGCTcpCreate(pVM, &pvUser);
     460                    if (    VBOX_SUCCESS(rc)
     461                        ||  rc == VERR_NET_ADDRESS_IN_USE)
    445462                    {
    446                         /* Relocate again, because some switcher fixups depends on R0 init results. */
    447                         VMR3Relocate(pVM, 0);
    448 
    449 #ifdef VBOX_WITH_DEBUGGER
     463                        pUVM->vm.s.pvDBGC = pvUser;
     464#endif
    450465                        /*
    451                          * Init the tcp debugger console if we're building
    452                          * with debugger support.
     466                         * Init the Guest Context components.
    453467                         */
    454                         void *pvUser = NULL;
    455                         rc = DBGCTcpCreate(pVM, &pvUser);
    456                         if (    VBOX_SUCCESS(rc)
    457                             ||  rc == VERR_NET_ADDRESS_IN_USE)
     468                        rc = vmR3InitGC(pVM);
     469                        if (VBOX_SUCCESS(rc))
    458470                        {
    459                             pVM->vm.s.pvDBGC = pvUser;
    460 #endif
    461471                            /*
    462                              * Init the Guest Context components.
     472                             * Now we can safely set the VM halt method to default.
    463473                             */
    464                             rc = vmR3InitGC(pVM);
    465                             if (VBOX_SUCCESS(rc))
     474                            rc = vmR3SetHaltMethodU(pUVM, VMHALTMETHOD_DEFAULT);
     475                            if (RT_SUCCESS(rc))
    466476                            {
    467477                                /*
    468                                  * Now we can safely set the VM halt method to default.
     478                                 * Set the state and link into the global list.
    469479                                 */
    470                                 rc = vmR3SetHaltMethod(pVM, VMHALTMETHOD_DEFAULT);
    471                                 if (RT_SUCCESS(rc))
    472                                 {
    473                                     /*
    474                                      * Set the state and link into the global list.
    475                                      */
    476                                     vmR3SetState(pVM, VMSTATE_CREATED);
    477                                     pVM->pNext = g_pVMsHead;
    478                                     g_pVMsHead = pVM;
    479                                     return VINF_SUCCESS;
    480                                 }
     480                                vmR3SetState(pVM, VMSTATE_CREATED);
     481                                pUVM->pNext = g_pUVMsHead;
     482                                g_pUVMsHead = pUVM;
     483                                return VINF_SUCCESS;
    481484                            }
     485                        }
    482486#ifdef VBOX_WITH_DEBUGGER
    483                             DBGCTcpTerminate(pVM, pVM->vm.s.pvDBGC);
    484                             pVM->vm.s.pvDBGC = NULL;
    485                         }
     487                        DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC);
     488                        pUVM->vm.s.pvDBGC = NULL;
     489                    }
    486490#endif
    487                         //..
    488                     }
    489                     vmR3Destroy(pVM);
     491                    //..
    490492                }
    491                 //..
     493                vmR3Destroy(pVM);
    492494            }
     495            //..
    493496
    494497            /* Clean CFGM. */
     
    496499            AssertRC(rc2);
    497500        }
    498         //..
    499     }
    500 
    501     LogFlow(("vmR3Create: returns %Vrc\n", rc));
     501
     502        /* Tell GVMM that it can destroy the VM now. */
     503        int rc2 = SUPCallVMMR0Ex(CreateVMReq.pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
     504        AssertRC(rc2);
     505    }
     506    else
     507        vmR3SetErrorU(pUVM, rc, RT_SRC_POS, N_("VM creation failed (GVMM)"));
     508
     509    LogFlow(("vmR3Create: returns %Rrc\n", rc));
    502510    return rc;
    503511}
     
    508516 * Initializes all R3 components of the VM
    509517 */
    510 static int vmR3InitRing3(PVM pVM)
     518static int vmR3InitRing3(PVM pVM, PUVM pUVM)
    511519{
    512520    int rc;
     
    521529        STAM_REG(pVM, &pVM->StatSwitcherToGC,       STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToGC",    STAMUNIT_TICKS_PER_CALL,    "Profiling switching to GC.");
    522530        STAM_REG(pVM, &pVM->StatSwitcherToHC,       STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToHC",    STAMUNIT_TICKS_PER_CALL,    "Profiling switching to HC.");
    523 
    524         STAM_REL_REG(pVM, &pVM->vm.s.StatHaltYield, STAMTYPE_PROFILE,     "/PROF/VM/Halt/Yield",    STAMUNIT_TICKS_PER_CALL,    "Profiling halted state yielding.");
    525         STAM_REL_REG(pVM, &pVM->vm.s.StatHaltBlock, STAMTYPE_PROFILE,     "/PROF/VM/Halt/Block",    STAMUNIT_TICKS_PER_CALL,    "Profiling halted state blocking.");
    526         STAM_REL_REG(pVM, &pVM->vm.s.StatHaltTimers,STAMTYPE_PROFILE,     "/PROF/VM/Halt/Timers",   STAMUNIT_TICKS_PER_CALL,    "Profiling halted state timer tasks.");
    527         STAM_REL_REG(pVM, &pVM->vm.s.StatHaltPoll,  STAMTYPE_PROFILE,     "/PROF/VM/Halt/Poll",     STAMUNIT_TICKS_PER_CALL,    "Profiling halted state poll tasks.");
    528 
    529531        STAM_REG(pVM, &pVM->StatSwitcherSaveRegs,   STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SaveRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
    530532        STAM_REG(pVM, &pVM->StatSwitcherSysEnter,   STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SysEnter", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
     
    539541        STAM_REG(pVM, &pVM->StatSwitcherRstrRegs,   STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/RstrRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC.");
    540542
    541         STAM_REG(pVM, &pVM->vm.s.StatReqAllocNew,   STAMTYPE_COUNTER,     "/VM/Req/AllocNew",       STAMUNIT_OCCURENCES,        "Number of VMR3ReqAlloc returning a new packet.");
    542         STAM_REG(pVM, &pVM->vm.s.StatReqAllocRaces, STAMTYPE_COUNTER,     "/VM/Req/AllocRaces",     STAMUNIT_OCCURENCES,        "Number of VMR3ReqAlloc causing races.");
    543         STAM_REG(pVM, &pVM->vm.s.StatReqAllocRecycled, STAMTYPE_COUNTER,  "/VM/Req/AllocRecycled",  STAMUNIT_OCCURENCES,        "Number of VMR3ReqAlloc returning a recycled packet.");
    544         STAM_REG(pVM, &pVM->vm.s.StatReqFree,       STAMTYPE_COUNTER,     "/VM/Req/Free",           STAMUNIT_OCCURENCES,        "Number of VMR3ReqFree calls.");
    545         STAM_REG(pVM, &pVM->vm.s.StatReqFreeOverflow, STAMTYPE_COUNTER,   "/VM/Req/FreeOverflow",   STAMUNIT_OCCURENCES,        "Number of times the request was actually freed.");
     543        STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltYield, STAMTYPE_PROFILE,     "/PROF/VM/Halt/Yield",    STAMUNIT_TICKS_PER_CALL,    "Profiling halted state yielding.");
     544        STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltBlock, STAMTYPE_PROFILE,     "/PROF/VM/Halt/Block",    STAMUNIT_TICKS_PER_CALL,    "Profiling halted state blocking.");
     545        STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltTimers,STAMTYPE_PROFILE,     "/PROF/VM/Halt/Timers",   STAMUNIT_TICKS_PER_CALL,    "Profiling halted state timer tasks.");
     546        STAM_REL_REG(pVM, &pUVM->vm.s.StatHaltPoll,  STAMTYPE_PROFILE,     "/PROF/VM/Halt/Poll",     STAMUNIT_TICKS_PER_CALL,    "Profiling halted state poll tasks.");
     547
     548        STAM_REG(pVM, &pUVM->vm.s.StatReqAllocNew,   STAMTYPE_COUNTER,     "/VM/Req/AllocNew",       STAMUNIT_OCCURENCES,        "Number of VMR3ReqAlloc returning a new packet.");
     549        STAM_REG(pVM, &pUVM->vm.s.StatReqAllocRaces, STAMTYPE_COUNTER,     "/VM/Req/AllocRaces",     STAMUNIT_OCCURENCES,        "Number of VMR3ReqAlloc causing races.");
     550        STAM_REG(pVM, &pUVM->vm.s.StatReqAllocRecycled, STAMTYPE_COUNTER,  "/VM/Req/AllocRecycled",  STAMUNIT_OCCURENCES,        "Number of VMR3ReqAlloc returning a recycled packet.");
     551        STAM_REG(pVM, &pUVM->vm.s.StatReqFree,       STAMTYPE_COUNTER,     "/VM/Req/Free",           STAMUNIT_OCCURENCES,        "Number of VMR3ReqFree calls.");
     552        STAM_REG(pVM, &pUVM->vm.s.StatReqFreeOverflow, STAMTYPE_COUNTER,   "/VM/Req/FreeOverflow",   STAMUNIT_OCCURENCES,        "Number of times the request was actually freed.");
    546553
    547554        rc = CPUMR3Init(pVM);
     
    756763     */
    757764    PGMR3Relocate(pVM, offDelta);
    758     PDMR3LdrRelocate(pVM, offDelta);
     765    PDMR3LdrRelocateU(pVM->pUVM, offDelta);
    759766    PGMR3Relocate(pVM, 0);              /* Repeat after PDM relocation. */
    760767    CPUMR3Relocate(pVM);
     
    13321339 * The VM handle is destroyed and can no longer be used up successful return.
    13331340 *
    1334  * @returns 0 on success.
    1335  * @returns VBox error code on failure.
     1341 * @returns VBox status code.
    13361342 * @param   pVM     VM which should be destroyed.
    13371343 * @thread      Any thread but the emulation thread.
     
    13481354    if (!pVM)
    13491355        return VERR_INVALID_PARAMETER;
    1350     if (    pVM->enmVMState != VMSTATE_OFF
    1351         &&  pVM->enmVMState != VMSTATE_CREATED)
    1352     {
    1353         AssertMsgFailed(("Invalid VM state %d\n", pVM->enmVMState));
    1354         return VERR_VM_INVALID_VM_STATE;
    1355     }
    1356 
    1357     /*
    1358      * Unlink the VM and change it's state to destroying.
    1359      */
    1360 /** @todo lock this when we start having multiple machines in a process... */
    1361     PVM pPrev = NULL;
    1362     PVM pCur = g_pVMsHead;
    1363     while (pCur && pCur != pVM)
    1364     {
    1365         pPrev = pCur;
    1366         pCur = pCur->pNext;
    1367     }
    1368     if (!pCur)
    1369     {
    1370         AssertMsgFailed(("pVM=%p is INVALID!\n", pVM));
    1371         return VERR_INVALID_PARAMETER;
    1372     }
    1373     if (pPrev)
    1374         pPrev->pNext = pCur->pNext;
     1356    AssertPtrReturn(pVM, VERR_INVALID_POINTER);
     1357    AssertMsgReturn(   pVM->enmVMState == VMSTATE_OFF
     1358                    || pVM->enmVMState == VMSTATE_CREATED,
     1359                    ("Invalid VM state %d\n", pVM->enmVMState),
     1360                    VERR_VM_INVALID_VM_STATE);
     1361
     1362    /*
     1363     * Change VM state to destroying and unlink the VM.
     1364     */
     1365    vmR3SetState(pVM, VMSTATE_DESTROYING);
     1366
     1367    /** @todo lock this when we start having multiple machines in a process... */
     1368    PUVM pUVM = pVM->pUVM; AssertPtr(pUVM);
     1369    if (g_pUVMsHead == pUVM)
     1370        g_pUVMsHead = pUVM->pNext;
    13751371    else
    1376         g_pVMsHead = pCur->pNext;
    1377 
    1378     vmR3SetState(pVM, VMSTATE_DESTROYING);
    1379 
     1372    {
     1373        PUVM pPrev = g_pUVMsHead;
     1374        while (pPrev && pPrev->pNext != pUVM)
     1375            pPrev = pPrev->pNext;
     1376        AssertMsgReturn(pPrev, ("pUVM=%p / pVM=%p  is INVALID!\n", pUVM, pVM), VERR_INVALID_PARAMETER);
     1377
     1378        pPrev->pNext = pUVM->pNext;
     1379    }
     1380    pUVM->pNext = NULL;
    13801381
    13811382    /*
     
    13851386    vmR3AtDtor(pVM);
    13861387
    1387     pVM->pNext = g_pVMsHead;
    1388     g_pVMsHead = pVM;
    1389 
    13901388    /*
    13911389     * If we are the EMT we'll delay the cleanup till later.
     
    13931391    if (VM_IS_EMT(pVM))
    13941392    {
    1395         pVM->vm.s.fEMTDoesTheCleanup = true;
     1393        pUVM->vm.s.fEMTDoesTheCleanup = true;
     1394        pUVM->vm.s.fTerminateEMT = true;
    13961395        VM_FF_SET(pVM, VM_FF_TERMINATE);
    13971396    }
     
    14021401         */
    14031402        PVMREQ pReq = NULL;
    1404         int rc = VMR3ReqCall(pVM, &pReq, 0, (PFNRT)vmR3Destroy, 1, pVM);
    1405         while (rc == VERR_TIMEOUT)
    1406             rc = VMR3ReqWait(pReq, RT_INDEFINITE_WAIT);
    1407         if (VBOX_SUCCESS(rc))
     1403        int rc = VMR3ReqCallU(pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3Destroy, 1, pVM);
     1404        if (RT_SUCCESS(rc))
    14081405            rc = pReq->iStatus;
     1406        AssertRC(rc);
    14091407        VMR3ReqFree(pReq);
    14101408
     
    14121410         * Wait for the EMT thread to terminate.
    14131411         */
    1414         VM_FF_SET(pVM, VM_FF_TERMINATE);
    1415         uint64_t u64Start = RTTimeMilliTS();
    1416         do
    1417         {
    1418             VMR3NotifyFF(pVM, false);
    1419             rc = RTThreadWait(pVM->ThreadEMT, 1000, NULL);
    1420         } while (   RTTimeMilliTS() - u64Start < 30000 /* 30 sec */
    1421                  && rc == VERR_TIMEOUT);
    1422         AssertMsgRC(rc, ("EMT thread wait failed, rc=%Vrc\n", rc));
     1412        Assert(pUVM->vm.s.fTerminateEMT);
     1413        rc = RTThreadWait(pUVM->vm.s.ThreadEMT, 30000, NULL);
     1414        AssertMsgRC(rc, ("EMT thread wait failed, rc=%Rrc\n", rc));
    14231415
    14241416        /*
    14251417         * Now do the final bit where the heap and VM structures are freed up.
    14261418         */
    1427         vmR3DestroyFinalBit(pVM);
     1419        vmR3DestroyUVM(pUVM);
    14281420    }
    14291421
     
    14341426
    14351427/**
    1436  * Internal destruction worker. This will do nearly all of the
    1437  * job, including quitting the emulation thread.
     1428 * Internal destruction worker.
     1429 *
     1430 * This will do nearly all of the job, including sacking the EMT.
    14381431 *
    14391432 * @returns VBox status.
     
    14421435DECLCALLBACK(int) vmR3Destroy(PVM pVM)
    14431436{
    1444     LogFlow(("vmR3Destroy: pVM=%p\n", pVM));
     1437    PUVM pUVM = pVM->pUVM;
     1438    LogFlow(("vmR3Destroy: pVM=%p pUVM=%p\n", pVM, pUVM));
    14451439    VM_ASSERT_EMT(pVM);
    14461440
     
    14671461    AssertRC(rc);
    14681462#ifdef VBOX_WITH_DEBUGGER
    1469     rc = DBGCTcpTerminate(pVM, pVM->vm.s.pvDBGC);
    1470     pVM->vm.s.pvDBGC = NULL;
     1463    rc = DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC);
     1464    pVM->pUVM->vm.s.pvDBGC = NULL;
    14711465#endif
    14721466    AssertRC(rc);
     
    14971491    rc = CPUMR3Term(pVM);
    14981492    AssertRC(rc);
    1499     rc = STAMR3Term(pVM);
    1500     AssertRC(rc);
    15011493    rc = PDMR3CritSectTerm(pVM);
    15021494    AssertRC(rc);
    1503     /* MM is destroyed later in vmR3DestroyFinalBit() for heap reasons. */
    1504 
    1505     /*
    1506      * We're done in this thread.
    1507      */
    1508     pVM->fForcedActions = VM_FF_TERMINATE;
     1495    rc = MMR3Term(pVM);
     1496    AssertRC(rc);
     1497
     1498    /*
     1499     * We're done in this thread (EMT).
     1500     */
     1501    ASMAtomicUoWriteBool(&pVM->pUVM->vm.s.fTerminateEMT, true);
     1502    ASMAtomicWriteU32(&pVM->fForcedActions, VM_FF_TERMINATE);
    15091503    LogFlow(("vmR3Destroy: returning %Vrc\n", VINF_EM_TERMINATE));
    15101504    return VINF_EM_TERMINATE;
     
    15131507
    15141508/**
    1515  * Does the final part of the VM destruction.
    1516  * This is called by EMT in it's final stage or by the VMR3Destroy caller.
     1509 * Destroys the shared VM structure, leaving only UVM behind.
     1510 *
     1511 * This is called by EMT right before terminating.
     1512 *
     1513 * @param   pUVM        The UVM handle.
     1514 */
     1515void vmR3DestroyFinalBitFromEMT(PUVM pUVM)
     1516{
     1517    if (pUVM->pVM)
     1518    {
     1519        /*
     1520         * Modify state and then terminate MM.
     1521         * (MM must be delayed until this point so we don't destroy the callbacks and the request packet.)
     1522         */
     1523        vmR3SetState(pUVM->pVM, VMSTATE_TERMINATED);
     1524
     1525        /*
     1526         * Tell GVMM to destroy the VM and free its resources.
     1527         */
     1528        int rc = SUPCallVMMR0Ex(pUVM->pVM->pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
     1529        AssertRC(rc);
     1530        pUVM->pVM = NULL;
     1531    }
     1532
     1533    /*
     1534     * Did EMT call VMR3Destroy and have to do it all?
     1535     */
     1536    if (pUVM->vm.s.fEMTDoesTheCleanup)
     1537        vmR3DestroyUVM(pUVM);
     1538}
     1539
     1540
     1541/**
     1542 * Destroys the UVM portion.
     1543 *
     1544 * This is called as the final step in the VM destruction or as the cleanup
     1545 * in case of a creation failure. If EMT called VMR3Destroy, meaning
     1546 * VMINTUSERPERVM::fEMTDoesTheCleanup is true, it will call this as
     1547 * vmR3DestroyFinalBitFromEMT completes.
    15171548 *
    15181549 * @param   pVM     VM Handle.
    15191550 */
    1520 void vmR3DestroyFinalBit(PVM pVM)
    1521 {
     1551static void vmR3DestroyUVM(PUVM pUVM)
     1552{
     1553    /*
     1554     * Terminate the EMT if still running (creation failure only).
     1555     */
     1556    if (!pUVM->vm.s.fTerminateEMT)
     1557    {
     1558        ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
     1559        if (pUVM->pVM)
     1560        {
     1561            VM_FF_SET(pUVM->pVM, VM_FF_TERMINATE);
     1562            VMR3NotifyFF(pUVM->pVM, false);
     1563        }
     1564        RTSemEventSignal(pUVM->vm.s.EventSemWait);
     1565
     1566        int rc2 = RTThreadWait(pUVM->vm.s.ThreadEMT, 2000, NULL);
     1567        AssertRC(rc2);
     1568    }
     1569    RTSemEventDestroy(pUVM->vm.s.EventSemWait);
     1570    pUVM->vm.s.EventSemWait = NIL_RTSEMEVENT;
     1571
    15221572    /*
    15231573     * Free the event semaphores associated with the request packets.
    15241574     */
    15251575    unsigned cReqs = 0;
    1526     for (unsigned i = 0; i < ELEMENTS(pVM->vm.s.apReqFree); i++)
    1527     {
    1528         PVMREQ pReq = pVM->vm.s.apReqFree[i];
    1529         pVM->vm.s.apReqFree[i] = NULL;
     1576    for (unsigned i = 0; i < RT_ELEMENTS(pUVM->vm.s.apReqFree); i++)
     1577    {
     1578        PVMREQ pReq = pUVM->vm.s.apReqFree[i];
     1579        pUVM->vm.s.apReqFree[i] = NULL;
    15301580        for (; pReq; pReq = pReq->pNext, cReqs++)
    15311581        {
     
    15341584        }
    15351585    }
    1536     Assert(cReqs == pVM->vm.s.cReqFree); NOREF(cReqs);
     1586    Assert(cReqs == pUVM->vm.s.cReqFree); NOREF(cReqs);
    15371587
    15381588    /*
     
    15411591    for (unsigned i = 0; i < 10; i++)
    15421592    {
    1543         PVMREQ pReqHead = (PVMREQ)ASMAtomicXchgPtr((void *volatile *)&pVM->vm.s.pReqs, NULL);
     1593        PVMREQ pReqHead = (PVMREQ)ASMAtomicXchgPtr((void *volatile *)&pUVM->vm.s.pReqs, NULL);
    15441594        AssertMsg(!pReqHead, ("This isn't supposed to happen! VMR3Destroy caller has to serialize this.\n"));
    15451595        if (!pReqHead)
     
    15471597        for (PVMREQ pReq = pReqHead; pReq; pReq = pReq->pNext)
    15481598        {
    1549             ASMAtomicXchgSize(&pReq->iStatus, VERR_INTERNAL_ERROR);
    1550             ASMAtomicXchgSize(&pReq->enmState, VMREQSTATE_INVALID);
     1599            ASMAtomicUoWriteSize(&pReq->iStatus, VERR_INTERNAL_ERROR);
     1600            ASMAtomicWriteSize(&pReq->enmState, VMREQSTATE_INVALID);
    15511601            RTSemEventSignal(pReq->EventSem);
    15521602            RTThreadSleep(2);
     
    15581608
    15591609    /*
    1560      * Modify state and then terminate MM.
    1561      * (MM must be delayed until this point so we don't destroy the callbacks and the request packet.)
    1562      */
    1563     vmR3SetState(pVM, VMSTATE_TERMINATED);
    1564     int rc = MMR3Term(pVM);
    1565     AssertRC(rc);
    1566 
    1567     /*
    1568      * Tell GVMM that it can destroy the VM now.
    1569      */
    1570     rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_DESTROY_VM, 0, NULL);
    1571     AssertRC(rc);
    1572     rc = SUPTerm();
    1573     AssertRC(rc);
     1610     * Make sure the VMMR0.r0 module and whatever else is unloaded.
     1611     */
     1612    PDMR3TermUVM(pUVM);
     1613
     1614    /*
     1615     * Terminate the support library if initialized.
     1616     */
     1617    if (pUVM->vm.s.pSession)
     1618    {
     1619        int rc = SUPTerm();
     1620        AssertRC(rc);
     1621        pUVM->vm.s.pSession = NIL_RTR0PTR;
     1622    }
     1623
     1624    /*
     1625     * Destroy the MM heap and free the UVM structure.
     1626     */
     1627    MMR3TermUVM(pUVM);
     1628    STAMR3TermUVM(pUVM);
     1629
     1630    ASMAtomicUoWriteU32(&pUVM->u32Magic, UINT32_MAX);
     1631    RTMemFree(pUVM);
    15741632
    15751633    RTLogFlush(NULL);
     
    15911649     * destroyed during the enumeration.
    15921650     */
     1651    PUVM pNext;
    15931652    if (pVMPrev)
    1594         return pVMPrev->pNext;
    1595     return g_pVMsHead;
     1653        pNext = pVMPrev->pUVM->pNext;
     1654    else
     1655        pNext = g_pUVMsHead;
     1656    return pNext ? pNext->pVM : NULL;
    15961657}
    15971658
     
    17811842    SELMR3Reset(pVM);
    17821843    TRPMR3Reset(pVM);
    1783     vmR3AtReset(pVM);
     1844    vmR3AtResetU(pVM->pUVM);
    17841845    REMR3Reset(pVM);
    17851846    IOMR3Reset(pVM);
     
    18131874 * @returns VBox status code.
    18141875 *          Any failure is fatal.
    1815  * @param   pVM     The VM which is being reset.
    1816  */
    1817 static int vmR3AtReset(PVM pVM)
     1876 * @param   pUVM        Pointe to the user mode VM structure.
     1877 */
     1878static int vmR3AtResetU(PUVM pUVM)
    18181879{
    18191880    /*
     
    18211882     */
    18221883    int rc = VINF_SUCCESS;
    1823     for (PVMATRESET pCur = pVM->vm.s.pAtReset; pCur; pCur = pCur->pNext)
     1884    for (PVMATRESET pCur = pUVM->vm.s.pAtReset; pCur; pCur = pCur->pNext)
    18241885    {
    18251886        /* do the call */
     
    18301891                break;
    18311892            case VMATRESETTYPE_INTERNAL:
    1832                 rc = pCur->u.Internal.pfnCallback(pVM, pCur->pvUser);
     1893                rc = pCur->u.Internal.pfnCallback(pUVM->pVM, pCur->pvUser);
    18331894                break;
    18341895            case VMATRESETTYPE_EXTERNAL:
     
    18541915 * Internal registration function
    18551916 */
    1856 static int vmr3AtResetRegister(PVM pVM, void *pvUser, const char *pszDesc, PVMATRESET *ppNew)
     1917static int vmr3AtResetRegisterU(PUVM pUVM, void *pvUser, const char *pszDesc, PVMATRESET *ppNew)
    18571918{
    18581919    /*
    18591920     * Allocate restration structure.
    18601921     */
    1861     PVMATRESET pNew = (PVMATRESET)MMR3HeapAlloc(pVM, MM_TAG_VM,  sizeof(*pNew));
     1922    PVMATRESET pNew = (PVMATRESET)MMR3HeapAllocU(pUVM, MM_TAG_VM,  sizeof(*pNew));
    18621923    if (pNew)
    18631924    {
     
    18681929
    18691930        /* insert */
    1870         *pVM->vm.s.ppAtResetNext = pNew;
    1871         pVM->vm.s.ppAtResetNext = &pNew->pNext;
     1931        *pUVM->vm.s.ppAtResetNext = pNew;
     1932        pUVM->vm.s.ppAtResetNext = &pNew->pNext;
    18721933
    18731934        *ppNew = pNew;
     
    19031964     */
    19041965    PVMATRESET pNew;
    1905     int rc = vmr3AtResetRegister(pVM, pvUser, pszDesc, &pNew);
     1966    int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);
    19061967    if (VBOX_SUCCESS(rc))
    19071968    {
     
    19422003     */
    19432004    PVMATRESET pNew;
    1944     int rc = vmr3AtResetRegister(pVM, pvUser, pszDesc, &pNew);
     2005    int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);
    19452006    if (VBOX_SUCCESS(rc))
    19462007    {
     
    19802041     */
    19812042    PVMATRESET pNew;
    1982     int rc = vmr3AtResetRegister(pVM, pvUser, pszDesc, &pNew);
     2043    int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew);
    19832044    if (VBOX_SUCCESS(rc))
    19842045    {
     
    19982059 *
    19992060 * @returns Pointer to the next callback structure.
    2000  * @param   pVM             The VM.
     2061 * @param   pUVM            Pointer to the user mode VM structure.
    20012062 * @param   pCur            The one to free.
    20022063 * @param   pPrev           The one before pCur.
    20032064 */
    2004 static PVMATRESET vmr3AtResetFree(PVM pVM, PVMATRESET pCur, PVMATRESET pPrev)
     2065static PVMATRESET vmr3AtResetFreeU(PUVM pUVM, PVMATRESET pCur, PVMATRESET pPrev)
    20052066{
    20062067    /*
     
    20122073        pPrev->pNext = pNext;
    20132074        if (!pNext)
    2014             pVM->vm.s.ppAtResetNext = &pPrev->pNext;
     2075            pUVM->vm.s.ppAtResetNext = &pPrev->pNext;
    20152076    }
    20162077    else
    20172078    {
    2018         pVM->vm.s.pAtReset = pNext;
     2079        pUVM->vm.s.pAtReset = pNext;
    20192080        if (!pNext)
    2020             pVM->vm.s.ppAtResetNext = &pVM->vm.s.pAtReset;
     2081            pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset;
    20212082    }
    20222083
     
    20422103    int         rc = VERR_VM_ATRESET_NOT_FOUND;
    20432104    PVMATRESET  pPrev = NULL;
    2044     PVMATRESET  pCur = pVM->vm.s.pAtReset;
     2105    PVMATRESET  pCur = pVM->pUVM->vm.s.pAtReset;
    20452106    while (pCur)
    20462107    {
     
    20492110            &&  (!pfnCallback || pCur->u.Dev.pfnCallback == pfnCallback))
    20502111        {
    2051             pCur = vmr3AtResetFree(pVM, pCur, pPrev);
     2112            pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev);
    20522113            rc = VINF_SUCCESS;
    20532114        }
     
    20752136    int         rc = VERR_VM_ATRESET_NOT_FOUND;
    20762137    PVMATRESET  pPrev = NULL;
    2077     PVMATRESET  pCur = pVM->vm.s.pAtReset;
     2138    PVMATRESET  pCur = pVM->pUVM->vm.s.pAtReset;
    20782139    while (pCur)
    20792140    {
     
    20812142            &&  pCur->u.Internal.pfnCallback == pfnCallback)
    20822143        {
    2083             pCur = vmr3AtResetFree(pVM, pCur, pPrev);
     2144            pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev);
    20842145            rc = VINF_SUCCESS;
    20852146        }
     
    21072168    int         rc = VERR_VM_ATRESET_NOT_FOUND;
    21082169    PVMATRESET  pPrev = NULL;
    2109     PVMATRESET  pCur = pVM->vm.s.pAtReset;
     2170    PVMATRESET  pCur = pVM->pUVM->vm.s.pAtReset;
    21102171    while (pCur)
    21112172    {
     
    21132174            &&  pCur->u.External.pfnCallback == pfnCallback)
    21142175        {
    2115             pCur = vmr3AtResetFree(pVM, pCur, pPrev);
     2176            pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev);
    21162177            rc = VINF_SUCCESS;
    21172178        }
     
    21862247     * Call the at state change callbacks.
    21872248     */
    2188     for (PVMATSTATE pCur = pVM->vm.s.pAtState; pCur; pCur = pCur->pNext)
     2249    for (PVMATSTATE pCur = pVM->pUVM->vm.s.pAtState; pCur; pCur = pCur->pNext)
    21892250    {
    21902251        pCur->pfnAtState(pVM, enmStateNew, enmStateOld, pCur->pvUser);
     
    22292290     */
    22302291    PVMREQ pReq;
    2231     int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateRegister, 3, pVM, pfnAtState, pvUser);
     2292    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateRegisterU, 3, pVM->pUVM, pfnAtState, pvUser);
    22322293    if (VBOX_FAILURE(rc))
    22332294        return rc;
     
    22442305 *
    22452306 * @returns VBox status code.
    2246  * @param   pVM             VM handle.
     2307 * @param   pUVM            Pointer to the user mode VM structure.
    22472308 * @param   pfnAtState      Pointer to callback.
    22482309 * @param   pvUser          User argument.
    22492310 * @thread  EMT
    22502311 */
    2251 static DECLCALLBACK(int) vmR3AtStateRegister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)
     2312static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser)
    22522313{
    22532314    /*
     
    22552316     */
    22562317
    2257     PVMATSTATE pNew = (PVMATSTATE)MMR3HeapAlloc(pVM, MM_TAG_VM, sizeof(*pNew));
     2318    PVMATSTATE pNew = (PVMATSTATE)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
    22582319    if (!pNew)
    22592320        return VERR_NO_MEMORY;
     
    22652326
    22662327    /* insert */
    2267     *pVM->vm.s.ppAtStateNext = pNew;
    2268     pVM->vm.s.ppAtStateNext = &pNew->pNext;
     2328    *pUVM->vm.s.ppAtStateNext = pNew;
     2329    pUVM->vm.s.ppAtStateNext = &pNew->pNext;
    22692330
    22702331    return VINF_SUCCESS;
     
    22982359     */
    22992360    PVMREQ pReq;
    2300     int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateDeregister, 3, pVM, pfnAtState, pvUser);
     2361    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtStateDeregisterU, 3, pVM->pUVM, pfnAtState, pvUser);
    23012362    if (VBOX_FAILURE(rc))
    23022363        return rc;
     
    23132374 *
    23142375 * @returns VBox status code.
    2315  * @param   pVM             VM handle.
     2376 * @param   pUVM            Pointer to the user mode VM structure.
    23162377 * @param   pfnAtState      Pointer to callback.
    23172378 * @param   pvUser          User argument.
    23182379 * @thread  EMT
    23192380 */
    2320 static DECLCALLBACK(int) vmR3AtStateDeregister(PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)
    2321 {
    2322     LogFlow(("vmR3AtStateDeregister: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));
     2381static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser)
     2382{
     2383    LogFlow(("vmR3AtStateDeregisterU: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));
    23232384
    23242385    /*
     
    23262387     */
    23272388    PVMATSTATE pPrev = NULL;
    2328     PVMATSTATE pCur = pVM->vm.s.pAtState;
     2389    PVMATSTATE pCur = pUVM->vm.s.pAtState;
    23292390    while (     pCur
    23302391           &&   pCur->pfnAtState == pfnAtState
     
    23472408        pPrev->pNext = pCur->pNext;
    23482409        if (!pCur->pNext)
    2349             pVM->vm.s.ppAtStateNext = &pPrev->pNext;
     2410            pUVM->vm.s.ppAtStateNext = &pPrev->pNext;
    23502411    }
    23512412    else
    23522413    {
    2353         pVM->vm.s.pAtState = pCur->pNext;
     2414        pUVM->vm.s.pAtState = pCur->pNext;
    23542415        if (!pCur->pNext)
    2355             pVM->vm.s.ppAtStateNext = &pVM->vm.s.pAtState;
     2416            pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState;
    23562417    }
    23572418
     
    23782439VMR3DECL(int)   VMR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)
    23792440{
     2441    return VMR3AtErrorRegisterU(pVM->pUVM, pfnAtError, pvUser);
     2442}
     2443
     2444
     2445/**
     2446 * Registers a VM error callback.
     2447 *
     2448 * @returns VBox status code.
     2449 * @param   pUVM            The VM handle.
     2450 * @param   pfnAtError      Pointer to callback.
     2451 * @param   pvUser          User argument.
     2452 * @thread  Any.
     2453 */
     2454VMR3DECL(int)   VMR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser)
     2455{
    23802456    LogFlow(("VMR3AtErrorRegister: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));
    2381 
    2382     /*
    2383      * Validate input.
    2384      */
    2385     if (!pfnAtError)
    2386     {
    2387         AssertMsgFailed(("callback is required\n"));
    2388         return VERR_INVALID_PARAMETER;
    2389     }
     2457    AssertPtrReturn(pfnAtError, VERR_INVALID_PARAMETER);
    23902458
    23912459    /*
     
    23932461     */
    23942462    PVMREQ pReq;
    2395     int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtErrorRegister, 3, pVM, pfnAtError, pvUser);
     2463    int rc = VMR3ReqCallU(pUVM, &pReq, RT_INDEFINITE_WAIT, 0, (PFNRT)vmR3AtErrorRegisterU, 3, pUVM, pfnAtError, pvUser);
    23962464    if (VBOX_FAILURE(rc))
    23972465        return rc;
     
    24082476 *
    24092477 * @returns VBox status code.
    2410  * @param   pVM             The VM handle.
     2478 * @param   pUVM            Pointer to the user mode VM structure.
    24112479 * @param   pfnAtError      Pointer to callback.
    24122480 * @param   pvUser          User argument.
    24132481 * @thread  EMT
    24142482 */
    2415 static DECLCALLBACK(int)    vmR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)
     2483static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser)
    24162484{
    24172485    /*
     
    24192487     */
    24202488
    2421     PVMATERROR pNew = (PVMATERROR)MMR3HeapAlloc(pVM, MM_TAG_VM, sizeof(*pNew));
     2489    PVMATERROR pNew = (PVMATERROR)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
    24222490    if (!pNew)
    24232491        return VERR_NO_MEMORY;
     
    24292497
    24302498    /* insert */
    2431     *pVM->vm.s.ppAtErrorNext = pNew;
    2432     pVM->vm.s.ppAtErrorNext = &pNew->pNext;
     2499    *pUVM->vm.s.ppAtErrorNext = pNew;
     2500    pUVM->vm.s.ppAtErrorNext = &pNew->pNext;
    24332501
    24342502    return VINF_SUCCESS;
     
    24622530     */
    24632531    PVMREQ pReq;
    2464     int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtErrorDeregister, 3, pVM, pfnAtError, pvUser);
     2532    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtErrorDeregisterU, 3, pVM->pUVM, pfnAtError, pvUser);
    24652533    if (VBOX_FAILURE(rc))
    24662534        return rc;
     
    24772545 *
    24782546 * @returns VBox status code.
    2479  * @param   pVM             The VM handle.
     2547 * @param   pUVM            Pointer to the user mode VM structure.
    24802548 * @param   pfnAtError      Pointer to callback.
    24812549 * @param   pvUser          User argument.
    24822550 * @thread  EMT
    24832551 */
    2484 static DECLCALLBACK(int)    vmR3AtErrorDeregister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)
    2485 {
    2486     LogFlow(("vmR3AtErrorDeregister: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));
     2552static DECLCALLBACK(int)    vmR3AtErrorDeregisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser)
     2553{
     2554    LogFlow(("vmR3AtErrorDeregisterU: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));
    24872555
    24882556    /*
     
    24902558     */
    24912559    PVMATERROR pPrev = NULL;
    2492     PVMATERROR pCur = pVM->vm.s.pAtError;
     2560    PVMATERROR pCur = pUVM->vm.s.pAtError;
    24932561    while (     pCur
    24942562           &&   pCur->pfnAtError == pfnAtError
     
    25112579        pPrev->pNext = pCur->pNext;
    25122580        if (!pCur->pNext)
    2513             pVM->vm.s.ppAtErrorNext = &pPrev->pNext;
     2581            pUVM->vm.s.ppAtErrorNext = &pPrev->pNext;
    25142582    }
    25152583    else
    25162584    {
    2517         pVM->vm.s.pAtError = pCur->pNext;
     2585        pUVM->vm.s.pAtError = pCur->pNext;
    25182586        if (!pCur->pNext)
    2519             pVM->vm.s.ppAtErrorNext = &pVM->vm.s.pAtError;
     2587            pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError;
    25202588    }
    25212589
     
    25832651     * Call the at error callbacks.
    25842652     */
    2585     for (PVMATERROR pCur = pVM->vm.s.pAtError; pCur; pCur = pCur->pNext)
     2653    for (PVMATERROR pCur = pVM->pUVM->vm.s.pAtError; pCur; pCur = pCur->pNext)
    25862654        vmR3SetErrorWorkerDoCall(pVM, pCur, rc, RT_SRC_POS_ARGS, "%s", pszMessage);
    25872655}
     
    25892657
    25902658/**
     2659 * Creation time wrapper for vmR3SetErrorUV.
     2660 *
     2661 * @returns rc.
     2662 * @param   pUVM            Pointer to the user mode VM structure.
     2663 * @param   rc              The VBox status code.
     2664 * @param   RT_SRC_POS_DECL The source position of this error.
     2665 * @param   pszFormat       Format string.
     2666 * @param   ...             The arguments.
     2667 * @thread  Any thread.
     2668 */
     2669static int vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...)
     2670{
     2671    va_list va;
     2672    va_start(va, pszFormat);
     2673    vmR3SetErrorUV(pUVM, rc, pszFile, iLine, pszFunction, pszFormat, &va);
     2674    va_end(va);
     2675    return rc;
     2676}
     2677
     2678
     2679/**
    25912680 * Worker which calls everyone listening to the VM error messages.
    25922681 *
    2593  * @param   pVM             The VM handle.
     2682 * @param   pUVM            Pointer to the user mode VM structure.
    25942683 * @param   rc              The VBox status code.
    25952684 * @param   RT_SRC_POS_DECL The source position of this error.
     
    25982687 * @thread  EMT
    25992688 */
    2600 DECLCALLBACK(void) vmR3SetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *pArgs)
     2689DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *pArgs)
    26012690{
    26022691#ifdef LOG_ENABLED
     
    26152704     * Make a copy of the message.
    26162705     */
    2617     vmSetErrorCopy(pVM, rc, RT_SRC_POS_ARGS, pszFormat, *pArgs);
     2706    if (pUVM->pVM)
     2707        vmSetErrorCopy(pUVM->pVM, rc, RT_SRC_POS_ARGS, pszFormat, *pArgs);
    26182708
    26192709    /*
    26202710     * Call the at error callbacks.
    26212711     */
    2622     for (PVMATERROR pCur = pVM->vm.s.pAtError; pCur; pCur = pCur->pNext)
     2712    for (PVMATERROR pCur = pUVM->vm.s.pAtError; pCur; pCur = pCur->pNext)
    26232713    {
    26242714        va_list va2;
    26252715        va_copy(va2, *pArgs);
    2626         pCur->pfnAtError(pVM, pCur->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va2);
     2716        pCur->pfnAtError(pUVM->pVM, pCur->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va2);
    26272717        va_end(va2);
    26282718    }
     
    26562746     */
    26572747    PVMREQ pReq;
    2658     int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorRegister, 3, pVM, pfnAtRuntimeError, pvUser);
     2748    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorRegisterU, 3, pVM->pUVM, pfnAtRuntimeError, pvUser);
    26592749    if (VBOX_FAILURE(rc))
    26602750        return rc;
     
    26712761 *
    26722762 * @returns VBox status code.
    2673  * @param   pVM                 The VM handle.
     2763 * @param   pUVM            Pointer to the user mode VM structure.
    26742764 * @param   pfnAtRuntimeError   Pointer to callback.
    26752765 * @param   pvUser              User argument.
    26762766 * @thread  EMT
    26772767 */
    2678 static DECLCALLBACK(int)    vmR3AtRuntimeErrorRegister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
     2768static DECLCALLBACK(int)    vmR3AtRuntimeErrorRegisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
    26792769{
    26802770    /*
     
    26822772     */
    26832773
    2684     PVMATRUNTIMEERROR pNew = (PVMATRUNTIMEERROR)MMR3HeapAlloc(pVM, MM_TAG_VM, sizeof(*pNew));
     2774    PVMATRUNTIMEERROR pNew = (PVMATRUNTIMEERROR)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew));
    26852775    if (!pNew)
    26862776        return VERR_NO_MEMORY;
     
    26922782
    26932783    /* insert */
    2694     *pVM->vm.s.ppAtRuntimeErrorNext = pNew;
    2695     pVM->vm.s.ppAtRuntimeErrorNext = &pNew->pNext;
     2784    *pUVM->vm.s.ppAtRuntimeErrorNext = pNew;
     2785    pUVM->vm.s.ppAtRuntimeErrorNext = &pNew->pNext;
    26962786
    26972787    return VINF_SUCCESS;
     
    27252815     */
    27262816    PVMREQ pReq;
    2727     int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorDeregister, 3, pVM, pfnAtRuntimeError, pvUser);
     2817    int rc = VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3AtRuntimeErrorDeregisterU, 3, pVM->pUVM, pfnAtRuntimeError, pvUser);
    27282818    if (VBOX_FAILURE(rc))
    27292819        return rc;
     
    27402830 *
    27412831 * @returns VBox status code.
    2742  * @param   pVM                 The VM handle.
     2832 * @param   pUVM            Pointer to the user mode VM structure.
    27432833 * @param   pfnAtRuntimeError   Pointer to callback.
    27442834 * @param   pvUser              User argument.
    27452835 * @thread  EMT
    27462836 */
    2747 static DECLCALLBACK(int)    vmR3AtRuntimeErrorDeregister(PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
    2748 {
    2749     LogFlow(("vmR3AtRuntimeErrorDeregister: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
     2837static DECLCALLBACK(int)    vmR3AtRuntimeErrorDeregisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)
     2838{
     2839    LogFlow(("vmR3AtRuntimeErrorDeregisterU: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));
    27502840
    27512841    /*
     
    27532843     */
    27542844    PVMATRUNTIMEERROR pPrev = NULL;
    2755     PVMATRUNTIMEERROR pCur = pVM->vm.s.pAtRuntimeError;
     2845    PVMATRUNTIMEERROR pCur = pUVM->vm.s.pAtRuntimeError;
    27562846    while (     pCur
    27572847           &&   pCur->pfnAtRuntimeError == pfnAtRuntimeError
     
    27742864        pPrev->pNext = pCur->pNext;
    27752865        if (!pCur->pNext)
    2776             pVM->vm.s.ppAtRuntimeErrorNext = &pPrev->pNext;
     2866            pUVM->vm.s.ppAtRuntimeErrorNext = &pPrev->pNext;
    27772867    }
    27782868    else
    27792869    {
    2780         pVM->vm.s.pAtRuntimeError = pCur->pNext;
     2870        pUVM->vm.s.pAtRuntimeError = pCur->pNext;
    27812871        if (!pCur->pNext)
    2782             pVM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;
     2872            pUVM->vm.s.ppAtRuntimeErrorNext = &pUVM->vm.s.pAtRuntimeError;
    27832873    }
    27842874
     
    28442934     * Call the at runtime error callbacks.
    28452935     */
    2846     for (PVMATRUNTIMEERROR pCur = pVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
     2936    for (PVMATRUNTIMEERROR pCur = pVM->pUVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
    28472937        vmR3SetRuntimeErrorWorkerDoCall(pVM, pCur, fFatal, pszErrorID, "%s", pszMessage);
    28482938}
     
    28712961     * Call the at error callbacks.
    28722962     */
    2873     for (PVMATRUNTIMEERROR pCur = pVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
     2963    for (PVMATRUNTIMEERROR pCur = pVM->pUVM->vm.s.pAtRuntimeError; pCur; pCur = pCur->pNext)
    28742964    {
    28752965        va_list va2;
  • trunk/src/VBox/VMM/VMEmt.cpp

    r6632 r6796  
    2828#include "VMInternal.h"
    2929#include <VBox/vm.h>
     30#include <VBox/uvm.h>
    3031
    3132#include <VBox/err.h>
     
    4647 * @returns Thread exit code.
    4748 * @param   ThreadSelf  The handle to the executing thread.
    48  * @param   pvArgs      Pointer to a VMEMULATIONTHREADARGS structure.
     49 * @param   pvArgs      Pointer to the user mode VM structure (UVM).
    4950 */
    5051DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArgs)
    5152{
    52     PVMEMULATIONTHREADARGS pArgs = (PVMEMULATIONTHREADARGS)pvArgs;
    53     AssertReleaseMsg(pArgs && pArgs->pVM, ("Invalid arguments to the emulation thread!\n"));
     53    PUVM pUVM = (PUVM)pvArgs;
     54    AssertReleaseMsg(VALID_PTR(pUVM) && pUVM->u32Magic == UVM_MAGIC,
     55                     ("Invalid arguments to the emulation thread!\n"));
    5456
    5557    /*
    5658     * Init the native thread member.
    5759     */
    58     PVM pVM = pArgs->pVM;
    59     pVM->NativeThreadEMT = RTThreadGetNative(ThreadSelf);
     60    pUVM->vm.s.NativeThreadEMT = RTThreadGetNative(ThreadSelf);
    6061
    6162    /*
    6263     * The request loop.
    6364     */
     65    int     rc = VINF_SUCCESS;
     66    VMSTATE enmBefore = VMSTATE_CREATING;
     67    Log(("vmR3EmulationThread: Emulation thread starting the days work... Thread=%#x pUVM=%p\n", ThreadSelf, pUVM));
     68    for (;;)
     69    {
     70        /* Requested to exit the EMT thread out of sync? (currently only VMR3WaitForResume) */
     71        if (setjmp(pUVM->vm.s.emtJumpEnv) != 0)
     72        {
     73            rc = VINF_SUCCESS;
     74            break;
     75        }
     76
     77        /*
     78         * During early init there is no pVM, so make a special path
     79         * for that to keep things clearly separate.
     80         */
     81        if (!pUVM->pVM)
     82        {
     83            /*
     84             * Check for termination first.
     85             */
     86            if (pUVM->vm.s.fTerminateEMT)
     87            {
     88                rc = VINF_EM_TERMINATE;
     89                break;
     90            }
     91            if (pUVM->vm.s.pReqs)
     92            {
     93                /*
     94                 * Service execute in EMT request.
     95                 */
     96                rc = VMR3ReqProcessU(pUVM);
     97                Log(("vmR3EmulationThread: Req rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_CREATING));
     98            }
     99            else
     100            {
     101                /*
     102                 * Nothing important is pending, so wait for something.
     103                 */
     104                rc = VMR3WaitU(pUVM);
     105                if (VBOX_FAILURE(rc))
     106                    break;
     107            }
     108        }
     109        else
     110        {
     111
     112            /*
     113             * Pending requests which needs servicing?
     114             *
     115             * We check for state changes in addition to status codes when
     116             * servicing requests. (Look after the ifs.)
     117             */
     118            PVM pVM = pUVM->pVM;
     119            enmBefore = pVM->enmVMState;
     120            if (    VM_FF_ISSET(pVM, VM_FF_TERMINATE)
     121                ||  pUVM->vm.s.fTerminateEMT)
     122            {
     123                rc = VINF_EM_TERMINATE;
     124                break;
     125            }
     126            if (pUVM->vm.s.pReqs)
     127            {
     128                /*
     129                 * Service execute in EMT request.
     130                 */
     131                rc = VMR3ReqProcessU(pUVM);
     132                Log(("vmR3EmulationThread: Req rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
     133            }
     134            else if (VM_FF_ISSET(pVM, VM_FF_DBGF))
     135            {
     136                /*
     137                 * Service the debugger request.
     138                 */
     139                rc = DBGFR3VMMForcedAction(pVM);
     140                Log(("vmR3EmulationThread: Dbg rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
     141            }
     142            else if (VM_FF_ISSET(pVM, VM_FF_RESET))
     143            {
     144                /*
     145                 * Service a delayed reset request.
     146                 */
     147                rc = VMR3Reset(pVM);
     148                VM_FF_CLEAR(pVM, VM_FF_RESET);
     149                Log(("vmR3EmulationThread: Reset rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
     150            }
     151            else
     152            {
     153                /*
     154                 * Nothing important is pending, so wait for something.
     155                 */
     156                rc = VMR3WaitU(pUVM);
     157                if (VBOX_FAILURE(rc))
     158                    break;
     159            }
     160
     161            /*
     162             * Check for termination requests, these have extremely high priority.
     163             */
     164            if (    rc == VINF_EM_TERMINATE
     165                ||  VM_FF_ISSET(pVM, VM_FF_TERMINATE)
     166                ||  pUVM->vm.s.fTerminateEMT)
     167                break;
     168
     169            /*
     170             * Some requests (both VMR3Req* and the DBGF) can potentially
     171             * resume or start the VM, in that case we'll get a change in
     172             * VM status indicating that we're now running.
     173             */
     174            if (    VBOX_SUCCESS(rc)
     175                &&  enmBefore != pVM->enmVMState
     176                &&  (pVM->enmVMState == VMSTATE_RUNNING))
     177            {
     178                rc = EMR3ExecuteVM(pVM);
     179                Log(("vmR3EmulationThread: EMR3ExecuteVM() -> rc=%Vrc, enmVMState=%d\n", rc, pVM->enmVMState));
     180                if (EMGetState(pVM) == EMSTATE_GURU_MEDITATION)
     181                    vmR3SetState(pVM, VMSTATE_GURU_MEDITATION);
     182            }
     183        }
     184    } /* forever */
     185
     186
     187    /*
     188     * Exiting.
     189     */
     190    Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pUVM=%p rc=%Vrc enmBefore=%d enmVMState=%d\n",
     191         ThreadSelf, pUVM, rc, enmBefore, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_TERMINATED));
     192    if (pUVM->vm.s.fEMTDoesTheCleanup)
     193    {
     194        Log(("vmR3EmulationThread: executing delayed Destroy\n"));
     195        Assert(pUVM->pVM);
     196        vmR3Destroy(pUVM->pVM);
     197        vmR3DestroyFinalBitFromEMT(pUVM);
     198    }
     199    else
     200    {
     201        vmR3DestroyFinalBitFromEMT(pUVM);
     202
     203        /* we don't reset ThreadEMT here because it's used in waiting. */
     204        pUVM->vm.s.NativeThreadEMT = NIL_RTNATIVETHREAD;
     205    }
     206    Log(("vmR3EmulationThread: EMT is terminated.\n"));
     207    return rc;
     208}
     209
     210
     211/**
     212 * Wait for VM to be resumed. Handle events like vmR3EmulationThread does.
     213 * In case the VM is stopped, clean up and long jump to the main EMT loop.
     214 *
     215 * @returns VINF_SUCCESS or doesn't return
     216 * @param   pVM             VM handle.
     217 */
     218VMR3DECL(int) VMR3WaitForResume(PVM pVM)
     219{
     220    /*
     221     * The request loop.
     222     */
     223    PUVM    pUVM = pVM->pUVM;
    64224    VMSTATE enmBefore;
    65225    int     rc;
    66     Log(("vmR3EmulationThread: Emulation thread starting the days work... Thread=%#x pVM=%p\n", ThreadSelf, pVM));
    67226    for (;;)
    68227    {
    69         /* Requested to exit the EMT thread out of sync? (currently only VMR3WaitForResume) */
    70         if (setjmp(pVM->vm.s.emtJumpEnv) != 0)
    71         {
    72             rc = VINF_SUCCESS;
    73             break;
    74         }
    75228
    76229        /*
     
    81234         */
    82235        enmBefore = pVM->enmVMState;
    83         if (VM_FF_ISSET(pVM, VM_FF_TERMINATE))
     236        if (    VM_FF_ISSET(pVM, VM_FF_TERMINATE)
     237            ||  pUVM->vm.s.fTerminateEMT)
    84238        {
    85239            rc = VINF_EM_TERMINATE;
    86240            break;
    87241        }
    88         if (pVM->vm.s.pReqs)
     242        else if (pUVM->vm.s.pReqs)
    89243        {
    90244            /*
    91245             * Service execute in EMT request.
    92246             */
    93             rc = VMR3ReqProcess(pVM);
    94             Log(("vmR3EmulationThread: Req rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
    95         }
    96         else if (VM_FF_ISSET(pVM, VM_FF_DBGF))
    97         {
    98             /*
    99              * Service the debugger request.
    100              */
    101             rc = DBGFR3VMMForcedAction(pVM);
    102             Log(("vmR3EmulationThread: Dbg rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
    103         }
    104         else if (VM_FF_ISSET(pVM, VM_FF_RESET))
    105         {
    106             /*
    107              * Service a delayed reset request.
    108              */
    109             rc = VMR3Reset(pVM);
    110             VM_FF_CLEAR(pVM, VM_FF_RESET);
    111             Log(("vmR3EmulationThread: Reset rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
    112         }
    113         else
    114         {
    115             /*
    116              * Nothing important is pending, so wait for something.
    117              */
    118             rc = VMR3Wait(pVM);
    119             if (VBOX_FAILURE(rc))
    120                 break;
    121         }
    122 
    123         /*
    124          * Check for termination requests, these are extremely high priority.
    125          */
    126         if (    rc == VINF_EM_TERMINATE
    127             ||  VM_FF_ISSET(pVM, VM_FF_TERMINATE))
    128             break;
    129 
    130         /*
    131          * Some requests (both VMR3Req* and the DBGF) can potentially
    132          * resume or start the VM, in that case we'll get a change in
    133          * VM status indicating that we're now running.
    134          */
    135         if (    VBOX_SUCCESS(rc)
    136             &&  enmBefore != pVM->enmVMState
    137             &&  (pVM->enmVMState == VMSTATE_RUNNING))
    138         {
    139             rc = EMR3ExecuteVM(pVM);
    140             Log(("vmR3EmulationThread: EMR3ExecuteVM() -> rc=%Vrc, enmVMState=%d\n", rc, pVM->enmVMState));
    141             if (EMGetState(pVM) == EMSTATE_GURU_MEDITATION)
    142                 vmR3SetState(pVM, VMSTATE_GURU_MEDITATION);
    143         }
    144 
    145     } /* forever */
    146 
    147 
    148     /*
    149      * Exiting.
    150      */
    151     Log(("vmR3EmulationThread: Terminating emulation thread! Thread=%#x pVM=%p rc=%Vrc enmBefore=%d enmVMState=%d\n",
    152          ThreadSelf, pVM, rc, enmBefore, pVM->enmVMState));
    153     if (pVM->vm.s.fEMTDoesTheCleanup)
    154     {
    155         Log(("vmR3EmulationThread: executing delayed Destroy\n"));
    156         vmR3Destroy(pVM);
    157         vmR3DestroyFinalBit(pVM);
    158         Log(("vmR3EmulationThread: EMT is terminated.\n"));
    159     }
    160     else
    161     {
    162         /* we don't reset ThreadEMT here because it's used in waiting. */
    163         pVM->NativeThreadEMT = NIL_RTNATIVETHREAD;
    164     }
    165     return rc;
    166 }
    167 
    168 
    169 /**
    170  * Wait for VM to be resumed. Handle events like vmR3EmulationThread does.
    171  * In case the VM is stopped, clean up and long jump to the main EMT loop.
    172  *
    173  * @returns VINF_SUCCESS or doesn't return
    174  * @param   pVM             VM handle.
    175  */
    176 VMR3DECL(int) VMR3WaitForResume(PVM pVM)
    177 {
    178     /*
    179      * The request loop.
    180      */
    181     VMSTATE enmBefore;
    182     int     rc;
    183     for (;;)
    184     {
    185 
    186         /*
    187          * Pending requests which needs servicing?
    188          *
    189          * We check for state changes in addition to status codes when
    190          * servicing requests. (Look after the ifs.)
    191          */
    192         enmBefore = pVM->enmVMState;
    193         if (VM_FF_ISSET(pVM, VM_FF_TERMINATE))
    194         {
    195             rc = VINF_EM_TERMINATE;
    196             break;
    197         }
    198         else if (pVM->vm.s.pReqs)
    199         {
    200             /*
    201              * Service execute in EMT request.
    202              */
    203             rc = VMR3ReqProcess(pVM);
     247            rc = VMR3ReqProcessU(pUVM);
    204248            Log(("vmR3EmulationThread: Req rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState));
    205249        }
     
    226270             * Nothing important is pending, so wait for something.
    227271             */
    228             rc = VMR3Wait(pVM);
     272            rc = VMR3WaitU(pUVM);
    229273            if (VBOX_FAILURE(rc))
    230274                break;
     
    235279         */
    236280        if (    rc == VINF_EM_TERMINATE
    237             ||  VM_FF_ISSET(pVM, VM_FF_TERMINATE))
     281            ||  VM_FF_ISSET(pVM, VM_FF_TERMINATE)
     282            ||  pUVM->vm.s.fTerminateEMT)
    238283            break;
    239284
     
    245290        if (    VBOX_SUCCESS(rc)
    246291            &&  enmBefore != pVM->enmVMState
    247             &&  (pVM->enmVMState == VMSTATE_RUNNING))
     292            &&  pVM->enmVMState == VMSTATE_RUNNING)
    248293        {
    249294            /* Only valid exit reason. */
     
    254299
    255300    /* Return to the main loop in vmR3EmulationThread, which will clean up for us. */
    256     longjmp(pVM->vm.s.emtJumpEnv, 1);
     301    longjmp(pUVM->vm.s.emtJumpEnv, 1);
    257302}
    258303
     
    268313    switch (enmMethod)
    269314    {
    270         case VMHALTMETHOD_DEFAULT:  return "default";
    271         case VMHALTMETHOD_OLD:      return "old";
    272         case VMHALTMETHOD_1:        return "method1";
    273         //case VMHALTMETHOD_2:        return "method2";
    274         case VMHALTMETHOD_GLOBAL_1: return "global1";
    275         default:                    return "unknown";
     315        case VMHALTMETHOD_BOOTSTRAP:    return "bootstrap";
     316        case VMHALTMETHOD_DEFAULT:      return "default";
     317        case VMHALTMETHOD_OLD:          return "old";
     318        case VMHALTMETHOD_1:            return "method1";
     319        //case VMHALTMETHOD_2:            return "method2";
     320        case VMHALTMETHOD_GLOBAL_1:     return "global1";
     321        default:                        return "unknown";
    276322    }
    277323}
     
    280326/**
    281327 * The old halt loop.
    282  */
    283 static DECLCALLBACK(int) vmR3HaltOldDoHalt(PVM pVM, const uint32_t fMask, uint64_t /* u64Now*/)
     328 *
     329 * @param   pUVM            Pointer to the user mode VM structure.
     330 */
     331static DECLCALLBACK(int) vmR3HaltOldDoHalt(PUVM pUVM, const uint32_t fMask, uint64_t /* u64Now*/)
    284332{
    285333    /*
    286334     * Halt loop.
    287335     */
     336    PVM pVM = pUVM->pVM;
    288337    int rc = VINF_SUCCESS;
    289     ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);
     338    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true);
    290339    //unsigned cLoops = 0;
    291340    for (;;)
     
    296345         * addition to perhaps set an FF.
    297346         */
    298         STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltPoll, a);
     347        STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltPoll, a);
    299348        PDMR3Poll(pVM);
    300         STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltPoll, a);
    301         STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltTimers, b);
     349        STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltPoll, a);
     350        STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltTimers, b);
    302351        TMR3TimerQueuesDo(pVM);
    303         STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltTimers, b);
     352        STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltTimers, b);
    304353        if (VM_FF_ISPENDING(pVM, fMask))
    305354            break;
     
    324373            {
    325374                //RTLogPrintf("u64NanoTS=%RI64 cLoops=%d yield", u64NanoTS, cLoops++);
    326                 STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltYield, a);
     375                STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltYield, a);
    327376                RTThreadYield(); /* this is the best we can do here */
    328                 STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltYield, a);
     377                STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltYield, a);
    329378            }
    330379            else if (u64NanoTS < 2000000)
    331380            {
    332381                //RTLogPrintf("u64NanoTS=%RI64 cLoops=%d sleep 1ms", u64NanoTS, cLoops++);
    333                 STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltBlock, a);
    334                 rc = RTSemEventWait(pVM->vm.s.EventSemWait, 1);
    335                 STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltBlock, a);
     382                STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltBlock, a);
     383                rc = RTSemEventWait(pUVM->vm.s.EventSemWait, 1);
     384                STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltBlock, a);
    336385            }
    337386            else
    338387            {
    339388                //RTLogPrintf("u64NanoTS=%RI64 cLoops=%d sleep %dms", u64NanoTS, cLoops++, (uint32_t)RT_MIN((u64NanoTS - 500000) / 1000000, 15));
    340                 STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltBlock, a);
    341                 rc = RTSemEventWait(pVM->vm.s.EventSemWait, RT_MIN((u64NanoTS - 1000000) / 1000000, 15));
    342                 STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltBlock, a);
     389                STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltBlock, a);
     390                rc = RTSemEventWait(pUVM->vm.s.EventSemWait, RT_MIN((u64NanoTS - 1000000) / 1000000, 15));
     391                STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltBlock, a);
    343392            }
    344393            //uint64_t u64Slept = RTTimeNanoTS() - u64Start;
     
    351400            AssertRC(rc != VERR_INTERRUPTED);
    352401            AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc));
     402            ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    353403            VM_FF_SET(pVM, VM_FF_TERMINATE);
    354404            rc = VERR_INTERNAL_ERROR;
     
    357407    }
    358408
     409    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false);
    359410    return rc;
    360411}
     
    367418 * @param   pVM     The VM handle.
    368419 */
    369 static int vmR3HaltMethod12ReadConfig(PVM pVM)
     420static int vmR3HaltMethod12ReadConfigU(PUVM pUVM)
    370421{
    371422    /*
     
    373424     */
    374425#if 1 /* DEBUGGING STUFF - REMOVE LATER */
    375     pVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4;
    376     pVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg =   2*1000000;
    377     pVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg =  75*1000000;
    378     pVM->vm.s.Halt.Method12.u32StartSpinningCfg    =  30*1000000;
    379     pVM->vm.s.Halt.Method12.u32StopSpinningCfg     =  20*1000000;
     426    pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4;
     427    pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg =   2*1000000;
     428    pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg =  75*1000000;
     429    pUVM->vm.s.Halt.Method12.u32StartSpinningCfg    =  30*1000000;
     430    pUVM->vm.s.Halt.Method12.u32StopSpinningCfg     =  20*1000000;
    380431#else
    381     pVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4;
    382     pVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg =   5*1000000;
    383     pVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = 200*1000000;
    384     pVM->vm.s.Halt.Method12.u32StartSpinningCfg    =  20*1000000;
    385     pVM->vm.s.Halt.Method12.u32StopSpinningCfg     =   2*1000000;
     432    pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4;
     433    pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg =   5*1000000;
     434    pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = 200*1000000;
     435    pUVM->vm.s.Halt.Method12.u32StartSpinningCfg    =  20*1000000;
     436    pUVM->vm.s.Halt.Method12.u32StopSpinningCfg     =   2*1000000;
    386437#endif
    387438
     
    392443     * here right now. sorry.
    393444     */
    394     PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "/VMM/HaltedMethod1");
     445    PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pUVM->pVM), "/VMM/HaltedMethod1");
    395446    if (pCfg)
    396447    {
    397448        uint32_t u32;
    398449        if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "LagBlockIntervalDivisor", &u32)))
    399             pVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = u32;
     450            pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = u32;
    400451        if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "MinBlockInterval", &u32)))
    401             pVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = u32;
     452            pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = u32;
    402453        if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "MaxBlockInterval", &u32)))
    403             pVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = u32;
     454            pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = u32;
    404455        if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "StartSpinning", &u32)))
    405             pVM->vm.s.Halt.Method12.u32StartSpinningCfg = u32;
     456            pUVM->vm.s.Halt.Method12.u32StartSpinningCfg = u32;
    406457        if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "StopSpinning", &u32)))
    407             pVM->vm.s.Halt.Method12.u32StopSpinningCfg = u32;
     458            pUVM->vm.s.Halt.Method12.u32StopSpinningCfg = u32;
    408459        LogRel(("HaltedMethod1 config: %d/%d/%d/%d/%d\n",
    409                 pVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg,
    410                 pVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg,
    411                 pVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg,
    412                 pVM->vm.s.Halt.Method12.u32StartSpinningCfg,
    413                 pVM->vm.s.Halt.Method12.u32StopSpinningCfg));
     460                pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg,
     461                pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg,
     462                pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg,
     463                pUVM->vm.s.Halt.Method12.u32StartSpinningCfg,
     464                pUVM->vm.s.Halt.Method12.u32StopSpinningCfg));
    414465    }
    415466
     
    422473 *
    423474 * @return VBox status code.
    424  * @param   pVM     The VM handle.
    425  */
    426 static DECLCALLBACK(int) vmR3HaltMethod1Init(PVM pVM)
    427 {
    428     return vmR3HaltMethod12ReadConfig(pVM);
     475 * @param   pUVM            Pointer to the user mode VM structure.
     476 */
     477static DECLCALLBACK(int) vmR3HaltMethod1Init(PUVM pUVM)
     478{
     479    return vmR3HaltMethod12ReadConfigU(pUVM);
    429480}
    430481
     
    435486 * the lag has been eliminated.
    436487 */
    437 static DECLCALLBACK(int) vmR3HaltMethod1Halt(PVM pVM, const uint32_t fMask, uint64_t u64Now)
    438 {
     488static DECLCALLBACK(int) vmR3HaltMethod1Halt(PUVM pUVM, const uint32_t fMask, uint64_t u64Now)
     489{
     490    PVM pVM = pUVM->pVM;
     491
    439492    /*
    440493     * To simplify things, we decide up-front whether we should switch to spinning or
     
    448501    if (u32CatchUpPct /* non-zero if catching up */)
    449502    {
    450         if (pVM->vm.s.Halt.Method12.u64StartSpinTS)
    451         {
    452             fSpinning = TMVirtualSyncGetLag(pVM) >= pVM->vm.s.Halt.Method12.u32StopSpinningCfg;
     503        if (pUVM->vm.s.Halt.Method12.u64StartSpinTS)
     504        {
     505            fSpinning = TMVirtualSyncGetLag(pVM) >= pUVM->vm.s.Halt.Method12.u32StopSpinningCfg;
    453506            if (fSpinning)
    454507            {
    455508                uint64_t u64Lag = TMVirtualSyncGetLag(pVM);
    456                 fBlockOnce = u64Now - pVM->vm.s.Halt.Method12.u64LastBlockTS
    457                            > RT_MAX(pVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg,
    458                                     RT_MIN(u64Lag / pVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg,
    459                                            pVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg));
     509                fBlockOnce = u64Now - pUVM->vm.s.Halt.Method12.u64LastBlockTS
     510                           > RT_MAX(pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg,
     511                                    RT_MIN(u64Lag / pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg,
     512                                           pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg));
    460513            }
    461514            else
    462515            {
    463                 //RTLogRelPrintf("Stopped spinning (%u ms)\n", (u64Now - pVM->vm.s.Halt.Method12.u64StartSpinTS) / 1000000);
    464                 pVM->vm.s.Halt.Method12.u64StartSpinTS = 0;
     516                //RTLogRelPrintf("Stopped spinning (%u ms)\n", (u64Now - pUVM->vm.s.Halt.Method12.u64StartSpinTS) / 1000000);
     517                pUVM->vm.s.Halt.Method12.u64StartSpinTS = 0;
    465518            }
    466519        }
    467520        else
    468521        {
    469             fSpinning = TMVirtualSyncGetLag(pVM) >= pVM->vm.s.Halt.Method12.u32StartSpinningCfg;
     522            fSpinning = TMVirtualSyncGetLag(pVM) >= pUVM->vm.s.Halt.Method12.u32StartSpinningCfg;
    470523            if (fSpinning)
    471                 pVM->vm.s.Halt.Method12.u64StartSpinTS = u64Now;
    472         }
    473     }
    474     else if (pVM->vm.s.Halt.Method12.u64StartSpinTS)
    475     {
    476         //RTLogRelPrintf("Stopped spinning (%u ms)\n", (u64Now - pVM->vm.s.Halt.Method12.u64StartSpinTS) / 1000000);
    477         pVM->vm.s.Halt.Method12.u64StartSpinTS = 0;
     524                pUVM->vm.s.Halt.Method12.u64StartSpinTS = u64Now;
     525        }
     526    }
     527    else if (pUVM->vm.s.Halt.Method12.u64StartSpinTS)
     528    {
     529        //RTLogRelPrintf("Stopped spinning (%u ms)\n", (u64Now - pUVM->vm.s.Halt.Method12.u64StartSpinTS) / 1000000);
     530        pUVM->vm.s.Halt.Method12.u64StartSpinTS = 0;
    478531    }
    479532
     
    482535     */
    483536    int rc = VINF_SUCCESS;
    484     ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);
     537    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true);
    485538    unsigned cLoops = 0;
    486539    for (;; cLoops++)
     
    489542         * Work the timers and check if we can exit.
    490543         */
    491         STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltPoll, a);
     544        STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltPoll, a);
    492545        PDMR3Poll(pVM);
    493         STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltPoll, a);
    494         STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltTimers, b);
     546        STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltPoll, a);
     547        STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltTimers, b);
    495548        TMR3TimerQueuesDo(pVM);
    496         STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltTimers, b);
     549        STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltTimers, b);
    497550        if (VM_FF_ISPENDING(pVM, fMask))
    498551            break;
     
    516569#endif
    517570        {
    518             const uint64_t Start = pVM->vm.s.Halt.Method12.u64LastBlockTS = RTTimeNanoTS();
     571            const uint64_t Start = pUVM->vm.s.Halt.Method12.u64LastBlockTS = RTTimeNanoTS();
    519572            VMMR3YieldStop(pVM);
    520573
    521574            uint32_t cMilliSecs = RT_MIN(u64NanoTS / 1000000, 15);
    522             if (cMilliSecs <= pVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg)
     575            if (cMilliSecs <= pUVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg)
    523576                cMilliSecs = 1;
    524577            else
    525                 cMilliSecs -= pVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg;
     578                cMilliSecs -= pUVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg;
    526579            //RTLogRelPrintf("u64NanoTS=%RI64 cLoops=%3d sleep %02dms (%7RU64) ", u64NanoTS, cLoops, cMilliSecs, u64NanoTS);
    527             STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltBlock, a);
    528             rc = RTSemEventWait(pVM->vm.s.EventSemWait, cMilliSecs);
    529             STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltBlock, a);
     580            STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltBlock, a);
     581            rc = RTSemEventWait(pUVM->vm.s.EventSemWait, cMilliSecs);
     582            STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltBlock, a);
    530583            if (rc == VERR_TIMEOUT)
    531584                rc = VINF_SUCCESS;
     
    534587                AssertRC(rc != VERR_INTERRUPTED);
    535588                AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc));
     589                ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    536590                VM_FF_SET(pVM, VM_FF_TERMINATE);
    537591                rc = VERR_INTERNAL_ERROR;
     
    544598             */
    545599            const uint64_t Elapsed = RTTimeNanoTS() - Start;
    546             pVM->vm.s.Halt.Method12.cNSBlocked += Elapsed;
     600            pUVM->vm.s.Halt.Method12.cNSBlocked += Elapsed;
    547601            if (Elapsed > u64NanoTS)
    548                 pVM->vm.s.Halt.Method12.cNSBlockedTooLong += Elapsed - u64NanoTS;
    549             pVM->vm.s.Halt.Method12.cBlocks++;
    550             if (!(pVM->vm.s.Halt.Method12.cBlocks & 0xf))
    551             {
    552                 pVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg = pVM->vm.s.Halt.Method12.cNSBlockedTooLong / pVM->vm.s.Halt.Method12.cBlocks;
    553                 if (!(pVM->vm.s.Halt.Method12.cBlocks & 0x3f))
     602                pUVM->vm.s.Halt.Method12.cNSBlockedTooLong += Elapsed - u64NanoTS;
     603            pUVM->vm.s.Halt.Method12.cBlocks++;
     604            if (!(pUVM->vm.s.Halt.Method12.cBlocks & 0xf))
     605            {
     606                pUVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg = pUVM->vm.s.Halt.Method12.cNSBlockedTooLong / pUVM->vm.s.Halt.Method12.cBlocks;
     607                if (!(pUVM->vm.s.Halt.Method12.cBlocks & 0x3f))
    554608                {
    555                     pVM->vm.s.Halt.Method12.cNSBlockedTooLong = pVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg * 0x40;
    556                     pVM->vm.s.Halt.Method12.cBlocks = 0x40;
     609                    pUVM->vm.s.Halt.Method12.cNSBlockedTooLong = pUVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg * 0x40;
     610                    pUVM->vm.s.Halt.Method12.cBlocks = 0x40;
    557611                }
    558612            }
     
    569623    //if (fSpinning) RTLogRelPrintf("spun for %RU64 ns %u loops; lag=%RU64 pct=%d\n", RTTimeNanoTS() - u64Now, cLoops, TMVirtualSyncGetLag(pVM), u32CatchUpPct);
    570624
     625    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false);
    571626    return rc;
    572627}
     
    577632 *
    578633 * @return VBox status code.
    579  * @param   pVM     The VM handle.
    580  */
    581 static DECLCALLBACK(int) vmR3HaltGlobal1Init(PVM pVM)
     634 * @param   pUVM            Pointer to the user mode VM structure.
     635 */
     636static DECLCALLBACK(int) vmR3HaltGlobal1Init(PUVM pUVM)
    582637{
    583638    return VINF_SUCCESS;
     
    589644 * try take care of the global scheduling of EMT threads.
    590645 */
    591 static DECLCALLBACK(int) vmR3HaltGlobal1Halt(PVM pVM, const uint32_t fMask, uint64_t u64Now)
    592 {
     646static DECLCALLBACK(int) vmR3HaltGlobal1Halt(PUVM pUVM, const uint32_t fMask, uint64_t u64Now)
     647{
     648    PVM pVM = pUVM->pVM;
     649
    593650    /*
    594651     * Halt loop.
    595652     */
    596653    int rc = VINF_SUCCESS;
    597     ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);
     654    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true);
    598655    unsigned cLoops = 0;
    599656    for (;; cLoops++)
     
    602659         * Work the timers and check if we can exit.
    603660         */
    604         STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltPoll, a);
     661        STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltPoll, a);
    605662        PDMR3Poll(pVM);
    606         STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltPoll, a);
    607         STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltTimers, b);
     663        STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltPoll, a);
     664        STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltTimers, b);
    608665        TMR3TimerQueuesDo(pVM);
    609         STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltTimers, b);
     666        STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltTimers, b);
    610667        if (VM_FF_ISPENDING(pVM, fMask))
    611668            break;
     
    625682        {
    626683            VMMR3YieldStop(pVM);
    627             ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);
    628684            if (VM_FF_ISPENDING(pVM, fMask))
    629685                break;
    630686
    631687            //RTLogRelPrintf("u64NanoTS=%RI64 cLoops=%3d sleep %02dms (%7RU64) ", u64NanoTS, cLoops, cMilliSecs, u64NanoTS);
    632             STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltBlock, c);
     688            STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltBlock, c);
    633689            rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_SCHED_HALT, u64GipTime, NULL);
    634             STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltBlock, c);
     690            STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltBlock, c);
    635691            if (rc == VERR_INTERRUPTED)
    636692                rc = VINF_SUCCESS;
     
    638694            {
    639695                AssertMsgFailed(("VMMR0_DO_GVMM_SCHED_HALT->%Vrc\n", rc));
     696                ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    640697                VM_FF_SET(pVM, VM_FF_TERMINATE);
    641698                rc = VERR_INTERNAL_ERROR;
     
    649706        else if (!(cLoops & 0x1fff))
    650707        {
    651             STAM_REL_PROFILE_START(&pVM->vm.s.StatHaltYield, d);
     708            STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltYield, d);
    652709            rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_SCHED_POLL, false /* don't yield */, NULL);
    653             STAM_REL_PROFILE_STOP(&pVM->vm.s.StatHaltYield, d);
     710            STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltYield, d);
    654711        }
    655712    }
    656713    //if (fSpinning) RTLogRelPrintf("spun for %RU64 ns %u loops; lag=%RU64 pct=%d\n", RTTimeNanoTS() - u64Now, cLoops, TMVirtualSyncGetLag(pVM), u32CatchUpPct);
    657714
     715    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false);
    658716    return rc;
    659717}
     
    664722 *
    665723 * @returns VBox status code.
    666  * @param   pVM     The VM handle.
    667  */
    668 static DECLCALLBACK(int) vmR3HaltGlobal1Wait(PVM pVM)
    669 {
     724 * @param   pUVM            Pointer to the user mode VM structure.
     725 */
     726static DECLCALLBACK(int) vmR3HaltGlobal1Wait(PUVM pUVM)
     727{
     728    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true);
     729
     730    PVM pVM = pUVM->pVM;
    670731    int rc = VINF_SUCCESS;
    671     ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);
    672732    for (;;)
    673733    {
     
    688748        {
    689749            AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc));
     750            ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    690751            VM_FF_SET(pVM, VM_FF_TERMINATE);
    691752            rc = VERR_INTERNAL_ERROR;
     
    694755
    695756    }
    696     ASMAtomicXchgU32(&pVM->vm.s.fWait, 0);
     757
     758    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false);
    697759    return rc;
    698760}
     
    702764 * The global 1 halt method - VMR3NotifyFF() worker.
    703765 *
    704  * @param   pVM             The VM handle.
    705  * @param   fNotifiedREM    Se VMR3NotifyFF().
    706  */
    707 static DECLCALLBACK(void) vmR3HaltGlobal1NotifyFF(PVM pVM, bool fNotifiedREM)
    708 {
    709     if (pVM->vm.s.fWait)
    710     {
    711         int rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_SCHED_WAKE_UP, 0, NULL);
     766 * @param   pUVM            Pointer to the user mode VM structure.
     767 * @param   fNotifiedREM    See VMR3NotifyFF().
     768 */
     769static DECLCALLBACK(void) vmR3HaltGlobal1NotifyFF(PUVM pUVM, bool fNotifiedREM)
     770{
     771    if (pUVM->vm.s.fWait)
     772    {
     773        int rc = SUPCallVMMR0Ex(pUVM->pVM->pVMR0, VMMR0_DO_GVMM_SCHED_WAKE_UP, 0, NULL);
    712774        AssertRC(rc);
    713775    }
    714776    else if (!fNotifiedREM)
    715         REMR3NotifyFF(pVM);
    716 }
    717 
    718 
    719 /**
    720  * Default VMR3Wait() worker.
     777        REMR3NotifyFF(pUVM->pVM);
     778}
     779
     780
     781/**
     782 * Bootstrap VMR3Wait() worker.
    721783 *
    722784 * @returns VBox status code.
    723  * @param   pVM     The VM handle.
    724  */
    725 static DECLCALLBACK(int) vmR3DefaultWait(PVM pVM)
    726 {
     785 * @param   pUVM            Pointer to the user mode VM structure.
     786 */
     787static DECLCALLBACK(int) vmR3BootstrapWait(PUVM pUVM)
     788{
     789    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true);
     790
    727791    int rc = VINF_SUCCESS;
    728     ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);
    729792    for (;;)
    730793    {
     
    732795         * Check Relevant FFs.
    733796         */
    734         if (VM_FF_ISPENDING(pVM, VM_FF_EXTERNAL_SUSPENDED_MASK))
     797        if (pUVM->vm.s.pReqs)
     798            break;
     799        if (    pUVM->pVM
     800            &&  VM_FF_ISPENDING(pUVM->pVM, VM_FF_EXTERNAL_SUSPENDED_MASK))
    735801            break;
    736802
     
    739805         * anything needs our attention.
    740806         */
    741         rc = RTSemEventWait(pVM->vm.s.EventSemWait, 1000);
     807        rc = RTSemEventWait(pUVM->vm.s.EventSemWait, 1000);
    742808        if (rc == VERR_TIMEOUT)
    743809            rc = VINF_SUCCESS;
     
    745811        {
    746812            AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc));
     813            ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
     814            if (pUVM->pVM)
     815                VM_FF_SET(pUVM->pVM, VM_FF_TERMINATE);
     816            rc = VERR_INTERNAL_ERROR;
     817            break;
     818        }
     819
     820    }
     821
     822    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false);
     823    return rc;
     824}
     825
     826
     827/**
     828 * Bootstrap VMR3NotifyFF() worker.
     829 *
     830 * @param   pUVM            Pointer to the user mode VM structure.
     831 * @param   fNotifiedREM    See VMR3NotifyFF().
     832 */
     833static DECLCALLBACK(void) vmR3BootstrapNotifyFF(PUVM pUVM, bool fNotifiedREM)
     834{
     835    if (pUVM->vm.s.fWait)
     836    {
     837        int rc = RTSemEventSignal(pUVM->vm.s.EventSemWait);
     838        AssertRC(rc);
     839    }
     840}
     841
     842
     843
     844/**
     845 * Default VMR3Wait() worker.
     846 *
     847 * @returns VBox status code.
     848 * @param   pUVM            Pointer to the user mode VM structure.
     849 */
     850static DECLCALLBACK(int) vmR3DefaultWait(PUVM pUVM)
     851{
     852    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true);
     853
     854    PVM pVM = pUVM->pVM;
     855    int rc = VINF_SUCCESS;
     856    for (;;)
     857    {
     858        /*
     859         * Check Relevant FFs.
     860         */
     861        if (VM_FF_ISPENDING(pVM, VM_FF_EXTERNAL_SUSPENDED_MASK))
     862            break;
     863
     864        /*
     865         * Wait for a while. Someone will wake us up or interrupt the call if
     866         * anything needs our attention.
     867         */
     868        rc = RTSemEventWait(pUVM->vm.s.EventSemWait, 1000);
     869        if (rc == VERR_TIMEOUT)
     870            rc = VINF_SUCCESS;
     871        else if (VBOX_FAILURE(rc))
     872        {
     873            AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc));
     874            ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true);
    747875            VM_FF_SET(pVM, VM_FF_TERMINATE);
    748876            rc = VERR_INTERNAL_ERROR;
     
    751879
    752880    }
    753     ASMAtomicXchgU32(&pVM->vm.s.fWait, 0);
     881
     882    ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false);
    754883    return rc;
    755884}
     
    759888 * Default VMR3NotifyFF() worker.
    760889 *
    761  * @param   pVM             The VM handle.
    762  * @param   fNotifiedREM    Se VMR3NotifyFF().
    763  */
    764 static DECLCALLBACK(void) vmR3DefaultNotifyFF(PVM pVM, bool fNotifiedREM)
    765 {
    766     if (pVM->vm.s.fWait)
    767     {
    768         int rc = RTSemEventSignal(pVM->vm.s.EventSemWait);
     890 * @param   pUVM            Pointer to the user mode VM structure.
     891 * @param   fNotifiedREM    See VMR3NotifyFF().
     892 */
     893static DECLCALLBACK(void) vmR3DefaultNotifyFF(PUVM pUVM, bool fNotifiedREM)
     894{
     895    if (pUVM->vm.s.fWait)
     896    {
     897        int rc = RTSemEventSignal(pUVM->vm.s.EventSemWait);
    769898        AssertRC(rc);
    770899    }
    771900    else if (!fNotifiedREM)
    772         REMR3NotifyFF(pVM);
     901        REMR3NotifyFF(pUVM->pVM);
    773902}
    774903
     
    783912    VMHALTMETHOD enmHaltMethod;
    784913    /** The init function for loading config and initialize variables. */
    785     DECLR3CALLBACKMEMBER(int,  pfnInit,(PVM pVM));
     914    DECLR3CALLBACKMEMBER(int,  pfnInit,(PUVM pUVM));
    786915    /** The term function. */
    787     DECLR3CALLBACKMEMBER(void, pfnTerm,(PVM pVM));
     916    DECLR3CALLBACKMEMBER(void, pfnTerm,(PUVM pUVM));
    788917    /** The halt function. */
    789     DECLR3CALLBACKMEMBER(int,  pfnHalt,(PVM pVM, const uint32_t fMask, uint64_t u64Now));
     918    DECLR3CALLBACKMEMBER(int,  pfnHalt,(PUVM pUVM, const uint32_t fMask, uint64_t u64Now));
    790919    /** The wait function. */
    791     DECLR3CALLBACKMEMBER(int,  pfnWait,(PVM pVM));
     920    DECLR3CALLBACKMEMBER(int,  pfnWait,(PUVM pUVM));
    792921    /** The notifyFF function. */
    793     DECLR3CALLBACKMEMBER(void, pfnNotifyFF,(PVM pVM, bool fNotifiedREM));
     922    DECLR3CALLBACKMEMBER(void, pfnNotifyFF,(PUVM pUVM, bool fNotifiedREM));
    794923} g_aHaltMethods[] =
    795924{
     925    { VMHALTMETHOD_BOOTSTRAP, NULL,                 NULL,                   NULL,                   vmR3BootstrapWait,      vmR3BootstrapNotifyFF },
    796926    { VMHALTMETHOD_OLD,     NULL,                   NULL,                   vmR3HaltOldDoHalt,      vmR3DefaultWait,        vmR3DefaultNotifyFF },
    797927    { VMHALTMETHOD_1,       vmR3HaltMethod1Init,    NULL,                   vmR3HaltMethod1Halt,    vmR3DefaultWait,        vmR3DefaultNotifyFF },
     
    814944{
    815945    LogFlow(("VMR3NotifyFF:\n"));
    816     g_aHaltMethods[pVM->vm.s.iHaltMethod].pfnNotifyFF(pVM, fNotifiedREM);
     946    PUVM pUVM = pVM->pUVM;
     947    g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnNotifyFF(pUVM, fNotifiedREM);
     948}
     949
     950
     951/**
     952 * Notify the emulation thread (EMT) about pending Forced Action (FF).
     953 *
     954 * This function is called by thread other than EMT to make
     955 * sure EMT wakes up and promptly service an FF request.
     956 *
     957 * @param   pUVM            Pointer to the user mode VM structure.
     958 * @param   fNotifiedREM    Set if REM have already been notified. If clear the
     959 *                          generic REMR3NotifyFF() method is called.
     960 */
     961VMR3DECL(void) VMR3NotifyFFU(PUVM pUVM, bool fNotifiedREM)
     962{
     963    LogFlow(("VMR3NotifyFF:\n"));
     964    g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnNotifyFF(pUVM, fNotifiedREM);
    817965}
    818966
     
    8521000     * Record halt averages for the last second.
    8531001     */
     1002    PUVM pUVM = pVM->pUVM;
    8541003    uint64_t u64Now = RTTimeNanoTS();
    855     int64_t off = u64Now - pVM->vm.s.u64HaltsStartTS;
     1004    int64_t off = u64Now - pUVM->vm.s.u64HaltsStartTS;
    8561005    if (off > 1000000000)
    8571006    {
    858         if (off > _4G || !pVM->vm.s.cHalts)
    859         {
    860             pVM->vm.s.HaltInterval = 1000000000 /* 1 sec */;
    861             pVM->vm.s.HaltFrequency = 1;
     1007        if (off > _4G || !pUVM->vm.s.cHalts)
     1008        {
     1009            pUVM->vm.s.HaltInterval = 1000000000 /* 1 sec */;
     1010            pUVM->vm.s.HaltFrequency = 1;
    8621011        }
    8631012        else
    8641013        {
    865             pVM->vm.s.HaltInterval = (uint32_t)off / pVM->vm.s.cHalts;
    866             pVM->vm.s.HaltFrequency = ASMMultU64ByU32DivByU32(pVM->vm.s.cHalts, 1000000000, (uint32_t)off);
    867         }
    868         pVM->vm.s.u64HaltsStartTS = u64Now;
    869         pVM->vm.s.cHalts = 0;
    870     }
    871     pVM->vm.s.cHalts++;
     1014            pUVM->vm.s.HaltInterval = (uint32_t)off / pUVM->vm.s.cHalts;
     1015            pUVM->vm.s.HaltFrequency = ASMMultU64ByU32DivByU32(pUVM->vm.s.cHalts, 1000000000, (uint32_t)off);
     1016        }
     1017        pUVM->vm.s.u64HaltsStartTS = u64Now;
     1018        pUVM->vm.s.cHalts = 0;
     1019    }
     1020    pUVM->vm.s.cHalts++;
    8721021
    8731022    /*
    8741023     * Do the halt.
    8751024     */
    876     int rc = g_aHaltMethods[pVM->vm.s.iHaltMethod].pfnHalt(pVM, fMask, u64Now);
    877 
    878     /*
    879      * Resume the yielder and tell the world we're not blocking.
    880      */
    881     ASMAtomicXchgU32(&pVM->vm.s.fWait, 0);
     1025    int rc = g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnHalt(pUVM, fMask, u64Now);
     1026
     1027    /*
     1028     * Resume the yielder.
     1029     */
    8821030    VMMR3YieldResume(pVM);
    8831031
     
    8941042 * @returns VINF_SUCCESS unless a fatal error occured. In the latter
    8951043 *          case an appropriate status code is returned.
    896  * @param   pVM         VM handle.
     1044 * @param   pUVM            Pointer to the user mode VM structure.
    8971045 * @thread  The emulation thread.
    8981046 */
    899 VMR3DECL(int) VMR3Wait(PVM pVM)
    900 {
    901     LogFlow(("VMR3Wait:\n"));
     1047VMR3DECL(int) VMR3WaitU(PUVM pUVM)
     1048{
     1049    LogFlow(("VMR3WaitU:\n"));
    9021050
    9031051    /*
    9041052     * Check Relevant FFs.
    9051053     */
    906     if (VM_FF_ISPENDING(pVM, VM_FF_EXTERNAL_SUSPENDED_MASK))
     1054    PVM pVM = pUVM->pVM;
     1055    if (    pVM
     1056        &&  VM_FF_ISPENDING(pVM, VM_FF_EXTERNAL_SUSPENDED_MASK))
    9071057    {
    9081058        LogFlow(("VMR3Wait: returns VINF_SUCCESS (FF %#x)\n", pVM->fForcedActions));
     
    9141064     * doesn't have to special case anything).
    9151065     */
    916     int rc = g_aHaltMethods[pVM->vm.s.iHaltMethod].pfnWait(pVM);
    917     LogFlow(("VMR3Wait: returns %Vrc (FF %#x)\n", rc, pVM->fForcedActions));
     1066    int rc = g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnWait(pUVM);
     1067    LogFlow(("VMR3WaitU: returns %Vrc (FF %#x)\n", rc, pVM ? pVM->fForcedActions : 0));
    9181068    return rc;
    9191069}
     
    9241074 *
    9251075 * @returns VBox status code.
    926  * @param   pVM             The VM handle.
     1076 * @param   pUVM            Pointer to the user mode VM structure.
    9271077 * @param   enmHaltMethod   The new halt method.
    9281078 * @thread  EMT.
    9291079 */
    930 int vmR3SetHaltMethod(PVM pVM, VMHALTMETHOD enmHaltMethod)
    931 {
     1080int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod)
     1081{
     1082    PVM pVM = pUVM->pVM; Assert(pVM);
    9321083    VM_ASSERT_EMT(pVM);
    9331084    AssertReturn(enmHaltMethod > VMHALTMETHOD_INVALID && enmHaltMethod < VMHALTMETHOD_END, VERR_INVALID_PARAMETER);
     
    9671118     * Terminate the old one.
    9681119     */
    969     if (    pVM->vm.s.enmHaltMethod != VMHALTMETHOD_INVALID
    970         &&  g_aHaltMethods[pVM->vm.s.iHaltMethod].pfnTerm)
    971     {
    972         g_aHaltMethods[pVM->vm.s.iHaltMethod].pfnTerm(pVM);
    973         pVM->vm.s.enmHaltMethod = VMHALTMETHOD_INVALID;
     1120    if (    pUVM->vm.s.enmHaltMethod != VMHALTMETHOD_INVALID
     1121        &&  g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnTerm)
     1122    {
     1123        g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnTerm(pUVM);
     1124        pUVM->vm.s.enmHaltMethod = VMHALTMETHOD_INVALID;
    9741125    }
    9751126
     
    9771128     * Init the new one.
    9781129     */
    979     memset(&pVM->vm.s.Halt, 0, sizeof(pVM->vm.s.Halt));
     1130    memset(&pUVM->vm.s.Halt, 0, sizeof(pUVM->vm.s.Halt));
    9801131    if (g_aHaltMethods[i].pfnInit)
    9811132    {
    982         int rc = g_aHaltMethods[i].pfnInit(pVM);
     1133        int rc = g_aHaltMethods[i].pfnInit(pUVM);
    9831134        AssertRCReturn(rc, rc);
    9841135    }
    985     pVM->vm.s.enmHaltMethod = enmHaltMethod;
    986     ASMAtomicXchgU32(&pVM->vm.s.iHaltMethod, i);
     1136    pUVM->vm.s.enmHaltMethod = enmHaltMethod;
     1137
     1138    ASMAtomicWriteU32(&pUVM->vm.s.iHaltMethod, i);
    9871139    return VINF_SUCCESS;
    9881140}
  • trunk/src/VBox/VMM/VMInternal.h

    r6398 r6796  
    192192    /** The usual invalid value. */
    193193    VMHALTMETHOD_INVALID = 0,
     194    /** Use the method used during bootstrapping. */
     195    VMHALTMETHOD_BOOTSTRAP,
    194196    /** Use the default method. */
    195197    VMHALTMETHOD_DEFAULT,
     
    223225     * See VMINT2VM(). */
    224226    RTINT                           offVM;
    225 
    226     /** List of registered reset callbacks. */
    227     R3PTRTYPE(PVMATRESET)           pAtReset;
    228     /** List of registered reset callbacks. */
    229     R3PTRTYPE(PVMATRESET *)         ppAtResetNext;
    230 
    231     /** List of registered state change callbacks. */
    232     R3PTRTYPE(PVMATSTATE)           pAtState;
    233     /** List of registered state change callbacks. */
    234     R3PTRTYPE(PVMATSTATE *)         ppAtStateNext;
    235 
    236     /** List of registered error callbacks. */
    237     R3PTRTYPE(PVMATERROR)           pAtError;
    238     /** List of registered error callbacks. */
    239     R3PTRTYPE(PVMATERROR *)         ppAtErrorNext;
    240 
    241     /** List of registered error callbacks. */
    242     R3PTRTYPE(PVMATRUNTIMEERROR)    pAtRuntimeError;
    243     /** List of registered error callbacks. */
    244     R3PTRTYPE(PVMATRUNTIMEERROR *)  ppAtRuntimeErrorNext;
    245 
     227    /** VM Error Message. */
     228    R3PTRTYPE(PVMERROR)             pErrorR3;
     229    /** VM Runtime Error Message. */
     230    R3PTRTYPE(PVMRUNTIMEERROR)      pRuntimeErrorR3;
     231    /** Set by VMR3SuspendNoSave; cleared by VMR3Resume; signals the VM is in an inconsistent state and saving is not allowed. */
     232    bool                            fPreventSaveState;
     233} VMINT, *PVMINT;
     234
     235
     236/**
     237 * VM internal data kept in the UVM.
     238 */
     239typedef struct VMINTUSERPERVM
     240{
    246241    /** Head of the request queue. Atomic. */
    247     volatile R3PTRTYPE(PVMREQ)      pReqs;
     242    volatile PVMREQ                 pReqs;
    248243    /** The last index used during alloc/free. */
    249244    volatile uint32_t               iReqFree;
    250     /** Array of pointers to lists of free request packets. Atomic. */
    251     volatile R3PTRTYPE(PVMREQ)      apReqFree[9];
    252245    /** Number of free request packets. */
    253246    volatile uint32_t               cReqFree;
    254 
     247    /** Array of pointers to lists of free request packets. Atomic. */
     248    volatile PVMREQ                 apReqFree[9];
     249
     250#ifdef VBOX_WITH_STATISTICS
     251    /** Number of VMR3ReqAlloc returning a new packet. */
     252    STAMCOUNTER                     StatReqAllocNew;
     253    /** Number of VMR3ReqAlloc causing races. */
     254    STAMCOUNTER                     StatReqAllocRaces;
     255    /** Number of VMR3ReqAlloc returning a recycled packet. */
     256    STAMCOUNTER                     StatReqAllocRecycled;
     257    /** Number of VMR3ReqFree calls. */
     258    STAMCOUNTER                     StatReqFree;
     259    /** Number of times the request was actually freed. */
     260    STAMCOUNTER                     StatReqFreeOverflow;
     261#endif
     262
     263    /** Pointer to the support library session.
     264     * Mainly for creation and destruction.. */
     265    PSUPDRVSESSION                  pSession;
     266
     267    /** The handle to the EMT thread. */
     268    RTTHREAD                        ThreadEMT;
     269    /** The native of the EMT thread. */
     270    RTNATIVETHREAD                  NativeThreadEMT;
     271    /** Wait event semaphore. */
     272    RTSEMEVENT                      EventSemWait;
    255273    /** Wait/Idle indicator. */
    256     volatile uint32_t               fWait;
    257     /** Wait event semaphore. */
    258     R3PTRTYPE(RTSEMEVENT)           EventSemWait;
    259 
    260     /** VM Error Message. */
    261     R3PTRTYPE(PVMERROR)             pErrorR3;
    262 
    263     /** VM Runtime Error Message. */
    264     R3PTRTYPE(PVMRUNTIMEERROR)      pRuntimeErrorR3;
    265 
    266     /** Pointer to the DBGC instance data. */
    267     R3PTRTYPE(void *)               pvDBGC;
    268 
     274    bool volatile                   fWait;
     275    /** Force EMT to terminate. */
     276    bool volatile                   fTerminateEMT;
    269277    /** If set the EMT does the final VM cleanup when it exits.
    270278     * If clear the VMR3Destroy() caller does so. */
    271279    bool                            fEMTDoesTheCleanup;
    272 
    273     /** Set by VMR3SuspendNoSave; cleared by VMR3Resume; signals the VM is in an inconsistent state and saving is not allowed. */
    274     bool                            fPreventSaveState;
    275 
    276     /** vmR3EmulationThread longjmp buffer
    277      * @todo r=bird: requires union with padding. See EMInternal.h. */
    278     jmp_buf                         emtJumpEnv;
    279280
    280281    /** @name Generic Halt data
     
    374375    }                               Halt;
    375376
    376     /** @} */
    377 
    378     /** Number of VMR3ReqAlloc returning a new packet. */
    379     STAMCOUNTER                     StatReqAllocNew;
    380     /** Number of VMR3ReqAlloc causing races. */
    381     STAMCOUNTER                     StatReqAllocRaces;
    382     /** Number of VMR3ReqAlloc returning a recycled packet. */
    383     STAMCOUNTER                     StatReqAllocRecycled;
    384     /** Number of VMR3ReqFree calls. */
    385     STAMCOUNTER                     StatReqFree;
    386     /** Number of times the request was actually freed. */
    387     STAMCOUNTER                     StatReqFreeOverflow;
    388 
    389     /** Profiling the halted state; yielding vs blocking. */
     377    /** Profiling the halted state; yielding vs blocking.
     378     * @{ */
    390379    STAMPROFILE                     StatHaltYield;
    391380    STAMPROFILE                     StatHaltBlock;
    392381    STAMPROFILE                     StatHaltTimers;
    393382    STAMPROFILE                     StatHaltPoll;
    394 } VMINT, *PVMINT;
    395 
    396 
    397 /**
    398  * Emulation thread arguments.
    399  */
    400 typedef struct VMEMULATIONTHREADARGS
    401 {
    402     /** Pointer to the VM structure. */
    403     PVM     pVM;
    404 } VMEMULATIONTHREADARGS;
    405 /** Pointer to the emulation thread arguments. */
    406 typedef VMEMULATIONTHREADARGS *PVMEMULATIONTHREADARGS;
     383    /** @} */
     384
     385
     386    /** List of registered reset callbacks. */
     387    PVMATRESET                      pAtReset;
     388    /** List of registered reset callbacks. */
     389    PVMATRESET                     *ppAtResetNext;
     390
     391    /** List of registered state change callbacks. */
     392    PVMATSTATE                      pAtState;
     393    /** List of registered state change callbacks. */
     394    PVMATSTATE                     *ppAtStateNext;
     395
     396    /** List of registered error callbacks. */
     397    PVMATERROR                      pAtError;
     398    /** List of registered error callbacks. */
     399    PVMATERROR                     *ppAtErrorNext;
     400
     401    /** List of registered error callbacks. */
     402    PVMATRUNTIMEERROR               pAtRuntimeError;
     403    /** List of registered error callbacks. */
     404    PVMATRUNTIMEERROR              *ppAtRuntimeErrorNext;
     405
     406    /** Pointer to the DBGC instance data. */
     407    void                           *pvDBGC;
     408
     409
     410    /** vmR3EmulationThread longjmp buffer. Must be last in the structure. */
     411    jmp_buf                         emtJumpEnv;
     412} VMINTUSERPERVM;
     413
     414/** Pointer to the VM internal data kept in the UVM. */
     415typedef VMINTUSERPERVM *PVMINTUSERPERVM;
     416
    407417
    408418DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArg);
    409 int vmR3SetHaltMethod(PVM pVM, VMHALTMETHOD enmHaltMethod);
     419int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod);
    410420DECLCALLBACK(int) vmR3Destroy(PVM pVM);
    411 DECLCALLBACK(void) vmR3SetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);
     421DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);
    412422void vmSetErrorCopy(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args);
    413423DECLCALLBACK(void) vmR3SetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list *args);
    414424void vmSetRuntimeErrorCopy(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list args);
    415 void vmR3DestroyFinalBit(PVM pVM);
     425void vmR3DestroyFinalBitFromEMT(PUVM pUVM);
    416426void vmR3SetState(PVM pVM, VMSTATE enmStateNew);
    417427
  • trunk/src/VBox/VMM/VMMAll/VMAll.cpp

    r5999 r6796  
    7878    va_copy(va2, args); /* Have to make a copy here or GCC will break. */
    7979    PVMREQ pReq;
    80     VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3SetErrorV, 7,  /* ASSUMES 3 source pos args! */
    81                 pVM, rc, RT_SRC_POS_ARGS, pszFormat, &va2);
     80    VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3SetErrorUV, 7,   /* ASSUMES 3 source pos args! */
     81                pVM->pUVM, rc, RT_SRC_POS_ARGS, pszFormat, &va2);
    8282    VMR3ReqFree(pReq);
    8383    va_end(va2);
     
    202202 * containig possible actions (for example, Retry/Ignore). For this reason,
    203203 * an error ID assigned once to some particular error condition should not
    204  * change in the future. The format of this parameter is "someErrorCondition". 
     204 * change in the future. The format of this parameter is "someErrorCondition".
    205205 *
    206206 * @param   pVM             VM handle. Must be non-NULL.
     
    214214 *
    215215 * @thread  Any
    216  * @todo    r=bird: The pausing/suspending of the VM should be done here, we'll just end 
    217  *                  up duplicating code all over the place otherwise. In the case of 
    218  *                  devices/drivers/etc they might not be trusted to pause/suspend the 
     216 * @todo    r=bird: The pausing/suspending of the VM should be done here, we'll just end
     217 *                  up duplicating code all over the place otherwise. In the case of
     218 *                  devices/drivers/etc they might not be trusted to pause/suspend the
    219219 *                  vm even. Change fFatal to fFlags and define action flags and a fatal flag.
    220  *                     
     220 *
    221221 *                  Also, why a string ID and not an enum?
    222222 */
  • trunk/src/VBox/VMM/VMMR0/VMMR0.cpp

    r6528 r6796  
    8383    if (RT_SUCCESS(rc))
    8484    {
    85 #ifdef VBOX_WITH_NEW_PHYS_CODE /* need to test on windows, solaris and darwin. */
     85//#ifdef VBOX_WITH_NEW_PHYS_CODE /* need to test on windows, solaris and darwin. */
    8686        rc = GMMR0Init();
    87 #endif
     87//#endif
    8888        if (RT_SUCCESS(rc))
    8989        {
     
    134134     * Destroy the GMM and GVMM instances.
    135135     */
    136 #ifdef VBOX_WITH_NEW_PHYS_CODE
     136//#ifdef VBOX_WITH_NEW_PHYS_CODE
    137137    GMMR0Term();
    138 #endif
     138//#endif
    139139    GVMMR0Term();
    140140
  • trunk/src/VBox/VMM/VMReq.cpp

    r6274 r6796  
    2525#include "VMInternal.h"
    2626#include <VBox/vm.h>
     27#include <VBox/uvm.h>
    2728
    2829#include <VBox/err.h>
     
    4041*   Internal Functions                                                         *
    4142*******************************************************************************/
    42 static int  vmR3ReqProcessOne(PVM pVM, PVMREQ pReq);
     43static int  vmR3ReqProcessOneU(PUVM pUVM, PVMREQ pReq);
     44
     45
     46/**
     47 * Allocate and queue a call request.
     48 *
     49 * If it's desired to poll on the completion of the request set cMillies
     50 * to 0 and use VMR3ReqWait() to check for completation. In the other case
     51 * use RT_INDEFINITE_WAIT.
     52 * The returned request packet must be freed using VMR3ReqFree().
     53 *
     54 * @returns VBox status code.
     55 *          Will not return VERR_INTERRUPTED.
     56 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
     57 *
     58 * @param   pUVM            Pointer to the user mode VM structure.
     59 * @param   ppReq           Where to store the pointer to the request.
     60 *                          This will be NULL or a valid request pointer not matter what happends.
     61 * @param   cMillies        Number of milliseconds to wait for the request to
     62 *                          be completed. Use RT_INDEFINITE_WAIT to only
     63 *                          wait till it's completed.
     64 * @param   pfnFunction     Pointer to the function to call.
     65 * @param   cArgs           Number of arguments following in the ellipsis.
     66 *                          Not possible to pass 64-bit arguments!
     67 * @param   ...             Function arguments.
     68 */
     69VMR3DECL(int) VMR3ReqCallU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...)
     70{
     71    va_list va;
     72    va_start(va, cArgs);
     73    int rc = VMR3ReqCallVU(pUVM, ppReq, cMillies, VMREQFLAGS_VBOX_STATUS, pfnFunction, cArgs, va);
     74    va_end(va);
     75    return rc;
     76}
    4377
    4478
     
    70104    va_list va;
    71105    va_start(va, cArgs);
    72     int rc = VMR3ReqCallV(pVM, ppReq, cMillies, VMREQFLAGS_VBOX_STATUS, pfnFunction, cArgs, va);
     106    int rc = VMR3ReqCallVU(pVM->pUVM, ppReq, cMillies, VMREQFLAGS_VBOX_STATUS, pfnFunction, cArgs, va);
     107    va_end(va);
     108    return rc;
     109}
     110
     111
     112/**
     113 * Allocate and queue a call request to a void function.
     114 *
     115 * If it's desired to poll on the completion of the request set cMillies
     116 * to 0 and use VMR3ReqWait() to check for completation. In the other case
     117 * use RT_INDEFINITE_WAIT.
     118 * The returned request packet must be freed using VMR3ReqFree().
     119 *
     120 * @returns VBox status code.
     121 *          Will not return VERR_INTERRUPTED.
     122 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
     123 *
     124 * @param   pUVM            Pointer to the user mode VM structure.
     125 * @param   ppReq           Where to store the pointer to the request.
     126 *                          This will be NULL or a valid request pointer not matter what happends.
     127 * @param   cMillies        Number of milliseconds to wait for the request to
     128 *                          be completed. Use RT_INDEFINITE_WAIT to only
     129 *                          wait till it's completed.
     130 * @param   pfnFunction     Pointer to the function to call.
     131 * @param   cArgs           Number of arguments following in the ellipsis.
     132 *                          Not possible to pass 64-bit arguments!
     133 * @param   ...             Function arguments.
     134 */
     135VMR3DECL(int) VMR3ReqCallVoidU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...)
     136{
     137    va_list va;
     138    va_start(va, cArgs);
     139    int rc = VMR3ReqCallVU(pUVM, ppReq, cMillies, VMREQFLAGS_VOID, pfnFunction, cArgs, va);
    73140    va_end(va);
    74141    return rc;
     
    103170    va_list va;
    104171    va_start(va, cArgs);
    105     int rc = VMR3ReqCallV(pVM, ppReq, cMillies, VMREQFLAGS_VOID, pfnFunction, cArgs, va);
     172    int rc = VMR3ReqCallVU(pVM->pUVM, ppReq, cMillies, VMREQFLAGS_VOID, pfnFunction, cArgs, va);
    106173    va_end(va);
    107174    return rc;
     
    138205    va_list va;
    139206    va_start(va, cArgs);
    140     int rc = VMR3ReqCallV(pVM, ppReq, cMillies, fFlags, pfnFunction, cArgs, va);
     207    int rc = VMR3ReqCallVU(pVM->pUVM, ppReq, cMillies, fFlags, pfnFunction, cArgs, va);
    141208    va_end(va);
    142209    return rc;
     
    145212
    146213/**
    147  * Allocate and queue a call request.
     214 * Allocate and queue a call request to a void function.
    148215 *
    149216 * If it's desired to poll on the completion of the request set cMillies
     
    156223 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
    157224 *
    158  * @param   pVM             The VM handle.
     225 * @param   pUVM            Pointer to the user mode VM structure.
     226 * @param   ppReq           Where to store the pointer to the request.
     227 *                          This will be NULL or a valid request pointer not matter what happends, unless fFlags
     228 *                          contains VMREQFLAGS_NO_WAIT when it will be optional and always NULL.
     229 * @param   cMillies        Number of milliseconds to wait for the request to
     230 *                          be completed. Use RT_INDEFINITE_WAIT to only
     231 *                          wait till it's completed.
     232 * @param   fFlags          A combination of the VMREQFLAGS values.
     233 * @param   pfnFunction     Pointer to the function to call.
     234 * @param   cArgs           Number of arguments following in the ellipsis.
     235 *                          Not possible to pass 64-bit arguments!
     236 * @param   ...             Function arguments.
     237 */
     238VMR3DECL(int) VMR3ReqCallU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...)
     239{
     240    va_list va;
     241    va_start(va, cArgs);
     242    int rc = VMR3ReqCallVU(pUVM, ppReq, cMillies, fFlags, pfnFunction, cArgs, va);
     243    va_end(va);
     244    return rc;
     245}
     246
     247
     248/**
     249 * Allocate and queue a call request.
     250 *
     251 * If it's desired to poll on the completion of the request set cMillies
     252 * to 0 and use VMR3ReqWait() to check for completation. In the other case
     253 * use RT_INDEFINITE_WAIT.
     254 * The returned request packet must be freed using VMR3ReqFree().
     255 *
     256 * @returns VBox status code.
     257 *          Will not return VERR_INTERRUPTED.
     258 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed.
     259 *
     260 * @param   pUVM            Pointer to the user mode VM structure.
    159261 * @param   ppReq           Where to store the pointer to the request.
    160262 *                          This will be NULL or a valid request pointer not matter what happends, unless fFlags
     
    169271 * @param   Args            Argument vector.
    170272 */
    171 VMR3DECL(int) VMR3ReqCallV(PVM pVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args)
     273VMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args)
    172274{
    173275    LogFlow(("VMR3ReqCallV: cMillies=%d fFlags=%#x pfnFunction=%p cArgs=%d\n", cMillies, fFlags, pfnFunction, cArgs));
    174276
    175277    /*
    176      * Check input.
    177      */
    178     if (!pfnFunction || !pVM || (fFlags & ~(VMREQFLAGS_RETURN_MASK | VMREQFLAGS_NO_WAIT)))
    179     {
    180         AssertFailed();
    181         return VERR_INVALID_PARAMETER;
    182     }
     278     * Validate input.
     279     */
     280    AssertPtrReturn(pfnFunction, VERR_INVALID_POINTER);
     281    AssertPtrReturn(pUVM, VERR_INVALID_POINTER);
     282    AssertReturn(!(fFlags & ~(VMREQFLAGS_RETURN_MASK | VMREQFLAGS_NO_WAIT)), VERR_INVALID_PARAMETER);
    183283    if (!(fFlags & VMREQFLAGS_NO_WAIT) || ppReq)
    184284    {
    185         Assert(ppReq);
     285        AssertPtrReturn(ppReq, VERR_INVALID_POINTER);
    186286        *ppReq = NULL;
    187287    }
    188288    PVMREQ pReq = NULL;
    189     if (cArgs * sizeof(uintptr_t) > sizeof(pReq->u.Internal.aArgs))
    190     {
    191         AssertMsgFailed(("cArg=%d\n", cArgs));
    192         return VERR_TOO_MUCH_DATA;
    193     }
     289    AssertMsgReturn(cArgs * sizeof(uintptr_t) <= sizeof(pReq->u.Internal.aArgs),
     290                    ("cArg=%d\n", cArgs),
     291                    VERR_TOO_MUCH_DATA);
    194292
    195293    /*
    196294     * Allocate request
    197295     */
    198     int rc = VMR3ReqAlloc(pVM, &pReq, VMREQTYPE_INTERNAL);
     296    int rc = VMR3ReqAllocU(pUVM, &pReq, VMREQTYPE_INTERNAL);
    199297    if (VBOX_FAILURE(rc))
    200298        return rc;
     
    260358 * Joins the list pList with whatever is linked up at *pHead.
    261359 */
    262 static void vmr3ReqJoinFree(PVMINT pVMInt, PVMREQ pList)
     360static void vmr3ReqJoinFree(PVMINTUSERPERVM pVMInt, PVMREQ pList)
    263361{
    264362    /*
     
    272370        {
    273371            const uint32_t i = pVMInt->iReqFree;
    274             vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(i + 2) % ELEMENTS(pVMInt->apReqFree)], pTail->pNext);
     372            vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(i + 2) % RT_ELEMENTS(pVMInt->apReqFree)], pTail->pNext);
    275373
    276374            pTail->pNext = NULL;
    277             vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(i + 2 + (i == pVMInt->iReqFree)) % ELEMENTS(pVMInt->apReqFree)], pTail->pNext);
     375            vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(i + 2 + (i == pVMInt->iReqFree)) % RT_ELEMENTS(pVMInt->apReqFree)], pTail->pNext);
    278376            return;
    279377        }
    280378        pTail = pTail->pNext;
    281379    }
    282     vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(pVMInt->iReqFree + 2) % ELEMENTS(pVMInt->apReqFree)], pList);
     380    vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(pVMInt->iReqFree + 2) % RT_ELEMENTS(pVMInt->apReqFree)], pList);
    283381}
    284382
     
    298396VMR3DECL(int) VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType)
    299397{
     398    return VMR3ReqAllocU(pVM->pUVM, ppReq, enmType);
     399}
     400
     401
     402/**
     403 * Allocates a request packet.
     404 *
     405 * The caller allocates a request packet, fills in the request data
     406 * union and queues the request.
     407 *
     408 * @returns VBox status code.
     409 *
     410 * @param   pUVM            Pointer to the user mode VM structure.
     411 * @param   ppReq           Where to store the pointer to the allocated packet.
     412 * @param   enmType         Package type.
     413 */
     414VMR3DECL(int) VMR3ReqAllocU(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType)
     415{
    300416    /*
    301417     * Validate input.
    302418     */
    303     if (    enmType < VMREQTYPE_INVALID
    304         ||  enmType > VMREQTYPE_MAX)
    305     {
    306         AssertMsgFailed(("Invalid package type %d valid range %d-%d inclusivly.\n",
    307                          enmType, VMREQTYPE_INVALID + 1, VMREQTYPE_MAX - 1));
    308         return VERR_VM_REQUEST_INVALID_TYPE;
    309     }
     419    AssertMsgReturn(enmType > VMREQTYPE_INVALID && enmType < VMREQTYPE_MAX,
     420                    ("Invalid package type %d valid range %d-%d inclusivly.\n",
     421                     enmType, VMREQTYPE_INVALID + 1, VMREQTYPE_MAX - 1),
     422                    VERR_VM_REQUEST_INVALID_TYPE);
     423    AssertPtrReturn(ppReq, VERR_INVALID_POINTER);
    310424
    311425    /*
     
    314428     * of mine to avoid locks.
    315429     */
    316     int cTries = ELEMENTS(pVM->vm.s.apReqFree) * 2;
     430    int cTries = RT_ELEMENTS(pUVM->vm.s.apReqFree) * 2;
    317431    while (--cTries >= 0)
    318432    {
    319         PVMREQ volatile *ppHead = &pVM->vm.s.apReqFree[ASMAtomicIncU32(&pVM->vm.s.iReqFree) % ELEMENTS(pVM->vm.s.apReqFree)];
     433        PVMREQ volatile *ppHead = &pUVM->vm.s.apReqFree[ASMAtomicIncU32(&pUVM->vm.s.iReqFree) % RT_ELEMENTS(pUVM->vm.s.apReqFree)];
    320434#if 0 /* sad, but this won't work safely because the reading of pReq->pNext. */
    321435        PVMREQ pNext = NULL;
     
    337451                &&  !ASMAtomicCmpXchgPtr((void * volatile *)ppHead, pNext, NULL))
    338452            {
    339                 STAM_COUNTER_INC(&pVM->vm.s.StatReqAllocRaces);
    340                 vmr3ReqJoinFree(&pVM->vm.s, pReq->pNext);
     453                STAM_COUNTER_INC(&pUVM->vm.s.StatReqAllocRaces);
     454                vmr3ReqJoinFree(&pUVM->vm.s, pReq->pNext);
    341455            }
    342456#endif
    343             ASMAtomicDecU32(&pVM->vm.s.cReqFree);
     457            ASMAtomicDecU32(&pUVM->vm.s.cReqFree);
    344458
    345459            /*
     
    372486            Assert(pReq->enmType == VMREQTYPE_INVALID);
    373487            Assert(pReq->enmState == VMREQSTATE_FREE);
    374             Assert(pReq->pVM == pVM);
     488            Assert(pReq->pUVM == pUVM);
    375489            ASMAtomicXchgSize(&pReq->pNext, NULL);
    376490            pReq->enmState = VMREQSTATE_ALLOCATED;
     
    380494
    381495            *ppReq = pReq;
    382             STAM_COUNTER_INC(&pVM->vm.s.StatReqAllocRecycled);
     496            STAM_COUNTER_INC(&pUVM->vm.s.StatReqAllocRecycled);
    383497            LogFlow(("VMR3ReqAlloc: returns VINF_SUCCESS *ppReq=%p recycled\n", pReq));
    384498            return VINF_SUCCESS;
     
    389503     * Ok allocate one.
    390504     */
    391     PVMREQ pReq = (PVMREQ)MMR3HeapAlloc(pVM, MM_TAG_VM_REQ, sizeof(*pReq));
     505    PVMREQ pReq = (PVMREQ)MMR3HeapAllocU(pUVM, MM_TAG_VM_REQ, sizeof(*pReq));
    392506    if (!pReq)
    393507        return VERR_NO_MEMORY;
     
    408522     */
    409523    pReq->pNext    = NULL;
    410     pReq->pVM      = pVM;
     524    pReq->pUVM     = pUVM;
    411525    pReq->enmState = VMREQSTATE_ALLOCATED;
    412526    pReq->iStatus  = VERR_VM_REQUEST_STATUS_STILL_PENDING;
     
    416530
    417531    *ppReq = pReq;
    418     STAM_COUNTER_INC(&pVM->vm.s.StatReqAllocNew);
     532    STAM_COUNTER_INC(&pUVM->vm.s.StatReqAllocNew);
    419533    LogFlow(("VMR3ReqAlloc: returns VINF_SUCCESS *ppReq=%p new\n", pReq));
    420534    return VINF_SUCCESS;
     
    437551    if (!pReq)
    438552        return VINF_SUCCESS;
    439 
    440     STAM_COUNTER_INC(&pReq->pVM->vm.s.StatReqFree);
    441553
    442554    /*
     
    460572    pReq->enmType  = VMREQTYPE_INVALID;
    461573
    462     PVM pVM = pReq->pVM;
    463     if (pVM->vm.s.cReqFree < 128)
    464     {
    465         ASMAtomicIncU32(&pVM->vm.s.cReqFree);
    466         PVMREQ volatile *ppHead = &pVM->vm.s.apReqFree[ASMAtomicIncU32(&pVM->vm.s.iReqFree) % ELEMENTS(pVM->vm.s.apReqFree)];
     574    PUVM pUVM = pReq->pUVM;
     575    STAM_COUNTER_INC(&pUVM->vm.s.StatReqFree);
     576
     577    if (pUVM->vm.s.cReqFree < 128)
     578    {
     579        ASMAtomicIncU32(&pUVM->vm.s.cReqFree);
     580        PVMREQ volatile *ppHead = &pUVM->vm.s.apReqFree[ASMAtomicIncU32(&pUVM->vm.s.iReqFree) % RT_ELEMENTS(pUVM->vm.s.apReqFree)];
    467581        PVMREQ pNext;
    468582        do
     
    474588    else
    475589    {
    476         STAM_COUNTER_INC(&pReq->pVM->vm.s.StatReqFreeOverflow);
     590        STAM_COUNTER_INC(&pReq->pUVM->vm.s.StatReqFreeOverflow);
    477591        RTSemEventDestroy(pReq->EventSem);
    478592        MMR3HeapFree(pReq);
     
    506620     * Verify the supplied package.
    507621     */
    508     if (pReq->enmState != VMREQSTATE_ALLOCATED)
    509     {
    510         AssertMsgFailed(("Invalid state %d\n", pReq->enmState));
    511         return VERR_VM_REQUEST_STATE;
    512     }
    513     if (   !pReq->pVM
    514         ||  pReq->pNext
    515         ||  !pReq->EventSem)
    516     {
    517         AssertMsgFailed(("Invalid request package! Anyone cooking their own packages???\n"));
    518         return VERR_VM_REQUEST_INVALID_PACKAGE;
    519     }
    520     if (    pReq->enmType < VMREQTYPE_INVALID
    521         || pReq->enmType > VMREQTYPE_MAX)
    522     {
    523         AssertMsgFailed(("Invalid package type %d valid range %d-%d inclusivly. This was verified on alloc too...\n",
    524                          pReq->enmType, VMREQTYPE_INVALID + 1, VMREQTYPE_MAX - 1));
    525         return VERR_VM_REQUEST_INVALID_TYPE;
    526     }
     622    AssertMsgReturn(pReq->enmState == VMREQSTATE_ALLOCATED, ("%d\n", pReq->enmState), VERR_VM_REQUEST_STATE);
     623    AssertMsgReturn(    VALID_PTR(pReq->pUVM)
     624                    &&  !pReq->pNext
     625                    &&  pReq->EventSem != NIL_RTSEMEVENT,
     626                    ("Invalid request package! Anyone cooking their own packages???\n"),
     627                    VERR_VM_REQUEST_INVALID_PACKAGE);
     628    AssertMsgReturn(    pReq->enmType > VMREQTYPE_INVALID
     629                    &&  pReq->enmType < VMREQTYPE_MAX,
     630                    ("Invalid package type %d valid range %d-%d inclusivly. This was verified on alloc too...\n",
     631                     pReq->enmType, VMREQTYPE_INVALID + 1, VMREQTYPE_MAX - 1),
     632                    VERR_VM_REQUEST_INVALID_TYPE);
    527633
    528634    /*
     
    531637     */
    532638    int rc = VINF_SUCCESS;
    533     PVM pVM = ((VMREQ volatile *)pReq)->pVM;                    /* volatile paranoia */
    534     if (pVM->NativeThreadEMT != RTThreadNativeSelf())
     639    PUVM pUVM = ((VMREQ volatile *)pReq)->pUVM;                 /* volatile paranoia */
     640    if (pUVM->vm.s.NativeThreadEMT != RTThreadNativeSelf())
    535641    {
    536642        unsigned fFlags = ((VMREQ volatile *)pReq)->fFlags;     /* volatile paranoia */
     
    543649        do
    544650        {
    545             pNext = pVM->vm.s.pReqs;
     651            pNext = pUVM->vm.s.pReqs;
    546652            pReq->pNext = pNext;
    547         } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pVM->vm.s.pReqs, (void *)pReq, (void *)pNext));
     653        } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pUVM->vm.s.pReqs, (void *)pReq, (void *)pNext));
    548654
    549655        /*
    550656         * Notify EMT.
    551657         */
    552         VM_FF_SET(pVM, VM_FF_REQUEST);
    553         VMR3NotifyFF(pVM, false);
     658        if (pUVM->pVM)
     659            VM_FF_SET(pUVM->pVM, VM_FF_REQUEST);
     660        VMR3NotifyFFU(pUVM, false);
    554661
    555662        /*
     
    566673         */
    567674        pReq->enmState = VMREQSTATE_QUEUED;
    568         rc = vmR3ReqProcessOne(pVM, pReq);
     675        rc = vmR3ReqProcessOneU(pUVM, pReq);
    569676        LogFlow(("VMR3ReqQueue: returns %Vrc (processed)\n", rc));
    570677    }
     
    590697     * Verify the supplied package.
    591698     */
    592     if (    pReq->enmState != VMREQSTATE_QUEUED
    593         &&  pReq->enmState != VMREQSTATE_PROCESSING
    594         &&  pReq->enmState != VMREQSTATE_COMPLETED)
    595     {
    596         AssertMsgFailed(("Invalid state %d\n", pReq->enmState));
    597         return VERR_VM_REQUEST_STATE;
    598     }
    599     if (    !pReq->pVM
    600         ||  !pReq->EventSem)
    601     {
    602         AssertMsgFailed(("Invalid request package! Anyone cooking their own packages???\n"));
    603         return VERR_VM_REQUEST_INVALID_PACKAGE;
    604     }
    605     if (    pReq->enmType < VMREQTYPE_INVALID
    606         ||  pReq->enmType > VMREQTYPE_MAX)
    607     {
    608         AssertMsgFailed(("Invalid package type %d valid range %d-%d inclusivly. This was verified on alloc and queue too...\n",
    609                          pReq->enmType, VMREQTYPE_INVALID + 1, VMREQTYPE_MAX - 1));
    610         return VERR_VM_REQUEST_INVALID_TYPE;
    611     }
     699    AssertMsgReturn(    pReq->enmState == VMREQSTATE_QUEUED
     700                    ||  pReq->enmState == VMREQSTATE_PROCESSING
     701                    ||  pReq->enmState == VMREQSTATE_COMPLETED,
     702                    ("Invalid state %d\n", pReq->enmState),
     703                    VERR_VM_REQUEST_STATE);
     704    AssertMsgReturn(    VALID_PTR(pReq->pUVM)
     705                    &&  pReq->EventSem != NIL_RTSEMEVENT,
     706                    ("Invalid request package! Anyone cooking their own packages???\n"),
     707                    VERR_VM_REQUEST_INVALID_PACKAGE);
     708    AssertMsgReturn(    pReq->enmType > VMREQTYPE_INVALID
     709                    &&  pReq->enmType < VMREQTYPE_MAX,
     710                    ("Invalid package type %d valid range %d-%d inclusivly. This was verified on alloc too...\n",
     711                     pReq->enmType, VMREQTYPE_INVALID + 1, VMREQTYPE_MAX - 1),
     712                    VERR_VM_REQUEST_INVALID_TYPE);
    612713
    613714    /*
    614715     * Check for deadlock condition
    615716     */
    616     AssertMsg(!VMMR3LockIsOwner(pReq->pVM), ("Waiting for EMT to process a request, but we own the global VM lock!?!?!?!\n"));
     717    PUVM pUVM = pReq->pUVM;
     718    AssertMsg(!pUVM->pVM || !VMMR3LockIsOwner(pUVM->pVM),
     719              ("Waiting for EMT to process a request, but we own the global VM lock!?!?!?!\n"));
    617720
    618721    /*
     
    644747 * Process pending request(s).
    645748 *
    646  * This function is called from a forced action handler in
    647  * the EMT.
    648  *
    649  * @returns VBox status code.
    650  *
    651  * @param   pVM         VM handle.
    652  */
    653 VMR3DECL(int) VMR3ReqProcess(PVM pVM)
    654 {
    655     LogFlow(("VMR3ReqProcess: (enmVMState=%d)\n", pVM->enmVMState));
     749 * This function is called from a forced action handler in the EMT
     750 * or from one of the EMT loops.
     751 *
     752 * @returns VBox status code.
     753 *
     754 * @param   pUVM            Pointer to the user mode VM structure.
     755 */
     756VMR3DECL(int) VMR3ReqProcessU(PUVM pUVM)
     757{
     758    LogFlow(("VMR3ReqProcessU: (enmVMState=%d)\n", pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_CREATING));
    656759
    657760    /*
     
    667770         * Get pending requests.
    668771         */
    669         VM_FF_CLEAR(pVM, VM_FF_REQUEST);
    670         PVMREQ pReqs = (PVMREQ)ASMAtomicXchgPtr((void * volatile *)&pVM->vm.s.pReqs, NULL);
     772        if (RT_LIKELY(pUVM->pVM))
     773            VM_FF_CLEAR(pUVM->pVM, VM_FF_REQUEST);
     774        PVMREQ pReqs = (PVMREQ)ASMAtomicXchgPtr((void * volatile *)&pUVM->vm.s.pReqs, NULL);
    671775        if (!pReqs)
    672776            break;
     
    682786        {
    683787            Assert(pReq->enmState == VMREQSTATE_QUEUED);
    684             Assert(pReq->pVM == pVM);
     788            Assert(pReq->pUVM == pUVM);
    685789            PVMREQ pCur = pReq;
    686790            pReq = pReq->pNext;
     
    704808
    705809            /* Process the request */
    706             int rc2 = vmR3ReqProcessOne(pVM, pReq);
     810            int rc2 = vmR3ReqProcessOneU(pUVM, pReq);
    707811
    708812            /*
     
    718822    }
    719823
    720     LogFlow(("VMR3ReqProcess: returns %Vrc (enmVMState=%d)\n", rc, pVM->enmVMState));
     824    LogFlow(("VMR3ReqProcess: returns %Vrc (enmVMState=%d)\n", rc, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_CREATING));
    721825    return rc;
    722826}
     
    731835 * @param   pReq        Request packet to process.
    732836 */
    733 static int  vmR3ReqProcessOne(PVM pVM, PVMREQ pReq)
     837static int  vmR3ReqProcessOneU(PUVM pUVM, PVMREQ pReq)
    734838{
    735839    LogFlow(("vmR3ReqProcessOne: pReq=%p type=%d fFlags=%#x\n", pReq, pReq->enmType, pReq->fFlags));
  • trunk/src/VBox/VMM/testcase/tstCFGM.cpp

    r5999 r6796  
    2525#include <VBox/mm.h>
    2626#include <VBox/vm.h>
     27#include <VBox/uvm.h>
    2728
    2829#include <VBox/err.h>
    2930#include <VBox/param.h>
    30 #include <iprt/runtime.h>
     31#include <iprt/initterm.h>
    3132#include <iprt/stream.h>
    3233#include <iprt/string.h>
     
    4647    int rc = SUPInit(NULL);
    4748    if (VBOX_SUCCESS(rc))
    48         rc = SUPPageAlloc((sizeof(*pVM) + PAGE_SIZE - 1) >> PAGE_SHIFT, (void **)&pVM);
     49        rc = SUPPageAlloc(RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT, (void **)&pVM);
    4950    if (VBOX_FAILURE(rc))
    5051    {
     
    5354    }
    5455
    55     rc = STAMR3Init(pVM);
     56    static UVM s_UVM;
     57    PUVM pUVM = &s_UVM;
     58    pUVM->pVM = pVM;
     59    pVM->pUVM = pUVM;
     60
     61    rc = STAMR3InitUVM(pUVM);
     62    if (VBOX_FAILURE(rc))
     63    {
     64        RTPrintf("FAILURE: STAMR3Init failed. rc=%Vrc\n", rc);
     65        return 1;
     66    }
     67
     68    rc = MMR3InitUVM(pUVM);
    5669    if (VBOX_FAILURE(rc))
    5770    {
  • trunk/src/VBox/VMM/testcase/tstMMHyperHeap.cpp

    r5999 r6796  
    2222#include <VBox/stam.h>
    2323#include <VBox/vm.h>
     24#include <VBox/uvm.h>
    2425#include <VBox/sup.h>
    2526#include <VBox/param.h>
     
    2728
    2829#include <VBox/log.h>
    29 #include <iprt/runtime.h>
     30#include <iprt/initterm.h>
     31#include <iprt/mem.h>
    3032#include <iprt/assert.h>
    3133#include <iprt/stream.h>
     
    3335
    3436
    35 int main(int argc, char *argv[])
     37int main(int argc, char **argv)
    3638{
    3739
     
    4547     */
    4648    PVM         pVM;
     49    RTR0PTR     pvR0;
     50    SUPPAGE     aPages[RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT];
    4751    int rc = SUPInit(NULL);
    4852    if (VBOX_SUCCESS(rc))
    49         rc = SUPPageAlloc((sizeof(*pVM) + PAGE_SIZE - 1) >> PAGE_SHIFT, (void **)&pVM);
     53        rc = SUPLowAlloc(RT_ELEMENTS(aPages), (void **)&pVM, &pvR0, &aPages[0]);
    5054    if (VBOX_FAILURE(rc))
    5155    {
     
    5357        return 1;
    5458    }
    55     rc = STAMR3Init(pVM);
    56     if (VBOX_FAILURE(rc))
    57     {
    58         RTPrintf("Fatal error: STAMR3Init failed! rc=%Vrc\n", rc);
    59         return 1;
    60     }
     59    memset(pVM, 0, sizeof(*pVM)); /* wtf? */
     60    pVM->paVMPagesR3 = aPages;
     61    pVM->pVMR0 = pvR0;
     62
     63    static UVM s_UVM;
     64    PUVM pUVM = &s_UVM;
     65    pUVM->pVM = pVM;
     66    pVM->pUVM = pUVM;
     67
     68    rc = STAMR3InitUVM(pUVM);
     69    if (VBOX_FAILURE(rc))
     70    {
     71        RTPrintf("FAILURE: STAMR3Init failed. rc=%Vrc\n", rc);
     72        return 1;
     73    }
     74
     75    rc = MMR3InitUVM(pUVM);
     76    if (VBOX_FAILURE(rc))
     77    {
     78        RTPrintf("FAILURE: STAMR3Init failed. rc=%Vrc\n", rc);
     79        return 1;
     80    }
     81
    6182    rc = MMR3Init(pVM);
    6283    if (VBOX_FAILURE(rc))
  • trunk/src/VBox/VMM/testcase/tstSSM.cpp

    r5999 r6796  
    573573    }
    574574
    575     rc = STAMR3Init(pVM);
     575///@todo    rc = STAMR3Init(pVM);
    576576    if (VBOX_FAILURE(rc))
    577577    {
  • trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp

    r6627 r6796  
    187187    GEN_CHECK_OFF(MM, cShadowPages);
    188188    GEN_CHECK_OFF(MM, cFixedPages);
    189     GEN_CHECK_OFF(MM, pHeap);
    190189    GEN_CHECK_SIZE(MMHYPERSTAT);
    191190    GEN_CHECK_SIZE(MMHYPERCHUNK);
     
    218217    GEN_CHECK_SIZE(PDM);
    219218    GEN_CHECK_OFF(PDM, offVM);
    220     GEN_CHECK_OFF(PDM, pModules);
    221219    GEN_CHECK_OFF(PDM, pDevs);
    222220    GEN_CHECK_OFF(PDM, pDevInstances);
     
    660658    GEN_CHECK_OFF(SELM, StatUpdateFromCPUM);
    661659
    662     GEN_CHECK_SIZE(STAM);
    663 
    664660    GEN_CHECK_SIZE(TM);
    665661    GEN_CHECK_OFF(TM, offVM);
  • trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp

    r5999 r6796  
    133133    CHECK_PADDING_VM(pgm);
    134134    CHECK_PADDING_VM(selm);
    135     CHECK_PADDING_VM(stam);
    136135    CHECK_PADDING_VM(tm);
    137136    CHECK_PADDING_VM(trpm);
Note: See TracChangeset for help on using the changeset viewer.

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