Changeset 54737 in vbox for trunk/src/VBox
- Timestamp:
- Mar 12, 2015 9:02:21 PM (10 years ago)
- Location:
- trunk/src/VBox/VMM
- Files:
-
- 37 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/CPUMAllMsrs.cpp
r54714 r54737 2986 2986 static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_AmdK8CpuNameN(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 2987 2987 { 2988 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), pRange->uValue / 2 + 0x80000001 , 0);2988 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), pRange->uValue / 2 + 0x80000001); 2989 2989 if (pLeaf) 2990 2990 { … … 3636 3636 static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_AmdK8CpuIdCtlStd07hEbax(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 3637 3637 { 3638 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000007, 0); 3638 bool fIgnored; 3639 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeafEx(pVCpu->CTX_SUFF(pVM), 0x00000007, 0, &fIgnored); 3639 3640 if (pLeaf) 3640 3641 *puValue = RT_MAKE_U64(pLeaf->uEbx, pLeaf->uEax); … … 3656 3657 static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_AmdK8CpuIdCtlStd06hEcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 3657 3658 { 3658 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000006 , 0);3659 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000006); 3659 3660 if (pLeaf) 3660 3661 *puValue = pLeaf->uEcx; … … 3676 3677 static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_AmdK8CpuIdCtlStd01hEdcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 3677 3678 { 3678 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000001 , 0);3679 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x00000001); 3679 3680 if (pLeaf) 3680 3681 *puValue = RT_MAKE_U64(pLeaf->uEdx, pLeaf->uEcx); … … 3696 3697 static DECLCALLBACK(VBOXSTRICTRC) cpumMsrRd_AmdK8CpuIdCtlExt01hEdcx(PVMCPU pVCpu, uint32_t idMsr, PCCPUMMSRRANGE pRange, uint64_t *puValue) 3697 3698 { 3698 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x80000001 , 0);3699 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf(pVCpu->CTX_SUFF(pVM), 0x80000001); 3699 3700 if (pLeaf) 3700 3701 *puValue = RT_MAKE_U64(pLeaf->uEdx, pLeaf->uEcx); -
trunk/src/VBox/VMM/VMMAll/CPUMAllRegs.cpp
r54714 r54737 1138 1138 1139 1139 /** 1140 * Looks up a CPUID leaf in the CPUID leaf array, no subleaf. 1141 * 1142 * @returns Pointer to the leaf if found, NULL if not. 1143 * 1144 * @param pVM Pointer to the cross context VM structure. 1145 * @param uLeaf The leaf to get. 1146 */ 1147 PCPUMCPUIDLEAF cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf) 1148 { 1149 unsigned iEnd = pVM->cpum.s.GuestInfo.cCpuIdLeaves; 1150 if (iEnd) 1151 { 1152 unsigned iStart = 0; 1153 PCPUMCPUIDLEAF paLeaves = pVM->cpum.s.GuestInfo.CTX_SUFF(paCpuIdLeaves); 1154 for (;;) 1155 { 1156 unsigned i = iStart + (iEnd - iStart) / 2U; 1157 if (uLeaf < paLeaves[i].uLeaf) 1158 { 1159 if (i <= iStart) 1160 return NULL; 1161 iEnd = i; 1162 } 1163 else if (uLeaf > paLeaves[i].uLeaf) 1164 { 1165 i += 1; 1166 if (i >= iEnd) 1167 return NULL; 1168 iStart = i; 1169 } 1170 else 1171 { 1172 if (RT_LIKELY(paLeaves[i].fSubLeafMask == 0 && paLeaves[i].uSubLeaf == 0)) 1173 return &paLeaves[i]; 1174 1175 /* This shouldn't normally happen. But in case the it does due 1176 to user configuration overrids or something, just return the 1177 first sub-leaf. */ 1178 AssertMsgFailed(("uLeaf=%#x fSubLeafMask=%#x uSubLeaf=%#x\n", 1179 uLeaf, paLeaves[i].fSubLeafMask, paLeaves[i].uSubLeaf)); 1180 while ( paLeaves[i].uSubLeaf != 0 1181 && i > 0 1182 && uLeaf == paLeaves[i - 1].uLeaf) 1183 i--; 1184 return &paLeaves[i]; 1185 } 1186 } 1187 } 1188 1189 return NULL; 1190 } 1191 1192 1193 /** 1140 1194 * Looks up a CPUID leaf in the CPUID leaf array. 1141 1195 * … … 1146 1200 * @param uSubLeaf The subleaf, if applicable. Just pass 0 if it 1147 1201 * isn't. 1148 */ 1149 PCPUMCPUIDLEAF cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf) 1202 * @param pfExactSubLeafHit Whether we've got an exact subleaf hit or not. 1203 */ 1204 PCPUMCPUIDLEAF cpumCpuIdGetLeafEx(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf, bool *pfExactSubLeafHit) 1150 1205 { 1151 1206 unsigned iEnd = pVM->cpum.s.GuestInfo.cCpuIdLeaves; … … 1173 1228 { 1174 1229 uSubLeaf &= paLeaves[i].fSubLeafMask; 1175 if (uSubLeaf != paLeaves[i].uSubLeaf) 1230 if (uSubLeaf == paLeaves[i].uSubLeaf) 1231 *pfExactSubLeafHit = true; 1232 else 1176 1233 { 1177 1234 /* Find the right subleaf. We return the last one before … … 1187 1244 && uSubLeaf >= paLeaves[i + 1].uSubLeaf) 1188 1245 i++; 1246 *pfExactSubLeafHit = uSubLeaf == paLeaves[i].uSubLeaf; 1189 1247 } 1190 1248 return &paLeaves[i]; … … 1193 1251 } 1194 1252 1253 *pfExactSubLeafHit = false; 1195 1254 return NULL; 1196 1255 } … … 1200 1259 * Gets a CPUID leaf. 1201 1260 * 1202 * @param pVCpu Pointer to the VMCPU. 1203 * @param iLeaf The CPUID leaf to get. 1204 * @param pEax Where to store the EAX value. 1205 * @param pEbx Where to store the EBX value. 1206 * @param pEcx Where to store the ECX value. 1207 * @param pEdx Where to store the EDX value. 1208 */ 1209 VMMDECL(void) CPUMGetGuestCpuId(PVMCPU pVCpu, uint32_t iLeaf, uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx) 1210 { 1211 PVM pVM = pVCpu->CTX_SUFF(pVM); 1212 1213 PCCPUMCPUID pCpuId; 1214 if (iLeaf < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmStd)) 1215 pCpuId = &pVM->cpum.s.aGuestCpuIdPatmStd[iLeaf]; 1216 else if (iLeaf - UINT32_C(0x80000000) < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmExt)) 1217 pCpuId = &pVM->cpum.s.aGuestCpuIdPatmExt[iLeaf - UINT32_C(0x80000000)]; 1218 else if ( iLeaf - UINT32_C(0x40000000) < 0x100 /** @todo Fix this later: Hyper-V says 0x400000FF is the last valid leaf. */ 1219 && (pVCpu->CTX_SUFF(pVM)->cpum.s.aGuestCpuIdPatmStd[1].uEcx & X86_CPUID_FEATURE_ECX_HVP)) /* Only report if HVP bit set. */ 1261 * @param pVCpu Pointer to the VMCPU. 1262 * @param uLeaf The CPUID leaf to get. 1263 * @param uSubLeaf The CPUID sub-leaf to get, if applicable. 1264 * @param pEax Where to store the EAX value. 1265 * @param pEbx Where to store the EBX value. 1266 * @param pEcx Where to store the ECX value. 1267 * @param pEdx Where to store the EDX value. 1268 */ 1269 VMMDECL(void) CPUMGetGuestCpuId(PVMCPU pVCpu, uint32_t uLeaf, uint32_t uSubLeaf, 1270 uint32_t *pEax, uint32_t *pEbx, uint32_t *pEcx, uint32_t *pEdx) 1271 { 1272 bool fExactSubLeafHit; 1273 PVM pVM = pVCpu->CTX_SUFF(pVM); 1274 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeafEx(pVM, uLeaf, uSubLeaf, &fExactSubLeafHit); 1275 if (pLeaf) 1220 1276 { 1221 PCPUMCPUIDLEAF pHyperLeaf = cpumCpuIdGetLeaf(pVM, iLeaf, 0 /* uSubLeaf */); 1222 if (RT_LIKELY(pHyperLeaf)) 1277 if (fExactSubLeafHit) 1223 1278 { 1224 *pEax = pHyperLeaf->uEax; 1225 *pEbx = pHyperLeaf->uEbx; 1226 *pEcx = pHyperLeaf->uEcx; 1227 *pEdx = pHyperLeaf->uEdx; 1279 *pEax = pLeaf->uEax; 1280 *pEbx = pLeaf->uEbx; 1281 *pEcx = pLeaf->uEcx; 1282 *pEdx = pLeaf->uEdx; 1283 1284 /* 1285 * Deal with CPU specific information (currently only APIC ID). 1286 */ 1287 if (pLeaf->fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID) 1288 { 1289 if (uLeaf == 1) 1290 { 1291 /* Bits 31-24: Initial APIC ID */ 1292 Assert(pVCpu->idCpu <= 255); 1293 Assert((*pEbx >> 24) == 0); /* raw-mode assumption */ 1294 *pEbx = (*pEbx & UINT32_C(0x00ffffff)) | (pVCpu->idCpu << 24); 1295 } 1296 else if (uLeaf == 0xb) 1297 { 1298 /* EDX: Initial extended APIC ID. */ 1299 Assert(*pEdx == 0); /* raw-mode assumption */ 1300 *pEdx = pVCpu->idCpu; 1301 } 1302 else if (uLeaf == UINT32_C(0x8000001e)) 1303 { 1304 /* EAX: Initial extended APIC ID. */ 1305 Assert(*pEax == 0); /* raw-mode assumption */ 1306 *pEax = pVCpu->idCpu; 1307 } 1308 else 1309 AssertMsgFailed(("uLeaf=%#x\n", uLeaf)); 1310 } 1228 1311 } 1312 /* 1313 * Out of range sub-leaves aren't quite as easy and pretty as we emulate 1314 * them here, but we do the best we can here... 1315 */ 1229 1316 else 1230 1317 { 1231 1318 *pEax = *pEbx = *pEcx = *pEdx = 0; 1319 if (pLeaf->fFlags & CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES) 1320 { 1321 *pEcx = uSubLeaf & 0xff; 1322 *pEdx = pVCpu->idCpu; 1323 } 1232 1324 } 1233 return;1234 1325 } 1235 else if (iLeaf - UINT32_C(0xc0000000) < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmCentaur))1236 pCpuId = &pVM->cpum.s.aGuestCpuIdPatmCentaur[iLeaf - UINT32_C(0xc0000000)];1237 1326 else 1238 pCpuId = &pVM->cpum.s.GuestCpuIdPatmDef;1239 1240 uint32_t cCurrentCacheIndex = *pEcx;1241 1242 *pEax = pCpuId->uEax;1243 *pEbx = pCpuId->uEbx;1244 *pEcx = pCpuId->uEcx;1245 *pEdx = pCpuId->uEdx;1246 1247 if ( iLeaf == 1)1248 1327 { 1249 /* Bits 31-24: Initial APIC ID */ 1250 Assert(pVCpu->idCpu <= 255); 1251 *pEbx |= (pVCpu->idCpu << 24); 1252 } 1253 1254 if ( iLeaf == 4 1255 && cCurrentCacheIndex < 3 1256 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL) 1257 { 1258 uint32_t type, level, sharing, linesize, 1259 partitions, associativity, sets, cores; 1260 1261 /* For type: 1 - data cache, 2 - i-cache, 3 - unified */ 1262 partitions = 1; 1263 /* Those are only to shut up compiler, as they will always 1264 get overwritten, and compiler should be able to figure that out */ 1265 sets = associativity = sharing = level = 1; 1266 cores = pVM->cCpus > 32 ? 32 : pVM->cCpus; 1267 switch (cCurrentCacheIndex) 1328 /* 1329 * Different CPUs have different ways of dealing with unknown CPUID leaves. 1330 */ 1331 switch (pVM->cpum.s.GuestInfo.enmUnknownCpuIdMethod) 1268 1332 { 1269 case 0: 1270 type = 1; 1271 level = 1; 1272 sharing = 1; 1273 linesize = 64; 1274 associativity = 8; 1275 sets = 64; 1333 default: 1334 AssertFailed(); 1335 case CPUMUNKNOWNCPUID_DEFAULTS: 1336 case CPUMUNKNOWNCPUID_LAST_STD_LEAF: /* ASSUME this is executed */ 1337 case CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX: /** @todo Implement CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX */ 1338 *pEax = pVM->cpum.s.GuestInfo.DefCpuId.uEax; 1339 *pEbx = pVM->cpum.s.GuestInfo.DefCpuId.uEbx; 1340 *pEcx = pVM->cpum.s.GuestInfo.DefCpuId.uEcx; 1341 *pEdx = pVM->cpum.s.GuestInfo.DefCpuId.uEdx; 1276 1342 break; 1277 case 1: 1278 level = 1; 1279 type = 2; 1280 sharing = 1; 1281 linesize = 64; 1282 associativity = 8; 1283 sets = 64; 1284 break; 1285 default: /* shut up gcc.*/ 1286 AssertFailed(); 1287 case 2: 1288 level = 2; 1289 type = 3; 1290 sharing = cores; /* our L2 cache is modelled as shared between all cores */ 1291 linesize = 64; 1292 associativity = 24; 1293 sets = 4096; 1343 case CPUMUNKNOWNCPUID_PASSTHRU: 1344 *pEax = uLeaf; 1345 *pEbx = 0; 1346 *pEcx = uSubLeaf; 1347 *pEdx = 0; 1294 1348 break; 1295 1349 } 1296 1297 NOREF(type);1298 *pEax |= ((cores - 1) << 26) |1299 ((sharing - 1) << 14) |1300 (level << 5) |1301 1;1302 *pEbx = (linesize - 1) |1303 ((partitions - 1) << 12) |1304 ((associativity - 1) << 22); /* -1 encoding */1305 *pEcx = sets - 1;1306 1350 } 1307 1308 Log2(("CPUMGetGuestCpuId: iLeaf=%#010x %RX32 %RX32 %RX32 %RX32\n", iLeaf, *pEax, *pEbx, *pEcx, *pEdx)); 1351 Log2(("CPUMGetGuestCpuId: uLeaf=%#010x/%#010x %RX32 %RX32 %RX32 %RX32\n", uLeaf, uSubLeaf, *pEax, *pEbx, *pEcx, *pEdx)); 1309 1352 } 1310 1353 … … 1326 1369 */ 1327 1370 case CPUMCPUIDFEATURE_APIC: 1328 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1371 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1329 1372 if (pLeaf) 1330 1373 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_APIC; 1331 1374 1332 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1375 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1333 1376 if ( pLeaf 1334 1377 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) … … 1343 1386 */ 1344 1387 case CPUMCPUIDFEATURE_X2APIC: 1345 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1388 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1346 1389 if (pLeaf) 1347 1390 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEcx = pLeaf->uEcx |= X86_CPUID_FEATURE_ECX_X2APIC; … … 1361 1404 } 1362 1405 1363 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1406 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1364 1407 if (pLeaf) 1365 1408 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_SEP; … … 1373 1416 */ 1374 1417 case CPUMCPUIDFEATURE_SYSCALL: 1375 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1418 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1376 1419 if ( !pLeaf 1377 1420 || !pVM->cpum.s.HostFeatures.fSysCall) … … 1406 1449 } 1407 1450 1408 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1451 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1409 1452 if (pLeaf) 1410 1453 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_PAE; 1411 1454 1412 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1455 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1413 1456 if ( pLeaf 1414 1457 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) … … 1424 1467 */ 1425 1468 case CPUMCPUIDFEATURE_LONG_MODE: 1426 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1469 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1427 1470 if ( !pLeaf 1428 1471 || !pVM->cpum.s.HostFeatures.fLongMode) … … 1443 1486 */ 1444 1487 case CPUMCPUIDFEATURE_NX: 1445 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1488 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1446 1489 if ( !pLeaf 1447 1490 || !pVM->cpum.s.HostFeatures.fNoExecute) … … 1463 1506 */ 1464 1507 case CPUMCPUIDFEATURE_LAHF: 1465 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1508 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1466 1509 if ( !pLeaf 1467 1510 || !pVM->cpum.s.HostFeatures.fLahfSahf) … … 1483 1526 */ 1484 1527 case CPUMCPUIDFEATURE_PAT: 1485 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1528 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1486 1529 if (pLeaf) 1487 1530 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx |= X86_CPUID_FEATURE_EDX_PAT; 1488 1531 1489 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1532 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1490 1533 if ( pLeaf 1491 1534 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) … … 1501 1544 */ 1502 1545 case CPUMCPUIDFEATURE_RDTSCP: 1503 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1546 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1504 1547 if ( !pLeaf 1505 1548 || !pVM->cpum.s.HostFeatures.fRdTscP … … 1521 1564 */ 1522 1565 case CPUMCPUIDFEATURE_HVP: 1523 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1566 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1524 1567 if (pLeaf) 1525 1568 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEcx = pLeaf->uEcx |= X86_CPUID_FEATURE_ECX_HVP; … … 1533 1576 */ 1534 1577 case CPUMCPUIDFEATURE_MWAIT_EXTS: 1535 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000005) , 0);1578 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000005)); 1536 1579 if ( !pLeaf 1537 1580 || !pVM->cpum.s.HostFeatures.fMWaitExtensions) … … 1605 1648 { 1606 1649 case CPUMCPUIDFEATURE_APIC: 1607 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1650 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1608 1651 if (pLeaf) 1609 1652 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_APIC; 1610 1653 1611 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1654 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1612 1655 if ( pLeaf 1613 1656 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) … … 1619 1662 1620 1663 case CPUMCPUIDFEATURE_X2APIC: 1621 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1664 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1622 1665 if (pLeaf) 1623 1666 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEcx = pLeaf->uEcx &= ~X86_CPUID_FEATURE_ECX_X2APIC; … … 1627 1670 1628 1671 case CPUMCPUIDFEATURE_PAE: 1629 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1672 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1630 1673 if (pLeaf) 1631 1674 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_PAE; 1632 1675 1633 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1676 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1634 1677 if ( pLeaf 1635 1678 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) … … 1641 1684 1642 1685 case CPUMCPUIDFEATURE_PAT: 1643 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1686 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1644 1687 if (pLeaf) 1645 1688 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEdx = pLeaf->uEdx &= ~X86_CPUID_FEATURE_EDX_PAT; 1646 1689 1647 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1690 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1648 1691 if ( pLeaf 1649 1692 && pVM->cpum.s.GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) … … 1655 1698 1656 1699 case CPUMCPUIDFEATURE_LONG_MODE: 1657 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1700 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1658 1701 if (pLeaf) 1659 1702 pVM->cpum.s.aGuestCpuIdPatmExt[1].uEdx = pLeaf->uEdx &= ~X86_CPUID_EXT_FEATURE_EDX_LONG_MODE; … … 1662 1705 1663 1706 case CPUMCPUIDFEATURE_LAHF: 1664 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1707 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1665 1708 if (pLeaf) 1666 1709 pVM->cpum.s.aGuestCpuIdPatmExt[1].uEcx = pLeaf->uEcx &= ~X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF; … … 1669 1712 1670 1713 case CPUMCPUIDFEATURE_RDTSCP: 1671 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001) , 0);1714 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x80000001)); 1672 1715 if (pLeaf) 1673 1716 pVM->cpum.s.aGuestCpuIdPatmExt[1].uEdx = pLeaf->uEdx &= ~X86_CPUID_EXT_FEATURE_EDX_RDTSCP; … … 1677 1720 1678 1721 case CPUMCPUIDFEATURE_HVP: 1679 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001) , 0);1722 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000001)); 1680 1723 if (pLeaf) 1681 1724 pVM->cpum.s.aGuestCpuIdPatmStd[1].uEcx = pLeaf->uEcx &= ~X86_CPUID_FEATURE_ECX_HVP; … … 1684 1727 1685 1728 case CPUMCPUIDFEATURE_MWAIT_EXTS: 1686 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000005) , 0);1729 pLeaf = cpumCpuIdGetLeaf(pVM, UINT32_C(0x00000005)); 1687 1730 if (pLeaf) 1688 1731 pVM->cpum.s.aGuestCpuIdPatmStd[5].uEcx = pLeaf->uEcx &= ~(X86_CPUID_MWAIT_ECX_EXT | X86_CPUID_MWAIT_ECX_BREAKIRQIF0); -
trunk/src/VBox/VMM/VMMAll/EMAll.cpp
r53466 r54737 1214 1214 { 1215 1215 Assert(pRegFrame == CPUMGetGuestCtxCore(pVCpu)); 1216 uint32_t iLeaf = pRegFrame->eax; 1216 uint32_t iLeaf = pRegFrame->eax; 1217 uint32_t iSubLeaf = pRegFrame->ecx; 1217 1218 NOREF(pVM); 1218 1219 … … 1220 1221 pRegFrame->rax = 0; 1221 1222 pRegFrame->rbx = 0; 1222 pRegFrame->rcx &= UINT64_C(0x00000000ffffffff);1223 pRegFrame->rcx = 0; 1223 1224 pRegFrame->rdx = 0; 1224 1225 1225 1226 /* Note: operates the same in 64 and non-64 bits mode. */ 1226 CPUMGetGuestCpuId(pVCpu, iLeaf, &pRegFrame->eax, &pRegFrame->ebx, &pRegFrame->ecx, &pRegFrame->edx);1227 CPUMGetGuestCpuId(pVCpu, iLeaf, iSubLeaf, &pRegFrame->eax, &pRegFrame->ebx, &pRegFrame->ecx, &pRegFrame->edx); 1227 1228 Log(("Emulate: CPUID %x -> %08x %08x %08x %08x\n", iLeaf, pRegFrame->eax, pRegFrame->ebx, pRegFrame->ecx, pRegFrame->edx)); 1228 1229 return VINF_SUCCESS; … … 1345 1346 return VERR_EM_INTERPRETER; /* supervisor only */ 1346 1347 1347 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Dummy);1348 CPUMGetGuestCpuId(pVCpu, 1, 0, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Dummy); 1348 1349 if (!(u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR)) 1349 1350 return VERR_EM_INTERPRETER; /* not supported */ … … 1353 1354 * CPUID.05H.ECX[1] defines support for interrupts as break events for mwait even when IF=0 1354 1355 */ 1355 CPUMGetGuestCpuId(pVCpu, 5, &u32Dummy, &u32Dummy, &u32MWaitFeatures, &u32Dummy);1356 CPUMGetGuestCpuId(pVCpu, 5, 0, &u32Dummy, &u32Dummy, &u32MWaitFeatures, &u32Dummy); 1356 1357 if (pRegFrame->ecx > 1) 1357 1358 { … … 1390 1391 return VERR_EM_INTERPRETER; /* supervisor only */ 1391 1392 1392 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Dummy);1393 CPUMGetGuestCpuId(pVCpu, 1, 0, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Dummy); 1393 1394 if (!(u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR)) 1394 1395 return VERR_EM_INTERPRETER; /* not supported */ -
trunk/src/VBox/VMM/VMMAll/IEMAll.cpp
r53466 r54737 5143 5143 { 5144 5144 uint32_t uEax, uEbx, uEcx, uEdx; 5145 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 0x00000001, &uEax, &uEbx, &uEcx, &uEdx);5145 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 0x00000001, 0, &uEax, &uEbx, &uEcx, &uEdx); 5146 5146 return (fEcx && (uEcx & fEcx)) 5147 5147 || (fEdx && (uEdx & fEdx)); … … 5163 5163 { 5164 5164 uint32_t uEax, uEbx, uEcx, uEdx; 5165 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 0x80000001, &uEax, &uEbx, &uEcx, &uEdx);5165 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 0x80000001, 0, &uEax, &uEbx, &uEcx, &uEdx); 5166 5166 return (fEcx && (uEcx & fEcx)) 5167 5167 || (fEdx && (uEdx & fEdx)); -
trunk/src/VBox/VMM/VMMAll/IEMAllCImpl.cpp.h
r54203 r54737 5799 5799 uint32_t fMWaitFeatures = 0; 5800 5800 uint32_t uIgnore = 0; 5801 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 5, &uIgnore, &uIgnore, &fMWaitFeatures, &uIgnore);5801 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), 5, 0, &uIgnore, &uIgnore, &fMWaitFeatures, &uIgnore); 5802 5802 if ( (fMWaitFeatures & (X86_CPUID_MWAIT_ECX_EXT | X86_CPUID_MWAIT_ECX_BREAKIRQIF0)) 5803 5803 != (X86_CPUID_MWAIT_ECX_EXT | X86_CPUID_MWAIT_ECX_BREAKIRQIF0)) … … 5854 5854 PCPUMCTX pCtx = pIemCpu->CTX_SUFF(pCtx); 5855 5855 5856 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), pCtx->eax, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx);5856 CPUMGetGuestCpuId(IEMCPU_TO_VMCPU(pIemCpu), pCtx->eax, pCtx->ecx, &pCtx->eax, &pCtx->ebx, &pCtx->ecx, &pCtx->edx); 5857 5857 pCtx->rax &= UINT32_C(0xffffffff); 5858 5858 pCtx->rbx &= UINT32_C(0xffffffff); -
trunk/src/VBox/VMM/VMMR0/CPUMR0.cpp
r54714 r54737 286 286 for (uint32_t i = 0; i < RT_ELEMENTS(g_aCpuidUnifyBits); i++) 287 287 { 288 bool fIgnored; 288 289 uint32_t uLeaf = g_aCpuidUnifyBits[i].uLeaf; 289 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeaf (pVM, uLeaf, 0);290 PCPUMCPUIDLEAF pLeaf = cpumCpuIdGetLeafEx(pVM, uLeaf, 0, &fIgnored); 290 291 if (pLeaf) 291 292 { -
trunk/src/VBox/VMM/VMMR3/CFGM.cpp
r53574 r54737 893 893 { 894 894 /* 895 * Enumerate the lea fs and check them against pszValidValues.895 * Enumerate the leaves and check them against pszValidValues. 896 896 */ 897 897 for (PCFGMLEAF pLeaf = pNode->pFirstLeaf; pLeaf; pLeaf = pLeaf->pNext) … … 1470 1470 /* 1471 1471 * Use CFGMR3InsertNode to create a new node and then 1472 * re-attach the children and lea fs of the subtree to it.1472 * re-attach the children and leaves of the subtree to it. 1473 1473 */ 1474 1474 PCFGMNODE pNewChild; … … 1940 1940 1941 1941 /* 1942 * Free lea fs.1942 * Free leaves. 1943 1943 */ 1944 1944 while (pNode->pFirstLeaf) -
trunk/src/VBox/VMM/VMMR3/CPUM.cpp
r54714 r54737 106 106 static DECLCALLBACK(void) cpumR3InfoHyper(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 107 107 static DECLCALLBACK(void) cpumR3InfoHost(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 108 static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs);109 108 110 109 … … 677 676 678 677 /* 679 * Initialize the Guest CPUID state.680 */ 681 rc = cpumR3 CpuIdInit(pVM);678 * Initialize the Guest CPUID and MSR states. 679 */ 680 rc = cpumR3InitCpuIdAndMsrs(pVM); 682 681 if (RT_FAILURE(rc)) 683 682 return rc; … … 718 717 { 719 718 /* 720 * Workaround for missing cpuid(0) patches when leaf 4 returns Guest CpuIdPatmDef:719 * Workaround for missing cpuid(0) patches when leaf 4 returns GuestInfo.DefCpuId: 721 720 * If we miss to patch a cpuid(0).eax then Linux tries to determine the number 722 721 * of processors from (cpuid(4).eax >> 26) + 1. … … 997 996 */ 998 997 if ( uVersion != CPUM_SAVED_STATE_VERSION 998 && uVersion != CPUM_SAVED_STATE_VERSION_PUT_STRUCT 999 999 && uVersion != CPUM_SAVED_STATE_VERSION_MEM 1000 1000 && uVersion != CPUM_SAVED_STATE_VERSION_NO_MSR_SIZE … … 1180 1180 SSMR3GetMem(pSSM, &pVM->cpum.s.aGuestCpuIdPatmCentaur[0], sizeof(pVM->cpum.s.aGuestCpuIdPatmCentaur)); 1181 1181 1182 SSMR3GetMem(pSSM, &pVM->cpum.s.Guest CpuIdPatmDef, sizeof(pVM->cpum.s.GuestCpuIdPatmDef));1182 SSMR3GetMem(pSSM, &pVM->cpum.s.GuestInfo.DefCpuId, sizeof(pVM->cpum.s.GuestInfo.DefCpuId)); 1183 1183 1184 1184 /* … … 1800 1800 } 1801 1801 1802 1803 /**1804 * Get L1 cache / TLS associativity.1805 */1806 static const char *getCacheAss(unsigned u, char *pszBuf)1807 {1808 if (u == 0)1809 return "res0 ";1810 if (u == 1)1811 return "direct";1812 if (u == 255)1813 return "fully";1814 if (u >= 256)1815 return "???";1816 1817 RTStrPrintf(pszBuf, 16, "%d way", u);1818 return pszBuf;1819 }1820 1821 1822 /**1823 * Get L2 cache associativity.1824 */1825 const char *getL2CacheAss(unsigned u)1826 {1827 switch (u)1828 {1829 case 0: return "off ";1830 case 1: return "direct";1831 case 2: return "2 way ";1832 case 3: return "res3 ";1833 case 4: return "4 way ";1834 case 5: return "res5 ";1835 case 6: return "8 way ";1836 case 7: return "res7 ";1837 case 8: return "16 way";1838 case 9: return "res9 ";1839 case 10: return "res10 ";1840 case 11: return "res11 ";1841 case 12: return "res12 ";1842 case 13: return "res13 ";1843 case 14: return "res14 ";1844 case 15: return "fully ";1845 default: return "????";1846 }1847 }1848 1849 1850 /**1851 * Display the guest CpuId leaves.1852 *1853 * @param pVM Pointer to the VM.1854 * @param pHlp The info helper functions.1855 * @param pszArgs "terse", "default" or "verbose".1856 */1857 static DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs)1858 {1859 /*1860 * Parse the argument.1861 */1862 unsigned iVerbosity = 1;1863 if (pszArgs)1864 {1865 pszArgs = RTStrStripL(pszArgs);1866 if (!strcmp(pszArgs, "terse"))1867 iVerbosity--;1868 else if (!strcmp(pszArgs, "verbose"))1869 iVerbosity++;1870 }1871 1872 /*1873 * Start cracking.1874 */1875 CPUMCPUID Host;1876 CPUMCPUID Guest;1877 unsigned cStdMax = pVM->cpum.s.aGuestCpuIdPatmStd[0].uEax;1878 1879 uint32_t cStdHstMax;1880 uint32_t dummy;1881 ASMCpuIdExSlow(0, 0, 0, 0, &cStdHstMax, &dummy, &dummy, &dummy);1882 1883 unsigned cStdLstMax = RT_MAX(RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmStd), cStdHstMax);1884 1885 pHlp->pfnPrintf(pHlp,1886 " RAW Standard CPUIDs\n"1887 " Function eax ebx ecx edx\n");1888 for (unsigned i = 0; i <= cStdLstMax ; i++)1889 {1890 if (i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmStd))1891 {1892 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[i];1893 ASMCpuIdExSlow(i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);1894 1895 pHlp->pfnPrintf(pHlp,1896 "Gst: %08x %08x %08x %08x %08x%s\n"1897 "Hst: %08x %08x %08x %08x\n",1898 i, Guest.uEax, Guest.uEbx, Guest.uEcx, Guest.uEdx,1899 i <= cStdMax ? "" : "*",1900 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx);1901 }1902 else1903 {1904 ASMCpuIdExSlow(i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);1905 1906 pHlp->pfnPrintf(pHlp,1907 "Hst: %08x %08x %08x %08x %08x\n",1908 i, Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx);1909 }1910 }1911 1912 /*1913 * If verbose, decode it.1914 */1915 if (iVerbosity)1916 {1917 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[0];1918 pHlp->pfnPrintf(pHlp,1919 "Name: %.04s%.04s%.04s\n"1920 "Supports: 0-%x\n",1921 &Guest.uEbx, &Guest.uEdx, &Guest.uEcx, Guest.uEax);1922 }1923 1924 /*1925 * Get Features.1926 */1927 bool const fIntel = ASMIsIntelCpuEx(pVM->cpum.s.aGuestCpuIdPatmStd[0].uEbx,1928 pVM->cpum.s.aGuestCpuIdPatmStd[0].uEcx,1929 pVM->cpum.s.aGuestCpuIdPatmStd[0].uEdx);1930 if (cStdMax >= 1 && iVerbosity)1931 {1932 static const char * const s_apszTypes[4] = { "primary", "overdrive", "MP", "reserved" };1933 1934 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[1];1935 uint32_t uEAX = Guest.uEax;1936 1937 pHlp->pfnPrintf(pHlp,1938 "Family: %d \tExtended: %d \tEffective: %d\n"1939 "Model: %d \tExtended: %d \tEffective: %d\n"1940 "Stepping: %d\n"1941 "Type: %d (%s)\n"1942 "APIC ID: %#04x\n"1943 "Logical CPUs: %d\n"1944 "CLFLUSH Size: %d\n"1945 "Brand ID: %#04x\n",1946 (uEAX >> 8) & 0xf, (uEAX >> 20) & 0x7f, ASMGetCpuFamily(uEAX),1947 (uEAX >> 4) & 0xf, (uEAX >> 16) & 0x0f, ASMGetCpuModel(uEAX, fIntel),1948 ASMGetCpuStepping(uEAX),1949 (uEAX >> 12) & 3, s_apszTypes[(uEAX >> 12) & 3],1950 (Guest.uEbx >> 24) & 0xff,1951 (Guest.uEbx >> 16) & 0xff,1952 (Guest.uEbx >> 8) & 0xff,1953 (Guest.uEbx >> 0) & 0xff);1954 if (iVerbosity == 1)1955 {1956 uint32_t uEDX = Guest.uEdx;1957 pHlp->pfnPrintf(pHlp, "Features EDX: ");1958 if (uEDX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " FPU");1959 if (uEDX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " VME");1960 if (uEDX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " DE");1961 if (uEDX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " PSE");1962 if (uEDX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " TSC");1963 if (uEDX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " MSR");1964 if (uEDX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " PAE");1965 if (uEDX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " MCE");1966 if (uEDX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " CX8");1967 if (uEDX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " APIC");1968 if (uEDX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " 10");1969 if (uEDX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " SEP");1970 if (uEDX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " MTRR");1971 if (uEDX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " PGE");1972 if (uEDX & RT_BIT(14)) pHlp->pfnPrintf(pHlp, " MCA");1973 if (uEDX & RT_BIT(15)) pHlp->pfnPrintf(pHlp, " CMOV");1974 if (uEDX & RT_BIT(16)) pHlp->pfnPrintf(pHlp, " PAT");1975 if (uEDX & RT_BIT(17)) pHlp->pfnPrintf(pHlp, " PSE36");1976 if (uEDX & RT_BIT(18)) pHlp->pfnPrintf(pHlp, " PSN");1977 if (uEDX & RT_BIT(19)) pHlp->pfnPrintf(pHlp, " CLFSH");1978 if (uEDX & RT_BIT(20)) pHlp->pfnPrintf(pHlp, " 20");1979 if (uEDX & RT_BIT(21)) pHlp->pfnPrintf(pHlp, " DS");1980 if (uEDX & RT_BIT(22)) pHlp->pfnPrintf(pHlp, " ACPI");1981 if (uEDX & RT_BIT(23)) pHlp->pfnPrintf(pHlp, " MMX");1982 if (uEDX & RT_BIT(24)) pHlp->pfnPrintf(pHlp, " FXSR");1983 if (uEDX & RT_BIT(25)) pHlp->pfnPrintf(pHlp, " SSE");1984 if (uEDX & RT_BIT(26)) pHlp->pfnPrintf(pHlp, " SSE2");1985 if (uEDX & RT_BIT(27)) pHlp->pfnPrintf(pHlp, " SS");1986 if (uEDX & RT_BIT(28)) pHlp->pfnPrintf(pHlp, " HTT");1987 if (uEDX & RT_BIT(29)) pHlp->pfnPrintf(pHlp, " TM");1988 if (uEDX & RT_BIT(30)) pHlp->pfnPrintf(pHlp, " 30");1989 if (uEDX & RT_BIT(31)) pHlp->pfnPrintf(pHlp, " PBE");1990 pHlp->pfnPrintf(pHlp, "\n");1991 1992 uint32_t uECX = Guest.uEcx;1993 pHlp->pfnPrintf(pHlp, "Features ECX: ");1994 if (uECX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " SSE3");1995 if (uECX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " PCLMUL");1996 if (uECX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " DTES64");1997 if (uECX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " MONITOR");1998 if (uECX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " DS-CPL");1999 if (uECX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " VMX");2000 if (uECX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " SMX");2001 if (uECX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " EST");2002 if (uECX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " TM2");2003 if (uECX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " SSSE3");2004 if (uECX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " CNXT-ID");2005 if (uECX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " 11");2006 if (uECX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " FMA");2007 if (uECX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " CX16");2008 if (uECX & RT_BIT(14)) pHlp->pfnPrintf(pHlp, " TPRUPDATE");2009 if (uECX & RT_BIT(15)) pHlp->pfnPrintf(pHlp, " PDCM");2010 if (uECX & RT_BIT(16)) pHlp->pfnPrintf(pHlp, " 16");2011 if (uECX & RT_BIT(17)) pHlp->pfnPrintf(pHlp, " PCID");2012 if (uECX & RT_BIT(18)) pHlp->pfnPrintf(pHlp, " DCA");2013 if (uECX & RT_BIT(19)) pHlp->pfnPrintf(pHlp, " SSE4.1");2014 if (uECX & RT_BIT(20)) pHlp->pfnPrintf(pHlp, " SSE4.2");2015 if (uECX & RT_BIT(21)) pHlp->pfnPrintf(pHlp, " X2APIC");2016 if (uECX & RT_BIT(22)) pHlp->pfnPrintf(pHlp, " MOVBE");2017 if (uECX & RT_BIT(23)) pHlp->pfnPrintf(pHlp, " POPCNT");2018 if (uECX & RT_BIT(24)) pHlp->pfnPrintf(pHlp, " TSCDEADL");2019 if (uECX & RT_BIT(25)) pHlp->pfnPrintf(pHlp, " AES");2020 if (uECX & RT_BIT(26)) pHlp->pfnPrintf(pHlp, " XSAVE");2021 if (uECX & RT_BIT(27)) pHlp->pfnPrintf(pHlp, " OSXSAVE");2022 if (uECX & RT_BIT(28)) pHlp->pfnPrintf(pHlp, " AVX");2023 if (uECX & RT_BIT(29)) pHlp->pfnPrintf(pHlp, " F16C");2024 if (uECX & RT_BIT(30)) pHlp->pfnPrintf(pHlp, " RDRAND");2025 if (uECX & RT_BIT(31)) pHlp->pfnPrintf(pHlp, " HVP");2026 pHlp->pfnPrintf(pHlp, "\n");2027 }2028 else2029 {2030 ASMCpuIdExSlow(1, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2031 2032 X86CPUIDFEATEDX EdxHost = *(PX86CPUIDFEATEDX)&Host.uEdx;2033 X86CPUIDFEATECX EcxHost = *(PX86CPUIDFEATECX)&Host.uEcx;2034 X86CPUIDFEATEDX EdxGuest = *(PX86CPUIDFEATEDX)&Guest.uEdx;2035 X86CPUIDFEATECX EcxGuest = *(PX86CPUIDFEATECX)&Guest.uEcx;2036 2037 pHlp->pfnPrintf(pHlp, "Mnemonic - Description = guest (host)\n");2038 pHlp->pfnPrintf(pHlp, "FPU - x87 FPU on Chip = %d (%d)\n", EdxGuest.u1FPU, EdxHost.u1FPU);2039 pHlp->pfnPrintf(pHlp, "VME - Virtual 8086 Mode Enhancements = %d (%d)\n", EdxGuest.u1VME, EdxHost.u1VME);2040 pHlp->pfnPrintf(pHlp, "DE - Debugging extensions = %d (%d)\n", EdxGuest.u1DE, EdxHost.u1DE);2041 pHlp->pfnPrintf(pHlp, "PSE - Page Size Extension = %d (%d)\n", EdxGuest.u1PSE, EdxHost.u1PSE);2042 pHlp->pfnPrintf(pHlp, "TSC - Time Stamp Counter = %d (%d)\n", EdxGuest.u1TSC, EdxHost.u1TSC);2043 pHlp->pfnPrintf(pHlp, "MSR - Model Specific Registers = %d (%d)\n", EdxGuest.u1MSR, EdxHost.u1MSR);2044 pHlp->pfnPrintf(pHlp, "PAE - Physical Address Extension = %d (%d)\n", EdxGuest.u1PAE, EdxHost.u1PAE);2045 pHlp->pfnPrintf(pHlp, "MCE - Machine Check Exception = %d (%d)\n", EdxGuest.u1MCE, EdxHost.u1MCE);2046 pHlp->pfnPrintf(pHlp, "CX8 - CMPXCHG8B instruction = %d (%d)\n", EdxGuest.u1CX8, EdxHost.u1CX8);2047 pHlp->pfnPrintf(pHlp, "APIC - APIC On-Chip = %d (%d)\n", EdxGuest.u1APIC, EdxHost.u1APIC);2048 pHlp->pfnPrintf(pHlp, "10 - Reserved = %d (%d)\n", EdxGuest.u1Reserved1, EdxHost.u1Reserved1);2049 pHlp->pfnPrintf(pHlp, "SEP - SYSENTER and SYSEXIT = %d (%d)\n", EdxGuest.u1SEP, EdxHost.u1SEP);2050 pHlp->pfnPrintf(pHlp, "MTRR - Memory Type Range Registers = %d (%d)\n", EdxGuest.u1MTRR, EdxHost.u1MTRR);2051 pHlp->pfnPrintf(pHlp, "PGE - PTE Global Bit = %d (%d)\n", EdxGuest.u1PGE, EdxHost.u1PGE);2052 pHlp->pfnPrintf(pHlp, "MCA - Machine Check Architecture = %d (%d)\n", EdxGuest.u1MCA, EdxHost.u1MCA);2053 pHlp->pfnPrintf(pHlp, "CMOV - Conditional Move Instructions = %d (%d)\n", EdxGuest.u1CMOV, EdxHost.u1CMOV);2054 pHlp->pfnPrintf(pHlp, "PAT - Page Attribute Table = %d (%d)\n", EdxGuest.u1PAT, EdxHost.u1PAT);2055 pHlp->pfnPrintf(pHlp, "PSE-36 - 36-bit Page Size Extention = %d (%d)\n", EdxGuest.u1PSE36, EdxHost.u1PSE36);2056 pHlp->pfnPrintf(pHlp, "PSN - Processor Serial Number = %d (%d)\n", EdxGuest.u1PSN, EdxHost.u1PSN);2057 pHlp->pfnPrintf(pHlp, "CLFSH - CLFLUSH Instruction. = %d (%d)\n", EdxGuest.u1CLFSH, EdxHost.u1CLFSH);2058 pHlp->pfnPrintf(pHlp, "20 - Reserved = %d (%d)\n", EdxGuest.u1Reserved2, EdxHost.u1Reserved2);2059 pHlp->pfnPrintf(pHlp, "DS - Debug Store = %d (%d)\n", EdxGuest.u1DS, EdxHost.u1DS);2060 pHlp->pfnPrintf(pHlp, "ACPI - Thermal Mon. & Soft. Clock Ctrl.= %d (%d)\n", EdxGuest.u1ACPI, EdxHost.u1ACPI);2061 pHlp->pfnPrintf(pHlp, "MMX - Intel MMX Technology = %d (%d)\n", EdxGuest.u1MMX, EdxHost.u1MMX);2062 pHlp->pfnPrintf(pHlp, "FXSR - FXSAVE and FXRSTOR Instructions = %d (%d)\n", EdxGuest.u1FXSR, EdxHost.u1FXSR);2063 pHlp->pfnPrintf(pHlp, "SSE - SSE Support = %d (%d)\n", EdxGuest.u1SSE, EdxHost.u1SSE);2064 pHlp->pfnPrintf(pHlp, "SSE2 - SSE2 Support = %d (%d)\n", EdxGuest.u1SSE2, EdxHost.u1SSE2);2065 pHlp->pfnPrintf(pHlp, "SS - Self Snoop = %d (%d)\n", EdxGuest.u1SS, EdxHost.u1SS);2066 pHlp->pfnPrintf(pHlp, "HTT - Hyper-Threading Technology = %d (%d)\n", EdxGuest.u1HTT, EdxHost.u1HTT);2067 pHlp->pfnPrintf(pHlp, "TM - Thermal Monitor = %d (%d)\n", EdxGuest.u1TM, EdxHost.u1TM);2068 pHlp->pfnPrintf(pHlp, "30 - Reserved = %d (%d)\n", EdxGuest.u1Reserved3, EdxHost.u1Reserved3);2069 pHlp->pfnPrintf(pHlp, "PBE - Pending Break Enable = %d (%d)\n", EdxGuest.u1PBE, EdxHost.u1PBE);2070 2071 pHlp->pfnPrintf(pHlp, "Supports SSE3 = %d (%d)\n", EcxGuest.u1SSE3, EcxHost.u1SSE3);2072 pHlp->pfnPrintf(pHlp, "PCLMULQDQ = %d (%d)\n", EcxGuest.u1PCLMULQDQ, EcxHost.u1PCLMULQDQ);2073 pHlp->pfnPrintf(pHlp, "DS Area 64-bit layout = %d (%d)\n", EcxGuest.u1DTE64, EcxHost.u1DTE64);2074 pHlp->pfnPrintf(pHlp, "Supports MONITOR/MWAIT = %d (%d)\n", EcxGuest.u1Monitor, EcxHost.u1Monitor);2075 pHlp->pfnPrintf(pHlp, "CPL-DS - CPL Qualified Debug Store = %d (%d)\n", EcxGuest.u1CPLDS, EcxHost.u1CPLDS);2076 pHlp->pfnPrintf(pHlp, "VMX - Virtual Machine Technology = %d (%d)\n", EcxGuest.u1VMX, EcxHost.u1VMX);2077 pHlp->pfnPrintf(pHlp, "SMX - Safer Mode Extensions = %d (%d)\n", EcxGuest.u1SMX, EcxHost.u1SMX);2078 pHlp->pfnPrintf(pHlp, "Enhanced SpeedStep Technology = %d (%d)\n", EcxGuest.u1EST, EcxHost.u1EST);2079 pHlp->pfnPrintf(pHlp, "Terminal Monitor 2 = %d (%d)\n", EcxGuest.u1TM2, EcxHost.u1TM2);2080 pHlp->pfnPrintf(pHlp, "Supplemental SSE3 instructions = %d (%d)\n", EcxGuest.u1SSSE3, EcxHost.u1SSSE3);2081 pHlp->pfnPrintf(pHlp, "L1 Context ID = %d (%d)\n", EcxGuest.u1CNTXID, EcxHost.u1CNTXID);2082 pHlp->pfnPrintf(pHlp, "11 - Reserved = %d (%d)\n", EcxGuest.u1Reserved1, EcxHost.u1Reserved1);2083 pHlp->pfnPrintf(pHlp, "FMA extensions using YMM state = %d (%d)\n", EcxGuest.u1FMA, EcxHost.u1FMA);2084 pHlp->pfnPrintf(pHlp, "CMPXCHG16B instruction = %d (%d)\n", EcxGuest.u1CX16, EcxHost.u1CX16);2085 pHlp->pfnPrintf(pHlp, "xTPR Update Control = %d (%d)\n", EcxGuest.u1TPRUpdate, EcxHost.u1TPRUpdate);2086 pHlp->pfnPrintf(pHlp, "Perf/Debug Capability MSR = %d (%d)\n", EcxGuest.u1PDCM, EcxHost.u1PDCM);2087 pHlp->pfnPrintf(pHlp, "16 - Reserved = %d (%d)\n", EcxGuest.u1Reserved2, EcxHost.u1Reserved2);2088 pHlp->pfnPrintf(pHlp, "PCID - Process-context identifiers = %d (%d)\n", EcxGuest.u1PCID, EcxHost.u1PCID);2089 pHlp->pfnPrintf(pHlp, "DCA - Direct Cache Access = %d (%d)\n", EcxGuest.u1DCA, EcxHost.u1DCA);2090 pHlp->pfnPrintf(pHlp, "SSE4.1 instruction extensions = %d (%d)\n", EcxGuest.u1SSE4_1, EcxHost.u1SSE4_1);2091 pHlp->pfnPrintf(pHlp, "SSE4.2 instruction extensions = %d (%d)\n", EcxGuest.u1SSE4_2, EcxHost.u1SSE4_2);2092 pHlp->pfnPrintf(pHlp, "Supports the x2APIC extensions = %d (%d)\n", EcxGuest.u1x2APIC, EcxHost.u1x2APIC);2093 pHlp->pfnPrintf(pHlp, "MOVBE instruction = %d (%d)\n", EcxGuest.u1MOVBE, EcxHost.u1MOVBE);2094 pHlp->pfnPrintf(pHlp, "POPCNT instruction = %d (%d)\n", EcxGuest.u1POPCNT, EcxHost.u1POPCNT);2095 pHlp->pfnPrintf(pHlp, "TSC-Deadline LAPIC timer mode = %d (%d)\n", EcxGuest.u1TSCDEADLINE,EcxHost.u1TSCDEADLINE);2096 pHlp->pfnPrintf(pHlp, "AESNI instruction extensions = %d (%d)\n", EcxGuest.u1AES, EcxHost.u1AES);2097 pHlp->pfnPrintf(pHlp, "XSAVE/XRSTOR extended state feature = %d (%d)\n", EcxGuest.u1XSAVE, EcxHost.u1XSAVE);2098 pHlp->pfnPrintf(pHlp, "Supports OSXSAVE = %d (%d)\n", EcxGuest.u1OSXSAVE, EcxHost.u1OSXSAVE);2099 pHlp->pfnPrintf(pHlp, "AVX instruction extensions = %d (%d)\n", EcxGuest.u1AVX, EcxHost.u1AVX);2100 pHlp->pfnPrintf(pHlp, "16-bit floating point conversion instr = %d (%d)\n", EcxGuest.u1F16C, EcxHost.u1F16C);2101 pHlp->pfnPrintf(pHlp, "RDRAND instruction = %d (%d)\n", EcxGuest.u1RDRAND, EcxHost.u1RDRAND);2102 pHlp->pfnPrintf(pHlp, "Hypervisor Present (we're a guest) = %d (%d)\n", EcxGuest.u1HVP, EcxHost.u1HVP);2103 }2104 }2105 if (cStdMax >= 2 && iVerbosity)2106 {2107 /** @todo */2108 }2109 2110 /*2111 * Extended.2112 * Implemented after AMD specs.2113 */2114 unsigned cExtMax = pVM->cpum.s.aGuestCpuIdPatmExt[0].uEax & 0xffff;2115 2116 pHlp->pfnPrintf(pHlp,2117 "\n"2118 " RAW Extended CPUIDs\n"2119 " Function eax ebx ecx edx\n");2120 bool fSupportsInvariantTsc = false;2121 for (unsigned i = 0; i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmExt); i++)2122 {2123 Guest = pVM->cpum.s.aGuestCpuIdPatmExt[i];2124 ASMCpuIdExSlow(0x80000000 | i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2125 2126 if ( i == 72127 && (Host.uEdx & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR))2128 {2129 fSupportsInvariantTsc = true;2130 }2131 pHlp->pfnPrintf(pHlp,2132 "Gst: %08x %08x %08x %08x %08x%s\n"2133 "Hst: %08x %08x %08x %08x\n",2134 0x80000000 | i, Guest.uEax, Guest.uEbx, Guest.uEcx, Guest.uEdx,2135 i <= cExtMax ? "" : "*",2136 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx);2137 }2138 2139 /*2140 * Understandable output2141 */2142 if (iVerbosity)2143 {2144 Guest = pVM->cpum.s.aGuestCpuIdPatmExt[0];2145 pHlp->pfnPrintf(pHlp,2146 "Ext Name: %.4s%.4s%.4s\n"2147 "Ext Supports: 0x80000000-%#010x\n",2148 &Guest.uEbx, &Guest.uEdx, &Guest.uEcx, Guest.uEax);2149 }2150 2151 if (iVerbosity && cExtMax >= 1)2152 {2153 Guest = pVM->cpum.s.aGuestCpuIdPatmExt[1];2154 uint32_t uEAX = Guest.uEax;2155 pHlp->pfnPrintf(pHlp,2156 "Family: %d \tExtended: %d \tEffective: %d\n"2157 "Model: %d \tExtended: %d \tEffective: %d\n"2158 "Stepping: %d\n"2159 "Brand ID: %#05x\n",2160 (uEAX >> 8) & 0xf, (uEAX >> 20) & 0x7f, ASMGetCpuFamily(uEAX),2161 (uEAX >> 4) & 0xf, (uEAX >> 16) & 0x0f, ASMGetCpuModel(uEAX, fIntel),2162 ASMGetCpuStepping(uEAX),2163 Guest.uEbx & 0xfff);2164 2165 if (iVerbosity == 1)2166 {2167 uint32_t uEDX = Guest.uEdx;2168 pHlp->pfnPrintf(pHlp, "Features EDX: ");2169 if (uEDX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " FPU");2170 if (uEDX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " VME");2171 if (uEDX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " DE");2172 if (uEDX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " PSE");2173 if (uEDX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " TSC");2174 if (uEDX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " MSR");2175 if (uEDX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " PAE");2176 if (uEDX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " MCE");2177 if (uEDX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " CX8");2178 if (uEDX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " APIC");2179 if (uEDX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " 10");2180 if (uEDX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " SCR");2181 if (uEDX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " MTRR");2182 if (uEDX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " PGE");2183 if (uEDX & RT_BIT(14)) pHlp->pfnPrintf(pHlp, " MCA");2184 if (uEDX & RT_BIT(15)) pHlp->pfnPrintf(pHlp, " CMOV");2185 if (uEDX & RT_BIT(16)) pHlp->pfnPrintf(pHlp, " PAT");2186 if (uEDX & RT_BIT(17)) pHlp->pfnPrintf(pHlp, " PSE36");2187 if (uEDX & RT_BIT(18)) pHlp->pfnPrintf(pHlp, " 18");2188 if (uEDX & RT_BIT(19)) pHlp->pfnPrintf(pHlp, " 19");2189 if (uEDX & RT_BIT(20)) pHlp->pfnPrintf(pHlp, " NX");2190 if (uEDX & RT_BIT(21)) pHlp->pfnPrintf(pHlp, " 21");2191 if (uEDX & RT_BIT(22)) pHlp->pfnPrintf(pHlp, " ExtMMX");2192 if (uEDX & RT_BIT(23)) pHlp->pfnPrintf(pHlp, " MMX");2193 if (uEDX & RT_BIT(24)) pHlp->pfnPrintf(pHlp, " FXSR");2194 if (uEDX & RT_BIT(25)) pHlp->pfnPrintf(pHlp, " FastFXSR");2195 if (uEDX & RT_BIT(26)) pHlp->pfnPrintf(pHlp, " Page1GB");2196 if (uEDX & RT_BIT(27)) pHlp->pfnPrintf(pHlp, " RDTSCP");2197 if (uEDX & RT_BIT(28)) pHlp->pfnPrintf(pHlp, " 28");2198 if (uEDX & RT_BIT(29)) pHlp->pfnPrintf(pHlp, " LongMode");2199 if (uEDX & RT_BIT(30)) pHlp->pfnPrintf(pHlp, " Ext3DNow");2200 if (uEDX & RT_BIT(31)) pHlp->pfnPrintf(pHlp, " 3DNow");2201 pHlp->pfnPrintf(pHlp, "\n");2202 2203 uint32_t uECX = Guest.uEcx;2204 pHlp->pfnPrintf(pHlp, "Features ECX: ");2205 if (uECX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " LAHF/SAHF");2206 if (uECX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " CMPL");2207 if (uECX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " SVM");2208 if (uECX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " ExtAPIC");2209 if (uECX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " CR8L");2210 if (uECX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " ABM");2211 if (uECX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " SSE4A");2212 if (uECX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " MISALNSSE");2213 if (uECX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " 3DNOWPRF");2214 if (uECX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " OSVW");2215 if (uECX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " IBS");2216 if (uECX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " SSE5");2217 if (uECX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " SKINIT");2218 if (uECX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " WDT");2219 for (unsigned iBit = 5; iBit < 32; iBit++)2220 if (uECX & RT_BIT(iBit))2221 pHlp->pfnPrintf(pHlp, " %d", iBit);2222 pHlp->pfnPrintf(pHlp, "\n");2223 }2224 else2225 {2226 ASMCpuIdExSlow(0x80000001, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2227 2228 uint32_t uEdxGst = Guest.uEdx;2229 uint32_t uEdxHst = Host.uEdx;2230 pHlp->pfnPrintf(pHlp, "Mnemonic - Description = guest (host)\n");2231 pHlp->pfnPrintf(pHlp, "FPU - x87 FPU on Chip = %d (%d)\n", !!(uEdxGst & RT_BIT( 0)), !!(uEdxHst & RT_BIT( 0)));2232 pHlp->pfnPrintf(pHlp, "VME - Virtual 8086 Mode Enhancements = %d (%d)\n", !!(uEdxGst & RT_BIT( 1)), !!(uEdxHst & RT_BIT( 1)));2233 pHlp->pfnPrintf(pHlp, "DE - Debugging extensions = %d (%d)\n", !!(uEdxGst & RT_BIT( 2)), !!(uEdxHst & RT_BIT( 2)));2234 pHlp->pfnPrintf(pHlp, "PSE - Page Size Extension = %d (%d)\n", !!(uEdxGst & RT_BIT( 3)), !!(uEdxHst & RT_BIT( 3)));2235 pHlp->pfnPrintf(pHlp, "TSC - Time Stamp Counter = %d (%d)\n", !!(uEdxGst & RT_BIT( 4)), !!(uEdxHst & RT_BIT( 4)));2236 pHlp->pfnPrintf(pHlp, "MSR - K86 Model Specific Registers = %d (%d)\n", !!(uEdxGst & RT_BIT( 5)), !!(uEdxHst & RT_BIT( 5)));2237 pHlp->pfnPrintf(pHlp, "PAE - Physical Address Extension = %d (%d)\n", !!(uEdxGst & RT_BIT( 6)), !!(uEdxHst & RT_BIT( 6)));2238 pHlp->pfnPrintf(pHlp, "MCE - Machine Check Exception = %d (%d)\n", !!(uEdxGst & RT_BIT( 7)), !!(uEdxHst & RT_BIT( 7)));2239 pHlp->pfnPrintf(pHlp, "CX8 - CMPXCHG8B instruction = %d (%d)\n", !!(uEdxGst & RT_BIT( 8)), !!(uEdxHst & RT_BIT( 8)));2240 pHlp->pfnPrintf(pHlp, "APIC - APIC On-Chip = %d (%d)\n", !!(uEdxGst & RT_BIT( 9)), !!(uEdxHst & RT_BIT( 9)));2241 pHlp->pfnPrintf(pHlp, "10 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(10)), !!(uEdxHst & RT_BIT(10)));2242 pHlp->pfnPrintf(pHlp, "SEP - SYSCALL and SYSRET = %d (%d)\n", !!(uEdxGst & RT_BIT(11)), !!(uEdxHst & RT_BIT(11)));2243 pHlp->pfnPrintf(pHlp, "MTRR - Memory Type Range Registers = %d (%d)\n", !!(uEdxGst & RT_BIT(12)), !!(uEdxHst & RT_BIT(12)));2244 pHlp->pfnPrintf(pHlp, "PGE - PTE Global Bit = %d (%d)\n", !!(uEdxGst & RT_BIT(13)), !!(uEdxHst & RT_BIT(13)));2245 pHlp->pfnPrintf(pHlp, "MCA - Machine Check Architecture = %d (%d)\n", !!(uEdxGst & RT_BIT(14)), !!(uEdxHst & RT_BIT(14)));2246 pHlp->pfnPrintf(pHlp, "CMOV - Conditional Move Instructions = %d (%d)\n", !!(uEdxGst & RT_BIT(15)), !!(uEdxHst & RT_BIT(15)));2247 pHlp->pfnPrintf(pHlp, "PAT - Page Attribute Table = %d (%d)\n", !!(uEdxGst & RT_BIT(16)), !!(uEdxHst & RT_BIT(16)));2248 pHlp->pfnPrintf(pHlp, "PSE-36 - 36-bit Page Size Extention = %d (%d)\n", !!(uEdxGst & RT_BIT(17)), !!(uEdxHst & RT_BIT(17)));2249 pHlp->pfnPrintf(pHlp, "18 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(18)), !!(uEdxHst & RT_BIT(18)));2250 pHlp->pfnPrintf(pHlp, "19 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(19)), !!(uEdxHst & RT_BIT(19)));2251 pHlp->pfnPrintf(pHlp, "NX - No-Execute Page Protection = %d (%d)\n", !!(uEdxGst & RT_BIT(20)), !!(uEdxHst & RT_BIT(20)));2252 pHlp->pfnPrintf(pHlp, "DS - Debug Store = %d (%d)\n", !!(uEdxGst & RT_BIT(21)), !!(uEdxHst & RT_BIT(21)));2253 pHlp->pfnPrintf(pHlp, "AXMMX - AMD Extensions to MMX Instr. = %d (%d)\n", !!(uEdxGst & RT_BIT(22)), !!(uEdxHst & RT_BIT(22)));2254 pHlp->pfnPrintf(pHlp, "MMX - Intel MMX Technology = %d (%d)\n", !!(uEdxGst & RT_BIT(23)), !!(uEdxHst & RT_BIT(23)));2255 pHlp->pfnPrintf(pHlp, "FXSR - FXSAVE and FXRSTOR Instructions = %d (%d)\n", !!(uEdxGst & RT_BIT(24)), !!(uEdxHst & RT_BIT(24)));2256 pHlp->pfnPrintf(pHlp, "25 - AMD fast FXSAVE and FXRSTOR Instr.= %d (%d)\n", !!(uEdxGst & RT_BIT(25)), !!(uEdxHst & RT_BIT(25)));2257 pHlp->pfnPrintf(pHlp, "26 - 1 GB large page support = %d (%d)\n", !!(uEdxGst & RT_BIT(26)), !!(uEdxHst & RT_BIT(26)));2258 pHlp->pfnPrintf(pHlp, "27 - RDTSCP instruction = %d (%d)\n", !!(uEdxGst & RT_BIT(27)), !!(uEdxHst & RT_BIT(27)));2259 pHlp->pfnPrintf(pHlp, "28 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(28)), !!(uEdxHst & RT_BIT(28)));2260 pHlp->pfnPrintf(pHlp, "29 - AMD Long Mode = %d (%d)\n", !!(uEdxGst & RT_BIT(29)), !!(uEdxHst & RT_BIT(29)));2261 pHlp->pfnPrintf(pHlp, "30 - AMD Extensions to 3DNow! = %d (%d)\n", !!(uEdxGst & RT_BIT(30)), !!(uEdxHst & RT_BIT(30)));2262 pHlp->pfnPrintf(pHlp, "31 - AMD 3DNow! = %d (%d)\n", !!(uEdxGst & RT_BIT(31)), !!(uEdxHst & RT_BIT(31)));2263 2264 uint32_t uEcxGst = Guest.uEcx;2265 uint32_t uEcxHst = Host.uEcx;2266 pHlp->pfnPrintf(pHlp, "LahfSahf - LAHF/SAHF in 64-bit mode = %d (%d)\n", !!(uEcxGst & RT_BIT( 0)), !!(uEcxHst & RT_BIT( 0)));2267 pHlp->pfnPrintf(pHlp, "CmpLegacy - Core MP legacy mode (depr) = %d (%d)\n", !!(uEcxGst & RT_BIT( 1)), !!(uEcxHst & RT_BIT( 1)));2268 pHlp->pfnPrintf(pHlp, "SVM - AMD VM Extensions = %d (%d)\n", !!(uEcxGst & RT_BIT( 2)), !!(uEcxHst & RT_BIT( 2)));2269 pHlp->pfnPrintf(pHlp, "APIC registers starting at 0x400 = %d (%d)\n", !!(uEcxGst & RT_BIT( 3)), !!(uEcxHst & RT_BIT( 3)));2270 pHlp->pfnPrintf(pHlp, "AltMovCR8 - LOCK MOV CR0 means MOV CR8 = %d (%d)\n", !!(uEcxGst & RT_BIT( 4)), !!(uEcxHst & RT_BIT( 4)));2271 pHlp->pfnPrintf(pHlp, "5 - Advanced bit manipulation = %d (%d)\n", !!(uEcxGst & RT_BIT( 5)), !!(uEcxHst & RT_BIT( 5)));2272 pHlp->pfnPrintf(pHlp, "6 - SSE4A instruction support = %d (%d)\n", !!(uEcxGst & RT_BIT( 6)), !!(uEcxHst & RT_BIT( 6)));2273 pHlp->pfnPrintf(pHlp, "7 - Misaligned SSE mode = %d (%d)\n", !!(uEcxGst & RT_BIT( 7)), !!(uEcxHst & RT_BIT( 7)));2274 pHlp->pfnPrintf(pHlp, "8 - PREFETCH and PREFETCHW instruction= %d (%d)\n", !!(uEcxGst & RT_BIT( 8)), !!(uEcxHst & RT_BIT( 8)));2275 pHlp->pfnPrintf(pHlp, "9 - OS visible workaround = %d (%d)\n", !!(uEcxGst & RT_BIT( 9)), !!(uEcxHst & RT_BIT( 9)));2276 pHlp->pfnPrintf(pHlp, "10 - Instruction based sampling = %d (%d)\n", !!(uEcxGst & RT_BIT(10)), !!(uEcxHst & RT_BIT(10)));2277 pHlp->pfnPrintf(pHlp, "11 - SSE5 support = %d (%d)\n", !!(uEcxGst & RT_BIT(11)), !!(uEcxHst & RT_BIT(11)));2278 pHlp->pfnPrintf(pHlp, "12 - SKINIT, STGI, and DEV support = %d (%d)\n", !!(uEcxGst & RT_BIT(12)), !!(uEcxHst & RT_BIT(12)));2279 pHlp->pfnPrintf(pHlp, "13 - Watchdog timer support. = %d (%d)\n", !!(uEcxGst & RT_BIT(13)), !!(uEcxHst & RT_BIT(13)));2280 pHlp->pfnPrintf(pHlp, "31:14 - Reserved = %#x (%#x)\n", uEcxGst >> 14, uEcxHst >> 14);2281 }2282 }2283 2284 if (iVerbosity && cExtMax >= 2)2285 {2286 char szString[4*4*3+1] = {0};2287 uint32_t *pu32 = (uint32_t *)szString;2288 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEax;2289 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEbx;2290 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEcx;2291 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEdx;2292 if (cExtMax >= 3)2293 {2294 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEax;2295 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEbx;2296 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEcx;2297 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEdx;2298 }2299 if (cExtMax >= 4)2300 {2301 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEax;2302 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEbx;2303 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEcx;2304 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEdx;2305 }2306 pHlp->pfnPrintf(pHlp, "Full Name: %s\n", szString);2307 }2308 2309 if (iVerbosity && cExtMax >= 5)2310 {2311 uint32_t uEAX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEax;2312 uint32_t uEBX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEbx;2313 uint32_t uECX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEcx;2314 uint32_t uEDX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEdx;2315 char sz1[32];2316 char sz2[32];2317 2318 pHlp->pfnPrintf(pHlp,2319 "TLB 2/4M Instr/Uni: %s %3d entries\n"2320 "TLB 2/4M Data: %s %3d entries\n",2321 getCacheAss((uEAX >> 8) & 0xff, sz1), (uEAX >> 0) & 0xff,2322 getCacheAss((uEAX >> 24) & 0xff, sz2), (uEAX >> 16) & 0xff);2323 pHlp->pfnPrintf(pHlp,2324 "TLB 4K Instr/Uni: %s %3d entries\n"2325 "TLB 4K Data: %s %3d entries\n",2326 getCacheAss((uEBX >> 8) & 0xff, sz1), (uEBX >> 0) & 0xff,2327 getCacheAss((uEBX >> 24) & 0xff, sz2), (uEBX >> 16) & 0xff);2328 pHlp->pfnPrintf(pHlp, "L1 Instr Cache Line Size: %d bytes\n"2329 "L1 Instr Cache Lines Per Tag: %d\n"2330 "L1 Instr Cache Associativity: %s\n"2331 "L1 Instr Cache Size: %d KB\n",2332 (uEDX >> 0) & 0xff,2333 (uEDX >> 8) & 0xff,2334 getCacheAss((uEDX >> 16) & 0xff, sz1),2335 (uEDX >> 24) & 0xff);2336 pHlp->pfnPrintf(pHlp,2337 "L1 Data Cache Line Size: %d bytes\n"2338 "L1 Data Cache Lines Per Tag: %d\n"2339 "L1 Data Cache Associativity: %s\n"2340 "L1 Data Cache Size: %d KB\n",2341 (uECX >> 0) & 0xff,2342 (uECX >> 8) & 0xff,2343 getCacheAss((uECX >> 16) & 0xff, sz1),2344 (uECX >> 24) & 0xff);2345 }2346 2347 if (iVerbosity && cExtMax >= 6)2348 {2349 uint32_t uEAX = pVM->cpum.s.aGuestCpuIdPatmExt[6].uEax;2350 uint32_t uEBX = pVM->cpum.s.aGuestCpuIdPatmExt[6].uEbx;2351 uint32_t uEDX = pVM->cpum.s.aGuestCpuIdPatmExt[6].uEdx;2352 2353 pHlp->pfnPrintf(pHlp,2354 "L2 TLB 2/4M Instr/Uni: %s %4d entries\n"2355 "L2 TLB 2/4M Data: %s %4d entries\n",2356 getL2CacheAss((uEAX >> 12) & 0xf), (uEAX >> 0) & 0xfff,2357 getL2CacheAss((uEAX >> 28) & 0xf), (uEAX >> 16) & 0xfff);2358 pHlp->pfnPrintf(pHlp,2359 "L2 TLB 4K Instr/Uni: %s %4d entries\n"2360 "L2 TLB 4K Data: %s %4d entries\n",2361 getL2CacheAss((uEBX >> 12) & 0xf), (uEBX >> 0) & 0xfff,2362 getL2CacheAss((uEBX >> 28) & 0xf), (uEBX >> 16) & 0xfff);2363 pHlp->pfnPrintf(pHlp,2364 "L2 Cache Line Size: %d bytes\n"2365 "L2 Cache Lines Per Tag: %d\n"2366 "L2 Cache Associativity: %s\n"2367 "L2 Cache Size: %d KB\n",2368 (uEDX >> 0) & 0xff,2369 (uEDX >> 8) & 0xf,2370 getL2CacheAss((uEDX >> 12) & 0xf),2371 (uEDX >> 16) & 0xffff);2372 }2373 2374 if (iVerbosity && cExtMax >= 7)2375 {2376 uint32_t uEDX = pVM->cpum.s.aGuestCpuIdPatmExt[7].uEdx;2377 2378 pHlp->pfnPrintf(pHlp, "Host Invariant-TSC support: %RTbool\n", fSupportsInvariantTsc);2379 pHlp->pfnPrintf(pHlp, "APM Features: ");2380 if (uEDX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " TS");2381 if (uEDX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " FID");2382 if (uEDX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " VID");2383 if (uEDX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " TTP");2384 if (uEDX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " TM");2385 if (uEDX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " STC");2386 for (unsigned iBit = 6; iBit < 32; iBit++)2387 {2388 if (uEDX & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)2389 pHlp->pfnPrintf(pHlp, " TSCINVARIANT");2390 else if (uEDX & RT_BIT(iBit))2391 pHlp->pfnPrintf(pHlp, " %d", iBit);2392 }2393 pHlp->pfnPrintf(pHlp, "\n");2394 }2395 2396 if (iVerbosity && cExtMax >= 8)2397 {2398 uint32_t uEAX = pVM->cpum.s.aGuestCpuIdPatmExt[8].uEax;2399 uint32_t uECX = pVM->cpum.s.aGuestCpuIdPatmExt[8].uEcx;2400 2401 pHlp->pfnPrintf(pHlp,2402 "Physical Address Width: %d bits\n"2403 "Virtual Address Width: %d bits\n"2404 "Guest Physical Address Width: %d bits\n",2405 (uEAX >> 0) & 0xff,2406 (uEAX >> 8) & 0xff,2407 (uEAX >> 16) & 0xff);2408 pHlp->pfnPrintf(pHlp,2409 "Physical Core Count: %d\n",2410 (uECX >> 0) & 0xff);2411 }2412 2413 2414 /*2415 * Hypervisor leaves.2416 *2417 * Unlike most of the other leaves reported, the guest hypervisor leaves2418 * aren't a subset of the host CPUID bits.2419 */2420 RT_ZERO(Host);2421 if (cStdHstMax >= 1)2422 ASMCpuIdExSlow(1, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2423 bool fHostHvp = RT_BOOL(Host.uEcx & X86_CPUID_FEATURE_ECX_HVP);2424 bool fGuestHvp = false;2425 if (cStdMax >= 1)2426 {2427 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[1];2428 fGuestHvp = RT_BOOL(Guest.uEcx & X86_CPUID_FEATURE_ECX_HVP);2429 }2430 2431 if ( fHostHvp2432 || fGuestHvp)2433 {2434 uint32_t const uHyperLeaf = 0x40000000;2435 pHlp->pfnPrintf(pHlp,2436 "\n"2437 " Hypervisor CPUIDs\n"2438 " Function eax ebx ecx edx\n");2439 2440 PCCPUMCPUIDLEAF pHyperLeafGst = NULL;2441 if (fGuestHvp)2442 {2443 pHyperLeafGst = cpumR3CpuIdGetLeaf(pVM->cpum.s.GuestInfo.paCpuIdLeavesR3, pVM->cpum.s.GuestInfo.cCpuIdLeaves,2444 uHyperLeaf, 0 /* uSubLeaf */);2445 }2446 2447 RT_ZERO(Host);2448 if (fHostHvp)2449 ASMCpuIdExSlow(uHyperLeaf, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2450 2451 CPUMCPUIDLEAF GuestLeaf;2452 uint32_t const cHyperGstMax = pHyperLeafGst ? pHyperLeafGst->uEax : 0;2453 uint32_t const cHyperHstMax = Host.uEax;2454 uint32_t const cHyperMax = RT_MAX(cHyperHstMax, cHyperGstMax);2455 for (uint32_t i = uHyperLeaf; i <= cHyperMax; i++)2456 {2457 RT_ZERO(Host);2458 RT_ZERO(GuestLeaf);2459 if (i <= cHyperHstMax)2460 ASMCpuIdExSlow(i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2461 CPUMR3CpuIdGetLeaf(pVM, &GuestLeaf, i, 0 /* uSubLeaf */);2462 if (!fHostHvp)2463 {2464 pHlp->pfnPrintf(pHlp,2465 "Gst: %08x %08x %08x %08x %08x\n",2466 i, GuestLeaf.uEax, GuestLeaf.uEbx, GuestLeaf.uEcx, GuestLeaf.uEdx);2467 }2468 else2469 {2470 pHlp->pfnPrintf(pHlp,2471 "Gst: %08x %08x %08x %08x %08x%s\n"2472 "Hst: %08x %08x %08x %08x%s\n",2473 i, GuestLeaf.uEax, GuestLeaf.uEbx, GuestLeaf.uEcx, GuestLeaf.uEdx,2474 i <= cHyperGstMax ? "" : "*",2475 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx, i <= cHyperHstMax ? "" : "*");2476 }2477 }2478 }2479 2480 /*2481 * Centaur.2482 */2483 unsigned cCentaurMax = pVM->cpum.s.aGuestCpuIdPatmCentaur[0].uEax & 0xffff;2484 2485 pHlp->pfnPrintf(pHlp,2486 "\n"2487 " RAW Centaur CPUIDs\n"2488 " Function eax ebx ecx edx\n");2489 for (unsigned i = 0; i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmCentaur); i++)2490 {2491 Guest = pVM->cpum.s.aGuestCpuIdPatmCentaur[i];2492 ASMCpuIdExSlow(0xc0000000 | i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2493 2494 pHlp->pfnPrintf(pHlp,2495 "Gst: %08x %08x %08x %08x %08x%s\n"2496 "Hst: %08x %08x %08x %08x\n",2497 0xc0000000 | i, Guest.uEax, Guest.uEbx, Guest.uEcx, Guest.uEdx,2498 i <= cCentaurMax ? "" : "*",2499 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx);2500 }2501 2502 /*2503 * Understandable output2504 */2505 if (iVerbosity)2506 {2507 Guest = pVM->cpum.s.aGuestCpuIdPatmCentaur[0];2508 pHlp->pfnPrintf(pHlp,2509 "Centaur Supports: 0xc0000000-%#010x\n",2510 Guest.uEax);2511 }2512 2513 if (iVerbosity && cCentaurMax >= 1)2514 {2515 ASMCpuIdExSlow(0xc0000001, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx);2516 uint32_t uEdxGst = pVM->cpum.s.aGuestCpuIdPatmCentaur[1].uEdx;2517 uint32_t uEdxHst = Host.uEdx;2518 2519 if (iVerbosity == 1)2520 {2521 pHlp->pfnPrintf(pHlp, "Centaur Features EDX: ");2522 if (uEdxGst & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " AIS");2523 if (uEdxGst & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " AIS-E");2524 if (uEdxGst & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " RNG");2525 if (uEdxGst & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " RNG-E");2526 if (uEdxGst & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " LH");2527 if (uEdxGst & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " FEMMS");2528 if (uEdxGst & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " ACE");2529 if (uEdxGst & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " ACE-E");2530 /* possibly indicating MM/HE and MM/HE-E on older chips... */2531 if (uEdxGst & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " ACE2");2532 if (uEdxGst & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " ACE2-E");2533 if (uEdxGst & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " PHE");2534 if (uEdxGst & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " PHE-E");2535 if (uEdxGst & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " PMM");2536 if (uEdxGst & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " PMM-E");2537 for (unsigned iBit = 14; iBit < 32; iBit++)2538 if (uEdxGst & RT_BIT(iBit))2539 pHlp->pfnPrintf(pHlp, " %d", iBit);2540 pHlp->pfnPrintf(pHlp, "\n");2541 }2542 else2543 {2544 pHlp->pfnPrintf(pHlp, "Mnemonic - Description = guest (host)\n");2545 pHlp->pfnPrintf(pHlp, "AIS - Alternate Instruction Set = %d (%d)\n", !!(uEdxGst & RT_BIT( 0)), !!(uEdxHst & RT_BIT( 0)));2546 pHlp->pfnPrintf(pHlp, "AIS-E - AIS enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 1)), !!(uEdxHst & RT_BIT( 1)));2547 pHlp->pfnPrintf(pHlp, "RNG - Random Number Generator = %d (%d)\n", !!(uEdxGst & RT_BIT( 2)), !!(uEdxHst & RT_BIT( 2)));2548 pHlp->pfnPrintf(pHlp, "RNG-E - RNG enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 3)), !!(uEdxHst & RT_BIT( 3)));2549 pHlp->pfnPrintf(pHlp, "LH - LongHaul MSR 0000_110Ah = %d (%d)\n", !!(uEdxGst & RT_BIT( 4)), !!(uEdxHst & RT_BIT( 4)));2550 pHlp->pfnPrintf(pHlp, "FEMMS - FEMMS = %d (%d)\n", !!(uEdxGst & RT_BIT( 5)), !!(uEdxHst & RT_BIT( 5)));2551 pHlp->pfnPrintf(pHlp, "ACE - Advanced Cryptography Engine = %d (%d)\n", !!(uEdxGst & RT_BIT( 6)), !!(uEdxHst & RT_BIT( 6)));2552 pHlp->pfnPrintf(pHlp, "ACE-E - ACE enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 7)), !!(uEdxHst & RT_BIT( 7)));2553 /* possibly indicating MM/HE and MM/HE-E on older chips... */2554 pHlp->pfnPrintf(pHlp, "ACE2 - Advanced Cryptography Engine 2 = %d (%d)\n", !!(uEdxGst & RT_BIT( 8)), !!(uEdxHst & RT_BIT( 8)));2555 pHlp->pfnPrintf(pHlp, "ACE2-E - ACE enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 9)), !!(uEdxHst & RT_BIT( 9)));2556 pHlp->pfnPrintf(pHlp, "PHE - Padlock Hash Engine = %d (%d)\n", !!(uEdxGst & RT_BIT(10)), !!(uEdxHst & RT_BIT(10)));2557 pHlp->pfnPrintf(pHlp, "PHE-E - PHE enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(11)), !!(uEdxHst & RT_BIT(11)));2558 pHlp->pfnPrintf(pHlp, "PMM - Montgomery Multiplier = %d (%d)\n", !!(uEdxGst & RT_BIT(12)), !!(uEdxHst & RT_BIT(12)));2559 pHlp->pfnPrintf(pHlp, "PMM-E - PMM enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(13)), !!(uEdxHst & RT_BIT(13)));2560 pHlp->pfnPrintf(pHlp, "14 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(14)), !!(uEdxHst & RT_BIT(14)));2561 pHlp->pfnPrintf(pHlp, "15 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(15)), !!(uEdxHst & RT_BIT(15)));2562 pHlp->pfnPrintf(pHlp, "Parallax = %d (%d)\n", !!(uEdxGst & RT_BIT(16)), !!(uEdxHst & RT_BIT(16)));2563 pHlp->pfnPrintf(pHlp, "Parallax enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(17)), !!(uEdxHst & RT_BIT(17)));2564 pHlp->pfnPrintf(pHlp, "Overstress = %d (%d)\n", !!(uEdxGst & RT_BIT(18)), !!(uEdxHst & RT_BIT(18)));2565 pHlp->pfnPrintf(pHlp, "Overstress enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(19)), !!(uEdxHst & RT_BIT(19)));2566 pHlp->pfnPrintf(pHlp, "TM3 - Temperature Monitoring 3 = %d (%d)\n", !!(uEdxGst & RT_BIT(20)), !!(uEdxHst & RT_BIT(20)));2567 pHlp->pfnPrintf(pHlp, "TM3-E - TM3 enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(21)), !!(uEdxHst & RT_BIT(21)));2568 pHlp->pfnPrintf(pHlp, "RNG2 - Random Number Generator 2 = %d (%d)\n", !!(uEdxGst & RT_BIT(22)), !!(uEdxHst & RT_BIT(22)));2569 pHlp->pfnPrintf(pHlp, "RNG2-E - RNG2 enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(23)), !!(uEdxHst & RT_BIT(23)));2570 pHlp->pfnPrintf(pHlp, "24 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(24)), !!(uEdxHst & RT_BIT(24)));2571 pHlp->pfnPrintf(pHlp, "PHE2 - Padlock Hash Engine 2 = %d (%d)\n", !!(uEdxGst & RT_BIT(25)), !!(uEdxHst & RT_BIT(25)));2572 pHlp->pfnPrintf(pHlp, "PHE2-E - PHE2 enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(26)), !!(uEdxHst & RT_BIT(26)));2573 for (unsigned iBit = 27; iBit < 32; iBit++)2574 if ((uEdxGst | uEdxHst) & RT_BIT(iBit))2575 pHlp->pfnPrintf(pHlp, "Bit %d = %d (%d)\n", iBit, !!(uEdxGst & RT_BIT(iBit)), !!(uEdxHst & RT_BIT(iBit)));2576 pHlp->pfnPrintf(pHlp, "\n");2577 }2578 }2579 }2580 2581 2582 1802 /** 2583 1803 * Structure used when disassembling and instructions in DBGF. -
trunk/src/VBox/VMM/VMMR3/CPUMR3CpuId.cpp
r54714 r54737 21 21 #define LOG_GROUP LOG_GROUP_CPUM 22 22 #include <VBox/vmm/cpum.h> 23 #include <VBox/vmm/dbgf.h> 23 24 #include <VBox/vmm/hm.h> 24 25 #include <VBox/vmm/ssm.h> … … 32 33 #include <iprt/mem.h> 33 34 #include <iprt/string.h> 35 36 37 /******************************************************************************* 38 * Defined Constants And Macros * 39 *******************************************************************************/ 40 /** For sanity and avoid wasting hyper heap on buggy config / saved state. */ 41 #define CPUM_CPUID_MAX_LEAVES 2048 34 42 35 43 … … 514 522 * @param uSubLeaf The subleaf to locate. Pass 0 if no subleaves. 515 523 */ 516 PCPUMCPUIDLEAF cpumR3CpuIdGetLeaf(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf)524 static PCPUMCPUIDLEAF cpumR3CpuIdGetLeaf(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf) 517 525 { 518 526 /* Lazy bird does linear lookup here since this is only used for the … … 536 544 * @param pLegacy The legacy output leaf. 537 545 */ 538 bool cpumR3CpuIdGetLeafLegacy(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf, PCPUMCPUID pLegacy) 546 static bool cpumR3CpuIdGetLeafLegacy(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf, 547 PCPUMCPUID pLegacy) 539 548 { 540 549 PCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(paLeaves, cLeaves, uLeaf, uSubLeaf); … … 569 578 static PCPUMCPUIDLEAF cpumR3CpuIdEnsureSpace(PVM pVM, PCPUMCPUIDLEAF *ppaLeaves, uint32_t cLeaves) 570 579 { 580 /* 581 * If pVM is not specified, we're on the regular heap and can waste a 582 * little space to speed things up. 583 */ 571 584 uint32_t cAllocated; 572 585 if (!pVM) 586 { 573 587 cAllocated = RT_ALIGN(cLeaves, 16); 574 else 575 { 576 /* 577 * We're using the hyper heap now, but when the arrays were copied over to it from 578 * the host-context heap, we only copy the exact size and not the ensured size. 579 * See @bugref{7270}. 580 */ 581 cAllocated = cLeaves; 582 } 583 584 if (cLeaves + 1 > cAllocated) 585 { 586 void *pvNew; 587 #ifndef IN_VBOX_CPU_REPORT 588 if (pVM) 589 { 590 Assert(ppaLeaves == &pVM->cpum.s.GuestInfo.paCpuIdLeavesR3); 591 Assert(cLeaves == pVM->cpum.s.GuestInfo.cCpuIdLeaves); 592 593 size_t cb = cAllocated * sizeof(**ppaLeaves); 594 size_t cbNew = (cAllocated + 16) * sizeof(**ppaLeaves); 595 int rc = MMR3HyperRealloc(pVM, *ppaLeaves, cb, 32, MM_TAG_CPUM_CPUID, cbNew, &pvNew); 596 if (RT_FAILURE(rc)) 597 { 598 *ppaLeaves = NULL; 599 pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = NIL_RTR0PTR; 600 pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = NIL_RTRCPTR; 601 LogRel(("CPUM: cpumR3CpuIdEnsureSpace: MMR3HyperRealloc failed. rc=%Rrc\n", rc)); 602 return NULL; 603 } 604 *ppaLeaves = (PCPUMCPUIDLEAF)pvNew; 605 } 606 else 607 #endif 608 { 609 pvNew = RTMemRealloc(*ppaLeaves, (cAllocated + 16) * sizeof(**ppaLeaves)); 610 if (!pvNew) 588 if (cLeaves + 1 > cAllocated) 589 { 590 void *pvNew = RTMemRealloc(*ppaLeaves, (cAllocated + 16) * sizeof(**ppaLeaves)); 591 if (pvNew) 592 *ppaLeaves = (PCPUMCPUIDLEAF)pvNew; 593 else 611 594 { 612 595 RTMemFree(*ppaLeaves); 613 596 *ppaLeaves = NULL; 614 return NULL;615 597 } 616 *ppaLeaves = (PCPUMCPUIDLEAF)pvNew; 617 } 618 } 619 620 #ifndef IN_VBOX_CPU_REPORT 621 /* Update the R0 and RC pointers. */ 622 if (pVM) 623 { 598 } 599 } 600 /* 601 * Otherwise, we're on the hyper heap and are probably just inserting 602 * one or two leaves and should conserve space. 603 */ 604 else 605 { 606 #ifdef IN_VBOX_CPU_REPORT 607 AssertReleaseFailed(); 608 #else 624 609 Assert(ppaLeaves == &pVM->cpum.s.GuestInfo.paCpuIdLeavesR3); 625 pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = MMHyperR3ToR0(pVM, *ppaLeaves); 626 pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, *ppaLeaves); 627 } 610 Assert(cLeaves == pVM->cpum.s.GuestInfo.cCpuIdLeaves); 611 612 size_t cb = cLeaves * sizeof(**ppaLeaves); 613 size_t cbNew = (cLeaves + 1) * sizeof(**ppaLeaves); 614 int rc = MMR3HyperRealloc(pVM, *ppaLeaves, cb, 32, MM_TAG_CPUM_CPUID, cbNew, (void **)ppaLeaves); 615 if (RT_SUCCESS(rc)) 616 { 617 /* Update the R0 and RC pointers. */ 618 pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = MMHyperR3ToR0(pVM, *ppaLeaves); 619 pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, *ppaLeaves); 620 } 621 else 622 { 623 *ppaLeaves = NULL; 624 pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = NIL_RTR0PTR; 625 pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = NIL_RTRCPTR; 626 LogRel(("CPUM: cpumR3CpuIdEnsureSpace: MMR3HyperRealloc failed. rc=%Rrc\n", rc)); 627 } 628 628 #endif 629 629 } 630 630 return *ppaLeaves; 631 631 } … … 700 700 * insert. 701 701 */ 702 int cpumR3CpuIdInsert(PVM pVM, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves, PCPUMCPUIDLEAF pNewLeaf)702 static int cpumR3CpuIdInsert(PVM pVM, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves, PCPUMCPUIDLEAF pNewLeaf) 703 703 { 704 704 /* … … 720 720 * Validate the new leaf a little. 721 721 */ 722 AssertReturn(!(pNewLeaf->fFlags & ~CPUMCPUIDLEAF_F_ SUBLEAVES_ECX_UNCHANGED), VERR_INVALID_FLAGS);722 AssertReturn(!(pNewLeaf->fFlags & ~CPUMCPUIDLEAF_F_VALID_MASK), VERR_INVALID_FLAGS); 723 723 AssertReturn(pNewLeaf->fSubLeafMask != 0 || pNewLeaf->uSubLeaf == 0, VERR_INVALID_PARAMETER); 724 724 AssertReturn(RT_IS_POWER_OF_TWO(pNewLeaf->fSubLeafMask + 1), VERR_INVALID_PARAMETER); … … 726 726 727 727 /* 728 * Find insertion point. The lazy bird uses the same excuse as in 729 * cpumR3CpuIdGetLeaf(). 730 */ 731 uint32_t i = 0; 732 while ( i < cLeaves 733 && paLeaves[i].uLeaf < pNewLeaf->uLeaf) 734 i++; 728 * Find insertion point. The lazy bird uses the same excuse as in 729 * cpumR3CpuIdGetLeaf(), but optimizes for linear insertion (saved state). 730 */ 731 uint32_t i; 732 if ( cLeaves > 0 733 && paLeaves[cLeaves - 1].uLeaf < pNewLeaf->uLeaf) 734 { 735 /* Add at end. */ 736 i = cLeaves; 737 } 738 else if ( cLeaves > 0 739 && paLeaves[cLeaves - 1].uLeaf == pNewLeaf->uLeaf) 740 { 741 /* Either replacing the last leaf or dealing with sub-leaves. Spool 742 back to the first sub-leaf to pretend we did the linear search. */ 743 i = cLeaves - 1; 744 while ( i > 0 745 && paLeaves[i - 1].uLeaf == pNewLeaf->uLeaf) 746 i--; 747 } 748 else 749 { 750 /* Linear search from the start. */ 751 i = 0; 752 while ( i < cLeaves 753 && paLeaves[i].uLeaf < pNewLeaf->uLeaf) 754 i++; 755 } 735 756 if ( i < cLeaves 736 757 && paLeaves[i].uLeaf == pNewLeaf->uLeaf) … … 739 760 { 740 761 /* 741 * The sub leaf mask differs, replace all existing leaves with the762 * The sub-leaf mask differs, replace all existing leaves with the 742 763 * same leaf number. 743 764 */ 744 765 uint32_t c = 1; 745 766 while ( i + c < cLeaves 746 && paLeaves[i + c].u SubLeaf == pNewLeaf->uLeaf)767 && paLeaves[i + c].uLeaf == pNewLeaf->uLeaf) 747 768 c++; 748 769 if (c > 1 && i + c < cLeaves) … … 756 777 } 757 778 758 /* Find sub leaf insertion point. */779 /* Find sub-leaf insertion point. */ 759 780 while ( i < cLeaves 760 781 && paLeaves[i].uSubLeaf < pNewLeaf->uSubLeaf) … … 775 796 * Adding a new leaf at 'i'. 776 797 */ 798 AssertLogRelReturn(cLeaves < CPUM_CPUID_MAX_LEAVES, VERR_TOO_MANY_CPUID_LEAVES); 777 799 paLeaves = cpumR3CpuIdEnsureSpace(pVM, ppaLeaves, cLeaves); 778 800 if (!paLeaves) … … 797 819 * @param uLast The last leaf. 798 820 */ 799 void cpumR3CpuIdRemoveRange(PCPUMCPUIDLEAF paLeaves, uint32_t *pcLeaves, uint32_t uFirst, uint32_t uLast)821 static void cpumR3CpuIdRemoveRange(PCPUMCPUIDLEAF paLeaves, uint32_t *pcLeaves, uint32_t uFirst, uint32_t uLast) 800 822 { 801 823 uint32_t cLeaves = *pcLeaves; … … 839 861 * @param pcSubLeaves Number of sub-leaves accessible via ECX. 840 862 * @param pfFinalEcxUnchanged Whether ECX is passed thru when going beyond the 841 * final sub-leaf .863 * final sub-leaf (for leaf 0xb only). 842 864 */ 843 865 static bool cpumR3IsEcxRelevantForCpuIdLeaf(uint32_t uLeaf, uint32_t *pcSubLeaves, bool *pfFinalEcxUnchanged) … … 919 941 if (cDocLimit != UINT32_MAX) 920 942 { 921 *pfFinalEcxUnchanged = auCur[2] == uSubLeaf ;943 *pfFinalEcxUnchanged = auCur[2] == uSubLeaf && uLeaf == 0xb; 922 944 *pcSubLeaves = cDocLimit + 3; 923 945 return true; … … 934 956 935 957 /* Standard exit. */ 936 *pfFinalEcxUnchanged = auCur[2] == uSubLeaf ;958 *pfFinalEcxUnchanged = auCur[2] == uSubLeaf && uLeaf == 0xb; 937 959 *pcSubLeaves = uSubLeaf + 1 - cRepeats; 938 960 return true; … … 984 1006 */ 985 1007 if ( pNewLeaf->uLeaf == UINT32_C(0x00000000) /* Standard */ 1008 || pNewLeaf->uLeaf == UINT32_C(0x00000001) 986 1009 || pNewLeaf->uLeaf == UINT32_C(0x80000000) /* Extended */ 987 || pNewLeaf->uLeaf == UINT32_C(0xc0000000)) /* Centaur */ 1010 || pNewLeaf->uLeaf == UINT32_C(0x80000001) 1011 || pNewLeaf->uLeaf == UINT32_C(0xc0000000) /* Centaur */ 1012 || pNewLeaf->uLeaf == UINT32_C(0xc0000001) ) 988 1013 { 989 1014 return VERR_NOT_SUPPORTED; … … 1049 1074 while (cLeaves-- > 0) 1050 1075 { 1076 ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx); 1077 1078 uint32_t fFlags = 0; 1079 1080 /* There are currently three known leaves containing an APIC ID 1081 that needs EMT specific attention */ 1082 if (uLeaf == 1) 1083 fFlags |= CPUMCPUIDLEAF_F_CONTAINS_APIC_ID; 1084 else if (uLeaf == 0xb && uEcx != 0) 1085 fFlags |= CPUMCPUIDLEAF_F_CONTAINS_APIC_ID; 1086 else if ( uLeaf == UINT32_C(0x8000001e) 1087 && ( uEax 1088 || uEbx 1089 || uEdx 1090 || ASMIsAmdCpuEx((*ppaLeaves)[0].uEbx, (*ppaLeaves)[0].uEcx, (*ppaLeaves)[0].uEdx)) ) 1091 fFlags |= CPUMCPUIDLEAF_F_CONTAINS_APIC_ID; 1092 1093 1051 1094 /* Check three times here to reduce the chance of CPU migration 1052 1095 resulting in false positives with things like the APIC ID. */ … … 1079 1122 } 1080 1123 1124 if (fFinalEcxUnchanged) 1125 fFlags |= CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES; 1126 1081 1127 for (uint32_t uSubLeaf = 0; uSubLeaf < cSubLeaves; uSubLeaf++) 1082 1128 { 1083 1129 ASMCpuIdExSlow(uLeaf, 0, uSubLeaf, 0, &uEax, &uEbx, &uEcx, &uEdx); 1084 1130 int rc = cpumR3CollectCpuIdInfoAddOne(ppaLeaves, pcLeaves, 1085 uLeaf, uSubLeaf, UINT32_MAX, uEax, uEbx, uEcx, uEdx, 1086 uSubLeaf + 1 == cSubLeaves && fFinalEcxUnchanged 1087 ? CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED : 0); 1131 uLeaf, uSubLeaf, UINT32_MAX, uEax, uEbx, uEcx, uEdx, fFlags); 1088 1132 if (RT_FAILURE(rc)) 1089 1133 return rc; … … 1092 1136 else 1093 1137 { 1094 ASMCpuIdExSlow(uLeaf, 0, 0, 0, &uEax, &uEbx, &uEcx, &uEdx);1095 1138 int rc = cpumR3CollectCpuIdInfoAddOne(ppaLeaves, pcLeaves, 1096 uLeaf, 0, 0, uEax, uEbx, uEcx, uEdx, 0);1139 uLeaf, 0, 0, uEax, uEbx, uEcx, uEdx, fFlags); 1097 1140 if (RT_FAILURE(rc)) 1098 1141 return rc; … … 1153 1196 * doesn't actually needs it. 1154 1197 */ 1155 VMMR3DECL(int) CPUMR3CpuIdDetectUnknownLeafMethod(PCPUMU KNOWNCPUID penmUnknownMethod, PCPUMCPUID pDefUnknown)1198 VMMR3DECL(int) CPUMR3CpuIdDetectUnknownLeafMethod(PCPUMUNKNOWNCPUID penmUnknownMethod, PCPUMCPUID pDefUnknown) 1156 1199 { 1157 1200 uint32_t uLastStd = ASMCpuId_EAX(0); … … 1194 1237 * Simple method, all zeros. 1195 1238 */ 1196 *penmUnknownMethod = CPUMU KNOWNCPUID_DEFAULTS;1239 *penmUnknownMethod = CPUMUNKNOWNCPUID_DEFAULTS; 1197 1240 pDefUnknown->uEax = 0; 1198 1241 pDefUnknown->uEbx = 0; … … 1253 1296 Log(("CPUM: cNeither=%d cSame=%d cLastWithEcx=%d cTotal=%d\n", cNeither, cSame, cLastWithEcx, cTotal)); 1254 1297 if (cSame == cTotal) 1255 *penmUnknownMethod = CPUMU KNOWNCPUID_LAST_STD_LEAF;1298 *penmUnknownMethod = CPUMUNKNOWNCPUID_LAST_STD_LEAF; 1256 1299 else if (cLastWithEcx == cTotal) 1257 *penmUnknownMethod = CPUMU KNOWNCPUID_LAST_STD_LEAF_WITH_ECX;1300 *penmUnknownMethod = CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX; 1258 1301 else 1259 *penmUnknownMethod = CPUMU KNOWNCPUID_LAST_STD_LEAF;1302 *penmUnknownMethod = CPUMUNKNOWNCPUID_LAST_STD_LEAF; 1260 1303 pDefUnknown->uEax = auLast[0]; 1261 1304 pDefUnknown->uEbx = auLast[1]; … … 1291 1334 if (cChecks == 0) 1292 1335 { 1293 *penmUnknownMethod = CPUMU KNOWNCPUID_PASSTHRU;1336 *penmUnknownMethod = CPUMUNKNOWNCPUID_PASSTHRU; 1294 1337 return VINF_SUCCESS; 1295 1338 } … … 1308 1351 * @param enmUnknownMethod The method to translate. 1309 1352 */ 1310 VMMR3DECL(const char *) CPUMR3CpuIdUnknownLeafMethodName(CPUMU KNOWNCPUID enmUnknownMethod)1353 VMMR3DECL(const char *) CPUMR3CpuIdUnknownLeafMethodName(CPUMUNKNOWNCPUID enmUnknownMethod) 1311 1354 { 1312 1355 switch (enmUnknownMethod) 1313 1356 { 1314 case CPUMU KNOWNCPUID_DEFAULTS: return "DEFAULTS";1315 case CPUMU KNOWNCPUID_LAST_STD_LEAF: return "LAST_STD_LEAF";1316 case CPUMU KNOWNCPUID_LAST_STD_LEAF_WITH_ECX: return "LAST_STD_LEAF_WITH_ECX";1317 case CPUMU KNOWNCPUID_PASSTHRU: return "PASSTHRU";1318 1319 case CPUMU KNOWNCPUID_INVALID:1320 case CPUMU KNOWNCPUID_END:1321 case CPUMU KNOWNCPUID_32BIT_HACK:1357 case CPUMUNKNOWNCPUID_DEFAULTS: return "DEFAULTS"; 1358 case CPUMUNKNOWNCPUID_LAST_STD_LEAF: return "LAST_STD_LEAF"; 1359 case CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX: return "LAST_STD_LEAF_WITH_ECX"; 1360 case CPUMUNKNOWNCPUID_PASSTHRU: return "PASSTHRU"; 1361 1362 case CPUMUNKNOWNCPUID_INVALID: 1363 case CPUMUNKNOWNCPUID_END: 1364 case CPUMUNKNOWNCPUID_32BIT_HACK: 1322 1365 break; 1323 1366 } … … 1500 1543 #ifdef VBOX_IN_VMM 1501 1544 1545 1546 /** 1547 * Gets an exactly matching leaf + sub-leaf in the CPUID leaf array. 1548 * 1549 * This ignores the fSubLeafMask. 1550 * 1551 * @returns Pointer to the matching leaf, or NULL if not found. 1552 * @param paLeaves The CPUID leaves to search. This is sorted. 1553 * @param cLeaves The number of leaves in the array. 1554 * @param uLeaf The leaf to locate. 1555 * @param uSubLeaf The subleaf to locate. 1556 */ 1557 static PCPUMCPUIDLEAF cpumR3CpuIdGetExactLeaf(PCPUM pCpum, uint32_t uLeaf, uint32_t uSubLeaf) 1558 { 1559 uint64_t uNeedle = RT_MAKE_U64(uSubLeaf, uLeaf); 1560 PCPUMCPUIDLEAF paLeaves = pCpum->GuestInfo.paCpuIdLeavesR3; 1561 uint32_t iEnd = pCpum->GuestInfo.cCpuIdLeaves; 1562 if (iEnd) 1563 { 1564 uint32_t iBegin = 0; 1565 for (;;) 1566 { 1567 uint32_t const i = (iEnd - iBegin) / 2 + iBegin; 1568 uint64_t const uCur = RT_MAKE_U64(paLeaves[i].uSubLeaf, paLeaves[i].uLeaf); 1569 if (uNeedle < uCur) 1570 { 1571 if (i > iBegin) 1572 iEnd = i; 1573 else 1574 break; 1575 } 1576 else if (uNeedle > uCur) 1577 { 1578 if (i + 1 < iEnd) 1579 iBegin = i + 1; 1580 else 1581 break; 1582 } 1583 else 1584 return &paLeaves[i]; 1585 } 1586 } 1587 return NULL; 1588 } 1589 1590 1502 1591 /** 1503 1592 * Loads MSR range overrides. … … 1632 1721 * register, without needing to know the other values. 1633 1722 */ 1634 PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(pVM->cpum.s.GuestInfo.paCpuIdLeavesR3, pVM->cpum.s.GuestInfo.cCpuIdLeaves, 1635 uLeaf, uSubLeaf); 1723 PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetExactLeaf(&pVM->cpum.s, uLeaf, uSubLeaf); 1636 1724 CPUMCPUIDLEAF Leaf; 1637 1725 if (pLeaf) … … 1761 1849 1762 1850 1763 static int cpumR3CpuIdInstallAndExplodeLeaves(PVM pVM, PCPUM pC PUM, PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves)1851 static int cpumR3CpuIdInstallAndExplodeLeaves(PVM pVM, PCPUM pCpum, PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves) 1764 1852 { 1765 1853 /* … … 1767 1855 */ 1768 1856 int rc = MMHyperDupMem(pVM, paLeaves, sizeof(paLeaves[0]) * cLeaves, 32, 1769 MM_TAG_CPUM_CPUID, (void **)&pC PUM->GuestInfo.paCpuIdLeavesR3);1857 MM_TAG_CPUM_CPUID, (void **)&pCpum->GuestInfo.paCpuIdLeavesR3); 1770 1858 1771 1859 AssertLogRelRCReturn(rc, rc); 1772 1860 1773 1861 1774 pCPUM->GuestInfo.paCpuIdLeavesR0 = MMHyperR3ToR0(pVM, pCPUM->GuestInfo.paCpuIdLeavesR3); 1775 pCPUM->GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, pCPUM->GuestInfo.paCpuIdLeavesR3); 1776 Assert(MMHyperR0ToR3(pVM, pCPUM->GuestInfo.paCpuIdLeavesR0) == (void *)pCPUM->GuestInfo.paCpuIdLeavesR3); 1777 Assert(MMHyperRCToR3(pVM, pCPUM->GuestInfo.paCpuIdLeavesRC) == (void *)pCPUM->GuestInfo.paCpuIdLeavesR3); 1862 pCpum->GuestInfo.paCpuIdLeavesR0 = MMHyperR3ToR0(pVM, pCpum->GuestInfo.paCpuIdLeavesR3); 1863 pCpum->GuestInfo.paCpuIdLeavesRC = MMHyperR3ToRC(pVM, pCpum->GuestInfo.paCpuIdLeavesR3); 1864 Assert(MMHyperR0ToR3(pVM, pCpum->GuestInfo.paCpuIdLeavesR0) == (void *)pCpum->GuestInfo.paCpuIdLeavesR3); 1865 Assert(MMHyperRCToR3(pVM, pCpum->GuestInfo.paCpuIdLeavesRC) == (void *)pCpum->GuestInfo.paCpuIdLeavesR3); 1866 1867 /* 1868 * Update the default CPUID leaf if necessary. 1869 */ 1870 switch (pCpum->GuestInfo.enmUnknownCpuIdMethod) 1871 { 1872 case CPUMUNKNOWNCPUID_LAST_STD_LEAF: 1873 case CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX: 1874 { 1875 /* We don't use CPUID(0).eax here because of the NT hack that only 1876 changes that value without actually removing any leaves. */ 1877 uint32_t i = 0; 1878 if ( pCpum->GuestInfo.cCpuIdLeaves > 0 1879 && pCpum->GuestInfo.paCpuIdLeavesR3[0].uEax <= UINT32_C(0xff)) 1880 { 1881 while ( i + 1 < pCpum->GuestInfo.cCpuIdLeaves 1882 && pCpum->GuestInfo.paCpuIdLeavesR3[i + 1].uEax <= UINT32_C(0xff)) 1883 i++; 1884 pCpum->GuestInfo.DefCpuId.uEax = pCpum->GuestInfo.paCpuIdLeavesR3[i].uEax; 1885 pCpum->GuestInfo.DefCpuId.uEbx = pCpum->GuestInfo.paCpuIdLeavesR3[i].uEbx; 1886 pCpum->GuestInfo.DefCpuId.uEcx = pCpum->GuestInfo.paCpuIdLeavesR3[i].uEcx; 1887 pCpum->GuestInfo.DefCpuId.uEdx = pCpum->GuestInfo.paCpuIdLeavesR3[i].uEdx; 1888 } 1889 break; 1890 } 1891 default: 1892 break; 1893 } 1778 1894 1779 1895 /* 1780 1896 * Explode the guest CPU features. 1781 1897 */ 1782 rc = cpumR3CpuIdExplodeFeatures(pC PUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, &pCPUM->GuestFeatures);1898 rc = cpumR3CpuIdExplodeFeatures(pCpum->GuestInfo.paCpuIdLeavesR3, pCpum->GuestInfo.cCpuIdLeaves, &pCpum->GuestFeatures); 1783 1899 AssertLogRelRCReturn(rc, rc); 1784 1900 … … 1788 1904 */ 1789 1905 if (CPUMMICROARCH_IS_INTEL_CORE7(pVM->cpum.s.GuestFeatures.enmMicroarch)) 1790 pC PUM->GuestInfo.uScalableBusFreq = pCPUM->GuestFeatures.enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge1906 pCpum->GuestInfo.uScalableBusFreq = pCpum->GuestFeatures.enmMicroarch >= kCpumMicroarch_Intel_Core7_SandyBridge 1791 1907 ? UINT64_C(100000000) /* 100MHz */ 1792 1908 : UINT64_C(133333333); /* 133MHz */ … … 1798 1914 struct { PCPUMCPUID paCpuIds; uint32_t cCpuIds, uBase; } aOldRanges[] = 1799 1915 { 1800 { pC PUM->aGuestCpuIdPatmStd, RT_ELEMENTS(pCPUM->aGuestCpuIdPatmStd), 0x00000000 },1801 { pC PUM->aGuestCpuIdPatmExt, RT_ELEMENTS(pCPUM->aGuestCpuIdPatmExt), 0x80000000 },1802 { pC PUM->aGuestCpuIdPatmCentaur, RT_ELEMENTS(pCPUM->aGuestCpuIdPatmCentaur), 0xc0000000 },1916 { pCpum->aGuestCpuIdPatmStd, RT_ELEMENTS(pCpum->aGuestCpuIdPatmStd), 0x00000000 }, 1917 { pCpum->aGuestCpuIdPatmExt, RT_ELEMENTS(pCpum->aGuestCpuIdPatmExt), 0x80000000 }, 1918 { pCpum->aGuestCpuIdPatmCentaur, RT_ELEMENTS(pCpum->aGuestCpuIdPatmCentaur), 0xc0000000 }, 1803 1919 }; 1804 1920 for (uint32_t i = 0; i < RT_ELEMENTS(aOldRanges); i++) … … 1812 1928 pLegacyLeaf--; 1813 1929 1814 PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, uLeaf, 1815 0 /* uSubLeaf */); 1930 PCCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetExactLeaf(pCpum, uLeaf, 0 /* uSubLeaf */); 1816 1931 if (pLeaf) 1817 1932 { … … 1822 1937 } 1823 1938 else 1824 *pLegacyLeaf = pCPUM->GuestInfo.DefCpuId; 1825 } 1826 } 1827 1828 pCPUM->GuestCpuIdPatmDef = pCPUM->GuestInfo.DefCpuId; 1939 *pLegacyLeaf = pCpum->GuestInfo.DefCpuId; 1940 } 1941 } 1829 1942 1830 1943 return VINF_SUCCESS; … … 1833 1946 1834 1947 /** 1835 * Initializes the emulated CPU's cpuid information. 1948 * CPUID Configuration (from CFGM). 1949 * 1950 * @remarks The members aren't document since we would only be duplicating the 1951 * \@cfgm entries in cpumR3CpuIdReadConfig. 1952 */ 1953 typedef struct CPUMCPUIDCONFIG 1954 { 1955 bool fSyntheticCpu; 1956 bool fCmpXchg16b; 1957 bool fMonitor; 1958 bool fMWaitExtensions; 1959 bool fSse41; 1960 bool fSse42; 1961 bool fNt4LeafLimit; 1962 bool fInvariantTsc; 1963 uint32_t uMaxIntelFamilyModelStep; 1964 char szCpuName[128]; 1965 } CPUMCPUIDCONFIG; 1966 /** Pointer to CPUID config (from CFGM). */ 1967 typedef CPUMCPUIDCONFIG *PCPUMCPUIDCONFIG; 1968 1969 1970 /** 1971 * Insert hypervisor identification leaves. 1972 * 1973 * We only return minimal information, primarily ensuring that the 1974 * 0x40000000 function returns 0x40000001 and identifying ourselves. 1975 * Hypervisor-specific interface is supported through GIM which will 1976 * modify these leaves if required depending on the GIM provider. 1836 1977 * 1837 1978 * @returns VBox status code. 1838 * @param pVM Pointer to the VM. 1839 */ 1840 int cpumR3CpuIdInit(PVM pVM) 1979 * @param pCpum The CPUM instance data. 1980 * @param pConfig The CPUID configuration we've read from CFGM. 1981 */ 1982 static int cpumR3CpuIdPlantHypervisorLeaves(PCPUM pCpum, PCPUMCPUIDCONFIG pConfig) 1841 1983 { 1842 PCPUM pCPUM = &pVM->cpum.s; 1843 PCFGMNODE pCpumCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM"); 1844 int rc; 1845 1984 CPUMCPUIDLEAF NewLeaf; 1985 NewLeaf.uLeaf = UINT32_C(0x40000000); 1986 NewLeaf.uSubLeaf = 0; 1987 NewLeaf.fSubLeafMask = 0; 1988 NewLeaf.uEax = UINT32_C(0x40000001); 1989 NewLeaf.uEbx = 0x786f4256 /* 'VBox' */; 1990 NewLeaf.uEcx = 0x786f4256 /* 'VBox' */; 1991 NewLeaf.uEdx = 0x786f4256 /* 'VBox' */; 1992 NewLeaf.fFlags = 0; 1993 int rc = cpumR3CpuIdInsert(NULL /* pVM */, &pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, &NewLeaf); 1994 AssertLogRelRCReturn(rc, rc); 1995 1996 NewLeaf.uLeaf = UINT32_C(0x40000001); 1997 NewLeaf.uEax = 0x656e6f6e; /* 'none' */ 1998 NewLeaf.uEbx = 0; 1999 NewLeaf.uEcx = 0; 2000 NewLeaf.uEdx = 0; 2001 NewLeaf.fFlags = 0; 2002 rc = cpumR3CpuIdInsert(NULL /* pVM */, &pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, &NewLeaf); 2003 AssertLogRelRCReturn(rc, rc); 2004 2005 return VINF_SUCCESS; 2006 } 2007 2008 2009 /** 2010 * Mini CPU selection support for making Mac OS X happy. 2011 * 2012 * Executes the /CPUM/MaxIntelFamilyModelStep config. 2013 * 2014 * @param pCpum The CPUM instance data. 2015 * @param pConfig The CPUID configuration we've read from CFGM. 2016 */ 2017 static void cpumR3CpuIdLimitIntelFamModStep(PCPUM pCpum, PCPUMCPUIDCONFIG pConfig) 2018 { 2019 if (pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL) 2020 { 2021 PCPUMCPUIDLEAF pStdFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 1, 0); 2022 uint32_t uCurIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(ASMGetCpuStepping(pStdFeatureLeaf->uEax), 2023 ASMGetCpuModelIntel(pStdFeatureLeaf->uEax), 2024 ASMGetCpuFamily(pStdFeatureLeaf->uEax), 2025 0); 2026 uint32_t uMaxIntelFamilyModelStep = pConfig->uMaxIntelFamilyModelStep; 2027 if (pConfig->uMaxIntelFamilyModelStep < uCurIntelFamilyModelStep) 2028 { 2029 uint32_t uNew = pStdFeatureLeaf->uEax & UINT32_C(0xf0003000); 2030 uNew |= RT_BYTE1(uMaxIntelFamilyModelStep) & 0xf; /* stepping */ 2031 uNew |= (RT_BYTE2(uMaxIntelFamilyModelStep) & 0xf) << 4; /* 4 low model bits */ 2032 uNew |= (RT_BYTE2(uMaxIntelFamilyModelStep) >> 4) << 16; /* 4 high model bits */ 2033 uNew |= (RT_BYTE3(uMaxIntelFamilyModelStep) & 0xf) << 8; /* 4 low family bits */ 2034 if (RT_BYTE3(uMaxIntelFamilyModelStep) > 0xf) /* 8 high family bits, using intel's suggested calculation. */ 2035 uNew |= ( (RT_BYTE3(uMaxIntelFamilyModelStep) - (RT_BYTE3(uMaxIntelFamilyModelStep) & 0xf)) & 0xff ) << 20; 2036 LogRel(("CPU: CPUID(0).EAX %#x -> %#x (uMaxIntelFamilyModelStep=%#x, uCurIntelFamilyModelStep=%#x\n", 2037 pStdFeatureLeaf->uEax, uNew, uMaxIntelFamilyModelStep, uCurIntelFamilyModelStep)); 2038 pStdFeatureLeaf->uEax = uNew; 2039 } 2040 } 2041 } 2042 2043 2044 2045 /** 2046 * Limit it the number of entries, zapping the remainder. 2047 * 2048 * The limits are masking off stuff about power saving and similar, this 2049 * is perhaps a bit crudely done as there is probably some relatively harmless 2050 * info too in these leaves (like words about having a constant TSC). 2051 * 2052 * @param pCpum The CPUM instance data. 2053 * @param pConfig The CPUID configuration we've read from CFGM. 2054 */ 2055 static void cpumR3CpuIdLimitLeaves(PCPUM pCpum, PCPUMCPUIDCONFIG pConfig) 2056 { 2057 /* 2058 * Standard leaves. 2059 */ 2060 uint32_t uSubLeaf = 0; 2061 PCPUMCPUIDLEAF pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 0, uSubLeaf); 2062 if (pCurLeaf) 2063 { 2064 uint32_t uLimit = pCurLeaf->uEax; 2065 if ( uLimit >= UINT32_C(0x00000000) 2066 && uLimit <= UINT32_C(0x000fffff)) 2067 { 2068 /** @todo raise the limits! */ 2069 if (pCurLeaf->uEax > 5) 2070 { 2071 pCurLeaf->uEax = uLimit = 5; 2072 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2073 uLimit + 1, UINT32_C(0x000fffff)); 2074 } 2075 2076 /* NT4 hack, no zapping of extra leaves here. */ 2077 if (pConfig->fNt4LeafLimit && uLimit > 3) 2078 pCurLeaf->uEax = uLimit = 3; 2079 2080 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x00000000), ++uSubLeaf)) != NULL) 2081 pCurLeaf->uEax = uLimit; 2082 } 2083 else 2084 { 2085 LogRel(("CPUID: Invalid standard range: %#x\n", uLimit)); 2086 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2087 UINT32_C(0x00000000), UINT32_C(0x0fffffff)); 2088 } 2089 } 2090 2091 /* 2092 * Extended leaves. 2093 */ 2094 uSubLeaf = 0; 2095 pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x80000000), uSubLeaf); 2096 if (pCurLeaf) 2097 { 2098 uint32_t uLimit = pCurLeaf->uEax; 2099 if ( uLimit >= UINT32_C(0x80000000) 2100 && uLimit <= UINT32_C(0x800fffff)) 2101 { 2102 /** @todo raise the limits! */ 2103 if (pCurLeaf->uEax > UINT32_C(0x80000008)) 2104 { 2105 pCurLeaf->uEax = uLimit = UINT32_C(0x80000008); 2106 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2107 uLimit + 1, UINT32_C(0x800fffff)); 2108 } 2109 2110 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x80000000), ++uSubLeaf)) != NULL) 2111 pCurLeaf->uEax = uLimit; 2112 } 2113 else 2114 { 2115 LogRel(("CPUID: Invalid extended range: %#x\n", uLimit)); 2116 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2117 UINT32_C(0x80000000), UINT32_C(0x8ffffffd)); 2118 } 2119 } 2120 2121 /* 2122 * Centaur leaves (VIA). 2123 */ 2124 uSubLeaf = 0; 2125 pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0xc0000000), uSubLeaf); 2126 if (pCurLeaf) 2127 { 2128 uint32_t uLimit = pCurLeaf->uEax; 2129 if ( uLimit >= UINT32_C(0xc0000000) 2130 && uLimit <= UINT32_C(0xc00fffff)) 2131 { 2132 pCurLeaf->uEax = RT_MIN(uLimit, UINT32_C(0xc0000004)); 2133 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2134 uLimit + 1, UINT32_C(0xcfffffff)); 2135 2136 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0xc0000000), ++uSubLeaf)) != NULL) 2137 pCurLeaf->uEax = uLimit; 2138 } 2139 else 2140 { 2141 LogRel(("CPUID: Invalid centaur range: %#x\n", uLimit)); 2142 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2143 UINT32_C(0xc0000000), UINT32_C(0xcfffffff)); 2144 } 2145 } 2146 } 2147 2148 2149 /** 2150 * Clears a CPUID leaf and all sub-leaves (to zero). 2151 * 2152 * @param pCpum The CPUM instance data. 2153 * @param uLeaf The leaf to clear. 2154 */ 2155 static void cpumR3CpuIdZeroLeaf(PCPUM pCpum, uint32_t uLeaf) 2156 { 2157 uint32_t uSubLeaf = 0; 2158 PCPUMCPUIDLEAF pCurLeaf; 2159 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, uLeaf, uSubLeaf)) != NULL) 2160 { 2161 pCurLeaf->uEax = 0; 2162 pCurLeaf->uEbx = 0; 2163 pCurLeaf->uEcx = 0; 2164 pCurLeaf->uEdx = 0; 2165 uSubLeaf++; 2166 } 2167 } 2168 2169 2170 /** 2171 * Sanitizes and adjust the CPUID leaves. 2172 * 2173 * Drop features that aren't virtualized (or virtualizable). Adjust information 2174 * and capabilities to fit the virtualized hardware. Remove information the 2175 * guest shouldn't have (because it's wrong in the virtual world or because it 2176 * gives away host details) or that we don't have documentation for and no idea 2177 * what means. 2178 * 2179 * @returns VBox status code. 2180 * @param pVM Pointer to the cross context VM structure (for cCpus). 2181 * @param pCpum The CPUM instance data. 2182 * @param pConfig The CPUID configuration we've read from CFGM. 2183 */ 2184 static int cpumR3CpuIdSanitize(PVM pVM, PCPUM pCpum, PCPUMCPUIDCONFIG pConfig) 2185 { 1846 2186 #define PORTABLE_CLEAR_BITS_WHEN(Lvl, a_pLeafReg, FeatNm, fMask, uValue) \ 1847 if ( pC PUM->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fMask)) == (uValue) ) \2187 if ( pCpum->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fMask)) == (uValue) ) \ 1848 2188 { \ 1849 2189 LogRel(("PortableCpuId: " #a_pLeafReg "[" #FeatNm "]: %#x -> 0\n", (a_pLeafReg) & (fMask))); \ … … 1851 2191 } 1852 2192 #define PORTABLE_DISABLE_FEATURE_BIT(Lvl, a_pLeafReg, FeatNm, fBitMask) \ 1853 if ( pC PUM->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fBitMask)) ) \2193 if ( pCpum->u8PortableCpuIdLevel >= (Lvl) && ((a_pLeafReg) & (fBitMask)) ) \ 1854 2194 { \ 1855 2195 LogRel(("PortableCpuId: " #a_pLeafReg "[" #FeatNm "]: 1 -> 0\n")); \ 1856 2196 (a_pLeafReg) &= ~(uint32_t)(fBitMask); \ 1857 2197 } 1858 1859 /* 1860 * Read the configuration. 1861 */ 1862 /** @cfgm{/CPUM/SyntheticCpu, boolean, false} 1863 * Enables the Synthetic CPU. The Vendor ID and Processor Name are 1864 * completely overridden by VirtualBox custom strings. Some 1865 * CPUID information is withheld, like the cache info. 2198 Assert(pCpum->GuestFeatures.enmCpuVendor != CPUMCPUVENDOR_INVALID); 2199 2200 /* Cpuid 1: 2201 * EAX: CPU model, family and stepping. 1866 2202 * 1867 * This is obsoleted by PortableCpuIdLevel. */ 1868 bool fSyntheticCpu; 1869 rc = CFGMR3QueryBoolDef(pCpumCfg, "SyntheticCpu", &fSyntheticCpu, false); 1870 AssertRCReturn(rc, rc); 1871 1872 /** @cfgm{/CPUM/PortableCpuIdLevel, 8-bit, 0, 3, 0} 1873 * When non-zero CPUID features that could cause portability issues will be 1874 * stripped. The higher the value the more features gets stripped. Higher 1875 * values should only be used when older CPUs are involved since it may 1876 * harm performance and maybe also cause problems with specific guests. */ 1877 rc = CFGMR3QueryU8Def(pCpumCfg, "PortableCpuIdLevel", &pCPUM->u8PortableCpuIdLevel, fSyntheticCpu ? 1 : 0); 1878 AssertLogRelRCReturn(rc, rc); 1879 1880 /** @cfgm{/CPUM/GuestCpuName, string} 1881 * The name of the CPU we're to emulate. The default is the host CPU. 1882 * Note! CPUs other than "host" one is currently unsupported. */ 1883 char szCpuName[128]; 1884 rc = CFGMR3QueryStringDef(pCpumCfg, "GuestCpuName", szCpuName, sizeof(szCpuName), "host"); 1885 AssertLogRelRCReturn(rc, rc); 1886 1887 /** @cfgm{/CPUM/CMPXCHG16B, boolean, false} 1888 * Expose CMPXCHG16B to the guest if supported by the host. 1889 */ 1890 bool fCmpXchg16b; 1891 rc = CFGMR3QueryBoolDef(pCpumCfg, "CMPXCHG16B", &fCmpXchg16b, false); 1892 AssertLogRelRCReturn(rc, rc); 1893 1894 /** @cfgm{/CPUM/MONITOR, boolean, true} 1895 * Expose MONITOR/MWAIT instructions to the guest. 1896 */ 1897 bool fMonitor; 1898 rc = CFGMR3QueryBoolDef(pCpumCfg, "MONITOR", &fMonitor, true); 1899 AssertLogRelRCReturn(rc, rc); 1900 1901 /** @cfgm{/CPUM/MWaitExtensions, boolean, false} 1902 * Expose MWAIT extended features to the guest. For now we expose just MWAIT 1903 * break on interrupt feature (bit 1). 1904 */ 1905 bool fMWaitExtensions; 1906 rc = CFGMR3QueryBoolDef(pCpumCfg, "MWaitExtensions", &fMWaitExtensions, false); 1907 AssertLogRelRCReturn(rc, rc); 1908 1909 /** @cfgm{/CPUM/SSE4.1, boolean, true} 1910 * Expose SSE4.1 to the guest if available. 1911 */ 1912 bool fSse41; 1913 rc = CFGMR3QueryBoolDef(pCpumCfg, "SSE4.1", &fSse41, true); 1914 AssertLogRelRCReturn(rc, rc); 1915 1916 /** @cfgm{/CPUM/SSE4.2, boolean, true} 1917 * Expose SSE4.2 to the guest if available. 1918 */ 1919 bool fSse42; 1920 rc = CFGMR3QueryBoolDef(pCpumCfg, "SSE4.2", &fSse42, true); 1921 AssertLogRelRCReturn(rc, rc); 1922 1923 /** @cfgm{/CPUM/NT4LeafLimit, boolean, false} 1924 * Limit the number of standard CPUID leaves to 0..3 to prevent NT4 from 1925 * bugchecking with MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED (0x3e). 1926 * This option corresponds somewhat to IA32_MISC_ENABLES.BOOT_NT4[bit 22]. 1927 */ 1928 bool fNt4LeafLimit; 1929 rc = CFGMR3QueryBoolDef(pCpumCfg, "NT4LeafLimit", &fNt4LeafLimit, false); 1930 AssertLogRelRCReturn(rc, rc); 1931 1932 /** @cfgm{/CPUM/MaxIntelFamilyModelStep, uint32_t, UINT32_MAX} 1933 * Restrict the reported CPU family+model+stepping of intel CPUs. This is 1934 * probably going to be a temporary hack, so don't depend on this. 1935 * The 1st byte of the value is the stepping, the 2nd byte value is the model 1936 * number and the 3rd byte value is the family, and the 4th value must be zero. 1937 */ 1938 uint32_t uMaxIntelFamilyModelStep; 1939 rc = CFGMR3QueryU32Def(pCpumCfg, "MaxIntelFamilyModelStep", &uMaxIntelFamilyModelStep, UINT32_MAX); 1940 AssertLogRelRCReturn(rc, rc); 1941 1942 /* 1943 * Get the guest CPU data from the database and/or the host. 1944 */ 1945 rc = cpumR3DbGetCpuInfo(szCpuName, &pCPUM->GuestInfo); 1946 if (RT_FAILURE(rc)) 1947 return rc == VERR_CPUM_DB_CPU_NOT_FOUND 1948 ? VMSetError(pVM, rc, RT_SRC_POS, 1949 "Info on guest CPU '%s' could not be found. Please, select a different CPU.", szCpuName) 1950 : rc; 1951 1952 /** @cfgm{/CPUM/MSRs/[Name]/[First|Last|Type|Value|...],} 1953 * Overrides the guest MSRs. 1954 */ 1955 rc = cpumR3LoadMsrOverrides(pVM, CFGMR3GetChild(pCpumCfg, "MSRs")); 1956 1957 /** @cfgm{/CPUM/HostCPUID/[000000xx|800000xx|c000000x]/[eax|ebx|ecx|edx],32-bit} 1958 * Overrides the CPUID leaf values (from the host CPU usually) used for 1959 * calculating the guest CPUID leaves. This can be used to preserve the CPUID 1960 * values when moving a VM to a different machine. Another use is restricting 1961 * (or extending) the feature set exposed to the guest. */ 1962 if (RT_SUCCESS(rc)) 1963 rc = cpumR3LoadCpuIdOverrides(pVM, CFGMR3GetChild(pCpumCfg, "HostCPUID"), "HostCPUID"); 1964 1965 if (RT_SUCCESS(rc) && CFGMR3GetChild(pCpumCfg, "CPUID")) /* 2nd override, now discontinued. */ 1966 rc = VMSetError(pVM, VERR_CFGM_CONFIG_UNKNOWN_NODE, RT_SRC_POS, 1967 "Found unsupported configuration node '/CPUM/CPUID/'. " 1968 "Please use IMachine::setCPUIDLeaf() instead."); 1969 1970 /* 1971 * Pre-explode the CPUID info. 1972 */ 1973 if (RT_SUCCESS(rc)) 1974 rc = cpumR3CpuIdExplodeFeatures(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, &pCPUM->GuestFeatures); 1975 if (RT_FAILURE(rc)) 1976 { 1977 RTMemFree(pCPUM->GuestInfo.paCpuIdLeavesR3); 1978 pCPUM->GuestInfo.paCpuIdLeavesR3 = NULL; 1979 RTMemFree(pCPUM->GuestInfo.paMsrRangesR3); 1980 pCPUM->GuestInfo.paMsrRangesR3 = NULL; 1981 return rc; 1982 } 1983 1984 1985 /* ... split this function about here ... */ 1986 1987 1988 /* Cpuid 1: 1989 * Only report features we can support. 1990 * 1991 * Note! When enabling new features the Synthetic CPU and Portable CPUID 1992 * options may require adjusting (i.e. stripping what was enabled). 1993 */ 1994 PCPUMCPUIDLEAF pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1995 1, 0); /* Note! Must refetch when used later. */ 1996 AssertLogRelReturn(pStdFeatureLeaf, VERR_CPUM_IPE_2); 1997 pStdFeatureLeaf->uEdx &= X86_CPUID_FEATURE_EDX_FPU 1998 | X86_CPUID_FEATURE_EDX_VME 1999 | X86_CPUID_FEATURE_EDX_DE 2000 | X86_CPUID_FEATURE_EDX_PSE 2001 | X86_CPUID_FEATURE_EDX_TSC 2002 | X86_CPUID_FEATURE_EDX_MSR 2003 //| X86_CPUID_FEATURE_EDX_PAE - set later if configured. 2004 | X86_CPUID_FEATURE_EDX_MCE 2005 | X86_CPUID_FEATURE_EDX_CX8 2006 //| X86_CPUID_FEATURE_EDX_APIC - set by the APIC device if present. 2007 /* Note! we don't report sysenter/sysexit support due to our inability to keep the IOPL part of eflags in sync while in ring 1 (see @bugref{1757}) */ 2008 //| X86_CPUID_FEATURE_EDX_SEP 2009 | X86_CPUID_FEATURE_EDX_MTRR 2010 | X86_CPUID_FEATURE_EDX_PGE 2011 | X86_CPUID_FEATURE_EDX_MCA 2012 | X86_CPUID_FEATURE_EDX_CMOV 2013 | X86_CPUID_FEATURE_EDX_PAT 2014 | X86_CPUID_FEATURE_EDX_PSE36 2015 //| X86_CPUID_FEATURE_EDX_PSN - no serial number. 2016 | X86_CPUID_FEATURE_EDX_CLFSH 2017 //| X86_CPUID_FEATURE_EDX_DS - no debug store. 2018 //| X86_CPUID_FEATURE_EDX_ACPI - not virtualized yet. 2019 | X86_CPUID_FEATURE_EDX_MMX 2020 | X86_CPUID_FEATURE_EDX_FXSR 2021 | X86_CPUID_FEATURE_EDX_SSE 2022 | X86_CPUID_FEATURE_EDX_SSE2 2023 //| X86_CPUID_FEATURE_EDX_SS - no self snoop. 2024 //| X86_CPUID_FEATURE_EDX_HTT - no hyperthreading. 2025 //| X86_CPUID_FEATURE_EDX_TM - no thermal monitor. 2026 //| X86_CPUID_FEATURE_EDX_PBE - no pending break enabled. 2027 | 0; 2028 pStdFeatureLeaf->uEcx &= 0 2029 | X86_CPUID_FEATURE_ECX_SSE3 2030 /* Can't properly emulate monitor & mwait with guest SMP; force the guest to use hlt for idling VCPUs. */ 2031 | ((fMonitor && pVM->cCpus == 1) ? X86_CPUID_FEATURE_ECX_MONITOR : 0) 2032 //| X86_CPUID_FEATURE_ECX_CPLDS - no CPL qualified debug store. 2033 //| X86_CPUID_FEATURE_ECX_VMX - not virtualized. 2034 //| X86_CPUID_FEATURE_ECX_EST - no extended speed step. 2035 //| X86_CPUID_FEATURE_ECX_TM2 - no thermal monitor 2. 2036 | X86_CPUID_FEATURE_ECX_SSSE3 2037 //| X86_CPUID_FEATURE_ECX_CNTXID - no L1 context id (MSR++). 2038 | (fCmpXchg16b ? X86_CPUID_FEATURE_ECX_CX16 : 0) 2039 /* ECX Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */ 2040 //| X86_CPUID_FEATURE_ECX_TPRUPDATE 2041 | (fSse41 ? X86_CPUID_FEATURE_ECX_SSE4_1 : 0) 2042 | (fSse42 ? X86_CPUID_FEATURE_ECX_SSE4_2 : 0) 2043 /* ECX Bit 21 - x2APIC support - not yet. */ 2044 // | X86_CPUID_FEATURE_ECX_X2APIC 2045 /* ECX Bit 23 - POPCNT instruction. */ 2046 //| X86_CPUID_FEATURE_ECX_POPCNT 2047 | 0; 2048 if (pCPUM->u8PortableCpuIdLevel > 0) 2049 { 2050 PORTABLE_CLEAR_BITS_WHEN(1, pStdFeatureLeaf->uEax, ProcessorType, (UINT32_C(3) << 12), (UINT32_C(2) << 12)); 2051 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSSE3, X86_CPUID_FEATURE_ECX_SSSE3); 2052 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE3, X86_CPUID_FEATURE_ECX_SSE3); 2053 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE4_1, X86_CPUID_FEATURE_ECX_SSE4_1); 2054 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE4_2, X86_CPUID_FEATURE_ECX_SSE4_2); 2055 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, CX16, X86_CPUID_FEATURE_ECX_CX16); 2056 PORTABLE_DISABLE_FEATURE_BIT(2, pStdFeatureLeaf->uEdx, SSE2, X86_CPUID_FEATURE_EDX_SSE2); 2057 PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, SSE, X86_CPUID_FEATURE_EDX_SSE); 2058 PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, CLFSH, X86_CPUID_FEATURE_EDX_CLFSH); 2059 PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, CMOV, X86_CPUID_FEATURE_EDX_CMOV); 2060 2061 Assert(!(pStdFeatureLeaf->uEdx & ( X86_CPUID_FEATURE_EDX_SEP 2062 | X86_CPUID_FEATURE_EDX_PSN 2063 | X86_CPUID_FEATURE_EDX_DS 2064 | X86_CPUID_FEATURE_EDX_ACPI 2065 | X86_CPUID_FEATURE_EDX_SS 2066 | X86_CPUID_FEATURE_EDX_TM 2067 | X86_CPUID_FEATURE_EDX_PBE 2068 ))); 2069 Assert(!(pStdFeatureLeaf->uEcx & ( X86_CPUID_FEATURE_ECX_PCLMUL 2070 | X86_CPUID_FEATURE_ECX_DTES64 2071 | X86_CPUID_FEATURE_ECX_CPLDS 2072 | X86_CPUID_FEATURE_ECX_VMX 2073 | X86_CPUID_FEATURE_ECX_SMX 2074 | X86_CPUID_FEATURE_ECX_EST 2075 | X86_CPUID_FEATURE_ECX_TM2 2076 | X86_CPUID_FEATURE_ECX_CNTXID 2077 | X86_CPUID_FEATURE_ECX_FMA 2078 | X86_CPUID_FEATURE_ECX_CX16 2079 | X86_CPUID_FEATURE_ECX_TPRUPDATE 2080 | X86_CPUID_FEATURE_ECX_PDCM 2081 | X86_CPUID_FEATURE_ECX_DCA 2082 | X86_CPUID_FEATURE_ECX_MOVBE 2083 | X86_CPUID_FEATURE_ECX_AES 2084 | X86_CPUID_FEATURE_ECX_POPCNT 2085 | X86_CPUID_FEATURE_ECX_XSAVE 2086 | X86_CPUID_FEATURE_ECX_OSXSAVE 2087 | X86_CPUID_FEATURE_ECX_AVX 2088 ))); 2089 } 2090 2091 /* Cpuid 0x80000001: 2092 * Only report features we can support. 2093 * 2203 * ECX + EDX: Supported features. Only report features we can support. 2094 2204 * Note! When enabling new features the Synthetic CPU and Portable CPUID 2095 2205 * options may require adjusting (i.e. stripping what was enabled). 2096 2206 * 2097 * ASSUMES that this is ALWAYS the AMD defined feature set if present. 2098 */ 2099 PCPUMCPUIDLEAF pExtFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 2100 UINT32_C(0x80000001), 0); /* Note! Must refetch when used later. */ 2207 * EBX: Branding, CLFLUSH line size, logical processors per package and 2208 * initial APIC ID. 2209 */ 2210 PCPUMCPUIDLEAF pStdFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 1, 0); /* Note! Must refetch when used later. */ 2211 AssertLogRelReturn(pStdFeatureLeaf, VERR_CPUM_IPE_2); 2212 AssertLogRelReturn(pStdFeatureLeaf->fSubLeafMask == 0, VERR_CPUM_IPE_2); 2213 2214 pStdFeatureLeaf->uEdx &= X86_CPUID_FEATURE_EDX_FPU 2215 | X86_CPUID_FEATURE_EDX_VME 2216 | X86_CPUID_FEATURE_EDX_DE 2217 | X86_CPUID_FEATURE_EDX_PSE 2218 | X86_CPUID_FEATURE_EDX_TSC 2219 | X86_CPUID_FEATURE_EDX_MSR 2220 //| X86_CPUID_FEATURE_EDX_PAE - set later if configured. 2221 | X86_CPUID_FEATURE_EDX_MCE 2222 | X86_CPUID_FEATURE_EDX_CX8 2223 //| X86_CPUID_FEATURE_EDX_APIC - set by the APIC device if present. 2224 //| RT_BIT_32(10) - not defined 2225 /* Note! we don't report sysenter/sysexit support due to our inability to keep the IOPL part of eflags in sync while in ring 1 (see @bugref{1757}) */ 2226 //| X86_CPUID_FEATURE_EDX_SEP 2227 | X86_CPUID_FEATURE_EDX_MTRR 2228 | X86_CPUID_FEATURE_EDX_PGE 2229 | X86_CPUID_FEATURE_EDX_MCA 2230 | X86_CPUID_FEATURE_EDX_CMOV 2231 | X86_CPUID_FEATURE_EDX_PAT /* 16 */ 2232 | X86_CPUID_FEATURE_EDX_PSE36 2233 //| X86_CPUID_FEATURE_EDX_PSN - no serial number. 2234 | X86_CPUID_FEATURE_EDX_CLFSH 2235 //| RT_BIT_32(20) - not defined 2236 //| X86_CPUID_FEATURE_EDX_DS - no debug store. 2237 //| X86_CPUID_FEATURE_EDX_ACPI - not supported (not DevAcpi, right?). 2238 | X86_CPUID_FEATURE_EDX_MMX 2239 | X86_CPUID_FEATURE_EDX_FXSR 2240 | X86_CPUID_FEATURE_EDX_SSE 2241 | X86_CPUID_FEATURE_EDX_SSE2 2242 //| X86_CPUID_FEATURE_EDX_SS - no self snoop. 2243 //| X86_CPUID_FEATURE_EDX_HTT - no hyperthreading/cores - see below. 2244 //| X86_CPUID_FEATURE_EDX_TM - no thermal monitor. 2245 //| RT_BIT_32(30) - not defined 2246 //| X86_CPUID_FEATURE_EDX_PBE - no pending break enabled. 2247 ; 2248 pStdFeatureLeaf->uEcx &= 0 2249 | X86_CPUID_FEATURE_ECX_SSE3 2250 //| X86_CPUID_FEATURE_ECX_PCLMUL - not implemented yet. 2251 //| X86_CPUID_FEATURE_ECX_DTES64 - not implemented yet. 2252 /* Can't properly emulate monitor & mwait with guest SMP; force the guest to use hlt for idling VCPUs. */ 2253 | ((pConfig->fMonitor && pVM->cCpus == 1) ? X86_CPUID_FEATURE_ECX_MONITOR : 0) 2254 //| X86_CPUID_FEATURE_ECX_CPLDS - no CPL qualified debug store. 2255 //| X86_CPUID_FEATURE_ECX_VMX - not virtualized yet. 2256 //| X86_CPUID_FEATURE_ECX_SMX - not virtualized yet. 2257 //| X86_CPUID_FEATURE_ECX_EST - no extended speed step. 2258 //| X86_CPUID_FEATURE_ECX_TM2 - no thermal monitor 2. 2259 | X86_CPUID_FEATURE_ECX_SSSE3 2260 //| X86_CPUID_FEATURE_ECX_CNTXID - no L1 context id (MSR++). 2261 //| X86_CPUID_FEATURE_ECX_FMA - not implemented yet. 2262 | (pConfig->fCmpXchg16b ? X86_CPUID_FEATURE_ECX_CX16 : 0) 2263 /* ECX Bit 14 - xTPR Update Control. Processor supports changing IA32_MISC_ENABLES[bit 23]. */ 2264 //| X86_CPUID_FEATURE_ECX_TPRUPDATE 2265 //| X86_CPUID_FEATURE_ECX_PDCM - not implemented yet. 2266 //| X86_CPUID_FEATURE_ECX_PCID - not implemented yet. 2267 //| X86_CPUID_FEATURE_ECX_DCA - not implemented yet. 2268 | (pConfig->fSse41 ? X86_CPUID_FEATURE_ECX_SSE4_1 : 0) 2269 | (pConfig->fSse42 ? X86_CPUID_FEATURE_ECX_SSE4_2 : 0) 2270 //| X86_CPUID_FEATURE_ECX_X2APIC - turned on later by the device if enabled. 2271 //| X86_CPUID_FEATURE_ECX_MOVBE - not implemented yet. 2272 //| X86_CPUID_FEATURE_ECX_POPCNT 2273 //| X86_CPUID_FEATURE_ECX_TSCDEADL - not implemented yet. 2274 //| X86_CPUID_FEATURE_ECX_AES - not implemented yet. 2275 //| X86_CPUID_FEATURE_ECX_XSAVE - not implemented yet. 2276 //| X86_CPUID_FEATURE_ECX_OSXSAVE - not implemented yet. 2277 //| X86_CPUID_FEATURE_ECX_AVX - not implemented yet. 2278 //| X86_CPUID_FEATURE_ECX_F16C - not implemented yet. 2279 //| X86_CPUID_FEATURE_ECX_RDRAND - not implemented yet. 2280 //| X86_CPUID_FEATURE_ECX_HVP - Set explicitly later. 2281 ; 2282 2283 if (pCpum->u8PortableCpuIdLevel > 0) 2284 { 2285 PORTABLE_CLEAR_BITS_WHEN(1, pStdFeatureLeaf->uEax, ProcessorType, (UINT32_C(3) << 12), (UINT32_C(2) << 12)); 2286 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSSE3, X86_CPUID_FEATURE_ECX_SSSE3); 2287 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE3, X86_CPUID_FEATURE_ECX_SSE3); 2288 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE4_1, X86_CPUID_FEATURE_ECX_SSE4_1); 2289 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, SSE4_2, X86_CPUID_FEATURE_ECX_SSE4_2); 2290 PORTABLE_DISABLE_FEATURE_BIT(1, pStdFeatureLeaf->uEcx, CX16, X86_CPUID_FEATURE_ECX_CX16); 2291 PORTABLE_DISABLE_FEATURE_BIT(2, pStdFeatureLeaf->uEdx, SSE2, X86_CPUID_FEATURE_EDX_SSE2); 2292 PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, SSE, X86_CPUID_FEATURE_EDX_SSE); 2293 PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, CLFSH, X86_CPUID_FEATURE_EDX_CLFSH); 2294 PORTABLE_DISABLE_FEATURE_BIT(3, pStdFeatureLeaf->uEdx, CMOV, X86_CPUID_FEATURE_EDX_CMOV); 2295 2296 Assert(!(pStdFeatureLeaf->uEdx & ( X86_CPUID_FEATURE_EDX_SEP 2297 | X86_CPUID_FEATURE_EDX_PSN 2298 | X86_CPUID_FEATURE_EDX_DS 2299 | X86_CPUID_FEATURE_EDX_ACPI 2300 | X86_CPUID_FEATURE_EDX_SS 2301 | X86_CPUID_FEATURE_EDX_TM 2302 | X86_CPUID_FEATURE_EDX_PBE 2303 ))); 2304 Assert(!(pStdFeatureLeaf->uEcx & ( X86_CPUID_FEATURE_ECX_PCLMUL 2305 | X86_CPUID_FEATURE_ECX_DTES64 2306 | X86_CPUID_FEATURE_ECX_CPLDS 2307 | X86_CPUID_FEATURE_ECX_VMX 2308 | X86_CPUID_FEATURE_ECX_SMX 2309 | X86_CPUID_FEATURE_ECX_EST 2310 | X86_CPUID_FEATURE_ECX_TM2 2311 | X86_CPUID_FEATURE_ECX_CNTXID 2312 | X86_CPUID_FEATURE_ECX_FMA 2313 | X86_CPUID_FEATURE_ECX_CX16 2314 | X86_CPUID_FEATURE_ECX_TPRUPDATE 2315 | X86_CPUID_FEATURE_ECX_PDCM 2316 | X86_CPUID_FEATURE_ECX_DCA 2317 | X86_CPUID_FEATURE_ECX_MOVBE 2318 | X86_CPUID_FEATURE_ECX_AES 2319 | X86_CPUID_FEATURE_ECX_POPCNT 2320 | X86_CPUID_FEATURE_ECX_XSAVE 2321 | X86_CPUID_FEATURE_ECX_OSXSAVE 2322 | X86_CPUID_FEATURE_ECX_AVX 2323 ))); 2324 } 2325 2326 /* Set up APIC ID for CPU 0, configure multi core/threaded smp. */ 2327 pStdFeatureLeaf->uEbx &= UINT32_C(0x0000ffff); /* (APIC-ID := 0 and #LogCpus := 0) */ 2328 #ifdef VBOX_WITH_MULTI_CORE 2329 if (pVM->cCpus > 1) 2330 { 2331 /* If CPUID Fn0000_0001_EDX[HTT] = 1 then LogicalProcessorCount is the number of threads per CPU 2332 core times the number of CPU cores per processor */ 2333 pStdFeatureLeaf->uEbx |= pVM->cCpus <= 0xff ? (pVM->cCpus << 16) : UINT32_C(0x00ff0000); 2334 pStdFeatureLeaf->uEdx |= X86_CPUID_FEATURE_EDX_HTT; /* necessary for hyper-threading *or* multi-core CPUs */ 2335 } 2336 #endif 2337 pStdFeatureLeaf = NULL; /* Must refetch! */ 2338 2339 2340 /* Cpuid 0x80000001: (Similar, but in no way identical to 0x00000001.) 2341 * AMD: 2342 * EAX: CPU model, family and stepping. 2343 * 2344 * ECX + EDX: Supported features. Only report features we can support. 2345 * Note! When enabling new features the Synthetic CPU and Portable CPUID 2346 * options may require adjusting (i.e. stripping what was enabled). 2347 * ASSUMES that this is ALWAYS the AMD defined feature set if present. 2348 * 2349 * EBX: Branding ID and package type (or reserved). 2350 * 2351 * Intel and probably most others: 2352 * EAX: 0 2353 * EBX: 0 2354 * ECX + EDX: Subset of AMD features, mainly for AMD64 support. 2355 */ 2356 PCPUMCPUIDLEAF pExtFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x80000001), 0); 2101 2357 if (pExtFeatureLeaf) 2102 2358 { 2103 pExtFeatureLeaf->uEdx &= X86_CPUID_AMD_FEATURE_EDX_FPU 2104 | X86_CPUID_AMD_FEATURE_EDX_VME 2105 | X86_CPUID_AMD_FEATURE_EDX_DE 2106 | X86_CPUID_AMD_FEATURE_EDX_PSE 2107 | X86_CPUID_AMD_FEATURE_EDX_TSC 2108 | X86_CPUID_AMD_FEATURE_EDX_MSR //?? this means AMD MSRs.. 2109 //| X86_CPUID_AMD_FEATURE_EDX_PAE - not implemented yet. 2110 //| X86_CPUID_AMD_FEATURE_EDX_MCE - not virtualized yet. 2111 | X86_CPUID_AMD_FEATURE_EDX_CX8 2112 //| X86_CPUID_AMD_FEATURE_EDX_APIC - set by the APIC device if present. 2113 /* Note! we don't report sysenter/sysexit support due to our inability to keep the IOPL part of eflags in sync while in ring 1 (see @bugref{1757}) */ 2114 //| X86_CPUID_EXT_FEATURE_EDX_SEP 2115 | X86_CPUID_AMD_FEATURE_EDX_MTRR 2116 | X86_CPUID_AMD_FEATURE_EDX_PGE 2117 | X86_CPUID_AMD_FEATURE_EDX_MCA 2118 | X86_CPUID_AMD_FEATURE_EDX_CMOV 2119 | X86_CPUID_AMD_FEATURE_EDX_PAT 2120 | X86_CPUID_AMD_FEATURE_EDX_PSE36 2121 //| X86_CPUID_EXT_FEATURE_EDX_NX - not virtualized, requires PAE. 2122 //| X86_CPUID_AMD_FEATURE_EDX_AXMMX 2123 | X86_CPUID_AMD_FEATURE_EDX_MMX 2124 | X86_CPUID_AMD_FEATURE_EDX_FXSR 2125 | X86_CPUID_AMD_FEATURE_EDX_FFXSR 2126 //| X86_CPUID_EXT_FEATURE_EDX_PAGE1GB 2127 | X86_CPUID_EXT_FEATURE_EDX_RDTSCP 2128 //| X86_CPUID_EXT_FEATURE_EDX_LONG_MODE - turned on when necessary 2129 | X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX 2130 | X86_CPUID_AMD_FEATURE_EDX_3DNOW 2131 | 0; 2132 pExtFeatureLeaf->uEcx &= 0 2133 //| X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF 2134 //| X86_CPUID_AMD_FEATURE_ECX_CMPL 2135 //| X86_CPUID_AMD_FEATURE_ECX_SVM - not virtualized. 2136 //| X86_CPUID_AMD_FEATURE_ECX_EXT_APIC 2137 /* Note: This could prevent teleporting from AMD to Intel CPUs! */ 2138 | X86_CPUID_AMD_FEATURE_ECX_CR8L /* expose lock mov cr0 = mov cr8 hack for guests that can use this feature to access the TPR. */ 2139 //| X86_CPUID_AMD_FEATURE_ECX_ABM 2140 //| X86_CPUID_AMD_FEATURE_ECX_SSE4A 2141 //| X86_CPUID_AMD_FEATURE_ECX_MISALNSSE 2142 //| X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF 2143 //| X86_CPUID_AMD_FEATURE_ECX_OSVW 2144 //| X86_CPUID_AMD_FEATURE_ECX_IBS 2145 //| X86_CPUID_AMD_FEATURE_ECX_SSE5 2146 //| X86_CPUID_AMD_FEATURE_ECX_SKINIT 2147 //| X86_CPUID_AMD_FEATURE_ECX_WDT 2148 | 0; 2149 if (pCPUM->u8PortableCpuIdLevel > 0) 2359 AssertLogRelReturn(pExtFeatureLeaf->fSubLeafMask == 0, VERR_CPUM_IPE_2); 2360 2361 pExtFeatureLeaf->uEdx &= X86_CPUID_AMD_FEATURE_EDX_FPU 2362 | X86_CPUID_AMD_FEATURE_EDX_VME 2363 | X86_CPUID_AMD_FEATURE_EDX_DE 2364 | X86_CPUID_AMD_FEATURE_EDX_PSE 2365 | X86_CPUID_AMD_FEATURE_EDX_TSC 2366 | X86_CPUID_AMD_FEATURE_EDX_MSR //?? this means AMD MSRs.. 2367 //| X86_CPUID_AMD_FEATURE_EDX_PAE - turned on when necessary 2368 //| X86_CPUID_AMD_FEATURE_EDX_MCE - not virtualized yet. 2369 | X86_CPUID_AMD_FEATURE_EDX_CX8 2370 //| X86_CPUID_AMD_FEATURE_EDX_APIC - set by the APIC device if present. 2371 //| RT_BIT_32(10) - reserved 2372 /* Note! We don't report sysenter/sysexit support due to our inability to keep the IOPL part of 2373 eflags in sync while in ring 1 (see @bugref{1757}). HM enables them later. */ 2374 //| X86_CPUID_EXT_FEATURE_EDX_SYSCALL 2375 | X86_CPUID_AMD_FEATURE_EDX_MTRR 2376 | X86_CPUID_AMD_FEATURE_EDX_PGE 2377 | X86_CPUID_AMD_FEATURE_EDX_MCA 2378 | X86_CPUID_AMD_FEATURE_EDX_CMOV 2379 | X86_CPUID_AMD_FEATURE_EDX_PAT 2380 | X86_CPUID_AMD_FEATURE_EDX_PSE36 2381 //| RT_BIT_32(18) - reserved 2382 //| RT_BIT_32(19) - reserved 2383 //| X86_CPUID_EXT_FEATURE_EDX_NX - enabled later by PGM 2384 //| RT_BIT_32(21) - reserved 2385 //| X86_CPUID_AMD_FEATURE_EDX_AXMMX 2386 | X86_CPUID_AMD_FEATURE_EDX_MMX 2387 | X86_CPUID_AMD_FEATURE_EDX_FXSR 2388 | X86_CPUID_AMD_FEATURE_EDX_FFXSR 2389 //| X86_CPUID_EXT_FEATURE_EDX_PAGE1GB 2390 | X86_CPUID_EXT_FEATURE_EDX_RDTSCP 2391 //| RT_BIT_32(28) - reserved 2392 //| X86_CPUID_EXT_FEATURE_EDX_LONG_MODE - turned on when necessary 2393 | X86_CPUID_AMD_FEATURE_EDX_3DNOW_EX 2394 | X86_CPUID_AMD_FEATURE_EDX_3DNOW 2395 ; 2396 pExtFeatureLeaf->uEcx &= 0 2397 //| X86_CPUID_EXT_FEATURE_ECX_LAHF_SAHF 2398 //| X86_CPUID_AMD_FEATURE_ECX_CMPL - set below if applicable. 2399 //| X86_CPUID_AMD_FEATURE_ECX_SVM - not virtualized. 2400 //| X86_CPUID_AMD_FEATURE_ECX_EXT_APIC 2401 /* Note: This could prevent teleporting from AMD to Intel CPUs! */ 2402 | X86_CPUID_AMD_FEATURE_ECX_CR8L /* expose lock mov cr0 = mov cr8 hack for guests that can use this feature to access the TPR. */ 2403 //| X86_CPUID_AMD_FEATURE_ECX_ABM 2404 //| X86_CPUID_AMD_FEATURE_ECX_SSE4A 2405 //| X86_CPUID_AMD_FEATURE_ECX_MISALNSSE 2406 //| X86_CPUID_AMD_FEATURE_ECX_3DNOWPRF 2407 //| X86_CPUID_AMD_FEATURE_ECX_OSVW 2408 //| X86_CPUID_AMD_FEATURE_ECX_IBS 2409 //| X86_CPUID_AMD_FEATURE_ECX_SSE5 2410 //| X86_CPUID_AMD_FEATURE_ECX_SKINIT 2411 //| X86_CPUID_AMD_FEATURE_ECX_WDT 2412 //| RT_BIT_32(14) - reserved 2413 //| X86_CPUID_AMD_FEATURE_ECX_LWP - not supported 2414 //| X86_CPUID_AMD_FEATURE_ECX_FMA4 - not yet virtualized. 2415 //| RT_BIT_32(17) - reserved 2416 //| RT_BIT_32(18) - reserved 2417 //| X86_CPUID_AMD_FEATURE_ECX_NODEID - not yet virtualized. 2418 //| RT_BIT_32(20) - reserved 2419 //| X86_CPUID_AMD_FEATURE_ECX_TBM - not yet virtualized. 2420 //| X86_CPUID_AMD_FEATURE_ECX_TOPOEXT - not yet virtualized. 2421 //| RT_BIT_32(23) - reserved 2422 //| RT_BIT_32(24) - reserved 2423 //| RT_BIT_32(25) - reserved 2424 //| RT_BIT_32(26) - reserved 2425 //| RT_BIT_32(27) - reserved 2426 //| RT_BIT_32(28) - reserved 2427 //| RT_BIT_32(29) - reserved 2428 //| RT_BIT_32(30) - reserved 2429 //| RT_BIT_32(31) - reserved 2430 ; 2431 #ifdef VBOX_WITH_MULTI_CORE 2432 if ( pVM->cCpus > 1 2433 && pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) 2434 pExtFeatureLeaf->uEcx |= X86_CPUID_AMD_FEATURE_ECX_CMPL; /* CmpLegacy */ 2435 #endif 2436 2437 if (pCpum->u8PortableCpuIdLevel > 0) 2150 2438 { 2151 2439 PORTABLE_DISABLE_FEATURE_BIT(1, pExtFeatureLeaf->uEcx, CR8L, X86_CPUID_AMD_FEATURE_ECX_CR8L); … … 2157 2445 PORTABLE_DISABLE_FEATURE_BIT(3, pExtFeatureLeaf->uEcx, CMOV, X86_CPUID_AMD_FEATURE_EDX_CMOV); 2158 2446 2159 Assert(!(pExtFeatureLeaf->uEcx & ( X86_CPUID_AMD_FEATURE_ECX_CMPL 2160 | X86_CPUID_AMD_FEATURE_ECX_SVM 2447 Assert(!(pExtFeatureLeaf->uEcx & ( X86_CPUID_AMD_FEATURE_ECX_SVM 2161 2448 | X86_CPUID_AMD_FEATURE_ECX_EXT_APIC 2162 2449 | X86_CPUID_AMD_FEATURE_ECX_CR8L … … 2183 2470 } 2184 2471 } 2185 2186 /* 2187 * Hide HTT, multicode, SMP, whatever. 2188 * (APIC-ID := 0 and #LogCpus := 0) 2189 */ 2190 pStdFeatureLeaf->uEbx &= 0x0000ffff; 2191 #ifdef VBOX_WITH_MULTI_CORE 2192 if (pVM->cCpus > 1) 2193 { 2194 /* If CPUID Fn0000_0001_EDX[HTT] = 1 then LogicalProcessorCount is the number of threads per CPU core times the number of CPU cores per processor */ 2195 pStdFeatureLeaf->uEbx |= (pVM->cCpus << 16); 2196 pStdFeatureLeaf->uEdx |= X86_CPUID_FEATURE_EDX_HTT; /* necessary for hyper-threading *or* multi-core CPUs */ 2197 } 2198 #endif 2472 pExtFeatureLeaf = NULL; /* Must refetch! */ 2473 2199 2474 2200 2475 /* Cpuid 2: 2201 * Intel: Cache and TLB information2476 * Intel: (Nondeterministic) Cache and TLB information 2202 2477 * AMD: Reserved 2203 2478 * VIA: Reserved 2204 * Safe to expose; restrict the number of calls to 1 for the portable case. 2205 */ 2206 PCPUMCPUIDLEAF pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 2, 0); 2207 if ( pCPUM->u8PortableCpuIdLevel > 0 2208 && pCurLeaf 2209 && (pCurLeaf->uEax & 0xff) > 1) 2210 { 2211 LogRel(("PortableCpuId: Std[2].al: %d -> 1\n", pCurLeaf->uEax & 0xff)); 2212 pCurLeaf->uEax &= UINT32_C(0xfffffffe); 2479 * Safe to expose. Restrict the number of calls to 1 since we don't 2480 * implement this kind of subleaves (is there hardware that does??). 2481 */ 2482 uint32_t uSubLeaf = 0; 2483 PCPUMCPUIDLEAF pCurLeaf; 2484 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 2, uSubLeaf)) != NULL) 2485 { 2486 if ((pCurLeaf->uEax & 0xff) > 1) 2487 { 2488 LogRel(("CpuId: Std[2].al: %d -> 1\n", pCurLeaf->uEax & 0xff)); 2489 pCurLeaf->uEax &= UINT32_C(0xffffff01); 2490 } 2491 uSubLeaf++; 2213 2492 } 2214 2493 … … 2220 2499 * Safe to expose 2221 2500 */ 2222 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 3, 0); 2223 pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1, 0); 2224 if ( !(pStdFeatureLeaf->uEdx & X86_CPUID_FEATURE_EDX_PSN) 2225 && pCurLeaf) 2226 { 2227 pCurLeaf->uEcx = pCurLeaf->uEdx = 0; 2228 if (pCPUM->u8PortableCpuIdLevel > 0) 2229 pCurLeaf->uEax = pCurLeaf->uEbx = 0; 2230 } 2231 2232 /* Cpuid 4: 2233 * Intel: Deterministic Cache Parameters Leaf 2234 * Note: Depends on the ECX input! -> Feeling rather lazy now, so we just return 0 2501 pStdFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 1, 0); 2502 if (!(pStdFeatureLeaf->uEdx & X86_CPUID_FEATURE_EDX_PSN)) 2503 { 2504 uSubLeaf = 0; 2505 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 3, uSubLeaf)) != NULL) 2506 { 2507 pCurLeaf->uEcx = pCurLeaf->uEdx = 0; 2508 if (pCpum->u8PortableCpuIdLevel > 0) 2509 pCurLeaf->uEax = pCurLeaf->uEbx = 0; 2510 uSubLeaf++; 2511 } 2512 } 2513 2514 /* Cpuid 4 + ECX: 2515 * Intel: Deterministic Cache Parameters Leaf. 2235 2516 * AMD: Reserved 2236 2517 * VIA: Reserved … … 2240 2521 * Note: These SMP values are constant regardless of ECX 2241 2522 */ 2242 CPUMCPUIDLEAF NewLeaf; 2243 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 4, 0); 2244 if (pCurLeaf) 2245 { 2246 NewLeaf.uLeaf = 4; 2247 NewLeaf.uSubLeaf = 0; 2248 NewLeaf.fSubLeafMask = 0; 2249 NewLeaf.uEax = 0; 2250 NewLeaf.uEbx = 0; 2251 NewLeaf.uEcx = 0; 2252 NewLeaf.uEdx = 0; 2253 NewLeaf.fFlags = 0; 2523 uSubLeaf = 0; 2524 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 4, uSubLeaf)) != NULL) 2525 { 2526 pCurLeaf->uEax &= UINT32_C(0xffffc000); /* Clear the #maxcores, #threads-sharing-cache (both are #-1).*/ 2254 2527 #ifdef VBOX_WITH_MULTI_CORE 2255 2528 if ( pVM->cCpus > 1 2256 && pC PUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL)2529 && pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL) 2257 2530 { 2258 2531 AssertReturn(pVM->cCpus <= 64, VERR_TOO_MANY_CPUS); 2259 2532 /* One logical processor with possibly multiple cores. */ 2260 2533 /* See http://www.intel.com/Assets/PDF/appnote/241618.pdf p. 29 */ 2261 NewLeaf.uEax |= ((pVM->cCpus - 1) << 26);/* 6 bits only -> 64 cores! */2534 pCurLeaf->uEax |= pVM->cCpus <= 0x40 ? ((pVM->cCpus - 1) << 26) : UINT32_C(0xfc000000); /* 6 bits only -> 64 cores! */ 2262 2535 } 2263 2536 #endif 2264 rc = cpumR3CpuIdInsert(NULL /* pVM */, &pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, &NewLeaf); 2265 AssertLogRelRCReturn(rc, rc); 2537 uSubLeaf++; 2266 2538 } 2267 2539 … … 2275 2547 * Safe to expose 2276 2548 */ 2277 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 5, 0);2278 if (pCurLeaf)2279 { 2280 pStdFeatureLeaf = cpumR3CpuIdGet Leaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1, 0);2549 uSubLeaf = 0; 2550 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 5, uSubLeaf)) != NULL) 2551 { 2552 pStdFeatureLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 1, 0); 2281 2553 if (!(pStdFeatureLeaf->uEcx & X86_CPUID_FEATURE_ECX_MONITOR)) 2282 2554 pCurLeaf->uEax = pCurLeaf->uEbx = 0; 2283 2555 2284 2556 pCurLeaf->uEcx = pCurLeaf->uEdx = 0; 2285 if ( fMWaitExtensions)2557 if (pConfig->fMWaitExtensions) 2286 2558 { 2287 2559 pCurLeaf->uEcx = X86_CPUID_MWAIT_ECX_EXT | X86_CPUID_MWAIT_ECX_BREAKIRQIF0; … … 2301 2573 else 2302 2574 pCurLeaf->uEcx = pCurLeaf->uEdx = 0; 2303 } 2575 uSubLeaf++; 2576 } 2577 2578 /* Cpuid 6: Digital Thermal Sensor and Power Management Paramenters. 2579 * Intel: Various stuff. 2580 * AMD: EAX, EBX, EDX - reserved. 2581 * ECX - Bit zero is EffFreq, indicating MSR_0000_00e7 and MSR_0000_00e8 2582 * present. Same as intel. 2583 * VIA: ?? 2584 * 2585 * We clear everything here for now. 2586 */ 2587 cpumR3CpuIdZeroLeaf(pCpum, 6); 2588 2589 /* Cpuid 7 + ECX: Structured Extended Feature Flags Enumeration 2590 * EAX: Number of sub leaves. 2591 * EBX+ECX+EDX: Feature flags 2592 * 2593 * We only have documentation for one sub-leaf, so clear all other (no need 2594 * to remove them as such, just set them to zero). 2595 * 2596 * Note! When enabling new features the Synthetic CPU and Portable CPUID 2597 * options may require adjusting (i.e. stripping what was enabled). 2598 */ 2599 uSubLeaf = 0; 2600 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 7, uSubLeaf)) != NULL) 2601 { 2602 switch (uSubLeaf) 2603 { 2604 case 0: 2605 { 2606 pCurLeaf->uEax = 0; /* Max ECX input is 0. */ 2607 pCurLeaf->uEbx &= 0 2608 //| X86_CPUID_STEXT_FEATURE_EBX_FSGSBASE RT_BIT(0) 2609 //| X86_CPUID_STEXT_FEATURE_EBX_TSC_ADJUST RT_BIT(1) 2610 //| RT_BIT(2) - reserved 2611 //| X86_CPUID_STEXT_FEATURE_EBX_BMI1 RT_BIT(3) 2612 //| X86_CPUID_STEXT_FEATURE_EBX_HLE RT_BIT(4) 2613 //| X86_CPUID_STEXT_FEATURE_EBX_AVX2 RT_BIT(5) 2614 //| RT_BIT(6) - reserved 2615 //| X86_CPUID_STEXT_FEATURE_EBX_SMEP RT_BIT(7) 2616 //| X86_CPUID_STEXT_FEATURE_EBX_BMI2 RT_BIT(8) 2617 //| X86_CPUID_STEXT_FEATURE_EBX_ERMS RT_BIT(9) 2618 //| X86_CPUID_STEXT_FEATURE_EBX_INVPCID RT_BIT(10) 2619 //| X86_CPUID_STEXT_FEATURE_EBX_RTM RT_BIT(11) 2620 //| X86_CPUID_STEXT_FEATURE_EBX_PQM RT_BIT(12) 2621 //| X86_CPUID_STEXT_FEATURE_EBX_DEPR_FPU_CS_DS RT_BIT(13) 2622 //| X86_CPUID_STEXT_FEATURE_EBX_MPE RT_BIT(14) 2623 //| X86_CPUID_STEXT_FEATURE_EBX_PQE RT_BIT(15) 2624 //| X86_CPUID_STEXT_FEATURE_EBX_AVX512F RT_BIT(16) 2625 //| RT_BIT(17) - reserved 2626 //| X86_CPUID_STEXT_FEATURE_EBX_RDSEED RT_BIT(18) 2627 //| X86_CPUID_STEXT_FEATURE_EBX_ADX RT_BIT(19) 2628 //| X86_CPUID_STEXT_FEATURE_EBX_SMAP RT_BIT(20) 2629 //| RT_BIT(21) - reserved 2630 //| RT_BIT(22) - reserved 2631 //| X86_CPUID_STEXT_FEATURE_EBX_CLFLUSHOPT RT_BIT(23) 2632 //| RT_BIT(24) - reserved 2633 //| X86_CPUID_STEXT_FEATURE_EBX_INTEL_PT RT_BIT(25) 2634 //| X86_CPUID_STEXT_FEATURE_EBX_AVX512PF RT_BIT(26) 2635 //| X86_CPUID_STEXT_FEATURE_EBX_AVX512ER RT_BIT(27) 2636 //| X86_CPUID_STEXT_FEATURE_EBX_AVX512CD RT_BIT(28) 2637 //| X86_CPUID_STEXT_FEATURE_EBX_SHA RT_BIT(29) 2638 //| RT_BIT(30) - reserved 2639 //| RT_BIT(31) - reserved 2640 ; 2641 pCurLeaf->uEcx &= 0 2642 //| X86_CPUID_STEXT_FEATURE_ECX_PREFETCHWT1 - we do not do vector functions yet. 2643 ; 2644 pCurLeaf->uEdx &= 0; 2645 2646 if (pCpum->u8PortableCpuIdLevel > 0) 2647 { 2648 PORTABLE_DISABLE_FEATURE_BIT(2, pCurLeaf->uEcx, PREFETCHWT1, X86_CPUID_STEXT_FEATURE_ECX_PREFETCHWT1); 2649 } 2650 break; 2651 } 2652 2653 default: 2654 /* Invalid index, all values are zero. */ 2655 pCurLeaf->uEax = 0; 2656 pCurLeaf->uEbx = 0; 2657 pCurLeaf->uEcx = 0; 2658 pCurLeaf->uEdx = 0; 2659 break; 2660 } 2661 uSubLeaf++; 2662 } 2663 2664 /* Cpuid 8: Marked as reserved by Intel and AMD. 2665 * We zero this since we don't know what it may have been used for. 2666 */ 2667 cpumR3CpuIdZeroLeaf(pCpum, 8); 2668 2669 /* Cpuid 9: Direct Cache Access (DCA) Parameters 2670 * Intel: EAX - Value of PLATFORM_DCA_CAP bits. 2671 * EBX, ECX, EDX - reserved. 2672 * AMD: Reserved 2673 * VIA: ?? 2674 * 2675 * We zero this. 2676 */ 2677 cpumR3CpuIdZeroLeaf(pCpum, 9); 2678 2679 /* Cpuid 0xa: Architectural Performance Monitor Features 2680 * Intel: EAX - Value of PLATFORM_DCA_CAP bits. 2681 * EBX, ECX, EDX - reserved. 2682 * AMD: Reserved 2683 * VIA: ?? 2684 * 2685 * We zero this, for now at least. 2686 */ 2687 cpumR3CpuIdZeroLeaf(pCpum, 10); 2688 2689 /* Cpuid 0xb+ECX: x2APIC Features / Processor Topology. 2690 * Intel: EAX - APCI ID shift right for next level. 2691 * EBX - Factory configured cores/threads at this level. 2692 * ECX - Level number (same as input) and level type (1,2,0). 2693 * EDX - Extended initial APIC ID. 2694 * AMD: Reserved 2695 * VIA: ?? 2696 */ 2697 uSubLeaf = 0; 2698 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 11, uSubLeaf)) != NULL) 2699 { 2700 if (pCurLeaf->fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID) 2701 { 2702 uint8_t bLevelType = RT_BYTE2(pCurLeaf->uEcx); 2703 if (bLevelType == 1) 2704 { 2705 /* Thread level - we don't do threads at the moment. */ 2706 pCurLeaf->uEax = 0; /** @todo is this correct? Real CPUs never do 0 here, I think... */ 2707 pCurLeaf->uEbx = 1; 2708 } 2709 else if (bLevelType == 2) 2710 { 2711 /* Core level. */ 2712 pCurLeaf->uEax = 1; /** @todo real CPUs are supposed to be in the 4-6 range, not 1. Our APIC ID assignments are a little special... */ 2713 #ifdef VBOX_WITH_MULTI_CORE 2714 while (RT_BIT_32(pCurLeaf->uEax) < pVM->cCpus) 2715 pCurLeaf->uEax++; 2716 #endif 2717 pCurLeaf->uEbx = pVM->cCpus; 2718 } 2719 else 2720 { 2721 AssertLogRelMsg(bLevelType == 0, ("bLevelType=%#x uSubLeaf=%#x\n", bLevelType, uSubLeaf)); 2722 pCurLeaf->uEax = 0; 2723 pCurLeaf->uEbx = 0; 2724 pCurLeaf->uEcx = 0; 2725 } 2726 pCurLeaf->uEcx = (pCurLeaf->uEcx & UINT32_C(0xffffff00)) | (uSubLeaf & 0xff); 2727 pCurLeaf->uEdx = 0; /* APIC ID is filled in by CPUMGetGuestCpuId() at runtime. Init for EMT(0) as usual. */ 2728 } 2729 else 2730 { 2731 Assert(pCpum->GuestFeatures.enmCpuVendor != CPUMCPUVENDOR_INTEL); 2732 pCurLeaf->uEax = 0; 2733 pCurLeaf->uEbx = 0; 2734 pCurLeaf->uEcx = 0; 2735 pCurLeaf->uEdx = 0; 2736 } 2737 uSubLeaf++; 2738 } 2739 2740 /* Cpuid 0xc: Marked as reserved by Intel and AMD. 2741 * We zero this since we don't know what it may have been used for. 2742 */ 2743 cpumR3CpuIdZeroLeaf(pCpum, 12); 2744 2745 /* Cpuid 0xd + ECX: Processor Extended State Enumeration 2746 * ECX=0: EAX - Valid bits in XCR0[31:0]. 2747 * EBX - Maximum state size as per current XCR0 value. 2748 * ECX - Maximum state size for all supported features. 2749 * EDX - Valid bits in XCR0[63:32]. 2750 * ECX=1: EAX - Various X-features. 2751 * EBX - Maximum state size as per current XCR0|IA32_XSS value. 2752 * ECX - Valid bits in IA32_XSS[31:0]. 2753 * EDX - Valid bits in IA32_XSS[63:32]. 2754 * ECX=N, where N in 2..63 and indicates a bit in XCR0 and/or IA32_XSS, 2755 * if the bit invalid all four registers are set to zero. 2756 * EAX - The state size for this feature. 2757 * EBX - The state byte offset of this feature. 2758 * ECX - Bit 0 indicates whether this sub-leaf maps to a valid IA32_XSS bit (=1) or a valid XCR0 bit (=0). 2759 * EDX - Reserved, but is set to zero if invalid sub-leaf index. 2760 * 2761 * Clear them all as we don't currently implement extended CPU state. 2762 */ 2763 uSubLeaf = 0; 2764 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, 13, uSubLeaf)) != NULL) 2765 { 2766 pCurLeaf->uEax = 0; 2767 pCurLeaf->uEbx = 0; 2768 pCurLeaf->uEcx = 0; 2769 pCurLeaf->uEdx = 0; 2770 uSubLeaf++; 2771 } 2772 2773 /* Cpuid 0xe: Marked as reserved by Intel and AMD. 2774 * We zero this since we don't know what it may have been used for. 2775 */ 2776 cpumR3CpuIdZeroLeaf(pCpum, 14); 2777 2778 /* Cpuid 0xf + ECX: Platform qualifity of service monitoring (PQM). 2779 * We zero this as we don't currently virtualize PQM. 2780 */ 2781 cpumR3CpuIdZeroLeaf(pCpum, 15); 2782 2783 /* Cpuid 0x10 + ECX: Platform qualifity of service enforcement (PQE). 2784 * We zero this as we don't currently virtualize PQE. 2785 */ 2786 cpumR3CpuIdZeroLeaf(pCpum, 16); 2787 2788 /* Cpuid 0x11: Marked as reserved by Intel and AMD. 2789 * We zero this since we don't know what it may have been used for. 2790 */ 2791 cpumR3CpuIdZeroLeaf(pCpum, 17); 2792 2793 /* Cpuid 0x12 + ECX: SGX resource enumeration. 2794 * We zero this as we don't currently virtualize this. 2795 */ 2796 cpumR3CpuIdZeroLeaf(pCpum, 18); 2797 2798 /* Cpuid 0x13: Marked as reserved by Intel and AMD. 2799 * We zero this since we don't know what it may have been used for. 2800 */ 2801 cpumR3CpuIdZeroLeaf(pCpum, 19); 2802 2803 /* Cpuid 0x14 + ECX: Processor Trace (PT) capability enumeration. 2804 * We zero this as we don't currently virtualize this. 2805 */ 2806 cpumR3CpuIdZeroLeaf(pCpum, 20); 2807 2808 /* Cpuid 0x15: Timestamp Counter / Core Crystal Clock info. 2809 * Intel: uTscFrequency = uCoreCrystalClockFrequency * EBX / EAX. 2810 * EAX - denominator (unsigned). 2811 * EBX - numerator (unsigned). 2812 * ECX, EDX - reserved. 2813 * AMD: Reserved / undefined / not implemented. 2814 * VIA: Reserved / undefined / not implemented. 2815 * We zero this as we don't currently virtualize this. 2816 */ 2817 cpumR3CpuIdZeroLeaf(pCpum, 21); 2818 2819 /* Cpuid 0x16: Processor frequency info 2820 * Intel: EAX - Core base frequency in MHz. 2821 * EBX - Core maximum frequency in MHz. 2822 * ECX - Bus (reference) frequency in MHz. 2823 * EDX - Reserved. 2824 * AMD: Reserved / undefined / not implemented. 2825 * VIA: Reserved / undefined / not implemented. 2826 * We zero this as we don't currently virtualize this. 2827 */ 2828 cpumR3CpuIdZeroLeaf(pCpum, 22); 2829 2830 /* Cpuid 0x17..0x10000000: Unknown. 2831 * We don't know these and what they mean, so remove them. */ 2832 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2833 UINT32_C(0x00000017), UINT32_C(0x0fffffff)); 2834 2835 2836 /* CpuId 0x40000000..0x4fffffff: Reserved for hypervisor/emulator. 2837 * We remove all these as we're a hypervisor and must provide our own. 2838 */ 2839 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 2840 UINT32_C(0x40000000), UINT32_C(0x4fffffff)); 2841 2842 2843 /* Cpuid 0x80000000 is harmless. */ 2844 2845 /* Cpuid 0x80000001 is handled with cpuid 1 way up above. */ 2846 2847 /* Cpuid 0x80000002...0x80000004 contains the processor name and is considered harmless. */ 2304 2848 2305 2849 /* Cpuid 0x800000005 & 0x800000006 contain information about L1, L2 & L3 cache and TLB identifiers. 2306 2850 * Safe to pass on to the guest. 2307 2851 * 2852 * AMD: 0x800000005 L1 cache information 2853 * 0x800000006 L2/L3 cache information 2308 2854 * Intel: 0x800000005 reserved 2309 2855 * 0x800000006 L2 cache information 2310 * AMD: 0x800000005 L1 cache information2311 * 0x800000006 L2/L3 cache information2312 2856 * VIA: 0x800000005 TLB and L1 cache information 2313 2857 * 0x800000006 L2 cache information 2314 2858 */ 2315 2859 2316 /* Cpuid 0x800000007: 2317 * Intel: Reserved 2318 * AMD: EAX, EBX, ECX - reserved 2319 * EDX: Advanced Power Management Information 2320 * VIA: Reserved 2321 */ 2322 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0x80000007), 0); 2323 if (pCurLeaf) 2324 { 2325 Assert(pCPUM->GuestFeatures.enmCpuVendor != CPUMCPUVENDOR_INVALID); 2326 2860 /* Cpuid 0x800000007: Advanced Power Management Information. 2861 * AMD: EAX: Processor feedback capabilities. 2862 * EBX: RAS capabilites. 2863 * ECX: Advanced power monitoring interface. 2864 * EDX: Enhanced power management capabilities. 2865 * Intel: EAX, EBX, ECX - reserved. 2866 * EDX - Invariant TSC indicator supported (bit 8), the rest is reserved. 2867 * VIA: Reserved 2868 * We let the guest see EDX_TSCINVAR (and later maybe EDX_EFRO). Actually, we should set EDX_TSCINVAR. 2869 */ 2870 uSubLeaf = 0; 2871 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x80000007), uSubLeaf)) != NULL) 2872 { 2327 2873 pCurLeaf->uEax = pCurLeaf->uEbx = pCurLeaf->uEcx = 0; 2328 2329 if (pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) 2330 { 2331 /* Only expose the TSC invariant capability bit to the guest. */ 2332 pCurLeaf->uEdx &= 0 2333 //| X86_CPUID_AMD_ADVPOWER_EDX_TS 2334 //| X86_CPUID_AMD_ADVPOWER_EDX_FID 2335 //| X86_CPUID_AMD_ADVPOWER_EDX_VID 2336 //| X86_CPUID_AMD_ADVPOWER_EDX_TTP 2337 //| X86_CPUID_AMD_ADVPOWER_EDX_TM 2338 //| X86_CPUID_AMD_ADVPOWER_EDX_STC 2339 //| X86_CPUID_AMD_ADVPOWER_EDX_MC 2340 //| X86_CPUID_AMD_ADVPOWER_EDX_HWPSTATE 2341 #if 0 2342 /* 2874 if (pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) 2875 { 2876 pCurLeaf->uEdx &= 0 2877 //| X86_CPUID_AMD_ADVPOWER_EDX_TS 2878 //| X86_CPUID_AMD_ADVPOWER_EDX_FID 2879 //| X86_CPUID_AMD_ADVPOWER_EDX_VID 2880 //| X86_CPUID_AMD_ADVPOWER_EDX_TTP 2881 //| X86_CPUID_AMD_ADVPOWER_EDX_TM 2882 //| X86_CPUID_AMD_ADVPOWER_EDX_STC 2883 //| X86_CPUID_AMD_ADVPOWER_EDX_MC 2884 //| X86_CPUID_AMD_ADVPOWER_EDX_HWPSTATE 2885 #if 0 /* 2343 2886 * We don't expose X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR, because newer 2344 2887 * Linux kernels blindly assume that the AMD performance counters work … … 2346 2889 * bit for them though.) 2347 2890 */ 2348 | X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR 2891 /** @todo need to recheck this with new MSR emulation. */ 2892 | X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR 2349 2893 #endif 2350 | 0; 2894 //| X86_CPUID_AMD_ADVPOWER_EDX_CPB RT_BIT(9) 2895 //| X86_CPUID_AMD_ADVPOWER_EDX_EFRO RT_BIT(10) 2896 //| X86_CPUID_AMD_ADVPOWER_EDX_PFI RT_BIT(11) 2897 //| X86_CPUID_AMD_ADVPOWER_EDX_PA RT_BIT(12) 2898 | 0; 2351 2899 } 2352 2900 else 2353 pCurLeaf->uEdx = 0; 2354 } 2355 2356 /* Cpuid 0x800000008: 2357 * Intel: EAX: Virtual/Physical address Size 2358 * EBX, ECX, EDX - reserved 2901 pCurLeaf->uEdx &= X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR; 2902 if (pConfig->fInvariantTsc) 2903 pCurLeaf->uEdx |= X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR; 2904 uSubLeaf++; 2905 } 2906 2907 /* Cpuid 0x80000008: 2359 2908 * AMD: EBX, EDX - reserved 2360 2909 * EAX: Virtual/Physical/Guest address Size 2361 2910 * ECX: Number of cores + APICIdCoreIdSize 2911 * Intel: EAX: Virtual/Physical address Size 2912 * EBX, ECX, EDX - reserved 2362 2913 * VIA: EAX: Virtual/Physical address Size 2363 2914 * EBX, ECX, EDX - reserved 2364 */ 2365 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0x80000008), 0); 2366 if (pCurLeaf) 2367 { 2368 /* Only expose the virtual and physical address sizes to the guest. */ 2369 pCurLeaf->uEax &= UINT32_C(0x0000ffff); 2370 pCurLeaf->uEbx = pCurLeaf->uEdx = 0; /* reserved */ 2371 /* Set APICIdCoreIdSize to zero (use legacy method to determine the number of cores per cpu) 2372 * NC (0-7) Number of cores; 0 equals 1 core */ 2915 * 2916 * We only expose the virtual+pysical address size to the guest atm. 2917 * On AMD we set the core count, but not the apic id stuff as we're 2918 * currently not doing the apic id assignments in a complatible manner. 2919 */ 2920 uSubLeaf = 0; 2921 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x80000008), uSubLeaf)) != NULL) 2922 { 2923 pCurLeaf->uEax &= UINT32_C(0x0000ffff); /* Virtual & physical address sizes only. */ 2924 pCurLeaf->uEbx = 0; /* reserved */ 2925 pCurLeaf->uEdx = 0; /* reserved */ 2926 2927 /* Set APICIdCoreIdSize to zero (use legacy method to determine the number of cores per cpu). 2928 * Set core count to 0, indicating 1 core. Adjust if we're in multi core mode on AMD. */ 2373 2929 pCurLeaf->uEcx = 0; 2374 2930 #ifdef VBOX_WITH_MULTI_CORE 2375 if ( pVM->cCpus > 1 2376 && pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) 2377 { 2378 /* Legacy method to determine the number of cores. */ 2379 pCurLeaf->uEcx |= (pVM->cCpus - 1); /* NC: Number of CPU cores - 1; 8 bits */ 2380 pExtFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 2381 UINT32_C(0x80000001), 0); 2382 if (pExtFeatureLeaf) 2383 pExtFeatureLeaf->uEcx |= X86_CPUID_AMD_FEATURE_ECX_CMPL; 2384 } 2931 if ( pVM->cCpus > 1 2932 && pCpum->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_AMD) 2933 pCurLeaf->uEcx |= (pVM->cCpus - 1) & UINT32_C(0xff); 2385 2934 #endif 2386 } 2387 2935 uSubLeaf++; 2936 } 2937 2938 /* Cpuid 0x80000009: Reserved 2939 * We zero this since we don't know what it may have been used for. 2940 */ 2941 cpumR3CpuIdZeroLeaf(pCpum, UINT32_C(0x80000009)); 2942 2943 /* Cpuid 0x8000000a: SVM Information 2944 * AMD: EAX - SVM revision. 2945 * EBX - Number of ASIDs. 2946 * ECX - Reserved. 2947 * EDX - SVM Feature identification. 2948 * We clear all as we currently does not virtualize SVM. 2949 */ 2950 cpumR3CpuIdZeroLeaf(pCpum, UINT32_C(0x8000000a)); 2951 2952 /* Cpuid 0x8000000b thru 0x80000018: Reserved 2953 * We clear these as we don't know what purpose they might have. */ 2954 for (uint32_t uLeaf = UINT32_C(0x8000000b); uLeaf <= UINT32_C(0x80000018); uLeaf++) 2955 cpumR3CpuIdZeroLeaf(pCpum, uLeaf); 2956 2957 /* Cpuid 0x80000019: TLB configuration 2958 * Seems to be harmless, pass them thru as is. */ 2959 2960 /* Cpuid 0x8000001a: Peformance optimization identifiers. 2961 * Strip anything we don't know what is or addresses feature we don't implement. */ 2962 uSubLeaf = 0; 2963 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x8000001a), uSubLeaf)) != NULL) 2964 { 2965 pCurLeaf->uEax &= RT_BIT_32(0) /* FP128 - use 1x128-bit instead of 2x64-bit. */ 2966 | RT_BIT_32(1) /* MOVU - Prefere unaligned MOV over MOVL + MOVH. */ 2967 //| RT_BIT_32(2) /* FP256 - use 1x256-bit instead of 2x128-bit. */ 2968 ; 2969 pCurLeaf->uEbx = 0; /* reserved */ 2970 pCurLeaf->uEcx = 0; /* reserved */ 2971 pCurLeaf->uEdx = 0; /* reserved */ 2972 uSubLeaf++; 2973 } 2974 2975 /* Cpuid 0x8000001b: Instruct based sampling (IBS) information. 2976 * Clear this as we don't currently virtualize this feature. */ 2977 cpumR3CpuIdZeroLeaf(pCpum, UINT32_C(0x8000001b)); 2978 2979 /* Cpuid 0x8000001c: Lightweight profiling (LWP) information. 2980 * Clear this as we don't currently virtualize this feature. */ 2981 cpumR3CpuIdZeroLeaf(pCpum, UINT32_C(0x8000001c)); 2982 2983 /* Cpuid 0x8000001d+ECX: Get cache configuration descriptors. 2984 * We need to sanitize the cores per cache (EAX[25:14]). 2985 * 2986 * This is very much the same as Intel's CPUID(4) leaf, except EAX[31:26] 2987 * and EDX[2] are reserved here, and EAX[14:25] is documented having a 2988 * slightly different meaning. 2989 */ 2990 uSubLeaf = 0; 2991 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x8000001d), uSubLeaf)) != NULL) 2992 { 2993 #ifdef VBOX_WITH_MULTI_CORE 2994 uint32_t cCores = ((pCurLeaf->uEax >> 14) & 0xfff) + 1; 2995 if (cCores > pVM->cCpus) 2996 cCores = pVM->cCpus; 2997 pCurLeaf->uEax &= UINT32_C(0x00003fff); 2998 pCurLeaf->uEax |= ((cCores - 1) & 0xfff) << 14; 2999 #else 3000 pCurLeaf->uEax &= UINT32_C(0x00003fff); 3001 #endif 3002 uSubLeaf++; 3003 } 3004 3005 /* Cpuid 0x8000001e: Get APIC / unit / node information. 3006 * If AMD, we configure it for our layout (on EMT(0)). In the multi-core 3007 * setup, we have one compute unit with all the cores in it. Single node. 3008 */ 3009 uSubLeaf = 0; 3010 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0x8000001e), uSubLeaf)) != NULL) 3011 { 3012 pCurLeaf->uEax = 0; /* Extended APIC ID = EMT(0).idApic (== 0). */ 3013 if (pCurLeaf->fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID) 3014 { 3015 #ifdef VBOX_WITH_MULTI_CORE 3016 pCurLeaf->uEbx = pVM->cCpus < 0x100 3017 ? (pVM->cCpus - 1) << 8 : UINT32_C(0x0000ff00); /* Compute unit ID 0, core per unit. */ 3018 #else 3019 pCurLeaf->uEbx = 0; /* Compute unit ID 0, 1 core per unit. */ 3020 #endif 3021 pCurLeaf->uEcx = 0; /* Node ID 0, 1 node per CPU. */ 3022 } 3023 else 3024 { 3025 Assert(pCpum->GuestFeatures.enmCpuVendor != CPUMCPUVENDOR_AMD); 3026 pCurLeaf->uEbx = 0; /* Reserved. */ 3027 pCurLeaf->uEcx = 0; /* Reserved. */ 3028 } 3029 pCurLeaf->uEdx = 0; /* Reserved. */ 3030 uSubLeaf++; 3031 } 3032 3033 /* Cpuid 0x8000001f...0x8ffffffd: Unknown. 3034 * We don't know these and what they mean, so remove them. */ 3035 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 3036 UINT32_C(0x8000001f), UINT32_C(0x8ffffffd)); 3037 3038 /* Cpuid 0x8ffffffe: Mystery AMD K6 leaf. 3039 * Just pass it thru for now. */ 3040 3041 /* Cpuid 0x8fffffff: Mystery hammer time leaf! 3042 * Just pass it thru for now. */ 3043 3044 /* Cpuid 0xc0000000: Centaur stuff. 3045 * Harmless, pass it thru. */ 3046 3047 /* Cpuid 0xc0000001: Centaur features. 3048 * VIA: EAX - Family, model, stepping. 3049 * EDX - Centaur extended feature flags. Nothing interesting, except may 3050 * FEMMS (bit 5), but VIA marks it as 'reserved', so never mind. 3051 * EBX, ECX - reserved. 3052 * We keep EAX but strips the rest. 3053 */ 3054 uSubLeaf = 0; 3055 while ((pCurLeaf = cpumR3CpuIdGetExactLeaf(pCpum, UINT32_C(0xc0000001), uSubLeaf)) != NULL) 3056 { 3057 pCurLeaf->uEbx = 0; 3058 pCurLeaf->uEcx = 0; 3059 pCurLeaf->uEdx = 0; /* Bits 0 thru 9 are documented on sandpil.org, but we don't want them, except maybe 5 (FEMMS). */ 3060 uSubLeaf++; 3061 } 3062 3063 /* Cpuid 0xc0000002: Old Centaur Current Performance Data. 3064 * We only have fixed stale values, but should be harmless. */ 3065 3066 /* Cpuid 0xc0000003: Reserved. 3067 * We zero this since we don't know what it may have been used for. 3068 */ 3069 cpumR3CpuIdZeroLeaf(pCpum, UINT32_C(0xc0000003)); 3070 3071 /* Cpuid 0xc0000004: Centaur Performance Info. 3072 * We only have fixed stale values, but should be harmless. */ 3073 3074 3075 /* Cpuid 0xc0000005...0xcfffffff: Unknown. 3076 * We don't know these and what they mean, so remove them. */ 3077 cpumR3CpuIdRemoveRange(pCpum->GuestInfo.paCpuIdLeavesR3, &pCpum->GuestInfo.cCpuIdLeaves, 3078 UINT32_C(0xc0000005), UINT32_C(0xcfffffff)); 3079 3080 return VINF_SUCCESS; 3081 #undef PORTABLE_DISABLE_FEATURE_BIT 3082 #undef PORTABLE_CLEAR_BITS_WHEN 3083 } 3084 3085 3086 static int cpumR3CpuIdReadConfig(PCPUM pCpum, PCPUMCPUIDCONFIG pConfig, PCFGMNODE pCpumCfg) 3087 { 3088 int rc; 3089 3090 /** @cfgm{/CPUM/SyntheticCpu, boolean, false} 3091 * Enables the Synthetic CPU. The Vendor ID and Processor Name are 3092 * completely overridden by VirtualBox custom strings. Some 3093 * CPUID information is withheld, like the cache info. 3094 * 3095 * This is obsoleted by PortableCpuIdLevel. */ 3096 rc = CFGMR3QueryBoolDef(pCpumCfg, "SyntheticCpu", &pConfig->fSyntheticCpu, false); 3097 AssertRCReturn(rc, rc); 3098 3099 /** @cfgm{/CPUM/PortableCpuIdLevel, 8-bit, 0, 3, 0} 3100 * When non-zero CPUID features that could cause portability issues will be 3101 * stripped. The higher the value the more features gets stripped. Higher 3102 * values should only be used when older CPUs are involved since it may 3103 * harm performance and maybe also cause problems with specific guests. */ 3104 rc = CFGMR3QueryU8Def(pCpumCfg, "PortableCpuIdLevel", &pCpum->u8PortableCpuIdLevel, pConfig->fSyntheticCpu ? 1 : 0); 3105 AssertLogRelRCReturn(rc, rc); 3106 3107 /** @cfgm{/CPUM/GuestCpuName, string} 3108 * The name of the CPU we're to emulate. The default is the host CPU. 3109 * Note! CPUs other than "host" one is currently unsupported. */ 3110 rc = CFGMR3QueryStringDef(pCpumCfg, "GuestCpuName", pConfig->szCpuName, sizeof(pConfig->szCpuName), "host"); 3111 AssertLogRelRCReturn(rc, rc); 3112 3113 /** @cfgm{/CPUM/CMPXCHG16B, boolean, false} 3114 * Expose CMPXCHG16B to the guest if supported by the host. 3115 */ 3116 rc = CFGMR3QueryBoolDef(pCpumCfg, "CMPXCHG16B", &pConfig->fCmpXchg16b, false); 3117 AssertLogRelRCReturn(rc, rc); 3118 3119 /** @cfgm{/CPUM/MONITOR, boolean, true} 3120 * Expose MONITOR/MWAIT instructions to the guest. 3121 */ 3122 rc = CFGMR3QueryBoolDef(pCpumCfg, "MONITOR", &pConfig->fMonitor, true); 3123 AssertLogRelRCReturn(rc, rc); 3124 3125 /** @cfgm{/CPUM/MWaitExtensions, boolean, false} 3126 * Expose MWAIT extended features to the guest. For now we expose just MWAIT 3127 * break on interrupt feature (bit 1). 3128 */ 3129 rc = CFGMR3QueryBoolDef(pCpumCfg, "MWaitExtensions", &pConfig->fMWaitExtensions, false); 3130 AssertLogRelRCReturn(rc, rc); 3131 3132 /** @cfgm{/CPUM/SSE4.1, boolean, true} 3133 * Expose SSE4.1 to the guest if available. 3134 */ 3135 rc = CFGMR3QueryBoolDef(pCpumCfg, "SSE4.1", &pConfig->fSse41, true); 3136 AssertLogRelRCReturn(rc, rc); 3137 3138 /** @cfgm{/CPUM/SSE4.2, boolean, true} 3139 * Expose SSE4.2 to the guest if available. 3140 */ 3141 rc = CFGMR3QueryBoolDef(pCpumCfg, "SSE4.2", &pConfig->fSse42, true); 3142 AssertLogRelRCReturn(rc, rc); 3143 3144 /** @cfgm{/CPUM/NT4LeafLimit, boolean, false} 3145 * Limit the number of standard CPUID leaves to 0..3 to prevent NT4 from 3146 * bugchecking with MULTIPROCESSOR_CONFIGURATION_NOT_SUPPORTED (0x3e). 3147 * This option corresponds somewhat to IA32_MISC_ENABLES.BOOT_NT4[bit 22]. 3148 */ 3149 rc = CFGMR3QueryBoolDef(pCpumCfg, "NT4LeafLimit", &pConfig->fNt4LeafLimit, false); 3150 AssertLogRelRCReturn(rc, rc); 3151 3152 /** @cfgm{/CPUM/InvariantTsc, boolean, complicated} 3153 * Set the invariant TSC flag in 0x80000007 if true, otherwas take default 3154 * action. By default the flag is passed thru as is from the host CPU, except 3155 * on AMD CPUs where it's suppressed to avoid trouble from linux assuming we 3156 * virtualize performance counters. 3157 */ 3158 rc = CFGMR3QueryBoolDef(pCpumCfg, "InvariantTsc", &pConfig->fInvariantTsc, false); 3159 AssertLogRelRCReturn(rc, rc); 3160 3161 /** @cfgm{/CPUM/MaxIntelFamilyModelStep, uint32_t, UINT32_MAX} 3162 * Restrict the reported CPU family+model+stepping of intel CPUs. This is 3163 * probably going to be a temporary hack, so don't depend on this. 3164 * The 1st byte of the value is the stepping, the 2nd byte value is the model 3165 * number and the 3rd byte value is the family, and the 4th value must be zero. 3166 */ 3167 rc = CFGMR3QueryU32Def(pCpumCfg, "MaxIntelFamilyModelStep", &pConfig->uMaxIntelFamilyModelStep, UINT32_MAX); 3168 AssertLogRelRCReturn(rc, rc); 3169 3170 return VINF_SUCCESS; 3171 } 3172 3173 3174 /** 3175 * Initializes the emulated CPU's CPUID & MSR information. 3176 * 3177 * @returns VBox status code. 3178 * @param pVM Pointer to the VM. 3179 */ 3180 int cpumR3InitCpuIdAndMsrs(PVM pVM) 3181 { 3182 PCPUM pCpum = &pVM->cpum.s; 3183 PCFGMNODE pCpumCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM"); 2388 3184 2389 3185 /* 2390 * Limit it the number of entries, zapping the remainder. 3186 * Read the configuration. 3187 */ 3188 CPUMCPUIDCONFIG Config; 3189 RT_ZERO(Config); 3190 int rc = cpumR3CpuIdReadConfig(pCpum, &Config, pCpumCfg); 3191 AssertRCReturn(rc, rc); 3192 3193 /* 3194 * Get the guest CPU data from the database and/or the host. 2391 3195 * 2392 * The limits are masking off stuff about power saving and similar, this 2393 * is perhaps a bit crudely done as there is probably some relatively harmless 2394 * info too in these leaves (like words about having a constant TSC). 2395 */ 2396 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 0, 0); 2397 if (pCurLeaf) 2398 { 2399 if (pCurLeaf->uEax > 5) 2400 { 2401 pCurLeaf->uEax = 5; 2402 cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, 2403 pCurLeaf->uEax + 1, UINT32_C(0x000fffff)); 2404 } 2405 2406 /* NT4 hack, no zapping of extra leaves here. */ 2407 if (fNt4LeafLimit && pCurLeaf->uEax > 3) 2408 pCurLeaf->uEax = 3; 2409 } 2410 2411 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0x80000000), 0); 2412 if (pCurLeaf) 2413 { 2414 if (pCurLeaf->uEax > UINT32_C(0x80000008)) 2415 { 2416 pCurLeaf->uEax = UINT32_C(0x80000008); 2417 cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, 2418 pCurLeaf->uEax + 1, UINT32_C(0x800fffff)); 2419 } 2420 } 3196 * The CPUID and MSRs are currently living on the regular heap to avoid 3197 * fragmenting the hyper heap (and because there isn't/wasn't any realloc 3198 * API for the hyper heap). This means special cleanup considerations. 3199 */ 3200 rc = cpumR3DbGetCpuInfo(Config.szCpuName, &pCpum->GuestInfo); 3201 if (RT_FAILURE(rc)) 3202 return rc == VERR_CPUM_DB_CPU_NOT_FOUND 3203 ? VMSetError(pVM, rc, RT_SRC_POS, 3204 "Info on guest CPU '%s' could not be found. Please, select a different CPU.", Config.szCpuName) 3205 : rc; 3206 3207 /** @cfgm{/CPUM/MSRs/[Name]/[First|Last|Type|Value|...],} 3208 * Overrides the guest MSRs. 3209 */ 3210 rc = cpumR3LoadMsrOverrides(pVM, CFGMR3GetChild(pCpumCfg, "MSRs")); 3211 3212 /** @cfgm{/CPUM/HostCPUID/[000000xx|800000xx|c000000x]/[eax|ebx|ecx|edx],32-bit} 3213 * Overrides the CPUID leaf values (from the host CPU usually) used for 3214 * calculating the guest CPUID leaves. This can be used to preserve the CPUID 3215 * values when moving a VM to a different machine. Another use is restricting 3216 * (or extending) the feature set exposed to the guest. */ 3217 if (RT_SUCCESS(rc)) 3218 rc = cpumR3LoadCpuIdOverrides(pVM, CFGMR3GetChild(pCpumCfg, "HostCPUID"), "HostCPUID"); 3219 3220 if (RT_SUCCESS(rc) && CFGMR3GetChild(pCpumCfg, "CPUID")) /* 2nd override, now discontinued. */ 3221 rc = VMSetError(pVM, VERR_CFGM_CONFIG_UNKNOWN_NODE, RT_SRC_POS, 3222 "Found unsupported configuration node '/CPUM/CPUID/'. " 3223 "Please use IMachine::setCPUIDLeaf() instead."); 2421 3224 2422 3225 /* 2423 * Centaur stuff (VIA). 2424 * 2425 * The important part here (we think) is to make sure the 0xc0000000 2426 * function returns 0xc0000001. As for the features, we don't currently 2427 * let on about any of those... 0xc0000002 seems to be some 2428 * temperature/hz/++ stuff, include it as well (static). 2429 */ 2430 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, UINT32_C(0xc0000000), 0); 2431 if (pCurLeaf) 2432 { 2433 if ( pCurLeaf->uEax >= UINT32_C(0xc0000000) 2434 && pCurLeaf->uEax <= UINT32_C(0xc0000004)) 2435 { 2436 pCurLeaf->uEax = RT_MIN(pCurLeaf->uEax, UINT32_C(0xc0000002)); 2437 cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, 2438 UINT32_C(0xc0000002), UINT32_C(0xc00fffff)); 2439 2440 pCurLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 2441 UINT32_C(0xc0000001), 0); 2442 if (pCurLeaf) 2443 pCurLeaf->uEdx = 0; /* all features hidden */ 2444 } 2445 else 2446 cpumR3CpuIdRemoveRange(pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, 2447 UINT32_C(0xc0000000), UINT32_C(0xc00fffff)); 2448 } 3226 * Pre-explode the CPUID info. 3227 */ 3228 if (RT_SUCCESS(rc)) 3229 rc = cpumR3CpuIdExplodeFeatures(pCpum->GuestInfo.paCpuIdLeavesR3, pCpum->GuestInfo.cCpuIdLeaves, &pCpum->GuestFeatures); 2449 3230 2450 3231 /* 2451 * Hypervisor identification. 2452 * 2453 * We only return minimal information, primarily ensuring that the 2454 * 0x40000000 function returns 0x40000001 and identifying ourselves. 2455 * Hypervisor-specific interface is supported through GIM which will 2456 * modify these leaves if required depending on the GIM provider. 2457 */ 2458 NewLeaf.uLeaf = UINT32_C(0x40000000); 2459 NewLeaf.uSubLeaf = 0; 2460 NewLeaf.fSubLeafMask = 0; 2461 NewLeaf.uEax = UINT32_C(0x40000001); 2462 NewLeaf.uEbx = 0x786f4256 /* 'VBox' */; 2463 NewLeaf.uEcx = 0x786f4256 /* 'VBox' */; 2464 NewLeaf.uEdx = 0x786f4256 /* 'VBox' */; 2465 NewLeaf.fFlags = 0; 2466 rc = cpumR3CpuIdInsert(NULL /* pVM */, &pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, &NewLeaf); 2467 AssertLogRelRCReturn(rc, rc); 2468 2469 NewLeaf.uLeaf = UINT32_C(0x40000001); 2470 NewLeaf.uEax = 0x656e6f6e; /* 'none' */ 2471 NewLeaf.uEbx = 0; 2472 NewLeaf.uEcx = 0; 2473 NewLeaf.uEdx = 0; 2474 NewLeaf.fFlags = 0; 2475 rc = cpumR3CpuIdInsert(NULL /* pVM */, &pCPUM->GuestInfo.paCpuIdLeavesR3, &pCPUM->GuestInfo.cCpuIdLeaves, &NewLeaf); 2476 AssertLogRelRCReturn(rc, rc); 3232 * Sanitize the cpuid information passed on to the guest. 3233 */ 3234 if (RT_SUCCESS(rc)) 3235 { 3236 rc = cpumR3CpuIdSanitize(pVM, pCpum, &Config); 3237 if (RT_SUCCESS(rc)) 3238 { 3239 cpumR3CpuIdLimitLeaves(pCpum, &Config); 3240 cpumR3CpuIdLimitIntelFamModStep(pCpum, &Config); 3241 } 3242 } 2477 3243 2478 3244 /* 2479 * Mini CPU selection support for making Mac OS X happy. 2480 */ 2481 if (pCPUM->GuestFeatures.enmCpuVendor == CPUMCPUVENDOR_INTEL) 2482 { 2483 pStdFeatureLeaf = cpumR3CpuIdGetLeaf(pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves, 1, 0); 2484 uint32_t uCurIntelFamilyModelStep = RT_MAKE_U32_FROM_U8(ASMGetCpuStepping(pStdFeatureLeaf->uEax), 2485 ASMGetCpuModelIntel(pStdFeatureLeaf->uEax), 2486 ASMGetCpuFamily(pStdFeatureLeaf->uEax), 2487 0); 2488 if (uMaxIntelFamilyModelStep < uCurIntelFamilyModelStep) 2489 { 2490 uint32_t uNew = pStdFeatureLeaf->uEax & UINT32_C(0xf0003000); 2491 uNew |= RT_BYTE1(uMaxIntelFamilyModelStep) & 0xf; /* stepping */ 2492 uNew |= (RT_BYTE2(uMaxIntelFamilyModelStep) & 0xf) << 4; /* 4 low model bits */ 2493 uNew |= (RT_BYTE2(uMaxIntelFamilyModelStep) >> 4) << 16; /* 4 high model bits */ 2494 uNew |= (RT_BYTE3(uMaxIntelFamilyModelStep) & 0xf) << 8; /* 4 low family bits */ 2495 if (RT_BYTE3(uMaxIntelFamilyModelStep) > 0xf) /* 8 high family bits, using intel's suggested calculation. */ 2496 uNew |= ( (RT_BYTE3(uMaxIntelFamilyModelStep) - (RT_BYTE3(uMaxIntelFamilyModelStep) & 0xf)) & 0xff ) << 20; 2497 LogRel(("CPU: CPUID(0).EAX %#x -> %#x (uMaxIntelFamilyModelStep=%#x, uCurIntelFamilyModelStep=%#x\n", 2498 pStdFeatureLeaf->uEax, uNew, uMaxIntelFamilyModelStep, uCurIntelFamilyModelStep)); 2499 pStdFeatureLeaf->uEax = uNew; 2500 } 2501 } 3245 * Plant our own hypervisor CPUID leaves. 3246 */ 3247 if (RT_SUCCESS(rc)) 3248 rc = cpumR3CpuIdPlantHypervisorLeaves(pCpum, &Config); 2502 3249 2503 3250 /* 2504 3251 * MSR fudging. 2505 3252 */ 2506 /** @cfgm{/CPUM/FudgeMSRs, boolean, true} 2507 * Fudges some common MSRs if not present in the selected CPU database entry. 2508 * This is for trying to keep VMs running when moved between different hosts 2509 * and different CPU vendors. */ 2510 bool fEnable; 2511 rc = CFGMR3QueryBoolDef(pCpumCfg, "FudgeMSRs", &fEnable, true); AssertRCReturn(rc, rc); 2512 if (fEnable) 2513 { 2514 rc = cpumR3MsrApplyFudge(pVM); 2515 AssertLogRelRCReturn(rc, rc); 3253 if (RT_SUCCESS(rc)) 3254 { 3255 /** @cfgm{/CPUM/FudgeMSRs, boolean, true} 3256 * Fudges some common MSRs if not present in the selected CPU database entry. 3257 * This is for trying to keep VMs running when moved between different hosts 3258 * and different CPU vendors. */ 3259 bool fEnable; 3260 rc = CFGMR3QueryBoolDef(pCpumCfg, "FudgeMSRs", &fEnable, true); AssertRC(rc); 3261 if (RT_SUCCESS(rc) && fEnable) 3262 { 3263 rc = cpumR3MsrApplyFudge(pVM); 3264 AssertLogRelRC(rc); 3265 } 3266 } 3267 if (RT_SUCCESS(rc)) 3268 { 3269 /* 3270 * Move the MSR and CPUID arrays over on the hypervisor heap, and explode 3271 * guest CPU features again. 3272 */ 3273 void *pvFree = pCpum->GuestInfo.paCpuIdLeavesR3; 3274 int rc1 = cpumR3CpuIdInstallAndExplodeLeaves(pVM, pCpum, pCpum->GuestInfo.paCpuIdLeavesR3, 3275 pCpum->GuestInfo.cCpuIdLeaves); 3276 RTMemFree(pvFree); 3277 3278 pvFree = pCpum->GuestInfo.paMsrRangesR3; 3279 int rc2 = MMHyperDupMem(pVM, pvFree, 3280 sizeof(pCpum->GuestInfo.paMsrRangesR3[0]) * pCpum->GuestInfo.cMsrRanges, 32, 3281 MM_TAG_CPUM_MSRS, (void **)&pCpum->GuestInfo.paMsrRangesR3); 3282 RTMemFree(pvFree); 3283 AssertLogRelRCReturn(rc1, rc1); 3284 AssertLogRelRCReturn(rc2, rc2); 3285 3286 pCpum->GuestInfo.paMsrRangesR0 = MMHyperR3ToR0(pVM, pCpum->GuestInfo.paMsrRangesR3); 3287 pCpum->GuestInfo.paMsrRangesRC = MMHyperR3ToRC(pVM, pCpum->GuestInfo.paMsrRangesR3); 3288 cpumR3MsrRegStats(pVM); 3289 3290 3291 /* 3292 * Some more configuration that we're applying at the end of everything 3293 * via the CPUMSetGuestCpuIdFeature API. 3294 */ 3295 3296 /* Check if PAE was explicitely enabled by the user. */ 3297 bool fEnable; 3298 rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "EnablePAE", &fEnable, false); 3299 AssertRCReturn(rc, rc); 3300 if (fEnable) 3301 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE); 3302 3303 /* We don't normally enable NX for raw-mode, so give the user a chance to force it on. */ 3304 rc = CFGMR3QueryBoolDef(pCpumCfg, "EnableNX", &fEnable, false); 3305 AssertRCReturn(rc, rc); 3306 if (fEnable) 3307 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX); 3308 3309 /* We don't enable the Hypervisor Present bit by default, but it may be needed by some guests. */ 3310 rc = CFGMR3QueryBoolDef(pCpumCfg, "EnableHVP", &fEnable, false); 3311 AssertRCReturn(rc, rc); 3312 if (fEnable) 3313 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP); 3314 3315 return VINF_SUCCESS; 2516 3316 } 2517 3317 2518 3318 /* 2519 * Move the MSR and CPUID arrays over on the hypervisor heap, and explode 2520 * guest CPU features again. 2521 */ 2522 void *pvFree = pCPUM->GuestInfo.paCpuIdLeavesR3; 2523 int rc1 = cpumR3CpuIdInstallAndExplodeLeaves(pVM, pCPUM, pCPUM->GuestInfo.paCpuIdLeavesR3, pCPUM->GuestInfo.cCpuIdLeaves); 2524 RTMemFree(pvFree); 2525 2526 pvFree = pCPUM->GuestInfo.paMsrRangesR3; 2527 int rc2 = MMHyperDupMem(pVM, pvFree, 2528 sizeof(pCPUM->GuestInfo.paMsrRangesR3[0]) * pCPUM->GuestInfo.cMsrRanges, 32, 2529 MM_TAG_CPUM_MSRS, (void **)&pCPUM->GuestInfo.paMsrRangesR3); 2530 RTMemFree(pvFree); 2531 AssertLogRelRCReturn(rc1, rc1); 2532 AssertLogRelRCReturn(rc2, rc2); 2533 2534 pCPUM->GuestInfo.paMsrRangesR0 = MMHyperR3ToR0(pVM, pCPUM->GuestInfo.paMsrRangesR3); 2535 pCPUM->GuestInfo.paMsrRangesRC = MMHyperR3ToRC(pVM, pCPUM->GuestInfo.paMsrRangesR3); 2536 cpumR3MsrRegStats(pVM); 2537 2538 /* 2539 * Some more configuration that we're applying at the end of everything 2540 * via the CPUMSetGuestCpuIdFeature API. 2541 */ 2542 2543 /* Check if PAE was explicitely enabled by the user. */ 2544 rc = CFGMR3QueryBoolDef(CFGMR3GetRoot(pVM), "EnablePAE", &fEnable, false); AssertRCReturn(rc, rc); 2545 if (fEnable) 2546 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_PAE); 2547 2548 /* We don't normally enable NX for raw-mode, so give the user a chance to force it on. */ 2549 rc = CFGMR3QueryBoolDef(pCpumCfg, "EnableNX", &fEnable, false); AssertRCReturn(rc, rc); 2550 if (fEnable) 2551 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_NX); 2552 2553 /* We don't enable the Hypervisor Present bit by default, but it may be needed by some guests. */ 2554 rc = CFGMR3QueryBoolDef(pCpumCfg, "EnableHVP", &fEnable, false); AssertRCReturn(rc, rc); 2555 if (fEnable) 2556 CPUMSetGuestCpuIdFeature(pVM, CPUMCPUIDFEATURE_HVP); 2557 2558 #undef PORTABLE_DISABLE_FEATURE_BIT 2559 #undef PORTABLE_CLEAR_BITS_WHEN 2560 2561 return VINF_SUCCESS; 3319 * Failed before switching to hyper heap. 3320 */ 3321 RTMemFree(pCpum->GuestInfo.paCpuIdLeavesR3); 3322 pCpum->GuestInfo.paCpuIdLeavesR3 = NULL; 3323 RTMemFree(pCpum->GuestInfo.paMsrRangesR3); 3324 pCpum->GuestInfo.paMsrRangesR3 = NULL; 3325 return rc; 2562 3326 } 2563 3327 … … 2583 3347 { 2584 3348 /* 2585 * Save all the CPU ID leaves here so we can check them for compatibility 2586 * upon loading. 2587 */ 2588 SSMR3PutU32(pSSM, RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmStd)); 2589 SSMR3PutMem(pSSM, &pVM->cpum.s.aGuestCpuIdPatmStd[0], sizeof(pVM->cpum.s.aGuestCpuIdPatmStd)); 2590 2591 SSMR3PutU32(pSSM, RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmExt)); 2592 SSMR3PutMem(pSSM, &pVM->cpum.s.aGuestCpuIdPatmExt[0], sizeof(pVM->cpum.s.aGuestCpuIdPatmExt)); 2593 2594 SSMR3PutU32(pSSM, RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmCentaur)); 2595 SSMR3PutMem(pSSM, &pVM->cpum.s.aGuestCpuIdPatmCentaur[0], sizeof(pVM->cpum.s.aGuestCpuIdPatmCentaur)); 2596 2597 SSMR3PutMem(pSSM, &pVM->cpum.s.GuestCpuIdPatmDef, sizeof(pVM->cpum.s.GuestCpuIdPatmDef)); 3349 * Save all the CPU ID leaves. 3350 */ 3351 SSMR3PutU32(pSSM, sizeof(pVM->cpum.s.GuestInfo.paCpuIdLeavesR3[0])); 3352 SSMR3PutU32(pSSM, pVM->cpum.s.GuestInfo.cCpuIdLeaves); 3353 SSMR3PutMem(pSSM, pVM->cpum.s.GuestInfo.paCpuIdLeavesR3, 3354 sizeof(pVM->cpum.s.GuestInfo.paCpuIdLeavesR3[0]) * pVM->cpum.s.GuestInfo.cCpuIdLeaves); 3355 3356 SSMR3PutMem(pSSM, &pVM->cpum.s.GuestInfo.DefCpuId, sizeof(pVM->cpum.s.GuestInfo.DefCpuId)); 2598 3357 2599 3358 /* … … 2615 3374 2616 3375 2617 static int cpumR3Load CpuIdOneGuestArray(PSSMHANDLE pSSM, uint32_t uBase, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves)3376 static int cpumR3LoadOneOldGuestCpuIdArray(PSSMHANDLE pSSM, uint32_t uBase, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves) 2618 3377 { 2619 3378 uint32_t cCpuIds; … … 2655 3414 2656 3415 2657 static int cpumR3Load CpuIdGuestArrays(PSSMHANDLE pSSM, uint32_t uVersion, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves)3416 static int cpumR3LoadGuestCpuIdArray(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves) 2658 3417 { 2659 3418 *ppaLeaves = NULL; 2660 3419 *pcLeaves = 0; 2661 3420 2662 int rc = cpumR3LoadCpuIdOneGuestArray(pSSM, UINT32_C(0x00000000), ppaLeaves, pcLeaves); 2663 if (RT_SUCCESS(rc)) 2664 rc = cpumR3LoadCpuIdOneGuestArray(pSSM, UINT32_C(0x80000000), ppaLeaves, pcLeaves); 2665 if (RT_SUCCESS(rc)) 2666 rc = cpumR3LoadCpuIdOneGuestArray(pSSM, UINT32_C(0xc0000000), ppaLeaves, pcLeaves); 2667 3421 int rc; 3422 if (uVersion > CPUM_SAVED_STATE_VERSION_PUT_STRUCT) 3423 { 3424 /* 3425 * The new format. Starts by declaring the leave size and count. 3426 */ 3427 uint32_t cbLeaf; 3428 SSMR3GetU32(pSSM, &cbLeaf); 3429 uint32_t cLeaves; 3430 rc = SSMR3GetU32(pSSM, &cLeaves); 3431 if (RT_SUCCESS(rc)) 3432 { 3433 if (cbLeaf == sizeof(**ppaLeaves)) 3434 { 3435 if (cLeaves <= CPUM_CPUID_MAX_LEAVES) 3436 { 3437 /* 3438 * Load the leaves one by one. 3439 */ 3440 for (uint32_t i = 0; i < cLeaves && RT_SUCCESS(rc); i++) 3441 { 3442 CPUMCPUIDLEAF Leaf; 3443 rc = SSMR3GetMem(pSSM, &Leaf, sizeof(Leaf)); 3444 if (RT_SUCCESS(rc)) 3445 rc = cpumR3CpuIdInsert(NULL /* pVM */, ppaLeaves, pcLeaves, &Leaf); 3446 } 3447 } 3448 else 3449 rc = SSMR3SetLoadError(pSSM, VERR_TOO_MANY_CPUID_LEAVES, RT_SRC_POS, 3450 "Too many CPUID leaves: %#x, max %#x", cLeaves, CPUM_CPUID_MAX_LEAVES); 3451 } 3452 else 3453 rc = SSMR3SetLoadError(pSSM, VERR_SSM_DATA_UNIT_FORMAT_CHANGED, RT_SRC_POS, 3454 "CPUMCPUIDLEAF size differs: saved=%#x, our=%#x", cbLeaf, sizeof(**ppaLeaves)); 3455 } 3456 } 3457 else 3458 { 3459 /* 3460 * The old format with its three inflexible arrays. 3461 */ 3462 rc = cpumR3LoadOneOldGuestCpuIdArray(pSSM, UINT32_C(0x00000000), ppaLeaves, pcLeaves); 3463 if (RT_SUCCESS(rc)) 3464 rc = cpumR3LoadOneOldGuestCpuIdArray(pSSM, UINT32_C(0x80000000), ppaLeaves, pcLeaves); 3465 if (RT_SUCCESS(rc)) 3466 rc = cpumR3LoadOneOldGuestCpuIdArray(pSSM, UINT32_C(0xc0000000), ppaLeaves, pcLeaves); 3467 if (RT_SUCCESS(rc)) 3468 { 3469 /* 3470 * Fake up leaf 4 on intel like we used to do in CPUMGetGuestCpuId earlier. 3471 */ 3472 PCPUMCPUIDLEAF pLeaf = cpumR3CpuIdGetLeaf(*ppaLeaves, *pcLeaves, 0, 0); 3473 if ( pLeaf 3474 && ASMIsIntelCpuEx(pLeaf->uEbx, pLeaf->uEcx, pLeaf->uEdx)) 3475 { 3476 CPUMCPUIDLEAF Leaf; 3477 Leaf.uLeaf = 4; 3478 Leaf.fSubLeafMask = UINT32_MAX; 3479 Leaf.uSubLeaf = 0; 3480 Leaf.uEdx = UINT32_C(0); /* 3 flags, 0 is fine. */ 3481 Leaf.uEcx = UINT32_C(63); /* sets - 1 */ 3482 Leaf.uEbx = (UINT32_C(7) << 22) /* associativity -1 */ 3483 | (UINT32_C(0) << 12) /* phys line partitions - 1 */ 3484 | UINT32_C(63); /* system coherency line size - 1 */ 3485 Leaf.uEax = (RT_MIN(pVM->cCpus - 1, UINT32_C(0x3f)) << 26) /* cores per package - 1 */ 3486 | (UINT32_C(0) << 14) /* threads per cache - 1 */ 3487 | (UINT32_C(1) << 5) /* cache level */ 3488 | UINT32_C(1); /* cache type (data) */ 3489 rc = cpumR3CpuIdInsert(NULL /* pVM */, ppaLeaves, pcLeaves, &Leaf); 3490 if (RT_SUCCESS(rc)) 3491 { 3492 Leaf.uSubLeaf = 1; /* Should've been cache type 2 (code), but buggy code made it data. */ 3493 rc = cpumR3CpuIdInsert(NULL /* pVM */, ppaLeaves, pcLeaves, &Leaf); 3494 } 3495 if (RT_SUCCESS(rc)) 3496 { 3497 Leaf.uSubLeaf = 2; /* Should've been cache type 3 (unified), but buggy code made it data. */ 3498 Leaf.uEcx = 4095; /* sets - 1 */ 3499 Leaf.uEbx &= UINT32_C(0x003fffff); /* associativity - 1 */ 3500 Leaf.uEbx |= UINT32_C(23) << 22; 3501 Leaf.uEax &= UINT32_C(0xfc003fff); /* threads per cache - 1 */ 3502 Leaf.uEax |= RT_MIN(pVM->cCpus - 1, UINT32_C(0xfff)) << 14; 3503 Leaf.uEax &= UINT32_C(0xffffff1f); /* level */ 3504 Leaf.uEax |= UINT32_C(2) << 5; 3505 rc = cpumR3CpuIdInsert(NULL /* pVM */, ppaLeaves, pcLeaves, &Leaf); 3506 } 3507 } 3508 } 3509 } 2668 3510 return rc; 2669 3511 } … … 2671 3513 2672 3514 /** 2673 * Loads the CPU ID leaves saved by pass 0 .3515 * Loads the CPU ID leaves saved by pass 0, inner worker. 2674 3516 * 2675 3517 * @returns VBox status code. … … 2677 3519 * @param pSSM The saved state handle. 2678 3520 * @param uVersion The format version. 2679 */ 2680 int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion) 3521 * @param paLeaves Guest CPUID leaves loaded from the state. 3522 * @param cLeaves The number of leaves in @a paLeaves. 3523 */ 3524 int cpumR3LoadCpuIdInner(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion, PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves) 2681 3525 { 2682 3526 AssertMsgReturn(uVersion >= CPUM_SAVED_STATE_VERSION_VER3_2, ("%u\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION); 2683 3527 2684 3528 /* 2685 * Define a bunch of macros for simplifying the code. 3529 * Continue loading the state into stack buffers. 3530 */ 3531 CPUMCPUID GuestDefCpuId; 3532 int rc = SSMR3GetMem(pSSM, &GuestDefCpuId, sizeof(GuestDefCpuId)); 3533 AssertRCReturn(rc, rc); 3534 3535 CPUMCPUID aRawStd[16]; 3536 uint32_t cRawStd; 3537 rc = SSMR3GetU32(pSSM, &cRawStd); AssertRCReturn(rc, rc); 3538 if (cRawStd > RT_ELEMENTS(aRawStd)) 3539 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; 3540 rc = SSMR3GetMem(pSSM, &aRawStd[0], cRawStd * sizeof(aRawStd[0])); 3541 AssertRCReturn(rc, rc); 3542 for (uint32_t i = cRawStd; i < RT_ELEMENTS(aRawStd); i++) 3543 ASMCpuIdExSlow(i, 0, 0, 0, &aRawStd[i].uEax, &aRawStd[i].uEbx, &aRawStd[i].uEcx, &aRawStd[i].uEdx); 3544 3545 CPUMCPUID aRawExt[32]; 3546 uint32_t cRawExt; 3547 rc = SSMR3GetU32(pSSM, &cRawExt); AssertRCReturn(rc, rc); 3548 if (cRawExt > RT_ELEMENTS(aRawExt)) 3549 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED; 3550 rc = SSMR3GetMem(pSSM, &aRawExt[0], cRawExt * sizeof(aRawExt[0])); 3551 AssertRCReturn(rc, rc); 3552 for (uint32_t i = cRawExt; i < RT_ELEMENTS(aRawExt); i++) 3553 ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0, &aRawExt[i].uEax, &aRawExt[i].uEbx, &aRawExt[i].uEcx, &aRawExt[i].uEdx); 3554 3555 /* 3556 * Get the raw CPU IDs for the current host. 3557 */ 3558 CPUMCPUID aHostRawStd[16]; 3559 for (unsigned i = 0; i < RT_ELEMENTS(aHostRawStd); i++) 3560 ASMCpuIdExSlow(i, 0, 0, 0, &aHostRawStd[i].uEax, &aHostRawStd[i].uEbx, &aHostRawStd[i].uEcx, &aHostRawStd[i].uEdx); 3561 3562 CPUMCPUID aHostRawExt[32]; 3563 for (unsigned i = 0; i < RT_ELEMENTS(aHostRawExt); i++) 3564 ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0, 3565 &aHostRawExt[i].uEax, &aHostRawExt[i].uEbx, &aHostRawExt[i].uEcx, &aHostRawExt[i].uEdx); 3566 3567 /* 3568 * Get the host and guest overrides so we don't reject the state because 3569 * some feature was enabled thru these interfaces. 3570 * Note! We currently only need the feature leaves, so skip rest. 3571 */ 3572 PCFGMNODE pOverrideCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM/HostCPUID"); 3573 CPUMCPUID aHostOverrideStd[2]; 3574 memcpy(&aHostOverrideStd[0], &aHostRawStd[0], sizeof(aHostOverrideStd)); 3575 cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x00000000), &aHostOverrideStd[0], RT_ELEMENTS(aHostOverrideStd), pOverrideCfg); 3576 3577 CPUMCPUID aHostOverrideExt[2]; 3578 memcpy(&aHostOverrideExt[0], &aHostRawExt[0], sizeof(aHostOverrideExt)); 3579 cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x80000000), &aHostOverrideExt[0], RT_ELEMENTS(aHostOverrideExt), pOverrideCfg); 3580 3581 /* 3582 * This can be skipped. 3583 */ 3584 bool fStrictCpuIdChecks; 3585 CFGMR3QueryBoolDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM"), "StrictCpuIdChecks", &fStrictCpuIdChecks, true); 3586 3587 /* 3588 * Define a bunch of macros for simplifying the santizing/checking code below. 2686 3589 */ 2687 3590 /* Generic expression + failure message. */ … … 2852 3755 2853 3756 /* 2854 * Load them into stack buffers first.2855 */2856 PCPUMCPUIDLEAF paLeaves;2857 uint32_t cLeaves;2858 int rc = cpumR3LoadCpuIdGuestArrays(pSSM, uVersion, &paLeaves, &cLeaves);2859 AssertRCReturn(rc, rc);2860 2861 /** @todo we'll be leaking paLeaves on error return... */2862 2863 CPUMCPUID GuestCpuIdPatmDef;2864 rc = SSMR3GetMem(pSSM, &GuestCpuIdPatmDef, sizeof(GuestCpuIdPatmDef));2865 AssertRCReturn(rc, rc);2866 2867 CPUMCPUID aRawStd[16];2868 uint32_t cRawStd;2869 rc = SSMR3GetU32(pSSM, &cRawStd); AssertRCReturn(rc, rc);2870 if (cRawStd > RT_ELEMENTS(aRawStd))2871 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;2872 rc = SSMR3GetMem(pSSM, &aRawStd[0], cRawStd * sizeof(aRawStd[0]));2873 AssertRCReturn(rc, rc);2874 for (uint32_t i = cRawStd; i < RT_ELEMENTS(aRawStd); i++)2875 ASMCpuIdExSlow(i, 0, 0, 0, &aRawStd[i].uEax, &aRawStd[i].uEbx, &aRawStd[i].uEcx, &aRawStd[i].uEdx);2876 2877 CPUMCPUID aRawExt[32];2878 uint32_t cRawExt;2879 rc = SSMR3GetU32(pSSM, &cRawExt); AssertRCReturn(rc, rc);2880 if (cRawExt > RT_ELEMENTS(aRawExt))2881 return VERR_SSM_DATA_UNIT_FORMAT_CHANGED;2882 rc = SSMR3GetMem(pSSM, &aRawExt[0], cRawExt * sizeof(aRawExt[0]));2883 AssertRCReturn(rc, rc);2884 for (uint32_t i = cRawExt; i < RT_ELEMENTS(aRawExt); i++)2885 ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0, &aRawExt[i].uEax, &aRawExt[i].uEbx, &aRawExt[i].uEcx, &aRawExt[i].uEdx);2886 2887 /*2888 * Get the raw CPU IDs for the current host.2889 */2890 CPUMCPUID aHostRawStd[16];2891 for (unsigned i = 0; i < RT_ELEMENTS(aHostRawStd); i++)2892 ASMCpuIdExSlow(i, 0, 0, 0, &aHostRawStd[i].uEax, &aHostRawStd[i].uEbx, &aHostRawStd[i].uEcx, &aHostRawStd[i].uEdx);2893 2894 CPUMCPUID aHostRawExt[32];2895 for (unsigned i = 0; i < RT_ELEMENTS(aHostRawExt); i++)2896 ASMCpuIdExSlow(i | UINT32_C(0x80000000), 0, 0, 0,2897 &aHostRawExt[i].uEax, &aHostRawExt[i].uEbx, &aHostRawExt[i].uEcx, &aHostRawExt[i].uEdx);2898 2899 /*2900 * Get the host and guest overrides so we don't reject the state because2901 * some feature was enabled thru these interfaces.2902 * Note! We currently only need the feature leaves, so skip rest.2903 */2904 PCFGMNODE pOverrideCfg = CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM/HostCPUID");2905 CPUMCPUID aHostOverrideStd[2];2906 memcpy(&aHostOverrideStd[0], &aHostRawStd[0], sizeof(aHostOverrideStd));2907 cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x00000000), &aHostOverrideStd[0], RT_ELEMENTS(aHostOverrideStd), pOverrideCfg);2908 2909 CPUMCPUID aHostOverrideExt[2];2910 memcpy(&aHostOverrideExt[0], &aHostRawExt[0], sizeof(aHostOverrideExt));2911 cpumR3CpuIdInitLoadOverrideSet(UINT32_C(0x80000000), &aHostOverrideExt[0], RT_ELEMENTS(aHostOverrideExt), pOverrideCfg);2912 2913 /*2914 * This can be skipped.2915 */2916 bool fStrictCpuIdChecks;2917 CFGMR3QueryBoolDef(CFGMR3GetChild(CFGMR3GetRoot(pVM), "CPUM"), "StrictCpuIdChecks", &fStrictCpuIdChecks, true);2918 2919 2920 2921 /*2922 3757 * For raw-mode we'll require that the CPUs are very similar since we don't 2923 3758 * intercept CPUID instructions for user mode applications. … … 3303 4138 } 3304 4139 3305 /*3306 * We're good, commit the CPU ID leaves.3307 */3308 MMHyperFree(pVM, pVM->cpum.s.GuestInfo.paCpuIdLeavesR3);3309 pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = NIL_RTR0PTR;3310 pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = NIL_RTRCPTR;3311 pVM->cpum.s.GuestInfo.DefCpuId = GuestCpuIdPatmDef;3312 rc = cpumR3CpuIdInstallAndExplodeLeaves(pVM, &pVM->cpum.s, paLeaves, cLeaves);3313 RTMemFree(paLeaves);3314 AssertLogRelRCReturn(rc, rc);3315 3316 3317 4140 #undef CPUID_CHECK_RET 3318 4141 #undef CPUID_CHECK_WRN … … 3335 4158 #undef CPUID_GST_AMD_FEATURE_IGN 3336 4159 4160 /* 4161 * We're good, commit the CPU ID leaves. 4162 */ 4163 MMHyperFree(pVM, pVM->cpum.s.GuestInfo.paCpuIdLeavesR3); 4164 pVM->cpum.s.GuestInfo.paCpuIdLeavesR3 = NULL; 4165 pVM->cpum.s.GuestInfo.paCpuIdLeavesR0 = NIL_RTR0PTR; 4166 pVM->cpum.s.GuestInfo.paCpuIdLeavesRC = NIL_RTRCPTR; 4167 pVM->cpum.s.GuestInfo.DefCpuId = GuestDefCpuId; 4168 rc = cpumR3CpuIdInstallAndExplodeLeaves(pVM, &pVM->cpum.s, paLeaves, cLeaves); 4169 AssertLogRelRCReturn(rc, rc); 4170 3337 4171 return VINF_SUCCESS; 3338 4172 } 3339 4173 4174 4175 /** 4176 * Loads the CPU ID leaves saved by pass 0. 4177 * 4178 * @returns VBox status code. 4179 * @param pVM Pointer to the VM. 4180 * @param pSSM The saved state handle. 4181 * @param uVersion The format version. 4182 */ 4183 int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion) 4184 { 4185 AssertMsgReturn(uVersion >= CPUM_SAVED_STATE_VERSION_VER3_2, ("%u\n", uVersion), VERR_SSM_UNSUPPORTED_DATA_UNIT_VERSION); 4186 4187 /* 4188 * Load the CPUID leaves array first and call worker to do the rest, just so 4189 * we can free the memory when we need to without ending up in column 1000. 4190 */ 4191 PCPUMCPUIDLEAF paLeaves; 4192 uint32_t cLeaves; 4193 int rc = cpumR3LoadGuestCpuIdArray(pVM, pSSM, uVersion, &paLeaves, &cLeaves); 4194 AssertRC(rc); 4195 if (RT_SUCCESS(rc)) 4196 { 4197 rc = cpumR3LoadCpuIdInner(pVM, pSSM, uVersion, paLeaves, cLeaves); 4198 RTMemFree(paLeaves); 4199 } 4200 return rc; 4201 } 4202 4203 4204 4205 4206 /* 4207 * 4208 * 4209 * CPUID Info Handler. 4210 * CPUID Info Handler. 4211 * CPUID Info Handler. 4212 * 4213 * 4214 */ 4215 4216 4217 4218 /** 4219 * Get L1 cache / TLS associativity. 4220 */ 4221 static const char *getCacheAss(unsigned u, char *pszBuf) 4222 { 4223 if (u == 0) 4224 return "res0 "; 4225 if (u == 1) 4226 return "direct"; 4227 if (u == 255) 4228 return "fully"; 4229 if (u >= 256) 4230 return "???"; 4231 4232 RTStrPrintf(pszBuf, 16, "%d way", u); 4233 return pszBuf; 4234 } 4235 4236 4237 /** 4238 * Get L2 cache associativity. 4239 */ 4240 const char *getL2CacheAss(unsigned u) 4241 { 4242 switch (u) 4243 { 4244 case 0: return "off "; 4245 case 1: return "direct"; 4246 case 2: return "2 way "; 4247 case 3: return "res3 "; 4248 case 4: return "4 way "; 4249 case 5: return "res5 "; 4250 case 6: return "8 way "; 4251 case 7: return "res7 "; 4252 case 8: return "16 way"; 4253 case 9: return "res9 "; 4254 case 10: return "res10 "; 4255 case 11: return "res11 "; 4256 case 12: return "res12 "; 4257 case 13: return "res13 "; 4258 case 14: return "res14 "; 4259 case 15: return "fully "; 4260 default: return "????"; 4261 } 4262 } 4263 4264 4265 /** 4266 * Display the guest CpuId leaves. 4267 * 4268 * @param pVM Pointer to the VM. 4269 * @param pHlp The info helper functions. 4270 * @param pszArgs "terse", "default" or "verbose". 4271 */ 4272 DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs) 4273 { 4274 /* 4275 * Parse the argument. 4276 */ 4277 unsigned iVerbosity = 1; 4278 if (pszArgs) 4279 { 4280 pszArgs = RTStrStripL(pszArgs); 4281 if (!strcmp(pszArgs, "terse")) 4282 iVerbosity--; 4283 else if (!strcmp(pszArgs, "verbose")) 4284 iVerbosity++; 4285 } 4286 4287 /* 4288 * Start cracking. 4289 */ 4290 CPUMCPUID Host; 4291 CPUMCPUID Guest; 4292 unsigned cStdMax = pVM->cpum.s.aGuestCpuIdPatmStd[0].uEax; 4293 4294 uint32_t cStdHstMax; 4295 uint32_t dummy; 4296 ASMCpuIdExSlow(0, 0, 0, 0, &cStdHstMax, &dummy, &dummy, &dummy); 4297 4298 unsigned cStdLstMax = RT_MAX(RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmStd), cStdHstMax); 4299 4300 pHlp->pfnPrintf(pHlp, 4301 " RAW Standard CPUIDs\n" 4302 " Function eax ebx ecx edx\n"); 4303 for (unsigned i = 0; i <= cStdLstMax ; i++) 4304 { 4305 if (i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmStd)) 4306 { 4307 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[i]; 4308 ASMCpuIdExSlow(i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4309 4310 pHlp->pfnPrintf(pHlp, 4311 "Gst: %08x %08x %08x %08x %08x%s\n" 4312 "Hst: %08x %08x %08x %08x\n", 4313 i, Guest.uEax, Guest.uEbx, Guest.uEcx, Guest.uEdx, 4314 i <= cStdMax ? "" : "*", 4315 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx); 4316 } 4317 else 4318 { 4319 ASMCpuIdExSlow(i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4320 4321 pHlp->pfnPrintf(pHlp, 4322 "Hst: %08x %08x %08x %08x %08x\n", 4323 i, Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx); 4324 } 4325 } 4326 4327 /* 4328 * If verbose, decode it. 4329 */ 4330 if (iVerbosity) 4331 { 4332 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[0]; 4333 pHlp->pfnPrintf(pHlp, 4334 "Name: %.04s%.04s%.04s\n" 4335 "Supports: 0-%x\n", 4336 &Guest.uEbx, &Guest.uEdx, &Guest.uEcx, Guest.uEax); 4337 } 4338 4339 /* 4340 * Get Features. 4341 */ 4342 bool const fIntel = ASMIsIntelCpuEx(pVM->cpum.s.aGuestCpuIdPatmStd[0].uEbx, 4343 pVM->cpum.s.aGuestCpuIdPatmStd[0].uEcx, 4344 pVM->cpum.s.aGuestCpuIdPatmStd[0].uEdx); 4345 if (cStdMax >= 1 && iVerbosity) 4346 { 4347 static const char * const s_apszTypes[4] = { "primary", "overdrive", "MP", "reserved" }; 4348 4349 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[1]; 4350 uint32_t uEAX = Guest.uEax; 4351 4352 pHlp->pfnPrintf(pHlp, 4353 "Family: %d \tExtended: %d \tEffective: %d\n" 4354 "Model: %d \tExtended: %d \tEffective: %d\n" 4355 "Stepping: %d\n" 4356 "Type: %d (%s)\n" 4357 "APIC ID: %#04x\n" 4358 "Logical CPUs: %d\n" 4359 "CLFLUSH Size: %d\n" 4360 "Brand ID: %#04x\n", 4361 (uEAX >> 8) & 0xf, (uEAX >> 20) & 0x7f, ASMGetCpuFamily(uEAX), 4362 (uEAX >> 4) & 0xf, (uEAX >> 16) & 0x0f, ASMGetCpuModel(uEAX, fIntel), 4363 ASMGetCpuStepping(uEAX), 4364 (uEAX >> 12) & 3, s_apszTypes[(uEAX >> 12) & 3], 4365 (Guest.uEbx >> 24) & 0xff, 4366 (Guest.uEbx >> 16) & 0xff, 4367 (Guest.uEbx >> 8) & 0xff, 4368 (Guest.uEbx >> 0) & 0xff); 4369 if (iVerbosity == 1) 4370 { 4371 uint32_t uEDX = Guest.uEdx; 4372 pHlp->pfnPrintf(pHlp, "Features EDX: "); 4373 if (uEDX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " FPU"); 4374 if (uEDX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " VME"); 4375 if (uEDX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " DE"); 4376 if (uEDX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " PSE"); 4377 if (uEDX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " TSC"); 4378 if (uEDX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " MSR"); 4379 if (uEDX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " PAE"); 4380 if (uEDX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " MCE"); 4381 if (uEDX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " CX8"); 4382 if (uEDX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " APIC"); 4383 if (uEDX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " 10"); 4384 if (uEDX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " SEP"); 4385 if (uEDX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " MTRR"); 4386 if (uEDX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " PGE"); 4387 if (uEDX & RT_BIT(14)) pHlp->pfnPrintf(pHlp, " MCA"); 4388 if (uEDX & RT_BIT(15)) pHlp->pfnPrintf(pHlp, " CMOV"); 4389 if (uEDX & RT_BIT(16)) pHlp->pfnPrintf(pHlp, " PAT"); 4390 if (uEDX & RT_BIT(17)) pHlp->pfnPrintf(pHlp, " PSE36"); 4391 if (uEDX & RT_BIT(18)) pHlp->pfnPrintf(pHlp, " PSN"); 4392 if (uEDX & RT_BIT(19)) pHlp->pfnPrintf(pHlp, " CLFSH"); 4393 if (uEDX & RT_BIT(20)) pHlp->pfnPrintf(pHlp, " 20"); 4394 if (uEDX & RT_BIT(21)) pHlp->pfnPrintf(pHlp, " DS"); 4395 if (uEDX & RT_BIT(22)) pHlp->pfnPrintf(pHlp, " ACPI"); 4396 if (uEDX & RT_BIT(23)) pHlp->pfnPrintf(pHlp, " MMX"); 4397 if (uEDX & RT_BIT(24)) pHlp->pfnPrintf(pHlp, " FXSR"); 4398 if (uEDX & RT_BIT(25)) pHlp->pfnPrintf(pHlp, " SSE"); 4399 if (uEDX & RT_BIT(26)) pHlp->pfnPrintf(pHlp, " SSE2"); 4400 if (uEDX & RT_BIT(27)) pHlp->pfnPrintf(pHlp, " SS"); 4401 if (uEDX & RT_BIT(28)) pHlp->pfnPrintf(pHlp, " HTT"); 4402 if (uEDX & RT_BIT(29)) pHlp->pfnPrintf(pHlp, " TM"); 4403 if (uEDX & RT_BIT(30)) pHlp->pfnPrintf(pHlp, " 30"); 4404 if (uEDX & RT_BIT(31)) pHlp->pfnPrintf(pHlp, " PBE"); 4405 pHlp->pfnPrintf(pHlp, "\n"); 4406 4407 uint32_t uECX = Guest.uEcx; 4408 pHlp->pfnPrintf(pHlp, "Features ECX: "); 4409 if (uECX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " SSE3"); 4410 if (uECX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " PCLMUL"); 4411 if (uECX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " DTES64"); 4412 if (uECX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " MONITOR"); 4413 if (uECX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " DS-CPL"); 4414 if (uECX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " VMX"); 4415 if (uECX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " SMX"); 4416 if (uECX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " EST"); 4417 if (uECX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " TM2"); 4418 if (uECX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " SSSE3"); 4419 if (uECX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " CNXT-ID"); 4420 if (uECX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " 11"); 4421 if (uECX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " FMA"); 4422 if (uECX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " CX16"); 4423 if (uECX & RT_BIT(14)) pHlp->pfnPrintf(pHlp, " TPRUPDATE"); 4424 if (uECX & RT_BIT(15)) pHlp->pfnPrintf(pHlp, " PDCM"); 4425 if (uECX & RT_BIT(16)) pHlp->pfnPrintf(pHlp, " 16"); 4426 if (uECX & RT_BIT(17)) pHlp->pfnPrintf(pHlp, " PCID"); 4427 if (uECX & RT_BIT(18)) pHlp->pfnPrintf(pHlp, " DCA"); 4428 if (uECX & RT_BIT(19)) pHlp->pfnPrintf(pHlp, " SSE4.1"); 4429 if (uECX & RT_BIT(20)) pHlp->pfnPrintf(pHlp, " SSE4.2"); 4430 if (uECX & RT_BIT(21)) pHlp->pfnPrintf(pHlp, " X2APIC"); 4431 if (uECX & RT_BIT(22)) pHlp->pfnPrintf(pHlp, " MOVBE"); 4432 if (uECX & RT_BIT(23)) pHlp->pfnPrintf(pHlp, " POPCNT"); 4433 if (uECX & RT_BIT(24)) pHlp->pfnPrintf(pHlp, " TSCDEADL"); 4434 if (uECX & RT_BIT(25)) pHlp->pfnPrintf(pHlp, " AES"); 4435 if (uECX & RT_BIT(26)) pHlp->pfnPrintf(pHlp, " XSAVE"); 4436 if (uECX & RT_BIT(27)) pHlp->pfnPrintf(pHlp, " OSXSAVE"); 4437 if (uECX & RT_BIT(28)) pHlp->pfnPrintf(pHlp, " AVX"); 4438 if (uECX & RT_BIT(29)) pHlp->pfnPrintf(pHlp, " F16C"); 4439 if (uECX & RT_BIT(30)) pHlp->pfnPrintf(pHlp, " RDRAND"); 4440 if (uECX & RT_BIT(31)) pHlp->pfnPrintf(pHlp, " HVP"); 4441 pHlp->pfnPrintf(pHlp, "\n"); 4442 } 4443 else 4444 { 4445 ASMCpuIdExSlow(1, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4446 4447 X86CPUIDFEATEDX EdxHost = *(PX86CPUIDFEATEDX)&Host.uEdx; 4448 X86CPUIDFEATECX EcxHost = *(PX86CPUIDFEATECX)&Host.uEcx; 4449 X86CPUIDFEATEDX EdxGuest = *(PX86CPUIDFEATEDX)&Guest.uEdx; 4450 X86CPUIDFEATECX EcxGuest = *(PX86CPUIDFEATECX)&Guest.uEcx; 4451 4452 pHlp->pfnPrintf(pHlp, "Mnemonic - Description = guest (host)\n"); 4453 pHlp->pfnPrintf(pHlp, "FPU - x87 FPU on Chip = %d (%d)\n", EdxGuest.u1FPU, EdxHost.u1FPU); 4454 pHlp->pfnPrintf(pHlp, "VME - Virtual 8086 Mode Enhancements = %d (%d)\n", EdxGuest.u1VME, EdxHost.u1VME); 4455 pHlp->pfnPrintf(pHlp, "DE - Debugging extensions = %d (%d)\n", EdxGuest.u1DE, EdxHost.u1DE); 4456 pHlp->pfnPrintf(pHlp, "PSE - Page Size Extension = %d (%d)\n", EdxGuest.u1PSE, EdxHost.u1PSE); 4457 pHlp->pfnPrintf(pHlp, "TSC - Time Stamp Counter = %d (%d)\n", EdxGuest.u1TSC, EdxHost.u1TSC); 4458 pHlp->pfnPrintf(pHlp, "MSR - Model Specific Registers = %d (%d)\n", EdxGuest.u1MSR, EdxHost.u1MSR); 4459 pHlp->pfnPrintf(pHlp, "PAE - Physical Address Extension = %d (%d)\n", EdxGuest.u1PAE, EdxHost.u1PAE); 4460 pHlp->pfnPrintf(pHlp, "MCE - Machine Check Exception = %d (%d)\n", EdxGuest.u1MCE, EdxHost.u1MCE); 4461 pHlp->pfnPrintf(pHlp, "CX8 - CMPXCHG8B instruction = %d (%d)\n", EdxGuest.u1CX8, EdxHost.u1CX8); 4462 pHlp->pfnPrintf(pHlp, "APIC - APIC On-Chip = %d (%d)\n", EdxGuest.u1APIC, EdxHost.u1APIC); 4463 pHlp->pfnPrintf(pHlp, "10 - Reserved = %d (%d)\n", EdxGuest.u1Reserved1, EdxHost.u1Reserved1); 4464 pHlp->pfnPrintf(pHlp, "SEP - SYSENTER and SYSEXIT = %d (%d)\n", EdxGuest.u1SEP, EdxHost.u1SEP); 4465 pHlp->pfnPrintf(pHlp, "MTRR - Memory Type Range Registers = %d (%d)\n", EdxGuest.u1MTRR, EdxHost.u1MTRR); 4466 pHlp->pfnPrintf(pHlp, "PGE - PTE Global Bit = %d (%d)\n", EdxGuest.u1PGE, EdxHost.u1PGE); 4467 pHlp->pfnPrintf(pHlp, "MCA - Machine Check Architecture = %d (%d)\n", EdxGuest.u1MCA, EdxHost.u1MCA); 4468 pHlp->pfnPrintf(pHlp, "CMOV - Conditional Move Instructions = %d (%d)\n", EdxGuest.u1CMOV, EdxHost.u1CMOV); 4469 pHlp->pfnPrintf(pHlp, "PAT - Page Attribute Table = %d (%d)\n", EdxGuest.u1PAT, EdxHost.u1PAT); 4470 pHlp->pfnPrintf(pHlp, "PSE-36 - 36-bit Page Size Extention = %d (%d)\n", EdxGuest.u1PSE36, EdxHost.u1PSE36); 4471 pHlp->pfnPrintf(pHlp, "PSN - Processor Serial Number = %d (%d)\n", EdxGuest.u1PSN, EdxHost.u1PSN); 4472 pHlp->pfnPrintf(pHlp, "CLFSH - CLFLUSH Instruction. = %d (%d)\n", EdxGuest.u1CLFSH, EdxHost.u1CLFSH); 4473 pHlp->pfnPrintf(pHlp, "20 - Reserved = %d (%d)\n", EdxGuest.u1Reserved2, EdxHost.u1Reserved2); 4474 pHlp->pfnPrintf(pHlp, "DS - Debug Store = %d (%d)\n", EdxGuest.u1DS, EdxHost.u1DS); 4475 pHlp->pfnPrintf(pHlp, "ACPI - Thermal Mon. & Soft. Clock Ctrl.= %d (%d)\n", EdxGuest.u1ACPI, EdxHost.u1ACPI); 4476 pHlp->pfnPrintf(pHlp, "MMX - Intel MMX Technology = %d (%d)\n", EdxGuest.u1MMX, EdxHost.u1MMX); 4477 pHlp->pfnPrintf(pHlp, "FXSR - FXSAVE and FXRSTOR Instructions = %d (%d)\n", EdxGuest.u1FXSR, EdxHost.u1FXSR); 4478 pHlp->pfnPrintf(pHlp, "SSE - SSE Support = %d (%d)\n", EdxGuest.u1SSE, EdxHost.u1SSE); 4479 pHlp->pfnPrintf(pHlp, "SSE2 - SSE2 Support = %d (%d)\n", EdxGuest.u1SSE2, EdxHost.u1SSE2); 4480 pHlp->pfnPrintf(pHlp, "SS - Self Snoop = %d (%d)\n", EdxGuest.u1SS, EdxHost.u1SS); 4481 pHlp->pfnPrintf(pHlp, "HTT - Hyper-Threading Technology = %d (%d)\n", EdxGuest.u1HTT, EdxHost.u1HTT); 4482 pHlp->pfnPrintf(pHlp, "TM - Thermal Monitor = %d (%d)\n", EdxGuest.u1TM, EdxHost.u1TM); 4483 pHlp->pfnPrintf(pHlp, "30 - Reserved = %d (%d)\n", EdxGuest.u1Reserved3, EdxHost.u1Reserved3); 4484 pHlp->pfnPrintf(pHlp, "PBE - Pending Break Enable = %d (%d)\n", EdxGuest.u1PBE, EdxHost.u1PBE); 4485 4486 pHlp->pfnPrintf(pHlp, "Supports SSE3 = %d (%d)\n", EcxGuest.u1SSE3, EcxHost.u1SSE3); 4487 pHlp->pfnPrintf(pHlp, "PCLMULQDQ = %d (%d)\n", EcxGuest.u1PCLMULQDQ, EcxHost.u1PCLMULQDQ); 4488 pHlp->pfnPrintf(pHlp, "DS Area 64-bit layout = %d (%d)\n", EcxGuest.u1DTE64, EcxHost.u1DTE64); 4489 pHlp->pfnPrintf(pHlp, "Supports MONITOR/MWAIT = %d (%d)\n", EcxGuest.u1Monitor, EcxHost.u1Monitor); 4490 pHlp->pfnPrintf(pHlp, "CPL-DS - CPL Qualified Debug Store = %d (%d)\n", EcxGuest.u1CPLDS, EcxHost.u1CPLDS); 4491 pHlp->pfnPrintf(pHlp, "VMX - Virtual Machine Technology = %d (%d)\n", EcxGuest.u1VMX, EcxHost.u1VMX); 4492 pHlp->pfnPrintf(pHlp, "SMX - Safer Mode Extensions = %d (%d)\n", EcxGuest.u1SMX, EcxHost.u1SMX); 4493 pHlp->pfnPrintf(pHlp, "Enhanced SpeedStep Technology = %d (%d)\n", EcxGuest.u1EST, EcxHost.u1EST); 4494 pHlp->pfnPrintf(pHlp, "Terminal Monitor 2 = %d (%d)\n", EcxGuest.u1TM2, EcxHost.u1TM2); 4495 pHlp->pfnPrintf(pHlp, "Supplemental SSE3 instructions = %d (%d)\n", EcxGuest.u1SSSE3, EcxHost.u1SSSE3); 4496 pHlp->pfnPrintf(pHlp, "L1 Context ID = %d (%d)\n", EcxGuest.u1CNTXID, EcxHost.u1CNTXID); 4497 pHlp->pfnPrintf(pHlp, "11 - Reserved = %d (%d)\n", EcxGuest.u1Reserved1, EcxHost.u1Reserved1); 4498 pHlp->pfnPrintf(pHlp, "FMA extensions using YMM state = %d (%d)\n", EcxGuest.u1FMA, EcxHost.u1FMA); 4499 pHlp->pfnPrintf(pHlp, "CMPXCHG16B instruction = %d (%d)\n", EcxGuest.u1CX16, EcxHost.u1CX16); 4500 pHlp->pfnPrintf(pHlp, "xTPR Update Control = %d (%d)\n", EcxGuest.u1TPRUpdate, EcxHost.u1TPRUpdate); 4501 pHlp->pfnPrintf(pHlp, "Perf/Debug Capability MSR = %d (%d)\n", EcxGuest.u1PDCM, EcxHost.u1PDCM); 4502 pHlp->pfnPrintf(pHlp, "16 - Reserved = %d (%d)\n", EcxGuest.u1Reserved2, EcxHost.u1Reserved2); 4503 pHlp->pfnPrintf(pHlp, "PCID - Process-context identifiers = %d (%d)\n", EcxGuest.u1PCID, EcxHost.u1PCID); 4504 pHlp->pfnPrintf(pHlp, "DCA - Direct Cache Access = %d (%d)\n", EcxGuest.u1DCA, EcxHost.u1DCA); 4505 pHlp->pfnPrintf(pHlp, "SSE4.1 instruction extensions = %d (%d)\n", EcxGuest.u1SSE4_1, EcxHost.u1SSE4_1); 4506 pHlp->pfnPrintf(pHlp, "SSE4.2 instruction extensions = %d (%d)\n", EcxGuest.u1SSE4_2, EcxHost.u1SSE4_2); 4507 pHlp->pfnPrintf(pHlp, "Supports the x2APIC extensions = %d (%d)\n", EcxGuest.u1x2APIC, EcxHost.u1x2APIC); 4508 pHlp->pfnPrintf(pHlp, "MOVBE instruction = %d (%d)\n", EcxGuest.u1MOVBE, EcxHost.u1MOVBE); 4509 pHlp->pfnPrintf(pHlp, "POPCNT instruction = %d (%d)\n", EcxGuest.u1POPCNT, EcxHost.u1POPCNT); 4510 pHlp->pfnPrintf(pHlp, "TSC-Deadline LAPIC timer mode = %d (%d)\n", EcxGuest.u1TSCDEADLINE,EcxHost.u1TSCDEADLINE); 4511 pHlp->pfnPrintf(pHlp, "AESNI instruction extensions = %d (%d)\n", EcxGuest.u1AES, EcxHost.u1AES); 4512 pHlp->pfnPrintf(pHlp, "XSAVE/XRSTOR extended state feature = %d (%d)\n", EcxGuest.u1XSAVE, EcxHost.u1XSAVE); 4513 pHlp->pfnPrintf(pHlp, "Supports OSXSAVE = %d (%d)\n", EcxGuest.u1OSXSAVE, EcxHost.u1OSXSAVE); 4514 pHlp->pfnPrintf(pHlp, "AVX instruction extensions = %d (%d)\n", EcxGuest.u1AVX, EcxHost.u1AVX); 4515 pHlp->pfnPrintf(pHlp, "16-bit floating point conversion instr = %d (%d)\n", EcxGuest.u1F16C, EcxHost.u1F16C); 4516 pHlp->pfnPrintf(pHlp, "RDRAND instruction = %d (%d)\n", EcxGuest.u1RDRAND, EcxHost.u1RDRAND); 4517 pHlp->pfnPrintf(pHlp, "Hypervisor Present (we're a guest) = %d (%d)\n", EcxGuest.u1HVP, EcxHost.u1HVP); 4518 } 4519 } 4520 if (cStdMax >= 2 && iVerbosity) 4521 { 4522 /** @todo */ 4523 } 4524 4525 /* 4526 * Extended. 4527 * Implemented after AMD specs. 4528 */ 4529 unsigned cExtMax = pVM->cpum.s.aGuestCpuIdPatmExt[0].uEax & 0xffff; 4530 4531 pHlp->pfnPrintf(pHlp, 4532 "\n" 4533 " RAW Extended CPUIDs\n" 4534 " Function eax ebx ecx edx\n"); 4535 bool fSupportsInvariantTsc = false; 4536 for (unsigned i = 0; i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmExt); i++) 4537 { 4538 Guest = pVM->cpum.s.aGuestCpuIdPatmExt[i]; 4539 ASMCpuIdExSlow(0x80000000 | i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4540 4541 if ( i == 7 4542 && (Host.uEdx & X86_CPUID_AMD_ADVPOWER_EDX_TSCINVAR)) 4543 { 4544 fSupportsInvariantTsc = true; 4545 } 4546 pHlp->pfnPrintf(pHlp, 4547 "Gst: %08x %08x %08x %08x %08x%s\n" 4548 "Hst: %08x %08x %08x %08x\n", 4549 0x80000000 | i, Guest.uEax, Guest.uEbx, Guest.uEcx, Guest.uEdx, 4550 i <= cExtMax ? "" : "*", 4551 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx); 4552 } 4553 4554 /* 4555 * Understandable output 4556 */ 4557 if (iVerbosity) 4558 { 4559 Guest = pVM->cpum.s.aGuestCpuIdPatmExt[0]; 4560 pHlp->pfnPrintf(pHlp, 4561 "Ext Name: %.4s%.4s%.4s\n" 4562 "Ext Supports: 0x80000000-%#010x\n", 4563 &Guest.uEbx, &Guest.uEdx, &Guest.uEcx, Guest.uEax); 4564 } 4565 4566 if (iVerbosity && cExtMax >= 1) 4567 { 4568 Guest = pVM->cpum.s.aGuestCpuIdPatmExt[1]; 4569 uint32_t uEAX = Guest.uEax; 4570 pHlp->pfnPrintf(pHlp, 4571 "Family: %d \tExtended: %d \tEffective: %d\n" 4572 "Model: %d \tExtended: %d \tEffective: %d\n" 4573 "Stepping: %d\n" 4574 "Brand ID: %#05x\n", 4575 (uEAX >> 8) & 0xf, (uEAX >> 20) & 0x7f, ASMGetCpuFamily(uEAX), 4576 (uEAX >> 4) & 0xf, (uEAX >> 16) & 0x0f, ASMGetCpuModel(uEAX, fIntel), 4577 ASMGetCpuStepping(uEAX), 4578 Guest.uEbx & 0xfff); 4579 4580 if (iVerbosity == 1) 4581 { 4582 uint32_t uEDX = Guest.uEdx; 4583 pHlp->pfnPrintf(pHlp, "Features EDX: "); 4584 if (uEDX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " FPU"); 4585 if (uEDX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " VME"); 4586 if (uEDX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " DE"); 4587 if (uEDX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " PSE"); 4588 if (uEDX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " TSC"); 4589 if (uEDX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " MSR"); 4590 if (uEDX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " PAE"); 4591 if (uEDX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " MCE"); 4592 if (uEDX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " CX8"); 4593 if (uEDX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " APIC"); 4594 if (uEDX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " 10"); 4595 if (uEDX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " SCR"); 4596 if (uEDX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " MTRR"); 4597 if (uEDX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " PGE"); 4598 if (uEDX & RT_BIT(14)) pHlp->pfnPrintf(pHlp, " MCA"); 4599 if (uEDX & RT_BIT(15)) pHlp->pfnPrintf(pHlp, " CMOV"); 4600 if (uEDX & RT_BIT(16)) pHlp->pfnPrintf(pHlp, " PAT"); 4601 if (uEDX & RT_BIT(17)) pHlp->pfnPrintf(pHlp, " PSE36"); 4602 if (uEDX & RT_BIT(18)) pHlp->pfnPrintf(pHlp, " 18"); 4603 if (uEDX & RT_BIT(19)) pHlp->pfnPrintf(pHlp, " 19"); 4604 if (uEDX & RT_BIT(20)) pHlp->pfnPrintf(pHlp, " NX"); 4605 if (uEDX & RT_BIT(21)) pHlp->pfnPrintf(pHlp, " 21"); 4606 if (uEDX & RT_BIT(22)) pHlp->pfnPrintf(pHlp, " ExtMMX"); 4607 if (uEDX & RT_BIT(23)) pHlp->pfnPrintf(pHlp, " MMX"); 4608 if (uEDX & RT_BIT(24)) pHlp->pfnPrintf(pHlp, " FXSR"); 4609 if (uEDX & RT_BIT(25)) pHlp->pfnPrintf(pHlp, " FastFXSR"); 4610 if (uEDX & RT_BIT(26)) pHlp->pfnPrintf(pHlp, " Page1GB"); 4611 if (uEDX & RT_BIT(27)) pHlp->pfnPrintf(pHlp, " RDTSCP"); 4612 if (uEDX & RT_BIT(28)) pHlp->pfnPrintf(pHlp, " 28"); 4613 if (uEDX & RT_BIT(29)) pHlp->pfnPrintf(pHlp, " LongMode"); 4614 if (uEDX & RT_BIT(30)) pHlp->pfnPrintf(pHlp, " Ext3DNow"); 4615 if (uEDX & RT_BIT(31)) pHlp->pfnPrintf(pHlp, " 3DNow"); 4616 pHlp->pfnPrintf(pHlp, "\n"); 4617 4618 uint32_t uECX = Guest.uEcx; 4619 pHlp->pfnPrintf(pHlp, "Features ECX: "); 4620 if (uECX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " LAHF/SAHF"); 4621 if (uECX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " CMPL"); 4622 if (uECX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " SVM"); 4623 if (uECX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " ExtAPIC"); 4624 if (uECX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " CR8L"); 4625 if (uECX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " ABM"); 4626 if (uECX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " SSE4A"); 4627 if (uECX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " MISALNSSE"); 4628 if (uECX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " 3DNOWPRF"); 4629 if (uECX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " OSVW"); 4630 if (uECX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " IBS"); 4631 if (uECX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " SSE5"); 4632 if (uECX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " SKINIT"); 4633 if (uECX & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " WDT"); 4634 for (unsigned iBit = 5; iBit < 32; iBit++) 4635 if (uECX & RT_BIT(iBit)) 4636 pHlp->pfnPrintf(pHlp, " %d", iBit); 4637 pHlp->pfnPrintf(pHlp, "\n"); 4638 } 4639 else 4640 { 4641 ASMCpuIdExSlow(0x80000001, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4642 4643 uint32_t uEdxGst = Guest.uEdx; 4644 uint32_t uEdxHst = Host.uEdx; 4645 pHlp->pfnPrintf(pHlp, "Mnemonic - Description = guest (host)\n"); 4646 pHlp->pfnPrintf(pHlp, "FPU - x87 FPU on Chip = %d (%d)\n", !!(uEdxGst & RT_BIT( 0)), !!(uEdxHst & RT_BIT( 0))); 4647 pHlp->pfnPrintf(pHlp, "VME - Virtual 8086 Mode Enhancements = %d (%d)\n", !!(uEdxGst & RT_BIT( 1)), !!(uEdxHst & RT_BIT( 1))); 4648 pHlp->pfnPrintf(pHlp, "DE - Debugging extensions = %d (%d)\n", !!(uEdxGst & RT_BIT( 2)), !!(uEdxHst & RT_BIT( 2))); 4649 pHlp->pfnPrintf(pHlp, "PSE - Page Size Extension = %d (%d)\n", !!(uEdxGst & RT_BIT( 3)), !!(uEdxHst & RT_BIT( 3))); 4650 pHlp->pfnPrintf(pHlp, "TSC - Time Stamp Counter = %d (%d)\n", !!(uEdxGst & RT_BIT( 4)), !!(uEdxHst & RT_BIT( 4))); 4651 pHlp->pfnPrintf(pHlp, "MSR - K86 Model Specific Registers = %d (%d)\n", !!(uEdxGst & RT_BIT( 5)), !!(uEdxHst & RT_BIT( 5))); 4652 pHlp->pfnPrintf(pHlp, "PAE - Physical Address Extension = %d (%d)\n", !!(uEdxGst & RT_BIT( 6)), !!(uEdxHst & RT_BIT( 6))); 4653 pHlp->pfnPrintf(pHlp, "MCE - Machine Check Exception = %d (%d)\n", !!(uEdxGst & RT_BIT( 7)), !!(uEdxHst & RT_BIT( 7))); 4654 pHlp->pfnPrintf(pHlp, "CX8 - CMPXCHG8B instruction = %d (%d)\n", !!(uEdxGst & RT_BIT( 8)), !!(uEdxHst & RT_BIT( 8))); 4655 pHlp->pfnPrintf(pHlp, "APIC - APIC On-Chip = %d (%d)\n", !!(uEdxGst & RT_BIT( 9)), !!(uEdxHst & RT_BIT( 9))); 4656 pHlp->pfnPrintf(pHlp, "10 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(10)), !!(uEdxHst & RT_BIT(10))); 4657 pHlp->pfnPrintf(pHlp, "SEP - SYSCALL and SYSRET = %d (%d)\n", !!(uEdxGst & RT_BIT(11)), !!(uEdxHst & RT_BIT(11))); 4658 pHlp->pfnPrintf(pHlp, "MTRR - Memory Type Range Registers = %d (%d)\n", !!(uEdxGst & RT_BIT(12)), !!(uEdxHst & RT_BIT(12))); 4659 pHlp->pfnPrintf(pHlp, "PGE - PTE Global Bit = %d (%d)\n", !!(uEdxGst & RT_BIT(13)), !!(uEdxHst & RT_BIT(13))); 4660 pHlp->pfnPrintf(pHlp, "MCA - Machine Check Architecture = %d (%d)\n", !!(uEdxGst & RT_BIT(14)), !!(uEdxHst & RT_BIT(14))); 4661 pHlp->pfnPrintf(pHlp, "CMOV - Conditional Move Instructions = %d (%d)\n", !!(uEdxGst & RT_BIT(15)), !!(uEdxHst & RT_BIT(15))); 4662 pHlp->pfnPrintf(pHlp, "PAT - Page Attribute Table = %d (%d)\n", !!(uEdxGst & RT_BIT(16)), !!(uEdxHst & RT_BIT(16))); 4663 pHlp->pfnPrintf(pHlp, "PSE-36 - 36-bit Page Size Extention = %d (%d)\n", !!(uEdxGst & RT_BIT(17)), !!(uEdxHst & RT_BIT(17))); 4664 pHlp->pfnPrintf(pHlp, "18 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(18)), !!(uEdxHst & RT_BIT(18))); 4665 pHlp->pfnPrintf(pHlp, "19 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(19)), !!(uEdxHst & RT_BIT(19))); 4666 pHlp->pfnPrintf(pHlp, "NX - No-Execute Page Protection = %d (%d)\n", !!(uEdxGst & RT_BIT(20)), !!(uEdxHst & RT_BIT(20))); 4667 pHlp->pfnPrintf(pHlp, "DS - Debug Store = %d (%d)\n", !!(uEdxGst & RT_BIT(21)), !!(uEdxHst & RT_BIT(21))); 4668 pHlp->pfnPrintf(pHlp, "AXMMX - AMD Extensions to MMX Instr. = %d (%d)\n", !!(uEdxGst & RT_BIT(22)), !!(uEdxHst & RT_BIT(22))); 4669 pHlp->pfnPrintf(pHlp, "MMX - Intel MMX Technology = %d (%d)\n", !!(uEdxGst & RT_BIT(23)), !!(uEdxHst & RT_BIT(23))); 4670 pHlp->pfnPrintf(pHlp, "FXSR - FXSAVE and FXRSTOR Instructions = %d (%d)\n", !!(uEdxGst & RT_BIT(24)), !!(uEdxHst & RT_BIT(24))); 4671 pHlp->pfnPrintf(pHlp, "25 - AMD fast FXSAVE and FXRSTOR Instr.= %d (%d)\n", !!(uEdxGst & RT_BIT(25)), !!(uEdxHst & RT_BIT(25))); 4672 pHlp->pfnPrintf(pHlp, "26 - 1 GB large page support = %d (%d)\n", !!(uEdxGst & RT_BIT(26)), !!(uEdxHst & RT_BIT(26))); 4673 pHlp->pfnPrintf(pHlp, "27 - RDTSCP instruction = %d (%d)\n", !!(uEdxGst & RT_BIT(27)), !!(uEdxHst & RT_BIT(27))); 4674 pHlp->pfnPrintf(pHlp, "28 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(28)), !!(uEdxHst & RT_BIT(28))); 4675 pHlp->pfnPrintf(pHlp, "29 - AMD Long Mode = %d (%d)\n", !!(uEdxGst & RT_BIT(29)), !!(uEdxHst & RT_BIT(29))); 4676 pHlp->pfnPrintf(pHlp, "30 - AMD Extensions to 3DNow! = %d (%d)\n", !!(uEdxGst & RT_BIT(30)), !!(uEdxHst & RT_BIT(30))); 4677 pHlp->pfnPrintf(pHlp, "31 - AMD 3DNow! = %d (%d)\n", !!(uEdxGst & RT_BIT(31)), !!(uEdxHst & RT_BIT(31))); 4678 4679 uint32_t uEcxGst = Guest.uEcx; 4680 uint32_t uEcxHst = Host.uEcx; 4681 pHlp->pfnPrintf(pHlp, "LahfSahf - LAHF/SAHF in 64-bit mode = %d (%d)\n", !!(uEcxGst & RT_BIT( 0)), !!(uEcxHst & RT_BIT( 0))); 4682 pHlp->pfnPrintf(pHlp, "CmpLegacy - Core MP legacy mode (depr) = %d (%d)\n", !!(uEcxGst & RT_BIT( 1)), !!(uEcxHst & RT_BIT( 1))); 4683 pHlp->pfnPrintf(pHlp, "SVM - AMD VM Extensions = %d (%d)\n", !!(uEcxGst & RT_BIT( 2)), !!(uEcxHst & RT_BIT( 2))); 4684 pHlp->pfnPrintf(pHlp, "APIC registers starting at 0x400 = %d (%d)\n", !!(uEcxGst & RT_BIT( 3)), !!(uEcxHst & RT_BIT( 3))); 4685 pHlp->pfnPrintf(pHlp, "AltMovCR8 - LOCK MOV CR0 means MOV CR8 = %d (%d)\n", !!(uEcxGst & RT_BIT( 4)), !!(uEcxHst & RT_BIT( 4))); 4686 pHlp->pfnPrintf(pHlp, "5 - Advanced bit manipulation = %d (%d)\n", !!(uEcxGst & RT_BIT( 5)), !!(uEcxHst & RT_BIT( 5))); 4687 pHlp->pfnPrintf(pHlp, "6 - SSE4A instruction support = %d (%d)\n", !!(uEcxGst & RT_BIT( 6)), !!(uEcxHst & RT_BIT( 6))); 4688 pHlp->pfnPrintf(pHlp, "7 - Misaligned SSE mode = %d (%d)\n", !!(uEcxGst & RT_BIT( 7)), !!(uEcxHst & RT_BIT( 7))); 4689 pHlp->pfnPrintf(pHlp, "8 - PREFETCH and PREFETCHW instruction= %d (%d)\n", !!(uEcxGst & RT_BIT( 8)), !!(uEcxHst & RT_BIT( 8))); 4690 pHlp->pfnPrintf(pHlp, "9 - OS visible workaround = %d (%d)\n", !!(uEcxGst & RT_BIT( 9)), !!(uEcxHst & RT_BIT( 9))); 4691 pHlp->pfnPrintf(pHlp, "10 - Instruction based sampling = %d (%d)\n", !!(uEcxGst & RT_BIT(10)), !!(uEcxHst & RT_BIT(10))); 4692 pHlp->pfnPrintf(pHlp, "11 - SSE5 support = %d (%d)\n", !!(uEcxGst & RT_BIT(11)), !!(uEcxHst & RT_BIT(11))); 4693 pHlp->pfnPrintf(pHlp, "12 - SKINIT, STGI, and DEV support = %d (%d)\n", !!(uEcxGst & RT_BIT(12)), !!(uEcxHst & RT_BIT(12))); 4694 pHlp->pfnPrintf(pHlp, "13 - Watchdog timer support. = %d (%d)\n", !!(uEcxGst & RT_BIT(13)), !!(uEcxHst & RT_BIT(13))); 4695 pHlp->pfnPrintf(pHlp, "31:14 - Reserved = %#x (%#x)\n", uEcxGst >> 14, uEcxHst >> 14); 4696 } 4697 } 4698 4699 if (iVerbosity && cExtMax >= 2) 4700 { 4701 char szString[4*4*3+1] = {0}; 4702 uint32_t *pu32 = (uint32_t *)szString; 4703 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEax; 4704 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEbx; 4705 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEcx; 4706 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[2].uEdx; 4707 if (cExtMax >= 3) 4708 { 4709 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEax; 4710 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEbx; 4711 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEcx; 4712 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[3].uEdx; 4713 } 4714 if (cExtMax >= 4) 4715 { 4716 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEax; 4717 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEbx; 4718 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEcx; 4719 *pu32++ = pVM->cpum.s.aGuestCpuIdPatmExt[4].uEdx; 4720 } 4721 pHlp->pfnPrintf(pHlp, "Full Name: %s\n", szString); 4722 } 4723 4724 if (iVerbosity && cExtMax >= 5) 4725 { 4726 uint32_t uEAX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEax; 4727 uint32_t uEBX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEbx; 4728 uint32_t uECX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEcx; 4729 uint32_t uEDX = pVM->cpum.s.aGuestCpuIdPatmExt[5].uEdx; 4730 char sz1[32]; 4731 char sz2[32]; 4732 4733 pHlp->pfnPrintf(pHlp, 4734 "TLB 2/4M Instr/Uni: %s %3d entries\n" 4735 "TLB 2/4M Data: %s %3d entries\n", 4736 getCacheAss((uEAX >> 8) & 0xff, sz1), (uEAX >> 0) & 0xff, 4737 getCacheAss((uEAX >> 24) & 0xff, sz2), (uEAX >> 16) & 0xff); 4738 pHlp->pfnPrintf(pHlp, 4739 "TLB 4K Instr/Uni: %s %3d entries\n" 4740 "TLB 4K Data: %s %3d entries\n", 4741 getCacheAss((uEBX >> 8) & 0xff, sz1), (uEBX >> 0) & 0xff, 4742 getCacheAss((uEBX >> 24) & 0xff, sz2), (uEBX >> 16) & 0xff); 4743 pHlp->pfnPrintf(pHlp, "L1 Instr Cache Line Size: %d bytes\n" 4744 "L1 Instr Cache Lines Per Tag: %d\n" 4745 "L1 Instr Cache Associativity: %s\n" 4746 "L1 Instr Cache Size: %d KB\n", 4747 (uEDX >> 0) & 0xff, 4748 (uEDX >> 8) & 0xff, 4749 getCacheAss((uEDX >> 16) & 0xff, sz1), 4750 (uEDX >> 24) & 0xff); 4751 pHlp->pfnPrintf(pHlp, 4752 "L1 Data Cache Line Size: %d bytes\n" 4753 "L1 Data Cache Lines Per Tag: %d\n" 4754 "L1 Data Cache Associativity: %s\n" 4755 "L1 Data Cache Size: %d KB\n", 4756 (uECX >> 0) & 0xff, 4757 (uECX >> 8) & 0xff, 4758 getCacheAss((uECX >> 16) & 0xff, sz1), 4759 (uECX >> 24) & 0xff); 4760 } 4761 4762 if (iVerbosity && cExtMax >= 6) 4763 { 4764 uint32_t uEAX = pVM->cpum.s.aGuestCpuIdPatmExt[6].uEax; 4765 uint32_t uEBX = pVM->cpum.s.aGuestCpuIdPatmExt[6].uEbx; 4766 uint32_t uEDX = pVM->cpum.s.aGuestCpuIdPatmExt[6].uEdx; 4767 4768 pHlp->pfnPrintf(pHlp, 4769 "L2 TLB 2/4M Instr/Uni: %s %4d entries\n" 4770 "L2 TLB 2/4M Data: %s %4d entries\n", 4771 getL2CacheAss((uEAX >> 12) & 0xf), (uEAX >> 0) & 0xfff, 4772 getL2CacheAss((uEAX >> 28) & 0xf), (uEAX >> 16) & 0xfff); 4773 pHlp->pfnPrintf(pHlp, 4774 "L2 TLB 4K Instr/Uni: %s %4d entries\n" 4775 "L2 TLB 4K Data: %s %4d entries\n", 4776 getL2CacheAss((uEBX >> 12) & 0xf), (uEBX >> 0) & 0xfff, 4777 getL2CacheAss((uEBX >> 28) & 0xf), (uEBX >> 16) & 0xfff); 4778 pHlp->pfnPrintf(pHlp, 4779 "L2 Cache Line Size: %d bytes\n" 4780 "L2 Cache Lines Per Tag: %d\n" 4781 "L2 Cache Associativity: %s\n" 4782 "L2 Cache Size: %d KB\n", 4783 (uEDX >> 0) & 0xff, 4784 (uEDX >> 8) & 0xf, 4785 getL2CacheAss((uEDX >> 12) & 0xf), 4786 (uEDX >> 16) & 0xffff); 4787 } 4788 4789 if (iVerbosity && cExtMax >= 7) 4790 { 4791 uint32_t uEDX = pVM->cpum.s.aGuestCpuIdPatmExt[7].uEdx; 4792 4793 pHlp->pfnPrintf(pHlp, "Host Invariant-TSC support: %RTbool\n", fSupportsInvariantTsc); 4794 pHlp->pfnPrintf(pHlp, "APM Features: "); 4795 if (uEDX & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " TS"); 4796 if (uEDX & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " FID"); 4797 if (uEDX & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " VID"); 4798 if (uEDX & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " TTP"); 4799 if (uEDX & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " TM"); 4800 if (uEDX & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " STC"); 4801 if (uEDX & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " MC"); 4802 if (uEDX & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " HWPSTATE"); 4803 if (uEDX & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " TscInvariant"); 4804 if (uEDX & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " CPB"); 4805 if (uEDX & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " EffFreqRO"); 4806 if (uEDX & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " PFI"); 4807 if (uEDX & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " PA"); 4808 for (unsigned iBit = 13; iBit < 32; iBit++) 4809 if (uEDX & RT_BIT(iBit)) 4810 pHlp->pfnPrintf(pHlp, " %d", iBit); 4811 pHlp->pfnPrintf(pHlp, "\n"); 4812 } 4813 4814 if (iVerbosity && cExtMax >= 8) 4815 { 4816 uint32_t uEAX = pVM->cpum.s.aGuestCpuIdPatmExt[8].uEax; 4817 uint32_t uECX = pVM->cpum.s.aGuestCpuIdPatmExt[8].uEcx; 4818 4819 pHlp->pfnPrintf(pHlp, 4820 "Physical Address Width: %d bits\n" 4821 "Virtual Address Width: %d bits\n" 4822 "Guest Physical Address Width: %d bits\n", 4823 (uEAX >> 0) & 0xff, 4824 (uEAX >> 8) & 0xff, 4825 (uEAX >> 16) & 0xff); 4826 pHlp->pfnPrintf(pHlp, 4827 "Physical Core Count: %d\n", 4828 (uECX >> 0) & 0xff); 4829 } 4830 4831 4832 /* 4833 * Hypervisor leaves. 4834 * 4835 * Unlike most of the other leaves reported, the guest hypervisor leaves 4836 * aren't a subset of the host CPUID bits. 4837 */ 4838 RT_ZERO(Host); 4839 if (cStdHstMax >= 1) 4840 ASMCpuIdExSlow(1, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4841 bool fHostHvp = RT_BOOL(Host.uEcx & X86_CPUID_FEATURE_ECX_HVP); 4842 bool fGuestHvp = false; 4843 if (cStdMax >= 1) 4844 { 4845 Guest = pVM->cpum.s.aGuestCpuIdPatmStd[1]; 4846 fGuestHvp = RT_BOOL(Guest.uEcx & X86_CPUID_FEATURE_ECX_HVP); 4847 } 4848 4849 if ( fHostHvp 4850 || fGuestHvp) 4851 { 4852 uint32_t const uHyperLeaf = 0x40000000; 4853 pHlp->pfnPrintf(pHlp, 4854 "\n" 4855 " Hypervisor CPUIDs\n" 4856 " Function eax ebx ecx edx\n"); 4857 4858 PCCPUMCPUIDLEAF pHyperLeafGst = NULL; 4859 if (fGuestHvp) 4860 { 4861 pHyperLeafGst = cpumR3CpuIdGetLeaf(pVM->cpum.s.GuestInfo.paCpuIdLeavesR3, pVM->cpum.s.GuestInfo.cCpuIdLeaves, 4862 uHyperLeaf, 0 /* uSubLeaf */); 4863 } 4864 4865 RT_ZERO(Host); 4866 if (fHostHvp) 4867 ASMCpuIdExSlow(uHyperLeaf, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4868 4869 CPUMCPUIDLEAF GuestLeaf; 4870 uint32_t const cHyperGstMax = pHyperLeafGst ? pHyperLeafGst->uEax : 0; 4871 uint32_t const cHyperHstMax = Host.uEax; 4872 uint32_t const cHyperMax = RT_MAX(cHyperHstMax, cHyperGstMax); 4873 for (uint32_t i = uHyperLeaf; i <= cHyperMax; i++) 4874 { 4875 RT_ZERO(Host); 4876 RT_ZERO(GuestLeaf); 4877 if (i <= cHyperHstMax) 4878 ASMCpuIdExSlow(i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4879 CPUMR3CpuIdGetLeaf(pVM, &GuestLeaf, i, 0 /* uSubLeaf */); 4880 if (!fHostHvp) 4881 { 4882 pHlp->pfnPrintf(pHlp, 4883 "Gst: %08x %08x %08x %08x %08x\n", 4884 i, GuestLeaf.uEax, GuestLeaf.uEbx, GuestLeaf.uEcx, GuestLeaf.uEdx); 4885 } 4886 else 4887 { 4888 pHlp->pfnPrintf(pHlp, 4889 "Gst: %08x %08x %08x %08x %08x%s\n" 4890 "Hst: %08x %08x %08x %08x%s\n", 4891 i, GuestLeaf.uEax, GuestLeaf.uEbx, GuestLeaf.uEcx, GuestLeaf.uEdx, 4892 i <= cHyperGstMax ? "" : "*", 4893 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx, i <= cHyperHstMax ? "" : "*"); 4894 } 4895 } 4896 } 4897 4898 /* 4899 * Centaur. 4900 */ 4901 unsigned cCentaurMax = pVM->cpum.s.aGuestCpuIdPatmCentaur[0].uEax & 0xffff; 4902 4903 pHlp->pfnPrintf(pHlp, 4904 "\n" 4905 " RAW Centaur CPUIDs\n" 4906 " Function eax ebx ecx edx\n"); 4907 for (unsigned i = 0; i < RT_ELEMENTS(pVM->cpum.s.aGuestCpuIdPatmCentaur); i++) 4908 { 4909 Guest = pVM->cpum.s.aGuestCpuIdPatmCentaur[i]; 4910 ASMCpuIdExSlow(0xc0000000 | i, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4911 4912 pHlp->pfnPrintf(pHlp, 4913 "Gst: %08x %08x %08x %08x %08x%s\n" 4914 "Hst: %08x %08x %08x %08x\n", 4915 0xc0000000 | i, Guest.uEax, Guest.uEbx, Guest.uEcx, Guest.uEdx, 4916 i <= cCentaurMax ? "" : "*", 4917 Host.uEax, Host.uEbx, Host.uEcx, Host.uEdx); 4918 } 4919 4920 /* 4921 * Understandable output 4922 */ 4923 if (iVerbosity) 4924 { 4925 Guest = pVM->cpum.s.aGuestCpuIdPatmCentaur[0]; 4926 pHlp->pfnPrintf(pHlp, 4927 "Centaur Supports: 0xc0000000-%#010x\n", 4928 Guest.uEax); 4929 } 4930 4931 if (iVerbosity && cCentaurMax >= 1) 4932 { 4933 ASMCpuIdExSlow(0xc0000001, 0, 0, 0, &Host.uEax, &Host.uEbx, &Host.uEcx, &Host.uEdx); 4934 uint32_t uEdxGst = pVM->cpum.s.aGuestCpuIdPatmCentaur[1].uEdx; 4935 uint32_t uEdxHst = Host.uEdx; 4936 4937 if (iVerbosity == 1) 4938 { 4939 pHlp->pfnPrintf(pHlp, "Centaur Features EDX: "); 4940 if (uEdxGst & RT_BIT(0)) pHlp->pfnPrintf(pHlp, " AIS"); 4941 if (uEdxGst & RT_BIT(1)) pHlp->pfnPrintf(pHlp, " AIS-E"); 4942 if (uEdxGst & RT_BIT(2)) pHlp->pfnPrintf(pHlp, " RNG"); 4943 if (uEdxGst & RT_BIT(3)) pHlp->pfnPrintf(pHlp, " RNG-E"); 4944 if (uEdxGst & RT_BIT(4)) pHlp->pfnPrintf(pHlp, " LH"); 4945 if (uEdxGst & RT_BIT(5)) pHlp->pfnPrintf(pHlp, " FEMMS"); 4946 if (uEdxGst & RT_BIT(6)) pHlp->pfnPrintf(pHlp, " ACE"); 4947 if (uEdxGst & RT_BIT(7)) pHlp->pfnPrintf(pHlp, " ACE-E"); 4948 /* possibly indicating MM/HE and MM/HE-E on older chips... */ 4949 if (uEdxGst & RT_BIT(8)) pHlp->pfnPrintf(pHlp, " ACE2"); 4950 if (uEdxGst & RT_BIT(9)) pHlp->pfnPrintf(pHlp, " ACE2-E"); 4951 if (uEdxGst & RT_BIT(10)) pHlp->pfnPrintf(pHlp, " PHE"); 4952 if (uEdxGst & RT_BIT(11)) pHlp->pfnPrintf(pHlp, " PHE-E"); 4953 if (uEdxGst & RT_BIT(12)) pHlp->pfnPrintf(pHlp, " PMM"); 4954 if (uEdxGst & RT_BIT(13)) pHlp->pfnPrintf(pHlp, " PMM-E"); 4955 for (unsigned iBit = 14; iBit < 32; iBit++) 4956 if (uEdxGst & RT_BIT(iBit)) 4957 pHlp->pfnPrintf(pHlp, " %d", iBit); 4958 pHlp->pfnPrintf(pHlp, "\n"); 4959 } 4960 else 4961 { 4962 pHlp->pfnPrintf(pHlp, "Mnemonic - Description = guest (host)\n"); 4963 pHlp->pfnPrintf(pHlp, "AIS - Alternate Instruction Set = %d (%d)\n", !!(uEdxGst & RT_BIT( 0)), !!(uEdxHst & RT_BIT( 0))); 4964 pHlp->pfnPrintf(pHlp, "AIS-E - AIS enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 1)), !!(uEdxHst & RT_BIT( 1))); 4965 pHlp->pfnPrintf(pHlp, "RNG - Random Number Generator = %d (%d)\n", !!(uEdxGst & RT_BIT( 2)), !!(uEdxHst & RT_BIT( 2))); 4966 pHlp->pfnPrintf(pHlp, "RNG-E - RNG enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 3)), !!(uEdxHst & RT_BIT( 3))); 4967 pHlp->pfnPrintf(pHlp, "LH - LongHaul MSR 0000_110Ah = %d (%d)\n", !!(uEdxGst & RT_BIT( 4)), !!(uEdxHst & RT_BIT( 4))); 4968 pHlp->pfnPrintf(pHlp, "FEMMS - FEMMS = %d (%d)\n", !!(uEdxGst & RT_BIT( 5)), !!(uEdxHst & RT_BIT( 5))); 4969 pHlp->pfnPrintf(pHlp, "ACE - Advanced Cryptography Engine = %d (%d)\n", !!(uEdxGst & RT_BIT( 6)), !!(uEdxHst & RT_BIT( 6))); 4970 pHlp->pfnPrintf(pHlp, "ACE-E - ACE enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 7)), !!(uEdxHst & RT_BIT( 7))); 4971 /* possibly indicating MM/HE and MM/HE-E on older chips... */ 4972 pHlp->pfnPrintf(pHlp, "ACE2 - Advanced Cryptography Engine 2 = %d (%d)\n", !!(uEdxGst & RT_BIT( 8)), !!(uEdxHst & RT_BIT( 8))); 4973 pHlp->pfnPrintf(pHlp, "ACE2-E - ACE enabled = %d (%d)\n", !!(uEdxGst & RT_BIT( 9)), !!(uEdxHst & RT_BIT( 9))); 4974 pHlp->pfnPrintf(pHlp, "PHE - Padlock Hash Engine = %d (%d)\n", !!(uEdxGst & RT_BIT(10)), !!(uEdxHst & RT_BIT(10))); 4975 pHlp->pfnPrintf(pHlp, "PHE-E - PHE enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(11)), !!(uEdxHst & RT_BIT(11))); 4976 pHlp->pfnPrintf(pHlp, "PMM - Montgomery Multiplier = %d (%d)\n", !!(uEdxGst & RT_BIT(12)), !!(uEdxHst & RT_BIT(12))); 4977 pHlp->pfnPrintf(pHlp, "PMM-E - PMM enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(13)), !!(uEdxHst & RT_BIT(13))); 4978 pHlp->pfnPrintf(pHlp, "14 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(14)), !!(uEdxHst & RT_BIT(14))); 4979 pHlp->pfnPrintf(pHlp, "15 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(15)), !!(uEdxHst & RT_BIT(15))); 4980 pHlp->pfnPrintf(pHlp, "Parallax = %d (%d)\n", !!(uEdxGst & RT_BIT(16)), !!(uEdxHst & RT_BIT(16))); 4981 pHlp->pfnPrintf(pHlp, "Parallax enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(17)), !!(uEdxHst & RT_BIT(17))); 4982 pHlp->pfnPrintf(pHlp, "Overstress = %d (%d)\n", !!(uEdxGst & RT_BIT(18)), !!(uEdxHst & RT_BIT(18))); 4983 pHlp->pfnPrintf(pHlp, "Overstress enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(19)), !!(uEdxHst & RT_BIT(19))); 4984 pHlp->pfnPrintf(pHlp, "TM3 - Temperature Monitoring 3 = %d (%d)\n", !!(uEdxGst & RT_BIT(20)), !!(uEdxHst & RT_BIT(20))); 4985 pHlp->pfnPrintf(pHlp, "TM3-E - TM3 enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(21)), !!(uEdxHst & RT_BIT(21))); 4986 pHlp->pfnPrintf(pHlp, "RNG2 - Random Number Generator 2 = %d (%d)\n", !!(uEdxGst & RT_BIT(22)), !!(uEdxHst & RT_BIT(22))); 4987 pHlp->pfnPrintf(pHlp, "RNG2-E - RNG2 enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(23)), !!(uEdxHst & RT_BIT(23))); 4988 pHlp->pfnPrintf(pHlp, "24 - Reserved = %d (%d)\n", !!(uEdxGst & RT_BIT(24)), !!(uEdxHst & RT_BIT(24))); 4989 pHlp->pfnPrintf(pHlp, "PHE2 - Padlock Hash Engine 2 = %d (%d)\n", !!(uEdxGst & RT_BIT(25)), !!(uEdxHst & RT_BIT(25))); 4990 pHlp->pfnPrintf(pHlp, "PHE2-E - PHE2 enabled = %d (%d)\n", !!(uEdxGst & RT_BIT(26)), !!(uEdxHst & RT_BIT(26))); 4991 for (unsigned iBit = 27; iBit < 32; iBit++) 4992 if ((uEdxGst | uEdxHst) & RT_BIT(iBit)) 4993 pHlp->pfnPrintf(pHlp, "Bit %d = %d (%d)\n", iBit, !!(uEdxGst & RT_BIT(iBit)), !!(uEdxHst & RT_BIT(iBit))); 4994 pHlp->pfnPrintf(pHlp, "\n"); 4995 } 4996 } 4997 } 4998 4999 5000 5001 5002 5003 /* 5004 * 5005 * 5006 * PATM interfaces. 5007 * PATM interfaces. 5008 * PATM interfaces. 5009 * 5010 * 5011 */ 3340 5012 3341 5013 … … 3354 5026 VMMR3_INT_DECL(RCPTRTYPE(PCCPUMCPUID)) CPUMR3GetGuestCpuIdPatmDefRCPtr(PVM pVM) 3355 5027 { 3356 return (RCPTRTYPE(PCCPUMCPUID))VM_RC_ADDR(pVM, &pVM->cpum.s.Guest CpuIdPatmDef);5028 return (RCPTRTYPE(PCCPUMCPUID))VM_RC_ADDR(pVM, &pVM->cpum.s.GuestInfo.DefCpuId); 3357 5029 } 3358 5030 … … 3394 5066 * @remark Intended for PATM only. 3395 5067 */ 3396 VMMR3_INT_DECL(CPUMU KNOWNCPUID) CPUMR3GetGuestCpuIdPatmUnknownLeafMethod(PVM pVM)5068 VMMR3_INT_DECL(CPUMUNKNOWNCPUID) CPUMR3GetGuestCpuIdPatmUnknownLeafMethod(PVM pVM) 3397 5069 { 3398 5070 return pVM->cpum.s.GuestInfo.enmUnknownCpuIdMethod; … … 3402 5074 3403 5075 /** 3404 * Gets a number of standard CPUID lea fs (PATM only).3405 * 3406 * @returns Number of lea fs.5076 * Gets a number of standard CPUID leaves (PATM only). 5077 * 5078 * @returns Number of leaves. 3407 5079 * @param pVM Pointer to the VM. 3408 5080 * @remark Intended for PATM - legacy, don't use in new code. … … 3415 5087 3416 5088 /** 3417 * Gets a number of extended CPUID lea fs (PATM only).3418 * 3419 * @returns Number of lea fs.5089 * Gets a number of extended CPUID leaves (PATM only). 5090 * 5091 * @returns Number of leaves. 3420 5092 * @param pVM Pointer to the VM. 3421 5093 * @remark Intended for PATM - legacy, don't use in new code. … … 3428 5100 3429 5101 /** 3430 * Gets a number of centaur CPUID lea fs.3431 * 3432 * @returns Number of lea fs.5102 * Gets a number of centaur CPUID leaves. 5103 * 5104 * @returns Number of leaves. 3433 5105 * @param pVM Pointer to the VM. 3434 5106 * @remark Intended for PATM - legacy, don't use in new code. -
trunk/src/VBox/VMM/VMMR3/CPUMR3Db.cpp
r54674 r54737 62 62 uint32_t cCpuIdLeaves; 63 63 /** The method used to deal with unknown CPUID leaves. */ 64 CPUMU KNOWNCPUID enmUnknownCpuId;64 CPUMUNKNOWNCPUID enmUnknownCpuId; 65 65 /** The default unknown CPUID value. */ 66 66 CPUMCPUID DefUnknownCpuId; -
trunk/src/VBox/VMM/VMMR3/EM.cpp
r51987 r54737 1407 1407 uint32_t u32Dummy, u32Features; 1408 1408 1409 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);1409 CPUMGetGuestCpuId(pVCpu, 1, 0, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features); 1410 1410 if (!(u32Features & X86_CPUID_FEATURE_EDX_PAE)) 1411 1411 return EMSTATE_REM; -
trunk/src/VBox/VMM/VMMR3/EMRaw.cpp
r47823 r54737 635 635 { 636 636 uint32_t u32Dummy, u32Features, u32ExtFeatures; 637 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Features);637 CPUMGetGuestCpuId(pVCpu, 1, 0, &u32Dummy, &u32Dummy, &u32ExtFeatures, &u32Features); 638 638 if (u32ExtFeatures & X86_CPUID_FEATURE_ECX_MONITOR) 639 639 { -
trunk/src/VBox/VMM/VMMR3/GIMMinimal.cpp
r54701 r54737 81 81 82 82 /* 83 * Insert missing zero leaves (you never know what missing leaves are 84 * going to return when read). 85 */ 86 for (uint32_t uLeaf = UINT32_C(0x40000001); uLeaf < UINT32_C(0x40000010); uLeaf++) 87 { 88 rc = CPUMR3CpuIdGetLeaf(pVM, &HyperLeaf, uLeaf, 0 /* uSubLeaf */); 89 if (RT_FAILURE(rc)) 90 { 91 RT_ZERO(HyperLeaf); 92 HyperLeaf.uLeaf = uLeaf; 93 rc = CPUMR3CpuIdInsert(pVM, &HyperLeaf); 94 AssertLogRelRCReturn(rc, rc); 95 } 96 } 97 98 /* 83 99 * Add the timing information hypervisor leaf. 84 100 * MacOS X uses this to determine the TSC, bus frequency. See @bugref{7270}. -
trunk/src/VBox/VMM/VMMR3/IEMR3.cpp
r48266 r54737 72 72 { 73 73 uint32_t uIgnored; 74 CPUMGetGuestCpuId(pVCpu, 1, &uIgnored, &uIgnored,74 CPUMGetGuestCpuId(pVCpu, 1, 0, &uIgnored, &uIgnored, 75 75 &pVCpu->iem.s.fCpuIdStdFeaturesEcx, &pVCpu->iem.s.fCpuIdStdFeaturesEdx); 76 76 pVCpu->iem.s.enmCpuVendor = CPUMGetGuestCpuVendor(pVM); -
trunk/src/VBox/VMM/VMMR3/MMHyper.cpp
r51271 r54737 1443 1443 * @returns VBox status code. 1444 1444 * @param pVM Pointer to the VM. 1445 * @param pvOld The existing block of memory in the 1446 * hyper heap to re-allocate (can be 1447 * NULL). 1445 * @param pvOld The existing block of memory in the hyper heap to 1446 * re-allocate (can be NULL). 1448 1447 * @param cbOld Size of the existing block. 1449 * @param uAlignmentNew Required memory alignment in bytes. 1450 * Values are 0,8,16,32 and PAGE_SIZE.1451 * 0 -> default alignment,i.e. 8 bytes.1448 * @param uAlignmentNew Required memory alignment in bytes. Values are 1449 * 0,8,16,32 and PAGE_SIZE. 0 -> default alignment, 1450 * i.e. 8 bytes. 1452 1451 * @param enmTagNew The statistics tag. 1453 1452 * @param cbNew The required size of the new block. 1454 * @param ppv Where to store the address to the 1455 * re-allocated block. 1456 * 1457 * @remarks This does not work like normal realloc() 1458 * on failure, the memory pointed to by @a pvOld is 1459 * lost if there isn't sufficient space on the hyper 1460 * heap for the re-allocation to succeed. 1453 * @param ppv Where to store the address to the re-allocated 1454 * block. 1455 * 1456 * @remarks This does not work like normal realloc() on failure, the memory 1457 * pointed to by @a pvOld is lost if there isn't sufficient space on 1458 * the hyper heap for the re-allocation to succeed. 1461 1459 */ 1462 1460 VMMR3DECL(int) MMR3HyperRealloc(PVM pVM, void *pvOld, size_t cbOld, unsigned uAlignmentNew, MMTAG enmTagNew, size_t cbNew, -
trunk/src/VBox/VMM/VMMR3/PATMA.asm
r54714 r54737 1784 1784 1785 1785 ; 1786 ; Out of range sub-lea fs aren't quite as easy and pretty as we emulate them1786 ; Out of range sub-leaves aren't quite as easy and pretty as we emulate them 1787 1787 ; here, but we do an adequate job. 1788 1788 ; 1789 1789 cpuid_subleaf_not_found: 1790 xor ecx, ecx 1791 test dword [ss:ebx + CPUMCPUIDLEAF.fFlags], CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES 1792 jz cpuid_load_zeros_except_ecx 1790 1793 mov ecx, [esp + 4] 1791 test dword [ss:ebx + CPUMCPUIDLEAF.fFlags], CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED 1792 jnz cpuid_load_zeros_except_ecx 1793 cpuid_load_zeros: 1794 xor ecx, ecx 1794 and ecx, 0ffh 1795 1795 cpuid_load_zeros_except_ecx: 1796 1796 xor edx, edx … … 1805 1805 mov edx, PATM_CPUID_UNKNOWN_METHOD 1806 1806 PATCH_FIXUP PATM_CPUID_UNKNOWN_METHOD 1807 cmp edx, CPUMU KNOWNCPUID_PASSTHRU1807 cmp edx, CPUMUNKNOWNCPUID_PASSTHRU 1808 1808 je cpuid_unknown_passthru 1809 1809 ; Load the default cpuid leaf. -
trunk/src/VBox/VMM/VMMR3/PATMSSM.cpp
r54714 r54737 1254 1254 * 2. That the forced actions were in the first 32 bytes of the VM 1255 1255 * structure. 1256 * 3. That the CPUM lea fs are less than 8KB into the structure.1256 * 3. That the CPUM leaves are less than 8KB into the structure. 1257 1257 */ 1258 1258 else if ( uVersion <= PATM_SAVED_STATE_VERSION_FIXUP_HACK -
trunk/src/VBox/VMM/VMMR3/PDMDevHlp.cpp
r53797 r54737 3454 3454 AssertPtr(pEax); AssertPtr(pEbx); AssertPtr(pEcx); AssertPtr(pEdx); 3455 3455 3456 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, pEax, pEbx, pEcx, pEdx);3456 CPUMGetGuestCpuId(VMMGetCpu(pDevIns->Internal.s.pVMR3), iLeaf, 0 /*iSubLeaf*/, pEax, pEbx, pEcx, pEdx); 3457 3457 3458 3458 LogFlow(("pdmR3DevHlp_GetCpuId: caller='%s'/%d: returns void - *pEax=%#x *pEbx=%#x *pEcx=%#x *pEdx=%#x\n", -
trunk/src/VBox/VMM/VMMR3/PGM.cpp
r49893 r54737 2214 2214 */ 2215 2215 uint32_t u32Dummy, u32Features; 2216 CPUMGetGuestCpuId(VMMGetCpu(pVM), 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);2216 CPUMGetGuestCpuId(VMMGetCpu(pVM), 1, 0, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features); 2217 2217 if (u32Features & X86_CPUID_FEATURE_EDX_PSE36) 2218 2218 pVM->pgm.s.GCPhys4MBPSEMask = RT_BIT_64(RT_MAX(36, cMaxPhysAddrWidth)) - 1; … … 3578 3578 uint32_t u32Dummy, u32Features; 3579 3579 3580 CPUMGetGuestCpuId(pVCpu, 1, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features);3580 CPUMGetGuestCpuId(pVCpu, 1, 0, &u32Dummy, &u32Dummy, &u32Dummy, &u32Features); 3581 3581 if (!(u32Features & X86_CPUID_FEATURE_EDX_PAE)) 3582 3582 return VMSetRuntimeError(pVM, VMSETRTERR_FLAGS_FATAL, "PAEmode", -
trunk/src/VBox/VMM/VMMR3/VMM.cpp
r53466 r54737 711 711 712 712 /* 713 * Last chance for GIM to update its CPUID lea fs if it requires knowledge/information714 * from HM initialization.713 * Last chance for GIM to update its CPUID leaves if it requires 714 * knowledge/information from HM initialization. 715 715 */ 716 716 rc = GIMR3InitCompleted(pVM); -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_3200.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x00000f48, 0x00000800, 0x00000000, 0x078bfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x00000f48, 0x00000800, 0x00000000, 0x078bfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x80000000, 0x00000000, 0x00000000, 0x80000018, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 32 32 { 0x80000001, 0x00000000, 0x00000000, 0x00000f48, 0x0000010a, 0x00000000, 0xe1d3fbff, 0 }, … … 210 210 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_AMD_Athlon_64_3200), 211 211 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_Athlon_64_3200)), 212 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_DEFAULTS,212 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_DEFAULTS, 213 213 /*.DefUnknownCpuId = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 214 214 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Athlon_64_X2_Dual_Core_4200.h
r51234 r54737 11 11 12 12 /* 13 * Copyright (C) 2013 Oracle Corporation13 * Copyright (C) 2013-2015 Oracle Corporation 14 14 * 15 15 * This file is part of VirtualBox Open Source Edition (OSE), as … … 33 33 { 34 34 { 0x00000000, 0x00000000, 0x00000000, 0x00000001, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 35 { 0x00000001, 0x00000000, 0x00000000, 0x00040fb2, 0x01020800, 0x00002001, 0x178bfbff, 0 },35 { 0x00000001, 0x00000000, 0x00000000, 0x00040fb2, 0x01020800, 0x00002001, 0x178bfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 36 36 { 0x80000000, 0x00000000, 0x00000000, 0x80000018, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 37 37 { 0x80000001, 0x00000000, 0x00000000, 0x00040fb2, 0x000008d1, 0x0000001f, 0xebd3fbff, 0 }, … … 218 218 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_AMD_Athlon_64_X2_Dual_Core_4200), 219 219 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_Athlon_64_X2_Dual_Core_4200)), 220 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_DEFAULTS,220 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_DEFAULTS, 221 221 /*.DefUnknownCpuId = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 222 222 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_FX_8150_Eight_Core.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x00600f12, 0x02080800, 0x1e98220b, 0x178bfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x00600f12, 0x02080800, 0x1e98220b, 0x178bfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 76 76 { 0x8000001d, 0x00000003, UINT32_MAX, 0x0001c163, 0x0fc0003f, 0x000007ff, 0x00000001, 0 }, 77 77 { 0x8000001d, 0x00000004, UINT32_MAX, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 78 { 0x8000001e, 0x00000000, 0x00000000, 0x00000012, 0x00000101, 0x00000000, 0x00000000, 0 },78 { 0x8000001e, 0x00000000, 0x00000000, 0x00000012, 0x00000101, 0x00000000, 0x00000000, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 79 79 }; 80 80 #endif /* !CPUM_DB_STANDALONE */ … … 369 369 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_AMD_FX_8150_Eight_Core), 370 370 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_FX_8150_Eight_Core)), 371 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_DEFAULTS,371 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_DEFAULTS, 372 372 /*.DefUnknownCpuId = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 373 373 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/AMD_Phenom_II_X6_1100T.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x00000006, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x00100fa0, 0x01060800, 0x00802009, 0x178bfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x00100fa0, 0x01060800, 0x00802009, 0x178bfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 258 258 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_AMD_Phenom_II_X6_1100T), 259 259 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_AMD_Phenom_II_X6_1100T)), 260 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_DEFAULTS,260 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_DEFAULTS, 261 261 /*.DefUnknownCpuId = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 262 262 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i5_3570.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x000306a9, 0x04100800, 0x7fbae3ff, 0xbfebfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x000306a9, 0x04100800, 0x7fbae3ff, 0xbfebfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b0ff, 0x00000000, 0x00ca0000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 38 38 { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 39 39 { 0x0000000a, 0x00000000, 0x00000000, 0x07300803, 0x00000000, 0x00000000, 0x00000603, 0 }, 40 { 0x0000000b, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000100, 0x00000004, 0 },40 { 0x0000000b, 0x00000000, 0x00000000, 0x00000001, 0x00000001, 0x00000100, 0x00000004, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 41 41 { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 42 42 { 0x0000000d, 0x00000000, 0x00000000, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 }, … … 325 325 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i5_3570), 326 326 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i5_3570)), 327 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF_WITH_ECX,327 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX, 328 328 /*.DefUnknownCpuId = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 }, 329 329 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_2635QM.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x000206a7, 0x04100800, 0x1fbae3bf, 0xbfebfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x000206a7, 0x04100800, 0x1fbae3bf, 0xbfebfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 42 42 { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 43 43 { 0x0000000a, 0x00000000, 0x00000000, 0x07300403, 0x00000000, 0x00000000, 0x00000603, 0 }, 44 /** @todo the b entry here is WRONG! */ 45 { 0x0000000b, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 44 46 { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 45 47 { 0x0000000d, 0x00000000, UINT32_MAX, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 }, … … 316 318 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_2635QM), 317 319 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i7_2635QM)), 318 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF_WITH_ECX,320 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX, 319 321 /*.DefUnknownCpuId = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 }, 320 322 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3820QM.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x000306a9, 0x02100800, 0x7fbae3ff, 0xbfebfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x000306a9, 0x02100800, 0x7fbae3ff, 0xbfebfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 38 38 { 0x00000009, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 39 39 { 0x0000000a, 0x00000000, 0x00000000, 0x07300403, 0x00000000, 0x00000000, 0x00000603, 0 }, 40 { 0x0000000b, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000100, 0x00000002, 0 },40 { 0x0000000b, 0x00000000, 0x00000000, 0x00000001, 0x00000002, 0x00000100, 0x00000002, 0 | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 41 41 { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 42 42 { 0x0000000d, 0x00000000, 0x00000000, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 }, … … 367 367 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_3820QM), 368 368 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i7_3820QM)), 369 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF_WITH_ECX,369 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX, 370 370 /*.DefUnknownCpuId = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 }, 371 371 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Core_i7_3960X.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000d, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x000206d6, 0x02200800, 0x1fbee3bf, 0xbfebfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x000206d6, 0x02200800, 0x1fbee3bf, 0xbfebfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x76035a01, 0x00f0b2ff, 0x00000000, 0x00ca0000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 42 42 { 0x00000009, 0x00000000, 0x00000000, 0x00000001, 0x00000000, 0x00000000, 0x00000000, 0 }, 43 43 { 0x0000000a, 0x00000000, 0x00000000, 0x07300403, 0x00000000, 0x00000000, 0x00000603, 0 }, 44 { 0x0000000b, 0x00000000, UINT32_MAX, 0x00000001, 0x00000002, 0x00000100, 0x00000002, 0 },45 { 0x0000000b, 0x00000001, UINT32_MAX, 0x00000005, 0x0000000c, 0x00000201, 0x00000002, 0 },46 { 0x0000000b, 0x00000002, UINT32_MAX, 0x00000000, 0x00000000, 0x00000002, 0x00000002, 0 | CPUMCPUIDLEAF_F_ SUBLEAVES_ECX_UNCHANGED },44 { 0x0000000b, 0x00000000, UINT32_MAX, 0x00000001, 0x00000002, 0x00000100, 0x00000002, 0 | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 45 { 0x0000000b, 0x00000001, UINT32_MAX, 0x00000005, 0x0000000c, 0x00000201, 0x00000002, 0 | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 46 { 0x0000000b, 0x00000002, UINT32_MAX, 0x00000000, 0x00000000, 0x00000002, 0x00000002, 0 | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 47 47 { 0x0000000c, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 48 48 { 0x0000000d, 0x00000000, UINT32_MAX, 0x00000007, 0x00000340, 0x00000340, 0x00000000, 0 }, … … 355 355 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Core_i7_3960X), 356 356 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Core_i7_3960X)), 357 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF_WITH_ECX,357 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX, 358 358 /*.DefUnknownCpuId = */ { 0x00000007, 0x00000340, 0x00000340, 0x00000000 }, 359 359 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_4_3_00GHz.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x00000005, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x00000f43, 0x00020800, 0x0000649d, 0xbfebfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x00000f43, 0x00020800, 0x0000649d, 0xbfebfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x605b5001, 0x00000000, 0x00000000, 0x007d7040, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 263 263 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Pentium_4_3_00GHz), 264 264 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Pentium_4_3_00GHz)), 265 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF,265 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF, 266 266 /*.DefUnknownCpuId = */ { 0x00000040, 0x00000040, 0x00000000, 0x00000000 }, 267 267 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Pentium_M_processor_2_00GHz.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x00000002, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x000006d6, 0x00000816, 0x00000180, 0xafe9f9bf, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x000006d6, 0x00000816, 0x00000180, 0xafe9f9bf, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x02b3b001, 0x000000f0, 0x00000000, 0x2c04307d, 0 }, 32 32 { 0x80000000, 0x00000000, 0x00000000, 0x80000004, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 202 202 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Pentium_M_processor_2_00GHz), 203 203 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Pentium_M_processor_2_00GHz)), 204 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF,204 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF, 205 205 /*.DefUnknownCpuId = */ { 0x02b3b001, 0x000000f0, 0x00000000, 0x2c04307d }, 206 206 /*.fMsrMask = */ UINT32_C(0x3fff), -
trunk/src/VBox/VMM/VMMR3/cpus/Intel_Xeon_X5482_3_20GHz.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000a, 0x756e6547, 0x6c65746e, 0x49656e69, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x00010676, 0x04040800, 0x000ce3bd, 0xbfebfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x00010676, 0x04040800, 0x000ce3bd, 0xbfebfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x05b0b101, 0x005657f0, 0x00000000, 0x2cb4304e, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 231 231 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Intel_Xeon_X5482_3_20GHz), 232 232 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Intel_Xeon_X5482_3_20GHz)), 233 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_LAST_STD_LEAF,233 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_LAST_STD_LEAF, 234 234 /*.DefUnknownCpuId = */ { 0x07280202, 0x00000000, 0x00000000, 0x00000503 }, 235 235 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/Quad_Core_AMD_Opteron_2384.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x00000005, 0x68747541, 0x444d4163, 0x69746e65, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x00100f42, 0x06040800, 0x00802009, 0x178bfbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x00100f42, 0x06040800, 0x00802009, 0x178bfbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 256 256 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_Quad_Core_AMD_Opteron_2384), 257 257 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_Quad_Core_AMD_Opteron_2384)), 258 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_DEFAULTS,258 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_DEFAULTS, 259 259 /*.DefUnknownCpuId = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 260 260 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/VMMR3/cpus/VIA_QuadCore_L4700_1_2_GHz.h
r53624 r54737 6 6 7 7 /* 8 * Copyright (C) 2013 Oracle Corporation8 * Copyright (C) 2013-2015 Oracle Corporation 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 28 28 { 29 29 { 0x00000000, 0x00000000, 0x00000000, 0x0000000a, 0x746e6543, 0x736c7561, 0x48727561, 0 }, 30 { 0x00000001, 0x00000000, 0x00000000, 0x000006fd, 0x06080800, 0x008863a9, 0xbfc9fbff, 0 },30 { 0x00000001, 0x00000000, 0x00000000, 0x000006fd, 0x06080800, 0x008863a9, 0xbfc9fbff, 0 | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID }, 31 31 { 0x00000002, 0x00000000, 0x00000000, 0x02b3b001, 0x00000000, 0x00000000, 0x2c04307d, 0 }, 32 32 { 0x00000003, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0 }, … … 390 390 /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_VIA_QuadCore_L4700_1_2_GHz), 391 391 /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_VIA_QuadCore_L4700_1_2_GHz)), 392 /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_DEFAULTS,392 /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_DEFAULTS, 393 393 /*.DefUnknownCpuId = */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000 }, 394 394 /*.fMsrMask = */ UINT32_MAX, -
trunk/src/VBox/VMM/include/CPUMInternal.h
r54674 r54737 30 30 /* Some fudging. */ 31 31 typedef uint32_t CPUMMICROARCH; 32 typedef uint32_t CPUMU KNOWNCPUID;32 typedef uint32_t CPUMUNKNOWNCPUID; 33 33 typedef struct CPUMCPUIDLEAF *PCPUMCPUIDLEAF; 34 34 typedef struct CPUMMSRRANGE *PCPUMMSRRANGE; … … 123 123 * @{ */ 124 124 /** The current saved state version. */ 125 #define CPUM_SAVED_STATE_VERSION 14 126 /** The current saved state version before using SSMR3PutStruct. */ 125 #define CPUM_SAVED_STATE_VERSION 15 126 /** The saved state version before the CPUIDs changes. */ 127 #define CPUM_SAVED_STATE_VERSION_PUT_STRUCT 14 128 /** The saved state version before using SSMR3PutStruct. */ 127 129 #define CPUM_SAVED_STATE_VERSION_MEM 13 128 130 /** The saved state version before introducing the MSR size field. */ … … 244 246 uint32_t uPadding; 245 247 /** How to handle unknown CPUID leaves. */ 246 CPUMUKNOWNCPUID enmUnknownCpuIdMethod; 247 /** For use with CPUMUKNOWNCPUID_DEFAULTS. */ 248 CPUMUNKNOWNCPUID enmUnknownCpuIdMethod; 249 /** For use with CPUMUNKNOWNCPUID_DEFAULTS (DB & VM), 250 * CPUMUNKNOWNCPUID_LAST_STD_LEAF (VM) and CPUMUNKNOWNCPUID_LAST_STD_LEAF_WITH_ECX (VM). */ 248 251 CPUMCPUID DefCpuId; 249 252 … … 492 495 /** The centaur set of CpuId leaves. */ 493 496 CPUMCPUID aGuestCpuIdPatmCentaur[4]; 494 /** The default set of CpuId leaves. */495 CPUMCPUID GuestCpuIdPatmDef;496 497 497 498 #if HC_ARCH_BITS == 32 … … 601 602 RT_C_DECLS_BEGIN 602 603 603 PCPUMCPUIDLEAF cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf); 604 PCPUMCPUIDLEAF cpumCpuIdGetLeaf(PVM pVM, uint32_t uLeaf); 605 PCPUMCPUIDLEAF cpumCpuIdGetLeafEx(PVM pVM, uint32_t uLeaf, uint32_t uSubLeaf, bool *pfExactSubLeafHit); 604 606 605 607 #ifdef IN_RING3 606 608 int cpumR3DbgInit(PVM pVM); 607 PCPUMCPUIDLEAF cpumR3CpuIdGetLeaf(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf);608 bool cpumR3CpuIdGetLeafLegacy(PCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, uint32_t uLeaf, uint32_t uSubLeaf,609 PCPUMCPUID pLeagcy);610 int cpumR3CpuIdInsert(PVM pVM, PCPUMCPUIDLEAF *ppaLeaves, uint32_t *pcLeaves, PCPUMCPUIDLEAF pNewLeaf);611 void cpumR3CpuIdRemoveRange(PCPUMCPUIDLEAF paLeaves, uint32_t *pcLeaves, uint32_t uFirst, uint32_t uLast);612 609 int cpumR3CpuIdExplodeFeatures(PCCPUMCPUIDLEAF paLeaves, uint32_t cLeaves, PCPUMFEATURES pFeatures); 613 int cpumR3 CpuIdInit(PVM pVM);610 int cpumR3InitCpuIdAndMsrs(PVM pVM); 614 611 void cpumR3SaveCpuId(PVM pVM, PSSMHANDLE pSSM); 615 612 int cpumR3LoadCpuId(PVM pVM, PSSMHANDLE pSSM, uint32_t uVersion); 613 DECLCALLBACK(void) cpumR3CpuIdInfo(PVM pVM, PCDBGFINFOHLP pHlp, const char *pszArgs); 616 614 617 615 int cpumR3DbGetCpuInfo(const char *pszName, PCPUMINFO pInfo); -
trunk/src/VBox/VMM/include/CPUMInternal.mac
r54674 r54737 80 80 %endif 81 81 82 ; CPUID leafs82 ; Patch manager saved state compatability CPUID leaf arrays 83 83 .aGuestCpuIdPatmStd resb 16*6 84 84 .aGuestCpuIdPatmExt resb 16*10 85 85 .aGuestCpuIdPatmCentaur resb 16*4 86 .GuestCpuIdPatmDef resb 1687 86 88 87 %if HC_ARCH_BITS == 32 -
trunk/src/VBox/VMM/testcase/tstVMStruct.h
r54674 r54737 40 40 GEN_CHECK_OFF(CPUM, aGuestCpuIdPatmExt); 41 41 GEN_CHECK_OFF(CPUM, aGuestCpuIdPatmCentaur); 42 GEN_CHECK_OFF(CPUM, GuestCpuIdPatmDef);43 42 44 43 GEN_CHECK_SIZE(CPUMCPU); // has .mac -
trunk/src/VBox/VMM/tools/VBoxCpuReport.cpp
r54714 r54737 5 5 6 6 /* 7 * Copyright (C) 2013 Oracle Corporation7 * Copyright (C) 2013-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 4389 4389 vbCpuRepPrintf("0"); 4390 4390 uint32_t fFlags = paLeaves[i].fFlags; 4391 if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_ SUBLEAVES_ECX_UNCHANGED)4391 if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES) 4392 4392 { 4393 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED"); 4394 fFlags &= ~CPUMCPUIDLEAF_F_SUBLEAVES_ECX_UNCHANGED; 4393 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES"); 4394 fFlags &= ~CPUMCPUIDLEAF_F_INTEL_TOPOLOGY_SUBLEAVES; 4395 } 4396 if (paLeaves[i].fFlags & CPUMCPUIDLEAF_F_CONTAINS_APIC_ID) 4397 { 4398 vbCpuRepPrintf(" | CPUMCPUIDLEAF_F_CONTAINS_APIC_ID"); 4399 fFlags &= ~CPUMCPUIDLEAF_F_CONTAINS_APIC_ID; 4395 4400 } 4396 4401 if (fFlags) … … 4589 4594 "\n" 4590 4595 "/*\n" 4591 " * Copyright (C) 2013 Oracle Corporation\n"4596 " * Copyright (C) 2013-2015 Oracle Corporation\n" 4592 4597 " *\n" 4593 4598 " * This file is part of VirtualBox Open Source Edition (OSE), as\n" … … 4615 4620 return rc; 4616 4621 4617 CPUMU KNOWNCPUID enmUnknownMethod;4622 CPUMUNKNOWNCPUID enmUnknownMethod; 4618 4623 CPUMCPUID DefUnknown; 4619 4624 rc = CPUMR3CpuIdDetectUnknownLeafMethod(&enmUnknownMethod, &DefUnknown); … … 4650 4655 " /*.paCpuIdLeaves = */ NULL_ALONE(g_aCpuIdLeaves_%s),\n" 4651 4656 " /*.cCpuIdLeaves = */ ZERO_ALONE(RT_ELEMENTS(g_aCpuIdLeaves_%s)),\n" 4652 " /*.enmUnknownCpuId = */ CPUMU KNOWNCPUID_%s,\n"4657 " /*.enmUnknownCpuId = */ CPUMUNKNOWNCPUID_%s,\n" 4653 4658 " /*.DefUnknownCpuId = */ { %#010x, %#010x, %#010x, %#010x },\n" 4654 4659 " /*.fMsrMask = */ %s,\n"
Note:
See TracChangeset
for help on using the changeset viewer.