Hi,
I'm working on dumping the features offered by the processor using CPUID and found something interesting with QEMU. CPUID function 0x01 returns with bit 31 set in ECX. The Intel Processor Identification and the CPUID Instruction guide (http://www.intel.com/content/www/us/en/ ... -note.html) [May, 2012] notes on page 30 that bit 31 is, "Not Used," and "Always returns 0." My Intel Instruction Set Reference [May, 2011] agrees. A more recent version (http://download.intel.com/products/proc ... 253666.pdf) [May, 2012] also agrees. Bochs does not return the same bit set.
My question is this: Is QEMU reporting some feature for which I have not yet found the documentation? Or is this bit used by QEMU to indicate that I am running in the QEMU emulator (and can I rely on that)?
Thanks for the help
CPUID Question
- eryjus
- Member
- Posts: 286
- Joined: Fri Oct 21, 2011 9:47 pm
- Libera.chat IRC: eryjus
- Location: Tustin, CA USA
CPUID Question
Adam
The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal
"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal
"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
Re: CPUID Question
Hi,
the CPUID.ECX[31] is set in purpose and it is not QEMU specific thing.
you can browse http://homepage.ntlworld.com/jonathan.d ... hines.html for more details.
quoting from there:
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.
the CPUID.ECX[31] is set in purpose and it is not QEMU specific thing.
you can browse http://homepage.ntlworld.com/jonathan.d ... hines.html for more details.
quoting from there:
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.
Re: CPUID Question
Because the CPUID definition is not a 100% guarantee, use extended fingerprinting:
- Google "virtualization detection blue pill"
- PCI Device IDs. For example, QEMU uses a very short list of PCI devices; you're not going to see that exact list on a real machine.
- Hard disk product / manufacturer string. For example, QEMU's hard disk identifiers start with 'Q'.
- DMI Strings
- eryjus
- Member
- Posts: 286
- Joined: Fri Oct 21, 2011 9:47 pm
- Libera.chat IRC: eryjus
- Location: Tustin, CA USA
Re: CPUID Question
Thank you!
Adam
The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal
"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber
The name is fitting: Century Hobby OS -- At this rate, it's gonna take me that long!
Read about my mistakes and missteps with this iteration: Journal
"Sometimes things just don't make sense until you figure them out." -- Phil Stahlheber