Chameleon

Chameleon Svn Source Tree

Root/trunk/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 "platform.h"
10
11extern void scan_cpu(PlatformInfo_t *);
12
13#define CPU_STRING_UNKNOWN"Unknown CPU Type"
14
15//definitions from Apple XNU
16
17/* CPU defines */
18#define bit(n)(1ULL << (n))
19#define bitmask(h,l)((bit(h) | (bit(h)-1)) & ~(bit(l)-1))
20#define bitfield(x,h,l)(((x) & bitmask(h,l)) >> l)
21#define hbit(n)(1ULL << ((n)+32))
22#define min(a,b)((a) < (b) ? (a) : (b))
23#define quad32(hi,lo)((((uint32_t)(hi)) << 16) | (((uint32_t)(lo)) & 0xFFFF))
24#define quad64(hi,lo)((((uint64_t)(hi)) << 32) | (((uint64_t)(lo)) & 0xFFFFFFFFUL))
25
26/*
27 * The CPUID_FEATURE_XXX values define 64-bit values
28 * returned in %ecx:%edx to a CPUID request with %eax of 1:
29 */
30#define CPUID_FEATURE_FPUbit(0) /* Floating point unit on-chip */
31#define CPUID_FEATURE_VMEbit(1) /* Virtual Mode Extension */
32#define CPUID_FEATURE_DEbit(2) /* Debugging Extension */
33#define CPUID_FEATURE_PSEbit(3) /* Page Size Extension */
34#define CPUID_FEATURE_TSCbit(4) /* Time Stamp Counter */
35#define CPUID_FEATURE_MSRbit(5) /* Model Specific Registers */
36#define CPUID_FEATURE_PAEbit(6) /* Physical Address Extension */
37#define CPUID_FEATURE_MCEbit(7) /* Machine Check Exception */
38#define CPUID_FEATURE_CX8bit(8) /* CMPXCHG8B */
39#define CPUID_FEATURE_APICbit(9) /* On-chip APIC */
40#define CPUID_FEATURE_SEPbit(11) /* Fast System Call */
41#define CPUID_FEATURE_MTRRbit(12) /* Memory Type Range Register */
42#define CPUID_FEATURE_PGEbit(13) /* Page Global Enable */
43#define CPUID_FEATURE_MCAbit(14) /* Machine Check Architecture */
44#define CPUID_FEATURE_CMOVbit(15) /* Conditional Move Instruction */
45#define CPUID_FEATURE_PATbit(16) /* Page Attribute Table */
46#define CPUID_FEATURE_PSE36bit(17) /* 36-bit Page Size Extension */
47#define CPUID_FEATURE_PSNbit(18) /* Processor Serial Number */
48#define CPUID_FEATURE_CLFSHbit(19) /* CLFLUSH Instruction supported */
49#define CPUID_FEATURE_DSbit(21) /* Debug Store */
50#define CPUID_FEATURE_ACPIbit(22) /* Thermal monitor and Clock Ctrl */
51#define CPUID_FEATURE_MMXbit(23) /* MMX supported */
52#define CPUID_FEATURE_FXSRbit(24) /* Fast floating pt save/restore */
53#define CPUID_FEATURE_SSEbit(25) /* Streaming SIMD extensions */
54#define CPUID_FEATURE_SSE2bit(26) /* Streaming SIMD extensions 2 */
55#define CPUID_FEATURE_SSbit(27) /* Self-Snoop */
56#define CPUID_FEATURE_HTTbit(28) /* Hyper-Threading Technology */
57#define CPUID_FEATURE_TMbit(29) /* Thermal Monitor (TM1) */
58#define CPUID_FEATURE_PBEbit(31) /* Pend Break Enable */
59
60#define CPUID_FEATURE_SSE3hbit(0) /* Streaming SIMD extensions 3 */
61#define CPUID_FEATURE_PCLMULQDQhbit(1) /* PCLMULQDQ Instruction */
62#define CPUID_FEATURE_DTES64hbit(2) /* 64-bit DS layout */
63#define CPUID_FEATURE_MONITORhbit(3) /* Monitor/mwait */
64#define CPUID_FEATURE_DSCPLhbit(4) /* Debug Store CPL */
65#define CPUID_FEATURE_VMXhbit(5) /* VMX */
66#define CPUID_FEATURE_SMXhbit(6) /* SMX */
67#define CPUID_FEATURE_ESThbit(7) /* Enhanced SpeedsTep (GV3) */
68#define CPUID_FEATURE_TM2hbit(8) /* Thermal Monitor 2 */
69#define CPUID_FEATURE_SSSE3hbit(9) /* Supplemental SSE3 instructions */
70#define CPUID_FEATURE_CIDhbit(10) /* L1 Context ID */
71#define CPUID_FEATURE_SEGLIM64hbit(11) /* 64-bit segment limit checking */
72#define CPUID_FEATURE_FMAhbit(12) /* Fused-Multiply-Add support */
73#define CPUID_FEATURE_CX16hbit(13) /* CmpXchg16b instruction */
74#define CPUID_FEATURE_xTPRhbit(14) /* Send Task PRiority msgs */
75#define CPUID_FEATURE_PDCMhbit(15) /* Perf/Debug Capability MSR */
76
77#define CPUID_FEATURE_PCIDhbit(17) /* ASID-PCID support */
78#define CPUID_FEATURE_DCAhbit(18) /* Direct Cache Access */
79#define CPUID_FEATURE_SSE4_1hbit(19) /* Streaming SIMD extensions 4.1 */
80#define CPUID_FEATURE_SSE4_2hbit(20) /* Streaming SIMD extensions 4.2 */
81#define CPUID_FEATURE_x2APIChbit(21) /* Extended APIC Mode */
82#define CPUID_FEATURE_MOVBEhbit(22) /* MOVBE instruction */
83#define CPUID_FEATURE_POPCNThbit(23) /* POPCNT instruction */
84#define CPUID_FEATURE_TSCTMRhbit(24) /* TSC deadline timer */
85#define CPUID_FEATURE_AEShbit(25) /* AES instructions */
86#define CPUID_FEATURE_XSAVEhbit(26) /* XSAVE instructions */
87#define CPUID_FEATURE_OSXSAVEhbit(27) /* XGETBV/XSETBV instructions */
88#define CPUID_FEATURE_AVX1_0hbit(28) /* AVX 1.0 instructions */
89#define CPUID_FEATURE_F16Chbit(29) /* Float16 convert instructions */
90#define CPUID_FEATURE_RDRANDhbit(30) /* RDRAND instruction */
91#define CPUID_FEATURE_VMMhbit(31) /* VMM (Hypervisor) present */
92
93/*
94 * Leaf 7, subleaf 0 additional features.
95 * Bits returned in %ebx to a CPUID request with {%eax,%ecx} of (0x7,0x0}:
96 */
97#define CPUID_LEAF7_FEATURE_RDWRFSGSbit(0)/* FS/GS base read/write */
98#define CPUID_LEAF7_FEATURE_TSCOFFbit(1)/* TSC thread offset */
99#define CPUID_LEAF7_FEATURE_BMI1bit(3)/* Bit Manipulation Instrs, set 1 */
100#define CPUID_LEAF7_FEATURE_HLEbit(4)/* Hardware Lock Elision*/
101#define CPUID_LEAF7_FEATURE_AVX2bit(5)/* AVX2 Instructions */
102#define CPUID_LEAF7_FEATURE_SMEPbit(7)/* Supervisor Mode Execute Protect */
103#define CPUID_LEAF7_FEATURE_BMI2bit(8)/* Bit Manipulation Instrs, set 2 */
104#define CPUID_LEAF7_FEATURE_ENFSTRGbit(9)/* ENhanced Fast STRinG copy */
105#define CPUID_LEAF7_FEATURE_INVPCIDbit(10)/* INVPCID intruction, TDB */
106#define CPUID_LEAF7_FEATURE_RTMbit(11)/* TBD */
107
108/*
109 * The CPUID_EXTFEATURE_XXX values define 64-bit values
110 * returned in %ecx:%edx to a CPUID request with %eax of 0x80000001:
111 */
112#define CPUID_EXTFEATURE_SYSCALLbit(11)/* SYSCALL/sysret */
113#define CPUID_EXTFEATURE_XDbit(20)/* eXecute Disable */
114
115#define CPUID_EXTFEATURE_1GBPAGEbit(26)/* 1GB pages support */
116#define CPUID_EXTFEATURE_RDTSCPbit(27)/* RDTSCP */
117#define CPUID_EXTFEATURE_EM64Tbit(29)/* Extended Mem 64 Technology */
118
119
120
121#define CPUID_EXTFEATURE_LAHFhbit(0)/* LAFH/SAHF instructions */
122
123/*
124 * The CPUID_EXTFEATURE_XXX values define 64-bit values
125 * returned in %ecx:%edx to a CPUID request with %eax of 0x80000007:
126 */
127#define CPUID_EXTFEATURE_TSCIbit(8)/* TSC Invariant */
128
129#defineCPUID_CACHE_SIZE16/* Number of descriptor values */
130
131#define CPUID_MWAIT_EXTENSIONbit(0)/* enumeration of WMAIT extensions */
132#define CPUID_MWAIT_BREAKbit(1)/* interrupts are break events */
133
134//-- processor type -> p_type:
135#define PT_OEM0x00// Intel Original OEM Processor;
136#define PT_OD0x01 // Intel Over Drive Processor;
137#define PT_DUAL0x02// Intel Dual Processor;
138#define PT_RES0x03// Intel Reserved;
139
140/* Known MSR registers */
141#define MSR_IA32_PLATFORM_ID0x0017
142#define IA32_APIC_BASE0x001B /* used also for AMD */
143#define MSR_CORE_THREAD_COUNT0x0035/* limited use - not for Penryn or older */
144#define IA32_TSC_ADJUST0x003B
145#define MSR_IA32_BIOS_SIGN_ID0x008B/* microcode version */
146#define MSR_FSB_FREQ0x00CD/* limited use - not for i7 */
147#defineMSR_PLATFORM_INFO0x00CE/* limited use - MinRatio for i7 but Max for Yonah*/
148/* turbo for penryn */
149#define MSR_PKG_CST_CONFIG_CONTROL0x00E2// sandy and ivy
150#define MSR_PMG_IO_CAPTURE_BASE0x00E4
151#define IA32_MPERF0x00E7// TSC in C0 only
152#define IA32_APERF0x00E8// actual clocks in C0
153#define MSR_IA32_EXT_CONFIG0x00EE// limited use - not for i7
154#define MSR_FLEX_RATIO0x0194// limited use - not for Penryn or older
155//see no value on most CPUs
156#defineMSR_IA32_PERF_STATUS0x0198
157#define MSR_IA32_PERF_CONTROL0x0199
158#define MSR_IA32_CLOCK_MODULATION0x019A
159#define MSR_THERMAL_STATUS0x019C
160#define MSR_IA32_MISC_ENABLE0x01A0
161#define MSR_THERMAL_TARGET0x01A2// TjMax limited use - not for Penryn or older
162#define MSR_MISC_PWR_MGMT0x01AA
163#define MSR_TURBO_RATIO_LIMIT0x01AD// limited use - not for Penryn or older
164
165#define IA32_ENERGY_PERF_BIAS0x01B0
166#define MSR_PACKAGE_THERM_STATUS0x01B1
167#define IA32_PLATFORM_DCA_CAP0x01F8
168#define MSR_POWER_CTL0x01FC// MSR 000001FC 0000-0000-0004-005F
169
170// Sandy Bridge & JakeTown specific 'Running Average Power Limit' MSR's.
171#define MSR_RAPL_POWER_UNIT0x606// R/O
172//MSR 00000606 0000-0000-000A-1003
173#define MSR_PKGC3_IRTL0x60A// RW time limit to go C3
174// bit 15 = 1 -- the value valid for C-state PM
175#define MSR_PKGC6_IRTL0x60B// RW time limit to go C6
176//MSR 0000060B 0000-0000-0000-8854
177//Valid + 010=1024ns + 0x54=84mks
178#define MSR_PKGC7_IRTL0x60C// RW time limit to go C7
179//MSR 0000060C 0000-0000-0000-8854
180#define MSR_PKG_C2_RESIDENCY0x60D// same as TSC but in C2 only
181
182#define MSR_PKG_RAPL_POWER_LIMIT0x610//MSR 00000610 0000-A580-0000-8960
183#define MSR_PKG_ENERGY_STATUS0x611//MSR 00000611 0000-0000-3212-A857
184#define MSR_PKG_POWER_INFO0x614//MSR 00000614 0000-0000-01E0-02F8
185
186// Sandy Bridge IA (Core) domain MSR's.
187#define MSR_PP0_POWER_LIMIT0x638
188#define MSR_PP0_ENERGY_STATUS0x639
189#define MSR_PP0_POLICY0x63A
190#define MSR_PP0_PERF_STATUS0x63B
191
192// Sandy Bridge Uncore (IGPU) domain MSR's (Not on JakeTown).
193#define MSR_PP1_POWER_LIMIT0x640
194#define MSR_PP1_ENERGY_STATUS 0x641
195//MSR 00000641 0000-0000-0000-0000
196#define MSR_PP1_POLICY0x642
197
198// JakeTown only Memory MSR's.
199#define MSR_PKG_PERF_STATUS0x613
200#define MSR_DRAM_POWER_LIMIT 0x618
201#define MSR_DRAM_ENERGY_STATUS0x619
202#define MSR_DRAM_PERF_STATUS0x61B
203#define MSR_DRAM_POWER_INFO0x61C
204
205//IVY_BRIDGE
206#define MSR_CONFIG_TDP_NOMINAL0x648
207#define MSR_CONFIG_TDP_LEVEL10x649
208#define MSR_CONFIG_TDP_LEVEL20x64A
209#define MSR_CONFIG_TDP_CONTROL0x64B// write once to lock
210#define MSR_TURBO_ACTIVATION_RATIO0x64C
211
212//AMD
213#define K8_FIDVID_STATUS0xC0010042
214#define K10_COFVID_LIMIT0xC0010061// max enabled p-state (msr >> 4) & 7
215#define K10_COFVID_CONTROL0xC0010062// switch to p-state
216#define K10_PSTATE_STATUS0xC0010064
217#define K10_COFVID_STATUS0xC0010071// current p-state (msr >> 16) & 7
218
219#define MSR_AMD_MPERF0x000000E7
220#define MSR_AMD_APERF0x000000E8
221
222#define DEFAULT_FSB100000 /* for now, hardcoding 100MHz for old CPUs */
223
224// DFE: This constant comes from older xnu:
225#define CLKNUM1193182/* formerly 1193167 */
226
227// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM
228#define CALIBRATE_TIME_MSEC30/* 30 msecs */
229#define CALIBRATE_LATCH((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)
230
231static inline uint64_t rdtsc64(void)
232{
233uint64_t ret;
234__asm__ volatile("rdtsc" : "=A" (ret));
235return ret;
236}
237
238static inline uint64_t rdmsr64(uint32_t msr)
239{
240 uint64_t ret;
241 __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
242 return ret;
243}
244
245static inline void wrmsr64(uint32_t msr, uint64_t val)
246{
247__asm__ volatile("wrmsr" : : "c" (msr), "A" (val));
248}
249
250static inline void intel_waitforsts(void) {
251uint32_t inline_timeout = 100000;
252while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; }
253}
254
255/* From Apple's cpuid.h */
256typedef enum { eax, ebx, ecx, edx } cpuid_register_t;
257
258static inline void cpuid(uint32_t *data)
259{
260asm(
261"cpuid" : "=a" (data[eax]),
262"=b" (data[ebx]),
263"=c" (data[ecx]),
264"=d" (data[edx]) : "a" (data[eax]),
265"b" (data[ebx]),
266"c" (data[ecx]),
267"d" (data[edx]));
268}
269
270static inline void do_cpuid(uint32_t selector, uint32_t *data)
271{
272asm(
273"cpuid" : "=a" (data[eax]),
274"=b" (data[ebx]),
275"=c" (data[ecx]),
276"=d" (data[edx]) : "a"(selector),
277"b" (0),
278"c" (0),
279"d" (0));
280}
281
282static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)
283{
284asm volatile (
285"cpuid" : "=a" (data[eax]),
286"=b" (data[ebx]),
287"=c" (data[ecx]),
288"=d" (data[edx]) : "a" (selector),
289"b" (0),
290"c" (selector2),
291"d" (0));
292}
293
294// DFE: enable_PIT2 and disable_PIT2 come from older xnu
295
296/*
297 * Enable or disable timer 2.
298 * Port 0x61 controls timer 2:
299 * bit 0 gates the clock,
300 * bit 1 gates output to speaker.
301 */
302static inline void enable_PIT2(void)
303{
304 /* Enable gate, disable speaker */
305 __asm__ volatile(
306 " inb $0x61,%%al \n\t"
307 " and $0xFC,%%al \n\t" /* & ~0x03 */
308 " or $1,%%al \n\t"
309 " outb %%al,$0x61 \n\t"
310 : : : "%al" );
311}
312
313static inline void disable_PIT2(void)
314{
315 /* Disable gate and output to speaker */
316 __asm__ volatile(
317 " inb $0x61,%%al \n\t"
318 " and $0xFC,%%al \n\t"/* & ~0x03 */
319 " outb %%al,$0x61 \n\t"
320 : : : "%al" );
321}
322
323// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
324// roughly based on Linux code
325
326/* Set the 8254 channel 2 to mode 0 with the specified value.
327 In mode 0, the counter will initially set its gate low when the
328 timer expires. For this to be useful, you ought to set it high
329 before calling this function. The enable_PIT2 function does this.
330 */
331static inline void set_PIT2_mode0(uint16_t value)
332{
333 __asm__ volatile(
334 " movb $0xB0,%%al \n\t"
335 " outb%%al,$0x43\n\t"
336 " movb%%dl,%%al\n\t"
337 " outb%%al,$0x42\n\t"
338 " movb%%dh,%%al\n\t"
339 " outb%%al,$0x42"
340 : : "d"(value) /*: no clobber */ );
341}
342
343/* Returns the number of times the loop ran before the PIT2 signaled */
344static inline unsigned long poll_PIT2_gate(void)
345{
346 unsigned long count = 0;
347 unsigned char nmi_sc_val;
348 do {
349 ++count;
350 __asm__ volatile(
351 "inb$0x61,%0"
352 : "=a"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
353 } while( (nmi_sc_val & 0x20) == 0);
354 return count;
355}
356
357inline static void
358set_PIT2(int value)
359{
360/*
361 * First, tell the clock we are going to write 16 bits to the counter
362 * and enable one-shot mode (command 0xB8 to port 0x43)
363 * Then write the two bytes into the PIT2 clock register (port 0x42).
364 * Loop until the value is "realized" in the clock,
365 * this happens on the next tick.
366 */
367 asm volatile(
368 " movb $0xB8,%%al \n\t"
369 " outb %%al,$0x43 \n\t"
370 " movb %%dl,%%al \n\t"
371 " outb %%al,$0x42 \n\t"
372 " movb %%dh,%%al \n\t"
373 " outb %%al,$0x42 \n"
374"1: inb $0x42,%%al \n\t"
375 " inb $0x42,%%al \n\t"
376 " cmp %%al,%%dh \n\t"
377 " jne 1b"
378 : : "d"(value) : "%al");
379}
380
381
382inline static uint64_t
383get_PIT2(unsigned int *value)
384{
385 register uint64_t result;
386/*
387 * This routine first latches the time (command 0x80 to port 0x43),
388 * then gets the time stamp so we know how long the read will take later.
389 * Read (from port 0x42) and return the current value of the timer.
390 */
391#ifdef __i386__
392 asm volatile(
393 " xorl %%ecx,%%ecx \n\t"
394 " movb $0x80,%%al \n\t"
395 " outb %%al,$0x43 \n\t"
396 " rdtsc \n\t"
397 " pushl %%eax \n\t"
398 " inb $0x42,%%al \n\t"
399 " movb %%al,%%cl \n\t"
400 " inb $0x42,%%al \n\t"
401 " movb %%al,%%ch \n\t"
402 " popl %%eax "
403 : "=A"(result), "=c"(*value));
404#else /* __x86_64__ */
405 asm volatile(
406" xorq %%rcx,%%rcx \n\t"
407" movb $0x80,%%al \n\t"
408" outb %%al,$0x43 \n\t"
409" rdtsc \n\t"
410" pushq %%rax \n\t"
411" inb $0x42,%%al \n\t"
412" movb %%al,%%cl \n\t"
413" inb $0x42,%%al \n\t"
414" movb %%al,%%ch \n\t"
415" popq %%rax "
416: "=A"(result), "=c"(*value));
417#endif
418
419 return result;
420}
421
422#endif /* !__LIBSAIO_CPU_H */
423

Archive Download this file

Revision: 2547