xref: /illumos-gate/usr/src/boot/sys/i386/include/cpufunc.h (revision 199767f8919635c4928607450d9e0abb932109ce)
1*199767f8SToomas Soome /*-
2*199767f8SToomas Soome  * Copyright (c) 1993 The Regents of the University of California.
3*199767f8SToomas Soome  * All rights reserved.
4*199767f8SToomas Soome  *
5*199767f8SToomas Soome  * Redistribution and use in source and binary forms, with or without
6*199767f8SToomas Soome  * modification, are permitted provided that the following conditions
7*199767f8SToomas Soome  * are met:
8*199767f8SToomas Soome  * 1. Redistributions of source code must retain the above copyright
9*199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer.
10*199767f8SToomas Soome  * 2. Redistributions in binary form must reproduce the above copyright
11*199767f8SToomas Soome  *    notice, this list of conditions and the following disclaimer in the
12*199767f8SToomas Soome  *    documentation and/or other materials provided with the distribution.
13*199767f8SToomas Soome  * 4. Neither the name of the University nor the names of its contributors
14*199767f8SToomas Soome  *    may be used to endorse or promote products derived from this software
15*199767f8SToomas Soome  *    without specific prior written permission.
16*199767f8SToomas Soome  *
17*199767f8SToomas Soome  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
18*199767f8SToomas Soome  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19*199767f8SToomas Soome  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20*199767f8SToomas Soome  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
21*199767f8SToomas Soome  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22*199767f8SToomas Soome  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23*199767f8SToomas Soome  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24*199767f8SToomas Soome  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25*199767f8SToomas Soome  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26*199767f8SToomas Soome  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27*199767f8SToomas Soome  * SUCH DAMAGE.
28*199767f8SToomas Soome  *
29*199767f8SToomas Soome  * $FreeBSD$
30*199767f8SToomas Soome  */
31*199767f8SToomas Soome 
32*199767f8SToomas Soome /*
33*199767f8SToomas Soome  * Functions to provide access to special i386 instructions.
34*199767f8SToomas Soome  * This in included in sys/systm.h, and that file should be
35*199767f8SToomas Soome  * used in preference to this.
36*199767f8SToomas Soome  */
37*199767f8SToomas Soome 
38*199767f8SToomas Soome #ifndef _MACHINE_CPUFUNC_H_
39*199767f8SToomas Soome #define	_MACHINE_CPUFUNC_H_
40*199767f8SToomas Soome 
41*199767f8SToomas Soome #ifndef _SYS_CDEFS_H_
42*199767f8SToomas Soome #error this file needs sys/cdefs.h as a prerequisite
43*199767f8SToomas Soome #endif
44*199767f8SToomas Soome 
45*199767f8SToomas Soome struct region_descriptor;
46*199767f8SToomas Soome 
47*199767f8SToomas Soome #define readb(va)	(*(volatile uint8_t *) (va))
48*199767f8SToomas Soome #define readw(va)	(*(volatile uint16_t *) (va))
49*199767f8SToomas Soome #define readl(va)	(*(volatile uint32_t *) (va))
50*199767f8SToomas Soome 
51*199767f8SToomas Soome #define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
52*199767f8SToomas Soome #define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
53*199767f8SToomas Soome #define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
54*199767f8SToomas Soome 
55*199767f8SToomas Soome #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
56*199767f8SToomas Soome 
57*199767f8SToomas Soome static __inline void
58*199767f8SToomas Soome breakpoint(void)
59*199767f8SToomas Soome {
60*199767f8SToomas Soome 	__asm __volatile("int $3");
61*199767f8SToomas Soome }
62*199767f8SToomas Soome 
63*199767f8SToomas Soome static __inline u_int
64*199767f8SToomas Soome bsfl(u_int mask)
65*199767f8SToomas Soome {
66*199767f8SToomas Soome 	u_int	result;
67*199767f8SToomas Soome 
68*199767f8SToomas Soome 	__asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
69*199767f8SToomas Soome 	return (result);
70*199767f8SToomas Soome }
71*199767f8SToomas Soome 
72*199767f8SToomas Soome static __inline u_int
73*199767f8SToomas Soome bsrl(u_int mask)
74*199767f8SToomas Soome {
75*199767f8SToomas Soome 	u_int	result;
76*199767f8SToomas Soome 
77*199767f8SToomas Soome 	__asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc");
78*199767f8SToomas Soome 	return (result);
79*199767f8SToomas Soome }
80*199767f8SToomas Soome 
81*199767f8SToomas Soome static __inline void
82*199767f8SToomas Soome clflush(u_long addr)
83*199767f8SToomas Soome {
84*199767f8SToomas Soome 
85*199767f8SToomas Soome 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
86*199767f8SToomas Soome }
87*199767f8SToomas Soome 
88*199767f8SToomas Soome static __inline void
89*199767f8SToomas Soome clflushopt(u_long addr)
90*199767f8SToomas Soome {
91*199767f8SToomas Soome 
92*199767f8SToomas Soome 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
93*199767f8SToomas Soome }
94*199767f8SToomas Soome 
95*199767f8SToomas Soome static __inline void
96*199767f8SToomas Soome clts(void)
97*199767f8SToomas Soome {
98*199767f8SToomas Soome 
99*199767f8SToomas Soome 	__asm __volatile("clts");
100*199767f8SToomas Soome }
101*199767f8SToomas Soome 
102*199767f8SToomas Soome static __inline void
103*199767f8SToomas Soome disable_intr(void)
104*199767f8SToomas Soome {
105*199767f8SToomas Soome 
106*199767f8SToomas Soome 	__asm __volatile("cli" : : : "memory");
107*199767f8SToomas Soome }
108*199767f8SToomas Soome 
109*199767f8SToomas Soome static __inline void
110*199767f8SToomas Soome do_cpuid(u_int ax, u_int *p)
111*199767f8SToomas Soome {
112*199767f8SToomas Soome 	__asm __volatile("cpuid"
113*199767f8SToomas Soome 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
114*199767f8SToomas Soome 			 :  "0" (ax));
115*199767f8SToomas Soome }
116*199767f8SToomas Soome 
117*199767f8SToomas Soome static __inline void
118*199767f8SToomas Soome cpuid_count(u_int ax, u_int cx, u_int *p)
119*199767f8SToomas Soome {
120*199767f8SToomas Soome 	__asm __volatile("cpuid"
121*199767f8SToomas Soome 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
122*199767f8SToomas Soome 			 :  "0" (ax), "c" (cx));
123*199767f8SToomas Soome }
124*199767f8SToomas Soome 
125*199767f8SToomas Soome static __inline void
126*199767f8SToomas Soome enable_intr(void)
127*199767f8SToomas Soome {
128*199767f8SToomas Soome 
129*199767f8SToomas Soome 	__asm __volatile("sti");
130*199767f8SToomas Soome }
131*199767f8SToomas Soome 
132*199767f8SToomas Soome static __inline void
133*199767f8SToomas Soome cpu_monitor(const void *addr, u_long extensions, u_int hints)
134*199767f8SToomas Soome {
135*199767f8SToomas Soome 
136*199767f8SToomas Soome 	__asm __volatile("monitor"
137*199767f8SToomas Soome 	    : : "a" (addr), "c" (extensions), "d" (hints));
138*199767f8SToomas Soome }
139*199767f8SToomas Soome 
140*199767f8SToomas Soome static __inline void
141*199767f8SToomas Soome cpu_mwait(u_long extensions, u_int hints)
142*199767f8SToomas Soome {
143*199767f8SToomas Soome 
144*199767f8SToomas Soome 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
145*199767f8SToomas Soome }
146*199767f8SToomas Soome 
147*199767f8SToomas Soome static __inline void
148*199767f8SToomas Soome lfence(void)
149*199767f8SToomas Soome {
150*199767f8SToomas Soome 
151*199767f8SToomas Soome 	__asm __volatile("lfence" : : : "memory");
152*199767f8SToomas Soome }
153*199767f8SToomas Soome 
154*199767f8SToomas Soome static __inline void
155*199767f8SToomas Soome mfence(void)
156*199767f8SToomas Soome {
157*199767f8SToomas Soome 
158*199767f8SToomas Soome 	__asm __volatile("mfence" : : : "memory");
159*199767f8SToomas Soome }
160*199767f8SToomas Soome 
161*199767f8SToomas Soome #ifdef _KERNEL
162*199767f8SToomas Soome 
163*199767f8SToomas Soome #define	HAVE_INLINE_FFS
164*199767f8SToomas Soome 
165*199767f8SToomas Soome static __inline int
166*199767f8SToomas Soome ffs(int mask)
167*199767f8SToomas Soome {
168*199767f8SToomas Soome 	/*
169*199767f8SToomas Soome 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
170*199767f8SToomas Soome 	 * this inline or turn off the builtin.  The builtin is faster but
171*199767f8SToomas Soome 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
172*199767f8SToomas Soome 	 * versions.
173*199767f8SToomas Soome 	 */
174*199767f8SToomas Soome 	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
175*199767f8SToomas Soome }
176*199767f8SToomas Soome 
177*199767f8SToomas Soome #define	HAVE_INLINE_FFSL
178*199767f8SToomas Soome 
179*199767f8SToomas Soome static __inline int
180*199767f8SToomas Soome ffsl(long mask)
181*199767f8SToomas Soome {
182*199767f8SToomas Soome 	return (ffs((int)mask));
183*199767f8SToomas Soome }
184*199767f8SToomas Soome 
185*199767f8SToomas Soome #define	HAVE_INLINE_FLS
186*199767f8SToomas Soome 
187*199767f8SToomas Soome static __inline int
188*199767f8SToomas Soome fls(int mask)
189*199767f8SToomas Soome {
190*199767f8SToomas Soome 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
191*199767f8SToomas Soome }
192*199767f8SToomas Soome 
193*199767f8SToomas Soome #define	HAVE_INLINE_FLSL
194*199767f8SToomas Soome 
195*199767f8SToomas Soome static __inline int
196*199767f8SToomas Soome flsl(long mask)
197*199767f8SToomas Soome {
198*199767f8SToomas Soome 	return (fls((int)mask));
199*199767f8SToomas Soome }
200*199767f8SToomas Soome 
201*199767f8SToomas Soome #endif /* _KERNEL */
202*199767f8SToomas Soome 
203*199767f8SToomas Soome static __inline void
204*199767f8SToomas Soome halt(void)
205*199767f8SToomas Soome {
206*199767f8SToomas Soome 	__asm __volatile("hlt");
207*199767f8SToomas Soome }
208*199767f8SToomas Soome 
209*199767f8SToomas Soome static __inline u_char
210*199767f8SToomas Soome inb(u_int port)
211*199767f8SToomas Soome {
212*199767f8SToomas Soome 	u_char	data;
213*199767f8SToomas Soome 
214*199767f8SToomas Soome 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
215*199767f8SToomas Soome 	return (data);
216*199767f8SToomas Soome }
217*199767f8SToomas Soome 
218*199767f8SToomas Soome static __inline u_int
219*199767f8SToomas Soome inl(u_int port)
220*199767f8SToomas Soome {
221*199767f8SToomas Soome 	u_int	data;
222*199767f8SToomas Soome 
223*199767f8SToomas Soome 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
224*199767f8SToomas Soome 	return (data);
225*199767f8SToomas Soome }
226*199767f8SToomas Soome 
227*199767f8SToomas Soome static __inline void
228*199767f8SToomas Soome insb(u_int port, void *addr, size_t count)
229*199767f8SToomas Soome {
230*199767f8SToomas Soome 	__asm __volatile("cld; rep; insb"
231*199767f8SToomas Soome 			 : "+D" (addr), "+c" (count)
232*199767f8SToomas Soome 			 : "d" (port)
233*199767f8SToomas Soome 			 : "memory");
234*199767f8SToomas Soome }
235*199767f8SToomas Soome 
236*199767f8SToomas Soome static __inline void
237*199767f8SToomas Soome insw(u_int port, void *addr, size_t count)
238*199767f8SToomas Soome {
239*199767f8SToomas Soome 	__asm __volatile("cld; rep; insw"
240*199767f8SToomas Soome 			 : "+D" (addr), "+c" (count)
241*199767f8SToomas Soome 			 : "d" (port)
242*199767f8SToomas Soome 			 : "memory");
243*199767f8SToomas Soome }
244*199767f8SToomas Soome 
245*199767f8SToomas Soome static __inline void
246*199767f8SToomas Soome insl(u_int port, void *addr, size_t count)
247*199767f8SToomas Soome {
248*199767f8SToomas Soome 	__asm __volatile("cld; rep; insl"
249*199767f8SToomas Soome 			 : "+D" (addr), "+c" (count)
250*199767f8SToomas Soome 			 : "d" (port)
251*199767f8SToomas Soome 			 : "memory");
252*199767f8SToomas Soome }
253*199767f8SToomas Soome 
254*199767f8SToomas Soome static __inline void
255*199767f8SToomas Soome invd(void)
256*199767f8SToomas Soome {
257*199767f8SToomas Soome 	__asm __volatile("invd");
258*199767f8SToomas Soome }
259*199767f8SToomas Soome 
260*199767f8SToomas Soome static __inline u_short
261*199767f8SToomas Soome inw(u_int port)
262*199767f8SToomas Soome {
263*199767f8SToomas Soome 	u_short	data;
264*199767f8SToomas Soome 
265*199767f8SToomas Soome 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
266*199767f8SToomas Soome 	return (data);
267*199767f8SToomas Soome }
268*199767f8SToomas Soome 
269*199767f8SToomas Soome static __inline void
270*199767f8SToomas Soome outb(u_int port, u_char data)
271*199767f8SToomas Soome {
272*199767f8SToomas Soome 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
273*199767f8SToomas Soome }
274*199767f8SToomas Soome 
275*199767f8SToomas Soome static __inline void
276*199767f8SToomas Soome outl(u_int port, u_int data)
277*199767f8SToomas Soome {
278*199767f8SToomas Soome 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
279*199767f8SToomas Soome }
280*199767f8SToomas Soome 
281*199767f8SToomas Soome static __inline void
282*199767f8SToomas Soome outsb(u_int port, const void *addr, size_t count)
283*199767f8SToomas Soome {
284*199767f8SToomas Soome 	__asm __volatile("cld; rep; outsb"
285*199767f8SToomas Soome 			 : "+S" (addr), "+c" (count)
286*199767f8SToomas Soome 			 : "d" (port));
287*199767f8SToomas Soome }
288*199767f8SToomas Soome 
289*199767f8SToomas Soome static __inline void
290*199767f8SToomas Soome outsw(u_int port, const void *addr, size_t count)
291*199767f8SToomas Soome {
292*199767f8SToomas Soome 	__asm __volatile("cld; rep; outsw"
293*199767f8SToomas Soome 			 : "+S" (addr), "+c" (count)
294*199767f8SToomas Soome 			 : "d" (port));
295*199767f8SToomas Soome }
296*199767f8SToomas Soome 
297*199767f8SToomas Soome static __inline void
298*199767f8SToomas Soome outsl(u_int port, const void *addr, size_t count)
299*199767f8SToomas Soome {
300*199767f8SToomas Soome 	__asm __volatile("cld; rep; outsl"
301*199767f8SToomas Soome 			 : "+S" (addr), "+c" (count)
302*199767f8SToomas Soome 			 : "d" (port));
303*199767f8SToomas Soome }
304*199767f8SToomas Soome 
305*199767f8SToomas Soome static __inline void
306*199767f8SToomas Soome outw(u_int port, u_short data)
307*199767f8SToomas Soome {
308*199767f8SToomas Soome 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
309*199767f8SToomas Soome }
310*199767f8SToomas Soome 
311*199767f8SToomas Soome static __inline void
312*199767f8SToomas Soome ia32_pause(void)
313*199767f8SToomas Soome {
314*199767f8SToomas Soome 	__asm __volatile("pause");
315*199767f8SToomas Soome }
316*199767f8SToomas Soome 
317*199767f8SToomas Soome static __inline u_int
318*199767f8SToomas Soome read_eflags(void)
319*199767f8SToomas Soome {
320*199767f8SToomas Soome 	u_int	ef;
321*199767f8SToomas Soome 
322*199767f8SToomas Soome 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
323*199767f8SToomas Soome 	return (ef);
324*199767f8SToomas Soome }
325*199767f8SToomas Soome 
326*199767f8SToomas Soome static __inline uint64_t
327*199767f8SToomas Soome rdmsr(u_int msr)
328*199767f8SToomas Soome {
329*199767f8SToomas Soome 	uint64_t rv;
330*199767f8SToomas Soome 
331*199767f8SToomas Soome 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
332*199767f8SToomas Soome 	return (rv);
333*199767f8SToomas Soome }
334*199767f8SToomas Soome 
335*199767f8SToomas Soome static __inline uint32_t
336*199767f8SToomas Soome rdmsr32(u_int msr)
337*199767f8SToomas Soome {
338*199767f8SToomas Soome 	uint32_t low;
339*199767f8SToomas Soome 
340*199767f8SToomas Soome 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "edx");
341*199767f8SToomas Soome 	return (low);
342*199767f8SToomas Soome }
343*199767f8SToomas Soome 
344*199767f8SToomas Soome static __inline uint64_t
345*199767f8SToomas Soome rdpmc(u_int pmc)
346*199767f8SToomas Soome {
347*199767f8SToomas Soome 	uint64_t rv;
348*199767f8SToomas Soome 
349*199767f8SToomas Soome 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
350*199767f8SToomas Soome 	return (rv);
351*199767f8SToomas Soome }
352*199767f8SToomas Soome 
353*199767f8SToomas Soome static __inline uint64_t
354*199767f8SToomas Soome rdtsc(void)
355*199767f8SToomas Soome {
356*199767f8SToomas Soome 	uint64_t rv;
357*199767f8SToomas Soome 
358*199767f8SToomas Soome 	__asm __volatile("rdtsc" : "=A" (rv));
359*199767f8SToomas Soome 	return (rv);
360*199767f8SToomas Soome }
361*199767f8SToomas Soome 
362*199767f8SToomas Soome static __inline uint32_t
363*199767f8SToomas Soome rdtsc32(void)
364*199767f8SToomas Soome {
365*199767f8SToomas Soome 	uint32_t rv;
366*199767f8SToomas Soome 
367*199767f8SToomas Soome 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
368*199767f8SToomas Soome 	return (rv);
369*199767f8SToomas Soome }
370*199767f8SToomas Soome 
371*199767f8SToomas Soome static __inline void
372*199767f8SToomas Soome wbinvd(void)
373*199767f8SToomas Soome {
374*199767f8SToomas Soome 	__asm __volatile("wbinvd");
375*199767f8SToomas Soome }
376*199767f8SToomas Soome 
377*199767f8SToomas Soome static __inline void
378*199767f8SToomas Soome write_eflags(u_int ef)
379*199767f8SToomas Soome {
380*199767f8SToomas Soome 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
381*199767f8SToomas Soome }
382*199767f8SToomas Soome 
383*199767f8SToomas Soome static __inline void
384*199767f8SToomas Soome wrmsr(u_int msr, uint64_t newval)
385*199767f8SToomas Soome {
386*199767f8SToomas Soome 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
387*199767f8SToomas Soome }
388*199767f8SToomas Soome 
389*199767f8SToomas Soome static __inline void
390*199767f8SToomas Soome load_cr0(u_int data)
391*199767f8SToomas Soome {
392*199767f8SToomas Soome 
393*199767f8SToomas Soome 	__asm __volatile("movl %0,%%cr0" : : "r" (data));
394*199767f8SToomas Soome }
395*199767f8SToomas Soome 
396*199767f8SToomas Soome static __inline u_int
397*199767f8SToomas Soome rcr0(void)
398*199767f8SToomas Soome {
399*199767f8SToomas Soome 	u_int	data;
400*199767f8SToomas Soome 
401*199767f8SToomas Soome 	__asm __volatile("movl %%cr0,%0" : "=r" (data));
402*199767f8SToomas Soome 	return (data);
403*199767f8SToomas Soome }
404*199767f8SToomas Soome 
405*199767f8SToomas Soome static __inline u_int
406*199767f8SToomas Soome rcr2(void)
407*199767f8SToomas Soome {
408*199767f8SToomas Soome 	u_int	data;
409*199767f8SToomas Soome 
410*199767f8SToomas Soome 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
411*199767f8SToomas Soome 	return (data);
412*199767f8SToomas Soome }
413*199767f8SToomas Soome 
414*199767f8SToomas Soome static __inline void
415*199767f8SToomas Soome load_cr3(u_int data)
416*199767f8SToomas Soome {
417*199767f8SToomas Soome 
418*199767f8SToomas Soome 	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
419*199767f8SToomas Soome }
420*199767f8SToomas Soome 
421*199767f8SToomas Soome static __inline u_int
422*199767f8SToomas Soome rcr3(void)
423*199767f8SToomas Soome {
424*199767f8SToomas Soome 	u_int	data;
425*199767f8SToomas Soome 
426*199767f8SToomas Soome 	__asm __volatile("movl %%cr3,%0" : "=r" (data));
427*199767f8SToomas Soome 	return (data);
428*199767f8SToomas Soome }
429*199767f8SToomas Soome 
430*199767f8SToomas Soome static __inline void
431*199767f8SToomas Soome load_cr4(u_int data)
432*199767f8SToomas Soome {
433*199767f8SToomas Soome 	__asm __volatile("movl %0,%%cr4" : : "r" (data));
434*199767f8SToomas Soome }
435*199767f8SToomas Soome 
436*199767f8SToomas Soome static __inline u_int
437*199767f8SToomas Soome rcr4(void)
438*199767f8SToomas Soome {
439*199767f8SToomas Soome 	u_int	data;
440*199767f8SToomas Soome 
441*199767f8SToomas Soome 	__asm __volatile("movl %%cr4,%0" : "=r" (data));
442*199767f8SToomas Soome 	return (data);
443*199767f8SToomas Soome }
444*199767f8SToomas Soome 
445*199767f8SToomas Soome static __inline uint64_t
446*199767f8SToomas Soome rxcr(u_int reg)
447*199767f8SToomas Soome {
448*199767f8SToomas Soome 	u_int low, high;
449*199767f8SToomas Soome 
450*199767f8SToomas Soome 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
451*199767f8SToomas Soome 	return (low | ((uint64_t)high << 32));
452*199767f8SToomas Soome }
453*199767f8SToomas Soome 
454*199767f8SToomas Soome static __inline void
455*199767f8SToomas Soome load_xcr(u_int reg, uint64_t val)
456*199767f8SToomas Soome {
457*199767f8SToomas Soome 	u_int low, high;
458*199767f8SToomas Soome 
459*199767f8SToomas Soome 	low = val;
460*199767f8SToomas Soome 	high = val >> 32;
461*199767f8SToomas Soome 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
462*199767f8SToomas Soome }
463*199767f8SToomas Soome 
464*199767f8SToomas Soome /*
465*199767f8SToomas Soome  * Global TLB flush (except for thise for pages marked PG_G)
466*199767f8SToomas Soome  */
467*199767f8SToomas Soome static __inline void
468*199767f8SToomas Soome invltlb(void)
469*199767f8SToomas Soome {
470*199767f8SToomas Soome 
471*199767f8SToomas Soome 	load_cr3(rcr3());
472*199767f8SToomas Soome }
473*199767f8SToomas Soome 
474*199767f8SToomas Soome /*
475*199767f8SToomas Soome  * TLB flush for an individual page (even if it has PG_G).
476*199767f8SToomas Soome  * Only works on 486+ CPUs (i386 does not have PG_G).
477*199767f8SToomas Soome  */
478*199767f8SToomas Soome static __inline void
479*199767f8SToomas Soome invlpg(u_int addr)
480*199767f8SToomas Soome {
481*199767f8SToomas Soome 
482*199767f8SToomas Soome 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
483*199767f8SToomas Soome }
484*199767f8SToomas Soome 
485*199767f8SToomas Soome static __inline u_short
486*199767f8SToomas Soome rfs(void)
487*199767f8SToomas Soome {
488*199767f8SToomas Soome 	u_short sel;
489*199767f8SToomas Soome 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
490*199767f8SToomas Soome 	return (sel);
491*199767f8SToomas Soome }
492*199767f8SToomas Soome 
493*199767f8SToomas Soome static __inline uint64_t
494*199767f8SToomas Soome rgdt(void)
495*199767f8SToomas Soome {
496*199767f8SToomas Soome 	uint64_t gdtr;
497*199767f8SToomas Soome 	__asm __volatile("sgdt %0" : "=m" (gdtr));
498*199767f8SToomas Soome 	return (gdtr);
499*199767f8SToomas Soome }
500*199767f8SToomas Soome 
501*199767f8SToomas Soome static __inline u_short
502*199767f8SToomas Soome rgs(void)
503*199767f8SToomas Soome {
504*199767f8SToomas Soome 	u_short sel;
505*199767f8SToomas Soome 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
506*199767f8SToomas Soome 	return (sel);
507*199767f8SToomas Soome }
508*199767f8SToomas Soome 
509*199767f8SToomas Soome static __inline uint64_t
510*199767f8SToomas Soome ridt(void)
511*199767f8SToomas Soome {
512*199767f8SToomas Soome 	uint64_t idtr;
513*199767f8SToomas Soome 	__asm __volatile("sidt %0" : "=m" (idtr));
514*199767f8SToomas Soome 	return (idtr);
515*199767f8SToomas Soome }
516*199767f8SToomas Soome 
517*199767f8SToomas Soome static __inline u_short
518*199767f8SToomas Soome rldt(void)
519*199767f8SToomas Soome {
520*199767f8SToomas Soome 	u_short ldtr;
521*199767f8SToomas Soome 	__asm __volatile("sldt %0" : "=g" (ldtr));
522*199767f8SToomas Soome 	return (ldtr);
523*199767f8SToomas Soome }
524*199767f8SToomas Soome 
525*199767f8SToomas Soome static __inline u_short
526*199767f8SToomas Soome rss(void)
527*199767f8SToomas Soome {
528*199767f8SToomas Soome 	u_short sel;
529*199767f8SToomas Soome 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
530*199767f8SToomas Soome 	return (sel);
531*199767f8SToomas Soome }
532*199767f8SToomas Soome 
533*199767f8SToomas Soome static __inline u_short
534*199767f8SToomas Soome rtr(void)
535*199767f8SToomas Soome {
536*199767f8SToomas Soome 	u_short tr;
537*199767f8SToomas Soome 	__asm __volatile("str %0" : "=g" (tr));
538*199767f8SToomas Soome 	return (tr);
539*199767f8SToomas Soome }
540*199767f8SToomas Soome 
541*199767f8SToomas Soome static __inline void
542*199767f8SToomas Soome load_fs(u_short sel)
543*199767f8SToomas Soome {
544*199767f8SToomas Soome 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
545*199767f8SToomas Soome }
546*199767f8SToomas Soome 
547*199767f8SToomas Soome static __inline void
548*199767f8SToomas Soome load_gs(u_short sel)
549*199767f8SToomas Soome {
550*199767f8SToomas Soome 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
551*199767f8SToomas Soome }
552*199767f8SToomas Soome 
553*199767f8SToomas Soome static __inline void
554*199767f8SToomas Soome lidt(struct region_descriptor *addr)
555*199767f8SToomas Soome {
556*199767f8SToomas Soome 	__asm __volatile("lidt (%0)" : : "r" (addr));
557*199767f8SToomas Soome }
558*199767f8SToomas Soome 
559*199767f8SToomas Soome static __inline void
560*199767f8SToomas Soome lldt(u_short sel)
561*199767f8SToomas Soome {
562*199767f8SToomas Soome 	__asm __volatile("lldt %0" : : "r" (sel));
563*199767f8SToomas Soome }
564*199767f8SToomas Soome 
565*199767f8SToomas Soome static __inline void
566*199767f8SToomas Soome ltr(u_short sel)
567*199767f8SToomas Soome {
568*199767f8SToomas Soome 	__asm __volatile("ltr %0" : : "r" (sel));
569*199767f8SToomas Soome }
570*199767f8SToomas Soome 
571*199767f8SToomas Soome static __inline u_int
572*199767f8SToomas Soome rdr0(void)
573*199767f8SToomas Soome {
574*199767f8SToomas Soome 	u_int	data;
575*199767f8SToomas Soome 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
576*199767f8SToomas Soome 	return (data);
577*199767f8SToomas Soome }
578*199767f8SToomas Soome 
579*199767f8SToomas Soome static __inline void
580*199767f8SToomas Soome load_dr0(u_int dr0)
581*199767f8SToomas Soome {
582*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
583*199767f8SToomas Soome }
584*199767f8SToomas Soome 
585*199767f8SToomas Soome static __inline u_int
586*199767f8SToomas Soome rdr1(void)
587*199767f8SToomas Soome {
588*199767f8SToomas Soome 	u_int	data;
589*199767f8SToomas Soome 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
590*199767f8SToomas Soome 	return (data);
591*199767f8SToomas Soome }
592*199767f8SToomas Soome 
593*199767f8SToomas Soome static __inline void
594*199767f8SToomas Soome load_dr1(u_int dr1)
595*199767f8SToomas Soome {
596*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
597*199767f8SToomas Soome }
598*199767f8SToomas Soome 
599*199767f8SToomas Soome static __inline u_int
600*199767f8SToomas Soome rdr2(void)
601*199767f8SToomas Soome {
602*199767f8SToomas Soome 	u_int	data;
603*199767f8SToomas Soome 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
604*199767f8SToomas Soome 	return (data);
605*199767f8SToomas Soome }
606*199767f8SToomas Soome 
607*199767f8SToomas Soome static __inline void
608*199767f8SToomas Soome load_dr2(u_int dr2)
609*199767f8SToomas Soome {
610*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
611*199767f8SToomas Soome }
612*199767f8SToomas Soome 
613*199767f8SToomas Soome static __inline u_int
614*199767f8SToomas Soome rdr3(void)
615*199767f8SToomas Soome {
616*199767f8SToomas Soome 	u_int	data;
617*199767f8SToomas Soome 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
618*199767f8SToomas Soome 	return (data);
619*199767f8SToomas Soome }
620*199767f8SToomas Soome 
621*199767f8SToomas Soome static __inline void
622*199767f8SToomas Soome load_dr3(u_int dr3)
623*199767f8SToomas Soome {
624*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
625*199767f8SToomas Soome }
626*199767f8SToomas Soome 
627*199767f8SToomas Soome static __inline u_int
628*199767f8SToomas Soome rdr4(void)
629*199767f8SToomas Soome {
630*199767f8SToomas Soome 	u_int	data;
631*199767f8SToomas Soome 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
632*199767f8SToomas Soome 	return (data);
633*199767f8SToomas Soome }
634*199767f8SToomas Soome 
635*199767f8SToomas Soome static __inline void
636*199767f8SToomas Soome load_dr4(u_int dr4)
637*199767f8SToomas Soome {
638*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
639*199767f8SToomas Soome }
640*199767f8SToomas Soome 
641*199767f8SToomas Soome static __inline u_int
642*199767f8SToomas Soome rdr5(void)
643*199767f8SToomas Soome {
644*199767f8SToomas Soome 	u_int	data;
645*199767f8SToomas Soome 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
646*199767f8SToomas Soome 	return (data);
647*199767f8SToomas Soome }
648*199767f8SToomas Soome 
649*199767f8SToomas Soome static __inline void
650*199767f8SToomas Soome load_dr5(u_int dr5)
651*199767f8SToomas Soome {
652*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
653*199767f8SToomas Soome }
654*199767f8SToomas Soome 
655*199767f8SToomas Soome static __inline u_int
656*199767f8SToomas Soome rdr6(void)
657*199767f8SToomas Soome {
658*199767f8SToomas Soome 	u_int	data;
659*199767f8SToomas Soome 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
660*199767f8SToomas Soome 	return (data);
661*199767f8SToomas Soome }
662*199767f8SToomas Soome 
663*199767f8SToomas Soome static __inline void
664*199767f8SToomas Soome load_dr6(u_int dr6)
665*199767f8SToomas Soome {
666*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
667*199767f8SToomas Soome }
668*199767f8SToomas Soome 
669*199767f8SToomas Soome static __inline u_int
670*199767f8SToomas Soome rdr7(void)
671*199767f8SToomas Soome {
672*199767f8SToomas Soome 	u_int	data;
673*199767f8SToomas Soome 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
674*199767f8SToomas Soome 	return (data);
675*199767f8SToomas Soome }
676*199767f8SToomas Soome 
677*199767f8SToomas Soome static __inline void
678*199767f8SToomas Soome load_dr7(u_int dr7)
679*199767f8SToomas Soome {
680*199767f8SToomas Soome 	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
681*199767f8SToomas Soome }
682*199767f8SToomas Soome 
683*199767f8SToomas Soome static __inline u_char
684*199767f8SToomas Soome read_cyrix_reg(u_char reg)
685*199767f8SToomas Soome {
686*199767f8SToomas Soome 	outb(0x22, reg);
687*199767f8SToomas Soome 	return inb(0x23);
688*199767f8SToomas Soome }
689*199767f8SToomas Soome 
690*199767f8SToomas Soome static __inline void
691*199767f8SToomas Soome write_cyrix_reg(u_char reg, u_char data)
692*199767f8SToomas Soome {
693*199767f8SToomas Soome 	outb(0x22, reg);
694*199767f8SToomas Soome 	outb(0x23, data);
695*199767f8SToomas Soome }
696*199767f8SToomas Soome 
697*199767f8SToomas Soome static __inline register_t
698*199767f8SToomas Soome intr_disable(void)
699*199767f8SToomas Soome {
700*199767f8SToomas Soome 	register_t eflags;
701*199767f8SToomas Soome 
702*199767f8SToomas Soome 	eflags = read_eflags();
703*199767f8SToomas Soome 	disable_intr();
704*199767f8SToomas Soome 	return (eflags);
705*199767f8SToomas Soome }
706*199767f8SToomas Soome 
707*199767f8SToomas Soome static __inline void
708*199767f8SToomas Soome intr_restore(register_t eflags)
709*199767f8SToomas Soome {
710*199767f8SToomas Soome 	write_eflags(eflags);
711*199767f8SToomas Soome }
712*199767f8SToomas Soome 
713*199767f8SToomas Soome #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
714*199767f8SToomas Soome 
715*199767f8SToomas Soome int	breakpoint(void);
716*199767f8SToomas Soome u_int	bsfl(u_int mask);
717*199767f8SToomas Soome u_int	bsrl(u_int mask);
718*199767f8SToomas Soome void	clflush(u_long addr);
719*199767f8SToomas Soome void	clts(void);
720*199767f8SToomas Soome void	cpuid_count(u_int ax, u_int cx, u_int *p);
721*199767f8SToomas Soome void	disable_intr(void);
722*199767f8SToomas Soome void	do_cpuid(u_int ax, u_int *p);
723*199767f8SToomas Soome void	enable_intr(void);
724*199767f8SToomas Soome void	halt(void);
725*199767f8SToomas Soome void	ia32_pause(void);
726*199767f8SToomas Soome u_char	inb(u_int port);
727*199767f8SToomas Soome u_int	inl(u_int port);
728*199767f8SToomas Soome void	insb(u_int port, void *addr, size_t count);
729*199767f8SToomas Soome void	insl(u_int port, void *addr, size_t count);
730*199767f8SToomas Soome void	insw(u_int port, void *addr, size_t count);
731*199767f8SToomas Soome register_t	intr_disable(void);
732*199767f8SToomas Soome void	intr_restore(register_t ef);
733*199767f8SToomas Soome void	invd(void);
734*199767f8SToomas Soome void	invlpg(u_int addr);
735*199767f8SToomas Soome void	invltlb(void);
736*199767f8SToomas Soome u_short	inw(u_int port);
737*199767f8SToomas Soome void	lidt(struct region_descriptor *addr);
738*199767f8SToomas Soome void	lldt(u_short sel);
739*199767f8SToomas Soome void	load_cr0(u_int cr0);
740*199767f8SToomas Soome void	load_cr3(u_int cr3);
741*199767f8SToomas Soome void	load_cr4(u_int cr4);
742*199767f8SToomas Soome void	load_dr0(u_int dr0);
743*199767f8SToomas Soome void	load_dr1(u_int dr1);
744*199767f8SToomas Soome void	load_dr2(u_int dr2);
745*199767f8SToomas Soome void	load_dr3(u_int dr3);
746*199767f8SToomas Soome void	load_dr4(u_int dr4);
747*199767f8SToomas Soome void	load_dr5(u_int dr5);
748*199767f8SToomas Soome void	load_dr6(u_int dr6);
749*199767f8SToomas Soome void	load_dr7(u_int dr7);
750*199767f8SToomas Soome void	load_fs(u_short sel);
751*199767f8SToomas Soome void	load_gs(u_short sel);
752*199767f8SToomas Soome void	ltr(u_short sel);
753*199767f8SToomas Soome void	outb(u_int port, u_char data);
754*199767f8SToomas Soome void	outl(u_int port, u_int data);
755*199767f8SToomas Soome void	outsb(u_int port, const void *addr, size_t count);
756*199767f8SToomas Soome void	outsl(u_int port, const void *addr, size_t count);
757*199767f8SToomas Soome void	outsw(u_int port, const void *addr, size_t count);
758*199767f8SToomas Soome void	outw(u_int port, u_short data);
759*199767f8SToomas Soome u_int	rcr0(void);
760*199767f8SToomas Soome u_int	rcr2(void);
761*199767f8SToomas Soome u_int	rcr3(void);
762*199767f8SToomas Soome u_int	rcr4(void);
763*199767f8SToomas Soome uint64_t rdmsr(u_int msr);
764*199767f8SToomas Soome uint64_t rdpmc(u_int pmc);
765*199767f8SToomas Soome u_int	rdr0(void);
766*199767f8SToomas Soome u_int	rdr1(void);
767*199767f8SToomas Soome u_int	rdr2(void);
768*199767f8SToomas Soome u_int	rdr3(void);
769*199767f8SToomas Soome u_int	rdr4(void);
770*199767f8SToomas Soome u_int	rdr5(void);
771*199767f8SToomas Soome u_int	rdr6(void);
772*199767f8SToomas Soome u_int	rdr7(void);
773*199767f8SToomas Soome uint64_t rdtsc(void);
774*199767f8SToomas Soome u_char	read_cyrix_reg(u_char reg);
775*199767f8SToomas Soome u_int	read_eflags(void);
776*199767f8SToomas Soome u_int	rfs(void);
777*199767f8SToomas Soome uint64_t rgdt(void);
778*199767f8SToomas Soome u_int	rgs(void);
779*199767f8SToomas Soome uint64_t ridt(void);
780*199767f8SToomas Soome u_short	rldt(void);
781*199767f8SToomas Soome u_short	rtr(void);
782*199767f8SToomas Soome void	wbinvd(void);
783*199767f8SToomas Soome void	write_cyrix_reg(u_char reg, u_char data);
784*199767f8SToomas Soome void	write_eflags(u_int ef);
785*199767f8SToomas Soome void	wrmsr(u_int msr, uint64_t newval);
786*199767f8SToomas Soome 
787*199767f8SToomas Soome #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
788*199767f8SToomas Soome 
789*199767f8SToomas Soome void    reset_dbregs(void);
790*199767f8SToomas Soome 
791*199767f8SToomas Soome #ifdef _KERNEL
792*199767f8SToomas Soome int	rdmsr_safe(u_int msr, uint64_t *val);
793*199767f8SToomas Soome int	wrmsr_safe(u_int msr, uint64_t newval);
794*199767f8SToomas Soome #endif
795*199767f8SToomas Soome 
796*199767f8SToomas Soome #endif /* !_MACHINE_CPUFUNC_H_ */
797