VirtualBox

Changeset 106054 in vbox for trunk/src/VBox/VMM/VMMR3


Ignore:
Timestamp:
Sep 13, 2024 8:11:59 PM (4 months ago)
Author:
vboxsync
Message:

GCM: Made saved state loading a bit more flexible so we can load 7.0.x states that doesn't have GCMFIXER_MESA_VMSVGA_DRV set - 2nd try. bugref:10683

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/VMM/VMMR3/GCM.cpp

    r106049 r106054  
    7979*   Global Variables                                                                                                             *
    8080*********************************************************************************************************************************/
     81typedef 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;
    8196/** Fixer flag configuration names. */
    8297static struct
    8398{
    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;
    88103} const g_aGcmFixerIds[] =
    89104{
    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   },
    94109};
     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)
    95116
    96117
     
    132153     */
    133154    /* Assemble valid value names for CFMGR3ValidateConfig. */
    134     char   szValidValues[1024];
     155    char   szValidValues[GCM_FIXER_SET_MAX_STRING_SIZE];
    135156    size_t offValidValues = 0;
    136157    for (unsigned i = 0; i < RT_ELEMENTS(g_aGcmFixerIds); i++)
    137158    {
     159        Assert(g_aGcmFixerIds[i].cchName > 0 && g_aGcmFixerIds[i].cchName <= GCM_FIXER_ID_MAX_NAME_LEN);
     160
    138161        AssertReturn(offValidValues + g_aGcmFixerIds[i].cchName + 2 <= sizeof(szValidValues), VERR_INTERNAL_ERROR_2);
    139162        if (offValidValues)
     
    165188                                g_aGcmFixerIds[i].pszName, rc);
    166189        if (fEnabled)
    167             pVM->gcm.s.fFixerSet = g_aGcmFixerIds[i].fFlag;
     190            pVM->gcm.s.fFixerSet = RT_BIT_32(g_aGcmFixerIds[i].uBit);
    168191    }
    169192
     
    192215    size_t offDst = 0;
    193216    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))
    195218        {
    196219            AssertReturn(offDst + g_aGcmFixerIds[i].cchName + 4 <= cbDst, pszDst);
     
    209232            pszDst[offDst] = '\0';
    210233
    211             fFixerIds &= ~g_aGcmFixerIds[i].fFlag;
     234            fFixerIds &= ~RT_BIT_32(g_aGcmFixerIds[i].uBit);
    212235            if (!fFixerIds)
    213236                break;
     
    282305     * Check if we can reconfigure to the loaded fixer set.
    283306     */
    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))
    288318        {
    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));
    295326                    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;
    300351            }
    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;
    308352        }
    309         if (!fNotSetInSavedState)
     353        else
    310354        {
    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);
    313358        }
    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];
    316369    return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GCM fixer set %#x%s differs from the configured one (%#x%s)."),
    317370                            fFixerSet, gcmFixerIdsToString(szTmp1, sizeof(szTmp1), fFixerSet, true),
Note: See TracChangeset for help on using the changeset viewer.

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