VirtualBox

Changeset 106049 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Sep 13, 2024 3:18:53 PM (3 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. bugref:10683

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

Legend:

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

    r105701 r106049  
     1/* $Id$ */
    12/** @file
    23 * GCM - Guest Compatibility Manager.
     
    7677
    7778/*********************************************************************************************************************************
     79*   Global Variables                                                                                                             *
     80*********************************************************************************************************************************/
     81/** Fixer flag configuration names. */
     82static struct
     83{
     84    const char *pszName;
     85    uint8_t     cchName;
     86    bool        fSafeToClearOnLoad;
     87    uint32_t    fFlag;
     88} const g_aGcmFixerIds[] =
     89{
     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. */
     94};
     95
     96
     97/*********************************************************************************************************************************
    7898*   Internal Functions                                                                                                           *
    7999*********************************************************************************************************************************/
    80100static FNSSMINTSAVEEXEC  gcmR3Save;
    81101static FNSSMINTLOADEXEC  gcmR3Load;
     102static char *gcmFixerIdsToString(char *pszDst, size_t cbDst, uint32_t fFixerIds, bool fInSpacePrefixedParenthesis) RT_NOEXCEPT;
    82103
    83104
     
    110131     * Read & validate configuration.
    111132     */
    112     static struct { const char *pszName; uint32_t cchName; uint32_t fFlag; } const s_aFixerIds[] =
    113     {
    114         { RT_STR_TUPLE("DivByZeroDOS"),       GCMFIXER_DBZ_DOS },
    115         { RT_STR_TUPLE("DivByZeroOS2"),       GCMFIXER_DBZ_OS2 },
    116         { RT_STR_TUPLE("DivByZeroWin9x"),     GCMFIXER_DBZ_WIN9X },
    117         { RT_STR_TUPLE("MesaVmsvgaDrv"),      GCMFIXER_MESA_VMSVGA_DRV },
    118     };
    119 
    120133    /* Assemble valid value names for CFMGR3ValidateConfig. */
    121134    char   szValidValues[1024];
    122135    size_t offValidValues = 0;
    123     for (unsigned i = 0; i < RT_ELEMENTS(s_aFixerIds); i++)
    124     {
    125         AssertReturn(offValidValues + s_aFixerIds[i].cchName + 2 <= sizeof(szValidValues), VERR_INTERNAL_ERROR_2);
     136    for (unsigned i = 0; i < RT_ELEMENTS(g_aGcmFixerIds); i++)
     137    {
     138        AssertReturn(offValidValues + g_aGcmFixerIds[i].cchName + 2 <= sizeof(szValidValues), VERR_INTERNAL_ERROR_2);
    126139        if (offValidValues)
    127140            szValidValues[offValidValues++] = '|';
    128         memcpy(&szValidValues[offValidValues], s_aFixerIds[i].pszName, s_aFixerIds[i].cchName);
    129         offValidValues += s_aFixerIds[i].cchName;
     141        memcpy(&szValidValues[offValidValues], g_aGcmFixerIds[i].pszName, g_aGcmFixerIds[i].cchName);
     142        offValidValues += g_aGcmFixerIds[i].cchName;
    130143    }
    131144    szValidValues[offValidValues] = '\0';
     
    144157    /* Read the configuration. */
    145158    pVM->gcm.s.fFixerSet = 0;
    146     for (unsigned i = 0; i < RT_ELEMENTS(s_aFixerIds); i++)
     159    for (unsigned i = 0; i < RT_ELEMENTS(g_aGcmFixerIds); i++)
    147160    {
    148161        bool fEnabled = false;
    149         rc = CFGMR3QueryBoolDef(pCfgNode, s_aFixerIds[i].pszName, &fEnabled, false);
     162        rc = CFGMR3QueryBoolDef(pCfgNode, g_aGcmFixerIds[i].pszName, &fEnabled, false);
    150163        if (RT_FAILURE(rc))
    151             return VMR3SetError(pVM->pUVM, rc, RT_SRC_POS, "Error reading /GCM/%s as boolean: %Rrc", s_aFixerIds[i].pszName, rc);
     164            return VMR3SetError(pVM->pUVM, rc, RT_SRC_POS, "Error reading /GCM/%s as boolean: %Rrc",
     165                                g_aGcmFixerIds[i].pszName, rc);
    152166        if (fEnabled)
    153             pVM->gcm.s.fFixerSet = s_aFixerIds[i].fFlag;
     167            pVM->gcm.s.fFixerSet = g_aGcmFixerIds[i].fFlag;
    154168    }
    155169
     
    161175     * Log what's enabled.
    162176     */
    163     offValidValues = 0;
    164     for (unsigned i = 0; i < RT_ELEMENTS(s_aFixerIds); i++)
    165         if (pVM->gcm.s.fFixerSet & s_aFixerIds[i].fFlag)
    166         {
    167             AssertReturn(offValidValues + s_aFixerIds[i].cchName + 4 <= sizeof(szValidValues), VERR_INTERNAL_ERROR_2);
    168             if (!offValidValues)
     177    LogRel(("GCM: Initialized - Fixer bits: %#x%s\n", pVM->gcm.s.fFixerSet,
     178            gcmFixerIdsToString(szValidValues, sizeof(szValidValues), pVM->gcm.s.fFixerSet, true)));
     179
     180    return VINF_SUCCESS;
     181}
     182
     183
     184/**
     185 * Converts the fixer ID set to a string for logging and error reporting.
     186 */
     187static char *gcmFixerIdsToString(char *pszDst, size_t cbDst, uint32_t fFixerIds, bool fInSpacePrefixedParenthesis) RT_NOEXCEPT
     188{
     189    AssertReturn(cbDst > 0, NULL);
     190    *pszDst = '\0';
     191
     192    size_t offDst = 0;
     193    for (unsigned i = 0; i < RT_ELEMENTS(g_aGcmFixerIds); i++)
     194        if (fFixerIds & g_aGcmFixerIds[i].fFlag)
     195        {
     196            AssertReturn(offDst + g_aGcmFixerIds[i].cchName + 4 <= cbDst, pszDst);
     197            if (offDst)
    169198            {
    170                 szValidValues[offValidValues++] = ' ';
    171                 szValidValues[offValidValues++] = '(';
     199                pszDst[offDst++] = ',';
     200                pszDst[offDst++] = ' ';
    172201            }
    173             else
     202            else if (fInSpacePrefixedParenthesis)
    174203            {
    175                 szValidValues[offValidValues++] = ',';
    176                 szValidValues[offValidValues++] = ' ';
     204                pszDst[offDst++] = ' ';
     205                pszDst[offDst++] = '(';
    177206            }
    178             memcpy(&szValidValues[offValidValues], s_aFixerIds[i].pszName, s_aFixerIds[i].cchName);
    179             offValidValues += s_aFixerIds[i].cchName;
    180         }
    181     if (offValidValues)
    182         szValidValues[offValidValues++] = ')';
    183     szValidValues[offValidValues] = '\0';
    184     LogRel(("GCM: Initialized - Fixer bits: %#x%s\n", pVM->gcm.s.fFixerSet, szValidValues));
    185 
    186     return VINF_SUCCESS;
     207            memcpy(&pszDst[offDst], g_aGcmFixerIds[i].pszName, g_aGcmFixerIds[i].cchName);
     208            offDst += g_aGcmFixerIds[i].cchName;
     209            pszDst[offDst] = '\0';
     210
     211            fFixerIds &= ~g_aGcmFixerIds[i].fFlag;
     212            if (!fFixerIds)
     213                break;
     214        }
     215
     216    if (fFixerIds)
     217    {
     218        char         szTmp[64];
     219        size_t const cchTmp = RTStrPrintf(szTmp, sizeof(szTmp), "%#x", fFixerIds);
     220        AssertReturn(offDst + cchTmp + 4 <= cbDst, pszDst);
     221        if (offDst)
     222        {
     223            pszDst[offDst++] = ',';
     224            pszDst[offDst++] = ' ';
     225        }
     226        else if (fInSpacePrefixedParenthesis)
     227        {
     228            pszDst[offDst++] = ' ';
     229            pszDst[offDst++] = '(';
     230        }
     231        memcpy(&pszDst[offDst], szTmp, cchTmp);
     232        offDst += cchTmp;
     233        pszDst[offDst] = '\0';
     234    }
     235
     236    if (offDst && fInSpacePrefixedParenthesis)
     237    {
     238        pszDst[offDst++] = ')';
     239        pszDst[offDst] = '\0';
     240    }
     241    return pszDst;
    187242}
    188243
     
    221276    AssertRCReturn(rc, rc);
    222277
    223     if (fFixerSet != pVM->gcm.s.fFixerSet)
    224         return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GCM fixer set %#X differs from the configured one (%#X)."),
    225                                 fFixerSet, pVM->gcm.s.fFixerSet);
    226 
    227     return VINF_SUCCESS;
     278    if (fFixerSet == pVM->gcm.s.fFixerSet)
     279        return VINF_SUCCESS;
     280
     281    /*
     282     * Check if we can reconfigure to the loaded fixer set.
     283     */
     284    if ((fFixerSet & pVM->gcm.s.fFixerSet) == fFixerSet)
     285    {
     286        uint32_t fNotSetInSavedState = fFixerSet ^ pVM->gcm.s.fFixerSet;
     287        while (fNotSetInSavedState)
     288        {
     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)
     295                    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;
     300            }
     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        }
     309        if (!fNotSetInSavedState)
     310        {
     311            pVM->gcm.s.fFixerSet &= fFixerSet;
     312            return VINF_SUCCESS;
     313        }
     314    }
     315    char szTmp1[1024], szTmp2[1024];
     316    return SSMR3SetCfgError(pSSM, RT_SRC_POS, N_("Saved GCM fixer set %#x%s differs from the configured one (%#x%s)."),
     317                            fFixerSet, gcmFixerIdsToString(szTmp1, sizeof(szTmp1), fFixerSet, true),
     318                            pVM->gcm.s.fFixerSet, gcmFixerIdsToString(szTmp2, sizeof(szTmp2), pVM->gcm.s.fFixerSet, true));
    228319}
    229320
  • trunk/src/VBox/VMM/include/GCMInternal.h

    r104516 r106049  
    5656/** Windows 9x division by zero. */
    5757#define GCMFIXER_DBZ_WIN9X          RT_BIT_32(2)
    58 /** Workaround for the Mesa vmsvga driver using a IN/OUT backdoor. */
     58/** Workaround for the Mesa vmsvga driver using a IN/OUT backdoor.
     59 * @since 7.0  */
    5960#define GCMFIXER_MESA_VMSVGA_DRV    RT_BIT_32(3)
    6061/** @} */
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