xref: /dpdk/lib/eal/x86/rte_cycles.c (revision 31d72ff4dc7c057366153e9918ac92bf9123a3bc)
199a2dd95SBruce Richardson /* SPDX-License-Identifier: BSD-3-Clause
299a2dd95SBruce Richardson  * Copyright(c) 2017 Intel Corporation
399a2dd95SBruce Richardson  */
499a2dd95SBruce Richardson 
599a2dd95SBruce Richardson #include <fcntl.h>
699a2dd95SBruce Richardson #include <unistd.h>
72454b37bSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
82454b37bSTyler Retzlaff #define bit_AVX (1 << 28)
92454b37bSTyler Retzlaff #else
1099a2dd95SBruce Richardson #include <cpuid.h>
112454b37bSTyler Retzlaff #endif
1299a2dd95SBruce Richardson 
13*31d72ff4SSivaprasad Tummala #define x86_vendor_amd(t1, t2, t3)        \
14*31d72ff4SSivaprasad Tummala 	((t1 == 0x68747541) && /* htuA */   \
15*31d72ff4SSivaprasad Tummala 	 (t2 == 0x444d4163) && /* DMAc */   \
16*31d72ff4SSivaprasad Tummala 	 (t3 == 0x69746e65))   /* itne */
1799a2dd95SBruce Richardson 
1899a2dd95SBruce Richardson #include "eal_private.h"
1999a2dd95SBruce Richardson 
2099a2dd95SBruce Richardson static unsigned int
rte_cpu_get_model(uint32_t fam_mod_step)2199a2dd95SBruce Richardson rte_cpu_get_model(uint32_t fam_mod_step)
2299a2dd95SBruce Richardson {
2399a2dd95SBruce Richardson 	uint32_t family, model, ext_model;
2499a2dd95SBruce Richardson 
2599a2dd95SBruce Richardson 	family = (fam_mod_step >> 8) & 0xf;
2699a2dd95SBruce Richardson 	model = (fam_mod_step >> 4) & 0xf;
2799a2dd95SBruce Richardson 
2899a2dd95SBruce Richardson 	if (family == 6 || family == 15) {
2999a2dd95SBruce Richardson 		ext_model = (fam_mod_step >> 16) & 0xf;
3099a2dd95SBruce Richardson 		model += (ext_model << 4);
3199a2dd95SBruce Richardson 	}
3299a2dd95SBruce Richardson 
3399a2dd95SBruce Richardson 	return model;
3499a2dd95SBruce Richardson }
3599a2dd95SBruce Richardson 
3699a2dd95SBruce Richardson static int32_t
rdmsr(int msr,uint64_t * val)3799a2dd95SBruce Richardson rdmsr(int msr, uint64_t *val)
3899a2dd95SBruce Richardson {
3999a2dd95SBruce Richardson #ifdef RTE_EXEC_ENV_LINUX
4099a2dd95SBruce Richardson 	int fd;
4199a2dd95SBruce Richardson 	int ret;
4299a2dd95SBruce Richardson 
4399a2dd95SBruce Richardson 	fd = open("/dev/cpu/0/msr", O_RDONLY);
4499a2dd95SBruce Richardson 	if (fd < 0)
4599a2dd95SBruce Richardson 		return fd;
4699a2dd95SBruce Richardson 
4799a2dd95SBruce Richardson 	ret = pread(fd, val, sizeof(uint64_t), msr);
4899a2dd95SBruce Richardson 
4999a2dd95SBruce Richardson 	close(fd);
5099a2dd95SBruce Richardson 
5199a2dd95SBruce Richardson 	return ret;
5299a2dd95SBruce Richardson #else
5399a2dd95SBruce Richardson 	RTE_SET_USED(msr);
5499a2dd95SBruce Richardson 	RTE_SET_USED(val);
5599a2dd95SBruce Richardson 
5699a2dd95SBruce Richardson 	return -1;
5799a2dd95SBruce Richardson #endif
5899a2dd95SBruce Richardson }
5999a2dd95SBruce Richardson 
6099a2dd95SBruce Richardson static uint32_t
check_model_wsm_nhm(uint8_t model)6199a2dd95SBruce Richardson check_model_wsm_nhm(uint8_t model)
6299a2dd95SBruce Richardson {
6399a2dd95SBruce Richardson 	switch (model) {
6499a2dd95SBruce Richardson 	/* Westmere */
6599a2dd95SBruce Richardson 	case 0x25:
6699a2dd95SBruce Richardson 	case 0x2C:
6799a2dd95SBruce Richardson 	case 0x2F:
6899a2dd95SBruce Richardson 	/* Nehalem */
6999a2dd95SBruce Richardson 	case 0x1E:
7099a2dd95SBruce Richardson 	case 0x1F:
7199a2dd95SBruce Richardson 	case 0x1A:
7299a2dd95SBruce Richardson 	case 0x2E:
7399a2dd95SBruce Richardson 		return 1;
7499a2dd95SBruce Richardson 	}
7599a2dd95SBruce Richardson 
7699a2dd95SBruce Richardson 	return 0;
7799a2dd95SBruce Richardson }
7899a2dd95SBruce Richardson 
7999a2dd95SBruce Richardson static uint32_t
check_model_gdm_dnv(uint8_t model)8099a2dd95SBruce Richardson check_model_gdm_dnv(uint8_t model)
8199a2dd95SBruce Richardson {
8299a2dd95SBruce Richardson 	switch (model) {
8399a2dd95SBruce Richardson 	/* Goldmont */
8499a2dd95SBruce Richardson 	case 0x5C:
8599a2dd95SBruce Richardson 	/* Denverton */
8699a2dd95SBruce Richardson 	case 0x5F:
8799a2dd95SBruce Richardson 		return 1;
8899a2dd95SBruce Richardson 	}
8999a2dd95SBruce Richardson 
9099a2dd95SBruce Richardson 	return 0;
9199a2dd95SBruce Richardson }
9299a2dd95SBruce Richardson 
932454b37bSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
942454b37bSTyler Retzlaff int
__get_cpuid_max(unsigned int e,unsigned int * s)952454b37bSTyler Retzlaff __get_cpuid_max(unsigned int e, unsigned int *s)
962454b37bSTyler Retzlaff {
972454b37bSTyler Retzlaff 	uint32_t cpuinfo[4];
982454b37bSTyler Retzlaff 
992454b37bSTyler Retzlaff 	__cpuid(cpuinfo, e);
1002454b37bSTyler Retzlaff 	if (s)
1012454b37bSTyler Retzlaff 		*s = cpuinfo[1];
1022454b37bSTyler Retzlaff 	return cpuinfo[0];
1032454b37bSTyler Retzlaff }
1042454b37bSTyler Retzlaff #endif
1052454b37bSTyler Retzlaff 
10699a2dd95SBruce Richardson uint64_t
get_tsc_freq_arch(void)10799a2dd95SBruce Richardson get_tsc_freq_arch(void)
10899a2dd95SBruce Richardson {
1092454b37bSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
1102454b37bSTyler Retzlaff 	int cpuinfo[4];
1112454b37bSTyler Retzlaff #endif
11299a2dd95SBruce Richardson 	uint64_t tsc_hz = 0;
11399a2dd95SBruce Richardson 	uint32_t a, b, c, d, maxleaf;
11499a2dd95SBruce Richardson 	uint8_t mult, model;
11599a2dd95SBruce Richardson 	int32_t ret;
11699a2dd95SBruce Richardson 
117*31d72ff4SSivaprasad Tummala #ifdef RTE_TOOLCHAIN_MSVC
118*31d72ff4SSivaprasad Tummala 	__cpuid(cpuinfo, 0);
119*31d72ff4SSivaprasad Tummala 	a = cpuinfo[0];
120*31d72ff4SSivaprasad Tummala 	b = cpuinfo[1];
121*31d72ff4SSivaprasad Tummala 	c = cpuinfo[2];
122*31d72ff4SSivaprasad Tummala 	d = cpuinfo[3];
123*31d72ff4SSivaprasad Tummala #else
124*31d72ff4SSivaprasad Tummala 	__cpuid(0, a, b, c, d);
125*31d72ff4SSivaprasad Tummala #endif
126*31d72ff4SSivaprasad Tummala 	if (x86_vendor_amd(b, c, d))
127*31d72ff4SSivaprasad Tummala 		return 0;
128*31d72ff4SSivaprasad Tummala 
12999a2dd95SBruce Richardson 	/*
13099a2dd95SBruce Richardson 	 * Time Stamp Counter and Nominal Core Crystal Clock
13199a2dd95SBruce Richardson 	 * Information Leaf
13299a2dd95SBruce Richardson 	 */
13399a2dd95SBruce Richardson 	maxleaf = __get_cpuid_max(0, NULL);
13499a2dd95SBruce Richardson 
13599a2dd95SBruce Richardson 	if (maxleaf >= 0x15) {
1362454b37bSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
1372454b37bSTyler Retzlaff 		__cpuid(cpuinfo, 0x15);
1382454b37bSTyler Retzlaff 		a = cpuinfo[0];
1392454b37bSTyler Retzlaff 		b = cpuinfo[1];
1402454b37bSTyler Retzlaff 		c = cpuinfo[2];
1412454b37bSTyler Retzlaff 		d = cpuinfo[3];
1422454b37bSTyler Retzlaff #else
14399a2dd95SBruce Richardson 		__cpuid(0x15, a, b, c, d);
1442454b37bSTyler Retzlaff #endif
14599a2dd95SBruce Richardson 
14699a2dd95SBruce Richardson 		/* EBX : TSC/Crystal ratio, ECX : Crystal Hz */
14799a2dd95SBruce Richardson 		if (b && c)
14899a2dd95SBruce Richardson 			return c * (b / a);
14999a2dd95SBruce Richardson 	}
15099a2dd95SBruce Richardson 
1512454b37bSTyler Retzlaff #ifdef RTE_TOOLCHAIN_MSVC
1522454b37bSTyler Retzlaff 	__cpuid(cpuinfo, 0x1);
1532454b37bSTyler Retzlaff 	a = cpuinfo[0];
1542454b37bSTyler Retzlaff 	b = cpuinfo[1];
1552454b37bSTyler Retzlaff 	c = cpuinfo[2];
1562454b37bSTyler Retzlaff 	d = cpuinfo[3];
1572454b37bSTyler Retzlaff #else
15899a2dd95SBruce Richardson 	__cpuid(0x1, a, b, c, d);
1592454b37bSTyler Retzlaff #endif
16099a2dd95SBruce Richardson 	model = rte_cpu_get_model(a);
16199a2dd95SBruce Richardson 
16299a2dd95SBruce Richardson 	if (check_model_wsm_nhm(model))
16399a2dd95SBruce Richardson 		mult = 133;
16499a2dd95SBruce Richardson 	else if ((c & bit_AVX) || check_model_gdm_dnv(model))
16599a2dd95SBruce Richardson 		mult = 100;
16699a2dd95SBruce Richardson 	else
16799a2dd95SBruce Richardson 		return 0;
16899a2dd95SBruce Richardson 
16999a2dd95SBruce Richardson 	ret = rdmsr(0xCE, &tsc_hz);
17099a2dd95SBruce Richardson 	if (ret < 0)
17199a2dd95SBruce Richardson 		return 0;
17299a2dd95SBruce Richardson 
17399a2dd95SBruce Richardson 	return ((tsc_hz >> 8) & 0xff) * mult * 1E6;
17499a2dd95SBruce Richardson }
175