forked from pool/util-linux
197 lines
5.0 KiB
Diff
197 lines
5.0 KiB
Diff
X-Gnus-Coding-System: -*- coding: utf-8; -*-
|
|
|
|
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@novell.com>.
|
|
>
|
|
> 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@redhat.com>
|
|
Date: Wed, 1 Oct 2008 01:29:32 +0200
|
|
Subject: [PATCH] lscpu: add Hypervisor vendor ID
|
|
|
|
Signed-off-by: Karel Zak <kzak@redhat.com>
|
|
---
|
|
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
|
|
|