1/*-
2 * Copyright (c) 2015 Martin Lucina.  All Rights Reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 *    notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 *    notice, this list of conditions and the following disclaimer in the
11 *    documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
14 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
17 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
19 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23 * SUCH DAMAGE.
24 */
25
26#include <hw/types.h>
27#include <hw/kernel.h>
28
29#include <arch/x86/hypervisor.h>
30
31int hypervisor_detect(void)
32{
33	uint32_t eax, ebx, ecx, edx;
34
35	/*
36	 * First check for generic "hypervisor present" bit.
37	 */
38	x86_cpuid(0x0, &eax, &ebx, &ecx, &edx);
39	if (eax >= 0x1) {
40		x86_cpuid(0x1, &eax, &ebx, &ecx, &edx);
41		if (!(ecx & (1 << 31)))
42			return 0;
43	}
44	else
45		return 0;
46
47	/*
48	 * CPUID leaf at 0x40000000 returns hypervisor vendor signature.
49	 * Source: https://lkml.org/lkml/2008/10/1/246
50	 */
51	x86_cpuid(0x40000000, &eax, &ebx, &ecx, &edx);
52	if (!(eax >= 0x40000000))
53		return 0;
54	/* Xen: "XenVMMXenVMM" */
55	if (ebx == 0x566e6558 && ecx == 0x65584d4d && edx == 0x4d4d566e)
56		return HYPERVISOR_XEN;
57	/* VMware: "VMwareVMware" */
58	else if (ebx == 0x61774d56 && ecx == 0x4d566572 && edx == 0x65726177)
59		return HYPERVISOR_VMWARE;
60	/* Hyper-V: "Microsoft Hv" */
61	else if (ebx == 0x7263694d && ecx == 0x666f736f && edx == 0x76482074)
62		return HYPERVISOR_HYPERV;
63	/* KVM: "KVMKVMKVM\0\0\0" */
64	else if (ebx == 0x4b4d564b && ecx == 0x564b4d56 && edx == 0x0000004d)
65		return HYPERVISOR_KVM;
66
67	return 0;
68}
69