Chameleon

Chameleon Svn Source Tree

Root/branches/valv/branch/i386/libsaio/cpu.c

  • Property svn:executable set to
1/*
2 * Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
3 * AsereBLN: 2009: cleanup and bugfix
4 * valv: 2010: fine-tuning and additions
5 */
6
7#include "libsaio.h"
8#include "platform.h"
9#include "cpu.h"
10#include "boot.h"
11#include "bootstruct.h"
12
13#ifndef DEBUG_CPU
14#define DEBUG_CPU 0
15#endif
16
17#if DEBUG_CPU
18#define DBG(x...)printf(x)
19#else
20#define DBG(x...)msglog(x)
21#endif
22
23/*
24 * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
25 */
26static uint64_t measure_tsc_frequency(void)
27{
28 uint64_t tscStart;
29 uint64_t tscEnd;
30 uint64_t tscDelta = 0xffffffffffffffffULL;
31 unsigned long pollCount;
32 uint64_t retval = 0;
33 int i;
34
35 /* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
36 * counter 2. We run this loop 3 times to make sure the cache
37 * is hot and we take the minimum delta from all of the runs.
38 * That is to say that we're biased towards measuring the minimum
39 * number of TSC ticks that occur while waiting for the timer to
40 * expire. That theoretically helps avoid inconsistencies when
41 * running under a VM if the TSC is not virtualized and the host
42 * steals time. The TSC is normally virtualized for VMware.
43 */
44 for(i = 0; i < 10; ++i)
45 {
46 enable_PIT2();
47 set_PIT2_mode0(CALIBRATE_LATCH);
48 tscStart = rdtsc64();
49 pollCount = poll_PIT2_gate();
50 tscEnd = rdtsc64();
51 /* The poll loop must have run at least a few times for accuracy */
52 if(pollCount <= 1)
53 continue;
54 /* The TSC must increment at LEAST once every millisecond. We
55 * should have waited exactly 30 msec so the TSC delta should
56 * be >= 30. Anything less and the processor is way too slow.
57 */
58 if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)
59 continue;
60 // tscDelta = min(tscDelta, (tscEnd - tscStart))
61 if( (tscEnd - tscStart) < tscDelta )
62 tscDelta = tscEnd - tscStart;
63 }
64 /* tscDelta is now the least number of TSC ticks the processor made in
65 * a timespan of 0.03 s (e.g. 30 milliseconds)
66 * Linux thus divides by 30 which gives the answer in kiloHertz because
67 * 1 / ms = kHz. But we're xnu and most of the rest of the code uses
68 * Hz so we need to convert our milliseconds to seconds. Since we're
69 * dividing by the milliseconds, we simply multiply by 1000.
70 */
71
72 /* Unlike linux, we're not limited to 32-bit, but we do need to take care
73 * that we're going to multiply by 1000 first so we do need at least some
74 * arithmetic headroom. For now, 32-bit should be enough.
75 * Also unlike Linux, our compiler can do 64-bit integer arithmetic.
76 */
77 if(tscDelta > (1ULL<<32))
78 retval = 0;
79 else
80 {
81 retval = tscDelta * 1000 / 30;
82 }
83 disable_PIT2();
84 return retval;
85}
86
87
88/*
89 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
90 * - multi. is read from a specific MSR. In the case of Intel, there is:
91 * a max multi. (used to calculate the FSB freq.),
92 * and a current multi. (used to calculate the CPU freq.)
93 * - fsbFrequency = tscFrequency / multi
94 * - cpuFrequency = fsbFrequency * multi
95 */
96
97void scan_cpu(PlatformInfo_t *p)
98{
99const char*newratio, *newfsb;
100intlen, myfsb, i;
101uint64_ttscFrequency, fsbFrequency, cpuFrequency;
102uint64_tmsr, flex_ratio = 0;
103uint32_ttms, ida, max_ratio, min_ratio;
104uint8_tbus_ratio_max, maxdiv, bus_ratio_min, currdiv;
105boolfix_fsb, did, core_i, turbo;
106
107max_ratio = min_ratio = myfsb = bus_ratio_max = maxdiv = bus_ratio_min = currdiv = i = 0;
108
109/* get cpuid values */
110for( ; i <= 3; i++)
111{
112do_cpuid(i, p->CPU.CPUID[i]);
113}
114
115do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
116do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
117if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {
118do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
119}
120#if DEBUG_CPU
121{
122inti;
123printf("CPUID Raw Values:\n");
124for (i=0; i<CPUID_MAX; i++) {
125printf("%02d: %08x-%08x-%08x-%08x\n", i,
126p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],
127p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);
128}
129}
130#endif
131p->CPU.Vendor= p->CPU.CPUID[CPUID_0][1];
132p->CPU.Signature= p->CPU.CPUID[CPUID_1][0];
133p->CPU.Stepping= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);
134p->CPU.Model= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);
135p->CPU.Type= bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12);
136p->CPU.Family= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);
137p->CPU.ExtModel= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);
138p->CPU.ExtFamily= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);
139p->CPU.NoThreads= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
140p->CPU.NoCores= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;
141
142p->CPU.Model += (p->CPU.ExtModel << 4);
143
144/* get brand string (if supported) */
145/* Copyright: from Apple's XNU cpuid.c */
146if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {
147uint32_treg[4];
148 char str[128], *s;
149/*
150 * The brand string 48 bytes (max), guaranteed to
151 * be NUL terminated.
152 */
153do_cpuid(0x80000002, reg);
154bcopy((char *)reg, &str[0], 16);
155do_cpuid(0x80000003, reg);
156bcopy((char *)reg, &str[16], 16);
157do_cpuid(0x80000004, reg);
158bcopy((char *)reg, &str[32], 16);
159for (s = str; *s != '\0'; s++) {
160if (*s != ' ') break;
161}
162
163strlcpy(p->CPU.BrandString,s, sizeof(p->CPU.BrandString));
164
165if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, min(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {
166 /*
167 * This string means we have a firmware-programmable brand string,
168 * and the firmware couldn't figure out what sort of CPU we have.
169 */
170 p->CPU.BrandString[0] = '\0';
171 }
172}
173
174/* setup features */
175p->CPU.Features |= (CPU_FEATURE_MMX | CPU_FEATURE_SSE | CPU_FEATURE_SSE2 | CPU_FEATURE_MSR | CPU_FEATURE_APIC | CPU_FEATURE_TM1 | CPU_FEATURE_ACPI) & p->CPU.CPUID[CPUID_1][3];
176p->CPU.Features |= (CPU_FEATURE_SSE3 | CPU_FEATURE_SSE41 | CPU_FEATURE_SSE42 | CPU_FEATURE_EST | CPU_FEATURE_TM2 | CPU_FEATURE_SSSE3 | CPU_FEATURE_xAPIC) & p->CPU.CPUID[CPUID_1][2];
177p->CPU.Features |= (CPU_FEATURE_EM64T | CPU_FEATURE_XD) & p->CPU.CPUID[CPUID_81][3];
178p->CPU.Features |= (CPU_FEATURE_LAHF) & p->CPU.CPUID[CPUID_81][2];
179
180
181//if ((CPU_FEATURE_HTT & p->CPU.CPUID[CPUID_1][3]) != 0) {
182if (p->CPU.NoThreads > p->CPU.NoCores) {
183p->CPU.Features |= CPU_FEATURE_HTT;
184}
185
186
187tscFrequency = measure_tsc_frequency();
188fsbFrequency = 0;
189cpuFrequency = 0;
190fix_fsb = false;
191did = false;
192core_i = false;
193turbo = false;
194
195if ((p->CPU.Vendor == 0x756E6547 /* Intel */) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f)))
196{
197verbose("CPU: ");
198int tjmax = 0;
199msr = rdmsr64(MSR_IA32_PLATFORM_ID);
200if (((msr >> 50) & 0x01) == 1)
201{
202p->CPU.Features |= CPU_FEATURE_MOBILE;
203verbose("Mobile ");
204}
205verbose("%s\n", p->CPU.BrandString);
206
207if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))
208{
209if (p->CPU.Family == 0x06)
210{
211int intelCPU = p->CPU.Model;
212int Stepp = p->CPU.Stepping;
213int bus;
214
215switch (intelCPU)
216{
217case 0x1a:// Core i7 LGA1366, Xeon 5500, "Bloomfield", "Gainstown", 45nm
218case 0x1e:// Core i7, i5 LGA1156, "Clarksfield", "Lynnfield", "Jasper", 45nm
219case 0x1f:// Core i7, i5, Nehalem
220case 0x25:// Core i7, i5, i3 LGA1156, "Westmere", "Clarkdale", "Arrandale", 32nm
221case 0x2c:// Core i7 LGA1366, Six-core, "Westmere", "Gulftown", 32nm
222case 0x2e:// Core i7, Nehalem-Ex Xeon, "Beckton"
223case 0x2f:// Core i7, Nehalem-Ex Xeon, "Eagleton"
224core_i = true;
225tjmax = (rdmsr64(MSR_THERMAL_TARGET) >> 16) & 0xff;
226msr = rdmsr64(MSR_PLATFORM_INFO);
227bus_ratio_max = (msr >> 8) & 0xff;
228bus_ratio_min = (msr >> 40) & 0xff; //valv: not sure about this one (Remarq.1)
229verbose("Flex: %d ", bus_ratio_max);
230min_ratio = bus_ratio_min * 10;
231msr = rdmsr64(MSR_FLEX_RATIO);
232if ((msr >> 16) & 0x01)
233{
234flex_ratio = (msr >> 8) & 0xff;
235verbose(">> %d", flex_ratio);
236if(bus_ratio_max > flex_ratio) bus_ratio_max = flex_ratio;
237}
238verbose("\n");
239if(bus_ratio_max) fsbFrequency = (tscFrequency / bus_ratio_max);
240
241//valv: Turbo Ratio Limit
242if ((intelCPU != 0x2e) && (intelCPU != 0x2f))
243{
244turbo = true;
245msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
246
247p->CPU.Tone = (msr >> 0) & 0xff;
248p->CPU.Ttwo = (msr >> 8) & 0xff;
249p->CPU.Tthr = (msr >> 16) & 0xff;
250p->CPU.Tfor = (msr >> 24) & 0xff;
251
252cpuFrequency = bus_ratio_max * fsbFrequency;
253max_ratio = bus_ratio_max * 10;
254}
255else cpuFrequency = tscFrequency;
256
257if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) && (len <= 4))
258{
259max_ratio = atoi(newratio);
260max_ratio = (max_ratio * 10);
261if (len >= 3) max_ratio = (max_ratio + 5);
262
263verbose("Bus-Ratio: min=%d%s, max=%d%s\n", bus_ratio_min, bus_ratio_max);
264
265// extreme overclockers may love 320 ;)
266if ((max_ratio >= min_ratio) && (max_ratio <= 320))
267{
268cpuFrequency = (fsbFrequency * max_ratio) / 10;
269if (len >= 3) maxdiv = 1;
270else maxdiv = 0;
271verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %s]\n", myfsb, newratio);
272}
273else max_ratio = (bus_ratio_max * 10);
274}
275//valv: to be uncommented if Remarq.1 didn't stick
276/*if(bus_ratio_max > 0) bus_ratio = flex_ratio;*/
277p->CPU.MaxRatio = max_ratio;
278p->CPU.MinRatio = min_ratio;
279
280if(getIntForKey(kForceFSB, &myfsb, &bootInfo->bootConfig)) goto forcefsb;
281break;
282case 0xe:// Core Duo/Solo, Pentium M DC
283goto teleport;
284case 0xf:// Core Xeon, Core 2 DC, 65nm
285switch (Stepp)
286{
287case 0x2:
288tjmax = 95;
289break;
290case 0x6:
291if (p->CPU.NoCores = 2) tjmax = 80;
292if (p->CPU.NoCores = 4) tjmax = 90;
293else tjmax = 85;
294break;
295case 0xb:
296tjmax = 90;
297break;
298case 0xd:
299default:
300teleport:
301msr = rdmsr64(MSR_IA32_EXT_CONFIG);
302if(msr & (1 << 30)) tjmax = 85;
303break;
304}
305case 0x1c:// Atom :)
306switch (Stepp)
307{
308case 0xa:
309tjmax = 100;
310break;
311case 0x2:
312default:
313tjmax = 90;
314break;
315}
316case 0x17:// Core 2 Duo/Extreme, Xeon, 45nm
317switch (Stepp)
318{
319case 0x6:// Mobile Core2 Duo
320tjmax = 104;
321break;
322case 0xa:// Mobile Centrino 2
323tjmax = 105;
324break;
325default:
326if (platformCPUFeature(CPU_FEATURE_MOBILE)) tjmax = 105;
327break;
328}
329case 0x16:// Celeron, Core 2 SC, 65nm
330case 0x27:// Atom Lincroft, 45nm
331core_i = false;
332
333if(platformCPUFeature(CPU_FEATURE_TM1))
334{
335msr_t msr32;
336msr32 = rdmsr(MSR_IA32_MISC_ENABLE);
337
338if(!(rdmsr64(MSR_IA32_MISC_ENABLE) & (1 << 3))) msr32.lo |= (1 << 3);
339verbose("Thermal Monitor: TM, ");
340if(platformCPUFeature(CPU_FEATURE_TM2))
341{
342msr32.lo |= (1 << 13);
343verbose("TM2, ");
344}
345msr32.lo |= (1 << 17);
346verbose("PROCHOT, ");
347msr32.lo |= (1 << 10);
348verbose("FERR\n");
349
350bool oem_ssdt, tmpval;
351oem_ssdt = false;
352
353oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
354if(oem_ssdt)
355{
356bool c2e, c4e, hc4e;
357c2e = c4e = hc4e = false;
358
359getBoolForKey(kC2EEnable, &c2e, &bootInfo->bootConfig);
360if(c2e) msr32.lo |= (1 << 26);
361
362getBoolForKey(kC4EEnable, &c4e, &bootInfo->bootConfig);
363if((c4e) && platformCPUFeature(CPU_FEATURE_MOBILE)) msr32.hi |= (1 << (32 - 32));
364getBoolForKey(kHardC4EEnable, &hc4e, &bootInfo->bootConfig);
365if((hc4e) && platformCPUFeature(CPU_FEATURE_MOBILE)) msr32.hi |= (1 << (33 - 32));
366}
367
368msr32.hi |= (1 << (36 - 32)); // EMTTM
369
370wrmsr(MSR_IA32_MISC_ENABLE, msr32);
371}
372
373if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
374{
375wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
376delay(1);
377did = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
378}
379getBoolForKey(kFixFSB, &fix_fsb, &bootInfo->bootConfig);
380if(fix_fsb)
381{
382msr = rdmsr64(MSR_FSB_FREQ);
383bus = (msr >> 0) & 0x7;
384switch (bus)
385{
386case 0:
387fsbFrequency = 266666667;
388myfsb = 266;
389break;
390case 1:
391fsbFrequency = 133333333;
392myfsb = 133;
393break;
394case 3:
395fsbFrequency = 166666667;
396myfsb = 166;
397break;
398case 4:
399fsbFrequency = 333333333;
400myfsb = 333;
401break;
402case 5:
403fsbFrequency = 100000000;
404myfsb = 100;
405break;
406case 6:
407fsbFrequency = 400000000;
408myfsb = 400;
409break;
410case 2:
411default:
412fsbFrequency = 200000000;
413myfsb = 200;
414break;
415}
416uint64_t minfsb = 183000000, maxfsb = 185000000;
417if (((fsbFrequency > minfsb) && (fsbFrequency < maxfsb)) || (!fsbFrequency)) fsbFrequency = 200000000;
418goto ratio;
419}
420case 0x1d:// Xeon MP MP 7400
421// for 0x2a & 0x2b turbo is true;
422//case 0x2a:// SNB
423//case 0x2b:// SNB Xeon
424default:
425if(getIntForKey(kForceFSB, &myfsb, &bootInfo->bootConfig))
426{
427forcefsb:
428switch(myfsb)
429{
430case 133:
431fsbFrequency = 133333333;
432break;
433case 166:
434fsbFrequency = 166666667;
435break;
436case 233:
437fsbFrequency = 233333333;
438break;
439case 266:
440fsbFrequency = 266666667;
441break;
442case 333:
443fsbFrequency = 333333333;
444break;
445case 100:
446case 200:
447case 400:
448fsbFrequency = (myfsb * 1000000);
449break;
450default:
451getValueForKey(kForceFSB, &newfsb, &len, &bootInfo->bootConfig);
452if((len <= 3) && (myfsb < 400))
453{
454fsbFrequency = (myfsb * 1000000);
455verbose("Specified FSB: %dMhz. Assuming you know what you 're doing !\n", myfsb);
456}
457else if(core_i) fsbFrequency = 133333333;
458else fsbFrequency = 200000000;
459break;
460}
461if(core_i)
462{
463cpuFrequency = (fsbFrequency * max_ratio) / 10;
464verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %s]\n", myfsb, newratio);
465break;
466}
467fix_fsb = true;
468}
469goto ratio;
470break;
471}
472}
473else
474{
475ratio:
476msr = rdmsr64(MSR_IA32_PERF_STATUS);
477maxdiv = (msr >> 46) & 0x01;
478//valv: this seems to be bit 15 instead of 14.
479currdiv = (msr >> 15) & 0x01;
480uint8_t XE = (msr >> 31) & 0x01;
481
482msr_t msr;
483msr = rdmsr(MSR_IA32_PERF_STATUS);
484bus_ratio_min = (msr.lo >> 24) & 0x1f;
485min_ratio = bus_ratio_min * 10;
486if(currdiv) min_ratio = min_ratio + 5;
487
488if(XE) bus_ratio_max = (msr.hi >> (40-32)) & 0x1f;
489else bus_ratio_max = ((rdmsr64(MSR_IA32_PLATFORM_ID) >> 8) & 0x1f);
490
491if(fix_fsb)
492{
493ratio_gn:
494if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) && (len <= 4))
495{
496max_ratio = atoi(newratio);
497max_ratio = (max_ratio * 10);
498if (len >= 3) max_ratio = (max_ratio + 5);
499
500verbose("Bus-Ratio defaults: min=%d%s, max=%d%s\n", bus_ratio_min, currdiv ? ".5" : "", bus_ratio_max, maxdiv ? ".5" : "");
501if ((max_ratio >= min_ratio) && (max_ratio < 200))
502{
503cpuFrequency = (fsbFrequency * max_ratio) / 10;
504if (len >= 3) maxdiv = 1;
505else maxdiv = 0;
506verbose("Sticking with [FSB: %dMhz, Bus-Ratio: %s]\n", myfsb, newratio);
507}
508else
509{
510printf("Bus-Ratio: Lowest allowed = %d%s. ", bus_ratio_min, currdiv ? ".5" : "");
511goto ratio_vldt;
512}
513}
514else
515{
516ratio_vldt:
517if (maxdiv)
518{
519cpuFrequency = ((fsbFrequency * ((bus_ratio_max * 2) + 1)) / 2);
520max_ratio = (bus_ratio_max * 10) + 5;
521}
522else
523{
524cpuFrequency = (fsbFrequency * bus_ratio_max);
525max_ratio = bus_ratio_max * 10;
526}
527verbose("CPU: Sticking with [FSB: %dMhz, Bus-Ratio: %d%s] %s\n", myfsb, bus_ratio_max, maxdiv ? ".5" : "", newratio ? "instead" : "");
528}
529}
530else
531{
532/* On lower models, currcoef defines TSC freq */
533if (((p->CPU.Family == 0x06) && (p->CPU.Model < 0x0e)) && (p->CPU.Family != 0x0f)) bus_ratio_max = bus_ratio_min;
534
535if (bus_ratio_max)
536{
537if (maxdiv)
538{
539fsbFrequency = ((tscFrequency * 2) / ((bus_ratio_max * 2) + 1));
540max_ratio = ((bus_ratio_max * 10) + 5);
541}
542else
543{
544fsbFrequency = (tscFrequency / bus_ratio_max);
545max_ratio = (bus_ratio_max * 10);
546}
547
548myfsb = (fsbFrequency / 1000000);
549if (getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) goto ratio_gn;
550else cpuFrequency = ((fsbFrequency * max_ratio) / 10);
551
552DBG("max: %d%s current: %d%s\n", bus_ratio_max, maxdiv ? ".5" : "", bus_ratio_min, currdiv ? ".5" : "");
553}
554}
555p->CPU.MaxRatio = max_ratio;
556p->CPU.MinRatio = min_ratio;
557}
558}
559
560// on-die sensor
561if (p->CPU.CPUID[CPUID_0][0] >= 0x6)
562{
563// Highest Basic Functions Number
564do_cpuid(6, p->CPU.CPUID[CPUID_81]);
565tms = bitfield(p->CPU.CPUID[CPUID_81][0], 0, 0);
566ida = bitfield(p->CPU.CPUID[CPUID_81][0], 1, 1);
567if(tms != 0)
568{
569int temp, utjmax;
570if (tjmax == 0) tjmax = 100;
571if((getIntForKey(kTjmax, &utjmax, &bootInfo->bootConfig)) && ((70 <= utjmax) && (utjmax <= 110))) tjmax = utjmax;
572msr = rdmsr64(MSR_THERMAL_STATUS);
573//if ((msr & 0x3) == 0x3)
574if (((msr >> 31) & 0x1) == 1)
575{
576temp = tjmax - ((msr >> 16) & 0x7F);
577verbose("CPU: Tjmax ~ %d°C Temperature= ~ %d°C\n", tjmax, temp);
578}
579else temp = -1;
580}
581if(ida == 0)
582{
583verbose("CPU: Attempting to enable IDA ");
584msr_t msr;
585msr = rdmsr(MSR_IA32_MISC_ENABLE);
586msr.hi |= (0 << (38-32));
587wrmsr(MSR_IA32_MISC_ENABLE, msr);
588delay(1);
589if(bitfield(p->CPU.CPUID[CPUID_81][0], 0, 1) == 0) verbose("Failed!\n");
590else verbose("Succeded!\n");
591}
592else verbose("CPU: Intel Dynamic Acceleration Enabled!\n");
593}
594}
595#if 0
596else if((p->CPU.Vendor == 0x68747541 /* AMD */) && (p->CPU.Family == 0x0f))
597{
598if(p->CPU.ExtFamily == 0x00 /* K8 */)
599{
600msr = rdmsr64(K8_FIDVID_STATUS);
601bus_ratio_max = (msr & 0x3f) / 2 + 4;
602currdiv = (msr & 0x01) * 2;
603}
604else if(p->CPU.ExtFamily >= 0x01 /* K10+ */)
605{
606msr = rdmsr64(K10_COFVID_STATUS);
607if(p->CPU.ExtFamily == 0x01 /* K10 */)
608bus_ratio_max = (msr & 0x3f) + 0x10;
609else /* K11+ */
610bus_ratio_max = (msr & 0x3f) + 0x08;
611currdiv = (2 << ((msr >> 6) & 0x07));
612}
613
614p->CPU.MaxRatio = bus_ratio_max * 10;
615
616if (bus_ratio_max)
617{
618if (currdiv)
619{
620fsbFrequency = ((tscFrequency * currdiv) / bus_ratio_max);
621DBG("%d.%d\n", bus_ratio_max / currdiv, ((bus_ratio_max % currdiv) * 100) / currdiv);
622}
623else
624{
625fsbFrequency = (tscFrequency / bus_ratio_max);
626DBG("%d\n", bus_ratio_max);
627}
628fsbFrequency = (tscFrequency / bus_ratio_max);
629cpuFrequency = tscFrequency;
630}
631}
632
633if (!fsbFrequency)
634{
635fsbFrequency = (DEFAULT_FSB * 1000);
636cpuFrequency = tscFrequency;
637DBG("0 ! using the default value for FSB !\n");
638}
639#endif
640
641p->CPU.MaxDiv = maxdiv;
642p->CPU.CurrDiv = currdiv;
643p->CPU.TSCFrequency = tscFrequency;
644p->CPU.FSBFrequency = fsbFrequency;
645p->CPU.CPUFrequency = cpuFrequency;
646p->CPU.ISerie = false;
647p->CPU.Turbo = false;
648
649if (platformCPUFeature(CPU_FEATURE_EST))
650{
651msr_t msr32;
652msr32 = rdmsr(MSR_IA32_MISC_ENABLE);
653if (!(rdmsr64(MSR_IA32_MISC_ENABLE) & (1 << 16)))
654{//valv: we can also attempt to enable
655msr32.lo |= (1 << 16);
656// Lock till next reset!
657msr32.lo |= (1 << 20);
658wrmsr(MSR_IA32_MISC_ENABLE, msr32);
659delay(1);
660if(rdmsr64(MSR_IA32_MISC_ENABLE) & (1 << 16))
661{
662p->CPU.EST = 1;
663verbose("EIST Successfully Enabled!");
664}
665else
666{
667p->CPU.EST = 0;
668verbose("EIST couldn't be enabled!");
669}
670}
671
672else p->CPU.EST = 1;
673}
674
675if(core_i) p->CPU.ISerie = true;
676DBG("CPU: Vendor/Family/ExtFamily: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Family, p->CPU.ExtFamily);
677DBG("CPU: Model/ExtModel/Stepping: 0x%x/0x%x/0x%x\n", p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping);
678DBG("CPU: Multipliers x10: max=%d, min=%d\n", p->CPU.MaxRatio, p->CPU.MinRatio);
679if(turbo)
680{
681DBG("Turbo Ratio: %d/%d/%d/%d\n", p->CPU.Tone, p->CPU.Ttwo, p->CPU.Tthr, p->CPU.Tfor);
682p->CPU.Turbo = true;
683}
684DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv);
685DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000);
686DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000);
687DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000);
688if(did)
689{
690p->CPU.SLFM = did;
691DBG("CPU: SLFM: %d\n", p->CPU.SLFM);
692}
693if(platformCPUFeature(CPU_FEATURE_EST))
694DBG("CPU: Enhanced SpeedStep: %d\n", p->CPU.EST);
695DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads);
696DBG("CPU: Features: 0x%08x\n", p->CPU.Features);
697}
698

Archive Download this file

Revision: 661