xref: /freebsd/sys/amd64/include/cpufunc.h (revision ba74981e7154d14d375995a559f5b9f8529e6c3d)
13c4dd356SDavid Greenman /*-
23c4dd356SDavid Greenman  * Copyright (c) 1993 The Regents of the University of California.
33c4dd356SDavid Greenman  * All rights reserved.
43c4dd356SDavid Greenman  *
53c4dd356SDavid Greenman  * Redistribution and use in source and binary forms, with or without
63c4dd356SDavid Greenman  * modification, are permitted provided that the following conditions
73c4dd356SDavid Greenman  * are met:
83c4dd356SDavid Greenman  * 1. Redistributions of source code must retain the above copyright
93c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer.
103c4dd356SDavid Greenman  * 2. Redistributions in binary form must reproduce the above copyright
113c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer in the
123c4dd356SDavid Greenman  *    documentation and/or other materials provided with the distribution.
133c4dd356SDavid Greenman  * 3. All advertising materials mentioning features or use of this software
143c4dd356SDavid Greenman  *    must display the following acknowledgement:
153c4dd356SDavid Greenman  *	This product includes software developed by the University of
163c4dd356SDavid Greenman  *	California, Berkeley and its contributors.
173c4dd356SDavid Greenman  * 4. Neither the name of the University nor the names of its contributors
183c4dd356SDavid Greenman  *    may be used to endorse or promote products derived from this software
193c4dd356SDavid Greenman  *    without specific prior written permission.
203c4dd356SDavid Greenman  *
213c4dd356SDavid Greenman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
223c4dd356SDavid Greenman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
233c4dd356SDavid Greenman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
243c4dd356SDavid Greenman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
253c4dd356SDavid Greenman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
263c4dd356SDavid Greenman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
273c4dd356SDavid Greenman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
283c4dd356SDavid Greenman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
293c4dd356SDavid Greenman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
303c4dd356SDavid Greenman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
313c4dd356SDavid Greenman  * SUCH DAMAGE.
323c4dd356SDavid Greenman  *
33c3aac50fSPeter Wemm  * $FreeBSD$
343c4dd356SDavid Greenman  */
353c4dd356SDavid Greenman 
365b81b6b3SRodney W. Grimes /*
375b81b6b3SRodney W. Grimes  * Functions to provide access to special i386 instructions.
38f5d9a10bSMark Murray  * This in included in sys/systm.h, and that file should be
39f5d9a10bSMark Murray  * used in preference to this.
405b81b6b3SRodney W. Grimes  */
415b81b6b3SRodney W. Grimes 
426e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
43004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
446e393973SGarrett Wollman 
4529d5de8aSWarner Losh #include <sys/cdefs.h>
467e1f6dfeSJohn Baldwin #include <machine/psl.h>
4729d5de8aSWarner Losh 
4829d5de8aSWarner Losh __BEGIN_DECLS
49e31fa854SDoug Rabson #define readb(va)	(*(volatile u_int8_t *) (va))
50e31fa854SDoug Rabson #define readw(va)	(*(volatile u_int16_t *) (va))
51e31fa854SDoug Rabson #define readl(va)	(*(volatile u_int32_t *) (va))
52e31fa854SDoug Rabson 
53e31fa854SDoug Rabson #define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
54e31fa854SDoug Rabson #define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
55e31fa854SDoug Rabson #define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
56e31fa854SDoug Rabson 
57181df8c9SMatthew Dillon #define	CRITICAL_FORK	(read_eflags() | PSL_I)
587e1f6dfeSJohn Baldwin 
595b81b6b3SRodney W. Grimes #ifdef	__GNUC__
605b81b6b3SRodney W. Grimes 
612a32c15fSBruce Evans #ifdef SWTCH_OPTIM_STATS
622a32c15fSBruce Evans extern	int	tlb_flush_count;	/* XXX */
632a32c15fSBruce Evans #endif
642a32c15fSBruce Evans 
655dbd168eSBruce Evans static __inline void
665dbd168eSBruce Evans breakpoint(void)
67004bedebSBruce Evans {
68004bedebSBruce Evans 	__asm __volatile("int $3");
695b81b6b3SRodney W. Grimes }
705b81b6b3SRodney W. Grimes 
71c83b1328SBruce Evans static __inline u_int
72c83b1328SBruce Evans bsfl(u_int mask)
73c83b1328SBruce Evans {
74c83b1328SBruce Evans 	u_int	result;
75c83b1328SBruce Evans 
763f9a462fSJohn Baldwin 	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
77c83b1328SBruce Evans 	return (result);
78c83b1328SBruce Evans }
79c83b1328SBruce Evans 
80c83b1328SBruce Evans static __inline u_int
81c83b1328SBruce Evans bsrl(u_int mask)
82c83b1328SBruce Evans {
83c83b1328SBruce Evans 	u_int	result;
84c83b1328SBruce Evans 
853f9a462fSJohn Baldwin 	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
86c83b1328SBruce Evans 	return (result);
87c83b1328SBruce Evans }
88c83b1328SBruce Evans 
89004bedebSBruce Evans static __inline void
905b81b6b3SRodney W. Grimes disable_intr(void)
915b81b6b3SRodney W. Grimes {
928966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
935b81b6b3SRodney W. Grimes }
945b81b6b3SRodney W. Grimes 
95004bedebSBruce Evans static __inline void
965b81b6b3SRodney W. Grimes enable_intr(void)
975b81b6b3SRodney W. Grimes {
98fadc51bdSBruce Evans 	__asm __volatile("sti");
995b81b6b3SRodney W. Grimes }
1005b81b6b3SRodney W. Grimes 
101264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
102264c3d87SPeter Wemm 
103264c3d87SPeter Wemm static __inline int
104264c3d87SPeter Wemm ffs(int mask)
105264c3d87SPeter Wemm {
106264c3d87SPeter Wemm 	/*
107004bedebSBruce Evans 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
108004bedebSBruce Evans 	 * this inline or turn off the builtin.  The builtin is faster but
109c83b1328SBruce Evans 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
110c83b1328SBruce Evans 	 * versions.
111004bedebSBruce Evans 	 */
112c83b1328SBruce Evans 	 return (mask == 0 ? mask : bsfl((u_int)mask) + 1);
113004bedebSBruce Evans }
114004bedebSBruce Evans 
11513f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
11613f588f8SGarrett Wollman 
11713f588f8SGarrett Wollman static __inline int
11813f588f8SGarrett Wollman fls(int mask)
11913f588f8SGarrett Wollman {
120c83b1328SBruce Evans 	return (mask == 0 ? mask : bsrl((u_int)mask) + 1);
12113f588f8SGarrett Wollman }
12213f588f8SGarrett Wollman 
123004bedebSBruce Evans #if __GNUC__ < 2
124004bedebSBruce Evans 
125004bedebSBruce Evans #define	inb(port)		inbv(port)
126004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
127004bedebSBruce Evans 
128004bedebSBruce Evans #else /* __GNUC >= 2 */
129004bedebSBruce Evans 
130004bedebSBruce Evans /*
1318089a043SBruce Evans  * The following complications are to get around gcc not having a
1328089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1338089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1348089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1358089a043SBruce Evans  * the non-working version gets optimized away.
1368089a043SBruce Evans  *
137004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
138004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
139004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
140388dfa71SBruce Evans  *
141388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
142388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
143388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
144388dfa71SBruce Evans  * careful to avoid generating warnings.
145004bedebSBruce Evans  */
146388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
147004bedebSBruce Evans 	u_char	_data;							\
148388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
149388dfa71SBruce Evans 	    && (port) < 0x10000)					\
150004bedebSBruce Evans 		_data = inbc(port);					\
151004bedebSBruce Evans 	else								\
152004bedebSBruce Evans 		_data = inbv(port);					\
153004bedebSBruce Evans 	_data; })
154004bedebSBruce Evans 
155388dfa71SBruce Evans #define	outb(port, data) (						\
156388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
157388dfa71SBruce Evans 	&& (port) < 0x10000						\
158004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
159004bedebSBruce Evans 
160004bedebSBruce Evans static __inline u_char
161004bedebSBruce Evans inbc(u_int port)
162004bedebSBruce Evans {
163004bedebSBruce Evans 	u_char	data;
164004bedebSBruce Evans 
1658089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
166004bedebSBruce Evans 	return (data);
167004bedebSBruce Evans }
168004bedebSBruce Evans 
169004bedebSBruce Evans static __inline void
170004bedebSBruce Evans outbc(u_int port, u_char data)
171004bedebSBruce Evans {
1728089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
173004bedebSBruce Evans }
174004bedebSBruce Evans 
175004bedebSBruce Evans #endif /* __GNUC <= 2 */
176004bedebSBruce Evans 
177004bedebSBruce Evans static __inline u_char
178004bedebSBruce Evans inbv(u_int port)
179004bedebSBruce Evans {
180004bedebSBruce Evans 	u_char	data;
181004bedebSBruce Evans 	/*
182004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
183004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
184004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
185004bedebSBruce Evans 	 */
186004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
187004bedebSBruce Evans 	return (data);
188004bedebSBruce Evans }
189004bedebSBruce Evans 
19000be8601SBruce Evans static __inline u_int
191004bedebSBruce Evans inl(u_int port)
192004bedebSBruce Evans {
19300be8601SBruce Evans 	u_int	data;
194004bedebSBruce Evans 
195004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
196004bedebSBruce Evans 	return (data);
197004bedebSBruce Evans }
198004bedebSBruce Evans 
199004bedebSBruce Evans static __inline void
200004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
201004bedebSBruce Evans {
202004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
2033f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2043f9a462fSJohn Baldwin 			 : "d" (port)
205896763faSBruce Evans 			 : "memory");
206004bedebSBruce Evans }
207004bedebSBruce Evans 
208004bedebSBruce Evans static __inline void
209004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
210004bedebSBruce Evans {
211004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
2123f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2133f9a462fSJohn Baldwin 			 : "d" (port)
214896763faSBruce Evans 			 : "memory");
215004bedebSBruce Evans }
216004bedebSBruce Evans 
217004bedebSBruce Evans static __inline void
218004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
219004bedebSBruce Evans {
220004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
2213f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2223f9a462fSJohn Baldwin 			 : "d" (port)
223896763faSBruce Evans 			 : "memory");
224004bedebSBruce Evans }
225004bedebSBruce Evans 
226ece15d78SBruce Evans static __inline void
2274c024bbdSKATO Takenori invd(void)
2284c024bbdSKATO Takenori {
2294c024bbdSKATO Takenori 	__asm __volatile("invd");
2304c024bbdSKATO Takenori }
2314c024bbdSKATO Takenori 
232d1693e17SPeter Wemm #if defined(SMP) && defined(_KERNEL)
233d1693e17SPeter Wemm 
234d1693e17SPeter Wemm /*
235d1693e17SPeter Wemm  * When using APIC IPI's, invlpg() is not simply the invlpg instruction
236d1693e17SPeter Wemm  * (this is a bug) and the inlining cost is prohibitive since the call
237d1693e17SPeter Wemm  * executes into the IPI transmission system.
238d1693e17SPeter Wemm  */
239b63dc6adSAlfred Perlstein void	invlpg		(u_int addr);
240b63dc6adSAlfred Perlstein void	invltlb		(void);
241d1693e17SPeter Wemm 
242d1693e17SPeter Wemm static __inline void
243d1693e17SPeter Wemm cpu_invlpg(void *addr)
244d1693e17SPeter Wemm {
245d1693e17SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
246d1693e17SPeter Wemm }
247d1693e17SPeter Wemm 
248d1693e17SPeter Wemm static __inline void
249d1693e17SPeter Wemm cpu_invltlb(void)
250d1693e17SPeter Wemm {
251d1693e17SPeter Wemm 	u_int	temp;
252d1693e17SPeter Wemm 	/*
253d1693e17SPeter Wemm 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
254d1693e17SPeter Wemm 	 * is inlined.
255d1693e17SPeter Wemm 	 */
256d1693e17SPeter Wemm 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
257d1693e17SPeter Wemm 			 : : "memory");
258d1693e17SPeter Wemm #if defined(SWTCH_OPTIM_STATS)
259d1693e17SPeter Wemm 	++tlb_flush_count;
260d1693e17SPeter Wemm #endif
261d1693e17SPeter Wemm }
262d1693e17SPeter Wemm 
263d1693e17SPeter Wemm #else /* !(SMP && _KERNEL) */
264d1693e17SPeter Wemm 
265d1693e17SPeter Wemm static __inline void
266d1693e17SPeter Wemm invlpg(u_int addr)
267d1693e17SPeter Wemm {
268d1693e17SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
269d1693e17SPeter Wemm }
270d1693e17SPeter Wemm 
271d1693e17SPeter Wemm static __inline void
272d1693e17SPeter Wemm invltlb(void)
273d1693e17SPeter Wemm {
274d1693e17SPeter Wemm 	u_int	temp;
275d1693e17SPeter Wemm 	/*
276d1693e17SPeter Wemm 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
277d1693e17SPeter Wemm 	 * is inlined.
278d1693e17SPeter Wemm 	 */
279d1693e17SPeter Wemm 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
280d1693e17SPeter Wemm 			 : : "memory");
281d1693e17SPeter Wemm #ifdef SWTCH_OPTIM_STATS
282d1693e17SPeter Wemm 	++tlb_flush_count;
283d1693e17SPeter Wemm #endif
284d1693e17SPeter Wemm }
285d1693e17SPeter Wemm 
286d1693e17SPeter Wemm #endif /* SMP && _KERNEL */
287d1693e17SPeter Wemm 
288004bedebSBruce Evans static __inline u_short
289004bedebSBruce Evans inw(u_int port)
290004bedebSBruce Evans {
291004bedebSBruce Evans 	u_short	data;
292004bedebSBruce Evans 
293004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
294004bedebSBruce Evans 	return (data);
295004bedebSBruce Evans }
296004bedebSBruce Evans 
297004bedebSBruce Evans static __inline void
298004bedebSBruce Evans outbv(u_int port, u_char data)
299004bedebSBruce Evans {
300004bedebSBruce Evans 	u_char	al;
301004bedebSBruce Evans 	/*
302004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
303004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
304004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
305004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
306004bedebSBruce Evans 	 */
307004bedebSBruce Evans 	al = data;
308004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
309004bedebSBruce Evans }
310004bedebSBruce Evans 
311004bedebSBruce Evans static __inline void
31200be8601SBruce Evans outl(u_int port, u_int data)
313004bedebSBruce Evans {
314004bedebSBruce Evans 	/*
315004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
316004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
317004bedebSBruce Evans 	 * assignment for them.
318004bedebSBruce Evans 	 */
319004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
320004bedebSBruce Evans }
321004bedebSBruce Evans 
322004bedebSBruce Evans static __inline void
323e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
324004bedebSBruce Evans {
325004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
3263f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3273f9a462fSJohn Baldwin 			 : "d" (port));
328004bedebSBruce Evans }
329004bedebSBruce Evans 
330004bedebSBruce Evans static __inline void
331e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
332004bedebSBruce Evans {
333004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
3343f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3353f9a462fSJohn Baldwin 			 : "d" (port));
336004bedebSBruce Evans }
337004bedebSBruce Evans 
338004bedebSBruce Evans static __inline void
339e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
340004bedebSBruce Evans {
341004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
3423f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3433f9a462fSJohn Baldwin 			 : "d" (port));
344004bedebSBruce Evans }
345004bedebSBruce Evans 
346004bedebSBruce Evans static __inline void
347004bedebSBruce Evans outw(u_int port, u_short data)
348004bedebSBruce Evans {
349004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
350004bedebSBruce Evans }
351004bedebSBruce Evans 
35200be8601SBruce Evans static __inline u_int
353d1693e17SPeter Wemm rcr2(void)
354d1693e17SPeter Wemm {
355d1693e17SPeter Wemm 	u_int	data;
356d1693e17SPeter Wemm 
357d1693e17SPeter Wemm 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
358d1693e17SPeter Wemm 	return (data);
359d1693e17SPeter Wemm }
360d1693e17SPeter Wemm 
361d1693e17SPeter Wemm static __inline u_int
362004bedebSBruce Evans read_eflags(void)
3635b81b6b3SRodney W. Grimes {
36400be8601SBruce Evans 	u_int	ef;
365004bedebSBruce Evans 
366004bedebSBruce Evans 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3678db02de8SPaul Richards 	return (ef);
3685b81b6b3SRodney W. Grimes }
3695b81b6b3SRodney W. Grimes 
37034221a45SDavid Malone static __inline void
37134221a45SDavid Malone do_cpuid(u_int ax, u_int *p)
37234221a45SDavid Malone {
37334221a45SDavid Malone 	__asm __volatile(
37434221a45SDavid Malone 	"cpuid"
37534221a45SDavid Malone 	: "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
37634221a45SDavid Malone 	:  "0" (ax)
37734221a45SDavid Malone 	);
37834221a45SDavid Malone }
37934221a45SDavid Malone 
38000be8601SBruce Evans static __inline u_int64_t
3815dbd168eSBruce Evans rdmsr(u_int msr)
3825dbd168eSBruce Evans {
38300be8601SBruce Evans 	u_int64_t rv;
3845dbd168eSBruce Evans 
38539413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3865dbd168eSBruce Evans 	return (rv);
3875dbd168eSBruce Evans }
3885dbd168eSBruce Evans 
38900be8601SBruce Evans static __inline u_int64_t
3905dbd168eSBruce Evans rdpmc(u_int pmc)
3915dbd168eSBruce Evans {
39200be8601SBruce Evans 	u_int64_t rv;
3935dbd168eSBruce Evans 
39439413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3955dbd168eSBruce Evans 	return (rv);
3965dbd168eSBruce Evans }
3975dbd168eSBruce Evans 
39800be8601SBruce Evans static __inline u_int64_t
3995dbd168eSBruce Evans rdtsc(void)
4005dbd168eSBruce Evans {
40100be8601SBruce Evans 	u_int64_t rv;
4025dbd168eSBruce Evans 
40339413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
4045dbd168eSBruce Evans 	return (rv);
4055dbd168eSBruce Evans }
4065dbd168eSBruce Evans 
407004bedebSBruce Evans static __inline void
4084c024bbdSKATO Takenori wbinvd(void)
4094c024bbdSKATO Takenori {
4104c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
4114c024bbdSKATO Takenori }
4124c024bbdSKATO Takenori 
4134c024bbdSKATO Takenori static __inline void
41400be8601SBruce Evans write_eflags(u_int ef)
4155b81b6b3SRodney W. Grimes {
416004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
4175b81b6b3SRodney W. Grimes }
4185b81b6b3SRodney W. Grimes 
419d69e8502SGarrett Wollman static __inline void
42000be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
421d69e8502SGarrett Wollman {
42239413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
423d69e8502SGarrett Wollman }
424d69e8502SGarrett Wollman 
4255206bca1SLuoqi Chen static __inline u_int
4265206bca1SLuoqi Chen rfs(void)
4275206bca1SLuoqi Chen {
4285206bca1SLuoqi Chen 	u_int sel;
429e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4305206bca1SLuoqi Chen 	return (sel);
4315206bca1SLuoqi Chen }
4325206bca1SLuoqi Chen 
4335206bca1SLuoqi Chen static __inline u_int
4345206bca1SLuoqi Chen rgs(void)
4355206bca1SLuoqi Chen {
4365206bca1SLuoqi Chen 	u_int sel;
437e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4385206bca1SLuoqi Chen 	return (sel);
4395206bca1SLuoqi Chen }
4405206bca1SLuoqi Chen 
4415206bca1SLuoqi Chen static __inline void
4425206bca1SLuoqi Chen load_fs(u_int sel)
4435206bca1SLuoqi Chen {
444e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4455206bca1SLuoqi Chen }
4465206bca1SLuoqi Chen 
4475206bca1SLuoqi Chen static __inline void
4485206bca1SLuoqi Chen load_gs(u_int sel)
4495206bca1SLuoqi Chen {
450e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4515206bca1SLuoqi Chen }
4525206bca1SLuoqi Chen 
453de8050f9SBrian S. Dean static __inline u_int
454de8050f9SBrian S. Dean rdr0(void)
455de8050f9SBrian S. Dean {
456de8050f9SBrian S. Dean 	u_int	data;
45780275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
458de8050f9SBrian S. Dean 	return (data);
459de8050f9SBrian S. Dean }
460de8050f9SBrian S. Dean 
4616eda157eSBrian S. Dean static __inline void
4626eda157eSBrian S. Dean load_dr0(u_int sel)
4636eda157eSBrian S. Dean {
4646eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr0" : : "r" (sel));
4656eda157eSBrian S. Dean }
4666eda157eSBrian S. Dean 
467de8050f9SBrian S. Dean static __inline u_int
468de8050f9SBrian S. Dean rdr1(void)
469de8050f9SBrian S. Dean {
470de8050f9SBrian S. Dean 	u_int	data;
47180275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
472de8050f9SBrian S. Dean 	return (data);
473de8050f9SBrian S. Dean }
474de8050f9SBrian S. Dean 
4756eda157eSBrian S. Dean static __inline void
4766eda157eSBrian S. Dean load_dr1(u_int sel)
4776eda157eSBrian S. Dean {
4786eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr1" : : "r" (sel));
4796eda157eSBrian S. Dean }
4806eda157eSBrian S. Dean 
481de8050f9SBrian S. Dean static __inline u_int
482de8050f9SBrian S. Dean rdr2(void)
483de8050f9SBrian S. Dean {
484de8050f9SBrian S. Dean 	u_int	data;
48580275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
486de8050f9SBrian S. Dean 	return (data);
487de8050f9SBrian S. Dean }
488de8050f9SBrian S. Dean 
4896eda157eSBrian S. Dean static __inline void
4906eda157eSBrian S. Dean load_dr2(u_int sel)
4916eda157eSBrian S. Dean {
4926eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr2" : : "r" (sel));
4936eda157eSBrian S. Dean }
4946eda157eSBrian S. Dean 
495de8050f9SBrian S. Dean static __inline u_int
496de8050f9SBrian S. Dean rdr3(void)
497de8050f9SBrian S. Dean {
498de8050f9SBrian S. Dean 	u_int	data;
49980275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
500de8050f9SBrian S. Dean 	return (data);
501de8050f9SBrian S. Dean }
502de8050f9SBrian S. Dean 
5036eda157eSBrian S. Dean static __inline void
5046eda157eSBrian S. Dean load_dr3(u_int sel)
5056eda157eSBrian S. Dean {
5066eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr3" : : "r" (sel));
5076eda157eSBrian S. Dean }
5086eda157eSBrian S. Dean 
5096eda157eSBrian S. Dean static __inline u_int
5106eda157eSBrian S. Dean rdr4(void)
5116eda157eSBrian S. Dean {
5126eda157eSBrian S. Dean 	u_int	data;
5136eda157eSBrian S. Dean 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
5146eda157eSBrian S. Dean 	return (data);
5156eda157eSBrian S. Dean }
5166eda157eSBrian S. Dean 
5176eda157eSBrian S. Dean static __inline void
5186eda157eSBrian S. Dean load_dr4(u_int sel)
5196eda157eSBrian S. Dean {
5206eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr4" : : "r" (sel));
5216eda157eSBrian S. Dean }
5226eda157eSBrian S. Dean 
5236eda157eSBrian S. Dean static __inline u_int
5246eda157eSBrian S. Dean rdr5(void)
5256eda157eSBrian S. Dean {
5266eda157eSBrian S. Dean 	u_int	data;
5276eda157eSBrian S. Dean 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
5286eda157eSBrian S. Dean 	return (data);
5296eda157eSBrian S. Dean }
5306eda157eSBrian S. Dean 
5316eda157eSBrian S. Dean static __inline void
5326eda157eSBrian S. Dean load_dr5(u_int sel)
5336eda157eSBrian S. Dean {
5346eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr5" : : "r" (sel));
5356eda157eSBrian S. Dean }
5366eda157eSBrian S. Dean 
537de8050f9SBrian S. Dean static __inline u_int
538de8050f9SBrian S. Dean rdr6(void)
539de8050f9SBrian S. Dean {
540de8050f9SBrian S. Dean 	u_int	data;
54180275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
542de8050f9SBrian S. Dean 	return (data);
543de8050f9SBrian S. Dean }
544de8050f9SBrian S. Dean 
5456eda157eSBrian S. Dean static __inline void
5466eda157eSBrian S. Dean load_dr6(u_int sel)
5476eda157eSBrian S. Dean {
5486eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr6" : : "r" (sel));
5496eda157eSBrian S. Dean }
5506eda157eSBrian S. Dean 
551de8050f9SBrian S. Dean static __inline u_int
552de8050f9SBrian S. Dean rdr7(void)
553de8050f9SBrian S. Dean {
554de8050f9SBrian S. Dean 	u_int	data;
55580275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
556de8050f9SBrian S. Dean 	return (data);
557de8050f9SBrian S. Dean }
558de8050f9SBrian S. Dean 
5596eda157eSBrian S. Dean static __inline void
5606eda157eSBrian S. Dean load_dr7(u_int sel)
5616eda157eSBrian S. Dean {
5626eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr7" : : "r" (sel));
5636eda157eSBrian S. Dean }
5646eda157eSBrian S. Dean 
565034dc442SJohn Baldwin static __inline critical_t
5667e1f6dfeSJohn Baldwin cpu_critical_enter(void)
567034dc442SJohn Baldwin {
568034dc442SJohn Baldwin 	critical_t eflags;
569034dc442SJohn Baldwin 
570034dc442SJohn Baldwin 	eflags = read_eflags();
571034dc442SJohn Baldwin 	disable_intr();
572034dc442SJohn Baldwin 	return (eflags);
573034dc442SJohn Baldwin }
574034dc442SJohn Baldwin 
575034dc442SJohn Baldwin static __inline void
5767e1f6dfeSJohn Baldwin cpu_critical_exit(critical_t eflags)
577034dc442SJohn Baldwin {
578034dc442SJohn Baldwin 	write_eflags(eflags);
579034dc442SJohn Baldwin }
580034dc442SJohn Baldwin 
581ba74981eSWarner Losh static __inline register_t
582ba74981eSWarner Losh intr_disable(void)
583ba74981eSWarner Losh {
584ba74981eSWarner Losh 	register_t eflags;
585ba74981eSWarner Losh 
586ba74981eSWarner Losh 	eflags = read_eflags();
587ba74981eSWarner Losh 	disable_intr();
588ba74981eSWarner Losh 	return (eflags);
589ba74981eSWarner Losh }
590ba74981eSWarner Losh 
591ba74981eSWarner Losh static __inline void
592ba74981eSWarner Losh intr_restore(register_t eflags)
593ba74981eSWarner Losh {
594ba74981eSWarner Losh 	write_eflags(eflags);
595ba74981eSWarner Losh }
596ba74981eSWarner Losh 
597004bedebSBruce Evans #else /* !__GNUC__ */
5985b81b6b3SRodney W. Grimes 
599b63dc6adSAlfred Perlstein int	breakpoint(void);
600b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
601b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
602b63dc6adSAlfred Perlstein void	disable_intr(void);
603b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
604b63dc6adSAlfred Perlstein void	enable_intr(void);
605b63dc6adSAlfred Perlstein u_char	inb(u_int port);
606b63dc6adSAlfred Perlstein u_int	inl(u_int port);
607b63dc6adSAlfred Perlstein void	insb(u_int port, void *addr, size_t cnt);
608b63dc6adSAlfred Perlstein void	insl(u_int port, void *addr, size_t cnt);
609b63dc6adSAlfred Perlstein void	insw(u_int port, void *addr, size_t cnt);
610b63dc6adSAlfred Perlstein void	invd(void);
611b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
612b63dc6adSAlfred Perlstein void	invltlb(void);
613b63dc6adSAlfred Perlstein u_short	inw(u_int port);
614b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
615b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
616b63dc6adSAlfred Perlstein void	outsb(u_int port, void *addr, size_t cnt);
617b63dc6adSAlfred Perlstein void	outsl(u_int port, void *addr, size_t cnt);
618b63dc6adSAlfred Perlstein void	outsw(u_int port, void *addr, size_t cnt);
619b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
620b63dc6adSAlfred Perlstein u_int	rcr2(void);
621b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr);
622b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc);
623b63dc6adSAlfred Perlstein u_int64_t rdtsc(void);
624b63dc6adSAlfred Perlstein u_int	read_eflags(void);
625b63dc6adSAlfred Perlstein void	wbinvd(void);
626b63dc6adSAlfred Perlstein void	write_eflags(u_int ef);
627b63dc6adSAlfred Perlstein void	wrmsr(u_int msr, u_int64_t newval);
628b63dc6adSAlfred Perlstein u_int	rfs(void);
629b63dc6adSAlfred Perlstein u_int	rgs(void);
630b63dc6adSAlfred Perlstein void	load_fs(u_int sel);
631b63dc6adSAlfred Perlstein void	load_gs(u_int sel);
632b63dc6adSAlfred Perlstein critical_t cpu_critical_enter(void);
633b63dc6adSAlfred Perlstein void	cpu_critical_exit(critical_t eflags);
634004bedebSBruce Evans 
6355b81b6b3SRodney W. Grimes #endif	/* __GNUC__ */
6365b81b6b3SRodney W. Grimes 
637b63dc6adSAlfred Perlstein void	load_cr0(u_int cr0);
638b63dc6adSAlfred Perlstein void	load_cr3(u_int cr3);
639b63dc6adSAlfred Perlstein void	load_cr4(u_int cr4);
640b63dc6adSAlfred Perlstein void	ltr(u_short sel);
641b63dc6adSAlfred Perlstein u_int	rcr0(void);
642b63dc6adSAlfred Perlstein u_int	rcr3(void);
643b63dc6adSAlfred Perlstein u_int	rcr4(void);
644b63dc6adSAlfred Perlstein void    reset_dbregs(void);
64529d5de8aSWarner Losh __END_DECLS
6465b81b6b3SRodney W. Grimes 
647004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
648