Chameleon

Chameleon Svn Source Tree

Root/branches/cparm/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
10#ifndef DEBUG_CPU
11#define DEBUG_CPU 0
12#endif
13
14#if DEBUG_CPU
15#define DBG(x...)printf(x)
16#else
17#define DBG(x...)msglog(x)
18#endif
19
20#if OLD_STYLE
21static uint64_t measure_tsc_frequency(void);
22
23// DFE: enable_PIT2 and disable_PIT2 come from older xnu
24
25/*
26 * Enable or disable timer 2.
27 * Port 0x61 controls timer 2:
28 * bit 0 gates the clock,
29 * bit 1 gates output to speaker.
30 */
31static inline void enable_PIT2(void)
32{
33 /* Enable gate, disable speaker */
34 __asm__ volatile(
35 " inb $0x61,%%al \n\t"
36 " and $0xFC,%%al \n\t" /* & ~0x03 */
37 " or $1,%%al \n\t"
38 " outb %%al,$0x61 \n\t"
39 : : : "%al" );
40}
41
42static inline void disable_PIT2(void)
43{
44 /* Disable gate and output to speaker */
45 __asm__ volatile(
46 " inb $0x61,%%al \n\t"
47 " and $0xFC,%%al \n\t"/* & ~0x03 */
48 " outb %%al,$0x61 \n\t"
49 : : : "%al" );
50}
51
52// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
53// roughly based on Linux code
54
55/* Set the 8254 channel 2 to mode 0 with the specified value.
56 In mode 0, the counter will initially set its gate low when the
57 timer expires. For this to be useful, you ought to set it high
58 before calling this function. The enable_PIT2 function does this.
59 */
60static inline void set_PIT2_mode0(uint16_t value)
61{
62 __asm__ volatile(
63 " movb $0xB0,%%al \n\t"
64 " outb%%al,$0x43\n\t"
65 " movb%%dl,%%al\n\t"
66 " outb%%al,$0x42\n\t"
67 " movb%%dh,%%al\n\t"
68 " outb%%al,$0x42"
69 : : "d"(value) /*: no clobber */ );
70}
71
72/* Returns the number of times the loop ran before the PIT2 signaled */
73static inline unsigned long poll_PIT2_gate(void)
74{
75 unsigned long count = 0;
76 unsigned char nmi_sc_val;
77 do {
78 ++count;
79 __asm__ volatile(
80 "inb$0x61,%0"
81 : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
82 } while( (nmi_sc_val & 0x20) == 0);
83 return count;
84}
85/*
86 * DFE: Measures the TSC frequency in Hz (64-bit) using the ACPI PM timer
87 */
88static uint64_t measure_tsc_frequency(void)
89{
90 uint64_t tscStart;
91 uint64_t tscEnd;
92 uint64_t tscDelta = 0xffffffffffffffffULL;
93 unsigned long pollCount;
94 uint64_t retval = 0;
95 int i;
96
97 /* Time how many TSC ticks elapse in 30 msec using the 8254 PIT
98 * counter 2. We run this loop 3 times to make sure the cache
99 * is hot and we take the minimum delta from all of the runs.
100 * That is to say that we're biased towards measuring the minimum
101 * number of TSC ticks that occur while waiting for the timer to
102 * expire. That theoretically helps avoid inconsistencies when
103 * running under a VM if the TSC is not virtualized and the host
104 * steals time. The TSC is normally virtualized for VMware.
105 */
106 for(i = 0; i < 10; ++i)
107 {
108 enable_PIT2();
109 set_PIT2_mode0(CALIBRATE_LATCH);
110 tscStart = rdtsc64();
111 pollCount = poll_PIT2_gate();
112 tscEnd = rdtsc64();
113 /* The poll loop must have run at least a few times for accuracy */
114 if(pollCount <= 1)
115 continue;
116 /* The TSC must increment at LEAST once every millisecond. We
117 * should have waited exactly 30 msec so the TSC delta should
118 * be >= 30. Anything less and the processor is way too slow.
119 */
120 if((tscEnd - tscStart) <= CALIBRATE_TIME_MSEC)
121 continue;
122 // tscDelta = min(tscDelta, (tscEnd - tscStart))
123 if( (tscEnd - tscStart) < tscDelta )
124 tscDelta = tscEnd - tscStart;
125 }
126 /* tscDelta is now the least number of TSC ticks the processor made in
127 * a timespan of 0.03 s (e.g. 30 milliseconds)
128 * Linux thus divides by 30 which gives the answer in kiloHertz because
129 * 1 / ms = kHz. But we're xnu and most of the rest of the code uses
130 * Hz so we need to convert our milliseconds to seconds. Since we're
131 * dividing by the milliseconds, we simply multiply by 1000.
132 */
133
134 /* Unlike linux, we're not limited to 32-bit, but we do need to take care
135 * that we're going to multiply by 1000 first so we do need at least some
136 * arithmetic headroom. For now, 32-bit should be enough.
137 * Also unlike Linux, our compiler can do 64-bit integer arithmetic.
138 */
139 if(tscDelta > (1ULL<<32))
140 retval = 0;
141 else
142 {
143 retval = tscDelta * 1000 / 30;
144 }
145 disable_PIT2();
146 return retval;
147}
148
149#else
150/*
151 License for x2apic_enabled, get_apicbase, compute_bclk.
152
153 Copyright (c) 2010, Intel Corporation
154 All rights reserved.
155
156 Redistribution and use in source and binary forms, with or without
157 modification, are permitted provided that the following conditions are met:
158
159 * Redistributions of source code must retain the above copyright notice,
160 this list of conditions and the following disclaimer.
161 * Redistributions in binary form must reproduce the above copyright notice,
162 this list of conditions and the following disclaimer in the documentation
163 and/or other materials provided with the distribution.
164 * Neither the name of Intel Corporation nor the names of its contributors
165 may be used to endorse or promote products derived from this software
166 without specific prior written permission.
167
168 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
169 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
170 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
171 DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
172 ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
173 (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
174 LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
175 ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
176 (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
177 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
178 */
179static inline __attribute__((always_inline)) void rdmsr32(uint32_t msr, uint32_t * lo_data_addr, uint32_t * hi_data_addr);
180static inline __attribute__((always_inline)) void wrmsr32(uint32_t msr, uint32_t lo_data, uint32_t hi_data);
181static uint32_t x2apic_enabled(void);
182static uint32_t get_apicbase(void);
183static uint32_t compute_bclk(void);
184static inline __attribute__((always_inline)) void rdmsr32(uint32_t msr, uint32_t * lo_data_addr, uint32_t * hi_data_addr)
185{
186 __asm__ volatile(
187 "rdmsr"
188 : "=a" (*lo_data_addr), "=d" (*hi_data_addr)
189 : "c" (msr)
190 );
191}
192static inline __attribute__((always_inline)) void wrmsr32(uint32_t msr, uint32_t lo_data, uint32_t hi_data)
193{
194 __asm__ __volatile__ (
195 "wrmsr"
196 : /* No outputs */
197 : "c" (msr), "a" (lo_data), "d" (hi_data)
198 );
199}
200#define MSR_APIC_BASE 0x1B
201#define APIC_TMR_INITIAL_CNT 0x380
202#define APIC_TMR_CURRENT_CNT 0x390
203#define APIC_TMR_DIVIDE_CFG 0x3E0
204#define MSR_APIC_TMR_INITIAL_CNT 0x838
205#define MSR_APIC_TMR_CURRENT_CNT 0x839
206#define MSR_APIC_TMR_DIVIDE_CFG 0x83E
207static uint32_t x2apic_enabled(void)
208{
209 uint64_t temp64;
210
211 temp64 = rdmsr64(MSR_APIC_BASE);
212
213 return (uint32_t) (temp64 & (1 << 10)) ? 1 : 0;
214}
215static uint32_t get_apicbase(void)
216{
217 uint64_t temp64;
218
219 temp64 = rdmsr64(MSR_APIC_BASE);
220
221 return (uint32_t) (temp64 & 0xfffff000);
222}
223static uint32_t compute_bclk(void)
224{
225 uint32_t dummy;
226 uint32_t start, stop;
227 uint8_t temp8;
228 uint16_t delay_count;
229 uint32_t bclk;
230
231#define DELAY_IN_US 1000
232
233 // Compute fixed delay as time
234 // delay count = desired time * PIT frequency
235 // PIT frequency = 1.193182 MHz
236 delay_count = 1193182 / DELAY_IN_US;
237
238 // PIT channel 2 gate is controlled by IO port 0x61, bit 0
239#define PIT_CH2_LATCH_REG 0x61
240#define CH2_SPEAKER (1 << 1) // bit 1 -- 1 = speaker enabled 0 = speaker disabled
241#define CH2_GATE_IN (1 << 0) // bit 0 -- 1 = gate enabled, 0 = gate disabled
242#define CH2_GATE_OUT (1 << 5) // bit 5 -- 1 = gate latched, 0 = gate not latched
243
244 // PIT Command register
245#define PIT_MODE_COMMAND_REG 0x43
246#define SELECT_CH2 (2 << 6)
247#define ACCESS_MODE_LOBYTE_HIBYTE (3 << 4)
248#define MODE0_INTERRUPT_ON_TERMINAL_COUNT 0 // Despite name, no interrupts on CH2
249
250 // PIT Channel 2 data port
251#define PIT_CH2_DATA 0x42
252
253 // Disable the PIT channel 2 speaker and gate
254 temp8 = inb(PIT_CH2_LATCH_REG);
255 temp8 &= ~(CH2_SPEAKER | CH2_GATE_IN);
256 outb(PIT_CH2_LATCH_REG, temp8);
257
258 // Setup command and mode
259 outb(PIT_MODE_COMMAND_REG, SELECT_CH2 | ACCESS_MODE_LOBYTE_HIBYTE | MODE0_INTERRUPT_ON_TERMINAL_COUNT);
260
261 // Set time for fixed delay
262 outb(PIT_CH2_DATA, (uint8_t) (delay_count));
263 outb(PIT_CH2_DATA, (uint8_t) (delay_count >> 8));
264
265 // Prepare to enable channel 2 gate but leave the speaker disabled
266 temp8 = inb(PIT_CH2_LATCH_REG);
267 temp8 &= ~CH2_SPEAKER;
268 temp8 |= CH2_GATE_IN;
269
270 if (x2apic_enabled())
271{
272 // Set APIC Timer Divide Value as 2
273 wrmsr32(MSR_APIC_TMR_DIVIDE_CFG, 0, 0);
274
275 // start APIC timer with a known value
276 start = ~0UL;
277 wrmsr32(MSR_APIC_TMR_INITIAL_CNT, start, 0);
278 }
279 else
280{
281 // Set APIC Timer Divide Value as 2
282 *(volatile uint32_t *)(uint32_t) (get_apicbase() + APIC_TMR_DIVIDE_CFG) = 0UL;
283
284 // start APIC timer with a known value
285 start = ~0UL;
286 *(volatile uint32_t *)(uint32_t) (get_apicbase() + APIC_TMR_INITIAL_CNT) = start;
287 }
288
289 // Actually start the PIT channel 2
290 outb(PIT_CH2_LATCH_REG, temp8);
291
292 // Wait for the fixed delay
293 while (!(inb(PIT_CH2_LATCH_REG) & CH2_GATE_OUT));
294
295 if (x2apic_enabled())
296{
297 // read the APIC timer to determine the change that occurred over this fixed delay
298 rdmsr32(MSR_APIC_TMR_CURRENT_CNT, &stop, &dummy);
299
300 // stop APIC timer
301 wrmsr32(MSR_APIC_TMR_INITIAL_CNT, 0, 0);
302
303 }
304 else
305{
306 // read the APIC timer to determine the change that occurred over this fixed delay
307 stop = *(volatile uint32_t *)(uint32_t) (get_apicbase() + APIC_TMR_CURRENT_CNT);
308
309 // stop APIC timer
310 *(volatile uint32_t *)(uint32_t) (get_apicbase() + APIC_TMR_INITIAL_CNT) = 0UL;
311 }
312
313 // Disable channel 2 speaker and gate input
314 temp8 = inb(PIT_CH2_LATCH_REG);
315 temp8 &= ~(CH2_SPEAKER | CH2_GATE_IN);
316 outb(PIT_CH2_LATCH_REG, temp8);
317
318 bclk = (start - stop) * 2 / DELAY_IN_US;
319
320 // Round bclk to the nearest 100/12 integer value
321 bclk = ((((bclk * 24) + 100) / 200) * 200) / 24;
322 DBG("\nCompute bclk: %dMHz\n", bclk);
323 return bclk;
324}
325#endif
326
327/*
328 * Calculates the FSB and CPU frequencies using specific MSRs for each CPU
329 * - multi. is read from a specific MSR. In the case of Intel, there is:
330 * a max multi. (used to calculate the FSB freq.),
331 * and a current multi. (used to calculate the CPU freq.)
332 * - fsbFrequency = tscFrequency / multi
333 * - cpuFrequency = fsbFrequency * multi
334 */
335
336void scan_cpu(PlatformInfo_t *p)
337{
338uint64_ttscFrequency, fsbFrequency, cpuFrequency;
339uint64_tmsr;
340uint8_tmaxcoef = 0, maxdiv = 0, currcoef = 0, currdiv = 0;
341 uint32_treg[4];
342 uint32_t cores_per_package;
343 uint32_t logical_per_package;
344
345do_cpuid(0, reg);
346 p->CPU.Vendor= reg[ebx];
347 p->CPU.cpuid_max_basic = reg[eax];
348
349 do_cpuid2(0x00000004, 0, reg);
350 cores_per_package= bitfield(reg[eax], 31, 26) + 1;
351
352 /* get extended cpuid results */
353do_cpuid(0x80000000, reg);
354uint32_t cpuid_max_ext = reg[eax];
355
356
357/* Begin of Copyright: from Apple's XNU cpuid.c */
358
359/* get brand string (if supported) */
360if (cpuid_max_ext > 0x80000004)
361{
362 char str[128], *s;
363/*
364 * The brand string 48 bytes (max), guaranteed to
365 * be NUL terminated.
366 */
367do_cpuid(0x80000002, reg);
368bcopy((char *)reg, &str[0], 16);
369do_cpuid(0x80000003, reg);
370bcopy((char *)reg, &str[16], 16);
371do_cpuid(0x80000004, reg);
372bcopy((char *)reg, &str[32], 16);
373for (s = str; *s != '\0'; s++)
374{
375if (*s != ' ') break;
376}
377
378strlcpy(p->CPU.BrandString,s, sizeof(p->CPU.BrandString));
379
380if (!strncmp(p->CPU.BrandString, CPUID_STRING_UNKNOWN, min(sizeof(p->CPU.BrandString), (unsigned)strlen(CPUID_STRING_UNKNOWN) + 1)))
381{
382 /*
383 * This string means we have a firmware-programmable brand string,
384 * and the firmware couldn't figure out what sort of CPU we have.
385 */
386 p->CPU.BrandString[0] = '\0';
387 }
388}
389
390 /*
391 * Get processor signature and decode
392 * and bracket this with the approved procedure for reading the
393 * the microcode version number a.k.a. signature a.k.a. BIOS ID
394 */
395wrmsr64(MSR_IA32_BIOS_SIGN_ID, 0);
396do_cpuid(1, reg);
397 p->CPU.MicrocodeVersion =
398 (uint32_t) (rdmsr64(MSR_IA32_BIOS_SIGN_ID) >> 32);
399
400p->CPU.Signature = reg[eax];
401p->CPU.Stepping = bitfield(reg[eax], 3, 0);
402p->CPU.Model = bitfield(reg[eax], 7, 4);
403p->CPU.Family = bitfield(reg[eax], 11, 8);
404p->CPU.ExtModel = bitfield(reg[eax], 19, 16);
405p->CPU.ExtFamily = bitfield(reg[eax], 27, 20);
406p->CPU.Brand = bitfield(reg[ebx], 7, 0);
407p->CPU.Features = quad(reg[ecx], reg[edx]);
408
409 /* Fold extensions into family/model */
410if (p->CPU.Family == 0x0f)
411p->CPU.Family += p->CPU.ExtFamily;
412if (p->CPU.Family == 0x0f || p->CPU.Family == 0x06)
413p->CPU.Model += (p->CPU.ExtModel << 4);
414
415 if (p->CPU.Features & CPUID_FEATURE_HTT)
416logical_per_package =
417 bitfield(reg[ebx], 23, 16);
418else
419logical_per_package = 1;
420
421if (cpuid_max_ext >= 0x80000001)
422{
423do_cpuid(0x80000001, reg);
424p->CPU.ExtFeatures =
425 quad(reg[ecx], reg[edx]);
426
427}
428
429/* Fold in the Invariant TSC feature bit, if present */
430if (cpuid_max_ext >= 0x80000007)
431{
432do_cpuid(0x80000007, reg);
433p->CPU.ExtFeatures |=
434 reg[edx] & (uint32_t)CPUID_EXTFEATURE_TSCI;
435}
436
437 if (p->CPU.cpuid_max_basic >= 0x5) {
438/*
439 * Extract the Monitor/Mwait Leaf info:
440 */
441do_cpuid(5, reg);
442 p->CPU.sub_Cstates = reg[edx];
443 p->CPU.extensions = reg[ecx];
444}
445
446 if (p->CPU.cpuid_max_basic >= 0x6)
447 {
448/*
449 * The thermal and Power Leaf:
450 */
451do_cpuid(6, reg);
452p->CPU.dynamic_acceleration = bitfield(reg[eax], 1, 1); // "Dynamic Acceleration Technology (Turbo Mode)"
453p->CPU.invariant_APIC_timer = bitfield(reg[eax], 2, 2); // "Invariant APIC Timer"
454 p->CPU.fine_grain_clock_mod = bitfield(reg[eax], 4, 4);
455}
456
457 if ((p->CPU.Vendor == 0x756E6547 /* Intel */) &&
458(p->CPU.Family == 0x06))
459{
460 /*
461 * Find the number of enabled cores and threads
462 * (which determines whether SMT/Hyperthreading is active).
463 */
464 switch (p->CPU.Model)
465{
466
467 case CPUID_MODEL_DALES_32NM:
468 case CPUID_MODEL_WESTMERE:
469 case CPUID_MODEL_WESTMERE_EX:
470 {
471 msr = rdmsr64(MSR_CORE_THREAD_COUNT);
472 p->CPU.NoThreads = bitfield((uint32_t)msr, 15, 0);
473 p->CPU.NoCores = bitfield((uint32_t)msr, 19, 16);
474 break;
475 }
476
477 case CPUID_MODEL_NEHALEM:
478 case CPUID_MODEL_FIELDS:
479 case CPUID_MODEL_DALES:
480 case CPUID_MODEL_NEHALEM_EX:
481case CPUID_MODEL_SANDYBRIDGE:
482case CPUID_MODEL_JAKETOWN:
483 {
484 msr = rdmsr64(MSR_CORE_THREAD_COUNT);
485 p->CPU.NoThreads = bitfield((uint32_t)msr, 15, 0);
486 p->CPU.NoCores = bitfield((uint32_t)msr, 31, 16);
487 break;
488 }
489 }
490 }
491
492 if (p->CPU.NoCores == 0)
493{
494p->CPU.NoThreads = cores_per_package;
495p->CPU.NoCores = logical_per_package;
496}
497
498/* End of Copyright: from Apple's XNU cpuid.c */
499
500#if OLD_STYLE
501tscFrequency = measure_tsc_frequency();
502fsbFrequency = 0;
503#else
504tscFrequency = 0;
505fsbFrequency = (uint64_t)(compute_bclk() * 1000000);
506#endif
507cpuFrequency = 0;
508
509
510if ((p->CPU.Vendor == 0x756E6547 /* Intel */) &&
511((p->CPU.Family == 0x06) ||
512 (p->CPU.Family == 0x0f)))
513{
514if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0c) ||
515(p->CPU.Family == 0x0f && p->CPU.Model >= 0x03))
516{
517/* Nehalem CPU model */
518if (p->CPU.Family == 0x06 && (p->CPU.Model == CPUID_MODEL_NEHALEM ||
519 p->CPU.Model == CPUID_MODEL_FIELDS ||
520 p->CPU.Model == CPUID_MODEL_DALES ||
521 p->CPU.Model == CPUID_MODEL_DALES_32NM ||
522 p->CPU.Model == CPUID_MODEL_WESTMERE ||
523 p->CPU.Model == CPUID_MODEL_NEHALEM_EX ||
524 p->CPU.Model == CPUID_MODEL_WESTMERE_EX ||
525 p->CPU.Model == CPUID_MODEL_SANDYBRIDGE ||
526 p->CPU.Model == CPUID_MODEL_JAKETOWN))
527{
528uint8_tbus_ratio_max = 0, bus_ratio_min = 0;
529uint32_tmax_ratio = 0;
530uint64_tflex_ratio = 0;
531msr = rdmsr64(MSR_PLATFORM_INFO);
532#if DEBUG_CPU
533DBG("msr(%d): platform_info %08x\n", __LINE__, msr & 0xffffffff);
534#endif
535bus_ratio_max = (msr >> 8) & 0xff;
536bus_ratio_min = (msr >> 40) & 0xff; //valv: not sure about this one (Remarq.1)
537msr = rdmsr64(MSR_FLEX_RATIO);
538#if DEBUG_CPU
539DBG("msr(%d): flex_ratio %08x\n", __LINE__, msr & 0xffffffff);
540#endif
541if ((msr >> 16) & 0x01)
542{
543flex_ratio = (msr >> 8) & 0xff;
544/* bcc9: at least on the gigabyte h67ma-ud2h,
545 where the cpu multipler can't be changed to
546 allow overclocking, the flex_ratio msr has unexpected (to OSX)
547 contents. These contents cause mach_kernel to
548 fail to compute the bus ratio correctly, instead
549 causing the system to crash since tscGranularity
550 is inadvertently set to 0.
551 */
552if (flex_ratio == 0)
553{
554/* Clear bit 16 (evidently the
555 presence bit) */
556wrmsr64(MSR_FLEX_RATIO, (msr & 0xFFFFFFFFFFFEFFFFULL));
557msr = rdmsr64(MSR_FLEX_RATIO);
558#if DEBUG_CPU
559DBG("Unusable flex ratio detected. MSR Patched to %08x\n", msr & 0xffffffff);
560#endif
561}
562else
563{
564if (bus_ratio_max > flex_ratio)
565{
566bus_ratio_max = flex_ratio;
567}
568}
569}
570#if OLD_STYLE
571if (bus_ratio_max)
572{
573fsbFrequency = (tscFrequency / bus_ratio_max);
574}
575#endif
576//valv: Turbo Ratio Limit
577if ((p->CPU.Model != 0x2e) && (p->CPU.Model != 0x2f))
578{
579//msr = rdmsr64(MSR_TURBO_RATIO_LIMIT);
580cpuFrequency = bus_ratio_max * fsbFrequency;
581max_ratio = bus_ratio_max * 10;
582}
583else
584{
585#if OLD_STYLE
586cpuFrequency = tscFrequency;
587#else
588cpuFrequency = bus_ratio_max * fsbFrequency;
589#endif
590}
591#if DEBUG_CPU
592DBG("Sticking with [BCLK: %dMhz, Bus-Ratio: %d]\n", fsbFrequency / 1000000, max_ratio);
593#endif
594currcoef = bus_ratio_max;
595}
596else
597{
598msr = rdmsr64(MSR_IA32_PERF_STATUS);
599#if DEBUG_CPU
600DBG("msr(%d): ia32_perf_stat 0x%08x\n", __LINE__, msr & 0xffffffff);
601#endif
602currcoef = (msr >> 8) & 0x1f;
603/* Non-integer bus ratio for the max-multi*/
604maxdiv = (msr >> 46) & 0x01;
605/* Non-integer bus ratio for the current-multi (undocumented)*/
606currdiv = (msr >> 14) & 0x01;
607
608if ((p->CPU.Family == 0x06 && p->CPU.Model >= 0x0e) ||
609(p->CPU.Family == 0x0f)) // This will always be model >= 3
610{
611/* On these models, maxcoef defines TSC freq */
612maxcoef = (msr >> 40) & 0x1f;
613}
614else
615{
616/* On lower models, currcoef defines TSC freq */
617/* XXX */
618maxcoef = currcoef;
619}
620#if OLD_STYLE
621if (maxcoef)
622{
623if (maxdiv)
624{
625fsbFrequency = ((tscFrequency * 2) / ((maxcoef * 2) + 1));
626}
627else
628{
629fsbFrequency = (tscFrequency / maxcoef);
630}
631
632if (currdiv)
633{
634cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
635}
636else
637{
638cpuFrequency = (fsbFrequency * currcoef);
639}
640#if DEBUG_CPU
641DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
642#endif
643}
644#else
645if (currdiv)
646{
647cpuFrequency = (fsbFrequency * ((currcoef * 2) + 1) / 2);
648}
649else
650{
651cpuFrequency = (fsbFrequency * currcoef);
652}
653
654if (maxcoef)
655{
656if (maxdiv)
657{
658tscFrequency = (fsbFrequency * ((maxcoef * 2) + 1)) / 2;
659}
660else
661{
662tscFrequency = fsbFrequency * maxcoef;
663}
664}
665#if DEBUG_CPU
666DBG("max: %d%s current: %d%s\n", maxcoef, maxdiv ? ".5" : "",currcoef, currdiv ? ".5" : "");
667#endif
668
669#endif // OLD_STYLE
670
671}
672}
673 /* Mobile CPU ? */
674//Slice
675 p->CPU.isMobile = false;
676switch (p->CPU.Model)
677{
678case 0x0D:
679p->CPU.isMobile = true;
680break;
681case 0x02:
682case 0x03:
683case 0x04:
684case 0x06:
685p->CPU.isMobile = (rdmsr64(0x2C) & (1 << 21));
686break;
687default:
688p->CPU.isMobile = (rdmsr64(0x17) & (1 << 28));
689break;
690}
691
692DBG("%s platform found.\n", p->CPU.isMobile?"Mobile":"Desktop");
693}
694
695p->CPU.MaxCoef = maxcoef;
696p->CPU.MaxDiv = maxdiv;
697p->CPU.CurrCoef = currcoef;
698p->CPU.CurrDiv = currdiv;
699
700//p->CPU.TSCFrequency = (tscFrequency / 1000000) * 1000000;
701//p->CPU.FSBFrequency = (fsbFrequency / 1000000) * 1000000;
702//p->CPU.CPUFrequency = (cpuFrequency / 1000000) * 1000000;
703
704 p->CPU.TSCFrequency = tscFrequency ;
705p->CPU.FSBFrequency = fsbFrequency ;
706p->CPU.CPUFrequency = cpuFrequency ;
707
708DBG("CPU: Vendor/Model/ExtModel: 0x%x/0x%x/0x%x\n", p->CPU.Vendor, p->CPU.Model, p->CPU.ExtModel);
709DBG("CPU: Family/ExtFamily: 0x%x/0x%x\n", p->CPU.Family, p->CPU.ExtFamily);
710DBG("CPU: TSCFreq: %dMHz\n", p->CPU.TSCFrequency / 1000000);
711if(p->CPU.Vendor == 0x756E6547 /* Intel */)
712{
713DBG("CPU: FSBFreq: %dMHz\n", p->CPU.FSBFrequency / 1000000);
714DBG("CPU: CPUFreq: %dMHz\n", p->CPU.CPUFrequency / 1000000);
715DBG("CPU: MaxCoef/CurrCoef: 0x%x/0x%x\n", p->CPU.MaxCoef, p->CPU.CurrCoef);
716DBG("CPU: MaxDiv/CurrDiv: 0x%x/0x%x\n", p->CPU.MaxDiv, p->CPU.CurrDiv);
717}
718
719DBG("CPU: NoCores/NoThreads: %d/%d\n", p->CPU.NoCores, p->CPU.NoThreads);
720DBG("CPU: Features: 0x%08x\n", p->CPU.Features);
721 DBG("CPU: ExtFeatures: 0x%08x\n", p->CPU.ExtFeatures);
722 DBG("CPU: MicrocodeVersion: %d\n", p->CPU.MicrocodeVersion);
723#if DEBUG_CPU
724pause();
725#endif
726
727}
728

Archive Download this file

Revision: 1468