+/*
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Copyright (C) 2008 Cai Qian <qcai@redhat.com>
+ * Copyright (C) 2008-2023 Karel Zak <kzak@redhat.com>
+ */
#include <errno.h>
#include <stdlib.h>
#include <sys/types.h>
#include <string.h>
#include <stdio.h>
-#include "lscpu-api.h"
+#include "lscpu.h"
+
+#if (defined(__x86_64__) || defined(__i386__))
+# define INCLUDE_VMWARE_BDOOR
+#endif
+
+#ifdef INCLUDE_VMWARE_BDOOR
+# include <stdint.h>
+# include <signal.h>
+# include <strings.h>
+# include <setjmp.h>
+# ifdef HAVE_SYS_IO_H
+# include <sys/io.h>
+# endif
+#endif
/* Xen Domain feature flag used for /sys/hypervisor/properties/features */
#define XENFEAT_supervisor_mode_kernel 3
#define WORD(x) (uint16_t)(*(const uint16_t *)(x))
#define DWORD(x) (uint32_t)(*(const uint32_t *)(x))
-static void *get_mem_chunk(size_t base, size_t len, const char *devmem)
+void *get_mem_chunk(size_t base, size_t len, const char *devmem)
{
void *p = NULL;
int fd;
static int hypervisor_from_dmi_table(uint32_t base, uint16_t len,
uint16_t num, const char *devmem)
{
- uint8_t *buf;
uint8_t *data;
- int i = 0;
- char *vendor = NULL;
- char *product = NULL;
- char *manufacturer = NULL;
int rc = VIRT_VENDOR_NONE;
+ struct dmi_info di;
- data = buf = get_mem_chunk(base, len, devmem);
- if (!buf)
- goto done;
-
- /* 4 is the length of an SMBIOS structure header */
- while (i < num && data + 4 <= buf + len) {
- uint8_t *next;
- struct lscpu_dmi_header h;
-
- to_dmi_header(&h, data);
-
- /*
- * If a short entry is found (less than 4 bytes), not only it
- * is invalid, but we cannot reliably locate the next entry.
- * Better stop at this point.
- */
- if (h.length < 4)
- goto done;
+ data = get_mem_chunk(base, len, devmem);
+ if (!data)
+ return rc;
- /* look for the next handle */
- next = data + h.length;
- while (next - buf + 1 < len && (next[0] != 0 || next[1] != 0))
- next++;
- next += 2;
- switch (h.type) {
- case 0:
- vendor = dmi_string(&h, data[0x04]);
- break;
- case 1:
- manufacturer = dmi_string(&h, data[0x04]);
- product = dmi_string(&h, data[0x05]);
- break;
- default:
- break;
- }
+ memset(&di, 0, sizeof(struct dmi_info));
+ rc = parse_dmi_table(len, num, data, &di);
+ if (rc < 0)
+ goto done;
- data = next;
- i++;
- }
- if (manufacturer && !strcmp(manufacturer, "innotek GmbH"))
+ if (di.manufacturer && !strcmp(di.manufacturer, "innotek GmbH"))
rc = VIRT_VENDOR_INNOTEK;
- else if (manufacturer && strstr(manufacturer, "HITACHI") &&
- product && strstr(product, "LPAR"))
+ else if (di.manufacturer && strstr(di.manufacturer, "HITACHI") &&
+ di.product && strstr(di.product, "LPAR"))
rc = VIRT_VENDOR_HITACHI;
- else if (vendor && !strcmp(vendor, "Parallels"))
+ else if (di.vendor && !strcmp(di.vendor, "Parallels"))
rc = VIRT_VENDOR_PARALLELS;
done:
- free(buf);
+ free(data);
return rc;
}
continue;
*(addrp++) = '\0';
if (strcmp(linebuf, "SMBIOS") == 0) {
+ errno = 0;
*address = strtoul(addrp, NULL, 0);
+ if (errno)
+ continue;
ret = 0;
break;
}
}
#else /* ! (__x86_64__ || __i386__) */
-static void read_hypervisor_cpuid(void)
+static int read_hypervisor_cpuid(void)
{
+ return 0;
}
#endif
&& ul_path_access(cxt->procfs, F_OK, "device-tree/hmc-managed?") == 0
&& ul_path_access(cxt->procfs, F_OK, "device-tree/chosen/qemu,graphic-width") != 0) {
- FILE *fd;
+ char buf[256];
vendor = VIRT_VENDOR_PHYP;
*type = VIRT_TYPE_PARA;
- fd = ul_path_fopen(cxt->procfs, "r", "device-tree/ibm,partition-name");
- if (fd) {
- char buf[256];
- if (fscanf(fd, "%255s", buf) == 1 && !strcmp(buf, "full"))
- *type = VIRT_TYPE_NONE;
- fclose(fd);
- }
+ if (ul_path_scanf(cxt->procfs, "device-tree/ibm,partition-name", "%255s", buf) == 1 &&
+ !strcmp(buf, "full"))
+ *type = VIRT_TYPE_NONE;
/* Qemu */
} else if (is_devtree_compatible(cxt, "qemu,pseries")) {
if (virt->vendor == VIRT_VENDOR_XEN) {
uint32_t features;
- fd = ul_prefix_fopen(cxt->prefix, "r", _PATH_SYS_HYP_FEATURES);
-
- if (fd && fscanf(fd, "%x", &features) == 1) {
+ if (ul_path_scanf(cxt->rootfs, _PATH_SYS_HYP_FEATURES, "%x", &features) == 1) {
/* Xen PV domain */
if (features & XEN_FEATURES_PV_MASK)
virt->type = VIRT_TYPE_PARA;
== XEN_FEATURES_PVH_MASK)
virt->type = VIRT_TYPE_PARA;
}
- if (fd)
- fclose(fd);
}
} else if ((virt->vendor = read_hypervisor_powerpc(cxt, &virt->type))) {
;
/* Xen para-virt or dom0 */
} else if (ul_path_access(cxt->procfs, F_OK, "xen") == 0) {
+ char xenbuf[256];
int dom0 = 0;
- fd = ul_path_fopen(cxt->procfs, "r", "xen/capabilities");
- if (fd) {
- char buf[256];
-
- if (fscanf(fd, "%255s", buf) == 1 &&
- !strcmp(buf, "control_d"))
- dom0 = 1;
- fclose(fd);
- }
+ if (ul_path_scanf(cxt->procfs, "xen/capabilities", "%255s", xenbuf) == 1 &&
+ !strcmp(xenbuf, "control_d"))
+ dom0 = 1;
virt->type = dom0 ? VIRT_TYPE_NONE : VIRT_TYPE_PARA;
virt->vendor = VIRT_VENDOR_XEN;
virt->hypervisor,
virt->vendor,
virt->type));
+
+ if (!virt->cpuflag && !virt->hypervisor && !virt->vendor && !virt->type) {
+ lscpu_free_virtualization(virt);
+ virt = NULL;
+ }
return virt;
}