static HWVIRTTYPE isHwVirtSupported(void) { #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) uint32_t uEax, uEbx, uEcx, uEdx; /* VT-x */ ASMCpuId(0x00000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidStdRange(uEax)) { ASMCpuId(0x00000001, &uEax, &uEbx, &uEcx, &uEdx); if (uEcx & X86_CPUID_FEATURE_ECX_VMX) return HWVIRTTYPE_VTX; } /* AMD-V */ ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax)) { ASMCpuId(0x80000001, &uEax, &uEbx, &uEcx, &uEdx); if (uEcx & X86_CPUID_AMD_FEATURE_ECX_SVM) return HWVIRTTYPE_AMDV; } #endif return HWVIRTTYPE_NONE; }
/** Print the 'true' if nested paging is supported, 'false' if not and * 'dunno' if we cannot tell. */ static RTEXITCODE handlerCpuNestedPaging(int argc, char **argv) { NOREF(argc); NOREF(argv); HWVIRTTYPE enmHwVirt = isHwVirtSupported(); int fSupported = -1; #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) if (enmHwVirt == HWVIRTTYPE_AMDV) { uint32_t uEax, uEbx, uEcx, uEdx; ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a) { ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */) fSupported = 1; else fSupported = 0; } } #endif int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n"); return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
/** Print the 'true' if long mode guests are supported, 'false' if not and * 'dunno' if we cannot tell. */ static RTEXITCODE handlerCpuLongMode(int argc, char **argv) { NOREF(argc); NOREF(argv); HWVIRTTYPE enmHwVirt = isHwVirtSupported(); int fSupported = 0; if (enmHwVirt != HWVIRTTYPE_NONE) { #if defined(RT_ARCH_AMD64) fSupported = 1; /* We're running long mode, so it must be supported. */ #elif defined(RT_ARCH_X86) # ifdef RT_OS_DARWIN /* On darwin, we just ask the kernel via sysctl. Rules are a bit different here. */ int f64bitCapable = 0; size_t cbParameter = sizeof(f64bitCapable); int rc = sysctlbyname("hw.cpu64bit_capable", &f64bitCapable, &cbParameter, NULL, NULL); if (rc != -1) fSupported = f64bitCapable != 0; else # endif { /* PAE and HwVirt are required */ uint32_t uEax, uEbx, uEcx, uEdx; ASMCpuId(0x00000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidStdRange(uEax)) { ASMCpuId(0x00000001, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & X86_CPUID_FEATURE_EDX_PAE) { /* AMD will usually advertise long mode in 32-bit mode. Intel OTOH, won't necessarily do so. */ ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax)) { ASMCpuId(0x80000001, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & X86_CPUID_EXT_FEATURE_EDX_LONG_MODE) fSupported = 1; else if (enmHwVirt != HWVIRTTYPE_AMDV) fSupported = -1; } } } } #endif } int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n"); return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }
/** Print the 'true' if nested paging is supported, 'false' if not and * 'dunno' if we cannot tell. */ static RTEXITCODE handlerCpuNestedPaging(int argc, char **argv) { NOREF(argc); NOREF(argv); HWVIRTTYPE enmHwVirt = isHwVirtSupported(); int fSupported = -1; #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_X86) if (enmHwVirt == HWVIRTTYPE_AMDV) { uint32_t uEax, uEbx, uEcx, uEdx; ASMCpuId(0x80000000, &uEax, &uEbx, &uEcx, &uEdx); if (ASMIsValidExtRange(uEax) && uEax >= 0x8000000a) { ASMCpuId(0x8000000a, &uEax, &uEbx, &uEcx, &uEdx); if (uEdx & RT_BIT(0) /* AMD_CPUID_SVM_FEATURE_EDX_NESTED_PAGING */) fSupported = 1; else fSupported = 0; } } # if defined(RT_OS_LINUX) else if (enmHwVirt == HWVIRTTYPE_VTX) { /* * For Intel there is no generic way to query EPT support but on * Linux we can resort to checking for the EPT flag in /proc/cpuinfo */ RTFILE hFileCpu; int rc = RTFileOpen(&hFileCpu, "/proc/cpuinfo", RTFILE_O_OPEN | RTFILE_O_READ | RTFILE_O_DENY_NONE); if (RT_SUCCESS(rc)) { /* * Read enough to fit the first CPU entry in, we only check the first * CPU as all the others should have the same features. */ char szBuf[_4K]; size_t cbRead = 0; RT_ZERO(szBuf); /* Ensure proper termination. */ rc = RTFileRead(hFileCpu, &szBuf[0], sizeof(szBuf) - 1, &cbRead); if (RT_SUCCESS(rc)) { /* Look for the start of the flags section. */ char *pszStrFlags = RTStrStr(&szBuf[0], "flags"); if (pszStrFlags) { /* Look for the end as indicated by new line. */ char *pszEnd = pszStrFlags; while ( *pszEnd != '\0' && *pszEnd != '\n') pszEnd++; *pszEnd = '\0'; /* Cut off everything after the flags section. */ /* * Search for the ept flag indicating support and the absence meaning * not supported. */ if (RTStrStr(pszStrFlags, "ept")) fSupported = 1; else fSupported = 0; } } RTFileClose(hFileCpu); } } # endif #endif int cch = RTPrintf(fSupported == 1 ? "true\n" : fSupported == 0 ? "false\n" : "dunno\n"); return cch > 0 ? RTEXITCODE_SUCCESS : RTEXITCODE_FAILURE; }