199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright(c) 2010-2014 Intel Corporation 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <stdio.h> 699a2dd95SBruce Richardson #include <inttypes.h> 799a2dd95SBruce Richardson 899a2dd95SBruce Richardson #include <rte_common.h> 999a2dd95SBruce Richardson #include <rte_log.h> 1099a2dd95SBruce Richardson #include <rte_cycles.h> 1199a2dd95SBruce Richardson #include <rte_pause.h> 1299a2dd95SBruce Richardson #include <rte_eal.h> 1399a2dd95SBruce Richardson 1499a2dd95SBruce Richardson #include "eal_private.h" 1599a2dd95SBruce Richardson #include "eal_memcfg.h" 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson /* The frequency of the RDTSC timer resolution */ 1899a2dd95SBruce Richardson static uint64_t eal_tsc_resolution_hz; 1999a2dd95SBruce Richardson 2099a2dd95SBruce Richardson /* Pointer to user delay function */ 2199a2dd95SBruce Richardson void (*rte_delay_us)(unsigned int) = NULL; 2299a2dd95SBruce Richardson 2399a2dd95SBruce Richardson void 2499a2dd95SBruce Richardson rte_delay_us_block(unsigned int us) 2599a2dd95SBruce Richardson { 2699a2dd95SBruce Richardson const uint64_t start = rte_get_timer_cycles(); 2799a2dd95SBruce Richardson const uint64_t ticks = (uint64_t)us * rte_get_timer_hz() / 1E6; 2899a2dd95SBruce Richardson while ((rte_get_timer_cycles() - start) < ticks) 2999a2dd95SBruce Richardson rte_pause(); 3099a2dd95SBruce Richardson } 3199a2dd95SBruce Richardson 3299a2dd95SBruce Richardson uint64_t 3399a2dd95SBruce Richardson rte_get_tsc_hz(void) 3499a2dd95SBruce Richardson { 3599a2dd95SBruce Richardson return eal_tsc_resolution_hz; 3699a2dd95SBruce Richardson } 3799a2dd95SBruce Richardson 3899a2dd95SBruce Richardson static uint64_t 3999a2dd95SBruce Richardson estimate_tsc_freq(void) 4099a2dd95SBruce Richardson { 4199a2dd95SBruce Richardson #define CYC_PER_10MHZ 1E7 42ae67895bSDavid Marchand EAL_LOG(WARNING, "WARNING: TSC frequency estimated roughly" 43ae67895bSDavid Marchand " - clock timings may be less accurate."); 4499a2dd95SBruce Richardson /* assume that the rte_delay_us_sleep() will sleep for 1 second */ 4599a2dd95SBruce Richardson uint64_t start = rte_rdtsc(); 4699a2dd95SBruce Richardson rte_delay_us_sleep(US_PER_S); 4799a2dd95SBruce Richardson /* Round up to 10Mhz. 1E7 ~ 10Mhz */ 4899a2dd95SBruce Richardson return RTE_ALIGN_MUL_NEAR(rte_rdtsc() - start, CYC_PER_10MHZ); 4999a2dd95SBruce Richardson } 5099a2dd95SBruce Richardson 5199a2dd95SBruce Richardson void 5299a2dd95SBruce Richardson set_tsc_freq(void) 5399a2dd95SBruce Richardson { 5499a2dd95SBruce Richardson struct rte_mem_config *mcfg = rte_eal_get_configuration()->mem_config; 5599a2dd95SBruce Richardson uint64_t freq; 5699a2dd95SBruce Richardson 5799a2dd95SBruce Richardson if (rte_eal_process_type() == RTE_PROC_SECONDARY) { 5899a2dd95SBruce Richardson /* 5999a2dd95SBruce Richardson * Just use the primary process calculated TSC rate in any 6099a2dd95SBruce Richardson * secondary process. It avoids any unnecessary overhead on 6199a2dd95SBruce Richardson * systems where arch-specific frequency detection is not 6299a2dd95SBruce Richardson * available. 6399a2dd95SBruce Richardson */ 6499a2dd95SBruce Richardson eal_tsc_resolution_hz = mcfg->tsc_hz; 6599a2dd95SBruce Richardson return; 6699a2dd95SBruce Richardson } 6799a2dd95SBruce Richardson 6899a2dd95SBruce Richardson freq = get_tsc_freq_arch(); 69*dbdf3d55SIsaac Boukris freq = get_tsc_freq(freq); 7099a2dd95SBruce Richardson if (!freq) 7199a2dd95SBruce Richardson freq = estimate_tsc_freq(); 7299a2dd95SBruce Richardson 73ae67895bSDavid Marchand EAL_LOG(DEBUG, "TSC frequency is ~%" PRIu64 " KHz", freq / 1000); 7499a2dd95SBruce Richardson eal_tsc_resolution_hz = freq; 7599a2dd95SBruce Richardson mcfg->tsc_hz = freq; 7699a2dd95SBruce Richardson } 7799a2dd95SBruce Richardson 7899a2dd95SBruce Richardson void rte_delay_us_callback_register(void (*userfunc)(unsigned int)) 7999a2dd95SBruce Richardson { 8099a2dd95SBruce Richardson rte_delay_us = userfunc; 8199a2dd95SBruce Richardson } 8299a2dd95SBruce Richardson 8399a2dd95SBruce Richardson RTE_INIT(rte_timer_init) 8499a2dd95SBruce Richardson { 8599a2dd95SBruce Richardson /* set rte_delay_us_block as a delay function */ 8699a2dd95SBruce Richardson rte_delay_us_callback_register(rte_delay_us_block); 8799a2dd95SBruce Richardson } 88