Changeset 6796 in vbox
- Timestamp:
- Feb 4, 2008 6:19:58 PM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 27892
- Location:
- trunk
- Files:
-
- 1 added
- 30 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/mm.h
r6626 r6796 340 340 */ 341 341 342 MMR3DECL(int) MMR3InitUVM(PUVM pUVM); 342 343 MMR3DECL(int) MMR3Init(PVM pVM); 343 344 MMR3DECL(int) MMR3InitPaging(PVM pVM); 344 345 MMR3DECL(int) MMR3HyperInitFinalize(PVM pVM); 345 346 MMR3DECL(int) MMR3Term(PVM pVM); 347 MMR3DECL(void) MMR3TermUVM(PUVM pUVM); 346 348 MMR3DECL(void) MMR3Reset(PVM pVM); 347 349 MMR3DECL(int) MMR3IncreaseBaseReservation(PVM pVM, uint64_t cAddBasePages); 348 MMR3DECL(int) MMR3Increa teFixedReservation(PVM pVM, uint32_t cAddFixedPages);350 MMR3DECL(int) MMR3IncreaseFixedReservation(PVM pVM, uint32_t cAddFixedPages); 349 351 MMR3DECL(int) MMR3UpdateShadowReservation(PVM pVM, uint32_t cShadowPages); 350 352 … … 404 406 * @{ */ 405 407 MMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize); 408 MMR3DECL(void *) MMR3HeapAllocU(PUVM pUVM, MMTAG enmTag, size_t cbSize); 406 409 MMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv); 410 MMR3DECL(int) MMR3HeapAllocExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv); 407 411 MMR3DECL(void *) MMR3HeapAllocZ(PVM pVM, MMTAG enmTag, size_t cbSize); 412 MMR3DECL(void *) MMR3HeapAllocZU(PUVM pUVM, MMTAG enmTag, size_t cbSize); 408 413 MMR3DECL(int) MMR3HeapAllocZEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv); 414 MMR3DECL(int) MMR3HeapAllocZExU(PUVM pUVM, MMTAG enmTag, size_t cbSize, void **ppv); 409 415 MMR3DECL(void *) MMR3HeapRealloc(void *pv, size_t cbNewSize); 410 416 MMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz); 417 MMR3DECL(char *) MMR3HeapStrDupU(PUVM pUVM, MMTAG enmTag, const char *psz); 411 418 MMR3DECL(void) MMR3HeapFree(void *pv); 412 419 /** @} */ -
trunk/include/VBox/pdmapi.h
r5999 r6796 111 111 */ 112 112 113 PDMR3DECL(int) PDMR3LdrLoadVMMR0(void **ppvOpaque);114 PDMR3DECL( void) PDMR3LdrLoadVMMR0Part2(PVM pVM, void *pvOpaque);113 PDMR3DECL(int) PDMR3InitUVM(PUVM pUVM); 114 PDMR3DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM); 115 115 116 116 /** … … 169 169 * process so that components can resolve GC symbols during relocation. 170 170 * 171 * @param p VM VM handle.171 * @param pUVM Pointer to the user mode VM structure. 172 172 * @param offDelta Relocation delta relative to old location. 173 173 */ 174 PDMR3DECL(void) PDMR3LdrRelocate (PVM pVM, RTGCINTPTR offDelta);174 PDMR3DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta); 175 175 176 176 /** … … 194 194 */ 195 195 PDMR3DECL(int) PDMR3Term(PVM pVM); 196 PDMR3DECL(void) PDMR3TermUVM(PUVM pUVM); 196 197 197 198 -
trunk/include/VBox/stam.h
r5999 r6796 955 955 */ 956 956 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, 957 STAMR3DECL(int) STAMR3InitUVM(PUVM pUVM); 958 STAMR3DECL(void) STAMR3TermUVM(PUVM pUVM); 959 STAMR3DECL(int) STAMR3RegisterU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, 1007 960 const char *pszName, STAMUNIT enmUnit, const char *pszDesc); 961 STAMR3DECL(int) STAMR3Register(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, 962 const char *pszName, STAMUNIT enmUnit, const char *pszDesc); 1008 963 1009 964 /** @def STAM_REL_REG … … 1063 1018 STAM_STATS({ STAM_REL_REG_USED(pVM, pvSample, enmType, pszName, enmUnit, pszDesc); }) 1064 1019 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 */ 1020 STAMR3DECL(int) STAMR3RegisterFU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 1021 const char *pszDesc, const char *pszName, ...); 1079 1022 STAMR3DECL(int) STAMR3RegisterF(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 1080 1023 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 */ 1024 STAMR3DECL(int) STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 1025 const char *pszDesc, const char *pszName, va_list args); 1096 1026 STAMR3DECL(int) STAMR3RegisterV(PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 1097 1027 const char *pszDesc, const char *pszName, va_list args); … … 1118 1048 typedef FNSTAMR3CALLBACKPRINT *PFNSTAMR3CALLBACKPRINT; 1119 1049 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 */1136 1050 STAMR3DECL(int) STAMR3RegisterCallback(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 1137 1051 PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint, 1138 1052 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 */1155 1053 STAMR3DECL(int) STAMR3RegisterCallbackV(PVM pVM, void *pvSample, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 1156 1054 PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint, 1157 1055 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 */ 1056 STAMR3DECL(int) STAMR3DeregisterU(PUVM pUVM, void *pvSample); 1170 1057 STAMR3DECL(int) STAMR3Deregister(PVM pVM, void *pvSample); 1171 1058 … … 1187 1074 STAM_STATS({ STAM_REL_DEREG(pVM, pvSample); }) 1188 1075 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 */ 1076 STAMR3DECL(int) STAMR3ResetU(PUVM pUVM, const char *pszPat); 1077 STAMR3DECL(int) STAMR3Reset(PVM pVM, const char *pszPat); 1078 STAMR3DECL(int) STAMR3SnapshotU(PUVM pUVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc); 1215 1079 STAMR3DECL(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); 1080 STAMR3DECL(int) STAMR3SnapshotFreeU(PUVM pUVM, char *pszSnapshot); 1081 STAMR3DECL(int) STAMR3SnapshotFree(PVM pVM, char *pszSnapshot); 1082 STAMR3DECL(int) STAMR3DumpU(PUVM pUVM, const char *pszPat); 1083 STAMR3DECL(int) STAMR3Dump(PVM pVM, const char *pszPat); 1084 STAMR3DECL(int) STAMR3DumpToReleaseLogU(PUVM pUVM, const char *pszPat); 1085 STAMR3DECL(int) STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat); 1086 STAMR3DECL(int) STAMR3PrintU(PUVM pUVM, const char *pszPat); 1087 STAMR3DECL(int) STAMR3Print(PVM pVM, const char *pszPat); 1256 1088 1257 1089 /** … … 1273 1105 typedef FNSTAMR3ENUM *PFNSTAMR3ENUM; 1274 1106 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 */ 1107 STAMR3DECL(int) STAMR3EnumU(PUVM pUVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser); 1285 1108 STAMR3DECL(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 */1293 1109 STAMR3DECL(const char *) STAMR3GetUnit(STAMUNIT enmUnit); 1294 1110 -
trunk/include/VBox/types.h
r5999 r6796 90 90 typedef GCPTRTYPE(struct VM *) PVMGC; 91 91 92 /** Pointer to a thering-0 (global) VM structure. */92 /** Pointer to a ring-0 (global) VM structure. */ 93 93 typedef R0PTRTYPE(struct GVM *) PGVM; 94 95 /** Pointer to a ring-3 (user mode) VM structure. */ 96 typedef R3PTRTYPE(struct UVM *) PUVM; 94 97 95 98 -
trunk/include/VBox/vm.h
r5999 r6796 239 239 /** Session handle. For use when calling SUPR0 APIs. */ 240 240 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; 246 243 /** Ring-3 Host Context VM Pointer. */ 247 244 R3PTRTYPE(struct VM *) pVMR3; … … 498 495 } dbgf; 499 496 500 /** STAM part. */501 union502 {503 #ifdef ___STAMInternal_h504 struct STAM s;505 #endif506 char padding[256]; /* multiple of 32 */507 } stam;508 509 497 /** SSM part. */ 510 498 union -
trunk/include/VBox/vm.mac
r5999 r6796 46 46 .fForcedActions resd 1 47 47 .paVMPagesR3 RTR3PTR_RES 1 48 .pSession RTR 3PTR_RES 149 .p Next RTHCPTR_RES 148 .pSession RTR0PTR_RES 1 49 .pUVM RTR3PTR_RES 1 50 50 .pVMR3 RTR3PTR_RES 1 51 51 .pVMR0 RTR0PTR_RES 1 -
trunk/include/VBox/vmapi.h
r5999 r6796 55 55 #else 56 56 # define VM_GUEST_ADDR(pVM, pvInVM) ( (RTGCPTR)(pvInVM) ) 57 #endif 57 #endif 58 58 59 59 /** @def VM_R3_ADDR … … 71 71 #else 72 72 # define VM_R3_ADDR(pVM, pvInVM) ( (RTR3PTR)(pvInVM) ) 73 #endif 73 #endif 74 74 75 75 … … 88 88 #else 89 89 # define VM_R0_ADDR(pVM, pvInVM) ( (RTR0PTR)(pvInVM) ) 90 #endif 90 #endif 91 91 92 92 /** @def VM_HOST_ADDR … … 118 118 typedef FNVMATERROR *PFNVMATERROR; 119 119 120 /**121 * Sets the error message.122 *123 * @returns rc. Meaning you can do:124 * @code125 * return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");126 * @endcode127 * @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 Any133 */134 120 VMDECL(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 * @code141 * return VM_SET_ERROR(pVM, VERR_OF_YOUR_CHOICE, "descriptive message");142 * @endcode143 * @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 Any149 */150 121 VMDECL(int) VMSetErrorV(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args); 151 122 … … 183 154 typedef FNVMATRUNTIMEERROR *PFNVMATRUNTIMEERROR; 184 155 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); 156 VMDECL(int) VMSetRuntimeError(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, ...); 157 VMDECL(int) VMSetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list args); 241 158 242 159 … … 347 264 /** Pointer to the next request in the chain. */ 348 265 struct VMREQ * volatile pNext; 349 /** Pointer to the VM this packet belongs to. */350 P VM pVM;266 /** Pointer to ring-3 VM structure which this request belongs to. */ 267 PUVM pUVM; 351 268 /** Request state. */ 352 269 volatile VMREQSTATE enmState; … … 414 331 415 332 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 be420 * 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/A433 * @vmstateto Created434 */435 333 VMR3DECL(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 Created445 * @vmstateto Running446 */447 334 VMR3DECL(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 Running456 * @vmstateto Suspended457 */458 335 VMR3DECL(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 */ 336 VMR3DECL(int) VMR3SuspendNoSave(PVM pVM); 481 337 VMR3DECL(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, Running490 * @vmstateto Unchanged state.491 */492 338 VMR3DECL(int) VMR3Reset(PVM pVM); 493 339 … … 506 352 typedef FNVMPROGRESS *PFNVMPROGRESS; 507 353 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 Suspended521 * @vmstateto Unchanged state.522 */523 354 VMR3DECL(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 then529 * 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, Suspended539 * @vmstateto Suspended540 */541 355 VMR3DECL(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 Failure551 * @vmstateto Off552 */553 356 VMR3DECL(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, Created565 * @vmstateto N/A566 */567 357 VMR3DECL(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 */ 358 VMR3DECL(void) VMR3Relocate(PVM pVM, RTGCINTPTR offDelta); 591 359 VMR3DECL(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 360 VMR3DECL(int) VMR3WaitForResume(PVM pVM); 602 361 603 362 /** … … 610 369 typedef FNVMATDTOR *PFNVMATDTOR; 611 370 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 */619 371 VMR3DECL(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 */627 372 VMR3DECL(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 */640 373 VMR3DECL(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 */651 374 VMR3DECL(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 */662 375 VMR3DECL(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 */673 376 VMR3DECL(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 */682 377 VMR3DECL(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 */691 378 VMR3DECL(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 a698 * 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 */706 379 VMR3DECL(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 */717 380 VMR3DECL(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 Any725 */726 381 VMR3DECL(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 */734 382 VMR3DECL(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 */745 383 VMR3DECL(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 */ 384 VMR3DECL(int) VMR3AtErrorRegisterU(PUVM pVM, PFNVMATERROR pfnAtError, void *pvUser); 756 385 VMR3DECL(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 */ 386 VMR3DECL(void) VMR3SetErrorWorker(PVM pVM); 776 387 VMR3DECL(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 */787 388 VMR3DECL(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); 389 VMR3DECL(void) VMR3SetRuntimeErrorWorker(PVM pVM); 390 VMR3DECL(int) VMR3ReqCall(PVM pVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...); 391 VMR3DECL(int) VMR3ReqCallVoidU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...); 392 VMR3DECL(int) VMR3ReqCallVoid(PVM pVM, PVMREQ *ppReq, unsigned cMillies, PFNRT pfnFunction, unsigned cArgs, ...); 393 VMR3DECL(int) VMR3ReqCallEx(PVM pVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...); 394 VMR3DECL(int) VMR3ReqCallU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, ...); 395 VMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args); 396 VMR3DECL(int) VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType); 397 VMR3DECL(int) VMR3ReqAllocU(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType); 398 VMR3DECL(int) VMR3ReqFree(PVMREQ pReq); 399 VMR3DECL(int) VMR3ReqQueue(PVMREQ pReq, unsigned cMillies); 400 VMR3DECL(int) VMR3ReqWait(PVMREQ pReq, unsigned cMillies); 401 VMR3DECL(int) VMR3ReqProcessU(PUVM pUVM); 402 VMR3DECL(void) VMR3NotifyFF(PVM pVM, bool fNotifiedREM); 403 VMR3DECL(void) VMR3NotifyFFU(PUVM pUVM, bool fNotifiedREM); 404 VMR3DECL(int) VMR3WaitHalted(PVM pVM, bool fIgnoreInterrupts); 405 VMR3DECL(int) VMR3WaitU(PUVM pUVM); 1010 406 1011 407 /** @} */ -
trunk/src/VBox/VMM/DBGF.cpp
r5999 r6796 604 604 { 605 605 LogFlow(("dbgfr3VMMWait: Processes requests...\n")); 606 rc = VMR3ReqProcess (pVM);606 rc = VMR3ReqProcessU(pVM->pUVM); 607 607 LogFlow(("dbgfr3VMMWait: VMR3ReqProcess -> %Vrc rcRet=%Vrc\n", rc, rcRet)); 608 608 if (rc >= VINF_EM_FIRST && rc <= VINF_EM_LAST) -
trunk/src/VBox/VMM/EM.cpp
r5999 r6796 2984 2984 if (VM_FF_ISSET(pVM, VM_FF_REQUEST)) 2985 2985 { 2986 rc2 = VMR3ReqProcess (pVM);2986 rc2 = VMR3ReqProcessU(pVM->pUVM); 2987 2987 if (rc2 == VINF_EM_OFF || rc2 == VINF_EM_TERMINATE) 2988 2988 { -
trunk/src/VBox/VMM/MM.cpp
r6634 r6796 88 88 #include "MMInternal.h" 89 89 #include <VBox/vm.h> 90 #include <VBox/uvm.h> 90 91 #include <VBox/err.h> 91 92 #include <VBox/param.h> … … 107 108 * Internal Functions * 108 109 *******************************************************************************/ 109 static int mmR3Term(PVM pVM, bool fKeepTheHeap);110 110 static DECLCALLBACK(int) mmR3Save(PVM pVM, PSSMHANDLE pSSM); 111 111 static DECLCALLBACK(int) mmR3Load(PVM pVM, PSSMHANDLE pSSM, uint32_t u32Version); 112 112 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 */ 122 MMR3DECL(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 } 113 136 114 137 … … 147 170 pVM->mm.s.offVM = RT_OFFSETOF(VM, mm); 148 171 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 }159 172 160 173 /* … … 182 195 } 183 196 } 184 mmR3Term(pVM, true /* keep the heap */);197 MMR3Term(pVM); 185 198 return rc; 186 199 } … … 346 359 */ 347 360 MMR3DECL(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're357 * called from MMR3Init, otherwise we'll get into trouble when358 * 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)365 361 { 366 362 /* … … 395 391 396 392 /* 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 /*406 393 * Zero stuff to detect after termination use of the MM interface 407 394 */ … … 413 400 414 401 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 */ 414 MMR3DECL(void) MMR3TermUVM(PUVM pUVM) 415 { 416 /* 417 * Destroy the heap. 418 */ 419 mmR3HeapDestroy(pUVM->mm.s.pHeap); 420 pUVM->mm.s.pHeap = NULL; 415 421 } 416 422 -
trunk/src/VBox/VMM/MMHeap.cpp
r6529 r6796 22 22 #define LOG_GROUP LOG_GROUP_MM_HEAP 23 23 #include <VBox/mm.h> 24 #include <VBox/stam.h> 24 25 #include <VBox/pgm.h> 25 26 #include "MMInternal.h" 26 27 #include <VBox/vm.h> 28 #include <VBox/uvm.h> 27 29 #include <VBox/err.h> 28 30 #include <VBox/param.h> … … 48 50 * @param ppHeap Where to store the heap pointer. 49 51 */ 50 int mmR3HeapCreate (PVM pVM, PMMHEAP *ppHeap)52 int mmR3HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap) 51 53 { 52 54 PMMHEAP pHeap = (PMMHEAP)RTMemAllocZ(sizeof(MMHEAP) + sizeof(MMHEAPSTAT)); … … 59 61 * Initialize the global stat record. 60 62 */ 61 pHeap->pVM = pVM; 62 63 pHeap->pUVM = pUVM; 63 64 pHeap->Stat.pHeap = pHeap; 64 65 #ifdef MMR3HEAP_WITH_STATISTICS 65 66 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."); 74 75 #endif 75 76 *ppHeap = pHeap; … … 121 122 * The memory will be allocated from the default heap but a header 122 123 * 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 aone go.124 * all the allocations together so they can be freed in one go. 124 125 * 125 126 * This interface is typically used for memory block which will not be … … 127 128 * 128 129 * @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 */ 136 MMR3DECL(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. 129 154 * @param pVM VM handle. 130 155 * @param enmTag Statistics tag. Statistics are collected on a per tag … … 135 160 MMR3DECL(void *) MMR3HeapAlloc(PVM pVM, MMTAG enmTag, size_t cbSize) 136 161 { 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. 153 171 * @param enmTag Statistics tag. Statistics are collected on a per tag 154 172 * basis in addition to a global one. Thus we can easily … … 157 175 * @param ppv Where to store the pointer to the allocated memory on success. 158 176 */ 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); 177 MMR3DECL(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); 168 181 if (pv) 169 182 { … … 176 189 177 190 /** 178 * Same as MMR3HeapAlloc() only the memory is zeroed. 179 * 191 * Same as MMR3HeapAlloc(). 180 192 * 181 193 * @returns Pointer to allocated memory. … … 185 197 * identify how memory is used by the VM. 186 198 * @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 tag207 * basis in addition to a global one. Thus we can easily208 * identify how memory is used by the VM.209 * @param cbSize Size of the block.210 199 * @param ppv Where to store the pointer to the allocated memory on success. 211 200 */ 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); 201 MMR3DECL(int) MMR3HeapAllocEx(PVM pVM, MMTAG enmTag, size_t cbSize, void **ppv) 202 { 203 void *pv = mmR3HeapAlloc(pVM->pUVM->mm.s.pHeap, enmTag, cbSize, false); 221 204 if (pv) 222 205 { … … 229 212 230 213 /** 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 */ 223 MMR3DECL(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 */ 239 MMR3DECL(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 */ 256 MMR3DECL(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 */ 280 MMR3DECL(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 /** 231 293 * Allocate memory from the heap. 232 294 * … … 239 301 * @param fZero Whether or not to zero the memory block. 240 302 */ 241 void * 303 void *mmR3HeapAlloc(PMMHEAP pHeap, MMTAG enmTag, size_t cbSize, bool fZero) 242 304 { 243 305 #ifdef MMR3HEAP_WITH_STATISTICS … … 273 335 274 336 /* register the statistics */ 275 P VM pVM = pHeap->pVM;337 PUVM pUVM = pHeap->pUVM; 276 338 char szName[80]; 277 339 const char *pszTag = mmR3GetTagName(enmTag); 278 340 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."); 280 342 281 343 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."); 283 345 284 346 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."); 286 348 287 349 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."); 289 351 290 352 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."); 292 354 293 355 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."); 295 357 296 358 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."); 298 360 } 299 361 #endif … … 452 514 RTCritSectEnter(&pHeap->Lock); 453 515 pHdrNew->pStat->cbAllocated += cbNewSize - pHdrNew->cbSize; 454 pHeap->Stat.cbAllocated 516 pHeap->Stat.cbAllocated += cbNewSize - pHdrNew->cbSize; 455 517 RTCritSectLeave(&pHeap->Lock); 456 518 #endif … … 459 521 460 522 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 */ 537 MMR3DECL(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; 461 548 } 462 549 … … 475 562 MMR3DECL(char *) MMR3HeapStrDup(PVM pVM, MMTAG enmTag, const char *psz) 476 563 { 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); 485 565 } 486 566 -
trunk/src/VBox/VMM/MMInternal.h
r6627 r6796 117 117 PAVLULNODECORE pStatTree; 118 118 /** The VM handle. */ 119 P VM pVM;119 PUVM pUVM; 120 120 /** Heap global statistics. */ 121 121 MMHEAPSTAT Stat; … … 675 675 /** The head of the ROM ranges. */ 676 676 R3PTRTYPE(PMMROMRANGE) pRomHead; 677 678 /** Pointer to the MM R3 Heap. */679 R3PTRTYPE(PMMHEAP) pHeap;680 681 677 } MM; 682 678 /** Pointer to MM Data (part of VM). */ 683 679 typedef MM *PMM; 684 680 681 682 /** 683 * MM data kept in the UVM. 684 */ 685 typedef 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. */ 691 typedef MMUSERPERVM *PMMUSERPERVM; 692 693 685 694 __BEGIN_DECLS 686 695 … … 691 700 void mmR3PagePoolTerm(PVM pVM); 692 701 693 int mmR3HeapCreate (PVM pVM, PMMHEAP *ppHeap);702 int mmR3HeapCreateU(PUVM pUVM, PMMHEAP *ppHeap); 694 703 void mmR3HeapDestroy(PMMHEAP pHeap); 695 704 -
trunk/src/VBox/VMM/PDM.cpp
r5999 r6796 109 109 #include <VBox/ssm.h> 110 110 #include <VBox/vm.h> 111 #include <VBox/uvm.h> 111 112 #include <VBox/vmm.h> 112 113 #include <VBox/param.h> … … 141 142 142 143 /** 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 */ 152 PDMR3DECL(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 /** 143 162 * Initializes the PDM. 144 163 * … … 174 193 if (VBOX_SUCCESS(rc)) 175 194 #endif 176 rc = pdmR3LdrInit (pVM);195 rc = pdmR3LdrInitU(pVM->pUVM); 177 196 if (VBOX_SUCCESS(rc)) 178 197 { … … 426 445 * Free modules. 427 446 */ 428 pdmR3LdrTerm (pVM);447 pdmR3LdrTermU(pVM->pUVM); 429 448 430 449 #ifdef VBOX_WITH_PDM_LOCK … … 438 457 return VINF_SUCCESS; 439 458 } 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 */ 468 PDMR3DECL(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 440 480 441 481 -
trunk/src/VBox/VMM/PDMDevice.cpp
r6475 r6796 994 994 * Load it. 995 995 */ 996 int rc = pdmR3LoadR3 (pVM, pszFilename, pszName);996 int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName); 997 997 if (VBOX_SUCCESS(rc)) 998 998 { -
trunk/src/VBox/VMM/PDMDriver.cpp
r6221 r6796 95 95 96 96 #ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 97 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 97 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 98 98 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc); 99 99 #endif … … 303 303 * Load it. 304 304 */ 305 int rc = pdmR3LoadR3 (pVM, pszFilename, pszName);305 int rc = pdmR3LoadR3U(pVM->pUVM, pszFilename, pszName); 306 306 if (VBOX_SUCCESS(rc)) 307 307 { … … 1075 1075 1076 1076 #ifdef VBOX_WITH_PDM_ASYNC_COMPLETION 1077 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 1077 static DECLCALLBACK(int) pdmR3DrvHlp_PDMAsyncCompletionTemplateCreate(PPDMDRVINS pDrvIns, PPPDMASYNCCOMPLETIONTEMPLATE ppTemplate, 1078 1078 PFNPDMASYNCCOMPLETEDRV pfnCompleted, const char *pszDesc) 1079 1079 { … … 1085 1085 int rc = PDMR3AsyncCompletionTemplateCreateDriver(pDrvIns->Internal.s.pVM, pDrvIns, ppTemplate, pfnCompleted, pszDesc); 1086 1086 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, 1088 1088 pDrvIns->iInstance, rc, *ppTemplate)); 1089 1089 return rc; -
trunk/src/VBox/VMM/PDMInternal.h
r5999 r6796 776 776 RTUINT uPadding0; /**< Alignment padding.*/ 777 777 778 /** Pointer to list of loaded modules. This is HC only! */779 R3PTRTYPE(PPDMMOD) pModules;780 781 778 /** List of registered devices. (FIFO) */ 782 779 R3PTRTYPE(PPDMDEV) pDevs; … … 867 864 868 865 866 /** 867 * PDM data kept in the UVM. 868 */ 869 typedef 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. */ 876 typedef PDMUSERPERVM *PPDMUSERPERVM; 877 878 869 879 870 880 /******************************************************************************* … … 902 912 PPDMDRV pdmR3DrvLookup(PVM pVM, const char *pszName); 903 913 904 int pdmR3LdrInit (PVM pVM);905 void pdmR3LdrTerm (PVM pVM);914 int pdmR3LdrInitU(PUVM pUVM); 915 void pdmR3LdrTermU(PUVM pUVM); 906 916 char * pdmR3FileR3(const char *pszFile, bool fShared = false); 907 int pdmR3LoadR3 (PVM pVM, const char *pszFilename, const char *pszName);917 int pdmR3LoadR3U(PUVM pUVM, const char *pszFilename, const char *pszName); 908 918 909 919 void pdmR3QueueRelocate(PVM pVM, RTGCINTPTR offDelta); -
trunk/src/VBox/VMM/PDMLdr.cpp
r5999 r6796 27 27 #include <VBox/vmm.h> 28 28 #include <VBox/vm.h> 29 #include <VBox/uvm.h> 29 30 #include <VBox/sup.h> 30 31 #include <VBox/param.h> … … 59 60 * Internal Functions * 60 61 *******************************************************************************/ 61 static DECLCALLBACK(int) pdm r3GetImportGC(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);62 static DECLCALLBACK(int) pdmR3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser); 63 static int pdmR3LoadR0U(PUVM pUVM, const char *pszFilename, const char *pszName); 63 64 static char * pdmR3FileGC(const char *pszFile); 64 65 static char * pdmR3FileR0(const char *pszFile); … … 69 70 70 71 /** 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. 75 73 * 76 74 * @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 */ 77 PDMR3DECL(int) PDMR3LdrLoadVMMR0U(PUVM pUVM) 78 { 79 return pdmR3LoadR0U(pUVM, NULL, VMMR0_MAIN_MODULE_NAME); 155 80 } 156 81 … … 163 88 * 164 89 * @returns VBox stutus code. 165 * @param p VM VM handle.90 * @param pUVM Pointer to the user mode VM structure. 166 91 * @param pvVMMR0Mod The opqaue returned by PDMR3LdrLoadVMMR0. 167 92 */ 168 int pdmR3LdrInit (PVM pVM)93 int pdmR3LdrInitU(PUVM pUVM) 169 94 { 170 95 #ifdef PDMLDR_FAKE_MODE … … 176 101 * Load the mandatory GC module, the VMMR0.r0 is loaded before VM creation. 177 102 */ 178 return PDMR3LoadGC(p VM, NULL, VMMGC_MAIN_MODULE_NAME);103 return PDMR3LoadGC(pUVM->pVM, NULL, VMMGC_MAIN_MODULE_NAME); 179 104 #endif 180 105 } … … 187 112 * 188 113 * @param pVM The VM handle. 189 */ 190 void pdmR3LdrTerm(PVM pVM) 114 * 115 * @remarks This is normally called twice during termination. 116 */ 117 void pdmR3LdrTermU(PUVM pUVM) 191 118 { 192 119 /* 193 120 * Free the modules. 194 121 */ 195 PPDMMOD pModule = pVM->pdm.s.pModules; 122 PPDMMOD pModule = pUVM->pdm.s.pModules; 123 pUVM->pdm.s.pModules = NULL; 196 124 while (pModule) 197 125 { … … 240 168 * process so that components can resolve GC symbols during relocation. 241 169 * 242 * @param p VM VM handle.170 * @param pUVM Pointer to the user mode VM structure. 243 171 * @param offDelta Relocation delta relative to old location. 244 172 */ 245 PDMR3DECL(void) PDMR3LdrRelocate (PVM pVM, RTGCINTPTR offDelta)173 PDMR3DECL(void) PDMR3LdrRelocateU(PUVM pUVM, RTGCINTPTR offDelta) 246 174 { 247 175 LogFlow(("PDMR3LdrRelocate: offDelta=%VGv\n", offDelta)); … … 250 178 * GC Modules. 251 179 */ 252 if (p VM->pdm.s.pModules)180 if (pUVM->pdm.s.pModules) 253 181 { 254 182 /* … … 260 188 /* pass 1 */ 261 189 PPDMMOD pCur; 262 for (pCur = p VM->pdm.s.pModules; pCur; pCur = pCur->pNext)190 for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext) 263 191 { 264 192 if (pCur->eType == PDMMOD_TYPE_GC) 265 193 { 266 194 pCur->OldImageBase = pCur->ImageBase; 267 pCur->ImageBase = MMHyperHC2GC(p VM, pCur->pvBits);195 pCur->ImageBase = MMHyperHC2GC(pUVM->pVM, pCur->pvBits); 268 196 } 269 197 } 270 198 271 199 /* pass 2 */ 272 for (pCur = p VM->pdm.s.pModules; pCur; pCur = pCur->pNext)200 for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext) 273 201 { 274 202 if (pCur->eType == PDMMOD_TYPE_GC) 275 203 { 276 204 PDMGETIMPORTARGS Args; 277 Args.pVM = p VM;205 Args.pVM = pUVM->pVM; 278 206 Args.pModule = pCur; 279 207 int rc = RTLdrRelocate(pCur->hLdrMod, pCur->pvBits, pCur->ImageBase, pCur->OldImageBase, 280 pdm r3GetImportGC, &Args);208 pdmR3GetImportGC, &Args); 281 209 AssertFatalMsgRC(rc, ("RTLdrRelocate failed, rc=%d\n", rc)); 282 DBGFR3ModuleRelocate(p VM, pCur->OldImageBase, pCur->ImageBase, RTLdrSize(pCur->hLdrMod),210 DBGFR3ModuleRelocate(pUVM->pVM, pCur->OldImageBase, pCur->ImageBase, RTLdrSize(pCur->hLdrMod), 283 211 pCur->szFilename, pCur->szName); 284 212 } … … 301 229 * 302 230 * @returns VBox status code. 303 * @param p VM The VM to load it into.231 * @param pUVM Pointer to the user mode VM structure. 304 232 * @param pszFilename Filename of the module binary. 305 233 * @param pszName Module name. Case sensitive and the length is limited! 306 234 */ 307 int pdmR3LoadR3 (PVM pVM, const char *pszFilename, const char *pszName)235 int pdmR3LoadR3U(PUVM pUVM, const char *pszFilename, const char *pszName) 308 236 { 309 237 /* 310 238 * Validate input. 311 239 */ 312 AssertMsg(p VM->pdm.s.offVM, ("bad init order!\n"));240 AssertMsg(pUVM->pVM->pdm.s.offVM, ("bad init order!\n")); 313 241 Assert(pszFilename); 314 242 size_t cchFilename = strlen(pszFilename); … … 325 253 * Try lookup the name and see if the module exists. 326 254 */ 327 for (pCur = p VM->pdm.s.pModules; pCur; pCur = pCur->pNext)255 for (pCur = pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext) 328 256 { 329 257 if (!strcmp(pCur->szName, pszName)) … … 353 281 if (VBOX_SUCCESS(rc)) 354 282 { 355 pModule->pNext = p VM->pdm.s.pModules;356 p VM->pdm.s.pModules = pModule;283 pModule->pNext = pUVM->pdm.s.pModules; 284 pUVM->pdm.s.pModules = pModule; 357 285 return rc; 358 286 } … … 360 288 /* Something went wrong, most likely module not found. Don't consider other unlikely errors */ 361 289 RTMemFree(pModule); 362 return VMSetError(p VM, 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); 363 291 } 364 292 … … 375 303 * @param pvUser User argument. 376 304 */ 377 static DECLCALLBACK(int) pdm r3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser)305 static DECLCALLBACK(int) pdmR3GetImportGC(RTLDRMOD hLdrMod, const char *pszModule, const char *pszSymbol, unsigned uSymbol, RTUINTPTR *pValue, void *pvUser) 378 306 { 379 307 PVM pVM = ((PPDMGETIMPORTARGS)pvUser)->pVM; … … 427 355 * Search for module. 428 356 */ 429 PPDMMOD pCur = pVM->p dm.s.pModules;357 PPDMMOD pCur = pVM->pUVM->pdm.s.pModules; 430 358 while (pCur) 431 359 { … … 478 406 */ 479 407 AssertMsg(pVM->pdm.s.offVM, ("bad init order!\n")); 480 PPDMMOD pCur = pVM->p dm.s.pModules;408 PPDMMOD pCur = pVM->pUVM->pdm.s.pModules; 481 409 while (pCur) 482 410 { … … 541 469 Args.pVM = pVM; 542 470 Args.pModule = pModule; 543 rc = RTLdrGetBits(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, pdm r3GetImportGC, &Args);471 rc = RTLdrGetBits(pModule->hLdrMod, pModule->pvBits, pModule->ImageBase, pdmR3GetImportGC, &Args); 544 472 if (VBOX_SUCCESS(rc)) 545 473 { … … 547 475 * Insert the module. 548 476 */ 549 if (pVM->pdm.s.pModules) 477 PUVM pUVM = pVM->pUVM; 478 if (pUVM->pdm.s.pModules) 550 479 { 551 480 /* we don't expect this list to be very long, so rather save the tail pointer. */ 552 PPDMMOD pCur = p VM->pdm.s.pModules;481 PPDMMOD pCur = pUVM->pdm.s.pModules; 553 482 while (pCur->pNext) 554 483 pCur = pCur->pNext; … … 556 485 } 557 486 else 558 p VM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */487 pUVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */ 559 488 Log(("PDM: GC Module at %VGvx %s (%s)\n", (RTGCPTR)pModule->ImageBase, pszName, pszFilename)); 560 489 RTMemTmpFree(pszFile); … … 587 516 * 588 517 * @returns VBox status code. 589 * @param p VM The VM to load it into.518 * @param pUVM Pointer to the user mode VM structure. 590 519 * @param pszFilename Filename of the module binary. 591 520 * @param pszName Module name. Case sensitive and the length is limited! 592 521 */ 593 static int pdmR3LoadR0 (PVM pVM, const char *pszFilename, const char *pszName)522 static int pdmR3LoadR0U(PUVM pUVM, const char *pszFilename, const char *pszName) 594 523 { 595 524 /* 596 525 * Validate input. 597 526 */ 598 AssertMsg(pVM->pdm.s.offVM, ("bad init order!\n")); 599 PPDMMOD pCur = pVM->pdm.s.pModules; 527 PPDMMOD pCur = pUVM->pdm.s.pModules; 600 528 while (pCur) 601 529 { … … 608 536 pCur = pCur->pNext; 609 537 } 610 AssertReturn(strcmp(pszName, VMMR0_MAIN_MODULE_NAME), VERR_INTERNAL_ERROR);611 538 612 539 /* … … 645 572 * Insert the module. 646 573 */ 647 if (p VM->pdm.s.pModules)574 if (pUVM->pdm.s.pModules) 648 575 { 649 576 /* we don't expect this list to be very long, so rather save the tail pointer. */ 650 PPDMMOD pCur = p VM->pdm.s.pModules;577 PPDMMOD pCur = pUVM->pdm.s.pModules; 651 578 while (pCur->pNext) 652 579 pCur = pCur->pNext; … … 654 581 } 655 582 else 656 p VM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */583 pUVM->pdm.s.pModules = pModule; /* (pNext is zeroed by alloc) */ 657 584 Log(("PDM: GC Module at %VGvx %s (%s)\n", (RTGCPTR)pModule->ImageBase, pszName, pszFilename)); 658 585 RTMemTmpFree(pszFile); … … 662 589 RTMemFree(pModule); 663 590 RTMemTmpFree(pszFile); 664 LogRel(("pdmR3LoadR0 : pszName=\"%s\" rc=%Vrc\n", pszName, rc));591 LogRel(("pdmR3LoadR0U: pszName=\"%s\" rc=%Vrc\n", pszName, rc)); 665 592 666 593 /* 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(p VM, 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); 669 596 return rc; 670 597 } … … 692 619 * Find the module. 693 620 */ 694 for (PPDMMOD pModule = pVM->p dm.s.pModules; pModule; pModule = pModule->pNext)621 for (PPDMMOD pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext) 695 622 { 696 623 if ( pModule->eType == PDMMOD_TYPE_R3 … … 747 674 * Find the module. 748 675 */ 749 for (PPDMMOD pModule = pVM->p dm.s.pModules; pModule; pModule = pModule->pNext)676 for (PPDMMOD pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext) 750 677 { 751 678 if ( pModule->eType == PDMMOD_TYPE_R0 … … 794 721 AssertMsgReturn(!strpbrk(pszModule, "/\\:\n\r\t"), ("pszModule=%s\n", pszModule), VERR_INVALID_PARAMETER); 795 722 PPDMMOD pModule; 796 for (pModule = pVM->p dm.s.pModules; pModule; pModule = pModule->pNext)723 for (pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext) 797 724 if ( pModule->eType == PDMMOD_TYPE_R0 798 725 && !strcmp(pModule->szName, pszModule)) … … 800 727 if (!pModule) 801 728 { 802 int rc = pdmR3LoadR0 (pVM, NULL, pszModule);729 int rc = pdmR3LoadR0U(pVM->pUVM, NULL, pszModule); 803 730 AssertMsgRCReturn(rc, ("pszModule=%s rc=%Vrc\n", pszModule, rc), VERR_MODULE_NOT_FOUND); 804 731 } … … 836 763 * Find the module. 837 764 */ 838 for (PPDMMOD pModule = pVM->p dm.s.pModules; pModule; pModule = pModule->pNext)765 for (PPDMMOD pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext) 839 766 { 840 767 if ( pModule->eType == PDMMOD_TYPE_GC … … 891 818 AssertMsgReturn(!strpbrk(pszModule, "/\\:\n\r\t"), ("pszModule=%s\n", pszModule), VERR_INVALID_PARAMETER); 892 819 PPDMMOD pModule; 893 for (pModule = pVM->p dm.s.pModules; pModule; pModule = pModule->pNext)820 for (pModule = pVM->pUVM->pdm.s.pModules; pModule; pModule = pModule->pNext) 894 821 if ( pModule->eType == PDMMOD_TYPE_GC 895 822 && !strcmp(pModule->szName, pszModule)) … … 1078 1005 int rc = VERR_MODULE_NOT_FOUND; 1079 1006 PPDMMOD pCur; 1080 for (pCur = pVM->p dm.s.pModules; pCur; pCur = pCur->pNext)1007 for (pCur = pVM->pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext) 1081 1008 { 1082 1009 /* Skip anything which isn't in GC. */ … … 1195 1122 { 1196 1123 PPDMMOD pCur; 1197 for (pCur = pVM->p dm.s.pModules; pCur; pCur = pCur->pNext)1124 for (pCur = pVM->pUVM->pdm.s.pModules; pCur; pCur = pCur->pNext) 1198 1125 { 1199 1126 int rc = pfnCallback(pVM, -
trunk/src/VBox/VMM/STAM.cpp
r6617 r6796 24 24 #include "STAMInternal.h" 25 25 #include <VBox/vm.h> 26 #include <VBox/uvm.h> 26 27 #include <VBox/err.h> 27 28 #include <VBox/dbg.h> … … 72 73 /** Pointer to the current buffer position. */ 73 74 char *psz; 74 /** The VM handle (just in case). */75 /** The VM handle. */ 75 76 PVM pVM; 76 77 /** The number of bytes allocated. */ … … 104 105 * Internal Functions * 105 106 *******************************************************************************/ 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);107 static int stamR3RegisterU(PUVM pUVM, void *pvSample, PFNSTAMR3CALLBACKRESET pfnReset, PFNSTAMR3CALLBACKPRINT pfnPrint, 108 STAMTYPE enmType, STAMVISIBILITY enmVisibility, const char *pszName, STAMUNIT enmUnit, const char *pszDesc); 108 109 static int stamR3ResetOne(PSTAMDESC pDesc, void *pvArg); 109 110 static DECLCALLBACK(void) stamR3EnumLogPrintf(PSTAMR3PRINTONEARGS pvArg, const char *pszFormat, ...); … … 116 117 static bool stamR3MultiMatch(const char * const *papszExpressions, unsigned cExpressions, unsigned *piExpression, const char *pszName); 117 118 static 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);119 static int stamR3EnumU(PUVM pUVM, const char *pszPat, bool fUpdateRing0, int (pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg); 120 static void stamR3Ring0StatsRegisterU(PUVM pUVM); 121 static void stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat); 122 static void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions); 122 123 123 124 #ifdef VBOX_WITH_DEBUGGER … … 188 189 * @param pVM The VM to operate on. 189 190 */ 190 STAMR3DECL(int) STAMR3Init (PVM pVM)191 STAMR3DECL(int) STAMR3InitUVM(PUVM pUVM) 191 192 { 192 193 LogFlow(("STAMR3Init\n")); … … 195 196 * Assert alignment and sizes. 196 197 */ 197 Assert Release(!(RT_OFFSETOF(VM, stam.s) & 31));198 AssertRelease(sizeof(p VM->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)); 199 200 200 201 /* 201 202 * Setup any fixed pointers and offsets. 202 203 */ 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); 208 206 209 207 /* 210 208 * Register the ring-0 statistics (GVMM/GMM). 211 209 */ 212 stamR3Ring0StatsRegister (pVM);210 stamR3Ring0StatsRegisterU(pUVM); 213 211 214 212 #ifdef VBOX_WITH_DEBUGGER … … 230 228 231 229 /** 232 * Applies relocations to data and code managed by this233 * component. This function will be called at init and234 * 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 /**246 230 * Terminates the STAM. 247 231 * 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 */ 234 STAMR3DECL(void) STAMR3TermUVM(PUVM pUVM) 255 235 { 256 236 /* 257 237 * Free used memory and the RWLock. 258 238 */ 259 PSTAMDESC pCur = pVM->stam.s.pHead;239 PSTAMDESC pCur = pUVM->stam.s.pHead; 260 240 while (pCur) 261 241 { … … 264 244 RTMemFree(pvFree); 265 245 } 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 } 276 252 277 253 … … 279 255 * Registers a sample with the statistics mamanger. 280 256 * 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 */ 276 STAMR3DECL(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. 286 292 * 287 293 * It is not possible to register the same sample twice. … … 300 306 { 301 307 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 */ 326 STAMR3DECL(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; 303 334 } 304 335 … … 323 354 va_list args; 324 355 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); 326 357 va_end(args); 327 358 return rc; … … 343 374 * @param args Arguments to the format string. 344 375 */ 345 STAMR3DECL(int) STAMR3RegisterV (PVM pVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit,346 const char *pszDesc, const char *pszName, va_list args)376 STAMR3DECL(int) STAMR3RegisterVU(PUVM pUVM, void *pvSample, STAMTYPE enmType, STAMVISIBILITY enmVisibility, STAMUNIT enmUnit, 377 const char *pszDesc, const char *pszName, va_list args) 347 378 { 348 379 AssertReturn(enmType != STAMTYPE_CALLBACK, VERR_INVALID_PARAMETER); … … 353 384 return VERR_NO_MEMORY; 354 385 355 int rc = STAMR3Register (pVM, pvSample, enmType, enmVisibility, pszFormattedName, enmUnit, pszDesc);386 int rc = STAMR3RegisterU(pUVM, pvSample, enmType, enmVisibility, pszFormattedName, enmUnit, pszDesc); 356 387 RTStrFree(pszFormattedName); 357 388 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 */ 406 STAMR3DECL(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); 358 410 } 359 411 … … 411 463 return VERR_NO_MEMORY; 412 464 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); 414 466 RTStrFree(pszFormattedName); 415 467 return rc; … … 421 473 * 422 474 * @returns VBox status. 423 * @param p VM The VM handle.475 * @param pUVM Pointer to the user mode VM structure. 424 476 * @param pvSample Pointer to the sample. 425 477 * @param pfnReset Callback for resetting the sample. NULL should be used if the sample can't be reset. … … 433 485 * @remark There is currently no device or driver variant of this API. Add one if it should become necessary! 434 486 */ 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(p VM);487 static 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); 439 491 440 492 /* … … 442 494 */ 443 495 PSTAMDESC pPrev = NULL; 444 PSTAMDESC pCur = p VM->stam.s.pHead;496 PSTAMDESC pCur = pUVM->stam.s.pHead; 445 497 while (pCur) 446 498 { … … 452 504 if (!iDiff) 453 505 { 454 STAM_UNLOCK_WR(p VM);506 STAM_UNLOCK_WR(pUVM); 455 507 AssertMsgFailed(("Duplicate sample name: %s\n", pszName)); 456 508 return VERR_ALREADY_EXISTS; … … 491 543 pPrev->pNext = pNew; 492 544 else 493 p VM->stam.s.pHead = pNew;494 495 stamR3ResetOne(pNew, p VM);545 pUVM->stam.s.pHead = pNew; 546 547 stamR3ResetOne(pNew, pUVM->pVM); 496 548 rc = VINF_SUCCESS; 497 549 } … … 499 551 rc = VERR_NO_MEMORY; 500 552 501 STAM_UNLOCK_WR(p VM);553 STAM_UNLOCK_WR(pUVM); 502 554 return rc; 503 555 } … … 511 563 * 512 564 * @returns VBox status. 513 * @param p VM The VM handle.565 * @param pUVM Pointer to the user mode VM structure. 514 566 * @param pvSample Pointer to the sample registered with STAMR3Register(). 515 567 */ 516 STAMR3DECL(int) STAMR3Deregister (PVM pVM, void *pvSample)517 { 518 STAM_LOCK_WR(p VM);568 STAMR3DECL(int) STAMR3DeregisterU(PUVM pUVM, void *pvSample) 569 { 570 STAM_LOCK_WR(pUVM); 519 571 520 572 /* … … 523 575 int rc = VERR_INVALID_HANDLE; 524 576 PSTAMDESC pPrev = NULL; 525 PSTAMDESC pCur = p VM->stam.s.pHead;577 PSTAMDESC pCur = pUVM->stam.s.pHead; 526 578 while (pCur) 527 579 { … … 533 585 pPrev->pNext = pCur; 534 586 else 535 p VM->stam.s.pHead = pCur;587 pUVM->stam.s.pHead = pCur; 536 588 537 589 RTMemFree(pvFree); … … 545 597 } 546 598 547 STAM_UNLOCK_WR(p VM);599 STAM_UNLOCK_WR(pUVM); 548 600 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 */ 614 STAMR3DECL(int) STAMR3Deregister(PVM pVM, void *pvSample) 615 { 616 return STAMR3DeregisterU(pVM->pUVM, pvSample); 549 617 } 550 618 … … 560 628 * @remarks Don't confuse this with the other 'XYZR3Reset' methods, it's not called at VM reset. 561 629 */ 562 STAMR3DECL(int) STAMR3Reset (PVM pVM, const char *pszPat)630 STAMR3DECL(int) STAMR3ResetU(PUVM pUVM, const char *pszPat) 563 631 { 564 632 int rc = VINF_SUCCESS; … … 601 669 } 602 670 603 STAM_LOCK_WR(p VM);671 STAM_LOCK_WR(pUVM); 604 672 if (fGVMMMatched) 605 673 { 674 PVM pVM = pUVM->pVM; 606 675 GVMMReq.Hdr.cbReq = sizeof(GVMMReq); 607 676 GVMMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; … … 612 681 // if (fGMMMatched) 613 682 // { 683 // PVM pVM = pUVM->pVM; 614 684 // GMMReq.Hdr.cbReq = sizeof(Req); 615 685 // GMMReq.Hdr.u32Magic = SUPVMMR0REQHDR_MAGIC; … … 619 689 620 690 /* and the reset */ 621 stamR3Enum (pVM, pszPat, false /* fUpdateRing0 */, stamR3ResetOne,pVM);622 623 STAM_UNLOCK_WR(p VM);691 stamR3EnumU(pUVM, pszPat, false /* fUpdateRing0 */, stamR3ResetOne, pUVM->pVM); 692 693 STAM_UNLOCK_WR(pUVM); 624 694 return rc; 625 695 } 626 696 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 */ 707 STAMR3DECL(int) STAMR3Reset(PVM pVM, const char *pszPat) 708 { 709 return STAMR3ResetU(pVM->pUVM, pszPat); 710 } 711 712 627 713 628 714 /** 629 715 * Resets one statistics sample. 630 * Callback for stamR3Enum ().716 * Callback for stamR3EnumU(). 631 717 * 632 718 * @returns VINF_SUCCESS … … 706 792 * 707 793 * @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 */ 804 STAMR3DECL(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.) 708 847 * @param pVM The VM handle. 709 848 * @param pszPat The name matching pattern. See somewhere_where_this_is_described_in_detail. … … 718 857 STAMR3DECL(int) STAMR3Snapshot(PVM pVM, const char *pszPat, char **ppszSnapshot, size_t *pcchSnapshot, bool fWithDesc) 719 858 { 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. 758 865 * 759 866 * @returns VBox status code, but it's interpreted as 0 == success / !0 == failure by enmR3Enum. … … 986 1093 * 987 1094 * @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 */ 1099 STAMR3DECL(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. 988 1111 * @param pVM The VM handle. 989 1112 * @param pszSnapshot The snapshot data pointer returned by STAMR3Snapshot(). … … 992 1115 STAMR3DECL(int) STAMR3SnapshotFree(PVM pVM, char *pszSnapshot) 993 1116 { 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 */ 1129 STAMR3DECL(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); 996 1139 return VINF_SUCCESS; 997 1140 } … … 1008 1151 STAMR3DECL(int) STAMR3Dump(PVM pVM, const char *pszPat) 1009 1152 { 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); 1019 1154 } 1020 1155 … … 1041 1176 * 1042 1177 * @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 */ 1182 STAMR3DECL(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. 1043 1200 * @param pVM The VM handle. 1044 1201 * @param pszPat The name matching pattern. See somewhere_where_this_is_described_in_detail. … … 1047 1204 STAMR3DECL(int) STAMR3DumpToReleaseLog(PVM pVM, const char *pszPat) 1048 1205 { 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); 1058 1207 } 1059 1208 … … 1084 1233 * If NULL all samples are reset. 1085 1234 */ 1086 STAMR3DECL(int) STAMR3Print (PVM pVM, const char *pszPat)1235 STAMR3DECL(int) STAMR3PrintU(PUVM pUVM, const char *pszPat) 1087 1236 { 1088 1237 STAMR3PRINTONEARGS Args; 1089 Args.pVM = p VM;1238 Args.pVM = pUVM->pVM; 1090 1239 Args.pvArg = NULL; 1091 1240 Args.pfnPrintf = stamR3EnumPrintf; 1092 1241 1093 STAM_LOCK_RD(p VM);1094 stamR3Enum (pVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args);1095 STAM_UNLOCK_RD(p VM);1242 STAM_LOCK_RD(pUVM); 1243 stamR3EnumU(pUVM, pszPat, true /* fUpdateRing0 */, stamR3PrintOne, &Args); 1244 STAM_UNLOCK_RD(pUVM); 1096 1245 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 */ 1257 STAMR3DECL(int) STAMR3Print(PVM pVM, const char *pszPat) 1258 { 1259 return STAMR3PrintU(pVM->pUVM, pszPat); 1097 1260 } 1098 1261 … … 1117 1280 /** 1118 1281 * Prints one sample. 1119 * Callback for stamR3Enum ().1282 * Callback for stamR3EnumU(). 1120 1283 * 1121 1284 * @returns VINF_SUCCESS … … 1235 1398 * @returns Whatever the callback returns. 1236 1399 * 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 */ 1405 STAMR3DECL(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 * 1237 1424 * @param pVM The VM handle. 1238 1425 * @param pszPat The pattern to match samples. … … 1242 1429 STAMR3DECL(int) STAMR3Enum(PVM pVM, const char *pszPat, PFNSTAMR3ENUM pfnEnum, void *pvUser) 1243 1430 { 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); 1253 1432 } 1254 1433 … … 1419 1598 * 1420 1599 * @returns The rc from the callback. 1421 * @param p VM VM handle1600 * @param pUVM Pointer to the user mode VM structure. 1422 1601 * @param pszPat Pattern. 1423 1602 * @param fUpdateRing0 Update the ring-0 . … … 1427 1606 * @param pvArg User parameter for the callback. 1428 1607 */ 1429 static int stamR3Enum (PVM pVM, const char *pszPat, bool fUpdateRing0, int (*pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg)1608 static int stamR3EnumU(PUVM pUVM, const char *pszPat, bool fUpdateRing0, int (*pfnCallback)(PSTAMDESC pDesc, void *pvArg), void *pvArg) 1430 1609 { 1431 1610 int rc = VINF_SUCCESS; … … 1437 1616 { 1438 1617 if (fUpdateRing0) 1439 stamR3Ring0StatsUpdate (pVM, "*");1440 1441 PSTAMDESC pCur = p VM->stam.s.pHead;1618 stamR3Ring0StatsUpdateU(pUVM, "*"); 1619 1620 PSTAMDESC pCur = pUVM->stam.s.pHead; 1442 1621 while (pCur) 1443 1622 { … … 1457 1636 { 1458 1637 if (fUpdateRing0) 1459 stamR3Ring0StatsUpdate (pVM, pszPat);1638 stamR3Ring0StatsUpdateU(pUVM, pszPat); 1460 1639 1461 1640 /** @todo This needs to be optimized since the GUI is using this path for the VM info dialog. 1462 1641 * Note that it's doing exact matching. Organizing the samples in a tree would speed up thing 1463 1642 * no end (at least for debug and profile builds). */ 1464 for (PSTAMDESC pCur = p VM->stam.s.pHead; pCur; pCur = pCur->pNext)1643 for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext) 1465 1644 if (stamR3Match(pszPat, pCur->pszName)) 1466 1645 { … … 1489 1668 */ 1490 1669 if (fUpdateRing0) 1491 stamR3Ring0StatsUpdateMulti (pVM, papszExpressions, cExpressions);1670 stamR3Ring0StatsUpdateMultiU(pUVM, papszExpressions, cExpressions); 1492 1671 1493 1672 unsigned iExpression = 0; 1494 for (PSTAMDESC pCur = p VM->stam.s.pHead; pCur; pCur = pCur->pNext)1673 for (PSTAMDESC pCur = pUVM->stam.s.pHead; pCur; pCur = pCur->pNext) 1495 1674 if (stamR3MultiMatch(papszExpressions, cExpressions, &iExpression, pCur->pszName)) 1496 1675 { … … 1511 1690 * Registers the ring-0 statistics. 1512 1691 * 1513 * @param p VM Pointer to the sharedVM structure.1514 */ 1515 static void stamR3Ring0StatsRegister (PVM pVM)1692 * @param pUVM Pointer to the user mode VM structure. 1693 */ 1694 static void stamR3Ring0StatsRegisterU(PUVM pUVM) 1516 1695 { 1517 1696 /* GVMM */ 1518 1697 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); 1522 1701 } 1523 1702 … … 1526 1705 * Updates the ring-0 statistics (the copy). 1527 1706 * 1528 * @param p VM Pointer to the sharedVM structure.1707 * @param pUVM Pointer to the user mode VM structure. 1529 1708 * @param pszPat The pattern. 1530 1709 */ 1531 static void stamR3Ring0StatsUpdate (PVM pVM, const char *pszPat)1532 { 1533 stamR3Ring0StatsUpdateMulti (pVM, &pszPat, 1);1710 static void stamR3Ring0StatsUpdateU(PUVM pUVM, const char *pszPat) 1711 { 1712 stamR3Ring0StatsUpdateMultiU(pUVM, &pszPat, 1); 1534 1713 } 1535 1714 … … 1541 1720 * must be copied when needed. 1542 1721 * 1543 * @param p VM Pointer to the sharedVM structure.1722 * @param pUVM Pointer to the user mode VM structure. 1544 1723 * @param pszPat The pattern (for knowing when to skip). 1545 1724 */ 1546 static void stamR3Ring0StatsUpdateMulti(PVM pVM, const char * const *papszExpressions, unsigned cExpressions) 1547 { 1548 if (!pVM->pSession) 1725 static void stamR3Ring0StatsUpdateMultiU(PUVM pUVM, const char * const *papszExpressions, unsigned cExpressions) 1726 { 1727 PVM pVM = pUVM->pVM; 1728 if (!pVM || !pVM->pSession) 1549 1729 return; 1550 1730 … … 1565 1745 int rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_QUERY_STATISTICS, 0, &Req.Hdr); 1566 1746 if (RT_SUCCESS(rc)) 1567 p VM->stam.s.GVMMStats = Req.Stats;1747 pUVM->stam.s.GVMMStats = Req.Stats; 1568 1748 } 1569 1749 } … … 1622 1802 if (!pVM) 1623 1803 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) 1625 1806 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Sorry, no statistics present.\n"); 1626 1807 … … 1633 1814 Args.pfnPrintf = stamR3EnumDbgfPrintf; 1634 1815 1635 STAM_LOCK_RD(p VM);1636 int rc = stamR3Enum (pVM, cArgs ? paArgs[0].u.pszString : NULL, true /* fUpdateRing0 */, stamR3PrintOne, &Args);1637 STAM_UNLOCK_RD(p VM);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); 1638 1819 1639 1820 return rc; … … 1677 1858 if (!pVM) 1678 1859 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) 1680 1862 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "Sorry, no statistics present.\n"); 1681 1863 … … 1683 1865 * Execute reset. 1684 1866 */ 1685 int rc = STAMR3Reset (pVM, cArgs ? paArgs[0].u.pszString : NULL);1867 int rc = STAMR3ResetU(pUVM, cArgs ? paArgs[0].u.pszString : NULL); 1686 1868 if (VBOX_SUCCESS(rc)) 1687 1869 return pCmdHlp->pfnPrintf(pCmdHlp, NULL, "info: Statistics reset.\n"); -
trunk/src/VBox/VMM/STAMInternal.h
r5999 r6796 95 95 96 96 /** 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. 100 98 */ 101 #define STAM2VM(pSTAM) ( (PVM)((char*)pSTAM - pSTAM->offVM) ) 102 103 104 /** 105 * The stam data in the VM. 106 */ 107 struct STAM 99 typedef struct STAMUSERPERVM 108 100 { 109 /** Offset to the VM structure.110 * See STAM2VM(). */111 RTINT offVM;112 /** Alignment padding. */113 RTUINT uPadding;114 101 /** Pointer to the first sample. */ 115 102 R3PTRTYPE(PSTAMDESC) pHead; … … 119 106 /** The copy of the GVMM statistics. */ 120 107 GVMMSTATS GVMMStats; 121 }; 108 } STAMUSERPERVM; 109 /** Pointer to the STAM data kept in the UVM. */ 110 typedef STAMUSERPERVM *PSTAMUSERPERVM; 111 122 112 123 113 /** Locks the sample descriptors for reading. */ 124 #define STAM_LOCK_RD(p VM) 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) 125 115 /** Locks the sample descriptors for writing. */ 126 #define STAM_LOCK_WR(p VM) 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) 127 117 /** UnLocks the sample descriptors after reading. */ 128 #define STAM_UNLOCK_RD(p VM) 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) 129 119 /** UnLocks the sample descriptors after writing. */ 130 #define STAM_UNLOCK_WR(p VM) 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) 131 121 132 122 /** @} */ -
trunk/src/VBox/VMM/VM.cpp
r6633 r6796 43 43 #include "VMInternal.h" 44 44 #include <VBox/vm.h> 45 #include <VBox/uvm.h> 45 46 46 47 #include <VBox/sup.h> … … 82 83 *******************************************************************************/ 83 84 /** Pointer to the list of VMs. */ 84 static P VM g_pVMsHead;85 static PUVM g_pUVMsHead = NULL; 85 86 86 87 /** Pointer to the list of at VM destruction callbacks. */ 87 static PVMATDTOR g_pVMAtDtorHead ;88 static PVMATDTOR g_pVMAtDtorHead = NULL; 88 89 /** Lock the g_pVMAtDtorHead list. */ 89 90 #define VM_ATDTOR_LOCK() do { } while (0) … … 91 92 #define VM_ATDTOR_UNLOCK() do { } while (0) 92 93 94 93 95 /******************************************************************************* 94 96 * Internal Functions * 95 97 *******************************************************************************/ 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 );98 static int vmR3CreateUVM(PUVM *ppUVM); 99 static int vmR3CreateU(PUVM pUVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM); 100 static int vmR3InitRing3(PVM pVM, PUVM pUVM); 99 101 static int vmR3InitRing0(PVM pVM); 100 102 static int vmR3InitGC(PVM pVM); … … 106 108 static DECLCALLBACK(int) vmR3Load(PVM pVM, const char *pszFilename, PFNVMPROGRESS pfnProgress, void *pvUser); 107 109 static DECLCALLBACK(int) vmR3PowerOff(PVM pVM); 110 static void vmR3DestroyUVM(PUVM pUVM); 108 111 static void vmR3AtDtor(PVM pVM); 109 static int vmR3AtReset (PVM pVM);112 static int vmR3AtResetU(PUVM pUVM); 110 113 static 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); 114 static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser); 115 static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser); 116 static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser); 117 static DECLCALLBACK(int) vmR3AtErrorDeregisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser); 118 static int vmR3SetErrorU(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...); 119 static DECLCALLBACK(int) vmR3AtRuntimeErrorRegisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser); 120 static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser); 117 121 118 122 … … 127 131 * Only once. 128 132 */ 129 static bool fDone = false;130 if ( fDone)133 static bool volatile s_fDone = false; 134 if (s_fDone) 131 135 return VINF_SUCCESS; 132 136 … … 134 138 * We're done. 135 139 */ 136 fDone = true;140 s_fDone = true; 137 141 return VINF_SUCCESS; 138 142 } … … 175 179 176 180 /* 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); 189 196 if (RT_SUCCESS(rc)) 190 197 { 191 198 /* 192 * Request GVMM to create a new VM for us.199 * Call vmR3CreateU in the EMT thread and wait for it to finish. 193 200 */ 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); 201 204 if (RT_SUCCESS(rc)) 202 205 { 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); 218 208 if (RT_SUCCESS(rc)) 219 209 { 220 210 /* 221 * Initialize STAM.211 * Success! 222 212 */ 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; 291 216 } 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);299 217 } 300 218 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) 301 227 { 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; 305 241 } 242 vmR3SetErrorU(pUVM, rc, RT_SRC_POS, pszError, rc); 306 243 } 307 244 else 308 245 { 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); 311 301 } 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); 376 306 LogFlow(("VMR3Create: returns %Vrc\n", rc)); 377 307 return rc; … … 380 310 381 311 /** 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 */ 320 static 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 */ 378 static int vmR3CreateU(PUVM pUVM, PFNCFGMCONSTRUCTOR pfnCFGMConstructor, void *pvUserCFGM) 399 379 { 400 380 int rc = VINF_SUCCESS; 401 381 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 407 417 /* 408 418 * Init the configuration. … … 424 434 425 435 /* 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. 427 437 */ 428 /** @todo Check if the required minimum of resources are available. */438 rc = vmR3InitRing3(pVM, pUVM); 429 439 if (VBOX_SUCCESS(rc)) 430 440 { 441 VMR3Relocate(pVM, 0); 442 LogFlow(("Ring-3 init succeeded\n")); 443 431 444 /* 432 * Init the Ring- 3 components and do a round of relocations with 0 delta.445 * Init the Ring-0 components. 433 446 */ 434 rc = vmR3InitRing 3(pVM);447 rc = vmR3InitRing0(pVM); 435 448 if (VBOX_SUCCESS(rc)) 436 449 { 450 /* Relocate again, because some switcher fixups depends on R0 init results. */ 437 451 VMR3Relocate(pVM, 0); 438 LogFlow(("Ring-3 init succeeded\n")); 439 452 453 #ifdef VBOX_WITH_DEBUGGER 440 454 /* 441 * Init the Ring-0 components. 455 * Init the tcp debugger console if we're building 456 * with debugger support. 442 457 */ 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) 445 462 { 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 450 465 /* 451 * Init the tcp debugger console if we're building 452 * with debugger support. 466 * Init the Guest Context components. 453 467 */ 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)) 458 470 { 459 pVM->vm.s.pvDBGC = pvUser;460 #endif461 471 /* 462 * Init the Guest Context components.472 * Now we can safely set the VM halt method to default. 463 473 */ 464 rc = vmR3 InitGC(pVM);465 if ( VBOX_SUCCESS(rc))474 rc = vmR3SetHaltMethodU(pUVM, VMHALTMETHOD_DEFAULT); 475 if (RT_SUCCESS(rc)) 466 476 { 467 477 /* 468 * Now we can safely set the VM halt method to default.478 * Set the state and link into the global list. 469 479 */ 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; 481 484 } 485 } 482 486 #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 } 486 490 #endif 487 //.. 488 } 489 vmR3Destroy(pVM); 491 //.. 490 492 } 491 //..493 vmR3Destroy(pVM); 492 494 } 495 //.. 493 496 494 497 /* Clean CFGM. */ … … 496 499 AssertRC(rc2); 497 500 } 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)); 502 510 return rc; 503 511 } … … 508 516 * Initializes all R3 components of the VM 509 517 */ 510 static int vmR3InitRing3(PVM pVM )518 static int vmR3InitRing3(PVM pVM, PUVM pUVM) 511 519 { 512 520 int rc; … … 521 529 STAM_REG(pVM, &pVM->StatSwitcherToGC, STAMTYPE_PROFILE_ADV, "/PROF/VM/SwitchToGC", STAMUNIT_TICKS_PER_CALL, "Profiling switching to GC."); 522 530 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 529 531 STAM_REG(pVM, &pVM->StatSwitcherSaveRegs, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SaveRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC."); 530 532 STAM_REG(pVM, &pVM->StatSwitcherSysEnter, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/SysEnter", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC."); … … 539 541 STAM_REG(pVM, &pVM->StatSwitcherRstrRegs, STAMTYPE_PROFILE_ADV, "/VM/Switcher/ToGC/RstrRegs", STAMUNIT_TICKS_PER_CALL,"Profiling switching to GC."); 540 542 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."); 546 553 547 554 rc = CPUMR3Init(pVM); … … 756 763 */ 757 764 PGMR3Relocate(pVM, offDelta); 758 PDMR3LdrRelocate (pVM, offDelta);765 PDMR3LdrRelocateU(pVM->pUVM, offDelta); 759 766 PGMR3Relocate(pVM, 0); /* Repeat after PDM relocation. */ 760 767 CPUMR3Relocate(pVM); … … 1332 1339 * The VM handle is destroyed and can no longer be used up successful return. 1333 1340 * 1334 * @returns 0 on success. 1335 * @returns VBox error code on failure. 1341 * @returns VBox status code. 1336 1342 * @param pVM VM which should be destroyed. 1337 1343 * @thread Any thread but the emulation thread. … … 1348 1354 if (!pVM) 1349 1355 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; 1375 1371 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; 1380 1381 1381 1382 /* … … 1385 1386 vmR3AtDtor(pVM); 1386 1387 1387 pVM->pNext = g_pVMsHead;1388 g_pVMsHead = pVM;1389 1390 1388 /* 1391 1389 * If we are the EMT we'll delay the cleanup till later. … … 1393 1391 if (VM_IS_EMT(pVM)) 1394 1392 { 1395 pVM->vm.s.fEMTDoesTheCleanup = true; 1393 pUVM->vm.s.fEMTDoesTheCleanup = true; 1394 pUVM->vm.s.fTerminateEMT = true; 1396 1395 VM_FF_SET(pVM, VM_FF_TERMINATE); 1397 1396 } … … 1402 1401 */ 1403 1402 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)) 1408 1405 rc = pReq->iStatus; 1406 AssertRC(rc); 1409 1407 VMR3ReqFree(pReq); 1410 1408 … … 1412 1410 * Wait for the EMT thread to terminate. 1413 1411 */ 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)); 1423 1415 1424 1416 /* 1425 1417 * Now do the final bit where the heap and VM structures are freed up. 1426 1418 */ 1427 vmR3Destroy FinalBit(pVM);1419 vmR3DestroyUVM(pUVM); 1428 1420 } 1429 1421 … … 1434 1426 1435 1427 /** 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. 1438 1431 * 1439 1432 * @returns VBox status. … … 1442 1435 DECLCALLBACK(int) vmR3Destroy(PVM pVM) 1443 1436 { 1444 LogFlow(("vmR3Destroy: pVM=%p\n", pVM)); 1437 PUVM pUVM = pVM->pUVM; 1438 LogFlow(("vmR3Destroy: pVM=%p pUVM=%p\n", pVM, pUVM)); 1445 1439 VM_ASSERT_EMT(pVM); 1446 1440 … … 1467 1461 AssertRC(rc); 1468 1462 #ifdef VBOX_WITH_DEBUGGER 1469 rc = DBGCTcpTerminate(pVM, p VM->vm.s.pvDBGC);1470 pVM-> vm.s.pvDBGC = NULL;1463 rc = DBGCTcpTerminate(pVM, pUVM->vm.s.pvDBGC); 1464 pVM->pUVM->vm.s.pvDBGC = NULL; 1471 1465 #endif 1472 1466 AssertRC(rc); … … 1497 1491 rc = CPUMR3Term(pVM); 1498 1492 AssertRC(rc); 1499 rc = STAMR3Term(pVM);1500 AssertRC(rc);1501 1493 rc = PDMR3CritSectTerm(pVM); 1502 1494 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); 1509 1503 LogFlow(("vmR3Destroy: returning %Vrc\n", VINF_EM_TERMINATE)); 1510 1504 return VINF_EM_TERMINATE; … … 1513 1507 1514 1508 /** 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 */ 1515 void 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. 1517 1548 * 1518 1549 * @param pVM VM Handle. 1519 1550 */ 1520 void vmR3DestroyFinalBit(PVM pVM) 1521 { 1551 static 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 1522 1572 /* 1523 1573 * Free the event semaphores associated with the request packets. 1524 1574 */ 1525 1575 unsigned cReqs = 0; 1526 for (unsigned i = 0; i < ELEMENTS(pVM->vm.s.apReqFree); i++)1527 { 1528 PVMREQ pReq = p VM->vm.s.apReqFree[i];1529 p VM->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; 1530 1580 for (; pReq; pReq = pReq->pNext, cReqs++) 1531 1581 { … … 1534 1584 } 1535 1585 } 1536 Assert(cReqs == p VM->vm.s.cReqFree); NOREF(cReqs);1586 Assert(cReqs == pUVM->vm.s.cReqFree); NOREF(cReqs); 1537 1587 1538 1588 /* … … 1541 1591 for (unsigned i = 0; i < 10; i++) 1542 1592 { 1543 PVMREQ pReqHead = (PVMREQ)ASMAtomicXchgPtr((void *volatile *)&p VM->vm.s.pReqs, NULL);1593 PVMREQ pReqHead = (PVMREQ)ASMAtomicXchgPtr((void *volatile *)&pUVM->vm.s.pReqs, NULL); 1544 1594 AssertMsg(!pReqHead, ("This isn't supposed to happen! VMR3Destroy caller has to serialize this.\n")); 1545 1595 if (!pReqHead) … … 1547 1597 for (PVMREQ pReq = pReqHead; pReq; pReq = pReq->pNext) 1548 1598 { 1549 ASMAtomic XchgSize(&pReq->iStatus, VERR_INTERNAL_ERROR);1550 ASMAtomic XchgSize(&pReq->enmState, VMREQSTATE_INVALID);1599 ASMAtomicUoWriteSize(&pReq->iStatus, VERR_INTERNAL_ERROR); 1600 ASMAtomicWriteSize(&pReq->enmState, VMREQSTATE_INVALID); 1551 1601 RTSemEventSignal(pReq->EventSem); 1552 1602 RTThreadSleep(2); … … 1558 1608 1559 1609 /* 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); 1574 1632 1575 1633 RTLogFlush(NULL); … … 1591 1649 * destroyed during the enumeration. 1592 1650 */ 1651 PUVM pNext; 1593 1652 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; 1596 1657 } 1597 1658 … … 1781 1842 SELMR3Reset(pVM); 1782 1843 TRPMR3Reset(pVM); 1783 vmR3AtReset (pVM);1844 vmR3AtResetU(pVM->pUVM); 1784 1845 REMR3Reset(pVM); 1785 1846 IOMR3Reset(pVM); … … 1813 1874 * @returns VBox status code. 1814 1875 * Any failure is fatal. 1815 * @param p VM The VM which is being reset.1816 */ 1817 static int vmR3AtReset (PVM pVM)1876 * @param pUVM Pointe to the user mode VM structure. 1877 */ 1878 static int vmR3AtResetU(PUVM pUVM) 1818 1879 { 1819 1880 /* … … 1821 1882 */ 1822 1883 int rc = VINF_SUCCESS; 1823 for (PVMATRESET pCur = p VM->vm.s.pAtReset; pCur; pCur = pCur->pNext)1884 for (PVMATRESET pCur = pUVM->vm.s.pAtReset; pCur; pCur = pCur->pNext) 1824 1885 { 1825 1886 /* do the call */ … … 1830 1891 break; 1831 1892 case VMATRESETTYPE_INTERNAL: 1832 rc = pCur->u.Internal.pfnCallback(p VM, pCur->pvUser);1893 rc = pCur->u.Internal.pfnCallback(pUVM->pVM, pCur->pvUser); 1833 1894 break; 1834 1895 case VMATRESETTYPE_EXTERNAL: … … 1854 1915 * Internal registration function 1855 1916 */ 1856 static int vmr3AtResetRegister (PVM pVM, void *pvUser, const char *pszDesc, PVMATRESET *ppNew)1917 static int vmr3AtResetRegisterU(PUVM pUVM, void *pvUser, const char *pszDesc, PVMATRESET *ppNew) 1857 1918 { 1858 1919 /* 1859 1920 * Allocate restration structure. 1860 1921 */ 1861 PVMATRESET pNew = (PVMATRESET)MMR3HeapAlloc (pVM, MM_TAG_VM, sizeof(*pNew));1922 PVMATRESET pNew = (PVMATRESET)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew)); 1862 1923 if (pNew) 1863 1924 { … … 1868 1929 1869 1930 /* insert */ 1870 *p VM->vm.s.ppAtResetNext = pNew;1871 p VM->vm.s.ppAtResetNext = &pNew->pNext;1931 *pUVM->vm.s.ppAtResetNext = pNew; 1932 pUVM->vm.s.ppAtResetNext = &pNew->pNext; 1872 1933 1873 1934 *ppNew = pNew; … … 1903 1964 */ 1904 1965 PVMATRESET pNew; 1905 int rc = vmr3AtResetRegister (pVM, pvUser, pszDesc, &pNew);1966 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew); 1906 1967 if (VBOX_SUCCESS(rc)) 1907 1968 { … … 1942 2003 */ 1943 2004 PVMATRESET pNew; 1944 int rc = vmr3AtResetRegister (pVM, pvUser, pszDesc, &pNew);2005 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew); 1945 2006 if (VBOX_SUCCESS(rc)) 1946 2007 { … … 1980 2041 */ 1981 2042 PVMATRESET pNew; 1982 int rc = vmr3AtResetRegister (pVM, pvUser, pszDesc, &pNew);2043 int rc = vmr3AtResetRegisterU(pVM->pUVM, pvUser, pszDesc, &pNew); 1983 2044 if (VBOX_SUCCESS(rc)) 1984 2045 { … … 1998 2059 * 1999 2060 * @returns Pointer to the next callback structure. 2000 * @param p VM The VM.2061 * @param pUVM Pointer to the user mode VM structure. 2001 2062 * @param pCur The one to free. 2002 2063 * @param pPrev The one before pCur. 2003 2064 */ 2004 static PVMATRESET vmr3AtResetFree (PVM pVM, PVMATRESET pCur, PVMATRESET pPrev)2065 static PVMATRESET vmr3AtResetFreeU(PUVM pUVM, PVMATRESET pCur, PVMATRESET pPrev) 2005 2066 { 2006 2067 /* … … 2012 2073 pPrev->pNext = pNext; 2013 2074 if (!pNext) 2014 p VM->vm.s.ppAtResetNext = &pPrev->pNext;2075 pUVM->vm.s.ppAtResetNext = &pPrev->pNext; 2015 2076 } 2016 2077 else 2017 2078 { 2018 p VM->vm.s.pAtReset = pNext;2079 pUVM->vm.s.pAtReset = pNext; 2019 2080 if (!pNext) 2020 p VM->vm.s.ppAtResetNext = &pVM->vm.s.pAtReset;2081 pUVM->vm.s.ppAtResetNext = &pUVM->vm.s.pAtReset; 2021 2082 } 2022 2083 … … 2042 2103 int rc = VERR_VM_ATRESET_NOT_FOUND; 2043 2104 PVMATRESET pPrev = NULL; 2044 PVMATRESET pCur = pVM-> vm.s.pAtReset;2105 PVMATRESET pCur = pVM->pUVM->vm.s.pAtReset; 2045 2106 while (pCur) 2046 2107 { … … 2049 2110 && (!pfnCallback || pCur->u.Dev.pfnCallback == pfnCallback)) 2050 2111 { 2051 pCur = vmr3AtResetFree (pVM, pCur, pPrev);2112 pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev); 2052 2113 rc = VINF_SUCCESS; 2053 2114 } … … 2075 2136 int rc = VERR_VM_ATRESET_NOT_FOUND; 2076 2137 PVMATRESET pPrev = NULL; 2077 PVMATRESET pCur = pVM-> vm.s.pAtReset;2138 PVMATRESET pCur = pVM->pUVM->vm.s.pAtReset; 2078 2139 while (pCur) 2079 2140 { … … 2081 2142 && pCur->u.Internal.pfnCallback == pfnCallback) 2082 2143 { 2083 pCur = vmr3AtResetFree (pVM, pCur, pPrev);2144 pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev); 2084 2145 rc = VINF_SUCCESS; 2085 2146 } … … 2107 2168 int rc = VERR_VM_ATRESET_NOT_FOUND; 2108 2169 PVMATRESET pPrev = NULL; 2109 PVMATRESET pCur = pVM-> vm.s.pAtReset;2170 PVMATRESET pCur = pVM->pUVM->vm.s.pAtReset; 2110 2171 while (pCur) 2111 2172 { … … 2113 2174 && pCur->u.External.pfnCallback == pfnCallback) 2114 2175 { 2115 pCur = vmr3AtResetFree (pVM, pCur, pPrev);2176 pCur = vmr3AtResetFreeU(pVM->pUVM, pCur, pPrev); 2116 2177 rc = VINF_SUCCESS; 2117 2178 } … … 2186 2247 * Call the at state change callbacks. 2187 2248 */ 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) 2189 2250 { 2190 2251 pCur->pfnAtState(pVM, enmStateNew, enmStateOld, pCur->pvUser); … … 2229 2290 */ 2230 2291 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); 2232 2293 if (VBOX_FAILURE(rc)) 2233 2294 return rc; … … 2244 2305 * 2245 2306 * @returns VBox status code. 2246 * @param p VM VM handle.2307 * @param pUVM Pointer to the user mode VM structure. 2247 2308 * @param pfnAtState Pointer to callback. 2248 2309 * @param pvUser User argument. 2249 2310 * @thread EMT 2250 2311 */ 2251 static DECLCALLBACK(int) vmR3AtStateRegister (PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)2312 static DECLCALLBACK(int) vmR3AtStateRegisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser) 2252 2313 { 2253 2314 /* … … 2255 2316 */ 2256 2317 2257 PVMATSTATE pNew = (PVMATSTATE)MMR3HeapAlloc (pVM, MM_TAG_VM, sizeof(*pNew));2318 PVMATSTATE pNew = (PVMATSTATE)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew)); 2258 2319 if (!pNew) 2259 2320 return VERR_NO_MEMORY; … … 2265 2326 2266 2327 /* insert */ 2267 *p VM->vm.s.ppAtStateNext = pNew;2268 p VM->vm.s.ppAtStateNext = &pNew->pNext;2328 *pUVM->vm.s.ppAtStateNext = pNew; 2329 pUVM->vm.s.ppAtStateNext = &pNew->pNext; 2269 2330 2270 2331 return VINF_SUCCESS; … … 2298 2359 */ 2299 2360 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); 2301 2362 if (VBOX_FAILURE(rc)) 2302 2363 return rc; … … 2313 2374 * 2314 2375 * @returns VBox status code. 2315 * @param p VM VM handle.2376 * @param pUVM Pointer to the user mode VM structure. 2316 2377 * @param pfnAtState Pointer to callback. 2317 2378 * @param pvUser User argument. 2318 2379 * @thread EMT 2319 2380 */ 2320 static DECLCALLBACK(int) vmR3AtStateDeregister (PVM pVM, PFNVMATSTATE pfnAtState, void *pvUser)2321 { 2322 LogFlow(("vmR3AtStateDeregister : pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser));2381 static DECLCALLBACK(int) vmR3AtStateDeregisterU(PUVM pUVM, PFNVMATSTATE pfnAtState, void *pvUser) 2382 { 2383 LogFlow(("vmR3AtStateDeregisterU: pfnAtState=%p pvUser=%p\n", pfnAtState, pvUser)); 2323 2384 2324 2385 /* … … 2326 2387 */ 2327 2388 PVMATSTATE pPrev = NULL; 2328 PVMATSTATE pCur = p VM->vm.s.pAtState;2389 PVMATSTATE pCur = pUVM->vm.s.pAtState; 2329 2390 while ( pCur 2330 2391 && pCur->pfnAtState == pfnAtState … … 2347 2408 pPrev->pNext = pCur->pNext; 2348 2409 if (!pCur->pNext) 2349 p VM->vm.s.ppAtStateNext = &pPrev->pNext;2410 pUVM->vm.s.ppAtStateNext = &pPrev->pNext; 2350 2411 } 2351 2412 else 2352 2413 { 2353 p VM->vm.s.pAtState = pCur->pNext;2414 pUVM->vm.s.pAtState = pCur->pNext; 2354 2415 if (!pCur->pNext) 2355 p VM->vm.s.ppAtStateNext = &pVM->vm.s.pAtState;2416 pUVM->vm.s.ppAtStateNext = &pUVM->vm.s.pAtState; 2356 2417 } 2357 2418 … … 2378 2439 VMR3DECL(int) VMR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser) 2379 2440 { 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 */ 2454 VMR3DECL(int) VMR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser) 2455 { 2380 2456 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); 2390 2458 2391 2459 /* … … 2393 2461 */ 2394 2462 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); 2396 2464 if (VBOX_FAILURE(rc)) 2397 2465 return rc; … … 2408 2476 * 2409 2477 * @returns VBox status code. 2410 * @param p VM The VM handle.2478 * @param pUVM Pointer to the user mode VM structure. 2411 2479 * @param pfnAtError Pointer to callback. 2412 2480 * @param pvUser User argument. 2413 2481 * @thread EMT 2414 2482 */ 2415 static DECLCALLBACK(int) vmR3AtErrorRegister(PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)2483 static DECLCALLBACK(int) vmR3AtErrorRegisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser) 2416 2484 { 2417 2485 /* … … 2419 2487 */ 2420 2488 2421 PVMATERROR pNew = (PVMATERROR)MMR3HeapAlloc (pVM, MM_TAG_VM, sizeof(*pNew));2489 PVMATERROR pNew = (PVMATERROR)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew)); 2422 2490 if (!pNew) 2423 2491 return VERR_NO_MEMORY; … … 2429 2497 2430 2498 /* insert */ 2431 *p VM->vm.s.ppAtErrorNext = pNew;2432 p VM->vm.s.ppAtErrorNext = &pNew->pNext;2499 *pUVM->vm.s.ppAtErrorNext = pNew; 2500 pUVM->vm.s.ppAtErrorNext = &pNew->pNext; 2433 2501 2434 2502 return VINF_SUCCESS; … … 2462 2530 */ 2463 2531 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); 2465 2533 if (VBOX_FAILURE(rc)) 2466 2534 return rc; … … 2477 2545 * 2478 2546 * @returns VBox status code. 2479 * @param p VM The VM handle.2547 * @param pUVM Pointer to the user mode VM structure. 2480 2548 * @param pfnAtError Pointer to callback. 2481 2549 * @param pvUser User argument. 2482 2550 * @thread EMT 2483 2551 */ 2484 static DECLCALLBACK(int) vmR3AtErrorDeregister (PVM pVM, PFNVMATERROR pfnAtError, void *pvUser)2485 { 2486 LogFlow(("vmR3AtErrorDeregister : pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser));2552 static DECLCALLBACK(int) vmR3AtErrorDeregisterU(PUVM pUVM, PFNVMATERROR pfnAtError, void *pvUser) 2553 { 2554 LogFlow(("vmR3AtErrorDeregisterU: pfnAtError=%p pvUser=%p\n", pfnAtError, pvUser)); 2487 2555 2488 2556 /* … … 2490 2558 */ 2491 2559 PVMATERROR pPrev = NULL; 2492 PVMATERROR pCur = p VM->vm.s.pAtError;2560 PVMATERROR pCur = pUVM->vm.s.pAtError; 2493 2561 while ( pCur 2494 2562 && pCur->pfnAtError == pfnAtError … … 2511 2579 pPrev->pNext = pCur->pNext; 2512 2580 if (!pCur->pNext) 2513 p VM->vm.s.ppAtErrorNext = &pPrev->pNext;2581 pUVM->vm.s.ppAtErrorNext = &pPrev->pNext; 2514 2582 } 2515 2583 else 2516 2584 { 2517 p VM->vm.s.pAtError = pCur->pNext;2585 pUVM->vm.s.pAtError = pCur->pNext; 2518 2586 if (!pCur->pNext) 2519 p VM->vm.s.ppAtErrorNext = &pVM->vm.s.pAtError;2587 pUVM->vm.s.ppAtErrorNext = &pUVM->vm.s.pAtError; 2520 2588 } 2521 2589 … … 2583 2651 * Call the at error callbacks. 2584 2652 */ 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) 2586 2654 vmR3SetErrorWorkerDoCall(pVM, pCur, rc, RT_SRC_POS_ARGS, "%s", pszMessage); 2587 2655 } … … 2589 2657 2590 2658 /** 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 */ 2669 static 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 /** 2591 2680 * Worker which calls everyone listening to the VM error messages. 2592 2681 * 2593 * @param p VM The VM handle.2682 * @param pUVM Pointer to the user mode VM structure. 2594 2683 * @param rc The VBox status code. 2595 2684 * @param RT_SRC_POS_DECL The source position of this error. … … 2598 2687 * @thread EMT 2599 2688 */ 2600 DECLCALLBACK(void) vmR3SetError V(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *pArgs)2689 DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *pArgs) 2601 2690 { 2602 2691 #ifdef LOG_ENABLED … … 2615 2704 * Make a copy of the message. 2616 2705 */ 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); 2618 2708 2619 2709 /* 2620 2710 * Call the at error callbacks. 2621 2711 */ 2622 for (PVMATERROR pCur = p VM->vm.s.pAtError; pCur; pCur = pCur->pNext)2712 for (PVMATERROR pCur = pUVM->vm.s.pAtError; pCur; pCur = pCur->pNext) 2623 2713 { 2624 2714 va_list va2; 2625 2715 va_copy(va2, *pArgs); 2626 pCur->pfnAtError(p VM, pCur->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va2);2716 pCur->pfnAtError(pUVM->pVM, pCur->pvUser, rc, RT_SRC_POS_ARGS, pszFormat, va2); 2627 2717 va_end(va2); 2628 2718 } … … 2656 2746 */ 2657 2747 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); 2659 2749 if (VBOX_FAILURE(rc)) 2660 2750 return rc; … … 2671 2761 * 2672 2762 * @returns VBox status code. 2673 * @param p VM The VM handle.2763 * @param pUVM Pointer to the user mode VM structure. 2674 2764 * @param pfnAtRuntimeError Pointer to callback. 2675 2765 * @param pvUser User argument. 2676 2766 * @thread EMT 2677 2767 */ 2678 static DECLCALLBACK(int) vmR3AtRuntimeErrorRegister (PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)2768 static DECLCALLBACK(int) vmR3AtRuntimeErrorRegisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser) 2679 2769 { 2680 2770 /* … … 2682 2772 */ 2683 2773 2684 PVMATRUNTIMEERROR pNew = (PVMATRUNTIMEERROR)MMR3HeapAlloc (pVM, MM_TAG_VM, sizeof(*pNew));2774 PVMATRUNTIMEERROR pNew = (PVMATRUNTIMEERROR)MMR3HeapAllocU(pUVM, MM_TAG_VM, sizeof(*pNew)); 2685 2775 if (!pNew) 2686 2776 return VERR_NO_MEMORY; … … 2692 2782 2693 2783 /* insert */ 2694 *p VM->vm.s.ppAtRuntimeErrorNext = pNew;2695 p VM->vm.s.ppAtRuntimeErrorNext = &pNew->pNext;2784 *pUVM->vm.s.ppAtRuntimeErrorNext = pNew; 2785 pUVM->vm.s.ppAtRuntimeErrorNext = &pNew->pNext; 2696 2786 2697 2787 return VINF_SUCCESS; … … 2725 2815 */ 2726 2816 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); 2728 2818 if (VBOX_FAILURE(rc)) 2729 2819 return rc; … … 2740 2830 * 2741 2831 * @returns VBox status code. 2742 * @param p VM The VM handle.2832 * @param pUVM Pointer to the user mode VM structure. 2743 2833 * @param pfnAtRuntimeError Pointer to callback. 2744 2834 * @param pvUser User argument. 2745 2835 * @thread EMT 2746 2836 */ 2747 static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregister (PVM pVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser)2748 { 2749 LogFlow(("vmR3AtRuntimeErrorDeregister : pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser));2837 static DECLCALLBACK(int) vmR3AtRuntimeErrorDeregisterU(PUVM pUVM, PFNVMATRUNTIMEERROR pfnAtRuntimeError, void *pvUser) 2838 { 2839 LogFlow(("vmR3AtRuntimeErrorDeregisterU: pfnAtRuntimeError=%p pvUser=%p\n", pfnAtRuntimeError, pvUser)); 2750 2840 2751 2841 /* … … 2753 2843 */ 2754 2844 PVMATRUNTIMEERROR pPrev = NULL; 2755 PVMATRUNTIMEERROR pCur = p VM->vm.s.pAtRuntimeError;2845 PVMATRUNTIMEERROR pCur = pUVM->vm.s.pAtRuntimeError; 2756 2846 while ( pCur 2757 2847 && pCur->pfnAtRuntimeError == pfnAtRuntimeError … … 2774 2864 pPrev->pNext = pCur->pNext; 2775 2865 if (!pCur->pNext) 2776 p VM->vm.s.ppAtRuntimeErrorNext = &pPrev->pNext;2866 pUVM->vm.s.ppAtRuntimeErrorNext = &pPrev->pNext; 2777 2867 } 2778 2868 else 2779 2869 { 2780 p VM->vm.s.pAtRuntimeError = pCur->pNext;2870 pUVM->vm.s.pAtRuntimeError = pCur->pNext; 2781 2871 if (!pCur->pNext) 2782 p VM->vm.s.ppAtRuntimeErrorNext = &pVM->vm.s.pAtRuntimeError;2872 pUVM->vm.s.ppAtRuntimeErrorNext = &pUVM->vm.s.pAtRuntimeError; 2783 2873 } 2784 2874 … … 2844 2934 * Call the at runtime error callbacks. 2845 2935 */ 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) 2847 2937 vmR3SetRuntimeErrorWorkerDoCall(pVM, pCur, fFatal, pszErrorID, "%s", pszMessage); 2848 2938 } … … 2871 2961 * Call the at error callbacks. 2872 2962 */ 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) 2874 2964 { 2875 2965 va_list va2; -
trunk/src/VBox/VMM/VMEmt.cpp
r6632 r6796 28 28 #include "VMInternal.h" 29 29 #include <VBox/vm.h> 30 #include <VBox/uvm.h> 30 31 31 32 #include <VBox/err.h> … … 46 47 * @returns Thread exit code. 47 48 * @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). 49 50 */ 50 51 DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArgs) 51 52 { 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")); 54 56 55 57 /* 56 58 * Init the native thread member. 57 59 */ 58 PVM pVM = pArgs->pVM; 59 pVM->NativeThreadEMT = RTThreadGetNative(ThreadSelf); 60 pUVM->vm.s.NativeThreadEMT = RTThreadGetNative(ThreadSelf); 60 61 61 62 /* 62 63 * The request loop. 63 64 */ 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 */ 218 VMR3DECL(int) VMR3WaitForResume(PVM pVM) 219 { 220 /* 221 * The request loop. 222 */ 223 PUVM pUVM = pVM->pUVM; 64 224 VMSTATE enmBefore; 65 225 int rc; 66 Log(("vmR3EmulationThread: Emulation thread starting the days work... Thread=%#x pVM=%p\n", ThreadSelf, pVM));67 226 for (;;) 68 227 { 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 }75 228 76 229 /* … … 81 234 */ 82 235 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) 84 238 { 85 239 rc = VINF_EM_TERMINATE; 86 240 break; 87 241 } 88 if (pVM->vm.s.pReqs)242 else if (pUVM->vm.s.pReqs) 89 243 { 90 244 /* 91 245 * Service execute in EMT request. 92 246 */ 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); 204 248 Log(("vmR3EmulationThread: Req rc=%Vrc, VM state %d -> %d\n", rc, enmBefore, pVM->enmVMState)); 205 249 } … … 226 270 * Nothing important is pending, so wait for something. 227 271 */ 228 rc = VMR3Wait (pVM);272 rc = VMR3WaitU(pUVM); 229 273 if (VBOX_FAILURE(rc)) 230 274 break; … … 235 279 */ 236 280 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) 238 283 break; 239 284 … … 245 290 if ( VBOX_SUCCESS(rc) 246 291 && enmBefore != pVM->enmVMState 247 && (pVM->enmVMState == VMSTATE_RUNNING))292 && pVM->enmVMState == VMSTATE_RUNNING) 248 293 { 249 294 /* Only valid exit reason. */ … … 254 299 255 300 /* Return to the main loop in vmR3EmulationThread, which will clean up for us. */ 256 longjmp(p VM->vm.s.emtJumpEnv, 1);301 longjmp(pUVM->vm.s.emtJumpEnv, 1); 257 302 } 258 303 … … 268 313 switch (enmMethod) 269 314 { 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"; 276 322 } 277 323 } … … 280 326 /** 281 327 * 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 */ 331 static DECLCALLBACK(int) vmR3HaltOldDoHalt(PUVM pUVM, const uint32_t fMask, uint64_t /* u64Now*/) 284 332 { 285 333 /* 286 334 * Halt loop. 287 335 */ 336 PVM pVM = pUVM->pVM; 288 337 int rc = VINF_SUCCESS; 289 ASMAtomic XchgU32(&pVM->vm.s.fWait, 1);338 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true); 290 339 //unsigned cLoops = 0; 291 340 for (;;) … … 296 345 * addition to perhaps set an FF. 297 346 */ 298 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltPoll, a);347 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltPoll, a); 299 348 PDMR3Poll(pVM); 300 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltPoll, a);301 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltTimers, b);349 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltPoll, a); 350 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltTimers, b); 302 351 TMR3TimerQueuesDo(pVM); 303 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltTimers, b);352 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltTimers, b); 304 353 if (VM_FF_ISPENDING(pVM, fMask)) 305 354 break; … … 324 373 { 325 374 //RTLogPrintf("u64NanoTS=%RI64 cLoops=%d yield", u64NanoTS, cLoops++); 326 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltYield, a);375 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltYield, a); 327 376 RTThreadYield(); /* this is the best we can do here */ 328 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltYield, a);377 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltYield, a); 329 378 } 330 379 else if (u64NanoTS < 2000000) 331 380 { 332 381 //RTLogPrintf("u64NanoTS=%RI64 cLoops=%d sleep 1ms", u64NanoTS, cLoops++); 333 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltBlock, a);334 rc = RTSemEventWait(p VM->vm.s.EventSemWait, 1);335 STAM_REL_PROFILE_STOP(&p VM->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); 336 385 } 337 386 else 338 387 { 339 388 //RTLogPrintf("u64NanoTS=%RI64 cLoops=%d sleep %dms", u64NanoTS, cLoops++, (uint32_t)RT_MIN((u64NanoTS - 500000) / 1000000, 15)); 340 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltBlock, a);341 rc = RTSemEventWait(p VM->vm.s.EventSemWait, RT_MIN((u64NanoTS - 1000000) / 1000000, 15));342 STAM_REL_PROFILE_STOP(&p VM->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); 343 392 } 344 393 //uint64_t u64Slept = RTTimeNanoTS() - u64Start; … … 351 400 AssertRC(rc != VERR_INTERRUPTED); 352 401 AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc)); 402 ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true); 353 403 VM_FF_SET(pVM, VM_FF_TERMINATE); 354 404 rc = VERR_INTERNAL_ERROR; … … 357 407 } 358 408 409 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false); 359 410 return rc; 360 411 } … … 367 418 * @param pVM The VM handle. 368 419 */ 369 static int vmR3HaltMethod12ReadConfig (PVM pVM)420 static int vmR3HaltMethod12ReadConfigU(PUVM pUVM) 370 421 { 371 422 /* … … 373 424 */ 374 425 #if 1 /* DEBUGGING STUFF - REMOVE LATER */ 375 p VM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4;376 p VM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = 2*1000000;377 p VM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = 75*1000000;378 p VM->vm.s.Halt.Method12.u32StartSpinningCfg = 30*1000000;379 p VM->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; 380 431 #else 381 p VM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = 4;382 p VM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = 5*1000000;383 p VM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = 200*1000000;384 p VM->vm.s.Halt.Method12.u32StartSpinningCfg = 20*1000000;385 p VM->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; 386 437 #endif 387 438 … … 392 443 * here right now. sorry. 393 444 */ 394 PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(p VM), "/VMM/HaltedMethod1");445 PCFGMNODE pCfg = CFGMR3GetChild(CFGMR3GetRoot(pUVM->pVM), "/VMM/HaltedMethod1"); 395 446 if (pCfg) 396 447 { 397 448 uint32_t u32; 398 449 if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "LagBlockIntervalDivisor", &u32))) 399 p VM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = u32;450 pUVM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg = u32; 400 451 if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "MinBlockInterval", &u32))) 401 p VM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = u32;452 pUVM->vm.s.Halt.Method12.u32MinBlockIntervalCfg = u32; 402 453 if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "MaxBlockInterval", &u32))) 403 p VM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = u32;454 pUVM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg = u32; 404 455 if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "StartSpinning", &u32))) 405 p VM->vm.s.Halt.Method12.u32StartSpinningCfg = u32;456 pUVM->vm.s.Halt.Method12.u32StartSpinningCfg = u32; 406 457 if (RT_SUCCESS(CFGMR3QueryU32(pCfg, "StopSpinning", &u32))) 407 p VM->vm.s.Halt.Method12.u32StopSpinningCfg = u32;458 pUVM->vm.s.Halt.Method12.u32StopSpinningCfg = u32; 408 459 LogRel(("HaltedMethod1 config: %d/%d/%d/%d/%d\n", 409 p VM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg,410 p VM->vm.s.Halt.Method12.u32MinBlockIntervalCfg,411 p VM->vm.s.Halt.Method12.u32MaxBlockIntervalCfg,412 p VM->vm.s.Halt.Method12.u32StartSpinningCfg,413 p VM->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)); 414 465 } 415 466 … … 422 473 * 423 474 * @return VBox status code. 424 * @param p VM The VM handle.425 */ 426 static DECLCALLBACK(int) vmR3HaltMethod1Init(P VM pVM)427 { 428 return vmR3HaltMethod12ReadConfig (pVM);475 * @param pUVM Pointer to the user mode VM structure. 476 */ 477 static DECLCALLBACK(int) vmR3HaltMethod1Init(PUVM pUVM) 478 { 479 return vmR3HaltMethod12ReadConfigU(pUVM); 429 480 } 430 481 … … 435 486 * the lag has been eliminated. 436 487 */ 437 static DECLCALLBACK(int) vmR3HaltMethod1Halt(PVM pVM, const uint32_t fMask, uint64_t u64Now) 438 { 488 static DECLCALLBACK(int) vmR3HaltMethod1Halt(PUVM pUVM, const uint32_t fMask, uint64_t u64Now) 489 { 490 PVM pVM = pUVM->pVM; 491 439 492 /* 440 493 * To simplify things, we decide up-front whether we should switch to spinning or … … 448 501 if (u32CatchUpPct /* non-zero if catching up */) 449 502 { 450 if (p VM->vm.s.Halt.Method12.u64StartSpinTS)451 { 452 fSpinning = TMVirtualSyncGetLag(pVM) >= p VM->vm.s.Halt.Method12.u32StopSpinningCfg;503 if (pUVM->vm.s.Halt.Method12.u64StartSpinTS) 504 { 505 fSpinning = TMVirtualSyncGetLag(pVM) >= pUVM->vm.s.Halt.Method12.u32StopSpinningCfg; 453 506 if (fSpinning) 454 507 { 455 508 uint64_t u64Lag = TMVirtualSyncGetLag(pVM); 456 fBlockOnce = u64Now - p VM->vm.s.Halt.Method12.u64LastBlockTS457 > RT_MAX(p VM->vm.s.Halt.Method12.u32MinBlockIntervalCfg,458 RT_MIN(u64Lag / p VM->vm.s.Halt.Method12.u32LagBlockIntervalDivisorCfg,459 p VM->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)); 460 513 } 461 514 else 462 515 { 463 //RTLogRelPrintf("Stopped spinning (%u ms)\n", (u64Now - p VM->vm.s.Halt.Method12.u64StartSpinTS) / 1000000);464 p VM->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; 465 518 } 466 519 } 467 520 else 468 521 { 469 fSpinning = TMVirtualSyncGetLag(pVM) >= p VM->vm.s.Halt.Method12.u32StartSpinningCfg;522 fSpinning = TMVirtualSyncGetLag(pVM) >= pUVM->vm.s.Halt.Method12.u32StartSpinningCfg; 470 523 if (fSpinning) 471 p VM->vm.s.Halt.Method12.u64StartSpinTS = u64Now;472 } 473 } 474 else if (p VM->vm.s.Halt.Method12.u64StartSpinTS)475 { 476 //RTLogRelPrintf("Stopped spinning (%u ms)\n", (u64Now - p VM->vm.s.Halt.Method12.u64StartSpinTS) / 1000000);477 p VM->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; 478 531 } 479 532 … … 482 535 */ 483 536 int rc = VINF_SUCCESS; 484 ASMAtomic XchgU32(&pVM->vm.s.fWait, 1);537 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true); 485 538 unsigned cLoops = 0; 486 539 for (;; cLoops++) … … 489 542 * Work the timers and check if we can exit. 490 543 */ 491 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltPoll, a);544 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltPoll, a); 492 545 PDMR3Poll(pVM); 493 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltPoll, a);494 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltTimers, b);546 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltPoll, a); 547 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltTimers, b); 495 548 TMR3TimerQueuesDo(pVM); 496 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltTimers, b);549 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltTimers, b); 497 550 if (VM_FF_ISPENDING(pVM, fMask)) 498 551 break; … … 516 569 #endif 517 570 { 518 const uint64_t Start = p VM->vm.s.Halt.Method12.u64LastBlockTS = RTTimeNanoTS();571 const uint64_t Start = pUVM->vm.s.Halt.Method12.u64LastBlockTS = RTTimeNanoTS(); 519 572 VMMR3YieldStop(pVM); 520 573 521 574 uint32_t cMilliSecs = RT_MIN(u64NanoTS / 1000000, 15); 522 if (cMilliSecs <= p VM->vm.s.Halt.Method12.cNSBlockedTooLongAvg)575 if (cMilliSecs <= pUVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg) 523 576 cMilliSecs = 1; 524 577 else 525 cMilliSecs -= p VM->vm.s.Halt.Method12.cNSBlockedTooLongAvg;578 cMilliSecs -= pUVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg; 526 579 //RTLogRelPrintf("u64NanoTS=%RI64 cLoops=%3d sleep %02dms (%7RU64) ", u64NanoTS, cLoops, cMilliSecs, u64NanoTS); 527 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltBlock, a);528 rc = RTSemEventWait(p VM->vm.s.EventSemWait, cMilliSecs);529 STAM_REL_PROFILE_STOP(&p VM->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); 530 583 if (rc == VERR_TIMEOUT) 531 584 rc = VINF_SUCCESS; … … 534 587 AssertRC(rc != VERR_INTERRUPTED); 535 588 AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc)); 589 ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true); 536 590 VM_FF_SET(pVM, VM_FF_TERMINATE); 537 591 rc = VERR_INTERNAL_ERROR; … … 544 598 */ 545 599 const uint64_t Elapsed = RTTimeNanoTS() - Start; 546 p VM->vm.s.Halt.Method12.cNSBlocked += Elapsed;600 pUVM->vm.s.Halt.Method12.cNSBlocked += Elapsed; 547 601 if (Elapsed > u64NanoTS) 548 p VM->vm.s.Halt.Method12.cNSBlockedTooLong += Elapsed - u64NanoTS;549 p VM->vm.s.Halt.Method12.cBlocks++;550 if (!(p VM->vm.s.Halt.Method12.cBlocks & 0xf))551 { 552 p VM->vm.s.Halt.Method12.cNSBlockedTooLongAvg = pVM->vm.s.Halt.Method12.cNSBlockedTooLong / pVM->vm.s.Halt.Method12.cBlocks;553 if (!(p VM->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)) 554 608 { 555 p VM->vm.s.Halt.Method12.cNSBlockedTooLong = pVM->vm.s.Halt.Method12.cNSBlockedTooLongAvg * 0x40;556 p VM->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; 557 611 } 558 612 } … … 569 623 //if (fSpinning) RTLogRelPrintf("spun for %RU64 ns %u loops; lag=%RU64 pct=%d\n", RTTimeNanoTS() - u64Now, cLoops, TMVirtualSyncGetLag(pVM), u32CatchUpPct); 570 624 625 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false); 571 626 return rc; 572 627 } … … 577 632 * 578 633 * @return VBox status code. 579 * @param p VM The VM handle.580 */ 581 static DECLCALLBACK(int) vmR3HaltGlobal1Init(P VM pVM)634 * @param pUVM Pointer to the user mode VM structure. 635 */ 636 static DECLCALLBACK(int) vmR3HaltGlobal1Init(PUVM pUVM) 582 637 { 583 638 return VINF_SUCCESS; … … 589 644 * try take care of the global scheduling of EMT threads. 590 645 */ 591 static DECLCALLBACK(int) vmR3HaltGlobal1Halt(PVM pVM, const uint32_t fMask, uint64_t u64Now) 592 { 646 static DECLCALLBACK(int) vmR3HaltGlobal1Halt(PUVM pUVM, const uint32_t fMask, uint64_t u64Now) 647 { 648 PVM pVM = pUVM->pVM; 649 593 650 /* 594 651 * Halt loop. 595 652 */ 596 653 int rc = VINF_SUCCESS; 597 ASMAtomic XchgU32(&pVM->vm.s.fWait, 1);654 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true); 598 655 unsigned cLoops = 0; 599 656 for (;; cLoops++) … … 602 659 * Work the timers and check if we can exit. 603 660 */ 604 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltPoll, a);661 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltPoll, a); 605 662 PDMR3Poll(pVM); 606 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltPoll, a);607 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltTimers, b);663 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltPoll, a); 664 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltTimers, b); 608 665 TMR3TimerQueuesDo(pVM); 609 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltTimers, b);666 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltTimers, b); 610 667 if (VM_FF_ISPENDING(pVM, fMask)) 611 668 break; … … 625 682 { 626 683 VMMR3YieldStop(pVM); 627 ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);628 684 if (VM_FF_ISPENDING(pVM, fMask)) 629 685 break; 630 686 631 687 //RTLogRelPrintf("u64NanoTS=%RI64 cLoops=%3d sleep %02dms (%7RU64) ", u64NanoTS, cLoops, cMilliSecs, u64NanoTS); 632 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltBlock, c);688 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltBlock, c); 633 689 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_SCHED_HALT, u64GipTime, NULL); 634 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltBlock, c);690 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltBlock, c); 635 691 if (rc == VERR_INTERRUPTED) 636 692 rc = VINF_SUCCESS; … … 638 694 { 639 695 AssertMsgFailed(("VMMR0_DO_GVMM_SCHED_HALT->%Vrc\n", rc)); 696 ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true); 640 697 VM_FF_SET(pVM, VM_FF_TERMINATE); 641 698 rc = VERR_INTERNAL_ERROR; … … 649 706 else if (!(cLoops & 0x1fff)) 650 707 { 651 STAM_REL_PROFILE_START(&p VM->vm.s.StatHaltYield, d);708 STAM_REL_PROFILE_START(&pUVM->vm.s.StatHaltYield, d); 652 709 rc = SUPCallVMMR0Ex(pVM->pVMR0, VMMR0_DO_GVMM_SCHED_POLL, false /* don't yield */, NULL); 653 STAM_REL_PROFILE_STOP(&p VM->vm.s.StatHaltYield, d);710 STAM_REL_PROFILE_STOP(&pUVM->vm.s.StatHaltYield, d); 654 711 } 655 712 } 656 713 //if (fSpinning) RTLogRelPrintf("spun for %RU64 ns %u loops; lag=%RU64 pct=%d\n", RTTimeNanoTS() - u64Now, cLoops, TMVirtualSyncGetLag(pVM), u32CatchUpPct); 657 714 715 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false); 658 716 return rc; 659 717 } … … 664 722 * 665 723 * @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 */ 726 static DECLCALLBACK(int) vmR3HaltGlobal1Wait(PUVM pUVM) 727 { 728 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true); 729 730 PVM pVM = pUVM->pVM; 670 731 int rc = VINF_SUCCESS; 671 ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);672 732 for (;;) 673 733 { … … 688 748 { 689 749 AssertMsgFailed(("RTSemEventWait->%Vrc\n", rc)); 750 ASMAtomicUoWriteBool(&pUVM->vm.s.fTerminateEMT, true); 690 751 VM_FF_SET(pVM, VM_FF_TERMINATE); 691 752 rc = VERR_INTERNAL_ERROR; … … 694 755 695 756 } 696 ASMAtomicXchgU32(&pVM->vm.s.fWait, 0); 757 758 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false); 697 759 return rc; 698 760 } … … 702 764 * The global 1 halt method - VMR3NotifyFF() worker. 703 765 * 704 * @param p VM The VM handle.705 * @param fNotifiedREM Se VMR3NotifyFF().706 */ 707 static DECLCALLBACK(void) vmR3HaltGlobal1NotifyFF(P VM pVM, bool fNotifiedREM)708 { 709 if (p VM->vm.s.fWait)710 { 711 int rc = SUPCallVMMR0Ex(p VM->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 */ 769 static 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); 712 774 AssertRC(rc); 713 775 } 714 776 else if (!fNotifiedREM) 715 REMR3NotifyFF(p VM);716 } 717 718 719 /** 720 * DefaultVMR3Wait() worker.777 REMR3NotifyFF(pUVM->pVM); 778 } 779 780 781 /** 782 * Bootstrap VMR3Wait() worker. 721 783 * 722 784 * @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 */ 787 static DECLCALLBACK(int) vmR3BootstrapWait(PUVM pUVM) 788 { 789 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, true); 790 727 791 int rc = VINF_SUCCESS; 728 ASMAtomicXchgU32(&pVM->vm.s.fWait, 1);729 792 for (;;) 730 793 { … … 732 795 * Check Relevant FFs. 733 796 */ 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)) 735 801 break; 736 802 … … 739 805 * anything needs our attention. 740 806 */ 741 rc = RTSemEventWait(p VM->vm.s.EventSemWait, 1000);807 rc = RTSemEventWait(pUVM->vm.s.EventSemWait, 1000); 742 808 if (rc == VERR_TIMEOUT) 743 809 rc = VINF_SUCCESS; … … 745 811 { 746 812 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 */ 833 static 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 */ 850 static 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); 747 875 VM_FF_SET(pVM, VM_FF_TERMINATE); 748 876 rc = VERR_INTERNAL_ERROR; … … 751 879 752 880 } 753 ASMAtomicXchgU32(&pVM->vm.s.fWait, 0); 881 882 ASMAtomicUoWriteBool(&pUVM->vm.s.fWait, false); 754 883 return rc; 755 884 } … … 759 888 * Default VMR3NotifyFF() worker. 760 889 * 761 * @param p VM The VM handle.762 * @param fNotifiedREM Se VMR3NotifyFF().763 */ 764 static DECLCALLBACK(void) vmR3DefaultNotifyFF(P VM pVM, bool fNotifiedREM)765 { 766 if (p VM->vm.s.fWait)767 { 768 int rc = RTSemEventSignal(p VM->vm.s.EventSemWait);890 * @param pUVM Pointer to the user mode VM structure. 891 * @param fNotifiedREM See VMR3NotifyFF(). 892 */ 893 static DECLCALLBACK(void) vmR3DefaultNotifyFF(PUVM pUVM, bool fNotifiedREM) 894 { 895 if (pUVM->vm.s.fWait) 896 { 897 int rc = RTSemEventSignal(pUVM->vm.s.EventSemWait); 769 898 AssertRC(rc); 770 899 } 771 900 else if (!fNotifiedREM) 772 REMR3NotifyFF(p VM);901 REMR3NotifyFF(pUVM->pVM); 773 902 } 774 903 … … 783 912 VMHALTMETHOD enmHaltMethod; 784 913 /** The init function for loading config and initialize variables. */ 785 DECLR3CALLBACKMEMBER(int, pfnInit,(P VM pVM));914 DECLR3CALLBACKMEMBER(int, pfnInit,(PUVM pUVM)); 786 915 /** The term function. */ 787 DECLR3CALLBACKMEMBER(void, pfnTerm,(P VM pVM));916 DECLR3CALLBACKMEMBER(void, pfnTerm,(PUVM pUVM)); 788 917 /** The halt function. */ 789 DECLR3CALLBACKMEMBER(int, pfnHalt,(P VM pVM, const uint32_t fMask, uint64_t u64Now));918 DECLR3CALLBACKMEMBER(int, pfnHalt,(PUVM pUVM, const uint32_t fMask, uint64_t u64Now)); 790 919 /** The wait function. */ 791 DECLR3CALLBACKMEMBER(int, pfnWait,(P VM pVM));920 DECLR3CALLBACKMEMBER(int, pfnWait,(PUVM pUVM)); 792 921 /** The notifyFF function. */ 793 DECLR3CALLBACKMEMBER(void, pfnNotifyFF,(P VM pVM, bool fNotifiedREM));922 DECLR3CALLBACKMEMBER(void, pfnNotifyFF,(PUVM pUVM, bool fNotifiedREM)); 794 923 } g_aHaltMethods[] = 795 924 { 925 { VMHALTMETHOD_BOOTSTRAP, NULL, NULL, NULL, vmR3BootstrapWait, vmR3BootstrapNotifyFF }, 796 926 { VMHALTMETHOD_OLD, NULL, NULL, vmR3HaltOldDoHalt, vmR3DefaultWait, vmR3DefaultNotifyFF }, 797 927 { VMHALTMETHOD_1, vmR3HaltMethod1Init, NULL, vmR3HaltMethod1Halt, vmR3DefaultWait, vmR3DefaultNotifyFF }, … … 814 944 { 815 945 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 */ 961 VMR3DECL(void) VMR3NotifyFFU(PUVM pUVM, bool fNotifiedREM) 962 { 963 LogFlow(("VMR3NotifyFF:\n")); 964 g_aHaltMethods[pUVM->vm.s.iHaltMethod].pfnNotifyFF(pUVM, fNotifiedREM); 817 965 } 818 966 … … 852 1000 * Record halt averages for the last second. 853 1001 */ 1002 PUVM pUVM = pVM->pUVM; 854 1003 uint64_t u64Now = RTTimeNanoTS(); 855 int64_t off = u64Now - p VM->vm.s.u64HaltsStartTS;1004 int64_t off = u64Now - pUVM->vm.s.u64HaltsStartTS; 856 1005 if (off > 1000000000) 857 1006 { 858 if (off > _4G || !p VM->vm.s.cHalts)859 { 860 p VM->vm.s.HaltInterval = 1000000000 /* 1 sec */;861 p VM->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; 862 1011 } 863 1012 else 864 1013 { 865 p VM->vm.s.HaltInterval = (uint32_t)off / pVM->vm.s.cHalts;866 p VM->vm.s.HaltFrequency = ASMMultU64ByU32DivByU32(pVM->vm.s.cHalts, 1000000000, (uint32_t)off);867 } 868 p VM->vm.s.u64HaltsStartTS = u64Now;869 p VM->vm.s.cHalts = 0;870 } 871 p VM->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++; 872 1021 873 1022 /* 874 1023 * Do the halt. 875 1024 */ 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 */ 882 1030 VMMR3YieldResume(pVM); 883 1031 … … 894 1042 * @returns VINF_SUCCESS unless a fatal error occured. In the latter 895 1043 * case an appropriate status code is returned. 896 * @param p VM VM handle.1044 * @param pUVM Pointer to the user mode VM structure. 897 1045 * @thread The emulation thread. 898 1046 */ 899 VMR3DECL(int) VMR3Wait (PVM pVM)900 { 901 LogFlow(("VMR3Wait :\n"));1047 VMR3DECL(int) VMR3WaitU(PUVM pUVM) 1048 { 1049 LogFlow(("VMR3WaitU:\n")); 902 1050 903 1051 /* 904 1052 * Check Relevant FFs. 905 1053 */ 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)) 907 1057 { 908 1058 LogFlow(("VMR3Wait: returns VINF_SUCCESS (FF %#x)\n", pVM->fForcedActions)); … … 914 1064 * doesn't have to special case anything). 915 1065 */ 916 int rc = g_aHaltMethods[p VM->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)); 918 1068 return rc; 919 1069 } … … 924 1074 * 925 1075 * @returns VBox status code. 926 * @param p VM The VM handle.1076 * @param pUVM Pointer to the user mode VM structure. 927 1077 * @param enmHaltMethod The new halt method. 928 1078 * @thread EMT. 929 1079 */ 930 int vmR3SetHaltMethod(PVM pVM, VMHALTMETHOD enmHaltMethod) 931 { 1080 int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod) 1081 { 1082 PVM pVM = pUVM->pVM; Assert(pVM); 932 1083 VM_ASSERT_EMT(pVM); 933 1084 AssertReturn(enmHaltMethod > VMHALTMETHOD_INVALID && enmHaltMethod < VMHALTMETHOD_END, VERR_INVALID_PARAMETER); … … 967 1118 * Terminate the old one. 968 1119 */ 969 if ( p VM->vm.s.enmHaltMethod != VMHALTMETHOD_INVALID970 && g_aHaltMethods[p VM->vm.s.iHaltMethod].pfnTerm)971 { 972 g_aHaltMethods[p VM->vm.s.iHaltMethod].pfnTerm(pVM);973 p VM->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; 974 1125 } 975 1126 … … 977 1128 * Init the new one. 978 1129 */ 979 memset(&p VM->vm.s.Halt, 0, sizeof(pVM->vm.s.Halt));1130 memset(&pUVM->vm.s.Halt, 0, sizeof(pUVM->vm.s.Halt)); 980 1131 if (g_aHaltMethods[i].pfnInit) 981 1132 { 982 int rc = g_aHaltMethods[i].pfnInit(p VM);1133 int rc = g_aHaltMethods[i].pfnInit(pUVM); 983 1134 AssertRCReturn(rc, rc); 984 1135 } 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); 987 1139 return VINF_SUCCESS; 988 1140 } -
trunk/src/VBox/VMM/VMInternal.h
r6398 r6796 192 192 /** The usual invalid value. */ 193 193 VMHALTMETHOD_INVALID = 0, 194 /** Use the method used during bootstrapping. */ 195 VMHALTMETHOD_BOOTSTRAP, 194 196 /** Use the default method. */ 195 197 VMHALTMETHOD_DEFAULT, … … 223 225 * See VMINT2VM(). */ 224 226 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 */ 239 typedef struct VMINTUSERPERVM 240 { 246 241 /** Head of the request queue. Atomic. */ 247 volatile R3PTRTYPE(PVMREQ)pReqs;242 volatile PVMREQ pReqs; 248 243 /** The last index used during alloc/free. */ 249 244 volatile uint32_t iReqFree; 250 /** Array of pointers to lists of free request packets. Atomic. */251 volatile R3PTRTYPE(PVMREQ) apReqFree[9];252 245 /** Number of free request packets. */ 253 246 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; 255 273 /** 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; 269 277 /** If set the EMT does the final VM cleanup when it exits. 270 278 * If clear the VMR3Destroy() caller does so. */ 271 279 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 buffer277 * @todo r=bird: requires union with padding. See EMInternal.h. */278 jmp_buf emtJumpEnv;279 280 280 281 /** @name Generic Halt data … … 374 375 } Halt; 375 376 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 * @{ */ 390 379 STAMPROFILE StatHaltYield; 391 380 STAMPROFILE StatHaltBlock; 392 381 STAMPROFILE StatHaltTimers; 393 382 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. */ 415 typedef VMINTUSERPERVM *PVMINTUSERPERVM; 416 407 417 408 418 DECLCALLBACK(int) vmR3EmulationThread(RTTHREAD ThreadSelf, void *pvArg); 409 int vmR3SetHaltMethod (PVM pVM, VMHALTMETHOD enmHaltMethod);419 int vmR3SetHaltMethodU(PUVM pUVM, VMHALTMETHOD enmHaltMethod); 410 420 DECLCALLBACK(int) vmR3Destroy(PVM pVM); 411 DECLCALLBACK(void) vmR3SetError V(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args);421 DECLCALLBACK(void) vmR3SetErrorUV(PUVM pUVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list *args); 412 422 void vmSetErrorCopy(PVM pVM, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list args); 413 423 DECLCALLBACK(void) vmR3SetRuntimeErrorV(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list *args); 414 424 void vmSetRuntimeErrorCopy(PVM pVM, bool fFatal, const char *pszErrorID, const char *pszFormat, va_list args); 415 void vmR3DestroyFinalBit (PVM pVM);425 void vmR3DestroyFinalBitFromEMT(PUVM pUVM); 416 426 void vmR3SetState(PVM pVM, VMSTATE enmStateNew); 417 427 -
trunk/src/VBox/VMM/VMMAll/VMAll.cpp
r5999 r6796 78 78 va_copy(va2, args); /* Have to make a copy here or GCC will break. */ 79 79 PVMREQ pReq; 80 VMR3ReqCall(pVM, &pReq, RT_INDEFINITE_WAIT, (PFNRT)vmR3SetError V, 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); 82 82 VMR3ReqFree(pReq); 83 83 va_end(va2); … … 202 202 * containig possible actions (for example, Retry/Ignore). For this reason, 203 203 * 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". 205 205 * 206 206 * @param pVM VM handle. Must be non-NULL. … … 214 214 * 215 215 * @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 219 219 * vm even. Change fFatal to fFlags and define action flags and a fatal flag. 220 * 220 * 221 221 * Also, why a string ID and not an enum? 222 222 */ -
trunk/src/VBox/VMM/VMMR0/VMMR0.cpp
r6528 r6796 83 83 if (RT_SUCCESS(rc)) 84 84 { 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. */ 86 86 rc = GMMR0Init(); 87 #endif87 //#endif 88 88 if (RT_SUCCESS(rc)) 89 89 { … … 134 134 * Destroy the GMM and GVMM instances. 135 135 */ 136 #ifdef VBOX_WITH_NEW_PHYS_CODE136 //#ifdef VBOX_WITH_NEW_PHYS_CODE 137 137 GMMR0Term(); 138 #endif138 //#endif 139 139 GVMMR0Term(); 140 140 -
trunk/src/VBox/VMM/VMReq.cpp
r6274 r6796 25 25 #include "VMInternal.h" 26 26 #include <VBox/vm.h> 27 #include <VBox/uvm.h> 27 28 28 29 #include <VBox/err.h> … … 40 41 * Internal Functions * 41 42 *******************************************************************************/ 42 static int vmR3ReqProcessOne(PVM pVM, PVMREQ pReq); 43 static 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 */ 69 VMR3DECL(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 } 43 77 44 78 … … 70 104 va_list va; 71 105 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 */ 135 VMR3DECL(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); 73 140 va_end(va); 74 141 return rc; … … 103 170 va_list va; 104 171 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); 106 173 va_end(va); 107 174 return rc; … … 138 205 va_list va; 139 206 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); 141 208 va_end(va); 142 209 return rc; … … 145 212 146 213 /** 147 * Allocate and queue a call request .214 * Allocate and queue a call request to a void function. 148 215 * 149 216 * If it's desired to poll on the completion of the request set cMillies … … 156 223 * @returns VERR_TIMEOUT if cMillies was reached without the packet being completed. 157 224 * 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 */ 238 VMR3DECL(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. 159 261 * @param ppReq Where to store the pointer to the request. 160 262 * This will be NULL or a valid request pointer not matter what happends, unless fFlags … … 169 271 * @param Args Argument vector. 170 272 */ 171 VMR3DECL(int) VMR3ReqCallV (PVM pVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args)273 VMR3DECL(int) VMR3ReqCallVU(PUVM pUVM, PVMREQ *ppReq, unsigned cMillies, unsigned fFlags, PFNRT pfnFunction, unsigned cArgs, va_list Args) 172 274 { 173 275 LogFlow(("VMR3ReqCallV: cMillies=%d fFlags=%#x pfnFunction=%p cArgs=%d\n", cMillies, fFlags, pfnFunction, cArgs)); 174 276 175 277 /* 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); 183 283 if (!(fFlags & VMREQFLAGS_NO_WAIT) || ppReq) 184 284 { 185 Assert (ppReq);285 AssertPtrReturn(ppReq, VERR_INVALID_POINTER); 186 286 *ppReq = NULL; 187 287 } 188 288 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); 194 292 195 293 /* 196 294 * Allocate request 197 295 */ 198 int rc = VMR3ReqAlloc (pVM, &pReq, VMREQTYPE_INTERNAL);296 int rc = VMR3ReqAllocU(pUVM, &pReq, VMREQTYPE_INTERNAL); 199 297 if (VBOX_FAILURE(rc)) 200 298 return rc; … … 260 358 * Joins the list pList with whatever is linked up at *pHead. 261 359 */ 262 static void vmr3ReqJoinFree(PVMINT pVMInt, PVMREQ pList)360 static void vmr3ReqJoinFree(PVMINTUSERPERVM pVMInt, PVMREQ pList) 263 361 { 264 362 /* … … 272 370 { 273 371 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); 275 373 276 374 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); 278 376 return; 279 377 } 280 378 pTail = pTail->pNext; 281 379 } 282 vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(pVMInt->iReqFree + 2) % ELEMENTS(pVMInt->apReqFree)], pList);380 vmr3ReqJoinFreeSub(&pVMInt->apReqFree[(pVMInt->iReqFree + 2) % RT_ELEMENTS(pVMInt->apReqFree)], pList); 283 381 } 284 382 … … 298 396 VMR3DECL(int) VMR3ReqAlloc(PVM pVM, PVMREQ *ppReq, VMREQTYPE enmType) 299 397 { 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 */ 414 VMR3DECL(int) VMR3ReqAllocU(PUVM pUVM, PVMREQ *ppReq, VMREQTYPE enmType) 415 { 300 416 /* 301 417 * Validate input. 302 418 */ 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); 310 424 311 425 /* … … 314 428 * of mine to avoid locks. 315 429 */ 316 int cTries = ELEMENTS(pVM->vm.s.apReqFree) * 2;430 int cTries = RT_ELEMENTS(pUVM->vm.s.apReqFree) * 2; 317 431 while (--cTries >= 0) 318 432 { 319 PVMREQ volatile *ppHead = &p VM->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)]; 320 434 #if 0 /* sad, but this won't work safely because the reading of pReq->pNext. */ 321 435 PVMREQ pNext = NULL; … … 337 451 && !ASMAtomicCmpXchgPtr((void * volatile *)ppHead, pNext, NULL)) 338 452 { 339 STAM_COUNTER_INC(&p VM->vm.s.StatReqAllocRaces);340 vmr3ReqJoinFree(&p VM->vm.s, pReq->pNext);453 STAM_COUNTER_INC(&pUVM->vm.s.StatReqAllocRaces); 454 vmr3ReqJoinFree(&pUVM->vm.s, pReq->pNext); 341 455 } 342 456 #endif 343 ASMAtomicDecU32(&p VM->vm.s.cReqFree);457 ASMAtomicDecU32(&pUVM->vm.s.cReqFree); 344 458 345 459 /* … … 372 486 Assert(pReq->enmType == VMREQTYPE_INVALID); 373 487 Assert(pReq->enmState == VMREQSTATE_FREE); 374 Assert(pReq->p VM == pVM);488 Assert(pReq->pUVM == pUVM); 375 489 ASMAtomicXchgSize(&pReq->pNext, NULL); 376 490 pReq->enmState = VMREQSTATE_ALLOCATED; … … 380 494 381 495 *ppReq = pReq; 382 STAM_COUNTER_INC(&p VM->vm.s.StatReqAllocRecycled);496 STAM_COUNTER_INC(&pUVM->vm.s.StatReqAllocRecycled); 383 497 LogFlow(("VMR3ReqAlloc: returns VINF_SUCCESS *ppReq=%p recycled\n", pReq)); 384 498 return VINF_SUCCESS; … … 389 503 * Ok allocate one. 390 504 */ 391 PVMREQ pReq = (PVMREQ)MMR3HeapAlloc (pVM, MM_TAG_VM_REQ, sizeof(*pReq));505 PVMREQ pReq = (PVMREQ)MMR3HeapAllocU(pUVM, MM_TAG_VM_REQ, sizeof(*pReq)); 392 506 if (!pReq) 393 507 return VERR_NO_MEMORY; … … 408 522 */ 409 523 pReq->pNext = NULL; 410 pReq->p VM = pVM;524 pReq->pUVM = pUVM; 411 525 pReq->enmState = VMREQSTATE_ALLOCATED; 412 526 pReq->iStatus = VERR_VM_REQUEST_STATUS_STILL_PENDING; … … 416 530 417 531 *ppReq = pReq; 418 STAM_COUNTER_INC(&p VM->vm.s.StatReqAllocNew);532 STAM_COUNTER_INC(&pUVM->vm.s.StatReqAllocNew); 419 533 LogFlow(("VMR3ReqAlloc: returns VINF_SUCCESS *ppReq=%p new\n", pReq)); 420 534 return VINF_SUCCESS; … … 437 551 if (!pReq) 438 552 return VINF_SUCCESS; 439 440 STAM_COUNTER_INC(&pReq->pVM->vm.s.StatReqFree);441 553 442 554 /* … … 460 572 pReq->enmType = VMREQTYPE_INVALID; 461 573 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)]; 467 581 PVMREQ pNext; 468 582 do … … 474 588 else 475 589 { 476 STAM_COUNTER_INC(&pReq->p VM->vm.s.StatReqFreeOverflow);590 STAM_COUNTER_INC(&pReq->pUVM->vm.s.StatReqFreeOverflow); 477 591 RTSemEventDestroy(pReq->EventSem); 478 592 MMR3HeapFree(pReq); … … 506 620 * Verify the supplied package. 507 621 */ 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); 527 633 528 634 /* … … 531 637 */ 532 638 int rc = VINF_SUCCESS; 533 P VM pVM = ((VMREQ volatile *)pReq)->pVM;/* volatile paranoia */534 if (p VM->NativeThreadEMT != RTThreadNativeSelf())639 PUVM pUVM = ((VMREQ volatile *)pReq)->pUVM; /* volatile paranoia */ 640 if (pUVM->vm.s.NativeThreadEMT != RTThreadNativeSelf()) 535 641 { 536 642 unsigned fFlags = ((VMREQ volatile *)pReq)->fFlags; /* volatile paranoia */ … … 543 649 do 544 650 { 545 pNext = p VM->vm.s.pReqs;651 pNext = pUVM->vm.s.pReqs; 546 652 pReq->pNext = pNext; 547 } while (!ASMAtomicCmpXchgPtr((void * volatile *)&p VM->vm.s.pReqs, (void *)pReq, (void *)pNext));653 } while (!ASMAtomicCmpXchgPtr((void * volatile *)&pUVM->vm.s.pReqs, (void *)pReq, (void *)pNext)); 548 654 549 655 /* 550 656 * Notify EMT. 551 657 */ 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); 554 661 555 662 /* … … 566 673 */ 567 674 pReq->enmState = VMREQSTATE_QUEUED; 568 rc = vmR3ReqProcessOne (pVM, pReq);675 rc = vmR3ReqProcessOneU(pUVM, pReq); 569 676 LogFlow(("VMR3ReqQueue: returns %Vrc (processed)\n", rc)); 570 677 } … … 590 697 * Verify the supplied package. 591 698 */ 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); 612 713 613 714 /* 614 715 * Check for deadlock condition 615 716 */ 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")); 617 720 618 721 /* … … 644 747 * Process pending request(s). 645 748 * 646 * This function is called from a forced action handler in 647 * the EMT.648 * 649 * @returns VBox status code. 650 * 651 * @param p VM 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 */ 756 VMR3DECL(int) VMR3ReqProcessU(PUVM pUVM) 757 { 758 LogFlow(("VMR3ReqProcessU: (enmVMState=%d)\n", pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_CREATING)); 656 759 657 760 /* … … 667 770 * Get pending requests. 668 771 */ 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); 671 775 if (!pReqs) 672 776 break; … … 682 786 { 683 787 Assert(pReq->enmState == VMREQSTATE_QUEUED); 684 Assert(pReq->p VM == pVM);788 Assert(pReq->pUVM == pUVM); 685 789 PVMREQ pCur = pReq; 686 790 pReq = pReq->pNext; … … 704 808 705 809 /* Process the request */ 706 int rc2 = vmR3ReqProcessOne (pVM, pReq);810 int rc2 = vmR3ReqProcessOneU(pUVM, pReq); 707 811 708 812 /* … … 718 822 } 719 823 720 LogFlow(("VMR3ReqProcess: returns %Vrc (enmVMState=%d)\n", rc, p VM->enmVMState));824 LogFlow(("VMR3ReqProcess: returns %Vrc (enmVMState=%d)\n", rc, pUVM->pVM ? pUVM->pVM->enmVMState : VMSTATE_CREATING)); 721 825 return rc; 722 826 } … … 731 835 * @param pReq Request packet to process. 732 836 */ 733 static int vmR3ReqProcessOne (PVM pVM, PVMREQ pReq)837 static int vmR3ReqProcessOneU(PUVM pUVM, PVMREQ pReq) 734 838 { 735 839 LogFlow(("vmR3ReqProcessOne: pReq=%p type=%d fFlags=%#x\n", pReq, pReq->enmType, pReq->fFlags)); -
trunk/src/VBox/VMM/testcase/tstCFGM.cpp
r5999 r6796 25 25 #include <VBox/mm.h> 26 26 #include <VBox/vm.h> 27 #include <VBox/uvm.h> 27 28 28 29 #include <VBox/err.h> 29 30 #include <VBox/param.h> 30 #include <iprt/ runtime.h>31 #include <iprt/initterm.h> 31 32 #include <iprt/stream.h> 32 33 #include <iprt/string.h> … … 46 47 int rc = SUPInit(NULL); 47 48 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); 49 50 if (VBOX_FAILURE(rc)) 50 51 { … … 53 54 } 54 55 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); 56 69 if (VBOX_FAILURE(rc)) 57 70 { -
trunk/src/VBox/VMM/testcase/tstMMHyperHeap.cpp
r5999 r6796 22 22 #include <VBox/stam.h> 23 23 #include <VBox/vm.h> 24 #include <VBox/uvm.h> 24 25 #include <VBox/sup.h> 25 26 #include <VBox/param.h> … … 27 28 28 29 #include <VBox/log.h> 29 #include <iprt/runtime.h> 30 #include <iprt/initterm.h> 31 #include <iprt/mem.h> 30 32 #include <iprt/assert.h> 31 33 #include <iprt/stream.h> … … 33 35 34 36 35 int main(int argc, char * argv[])37 int main(int argc, char **argv) 36 38 { 37 39 … … 45 47 */ 46 48 PVM pVM; 49 RTR0PTR pvR0; 50 SUPPAGE aPages[RT_ALIGN_Z(sizeof(*pVM), PAGE_SIZE) >> PAGE_SHIFT]; 47 51 int rc = SUPInit(NULL); 48 52 if (VBOX_SUCCESS(rc)) 49 rc = SUP PageAlloc((sizeof(*pVM) + PAGE_SIZE - 1) >> PAGE_SHIFT, (void **)&pVM);53 rc = SUPLowAlloc(RT_ELEMENTS(aPages), (void **)&pVM, &pvR0, &aPages[0]); 50 54 if (VBOX_FAILURE(rc)) 51 55 { … … 53 57 return 1; 54 58 } 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 61 82 rc = MMR3Init(pVM); 62 83 if (VBOX_FAILURE(rc)) -
trunk/src/VBox/VMM/testcase/tstSSM.cpp
r5999 r6796 573 573 } 574 574 575 rc = STAMR3Init(pVM);575 ///@todo rc = STAMR3Init(pVM); 576 576 if (VBOX_FAILURE(rc)) 577 577 { -
trunk/src/VBox/VMM/testcase/tstVMStructGC.cpp
r6627 r6796 187 187 GEN_CHECK_OFF(MM, cShadowPages); 188 188 GEN_CHECK_OFF(MM, cFixedPages); 189 GEN_CHECK_OFF(MM, pHeap);190 189 GEN_CHECK_SIZE(MMHYPERSTAT); 191 190 GEN_CHECK_SIZE(MMHYPERCHUNK); … … 218 217 GEN_CHECK_SIZE(PDM); 219 218 GEN_CHECK_OFF(PDM, offVM); 220 GEN_CHECK_OFF(PDM, pModules);221 219 GEN_CHECK_OFF(PDM, pDevs); 222 220 GEN_CHECK_OFF(PDM, pDevInstances); … … 660 658 GEN_CHECK_OFF(SELM, StatUpdateFromCPUM); 661 659 662 GEN_CHECK_SIZE(STAM);663 664 660 GEN_CHECK_SIZE(TM); 665 661 GEN_CHECK_OFF(TM, offVM); -
trunk/src/VBox/VMM/testcase/tstVMStructSize.cpp
r5999 r6796 133 133 CHECK_PADDING_VM(pgm); 134 134 CHECK_PADDING_VM(selm); 135 CHECK_PADDING_VM(stam);136 135 CHECK_PADDING_VM(tm); 137 136 CHECK_PADDING_VM(trpm);
Note:
See TracChangeset
for help on using the changeset viewer.