diff options
-rw-r--r-- | Makefile.am | 2 | ||||
-rw-r--r-- | src/hypervisor_vendor.c | 76 |
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; +} |