The tool has been written by Ky Srinivasan <ksrinivasan@xxxxxxxxxx>. It detects the presence or absence of a hypervisor, currently Xen, KVM and HyperV. Signed-off-by: Matthias Koenig <mkoenig@xxxxxxx> --- sys-utils/Makefile.am | 5 + sys-utils/hypervisor.1 | 41 ++++++++++++ sys-utils/hypervisor.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 215 insertions(+), 0 deletions(-) diff --git a/configure.ac b/configure.ac index 770eb45..3714f00 100644 --- a/configure.ac +++ b/configure.ac @@ -466,6 +466,12 @@ AC_ARG_ENABLE([elvtune], ) AM_CONDITIONAL(BUILD_ELVTUNE, test "x$enable_elvtune" = xyes) +AC_ARG_ENABLE([hypervisor], + AS_HELP_STRING([--enable-hypervisor], [build hypervisor]), + [], enable_hypervisor=no +) +AM_CONDITIONAL(BUILD_HYPERVISOR, test "x$enable_hypervisor" = xyes) + AC_ARG_ENABLE([init], AS_HELP_STRING([--enable-init], [build simpleinit, shutdown, initctl]), diff --git a/sys-utils/Makefile.am b/sys-utils/Makefile.am index 0dbbb48..e3b7f2d 100644 --- a/sys-utils/Makefile.am +++ b/sys-utils/Makefile.am @@ -35,6 +35,11 @@ RDEV_LINKS += ramsize vidmode rootflags dist_man_MANS += rdev.8 endif +if BUILD_HYPERVISOR +bin_PROGRAMS += hypervisor +dist_man_MANS += hypervisor.1 +endif + SETARCH_LINKS = linux32 linux64 if ARCH_S390 diff --git a/sys-utils/hypervisor.1 b/sys-utils/hypervisor.1 new file mode 100644 index 0000000..807969b --- /dev/null +++ b/sys-utils/hypervisor.1 @@ -0,0 +1,41 @@ +.TH hypervisor 1 "September 2008" "" "User Commands" +.SH NAME +hypervisor \- detect presence of a hypervisor +.SH SYNOPSIS +.B hypervisor +[\fIOPTION\fR] +.SH DESCRIPTION +Detects the presence/absence of a hypervisor. +.SH OPTIONS +.TP +\fB\-h\fR, \fB\-\-help\fR +Show this message and exit. +.TP +\fB\-q\fR, \fB\-\-quiet\fR +Do not show output message. +.SH EXIT CODES +.TP +0 +No hypervisor detected. +.TP +1 +Xen detected. +.TP +2 +KVM detected. +.TP +3 +HyperV detected. +.TP +4 +HyperV emulating Xen detected. +.SH AUTHOR +Ky Srinivasan <ksrinivasan@xxxxxxxxxx> +.SH AVAILABILITY +The hypervisor command is part of the util-linux-ng package and is available from +ftp://ftp.kernel.org/pub/linux/utils/util-linux-ng/. +.SH COPYRIGHT +This is free software. You may redistribute copies of it under the terms +of the GNU General Public License <http://www.gnu.org/licenses/gpl.html>. +There is NO WARRANTY, to the extent permitted by law. + diff --git a/sys-utils/hypervisor.c b/sys-utils/hypervisor.c new file mode 100644 index 0000000..4afd962 --- /dev/null +++ b/sys-utils/hypervisor.c @@ -0,0 +1,169 @@ +/* Detect the presence of a hypervisor + * Copyright (C) 2008 Novell, Inc. + * Author: Ky Srinivasan <ksrinivasan@xxxxxxxxxx> + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public + * License along with this program; if not, write to the Free + * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, + * Boston, MA 02110-1301, USA. + * + */ + +#include <string.h> +#include <stdlib.h> +#include <stdio.h> +#include <unistd.h> +#include <getopt.h> + +static int opt_quiet = 0; + +struct option options[] = { + { "help", no_argument, NULL, 'h' }, + { "quiet", no_argument, NULL, 'q' }, + { NULL, 9, NULL, 0 } +}; + +enum { + HYPER_NONE = 0, + HYPER_XEN, + HYPER_KVM, + HYPER_MSHV, + HYPER_MSHV_XENPV +}; + +static inline void cpuid(unsigned int op, + unsigned int *eax, unsigned int *ebx, + unsigned int *ecx, unsigned int *edx) +{ + __asm__("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op), "c"(0)); +} + +static int hypervisor(void) +{ + unsigned int eax, ebx, ecx, edx; + char signature[13]; + int xen_pv =0; + + /* + * First check if we are running in a para-virtualized guest. + */ + if ((!access("/sys/hypervisor", F_OK) || + (!access("/proc/xen", F_OK)))) { + /* + * For now we are only dealing with para-virtualized + * Linux guests (para-virtualized on Xen). So, this must be + * Xen based. + */ + xen_pv = 1; + } + cpuid(0x40000000, &eax, &ebx, &ecx, &edx); + *(unsigned int*)(signature + 0) = ebx; + *(unsigned int*)(signature + 4) = ecx; + *(unsigned int*)(signature + 8) = edx; + signature[12] = 0; + + if ((!strncmp("XenVMMXenVMM", signature, 12) || (xen_pv))) + return HYPER_XEN; + if (!strncmp("KVMKVMKVM", signature, 9)) + return HYPER_KVM; + if (!strncmp("Microsoft Hv", signature, 12)) { + if (xen_pv) + return HYPER_MSHV_XENPV; + else + return HYPER_MSHV; + } + + return 0; +} + +static void help(void) +{ + printf("Usage: hypervisor [OPTION]\n"); + printf("Detects the presence/absence of a hypervisor.\n\n"); + printf("Options:\n"); + printf(" -h, --help\tShow this message and exit.\n"); + printf(" -q, --quiet\tDo not show output message.\n\n"); + printf("Exit status:\n"); + printf(" 0\tNo hypervisor detected.\n"); + printf(" 1\tXen detected.\n"); + printf(" 2\tKVM detected.\n"); + printf(" 3\tHyperV detected.\n"); + printf(" 4\tHyperV emulating Xen detected.\n"); +} + + +/* + * Program to determine if we are being hosted on the hypervisor. + * If the exit status is 0; we are running on bare hardware. The details of + * non-zero return values are as follows: + * + * 0: No hypervisor (running on bare hardware) + * 1: Xen is the hypervisor + * 2: KVM is the hypervisor + * 3: Veridian + * 4: Veridian hypervisor emulating Xen. + * TODO: VmWare Detection. + */ +int main(int argc, char **argv) +{ + int option_index, c; + int ret; + + while (1) { + c = getopt_long(argc, argv, "hq", options, &option_index); + if (c == -1) + break; + + switch (c) { + case 'h': + help(); + exit(EXIT_SUCCESS); + case 'q': + opt_quiet = 1; + break; + default: + break; + } + } + + ret = hypervisor(); + + if (!opt_quiet) { + switch (ret) { + case HYPER_NONE: + printf("No"); + break; + case HYPER_XEN: + printf("Xen"); + break; + case HYPER_KVM: + printf("KVM"); + break; + case HYPER_MSHV: + case HYPER_MSHV_XENPV: + printf("Microsoft"); + break; + default: + break; + } + printf(" Hypervisor found\n"); + } + + return ret; +} + -- To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html