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