199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause 299a2dd95SBruce Richardson * Copyright 2020 Mellanox Technologies, Ltd 399a2dd95SBruce Richardson */ 499a2dd95SBruce Richardson 599a2dd95SBruce Richardson #include <inttypes.h> 699a2dd95SBruce Richardson 799a2dd95SBruce Richardson #include <rte_windows.h> 899a2dd95SBruce Richardson #include <rte_common.h> 999a2dd95SBruce Richardson #include <rte_cycles.h> 1099a2dd95SBruce Richardson #include <rte_eal.h> 1199a2dd95SBruce Richardson #include <rte_errno.h> 1299a2dd95SBruce Richardson #include "eal_private.h" 1399a2dd95SBruce Richardson 1499a2dd95SBruce Richardson #define US_PER_SEC 1E6 157268f21aSIsaac Boukris #define CYC_PER_100KHZ 1E5 1699a2dd95SBruce Richardson 1799a2dd95SBruce Richardson void 1899a2dd95SBruce Richardson rte_delay_us_sleep(unsigned int us) 1999a2dd95SBruce Richardson { 2099a2dd95SBruce Richardson HANDLE timer; 2199a2dd95SBruce Richardson LARGE_INTEGER due_time; 2299a2dd95SBruce Richardson 2399a2dd95SBruce Richardson /* create waitable timer */ 2499a2dd95SBruce Richardson timer = CreateWaitableTimer(NULL, TRUE, NULL); 2599a2dd95SBruce Richardson if (!timer) { 2699a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("CreateWaitableTimer()"); 2799a2dd95SBruce Richardson rte_errno = ENOMEM; 2899a2dd95SBruce Richardson return; 2999a2dd95SBruce Richardson } 3099a2dd95SBruce Richardson 3199a2dd95SBruce Richardson /* 3299a2dd95SBruce Richardson * due_time's uom is 100 ns, multiply by 10 to convert to microseconds 3399a2dd95SBruce Richardson * set us microseconds time for timer 3499a2dd95SBruce Richardson */ 3599a2dd95SBruce Richardson due_time.QuadPart = -((int64_t)us * 10); 3699a2dd95SBruce Richardson if (!SetWaitableTimer(timer, &due_time, 0, NULL, NULL, FALSE)) { 3799a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("SetWaitableTimer()"); 3899a2dd95SBruce Richardson rte_errno = EINVAL; 3999a2dd95SBruce Richardson goto end; 4099a2dd95SBruce Richardson } 4199a2dd95SBruce Richardson /* start wait for timer for us microseconds */ 4299a2dd95SBruce Richardson if (WaitForSingleObject(timer, INFINITE) == WAIT_FAILED) { 4399a2dd95SBruce Richardson RTE_LOG_WIN32_ERR("WaitForSingleObject()"); 4499a2dd95SBruce Richardson rte_errno = EINVAL; 4599a2dd95SBruce Richardson } 4699a2dd95SBruce Richardson 4799a2dd95SBruce Richardson end: 4899a2dd95SBruce Richardson CloseHandle(timer); 4999a2dd95SBruce Richardson } 5099a2dd95SBruce Richardson 5199a2dd95SBruce Richardson uint64_t 52*dbdf3d55SIsaac Boukris get_tsc_freq(uint64_t arch_hz) 5399a2dd95SBruce Richardson { 5499a2dd95SBruce Richardson LARGE_INTEGER t_start, t_end, elapsed_us; 5599a2dd95SBruce Richardson LARGE_INTEGER frequency; 5699a2dd95SBruce Richardson uint64_t tsc_hz; 5799a2dd95SBruce Richardson uint64_t end, start; 5899a2dd95SBruce Richardson 59*dbdf3d55SIsaac Boukris if (arch_hz) 60*dbdf3d55SIsaac Boukris return arch_hz; 61*dbdf3d55SIsaac Boukris 6299a2dd95SBruce Richardson QueryPerformanceFrequency(&frequency); 6399a2dd95SBruce Richardson 6499a2dd95SBruce Richardson QueryPerformanceCounter(&t_start); 6599a2dd95SBruce Richardson start = rte_get_tsc_cycles(); 6699a2dd95SBruce Richardson 6799a2dd95SBruce Richardson rte_delay_us_sleep(US_PER_SEC / 10); /* 1/10 second */ 6899a2dd95SBruce Richardson 6999a2dd95SBruce Richardson if (rte_errno != 0) 7099a2dd95SBruce Richardson return 0; 7199a2dd95SBruce Richardson 7299a2dd95SBruce Richardson QueryPerformanceCounter(&t_end); 7399a2dd95SBruce Richardson end = rte_get_tsc_cycles(); 7499a2dd95SBruce Richardson 7599a2dd95SBruce Richardson elapsed_us.QuadPart = t_end.QuadPart - t_start.QuadPart; 7699a2dd95SBruce Richardson 7799a2dd95SBruce Richardson /* 7899a2dd95SBruce Richardson * To guard against loss-of-precision, convert to microseconds 7999a2dd95SBruce Richardson * *before* dividing by ticks-per-second. 8099a2dd95SBruce Richardson */ 8199a2dd95SBruce Richardson elapsed_us.QuadPart *= US_PER_SEC; 8299a2dd95SBruce Richardson elapsed_us.QuadPart /= frequency.QuadPart; 8399a2dd95SBruce Richardson 8499a2dd95SBruce Richardson double secs = ((double)elapsed_us.QuadPart)/US_PER_SEC; 8599a2dd95SBruce Richardson tsc_hz = (uint64_t)((end - start)/secs); 8699a2dd95SBruce Richardson 877268f21aSIsaac Boukris /* Round up to 100Khz. 1E5 ~ 100Khz */ 887268f21aSIsaac Boukris return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_100KHZ); 8999a2dd95SBruce Richardson } 9099a2dd95SBruce Richardson 9199a2dd95SBruce Richardson 9299a2dd95SBruce Richardson int 9399a2dd95SBruce Richardson rte_eal_timer_init(void) 9499a2dd95SBruce Richardson { 9599a2dd95SBruce Richardson set_tsc_freq(); 9699a2dd95SBruce Richardson return 0; 9799a2dd95SBruce Richardson } 98