On Mon, Sep 29, 2008 at 11:01:05PM +0200, Karel Zak wrote: > On Mon, Sep 29, 2008 at 03:17:28PM +0200, Matthias Koenig wrote: > > The tool has been written by Ky Srinivasan <ksrinivasan@xxxxxxxxxx>. > > Do we really need a new tool? IMHO the hypervisor Vendor ID should > be exported by kernel in /sys or /proc -- or we can add this info to > lscpu(1) or so. The (untested) patch below introduces a new fields "Hypervisor vendor ID:" and "Para-Virtualized:" in lscpu(1). The "Hypervisor vendor ID:" field reports the raw ID, it means it works for all hypervisors (the same logic like CPU "Vendor ID:"). I think this solution is a good compromise to avoid a new tool. (Note that lscpu(1) does not support XEN dom0 now. This problem will be resolved ASAP.) Comments? Karel >From 5a8e8f8b28eb6ea4bdce27ed6629dfb4fb1665b5 Mon Sep 17 00:00:00 2001 From: Karel Zak <kzak@xxxxxxxxxx> Date: Wed, 1 Oct 2008 01:29:32 +0200 Subject: [PATCH] lscpu: add Hypervisor vendor ID Signed-off-by: Karel Zak <kzak@xxxxxxxxxx> --- sys-utils/lscpu.c | 106 ++++++++++++++++++++++++++++++++++++++++++++++++++-- 1 files changed, 101 insertions(+), 5 deletions(-) diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c index d6bb8b9..5f39ced 100644 --- a/sys-utils/lscpu.c +++ b/sys-utils/lscpu.c @@ -38,7 +38,8 @@ /* /sys paths */ #define _PATH_SYS_SYSTEM "sys/devices/system" #define _PATH_SYS_CPU0 _PATH_SYS_SYSTEM "/cpu/cpu0" -#define _PATH_PROC_XENCAP "proc/xen/capabilities" +#define _PATH_PROC_XEN "proc/xen" +#define _PATH_PROC_XENCAP _PATH_PROC_XEN "/capabilities" #define _PATH_PROC_CPUINFO "proc/cpuinfo" int have_topology; @@ -67,6 +68,9 @@ struct cpu_desc { char *vendor; char *family; char *model; + char *virtflag; /* virtualization flag (vmx, svm) */ + char *hvid; /* hypervisor vendor ID */ + int is_para; /* is paravirtualized ? */ /* caches */ struct ca_desc cache[CACHE_MAX]; @@ -246,9 +250,94 @@ read_basicinfo(struct cpu_desc *cpu) else continue; } + + if (cpu->flags) { + snprintf(buf, sizeof(buf), " %s ", cpu->flags); + if (strstr(buf, " svm ")) + cpu->virtflag = strdup("svm"); + else if (strstr(buf, " vmx ")) + cpu->virtflag = strdup("vmx"); + } + fclose(fp); } +#if defined(__x86_64__) || defined(__i386__) + +/* + * 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__("cpuid" + : "=a" (*eax), + "=b" (*ebx), + "=c" (*ecx), + "=d" (*edx) + : "0" (op), "c"(0)); +} + +static void +read_hypervisor_cpuid(struct cpu_desc *cpu) +{ + unsigned int eax, ebx, ecx, edx; + 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]) + cpu->hvid = strdup(hyper_vendor_id); +} + +#else /* ! __x86_64__ */ +static void +read_hypervisor_cpuid(struct cpu_desc *cpu) +{ +} +#endif + +static void +read_hypervisor(struct cpu_desc *cpu) +{ + read_hypervisor_cpuid(cpu); + + if (!cpu->hvid) { + /* fallback for non-x86 archs */ + + if (!access(_PATH_PROC_XEN, F_OK)) + /* XEN dom0 or domU */ + cpu->hvid = strdup("Xen"); + } + + if (!cpu->virtflag && cpu->hvid && !strncmp(cpu->hvid, "Xen", 3)) { + + FILE *fd = fopen(_PATH_PROC_XENCAP, "r"); + int dom0 = 0; + + if (fd) { + char buf[256]; + + if (fscanf(fd, "%s", buf) == 1 && + !strcmp(buf, "control_d")) + dom0 = 1; + fclose(fd); + } + cpu->is_para = !dom0; + } +} + static void read_topology(struct cpu_desc *cpu) { @@ -344,6 +433,7 @@ check_system(void) fd = fopen(_PATH_PROC_XENCAP, "r"); if (fd) { if (fscanf(fd, "%s", buf) == 1 && !strcmp(buf, "control_d")) + /* !!!!!!!! TODO */ errx(EXIT_FAILURE, _("error: Dom0 Kernel is unsupported.")); fclose(fd); @@ -455,13 +545,17 @@ print_readable(struct cpu_desc *cpu) print_s(_("Stepping:"), cpu->stepping); if (cpu->mhz) print_s(_("CPU MHz:"), cpu->mhz); - if (cpu->flags) { - snprintf(buf, sizeof(buf), " %s ", cpu->flags); - if (strstr(buf, " svm ")) + if (cpu->virtflag) { + if (!strcmp(cpu->virtflag, "svm")) print_s(_("Virtualization:"), "AMD-V"); - else if (strstr(buf, " vmx ")) + else if (!strcmp(cpu->virtflag, "vmx")) print_s(_("Virtualization:"), "VT-x"); } + if (cpu->hvid) { + print_s(_("Hypervisor vendor ID:"), cpu->hvid); + print_s(_("Para-Virtualized:"), + cpu->is_para ? _("Yes") : _("Not")); + } if (have_cache) { int i; @@ -545,6 +639,8 @@ int main(int argc, char *argv[]) if (have_node) read_nodes(cpu); + read_hypervisor(cpu); + /* Show time! */ if (parsable) print_parsable(cpu); -- 1.5.5.1 -- 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