Changeset 73266 in vbox
- Timestamp:
- Jul 20, 2018 2:27:20 PM (7 years ago)
- svn:sync-xref-src-repo-rev:
- 123873
- Location:
- trunk
- Files:
-
- 8 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/vmm/hm.h
r73264 r73266 134 134 VMM_INT_DECL(bool) HMIsSvmActive(PVM pVM); 135 135 VMM_INT_DECL(bool) HMIsVmxActive(PVM pVM); 136 VMM_INT_DECL(void) HM PagingModeChanged(PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode);136 VMM_INT_DECL(void) HMHCPagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode); 137 137 /** @} */ 138 138 -
trunk/include/VBox/vmm/pgm.h
r73246 r73266 445 445 VMMDECL(int) PGMUpdateCR3(PVMCPU pVCpu, uint64_t cr3); 446 446 VMMDECL(int) PGMChangeMode(PVMCPU pVCpu, uint64_t cr0, uint64_t cr4, uint64_t efer); 447 VMM_INT_DECL(int) PGMHCChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode); 447 448 VMMDECL(void) PGMCr0WpEnabled(PVMCPU pVCpu); 448 449 VMMDECL(PGMMODE) PGMGetGuestMode(PVMCPU pVCpu); … … 810 811 VMMR3DECL(int) PGMR3Term(PVM pVM); 811 812 VMMR3DECL(int) PGMR3LockCall(PVM pVM); 812 VMMR3DECL(int) PGMR3ChangeMode(PVM pVM, PVMCPU pVCpu, PGMMODE enmGuestMode);813 813 814 814 VMMR3DECL(int) PGMR3PhysRegisterRam(PVM pVM, RTGCPHYS GCPhys, RTGCPHYS cb, const char *pszDesc); -
trunk/src/VBox/VMM/VMMAll/HMAll.cpp
r73263 r73266 21 21 *********************************************************************************************************************************/ 22 22 #define LOG_GROUP LOG_GROUP_HM 23 #define VMCPU_INCL_CPUM_GST_CTX 23 24 #include <VBox/vmm/hm.h> 24 25 #include <VBox/vmm/pgm.h> … … 543 544 544 545 546 #ifndef IN_RC 545 547 /** 546 548 * Notification callback which is called whenever there is a chance that a CR3 … … 549 551 * This is called by PGM. 550 552 * 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 */ 558 VMM_INT_DECL(void) HMHCPagingModeChanged(PVM pVM, PVMCPU pVCpu, PGMMODE enmShadowMode, PGMMODE enmGuestMode) 559 { 560 # ifdef IN_RING3 558 561 /* Ignore page mode changes during state loading. */ 559 if (VMR3GetState(pV Cpu->pVMR3) == VMSTATE_LOADING)562 if (VMR3GetState(pVM) == VMSTATE_LOADING) 560 563 return; 561 # endif564 # endif 562 565 563 566 pVCpu->hm.s.enmShadowMode = enmShadowMode; … … 570 573 pVCpu->hm.s.vmx.fWasInRealMode = true; 571 574 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), 573 594 PGMGetModeName(enmShadowMode))); 574 595 } 575 596 #endif /* !IN_RC */ 597 -
trunk/src/VBox/VMM/VMMAll/PGMAll.cpp
r73262 r73266 2891 2891 PGM_INVL_VCPU_TLBS(pVCpu); 2892 2892 2893 #if def IN_RING32894 return PGM R3ChangeMode(pVCpu->CTX_SUFF(pVM), pVCpu, enmGuestMode);2893 #if defined(IN_RING3) || defined(IN_RING0) 2894 return PGMHCChangeMode(pVCpu->CTX_SUFF(pVM), pVCpu, enmGuestMode); 2895 2895 #else 2896 2896 LogFlow(("PGMChangeMode: returns VINF_PGM_CHANGE_MODE.\n")); … … 2899 2899 } 2900 2900 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 */ 2909 DECLINLINE(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 */ 2941 static 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 */ 3162 VMM_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 */ 2901 3333 2902 3334 /** -
trunk/src/VBox/VMM/VMMR0/HMVMXR0.cpp
r73255 r73266 11905 11905 case VMX_EXIT_QUAL_CRX_ACCESS_WRITE: /* MOV to CRx */ 11906 11906 { 11907 uint32_t const uOldCr0 = pVCpu->cpum.GstCtx.cr0; 11907 11908 rcStrict = IEMExecDecodedMovCRxWrite(pVCpu, pVmxTransient->cbInstr, 11908 11909 VMX_EXIT_QUAL_CRX_REGISTER(uExitQualification), … … 11921 11922 STAM_COUNTER_INC(&pVCpu->hm.s.StatExitCR0Write); 11922 11923 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 } 11923 11945 break; 11924 11946 } … … 13140 13162 /** @todo We have to set pending-debug exceptions here when the guest is 13141 13163 * 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 13142 13177 Log4Func(("#GP rc=%Rrc\n", rc)); 13143 13178 break; … … 13148 13183 rc = VERR_EM_INTERPRETER; 13149 13184 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)); 13152 13191 return rc; 13153 13192 } -
trunk/src/VBox/VMM/VMMR3/HM.cpp
r73263 r73266 1185 1185 static void hmR3DisableRawMode(PVM pVM) 1186 1186 { 1187 /** @todo r=bird: HM shouldn't be doing this crap. */ 1187 1188 /* Reinit the paging mode to force the new shadow mode. */ 1188 1189 for (VMCPUID i = 0; i < pVM->cCpus; i++) 1189 1190 { 1190 1191 PVMCPU pVCpu = &pVM->aCpus[i]; 1191 PGM R3ChangeMode(pVM, pVCpu, PGMMODE_REAL);1192 PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL); 1192 1193 } 1193 1194 } -
trunk/src/VBox/VMM/VMMR3/PGM.cpp
r73263 r73266 1737 1737 { 1738 1738 PVMCPU pVCpu = &pVM->aCpus[i]; 1739 rc = PGM R3ChangeMode(pVM, pVCpu, PGMMODE_REAL);1739 rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL); 1740 1740 if (RT_FAILURE(rc)) 1741 1741 break; … … 2812 2812 pVCpu->pgm.s.GCPhysCR3 = NIL_RTGCPHYS; 2813 2813 2814 int rc = PGM R3ChangeMode(pVM, pVCpu, PGMMODE_REAL);2814 int rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL); 2815 2815 AssertReleaseRC(rc); 2816 2816 … … 2885 2885 PVMCPU pVCpu = &pVM->aCpus[i]; 2886 2886 2887 int rc = PGM R3ChangeMode(pVM, pVCpu, PGMMODE_REAL);2887 int rc = PGMHCChangeMode(pVM, pVCpu, PGMMODE_REAL); 2888 2888 AssertReleaseRC(rc); 2889 2889 … … 3230 3230 3231 3231 /** 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 change3277 * anything since it's likely that we'll switch back pretty soon.3278 *3279 * During pgmR3InitPaging we'll end up here with PGMMODE_INVALID3280 * and is supposed to determine which shadow paging and switcher to3281 * use during init.3282 */3283 case PGMMODE_REAL:3284 case PGMMODE_PROTECTED:3285 if ( enmShadowMode != PGMMODE_INVALID3286 && 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 else3428 {3429 bool fNestedPaging = HMIsNestedPagingActive(pVM);3430 pVM->pgm.s.fNestedPaging = fNestedPaging;3431 if (fNestedPaging)3432 {3433 if (HMIsVmxActive(pVM))3434 enmShadowMode = PGMMODE_EPT;3435 else3436 {3437 /* The nested SVM paging depends on the host one. */3438 Assert(HMIsSvmActive(pVM));3439 if ( enmGuestMode == PGMMODE_AMD643440 || enmGuestMode == PGMMODE_AMD64_NX)3441 enmShadowMode = PGMMODE_NESTED_AMD64;3442 else3443 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 #endif3465 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 this3483 * 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 from3488 * 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_R03503 if ( enmSwitcher != VMMSWITCHER_INVALID3504 && 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 #endif3513 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 else3530 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_RING33554 AssertPtrReturn(g_aPgmGuestModeData[idxNewGst].pfnRelocate, VERR_PGM_MODE_IPE);3555 #endif3556 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_RING33565 AssertPtrReturn(g_aPgmShadowModeData[idxNewShw].pfnRelocate, VERR_PGM_MODE_IPE);3566 #endif3567 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_RING33579 AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnRelocate, VERR_PGM_MODE_IPE);3580 #endif3581 #ifdef VBOX_STRICT3582 AssertPtrReturn(g_aPgmBothModeData[idxNewBth].pfnAssertCR3, VERR_PGM_MODE_IPE);3583 #endif3584 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 updates3598 */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_GUESTS3625 case PGMMODE_AMD64_NX:3626 case PGMMODE_AMD64:3627 GCPhysCR3 = CPUMGetGuestCR3(pVCpu) & X86_CR3_AMD64_PAGE_MASK;3628 break;3629 #endif3630 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 /**3661 3232 * Called by pgmPoolFlushAllInt prior to flushing the pool. 3662 3233 * … … 3700 3271 { 3701 3272 pVCpu->pgm.s.enmShadowMode = PGMMODE_INVALID; 3702 int rc = PGM R3ChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu));3273 int rc = PGMHCChangeMode(pVM, pVCpu, PGMGetGuestMode(pVCpu)); 3703 3274 Assert(VMCPU_FF_IS_SET(pVCpu, VMCPU_FF_PGM_SYNC_CR3)); 3704 3275 AssertRCReturn(rc, rc); -
trunk/src/VBox/VMM/VMMR3/PGMSavedState.cpp
r70977 r73266 3227 3227 PVMCPU pVCpu = &pVM->aCpus[i]; 3228 3228 3229 rc = PGM R3ChangeMode(pVM, pVCpu, pVCpu->pgm.s.enmGuestMode);3229 rc = PGMHCChangeMode(pVM, pVCpu, pVCpu->pgm.s.enmGuestMode); 3230 3230 AssertLogRelRCReturn(rc, rc); 3231 3231
Note:
See TracChangeset
for help on using the changeset viewer.