summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys-utils/lscpu.c32
1 files changed, 30 insertions, 2 deletions
diff --git a/sys-utils/lscpu.c b/sys-utils/lscpu.c
index 36e36c9ef..9af09e90c 100644
--- a/sys-utils/lscpu.c
+++ b/sys-utils/lscpu.c
@@ -73,6 +73,7 @@
/* /sys paths */
#define _PATH_SYS_SYSTEM "/sys/devices/system"
+#define _PATH_SYS_HYP_FEATURES "/sys/hypervisor/properties/features"
#define _PATH_SYS_CPU _PATH_SYS_SYSTEM "/cpu"
#define _PATH_SYS_NODE _PATH_SYS_SYSTEM "/node"
#define _PATH_PROC_XEN "/proc/xen"
@@ -86,6 +87,15 @@
#define _PATH_PROC_DEVICETREE "/proc/device-tree"
#define _PATH_DEV_MEM "/dev/mem"
+/* Xen Domain feature flag used for /sys/hypervisor/properties/features */
+#define XENFEAT_supervisor_mode_kernel 3
+#define XENFEAT_mmu_pt_update_preserve_ad 5
+#define XENFEAT_hvm_callback_vector 8
+
+#define XEN_FEATURES_PV_MASK (1U << XENFEAT_mmu_pt_update_preserve_ad)
+#define XEN_FEATURES_PVH_MASK ( (1U << XENFEAT_supervisor_mode_kernel) \
+ | (1U << XENFEAT_hvm_callback_vector) )
+
/* virtualization types */
enum {
VIRT_NONE = 0,
@@ -811,10 +821,28 @@ read_hypervisor(struct lscpu_desc *desc, struct lscpu_modifier *mod)
desc->hyper = HYPER_VMWARE;
}
- if (desc->hyper)
+ if (desc->hyper) {
desc->virtype = VIRT_FULL;
- else if (read_hypervisor_powerpc(desc) > 0) {}
+ if (desc->hyper == HYPER_XEN && path_exist(_PATH_SYS_HYP_FEATURES)) {
+ uint32_t features;
+
+ fd = path_fopen("r", 0, _PATH_SYS_HYP_FEATURES);
+ if (fd && fscanf(fd, "%x", &features) == 1) {
+ /* Xen PV domain */
+ if (features & XEN_FEATURES_PV_MASK)
+ desc->virtype = VIRT_PARA;
+ /* Xen PVH domain */
+ else if ((features & XEN_FEATURES_PVH_MASK)
+ == XEN_FEATURES_PVH_MASK)
+ desc->virtype = VIRT_PARA;
+ fclose(fd);
+ } else {
+ err(EXIT_FAILURE, _("failed to read from: %s"),
+ _PATH_SYS_HYP_FEATURES);
+ }
+ }
+ } else if (read_hypervisor_powerpc(desc) > 0) {}
/* Xen para-virt or dom0 */
else if (path_exist(_PATH_PROC_XEN)) {