Changeset 106054 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Sep 13, 2024 8:11:59 PM (4 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/GCM.cpp
r106049 r106054 79 79 * Global Variables * 80 80 *********************************************************************************************************************************/ 81 typedef enum 82 { 83 /** Invalid zero value. */ 84 kGcmLoadAct_Invalid = 0, 85 /** The fixer is set up at VM config and has additional state/whatever that 86 * prevents it from being reconfigured during state load. */ 87 kGcmLoadAct_NoReconfigFail, 88 /** The fixer is set up at VM config but it doesn't really matter too 89 * much whether we keep using the VM config instead of the saved state. */ 90 kGcmLoadAct_NoReconfigIgnore, 91 /** The fixer state is only checked at runtime, so it's no problem to 92 * reconfigure it during state load. */ 93 kGcmLoadAct_Reconfigurable, 94 kGcmLoadAct_End 95 } GCMLOADACTION; 81 96 /** Fixer flag configuration names. */ 82 97 static struct 83 98 { 84 const char *pszName;85 uint8_t cchName;86 bool fSafeToClearOnLoad;87 uint32_t fFlag;99 const char *pszName; 100 uint8_t cchName; 101 uint8_t uBit; 102 GCMLOADACTION enmLoadAction; 88 103 } const g_aGcmFixerIds[] = 89 104 { 90 { RT_STR_TUPLE("DivByZeroDOS"), false, GCMFIXER_DBZ_DOS }, /* These aren't safe to clear on load, */91 { RT_STR_TUPLE("DivByZeroOS2"), false, GCMFIXER_DBZ_OS2 }, /* because HM and NEM only queries them */92 { RT_STR_TUPLE("DivByZeroWin9x"), false, GCMFIXER_DBZ_WIN9X }, /* on VM init. */93 { RT_STR_TUPLE("MesaVmsvgaDrv"), true, GCMFIXER_MESA_VMSVGA_DRV }, /* This is checked for every access, so okay. */105 { RT_STR_TUPLE("DivByZeroDOS"), GCMFIXER_DBZ_DOS_BIT, kGcmLoadAct_NoReconfigIgnore }, 106 { RT_STR_TUPLE("DivByZeroOS2"), GCMFIXER_DBZ_OS2_BIT, kGcmLoadAct_NoReconfigIgnore }, 107 { RT_STR_TUPLE("DivByZeroWin9x"), GCMFIXER_DBZ_WIN9X_BIT, kGcmLoadAct_NoReconfigIgnore }, 108 { RT_STR_TUPLE("MesaVmsvgaDrv"), GCMFIXER_MESA_VMSVGA_DRV_BIT, kGcmLoadAct_Reconfigurable }, 94 109 }; 110 111 /** Max g_aGcmFixerIds::cchName value. */ 112 #define GCM_FIXER_ID_MAX_NAME_LEN 30 113 114 /** Max size of the gcmFixerIdsToString output. */ 115 #define GCM_FIXER_SET_MAX_STRING_SIZE (2 + (GCM_FIXER_ID_MAX_NAME_LEN + 2) * (RT_ELEMENTS(g_aGcmFixerIds) + 1) + 2) 95 116 96 117 … … 132 153 */ 133 154 /* Assemble valid value names for CFMGR3ValidateConfig. */ 134 char szValidValues[ 1024];155 char szValidValues[GCM_FIXER_SET_MAX_STRING_SIZE]; 135 156 size_t offValidValues = 0; 136 157 for (unsigned i = 0; i < RT_ELEMENTS(g_aGcmFixerIds); i++) 137 158 { 159 Assert(g_aGcmFixerIds[i].cchName > 0 && g_aGcmFixerIds[i].cchName <= GCM_FIXER_ID_MAX_NAME_LEN); 160 138 161 AssertReturn(offValidValues + g_aGcmFixerIds[i].cchName + 2 <= sizeof(szValidValues), VERR_INTERNAL_ERROR_2); 139 162 if (offValidValues) … … 165 188 g_aGcmFixerIds[i].pszName, rc); 166 189 if (fEnabled) 167 pVM->gcm.s.fFixerSet = g_aGcmFixerIds[i].fFlag;190 pVM->gcm.s.fFixerSet = RT_BIT_32(g_aGcmFixerIds[i].uBit); 168 191 } 169 192 … … 192 215 size_t offDst = 0; 193 216 for (unsigned i = 0; i < RT_ELEMENTS(g_aGcmFixerIds); i++) 194 if (fFixerIds & g_aGcmFixerIds[i].fFlag)217 if (fFixerIds & RT_BIT_32(g_aGcmFixerIds[i].uBit)) 195 218 { 196 219 AssertReturn(offDst + g_aGcmFixerIds[i].cchName + 4 <= cbDst, pszDst); … … 209 232 pszDst[offDst] = '\0'; 210 233 211 fFixerIds &= ~ g_aGcmFixerIds[i].fFlag;234 fFixerIds &= ~RT_BIT_32(g_aGcmFixerIds[i].uBit); 212 235 if (!fFixerIds) 213 236 break; … … 282 305 * Check if we can reconfigure to the loaded fixer set. 283 306 */ 284 if ((fFixerSet & pVM->gcm.s.fFixerSet) == fFixerSet) 285 { 286 uint32_t fNotSetInSavedState = fFixerSet ^ pVM->gcm.s.fFixerSet; 287 while (fNotSetInSavedState) 307 bool fSuccess = false; 308 uint32_t fNewFixerSet = fFixerSet; 309 uint32_t fDiffSet = fFixerSet ^ pVM->gcm.s.fFixerSet; 310 while (fDiffSet) 311 { 312 unsigned const uBit = ASMBitFirstSetU32(fDiffSet) - 1U; 313 unsigned idxEntry; 314 for (idxEntry = 0; idxEntry < RT_ELEMENTS(g_aGcmFixerIds); idxEntry++) 315 if (g_aGcmFixerIds[idxEntry].uBit == uBit) 316 break; 317 if (idxEntry < RT_ELEMENTS(g_aGcmFixerIds)) 288 318 { 289 unsigned iBit = ASMBitFirstSetU32(fNotSetInSavedState) - 1U; 290 uint32_t fFlag = RT_BIT_32(iBit); 291 292 unsigned idxEntry; 293 for (idxEntry = 0; idxEntry < RT_ELEMENTS(g_aGcmFixerIds); idxEntry++) 294 if (g_aGcmFixerIds[idxEntry].fFlag == fFlag) 319 switch (g_aGcmFixerIds[idxEntry].enmLoadAction) 320 { 321 case kGcmLoadAct_Reconfigurable: 322 if (fFixerSet & RT_BIT_32(uBit)) 323 LogRel(("GCM: Enabling %s (loading state).\n", g_aGcmFixerIds[idxEntry].pszName)); 324 else 325 LogRel(("GCM: Disabling %s (loading state).\n", g_aGcmFixerIds[idxEntry].pszName)); 295 326 break; 296 if (idxEntry >= RT_ELEMENTS(g_aGcmFixerIds)) 297 { 298 LogRel(("GCM: Error! Unknown fixer flag set in saved state: %#x\n", fFlag)); 299 break; 327 328 case kGcmLoadAct_NoReconfigIgnore: 329 if (fFixerSet & RT_BIT_32(uBit)) 330 LogRel(("GCM: %s is disabled in VM config but enabled in saved state being loaded, keeping it disabled as configured.\n", 331 g_aGcmFixerIds[idxEntry].pszName)); 332 else 333 LogRel(("GCM: %s is enabled in VM config but disabled in saved state being loaded, keeping it enabled as configured.\n", 334 g_aGcmFixerIds[idxEntry].pszName)); 335 fNewFixerSet &= ~RT_BIT_32(uBit); 336 fNewFixerSet |= pVM->gcm.s.fFixerSet & RT_BIT_32(uBit); 337 break; 338 339 default: 340 AssertFailed(); 341 RT_FALL_THRU(); 342 case kGcmLoadAct_NoReconfigFail: 343 if (fFixerSet & RT_BIT_32(uBit)) 344 LogRel(("GCM: Error! %s is disabled in VM config but enabled in saved state being loaded!\n", 345 g_aGcmFixerIds[idxEntry].pszName)); 346 else 347 LogRel(("GCM: Error! %s is enabled in VM config but disabled in saved state being loaded!\n", 348 g_aGcmFixerIds[idxEntry].pszName)); 349 fSuccess = false; 350 break; 300 351 } 301 if (g_aGcmFixerIds[idxEntry].fSafeToClearOnLoad)302 {303 LogRel(("GCM: Error! Fixer flag %s is set in saved state but no in the VM configuration!\n",304 g_aGcmFixerIds[idxEntry].pszName));305 break;306 }307 fNotSetInSavedState &= ~fFlag;308 352 } 309 if (!fNotSetInSavedState)353 else 310 354 { 311 pVM->gcm.s.fFixerSet &= fFixerSet; 312 return VINF_SUCCESS; 355 /* For max flexibility, we just ignore unknown fixers. */ 356 LogRel(("GCM: Warning! Ignoring unknown fixer ID set in saved state: %#x (bit %u)\n", RT_BIT_32(uBit), uBit)); 357 fNewFixerSet &= ~RT_BIT_32(uBit); 313 358 } 314 } 315 char szTmp1[1024], szTmp2[1024]; 359 fDiffSet &= ~RT_BIT_32(uBit); 360 } 361 if (fSuccess) 362 { 363 pVM->gcm.s.fFixerSet = fNewFixerSet; 364 return VINF_SUCCESS; 365 } 366 367 char szTmp1[GCM_FIXER_SET_MAX_STRING_SIZE]; 368 char szTmp2[GCM_FIXER_SET_MAX_STRING_SIZE]; 316 369 return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GCM fixer set %#x%s differs from the configured one (%#x%s)."), 317 370 fFixerSet, gcmFixerIdsToString(szTmp1, sizeof(szTmp1), fFixerSet, true),
Note:
See TracChangeset
for help on using the changeset viewer.