xref: /illumos-gate/usr/src/boot/sys/i386/include/cpufunc.h (revision 6efcf43c2657773c50e5f6c946b05c4b2004a22b)
1199767f8SToomas Soome /*-
2199767f8SToomas Soome  * Copyright (c) 1993 The Regents of the University of California.
3199767f8SToomas Soome  * All rights reserved.
4199767f8SToomas Soome  *
5199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
6199767f8SToomas Soome  * modification, are permitted provided that the following conditions
7199767f8SToomas Soome  * are met:
8199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
13199767f8SToomas Soome  * 4. Neither the name of the University nor the names of its contributors
14199767f8SToomas Soome  *    may be used to endorse or promote products derived from this software
15199767f8SToomas Soome  *    without specific prior written permission.
16199767f8SToomas Soome  *
17199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18199767f8SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19199767f8SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20199767f8SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21199767f8SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22199767f8SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23199767f8SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24199767f8SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25199767f8SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26199767f8SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27199767f8SToomas Soome  * SUCH DAMAGE.
28199767f8SToomas Soome  *
29199767f8SToomas Soome  * $FreeBSD$
30199767f8SToomas Soome  */
31199767f8SToomas Soome 
32199767f8SToomas Soome /*
33199767f8SToomas Soome  * Functions to provide access to special i386 instructions.
34199767f8SToomas Soome  * This in included in sys/systm.h, and that file should be
35199767f8SToomas Soome  * used in preference to this.
36199767f8SToomas Soome  */
37199767f8SToomas Soome 
38199767f8SToomas Soome #ifndef _MACHINE_CPUFUNC_H_
39199767f8SToomas Soome #define	_MACHINE_CPUFUNC_H_
40199767f8SToomas Soome 
41199767f8SToomas Soome #ifndef _SYS_CDEFS_H_
42199767f8SToomas Soome #error this file needs sys/cdefs.h as a prerequisite
43199767f8SToomas Soome #endif
44199767f8SToomas Soome 
45199767f8SToomas Soome struct region_descriptor;
46199767f8SToomas Soome 
47199767f8SToomas Soome #define readb(va)	(*(volatile uint8_t *) (va))
48199767f8SToomas Soome #define readw(va)	(*(volatile uint16_t *) (va))
49199767f8SToomas Soome #define readl(va)	(*(volatile uint32_t *) (va))
50199767f8SToomas Soome 
51199767f8SToomas Soome #define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
52199767f8SToomas Soome #define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
53199767f8SToomas Soome #define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
54199767f8SToomas Soome 
55199767f8SToomas Soome #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
56199767f8SToomas Soome 
57199767f8SToomas Soome static __inline void
58199767f8SToomas Soome breakpoint(void)
59199767f8SToomas Soome {
60199767f8SToomas Soome 	__asm __volatile("int $3");
61199767f8SToomas Soome }
62199767f8SToomas Soome 
63199767f8SToomas Soome static __inline u_int
64199767f8SToomas Soome bsfl(u_int mask)
65199767f8SToomas Soome {
66199767f8SToomas Soome 	u_int	result;
67199767f8SToomas Soome 
68199767f8SToomas Soome 	__asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
69199767f8SToomas Soome 	return (result);
70199767f8SToomas Soome }
71199767f8SToomas Soome 
72199767f8SToomas Soome static __inline u_int
73199767f8SToomas Soome bsrl(u_int mask)
74199767f8SToomas Soome {
75199767f8SToomas Soome 	u_int	result;
76199767f8SToomas Soome 
77199767f8SToomas Soome 	__asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
78199767f8SToomas Soome 	return (result);
79199767f8SToomas Soome }
80199767f8SToomas Soome 
81199767f8SToomas Soome static __inline void
82199767f8SToomas Soome clflush(u_long addr)
83199767f8SToomas Soome {
84199767f8SToomas Soome 
85199767f8SToomas Soome 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
86199767f8SToomas Soome }
87199767f8SToomas Soome 
88199767f8SToomas Soome static __inline void
89199767f8SToomas Soome clflushopt(u_long addr)
90199767f8SToomas Soome {
91199767f8SToomas Soome 
92199767f8SToomas Soome 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
93199767f8SToomas Soome }
94199767f8SToomas Soome 
95199767f8SToomas Soome static __inline void
96199767f8SToomas Soome clts(void)
97199767f8SToomas Soome {
98199767f8SToomas Soome 
99199767f8SToomas Soome 	__asm __volatile("clts");
100199767f8SToomas Soome }
101199767f8SToomas Soome 
102199767f8SToomas Soome static __inline void
103199767f8SToomas Soome disable_intr(void)
104199767f8SToomas Soome {
105199767f8SToomas Soome 
106199767f8SToomas Soome 	__asm __volatile("cli" : : : "memory");
107199767f8SToomas Soome }
108199767f8SToomas Soome 
109199767f8SToomas Soome static __inline void
110199767f8SToomas Soome do_cpuid(u_int ax, u_int *p)
111199767f8SToomas Soome {
112*6efcf43cSToomas Soome 	__asm __volatile("pushl %%ebx      \n\t"
113*6efcf43cSToomas Soome 			 "cpuid            \n\t"
114*6efcf43cSToomas Soome 			 "movl %%ebx, %1   \n\t"
115*6efcf43cSToomas Soome 			 "popl %%ebx       \n\t"
116*6efcf43cSToomas Soome 			 : "=a" (p[0]), "=m" (p[1]), "=c" (p[2]), "=d" (p[3])
117*6efcf43cSToomas Soome 			 : "0" (ax));
118199767f8SToomas Soome }
119199767f8SToomas Soome 
120199767f8SToomas Soome static __inline void
121199767f8SToomas Soome cpuid_count(u_int ax, u_int cx, u_int *p)
122199767f8SToomas Soome {
123199767f8SToomas Soome 	__asm __volatile("cpuid"
124199767f8SToomas Soome 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
125199767f8SToomas Soome 			 :  "0" (ax), "c" (cx));
126199767f8SToomas Soome }
127199767f8SToomas Soome 
128199767f8SToomas Soome static __inline void
129199767f8SToomas Soome enable_intr(void)
130199767f8SToomas Soome {
131199767f8SToomas Soome 
132199767f8SToomas Soome 	__asm __volatile("sti");
133199767f8SToomas Soome }
134199767f8SToomas Soome 
135199767f8SToomas Soome static __inline void
136199767f8SToomas Soome cpu_monitor(const void *addr, u_long extensions, u_int hints)
137199767f8SToomas Soome {
138199767f8SToomas Soome 
139199767f8SToomas Soome 	__asm __volatile("monitor"
140199767f8SToomas Soome 	    : : "a" (addr), "c" (extensions), "d" (hints));
141199767f8SToomas Soome }
142199767f8SToomas Soome 
143199767f8SToomas Soome static __inline void
144199767f8SToomas Soome cpu_mwait(u_long extensions, u_int hints)
145199767f8SToomas Soome {
146199767f8SToomas Soome 
147199767f8SToomas Soome 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
148199767f8SToomas Soome }
149199767f8SToomas Soome 
150199767f8SToomas Soome static __inline void
151199767f8SToomas Soome lfence(void)
152199767f8SToomas Soome {
153199767f8SToomas Soome 
154199767f8SToomas Soome 	__asm __volatile("lfence" : : : "memory");
155199767f8SToomas Soome }
156199767f8SToomas Soome 
157199767f8SToomas Soome static __inline void
158199767f8SToomas Soome mfence(void)
159199767f8SToomas Soome {
160199767f8SToomas Soome 
161199767f8SToomas Soome 	__asm __volatile("mfence" : : : "memory");
162199767f8SToomas Soome }
163199767f8SToomas Soome 
164199767f8SToomas Soome #ifdef _KERNEL
165199767f8SToomas Soome 
166199767f8SToomas Soome #define	HAVE_INLINE_FFS
167199767f8SToomas Soome 
168199767f8SToomas Soome static __inline int
169199767f8SToomas Soome ffs(int mask)
170199767f8SToomas Soome {
171199767f8SToomas Soome 	/*
172199767f8SToomas Soome 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
173199767f8SToomas Soome 	 * this inline or turn off the builtin.  The builtin is faster but
174199767f8SToomas Soome 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
175199767f8SToomas Soome 	 * versions.
176199767f8SToomas Soome 	 */
177199767f8SToomas Soome 	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
178199767f8SToomas Soome }
179199767f8SToomas Soome 
180199767f8SToomas Soome #define	HAVE_INLINE_FFSL
181199767f8SToomas Soome 
182199767f8SToomas Soome static __inline int
183199767f8SToomas Soome ffsl(long mask)
184199767f8SToomas Soome {
185199767f8SToomas Soome 	return (ffs((int)mask));
186199767f8SToomas Soome }
187199767f8SToomas Soome 
188199767f8SToomas Soome #define	HAVE_INLINE_FLS
189199767f8SToomas Soome 
190199767f8SToomas Soome static __inline int
191199767f8SToomas Soome fls(int mask)
192199767f8SToomas Soome {
193199767f8SToomas Soome 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
194199767f8SToomas Soome }
195199767f8SToomas Soome 
196199767f8SToomas Soome #define	HAVE_INLINE_FLSL
197199767f8SToomas Soome 
198199767f8SToomas Soome static __inline int
199199767f8SToomas Soome flsl(long mask)
200199767f8SToomas Soome {
201199767f8SToomas Soome 	return (fls((int)mask));
202199767f8SToomas Soome }
203199767f8SToomas Soome 
204199767f8SToomas Soome #endif /* _KERNEL */
205199767f8SToomas Soome 
206199767f8SToomas Soome static __inline void
207199767f8SToomas Soome halt(void)
208199767f8SToomas Soome {
209199767f8SToomas Soome 	__asm __volatile("hlt");
210199767f8SToomas Soome }
211199767f8SToomas Soome 
212199767f8SToomas Soome static __inline u_char
213199767f8SToomas Soome inb(u_int port)
214199767f8SToomas Soome {
215199767f8SToomas Soome 	u_char	data;
216199767f8SToomas Soome 
217199767f8SToomas Soome 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
218199767f8SToomas Soome 	return (data);
219199767f8SToomas Soome }
220199767f8SToomas Soome 
221199767f8SToomas Soome static __inline u_int
222199767f8SToomas Soome inl(u_int port)
223199767f8SToomas Soome {
224199767f8SToomas Soome 	u_int	data;
225199767f8SToomas Soome 
226199767f8SToomas Soome 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
227199767f8SToomas Soome 	return (data);
228199767f8SToomas Soome }
229199767f8SToomas Soome 
230199767f8SToomas Soome static __inline void
231199767f8SToomas Soome insb(u_int port, void *addr, size_t count)
232199767f8SToomas Soome {
233199767f8SToomas Soome 	__asm __volatile("cld; rep; insb"
234199767f8SToomas Soome 			 : "+D" (addr), "+c" (count)
235199767f8SToomas Soome 			 : "d" (port)
236199767f8SToomas Soome 			 : "memory");
237199767f8SToomas Soome }
238199767f8SToomas Soome 
239199767f8SToomas Soome static __inline void
240199767f8SToomas Soome insw(u_int port, void *addr, size_t count)
241199767f8SToomas Soome {
242199767f8SToomas Soome 	__asm __volatile("cld; rep; insw"
243199767f8SToomas Soome 			 : "+D" (addr), "+c" (count)
244199767f8SToomas Soome 			 : "d" (port)
245199767f8SToomas Soome 			 : "memory");
246199767f8SToomas Soome }
247199767f8SToomas Soome 
248199767f8SToomas Soome static __inline void
249199767f8SToomas Soome insl(u_int port, void *addr, size_t count)
250199767f8SToomas Soome {
251199767f8SToomas Soome 	__asm __volatile("cld; rep; insl"
252199767f8SToomas Soome 			 : "+D" (addr), "+c" (count)
253199767f8SToomas Soome 			 : "d" (port)
254199767f8SToomas Soome 			 : "memory");
255199767f8SToomas Soome }
256199767f8SToomas Soome 
257199767f8SToomas Soome static __inline void
258199767f8SToomas Soome invd(void)
259199767f8SToomas Soome {
260199767f8SToomas Soome 	__asm __volatile("invd");
261199767f8SToomas Soome }
262199767f8SToomas Soome 
263199767f8SToomas Soome static __inline u_short
264199767f8SToomas Soome inw(u_int port)
265199767f8SToomas Soome {
266199767f8SToomas Soome 	u_short	data;
267199767f8SToomas Soome 
268199767f8SToomas Soome 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
269199767f8SToomas Soome 	return (data);
270199767f8SToomas Soome }
271199767f8SToomas Soome 
272199767f8SToomas Soome static __inline void
273199767f8SToomas Soome outb(u_int port, u_char data)
274199767f8SToomas Soome {
275199767f8SToomas Soome 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
276199767f8SToomas Soome }
277199767f8SToomas Soome 
278199767f8SToomas Soome static __inline void
279199767f8SToomas Soome outl(u_int port, u_int data)
280199767f8SToomas Soome {
281199767f8SToomas Soome 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
282199767f8SToomas Soome }
283199767f8SToomas Soome 
284199767f8SToomas Soome static __inline void
285199767f8SToomas Soome outsb(u_int port, const void *addr, size_t count)
286199767f8SToomas Soome {
287199767f8SToomas Soome 	__asm __volatile("cld; rep; outsb"
288199767f8SToomas Soome 			 : "+S" (addr), "+c" (count)
289199767f8SToomas Soome 			 : "d" (port));
290199767f8SToomas Soome }
291199767f8SToomas Soome 
292199767f8SToomas Soome static __inline void
293199767f8SToomas Soome outsw(u_int port, const void *addr, size_t count)
294199767f8SToomas Soome {
295199767f8SToomas Soome 	__asm __volatile("cld; rep; outsw"
296199767f8SToomas Soome 			 : "+S" (addr), "+c" (count)
297199767f8SToomas Soome 			 : "d" (port));
298199767f8SToomas Soome }
299199767f8SToomas Soome 
300199767f8SToomas Soome static __inline void
301199767f8SToomas Soome outsl(u_int port, const void *addr, size_t count)
302199767f8SToomas Soome {
303199767f8SToomas Soome 	__asm __volatile("cld; rep; outsl"
304199767f8SToomas Soome 			 : "+S" (addr), "+c" (count)
305199767f8SToomas Soome 			 : "d" (port));
306199767f8SToomas Soome }
307199767f8SToomas Soome 
308199767f8SToomas Soome static __inline void
309199767f8SToomas Soome outw(u_int port, u_short data)
310199767f8SToomas Soome {
311199767f8SToomas Soome 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
312199767f8SToomas Soome }
313199767f8SToomas Soome 
314199767f8SToomas Soome static __inline void
315199767f8SToomas Soome ia32_pause(void)
316199767f8SToomas Soome {
317199767f8SToomas Soome 	__asm __volatile("pause");
318199767f8SToomas Soome }
319199767f8SToomas Soome 
320199767f8SToomas Soome static __inline u_int
321199767f8SToomas Soome read_eflags(void)
322199767f8SToomas Soome {
323199767f8SToomas Soome 	u_int	ef;
324199767f8SToomas Soome 
325199767f8SToomas Soome 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
326199767f8SToomas Soome 	return (ef);
327199767f8SToomas Soome }
328199767f8SToomas Soome 
329199767f8SToomas Soome static __inline uint64_t
330199767f8SToomas Soome rdmsr(u_int msr)
331199767f8SToomas Soome {
332199767f8SToomas Soome 	uint64_t rv;
333199767f8SToomas Soome 
334199767f8SToomas Soome 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
335199767f8SToomas Soome 	return (rv);
336199767f8SToomas Soome }
337199767f8SToomas Soome 
338199767f8SToomas Soome static __inline uint32_t
339199767f8SToomas Soome rdmsr32(u_int msr)
340199767f8SToomas Soome {
341199767f8SToomas Soome 	uint32_t low;
342199767f8SToomas Soome 
343199767f8SToomas Soome 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "edx");
344199767f8SToomas Soome 	return (low);
345199767f8SToomas Soome }
346199767f8SToomas Soome 
347199767f8SToomas Soome static __inline uint64_t
348199767f8SToomas Soome rdpmc(u_int pmc)
349199767f8SToomas Soome {
350199767f8SToomas Soome 	uint64_t rv;
351199767f8SToomas Soome 
352199767f8SToomas Soome 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
353199767f8SToomas Soome 	return (rv);
354199767f8SToomas Soome }
355199767f8SToomas Soome 
356199767f8SToomas Soome static __inline uint64_t
357199767f8SToomas Soome rdtsc(void)
358199767f8SToomas Soome {
359199767f8SToomas Soome 	uint64_t rv;
360199767f8SToomas Soome 
361199767f8SToomas Soome 	__asm __volatile("rdtsc" : "=A" (rv));
362199767f8SToomas Soome 	return (rv);
363199767f8SToomas Soome }
364199767f8SToomas Soome 
365199767f8SToomas Soome static __inline uint32_t
366199767f8SToomas Soome rdtsc32(void)
367199767f8SToomas Soome {
368199767f8SToomas Soome 	uint32_t rv;
369199767f8SToomas Soome 
370199767f8SToomas Soome 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
371199767f8SToomas Soome 	return (rv);
372199767f8SToomas Soome }
373199767f8SToomas Soome 
374199767f8SToomas Soome static __inline void
375199767f8SToomas Soome wbinvd(void)
376199767f8SToomas Soome {
377199767f8SToomas Soome 	__asm __volatile("wbinvd");
378199767f8SToomas Soome }
379199767f8SToomas Soome 
380199767f8SToomas Soome static __inline void
381199767f8SToomas Soome write_eflags(u_int ef)
382199767f8SToomas Soome {
383199767f8SToomas Soome 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
384199767f8SToomas Soome }
385199767f8SToomas Soome 
386199767f8SToomas Soome static __inline void
387199767f8SToomas Soome wrmsr(u_int msr, uint64_t newval)
388199767f8SToomas Soome {
389199767f8SToomas Soome 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
390199767f8SToomas Soome }
391199767f8SToomas Soome 
392199767f8SToomas Soome static __inline void
393199767f8SToomas Soome load_cr0(u_int data)
394199767f8SToomas Soome {
395199767f8SToomas Soome 
396199767f8SToomas Soome 	__asm __volatile("movl %0,%%cr0" : : "r" (data));
397199767f8SToomas Soome }
398199767f8SToomas Soome 
399199767f8SToomas Soome static __inline u_int
400199767f8SToomas Soome rcr0(void)
401199767f8SToomas Soome {
402199767f8SToomas Soome 	u_int	data;
403199767f8SToomas Soome 
404199767f8SToomas Soome 	__asm __volatile("movl %%cr0,%0" : "=r" (data));
405199767f8SToomas Soome 	return (data);
406199767f8SToomas Soome }
407199767f8SToomas Soome 
408199767f8SToomas Soome static __inline u_int
409199767f8SToomas Soome rcr2(void)
410199767f8SToomas Soome {
411199767f8SToomas Soome 	u_int	data;
412199767f8SToomas Soome 
413199767f8SToomas Soome 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
414199767f8SToomas Soome 	return (data);
415199767f8SToomas Soome }
416199767f8SToomas Soome 
417199767f8SToomas Soome static __inline void
418199767f8SToomas Soome load_cr3(u_int data)
419199767f8SToomas Soome {
420199767f8SToomas Soome 
421199767f8SToomas Soome 	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
422199767f8SToomas Soome }
423199767f8SToomas Soome 
424199767f8SToomas Soome static __inline u_int
425199767f8SToomas Soome rcr3(void)
426199767f8SToomas Soome {
427199767f8SToomas Soome 	u_int	data;
428199767f8SToomas Soome 
429199767f8SToomas Soome 	__asm __volatile("movl %%cr3,%0" : "=r" (data));
430199767f8SToomas Soome 	return (data);
431199767f8SToomas Soome }
432199767f8SToomas Soome 
433199767f8SToomas Soome static __inline void
434199767f8SToomas Soome load_cr4(u_int data)
435199767f8SToomas Soome {
436199767f8SToomas Soome 	__asm __volatile("movl %0,%%cr4" : : "r" (data));
437199767f8SToomas Soome }
438199767f8SToomas Soome 
439199767f8SToomas Soome static __inline u_int
440199767f8SToomas Soome rcr4(void)
441199767f8SToomas Soome {
442199767f8SToomas Soome 	u_int	data;
443199767f8SToomas Soome 
444199767f8SToomas Soome 	__asm __volatile("movl %%cr4,%0" : "=r" (data));
445199767f8SToomas Soome 	return (data);
446199767f8SToomas Soome }
447199767f8SToomas Soome 
448199767f8SToomas Soome static __inline uint64_t
449199767f8SToomas Soome rxcr(u_int reg)
450199767f8SToomas Soome {
451199767f8SToomas Soome 	u_int low, high;
452199767f8SToomas Soome 
453199767f8SToomas Soome 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
454199767f8SToomas Soome 	return (low | ((uint64_t)high << 32));
455199767f8SToomas Soome }
456199767f8SToomas Soome 
457199767f8SToomas Soome static __inline void
458199767f8SToomas Soome load_xcr(u_int reg, uint64_t val)
459199767f8SToomas Soome {
460199767f8SToomas Soome 	u_int low, high;
461199767f8SToomas Soome 
462199767f8SToomas Soome 	low = val;
463199767f8SToomas Soome 	high = val >> 32;
464199767f8SToomas Soome 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
465199767f8SToomas Soome }
466199767f8SToomas Soome 
467199767f8SToomas Soome /*
468199767f8SToomas Soome  * Global TLB flush (except for thise for pages marked PG_G)
469199767f8SToomas Soome  */
470199767f8SToomas Soome static __inline void
471199767f8SToomas Soome invltlb(void)
472199767f8SToomas Soome {
473199767f8SToomas Soome 
474199767f8SToomas Soome 	load_cr3(rcr3());
475199767f8SToomas Soome }
476199767f8SToomas Soome 
477199767f8SToomas Soome /*
478199767f8SToomas Soome  * TLB flush for an individual page (even if it has PG_G).
479199767f8SToomas Soome  * Only works on 486+ CPUs (i386 does not have PG_G).
480199767f8SToomas Soome  */
481199767f8SToomas Soome static __inline void
482199767f8SToomas Soome invlpg(u_int addr)
483199767f8SToomas Soome {
484199767f8SToomas Soome 
485199767f8SToomas Soome 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
486199767f8SToomas Soome }
487199767f8SToomas Soome 
488199767f8SToomas Soome static __inline u_short
489199767f8SToomas Soome rfs(void)
490199767f8SToomas Soome {
491199767f8SToomas Soome 	u_short sel;
492199767f8SToomas Soome 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
493199767f8SToomas Soome 	return (sel);
494199767f8SToomas Soome }
495199767f8SToomas Soome 
496199767f8SToomas Soome static __inline uint64_t
497199767f8SToomas Soome rgdt(void)
498199767f8SToomas Soome {
499199767f8SToomas Soome 	uint64_t gdtr;
500199767f8SToomas Soome 	__asm __volatile("sgdt %0" : "=m" (gdtr));
501199767f8SToomas Soome 	return (gdtr);
502199767f8SToomas Soome }
503199767f8SToomas Soome 
504199767f8SToomas Soome static __inline u_short
505199767f8SToomas Soome rgs(void)
506199767f8SToomas Soome {
507199767f8SToomas Soome 	u_short sel;
508199767f8SToomas Soome 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
509199767f8SToomas Soome 	return (sel);
510199767f8SToomas Soome }
511199767f8SToomas Soome 
512199767f8SToomas Soome static __inline uint64_t
513199767f8SToomas Soome ridt(void)
514199767f8SToomas Soome {
515199767f8SToomas Soome 	uint64_t idtr;
516199767f8SToomas Soome 	__asm __volatile("sidt %0" : "=m" (idtr));
517199767f8SToomas Soome 	return (idtr);
518199767f8SToomas Soome }
519199767f8SToomas Soome 
520199767f8SToomas Soome static __inline u_short
521199767f8SToomas Soome rldt(void)
522199767f8SToomas Soome {
523199767f8SToomas Soome 	u_short ldtr;
524199767f8SToomas Soome 	__asm __volatile("sldt %0" : "=g" (ldtr));
525199767f8SToomas Soome 	return (ldtr);
526199767f8SToomas Soome }
527199767f8SToomas Soome 
528199767f8SToomas Soome static __inline u_short
529199767f8SToomas Soome rss(void)
530199767f8SToomas Soome {
531199767f8SToomas Soome 	u_short sel;
532199767f8SToomas Soome 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
533199767f8SToomas Soome 	return (sel);
534199767f8SToomas Soome }
535199767f8SToomas Soome 
536199767f8SToomas Soome static __inline u_short
537199767f8SToomas Soome rtr(void)
538199767f8SToomas Soome {
539199767f8SToomas Soome 	u_short tr;
540199767f8SToomas Soome 	__asm __volatile("str %0" : "=g" (tr));
541199767f8SToomas Soome 	return (tr);
542199767f8SToomas Soome }
543199767f8SToomas Soome 
544199767f8SToomas Soome static __inline void
545199767f8SToomas Soome load_fs(u_short sel)
546199767f8SToomas Soome {
547199767f8SToomas Soome 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
548199767f8SToomas Soome }
549199767f8SToomas Soome 
550199767f8SToomas Soome static __inline void
551199767f8SToomas Soome load_gs(u_short sel)
552199767f8SToomas Soome {
553199767f8SToomas Soome 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
554199767f8SToomas Soome }
555199767f8SToomas Soome 
556199767f8SToomas Soome static __inline void
557199767f8SToomas Soome lidt(struct region_descriptor *addr)
558199767f8SToomas Soome {
559199767f8SToomas Soome 	__asm __volatile("lidt (%0)" : : "r" (addr));
560199767f8SToomas Soome }
561199767f8SToomas Soome 
562199767f8SToomas Soome static __inline void
563199767f8SToomas Soome lldt(u_short sel)
564199767f8SToomas Soome {
565199767f8SToomas Soome 	__asm __volatile("lldt %0" : : "r" (sel));
566199767f8SToomas Soome }
567199767f8SToomas Soome 
568199767f8SToomas Soome static __inline void
569199767f8SToomas Soome ltr(u_short sel)
570199767f8SToomas Soome {
571199767f8SToomas Soome 	__asm __volatile("ltr %0" : : "r" (sel));
572199767f8SToomas Soome }
573199767f8SToomas Soome 
574199767f8SToomas Soome static __inline u_int
575199767f8SToomas Soome rdr0(void)
576199767f8SToomas Soome {
577199767f8SToomas Soome 	u_int	data;
578199767f8SToomas Soome 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
579199767f8SToomas Soome 	return (data);
580199767f8SToomas Soome }
581199767f8SToomas Soome 
582199767f8SToomas Soome static __inline void
583199767f8SToomas Soome load_dr0(u_int dr0)
584199767f8SToomas Soome {
585199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
586199767f8SToomas Soome }
587199767f8SToomas Soome 
588199767f8SToomas Soome static __inline u_int
589199767f8SToomas Soome rdr1(void)
590199767f8SToomas Soome {
591199767f8SToomas Soome 	u_int	data;
592199767f8SToomas Soome 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
593199767f8SToomas Soome 	return (data);
594199767f8SToomas Soome }
595199767f8SToomas Soome 
596199767f8SToomas Soome static __inline void
597199767f8SToomas Soome load_dr1(u_int dr1)
598199767f8SToomas Soome {
599199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
600199767f8SToomas Soome }
601199767f8SToomas Soome 
602199767f8SToomas Soome static __inline u_int
603199767f8SToomas Soome rdr2(void)
604199767f8SToomas Soome {
605199767f8SToomas Soome 	u_int	data;
606199767f8SToomas Soome 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
607199767f8SToomas Soome 	return (data);
608199767f8SToomas Soome }
609199767f8SToomas Soome 
610199767f8SToomas Soome static __inline void
611199767f8SToomas Soome load_dr2(u_int dr2)
612199767f8SToomas Soome {
613199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
614199767f8SToomas Soome }
615199767f8SToomas Soome 
616199767f8SToomas Soome static __inline u_int
617199767f8SToomas Soome rdr3(void)
618199767f8SToomas Soome {
619199767f8SToomas Soome 	u_int	data;
620199767f8SToomas Soome 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
621199767f8SToomas Soome 	return (data);
622199767f8SToomas Soome }
623199767f8SToomas Soome 
624199767f8SToomas Soome static __inline void
625199767f8SToomas Soome load_dr3(u_int dr3)
626199767f8SToomas Soome {
627199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
628199767f8SToomas Soome }
629199767f8SToomas Soome 
630199767f8SToomas Soome static __inline u_int
631199767f8SToomas Soome rdr4(void)
632199767f8SToomas Soome {
633199767f8SToomas Soome 	u_int	data;
634199767f8SToomas Soome 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
635199767f8SToomas Soome 	return (data);
636199767f8SToomas Soome }
637199767f8SToomas Soome 
638199767f8SToomas Soome static __inline void
639199767f8SToomas Soome load_dr4(u_int dr4)
640199767f8SToomas Soome {
641199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
642199767f8SToomas Soome }
643199767f8SToomas Soome 
644199767f8SToomas Soome static __inline u_int
645199767f8SToomas Soome rdr5(void)
646199767f8SToomas Soome {
647199767f8SToomas Soome 	u_int	data;
648199767f8SToomas Soome 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
649199767f8SToomas Soome 	return (data);
650199767f8SToomas Soome }
651199767f8SToomas Soome 
652199767f8SToomas Soome static __inline void
653199767f8SToomas Soome load_dr5(u_int dr5)
654199767f8SToomas Soome {
655199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
656199767f8SToomas Soome }
657199767f8SToomas Soome 
658199767f8SToomas Soome static __inline u_int
659199767f8SToomas Soome rdr6(void)
660199767f8SToomas Soome {
661199767f8SToomas Soome 	u_int	data;
662199767f8SToomas Soome 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
663199767f8SToomas Soome 	return (data);
664199767f8SToomas Soome }
665199767f8SToomas Soome 
666199767f8SToomas Soome static __inline void
667199767f8SToomas Soome load_dr6(u_int dr6)
668199767f8SToomas Soome {
669199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
670199767f8SToomas Soome }
671199767f8SToomas Soome 
672199767f8SToomas Soome static __inline u_int
673199767f8SToomas Soome rdr7(void)
674199767f8SToomas Soome {
675199767f8SToomas Soome 	u_int	data;
676199767f8SToomas Soome 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
677199767f8SToomas Soome 	return (data);
678199767f8SToomas Soome }
679199767f8SToomas Soome 
680199767f8SToomas Soome static __inline void
681199767f8SToomas Soome load_dr7(u_int dr7)
682199767f8SToomas Soome {
683199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
684199767f8SToomas Soome }
685199767f8SToomas Soome 
686199767f8SToomas Soome static __inline u_char
687199767f8SToomas Soome read_cyrix_reg(u_char reg)
688199767f8SToomas Soome {
689199767f8SToomas Soome 	outb(0x22, reg);
690199767f8SToomas Soome 	return inb(0x23);
691199767f8SToomas Soome }
692199767f8SToomas Soome 
693199767f8SToomas Soome static __inline void
694199767f8SToomas Soome write_cyrix_reg(u_char reg, u_char data)
695199767f8SToomas Soome {
696199767f8SToomas Soome 	outb(0x22, reg);
697199767f8SToomas Soome 	outb(0x23, data);
698199767f8SToomas Soome }
699199767f8SToomas Soome 
700199767f8SToomas Soome static __inline register_t
701199767f8SToomas Soome intr_disable(void)
702199767f8SToomas Soome {
703199767f8SToomas Soome 	register_t eflags;
704199767f8SToomas Soome 
705199767f8SToomas Soome 	eflags = read_eflags();
706199767f8SToomas Soome 	disable_intr();
707199767f8SToomas Soome 	return (eflags);
708199767f8SToomas Soome }
709199767f8SToomas Soome 
710199767f8SToomas Soome static __inline void
711199767f8SToomas Soome intr_restore(register_t eflags)
712199767f8SToomas Soome {
713199767f8SToomas Soome 	write_eflags(eflags);
714199767f8SToomas Soome }
715199767f8SToomas Soome 
716199767f8SToomas Soome #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
717199767f8SToomas Soome 
718199767f8SToomas Soome int	breakpoint(void);
719199767f8SToomas Soome u_int	bsfl(u_int mask);
720199767f8SToomas Soome u_int	bsrl(u_int mask);
721199767f8SToomas Soome void	clflush(u_long addr);
722199767f8SToomas Soome void	clts(void);
723199767f8SToomas Soome void	cpuid_count(u_int ax, u_int cx, u_int *p);
724199767f8SToomas Soome void	disable_intr(void);
725199767f8SToomas Soome void	do_cpuid(u_int ax, u_int *p);
726199767f8SToomas Soome void	enable_intr(void);
727199767f8SToomas Soome void	halt(void);
728199767f8SToomas Soome void	ia32_pause(void);
729199767f8SToomas Soome u_char	inb(u_int port);
730199767f8SToomas Soome u_int	inl(u_int port);
731199767f8SToomas Soome void	insb(u_int port, void *addr, size_t count);
732199767f8SToomas Soome void	insl(u_int port, void *addr, size_t count);
733199767f8SToomas Soome void	insw(u_int port, void *addr, size_t count);
734199767f8SToomas Soome register_t	intr_disable(void);
735199767f8SToomas Soome void	intr_restore(register_t ef);
736199767f8SToomas Soome void	invd(void);
737199767f8SToomas Soome void	invlpg(u_int addr);
738199767f8SToomas Soome void	invltlb(void);
739199767f8SToomas Soome u_short	inw(u_int port);
740199767f8SToomas Soome void	lidt(struct region_descriptor *addr);
741199767f8SToomas Soome void	lldt(u_short sel);
742199767f8SToomas Soome void	load_cr0(u_int cr0);
743199767f8SToomas Soome void	load_cr3(u_int cr3);
744199767f8SToomas Soome void	load_cr4(u_int cr4);
745199767f8SToomas Soome void	load_dr0(u_int dr0);
746199767f8SToomas Soome void	load_dr1(u_int dr1);
747199767f8SToomas Soome void	load_dr2(u_int dr2);
748199767f8SToomas Soome void	load_dr3(u_int dr3);
749199767f8SToomas Soome void	load_dr4(u_int dr4);
750199767f8SToomas Soome void	load_dr5(u_int dr5);
751199767f8SToomas Soome void	load_dr6(u_int dr6);
752199767f8SToomas Soome void	load_dr7(u_int dr7);
753199767f8SToomas Soome void	load_fs(u_short sel);
754199767f8SToomas Soome void	load_gs(u_short sel);
755199767f8SToomas Soome void	ltr(u_short sel);
756199767f8SToomas Soome void	outb(u_int port, u_char data);
757199767f8SToomas Soome void	outl(u_int port, u_int data);
758199767f8SToomas Soome void	outsb(u_int port, const void *addr, size_t count);
759199767f8SToomas Soome void	outsl(u_int port, const void *addr, size_t count);
760199767f8SToomas Soome void	outsw(u_int port, const void *addr, size_t count);
761199767f8SToomas Soome void	outw(u_int port, u_short data);
762199767f8SToomas Soome u_int	rcr0(void);
763199767f8SToomas Soome u_int	rcr2(void);
764199767f8SToomas Soome u_int	rcr3(void);
765199767f8SToomas Soome u_int	rcr4(void);
766199767f8SToomas Soome uint64_t rdmsr(u_int msr);
767199767f8SToomas Soome uint64_t rdpmc(u_int pmc);
768199767f8SToomas Soome u_int	rdr0(void);
769199767f8SToomas Soome u_int	rdr1(void);
770199767f8SToomas Soome u_int	rdr2(void);
771199767f8SToomas Soome u_int	rdr3(void);
772199767f8SToomas Soome u_int	rdr4(void);
773199767f8SToomas Soome u_int	rdr5(void);
774199767f8SToomas Soome u_int	rdr6(void);
775199767f8SToomas Soome u_int	rdr7(void);
776199767f8SToomas Soome uint64_t rdtsc(void);
777199767f8SToomas Soome u_char	read_cyrix_reg(u_char reg);
778199767f8SToomas Soome u_int	read_eflags(void);
779199767f8SToomas Soome u_int	rfs(void);
780199767f8SToomas Soome uint64_t rgdt(void);
781199767f8SToomas Soome u_int	rgs(void);
782199767f8SToomas Soome uint64_t ridt(void);
783199767f8SToomas Soome u_short	rldt(void);
784199767f8SToomas Soome u_short	rtr(void);
785199767f8SToomas Soome void	wbinvd(void);
786199767f8SToomas Soome void	write_cyrix_reg(u_char reg, u_char data);
787199767f8SToomas Soome void	write_eflags(u_int ef);
788199767f8SToomas Soome void	wrmsr(u_int msr, uint64_t newval);
789199767f8SToomas Soome 
790199767f8SToomas Soome #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
791199767f8SToomas Soome 
792199767f8SToomas Soome void    reset_dbregs(void);
793199767f8SToomas Soome 
794199767f8SToomas Soome #ifdef _KERNEL
795199767f8SToomas Soome int	rdmsr_safe(u_int msr, uint64_t *val);
796199767f8SToomas Soome int	wrmsr_safe(u_int msr, uint64_t newval);
797199767f8SToomas Soome #endif
798199767f8SToomas Soome 
799199767f8SToomas Soome #endif /* !_MACHINE_CPUFUNC_H_ */
800