Chameleon

Chameleon Svn Source Tree

Root/branches/valv/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, fsbi;
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, isatom, fsbad;
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);
140if(p->CPU.Vendor == 0x68747541)
141{
142do_cpuid(0x80000008, p->CPU.CPUID[8]);
143p->CPU.NoCores= bitfield(p->CPU.CPUID[8][2], 7, 0) + 1;
144}
145else
146p->CPU.NoCores= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;
147
148p->CPU.Model += (p->CPU.ExtModel << 4);
149
150/* get brand string (if supported) */
151/* Copyright: from Apple's XNU cpuid.c */
152if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {
153uint32_treg[4];
154 char str[128], *s;
155/*
156 * The brand string 48 bytes (max), guaranteed to
157 * be NUL terminated.
158 */
159do_cpuid(0x80000002, reg);
160bcopy((char *)reg, &str[0], 16);
161do_cpuid(0x80000003, reg);
162bcopy((char *)reg, &str[16], 16);
163do_cpuid(0x80000004, reg);
164bcopy((char *)reg, &str[32], 16);
165for (s = str; *s != '\0'; s++) {
166if (*s != ' ') break;
167}
168
169strlcpy(p->CPU.BrandString,s, sizeof(p->CPU.BrandString));
170
171if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, min(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {
172 /*
173 * This string means we have a firmware-programmable brand string,
174 * and the firmware couldn't figure out what sort of CPU we have.
175 */
176 p->CPU.BrandString[0] = '\0';
177 }
178}
179
180/* setup features */
181p->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];
182p->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];
183p->CPU.Features |= (CPU_FEATURE_EM64T | CPU_FEATURE_XD) & p->CPU.CPUID[CPUID_81][3];
184p->CPU.Features |= (CPU_FEATURE_LAHF) & p->CPU.CPUID[CPUID_81][2];
185
186
187//if ((CPU_FEATURE_HTT & p->CPU.CPUID[CPUID_1][3]) != 0) {
188if (p->CPU.NoThreads > p->CPU.NoCores) {
189p->CPU.Features |= CPU_FEATURE_HTT;
190}
191
192
193tscFrequency = measure_tsc_frequency();
194fsbFrequency = 0;
195cpuFrequency = 0;
196fsbi = 0;
197fix_fsb = false;
198did = false;
199core_i = false;
200turbo = false;
201isatom = false;
202fsbad = false;
203
204if ((p->CPU.Vendor == 0x756E6547 /* Intel */) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f)))
205{
206verbose("CPU: ");
207int tjmax = 0;
208msr = rdmsr64(MSR_IA32_PLATFORM_ID);
209if((((msr >> 50) & 0x01) == 1) || (rdmsr64(0x17) & (1<<28)))
210{
211p->CPU.Features |= CPU_FEATURE_MOBILE;
212verbose("Mobile ");
213}
214verbose("%s\n", p->CPU.BrandString);
215
216if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))
217{
218if (p->CPU.Family == 0x06)
219{
220// valv: to be moved!
221/*if(p->CPU.CPUID[CPUID_0][0] >= 11)
222{
223if((p->CPU.CPUID[0xB][1] != 0) && (bitfield(p->CPU.CPUID[CPUID_1][3], 28, 28)))
224}*/
225
226/*int CoreOk = 0;
227int ThreadOk = 0;
228int lvlType, lvlShift;
229do
230{
231if(p->CPU.CPUID[0xB][1] == 0) break;
232lvlType = bitfield(p->CPU.CPUID[0xB][2], 15, 8);
233lvlShift = bitfield(p->CPU.CPUID[0xB][0], 4, 0);
234switch(lvlType)
235}*/
236int intelCPU = p->CPU.Model;
237int Stepp = p->CPU.Stepping;
238int bus;
239
240switch (intelCPU)
241{
242// valv: hoardcoded to BrandString for now, till the code above is ready!
243case 0x2a:// Sandy Bridge, 32nm
244if((strstr(p->CPU.BrandString, "i3"))
245|| (strstr(p->CPU.BrandString, "i5-2390T"))
246|| (strstr(p->CPU.BrandString, "i5-2100S")))
247p->CPU.NoCores = 2;
248else p->CPU.NoCores = 4;
249if(strstr(p->CPU.BrandString, "i7"))
250p->CPU.NoThreads = 8;
251else p->CPU.NoThreads = 4;
252case 0xc:// Core i7 & Atom
253if (strstr(p->CPU.BrandString, "Atom")) goto teleport1;
254case 0x1a:// Core i7 LGA1366, Xeon 5500, "Bloomfield", "Gainstown", 45nm
255case 0x1e:// Core i7, i5 LGA1156, "Clarksfield", "Lynnfield", "Jasper", 45nm
256case 0x1f:// Core i7, i5, Nehalem
257case 0x25:// Core i7, i5, i3 LGA1156, "Westmere", "Clarkdale", "Arrandale", 32nm
258case 0x2c:// Core i7 LGA1366, Six-core, "Westmere", "Gulftown", 32nm
259case 0x2e:// Core i7, Nehalem-Ex Xeon, "Beckton"
260case 0x2f:// Core i7, Nehalem-Ex Xeon, "Eagleton"
261core_i = true;
262tjmax = (rdmsr64(MSR_THERMAL_TARGET) >> 16) & 0xff;
263msr = rdmsr64(MSR_PLATFORM_INFO);
264bus_ratio_max = (msr >> 8) & 0xff;
265bus_ratio_min = (msr >> 40) & 0xff; //valv: not sure about this one (Remarq.1)
266verbose("CPU: Flex-Ratio = %d ", bus_ratio_max);
267min_ratio = bus_ratio_min * 10;
268msr = rdmsr64(MSR_FLEX_RATIO);
269if ((msr >> 16) & 0x01)
270{
271flex_ratio = (msr >> 8) & 0xff;
272verbose(">> %d", flex_ratio);
273if(bus_ratio_max > flex_ratio) bus_ratio_max = flex_ratio;
274}
275verbose("\n");
276if(bus_ratio_max) fsbFrequency = (tscFrequency / bus_ratio_max);
277
278//valv: Turbo Ratio Limit
279if ((intelCPU != 0x2e) && (intelCPU != 0x2f))
280{
281turbo = true;
282msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
283
284p->CPU.Tone = (msr >> 0) & 0xff;
285p->CPU.Ttwo = (msr >> 8) & 0xff;
286p->CPU.Tthr = (msr >> 16) & 0xff;
287p->CPU.Tfor = (msr >> 24) & 0xff;
288
289cpuFrequency = bus_ratio_max * fsbFrequency;
290max_ratio = bus_ratio_max * 10;
291}
292else cpuFrequency = tscFrequency;
293
294if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) && (len <= 4))
295{
296max_ratio = atoi(newratio);
297max_ratio = (max_ratio * 10);
298if (len >= 3) max_ratio = (max_ratio + 5);
299
300verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
301
302// extreme overclockers may love 320 ;)
303if ((max_ratio >= min_ratio) && (max_ratio <= 320))
304{
305cpuFrequency = (fsbFrequency * max_ratio) / 10;
306if (len >= 3) maxdiv = 1;
307else maxdiv = 0;
308}
309else max_ratio = (bus_ratio_max * 10);
310}
311//valv: to be uncommented if Remarq.1 didn't stick
312/*if(bus_ratio_max > 0) bus_ratio = flex_ratio;*/
313p->CPU.MaxRatio = max_ratio;
314p->CPU.MinRatio = min_ratio;
315
316//fsbi = fsbFrequency;
317if(getIntForKey(kForceFSB, &myfsb, &bootInfo->bootConfig)) goto forcefsb;
318else myfsb = fsbFrequency / 1000000;
319verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %s]\n", myfsb, newratio);
320break;
321case 0xd:// Pentium M, Dothan, 90nm
322case 0xe:// Core Duo/Solo, Pentium M DC
323teleport1:
324msr = rdmsr64(MSR_IA32_EXT_CONFIG);
325if(msr & (1 << 30)) tjmax = 85;
326goto teleport2;
327case 0xf:// Core Xeon, Core 2 DC, 65nm
328switch (Stepp)
329{
330case 0x2:
331tjmax = 95;
332break;
333case 0x6:
334if (p->CPU.NoCores = 2) tjmax = 80;
335if (p->CPU.NoCores = 4) tjmax = 90;
336else tjmax = 85;
337break;
338case 0xb:
339tjmax = 90;
340break;
341case 0xd:
342default:
343msr = rdmsr64(MSR_IA32_EXT_CONFIG);
344if(msr & (1 << 30)) tjmax = 85;
345break;
346}
347case 0x1c:// Atom :)
348switch (Stepp)
349{
350case 0xa:
351tjmax = 100;
352break;
353case 0x2:
354default:
355tjmax = 90;
356break;
357}
358case 0x17:// Core 2 Duo/Extreme, Xeon, 45nm
359switch (Stepp)
360{
361case 0x6:// Mobile Core2 Duo
362tjmax = 104;
363break;
364case 0xa:// Mobile Centrino 2
365tjmax = 105;
366break;
367default:
368if (platformCPUFeature(CPU_FEATURE_MOBILE)) tjmax = 105;
369break;
370}
371case 0x16:// Celeron, Core 2 SC, 65nm
372case 0x27:// Atom Lincroft, 45nm
373teleport2:
374core_i = false;
375//valv: todo: msr_therm2_ctl (0x19d) bit 16 (mode of automatic thermal monitor): 0=tm1, 1=tm2
376//also, if bit 3 of misc_enable is cleared the above would have no effect
377if (strstr(p->CPU.BrandString, "Atom"))
378isatom = true;
379if(!isatom && (platformCPUFeature(CPU_FEATURE_TM1)))
380{
381msr_t msr32;
382msr32 = rdmsr(MSR_IA32_MISC_ENABLE);
383bool tmfix = false;
384getBoolForKey(kFixTM, &tmfix, &bootInfo->bootConfig);
385if(tmfix)
386{
387//thermally-initiated on-die modulation of the stop-clock duty cycle
388if(!(rdmsr64(MSR_IA32_MISC_ENABLE) & (1 << 3))) msr32.lo |= (1 << 3);
389verbose("CPU: Thermal Monitor: TM, ");
390
391//BIOS must enable this feature if the TM2 feature flag (CPUID.1:ECX[8]) is set
392if(platformCPUFeature(CPU_FEATURE_TM2))
393{
394//thermally-initiated frequency transitions
395msr32.lo |= (1 << 13);
396verbose("TM2, ");
397}
398msr32.lo |= (1 << 17);
399verbose("PROCHOT, ");
400msr32.lo |= (1 << 10);
401verbose("FERR\n");
402}
403bool oem_ssdt, tmpval;
404oem_ssdt = false;
405
406oem_ssdt = getBoolForKey(kOEMSSDT, &tmpval, &bootInfo->bootConfig)&&tmpval;
407if(oem_ssdt)
408{
409bool c2e, c4e, hc4e;
410c2e = c4e = hc4e = false;
411
412getBoolForKey(kC2EEnable, &c2e, &bootInfo->bootConfig);
413if(c2e) msr32.lo |= (1 << 26);
414
415getBoolForKey(kC4EEnable, &c4e, &bootInfo->bootConfig);
416if((c4e) && platformCPUFeature(CPU_FEATURE_MOBILE)) msr32.hi |= (1 << (32 - 32));
417getBoolForKey(kHardC4EEnable, &hc4e, &bootInfo->bootConfig);
418if((hc4e) && platformCPUFeature(CPU_FEATURE_MOBILE)) msr32.hi |= (1 << (33 - 32));
419if(c2e || c4e || hc4e) tmfix = true;
420}
421
422if(tmfix)
423{
424msr32.hi |= (1 << (36 - 32)); // EMTTM
425wrmsr(MSR_IA32_MISC_ENABLE, msr32);
426
427msr32 = rdmsr(PIC_SENS_CFG);
428msr32.lo |= (1 << 21);
429wrmsr(PIC_SENS_CFG, msr32);
430}
431}
432
433if (rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 27))
434{
435wrmsr64(MSR_IA32_EXT_CONFIG, (rdmsr64(MSR_IA32_EXT_CONFIG) | (1 << 28)));
436delay(1);
437did = rdmsr64(MSR_IA32_EXT_CONFIG) & (1 << 28);
438}
439getBoolForKey(kFixFSB, &fix_fsb, &bootInfo->bootConfig);
440if(fix_fsb)
441{
442msr = rdmsr64(MSR_FSB_FREQ);
443bus = (msr >> 0) & 0x7;
444if(p->CPU.Model == 0xd && bus == 0)
445{
446fsbFrequency = 100000000;
447myfsb = 100;
448}
449else if(p->CPU.Model == 0xe && p->CPU.ExtModel == 1) goto ratio;
450else
451{
452switch (bus)
453{
454case 0:
455fsbFrequency = 266666667;
456myfsb = 266;
457break;
458case 1:
459fsbFrequency = 133333333;
460myfsb = 133;
461break;
462case 3:
463fsbFrequency = 166666667;
464myfsb = 166;
465break;
466case 4:
467fsbFrequency = 333333333;
468myfsb = 333;
469break;
470case 5:
471fsbFrequency = 100000000;
472myfsb = 100;
473break;
474case 6:
475fsbFrequency = 400000000;
476myfsb = 400;
477break;
478case 2:
479default:
480fsbFrequency = 200000000;
481myfsb = 200;
482break;
483}
484}
485uint64_t minfsb = 182000000, maxfsb = 185000000;
486if(((fsbFrequency > minfsb) && (fsbFrequency < maxfsb)) || !fsbFrequency)
487{
488fsbFrequency = 200000000;
489fsbad = true;
490}
491goto ratio;
492}
493case 0x1d:// Xeon MP MP 7400
494// for 0x2a & 0x2b turbo is true;
495//case 0x2a:// SNB
496//case 0x2b:// SNB Xeon
497default:
498if(getIntForKey(kForceFSB, &myfsb, &bootInfo->bootConfig))
499{
500forcefsb:
501switch(myfsb)
502{
503case 133:
504fsbFrequency = 133333333;
505break;
506case 166:
507fsbFrequency = 166666667;
508break;
509case 233:
510fsbFrequency = 233333333;
511break;
512case 266:
513fsbFrequency = 266666667;
514break;
515case 333:
516fsbFrequency = 333333333;
517break;
518case 100:
519case 200:
520case 400:
521fsbFrequency = (myfsb * 1000000);
522break;
523default:
524getValueForKey(kForceFSB, &newfsb, &len, &bootInfo->bootConfig);
525if((len <= 3) && (myfsb < 400))
526{
527fsbFrequency = (myfsb * 1000000);
528verbose("Specified FSB: %dMhz. Assuming you know what you 're doing !\n", myfsb);
529}
530else if(core_i) fsbFrequency = 133333333;
531else fsbFrequency = 200000000;
532break;
533}
534if(core_i)
535{
536cpuFrequency = (fsbFrequency * max_ratio) / 10;
537verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %s]\n", myfsb, newratio);
538break;
539}
540fix_fsb = true;
541}
542goto ratio;
543break;
544}
545}
546else
547{
548ratio:
549msr = rdmsr64(MSR_IA32_PERF_STATUS);
550maxdiv = (msr >> 46) & 0x01;
551//valv: this seems to be bit 15 instead of 14.
552currdiv = (msr >> 15) & 0x01;
553uint8_t XE = (msr >> 31) & 0x01;
554
555msr_t msr32;
556msr32 = rdmsr(MSR_IA32_PERF_STATUS);
557bus_ratio_min = (msr32.lo >> 24) & 0x1f;
558min_ratio = bus_ratio_min * 10;
559if(currdiv) min_ratio = min_ratio + 5;
560
561if(XE || (p->CPU.Family == 0x0f)) bus_ratio_max = (msr32.hi >> (40-32)) & 0x1f;
562else bus_ratio_max = ((rdmsr64(MSR_IA32_PLATFORM_ID) >> 8) & 0x1f);
563/* On lower models, currcoef defines TSC freq */
564if (((p->CPU.Family == 0x06) && (p->CPU.Model < 0x0e)) && (p->CPU.Family != 0x0f)) bus_ratio_max = bus_ratio_min;
565// bad hack! Could force a value relying on kpstates, but I fail to see its benefits.
566if(bus_ratio_min == 0) bus_ratio_min = bus_ratio_max;
567
568if(p->CPU.Family == 0x0f)
569{
570getBoolForKey(kFixFSB, &fix_fsb, &bootInfo->bootConfig);
571if(fix_fsb)
572{
573msr = rdmsr64(MSR_EBC_FREQUENCY_ID);
574int bus = (msr >> 16) & 0x7;
575switch (bus)
576{
577case 0:
578fsbFrequency = 266666667;
579myfsb = 266;
580break;
581case 1:
582fsbFrequency = 133333333;
583myfsb = 133;
584break;
585case 3:
586fsbFrequency = 166666667;
587myfsb = 166;
588break;
589case 2:
590default:
591fsbFrequency = 200000000;
592myfsb = 200;
593break;
594}
595uint64_t minfsb = 183000000, maxfsb = 185000000;
596if (((fsbFrequency > minfsb) && (fsbFrequency < maxfsb)) || (!fsbFrequency))
597{
598fsbFrequency = 200000000;
599fsbad = true;
600}
601}
602}
603
604if(fix_fsb)
605{
606if (bus_ratio_max)
607{
608if (maxdiv) fsbi = ((tscFrequency * 2) / ((bus_ratio_max * 2) + 1));
609else fsbi = (tscFrequency / bus_ratio_max);
610}
611ratio_gn:
612if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) && (len <= 4))
613{
614max_ratio = atoi(newratio);
615max_ratio = (max_ratio * 10);
616if (len >= 3) max_ratio = (max_ratio + 5);
617
618verbose("Bus-Ratio defaults: min=%d%s, max=%d%s\n", bus_ratio_min, currdiv ? ".5" : "", bus_ratio_max, maxdiv ? ".5" : "");
619if ((max_ratio >= min_ratio) && (max_ratio < 200))
620{
621cpuFrequency = (fsbFrequency * max_ratio) / 10;
622if (len >= 3) maxdiv = 1;
623else maxdiv = 0;
624verbose("Sticking with [FSB: %dMhz, Bus-Ratio: %s]\n", myfsb, newratio);
625}
626else
627{
628printf("Bus-Ratio: Lowest allowed = %d%s. ", bus_ratio_min, currdiv ? ".5" : "");
629goto ratio_vldt;
630}
631}
632else
633{
634ratio_vldt:
635if (maxdiv)
636{
637cpuFrequency = ((fsbFrequency * ((bus_ratio_max * 2) + 1)) / 2);
638max_ratio = (bus_ratio_max * 10) + 5;
639}
640else
641{
642cpuFrequency = (fsbFrequency * bus_ratio_max);
643max_ratio = bus_ratio_max * 10;
644}
645verbose("CPU: Sticking with: [FSB: %dMhz, Bus-Ratio: %d%s] %s\n", myfsb, bus_ratio_max, maxdiv ? ".5" : "", newratio ? "instead" : "");
646}
647}
648else
649{
650if (bus_ratio_max)
651{
652if (maxdiv)
653{
654fsbFrequency = ((tscFrequency * 2) / ((bus_ratio_max * 2) + 1));
655max_ratio = ((bus_ratio_max * 10) + 5);
656}
657else
658{
659fsbFrequency = (tscFrequency / bus_ratio_max);
660max_ratio = (bus_ratio_max * 10);
661}
662
663myfsb = (fsbFrequency / 1000000);
664if (getValueForKey(kbusratio, &newratio, &len, &bootInfo->bootConfig)) goto ratio_gn;
665else cpuFrequency = ((fsbFrequency * max_ratio) / 10);
666
667DBG("max: %d%s current: %d%s\n", bus_ratio_max, maxdiv ? ".5" : "", bus_ratio_min, currdiv ? ".5" : "");
668}
669}
670p->CPU.MaxRatio = max_ratio;
671p->CPU.MinRatio = min_ratio;
672}
673}
674
675// on-die sensor
676if (p->CPU.CPUID[CPUID_0][0] >= 0x6)
677{
678// Highest Basic Functions Number
679do_cpuid(6, p->CPU.CPUID[CPUID_81]);
680tms = bitfield(p->CPU.CPUID[CPUID_81][0], 0, 0);
681ida = bitfield(p->CPU.CPUID[CPUID_81][0], 1, 1);
682if(tms != 0)
683{
684int temp, utjmax;
685if (tjmax == 0) tjmax = 100;
686if((getIntForKey(kTjmax, &utjmax, &bootInfo->bootConfig)) && ((70 <= utjmax) && (utjmax <= 110))) tjmax = utjmax;
687msr = rdmsr64(MSR_THERMAL_STATUS);
688//if ((msr & 0x3) == 0x3)
689if (((msr >> 31) & 0x1) == 1)
690{
691temp = tjmax - ((msr >> 16) & 0x7F);
692verbose("CPU: Tjmax ~ %d°C Temperature= ~ %d°C\n", tjmax, temp);
693}
694else temp = -1;
695}
696if(ida == 0)
697{
698verbose("CPU: Attempting to enable IDA ");
699msr_t msr;
700msr = rdmsr(MSR_IA32_MISC_ENABLE);
701msr.hi |= (0 << (38-32));
702wrmsr(MSR_IA32_MISC_ENABLE, msr);
703delay(1);
704if(bitfield(p->CPU.CPUID[CPUID_81][0], 1, 1) == 0) verbose("Failed!\n");
705else verbose("Succeded!\n");
706}
707else verbose("CPU: IDA: Enabled!\n");
708}
709}
710//#if 0
711// valv: work in progress. Most of this code is going to be moved when ready
712else if(p->CPU.Vendor == 0x68747541 /* AMD */ && p->CPU.Family == 0x0f)
713{
714verbose("CPU: ");
715// valv: very experimental mobility check
716if (p->CPU.CPUID[0x80000000][0] >= 0x80000007)
717{
718uint32_t amo, const_tsc;
719do_cpuid(0x80000007, p->CPU.CPUID[CPUID_MAX]);
720amo = bitfield(p->CPU.CPUID[CPUID_MAX][0], 6, 6);
721const_tsc = bitfield(p->CPU.CPUID[CPUID_MAX][3], 8, 8);
722// valv: p-state support verification
723//uint32_t pstate_support = bitfield(p->CPU.CPUID[CPUID_MAX][3], 2, 1);
724//if(pstate_support != 0) verbose("supproted p-state transition\n")
725
726if (const_tsc != 0) verbose("Constant TSC!\n");
727if (amo == 1)
728{
729p->CPU.Features |= CPU_FEATURE_MOBILE;
730if (!strstr(p->CPU.BrandString, "obile")) verbose("Mobile ");
731}
732}
733//valv: 2nd attemp; just in case
734if (!platformCPUFeature(CPU_FEATURE_MOBILE))
735{
736if (strstr(p->CPU.BrandString, "obile"))
737{
738p->CPU.Features |= CPU_FEATURE_MOBILE;
739}
740}
741verbose("%s\n", p->CPU.BrandString);
742
743if(p->CPU.ExtFamily == 0x00 /* K8 */)
744{
745// valv: this section needs some work
746msr = rdmsr64(K8_FIDVID_STATUS);
747bus_ratio_max = bitfield(msr, 21, 16);
748//bus_ratio_max = (msr & 0x3f) / 2 + 4;
749bus_ratio_min = bitfield(msr, 13, 8);
750currdiv = (msr & 0x01) * 2;
751if (bus_ratio_max)
752{
753if (currdiv)
754{
755fsbFrequency = ((tscFrequency * currdiv) / bus_ratio_max); // ?
756DBG("%d.%d\n", bus_ratio_max / currdiv, ((bus_ratio_max % currdiv) * 100) / currdiv);
757}
758else
759{
760fsbFrequency = (tscFrequency / bus_ratio_max);
761DBG("%d\n", bus_ratio_max);
762}
763//fsbFrequency = (tscFrequency / bus_ratio_max); // ?
764cpuFrequency = tscFrequency; // ?
765}
766}
767
768else if(p->CPU.ExtFamily >= 0x01 /* K10+ */)
769{
770msr = rdmsr64(K10_COFVID_STATUS);
771currdiv = (2 << ((msr >> 6) & 0x07));
772msr = rdmsr64(AMD_10H_11H_CONFIG);
773bus_ratio_max = ((msr) & 0x3F);
774//verbose("max_multi: %d\n", bus_ratio_max);
775
776/*msr_t divmsr;
777divmsr = rdmsr(AMD_10H_11H_CONFIG);
778maxdiv = (divmsr.hi >> 0x08) & 0x01;
779verbose("maxdiv: %d, currdiv: %d\n", maxdiv, currdiv);*/
780
781if(p->CPU.ExtFamily == 0x01)
782cpuFrequency = 100 * (bus_ratio_max + 0x10);
783else
784cpuFrequency = 100 * (bus_ratio_max + 0x08);
785
786uint32_t minFreq = cpuFrequency / (1 << currdiv);
787
788uint8_t maxrtio = (cpuFrequency / 20);
789p->CPU.MaxRatio = maxrtio;
790
791fsbFrequency = ((tscFrequency / 100000) / maxrtio);
792verbose("fsb: %d\n", fsbFrequency);
793
794if(maxrtio == ((bus_ratio_max * 10) - 5))
795{
796verbose("multi: max:%d.5, min:", (bus_ratio_max - 1));
797maxdiv = 1;
798}
799else if(maxrtio == ((bus_ratio_max - 1) * 10))
800{
801verbose("multi: max:%d, min:", (bus_ratio_max - 1));
802maxdiv = 0;
803}
804
805bus_ratio_min = (minFreq / fsbFrequency);
806verbose("%d", bus_ratio_min);
807while(minFreq < 800)
808{
809bus_ratio_min = bus_ratio_min + 1; // bus_ratio_min++; ???
810verbose(" >> %d", bus_ratio_min);
811}
812verbose("\n");
813
814struct hwpstate
815{
816uint32_tfreq;/* CPU clock in Mhz. */
817uint32_tvolts;/* Voltage in mV. */
818uint32_tpower;/* Power consumed in mW. */
819uint8_tlat;/* Transition latency in us. */
820uint8_tpstate_id;/* P-State id */
821};
822
823struct hwpstate state[32];
824int max_state, i,/* did,*/ vid;
825uint8_t fid;
826msr = rdmsr64(MSR_AMD_10H_11H_LIMIT);
827max_state = 1 + (((msr) >> 4) & 0x7);
828
829for(i=0; i<max_state; i++)
830{
831msr = rdmsr64(AMD_10H_11H_CONFIG + i);
832//msr_t didmsr;
833//didmsr = rdmsr(AMD_10H_11H_CONFIG + i);
834if ((msr & ((uint64_t)1 << 63)) != ((uint64_t)1 << 63)) verbose("Invalid MSR!\n");
835else
836{
837//did = (didmsr.hi >> 0x08) & 0x01;
838if(i == 0)
839{
840//maxdiv = did;
841fid = p->CPU.MaxRatio;
842state[i].freq = ((fid * fsbFrequency) / 10);
843fid = (fid / 10);
844}
845else
846{
847fid = bitfield(msr, 5, 0);
848state[i].freq = (fid * fsbFrequency);
849}
850
851if(i == (max_state -1))
852{
853fid = bus_ratio_min;
854state[i].freq = (fid * fsbFrequency);
855}
856
857vid = bitfield(msr, 15, 9);
858
859if(i == 0) verbose("P-State %d: Frequency: %d, Multiplier: %d%s, vid: %d\n", i, state[i].freq, fid, maxdiv ? ".5" : "", vid);
860else if((state[i].freq > state[i-1].freq) || (state[i].freq < 800)) verbose("P-State %d: Removed!\n", i);
861else verbose("P-State %d: Frequency: %d, Multiplier: %d, vid: %d\n", i, state[i].freq, fid, vid);
862state[i].pstate_id = i;
863// valv: zeroed for now
864state[i].volts = 0;
865state[i].power = 0;
866state[i].lat = 0;
867}
868}
869fsbFrequency = (fsbFrequency * 1000000);
870cpuFrequency = (state[0].freq * 1000000);
871}
872
873p->CPU.MinRatio = bus_ratio_min * 10;
874}
875else if(p->CPU.Vendor == 0x746e6543 /* CENTAUR */ && p->CPU.Family == 6) //valv: partial!
876{
877msr = rdmsr64(MSR_EBL_CR_POWERON);
878int bus = (msr >> 18) & 0x3;
879switch (bus)
880{
881case 1:
882fsbFrequency = 133333333;
883break;
884case 2:
885fsbFrequency = 200000000;
886break;
887case 3:
888fsbFrequency = 166666667;
889break;
890case 0:
891default:
892fsbFrequency = 100000000;
893break;
894}
895msr_t msr;
896msr = rdmsr(MSR_IA32_PERF_STATUS);
897bus_ratio_min = (msr.lo >> 24) & 0x1f;
898min_ratio = bus_ratio_min * 10;
899bus_ratio_max = (msr.hi >> (40-32)) & 0x1f;
900max_ratio = bus_ratio_max * 10;
901cpuFrequency = ((fsbFrequency * max_ratio) / 10);
902}
903
904if (!fsbFrequency)
905{
906fsbFrequency = (DEFAULT_FSB * 1000);
907cpuFrequency = tscFrequency;
908DBG("0 ! using the default value for FSB !\n");
909}
910
911//#endif
912
913p->CPU.MaxDiv = maxdiv;
914p->CPU.CurrDiv = currdiv;
915p->CPU.TSCFrequency = tscFrequency;
916p->CPU.FSBFrequency = fsbFrequency;
917p->CPU.CPUFrequency = cpuFrequency;
918p->CPU.ISerie = false;
919p->CPU.Turbo = false;
920
921if(!fsbad) p->CPU.FSBIFrequency = fsbFrequency;
922else p->CPU.FSBIFrequency = fsbi;
923
924if (platformCPUFeature(CPU_FEATURE_EST))
925{
926msr_t msr32;
927msr32 = rdmsr(MSR_IA32_MISC_ENABLE);
928if (!(rdmsr64(MSR_IA32_MISC_ENABLE) & (1 << 16)))
929{//valv: we can also attempt to enable
930msr32.lo |= (1 << 16);
931// Lock till next reset!
932msr32.lo |= (1 << 20);
933wrmsr(MSR_IA32_MISC_ENABLE, msr32);
934delay(1);
935if(rdmsr64(MSR_IA32_MISC_ENABLE) & (1 << 16))
936{
937p->CPU.EST = 1;
938verbose("CPU: EIST Successfully Enabled!\n");
939}
940else
941{
942p->CPU.EST = 0;
943verbose("CPU: EIST couldn't be enabled!\n");
944}
945}
946
947else p->CPU.EST = 1;
948}
949
950if(core_i) p->CPU.ISerie = true;
951DBG("CPU: Vendor/Family/ExtFamily: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Family, p->CPU.ExtFamily);
952DBG("CPU: Model/ExtModel/Stepping: 0x%x/0x%x/0x%x\n", p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping);
953DBG("CPU: Multipliers x10: max=%d, min=%d\n", p->CPU.MaxRatio, p->CPU.MinRatio);
954if(turbo)
955{
956DBG("Turbo Ratio: %d/%d/%d/%d\n", p->CPU.Tone, p->CPU.Ttwo, p->CPU.Tthr, p->CPU.Tfor);
957p->CPU.Turbo = true;
958}
959DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv);
960DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000);
961DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000);
962DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000);
963if(did)
964{
965p->CPU.SLFM = did;
966DBG("CPU: SLFM: %d\n", p->CPU.SLFM);
967}
968if(platformCPUFeature(CPU_FEATURE_EST))
969DBG("CPU: Enhanced SpeedStep: %d\n", p->CPU.EST);
970DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads);
971DBG("CPU: Features: 0x%08x\n", p->CPU.Features);
972}
973

Archive Download this file

Revision: 709