diff options
Diffstat (limited to 'src/kernel/tests/lib/tst_virt.c')
-rw-r--r-- | src/kernel/tests/lib/tst_virt.c | 132 |
1 files changed, 132 insertions, 0 deletions
diff --git a/src/kernel/tests/lib/tst_virt.c b/src/kernel/tests/lib/tst_virt.c new file mode 100644 index 0000000..53d33e6 --- /dev/null +++ b/src/kernel/tests/lib/tst_virt.c @@ -0,0 +1,132 @@ +/* + * Copyright (C) 2013 Linux Test Project + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of version 2 of the GNU General Public + * License as published by the Free Software Foundation. + * + * This program is distributed in the hope that it would be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * + * Further, this software is distributed without any warranty that it + * is free of the rightful claim of any third person regarding + * infringement or the like. Any license provided herein, whether + * implied or otherwise, applies only to this software file. Patent + * licenses, if any, provided herein do not apply to combinations of + * this program with other software, or any other product whatsoever. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA + * 02110-1301, USA. + */ + +#include <unistd.h> +#include "test.h" +#include "safe_macros.h" + +static int is_kvm(void) +{ + FILE *cpuinfo; + char line[64]; + int found; + + /* this doesn't work with custom -cpu values, since there's + * no easy, reasonable or reliable way to work around those */ + cpuinfo = SAFE_FOPEN(NULL, "/proc/cpuinfo", "r"); + found = 0; + while (fgets(line, sizeof(line), cpuinfo) != NULL) { + if (strstr(line, "QEMU Virtual CPU")) { + found = 1; + break; + } + } + + SAFE_FCLOSE(NULL, cpuinfo); + return found; +} + +static int is_xen(void) +{ + char hypervisor_type[4]; + + if (access("/proc/xen", F_OK) == 0) + return 1; + + if (access("/sys/hypervisor/type", F_OK) == 0) { + SAFE_FILE_SCANF(NULL, "/sys/hypervisor/type", "%3s", + hypervisor_type); + return strncmp("xen", hypervisor_type, + sizeof(hypervisor_type)) == 0; + } + + return 0; +} + +static int try_systemd_detect_virt(void) +{ + FILE *f; + char virt_type[64]; + int ret; + + /* See tst_cmd.c */ + void *old_handler = signal(SIGCHLD, SIG_DFL); + + f = popen("systemd-detect-virt", "r"); + if (!f) { + signal(SIGCHLD, old_handler); + return 0; + } + + if (!fgets(virt_type, sizeof(virt_type), f)) + virt_type[0] = '\0'; + + ret = pclose(f); + + signal(SIGCHLD, old_handler); + + /* + * systemd-detect-virt not found by shell or no virtualization detected + * (systemd-detect-virt returns non-zero) + */ + if (ret < 0 || (WIFEXITED(ret) && WEXITSTATUS(ret) == 127)) + return -1; + + if (ret) + return 0; + + if (!strncmp("kvm", virt_type, 3)) + return VIRT_KVM; + + if (!strncmp("xen", virt_type, 3)) + return VIRT_XEN; + + return VIRT_OTHER; +} + +int tst_is_virt(int virt_type) +{ + int ret = try_systemd_detect_virt(); + + if (ret >= 0) { + if (virt_type == VIRT_ANY) + return ret != 0; + else + return ret == virt_type; + } + + switch (virt_type) { + case VIRT_ANY: + return is_xen() || is_kvm(); + case VIRT_XEN: + return is_xen(); + case VIRT_KVM: + return is_kvm(); + case VIRT_OTHER: + return 0; + } + + tst_brkm(TBROK, NULL, "invalid virt_type flag: %d", virt_type); + return -1; +} |