VirtualBox

Changeset 73266 in vbox


Ignore:
Timestamp:
Jul 20, 2018 2:27:20 PM (7 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
123873
Message:

PGM,HM: Made PGMR3ChangeMode work in ring-0 too. This required a kludge for the VT-x real-in-V86-mode stuff, as there are certain limitations on that mode which weren't checked as CR0.PE was cleared. The kludge isn't very smart, but it seems to do the job. Similar kludge for getting out of the mode. bugref:9044

Location:
trunk
Files:
8 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/VBox/vmm/hm.h

    r73264 r73266  
    134134VMM_INT_DECL(bool)              HMIsSvmActive(PVM pVM);
    135135VMM_INT_DECL(bool)              HMIsVmxActive(PVM pVM);
    136 VMM_INT_DECL(void)              HMPagingModeChanged(PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode);
     136VMM_INT_DECL(void)              HMHCPagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode);
    137137/** @} */
    138138
  • trunk/include/VBox/vmm/pgm.h

    r73246 r73266  
    445445VMMDECL(int)        PGMUpdateCR3(PVMCPU pVCpu, uint64_t cr3);
    446446VMMDECL(int)        PGMChangeMode(PVMCPU pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer);
     447VMM_INT_DECL(int)   PGMHCChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode);
    447448VMMDECL(void)       PGMCr0WpEnabled(PVMCPU pVCpu);
    448449VMMDECL(PGMMODE)    PGMGetGuestMode(PVMCPU pVCpu);
     
    810811VMMR3DECL(int)      PGMR3Term(PVM pVM);
    811812VMMR3DECL(int)      PGMR3LockCall(PVM pVM);
    812 VMMR3DECL(int)      PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode);
    813813
    814814VMMR3DECL(int)      PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, const char *pszDesc);
  • trunk/src/VBox/VMM/VMMAll/HMAll.cpp

    r73263 r73266  
    2121*********************************************************************************************************************************/
    2222#define LOG_GROUP LOG_GROUP_HM
     23#define VMCPU_INCL_CPUM_GST_CTX
    2324#include <VBox/vmm/hm.h>
    2425#include <VBox/vmm/pgm.h>
     
    543544
    544545
     546#ifndef IN_RC
    545547/**
    546548 * Notification callback which is called whenever there is a chance that a CR3
     
    549551 * This is called by PGM.
    550552 *
    551  * @param   pVCpu          The cross context virtual CPU structure.
    552  * @param   enmShadowMode  New shadow paging mode.
    553  * @param   enmGuestMode   New guest paging mode.
    554  */
    555 VMM_INT_DECL(void) HMPagingModeChanged(PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode)
    556 {
    557 #ifdef IN_RING3
     553 * @param   pVM             The cross context VM structure.
     554 * @param   pVCpu           The cross context virtual CPU structure.
     555 * @param   enmShadowMode   New shadow paging mode.
     556 * @param   enmGuestMode    New guest paging mode.
     557 */
     558VMM_INT_DECL(void) HMHCPagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode)
     559{
     560# ifdef IN_RING3
    558561    /* Ignore page mode changes during state loading. */
    559     if (VMR3GetState(pVCpu->pVMR3) == VMSTATE_LOADING)
     562    if (VMR3GetState(pVM) == VMSTATE_LOADING)
    560563        return;
    561 #endif
     564# endif
    562565
    563566    pVCpu->hm.s.enmShadowMode = enmShadowMode;
     
    570573        pVCpu->hm.s.vmx.fWasInRealMode = true;
    571574
    572     Log4(("HMR3PagingModeChanged: Guest paging mode '%s', shadow paging mode '%s'\n", PGMGetModeName(enmGuestMode),
     575# ifdef IN_RING0
     576    /*
     577     * We need to tickle SVM and VT-x state updates.
     578     *
     579     * Note! We could probably reduce this depending on what exactly changed.
     580     */
     581    if (VM_IS_HM_ENABLED(pVM))
     582    {
     583        CPUM_ASSERT_NOT_EXTRN(pVCpu, CPUMCTX_EXTRN_CR0 | CPUMCTX_EXTRN_CR3 | CPUMCTX_EXTRN_CR4 | CPUMCTX_EXTRN_EFER); /* No recursion! */
     584        uint64_t fChanged = HM_CHANGED_GUEST_CR0 | HM_CHANGED_GUEST_CR3 | HM_CHANGED_GUEST_CR4 | HM_CHANGED_GUEST_EFER_MSR;
     585        if (pVM->hm.s.svm.fSupported)
     586            fChanged |= HM_CHANGED_SVM_GUEST_XCPT_INTERCEPTS;
     587        else
     588            fChanged |= HM_CHANGED_VMX_GUEST_XCPT_INTERCEPTS | HM_CHANGED_VMX_ENTRY_CTLS | HM_CHANGED_VMX_EXIT_CTLS;
     589        ASMAtomicUoOrU64(&pVCpu->hm.s.fCtxChanged, fChanged);
     590    }
     591# endif
     592
     593    Log4(("HMHCPagingModeChanged: Guest paging mode '%s', shadow paging mode '%s'\n", PGMGetModeName(enmGuestMode),
    573594          PGMGetModeName(enmShadowMode)));
    574595}
    575 
     596#endif /* !IN_RC */
     597
  • trunk/src/VBox/VMM/VMMAll/PGMAll.cpp

    r73262 r73266  
    28912891    PGM_INVL_VCPU_TLBS(pVCpu);
    28922892
    2893 #ifdef IN_RING3
    2894     return PGMR3ChangeMode(pVCpu->CTX_SUFF(pVM), pVCpu, enmGuestMode);
     2893#if defined(IN_RING3) || defined(IN_RING0)
     2894    return PGMHCChangeMode(pVCpu->CTX_SUFF(pVM), pVCpu, enmGuestMode);
    28952895#else
    28962896    LogFlow(("PGMChangeMode: returns VINF_PGM_CHANGE_MODE.\n"));
     
    28992899}
    29002900
     2901#ifndef IN_RC
     2902
     2903/**
     2904 * Converts a PGMMODE value to a PGM_TYPE_* \#define.
     2905 *
     2906 * @returns PGM_TYPE_*.
     2907 * @param   pgmMode     The mode value to convert.
     2908 */
     2909DECLINLINE(unsigned) pgmModeToType(PGMMODE pgmMode)
     2910{
     2911    switch (pgmMode)
     2912    {
     2913        case PGMMODE_REAL:          return PGM_TYPE_REAL;
     2914        case PGMMODE_PROTECTED:     return PGM_TYPE_PROT;
     2915        case PGMMODE_32_BIT:        return PGM_TYPE_32BIT;
     2916        case PGMMODE_PAE:
     2917        case PGMMODE_PAE_NX:        return PGM_TYPE_PAE;
     2918        case PGMMODE_AMD64:
     2919        case PGMMODE_AMD64_NX:      return PGM_TYPE_AMD64;
     2920        case PGMMODE_NESTED_32BIT:  return PGM_TYPE_NESTED_32BIT;
     2921        case PGMMODE_NESTED_PAE:    return PGM_TYPE_NESTED_PAE;
     2922        case PGMMODE_NESTED_AMD64:  return PGM_TYPE_NESTED_AMD64;
     2923        case PGMMODE_EPT:           return PGM_TYPE_EPT;
     2924        default:
     2925            AssertFatalMsgFailed(("pgmMode=%d\n", pgmMode));
     2926    }
     2927}
     2928
     2929
     2930/**
     2931 * Calculates the shadow paging mode.
     2932 *
     2933 * @returns The shadow paging mode.
     2934 * @param   pVM             The cross context VM structure.
     2935 * @param   enmGuestMode    The guest mode.
     2936 * @param   enmHostMode     The host mode.
     2937 * @param   enmShadowMode   The current shadow mode.
     2938 * @param   penmSwitcher    Where to store the switcher to use.
     2939 *                          VMMSWITCHER_INVALID means no change.
     2940 */
     2941static PGMMODE pgmCalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode,
     2942                                 VMMSWITCHER *penmSwitcher)
     2943{
     2944    VMMSWITCHER enmSwitcher = VMMSWITCHER_INVALID;
     2945    switch (enmGuestMode)
     2946    {
     2947        /*
     2948         * When switching to real or protected mode we don't change
     2949         * anything since it's likely that we'll switch back pretty soon.
     2950         *
     2951         * During pgmR3InitPaging we'll end up here with PGMMODE_INVALID
     2952         * and is supposed to determine which shadow paging and switcher to
     2953         * use during init.
     2954         */
     2955        case PGMMODE_REAL:
     2956        case PGMMODE_PROTECTED:
     2957            if (    enmShadowMode != PGMMODE_INVALID
     2958                && VM_IS_RAW_MODE_ENABLED(pVM) /* always switch in hm and nem modes! */)
     2959                break; /* (no change) */
     2960
     2961            switch (enmHostMode)
     2962            {
     2963                case SUPPAGINGMODE_32_BIT:
     2964                case SUPPAGINGMODE_32_BIT_GLOBAL:
     2965                    enmShadowMode = PGMMODE_32_BIT;
     2966                    enmSwitcher = VMMSWITCHER_32_TO_32;
     2967                    break;
     2968
     2969                case SUPPAGINGMODE_PAE:
     2970                case SUPPAGINGMODE_PAE_NX:
     2971                case SUPPAGINGMODE_PAE_GLOBAL:
     2972                case SUPPAGINGMODE_PAE_GLOBAL_NX:
     2973                    enmShadowMode = PGMMODE_PAE;
     2974                    enmSwitcher = VMMSWITCHER_PAE_TO_PAE;
     2975                    break;
     2976
     2977                case SUPPAGINGMODE_AMD64:
     2978                case SUPPAGINGMODE_AMD64_GLOBAL:
     2979                case SUPPAGINGMODE_AMD64_NX:
     2980                case SUPPAGINGMODE_AMD64_GLOBAL_NX:
     2981                    enmShadowMode = PGMMODE_PAE;
     2982                    enmSwitcher = VMMSWITCHER_AMD64_TO_PAE;
     2983                    break;
     2984
     2985                default:
     2986                    AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
     2987                                                    *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
     2988            }
     2989            break;
     2990
     2991        case PGMMODE_32_BIT:
     2992            switch (enmHostMode)
     2993            {
     2994                case SUPPAGINGMODE_32_BIT:
     2995                case SUPPAGINGMODE_32_BIT_GLOBAL:
     2996                    enmShadowMode = PGMMODE_32_BIT;
     2997                    enmSwitcher = VMMSWITCHER_32_TO_32;
     2998                    break;
     2999
     3000                case SUPPAGINGMODE_PAE:
     3001                case SUPPAGINGMODE_PAE_NX:
     3002                case SUPPAGINGMODE_PAE_GLOBAL:
     3003                case SUPPAGINGMODE_PAE_GLOBAL_NX:
     3004                    enmShadowMode = PGMMODE_PAE;
     3005                    enmSwitcher = VMMSWITCHER_PAE_TO_PAE;
     3006                    break;
     3007
     3008                case SUPPAGINGMODE_AMD64:
     3009                case SUPPAGINGMODE_AMD64_GLOBAL:
     3010                case SUPPAGINGMODE_AMD64_NX:
     3011                case SUPPAGINGMODE_AMD64_GLOBAL_NX:
     3012                    enmShadowMode = PGMMODE_PAE;
     3013                    enmSwitcher = VMMSWITCHER_AMD64_TO_PAE;
     3014                    break;
     3015
     3016                default:
     3017                    AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
     3018                                                    *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
     3019            }
     3020            break;
     3021
     3022        case PGMMODE_PAE:
     3023        case PGMMODE_PAE_NX: /** @todo This might require more switchers and guest+both modes. */
     3024            switch (enmHostMode)
     3025            {
     3026                case SUPPAGINGMODE_32_BIT:
     3027                case SUPPAGINGMODE_32_BIT_GLOBAL:
     3028                    enmShadowMode = PGMMODE_PAE;
     3029                    enmSwitcher = VMMSWITCHER_32_TO_PAE;
     3030                    break;
     3031
     3032                case SUPPAGINGMODE_PAE:
     3033                case SUPPAGINGMODE_PAE_NX:
     3034                case SUPPAGINGMODE_PAE_GLOBAL:
     3035                case SUPPAGINGMODE_PAE_GLOBAL_NX:
     3036                    enmShadowMode = PGMMODE_PAE;
     3037                    enmSwitcher = VMMSWITCHER_PAE_TO_PAE;
     3038                    break;
     3039
     3040                case SUPPAGINGMODE_AMD64:
     3041                case SUPPAGINGMODE_AMD64_GLOBAL:
     3042                case SUPPAGINGMODE_AMD64_NX:
     3043                case SUPPAGINGMODE_AMD64_GLOBAL_NX:
     3044                    enmShadowMode = PGMMODE_PAE;
     3045                    enmSwitcher = VMMSWITCHER_AMD64_TO_PAE;
     3046                    break;
     3047
     3048                default:
     3049                    AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
     3050                                                    *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
     3051            }
     3052            break;
     3053
     3054        case PGMMODE_AMD64:
     3055        case PGMMODE_AMD64_NX:
     3056            switch (enmHostMode)
     3057            {
     3058                case SUPPAGINGMODE_32_BIT:
     3059                case SUPPAGINGMODE_32_BIT_GLOBAL:
     3060                    enmShadowMode = PGMMODE_AMD64;
     3061                    enmSwitcher = VMMSWITCHER_32_TO_AMD64;
     3062                    break;
     3063
     3064                case SUPPAGINGMODE_PAE:
     3065                case SUPPAGINGMODE_PAE_NX:
     3066                case SUPPAGINGMODE_PAE_GLOBAL:
     3067                case SUPPAGINGMODE_PAE_GLOBAL_NX:
     3068                    enmShadowMode = PGMMODE_AMD64;
     3069                    enmSwitcher = VMMSWITCHER_PAE_TO_AMD64;
     3070                    break;
     3071
     3072                case SUPPAGINGMODE_AMD64:
     3073                case SUPPAGINGMODE_AMD64_GLOBAL:
     3074                case SUPPAGINGMODE_AMD64_NX:
     3075                case SUPPAGINGMODE_AMD64_GLOBAL_NX:
     3076                    enmShadowMode = PGMMODE_AMD64;
     3077                    enmSwitcher = VMMSWITCHER_AMD64_TO_AMD64;
     3078                    break;
     3079
     3080                default:
     3081                    AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
     3082                                                    *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
     3083            }
     3084            break;
     3085
     3086        default:
     3087            AssertLogRelMsgFailedReturnStmt(("enmGuestMode=%d\n", enmGuestMode),
     3088                                            *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
     3089    }
     3090
     3091    /*
     3092     * Override the shadow mode when NEM or nested paging is active.
     3093     */
     3094    if (VM_IS_NEM_ENABLED(pVM))
     3095    {
     3096        pVM->pgm.s.fNestedPaging = true;
     3097        enmShadowMode = PGMMODE_EPT; /* whatever harmless... */
     3098    }
     3099    else
     3100    {
     3101        bool fNestedPaging = HMIsNestedPagingActive(pVM);
     3102        pVM->pgm.s.fNestedPaging = fNestedPaging;
     3103        if (fNestedPaging)
     3104        {
     3105            if (HMIsVmxActive(pVM))
     3106                enmShadowMode = PGMMODE_EPT;
     3107            else
     3108            {
     3109                /* The nested SVM paging depends on the host one. */
     3110                Assert(HMIsSvmActive(pVM));
     3111                if (   enmGuestMode == PGMMODE_AMD64
     3112                    || enmGuestMode == PGMMODE_AMD64_NX)
     3113                    enmShadowMode = PGMMODE_NESTED_AMD64;
     3114                else
     3115                    switch (pVM->pgm.s.enmHostMode)
     3116                    {
     3117                        case SUPPAGINGMODE_32_BIT:
     3118                        case SUPPAGINGMODE_32_BIT_GLOBAL:
     3119                            enmShadowMode = PGMMODE_NESTED_32BIT;
     3120                            break;
     3121
     3122                        case SUPPAGINGMODE_PAE:
     3123                        case SUPPAGINGMODE_PAE_GLOBAL:
     3124                        case SUPPAGINGMODE_PAE_NX:
     3125                        case SUPPAGINGMODE_PAE_GLOBAL_NX:
     3126                            enmShadowMode = PGMMODE_NESTED_PAE;
     3127                            break;
     3128
     3129#if HC_ARCH_BITS == 64 || defined(RT_OS_DARWIN)
     3130                        case SUPPAGINGMODE_AMD64:
     3131                        case SUPPAGINGMODE_AMD64_GLOBAL:
     3132                        case SUPPAGINGMODE_AMD64_NX:
     3133                        case SUPPAGINGMODE_AMD64_GLOBAL_NX:
     3134                            enmShadowMode = PGMMODE_NESTED_AMD64;
     3135                            break;
     3136#endif
     3137                        default:
     3138                            AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", pVM->pgm.s.enmHostMode),
     3139                                                            *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
     3140                    }
     3141            }
     3142        }
     3143    }
     3144
     3145    *penmSwitcher = enmSwitcher;
     3146    return enmShadowMode;
     3147}
     3148
     3149
     3150/**
     3151 * Performs the actual mode change.
     3152 * This is called by PGMChangeMode and pgmR3InitPaging().
     3153 *
     3154 * @returns VBox status code. May suspend or power off the VM on error, but this
     3155 *          will trigger using FFs and not informational status codes.
     3156 *
     3157 * @param   pVM             The cross context VM structure.
     3158 * @param   pVCpu           The cross context virtual CPU structure.
     3159 * @param   enmGuestMode    The new guest mode. This is assumed to be different from
     3160 *                          the current mode.
     3161 */
     3162VMM_INT_DECL(int) PGMHCChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
     3163{
     3164    Log(("PGMHCChangeMode: Guest mode: %s -> %s\n", PGMGetModeName(pVCpu->pgm.s.enmGuestMode), PGMGetModeName(enmGuestMode)));
     3165    STAM_REL_COUNTER_INC(&pVCpu->pgm.s.cGuestModeChanges);
     3166
     3167    /*
     3168     * Calc the shadow mode and switcher.
     3169     */
     3170    VMMSWITCHER enmSwitcher   = VMMSWITCHER_INVALID;
     3171    PGMMODE     enmShadowMode = PGMMODE_INVALID;
     3172    enmShadowMode = pgmCalcShadowMode(pVM, enmGuestMode, pVM->pgm.s.enmHostMode, pVCpu->pgm.s.enmShadowMode, &enmSwitcher);
     3173
     3174#ifdef VBOX_WITH_RAW_MODE_NOT_R0
     3175    if (   enmSwitcher != VMMSWITCHER_INVALID
     3176        && VM_IS_RAW_MODE_ENABLED(pVM))
     3177    {
     3178        /*
     3179         * Select new switcher.
     3180         */
     3181        int rc = VMMR3SelectSwitcher(pVM, enmSwitcher);
     3182        AssertLogRelMsgRCReturn(rc,("VMMR3SelectSwitcher(%d) -> %Rrc\n", enmSwitcher, rc), rc);
     3183    }
     3184#endif
     3185
     3186    /*
     3187     * Exit old mode(s).
     3188     */
     3189    /* shadow */
     3190    if (enmShadowMode != pVCpu->pgm.s.enmShadowMode)
     3191    {
     3192        LogFlow(("PGMHCChangeMode: Shadow mode: %s -> %s\n",  PGMGetModeName(pVCpu->pgm.s.enmShadowMode), PGMGetModeName(enmShadowMode)));
     3193        uintptr_t idxOldShw = pVCpu->pgm.s.idxShadowModeData;
     3194        if (   idxOldShw < RT_ELEMENTS(g_aPgmShadowModeData)
     3195            && g_aPgmShadowModeData[idxOldShw].pfnExit)
     3196        {
     3197            int rc = g_aPgmShadowModeData[idxOldShw].pfnExit(pVCpu);
     3198            AssertMsgRCReturn(rc, ("Exit failed for shadow mode %d: %Rrc\n", pVCpu->pgm.s.enmShadowMode, rc), rc);
     3199        }
     3200    }
     3201    else
     3202        LogFlow(("PGMHCChangeMode: Shadow mode remains: %s\n",  PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
     3203
     3204    /* guest */
     3205    uintptr_t const idxOldGst = pVCpu->pgm.s.idxGuestModeData;
     3206    if (   idxOldGst < RT_ELEMENTS(g_aPgmGuestModeData)
     3207        && g_aPgmGuestModeData[idxOldGst].pfnExit)
     3208    {
     3209        int rc = g_aPgmGuestModeData[idxOldGst].pfnExit(pVCpu);
     3210        AssertMsgReturn(RT_SUCCESS(rc), ("Exit failed for guest mode %d: %Rrc\n", pVCpu->pgm.s.enmGuestMode, rc), rc);
     3211    }
     3212    pVCpu->pgm.s.GCPhysCR3 = NIL_RTGCPHYS;
     3213
     3214    /*
     3215     * Change the paging mode data indexes.
     3216     */
     3217    uintptr_t idxNewGst = pVCpu->pgm.s.idxGuestModeData = pgmModeToType(enmGuestMode);
     3218    AssertReturn(idxNewGst < RT_ELEMENTS(g_aPgmGuestModeData), VERR_PGM_MODE_IPE);
     3219    AssertReturn(g_aPgmGuestModeData[idxNewGst].uType == idxNewGst, VERR_PGM_MODE_IPE);
     3220    AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnGetPage, VERR_PGM_MODE_IPE);
     3221    AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnModifyPage, VERR_PGM_MODE_IPE);
     3222    AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnGetPDE, VERR_PGM_MODE_IPE);
     3223    AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnExit, VERR_PGM_MODE_IPE);
     3224    AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnEnter, VERR_PGM_MODE_IPE);
     3225#ifdef IN_RING3
     3226    AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnRelocate, VERR_PGM_MODE_IPE);
     3227#endif
     3228
     3229    uintptr_t const idxNewShw = pVCpu->pgm.s.idxShadowModeData = pgmModeToType(enmShadowMode);
     3230    AssertReturn(idxNewShw < RT_ELEMENTS(g_aPgmShadowModeData), VERR_PGM_MODE_IPE);
     3231    AssertReturn(g_aPgmShadowModeData[idxNewShw].uType == idxNewShw, VERR_PGM_MODE_IPE);
     3232    AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnGetPage, VERR_PGM_MODE_IPE);
     3233    AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnModifyPage, VERR_PGM_MODE_IPE);
     3234    AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnExit, VERR_PGM_MODE_IPE);
     3235    AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnEnter, VERR_PGM_MODE_IPE);
     3236#ifdef IN_RING3
     3237    AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnRelocate, VERR_PGM_MODE_IPE);
     3238#endif
     3239
     3240    uintptr_t const idxNewBth = pVCpu->pgm.s.idxBothModeData = (idxNewShw - PGM_TYPE_FIRST_SHADOW) * PGM_TYPE_END + idxNewGst;
     3241    AssertReturn(g_aPgmBothModeData[idxNewBth].uShwType == idxNewShw, VERR_PGM_MODE_IPE);
     3242    AssertReturn(g_aPgmBothModeData[idxNewBth].uGstType == idxNewGst, VERR_PGM_MODE_IPE);
     3243    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnInvalidatePage, VERR_PGM_MODE_IPE);
     3244    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnSyncCR3, VERR_PGM_MODE_IPE);
     3245    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnPrefetchPage, VERR_PGM_MODE_IPE);
     3246    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnVerifyAccessSyncPage, VERR_PGM_MODE_IPE);
     3247    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnMapCR3, VERR_PGM_MODE_IPE);
     3248    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnUnmapCR3, VERR_PGM_MODE_IPE);
     3249    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnEnter, VERR_PGM_MODE_IPE);
     3250#ifdef IN_RING3
     3251    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnRelocate, VERR_PGM_MODE_IPE);
     3252#endif
     3253#ifdef VBOX_STRICT
     3254    AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnAssertCR3, VERR_PGM_MODE_IPE);
     3255#endif
     3256
     3257    /*
     3258     * Enter new shadow mode (if changed).
     3259     */
     3260    if (enmShadowMode != pVCpu->pgm.s.enmShadowMode)
     3261    {
     3262        pVCpu->pgm.s.enmShadowMode = enmShadowMode;
     3263        int rc = g_aPgmShadowModeData[idxNewShw].pfnEnter(pVCpu, enmGuestMode >= PGMMODE_AMD64);
     3264        AssertLogRelMsgRCReturnStmt(rc, ("Entering enmShadowMode=%s failed: %Rrc\n", PGMGetModeName(enmShadowMode), rc),
     3265                                    pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID, rc);
     3266    }
     3267
     3268    /*
     3269     * Always flag the necessary updates
     3270     */
     3271    VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
     3272
     3273    /*
     3274     * Enter the new guest and shadow+guest modes.
     3275     */
     3276    /* Calc the new CR3 value. */
     3277    RTGCPHYS GCPhysCR3;
     3278    switch (enmGuestMode)
     3279    {
     3280        case PGMMODE_REAL:
     3281        case PGMMODE_PROTECTED:
     3282            GCPhysCR3 = NIL_RTGCPHYS;
     3283            break;
     3284
     3285        case PGMMODE_32_BIT:
     3286            GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK;
     3287            break;
     3288
     3289        case PGMMODE_PAE_NX:
     3290        case PGMMODE_PAE:
     3291            if (!pVM->cpum.ro.GuestFeatures.fPae)
     3292                return VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_FATAL, "PAEmode",
     3293                                         N_("The guest is trying to switch to the PAE mode which is currently disabled by default in VirtualBox. PAE support can be enabled using the VM settings (System/Processor)"));
     3294            GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAE_PAGE_MASK;
     3295            break;
     3296
     3297#ifdef VBOX_WITH_64_BITS_GUESTS
     3298        case PGMMODE_AMD64_NX:
     3299        case PGMMODE_AMD64:
     3300            GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_AMD64_PAGE_MASK;
     3301            break;
     3302#endif
     3303        default:
     3304            AssertLogRelMsgFailedReturn(("enmGuestMode=%d\n", enmGuestMode), VERR_PGM_MODE_IPE);
     3305    }
     3306
     3307    /* Enter the new guest mode.  */
     3308    pVCpu->pgm.s.enmGuestMode = enmGuestMode;
     3309    int rc = g_aPgmGuestModeData[idxNewGst].pfnEnter(pVCpu, GCPhysCR3);
     3310    int rc2 = g_aPgmBothModeData[idxNewBth].pfnEnter(pVCpu, GCPhysCR3);
     3311
     3312    /* Set the new guest CR3. */
     3313    pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
     3314
     3315    /* status codes. */
     3316    AssertRC(rc);
     3317    AssertRC(rc2);
     3318    if (RT_SUCCESS(rc))
     3319    {
     3320        rc = rc2;
     3321        if (RT_SUCCESS(rc)) /* no informational status codes. */
     3322            rc = VINF_SUCCESS;
     3323    }
     3324
     3325    /*
     3326     * Notify HM.
     3327     */
     3328    HMHCPagingModeChanged(pVM, pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
     3329    return rc;
     3330}
     3331
     3332#endif /* !IN_RC */
    29013333
    29023334/**
  • trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp

    r73255 r73266  
    1190511905        case VMX_EXIT_QUAL_CRX_ACCESS_WRITE:       /* MOV to CRx */
    1190611906        {
     11907            uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0;
    1190711908            rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, pVmxTransient->cbInstr,
    1190811909                                                 VMX_EXIT_QUAL_CRX_REGISTER(uExitQualification),
     
    1192111922                    STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write);
    1192211923                    Log4(("CRX CR0 write rcStrict=%Rrc CR0=%#RX64\n", VBOXSTRICTRC_VAL(rcStrict), pVCpu->cpum.GstCtx.cr0));
     11924
     11925                    /*
     11926                     * This is a kludge for handling switches back to real mode when we try to use
     11927                     * V86 mode to run real mode code directly.  Problem is that V86 mode cannot
     11928                     * deal with special selector values, so we have to return to ring-3 and run
     11929                     * there till the selector values are V86 mode compatible.
     11930                     *
     11931                     * Note! Using VINF_EM_RESCHEDULE_REM here rather than VINF_EM_RESCHEDULE since the
     11932                     *       latter is an alias for VINF_IEM_RAISED_XCPT which is converted to VINF_SUCCESs
     11933                     *       at the end of this function.
     11934                     */
     11935                    if (   rc == VINF_SUCCESS
     11936                        && !pVCpu->CTX_SUFF(pVM)->hm.s.vmx.fUnrestrictedGuest
     11937                        && CPUMIsGuestInRealModeEx(&pVCpu->cpum.GstCtx)
     11938                        && (uOldCr0 & X86_CR0_PE)
     11939                        && !(pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE) )
     11940                    {
     11941                        /** @todo check selectors rather than returning all the time.  */
     11942                        Log4(("CRx CR0 write: back to real mode -> VINF_EM_RESCHEDULE_REM\n"));
     11943                        rcStrict = VINF_EM_RESCHEDULE_REM;
     11944                    }
    1192311945                    break;
    1192411946                }
     
    1314013162                /** @todo We have to set pending-debug exceptions here when the guest is
    1314113163                 *        single-stepping depending on the instruction that was interpreted. */
     13164
     13165                /*
     13166                 * HACK ALERT! Detect mode change and go to ring-3 to properly exit this
     13167                 *             real mode emulation stuff.
     13168                 */
     13169                if (   rc == VINF_SUCCESS
     13170                    && (pVCpu->cpum.GstCtx.cr0 & X86_CR0_PE))
     13171                {
     13172                    Log4(("hmR0VmxExitXcptGP: mode changed -> VINF_EM_RESCHEDULE\n"));
     13173                    /** @todo Exit fRealOnV86Active here w/o dropping back to ring-3. */
     13174                    rc = VINF_EM_RESCHEDULE;
     13175                }
     13176
    1314213177                Log4Func(("#GP rc=%Rrc\n", rc));
    1314313178                break;
     
    1314813183        rc = VERR_EM_INTERPRETER;
    1314913184
    13150     AssertMsg(rc == VINF_SUCCESS || rc == VERR_EM_INTERPRETER || rc == VINF_PGM_CHANGE_MODE || rc == VINF_EM_HALT,
    13151               ("#GP Unexpected rc=%Rrc\n", rc));
     13185    AssertMsg(   rc == VINF_SUCCESS
     13186              || rc == VERR_EM_INTERPRETER
     13187              || rc == VINF_EM_HALT
     13188              || rc == VINF_EM_RESCHEDULE
     13189              || rc == VINF_PGM_CHANGE_MODE
     13190              , ("#GP Unexpected rc=%Rrc\n", rc));
    1315213191    return rc;
    1315313192}
  • trunk/src/VBox/VMM/VMMR3/HM.cpp

    r73263 r73266  
    11851185static void hmR3DisableRawMode(PVM pVM)
    11861186{
     1187/** @todo r=bird: HM shouldn't be doing this crap. */
    11871188    /* Reinit the paging mode to force the new shadow mode. */
    11881189    for (VMCPUID i = 0; i < pVM->cCpus; i++)
    11891190    {
    11901191        PVMCPU pVCpu = &pVM->aCpus[i];
    1191         PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
     1192        PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
    11921193    }
    11931194}
  • trunk/src/VBox/VMM/VMMR3/PGM.cpp

    r73263 r73266  
    17371737        {
    17381738            PVMCPU pVCpu = &pVM->aCpus[i];
    1739             rc = PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
     1739            rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
    17401740            if (RT_FAILURE(rc))
    17411741                break;
     
    28122812    pVCpu->pgm.s.GCPhysCR3 = NIL_RTGCPHYS;
    28132813
    2814     int rc = PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
     2814    int rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
    28152815    AssertReleaseRC(rc);
    28162816
     
    28852885        PVMCPU  pVCpu = &pVM->aCpus[i];
    28862886
    2887         int rc = PGMR3ChangeMode(pVM, pVCpu, PGMMODE_REAL);
     2887        int rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL);
    28882888        AssertReleaseRC(rc);
    28892889
     
    32303230
    32313231/**
    3232  * Converts a PGMMODE value to a PGM_TYPE_* \#define.
    3233  *
    3234  * @returns PGM_TYPE_*.
    3235  * @param   pgmMode     The mode value to convert.
    3236  */
    3237 DECLINLINE(unsigned) pgmModeToType(PGMMODE pgmMode)
    3238 {
    3239     switch (pgmMode)
    3240     {
    3241         case PGMMODE_REAL:          return PGM_TYPE_REAL;
    3242         case PGMMODE_PROTECTED:     return PGM_TYPE_PROT;
    3243         case PGMMODE_32_BIT:        return PGM_TYPE_32BIT;
    3244         case PGMMODE_PAE:
    3245         case PGMMODE_PAE_NX:        return PGM_TYPE_PAE;
    3246         case PGMMODE_AMD64:
    3247         case PGMMODE_AMD64_NX:      return PGM_TYPE_AMD64;
    3248         case PGMMODE_NESTED_32BIT:  return PGM_TYPE_NESTED_32BIT;
    3249         case PGMMODE_NESTED_PAE:    return PGM_TYPE_NESTED_PAE;
    3250         case PGMMODE_NESTED_AMD64:  return PGM_TYPE_NESTED_AMD64;
    3251         case PGMMODE_EPT:           return PGM_TYPE_EPT;
    3252         default:
    3253             AssertFatalMsgFailed(("pgmMode=%d\n", pgmMode));
    3254     }
    3255 }
    3256 
    3257 
    3258 /**
    3259  * Calculates the shadow paging mode.
    3260  *
    3261  * @returns The shadow paging mode.
    3262  * @param   pVM             The cross context VM structure.
    3263  * @param   enmGuestMode    The guest mode.
    3264  * @param   enmHostMode     The host mode.
    3265  * @param   enmShadowMode   The current shadow mode.
    3266  * @param   penmSwitcher    Where to store the switcher to use.
    3267  *                          VMMSWITCHER_INVALID means no change.
    3268  */
    3269 static PGMMODE pgmCalcShadowMode(PVM pVM, PGMMODE enmGuestMode, SUPPAGINGMODE enmHostMode, PGMMODE enmShadowMode,
    3270                                  VMMSWITCHER *penmSwitcher)
    3271 {
    3272     VMMSWITCHER enmSwitcher = VMMSWITCHER_INVALID;
    3273     switch (enmGuestMode)
    3274     {
    3275         /*
    3276          * When switching to real or protected mode we don't change
    3277          * anything since it's likely that we'll switch back pretty soon.
    3278          *
    3279          * During pgmR3InitPaging we'll end up here with PGMMODE_INVALID
    3280          * and is supposed to determine which shadow paging and switcher to
    3281          * use during init.
    3282          */
    3283         case PGMMODE_REAL:
    3284         case PGMMODE_PROTECTED:
    3285             if (    enmShadowMode != PGMMODE_INVALID
    3286                 && VM_IS_RAW_MODE_ENABLED(pVM) /* always switch in hm and nem modes! */)
    3287                 break; /* (no change) */
    3288 
    3289             switch (enmHostMode)
    3290             {
    3291                 case SUPPAGINGMODE_32_BIT:
    3292                 case SUPPAGINGMODE_32_BIT_GLOBAL:
    3293                     enmShadowMode = PGMMODE_32_BIT;
    3294                     enmSwitcher = VMMSWITCHER_32_TO_32;
    3295                     break;
    3296 
    3297                 case SUPPAGINGMODE_PAE:
    3298                 case SUPPAGINGMODE_PAE_NX:
    3299                 case SUPPAGINGMODE_PAE_GLOBAL:
    3300                 case SUPPAGINGMODE_PAE_GLOBAL_NX:
    3301                     enmShadowMode = PGMMODE_PAE;
    3302                     enmSwitcher = VMMSWITCHER_PAE_TO_PAE;
    3303                     break;
    3304 
    3305                 case SUPPAGINGMODE_AMD64:
    3306                 case SUPPAGINGMODE_AMD64_GLOBAL:
    3307                 case SUPPAGINGMODE_AMD64_NX:
    3308                 case SUPPAGINGMODE_AMD64_GLOBAL_NX:
    3309                     enmShadowMode = PGMMODE_PAE;
    3310                     enmSwitcher = VMMSWITCHER_AMD64_TO_PAE;
    3311                     break;
    3312 
    3313                 default:
    3314                     AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
    3315                                                     *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
    3316             }
    3317             break;
    3318 
    3319         case PGMMODE_32_BIT:
    3320             switch (enmHostMode)
    3321             {
    3322                 case SUPPAGINGMODE_32_BIT:
    3323                 case SUPPAGINGMODE_32_BIT_GLOBAL:
    3324                     enmShadowMode = PGMMODE_32_BIT;
    3325                     enmSwitcher = VMMSWITCHER_32_TO_32;
    3326                     break;
    3327 
    3328                 case SUPPAGINGMODE_PAE:
    3329                 case SUPPAGINGMODE_PAE_NX:
    3330                 case SUPPAGINGMODE_PAE_GLOBAL:
    3331                 case SUPPAGINGMODE_PAE_GLOBAL_NX:
    3332                     enmShadowMode = PGMMODE_PAE;
    3333                     enmSwitcher = VMMSWITCHER_PAE_TO_PAE;
    3334                     break;
    3335 
    3336                 case SUPPAGINGMODE_AMD64:
    3337                 case SUPPAGINGMODE_AMD64_GLOBAL:
    3338                 case SUPPAGINGMODE_AMD64_NX:
    3339                 case SUPPAGINGMODE_AMD64_GLOBAL_NX:
    3340                     enmShadowMode = PGMMODE_PAE;
    3341                     enmSwitcher = VMMSWITCHER_AMD64_TO_PAE;
    3342                     break;
    3343 
    3344                 default:
    3345                     AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
    3346                                                     *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
    3347             }
    3348             break;
    3349 
    3350         case PGMMODE_PAE:
    3351         case PGMMODE_PAE_NX: /** @todo This might require more switchers and guest+both modes. */
    3352             switch (enmHostMode)
    3353             {
    3354                 case SUPPAGINGMODE_32_BIT:
    3355                 case SUPPAGINGMODE_32_BIT_GLOBAL:
    3356                     enmShadowMode = PGMMODE_PAE;
    3357                     enmSwitcher = VMMSWITCHER_32_TO_PAE;
    3358                     break;
    3359 
    3360                 case SUPPAGINGMODE_PAE:
    3361                 case SUPPAGINGMODE_PAE_NX:
    3362                 case SUPPAGINGMODE_PAE_GLOBAL:
    3363                 case SUPPAGINGMODE_PAE_GLOBAL_NX:
    3364                     enmShadowMode = PGMMODE_PAE;
    3365                     enmSwitcher = VMMSWITCHER_PAE_TO_PAE;
    3366                     break;
    3367 
    3368                 case SUPPAGINGMODE_AMD64:
    3369                 case SUPPAGINGMODE_AMD64_GLOBAL:
    3370                 case SUPPAGINGMODE_AMD64_NX:
    3371                 case SUPPAGINGMODE_AMD64_GLOBAL_NX:
    3372                     enmShadowMode = PGMMODE_PAE;
    3373                     enmSwitcher = VMMSWITCHER_AMD64_TO_PAE;
    3374                     break;
    3375 
    3376                 default:
    3377                     AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
    3378                                                     *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
    3379             }
    3380             break;
    3381 
    3382         case PGMMODE_AMD64:
    3383         case PGMMODE_AMD64_NX:
    3384             switch (enmHostMode)
    3385             {
    3386                 case SUPPAGINGMODE_32_BIT:
    3387                 case SUPPAGINGMODE_32_BIT_GLOBAL:
    3388                     enmShadowMode = PGMMODE_AMD64;
    3389                     enmSwitcher = VMMSWITCHER_32_TO_AMD64;
    3390                     break;
    3391 
    3392                 case SUPPAGINGMODE_PAE:
    3393                 case SUPPAGINGMODE_PAE_NX:
    3394                 case SUPPAGINGMODE_PAE_GLOBAL:
    3395                 case SUPPAGINGMODE_PAE_GLOBAL_NX:
    3396                     enmShadowMode = PGMMODE_AMD64;
    3397                     enmSwitcher = VMMSWITCHER_PAE_TO_AMD64;
    3398                     break;
    3399 
    3400                 case SUPPAGINGMODE_AMD64:
    3401                 case SUPPAGINGMODE_AMD64_GLOBAL:
    3402                 case SUPPAGINGMODE_AMD64_NX:
    3403                 case SUPPAGINGMODE_AMD64_GLOBAL_NX:
    3404                     enmShadowMode = PGMMODE_AMD64;
    3405                     enmSwitcher = VMMSWITCHER_AMD64_TO_AMD64;
    3406                     break;
    3407 
    3408                 default:
    3409                     AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", enmHostMode),
    3410                                                     *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
    3411             }
    3412             break;
    3413 
    3414         default:
    3415             AssertLogRelMsgFailedReturnStmt(("enmGuestMode=%d\n", enmGuestMode),
    3416                                             *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
    3417     }
    3418 
    3419     /*
    3420      * Override the shadow mode when NEM or nested paging is active.
    3421      */
    3422     if (VM_IS_NEM_ENABLED(pVM))
    3423     {
    3424         pVM->pgm.s.fNestedPaging = true;
    3425         enmShadowMode = PGMMODE_EPT; /* whatever harmless... */
    3426     }
    3427     else
    3428     {
    3429         bool fNestedPaging = HMIsNestedPagingActive(pVM);
    3430         pVM->pgm.s.fNestedPaging = fNestedPaging;
    3431         if (fNestedPaging)
    3432         {
    3433             if (HMIsVmxActive(pVM))
    3434                 enmShadowMode = PGMMODE_EPT;
    3435             else
    3436             {
    3437                 /* The nested SVM paging depends on the host one. */
    3438                 Assert(HMIsSvmActive(pVM));
    3439                 if (   enmGuestMode == PGMMODE_AMD64
    3440                     || enmGuestMode == PGMMODE_AMD64_NX)
    3441                     enmShadowMode = PGMMODE_NESTED_AMD64;
    3442                 else
    3443                     switch (pVM->pgm.s.enmHostMode)
    3444                     {
    3445                         case SUPPAGINGMODE_32_BIT:
    3446                         case SUPPAGINGMODE_32_BIT_GLOBAL:
    3447                             enmShadowMode = PGMMODE_NESTED_32BIT;
    3448                             break;
    3449 
    3450                         case SUPPAGINGMODE_PAE:
    3451                         case SUPPAGINGMODE_PAE_GLOBAL:
    3452                         case SUPPAGINGMODE_PAE_NX:
    3453                         case SUPPAGINGMODE_PAE_GLOBAL_NX:
    3454                             enmShadowMode = PGMMODE_NESTED_PAE;
    3455                             break;
    3456 
    3457 #if HC_ARCH_BITS == 64 || defined(RT_OS_DARWIN)
    3458                         case SUPPAGINGMODE_AMD64:
    3459                         case SUPPAGINGMODE_AMD64_GLOBAL:
    3460                         case SUPPAGINGMODE_AMD64_NX:
    3461                         case SUPPAGINGMODE_AMD64_GLOBAL_NX:
    3462                             enmShadowMode = PGMMODE_NESTED_AMD64;
    3463                             break;
    3464 #endif
    3465                         default:
    3466                             AssertLogRelMsgFailedReturnStmt(("enmHostMode=%d\n", pVM->pgm.s.enmHostMode),
    3467                                                             *penmSwitcher = VMMSWITCHER_INVALID, PGMMODE_INVALID);
    3468                     }
    3469             }
    3470         }
    3471     }
    3472 
    3473     *penmSwitcher = enmSwitcher;
    3474     return enmShadowMode;
    3475 }
    3476 
    3477 
    3478 /**
    3479  * Performs the actual mode change.
    3480  * This is called by PGMChangeMode and pgmR3InitPaging().
    3481  *
    3482  * @returns VBox status code. May suspend or power off the VM on error, but this
    3483  *          will trigger using FFs and not status codes.
    3484  *
    3485  * @param   pVM             The cross context VM structure.
    3486  * @param   pVCpu           The cross context virtual CPU structure.
    3487  * @param   enmGuestMode    The new guest mode. This is assumed to be different from
    3488  *                          the current mode.
    3489  */
    3490 VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode)
    3491 {
    3492     Log(("PGMR3ChangeMode: Guest mode: %s -> %s\n", PGMGetModeName(pVCpu->pgm.s.enmGuestMode), PGMGetModeName(enmGuestMode)));
    3493     STAM_REL_COUNTER_INC(&pVCpu->pgm.s.cGuestModeChanges);
    3494 
    3495     /*
    3496      * Calc the shadow mode and switcher.
    3497      */
    3498     VMMSWITCHER enmSwitcher   = VMMSWITCHER_INVALID;
    3499     PGMMODE     enmShadowMode = PGMMODE_INVALID;
    3500     enmShadowMode = pgmCalcShadowMode(pVM, enmGuestMode, pVM->pgm.s.enmHostMode, pVCpu->pgm.s.enmShadowMode, &enmSwitcher);
    3501 
    3502 #ifdef VBOX_WITH_RAW_MODE_NOT_R0
    3503     if (   enmSwitcher != VMMSWITCHER_INVALID
    3504         && VM_IS_RAW_MODE_ENABLED(pVM))
    3505     {
    3506         /*
    3507          * Select new switcher.
    3508          */
    3509         int rc = VMMR3SelectSwitcher(pVM, enmSwitcher);
    3510         AssertLogRelMsgRCReturn(rc,("VMMR3SelectSwitcher(%d) -> %Rrc\n", enmSwitcher, rc), rc);
    3511     }
    3512 #endif
    3513 
    3514     /*
    3515      * Exit old mode(s).
    3516      */
    3517     /* shadow */
    3518     if (enmShadowMode != pVCpu->pgm.s.enmShadowMode)
    3519     {
    3520         LogFlow(("PGMR3ChangeMode: Shadow mode: %s -> %s\n",  PGMGetModeName(pVCpu->pgm.s.enmShadowMode), PGMGetModeName(enmShadowMode)));
    3521         uintptr_t idxOldShw = pVCpu->pgm.s.idxShadowModeData;
    3522         if (   idxOldShw < RT_ELEMENTS(g_aPgmShadowModeData)
    3523             && g_aPgmShadowModeData[idxOldShw].pfnExit)
    3524         {
    3525             int rc = g_aPgmShadowModeData[idxOldShw].pfnExit(pVCpu);
    3526             AssertMsgRCReturn(rc, ("Exit failed for shadow mode %d: %Rrc\n", pVCpu->pgm.s.enmShadowMode, rc), rc);
    3527         }
    3528     }
    3529     else
    3530         LogFlow(("PGMR3ChangeMode: Shadow mode remains: %s\n",  PGMGetModeName(pVCpu->pgm.s.enmShadowMode)));
    3531 
    3532     /* guest */
    3533     uintptr_t const idxOldGst = pVCpu->pgm.s.idxGuestModeData;
    3534     if (   idxOldGst < RT_ELEMENTS(g_aPgmGuestModeData)
    3535         && g_aPgmGuestModeData[idxOldGst].pfnExit)
    3536     {
    3537         int rc = g_aPgmGuestModeData[idxOldGst].pfnExit(pVCpu);
    3538         AssertMsgReturn(RT_SUCCESS(rc), ("Exit failed for guest mode %d: %Rrc\n", pVCpu->pgm.s.enmGuestMode, rc), rc);
    3539     }
    3540     pVCpu->pgm.s.GCPhysCR3 = NIL_RTGCPHYS;
    3541 
    3542     /*
    3543      * Change the paging mode data indexes.
    3544      */
    3545     uintptr_t idxNewGst = pVCpu->pgm.s.idxGuestModeData = pgmModeToType(enmGuestMode);
    3546     AssertReturn(idxNewGst < RT_ELEMENTS(g_aPgmGuestModeData), VERR_PGM_MODE_IPE);
    3547     AssertReturn(g_aPgmGuestModeData[idxNewGst].uType == idxNewGst, VERR_PGM_MODE_IPE);
    3548     AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnGetPage, VERR_PGM_MODE_IPE);
    3549     AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnModifyPage, VERR_PGM_MODE_IPE);
    3550     AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnGetPDE, VERR_PGM_MODE_IPE);
    3551     AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnExit, VERR_PGM_MODE_IPE);
    3552     AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnEnter, VERR_PGM_MODE_IPE);
    3553 #ifdef IN_RING3
    3554     AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnRelocate, VERR_PGM_MODE_IPE);
    3555 #endif
    3556 
    3557     uintptr_t const idxNewShw = pVCpu->pgm.s.idxShadowModeData = pgmModeToType(enmShadowMode);
    3558     AssertReturn(idxNewShw < RT_ELEMENTS(g_aPgmShadowModeData), VERR_PGM_MODE_IPE);
    3559     AssertReturn(g_aPgmShadowModeData[idxNewShw].uType == idxNewShw, VERR_PGM_MODE_IPE);
    3560     AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnGetPage, VERR_PGM_MODE_IPE);
    3561     AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnModifyPage, VERR_PGM_MODE_IPE);
    3562     AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnExit, VERR_PGM_MODE_IPE);
    3563     AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnEnter, VERR_PGM_MODE_IPE);
    3564 #ifdef IN_RING3
    3565     AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnRelocate, VERR_PGM_MODE_IPE);
    3566 #endif
    3567 
    3568     uintptr_t const idxNewBth = pVCpu->pgm.s.idxBothModeData = (idxNewShw - PGM_TYPE_FIRST_SHADOW) * PGM_TYPE_END + idxNewGst;
    3569     AssertReturn(g_aPgmBothModeData[idxNewBth].uShwType == idxNewShw, VERR_PGM_MODE_IPE);
    3570     AssertReturn(g_aPgmBothModeData[idxNewBth].uGstType == idxNewGst, VERR_PGM_MODE_IPE);
    3571     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnInvalidatePage, VERR_PGM_MODE_IPE);
    3572     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnSyncCR3, VERR_PGM_MODE_IPE);
    3573     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnPrefetchPage, VERR_PGM_MODE_IPE);
    3574     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnVerifyAccessSyncPage, VERR_PGM_MODE_IPE);
    3575     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnMapCR3, VERR_PGM_MODE_IPE);
    3576     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnUnmapCR3, VERR_PGM_MODE_IPE);
    3577     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnEnter, VERR_PGM_MODE_IPE);
    3578 #ifdef IN_RING3
    3579     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnRelocate, VERR_PGM_MODE_IPE);
    3580 #endif
    3581 #ifdef VBOX_STRICT
    3582     AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnAssertCR3, VERR_PGM_MODE_IPE);
    3583 #endif
    3584 
    3585     /*
    3586      * Enter new shadow mode (if changed).
    3587      */
    3588     if (enmShadowMode != pVCpu->pgm.s.enmShadowMode)
    3589     {
    3590         pVCpu->pgm.s.enmShadowMode = enmShadowMode;
    3591         int rc = g_aPgmShadowModeData[idxNewShw].pfnEnter(pVCpu, enmGuestMode >= PGMMODE_AMD64);
    3592         AssertLogRelMsgRCReturnStmt(rc, ("Entering enmShadowMode=%s failed: %Rrc\n", PGMGetModeName(enmShadowMode), rc),
    3593                                     pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID, rc);
    3594     }
    3595 
    3596     /*
    3597      * Always flag the necessary updates
    3598      */
    3599     VMCPU_FF_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3);
    3600 
    3601     /*
    3602      * Enter the new guest and shadow+guest modes.
    3603      */
    3604     RTGCPHYS GCPhysCR3;
    3605     switch (enmGuestMode)
    3606     {
    3607         case PGMMODE_REAL:
    3608         case PGMMODE_PROTECTED:
    3609             GCPhysCR3 = NIL_RTGCPHYS;
    3610             break;
    3611 
    3612         case PGMMODE_32_BIT:
    3613             GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAGE_MASK;
    3614             break;
    3615 
    3616         case PGMMODE_PAE_NX:
    3617         case PGMMODE_PAE:
    3618             if (!pVM->cpum.ro.GuestFeatures.fPae)
    3619                 return VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_FATAL, "PAEmode",
    3620                                          N_("The guest is trying to switch to the PAE mode which is currently disabled by default in VirtualBox. PAE support can be enabled using the VM settings (System/Processor)"));
    3621             GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_PAE_PAGE_MASK;
    3622             break;
    3623 
    3624 #ifdef VBOX_WITH_64_BITS_GUESTS
    3625         case PGMMODE_AMD64_NX:
    3626         case PGMMODE_AMD64:
    3627             GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_AMD64_PAGE_MASK;
    3628             break;
    3629 #endif
    3630         default:
    3631             AssertLogRelMsgFailedReturn(("enmGuestMode=%d\n", enmGuestMode), VERR_NOT_IMPLEMENTED);
    3632     }
    3633 
    3634     pVCpu->pgm.s.enmGuestMode = enmGuestMode;
    3635 
    3636     int rc = g_aPgmGuestModeData[idxNewGst].pfnEnter(pVCpu, GCPhysCR3);
    3637     int rc2 = g_aPgmBothModeData[idxNewBth].pfnEnter(pVCpu, GCPhysCR3);
    3638 
    3639     /* Set the new guest CR3. */
    3640     pVCpu->pgm.s.GCPhysCR3 = GCPhysCR3;
    3641 
    3642     /* status codes. */
    3643     AssertRC(rc);
    3644     AssertRC(rc2);
    3645     if (RT_SUCCESS(rc))
    3646     {
    3647         rc = rc2;
    3648         if (RT_SUCCESS(rc)) /* no informational status codes. */
    3649             rc = VINF_SUCCESS;
    3650     }
    3651 
    3652     /*
    3653      * Notify HM.
    3654      */
    3655     HMPagingModeChanged(pVCpu, pVCpu->pgm.s.enmShadowMode, pVCpu->pgm.s.enmGuestMode);
    3656     return rc;
    3657 }
    3658 
    3659 
    3660 /**
    36613232 * Called by pgmPoolFlushAllInt prior to flushing the pool.
    36623233 *
     
    37003271{
    37013272    pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID;
    3702     int rc = PGMR3ChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));
     3273    int rc = PGMHCChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));
    37033274    Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3));
    37043275    AssertRCReturn(rc, rc);
  • trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp

    r70977 r73266  
    32273227                PVMCPU pVCpu = &pVM->aCpus[i];
    32283228
    3229                 rc = PGMR3ChangeMode(pVM, pVCpu, pVCpu->pgm.s.enmGuestMode);
     3229                rc = PGMHCChangeMode(pVM, pVCpu, pVCpu->pgm.s.enmGuestMode);
    32303230                AssertLogRelRCReturn(rc, rc);
    32313231
Note: See TracChangeset for help on using the changeset viewer.

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