Chameleon

Chameleon Svn Source Tree

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

Archive Download this file

Revision: 757