Root/
Source at commit 1146 created 12 years 10 months ago. By azimutz, Sync with trunk (r1145). Add nVidia dev id's, 0DF4 for "GeForce GT 450M" (issue 99) and 1251 for "GeForce GTX 560M" (thanks to oSxFr33k for testing). | |
---|---|
1 | /*␊ |
2 | * Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>␊ |
3 | * AsereBLN: 2009: cleanup and bugfix␊ |
4 | */␊ |
5 | ␊ |
6 | #include "libsaio.h"␊ |
7 | #include "platform.h"␊ |
8 | #include "cpu.h"␊ |
9 | ␊ |
10 | #ifndef DEBUG_CPU␊ |
11 | #define DEBUG_CPU 0␊ |
12 | #endif␊ |
13 | ␊ |
14 | #if DEBUG_CPU␊ |
15 | #define DBG(x...)␉␉printf(x)␊ |
16 | #else␊ |
17 | #define DBG(x...)␉␉msglog(x)␊ |
18 | #endif␊ |
19 | ␊ |
20 | /*␊ |
21 | * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer␊ |
22 | */␊ |
23 | static uint64_t measure_tsc_frequency(void)␊ |
24 | {␊ |
25 | uint64_t tscStart;␊ |
26 | uint64_t tscEnd;␊ |
27 | uint64_t tscDelta = 0xffffffffffffffffULL;␊ |
28 | unsigned long pollCount;␊ |
29 | uint64_t retval = 0;␊ |
30 | int i;␊ |
31 | ␊ |
32 | /* Time how many TSC ticks elapse in 30 msec using the 8254 PIT␊ |
33 | * counter 2. We run this loop 3 times to make sure the cache␊ |
34 | * is hot and we take the minimum delta from all of the runs.␊ |
35 | * That is to say that we're biased towards measuring the minimum␊ |
36 | * number of TSC ticks that occur while waiting for the timer to␊ |
37 | * expire. That theoretically helps avoid inconsistencies when␊ |
38 | * running under a VM if the TSC is not virtualized and the host␊ |
39 | * steals time. The TSC is normally virtualized for VMware.␊ |
40 | */␊ |
41 | for(i = 0; i < 10; ++i)␊ |
42 | {␊ |
43 | enable_PIT2();␊ |
44 | set_PIT2_mode0(CALIBRATE_LATCH);␊ |
45 | tscStart = rdtsc64();␊ |
46 | pollCount = poll_PIT2_gate();␊ |
47 | tscEnd = rdtsc64();␊ |
48 | /* The poll loop must have run at least a few times for accuracy */␊ |
49 | if(pollCount <= 1)␊ |
50 | continue;␊ |
51 | /* The TSC must increment at LEAST once every millisecond. We␊ |
52 | * should have waited exactly 30 msec so the TSC delta should␊ |
53 | * be >= 30. Anything less and the processor is way too slow.␊ |
54 | */␊ |
55 | if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)␊ |
56 | continue;␊ |
57 | // tscDelta = min(tscDelta, (tscEnd - tscStart))␊ |
58 | if( (tscEnd - tscStart) < tscDelta )␊ |
59 | tscDelta = tscEnd - tscStart;␊ |
60 | }␊ |
61 | /* tscDelta is now the least number of TSC ticks the processor made in␊ |
62 | * a timespan of 0.03 s (e.g. 30 milliseconds)␊ |
63 | * Linux thus divides by 30 which gives the answer in kiloHertz because␊ |
64 | * 1 / ms = kHz. But we're xnu and most of the rest of the code uses␊ |
65 | * Hz so we need to convert our milliseconds to seconds. Since we're␊ |
66 | * dividing by the milliseconds, we simply multiply by 1000.␊ |
67 | */␊ |
68 | ␊ |
69 | /* Unlike linux, we're not limited to 32-bit, but we do need to take care␊ |
70 | * that we're going to multiply by 1000 first so we do need at least some␊ |
71 | * arithmetic headroom. For now, 32-bit should be enough.␊ |
72 | * Also unlike Linux, our compiler can do 64-bit integer arithmetic.␊ |
73 | */␊ |
74 | if(tscDelta > (1ULL<<32))␊ |
75 | retval = 0;␊ |
76 | else␊ |
77 | {␊ |
78 | retval = tscDelta * 1000 / 30;␊ |
79 | }␊ |
80 | disable_PIT2();␊ |
81 | return retval;␊ |
82 | }␊ |
83 | ␊ |
84 | /*␊ |
85 | * Calculates the FSB and CPU frequencies using specific MSRs for each CPU␊ |
86 | * - multi. is read from a specific MSR. In the case of Intel, there is:␊ |
87 | * a max multi. (used to calculate the FSB freq.),␊ |
88 | * and a current multi. (used to calculate the CPU freq.)␊ |
89 | * - fsbFrequency = tscFrequency / multi␊ |
90 | * - cpuFrequency = fsbFrequency * multi␊ |
91 | */␊ |
92 | ␊ |
93 | void scan_cpu(PlatformInfo_t *p)␊ |
94 | {␉␊ |
95 | ␉int i = 0;␊ |
96 | ␉uint64_t␉tscFrequency, fsbFrequency, cpuFrequency;␊ |
97 | ␉uint64_t␉msr, flex_ratio;␊ |
98 | ␉uint8_t␉␉maxcoef, maxdiv, currcoef, currdiv;␊ |
99 | ␊ |
100 | ␉maxcoef = maxdiv = currcoef = currdiv = 0;␊ |
101 | ␊ |
102 | ␉␊ |
103 | ␉// Rename CPU to GeniuneIntel␊ |
104 | ␉//wrmsr64(MSR_VIA_FEAT_CONTROL2, 'GenuineI'/*'ntel'*/);␊ |
105 | ␊ |
106 | ␉␊ |
107 | ␉/* get cpuid values */␊ |
108 | ␉for( ; i <= 3; i++)␊ |
109 | ␉{␊ |
110 | ␉␉do_cpuid(i, p->CPU.CPUID[i]);␊ |
111 | ␉}␊ |
112 | ␉␊ |
113 | ␉do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);␊ |
114 | ␉do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);␊ |
115 | ␉if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {␊ |
116 | ␉␉do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);␊ |
117 | ␉}␊ |
118 | #if DEBUG_CPU␊ |
119 | ␉{␊ |
120 | ␉␉int␉␉i;␊ |
121 | ␉␉printf("CPUID Raw Values:\n");␊ |
122 | ␉␉for (i=0; i<CPUID_MAX; i++) {␊ |
123 | ␉␉␉printf("%02d: %08x-%08x-%08x-%08x\n", i,␊ |
124 | ␉␉␉␉p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],␊ |
125 | ␉␉␉␉p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);␊ |
126 | ␉␉}␊ |
127 | ␉}␊ |
128 | #endif␊ |
129 | ␉p->CPU.Vendor␉␉= p->CPU.CPUID[CPUID_0][1];␊ |
130 | ␉p->CPU.Signature␉= p->CPU.CPUID[CPUID_1][0];␊ |
131 | ␉p->CPU.Stepping␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);␊ |
132 | ␉p->CPU.Model␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);␊ |
133 | ␉p->CPU.Family␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);␊ |
134 | ␉p->CPU.ExtModel␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);␊ |
135 | ␉p->CPU.ExtFamily␉= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);␊ |
136 | ␉p->CPU.NoThreads␉= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);␊ |
137 | ␉p->CPU.NoCores␉␉= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;␊ |
138 | ␊ |
139 | ␉p->CPU.Model += (p->CPU.ExtModel << 4);␊ |
140 | ␉␊ |
141 | ␉/* get brand string (if supported) */␊ |
142 | ␉/* Copyright: from Apple's XNU cpuid.c */␊ |
143 | ␉if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {␊ |
144 | ␉␉uint32_t␉reg[4];␊ |
145 | char str[128], *s;␊ |
146 | ␉␉/*␊ |
147 | ␉␉ * The brand string 48 bytes (max), guaranteed to␊ |
148 | ␉␉ * be NUL terminated.␊ |
149 | ␉␉ */␊ |
150 | ␉␉do_cpuid(0x80000002, reg);␊ |
151 | ␉␉bcopy((char *)reg, &str[0], 16);␊ |
152 | ␉␉do_cpuid(0x80000003, reg);␊ |
153 | ␉␉bcopy((char *)reg, &str[16], 16);␊ |
154 | ␉␉do_cpuid(0x80000004, reg);␊ |
155 | ␉␉bcopy((char *)reg, &str[32], 16);␊ |
156 | ␉␉for (s = str; *s != '\0'; s++) {␊ |
157 | ␉␉␉if (*s != ' ') break;␊ |
158 | ␉␉}␊ |
159 | ␉␉␊ |
160 | ␉␉strlcpy(p->CPU.BrandString,␉s, sizeof(p->CPU.BrandString));␊ |
161 | ␉␉␊ |
162 | ␉␉if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, min(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {␊ |
163 | ␉␉␉ /*␊ |
164 | ␉␉␉ * This string means we have a firmware-programmable brand string,␊ |
165 | ␉␉␉ * and the firmware couldn't figure out what sort of CPU we have.␊ |
166 | ␉␉␉ */␊ |
167 | ␉␉␉ p->CPU.BrandString[0] = '\0';␊ |
168 | ␉␉ }␊ |
169 | ␉}␊ |
170 | ␉␊ |
171 | ␉/* setup features */␊ |
172 | ␉p->CPU.Features |= (CPU_FEATURE_MMX | CPU_FEATURE_SSE | CPU_FEATURE_SSE2 | CPU_FEATURE_MSR) & p->CPU.CPUID[CPUID_1][3];␊ |
173 | ␉p->CPU.Features |= (CPU_FEATURE_SSE3 | CPU_FEATURE_SSE41 | CPU_FEATURE_SSE42) & p->CPU.CPUID[CPUID_1][2];␉␊ |
174 | ␉p->CPU.Features |= (CPU_FEATURE_EM64T) & p->CPU.CPUID[CPUID_81][3];␊ |
175 | ␊ |
176 | ␊ |
177 | ␉//if ((CPU_FEATURE_HTT & p->CPU.CPUID[CPUID_1][3]) != 0) {␊ |
178 | ␉if (p->CPU.NoThreads > p->CPU.NoCores) {␊ |
179 | ␉␉p->CPU.Features |= CPU_FEATURE_HTT;␊ |
180 | ␉}␊ |
181 | ␉ ␊ |
182 | ␊ |
183 | ␉tscFrequency = measure_tsc_frequency();␊ |
184 | ␉fsbFrequency = 0;␊ |
185 | ␉cpuFrequency = 0;␊ |
186 | ␊ |
187 | ␉if ((p->CPU.Vendor == 0x756E6547 /* Intel */) && ␊ |
188 | ␉␉((p->CPU.Family == 0x06) || ␊ |
189 | ␉␉ (p->CPU.Family == 0x0f)))␊ |
190 | ␉{␊ |
191 | ␉␉if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || ␊ |
192 | ␉␉␉(p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))␊ |
193 | ␉␉{␊ |
194 | ␉␉␉/* Nehalem CPU model */␊ |
195 | ␉␉␉if (p->CPU.Family == 0x06 && (p->CPU.Model == 0x1a || p->CPU.Model == 0x1e ||␊ |
196 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == 0x1f || p->CPU.Model == 0x25 ||␊ |
197 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == 0x2c)) ␊ |
198 | ␉␉␉{␊ |
199 | ␉␉␉␉msr = rdmsr64(MSR_PLATFORM_INFO);␊ |
200 | ␉␉␉␉DBG("msr(%d): platform_info %08x\n", __LINE__, msr & 0xffffffff);␊ |
201 | ␉␉␉␉currcoef = (msr >> 8) & 0xff;␊ |
202 | ␉␉␉␉msr = rdmsr64(MSR_FLEX_RATIO);␊ |
203 | ␉␉␉␉DBG("msr(%d): flex_ratio %08x\n", __LINE__, msr & 0xffffffff);␊ |
204 | ␉␉␉␉if ((msr >> 16) & 0x01)␊ |
205 | ␉␉␉␉{␊ |
206 | ␉␉␉␉␉flex_ratio = (msr >> 8) & 0xff;␊ |
207 | ␉␉␉␉␉if (currcoef > flex_ratio) ␊ |
208 | ␉␉␉␉␉{␊ |
209 | ␉␉␉␉␉␉currcoef = flex_ratio;␊ |
210 | ␉␉␉␉␉}␊ |
211 | ␉␉␉␉}␊ |
212 | ␊ |
213 | ␉␉␉␉if (currcoef) {␊ |
214 | ␉␉␉␉␉fsbFrequency = (tscFrequency / currcoef);␊ |
215 | ␉␉␉␉}␊ |
216 | ␉␉␉␉cpuFrequency = tscFrequency;␊ |
217 | ␉␉␉} ␊ |
218 | ␉␉␉else␊ |
219 | ␉␉␉{␊ |
220 | ␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
221 | ␉␉␉␉DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, msr & 0xffffffff);␊ |
222 | ␉␉␉␉currcoef = (msr >> 8) & 0x1f;␊ |
223 | ␉␉␉␉/* Non-integer bus ratio for the max-multi*/␊ |
224 | ␉␉␉␉maxdiv = (msr >> 46) & 0x01;␊ |
225 | ␉␉␉␉/* Non-integer bus ratio for the current-multi (undocumented)*/␊ |
226 | ␉␉␉␉currdiv = (msr >> 14) & 0x01;␊ |
227 | ␊ |
228 | ␉␉␉␉if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || ␊ |
229 | ␉␉␉␉␉(p->CPU.Family == 0x0f)) // This will always be model >= 3␊ |
230 | ␉␉␉␉{␊ |
231 | ␉␉␉␉␉/* On these models, maxcoef defines TSC freq */␊ |
232 | ␉␉␉␉␉maxcoef = (msr >> 40) & 0x1f;␊ |
233 | ␉␉␉␉} ␊ |
234 | ␉␉␉␉else ␊ |
235 | ␉␉␉␉{␊ |
236 | ␉␉␉␉␉/* On lower models, currcoef defines TSC freq */␊ |
237 | ␉␉␉␉␉/* XXX */␊ |
238 | ␉␉␉␉␉maxcoef = currcoef;␊ |
239 | ␉␉␉␉}␊ |
240 | ␊ |
241 | ␉␉␉␉if (maxcoef) ␊ |
242 | ␉␉␉␉{␊ |
243 | ␉␉␉␉␉if (maxdiv)␊ |
244 | ␉␉␉␉␉{␊ |
245 | ␉␉␉␉␉␉fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));␊ |
246 | ␉␉␉␉␉}␊ |
247 | ␉␉␉␉␉else ␊ |
248 | ␉␉␉␉␉{␊ |
249 | ␉␉␉␉␉␉fsbFrequency = (tscFrequency / maxcoef);␊ |
250 | ␉␉␉␉␉}␊ |
251 | ␉␉␉␉␉␊ |
252 | ␉␉␉␉␉if (currdiv) ␊ |
253 | ␉␉␉␉␉{␊ |
254 | ␉␉␉␉␉␉cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);␊ |
255 | ␉␉␉␉␉}␊ |
256 | ␉␉␉␉␉else ␊ |
257 | ␉␉␉␉␉{␊ |
258 | ␉␉␉␉␉␉cpuFrequency = (fsbFrequency * currcoef);␊ |
259 | ␉␉␉␉␉}␊ |
260 | ␉␉␉␉␉DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");␊ |
261 | ␉␉␉␉}␊ |
262 | ␉␉␉}␊ |
263 | ␉␉}␊ |
264 | ␉␉/* Mobile CPU ? */␊ |
265 | ␉␉if (rdmsr64(0x17) & (1<<28))␊ |
266 | ␉␉{␊ |
267 | ␉␉␉p->CPU.Features |= CPU_FEATURE_MOBILE;␊ |
268 | ␉␉}␊ |
269 | ␉}␊ |
270 | #if 0␊ |
271 | ␉else if((p->CPU.Vendor == 0x68747541 /* AMD */) && (p->CPU.Family == 0x0f))␊ |
272 | ␉{␊ |
273 | ␉␉if(p->CPU.ExtFamily == 0x00 /* K8 */)␊ |
274 | ␉␉{␊ |
275 | ␉␉␉msr = rdmsr64(K8_FIDVID_STATUS);␊ |
276 | ␉␉␉currcoef = (msr & 0x3f) / 2 + 4;␊ |
277 | ␉␉␉currdiv = (msr & 0x01) * 2;␊ |
278 | ␉␉} ␊ |
279 | ␉␉else if(p->CPU.ExtFamily >= 0x01 /* K10+ */)␊ |
280 | ␉␉{␊ |
281 | ␉␉␉msr = rdmsr64(K10_COFVID_STATUS);␊ |
282 | ␉␉␉if(p->CPU.ExtFamily == 0x01 /* K10 */)␊ |
283 | ␉␉␉␉currcoef = (msr & 0x3f) + 0x10;␊ |
284 | ␉␉␉else /* K11+ */␊ |
285 | ␉␉␉␉currcoef = (msr & 0x3f) + 0x08;␊ |
286 | ␉␉␉currdiv = (2 << ((msr >> 6) & 0x07));␊ |
287 | ␉␉}␊ |
288 | ␊ |
289 | ␉␉if (currcoef) ␊ |
290 | ␉␉{␊ |
291 | ␉␉␉if (currdiv) ␊ |
292 | ␉␉␉{␊ |
293 | ␉␉␉␉fsbFrequency = ((tscFrequency * currdiv) / currcoef);␊ |
294 | ␉␉␉␉DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);␊ |
295 | ␉␉␉}␊ |
296 | ␉␉␉else␊ |
297 | ␉␉␉{␊ |
298 | ␉␉␉␉fsbFrequency = (tscFrequency / currcoef);␊ |
299 | ␉␉␉␉DBG("%d\n", currcoef);␊ |
300 | ␉␉␉}␊ |
301 | ␉␉␉fsbFrequency = (tscFrequency / currcoef);␊ |
302 | ␉␉␉cpuFrequency = tscFrequency;␊ |
303 | ␉␉}␊ |
304 | ␉}␊ |
305 | ␊ |
306 | ␉if (!fsbFrequency) ␊ |
307 | ␉{␊ |
308 | ␉␉fsbFrequency = (DEFAULT_FSB * 1000);␊ |
309 | ␉␉cpuFrequency = tscFrequency;␊ |
310 | ␉␉DBG("0 ! using the default value for FSB !\n");␊ |
311 | ␉}␊ |
312 | #endif␊ |
313 | ␉else if(p->CPU.Vendor == 0x746e6543 && p->CPU.Family == 6)␊ |
314 | ␉{␊ |
315 | ␉␉switch (p->CPU.Model) {␊ |
316 | ␉␉␉case CPU_VIA_NANO:␊ |
317 | ␉␉␉␉// NOTE: TSC is constant, irrelevent of speed steping ␊ |
318 | ␉␉␉␉break;␊ |
319 | ␉␉␉default:␊ |
320 | ␉␉␉␉break;␊ |
321 | ␉␉}␊ |
322 | ␉␉␊ |
323 | ␉␉msr = rdmsr64(MSR_NANO_FCR2);␊ |
324 | ␉␉printf("MSR_IA32_EBL_CR_POWERON Returns 0x%X 0x%X\n", msr >> 32, msr & 0xffffffff);␊ |
325 | ␉␉␊ |
326 | ␉␉//msr = msr >> 32;␊ |
327 | ␉␉msr |= VIA_ALTERNATIVE_VENDOR_BIT;␊ |
328 | ␉␉//msr = msr << 32;␊ |
329 | ␉␉␊ |
330 | ␉␉printf("MSR_IA32_EBL_CR_POWERON Returns 0x%X 0x%X\n", msr >> 32, msr & 0xffffffff);␊ |
331 | ␉␉wrmsr64(MSR_NANO_FCR2, msr);␊ |
332 | ␉␉msr = rdmsr64(MSR_NANO_FCR2);␊ |
333 | ␉␉printf("MSR_IA32_EBL_CR_POWERON Returns 0x%X 0x%X\n", msr >> 32, msr & 0xffffffff);␊ |
334 | ␉␉␊ |
335 | ␉␉␊ |
336 | ␉␉/* get cpuid values */␊ |
337 | ␉␉for( ; i <= 3; i++)␊ |
338 | ␉␉{␊ |
339 | ␉␉␉do_cpuid(i, p->CPU.CPUID[i]);␊ |
340 | ␉␉}␊ |
341 | ␉␉//int numcpuid_supported = p->CPU.CPUID[CPUID_0][0];␉// max number cpuid call␊ |
342 | ␉␉//int numextcpuid = p->CPU.CPUID[CPUID_80][0];␊ |
343 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉//p->CPU.Features = 0;␊ |
344 | ␉␉␉␉␉␉␉␉␉␉␉␉␉␉␉//␉␉bitfield(p->CPU.CPUID[CPUID_1][1], 0, 0) FEATURE_C␊ |
345 | ␉␉␊ |
346 | ␉␉// CPUID_0 -> largest cpuid val in EAX␊ |
347 | ␉␉// CPUID_0 -> rem = vendor string␊ |
348 | ␉␉/*␊ |
349 | ␉␉CPUID_1 EDX:␊ |
350 | ␉␉ 0 -> FPU␊ |
351 | ␉␉ 1 -> VME␊ |
352 | ␉␉ 2 -> DE␊ |
353 | ␉␉ 3 -> PSE␊ |
354 | ␉␉ 4 -> TSC␊ |
355 | ␉␉ 5 -> MSR␊ |
356 | ␉␉ 6 -> PAE␊ |
357 | ␉␉ 7 -> MCE␊ |
358 | ␉␉ 8 -> CX8␊ |
359 | ␉␉ 9 -> APIC␊ |
360 | ␉␉ 10 -> Reserved␊ |
361 | ␉␉ 11 -> Fast Call␊ |
362 | ␉␉ 12 -> MTTR␊ |
363 | ␉␉ 13 -> PGE␊ |
364 | ␉␉ 14 -> MCA␊ |
365 | ␉␉ 15 -> CMOV␊ |
366 | ␉␉ 16 -> PAT␊ |
367 | ␉␉ 17 -> PSE36␊ |
368 | ␉␉ 18 -> Serial Number ␊ |
369 | ␉␉ 23 -> MMX␊ |
370 | ␉␉ 24 -> FXSR␊ |
371 | ␉␉ 25 -> SSE␊ |
372 | ␉␉ */␊ |
373 | ␉␉␊ |
374 | ␉␉//CPUID_80 -> largest excpuid value in EAX␊ |
375 | ␉␉//CPUID_81,EAX -> Signature␊ |
376 | ␉␉//CPUID_80,EDX -> Ext Features␊ |
377 | ␉␉//CPUID_82 -> CPU String␊ |
378 | ␉␉//CPUID_83 -> CPU String␊ |
379 | ␉␉//CPUID_84 -> CPU String␊ |
380 | ␉␉p->CPU.NoThreads = p->CPU.NoCores;␊ |
381 | ␉␉␊ |
382 | ␉}␉␊ |
383 | ␉␊ |
384 | ␉p->CPU.MaxCoef = maxcoef;␊ |
385 | ␉p->CPU.MaxDiv = maxdiv;␊ |
386 | ␉p->CPU.CurrCoef = currcoef;␊ |
387 | ␉p->CPU.CurrDiv = currdiv;␊ |
388 | ␉p->CPU.TSCFrequency = tscFrequency;␊ |
389 | ␉p->CPU.FSBFrequency = fsbFrequency;␊ |
390 | ␉p->CPU.CPUFrequency = cpuFrequency;␊ |
391 | ␉DBG("CPU: Brand: %s\n", p->CPU.BrandString);␊ |
392 | ␉DBG("CPU: Vendor/Model/ExtModel: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Model, p->CPU.ExtModel);␊ |
393 | ␉DBG("CPU: Family/ExtFamily: 0x%x/0x%x\n", p->CPU.Family, p->CPU.ExtFamily);␊ |
394 | ␉DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef);␊ |
395 | ␉DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv);␊ |
396 | ␉DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000);␊ |
397 | ␉DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000);␊ |
398 | ␉DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000);␊ |
399 | ␉DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads);␊ |
400 | ␉DBG("CPU: Features: 0x%08x\n", p->CPU.Features);␊ |
401 | #if DEBUG_CPU␊ |
402 | ␉pause();␊ |
403 | #endif␊ |
404 | }␊ |
405 |