Hello,
I'm currently working on a personal project involving the use of CPUID and I've come across a rather interesting and confusion situation I'd like some clarity on.
Consider the following code:
unsigned int info[4];
__cpuidex(&info[0], 0x00000001, 0);
if ((info[2] >> 31) & 1)
{
printf("hypervisor detected\n");
}
On the host OS, I would expect this field to be 0 and both Intel and AMD documentation seem to agree with me that the field is 0 and reserved for indicating the OS is a guest. Considering I have an AMD 5600X I don't see how this could be otherwise. However, it seems that hyper-v (or some mechanism I don't understand) is somehow intercepting this CPUID call and setting that bit to 1. I've confirmed this with a friend who has a similar processor of a similar family (he has a 5700U) who mains linux. I've additionally tested this by turning SVM to off in by bios and that somehow sets the bit to 0 which would seem to make sense if hyper-v was involved because it can't function without it.
MSDN has this comment about it:
Before using any hypervisor interfaces, software should first determine whether it’s running within a virtualized environment. On x64 platforms that conform to this specification, this is done by executing the CPUID instruction with an input (EAX) value of 1. Upon execution, code should check bit 31 of register ECX (the “hypervisor present bit”). If this bit is set, a hypervisor is present. In a non-virtualized environment, the bit will be clear.
https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/tlfs/feature-discovery
This is strange wording to use if all the bit is supposed to do is tell you this is a guest operating system. So the theory we've come up with is that my host operating system is somehow executing code as a quasi-guest in a virtual environment and that hyper-v is setting that bit and what the docs mean when they say "a hypervisor is present" is that hyper-v is present on the host.
I don't have an explanation otherwise as to how this bit could change from what AMD says considering it's executing ASM on the host and the docs seem to illustrate the host OS operating on top of the hyervisor:
https://learn.microsoft.com/en-us/virtualization/hyper-v-on-windows/user-guide/nested-virtualization#how-nested-virtualization-works
I would appreciate clarity on the following:
- under what mechanism is the bit being set?
- if the bit is set, how do I determine via CPUID if I'm the host operating system?
If it helps I'm running Windows 11 21H2 build 22000.856
Thank you for your time.