From mboxrd@z Thu Jan  1 00:00:00 1970
Return-Path: <dev-bounces@dpdk.org>
Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124])
	by inbox.dpdk.org (Postfix) with ESMTP id 9BB5245AA0;
	Thu,  3 Oct 2024 14:30:37 +0200 (CEST)
Received: from mails.dpdk.org (localhost [127.0.0.1])
	by mails.dpdk.org (Postfix) with ESMTP id 32DF140612;
	Thu,  3 Oct 2024 14:30:33 +0200 (CEST)
Received: from mail-ed1-f51.google.com (mail-ed1-f51.google.com
 [209.85.208.51]) by mails.dpdk.org (Postfix) with ESMTP id 290EC40616
 for <dev@dpdk.org>; Thu,  3 Oct 2024 14:30:31 +0200 (CEST)
Received: by mail-ed1-f51.google.com with SMTP id
 4fb4d7f45d1cf-5c87ab540b3so3681598a12.1
 for <dev@dpdk.org>; Thu, 03 Oct 2024 05:30:31 -0700 (PDT)
DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=gmail.com; s=20230601; t=1727958630; x=1728563430; darn=dpdk.org;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:cc:to:from:from:to:cc:subject:date
 :message-id:reply-to;
 bh=CToo1Ls63Lu3FlLdm0VtRKavpnL8GNimO12wAbFtEyE=;
 b=Gm856xTaQqpC6JG86nZijerE9UlaK8endPt3YN9yUd4KfDQ5pz/yiCsiVA5Ho/xk1S
 l0ESpzUQ/2sprRE3LQLBWYCLPFt6svPlOEyfMuu8RRX15UuLsgyLzuNldqz5I8LtozsD
 e0m6wDlPgpp/ZpCDWkuV5l+kzTAC7YC33wdW1EZQWcU3Y4UcGejWyuvDlCQmwOM1UsE6
 KqSOyHMahUmLsNGsJ0H7GRHzVi1qIlhfkxDIakN67qN3s3NvjCldiKxmV6WZNUHE0B1R
 q4Rexyk939Cj7ULW/iJTfd3FGzFZPEVrX3BtTWOT54n5cYHC3dVdiBol+uqAn0bxLmok
 X0ZQ==
X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed;
 d=1e100.net; s=20230601; t=1727958630; x=1728563430;
 h=content-transfer-encoding:mime-version:references:in-reply-to
 :message-id:date:subject:cc:to:from:x-gm-message-state:from:to:cc
 :subject:date:message-id:reply-to;
 bh=CToo1Ls63Lu3FlLdm0VtRKavpnL8GNimO12wAbFtEyE=;
 b=T8U4B3pznsi9Ag3YhxLE0t9/hAeCkAesXmfQ+kDJS+NiUHrIvYvv0u8CfR0BwfTHnu
 pyx5FQ1Zrofg1jIA8AS9JISX3m52Z2yaxyIaHxu/u5r0BK0xpUbaygtVnF/SmEEgwwUo
 uQQOnxjb6q4Jvzoklla5GpFDkhylQEdLIGhyyo3DYarzYyUY+Kz8989sCB1CUwb09UbG
 up9YLzKiQtiRErcn4IrKL6KEZ4gBjTjMZnHSibgWJw4t6HvanjhPV/zUT7GFmXPNUVdY
 PAo3VL+iDSu9T+aJuU7R0/x6swmIIhN4YjQlxrFVsy8FV8eM1Ic+1FYW9HP4uOmAXoAQ
 5m4Q==
X-Gm-Message-State: AOJu0YxCmgBY4+aaCqTCqe7Odlyk8h6Huhi1iMg1UWsSgLkSNxv6YyRE
 sNXCw6ohbWsgL9DLMDKT63aOme8es09c5I8It3eCiHP4O7duCNG9plc+xk/e
X-Google-Smtp-Source: AGHT+IEVjbmkkN5nZSMULOlCRmANihabXeZa+Tri8ClOoBY09azDE30O4b+FvwDQ5B/7T54s4Mk7ZQ==
X-Received: by 2002:a17:907:3f04:b0:a8d:6dab:b8ee with SMTP id
 a640c23a62f3a-a990a09466amr292974166b.23.1727958630029; 
 Thu, 03 Oct 2024 05:30:30 -0700 (PDT)
