How one detects x86 virtual machines

There are, of course, many ways to detect x86 processor virtual machines. It is a truism, often ignored by operating system developers and others, that x86 virtual machines don't set out to exactly duplicate real hardware. Indeed, the paper by Garfinkel et al.1 not only points out this truism but describes some of the many unofficial ways in which it is possible to detect that one is running in a virtual machine.

Unofficial detection mechanisms rely upon one of several factors:

There are plenty of unofficial x86 virtual machine detection mechanisms around, often passed on by word of mouth. Equally as often, these mechanisms are highly specific to one virtual machine, or even to one version of the virtualization software (and its concomitant bugs). There are, however, official detection mechanisms for many x86 virtual machines. It is best to use those.

Detecting OS/2 Virtual DOS Machines

The official detection method for detecting whether one's code is running in a Virtual DOS Machine (or a Virtual Machine Boot, for that matter) in OS/2 is to issue INT 0x2F with the AX register set to 0x4010. If the code is executing in a VDM, the AX register value after the interrupt will be zero. (The default action for an unrecognized INT 0x2F call is to leave AX unchanged, of course. But the proper test is to test for equality to zero, not to test for inequality to 0x4010.) As a bonus, the BX register, if AX is zero, contains an encoding of the version number of OS/2.

Detecting Windows 3.1 running on top of DOS

The official detection method for detecting whether one's code is running in a DOS Box in DOS-Windows 3.1 is to issue INT 0x2F with the AX register set to 0x160A. If the code is executing in a DOS Box, the AX register value after the interrupt will be zero. (The same applies here as discussed for the OS/2 VDM check.) As a bonus, the BX register, if AX is zero, contains an encoding of the version number of DOS-Windows, and the CX register indicates either Standard mode (with value 0x0002) or 386 Enhanced mode (with value 0x0003).

Detecting xen, VMWare, KVM, Microsoft Hypervisor, et al.

The official detection method for detecting whether one's code is running in a xen, VMWare, KVM, or Microsoft Hypervisor virtual machine is to use the CPUID instruction. In addition to supporting either the behaviour of an Intel2 or an AMD3 processor, such virtual machine softwares explicitly adhere to a common extension protocol to both.

According to Microsoft4, a flag bit in the ECX register (bit #31, "Hypervisor present"), after executing CPUID with the EAX register set to 0x000000001, will be set to 1 in a (Microsoft) virtual machine and set to 0 on real hardware. This is indeed the official Hypervisor detection mechanism. It's also the official detection mechanism for VMWare6.

But here Microsoft and VMWare are incorrectly relying upon an accident of hardware implementation. Both Intel's2 and AMD's3 CPUID specifications state that bit #31 of the ECX register is reserved. Intel's specification even explicitly states that one should not count on the value of the bit. That includes not counting on the fact of it being zero on real hardware. As such, Microsoft's "official" detection mechanism is bogus.

The proper official detection mechanism is to follow the bit #31 check by executing CPUID with the EAX register set to 0x400000005. The output EAX register should be a number between 0x40000001 and 0x400000FF (as all protocol-compliant virtual machines are required to implement at least functions 0x40000000 and 0x40000001).

Even this is slightly bogus, because the real hardware specifications don't explicitly guarantee that on real hardware EAX will be 0x40000000. Formally, function 0x40000000 is in the "standard function" range of the CPUID instruction but outside of the subset of that range returned by function 0x00000000 and hence the behaviour of which is, as AMD's specification puts it, "undefined and should not be relied upon". But at least it is more than just one bit for the real hardware to accidentally happen to yield the same values as virtual machines do.

There is most definitely no guarantee that CPUID function 0x40000000 will be a no-operation on real hardware. Indeed, on the contrary, it is far more likely that it will not be. A hardware designer can legitimately note that all software that adheres to its part of the protocol will always set zeroes in some bits of the EAX register; and so can, whilst still remaining conformant with the specification, arrange not to decode those bits. So it is legitimately possible for function 0x40000000 to decode to the same as function 0x00000000, which is not a no-operation. It's equally possible, with yet another hardware design choice, that function 0x40000000 will pull some meaningless bit patterns out of a ROM, that may well accidentally happen to satisfy the virtual machine presence check. The behaviour on real hardware of function 0x40000000 really is, simply, "undefined and should not be relied upon".

One of these days, perhaps, the processor hardware manufacturers and the virtualization software vendors will all start singing from the same songsheet about CPUID's "software functions" range.


  1. Tal Garfinkel, Keith Adams, Andrew Warfield, and Jason Franklin (2007-05). Compatibility is Not Transparency: VMM Detection Myths and Realities; Proceedings of the 11th Workshop on Hot Topics in Operating Systems (HotOS-XI), May 2007.

  2. Intel Corporation (2009-08). Application Note 485: Intel Processor Identification and the CPUID Instruction. 241618-036.

  3. Advanced Micro Devices (2008-04). Technical Document 25481: CPUID Specification (Revision 2.28).

  4. Microsoft Corporation (2009-10). Determining if Hypervisor is installed. Microsoft Developer Network: Windows Driver Kit.

  5. Microsoft Corporation (2009-10). Standard Hypervisor CPUID leaves Microsoft Developer Network: Windows Driver Kit.

  6. VMWare Incorporated (2011-03). Mechanisms to determine if software is running in VMWare virtual machine 1009458. VMWare KnowledgeBase


© Copyright 2009 Jonathan de Boyne Pollard. "Moral" rights asserted.
Permission is hereby granted to copy and to distribute this web page in its original, unmodified form as long as its last modification datestamp is preserved.