forked from pool/util-linux
668729991b
- remove unnecessarily added patches from SLE11: * util-linux-update-default-commit-interval.patch, openSUSE has never changed the default and neither will SLE12 * sfdisk-warn-about-2TB-limit.patch, fixed by upstream years ago * umount-avoid-readlink.patch, this patch only affects unused code and the used code does not have this bug - edit util-linux-lscpu-improve-hypervisor-detection.patch to not change the default behaviour of "lscpu -p" as documented in it's man page. Now this patch only affects the summary output. Also see discussion here http://lists.opensuse.org/opensuse-factory/2014-03/msg00256.html (forwarded request 228719 from rudi_m) OBS-URL: https://build.opensuse.org/request/show/229044 OBS-URL: https://build.opensuse.org/package/show/openSUSE:Factory/util-linux?expand=0&rev=183
207 lines
5.9 KiB
Diff
207 lines
5.9 KiB
Diff
Index: util-linux-2.24.1/sys-utils/lscpu.c
|
|
===================================================================
|
|
--- util-linux-2.24.1.orig/sys-utils/lscpu.c
|
|
+++ util-linux-2.24.1/sys-utils/lscpu.c
|
|
@@ -32,6 +32,15 @@
|
|
#include <stdarg.h>
|
|
#include <sys/types.h>
|
|
#include <sys/stat.h>
|
|
+#include <stdint.h>
|
|
+#include <signal.h>
|
|
+#include <strings.h>
|
|
+#include <setjmp.h>
|
|
+#if defined(__x86_64__) || defined(__i386__)
|
|
+#ifdef HAVE_sys_io_h
|
|
+#include <sys/io.h>
|
|
+#endif
|
|
+#endif
|
|
|
|
#include "cpuset.h"
|
|
#include "nls.h"
|
|
@@ -59,6 +68,7 @@
|
|
#define _PATH_PROC_STATUS "/proc/self/status"
|
|
#define _PATH_PROC_VZ "/proc/vz"
|
|
#define _PATH_PROC_BC "/proc/bc"
|
|
+#define _PATH_PROC_DEVICETREE "/proc/device-tree"
|
|
#define _PATH_DEV_MEM "/dev/mem"
|
|
|
|
/* virtualization types */
|
|
@@ -86,7 +96,28 @@ const char *hv_vendors[] = {
|
|
[HYPER_UML] = "User-mode Linux",
|
|
[HYPER_INNOTEK] = "Innotek GmbH",
|
|
[HYPER_HITACHI] = "Hitachi",
|
|
- [HYPER_PARALLELS] = "Parallels"
|
|
+ [HYPER_PARALLELS] = "Parallels",
|
|
+ [HYPER_VBOX] = "Oracle",
|
|
+ [HYPER_OS400] = "OS/400",
|
|
+ [HYPER_PHYP] = "pHyp"
|
|
+};
|
|
+
|
|
+const int hv_vendor_pci[] = {
|
|
+ [HYPER_NONE] = 0x0000,
|
|
+ [HYPER_XEN] = 0x5853,
|
|
+ [HYPER_KVM] = 0x0000,
|
|
+ [HYPER_MSHV] = 0x1414,
|
|
+ [HYPER_VMWARE] = 0x15ad,
|
|
+ [HYPER_VBOX] = 0x80ee
|
|
+};
|
|
+
|
|
+const int hv_graphics_pci[] = {
|
|
+ [HYPER_NONE] = 0x0000,
|
|
+ [HYPER_XEN] = 0x0001,
|
|
+ [HYPER_KVM] = 0x0000,
|
|
+ [HYPER_MSHV] = 0x5353,
|
|
+ [HYPER_VMWARE] = 0x0710,
|
|
+ [HYPER_VBOX] = 0xbeef
|
|
};
|
|
|
|
/* CPU modes */
|
|
@@ -550,10 +581,111 @@ read_hypervisor_cpuid(struct lscpu_desc
|
|
desc->hyper = HYPER_VMWARE;
|
|
}
|
|
|
|
+#define VMWARE_BDOOR_MAGIC 0x564D5868
|
|
+#define VMWARE_BDOOR_PORT 0x5658
|
|
+#define VMWARE_BDOOR_CMD_GETVERSION 10
|
|
+
|
|
+#define VMWARE_BDOOR(eax, ebx, ecx, edx) \
|
|
+ __asm__("inl (%%dx)" : \
|
|
+ "=a"(eax), "=c"(ecx), "=d"(edx), "=b"(ebx) : \
|
|
+ "0"(VMWARE_BDOOR_MAGIC), "1"(VMWARE_BDOOR_CMD_GETVERSION), \
|
|
+ "2"(VMWARE_BDOOR_PORT), "3"(0) : \
|
|
+ "memory");
|
|
+
|
|
+static jmp_buf segv_handler_env;
|
|
+
|
|
+static void
|
|
+segv_handler(int sig, siginfo_t *info, void *ignored)
|
|
+{
|
|
+ siglongjmp(segv_handler_env, 1);
|
|
+}
|
|
+
|
|
+static int
|
|
+is_vmware_platform(void)
|
|
+{
|
|
+ uint32_t eax, ebx, ecx, edx;
|
|
+ struct sigaction act, oact;
|
|
+
|
|
+ /*
|
|
+ * The assembly routine for vmware detection works
|
|
+ * fine under vmware, even if ran as regular user. But
|
|
+ * on real HW or under other hypervisors, it segfaults (which is
|
|
+ * expected). So we temporarily install SIGSEGV handler to catch
|
|
+ * the signal. All this magic is needed because lscpu
|
|
+ * isn't supposed to require root privileges.
|
|
+ */
|
|
+ if (sigsetjmp(segv_handler_env, 1))
|
|
+ return 0;
|
|
+
|
|
+ bzero(&act, sizeof(act));
|
|
+ act.sa_sigaction = segv_handler;
|
|
+ act.sa_flags = SA_SIGINFO;
|
|
+
|
|
+ if (sigaction(SIGSEGV, &act, &oact))
|
|
+ err(EXIT_FAILURE, _("error: can not set signal handler"));
|
|
+
|
|
+ VMWARE_BDOOR(eax, ebx, ecx, edx);
|
|
+
|
|
+ if (sigaction(SIGSEGV, &oact, NULL))
|
|
+ err(EXIT_FAILURE, _("error: can not restore signal handler"));
|
|
+
|
|
+ return eax != (uint32_t)-1 && ebx == VMWARE_BDOOR_MAGIC;
|
|
+}
|
|
+
|
|
#else /* ! __x86_64__ */
|
|
static void
|
|
read_hypervisor_cpuid(struct lscpu_desc *desc __attribute__((__unused__)))
|
|
{
|
|
+#ifdef __powerpc__
|
|
+ /* powerpc:
|
|
+ * IBM iSeries: legacy, if /proc/iSeries exists, its para-virtualized on top of OS/400
|
|
+ * IBM pSeries: always has a hypervisor
|
|
+ * if partition-name is "full", its kind of "bare-metal": full-system-partition
|
|
+ * otherwise its some partition created by Hardware Management Console
|
|
+ * in any case, its always some sort of HVM
|
|
+ * KVM: "linux,kvm" in /hypervisor/compatible indicates a KVM guest
|
|
+ * Xen: not in use, not detected
|
|
+ */
|
|
+ if (path_exist("/proc/iSeries")) {
|
|
+ desc->hyper = HYPER_OS400;
|
|
+ desc->virtype = VIRT_FULL;
|
|
+ } else if (path_exist(_PATH_PROC_DEVICETREE "/ibm,partition-name")) {
|
|
+ FILE *fd;
|
|
+ desc->hyper = HYPER_PHYP;
|
|
+ desc->virtype = VIRT_FULL;
|
|
+ fd = fopen(_PATH_PROC_DEVICETREE "/ibm,partition-name", "r");
|
|
+ if (fd) {
|
|
+ char buf[256];
|
|
+ if (fscanf(fd, "%s", buf) == 1 && !strcmp(buf, "full"))
|
|
+ desc->virtype = VIRT_NONE;
|
|
+ fclose(fd);
|
|
+ }
|
|
+ } else if (path_exist(_PATH_PROC_DEVICETREE "/hypervisor/compatible")) {
|
|
+ FILE *fd;
|
|
+ fd = fopen(_PATH_PROC_DEVICETREE "/hypervisor/compatible", "r");
|
|
+ if (fd) {
|
|
+ char buf[256];
|
|
+ int i;
|
|
+ memset(buf, 0, sizeof(buf));
|
|
+ fread(buf, sizeof(buf) - 1, 1, fd);
|
|
+ fclose(fd);
|
|
+ for (i = 0; i < sizeof(buf);) {
|
|
+ if (!strcmp(&buf[i], "linux,kvm")) {
|
|
+ desc->hyper = HYPER_KVM;
|
|
+ desc->virtype = VIRT_FULL;
|
|
+ break;
|
|
+ }
|
|
+ i += strlen(&buf[i]);
|
|
+ i++;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+#endif
|
|
+}
|
|
+
|
|
+static int is_vmware_platform(void)
|
|
+{
|
|
+ return 0;
|
|
}
|
|
#endif
|
|
|
|
@@ -588,9 +720,18 @@ read_hypervisor(struct lscpu_desc *desc,
|
|
desc->hyper = HYPER_XEN;
|
|
|
|
/* Xen full-virt on non-x86_64 */
|
|
- } else if (has_pci_device(0x5853, 0x0001)) {
|
|
+ } else if (has_pci_device( hv_vendor_pci[HYPER_XEN], hv_graphics_pci[HYPER_XEN])) {
|
|
desc->hyper = HYPER_XEN;
|
|
desc->virtype = VIRT_FULL;
|
|
+ } else if (is_vmware_platform()) {
|
|
+ desc->hyper = HYPER_VMWARE;
|
|
+ desc->virtype = VIRT_FULL;
|
|
+ } else if (has_pci_device( hv_vendor_pci[HYPER_VMWARE], hv_graphics_pci[HYPER_VMWARE])) {
|
|
+ desc->hyper = HYPER_VMWARE;
|
|
+ desc->virtype = VIRT_FULL;
|
|
+ } else if (has_pci_device( hv_vendor_pci[HYPER_VBOX], hv_graphics_pci[HYPER_VBOX])) {
|
|
+ desc->hyper = HYPER_VBOX;
|
|
+ desc->virtype = VIRT_FULL;
|
|
|
|
/* IBM PR/SM */
|
|
} else if (path_exist(_PATH_PROC_SYSINFO)) {
|
|
Index: util-linux-2.24.1/sys-utils/lscpu.h
|
|
===================================================================
|
|
--- util-linux-2.24.1.orig/sys-utils/lscpu.h
|
|
+++ util-linux-2.24.1/sys-utils/lscpu.h
|
|
@@ -13,7 +13,10 @@ enum {
|
|
HYPER_UML,
|
|
HYPER_INNOTEK, /* VBOX */
|
|
HYPER_HITACHI,
|
|
- HYPER_PARALLELS /* OpenVZ/VIrtuozzo */
|
|
+ HYPER_PARALLELS, /* OpenVZ/VIrtuozzo */
|
|
+ HYPER_VBOX,
|
|
+ HYPER_OS400,
|
|
+ HYPER_PHYP
|
|
};
|
|
|
|
extern int read_hypervisor_dmi(void);
|