Chameleon

Chameleon Svn Source Tree

Root/branches/slice/trunkM/i386/libsaio/cpu.h

1/*
2 * Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
3 * AsereBLN: 2009: cleanup and bugfix
4 */
5
6#ifndef __LIBSAIO_CPU_H
7#define __LIBSAIO_CPU_H
8
9//#include "libsaio.h"
10
11extern void scan_cpu(PlatformInfo_t *);
12
13#ifndef bit
14#define bit(n)(1ULL << (n))
15#define bitmask(h,l)((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
16#define bitfield(x,h,l)(((x) & bitmask(h,l)) >> l)
17#endif
18
19#define CPU_STRING_UNKNOWN"Unknown CPU Type"
20
21
22
23#define MSR_IA32_PLATFORM_ID0x0017
24#define MSR_P4_EBC_FREQUENCY_ID0x002C
25#defineMSR_IA32_PERF_STATUS0x0198
26#define MSR_IA32_PERF_CONTROL0x0199
27#define MSR_IA32_EXT_CONFIG0x00EE
28#define MSR_FLEX_RATIO0x0194
29#define MSR_TURBO_RATIO_LIMIT0x01AD
30#defineMSR_PLATFORM_INFO0x00CE
31#define MSR_CORE_THREAD_COUNT0x0035// Undocumented
32
33#define K8_FIDVID_STATUS0xC0010042
34#define K10_COFVID_STATUS0xC0010071
35
36#define MSR_AMD_MPERF 0x000000E7
37#define MSR_AMD_APERF 0x000000E8
38
39
40#define DEFAULT_FSB100000 /* for now, hardcoding 100MHz for old CPUs */
41
42// DFE: This constant comes from older xnu:
43#define CLKNUM1193182/* formerly 1193167 */
44
45// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM
46#define CALIBRATE_TIME_MSEC30/* 30 msecs */
47#define CALIBRATE_LATCH((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)
48
49// CPUID Values
50#define CPUID_MODEL_YONAH14// Intel Mobile Core Solo, Duo
51#define CPUID_MODEL_MEROM15// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx
52#define CPUID_MODEL_PENRYN23// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx
53#define CPUID_MODEL_NEHALEM26// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)
54#define CPUID_MODEL_ATOM28// Intel Atom (45nm)
55#define CPUID_MODEL_FIELDS30// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)
56#define CPUID_MODEL_DALES31// Havendale, Auburndale
57#define CPUID_MODEL_DALES_32NM37// Intel Core i3, i5 LGA1156 (32nm)
58#define CPUID_MODEL_SANDY42// Intel Core i3, i5, i7 LGA1155 (32nm)
59#define CPUID_MODEL_WESTMERE44// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core
60#define CPUID_MODEL_NEHALEM_EX46// Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65x
61#define CPUID_MODEL_WESTMERE_EX47// Intel Xeon E7
62
63
64static inline uint64_t rdtsc64(void)
65{
66uint64_t ret;
67__asm__ volatile("rdtsc" : "=A" (ret));
68return ret;
69}
70
71static inline uint64_t rdmsr64(uint32_t msr)
72{
73 uint64_t ret;
74 __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
75 return ret;
76}
77
78static inline void wrmsr64(uint32_t msr, uint64_t val)
79{
80__asm__ volatile("wrmsr" : : "c" (msr), "A" (val));
81}
82
83static inline void intel_waitforsts(void) {
84uint32_t inline_timeout = 100000;
85while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; }
86}
87
88static inline void do_cpuid(uint32_t selector, uint32_t *data)
89{
90asm volatile ("cpuid"
91 : "=a" (data[0]),
92 "=b" (data[1]),
93 "=c" (data[2]),
94 "=d" (data[3])
95 : "a" (selector));
96}
97
98static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)
99{
100asm volatile ("cpuid"
101 : "=a" (data[0]),
102 "=b" (data[1]),
103 "=c" (data[2]),
104 "=d" (data[3])
105 : "a" (selector), "c" (selector2));
106}
107
108// DFE: enable_PIT2 and disable_PIT2 come from older xnu
109
110/*
111 * Enable or disable timer 2.
112 * Port 0x61 controls timer 2:
113 * bit 0 gates the clock,
114 * bit 1 gates output to speaker.
115 */
116static inline void enable_PIT2(void)
117{
118 /* Enable gate, disable speaker */
119 __asm__ volatile(
120 " inb $0x61,%%al \n\t"
121 " and $0xFC,%%al \n\t" /* & ~0x03 */
122 " or $1,%%al \n\t"
123 " outb %%al,$0x61 \n\t"
124 : : : "%al" );
125}
126
127static inline void disable_PIT2(void)
128{
129 /* Disable gate and output to speaker */
130 __asm__ volatile(
131 " inb $0x61,%%al \n\t"
132 " and $0xFC,%%al \n\t"/* & ~0x03 */
133 " outb %%al,$0x61 \n\t"
134 : : : "%al" );
135}
136
137// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
138// roughly based on Linux code
139
140/* Set the 8254 channel 2 to mode 0 with the specified value.
141 In mode 0, the counter will initially set its gate low when the
142 timer expires. For this to be useful, you ought to set it high
143 before calling this function. The enable_PIT2 function does this.
144 */
145static inline void set_PIT2_mode0(uint16_t value)
146{
147 __asm__ volatile(
148 " movb $0xB0,%%al \n\t"
149 " outb%%al,$0x43\n\t"
150 " movb%%dl,%%al\n\t"
151 " outb%%al,$0x42\n\t"
152 " movb%%dh,%%al\n\t"
153 " outb%%al,$0x42"
154 : : "d"(value) /*: no clobber */ );
155}
156
157/* Returns the number of times the loop ran before the PIT2 signaled */
158static inline unsigned long poll_PIT2_gate(void)
159{
160 unsigned long count = 0;
161 unsigned char nmi_sc_val;
162 do {
163 ++count;
164 __asm__ volatile(
165 "inb$0x61,%0"
166 : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
167 } while( (nmi_sc_val & 0x20) == 0);
168 return count;
169}
170
171#endif /* !__LIBSAIO_CPU_H */
172

Archive Download this file

Revision: 1207