Branch data Line data Source code
1 : : /* SPDX-License-Identifier: BSD-3-Clause
2 : : * Copyright(c) 2017 Intel Corporation
3 : : */
4 : :
5 : : #include <fcntl.h>
6 : : #include <unistd.h>
7 : : #ifdef RTE_TOOLCHAIN_MSVC
8 : : #define bit_AVX (1 << 28)
9 : : #else
10 : : #include <cpuid.h>
11 : : #endif
12 : :
13 : : #define x86_vendor_amd(t1, t2, t3) \
14 : : ((t1 == 0x68747541) && /* htuA */ \
15 : : (t2 == 0x444d4163) && /* DMAc */ \
16 : : (t3 == 0x69746e65)) /* itne */
17 : :
18 : : #include "eal_private.h"
19 : :
20 : : static unsigned int
21 : : rte_cpu_get_model(uint32_t fam_mod_step)
22 : : {
23 : : uint32_t family, model, ext_model;
24 : :
25 : 154 : family = (fam_mod_step >> 8) & 0xf;
26 : 154 : model = (fam_mod_step >> 4) & 0xf;
27 : :
28 [ + - ]: 154 : if (family == 6 || family == 15) {
29 : 154 : ext_model = (fam_mod_step >> 16) & 0xf;
30 : 154 : model += (ext_model << 4);
31 : : }
32 : :
33 : : return model;
34 : : }
35 : :
36 : : static int32_t
37 : 154 : rdmsr(int msr, uint64_t *val)
38 : : {
39 : : #ifdef RTE_EXEC_ENV_LINUX
40 : : int fd;
41 : : int ret;
42 : :
43 : : fd = open("/dev/cpu/0/msr", O_RDONLY);
44 [ + - ]: 154 : if (fd < 0)
45 : : return fd;
46 : :
47 [ + - ]: 154 : ret = pread(fd, val, sizeof(uint64_t), msr);
48 : :
49 : 154 : close(fd);
50 : :
51 : 154 : return ret;
52 : : #else
53 : : RTE_SET_USED(msr);
54 : : RTE_SET_USED(val);
55 : :
56 : : return -1;
57 : : #endif
58 : : }
59 : :
60 : : static uint32_t
61 : : check_model_wsm_nhm(uint8_t model)
62 : : {
63 : 154 : switch (model) {
64 : : /* Westmere */
65 : : case 0x25:
66 : : case 0x2C:
67 : : case 0x2F:
68 : : /* Nehalem */
69 : : case 0x1E:
70 : : case 0x1F:
71 : : case 0x1A:
72 : : case 0x2E:
73 : : return 1;
74 : : }
75 : :
76 : : return 0;
77 : : }
78 : :
79 : : static uint32_t
80 : : check_model_gdm_dnv(uint8_t model)
81 : : {
82 [ # # ]: 0 : switch (model) {
83 : : /* Goldmont */
84 : : case 0x5C:
85 : : /* Denverton */
86 : : case 0x5F:
87 : : return 1;
88 : : }
89 : :
90 : : return 0;
91 : : }
92 : :
93 : : #ifdef RTE_TOOLCHAIN_MSVC
94 : : int
95 : : __get_cpuid_max(unsigned int e, unsigned int *s)
96 : : {
97 : : uint32_t cpuinfo[4];
98 : :
99 : : __cpuid(cpuinfo, e);
100 : : if (s)
101 : : *s = cpuinfo[1];
102 : : return cpuinfo[0];
103 : : }
104 : : #endif
105 : :
106 : : uint64_t
107 : 154 : get_tsc_freq_arch(void)
108 : : {
109 : : #ifdef RTE_TOOLCHAIN_MSVC
110 : : int cpuinfo[4];
111 : : #endif
112 : 154 : uint64_t tsc_hz = 0;
113 : : uint32_t a, b, c, d, maxleaf;
114 : : uint8_t mult, model;
115 : : int32_t ret;
116 : :
117 : : #ifdef RTE_TOOLCHAIN_MSVC
118 : : __cpuid(cpuinfo, 0);
119 : : a = cpuinfo[0];
120 : : b = cpuinfo[1];
121 : : c = cpuinfo[2];
122 : : d = cpuinfo[3];
123 : : #else
124 : 154 : __cpuid(0, a, b, c, d);
125 : : #endif
126 [ - + - - ]: 154 : if (x86_vendor_amd(b, c, d))
127 : : return 0;
128 : :
129 : : /*
130 : : * Time Stamp Counter and Nominal Core Crystal Clock
131 : : * Information Leaf
132 : : */
133 : : maxleaf = __get_cpuid_max(0, NULL);
134 : :
135 [ + - ]: 154 : if (maxleaf >= 0x15) {
136 : : #ifdef RTE_TOOLCHAIN_MSVC
137 : : __cpuid(cpuinfo, 0x15);
138 : : a = cpuinfo[0];
139 : : b = cpuinfo[1];
140 : : c = cpuinfo[2];
141 : : d = cpuinfo[3];
142 : : #else
143 : 154 : __cpuid(0x15, a, b, c, d);
144 : : #endif
145 : :
146 : : /* EBX : TSC/Crystal ratio, ECX : Crystal Hz */
147 [ - + ]: 154 : if (b && c)
148 : 0 : return c * (b / a);
149 : : }
150 : :
151 : : #ifdef RTE_TOOLCHAIN_MSVC
152 : : __cpuid(cpuinfo, 0x1);
153 : : a = cpuinfo[0];
154 : : b = cpuinfo[1];
155 : : c = cpuinfo[2];
156 : : d = cpuinfo[3];
157 : : #else
158 : 154 : __cpuid(0x1, a, b, c, d);
159 : : #endif
160 [ + - ]: 154 : model = rte_cpu_get_model(a);
161 : :
162 : : if (check_model_wsm_nhm(model))
163 : : mult = 133;
164 [ - + ]: 154 : else if ((c & bit_AVX) || check_model_gdm_dnv(model))
165 : : mult = 100;
166 : : else
167 : : return 0;
168 : :
169 : 154 : ret = rdmsr(0xCE, &tsc_hz);
170 [ + - ]: 154 : if (ret < 0)
171 : : return 0;
172 : :
173 : 154 : return ((tsc_hz >> 8) & 0xff) * mult * 1E6;
174 : : }
|