Re: [PATCH] hypervisor: new tool for hypervisor detection

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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

[Index of Archives]     [Netdev]     [Ethernet Bridging]     [Linux Wireless]     [Kernel Newbies]     [Security]     [Linux for Hams]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux RAID]     [Linux Admin]     [Samba]

  Powered by Linux