Received: from localhost.localdomain (85-250-24-111.bb.netvision.net.il.
 [85.250.24.111]) by smtp.googlemail.com with ESMTPSA id
 a640c23a62f3a-a9910473a94sm79668566b.169.2024.10.03.05.30.27
 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256);
 Thu, 03 Oct 2024 05:30:29 -0700 (PDT)
From: Isaac Boukris <iboukris@gmail.com>
To: dev@dpdk.org
Cc: stephen@networkplumber.org, bruce.richardson@intel.com,
 roretzla@linux.microsoft.com, dmitry.kozliuk@gmail.com,
 david.marchand@redhat.com, Isaac Boukris <iboukris@gmail.com>
Subject: [PATCH v5 2/2] timer: allow platform to override cpu TSC frequency
Date: Thu,  3 Oct 2024 15:26:04 +0300
Message-ID: <20241003122819.354499-3-iboukris@gmail.com>
X-Mailer: git-send-email 2.45.0
In-Reply-To: <20241003122819.354499-1-iboukris@gmail.com>
References: <20240921140022.107239-1-iboukris@gmail.com>
 <20241003122819.354499-1-iboukris@gmail.com>
MIME-Version: 1.0
Content-Transfer-Encoding: 8bit
X-BeenThere: dev@dpdk.org
X-Mailman-Version: 2.1.29
Precedence: list
List-Id: DPDK patches and discussions <dev.dpdk.org>
List-Unsubscribe: <https://mails.dpdk.org/options/dev>,
 <mailto:dev-request@dpdk.org?subject=unsubscribe>
List-Archive: <http://mails.dpdk.org/archives/dev/>
List-Post: <mailto:dev@dpdk.org>
List-Help: <mailto:dev-request@dpdk.org?subject=help>
List-Subscribe: <https://mails.dpdk.org/listinfo/dev>,
 <mailto:dev-request@dpdk.org?subject=subscribe>
Errors-To: dev-bounces@dpdk.org

The CPU provided value is often not accurate, allow overriding it
based on info from the host OS.

On Linux X86, if the tsc_known_freq cpu flag is missing, it means
the kernel doesn't trust it and calculates its own. We should do
the same to avoid drift.

On freebsd we have access to the kernel tsc_hz value, just use it.

Signed-off-by: Isaac Boukris <iboukris@gmail.com>
---
 lib/eal/common/eal_common_timer.c |  3 +-
 lib/eal/common/eal_private.h      |  2 +-
 lib/eal/freebsd/eal_timer.c       |  8 +++--
 lib/eal/linux/eal_timer.c         | 53 +++++++++++++++++++++++++++++--
 lib/eal/windows/eal_timer.c       |  5 ++-
 5 files changed, 62 insertions(+), 9 deletions(-)

diff --git a/lib/eal/common/eal_common_timer.c b/lib/eal/common/eal_common_timer.c
index c5c4703f15..e00be0a5c8 100644
--- a/lib/eal/common/eal_common_timer.c
+++ b/lib/eal/common/eal_common_timer.c
@@ -66,8 +66,7 @@ set_tsc_freq(void)
 	}
 
 	freq = get_tsc_freq_arch();
-	if (!freq)
-		freq = get_tsc_freq();
+	freq = get_tsc_freq(freq);
 	if (!freq)
 		freq = estimate_tsc_freq();
 
diff --git a/lib/eal/common/eal_private.h b/lib/eal/common/eal_private.h
index af09620426..bb315dab04 100644
--- a/lib/eal/common/eal_private.h
+++ b/lib/eal/common/eal_private.h
@@ -374,7 +374,7 @@ void set_tsc_freq(void);
  *
  * This function is private to the EAL.
  */
