cpufunc.h revision 1.17 1 /* $NetBSD: cpufunc.h,v 1.17 2007/05/21 08:10:39 fvdl Exp $ */
2
3 /*-
4 * Copyright (c) 1998 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Charles M. Hannum.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 * 3. All advertising materials mentioning features or use of this software
19 * must display the following acknowledgement:
20 * This product includes software developed by the NetBSD
21 * Foundation, Inc. and its contributors.
22 * 4. Neither the name of The NetBSD Foundation nor the names of its
23 * contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
27 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
28 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
29 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
30 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
31 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
32 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
33 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
34 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
35 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
36 * POSSIBILITY OF SUCH DAMAGE.
37 */
38
39 #ifndef _AMD64_CPUFUNC_H_
40 #define _AMD64_CPUFUNC_H_
41
42 /*
43 * Functions to provide access to i386-specific instructions.
44 */
45
46 #include <sys/cdefs.h>
47 #include <sys/types.h>
48
49 #include <machine/segments.h>
50 #include <machine/specialreg.h>
51
52 #ifdef _KERNEL
53 void x86_pause(void);
54 #else
55 static __inline void
56 x86_pause(void)
57 {
58 __asm volatile("pause");
59 }
60 #endif
61
62 /*
63 * XXX if lfence isn't available...
64 *
65 * memory clobber to avoid compiler reordering.
66 */
67 static __inline void
68 x86_lfence(void)
69 {
70
71 __asm volatile("lfence" : : : "memory");
72 }
73
74 static __inline void
75 x86_sfence(void)
76 {
77
78 __asm volatile("sfence" : : : "memory");
79 }
80
81 static __inline void
82 x86_mfence(void)
83 {
84
85 __asm volatile("mfence" : : : "memory");
86 }
87
88 #ifdef _KERNEL
89
90 void x86_flush(void);
91 void x86_patch(void);
92
93 extern int cpu_feature;
94
95 static __inline void
96 invlpg(u_int64_t addr)
97 {
98 __asm volatile("invlpg (%0)" : : "r" (addr) : "memory");
99 }
100
101 static __inline void
102 lidt(struct region_descriptor *region)
103 {
104 __asm volatile("lidt %0" : : "m" (*region));
105 }
106
107 static __inline void
108 lldt(u_short sel)
109 {
110 __asm volatile("lldt %0" : : "r" (sel));
111 }
112
113 static __inline void
114 ltr(u_short sel)
115 {
116 __asm volatile("ltr %0" : : "r" (sel));
117 }
118
119 static __inline void
120 lcr8(u_int val)
121 {
122 u_int64_t val64 = val;
123 __asm volatile("movq %0,%%cr8" : : "r" (val64));
124 }
125
126 /*
127 * Upper 32 bits are reserved anyway, so just keep this 32bits.
128 */
129 static __inline void
130 lcr0(u_int val)
131 {
132 u_int64_t val64 = val;
133 __asm volatile("movq %0,%%cr0" : : "r" (val64));
134 }
135
136 static __inline u_int
137 rcr0(void)
138 {
139 u_int64_t val64;
140 u_int val;
141 __asm volatile("movq %%cr0,%0" : "=r" (val64));
142 val = val64;
143 return val;
144 }
145
146 static __inline u_int64_t
147 rcr2(void)
148 {
149 u_int64_t val;
150 __asm volatile("movq %%cr2,%0" : "=r" (val));
151 return val;
152 }
153
154 static __inline void
155 lcr3(u_int64_t val)
156 {
157 __asm volatile("movq %0,%%cr3" : : "r" (val));
158 }
159
160 static __inline u_int64_t
161 rcr3(void)
162 {
163 u_int64_t val;
164 __asm volatile("movq %%cr3,%0" : "=r" (val));
165 return val;
166 }
167
168 /*
169 * Same as for cr0. Don't touch upper 32 bits.
170 */
171 static __inline void
172 lcr4(u_int val)
173 {
174 u_int64_t val64 = val;
175
176 __asm volatile("movq %0,%%cr4" : : "r" (val64));
177 }
178
179 static __inline u_int
180 rcr4(void)
181 {
182 u_int val;
183 u_int64_t val64;
184 __asm volatile("movq %%cr4,%0" : "=r" (val64));
185 val = val64;
186 return val;
187 }
188
189 static __inline void
190 tlbflush(void)
191 {
192 u_int64_t val;
193 __asm volatile("movq %%cr3,%0" : "=r" (val));
194 __asm volatile("movq %0,%%cr3" : : "r" (val));
195 }
196
197 static __inline void
198 tlbflushg(void)
199 {
200 /*
201 * Big hammer: flush all TLB entries, including ones from PTE's
202 * with the G bit set. This should only be necessary if TLB
203 * shootdown falls far behind.
204 *
205 * Intel Architecture Software Developer's Manual, Volume 3,
206 * System Programming, section 9.10, "Invalidating the
207 * Translation Lookaside Buffers (TLBS)":
208 * "The following operations invalidate all TLB entries, irrespective
209 * of the setting of the G flag:
210 * ...
211 * "(P6 family processors only): Writing to control register CR4 to
212 * modify the PSE, PGE, or PAE flag."
213 *
214 * (the alternatives not quoted above are not an option here.)
215 *
216 * If PGE is not in use, we reload CR3 for the benefit of
217 * pre-P6-family processors.
218 */
219
220 if (cpu_feature & CPUID_PGE) {
221 u_int cr4 = rcr4();
222 lcr4(cr4 & ~CR4_PGE);
223 lcr4(cr4);
224 } else
225 tlbflush();
226 }
227
228 #ifdef notyet
229 void setidt __P((int idx, /*XXX*/void *func, int typ, int dpl));
230 #endif
231
232
233 /* XXXX ought to be in psl.h with spl() functions */
234
235 static __inline void
236 disable_intr(void)
237 {
238 __asm volatile("cli");
239 }
240
241 static __inline void
242 enable_intr(void)
243 {
244 __asm volatile("sti");
245 }
246
247 static __inline u_long
248 read_rflags(void)
249 {
250 u_long ef;
251
252 __asm volatile("pushfq; popq %0" : "=r" (ef));
253 return (ef);
254 }
255
256 static __inline void
257 write_rflags(u_long ef)
258 {
259 __asm volatile("pushq %0; popfq" : : "r" (ef));
260 }
261
262
263 static __inline u_int64_t
264 rdmsr(u_int msr)
265 {
266 uint32_t hi, lo;
267 __asm volatile("rdmsr" : "=d" (hi), "=a" (lo) : "c" (msr));
268 return (((uint64_t)hi << 32) | (uint64_t) lo);
269 }
270
271 static __inline void
272 wrmsr(u_int msr, u_int64_t newval)
273 {
274 __asm volatile("wrmsr" :
275 : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr));
276 }
277
278 /*
279 * Some of the undocumented AMD64 MSRs need a 'passcode' to access.
280 *
281 * See LinuxBIOSv2: src/cpu/amd/model_fxx/model_fxx_init.c
282 */
283
284 #define OPTERON_MSR_PASSCODE 0x9c5a203a
285
286 static __inline u_int64_t
287 rdmsr_locked(u_int msr, u_int code)
288 {
289 uint32_t hi, lo;
290 __asm volatile("rdmsr"
291 : "=d" (hi), "=a" (lo)
292 : "c" (msr), "D" (code));
293 return (((uint64_t)hi << 32) | (uint64_t) lo);
294 }
295
296 static __inline void
297 wrmsr_locked(u_int msr, u_int code, u_int64_t newval)
298 {
299 __asm volatile("wrmsr"
300 :
301 : "a" (newval & 0xffffffff), "d" (newval >> 32), "c" (msr),
302 "D" (code));
303 }
304
305 static __inline void
306 wbinvd(void)
307 {
308 __asm volatile("wbinvd");
309 }
310
311 static __inline u_int64_t
312 rdtsc(void)
313 {
314 uint32_t hi, lo;
315
316 __asm volatile("rdtsc" : "=d" (hi), "=a" (lo));
317 return (((uint64_t)hi << 32) | (uint64_t) lo);
318 }
319
320 static __inline u_int64_t
321 rdpmc(u_int pmc)
322 {
323 uint32_t hi, lo;
324
325 __asm volatile("rdpmc" : "=d" (hi), "=a" (lo) : "c" (pmc));
326 return (((uint64_t)hi << 32) | (uint64_t) lo);
327 }
328
329 /* Break into DDB/KGDB. */
330 static __inline void
331 breakpoint(void)
332 {
333 __asm volatile("int $3");
334 }
335
336 #define read_psl() read_rflags()
337 #define write_psl(x) write_rflags(x)
338
339 #endif /* _KERNEL */
340
341 #endif /* !_AMD64_CPUFUNC_H_ */
342