diff --git a/src/common/cpu.h b/src/common/cpu.h index 449fbe0..0b4d701 100644 --- a/src/common/cpu.h +++ b/src/common/cpu.h @@ -36,6 +36,7 @@ enum { HV_VENDOR_VMWARE, HV_VENDOR_XEN, HV_VENDOR_PARALLELS, + HV_VENDOR_PHYP, HV_VENDOR_INVALID }; diff --git a/src/common/printer.c b/src/common/printer.c index 414dc66..0948333 100644 --- a/src/common/printer.c +++ b/src/common/printer.c @@ -681,6 +681,9 @@ bool print_cpufetch_ppc(struct cpuInfo* cpu, STYLE s, struct color** cs, struct setAttribute(art, ATTRIBUTE_NAME, cpu_name); } setAttribute(art, ATTRIBUTE_UARCH, uarch); + if(cpu->hv->present) { + setAttribute(art, ATTRIBUTE_HYPERVISOR, cpu->hv->hv_name); + } setAttribute(art, ATTRIBUTE_TECHNOLOGY, manufacturing_process); setAttribute(art, ATTRIBUTE_FREQUENCY, max_frequency); uint32_t socket_num = get_nsockets(cpu->topo); diff --git a/src/common/udev.c b/src/common/udev.c index d1c41ac..ce35e5a 100644 --- a/src/common/udev.c +++ b/src/common/udev.c @@ -374,3 +374,18 @@ int get_num_sockets_package_cpus(struct topology* topo) { return ret; } + +// Inspired in is_devtree_compatible from lscpu +bool is_devtree_compatible(char* str) { + int filelen; + char* buf; + if((buf = read_file("/proc/device-tree/compatible", &filelen)) == NULL) { + return false; + } + + char* tmp; + if((tmp = strstr(buf, str)) == NULL) { + return false; + } + return true; +} diff --git a/src/common/udev.h b/src/common/udev.h index d0a4739..b9e1491 100644 --- a/src/common/udev.h +++ b/src/common/udev.h @@ -40,5 +40,6 @@ long get_l3_cache_size(uint32_t core); int get_num_caches_by_level(struct cpuInfo* cpu, uint32_t level); int get_num_sockets_package_cpus(struct topology* topo); int get_ncores_from_cpuinfo(void); +bool is_devtree_compatible(char* str); #endif diff --git a/src/ppc/ppc.c b/src/ppc/ppc.c index c2a31d6..0b3b939 100644 --- a/src/ppc/ppc.c +++ b/src/ppc/ppc.c @@ -11,6 +11,17 @@ #include "../common/udev.h" #include "../common/global.h" +static char *hv_vendors_name[] = { + [HV_VENDOR_KVM] = "KVM", + [HV_VENDOR_QEMU] = "QEMU", + [HV_VENDOR_HYPERV] = "Microsoft Hyper-V", + [HV_VENDOR_VMWARE] = "VMware", + [HV_VENDOR_XEN] = "Xen", + [HV_VENDOR_PARALLELS] = "Parallels", + [HV_VENDOR_PHYP] = "pHyp", + [HV_VENDOR_INVALID] = STRING_UNKNOWN +}; + struct cache* get_cache_info(struct cpuInfo* cpu) { struct cache* cach = emalloc(sizeof(struct cache)); init_cache_struct(cach); @@ -164,6 +175,28 @@ int64_t get_peak_performance(struct cpuInfo* cpu, struct topology* topo, int64_t return flops; } +struct hypervisor* get_hp_info(void) { + struct hypervisor* hv = emalloc(sizeof(struct hypervisor)); + hv->present = false; + + // Weird heuristic found in lscpu: + // https://github.com/util-linux/util-linux/blob/master/sys-utils/lscpu-virt.c + if(access("/proc" _PATH_DT_IBM_PARTIT_NAME, F_OK) == 0 && + access("/proc" _PATH_DT_HMC_MANAGED, F_OK) == 0 && + access("/proc" _PATH_DT_QEMU_WIDTH, F_OK) != 0) { + hv->present = true; + hv->hv_vendor = HV_VENDOR_PHYP; + } + else if(is_devtree_compatible("qemu,pseries")) { + hv->present = true; + hv->hv_vendor = HV_VENDOR_QEMU; + } + + hv->hv_name = hv_vendors_name[hv->hv_vendor]; + + return hv; +} + struct cpuInfo* get_cpu_info(void) { struct cpuInfo* cpu = emalloc(sizeof(struct cpuInfo)); struct features* feat = emalloc(sizeof(struct features)); @@ -182,6 +215,7 @@ struct cpuInfo* get_cpu_info(void) { printWarn("Could not open '%s'", path); } cpu->pvr = mfpvr(); + cpu->hv = get_hp_info(); cpu->arch = get_cpu_uarch(cpu); cpu->freq = get_frequency_info(); cpu->topo = get_topology_info(cpu->cach); diff --git a/src/ppc/udev.h b/src/ppc/udev.h index 5452382..2d0f9cc 100644 --- a/src/ppc/udev.h +++ b/src/ppc/udev.h @@ -2,8 +2,11 @@ #define __UDEV_PPC__ #include "../common/udev.h" -#define _PATH_DT "/proc/device-tree/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/processor@1000" -#define _PATH_DT_PART "/part-number" +#define _PATH_DT "/proc/device-tree/vpd/root-node-vpd@a000/enclosure@1e00/backplane@800/processor@1000" +#define _PATH_DT_PART "/part-number" +#define _PATH_DT_IBM_PARTIT_NAME "/device-tree/ibm,partition-name" +#define _PATH_DT_HMC_MANAGED "/device-tree/hmc-managed?" +#define _PATH_DT_QEMU_WIDTH "/device-tree/chosen/qemu,graphic-width" bool fill_core_ids_from_sys(int *core_ids, int total_cores); bool fill_package_ids_from_sys(int* package_ids, int total_cores); diff --git a/src/x86/cpuid.c b/src/x86/cpuid.c index 7bce0b4..751c000 100644 --- a/src/x86/cpuid.c +++ b/src/x86/cpuid.c @@ -30,6 +30,7 @@ static const char *hv_vendors_string[] = { [HV_VENDOR_VMWARE] = "VMwareVMware", [HV_VENDOR_XEN] = "XenVMMXenVMM", [HV_VENDOR_PARALLELS] = "lrpepyh vr", + [HV_VENDOR_PHYP] = NULL }; static char *hv_vendors_name[] = { @@ -39,11 +40,10 @@ static char *hv_vendors_name[] = { [HV_VENDOR_VMWARE] = "VMware", [HV_VENDOR_XEN] = "Xen", [HV_VENDOR_PARALLELS] = "Parallels", + [HV_VENDOR_PHYP] = "pHyp", [HV_VENDOR_INVALID] = STRING_UNKNOWN }; -#define HYPERVISOR_NAME_MAX_LENGTH 17 - #define MASK 0xFF /* @@ -269,7 +269,7 @@ struct hypervisor* get_hp_info(bool hv_present) { uint8_t len = sizeof(hv_vendors_string) / sizeof(hv_vendors_string[0]); for(uint8_t v=0; v < len && !found; v++) { - if(strcmp(hv_vendors_string[v], name) == 0) { + if(hv_vendors_string[v] != NULL && strcmp(hv_vendors_string[v], name) == 0) { hv->hv_vendor = v; found = true; } @@ -277,7 +277,7 @@ struct hypervisor* get_hp_info(bool hv_present) { if(!found) { hv->hv_vendor = HV_VENDOR_INVALID; - printWarn("Unknown hypervisor vendor: %s", name); + printBug("Unknown hypervisor vendor: %s", name); } hv->hv_name = hv_vendors_name[hv->hv_vendor];