From: Damien Millescamps <damien.millesca...@6wind.com> The VMware TSC mapping uses a hook to RDPMC to read the physical TSC in the case of VMware ESXi.
Introduce new option --vmware-tsc-map, ignored if CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set. Default is CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y. if CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is set: rte_rdtsc() selects at runtime between Vmware mapping of TSC or native TSC else rte_rdtsc() always uses native rdtsc. When running DPDK on VMware guest, enable --vmware-tsc-map to read the physical TSC. Caution: ESXi should pass monitor_control.pseudo_perfctr = TRUE otherwise it results in general protection fault. Acked-by: Vincent Jardin <vincent.jardin at 6wind.com> Acked-by: Olivier Matz <olivier.matz at 6wind.com> Acked-by: Thomas Monjalon <thomas.monjalon at 6wind.com> Signed-off-by: Damien Millescamps <damien.millescamps at 6wind.com> Signed-off-by: Jean-Mickael Guerin <jean-mickael.guerin at 6wind.com> --- config/defconfig_i686-default-linuxapp-gcc | 5 ++++ config/defconfig_i686-default-linuxapp-icc | 5 ++++ config/defconfig_x86_64-default-linuxapp-gcc | 5 ++++ config/defconfig_x86_64-default-linuxapp-icc | 5 ++++ lib/librte_eal/common/include/rte_cycles.h | 19 ++++++++++++++++ lib/librte_eal/linuxapp/eal/eal.c | 23 ++++++++++++++++++++ .../linuxapp/eal/include/eal_internal_cfg.h | 1 + 7 files changed, 63 insertions(+), 0 deletions(-) diff --git a/config/defconfig_i686-default-linuxapp-gcc b/config/defconfig_i686-default-linuxapp-gcc index ed54434..e64bb86 100644 --- a/config/defconfig_i686-default-linuxapp-gcc +++ b/config/defconfig_i686-default-linuxapp-gcc @@ -121,6 +121,11 @@ CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n # +# Compile Environment Abstraction Layer to support VMware TSC map +# +CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/config/defconfig_i686-default-linuxapp-icc b/config/defconfig_i686-default-linuxapp-icc index cb0d017..3f15a53 100644 --- a/config/defconfig_i686-default-linuxapp-icc +++ b/config/defconfig_i686-default-linuxapp-icc @@ -121,6 +121,11 @@ CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n # +# Compile Environment Abstraction Layer to support VMware TSC map +# +CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/config/defconfig_x86_64-default-linuxapp-gcc b/config/defconfig_x86_64-default-linuxapp-gcc index 3555187..f5213d5 100644 --- a/config/defconfig_x86_64-default-linuxapp-gcc +++ b/config/defconfig_x86_64-default-linuxapp-gcc @@ -121,6 +121,11 @@ CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n # +# Compile Environment Abstraction Layer to support VMware TSC map +# +CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/config/defconfig_x86_64-default-linuxapp-icc b/config/defconfig_x86_64-default-linuxapp-icc index f527f53..f28943a 100644 --- a/config/defconfig_x86_64-default-linuxapp-icc +++ b/config/defconfig_x86_64-default-linuxapp-icc @@ -121,6 +121,11 @@ CONFIG_RTE_LIBRTE_EAL_LINUXAPP=y CONFIG_RTE_LIBRTE_EAL_BAREMETAL=n # +# Compile Environment Abstraction Layer to support VMware TSC map +# +CONFIG_RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT=y + +# # Compile generic ethernet library # CONFIG_RTE_LIBRTE_ETHER=y diff --git a/lib/librte_eal/common/include/rte_cycles.h b/lib/librte_eal/common/include/rte_cycles.h index a1eca6c..fa0b408 100644 --- a/lib/librte_eal/common/include/rte_cycles.h +++ b/lib/librte_eal/common/include/rte_cycles.h @@ -2,6 +2,7 @@ * BSD LICENSE * * Copyright(c) 2010-2012 Intel Corporation. All rights reserved. + * Copyright(c) 2012-2013 6WIND. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -48,6 +49,13 @@ extern "C" { #include <stdint.h> +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT +/** Global switch to use VMware mapping of TSC instead of RDTSC */ +extern int rte_cycles_vmware_tsc_map; +#include <rte_branch_prediction.h> +#endif + + /** * Read the TSC register. * @@ -65,9 +73,20 @@ rte_rdtsc(void) }; } tsc; +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT + if (unlikely(rte_cycles_vmware_tsc_map)) { + /* ecx = 0x10000 corresponds to the Physical TSC for VMware */ + asm volatile("rdpmc" : + "=a" (tsc.lo_32), + "=d" (tsc.hi_32) : + "c"(0x10000)); + return tsc.tsc_64; + } +#endif asm volatile("rdtsc" : "=a" (tsc.lo_32), "=d" (tsc.hi_32)); + return tsc.tsc_64; } diff --git a/lib/librte_eal/linuxapp/eal/eal.c b/lib/librte_eal/linuxapp/eal/eal.c index 8d82cc3..a63881c 100644 --- a/lib/librte_eal/linuxapp/eal/eal.c +++ b/lib/librte_eal/linuxapp/eal/eal.c @@ -78,6 +78,7 @@ #define OPT_PROC_TYPE "proc-type" #define OPT_NO_SHCONF "no-shconf" #define OPT_NO_HPET "no-hpet" +#define OPT_VMWARE_TSC_MAP "vmware-tsc-map" #define OPT_NO_PCI "no-pci" #define OPT_NO_HUGE "no-huge" #define OPT_FILE_PREFIX "file-prefix" @@ -125,6 +126,9 @@ struct lcore_config lcore_config[RTE_MAX_LCORE]; /* internal configuration */ struct internal_config internal_config; +/* used by rte_rdtsc() */ +int rte_cycles_vmware_tsc_map; + /* Return a pointer to the configuration structure */ struct rte_config * rte_eal_get_configuration(void) @@ -264,6 +268,7 @@ eal_usage(const char *prgname) " --"OPT_HUGE_DIR" : directory where hugetlbfs is mounted\n" " --"OPT_PROC_TYPE": type of this process\n" " --"OPT_FILE_PREFIX": prefix for hugepage filenames\n" + " --"OPT_VMWARE_TSC_MAP" : use VMware TSC map instead of native RDTSC\n\n" "\nEAL options for DEBUG use only:\n" " --"OPT_NO_HUGE" : use malloc instead of hugetlbfs\n" " --"OPT_NO_PCI" : disable pci\n" @@ -379,6 +384,7 @@ eal_parse_args(int argc, char **argv) {OPT_NO_HUGE, 0, 0, 0}, {OPT_NO_PCI, 0, 0, 0}, {OPT_NO_HPET, 0, 0, 0}, + {OPT_VMWARE_TSC_MAP, 0, 0, 0}, {OPT_HUGE_DIR, 1, 0, 0}, {OPT_NO_SHCONF, 0, 0, 0}, {OPT_PROC_TYPE, 1, 0, 0}, @@ -399,6 +405,8 @@ eal_parse_args(int argc, char **argv) internal_config.no_hpet = 1; #endif + internal_config.vmware_tsc_map = 0; + while ((opt = getopt_long(argc, argvopt, "b:c:m:n:r:v", lgopts, &option_index)) != EOF) { @@ -464,6 +472,9 @@ eal_parse_args(int argc, char **argv) else if (!strcmp(lgopts[option_index].name, OPT_NO_HPET)) { internal_config.no_hpet = 1; } + else if (!strcmp(lgopts[option_index].name, OPT_VMWARE_TSC_MAP)) { + internal_config.vmware_tsc_map = 1; + } else if (!strcmp(lgopts[option_index].name, OPT_NO_SHCONF)) { internal_config.no_shconf = 1; } @@ -547,6 +558,18 @@ rte_eal_init(int argc, char **argv) internal_config.memory = eal_get_hugepage_mem_size(); } + if (internal_config.vmware_tsc_map == 1) { +#ifdef RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT + rte_cycles_vmware_tsc_map = 1; + RTE_LOG (DEBUG, EAL, "Using VMware TSC map, " + "you must have monitor_control.pseudo_perfctr = TRUE\n"); +#else + RTE_LOG (WARNING, EAL, "Ignoring --vmware-tsc-map because " + "RTE_LIBRTE_EAL_VMWARE_TSC_MAP_SUPPORT is not set\n"); +#endif + } else { + RTE_LOG (DEBUG, EAL, "Using native RDTSC\n"); + } rte_srand(rte_rdtsc()); rte_config_init(); diff --git a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h index 70d5afb..470b746 100644 --- a/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h +++ b/lib/librte_eal/linuxapp/eal/include/eal_internal_cfg.h @@ -63,6 +63,7 @@ struct internal_config { volatile unsigned no_hugetlbfs; /* true to disable hugetlbfs */ volatile unsigned no_pci; /* true to disable PCI */ volatile unsigned no_hpet; /* true to disable HPET */ + volatile unsigned vmware_tsc_map; /* true to use VMware TSC mapping instead of native TSC */ volatile unsigned no_shconf; /* true if there is no shared config */ volatile enum rte_proc_type_t process_type; /* multi-process proc type */ const char *hugefile_prefix; /* the base filename of hugetlbfs files */ -- 1.7.2.5