summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Makefile.am2
-rw-r--r--src/hypervisor_vendor.c76
2 files changed, 78 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am
index 23bdc3a1..3a05c0a5 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -76,9 +76,11 @@ sbin_SCRIPTS += scripts/vyatta-update-grub.pl
sbin_PROGRAMS = src/valid_address
sbin_PROGRAMS += src/local_ip
+sbin_PROGRAMS += src/hypervisor_vendor
src_valid_address = src/valid_address.c
src_local_ip = src/local_ip.c
+src_hypervisor_vendor = src/hypervisor_vendor.c
share_perl5_DATA = lib/Vyatta/Login/User.pm
share_perl5_DATA += lib/Vyatta/Login/RadiusServer.pm
diff --git a/src/hypervisor_vendor.c b/src/hypervisor_vendor.c
new file mode 100644
index 00000000..03ce1663
--- /dev/null
+++ b/src/hypervisor_vendor.c
@@ -0,0 +1,76 @@
+/*
+ * Identify hypervisor vendor
+ *
+ * based on code from util-linux lscpu
+ */
+
+#include <stdio.h>
+#include <string.h>
+
+/*
+ * This CPUID leaf returns the information about the hypervisor.
+ * EAX : maximum input value for CPUID supported by the hypervisor.
+ * EBX, ECX, EDX : Hypervisor vendor ID signature. E.g. VMwareVMware.
+ */
+#define HYPERVISOR_INFO_LEAF 0x40000000
+
+static inline void
+cpuid(unsigned int op, unsigned int *eax, unsigned int *ebx,
+ unsigned int *ecx, unsigned int *edx)
+{
+ __asm__(
+#if defined(__PIC__) && defined(__i386__)
+ /* x86 PIC cannot clobber ebx -- gcc bitches */
+ "pushl %%ebx;"
+ "cpuid;"
+ "movl %%ebx, %%esi;"
+ "popl %%ebx;"
+ : "=S" (*ebx),
+#else
+ "cpuid;"
+ : "=b" (*ebx),
+#endif
+ "=a" (*eax),
+ "=c" (*ecx),
+ "=d" (*edx)
+ : "1" (op), "c"(0));
+}
+
+static const char *get_hypervisor(void)
+{
+ unsigned int eax = 0, ebx = 0, ecx = 0, edx = 0;
+ char hyper_vendor_id[13];
+
+ memset(hyper_vendor_id, 0, sizeof(hyper_vendor_id));
+
+ cpuid(HYPERVISOR_INFO_LEAF, &eax, &ebx, &ecx, &edx);
+ memcpy(hyper_vendor_id + 0, &ebx, 4);
+ memcpy(hyper_vendor_id + 4, &ecx, 4);
+ memcpy(hyper_vendor_id + 8, &edx, 4);
+ hyper_vendor_id[12] = '\0';
+
+ if (!hyper_vendor_id[0])
+ return NULL;
+
+ else if (!strncmp("XenVMMXenVMM", hyper_vendor_id, 12))
+ return "Xen";
+ else if (!strncmp("KVMKVMKVM", hyper_vendor_id, 9))
+ return "KVM";
+ else if (!strncmp("Microsoft Hv", hyper_vendor_id, 12))
+ return "Microsoft HyperV";
+ else if (!strncmp("VMwareVMware", hyper_vendor_id, 12))
+ return "VMware";
+ else
+ return "Unknown";
+}
+
+int main(int argc, char **argv)
+{
+ const char *vm = get_hypervisor();
+
+ if (vm) {
+ printf("%s\n", vm);
+ return 0;
+ } else
+ return 1;
+}