Root/
Source at commit 2381 created 10 years 21 days ago. By ifabio, Apply patch: (Credits to Thomas Jansen aka tja) - Reading options from all devices during boot. The options for the boot menu are only read from the devices rd(0,0) or bt(0,0). Consequently, boot menu options (e.g. "Quiet Boot", "Timeout", etc.) in plists on other devices (like most users have) are ignored. This patch extends the list of paths to search for the options plist on all devices that can be found. | |
---|---|
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...)␉␉msglog(x)␊ |
20 | #endif␊ |
21 | ␊ |
22 | /*␊ |
23 | * timeRDTSC()␊ |
24 | * This routine sets up PIT counter 2 to count down 1/20 of a second.␊ |
25 | * It pauses until the value is latched in the counter␊ |
26 | * and then reads the time stamp counter to return to the caller.␊ |
27 | */␊ |
28 | uint64_t timeRDTSC(void)␊ |
29 | {␊ |
30 | int␉␉attempts = 0;␊ |
31 | uint64_t latchTime;␊ |
32 | uint64_t␉saveTime,intermediate;␊ |
33 | unsigned int timerValue, lastValue;␊ |
34 | //boolean_t␉int_enabled;␊ |
35 | /*␊ |
36 | * Table of correction factors to account for␊ |
37 | *␉ - timer counter quantization errors, and␊ |
38 | *␉ - undercounts 0..5␊ |
39 | */␊ |
40 | #define SAMPLE_CLKS_EXACT␉(((double) CLKNUM) / 20.0)␊ |
41 | #define SAMPLE_CLKS_INT␉␉((int) CLKNUM / 20)␊ |
42 | #define SAMPLE_NSECS␉␉(2000000000LL)␊ |
43 | #define SAMPLE_MULTIPLIER␉(((double)SAMPLE_NSECS)*SAMPLE_CLKS_EXACT)␊ |
44 | #define ROUND64(x)␉␉((uint64_t)((x) + 0.5))␊ |
45 | uint64_t␉scale[6] = {␊ |
46 | ␉␉ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-0)), ␊ |
47 | ␉␉ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-1)), ␊ |
48 | ␉␉ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-2)), ␊ |
49 | ␉␉ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-3)), ␊ |
50 | ␉␉ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-4)), ␊ |
51 | ␉␉ROUND64(SAMPLE_MULTIPLIER/(double)(SAMPLE_CLKS_INT-5))␊ |
52 | };␊ |
53 | ␊ |
54 | restart:␊ |
55 | if (attempts >= 9) // increase to up to 9 attempts.␊ |
56 | // This will flash-reboot. TODO: Use tscPanic instead.␊ |
57 | printf("Timestamp counter calibation failed with %d attempts\n", attempts);␊ |
58 | attempts++;␊ |
59 | enable_PIT2();␉␉// turn on PIT2␊ |
60 | set_PIT2(0);␉␉// reset timer 2 to be zero␊ |
61 | latchTime = rdtsc64();␉// get the time stamp to time ␊ |
62 | latchTime = get_PIT2(&timerValue) - latchTime; // time how long this takes␊ |
63 | set_PIT2(SAMPLE_CLKS_INT);␉// set up the timer for (almost) 1/20th a second␊ |
64 | saveTime = rdtsc64();␉// now time how long a 20th a second is...␊ |
65 | get_PIT2(&lastValue);␊ |
66 | get_PIT2(&lastValue);␉// read twice, first value may be unreliable␊ |
67 | do {␊ |
68 | ␉␉intermediate = get_PIT2(&timerValue);␊ |
69 | ␉␉if (timerValue > lastValue) {␊ |
70 | ␉␉␉// Timer wrapped␊ |
71 | ␉␉␉set_PIT2(0);␊ |
72 | ␉␉␉disable_PIT2();␊ |
73 | ␉␉␉goto restart;␊ |
74 | ␉␉}␊ |
75 | ␉␉lastValue = timerValue;␊ |
76 | } while (timerValue > 5);␊ |
77 | printf("timerValue␉ %d\n",timerValue);␊ |
78 | printf("intermediate 0x%016llx\n",intermediate);␊ |
79 | printf("saveTime␉ 0x%016llx\n",saveTime);␊ |
80 | ␊ |
81 | intermediate -= saveTime;␉␉// raw count for about 1/20 second␊ |
82 | intermediate *= scale[timerValue];␉// rescale measured time spent␊ |
83 | intermediate /= SAMPLE_NSECS;␉// so its exactly 1/20 a second␊ |
84 | intermediate += latchTime;␉␉// add on our save fudge␊ |
85 | ␊ |
86 | set_PIT2(0);␉␉␉// reset timer 2 to be zero␊ |
87 | disable_PIT2();␉␉␉// turn off PIT 2␊ |
88 | ␉␊ |
89 | return intermediate;␊ |
90 | }␊ |
91 | ␊ |
92 | /*␊ |
93 | * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer␊ |
94 | */␊ |
95 | static uint64_t measure_tsc_frequency(void)␊ |
96 | {␊ |
97 | ␉uint64_t tscStart;␊ |
98 | ␉uint64_t tscEnd;␊ |
99 | ␉uint64_t tscDelta = 0xffffffffffffffffULL;␊ |
100 | ␉unsigned long pollCount;␊ |
101 | ␉uint64_t retval = 0;␊ |
102 | ␉int i;␊ |
103 | ␉␊ |
104 | ␉/* Time how many TSC ticks elapse in 30 msec using the 8254 PIT␊ |
105 | ␉ * counter 2. We run this loop 3 times to make sure the cache␊ |
106 | ␉ * is hot and we take the minimum delta from all of the runs.␊ |
107 | ␉ * That is to say that we're biased towards measuring the minimum␊ |
108 | ␉ * number of TSC ticks that occur while waiting for the timer to␊ |
109 | ␉ * expire. That theoretically helps avoid inconsistencies when␊ |
110 | ␉ * running under a VM if the TSC is not virtualized and the host␊ |
111 | ␉ * steals time.␉ The TSC is normally virtualized for VMware.␊ |
112 | ␉ */␊ |
113 | ␉for(i = 0; i < 10; ++i)␊ |
114 | ␉{␊ |
115 | ␉␉enable_PIT2();␊ |
116 | ␉␉set_PIT2_mode0(CALIBRATE_LATCH);␊ |
117 | ␉␉tscStart = rdtsc64();␊ |
118 | ␉␉pollCount = poll_PIT2_gate();␊ |
119 | ␉␉tscEnd = rdtsc64();␊ |
120 | ␉␉/* The poll loop must have run at least a few times for accuracy */␊ |
121 | ␉␉if (pollCount <= 1)␊ |
122 | ␉␉␉continue;␊ |
123 | ␉␉/* The TSC must increment at LEAST once every millisecond.␊ |
124 | ␉␉ * We should have waited exactly 30 msec so the TSC delta should␊ |
125 | ␉␉ * be >= 30. Anything less and the processor is way too slow.␊ |
126 | ␉␉ */␊ |
127 | ␉␉if ((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)␊ |
128 | ␉␉␉continue;␊ |
129 | ␉␉// tscDelta = MIN(tscDelta, (tscEnd - tscStart))␊ |
130 | ␉␉if ( (tscEnd - tscStart) < tscDelta )␊ |
131 | ␉␉␉tscDelta = tscEnd - tscStart;␊ |
132 | ␉}␊ |
133 | ␉/* tscDelta is now the least number of TSC ticks the processor made in␊ |
134 | ␉ * a timespan of 0.03 s (e.g. 30 milliseconds)␊ |
135 | ␉ * Linux thus divides by 30 which gives the answer in kiloHertz because␊ |
136 | ␉ * 1 / ms = kHz. But we're xnu and most of the rest of the code uses␊ |
137 | ␉ * Hz so we need to convert our milliseconds to seconds. Since we're␊ |
138 | ␉ * dividing by the milliseconds, we simply multiply by 1000.␊ |
139 | ␉ */␊ |
140 | ␉␊ |
141 | ␉/* Unlike linux, we're not limited to 32-bit, but we do need to take care␊ |
142 | ␉ * that we're going to multiply by 1000 first so we do need at least some␊ |
143 | ␉ * arithmetic headroom. For now, 32-bit should be enough.␊ |
144 | ␉ * Also unlike Linux, our compiler can do 64-bit integer arithmetic.␊ |
145 | ␉ */␊ |
146 | ␉if (tscDelta > (1ULL<<32))␊ |
147 | ␉␉retval = 0;␊ |
148 | ␉else␊ |
149 | ␉{␊ |
150 | ␉␉retval = tscDelta * 1000 / 30;␊ |
151 | ␉}␊ |
152 | ␉disable_PIT2();␊ |
153 | ␉return retval;␊ |
154 | }␊ |
155 | ␊ |
156 | /*␊ |
157 | * Original comment/code:␊ |
158 | * "DFE: Measures the Max Performance Frequency in Hz (64-bit)"␊ |
159 | *␊ |
160 | * Measures the Actual Performance Frequency in Hz (64-bit)␊ |
161 | * (just a naming change, mperf --> aperf )␊ |
162 | */␊ |
163 | static uint64_t measure_aperf_frequency(void)␊ |
164 | {␊ |
165 | ␉uint64_t aperfStart;␊ |
166 | ␉uint64_t aperfEnd;␊ |
167 | ␉uint64_t aperfDelta = 0xffffffffffffffffULL;␊ |
168 | ␉unsigned long pollCount;␊ |
169 | ␉uint64_t retval = 0;␊ |
170 | ␉int i;␊ |
171 | ␉␊ |
172 | ␉/* Time how many APERF ticks elapse in 30 msec using the 8254 PIT␊ |
173 | ␉ * counter 2. We run this loop 3 times to make sure the cache␊ |
174 | ␉ * is hot and we take the minimum delta from all of the runs.␊ |
175 | ␉ * That is to say that we're biased towards measuring the minimum␊ |
176 | ␉ * number of APERF ticks that occur while waiting for the timer to␊ |
177 | ␉ * expire.␊ |
178 | ␉ */␊ |
179 | ␉for(i = 0; i < 10; ++i)␊ |
180 | ␉{␊ |
181 | ␉␉enable_PIT2();␊ |
182 | ␉␉set_PIT2_mode0(CALIBRATE_LATCH);␊ |
183 | ␉␉aperfStart = rdmsr64(MSR_AMD_APERF);␊ |
184 | ␉␉pollCount = poll_PIT2_gate();␊ |
185 | ␉␉aperfEnd = rdmsr64(MSR_AMD_APERF);␊ |
186 | ␉␉/* The poll loop must have run at least a few times for accuracy */␊ |
187 | ␉␉if (pollCount <= 1)␊ |
188 | ␉␉␉continue;␊ |
189 | ␉␉/* The TSC must increment at LEAST once every millisecond.␊ |
190 | ␉␉ * We should have waited exactly 30 msec so the APERF delta should␊ |
191 | ␉␉ * be >= 30. Anything less and the processor is way too slow.␊ |
192 | ␉␉ */␊ |
193 | ␉␉if ((aperfEnd - aperfStart) <= CALIBRATE_TIME_MSEC)␊ |
194 | ␉␉␉continue;␊ |
195 | ␉␉// tscDelta = MIN(tscDelta, (tscEnd - tscStart))␊ |
196 | ␉␉if ( (aperfEnd - aperfStart) < aperfDelta )␊ |
197 | ␉␉␉aperfDelta = aperfEnd - aperfStart;␊ |
198 | ␉}␊ |
199 | ␉/* mperfDelta is now the least number of MPERF ticks the processor made in␊ |
200 | ␉ * a timespan of 0.03 s (e.g. 30 milliseconds)␊ |
201 | ␉ */␊ |
202 | ␉␊ |
203 | ␉if (aperfDelta > (1ULL<<32))␊ |
204 | ␉␉retval = 0;␊ |
205 | ␉else␊ |
206 | ␉{␊ |
207 | ␉␉retval = aperfDelta * 1000 / 30;␊ |
208 | ␉}␊ |
209 | ␉disable_PIT2();␊ |
210 | ␉return retval;␊ |
211 | }␊ |
212 | ␊ |
213 | /*␊ |
214 | * Calculates the FSB and CPU frequencies using specific MSRs for each CPU␊ |
215 | * - multi. is read from a specific MSR. In the case of Intel, there is:␊ |
216 | *␉ a max multi. (used to calculate the FSB freq.),␊ |
217 | *␉ and a current multi. (used to calculate the CPU freq.)␊ |
218 | * - fsbFrequency = tscFrequency / multi␊ |
219 | * - cpuFrequency = fsbFrequency * multi␊ |
220 | */␊ |
221 | void scan_cpu(PlatformInfo_t *p)␊ |
222 | {␊ |
223 | ␉uint64_t␉tscFrequency, fsbFrequency, cpuFrequency;␊ |
224 | ␉uint64_t␉msr, flex_ratio;␊ |
225 | ␉uint8_t␉␉maxcoef, maxdiv, currcoef, bus_ratio_max, currdiv;␊ |
226 | ␉const char␉*newratio;␊ |
227 | ␉int␉␉␉len, myfsb;␊ |
228 | ␉uint8_t␉␉bus_ratio_min;␊ |
229 | ␉uint32_t␉max_ratio, min_ratio;␊ |
230 | ␉␊ |
231 | ␉max_ratio = min_ratio = myfsb = bus_ratio_min = 0;␊ |
232 | ␉maxcoef = maxdiv = bus_ratio_max = currcoef = currdiv = 0;␊ |
233 | ␉␊ |
234 | ␉/* get cpuid values */␊ |
235 | ␉do_cpuid(0x00000000, p->CPU.CPUID[CPUID_0]);␊ |
236 | ␉do_cpuid(0x00000001, p->CPU.CPUID[CPUID_1]);␊ |
237 | ␉do_cpuid(0x00000002, p->CPU.CPUID[CPUID_2]);␊ |
238 | ␉do_cpuid(0x00000003, p->CPU.CPUID[CPUID_3]);␊ |
239 | ␉do_cpuid2(0x00000004, 0, p->CPU.CPUID[CPUID_4]);␊ |
240 | ␉do_cpuid(0x80000000, p->CPU.CPUID[CPUID_80]);␊ |
241 | ␉if (p->CPU.CPUID[CPUID_0][0] >= 0x5) {␉␉␊ |
242 | ␉␉do_cpuid(5, p->CPU.CPUID[CPUID_5]); ␉␊ |
243 | ␉}␉␊ |
244 | ␉if (p->CPU.CPUID[CPUID_0][0] >= 6) {␊ |
245 | ␉␉do_cpuid(6, p->CPU.CPUID[CPUID_6]);␉␉␊ |
246 | ␉}␊ |
247 | ␉if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 8) {␊ |
248 | ␉␉do_cpuid(0x80000008, p->CPU.CPUID[CPUID_88]);␊ |
249 | ␉␉do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);␊ |
250 | ␉}␊ |
251 | ␉else if ((p->CPU.CPUID[CPUID_80][0] & 0x0000000f) >= 1) {␊ |
252 | ␉␉do_cpuid(0x80000001, p->CPU.CPUID[CPUID_81]);␊ |
253 | ␉}␊ |
254 | ␉␊ |
255 | #if DEBUG_CPU␊ |
256 | ␉{␊ |
257 | ␉␉int␉␉i;␊ |
258 | ␉␉printf("CPUID Raw Values:\n");␊ |
259 | ␉␉for (i=0; i<CPUID_MAX; i++) {␊ |
260 | ␉␉␉printf("%02d: %08x-%08x-%08x-%08x\n", i,␊ |
261 | ␉␉␉␉ p->CPU.CPUID[i][0], p->CPU.CPUID[i][1],␊ |
262 | ␉␉␉␉ p->CPU.CPUID[i][2], p->CPU.CPUID[i][3]);␊ |
263 | ␉␉}␊ |
264 | ␉}␊ |
265 | #endif␊ |
266 | ␉␊ |
267 | ␉p->CPU.Vendor␉␉= p->CPU.CPUID[CPUID_0][1];␊ |
268 | ␉p->CPU.Signature␉= p->CPU.CPUID[CPUID_1][0];␊ |
269 | ␉p->CPU.Stepping␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 3, 0);␊ |
270 | ␉p->CPU.Model␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 7, 4);␊ |
271 | ␉p->CPU.Family␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 11, 8);␊ |
272 | ␉p->CPU.ExtModel␉␉= bitfield(p->CPU.CPUID[CPUID_1][0], 19, 16);␊ |
273 | ␉p->CPU.ExtFamily␉= bitfield(p->CPU.CPUID[CPUID_1][0], 27, 20);␊ |
274 | ␉␊ |
275 | ␉p->CPU.Model += (p->CPU.ExtModel << 4);␊ |
276 | ␉␊ |
277 | ␉if (p->CPU.Vendor == CPUID_VENDOR_INTEL &&␊ |
278 | ␉␉p->CPU.Family == 0x06 &&␊ |
279 | ␉␉p->CPU.Model >= CPUID_MODEL_NEHALEM &&␊ |
280 | ␉␉p->CPU.Model != CPUID_MODEL_ATOM␉␉// MSR is *NOT* available on the Intel Atom CPU␊ |
281 | ␉␉)␊ |
282 | ␉{␊ |
283 | ␉␉msr = rdmsr64(MSR_CORE_THREAD_COUNT);␉␉␉␉␉// Undocumented MSR in Nehalem and newer CPUs␊ |
284 | ␉␉p->CPU.NoCores␉␉= bitfield((uint32_t)msr, 31, 16);␉// Using undocumented MSR to get actual values␊ |
285 | ␉␉p->CPU.NoThreads␉= bitfield((uint32_t)msr, 15, 0);␉// Using undocumented MSR to get actual values␊ |
286 | ␉}␊ |
287 | ␉else if (p->CPU.Vendor == CPUID_VENDOR_AMD)␊ |
288 | ␉{␊ |
289 | ␉␉p->CPU.NoThreads␉= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);␊ |
290 | ␉␉p->CPU.NoCores␉␉= bitfield(p->CPU.CPUID[CPUID_88][2], 7, 0) + 1;␊ |
291 | ␉}␊ |
292 | ␉else␊ |
293 | ␉{␊ |
294 | ␉␉// Use previous method for Cores and Threads␊ |
295 | ␉␉p->CPU.NoThreads␉= bitfield(p->CPU.CPUID[CPUID_1][1], 23, 16);␊ |
296 | ␉␉p->CPU.NoCores␉␉= bitfield(p->CPU.CPUID[CPUID_4][0], 31, 26) + 1;␊ |
297 | ␉}␊ |
298 | ␉␊ |
299 | ␉/* get brand string (if supported) */␊ |
300 | ␉/* Copyright: from Apple's XNU cpuid.c */␊ |
301 | ␉if (p->CPU.CPUID[CPUID_80][0] > 0x80000004) {␊ |
302 | ␉␉uint32_t␉reg[4];␊ |
303 | ␉␉char␉␉str[128], *s;␊ |
304 | ␉␉/*␊ |
305 | ␉␉ * The brand string 48 bytes (max), guaranteed to␊ |
306 | ␉␉ * be NULL terminated.␊ |
307 | ␉␉ */␊ |
308 | ␉␉do_cpuid(0x80000002, reg);␊ |
309 | ␉␉bcopy((char *)reg, &str[0], 16);␊ |
310 | ␉␉do_cpuid(0x80000003, reg);␊ |
311 | ␉␉bcopy((char *)reg, &str[16], 16);␊ |
312 | ␉␉do_cpuid(0x80000004, reg);␊ |
313 | ␉␉bcopy((char *)reg, &str[32], 16);␊ |
314 | ␉␉for (s = str; *s != '\0'; s++) {␊ |
315 | ␉␉␉if (*s != ' ') break;␊ |
316 | ␉␉}␊ |
317 | ␉␉␊ |
318 | ␉␉strlcpy(p->CPU.BrandString, s, sizeof(p->CPU.BrandString));␊ |
319 | ␉␉␊ |
320 | ␉␉if (!strncmp(p->CPU.BrandString, CPU_STRING_UNKNOWN, MIN(sizeof(p->CPU.BrandString), strlen(CPU_STRING_UNKNOWN) + 1))) {␊ |
321 | ␉␉␉/*␊ |
322 | ␉␉␉ * This string means we have a firmware-programmable brand string,␊ |
323 | ␉␉␉ * and the firmware couldn't figure out what sort of CPU we have.␊ |
324 | ␉␉␉ */␊ |
325 | ␉␉␉p->CPU.BrandString[0] = '\0';␊ |
326 | ␉␉}␊ |
327 | ␉}␊ |
328 | ␉␊ |
329 | ␉/* setup features */␊ |
330 | ␉if ((bit(23) & p->CPU.CPUID[CPUID_1][3]) != 0) {␊ |
331 | ␉␉p->CPU.Features |= CPU_FEATURE_MMX;␊ |
332 | ␉}␊ |
333 | ␉if ((bit(25) & p->CPU.CPUID[CPUID_1][3]) != 0) {␊ |
334 | ␉␉p->CPU.Features |= CPU_FEATURE_SSE;␊ |
335 | ␉}␊ |
336 | ␉if ((bit(26) & p->CPU.CPUID[CPUID_1][3]) != 0) {␊ |
337 | ␉␉p->CPU.Features |= CPU_FEATURE_SSE2;␊ |
338 | ␉}␊ |
339 | ␉if ((bit(0) & p->CPU.CPUID[CPUID_1][2]) != 0) {␊ |
340 | ␉␉p->CPU.Features |= CPU_FEATURE_SSE3;␊ |
341 | ␉}␊ |
342 | ␉if ((bit(19) & p->CPU.CPUID[CPUID_1][2]) != 0) {␊ |
343 | ␉␉p->CPU.Features |= CPU_FEATURE_SSE41;␊ |
344 | ␉}␊ |
345 | ␉if ((bit(20) & p->CPU.CPUID[CPUID_1][2]) != 0) {␊ |
346 | ␉␉p->CPU.Features |= CPU_FEATURE_SSE42;␊ |
347 | ␉}␊ |
348 | ␉if ((bit(29) & p->CPU.CPUID[CPUID_81][3]) != 0) {␊ |
349 | ␉␉p->CPU.Features |= CPU_FEATURE_EM64T;␊ |
350 | ␉}␊ |
351 | ␉if ((bit(5) & p->CPU.CPUID[CPUID_1][3]) != 0) {␊ |
352 | ␉␉p->CPU.Features |= CPU_FEATURE_MSR;␊ |
353 | ␉}␊ |
354 | ␉//if ((bit(28) & p->CPU.CPUID[CPUID_1][3]) != 0) {␊ |
355 | ␉if (p->CPU.NoThreads > p->CPU.NoCores) {␊ |
356 | ␉␉p->CPU.Features |= CPU_FEATURE_HTT;␊ |
357 | ␉}␊ |
358 | ␉␊ |
359 | ␉tscFrequency = measure_tsc_frequency();␊ |
360 | ␉/* if usual method failed */␊ |
361 | ␉if ( tscFrequency < 1000 )␊ |
362 | ␉{␊ |
363 | ␉tscFrequency = timeRDTSC() * 20;␊ |
364 | ␉}␊ |
365 | ␉fsbFrequency = 0;␊ |
366 | ␉cpuFrequency = 0;␊ |
367 | ␉␊ |
368 | ␉if ((p->CPU.Vendor == CPUID_VENDOR_INTEL) && ((p->CPU.Family == 0x06) || (p->CPU.Family == 0x0f))) {␊ |
369 | ␉␉int intelCPU = p->CPU.Model;␊ |
370 | ␉␉if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) || (p->CPU.Family == 0x0f && p->CPU.Model >= 0x03)) {␊ |
371 | ␉␉␉/* Nehalem CPU model */␊ |
372 | ␉␉␉if (p->CPU.Family == 0x06 && (p->CPU.Model == CPU_MODEL_NEHALEM ||␊ |
373 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_FIELDS ||␊ |
374 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_DALES ||␊ |
375 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_DALES_32NM ||␊ |
376 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_WESTMERE ||␊ |
377 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_NEHALEM_EX ||␊ |
378 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_WESTMERE_EX ||␊ |
379 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_SANDYBRIDGE ||␊ |
380 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_JAKETOWN ||␊ |
381 | ␉␉␉␉␉␉␉␉␉␉ p->CPU.Model == CPU_MODEL_IVYBRIDGE)) {␊ |
382 | ␉␉␉␉msr = rdmsr64(MSR_PLATFORM_INFO);␊ |
383 | ␉␉␉␉DBG("msr(%d): platform_info %08x\n", __LINE__, bitfield(msr, 31, 0));␊ |
384 | ␉␉␉␉bus_ratio_max = bitfield(msr, 14, 8);␊ |
385 | ␉␉␉␉bus_ratio_min = bitfield(msr, 46, 40); //valv: not sure about this one (Remarq.1)␊ |
386 | ␉␉␉␉msr = rdmsr64(MSR_FLEX_RATIO);␊ |
387 | ␉␉␉␉DBG("msr(%d): flex_ratio %08x\n", __LINE__, bitfield(msr, 31, 0));␊ |
388 | ␉␉␉␉if (bitfield(msr, 16, 16)) {␊ |
389 | ␉␉␉␉␉flex_ratio = bitfield(msr, 14, 8);␊ |
390 | ␉␉␉␉␉/* bcc9: at least on the gigabyte h67ma-ud2h,␊ |
391 | ␉␉␉␉␉ where the cpu multipler can't be changed to␊ |
392 | ␉␉␉␉␉ allow overclocking, the flex_ratio msr has unexpected (to OSX)␊ |
393 | ␉␉␉␉␉ contents.␉These contents cause mach_kernel to␊ |
394 | ␉␉␉␉␉ fail to compute the bus ratio correctly, instead␊ |
395 | ␉␉␉␉␉ causing the system to crash since tscGranularity␊ |
396 | ␉␉␉␉␉ is inadvertently set to 0.␊ |
397 | ␉␉␉␉␉ */␊ |
398 | ␉␉␉␉␉if (flex_ratio == 0) {␊ |
399 | ␉␉␉␉␉␉/* Clear bit 16 (evidently the presence bit) */␊ |
400 | ␉␉␉␉␉␉wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));␊ |
401 | ␉␉␉␉␉␉msr = rdmsr64(MSR_FLEX_RATIO);␊ |
402 | ␉␉␉␉␉␉verbose("Unusable flex ratio detected. Patched MSR now %08x\n", bitfield(msr, 31, 0));␊ |
403 | ␉␉␉␉␉} else {␊ |
404 | ␉␉␉␉␉␉if (bus_ratio_max > flex_ratio) {␊ |
405 | ␉␉␉␉␉␉␉bus_ratio_max = flex_ratio;␊ |
406 | ␉␉␉␉␉␉}␊ |
407 | ␉␉␉␉␉}␊ |
408 | ␉␉␉␉}␊ |
409 | ␉␉␉␉␊ |
410 | ␉␉␉␉if (bus_ratio_max) {␊ |
411 | ␉␉␉␉␉fsbFrequency = (tscFrequency / bus_ratio_max);␊ |
412 | ␉␉␉␉}␊ |
413 | ␉␉␉␉//valv: Turbo Ratio Limit␊ |
414 | ␉␉␉␉if ((intelCPU != 0x2e) && (intelCPU != 0x2f)) {␊ |
415 | ␉␉␉␉␉msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);␊ |
416 | ␉␉␉␉␉cpuFrequency = bus_ratio_max * fsbFrequency;␊ |
417 | ␉␉␉␉␉max_ratio = bus_ratio_max * 10;␊ |
418 | ␉␉␉␉} else {␊ |
419 | ␉␉␉␉␉cpuFrequency = tscFrequency;␊ |
420 | ␉␉␉␉}␊ |
421 | ␉␉␉␉if ((getValueForKey(kbusratio, &newratio, &len, &bootInfo->chameleonConfig)) && (len <= 4)) {␊ |
422 | ␉␉␉␉␉max_ratio = atoi(newratio);␊ |
423 | ␉␉␉␉␉max_ratio = (max_ratio * 10);␊ |
424 | ␉␉␉␉␉if (len >= 3) max_ratio = (max_ratio + 5);␊ |
425 | ␉␉␉␉␉␊ |
426 | ␉␉␉␉␉verbose("Bus-Ratio: min=%d, max=%s\n", bus_ratio_min, newratio);␊ |
427 | ␉␉␉␉␉␊ |
428 | ␉␉␉␉␉// extreme overclockers may love 320 ;)␊ |
429 | ␉␉␉␉␉if ((max_ratio >= min_ratio) && (max_ratio <= 320)) {␊ |
430 | ␉␉␉␉␉␉cpuFrequency = (fsbFrequency * max_ratio) / 10;␊ |
431 | ␉␉␉␉␉␉if (len >= 3) maxdiv = 1;␊ |
432 | ␉␉␉␉␉␉else maxdiv = 0;␊ |
433 | ␉␉␉␉␉} else {␊ |
434 | ␉␉␉␉␉␉max_ratio = (bus_ratio_max * 10);␊ |
435 | ␉␉␉␉␉}␊ |
436 | ␉␉␉␉}␊ |
437 | ␉␉␉␉//valv: to be uncommented if Remarq.1 didn't stick␊ |
438 | ␉␉␉␉/*if (bus_ratio_max > 0) bus_ratio = flex_ratio;*/␊ |
439 | ␉␉␉␉p->CPU.MaxRatio = max_ratio;␊ |
440 | ␉␉␉␉p->CPU.MinRatio = min_ratio;␊ |
441 | ␉␉␉␉␊ |
442 | ␉␉␉␉myfsb = fsbFrequency / 1000000;␊ |
443 | ␉␉␉␉verbose("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", myfsb, max_ratio);␊ |
444 | ␉␉␉␉currcoef = bus_ratio_max;␊ |
445 | ␉␉␉} else {␊ |
446 | ␉␉␉␉msr = rdmsr64(MSR_IA32_PERF_STATUS);␊ |
447 | ␉␉␉␉DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, bitfield(msr, 31, 0));␊ |
448 | ␉␉␉␉currcoef = bitfield(msr, 12, 8);␊ |
449 | ␉␉␉␉/* Non-integer bus ratio for the max-multi*/␊ |
450 | ␉␉␉␉maxdiv = bitfield(msr, 46, 46);␊ |
451 | ␉␉␉␉/* Non-integer bus ratio for the current-multi (undocumented)*/␊ |
452 | ␉␉␉␉currdiv = bitfield(msr, 14, 14);␊ |
453 | ␉␉␉␉␊ |
454 | ␉␉␉␉// This will always be model >= 3␊ |
455 | ␉␉␉␉if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) || (p->CPU.Family == 0x0f))␊ |
456 | ␉␉␉␉{␊ |
457 | ␉␉␉␉␉/* On these models, maxcoef defines TSC freq */␊ |
458 | ␉␉␉␉␉maxcoef = bitfield(msr, 44, 40);␊ |
459 | ␉␉␉␉} else {␊ |
460 | ␉␉␉␉␉/* On lower models, currcoef defines TSC freq */␊ |
461 | ␉␉␉␉␉/* XXX */␊ |
462 | ␉␉␉␉␉maxcoef = currcoef;␊ |
463 | ␉␉␉␉}␊ |
464 | ␉␉␉␉␊ |
465 | ␉␉␉␉if (maxcoef) {␊ |
466 | ␉␉␉␉␉if (maxdiv) {␊ |
467 | ␉␉␉␉␉␉fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));␊ |
468 | ␉␉␉␉␉} else {␊ |
469 | ␉␉␉␉␉␉fsbFrequency = (tscFrequency / maxcoef);␊ |
470 | ␉␉␉␉␉}␊ |
471 | ␉␉␉␉␉if (currdiv) {␊ |
472 | ␉␉␉␉␉␉cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);␊ |
473 | ␉␉␉␉␉} else {␊ |
474 | ␉␉␉␉␉␉cpuFrequency = (fsbFrequency * currcoef);␊ |
475 | ␉␉␉␉␉}␊ |
476 | ␉␉␉␉␉DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");␊ |
477 | ␉␉␉␉}␊ |
478 | ␉␉␉}␊ |
479 | ␉␉}␊ |
480 | ␉␉/* Mobile CPU */␊ |
481 | ␉␉if (rdmsr64(MSR_IA32_PLATFORM_ID) & (1<<28)) {␊ |
482 | ␉␉␉p->CPU.Features |= CPU_FEATURE_MOBILE;␊ |
483 | ␉␉}␊ |
484 | ␉}␊ |
485 | ␉else if ((p->CPU.Vendor == CPUID_VENDOR_AMD) && (p->CPU.Family == 0x0f))␊ |
486 | ␉{␊ |
487 | ␉␉switch(p->CPU.ExtFamily)␊ |
488 | ␉␉{␊ |
489 | ␉␉␉case 0x00: /* K8 */␊ |
490 | ␉␉␉␉msr = rdmsr64(K8_FIDVID_STATUS);␊ |
491 | ␉␉␉␉maxcoef = bitfield(msr, 21, 16) / 2 + 4;␊ |
492 | ␉␉␉␉currcoef = bitfield(msr, 5, 0) / 2 + 4;␊ |
493 | ␉␉␉␉break;␊ |
494 | ␉␉␉␉␊ |
495 | ␉␉␉case 0x01: /* K10 */␊ |
496 | ␉␉␉␉msr = rdmsr64(K10_COFVID_STATUS);␊ |
497 | ␉␉␉␉do_cpuid2(0x00000006, 0, p->CPU.CPUID[CPUID_6]);␊ |
498 | ␉␉␉␉// EffFreq: effective frequency interface␊ |
499 | ␉␉␉␉if (bitfield(p->CPU.CPUID[CPUID_6][2], 0, 0) == 1)␊ |
500 | ␉␉␉␉{␊ |
501 | ␉␉␉␉␉//uint64_t mperf = measure_mperf_frequency();␊ |
502 | ␉␉␉␉␉uint64_t aperf = measure_aperf_frequency();␊ |
503 | ␉␉␉␉␉cpuFrequency = aperf;␊ |
504 | ␉␉␉␉}␊ |
505 | ␉␉␉␉// NOTE: tsc runs at the maccoeff (non turbo)␊ |
506 | ␉␉␉␉//␉␉␉*not* at the turbo frequency.␊ |
507 | ␉␉␉␉maxcoef␉ = bitfield(msr, 54, 49) / 2 + 4;␊ |
508 | ␉␉␉␉currcoef = bitfield(msr, 5, 0) + 0x10;␊ |
509 | ␉␉␉␉currdiv = 2 << bitfield(msr, 8, 6);␊ |
510 | ␉␉␉␉␊ |
511 | ␉␉␉␉break;␊ |
512 | ␉␉␉␉␊ |
513 | ␉␉␉case 0x05: /* K14 */␊ |
514 | ␉␉␉␉msr = rdmsr64(K10_COFVID_STATUS);␊ |
515 | ␉␉␉␉currcoef = (bitfield(msr, 54, 49) + 0x10) << 2;␊ |
516 | ␉␉␉␉currdiv = (bitfield(msr, 8, 4) + 1) << 2;␊ |
517 | ␉␉␉␉currdiv += bitfield(msr, 3, 0);␊ |
518 | ␉␉␉␉␊ |
519 | ␉␉␉␉break;␊ |
520 | ␉␉␉␉␊ |
521 | ␉␉␉case 0x02: /* K11 */␊ |
522 | ␉␉␉␉// not implimented␊ |
523 | ␉␉␉␉break;␊ |
524 | ␉␉}␊ |
525 | ␉␉␊ |
526 | ␉␉if (maxcoef)␊ |
527 | ␉␉{␊ |
528 | ␉␉␉if (currdiv)␊ |
529 | ␉␉␉{␊ |
530 | ␉␉␉␉if (!currcoef) currcoef = maxcoef;␊ |
531 | ␉␉␉␉if (!cpuFrequency)␊ |
532 | ␉␉␉␉␉fsbFrequency = ((tscFrequency * currdiv) / currcoef);␊ |
533 | ␉␉␉␉else␊ |
534 | ␉␉␉␉␉fsbFrequency = ((cpuFrequency * currdiv) / currcoef);␊ |
535 | ␉␉␉␉␊ |
536 | ␉␉␉␉DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);␊ |
537 | ␉␉␉} else {␊ |
538 | ␉␉␉␉if (!cpuFrequency)␊ |
539 | ␉␉␉␉␉fsbFrequency = (tscFrequency / maxcoef);␊ |
540 | ␉␉␉␉else ␊ |
541 | ␉␉␉␉␉fsbFrequency = (cpuFrequency / maxcoef);␊ |
542 | ␉␉␉␉DBG("%d\n", currcoef);␊ |
543 | ␉␉␉}␊ |
544 | ␉␉}␊ |
545 | ␉␉else if (currcoef)␊ |
546 | ␉␉{␊ |
547 | ␉␉␉if (currdiv)␊ |
548 | ␉␉␉{␊ |
549 | ␉␉␉␉fsbFrequency = ((tscFrequency * currdiv) / currcoef);␊ |
550 | ␉␉␉␉DBG("%d.%d\n", currcoef / currdiv, ((currcoef % currdiv) * 100) / currdiv);␊ |
551 | ␉␉␉} else {␊ |
552 | ␉␉␉␉fsbFrequency = (tscFrequency / currcoef);␊ |
553 | ␉␉␉␉DBG("%d\n", currcoef);␊ |
554 | ␉␉␉}␊ |
555 | ␉␉}␊ |
556 | ␉␉if (!cpuFrequency) cpuFrequency = tscFrequency;␊ |
557 | ␉}␊ |
558 | ␉␊ |
559 | #if 0␊ |
560 | ␉if (!fsbFrequency) {␊ |
561 | ␉␉fsbFrequency = (DEFAULT_FSB * 1000);␊ |
562 | ␉␉cpuFrequency = tscFrequency;␊ |
563 | ␉␉DBG("0 ! using the default value for FSB !\n");␊ |
564 | ␉}␊ |
565 | #endif␊ |
566 | ␉␊ |
567 | ␉p->CPU.MaxCoef = maxcoef;␊ |
568 | ␉p->CPU.MaxDiv = maxdiv;␊ |
569 | ␉p->CPU.CurrCoef = currcoef;␊ |
570 | ␉p->CPU.CurrDiv = currdiv;␊ |
571 | ␉p->CPU.TSCFrequency = tscFrequency;␊ |
572 | ␉p->CPU.FSBFrequency = fsbFrequency;␊ |
573 | ␉p->CPU.CPUFrequency = cpuFrequency;␊ |
574 | ␉␊ |
575 | ␉// keep formatted with spaces instead of tabs␊ |
576 | ␉DBG("CPU: Brand String: %s\n", p->CPU.BrandString);␊ |
577 | DBG("CPU: Vendor/Family/ExtFamily: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Family, p->CPU.ExtFamily);␊ |
578 | DBG("CPU: Model/ExtModel/Stepping: 0x%x/0x%x/0x%x\n", p->CPU.Model, p->CPU.ExtModel, p->CPU.Stepping);␊ |
579 | DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef);␊ |
580 | DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv);␊ |
581 | DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000);␊ |
582 | DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000);␊ |
583 | DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000);␊ |
584 | DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads);␊ |
585 | DBG("CPU: Features: 0x%08x\n", p->CPU.Features);␊ |
586 | #if DEBUG_CPU␊ |
587 | ␉pause();␊ |
588 | #endif␊ |
589 | }␊ |
590 |