Chameleon

Chameleon Svn Source Tree

Root/branches/valv/i386/libsaio/cpu.h

  • Property svn:executable set to
1/*
2 * Copyright 2008 Islam Ahmed Zaid. All rights reserved. <azismed@gmail.com>
3 * AsereBLN: 2009: cleanup and bugfix
4 * valv: 2010: fine-tuning and additions
5 */
6
7#ifndef __LIBSAIO_CPU_H
8#define __LIBSAIO_CPU_H
9
10#include "libsaio.h"
11
12extern void scan_cpu(PlatformInfo_t *);
13
14#define bit(n)(1UL << (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
18#define CPU_STRING_UNKNOWN"Unknown CPU Type"
19
20#define MSR_FSB_FREQ 0xCD
21#define MSR_EBC_FREQUENCY_ID 0x2C
22#define MSR_TURBO_RATIO_LIMIT 0x1AD
23#define MSR_IA32_PLATFORM_ID 0x17
24#defineMSR_IA32_PERF_STATUS 0x198
25#define MSR_IA32_PERF_CONTROL 0x199
26#define MSR_IA32_EXT_CONFIG 0xEE
27#define MSR_FLEX_RATIO 0x194
28#defineMSR_PLATFORM_INFO 0xCE
29#define MSR_IA32_MISC_ENABLE 0x1A0
30#define MSR_THERMAL_STATUS 0x19C
31#define MSR_IA32_CLOCK_MODULATION 0x19A
32#define MSR_THERMAL_TARGET 0x01A2
33#define PIC_SENS_CFG 0x1aa
34#define MSR_EBL_CR_POWERON 0x02a
35#define K8_FIDVID_STATUS 0xC0010042
36#defineMSR_AMD_10H_11H_LIMIT 0xc0010061
37#defineAMD_10H_11H_CONFIG 0xc0010064
38#define K10_COFVID_STATUS 0xC0010071
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
49static inline uint64_t rdtsc64(void)
50{
51uint64_t ret;
52__asm__ volatile("rdtsc" : "=A" (ret));
53return ret;
54}
55
56static inline uint64_t rdmsr64(uint32_t msr)
57{
58 uint64_t ret;
59 __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));
60 return ret;
61}
62
63static inline void wrmsr64(uint32_t msr, uint64_t val)
64{
65__asm__ volatile("wrmsr" : : "c" (msr), "A" (val));
66}
67
68typedef struct msr_struct
69{
70unsigned lo;
71unsigned hi;
72} msr_t;
73
74static inline __attribute__((always_inline)) msr_t rdmsr(unsigned val)
75{
76msr_t ret;
77__asm__ volatile(
78"rdmsr"
79: "=a" (ret.lo), "=d" (ret.hi)
80: "c" (val)
81);
82return ret;
83}
84
85static inline __attribute__((always_inline)) void wrmsr(unsigned val, msr_t msr)
86{
87__asm__ __volatile__ (
88"wrmsr"
89: /* No outputs */
90: "c" (val), "a" (msr.lo), "d" (msr.hi)
91);
92}
93
94static inline void intel_waitforsts(void) {
95uint32_t inline_timeout = 100000;
96while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; }
97}
98
99static inline void do_cpuid(uint32_t selector, uint32_t *data)
100{
101asm volatile ("cpuid"
102 : "=a" (data[0]),
103 "=b" (data[1]),
104 "=c" (data[2]),
105 "=d" (data[3])
106 : "a" (selector));
107}
108
109static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)
110{
111asm volatile ("cpuid"
112 : "=a" (data[0]),
113 "=b" (data[1]),
114 "=c" (data[2]),
115 "=d" (data[3])
116 : "a" (selector), "c" (selector2));
117}
118
119// DFE: enable_PIT2 and disable_PIT2 come from older xnu
120
121/*
122 * Enable or disable timer 2.
123 * Port 0x61 controls timer 2:
124 * bit 0 gates the clock,
125 * bit 1 gates output to speaker.
126 */
127static inline void enable_PIT2(void)
128{
129 /* Enable gate, disable speaker */
130 __asm__ volatile(
131 " inb $0x61,%%al \n\t"
132 " and $0xFC,%%al \n\t" /* & ~0x03 */
133 " or $1,%%al \n\t"
134 " outb %%al,$0x61 \n\t"
135 : : : "%al" );
136}
137
138static inline void disable_PIT2(void)
139{
140 /* Disable gate and output to speaker */
141 __asm__ volatile(
142 " inb $0x61,%%al \n\t"
143 " and $0xFC,%%al \n\t"/* & ~0x03 */
144 " outb %%al,$0x61 \n\t"
145 : : : "%al" );
146}
147
148// DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are
149// roughly based on Linux code
150
151/* Set the 8254 channel 2 to mode 0 with the specified value.
152 In mode 0, the counter will initially set its gate low when the
153 timer expires. For this to be useful, you ought to set it high
154 before calling this function. The enable_PIT2 function does this.
155 */
156static inline void set_PIT2_mode0(uint16_t value)
157{
158 __asm__ volatile(
159 " movb $0xB0,%%al \n\t"
160 " outb%%al,$0x43\n\t"
161 " movb%%dl,%%al\n\t"
162 " outb%%al,$0x42\n\t"
163 " movb%%dh,%%al\n\t"
164 " outb%%al,$0x42"
165 : : "d"(value) /*: no clobber */ );
166}
167
168/* Returns the number of times the loop ran before the PIT2 signaled */
169static inline unsigned long poll_PIT2_gate(void)
170{
171 unsigned long count = 0;
172 unsigned char nmi_sc_val;
173 do {
174 ++count;
175 __asm__ volatile(
176 "inb$0x61,%0"
177 : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);
178 } while( (nmi_sc_val & 0x20) == 0);
179 return count;
180}
181
182#endif /* !__LIBSAIO_CPU_H */
183

Archive Download this file

Revision: 705