Chameleon

Chameleon Svn Source Tree

Root/branches/azimutz/Chazi/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#define bit(n)(1UL << (n))
14#define bitmask(h,l)((bit(h)|(bit(h)-1)) & ~(bit(l)-1))
15#define bitfield(x,h,l)(((x) & bitmask(h,l)) >> l)
16
17#define CPU_STRING_UNKNOWN"Unknown CPU Type"
18
19#defineMSR_IA32_PERF_STATUS0x198
20#define MSR_IA32_PERF_CONTROL0x199
21#define MSR_IA32_EXT_CONFIG0x00EE
22#define MSR_FLEX_RATIO0x194
23#define MSR_TURBO_RATIO_LIMIT0x1AD
24#defineMSR_PLATFORM_INFO0xCE
25#define K8_FIDVID_STATUS0xC0010042
26#define K10_COFVID_STATUS0xC0010071
27#define MSR_CORE_THREAD_COUNT0x35// Undocumented
28
29//#define DEFAULT_FSB100000 // for now, hardcoding 100MHz for old CPUs - disabled
30
31// DFE: This constant comes from older xnu:
32#define CLKNUM1193182/* formerly 1193167 */
33
34// DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM
35#define CALIBRATE_TIME_MSEC30/* 30 msecs */
36#define CALIBRATE_LATCH((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)
37
38static inline uint64_t rdtsc64(void)
39{
40uint64_t ret;
41__asm__ volatile("rdtsc" : "=A" (ret));
42return ret;
43}
44
45static inline uint64_t rdmsr64(uint32_t msr)
46{
47 uint64_t ret;
48 __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
49 return ret;
50}
51
52static inline void wrmsr64(uint32_t msr, uint64_t val)
53{
54__asm__ volatile("wrmsr" : : "c" (msr), "A" (val));
55}
56
57static inline void intel_waitforsts(void) {
58uint32_t inline_timeout = 100000;
59while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; }
60}
61
62static inline void do_cpuid(uint32_t selector, uint32_t *data)
63{
64asm volatile ("cpuid"
65 : "=a" (data[0]),
66 "=b" (data[1]),
67 "=c" (data[2]),
68 "=d" (data[3])
69 : "a" (selector));
70}
71
72static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)
73{
74asm volatile ("cpuid"
75 : "=a" (data[0]),
76 "=b" (data[1]),
77 "=c" (data[2]),
78 "=d" (data[3])
79 : "a" (selector), "c" (selector2));
80}
81
82// DFE: enable_PIT2 and disable_PIT2 come from older xnu
83
84/*
85 * Enable or disable timer 2.
86 * Port 0x61 controls timer 2:
87 * bit 0 gates the clock,
88 * bit 1 gates output to speaker.
89 */
90static inline void enable_PIT2(void)
91{
92 /* Enable gate, disable speaker */
93 __asm__ volatile(
94 " inb $0x61,%%al \n\t"
95 " and $0xFC,%%al \n\t" /* & ~0x03 */
96 " or $1,%%al \n\t"
97 " outb %%al,$0x61 \n\t"
98 : : : "%al" );
99}
100
101static inline void disable_PIT2(void)
102{
103 /* Disable gate and output to speaker */
104 __asm__ volatile(
105 " inb $0x61,%%al \n\t"
106 " and $0xFC,%%al \n\t"/* & ~0x03 */
107 " outb %%al,$0x61 \n\t"
108 : : : "%al" );
109}
110
111// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
112// roughly based on Linux code
113
114/* Set the 8254 channel 2 to mode 0 with the specified value.
115 In mode 0, the counter will initially set its gate low when the
116 timer expires. For this to be useful, you ought to set it high
117 before calling this function. The enable_PIT2 function does this.
118 */
119static inline void set_PIT2_mode0(uint16_t value)
120{
121 __asm__ volatile(
122 " movb $0xB0,%%al \n\t"
123 " outb%%al,$0x43\n\t"
124 " movb%%dl,%%al\n\t"
125 " outb%%al,$0x42\n\t"
126 " movb%%dh,%%al\n\t"
127 " outb%%al,$0x42"
128 : : "d"(value) /*: no clobber */ );
129}
130
131/* Returns the number of times the loop ran before the PIT2 signaled */
132static inline unsigned long poll_PIT2_gate(void)
133{
134 unsigned long count = 0;
135 unsigned char nmi_sc_val;
136 do {
137 ++count;
138 __asm__ volatile(
139 "inb$0x61,%0"
140 : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
141 } while( (nmi_sc_val & 0x20) == 0);
142 return count;
143}
144
145#endif /* !__LIBSAIO_CPU_H */
146

Archive Download this file

Revision: 842