The older detection methods (smbios.bios.vendor and smbios.system.product)

are able to determine some virtual machines, but the vm_guest variable was
still only being set to VM_GUEST_VM.

Since we do know what some of them specifically are, we can set vm_guest
appropriately.

Also, if we see the CPUID has the HV flag, but we were unable to find a
definitive vendor in the Hypervisor CPUID Information Leaf, fall back to
the older detection methods, as they may be able to determine a specific
HV type.

Add VM_GUEST_PARALLELS value to VM_GUEST for Parallels.

Approved by:	cem
Differential Revision:	https://reviews.freebsd.org/D20305
This commit is contained in:
Stephen J. Kiernan 2019-05-21 13:29:53 +00:00
parent 7c7d049637
commit 1177d38ce1
3 changed files with 51 additions and 35 deletions

View File

@ -146,15 +146,16 @@ SYSCTL_PROC(_kern, OID_AUTO, vm_guest, CTLFLAG_RD | CTLTYPE_STRING,
* corresponding enum VM_GUEST members.
*/
static const char *const vm_guest_sysctl_names[] = {
"none",
"generic",
"xen",
"hv",
"vmware",
"kvm",
"bhyve",
"vbox",
NULL
[VM_GUEST_NO] = "none",
[VM_GUEST_VM] = "generic",
[VM_GUEST_XEN] = "xen",
[VM_GUEST_HV] = "hv",
[VM_GUEST_VMWARE] = "vmware",
[VM_GUEST_KVM] = "kvm",
[VM_GUEST_BHYVE] = "bhyve",
[VM_GUEST_VBOX] = "vbox",
[VM_GUEST_PARALLELS] = "parallels",
[VM_LAST] = NULL
};
CTASSERT(nitems(vm_guest_sysctl_names) - 1 == VM_LAST);

View File

@ -79,7 +79,7 @@ extern int vm_guest; /* Running as virtual machine guest? */
*/
enum VM_GUEST { VM_GUEST_NO = 0, VM_GUEST_VM, VM_GUEST_XEN, VM_GUEST_HV,
VM_GUEST_VMWARE, VM_GUEST_KVM, VM_GUEST_BHYVE, VM_GUEST_VBOX,
VM_LAST };
VM_GUEST_PARALLELS, VM_LAST };
/*
* These functions need to be declared before the KASSERT macro is invoked in

View File

@ -1305,23 +1305,27 @@ hook_tsc_freq(void *arg __unused)
SYSINIT(hook_tsc_freq, SI_SUB_CONFIGURE, SI_ORDER_ANY, hook_tsc_freq, NULL);
static const char *const vm_bnames[] = {
"QEMU", /* QEMU */
"Plex86", /* Plex86 */
"Bochs", /* Bochs */
"Xen", /* Xen */
"BHYVE", /* bhyve */
"Seabios", /* KVM */
NULL
static const struct {
const char * vm_bname;
int vm_guest;
} vm_bnames[] = {
{ "QEMU", VM_GUEST_VM }, /* QEMU */
{ "Plex86", VM_GUEST_VM }, /* Plex86 */
{ "Bochs", VM_GUEST_VM }, /* Bochs */
{ "Xen", VM_GUEST_XEN }, /* Xen */
{ "BHYVE", VM_GUEST_BHYVE }, /* bhyve */
{ "Seabios", VM_GUEST_KVM }, /* KVM */
};
static const char *const vm_pnames[] = {
"VMware Virtual Platform", /* VMWare VM */
"Virtual Machine", /* Microsoft VirtualPC */
"VirtualBox", /* Sun xVM VirtualBox */
"Parallels Virtual Platform", /* Parallels VM */
"KVM", /* KVM */
NULL
static const struct {
const char * vm_pname;
int vm_guest;
} vm_pnames[] = {
{ "VMware Virtual Platform", VM_GUEST_VMWARE },
{ "Virtual Machine", VM_GUEST_VM }, /* Microsoft VirtualPC */
{ "VirtualBox", VM_GUEST_VBOX },
{ "Parallels Virtual Platform", VM_GUEST_PARALLELS },
{ "KVM", VM_GUEST_KVM },
};
static struct {
@ -1413,7 +1417,10 @@ identify_hypervisor(void)
if (cpu_feature2 & CPUID2_HV) {
vm_guest = VM_GUEST_VM;
identify_hypervisor_cpuid_base();
return;
/* If we have a definitive vendor, we can return now. */
if (*hv_vendor != '\0')
return;
}
/*
@ -1438,19 +1445,27 @@ identify_hypervisor(void)
*/
p = kern_getenv("smbios.bios.vendor");
if (p != NULL) {
for (i = 0; vm_bnames[i] != NULL; i++)
if (strcmp(p, vm_bnames[i]) == 0) {
vm_guest = VM_GUEST_VM;
freeenv(p);
return;
for (i = 0; i < nitems(vm_bnames); i++)
if (strcmp(p, vm_bnames[i].vm_bname) == 0) {
vm_guest = vm_bnames[i].vm_guest;
/* If we have a specific match, return */
if (vm_guest != VM_GUEST_VM) {
freeenv(p);
return;
}
/*
* We are done with bnames, but there might be
* a more specific match in the pnames
*/
break;
}
freeenv(p);
}
p = kern_getenv("smbios.system.product");
if (p != NULL) {
for (i = 0; vm_pnames[i] != NULL; i++)
if (strcmp(p, vm_pnames[i]) == 0) {
vm_guest = VM_GUEST_VM;
for (i = 0; i < nitems(vm_pnames); i++)
if (strcmp(p, vm_pnames[i].vm_pname) == 0) {
vm_guest = vm_pnames[i].vm_guest;
freeenv(p);
return;
}
@ -2586,7 +2601,7 @@ static void
print_hypervisor_info(void)
{
if (*hv_vendor)
if (*hv_vendor != '\0')
printf("Hypervisor: Origin = \"%s\"\n", hv_vendor);
}