The CPUID instruction is catched by hypervisor which can return a flag indicating one is running, and its name.
Suggested-by: Stephen Hemminger <sthem...@microsoft.com> Signed-off-by: Thomas Monjalon <tho...@monjalon.net> --- warning: to be tested --- lib/librte_eal/common/arch/arm/rte_cpuflags.c | 6 +++++ lib/librte_eal/common/arch/ppc_64/rte_cpuflags.c | 6 +++++ lib/librte_eal/common/arch/x86/rte_cpuflags.c | 30 ++++++++++++++++++++++ .../common/include/arch/x86/rte_cpuflags.h | 1 + .../common/include/generic/rte_cpuflags.h | 14 ++++++++++ lib/librte_eal/rte_eal_version.map | 9 ++++++- 6 files changed, 65 insertions(+), 1 deletion(-) diff --git a/lib/librte_eal/common/arch/arm/rte_cpuflags.c b/lib/librte_eal/common/arch/arm/rte_cpuflags.c index 88f1cbe37..f1f0cb51d 100644 --- a/lib/librte_eal/common/arch/arm/rte_cpuflags.c +++ b/lib/librte_eal/common/arch/arm/rte_cpuflags.c @@ -178,3 +178,9 @@ rte_cpu_get_flag_name(enum rte_cpu_flag_t feature) return NULL; return rte_cpu_feature_table[feature].name; } + +enum rte_hypervisor +rte_hypervisor_get_name(void) +{ + return RTE_HYPERVISOR_UNKNOWN; +} diff --git a/lib/librte_eal/common/arch/ppc_64/rte_cpuflags.c b/lib/librte_eal/common/arch/ppc_64/rte_cpuflags.c index 970a61c5e..b905cbd2c 100644 --- a/lib/librte_eal/common/arch/ppc_64/rte_cpuflags.c +++ b/lib/librte_eal/common/arch/ppc_64/rte_cpuflags.c @@ -146,3 +146,9 @@ rte_cpu_get_flag_name(enum rte_cpu_flag_t feature) return NULL; return rte_cpu_feature_table[feature].name; } + +enum rte_hypervisor +rte_hypervisor_get_name(void) +{ + return RTE_HYPERVISOR_UNKNOWN; +} diff --git a/lib/librte_eal/common/arch/x86/rte_cpuflags.c b/lib/librte_eal/common/arch/x86/rte_cpuflags.c index 7d4a0fefb..76893b8f1 100644 --- a/lib/librte_eal/common/arch/x86/rte_cpuflags.c +++ b/lib/librte_eal/common/arch/x86/rte_cpuflags.c @@ -34,6 +34,7 @@ #include "rte_cpuflags.h" #include <stdio.h> +#include <string.h> #include <errno.h> #include <stdint.h> #include <cpuid.h> @@ -92,6 +93,7 @@ const struct feature_entry rte_cpu_feature_table[] = { FEAT_DEF(AVX, 0x00000001, 0, RTE_REG_ECX, 28) FEAT_DEF(F16C, 0x00000001, 0, RTE_REG_ECX, 29) FEAT_DEF(RDRAND, 0x00000001, 0, RTE_REG_ECX, 30) + FEAT_DEF(HYPERVISOR, 0x00000001, 0, RTE_REG_ECX, 31) FEAT_DEF(FPU, 0x00000001, 0, RTE_REG_EDX, 0) FEAT_DEF(VME, 0x00000001, 0, RTE_REG_EDX, 1) @@ -194,3 +196,31 @@ rte_cpu_get_flag_name(enum rte_cpu_flag_t feature) return NULL; return rte_cpu_feature_table[feature].name; } + +/* See http://lwn.net/Articles/301888/ */ +#define HYPERVISOR_INFO_LEAF 0x40000000 + +enum rte_hypervisor +rte_hypervisor_get_name(void) +{ + cpuid_registers_t regs; + char name[13]; + + if (!rte_cpu_get_flag_enabled(RTE_CPUFLAG_HYPERVISOR)) + return RTE_HYPERVISOR_NONE; + + __cpuid(HYPERVISOR_INFO_LEAF, + regs[RTE_REG_EAX], regs[RTE_REG_EBX], + regs[RTE_REG_ECX], regs[RTE_REG_EDX]); + for (int reg = 1; reg < 4; reg++) + memcpy(name + (reg - 1) * 4, ®s[reg], 4); + name[12] = '\0'; + + if (strcmp("KVMKVMKVM", name) == 0) + return RTE_HYPERVISOR_KVM; + if (strcmp("Microsoft Hv", name) == 0) + return RTE_HYPERVISOR_HYPERV; + if (strcmp("VMwareVMware", name) == 0) + return RTE_HYPERVISOR_VMWARE; + return RTE_HYPERVISOR_UNKNOWN; +} diff --git a/lib/librte_eal/common/include/arch/x86/rte_cpuflags.h b/lib/librte_eal/common/include/arch/x86/rte_cpuflags.h index 26204fabb..686ac07f3 100644 --- a/lib/librte_eal/common/include/arch/x86/rte_cpuflags.h +++ b/lib/librte_eal/common/include/arch/x86/rte_cpuflags.h @@ -69,6 +69,7 @@ enum rte_cpu_flag_t { RTE_CPUFLAG_AVX, /**< AVX */ RTE_CPUFLAG_F16C, /**< F16C */ RTE_CPUFLAG_RDRAND, /**< RDRAND */ + RTE_CPUFLAG_HYPERVISOR, /**< Running on a hypervisor */ /* (EAX 01h) EDX features */ RTE_CPUFLAG_FPU, /**< FPU */ diff --git a/lib/librte_eal/common/include/generic/rte_cpuflags.h b/lib/librte_eal/common/include/generic/rte_cpuflags.h index c1c5551fc..3832fb851 100644 --- a/lib/librte_eal/common/include/generic/rte_cpuflags.h +++ b/lib/librte_eal/common/include/generic/rte_cpuflags.h @@ -93,4 +93,18 @@ rte_cpu_check_supported(void); int rte_cpu_is_supported(void); +enum rte_hypervisor { + RTE_HYPERVISOR_NONE, + RTE_HYPERVISOR_KVM, + RTE_HYPERVISOR_HYPERV, + RTE_HYPERVISOR_VMWARE, + RTE_HYPERVISOR_UNKNOWN +}; + +/** + * Get the type of hypervisor it is running on. + */ +enum rte_hypervisor +rte_hypervisor_get_name(void); + #endif /* _RTE_CPUFLAGS_H_ */ diff --git a/lib/librte_eal/rte_eal_version.map b/lib/librte_eal/rte_eal_version.map index f4f46c1be..3f8d81577 100644 --- a/lib/librte_eal/rte_eal_version.map +++ b/lib/librte_eal/rte_eal_version.map @@ -200,6 +200,13 @@ DPDK_17.11 { } DPDK_17.08; +DPDK_18.02 { + global: + + rte_hypervisor_get_name; + +} DPDK_17.11; + EXPERIMENTAL { global: @@ -235,4 +242,4 @@ EXPERIMENTAL { rte_service_set_stats_enable; rte_service_start_with_defaults; -} DPDK_17.11; +} DPDK_18.02; -- 2.15.0