Chameleon

Chameleon Svn Source Tree

Root/branches/Bungo/i386/libsaio/cpu.c

1/*
2 * Copyright (c) 2000-2006 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*
29 * @OSF_COPYRIGHT@
30 */
31/*
32 * Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
33 * AsereBLN: 2009: cleanup and bugfix
34 */
35
36#include "libsaio.h"
37#include "platform.h"
38#include "cpu.h"
39#include "bootstruct.h"
40#include "boot.h"
41
42#ifndef DEBUG_CPU
43#define DEBUG_CPU 0
44#endif
45
46#if DEBUG_CPU
47#define DBG(x...)printf(x)
48#else
49#define DBG(x...)msglog(x)
50#endif
51
52/*
53 * timeRDTSC()
54 * This routine sets up PIT counter 2 to count down 1/20 of a second.
55 * It pauses until the value is latched in the counter
56 * and then reads the time stamp counter to return to the caller.
57 */
58uint64_t timeRDTSC(void)
59{
60intattempts = 0;
61uint64_t latchTime;
62uint64_tsaveTime,intermediate;
63unsigned int timerValue, lastValue;
64//boolean_tint_enabled;
65/*
66 * Table of correction factors to account for
67 * - timer counter quantization errors, and
68 * - undercounts 0..5
69 */
70#define SAMPLE_CLKS_EXACT(((double) CLKNUM) / 20.0)
71#define SAMPLE_CLKS_INT((int) CLKNUM / 20)
72#define SAMPLE_NSECS(2000000000LL)
73#define SAMPLE_MULTIPLIER(((double)SAMPLE_NSECS)*SAMPLE_CLKS_EXACT)
74#define ROUND64(x)((uint64_t)((x) + 0.5))
75uint64_tscale[6] = {
76ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-0)),
77ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-1)),
78ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-2)),
79ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-3)),
80ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-4)),
81ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-5))
82};
83
84//int_enabled = ml_set_interrupts_enabled(FALSE);
85
86restart:
87if (attempts >= 9) // increase to up to 9 attempts.
88{
89 // This will flash-reboot. TODO: Use tscPanic instead.
90printf("Timestamp counter calibation failed with %d attempts\n", attempts);
91}
92attempts++;
93enable_PIT2();// turn on PIT2
94set_PIT2(0);// reset timer 2 to be zero
95latchTime = rdtsc64();// get the time stamp to time
96latchTime = get_PIT2(&timerValue) - latchTime; // time how long this takes
97set_PIT2(SAMPLE_CLKS_INT);// set up the timer for (almost) 1/20th a second
98saveTime = rdtsc64();// now time how long a 20th a second is...
99get_PIT2(&lastValue);
100get_PIT2(&lastValue);// read twice, first value may be unreliable
101do {
102intermediate = get_PIT2(&timerValue);
103if (timerValue > lastValue)
104{
105// Timer wrapped
106set_PIT2(0);
107disable_PIT2();
108goto restart;
109}
110lastValue = timerValue;
111} while (timerValue > 5);
112printf("timerValue %d\n",timerValue);
113printf("intermediate 0x%016llX\n",intermediate);
114printf("saveTime 0x%016llX\n",saveTime);
115
116intermediate -= saveTime;// raw count for about 1/20 second
117intermediate *= scale[timerValue];// rescale measured time spent
118intermediate /= SAMPLE_NSECS;// so its exactly 1/20 a second
119intermediate += latchTime;// add on our save fudge
120
121set_PIT2(0);// reset timer 2 to be zero
122disable_PIT2();// turn off PIT 2
123
124//ml_set_interrupts_enabled(int_enabled);
125return intermediate;
126}
127
128/*
129 * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
130 */
131static uint64_t measure_tsc_frequency(void)
132{
133uint64_t tscStart;
134uint64_t tscEnd;
135uint64_t tscDelta = 0xffffffffffffffffULL;
136unsigned long pollCount;
137uint64_t retval = 0;
138int i;
139
140/* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
141 * counter 2. We run this loop 3 times to make sure the cache
142 * is hot and we take the minimum delta from all of the runs.
143 * That is to say that we're biased towards measuring the minimum
144 * number of TSC ticks that occur while waiting for the timer to
145 * expire. That theoretically helps avoid inconsistencies when
146 * running under a VM if the TSC is not virtualized and the host
147 * steals time. The TSC is normally virtualized for VMware.
148 */
149for(i = 0; i < 10; ++i)
150{
151enable_PIT2();
152set_PIT2_mode0(CALIBRATE_LATCH);
153tscStart = rdtsc64();
154pollCount = poll_PIT2_gate();
155tscEnd = rdtsc64();
156/* The poll loop must have run at least a few times for accuracy */
157if (pollCount <= 1) {
158continue;
159}
160/* The TSC must increment at LEAST once every millisecond.
161 * We should have waited exactly 30 msec so the TSC delta should
162 * be >= 30. Anything less and the processor is way too slow.
163 */
164if ((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC) {
165continue;
166}
167// tscDelta = MIN(tscDelta, (tscEnd - tscStart))
168if ( (tscEnd - tscStart) < tscDelta ) {
169tscDelta = tscEnd - tscStart;
170}
171}
172/* tscDelta is now the least number of TSC ticks the processor made in
173 * a timespan of 0.03 s (e.g. 30 milliseconds)
174 * Linux thus divides by 30 which gives the answer in kiloHertz because
175 * 1 / ms = kHz. But we're xnu and most of the rest of the code uses
176 * Hz so we need to convert our milliseconds to seconds. Since we're
177 * dividing by the milliseconds, we simply multiply by 1000.
178 */
179
180/* Unlike linux, we're not limited to 32-bit, but we do need to take care
181 * that we're going to multiply by 1000 first so we do need at least some
182 * arithmetic headroom. For now, 32-bit should be enough.
183 * Also unlike Linux, our compiler can do 64-bit integer arithmetic.
184 */
185if (tscDelta > (1ULL<<32)) {
186retval = 0;
187} else {
188retval = tscDelta * 1000 / 30;
189}
190disable_PIT2();
191return retval;
192}
193
194/*
195 * Original comment/code:
196 * "DFE: Measures the Max Performance Frequency in Hz (64-bit)"
197 *
198 * Measures the Actual Performance Frequency in Hz (64-bit)
199 * (just a naming change, mperf --> aperf )
200 */
201static uint64_t measure_aperf_frequency(void)
202{
203uint64_t aperfStart;
204uint64_t aperfEnd;
205uint64_t aperfDelta = 0xffffffffffffffffULL;
206unsigned long pollCount;
207uint64_t retval = 0;
208int i;
209
210/* Time how many APERF ticks elapse in 30 msec using the 8254 PIT
211 * counter 2. We run this loop 3 times to make sure the cache
212 * is hot and we take the minimum delta from all of the runs.
213 * That is to say that we're biased towards measuring the minimum
214 * number of APERF ticks that occur while waiting for the timer to
215 * expire.
216 */
217for(i = 0; i < 10; ++i)
218{
219enable_PIT2();
220set_PIT2_mode0(CALIBRATE_LATCH);
221aperfStart = rdmsr64(MSR_AMD_APERF);
222pollCount = poll_PIT2_gate();
223aperfEnd = rdmsr64(MSR_AMD_APERF);
224/* The poll loop must have run at least a few times for accuracy */
225if (pollCount <= 1)
226{
227continue;
228}
229/* The TSC must increment at LEAST once every millisecond.
230 * We should have waited exactly 30 msec so the APERF delta should
231 * be >= 30. Anything less and the processor is way too slow.
232 */
233if ((aperfEnd - aperfStart) <= CALIBRATE_TIME_MSEC)
234{
235continue;
236}
237// tscDelta = MIN(tscDelta, (tscEnd - tscStart))
238if ( (aperfEnd - aperfStart) < aperfDelta )
239{
240aperfDelta = aperfEnd - aperfStart;
241}
242}
243/* mperfDelta is now the least number of MPERF ticks the processor made in
244 * a timespan of 0.03 s (e.g. 30 milliseconds)
245 */
246
247if (aperfDelta > (1ULL<<32))
248{
249retval = 0;
250}
251else
252{
253retval = aperfDelta * 1000 / 30;
254}
255disable_PIT2();
256return retval;
257}
258
259/*
260 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
261 * - multi. is read from a specific MSR. In the case of Intel, there is:
262 * a max multi. (used to calculate the FSB freq.),
263 * and a current multi. (used to calculate the CPU freq.)
264 * - fsbFrequency = tscFrequency / multi
265 * - cpuFrequency = fsbFrequency * multi
266 */
267void scan_cpu(PlatformInfo_t *p)
268{
269uint64_ttscFrequency = 0;
270uint64_tfsbFrequency = 0;
271uint64_tcpuFrequency = 0;
272uint64_tmsr = 0;
273uint64_tflex_ratio = 0;
274
275uint32_tmax_ratio = 0;
276uint32_tmin_ratio = 0;
277uint32_treg[4];
278uint32_tcores_per_package = 0;
279uint32_tlogical_per_package = 1;
280uint32_tthreads_per_core = 1;;
281
282uint8_tbus_ratio_max = 0;
283uint8_tbus_ratio_min = 0;
284uint8_tcurrdiv = 0;
285uint8_tcurrcoef = 0;
286uint8_tmaxdiv = 0;
287uint8_tmaxcoef = 0;
288
289const char*newratio;
290charstr[128];
291char*s = 0;
292
293intlen = 0;
294intmyfsb = 0;
295inti = 0;
296
297/* get cpuid values */
298do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]); // MaxFn, Vendor
299p->CPU.Vendor = p->CPU.CPUID[CPUID_0][ebx];
300
301do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]); // Signature, stepping, features
302
303if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && ((bit(28) & p->CPU.CPUID[CPUID_1][edx]) != 0)) // Intel && HTT/Multicore
304{
305logical_per_package = bitfield(p->CPU.CPUID[CPUID_1][ebx], 23, 16);
306}
307
308do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]); // TLB/Cache/Prefetch
309
310do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]); // S/N
311
312/* Based on Apple's XNU cpuid.c - Deterministic cache parameters */
313if ((p->CPU.CPUID[CPUID_0][eax] > 3) && (p->CPU.CPUID[CPUID_0][eax] < 0x80000000))
314{
315for (i = 0; i < 0xFF; i++) // safe loop
316{
317do_cpuid2(0x00000004, i, reg); // AX=4: Fn, CX=i: cache index
318if (bitfield(reg[eax], 4, 0) == 0)
319{
320break;
321}
322//cores_per_package = bitfield(reg[eax], 31, 26) + 1;
323}
324}
325do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);
326if (i > 0)
327{
328cores_per_package = bitfield(p->CPU.CPUID[CPUID_4][eax], 31, 26) + 1; // i = cache index
329threads_per_core = bitfield(p->CPU.CPUID[CPUID_4][eax], 25, 14) + 1;
330}
331
332if (cores_per_package == 0) cores_per_package = 1;
333
334if (p->CPU.CPUID[CPUID_0][0] >= 0x5) // Monitor/Mwait
335{
336do_cpuid(5, p->CPU.CPUID[CPUID_5]);
337}
338if (p->CPU.CPUID[CPUID_0][0] >= 6) // Thermal/Power
339{
340do_cpuid(6, p->CPU.CPUID[CPUID_6]);
341}
342
343do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);
344if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8)
345{
346do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);
347do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
348}
349else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1)
350{
351do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);
352}
353
354/*
355 EAX (Intel):
356 31 28 27 20 19 16 1514 1312 11 8 7 4 3 0
357 +--------+----------------+--------+----+----+--------+--------+--------+
358 |########|Extended family |Extmodel|####|type|familyid| model |stepping|
359 +--------+----------------+--------+----+----+--------+--------+--------+
360
361 EAX (AMD):
362 31 28 27 20 19 16 1514 1312 11 8 7 4 3 0
363 +--------+----------------+--------+----+----+--------+--------+--------+
364 |########|Extended family |Extmodel|####|####|familyid| model |stepping|
365 +--------+----------------+--------+----+----+--------+--------+--------+
366*/
367p->CPU.Signature= p->CPU.CPUID[CPUID_1][0];
368// stepping = cpu_feat_eax & 0xF;
369p->CPU.Stepping= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);
370// model = (cpu_feat_eax >> 4) & 0xF;
371p->CPU.Model= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);
372// family = (cpu_feat_eax >> 8) & 0xF;
373p->CPU.Family= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);
374// type = (cpu_feat_eax >> 12) & 0x3;
375//p->CPU.Type= bitfield(p->CPU.CPUID[CPUID_1][0], 13, 12);
376// ext_model = (cpu_feat_eax >> 16) & 0xF;
377p->CPU.ExtModel= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);
378// ext_family = (cpu_feat_eax >> 20) & 0xFF;
379p->CPU.ExtFamily= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);
380/*
381if (p->CPU.Family == 0x0f)
382{
383p->CPU.Family += p->CPU.ExtFamily;
384}
385
386if (p->CPU.Family == 0x0f || p->CPU.Family == 0x06)
387*/
388p->CPU.Model += (p->CPU.ExtModel << 4);
389
390/* get BrandString (if supported) */
391/* Copyright: from Apple's XNU cpuid.c */
392if (p->CPU.CPUID[CPUID_80][0] > 0x80000004)
393{
394bzero(str, 128);
395/*
396 * The brand string 48 bytes (max), guaranteed to
397 * be NULL terminated.
398 */
399do_cpuid(0x80000002, reg);
400memcpy(&str[0], (char *)reg, 16);
401do_cpuid(0x80000003, reg);
402memcpy(&str[16], (char *)reg, 16);
403do_cpuid(0x80000004, reg);
404memcpy(&str[32], (char *)reg, 16);
405for (s = str; *s != '\0'; s++)
406{
407if (*s != ' ')
408{
409break;
410}
411}
412strlcpy(p->CPU.BrandString, s, 48);
413
414if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), (unsigned)strlen(CPU_STRING_UNKNOWN) + 1)))
415{
416/*
417 * This string means we have a firmware-programmable brand string,
418 * and the firmware couldn't figure out what sort of CPU we have.
419 */
420p->CPU.BrandString[0] = '\0';
421}
422p->CPU.BrandString[47] = '\0';
423 //verbose("Brandstring = %s\n", p->CPU.BrandString);
424}
425
426/*
427 * Find the number of enabled cores and threads
428 * (which determines whether SMT/Hyperthreading is active).
429 */
430switch (p->CPU.Vendor)
431{
432case CPUID_VENDOR_INTEL:
433switch (p->CPU.Model)
434{
435case CPUID_MODEL_NEHALEM:
436case CPUID_MODEL_FIELDS:
437case CPUID_MODEL_DALES:
438case CPUID_MODEL_NEHALEM_EX:
439case CPUID_MODEL_JAKETOWN:
440case CPUID_MODEL_SANDYBRIDGE:
441case CPUID_MODEL_IVYBRIDGE:
442case CPUID_MODEL_IVYBRIDGE_EP:
443case CPUID_MODEL_HASWELL:
444case CPUID_MODEL_HASWELL_SVR:
445//case CPUID_MODEL_HASWELL_H:
446case CPUID_MODEL_HASWELL_ULT:
447case CPUID_MODEL_CRYSTALWELL:
448msr = rdmsr64(MSR_CORE_THREAD_COUNT);
449p->CPU.NoCores= (uint32_t)bitfield((uint32_t)msr, 31, 16);
450p->CPU.NoThreads= (uint32_t)bitfield((uint32_t)msr, 15, 0);
451break;
452
453case CPUID_MODEL_DALES_32NM:
454case CPUID_MODEL_WESTMERE:
455case CPUID_MODEL_WESTMERE_EX:
456msr = rdmsr64(MSR_CORE_THREAD_COUNT);
457p->CPU.NoCores= (uint32_t)bitfield((uint32_t)msr, 19, 16);
458p->CPU.NoThreads= (uint32_t)bitfield((uint32_t)msr, 15, 0);
459break;
460}
461
462if (p->CPU.NoCores == 0)
463{
464p->CPU.NoCores = cores_per_package;
465p->CPU.NoThreads = logical_per_package;
466}
467 break;
468
469case CPUID_VENDOR_AMD:
470p->CPU.NoCores= (uint32_t)bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;
471p->CPU.NoThreads= (uint32_t)bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);
472if (p->CPU.NoCores == 0)
473p->CPU.NoCores = 1;
474if (p->CPU.NoThreads < p->CPU.NoCores)
475p->CPU.NoThreads = p->CPU.NoCores;
476break;
477
478default:
479stop("Unsupported CPU detected! System halted.");
480}
481
482//workaround for N270. I don't know why it detected wrong
483// MSR is *NOT* available on the Intel Atom CPU
484if ((p->CPU.Model == CPUID_MODEL_ATOM) && (strstr(p->CPU.BrandString, "270")))
485{
486p->CPU.NoCores= 1;
487p->CPU.NoThreads= 2;
488}
489
490/* setup features */
491if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0)
492{
493p->CPU.Features |= CPU_FEATURE_MMX;
494}
495
496if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0)
497{
498p->CPU.Features |= CPU_FEATURE_SSE;
499}
500
501if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0)
502{
503p->CPU.Features |= CPU_FEATURE_SSE2;
504}
505
506if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0)
507{
508p->CPU.Features |= CPU_FEATURE_SSE3;
509}
510
511if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0)
512{
513p->CPU.Features |= CPU_FEATURE_SSE41;
514}
515
516if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0)
517{
518p->CPU.Features |= CPU_FEATURE_SSE42;
519}
520
521if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0)
522{
523p->CPU.Features |= CPU_FEATURE_EM64T;
524}
525
526if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0)
527{
528p->CPU.Features |= CPU_FEATURE_MSR;
529}
530
531if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && (p->CPU.NoThreads > p->CPU.NoCores))
532{
533p->CPU.Features |= CPU_FEATURE_HTT;
534}
535
536tscFrequency = measure_tsc_frequency();
537//verbose("cpu freq classic = 0x%016llx\n", tscFrequency);
538
539/* if usual method failed */
540if ( tscFrequency < 1000 )//TEST
541{
542tscFrequency = timeRDTSC() * 20;//measure_tsc_frequency();
543//verbose("cpu freq timeRDTSC = 0x%016llx\n", tscFrequency);
544}
545else
546{
547// verbose("cpu freq timeRDTSC = 0x%016llxn", timeRDTSC() * 20);
548}
549
550fsbFrequency = 0;
551cpuFrequency = 0;
552
553if (p->CPU.Vendor == CPUID_VENDOR_INTEL && ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)))
554{
555int intelCPU = p->CPU.Model;
556if (p->CPU.Family == 0x06)
557{
558/* Nehalem CPU model */
559switch (p->CPU.Model)
560{
561case CPUID_MODEL_NEHALEM:
562case CPUID_MODEL_FIELDS:
563case CPUID_MODEL_DALES:
564case CPUID_MODEL_DALES_32NM:
565case CPUID_MODEL_WESTMERE:
566case CPUID_MODEL_NEHALEM_EX:
567case CPUID_MODEL_WESTMERE_EX:
568/* --------------------------------------------------------- */
569case CPUID_MODEL_SANDYBRIDGE:
570case CPUID_MODEL_JAKETOWN:
571case CPUID_MODEL_IVYBRIDGE_EP:
572case CPUID_MODEL_IVYBRIDGE:
573case CPUID_MODEL_HASWELL:
574case CPUID_MODEL_HASWELL_SVR:
575
576case CPUID_MODEL_HASWELL_ULT:
577case CPUID_MODEL_CRYSTALWELL:
578/* --------------------------------------------------------- */
579msr = rdmsr64(MSR_PLATFORM_INFO);
580//verbose("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));
581bus_ratio_max = bitfield(msr, 15, 8);
582bus_ratio_min = bitfield(msr, 47, 40); //valv: not sure about this one (Remarq.1)
583msr = rdmsr64(MSR_FLEX_RATIO);
584//verbose("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));
585if (bitfield(msr, 16, 16))
586{
587flex_ratio = bitfield(msr, 15, 8);
588
589// bcc9: at least on the gigabyte h67ma-ud2h,
590// where the cpu multipler can't be changed to
591// allow overclocking, the flex_ratio msr has unexpected (to OSX)
592// contents.These contents cause mach_kernel to
593// fail to compute the bus ratio correctly, instead
594// causing the system to crash since tscGranularity
595// is inadvertently set to 0.
596if (flex_ratio == 0)
597{
598// Clear bit 16 (evidently the presence bit)
599wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
600msr = rdmsr64(MSR_FLEX_RATIO);
601verbose("CPU: Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));
602}
603else
604{
605if (bus_ratio_max > flex_ratio)
606{
607bus_ratio_max = flex_ratio;
608}
609}
610}
611
612if (bus_ratio_max)
613{
614fsbFrequency = (tscFrequency / bus_ratio_max);
615}
616
617//valv: Turbo Ratio Limit
618if ((intelCPU != 0x2e) && (intelCPU != 0x2f))
619{
620msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
621
622cpuFrequency = bus_ratio_max * fsbFrequency;
623max_ratio = bus_ratio_max * 10;
624}
625else
626{
627cpuFrequency = tscFrequency;
628}
629if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4))
630{
631max_ratio = atoi(newratio);
632max_ratio = (max_ratio * 10);
633if (len >= 3)
634{
635max_ratio = (max_ratio + 5);
636}
637
638//verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);
639
640// extreme overclockers may love 320 ;)
641if ((max_ratio >= min_ratio) && (max_ratio <= 320))
642{
643cpuFrequency = (fsbFrequency * max_ratio) / 10;
644if (len >= 3)
645{
646maxdiv = 1;
647}
648else
649{
650maxdiv = 0;
651}
652}
653else
654{
655max_ratio = (bus_ratio_max * 10);
656}
657}
658//valv: to be uncommented if Remarq.1 didn't stick
659//if (bus_ratio_max > 0) bus_ratio = flex_ratio;
660p->CPU.MaxRatio = max_ratio;
661p->CPU.MinRatio = min_ratio;
662
663myfsb = fsbFrequency / 1000000;
664//verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio/10); // Bungo: fixed wrong Bus-Ratio readout
665currcoef = bus_ratio_max;
666
667break;
668
669default:
670msr = rdmsr64(MSR_IA32_PERF_STATUS);
671//verbose("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));
672currcoef = bitfield(msr, 12, 8); // Bungo: reverted to 2263 state because of wrong old CPUs freq. calculating
673// Non-integer bus ratio for the max-multi
674maxdiv = bitfield(msr, 46, 46);
675// Non-integer bus ratio for the current-multi (undocumented)
676currdiv = bitfield(msr, 14, 14);
677
678// This will always be model >= 3
679if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f))
680{
681/* On these models, maxcoef defines TSC freq */
682maxcoef = bitfield(msr, 44, 40);
683}
684else
685{
686// On lower models, currcoef defines TSC freq
687// XXX
688maxcoef = currcoef;
689}
690
691if (!currcoef)
692{
693currcoef = maxcoef;
694}
695
696if (maxcoef)
697{
698if (maxdiv)
699{
700fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
701}
702else
703{
704fsbFrequency = (tscFrequency / maxcoef);
705}
706
707if (currdiv)
708{
709cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
710}
711else
712{
713cpuFrequency = (fsbFrequency * currcoef);
714}
715//verbose("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
716}
717break;
718}
719}
720// Mobile CPU
721if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28))
722{
723p->CPU.Features |= CPU_FEATURE_MOBILE;
724}
725}
726else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f))
727{
728switch(p->CPU.ExtFamily)
729{
730case 0x00: //* K8 *//
731msr = rdmsr64(K8_FIDVID_STATUS);
732maxcoef = bitfield(msr, 21, 16) / 2 + 4;
733currcoef = bitfield(msr, 5, 0) / 2 + 4;
734break;
735
736case 0x01: //* K10 *//
737msr = rdmsr64(K10_COFVID_STATUS);
738do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);
739// EffFreq: effective frequency interface
740if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1)
741{
742//uint64_t mperf = measure_mperf_frequency();
743uint64_t aperf = measure_aperf_frequency();
744cpuFrequency = aperf;
745}
746// NOTE: tsc runs at the maccoeff (non turbo)
747//*not* at the turbo frequency.
748maxcoef = bitfield(msr, 54, 49) / 2 + 4;
749currcoef = bitfield(msr, 5, 0) + 0x10;
750currdiv = 2 << bitfield(msr, 8, 6);
751
752break;
753
754case 0x05: //* K14 *//
755msr = rdmsr64(K10_COFVID_STATUS);
756currcoef = (bitfield(msr, 54, 49) + 0x10) << 2;
757currdiv = (bitfield(msr, 8, 4) + 1) << 2;
758currdiv += bitfield(msr, 3, 0);
759
760break;
761
762case 0x02: //* K11 *//
763// not implimented
764break;
765}
766
767if (maxcoef)
768{
769if (currdiv)
770{
771if (!currcoef)
772{
773currcoef = maxcoef;
774}
775
776if (!cpuFrequency)
777{
778fsbFrequency = ((tscFrequency * currdiv) / currcoef);
779}
780else
781{
782fsbFrequency = ((cpuFrequency * currdiv) / currcoef);
783}
784//verbose("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
785}
786else
787{
788if (!cpuFrequency)
789{
790fsbFrequency = (tscFrequency / maxcoef);
791}
792else
793{
794fsbFrequency = (cpuFrequency / maxcoef);
795}
796//verbose("%d\n", currcoef);
797}
798}
799else if (currcoef)
800{
801if (currdiv)
802{
803fsbFrequency = ((tscFrequency * currdiv) / currcoef);
804//verbose("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);
805}
806else
807{
808fsbFrequency = (tscFrequency / currcoef);
809//verbose("%d\n", currcoef);
810}
811}
812if (!cpuFrequency) cpuFrequency = tscFrequency;
813}
814
815#if 0
816if (!fsbFrequency)
817{
818fsbFrequency = (DEFAULT_FSB * 1000);
819verbose("CPU: fsbFrequency=0! using the default value for FSB!\n");
820cpuFrequency = tscFrequency;
821}
822
823//verbose("cpu freq = 0x%016llxn", timeRDTSC() * 20);
824
825#endif
826
827p->CPU.MaxCoef = maxcoef;
828p->CPU.MaxDiv = maxdiv;
829p->CPU.CurrCoef = currcoef;
830p->CPU.CurrDiv = currdiv;
831p->CPU.TSCFrequency = tscFrequency;
832p->CPU.FSBFrequency = fsbFrequency;
833p->CPU.CPUFrequency = cpuFrequency;
834
835// keep formatted with spaces instead of tabs
836//verbose("\n---------------------------------------------\n");
837 verbose("\n------------------ CPU INFO -----------------\n");
838//verbose("---------------------------------------------\n");
839verbose("\nCPUID Raw Values:\n");
840for (i = 0; i < CPUID_MAX; i++)
841{
842verbose("%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]);
843}
844verbose("\n");
845verbose("Brand String: %s\n",p->CPU.BrandString);// Processor name (BIOS)
846verbose("Vendor: 0x%X\n",p->CPU.Vendor);// Vendor ex: GenuineIntel
847verbose("Family: 0x%X\n",p->CPU.Family);// Family ex: 6 (06h)
848verbose("ExtFamily: 0x%X\n",p->CPU.ExtFamily);
849verbose("Signature: 0x%08X\n",p->CPU.Signature);// CPUID signature
850verbose("Model: 0x%X\n",p->CPU.Model);// Model ex: 37 (025h)
851verbose("ExtModel: 0x%X\n",p->CPU.ExtModel);
852verbose("Stepping: 0x%X\n",p->CPU.Stepping);// Stepping ex: 5 (05h)
853verbose("MaxCoef: %d\n",p->CPU.MaxCoef);
854verbose("CurrCoef: %d\n",p->CPU.CurrCoef);
855verbose("MaxDiv: %d\n",p->CPU.MaxDiv);
856verbose("CurrDiv: %d\n",p->CPU.CurrDiv);
857verbose("TSCFreq: %dMHz\n",p->CPU.TSCFrequency / 1000000);
858verbose("FSBFreq: %dMHz\n",p->CPU.FSBFrequency / 1000000);
859verbose("CPUFreq: %dMHz\n",p->CPU.CPUFrequency / 1000000);
860verbose("Cores: %d\n",p->CPU.NoCores);// Cores
861verbose("Logical procesors: %d\n",p->CPU.NoThreads);// Threads
862verbose("Features: 0x%08x\n",p->CPU.Features);
863
864verbose("---------------------------------------------\n\n");
865#if DEBUG_CPU
866pause("\n[DEBUG CPU] ");
867#endif
868}
869

Archive Download this file

Revision: 2839