Is this real? The Metaphysics of Hardware Virtualization

One of the philosophical principles of hardware virtualization is that the hardware should appear "real" to a virtualized operating system. One could generalize this to a principle of emulation - the emulated entity should not be "enlightened" to the reality of its environment. 

It is a useful assumption to be able to make when managing virtualized resources. If virtual hardware responds just like physical hardware, you can expect software running in a virtual machine to behave predictably, just as if it were running on a physical machine. As virtualization technology (both hardware and software) improves, and the performance overhead gets smaller the experiential difference between running virtualized and running natively should correspondingly reduce.

Should a process be able to determine whether or not it is running in a virtual machine? Taking the philosophical perspective, in a "pure" virtualization solution, epistemological solipsism should reign - a virtualized environment should be indistinguishable from a native environment.

That's all very well, but simple pragmatism can take precedence over idealism. For example, suppose a software product requires a low level device driver which is known not to run correctly in a virtualized environment. In this case it would be useful for the software to detect the virtualization state of its host operating system and issue a warning to the user. Or suppose a software vendor wishes to implement different licensing rules for a virtual machine than a physical one. Perhaps physical sockets should not be treated in the same way as virtual pocessors when charging for and enforcing licensing.

A documented method for a Windows process to determine whether or not it is running in a Hypervisor is to call CPUID. Place 1 in the input Register (EAX), and bit 31 of the ECX register becomes the hypervisor-present bit. Here is an example of checking the hypervisor status, calling the __cpuid intrinsic function in Visual Studio:

int CPUInfo[4] = {-1};
// call __cpuid to check if a Hypervisor is present
__cpuid(CPUInfo, 1);

// check bit 31 of ECX
if ((CPUInfo[2] >> 31) & 1)
{
    // Hypervisor is present
}

This level of Hypervisor awareness is demonstrated by SQL Server 2008 R2 for example, which records the presence of a Hypervisor in the log at startup, e.g.:

Developer Edition (64-bit) on Windows NT 6.1 <X64> (Build 7600: ) (Hypervisor)

But there is a potential problem. Suppose you installed Windows Server 2008 R2 with Hypervisor role and virtualization enabled in BIOS. You may not have created any guest virtual machines, but the above test would return true when you run it on the "host" OS, because it is running in a Hyper-V root partition. This might not be what you want if the reasons you require a process to be aware of its virtualization state are related to licensing or interaction with virtualized resources.

Is there a way a process can determine whether it is running on a Hyper-V root partition or running in a guest OS on child partition?

Yes. You can call CPUID again and check the Microsoft Hypervisor CPUID leaves. Firstly set an input parameter of 0x40000000 to check whether the hypervisor is Hyper-V. The EBX, ECX and EDX registers will contain the vendor identifier signature. In this case we are looking for "Microsoft Hv":

char HVProduct[13];

__cpuid(CPUInfo, 0x40000000);
memset(HVProduct, 0, sizeof(HVProduct));
memcpy(HVProduct, CPUInfo + 1, 12);

if (!strcmp(HVProduct, "Microsoft Hv"))
{
// Running in a Hyper-V partion
}

Next set an input parameter of 0x40000003 to query the features available to the partition. Bit 0 of the EBX register will then be set to 1 if running in a root partition, and 0 if running in a child partition.  Therefore if the vendor identifier signature is "Microsoft Hv" and the CreatePartitions bit it is set to zero, you can assume you are running in a Hyper-V guest OS.

Here is a code sample that puts these checks together. Note, since there's no error checking, this code is very unrecommended, and has only been tried on 64bit Windows 2008 R2 with Hyper-V:

 // IsVirt.cpp - Determine virtualization state of local machine
#include "StdAfx.h"
#include <stdio.h>
#include <intrin.h>

int main(int argc, char* argv[])
{
char HVProduct[13];
int CPUInfo[4] = {-1};

// call __cpuid to check if a Hypervisor is present
__cpuid(CPUInfo, 1);

// check bit 31 of ECX
if ((CPUInfo[2] >> 31) & 1)
{
// Hypervisor is present
// Check CPUID leaf 0x40000000 EBX, ECX, EDX for Hypvervisor prod name
__cpuid(CPUInfo, 0x40000000);
memset(HVProduct, 0, sizeof(HVProduct));
memcpy(HVProduct, CPUInfo + 1, 12);

if (!strcmp(HVProduct, "Microsoft Hv"))
{
// Check CPUID leaf 0x40000003 bit 1 (CreatePartitions bit)
__cpuid(CPUInfo, 0x40000003);
if (CPUInfo[1] & 1)
{
printf("\nRunning in a Hyper-V root partition\n");
}
else
{
printf("\nRunning inside a VM in a Hyper-V child partition\n");
}
}
else printf("\nRunning inside a VM on a hypervisor\n");
}
else printf("\nRunning on bare metal\n");
return 0;
}

SQL Server also records the "System Model" in the log at startup. This demonstrates another method to check the virtualization state of a process. On a Hyper-V guest OS, System Model is set to "Virtual Machine".

Hyper-V provides plenty of additional information to its guest operating systems. If you look at Hypervisor CPUID leaf 0x40000004 for example, it is defined as: Implementation recommendations that ... indicate the behaviors that the hypervisor recommends that the operating system implement for optimal performance. In other words, if a guest OS is looking in the right place it will find a set of recommendations from the hypervisor, such as how to handle address space switches, timing policy, handling spinlock failures etc.

Where is self-aware virtualization heading? It is reasonable to expect more software will be written to take advantage of knowledge of the virtualization state it is running in for performance purposes. For example, the variations in response rates and resource utilization in virtualized operating systems could result in changes to optimizer algorithms in performance intensive processes. It's possible this could result in challenges to virtual machine management software when it comes to guaranteeing fairness to the guest VM's if some applications are aware they are virtualized and some are not.

Further into the future I predict that bored computer science students will attempt to simulate René Descartes' brain running on their smartphones in order to ask him if he exists.