-uint64_t get_tsc_freq(void);
+uint64_t get_tsc_freq(uint64_t arch_hz);
 
 /**
  * Get TSC frequency if the architecture supports.
diff --git a/lib/eal/freebsd/eal_timer.c b/lib/eal/freebsd/eal_timer.c
index 3dd70e24ba..4eba66eadb 100644
--- a/lib/eal/freebsd/eal_timer.c
+++ b/lib/eal/freebsd/eal_timer.c
@@ -26,7 +26,7 @@
 enum timer_source eal_timer_source = EAL_TIMER_TSC;
 
 uint64_t
-get_tsc_freq(void)
+get_tsc_freq(uint64_t arch_hz)
 {
 	size_t sz;
 	int tmp;
@@ -50,9 +50,13 @@ get_tsc_freq(void)
 	sz = sizeof(tsc_hz);
 	if (sysctlbyname("machdep.tsc_freq", &tsc_hz, &sz, NULL, 0)) {
 		EAL_LOG(WARNING, "%s", strerror(errno));
-		return 0;
+		return arch_hz;
 	}
 
+	if (arch_hz && RTE_MAX(arch_hz, tsc_hz) - RTE_MIN(arch_hz, tsc_hz) > arch_hz / 100)
+		EAL_LOG(WARNING, "Host tsc_freq %"PRIu64" at odds with cpu value %"PRIu64,
+			tsc_hz, arch_hz);
+
 	return tsc_hz;
 }
 
diff --git a/lib/eal/linux/eal_timer.c b/lib/eal/linux/eal_timer.c
index f56a7ae15b..489732c116 100644
--- a/lib/eal/linux/eal_timer.c
+++ b/lib/eal/linux/eal_timer.c
@@ -5,9 +5,9 @@
 
 #include <stdio.h>
 #include <stdint.h>
+#include <inttypes.h>
 #ifdef RTE_LIBEAL_USE_HPET
 #include <fcntl.h>
-#include <inttypes.h>
 #include <sys/mman.h>
 #include <unistd.h>
 #endif
@@ -187,8 +187,41 @@ rte_eal_hpet_init(int make_default)
 }
 #endif
 
+/* Check if the kernel deems the arch provided TSC frequency trustworthy. */
+
+static bool
+is_tsc_known_freq(void)
+{
+	bool ret = true; /* Assume tsc_known_freq */
+
+#if defined(RTE_ARCH_X86)
+	char line[2048];
+	FILE *stream;
+
+	stream = fopen("/proc/cpuinfo", "r");
+	if (!stream) {
+		EAL_LOG(WARNING, "Unable to open /proc/cpuinfo");
+		return ret;
+	}
+
+	while (fgets(line, sizeof(line), stream)) {
+		if (strncmp(line, "flags", 5) != 0)
+			continue;
+
+		if (!strstr(line, "tsc_known_freq"))
+			ret = false;
+
+		break;
+	}
+
+	fclose(stream);
+#endif
+
+	return ret;
+}
+
 uint64_t
-get_tsc_freq(void)
+get_tsc_freq(uint64_t arch_hz)
 {
 #ifdef CLOCK_MONOTONIC_RAW
 #define NS_PER_SEC 1E9
@@ -199,6 +232,9 @@ get_tsc_freq(void)
 	struct timespec t_start, t_end;
 	uint64_t tsc_hz;
 
+	if (arch_hz && is_tsc_known_freq())
+		return arch_hz;
+
 	if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0) {
 		uint64_t ns, end, start = rte_rdtsc();
 		nanosleep(&sleeptime,NULL);
@@ -209,11 +245,22 @@ get_tsc_freq(void)
 
 		double secs = (double)ns/NS_PER_SEC;
 		tsc_hz = (uint64_t)((end - start)/secs);
+
+		if (arch_hz) {
+			/* Make sure we're within 1% for sanity check */
+			if (RTE_MAX(arch_hz, tsc_hz) - RTE_MIN(arch_hz, tsc_hz) > arch_hz / 100)
+				return arch_hz;
+
+			EAL_LOG(DEBUG,
+				"Refined arch frequency %"PRIu64" to measured frequency %"PRIu64,
+				arch_hz, tsc_hz);
+		}
+
 		/* Round up to 100Khz. 1E5 ~ 100Khz */
 		return RTE_ALIGN_MUL_NEAR(tsc_hz, CYC_PER_100KHZ);
 	}
 #endif
-	return 0;
+	return arch_hz;
 }
 
 int
diff --git a/lib/eal/windows/eal_timer.c b/lib/eal/windows/eal_timer.c
index 4003541b08..020035c4cc 100644
--- a/lib/eal/windows/eal_timer.c
+++ b/lib/eal/windows/eal_timer.c
@@ -49,13 +49,16 @@ rte_delay_us_sleep(unsigned int us)
 }
 
 uint64_t
-get_tsc_freq(void)
+get_tsc_freq(uint64_t arch_hz)
 {
 	LARGE_INTEGER t_start, t_end, elapsed_us;
 	LARGE_INTEGER frequency;
 	uint64_t tsc_hz;
 	uint64_t end, start;
 
+	if (arch_hz)
+		return arch_hz;
+
 	QueryPerformanceFrequency(&frequency);
 
 	QueryPerformanceCounter(&t_start);
-- 
2.45.0