VMX 这技术已经出现好多年了,市面上的CPU大多都支持了,那还有必要检查系统是否支持VMX吗?考虑一下还是要检查的,就算市面上的CPU都支持了,但各家的BIOS/UEFI有别,VMX可能会被禁用,所以你的软件应该进行检查,如果发现VMX被禁用,应该恰当的提示用户。
现在让我们来过一遍流程:
1,确认当前的CPU是不是intel的,毕竟这里讨论的都是VMX; 使用指令CPUID.1,返回值按照ebx,edx,ecx排列,就是GenuineIntel,知道就好,写代码的时候没必要抠这种细节,去排这个序。示例代码如下:(注意:代码默认使用WDK风格,如int 默认长度为 32个bit,此类问题以后不再赘述)
#define BASIC_INTEL_STR "GenuntelineI" int cpuInfo[4] = {0};//eax, ebx, ecx, edx __cpuid(cpuInfo, 0); if (3*sizeof(int) != RtlCompareMemory(BASIC_INTEL_STR, cpuInfo+1, 3*sizeof(int))) { //not match }
2,检查CPU是否支持VMX,使用CPUID.1:ECX.VMX[bit 5]来判断,示例代码如下:
#define CUPID_ECX_VMX (1 << 5) int cpuInfo[4] = {0};//eax, ebx, ecx, edx __cpuid(cpuInfo, 1); if(cpuInfo[2] & CUPID_ECX_VMX) { //OK,cpu support vmx }
3,检查BIOS/UEFI是否禁用了VMX,前面两个步骤中使用的 CPUID 可以在user mode中使用,但从这里开始 你将不得不写一些驱动代码。(有人需要《驱动编程指北》,我可以另开一个章节) 示例代码如下:
#define IA32_FEATURE_CONTROL_MSR 0x3a #define IA32_FEATURE_CONTROL_LOCKED (1 << 0) #define IA32_FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX (1 << 1) #define IA32_FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX (1 << 2) __int64 featureInfo = 0; featureInfo = __rdmsr( IA32_FEATURE_CONTROL_MSR); if(!(featureInfo & IA32_FEATURE_CONTROL_LOCKED)) { //your BIOS/UEFI code maybe not strong. It's time to buy a new one. //if the bit is clear, VMXON will causes a exception. } if(featureInfo & IA32_FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX) { // } if(featureInfo & IA32_FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX) { // }
SMX 指 Safer Mode Extension, 所以IA32_FEATURE_CONTROL_VMXON_ENABLED_INSIDE_SMX 和 IA32_FEATURE_CONTROL_VMXON_ENABLED_OUTSIDE_SMX,就是判断 VMX 能否在SMX内和外 执行。