]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
lscpu: detect OS/400 and pHyp hypervisors
authorRuediger Meier <ruediger.meier@ga-group.nl>
Tue, 20 May 2014 11:26:48 +0000 (11:26 +0000)
committerRuediger Meier <ruediger.meier@ga-group.nl>
Thu, 29 May 2014 11:16:32 +0000 (13:16 +0200)
This patch comes originally from openSUSE / SLE. Author was probably
Petr Uzel.
Internal SUSE references: fate310255, sr226509

In comparison to the original patch we have slightly corrected iSeries
and pSeries detection according to Alexander Graf's comments on
util-linux@vger.kernel.org. Maybe we would need to add some more code
to detect pSeries emulated by Qemu/KVM.

CC: Stanislav Brabec <sbrabec@suse.cz>
CC: Petr Uzel <petr.uzel@suse.cz>
CC: Alexander Graf <agraf@suse.de>
Signed-off-by: Ruediger Meier <ruediger.meier@ga-group.nl>
sys-utils/lscpu.c
sys-utils/lscpu.h

index 7203d0d7b7f3a3c6dc4021cff78d294f0d1c451b..11224b0bc90fb79a65b227029967ee720cb00a02 100644 (file)
@@ -19,6 +19,7 @@
  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
+#include <assert.h>
 #include <ctype.h>
 #include <dirent.h>
 #include <errno.h>
@@ -60,6 +61,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 */
@@ -89,6 +91,8 @@ const char *hv_vendors[] = {
        [HYPER_HITACHI] = "Hitachi",
        [HYPER_PARALLELS] = "Parallels",
        [HYPER_VBOX]    = "Oracle",
+       [HYPER_OS400]   = "OS/400",
+       [HYPER_PHYP]    = "pHyp",
 };
 
 const int hv_vendor_pci[] = {
@@ -577,6 +581,61 @@ read_hypervisor_cpuid(struct lscpu_desc *desc __attribute__((__unused__)))
 }
 #endif
 
+static int
+read_hypervisor_powerpc(struct lscpu_desc *desc)
+{
+       assert(!desc->hyper);
+
+       /* 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
+        *              Note that pSeries could also be emulated by qemu/KVM.
+        * 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_PARA;
+       } else if (path_exist(_PATH_PROC_DEVICETREE "/ibm,partition-name")
+                  && path_exist(_PATH_PROC_DEVICETREE "/hmc-managed?")
+                  && !path_exist(_PATH_PROC_DEVICETREE "/chosen/qemu,graphic-width")) {
+               FILE *fd;
+               desc->hyper = HYPER_PHYP;
+               desc->virtype = VIRT_PARA;
+               fd = path_fopen("r", 0, _PATH_PROC_DEVICETREE "/ibm,partition-name");
+               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 = path_fopen("r", 0, _PATH_PROC_DEVICETREE "/hypervisor/compatible");
+               if (fd) {
+                       char buf[256];
+                       size_t i, len;
+                       memset(buf, 0, sizeof(buf));
+                       len = fread(buf, 1, sizeof(buf) - 1, fd);
+                       fclose(fd);
+                       for (i = 0; i < len;) {
+                               if (!strcmp(&buf[i], "linux,kvm")) {
+                                       desc->hyper = HYPER_KVM;
+                                       desc->virtype = VIRT_FULL;
+                                       break;
+                               }
+                               i += strlen(&buf[i]);
+                               i++;
+                       }
+               }
+       }
+
+       return desc->hyper;
+}
+
 static void
 read_hypervisor(struct lscpu_desc *desc, struct lscpu_modifier *mod)
 {
@@ -591,6 +650,8 @@ read_hypervisor(struct lscpu_desc *desc, struct lscpu_modifier *mod)
        if (desc->hyper)
                desc->virtype = VIRT_FULL;
 
+       else if (read_hypervisor_powerpc(desc) > 0) {}
+
        /* Xen para-virt or dom0 */
        else if (path_exist(_PATH_PROC_XEN)) {
                int dom0 = 0;
index 5dc965001dac45898b15a4879b1c32d5dde26dd6..e340291941ce1343f76bfaa7c572c8e5f0b45a3b 100644 (file)
@@ -15,6 +15,8 @@ enum {
        HYPER_HITACHI,
        HYPER_PARALLELS,        /* OpenVZ/VIrtuozzo */
        HYPER_VBOX,
+       HYPER_OS400,
+       HYPER_PHYP,
 };
 
 extern int read_hypervisor_dmi(void);