Root/
Source at commit 2381 created 10 years 21 days ago. By ifabio, Apply patch: (Credits to Thomas Jansen aka tja) - Reading options from all devices during boot. The options for the boot menu are only read from the devices rd(0,0) or bt(0,0). Consequently, boot menu options (e.g. "Quiet Boot", "Timeout", etc.) in plists on other devices (like most users have) are ignored. This patch extends the list of paths to search for the options plist on all devices that can be found. | |
---|---|
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 | ␊ |
11 | extern void scan_cpu(PlatformInfo_t *);␊ |
12 | ␊ |
13 | #define bit(n)␉␉␉(1ULL << (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 | #define␉MSR_IA32_PERF_STATUS␉0x00000198␊ |
20 | #define MSR_IA32_PERF_CONTROL␉0x199␊ |
21 | #define MSR_IA32_EXT_CONFIG␉␉0x00EE␊ |
22 | #define MSR_FLEX_RATIO␉␉␉0x194␊ |
23 | #define MSR_TURBO_RATIO_LIMIT␉0x1AD␊ |
24 | #define␉MSR_PLATFORM_INFO␉␉0xCE␊ |
25 | #define MSR_CORE_THREAD_COUNT␉0x35␉␉␉// Undocumented␊ |
26 | #define MSR_IA32_PLATFORM_ID␉0x17␊ |
27 | ␊ |
28 | #define K8_FIDVID_STATUS␉␉0xC0010042␊ |
29 | #define K10_COFVID_STATUS␉␉0xC0010071␊ |
30 | ␊ |
31 | #define MSR_AMD_MPERF 0x000000E7␊ |
32 | #define MSR_AMD_APERF 0x000000E8␊ |
33 | ␊ |
34 | #define DEFAULT_FSB␉␉100000 /* for now, hardcoding 100MHz for old CPUs */␊ |
35 | ␊ |
36 | // DFE: This constant comes from older xnu:␊ |
37 | #define CLKNUM␉␉␉1193182␉␉/* formerly 1193167 */␊ |
38 | ␊ |
39 | // DFE: These two constants come from Linux except CLOCK_TICK_RATE replaced with CLKNUM␊ |
40 | #define CALIBRATE_TIME_MSEC␉30␉␉/* 30 msecs */␊ |
41 | #define CALIBRATE_LATCH␉␉((CLKNUM * CALIBRATE_TIME_MSEC + 1000/2)/1000)␊ |
42 | ␊ |
43 | // CPUID Values␊ |
44 | #define CPUID_MODEL_YONAH␉␉14␉// Intel Mobile Core Solo, Duo␊ |
45 | #define CPUID_MODEL_MEROM␉␉15␉// Intel Mobile Core 2 Solo, Duo, Xeon 30xx, Xeon 51xx, Xeon X53xx, Xeon E53xx, Xeon X32xx␊ |
46 | #define CPUID_MODEL_PENRYN␉␉23␉// Intel Core 2 Solo, Duo, Quad, Extreme, Xeon X54xx, Xeon X33xx␊ |
47 | #define CPUID_MODEL_NEHALEM␉␉26␉// Intel Core i7, Xeon W35xx, Xeon X55xx, Xeon E55xx LGA1366 (45nm)␊ |
48 | #define CPUID_MODEL_ATOM␉␉28␉// Intel Atom (45nm)␊ |
49 | #define CPUID_MODEL_FIELDS␉␉30␉// Intel Core i5, i7, Xeon X34xx LGA1156 (45nm)␊ |
50 | #define CPUID_MODEL_DALES␉␉31␉// Havendale, Auburndale␊ |
51 | #define CPUID_MODEL_DALES_32NM␉37␉// Intel Core i3, i5 LGA1156 (32nm)␊ |
52 | #define CPUID_MODEL_SANDYBRIDGE␉42␉// Intel Core i3, i5, i7 LGA1155 (32nm)␊ |
53 | #define CPUID_MODEL_WESTMERE␉44␉// Intel Core i7, Xeon X56xx, Xeon E56xx, Xeon W36xx LGA1366 (32nm) 6 Core␊ |
54 | #define CPUID_MODEL_JAKETOWN␉45␉// Intel Xeon E5 LGA2011 (22nm)␊ |
55 | #define CPUID_MODEL_NEHALEM_EX␉46␉// Intel Xeon X75xx, Xeon X65xx, Xeon E75xx, Xeon E65x␊ |
56 | #define CPUID_MODEL_WESTMERE_EX␉47␉// Intel Xeon E7␊ |
57 | #define CPUID_MODEL_IVYBRIDGE␉58␉// Intel Core i5, i7 LGA1155 (22nm)␊ |
58 | ␊ |
59 | ␊ |
60 | static inline uint64_t rdtsc64(void)␊ |
61 | {␊ |
62 | ␉uint64_t ret;␊ |
63 | ␉__asm__ volatile("rdtsc" : "=A" (ret));␊ |
64 | ␉return ret;␊ |
65 | }␊ |
66 | ␊ |
67 | static inline uint64_t rdmsr64(uint32_t msr)␊ |
68 | {␊ |
69 | uint64_t ret;␊ |
70 | __asm__ volatile("rdmsr" : "=A" (ret) : "c" (msr));␊ |
71 | return ret;␊ |
72 | }␊ |
73 | ␊ |
74 | static inline void wrmsr64(uint32_t msr, uint64_t val)␊ |
75 | {␊ |
76 | ␉__asm__ volatile("wrmsr" : : "c" (msr), "A" (val));␊ |
77 | }␊ |
78 | ␊ |
79 | static inline void intel_waitforsts(void) {␊ |
80 | ␉uint32_t inline_timeout = 100000;␊ |
81 | ␉while (rdmsr64(MSR_IA32_PERF_STATUS) & (1 << 21)) { if (!inline_timeout--) break; }␊ |
82 | }␊ |
83 | ␊ |
84 | static inline void do_cpuid(uint32_t selector, uint32_t *data)␊ |
85 | {␊ |
86 | ␉asm volatile ("cpuid"␊ |
87 | ␉␉␉␉ : "=a" (data[0]),␊ |
88 | ␉␉␉␉ "=b" (data[1]),␊ |
89 | ␉␉␉␉ "=c" (data[2]),␊ |
90 | ␉␉␉␉ "=d" (data[3])␊ |
91 | ␉␉␉␉ : "a" (selector));␊ |
92 | }␊ |
93 | ␊ |
94 | static inline void do_cpuid2(uint32_t selector, uint32_t selector2, uint32_t *data)␊ |
95 | {␊ |
96 | ␉asm volatile ("cpuid"␊ |
97 | ␉␉␉␉ : "=a" (data[0]),␊ |
98 | ␉␉␉␉ "=b" (data[1]),␊ |
99 | ␉␉␉␉ "=c" (data[2]),␊ |
100 | ␉␉␉␉ "=d" (data[3])␊ |
101 | ␉␉␉␉ : "a" (selector), "c" (selector2));␊ |
102 | }␊ |
103 | ␊ |
104 | // DFE: enable_PIT2 and disable_PIT2 come from older xnu␊ |
105 | ␊ |
106 | /*␊ |
107 | * Enable or disable timer 2.␊ |
108 | * Port 0x61 controls timer 2:␊ |
109 | * bit 0 gates the clock,␊ |
110 | * bit 1 gates output to speaker.␊ |
111 | */␊ |
112 | static inline void enable_PIT2(void)␊ |
113 | {␊ |
114 | /* Enable gate, disable speaker */␊ |
115 | __asm__ volatile(␊ |
116 | ␉␉␉␉␉ " inb $0x61,%%al \n\t"␊ |
117 | ␉␉␉␉␉ " and $0xFC,%%al \n\t" /* & ~0x03 */␊ |
118 | ␉␉␉␉␉ " or $1,%%al \n\t"␊ |
119 | ␉␉␉␉␉ " outb %%al,$0x61 \n\t"␊ |
120 | ␉␉␉␉␉ : : : "%al" );␊ |
121 | }␊ |
122 | ␊ |
123 | static inline void disable_PIT2(void)␊ |
124 | {␊ |
125 | /* Disable gate and output to speaker */␊ |
126 | __asm__ volatile(␊ |
127 | ␉␉␉␉␉ " inb $0x61,%%al \n\t"␊ |
128 | ␉␉␉␉␉ " and $0xFC,%%al \n\t"␉/* & ~0x03 */␊ |
129 | ␉␉␉␉␉ " outb %%al,$0x61 \n\t"␊ |
130 | ␉␉␉␉␉ : : : "%al" );␊ |
131 | }␊ |
132 | ␊ |
133 | // DFE: set_PIT2_mode0, poll_PIT2_gate, and measure_tsc_frequency are␊ |
134 | // roughly based on Linux code␊ |
135 | ␊ |
136 | /* Set the 8254 channel 2 to mode 0 with the specified value.␊ |
137 | In mode 0, the counter will initially set its gate low when the␊ |
138 | timer expires. For this to be useful, you ought to set it high␊ |
139 | before calling this function. The enable_PIT2 function does this.␊ |
140 | */␊ |
141 | static inline void set_PIT2_mode0(uint16_t value)␊ |
142 | {␊ |
143 | __asm__ volatile(␊ |
144 | ␉␉␉␉␉ " movb $0xB0,%%al \n\t"␊ |
145 | ␉␉␉␉␉ " outb␉%%al,$0x43␉\n\t"␊ |
146 | ␉␉␉␉␉ " movb␉%%dl,%%al␉\n\t"␊ |
147 | ␉␉␉␉␉ " outb␉%%al,$0x42␉\n\t"␊ |
148 | ␉␉␉␉␉ " movb␉%%dh,%%al␉\n\t"␊ |
149 | ␉␉␉␉␉ " outb␉%%al,$0x42"␊ |
150 | ␉␉␉␉␉ : : "d"(value) /*: no clobber */ );␊ |
151 | }␊ |
152 | ␊ |
153 | /* Returns the number of times the loop ran before the PIT2 signaled */␊ |
154 | static inline unsigned long poll_PIT2_gate(void)␊ |
155 | {␊ |
156 | unsigned long count = 0;␊ |
157 | unsigned char nmi_sc_val;␊ |
158 | do {␊ |
159 | ++count;␊ |
160 | __asm__ volatile(␊ |
161 | ␉␉␉␉␉␉ "inb␉$0x61,%0"␊ |
162 | ␉␉␉␉␉␉ : "=q"(nmi_sc_val) /*:*/ /* no input */ /*:*/ /* no clobber */);␊ |
163 | } while( (nmi_sc_val & 0x20) == 0);␊ |
164 | return count;␊ |
165 | }␊ |
166 | ␊ |
167 | ␊ |
168 | inline static void␊ |
169 | set_PIT2(int value)␊ |
170 | {␊ |
171 | /*␊ |
172 | * First, tell the clock we are going to write 16 bits to the counter␊ |
173 | * and enable one-shot mode (command 0xB8 to port 0x43)␊ |
174 | * Then write the two bytes into the PIT2 clock register (port 0x42).␊ |
175 | * Loop until the value is "realized" in the clock,␊ |
176 | * this happens on the next tick.␊ |
177 | */␊ |
178 | asm volatile(␊ |
179 | " movb $0xB8,%%al \n\t"␊ |
180 | " outb %%al,$0x43 \n\t"␊ |
181 | " movb %%dl,%%al \n\t"␊ |
182 | " outb %%al,$0x42 \n\t"␊ |
183 | " movb %%dh,%%al \n\t"␊ |
184 | " outb %%al,$0x42 \n"␊ |
185 | "1: inb $0x42,%%al \n\t" ␊ |
186 | " inb $0x42,%%al \n\t"␊ |
187 | " cmp %%al,%%dh \n\t"␊ |
188 | " jne 1b"␊ |
189 | : : "d"(value) : "%al");␊ |
190 | }␊ |
191 | ␊ |
192 | ␊ |
193 | inline static uint64_t␊ |
194 | get_PIT2(unsigned int *value)␊ |
195 | {␊ |
196 | register uint64_t result;␊ |
197 | /*␊ |
198 | * This routine first latches the time (command 0x80 to port 0x43),␊ |
199 | * then gets the time stamp so we know how long the read will take later.␊ |
200 | * Read (from port 0x42) and return the current value of the timer.␊ |
201 | */␊ |
202 | #ifdef __i386__␊ |
203 | asm volatile(␊ |
204 | " xorl %%ecx,%%ecx \n\t"␊ |
205 | " movb $0x80,%%al \n\t"␊ |
206 | " outb %%al,$0x43 \n\t"␊ |
207 | " rdtsc \n\t"␊ |
208 | " pushl %%eax \n\t"␊ |
209 | " inb $0x42,%%al \n\t"␊ |
210 | " movb %%al,%%cl \n\t"␊ |
211 | " inb $0x42,%%al \n\t"␊ |
212 | " movb %%al,%%ch \n\t"␊ |
213 | " popl %%eax "␊ |
214 | : "=A"(result), "=c"(*value));␊ |
215 | #else /* __x86_64__ */␊ |
216 | asm volatile(␊ |
217 | ␉␉" xorq %%rcx,%%rcx \n\t"␊ |
218 | ␉␉" movb $0x80,%%al \n\t"␊ |
219 | ␉␉" outb %%al,$0x43 \n\t"␊ |
220 | ␉␉" rdtsc \n\t"␊ |
221 | ␉␉" pushq %%rax \n\t"␊ |
222 | ␉␉" inb $0x42,%%al \n\t"␊ |
223 | ␉␉" movb %%al,%%cl \n\t"␊ |
224 | ␉␉" inb $0x42,%%al \n\t"␊ |
225 | ␉␉" movb %%al,%%ch \n\t"␊ |
226 | ␉␉" popq %%rax "␊ |
227 | ␉␉: "=A"(result), "=c"(*value));␊ |
228 | #endif␊ |
229 | ␊ |
230 | return result;␊ |
231 | }␊ |
232 | ␊ |
233 | #endif /* !__LIBSAIO_CPU_H */␊ |
234 |