Changeset 102604 in vbox for trunk/src/VBox/VMM/VMMR3
- Timestamp:
- Dec 15, 2023 6:49:33 AM (13 months ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
r102588 r102604 3048 3048 3049 3049 /** 3050 * Checks and fixes the maximum physical address width supported by the 3051 * variable-range MTRR MSRs to be consistent with what is reported in CPUID. 3052 * 3053 * @returns VBox status code. 3054 * @param pVM The cross context VM structure. 3055 * @param cVarMtrrs The number of variable-range MTRRs reported to the guest. 3056 */ 3057 static int cpumR3FixVarMtrrPhysAddrWidths(PVM pVM, uint8_t const cVarMtrrs) 3058 { 3059 AssertLogRelMsgReturn(cVarMtrrs <= RT_ELEMENTS(pVM->apCpusR3[0]->cpum.s.GuestMsrs.msr.aMtrrVarMsrs), 3060 ("Invalid number of variable range MTRRs reported (%u)\n", cVarMtrrs), 3061 VERR_CPUM_IPE_2); 3062 3063 /* 3064 * CPUID determines the actual maximum physical address width reported and supported. 3065 * If the CPU DB profile reported fewer address bits, we must correct it here by 3066 * updating the MSR write #GP masks of all the variable-range MTRR MSRs. Otherwise, 3067 * they cause problems when guests write to these MTRR MSRs, see @bugref{10498#c32}. 3068 */ 3069 for (uint8_t iVarMtrr = 0; iVarMtrr < cVarMtrrs; iVarMtrr++) 3070 { 3071 PCPUMMSRRANGE pBaseRange = cpumLookupMsrRange(pVM, MSR_IA32_MTRR_PHYSBASE0 + (iVarMtrr * 2)); 3072 AssertLogRelMsgReturn(pBaseRange, ("Failed to lookup the IA32_MTRR_PHYSBASE[%u] MSR range\n", iVarMtrr), 3073 VERR_NOT_FOUND); 3074 3075 PCPUMMSRRANGE pMaskRange = cpumLookupMsrRange(pVM, MSR_IA32_MTRR_PHYSMASK0 + (iVarMtrr * 2)); 3076 AssertLogRelMsgReturn(pBaseRange, ("Failed to lookup the IA32_MTRR_PHYSMASK[%u] MSR range\n", iVarMtrr), 3077 VERR_NOT_FOUND); 3078 3079 uint64_t const fBaseWrGpMask = pBaseRange->fWrGpMask; 3080 uint64_t const fMaskWrGpMask = pMaskRange->fWrGpMask; 3081 3082 uint8_t const cGuestMaxPhysAddrWidth = pVM->cpum.s.GuestFeatures.cMaxPhysAddrWidth; 3083 uint8_t const cProfilePhysBaseMaxPhysAddrWidth = ASMBitLastSetU64(~fBaseWrGpMask); 3084 uint8_t const cProfilePhysMaskMaxPhysAddrWidth = ASMBitLastSetU64(~fMaskWrGpMask); 3085 3086 AssertLogRelMsgReturn(cProfilePhysBaseMaxPhysAddrWidth == cProfilePhysMaskMaxPhysAddrWidth, 3087 ("IA32_MTRR_PHYSBASE and IA32_MTRR_PHYSMASK report different physical address widths (%u and %u)\n", 3088 cProfilePhysBaseMaxPhysAddrWidth, cProfilePhysMaskMaxPhysAddrWidth), 3089 VERR_CPUM_IPE_2); 3090 AssertLogRelMsgReturn(cProfilePhysBaseMaxPhysAddrWidth > 12 && cProfilePhysBaseMaxPhysAddrWidth <= 64, 3091 ("IA32_MTRR_PHYSBASE and IA32_MTRR_PHYSMASK reports an invalid physical address width of %u bits\n", 3092 cProfilePhysBaseMaxPhysAddrWidth), VERR_CPUM_IPE_2); 3093 3094 if (cProfilePhysBaseMaxPhysAddrWidth < cGuestMaxPhysAddrWidth) 3095 { 3096 uint64_t fNewBaseWrGpMask = fBaseWrGpMask; 3097 uint64_t fNewMaskWrGpMask = fMaskWrGpMask; 3098 int8_t cBits = cGuestMaxPhysAddrWidth - cProfilePhysBaseMaxPhysAddrWidth; 3099 while (cBits) 3100 { 3101 uint64_t const fWrGpAndMask = ~(uint64_t)RT_BIT_64(cProfilePhysBaseMaxPhysAddrWidth + cBits - 1); 3102 fNewBaseWrGpMask &= fWrGpAndMask; 3103 fNewMaskWrGpMask &= fWrGpAndMask; 3104 --cBits; 3105 } 3106 3107 pBaseRange->fWrGpMask = fBaseWrGpMask; 3108 pMaskRange->fWrGpMask = fMaskWrGpMask; 3109 3110 LogRel(("CPUM: Updated IA32_MTRR_PHYSBASE[%u] MSR write #GP mask (old=%#016RX64 new=%#016RX64)\n", 3111 iVarMtrr, fBaseWrGpMask, fNewBaseWrGpMask)); 3112 LogRel(("CPUM: Updated IA32_MTRR_PHYSMASK[%u] MSR write #GP mask (old=%#016RX64 new=%#016RX64)\n", 3113 iVarMtrr, fMaskWrGpMask, fNewMaskWrGpMask)); 3114 } 3115 } 3116 3117 return VINF_SUCCESS; 3118 } 3119 3120 3121 /** 3122 * Initialize MTRR capability based on what the guest CPU profile (typically host) 3123 * supports. 3124 * 3125 * @reports VBox status code. 3126 * @param pVM The cross context VM structure. 3127 */ 3128 static int cpumR3InitMtrrCap(PVM pVM) 3129 { 3130 #ifdef RT_ARCH_AMD64 3131 Assert(pVM->cpum.s.HostFeatures.fMtrr); 3132 #endif 3133 3134 /* Lookup the number of variable-range MTRRs supported by the CPU profile. */ 3135 PCCPUMMSRRANGE pMtrrCapRange = cpumLookupMsrRange(pVM, MSR_IA32_MTRR_CAP); 3136 AssertLogRelMsgReturn(pMtrrCapRange, ("Failed to lookup IA32_MTRR_CAP MSR range\n"), VERR_NOT_FOUND); 3137 uint8_t const cProfileVarRangeRegs = pMtrrCapRange->uValue & MSR_IA32_MTRR_CAP_VCNT_MASK; 3138 3139 /* Construct guest MTRR support capabilities. */ 3140 uint8_t const cGuestVarRangeRegs = RT_MIN(cProfileVarRangeRegs, CPUMCTX_MAX_MTRRVAR_COUNT); 3141 uint64_t const uGstMtrrCap = cGuestVarRangeRegs 3142 | MSR_IA32_MTRR_CAP_FIX 3143 | MSR_IA32_MTRR_CAP_WC; 3144 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 3145 { 3146 PVMCPU pVCpu = pVM->apCpusR3[idCpu]; 3147 pVCpu->cpum.s.GuestMsrs.msr.MtrrCap = uGstMtrrCap; 3148 pVCpu->cpum.s.GuestMsrs.msr.MtrrDefType = MSR_IA32_MTRR_DEF_TYPE_FIXED_EN 3149 | MSR_IA32_MTRR_DEF_TYPE_MTRR_EN 3150 | X86_MTRR_MT_UC; 3151 } 3152 3153 LogRel(("CPUM: Enabled fixed-range MTRRs and %u variable-range MTRRs\n", cGuestVarRangeRegs)); 3154 3155 /* 3156 * Ensure that the maximum physical address width supported by the variable-range MTRRs 3157 * are consistent with what is reported to the guest via CPUID. 3158 */ 3159 return cpumR3FixVarMtrrPhysAddrWidths(pVM, cGuestVarRangeRegs); 3160 } 3161 3162 3163 /** 3050 3164 * Initializes the emulated CPU's CPUID & MSR information. 3051 3165 * … … 3308 3422 if (pVM->cpum.s.fMtrrRead) 3309 3423 { 3310 #ifdef RT_ARCH_AMD64 3311 Assert(pVM->cpum.s.HostFeatures.fMtrr); 3312 #endif 3313 /* Lookup the number of variable-range MTRRs supported by the CPU profile. */ 3314 PCCPUMMSRRANGE pMtrrCapRange = cpumLookupMsrRange(pVM, MSR_IA32_MTRR_CAP); 3315 AssertLogRelReturn(pMtrrCapRange, VERR_CPUM_IPE_2); 3316 uint8_t const cProfileVarRangeRegs = pMtrrCapRange->uValue & MSR_IA32_MTRR_CAP_VCNT_MASK; 3317 3318 /* Construct guest MTRR support capabilities. */ 3319 uint8_t const cGuestVarRangeRegs = RT_MIN(cProfileVarRangeRegs, CPUMCTX_MAX_MTRRVAR_COUNT); 3320 uint64_t const uGstMtrrCap = cGuestVarRangeRegs 3321 | MSR_IA32_MTRR_CAP_FIX 3322 | MSR_IA32_MTRR_CAP_WC; 3323 for (VMCPUID idCpu = 0; idCpu < pVM->cCpus; idCpu++) 3324 { 3325 PVMCPU pVCpu = pVM->apCpusR3[idCpu]; 3326 pVCpu->cpum.s.GuestMsrs.msr.MtrrCap = uGstMtrrCap; 3327 pVCpu->cpum.s.GuestMsrs.msr.MtrrDefType = MSR_IA32_MTRR_DEF_TYPE_FIXED_EN 3328 | MSR_IA32_MTRR_DEF_TYPE_MTRR_EN 3329 | X86_MTRR_MT_UC; 3330 } 3331 LogRel(("CPUM: Enabled fixed-range MTRRs and %u variable-range MTRRs\n", cGuestVarRangeRegs)); 3424 rc = cpumR3InitMtrrCap(pVM); 3425 if (RT_SUCCESS(rc)) 3426 { /* likely */ } 3427 else 3428 return rc; 3332 3429 } 3333 3430 }
Note:
See TracChangeset
for help on using the changeset viewer.