Chameleon

Chameleon Svn Source Tree

Root/trunk/i386/libsaio/cpu.c

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#include "bootstruct.h"
10#include "boot.h"
11
12#ifndef DEBUG_CPU
13#define DEBUG_CPU 0
14#endif
15
16#if DEBUG_CPU
17#define DBG(x...)printf(x)
18#else
19#define DBG(x...)
20#endif
21
22
23boolean_t ForceAmdCpu = false;
24
25/* For AMD CPU's */
26boolean_t IsAmdCPU(void)
27{
28if (ForceAmdCpu)
29{
30return true;
31}
32
33uint32_t ourcpuid[4];
34do_cpuid(0, ourcpuid);
35if (
36/* This spells out "AuthenticAMD". */
37ourcpuid[ebx] == 0x68747541 && // Auth
38ourcpuid[ecx] == 0x444D4163 && // cAMD
39ourcpuid[edx] == 0x69746E65) // enti
40{
41return true;
42}
43
44return false;
45};
46
47/* For Intel CPU's */
48boolean_t IsIntelCPU(void)
49{
50uint32_t ourcpuid[4];
51do_cpuid(0, ourcpuid);
52if (
53/* This spells out "GenuineIntel". */
54ourcpuid[ebx] == 0x756E6547 && // Genu
55ourcpuid[ecx] == 0x6C65746E && // ntel
56ourcpuid[edx] == 0x49656E69) // ineI
57{
58return true;
59}
60
61if (!IsAmdCPU())
62{
63return true;
64}
65
66return false;
67}
68
69#define UI_CPUFREQ_ROUNDING_FACTOR10000000
70
71clock_frequency_info_t gPEClockFrequencyInfo;
72
73static inline uint32_t __unused clockspeed_rdtsc(void)
74{
75uint32_t out;
76__asm__ volatile (
77 "rdtsc\n"
78 "shl $32,%%edx\n"
79 "or %%edx,%%eax\n"
80 : "=a" (out)
81 :
82 : "%edx"
83 );
84return out;
85}
86
87/*
88 * timeRDTSC()
89 * This routine sets up PIT counter 2 to count down 1/20 of a second.
90 * It pauses until the value is latched in the counter
91 * and then reads the time stamp counter to return to the caller.
92 */
93static uint64_t timeRDTSC(void)
94{
95intattempts = 0;
96uint64_t latchTime;
97uint64_tsaveTime,intermediate;
98unsigned inttimerValue, lastValue;
99//boolean_tint_enabled;
100/*
101 * Table of correction factors to account for
102 * - timer counter quantization errors, and
103 * - undercounts 0..5
104 */
105#define SAMPLE_CLKS_EXACT(((double) CLKNUM) / 20.0)
106#define SAMPLE_CLKS_INT((int) CLKNUM / 20)
107#define SAMPLE_NSECS(2000000000LL)
108#define SAMPLE_MULTIPLIER(((double)SAMPLE_NSECS)*SAMPLE_CLKS_EXACT)
109#define ROUND64(x)((uint64_t)((x) + 0.5))
110uint64_tscale[6] = {
111ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-0)),
112ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-1)),
113ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-2)),
114ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-3)),
115ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-4)),
116ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-5))
117};
118
119//int_enabled = ml_set_interrupts_enabled(false);
120
121restart:
122if (attempts >= 3) // increase to up to 9 attempts.
123{
124// This will flash-reboot. TODO: Use tscPanic instead.
125//printf("Timestamp counter calibation failed with %d attempts\n", attempts);
126}
127attempts++;
128enable_PIT2();// turn on PIT2
129set_PIT2(0);// reset timer 2 to be zero
130latchTime = rdtsc64();// get the time stamp to time
131latchTime = get_PIT2(&timerValue) - latchTime; // time how long this takes
132set_PIT2(SAMPLE_CLKS_INT);// set up the timer for (almost) 1/20th a second
133saveTime = rdtsc64();// now time how long a 20th a second is...
134get_PIT2(&lastValue);
135get_PIT2(&lastValue);// read twice, first value may be unreliable
136do {
137intermediate = get_PIT2(&timerValue);
138if (timerValue > lastValue)
139{
140// Timer wrapped
141set_PIT2(0);
142disable_PIT2();
143goto restart;
144}
145lastValue = timerValue;
146} while (timerValue > 5);
147//printf("timerValue %d\n",timerValue);
148//printf("intermediate 0x%016llX\n",intermediate);
149//printf("saveTime 0x%016llX\n",saveTime);
150
151intermediate -= saveTime;// raw count for about 1/20 second
152intermediate *= scale[timerValue];// rescale measured time spent
153intermediate /= SAMPLE_NSECS;// so its exactly 1/20 a second
154intermediate += latchTime;// add on our save fudge
155
156set_PIT2(0);// reset timer 2 to be zero
157disable_PIT2();// turn off PIT 2
158
159//ml_set_interrupts_enabled(int_enabled);
160return intermediate;
161}
162
163/*
164 * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
165 */
166static uint64_t __unused measure_tsc_frequency(void)
167{
168uint64_t tscStart;
169uint64_t tscEnd;
170uint64_t tscDelta = 0xffffffffffffffffULL;
171unsigned long pollCount;
172uint64_t retval = 0;
173int i;
174
175/* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
176 * counter 2. We run this loop 3 times to make sure the cache
177 * is hot and we take the minimum delta from all of the runs.
178 * That is to say that we're biased towards measuring the minimum
179 * number of TSC ticks that occur while waiting for the timer to
180 * expire. That theoretically helps avoid inconsistencies when
181 * running under a VM if the TSC is not virtualized and the host
182 * steals time. The TSC is normally virtualized for VMware.
183 */
184for(i = 0; i < 10; ++i)
185{
186enable_PIT2();
187set_PIT2_mode0(CALIBRATE_LATCH);
188tscStart = rdtsc64();
189pollCount = poll_PIT2_gate();
190tscEnd = rdtsc64();
191/* The poll loop must have run at least a few times for accuracy */
192if (pollCount <= 1)
193{
194continue;
195}
196/* The TSC must increment at LEAST once every millisecond.
197 * We should have waited exactly 30 msec so the TSC delta should
198 * be >= 30. Anything less and the processor is way too slow.
199 */
200if ((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)
201{
202continue;
203}
204// tscDelta = MIN(tscDelta, (tscEnd - tscStart))
205if ( (tscEnd - tscStart) < tscDelta )
206{
207tscDelta = tscEnd - tscStart;
208}
209}
210/* tscDelta is now the least number of TSC ticks the processor made in
211 * a timespan of 0.03 s (e.g. 30 milliseconds)
212 * Linux thus divides by 30 which gives the answer in kiloHertz because
213 * 1 / ms = kHz. But we're xnu and most of the rest of the code uses
214 * Hz so we need to convert our milliseconds to seconds. Since we're
215 * dividing by the milliseconds, we simply multiply by 1000.
216 */
217
218/* Unlike linux, we're not limited to 32-bit, but we do need to take care
219 * that we're going to multiply by 1000 first so we do need at least some
220 * arithmetic headroom. For now, 32-bit should be enough.
221 * Also unlike Linux, our compiler can do 64-bit integer arithmetic.
222 */
223if (tscDelta > (1ULL<<32))
224{
225retval = 0;
226}
227else
228{
229retval = tscDelta * 1000 / 30;
230}
231disable_PIT2();
232return retval;
233}
234
235static uint64_trtc_set_cyc_per_sec(uint64_t cycles);
236#define RTC_FAST_DENOM0xFFFFFFFF
237
238inline static uint32_t
239create_mul_quant_GHZ(int shift, uint32_t quant)
240{
241return (uint32_t)((((uint64_t)NSEC_PER_SEC/20) << shift) / quant);
242}
243
244struct{
245mach_timespec_tcalend_offset;
246boolean_tcalend_is_set;
247
248int64_tcalend_adjtotal;
249int32_tcalend_adjdelta;
250
251uint32_tboottime;
252
253mach_timebase_info_data_ttimebase_const;
254
255decl_simple_lock_data(,lock)/* real-time clock device lock */
256} rtclock;
257
258uint32_trtc_quant_shift;/* clock to nanos right shift */
259uint32_trtc_quant_scale;/* clock to nanos multiplier */
260uint64_trtc_cyc_per_sec;/* processor cycles per sec */
261uint64_trtc_cycle_count;/* clocks in 1/20th second */
262//uint64_t cpuFreq;
263
264static uint64_t rtc_set_cyc_per_sec(uint64_t cycles)
265{
266
267if (cycles > (NSEC_PER_SEC/20))
268{
269// we can use just a "fast" multiply to get nanos
270rtc_quant_shift = 32;
271rtc_quant_scale = create_mul_quant_GHZ(rtc_quant_shift, (uint32_t)cycles);
272rtclock.timebase_const.numer = rtc_quant_scale; // timeRDTSC is 1/20
273rtclock.timebase_const.denom = (uint32_t)RTC_FAST_DENOM;
274}
275else
276{
277rtc_quant_shift = 26;
278rtc_quant_scale = create_mul_quant_GHZ(rtc_quant_shift, (uint32_t)cycles);
279rtclock.timebase_const.numer = NSEC_PER_SEC/20; // timeRDTSC is 1/20
280rtclock.timebase_const.denom = (uint32_t)cycles;
281}
282rtc_cyc_per_sec = cycles*20;// multiply it by 20 and we are done..
283// BUT we also want to calculate...
284
285cycles = ((rtc_cyc_per_sec + (UI_CPUFREQ_ROUNDING_FACTOR/2))
286 / UI_CPUFREQ_ROUNDING_FACTOR)
287* UI_CPUFREQ_ROUNDING_FACTOR;
288
289/*
290 * Set current measured speed.
291 */
292if (cycles >= 0x100000000ULL)
293{
294gPEClockFrequencyInfo.cpu_clock_rate_hz = 0xFFFFFFFFUL;
295}
296else
297{
298gPEClockFrequencyInfo.cpu_clock_rate_hz = (unsigned long)cycles;
299}
300gPEClockFrequencyInfo.cpu_frequency_hz = cycles;
301
302//printf("[RTCLOCK_1] frequency %llu (%llu) %llu\n", cycles, rtc_cyc_per_sec,timeRDTSC() * 20);
303return(rtc_cyc_per_sec);
304}
305
306/*
307 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
308 * - multi. is read from a specific MSR. In the case of Intel, there is:
309 * a max multi. (used to calculate the FSB freq.),
310 * and a current multi. (used to calculate the CPU freq.)
311 * - busFrequency = tscFrequency / multi
312 * - cpuFrequency = busFrequency * multi
313 */
314
315/* Decimal powers: */
316#define kilo (1000ULL)
317#define Mega (kilo * kilo)
318#define Giga (kilo * Mega)
319#define Tera (kilo * Giga)
320#define Peta (kilo * Tera)
321
322#define quad(hi,lo)(((uint64_t)(hi)) << 32 | (lo))
323
324void scan_cpu(PlatformInfo_t *p)
325{
326uint64_tbusFCvtt2n;
327uint64_ttscFCvtt2n;
328uint64_ttscFreq= 0;
329uint64_tbusFrequency= 0;
330uint64_tcpuFrequency= 0;
331uint64_tmsr= 0;
332uint64_tflex_ratio= 0;
333uint64_tcpuid_features;
334
335uint32_tmax_ratio= 0;
336uint32_tmin_ratio= 0;
337uint32_treg[4];
338uint32_tcores_per_package= 0;
339uint32_tlogical_per_package= 1;
340uint32_tthreads_per_core= 1;
341
342uint8_tbus_ratio_max= 0;
343uint8_tbus_ratio_min= 0;
344uint8_tcurrdiv= 0;
345uint8_tcurrcoef= 0;
346uint8_tmaxdiv= 0;
347uint8_tmaxcoef= 0;
348uint8_tcpuMultN2= 0;
349
350const char*newratio;
351charstr[128];
352char*s= 0;
353
354intlen= 0;
355intmyfsb= 0;
356inti= 0;
357
358if(IsIntelCPU())
359{
360
361do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]); // TLB/Cache/Prefetch
362
363do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]); // S/N
364
365/* Based on Apple's XNU cpuid.c - Deterministic cache parameters */
366if ((p->CPU.CPUID[CPUID_0][eax] > 3) && (p->CPU.CPUID[CPUID_0][eax] < 0x80000000))
367{
368for (i = 0; i < 0xFF; i++) // safe loop
369{
370do_cpuid2(0x00000004, i, reg); // AX=4: Fn, CX=i: cache index
371if (bitfield(reg[eax], 4, 0) == 0)
372{
373break;
374}
375cores_per_package = bitfield(reg[eax], 31, 26) + 1;
376}
377 }
378
379do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
380
381if (i > 0)
382{
383cores_per_package = bitfield(p->CPU.CPUID[CPUID_4][eax], 31, 26) + 1; // i = cache index
384threads_per_core = bitfield(p->CPU.CPUID[CPUID_4][eax], 25, 14) + 1;
385}
386
387if (cores_per_package == 0)
388{
389cores_per_package = 1;
390}
391
392if (p->CPU.CPUID[CPUID_0][0] >= 0x5)// Monitor/Mwait
393{
394do_cpuid(5, p->CPU.CPUID[CPUID_5]);
395}
396
397if (p->CPU.CPUID[CPUID_0][0] >= 6)// Thermal/Power
398{
399do_cpuid(6, p->CPU.CPUID[CPUID_6]);
400}
401
402do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
403
404if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8)
405{
406do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
407do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
408}
409else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1)
410{
411do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
412}
413}
414else if(IsAmdCPU())
415{
416do_cpuid(5, p->CPU.CPUID[CPUID_5]); // Monitor/Mwait
417
418do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
419if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8)
420{
421do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
422}
423
424if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1)
425{
426do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
427}
428
429do_cpuid(0x80000005, p->CPU.CPUID[CPUID_85]); // TLB/Cache/Prefetch
430do_cpuid(0x80000006, p->CPU.CPUID[CPUID_86]); // TLB/Cache/Prefetch
431do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
432
433cores_per_package = bitfield(p->CPU.CPUID[CPUID_88][ecx], 7, 0) + 1;
434threads_per_core = cores_per_package;
435
436if (cores_per_package == 0)
437{
438cores_per_package = 1;
439}
440
441p->CPU.NoThreads= logical_per_package;
442p->CPU.NoCores= cores_per_package;
443
444if (p->CPU.NoCores == 0)
445{
446p->CPU.NoCores = 1;
447p->CPU.NoThreads= 1;
448}
449}
450else
451{
452stop("Unsupported CPU detected! System halted.");
453}
454
455/* http://www.flounder.com/cpuid_explorer2.htm
456 EAX (Intel):
457 31 28 27 20 19 16 1514 1312 11 8 7 4 3 0
458 +--------+----------------+--------+----+----+--------+--------+--------+
459 |########|Extended family |Extmodel|####|type|familyid| model |stepping|
460 +--------+----------------+--------+----+----+--------+--------+--------+
461
462 EAX (AMD):
463 31 28 27 20 19 16 1514 1312 11 8 7 4 3 0
464 +--------+----------------+--------+----+----+--------+--------+--------+
465 |########|Extended family |Extmodel|####|####|familyid| model |stepping|
466 +--------+----------------+--------+----+----+--------+--------+--------+
467*/
468do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]); // Signature, stepping, features
469
470cpuid_features = quad(p->CPU.CPUID[CPUID_1][ecx],p->CPU.CPUID[CPUID_1][edx]);
471if (bit(28) & cpuid_features) // HTT/Multicore
472{
473logical_per_package = bitfield(p->CPU.CPUID[CPUID_1][ebx], 23, 16);
474}
475else
476{
477logical_per_package = 1;
478}
479
480do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]); // MaxFn, Vendor
481
482p->CPU.Vendor= p->CPU.CPUID[CPUID_0][1];
483p->CPU.Signature= p->CPU.CPUID[CPUID_1][0];
484p->CPU.Stepping= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);// stepping = cpu_feat_eax & 0xF;
485p->CPU.Model= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);// model = (cpu_feat_eax >> 4) & 0xF;
486p->CPU.Family= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);// family = (cpu_feat_eax >> 8) & 0xF;
487//p->CPU.Type= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12);// type = (cpu_feat_eax >> 12) & 0x3;
488p->CPU.ExtModel= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);// ext_model = (cpu_feat_eax >> 16) & 0xF;
489p->CPU.ExtFamily= (uint8_t)bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);// ext_family = (cpu_feat_eax >> 20) & 0xFF;
490
491if (p->CPU.Family == 0x0f)
492{
493p->CPU.Family += p->CPU.ExtFamily;
494}
495
496if (p->CPU.Family == 0x0f || p->CPU.Family == 0x06)
497{
498p->CPU.Model += (p->CPU.ExtModel << 4);
499}
500
501/* get BrandString (if supported) */
502/* Copyright: from Apple's XNU cpuid.c */
503if (p->CPU.CPUID[CPUID_80][0] > 0x80000004)
504{
505bzero(str, 128);
506/*
507 * The BrandString 48 bytes (max), guaranteed to
508 * be NULL terminated.
509 */
510do_cpuid(0x80000002, reg);
511memcpy(&str[0], (char *)reg, 16);
512do_cpuid(0x80000003, reg);
513memcpy(&str[16], (char *)reg, 16);
514do_cpuid(0x80000004, reg);
515memcpy(&str[32], (char *)reg, 16);
516for (s = str; *s != '\0'; s++)
517{
518if (*s != ' ')
519{
520break;
521}
522}
523strlcpy(p->CPU.BrandString, s, 48);
524
525if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), (unsigned)strlen(CPU_STRING_UNKNOWN) + 1)))
526{
527/*
528 * This string means we have a firmware-programmable brand string,
529 * and the firmware couldn't figure out what sort of CPU we have.
530 */
531p->CPU.BrandString[0] = '\0';
532}
533p->CPU.BrandString[47] = '\0';
534//DBG("Brandstring = %s\n", p->CPU.BrandString);
535}
536
537/*
538 * Find the number of enabled cores and threads
539 * (which determines whether SMT/Hyperthreading is active).
540 */
541
542if(IsIntelCPU())
543{
544switch (p->CPU.Model)
545{
546case CPUID_MODEL_NEHALEM:
547case CPUID_MODEL_FIELDS:
548case CPUID_MODEL_DALES:
549case CPUID_MODEL_NEHALEM_EX:
550case CPUID_MODEL_JAKETOWN:
551case CPUID_MODEL_SANDYBRIDGE:
552case CPUID_MODEL_IVYBRIDGE:
553
554case CPUID_MODEL_HASWELL:
555case CPUID_MODEL_HASWELL_SVR:
556//case CPUID_MODEL_HASWELL_H:
557case CPUID_MODEL_HASWELL_ULT:
558case CPUID_MODEL_CRYSTALWELL:
559//case CPUID_MODEL_:
560msr = rdmsr64(MSR_CORE_THREAD_COUNT);
561p->CPU.NoCores= (uint32_t)bitfield((uint32_t)msr, 31, 16);
562p->CPU.NoThreads= (uint32_t)bitfield((uint32_t)msr, 15, 0);
563break;
564
565case CPUID_MODEL_DALES_32NM:
566case CPUID_MODEL_WESTMERE:
567case CPUID_MODEL_WESTMERE_EX:
568msr = rdmsr64(MSR_CORE_THREAD_COUNT);
569p->CPU.NoCores= (uint32_t)bitfield((uint32_t)msr, 19, 16);
570p->CPU.NoThreads= (uint32_t)bitfield((uint32_t)msr, 15, 0);
571break;
572}
573
574if (p->CPU.NoCores == 0)
575{
576p->CPU.NoCores= cores_per_package;
577p->CPU.NoThreads= logical_per_package;
578}
579
580// MSR is *NOT* available on the Intel Atom CPU
581//workaround for N270. I don't know why it detected wrong
582if ((p->CPU.Model == CPUID_MODEL_ATOM) && (strstr(p->CPU.BrandString, "270")))
583{
584p->CPU.NoCores= 1;
585p->CPU.NoThreads= 2;
586}
587
588//workaround for Quad
589if ( strstr(p->CPU.BrandString, "Quad") )
590{
591p->CPU.NoCores= 4;
592p->CPU.NoThreads= 4;
593}
594}
595
596/* setup features */
597if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0)
598{
599p->CPU.Features |= CPU_FEATURE_MMX;
600}
601
602if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0)
603{
604p->CPU.Features |= CPU_FEATURE_SSE;
605}
606
607if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0)
608{
609p->CPU.Features |= CPU_FEATURE_SSE2;
610}
611
612if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0)
613{
614p->CPU.Features |= CPU_FEATURE_SSE3;
615}
616
617if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0)
618{
619p->CPU.Features |= CPU_FEATURE_SSE41;
620}
621
622if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0)
623{
624p->CPU.Features |= CPU_FEATURE_SSE42;
625}
626
627if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0)
628{
629p->CPU.Features |= CPU_FEATURE_EM64T;
630}
631
632if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0)
633{
634p->CPU.Features |= CPU_FEATURE_MSR;
635}
636
637if ((p->CPU.NoThreads > p->CPU.NoCores))
638{
639p->CPU.Features |= CPU_FEATURE_HTT;
640}
641
642uint64_t cycles;
643cycles = timeRDTSC();
644tscFreq = rtc_set_cyc_per_sec(cycles);
645DBG("cpu freq classic = 0x%016llx\n", tscFreq);
646// if usual method failed
647if ( tscFreq < 1000 )//TEST
648{
649tscFreq = timeRDTSC() * 20;//measure_tsc_frequency();
650// DBG("cpu freq timeRDTSC = 0x%016llx\n", tscFrequency);
651}
652
653if (IsIntelCPU() && ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)))
654{
655int intelCPU = p->CPU.Model;
656if (p->CPU.Family == 0x06)
657{
658/* Nehalem CPU model */
659switch (p->CPU.Model)
660{
661case CPUID_MODEL_NEHALEM:
662case CPUID_MODEL_FIELDS:
663case CPUID_MODEL_DALES:
664case CPUID_MODEL_DALES_32NM:
665case CPUID_MODEL_WESTMERE:
666case CPUID_MODEL_NEHALEM_EX:
667case CPUID_MODEL_WESTMERE_EX:
668/* --------------------------------------------------------- */
669case CPUID_MODEL_SANDYBRIDGE:
670case CPUID_MODEL_JAKETOWN:
671case CPUID_MODEL_IVYBRIDGE_XEON:
672case CPUID_MODEL_IVYBRIDGE:
673case CPUID_MODEL_HASWELL:
674case CPUID_MODEL_HASWELL_SVR:
675
676case CPUID_MODEL_HASWELL_ULT:
677case CPUID_MODEL_CRYSTALWELL:
678/* --------------------------------------------------------- */
679msr = rdmsr64(MSR_PLATFORM_INFO);
680DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
681bus_ratio_max = bitfield(msr, 15, 8);
682bus_ratio_min = bitfield(msr, 47, 40); //valv: not sure about this one (Remarq.1)
683msr = rdmsr64(MSR_FLEX_RATIO);
684DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
685if (bitfield(msr, 16, 16))
686{
687flex_ratio = bitfield(msr, 15, 8);
688// bcc9: at least on the gigabyte h67ma-ud2h,
689// where the cpu multipler can't be changed to
690// allow overclocking, the flex_ratio msr has unexpected (to OSX)
691// contents.These contents cause mach_kernel to
692// fail to compute the bus ratio correctly, instead
693// causing the system to crash since tscGranularity
694// is inadvertently set to 0.
695
696if (flex_ratio == 0)
697{
698// Clear bit 16 (evidently the presence bit)
699wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
700msr = rdmsr64(MSR_FLEX_RATIO);
701DBG("CPU: Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
702}
703else
704{
705if (bus_ratio_max > flex_ratio)
706{
707bus_ratio_max = flex_ratio;
708}
709}
710}
711
712if (bus_ratio_max)
713{
714busFrequency = (tscFreq / bus_ratio_max);
715}
716
717//valv: Turbo Ratio Limit
718if ((intelCPU != 0x2e) && (intelCPU != 0x2f))
719{
720msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
721
722cpuFrequency = bus_ratio_max * busFrequency;
723max_ratio = bus_ratio_max * 10;
724}
725else
726{
727cpuFrequency = tscFreq;
728}
729if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4))
730{
731max_ratio = atoi(newratio);
732max_ratio = (max_ratio * 10);
733if (len >= 3)
734{
735max_ratio = (max_ratio + 5);
736}
737
738verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
739
740// extreme overclockers may love 320 ;)
741if ((max_ratio >= min_ratio) && (max_ratio <= 320))
742{
743cpuFrequency = (busFrequency * max_ratio) / 10;
744if (len >= 3)
745{
746maxdiv = 1;
747}
748else
749{
750maxdiv = 0;
751}
752}
753else
754{
755max_ratio = (bus_ratio_max * 10);
756}
757}
758//valv: to be uncommented if Remarq.1 didn't stick
759//if (bus_ratio_max > 0) bus_ratio = flex_ratio;
760p->CPU.MaxRatio = max_ratio;
761p->CPU.MinRatio = min_ratio;
762
763myfsb = busFrequency / 1000000;
764verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio/10); // Bungo: fixed wrong Bus-Ratio readout
765currcoef = bus_ratio_max;
766
767break;
768
769default:
770msr = rdmsr64(MSR_IA32_PERF_STATUS);
771DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
772currcoef = bitfield(msr, 12, 8); // Bungo: reverted to 2263 state because of wrong old CPUs freq. calculating
773// Non-integer bus ratio for the max-multi
774maxdiv = bitfield(msr, 46, 46);
775// Non-integer bus ratio for the current-multi (undocumented)
776currdiv = bitfield(msr, 14, 14);
777
778// This will always be model >= 3
779if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f))
780{
781/* On these models, maxcoef defines TSC freq */
782maxcoef = bitfield(msr, 44, 40);
783}
784else
785{
786// On lower models, currcoef defines TSC freq
787// XXX
788maxcoef = currcoef;
789}
790
791if (!currcoef)
792{
793currcoef = maxcoef;
794}
795
796if (maxcoef)
797{
798if (maxdiv)
799{
800busFrequency = ((tscFreq * 2) / ((maxcoef * 2) + 1));
801}
802else
803{
804busFrequency = (tscFreq / maxcoef);
805}
806
807if (currdiv)
808{
809cpuFrequency = (busFrequency * ((currcoef * 2) + 1) / 2);
810}
811else
812{
813cpuFrequency = (busFrequency * currcoef);
814}
815
816DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
817}
818break;
819}
820}
821// Mobile CPU
822if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28))
823{
824p->CPU.Features |= CPU_FEATURE_MOBILE;
825}
826}
827
828else if (IsAmdCPU())
829{
830switch(p->CPU.Family)
831{
832case 0xF: /* K8 */
833{
834uint64_t fidvid = 0;
835uint64_t cpuMult;
836uint64_t fid;
837
838fidvid = rdmsr64(K8_FIDVID_STATUS);
839fid = bitfield(fidvid, 5, 0);
840
841cpuMult = (fid + 8) / 2;
842currcoef = cpuMult;
843
844cpuMultN2 = (fidvid & (uint64_t)bit(0));
845currdiv = cpuMultN2;
846/****** Addon END ******/
847}
848break;
849
850case 0x10: /*** AMD Family 10h ***/
851{
852uint64_t cofvid = 0;
853uint64_t cpuMult;
854uint64_t divisor = 0;
855uint64_t did;
856uint64_t fid;
857
858cofvid = rdmsr64(K10_COFVID_STATUS);
859did = bitfield(cofvid, 8, 6);
860fid = bitfield(cofvid, 5, 0);
861if (did == 0) divisor = 2;
862else if (did == 1) divisor = 4;
863else if (did == 2) divisor = 8;
864else if (did == 3) divisor = 16;
865else if (did == 4) divisor = 32;
866
867cpuMult = (fid + 16) / divisor;
868currcoef = cpuMult;
869
870cpuMultN2 = (cofvid & (uint64_t)bit(0));
871currdiv = cpuMultN2;
872
873/****** Addon END ******/
874}
875break;
876
877case 0x11: /*** AMD Family 11h ***/
878{
879uint64_t cofvid = 0;
880uint64_t cpuMult;
881uint64_t divisor = 0;
882uint64_t did;
883uint64_t fid;
884
885cofvid = rdmsr64(K10_COFVID_STATUS);
886did = bitfield(cofvid, 8, 6);
887fid = bitfield(cofvid, 5, 0);
888if (did == 0) divisor = 2;
889else if (did == 1) divisor = 4;
890else if (did == 2) divisor = 8;
891else if (did == 3) divisor = 16;
892else if (did == 4) divisor = 32;
893
894cpuMult = (fid + 8) / divisor;
895currcoef = cpuMult;
896
897cpuMultN2 = (cofvid & (uint64_t)bit(0));
898currdiv = cpuMultN2;
899
900/****** Addon END ******/
901}
902 break;
903
904case 0x12: /*** AMD Family 12h ***/
905{
906// 8:4 CpuFid: current CPU core frequency ID
907// 3:0 CpuDid: current CPU core divisor ID
908uint64_t prfsts,CpuFid,CpuDid;
909prfsts = rdmsr64(K10_COFVID_STATUS);
910
911CpuDid = bitfield(prfsts, 3, 0) ;
912CpuFid = bitfield(prfsts, 8, 4) ;
913uint64_t divisor;
914switch (CpuDid)
915{
916case 0: divisor = 1; break;
917case 1: divisor = (3/2); break;
918case 2: divisor = 2; break;
919case 3: divisor = 3; break;
920case 4: divisor = 4; break;
921case 5: divisor = 6; break;
922case 6: divisor = 8; break;
923case 7: divisor = 12; break;
924case 8: divisor = 16; break;
925default: divisor = 1; break;
926}
927currcoef = (CpuFid + 0x10) / divisor;
928
929cpuMultN2 = (prfsts & (uint64_t)bit(0));
930currdiv = cpuMultN2;
931
932}
933break;
934
935case 0x14: /* K14 */
936
937{
938// 8:4: current CPU core divisor ID most significant digit
939// 3:0: current CPU core divisor ID least significant digit
940uint64_t prfsts;
941prfsts = rdmsr64(K10_COFVID_STATUS);
942
943uint64_t CpuDidMSD,CpuDidLSD;
944CpuDidMSD = bitfield(prfsts, 8, 4) ;
945CpuDidLSD = bitfield(prfsts, 3, 0) ;
946
947uint64_t frequencyId = 0x10;
948currcoef = (frequencyId + 0x10) /
949(CpuDidMSD + (CpuDidLSD * 0.25) + 1);
950currdiv = ((CpuDidMSD) + 1) << 2;
951currdiv += bitfield(msr, 3, 0);
952
953cpuMultN2 = (prfsts & (uint64_t)bit(0));
954currdiv = cpuMultN2;
955}
956
957break;
958
959case 0x15: /*** AMD Family 15h ***/
960case 0x06: /*** AMD Family 06h ***/
961{
962
963uint64_t cofvid = 0;
964uint64_t cpuMult;
965uint64_t divisor = 0;
966uint64_t did;
967uint64_t fid;
968
969cofvid = rdmsr64(K10_COFVID_STATUS);
970did = bitfield(cofvid, 8, 6);
971fid = bitfield(cofvid, 5, 0);
972if (did == 0) divisor = 2;
973else if (did == 1) divisor = 4;
974else if (did == 2) divisor = 8;
975else if (did == 3) divisor = 16;
976else if (did == 4) divisor = 32;
977
978cpuMult = (fid + 16) / divisor;
979currcoef = cpuMult;
980
981cpuMultN2 = (cofvid & (uint64_t)bit(0));
982currdiv = cpuMultN2;
983}
984break;
985
986case 0x16: /*** AMD Family 16h kabini ***/
987{
988uint64_t cofvid = 0;
989uint64_t cpuMult;
990uint64_t divisor = 0;
991uint64_t did;
992uint64_t fid;
993
994cofvid = rdmsr64(K10_COFVID_STATUS);
995did = bitfield(cofvid, 8, 6);
996fid = bitfield(cofvid, 5, 0);
997if (did == 0) divisor = 1;
998else if (did == 1) divisor = 2;
999else if (did == 2) divisor = 4;
1000else if (did == 3) divisor = 8;
1001else if (did == 4) divisor = 16;
1002
1003cpuMult = (fid + 16) / divisor;
1004currcoef = cpuMult;
1005
1006cpuMultN2 = (cofvid & (uint64_t)bit(0));
1007currdiv = cpuMultN2;
1008/****** Addon END ******/
1009}
1010break;
1011
1012default:
1013{
1014typedef unsigned long long vlong;
1015uint64_t prfsts;
1016prfsts = rdmsr64(K10_COFVID_STATUS);
1017uint64_t r;
1018vlong hz;
1019r = (prfsts>>6) & 0x07;
1020hz = (((prfsts & 0x3f)+0x10)*100000000ll)/(1<<r);
1021
1022currcoef = hz / (200 * Mega);
1023}
1024}
1025
1026if (currcoef)
1027{
1028if (currdiv)
1029{
1030busFrequency = ((tscFreq * 2) / ((currcoef * 2) + 1));
1031busFCvtt2n = ((1 * Giga) << 32) / busFrequency;
1032tscFCvtt2n = busFCvtt2n * 2 / (1 + (2 * currcoef));
1033//cpuFrequency = (busFrequency * ((currcoef * 2) + 1) / 2);//((1 * Giga) << 32) / tscFCvtt2n;
1034cpuFrequency = ((1 * Giga) << 32) / tscFCvtt2n;
1035
1036//cpuFrequency = (busFrequency * ((currcoef * 2) + 1) / 2);
1037DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
1038}
1039else
1040{
1041busFrequency = (tscFreq / currcoef);
1042busFCvtt2n = ((1 * Giga) << 32) / busFrequency;
1043tscFCvtt2n = busFCvtt2n / currcoef;
1044cpuFrequency = ((1 * Giga) << 32) / tscFCvtt2n;
1045DBG("%d\n", currcoef);
1046}
1047}
1048else if (!cpuFrequency)
1049{
1050cpuFrequency = tscFreq;
1051}
1052}
1053
1054#if 0
1055if (!busFrequency)
1056{
1057busFrequency = (DEFAULT_FSB * 1000);
1058DBG("CPU: busFrequency = 0! using the default value for FSB!\n");
1059cpuFrequency = tscFreq;
1060}
1061
1062DBG("cpu freq = 0x%016llxn", timeRDTSC() * 20);
1063
1064#endif
1065
1066p->CPU.MaxCoef = maxcoef = currcoef;
1067p->CPU.MaxDiv = maxdiv = currdiv;
1068p->CPU.CurrCoef = currcoef;
1069p->CPU.CurrDiv = currdiv;
1070p->CPU.TSCFrequency = tscFreq;
1071p->CPU.FSBFrequency = busFrequency;
1072p->CPU.CPUFrequency = cpuFrequency;
1073
1074// keep formatted with spaces instead of tabs
1075DBG("\n------------------------------\n");
1076 DBG("\tCPU INFO\n");
1077DBG("------------------------------\n");
1078
1079DBG("CPUID Raw Values:\n");
1080for (i = 0; i < CPUID_MAX; i++)
1081{
1082DBG("%02d: %08X-%08X-%08X-%08X\n", i, p->CPU.CPUID[i][eax], p->CPU.CPUID[i][ebx], p->CPU.CPUID[i][ecx], p->CPU.CPUID[i][edx]);
1083}
1084DBG("\n");
1085DBG("Brand String: %s\n",p->CPU.BrandString);// Processor name (BIOS)
1086DBG("Vendor: 0x%X\n",p->CPU.Vendor);// Vendor ex: GenuineIntel
1087DBG("Family: 0x%X\n",p->CPU.Family);// Family ex: 6 (06h)
1088DBG("ExtFamily: 0x%X\n",p->CPU.ExtFamily);
1089DBG("Signature: 0x%08X\n",p->CPU.Signature);// CPUID signature
1090/*switch (p->CPU.Type) {
1091case PT_OEM:
1092DBG("Processor type: Intel Original OEM Processor\n");
1093break;
1094case PT_OD:
1095DBG("Processor type: Intel Over Drive Processor\n");
1096break;
1097case PT_DUAL:
1098DBG("Processor type: Intel Dual Processor\n");
1099break;
1100case PT_RES:
1101DBG("Processor type: Intel Reserved\n");
1102break;
1103default:
1104break;
1105}*/
1106DBG("Model: 0x%X\n",p->CPU.Model);// Model ex: 37 (025h)
1107DBG("ExtModel: 0x%X\n",p->CPU.ExtModel);
1108DBG("Stepping: 0x%X\n",p->CPU.Stepping);// Stepping ex: 5 (05h)
1109DBG("MaxCoef: %d\n",p->CPU.MaxCoef);
1110DBG("CurrCoef: %d\n",p->CPU.CurrCoef);
1111DBG("MaxDiv: %d\n",p->CPU.MaxDiv);
1112DBG("CurrDiv: %d\n",p->CPU.CurrDiv);
1113DBG("TSCFreq: %dMHz\n",p->CPU.TSCFrequency / 1000000);
1114DBG("FSBFreq: %dMHz\n",p->CPU.FSBFrequency / 1000000);
1115DBG("CPUFreq: %dMHz\n",p->CPU.CPUFrequency / 1000000);
1116DBG("Cores: %d\n",p->CPU.NoCores);// Cores
1117DBG("Logical processor: %d\n",p->CPU.NoThreads);// Logical procesor
1118DBG("Features: 0x%08x\n",p->CPU.Features);
1119
1120DBG("\n---------------------------------------------\n");
1121#if DEBUG_CPU
1122pause();
1123#endif
1124}
1125

Archive Download this file

Revision: 2647