xref: /freebsd/sys/amd64/include/cpufunc.h (revision 34221a4505175b5a07346c6c7ecb6ac8110564a7)
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.
385b81b6b3SRodney W. Grimes  */
395b81b6b3SRodney W. Grimes 
406e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
41004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
426e393973SGarrett Wollman 
4329d5de8aSWarner Losh #include <sys/cdefs.h>
447e1f6dfeSJohn Baldwin #include <machine/psl.h>
4529d5de8aSWarner Losh 
4629d5de8aSWarner Losh __BEGIN_DECLS
47e31fa854SDoug Rabson #define readb(va)	(*(volatile u_int8_t *) (va))
48e31fa854SDoug Rabson #define readw(va)	(*(volatile u_int16_t *) (va))
49e31fa854SDoug Rabson #define readl(va)	(*(volatile u_int32_t *) (va))
50e31fa854SDoug Rabson 
51e31fa854SDoug Rabson #define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
52e31fa854SDoug Rabson #define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
53e31fa854SDoug Rabson #define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
54e31fa854SDoug Rabson 
557e1f6dfeSJohn Baldwin #define	CRITICAL_FORK	(read_eflags() | PSL_I)
567e1f6dfeSJohn Baldwin 
575b81b6b3SRodney W. Grimes #ifdef	__GNUC__
585b81b6b3SRodney W. Grimes 
592a32c15fSBruce Evans #ifdef SWTCH_OPTIM_STATS
602a32c15fSBruce Evans extern	int	tlb_flush_count;	/* XXX */
612a32c15fSBruce Evans #endif
622a32c15fSBruce Evans 
635dbd168eSBruce Evans static __inline void
645dbd168eSBruce Evans breakpoint(void)
65004bedebSBruce Evans {
66004bedebSBruce Evans 	__asm __volatile("int $3");
675b81b6b3SRodney W. Grimes }
685b81b6b3SRodney W. Grimes 
69c83b1328SBruce Evans static __inline u_int
70c83b1328SBruce Evans bsfl(u_int mask)
71c83b1328SBruce Evans {
72c83b1328SBruce Evans 	u_int	result;
73c83b1328SBruce Evans 
743f9a462fSJohn Baldwin 	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
75c83b1328SBruce Evans 	return (result);
76c83b1328SBruce Evans }
77c83b1328SBruce Evans 
78c83b1328SBruce Evans static __inline u_int
79c83b1328SBruce Evans bsrl(u_int mask)
80c83b1328SBruce Evans {
81c83b1328SBruce Evans 	u_int	result;
82c83b1328SBruce Evans 
833f9a462fSJohn Baldwin 	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
84c83b1328SBruce Evans 	return (result);
85c83b1328SBruce Evans }
86c83b1328SBruce Evans 
87004bedebSBruce Evans static __inline void
885b81b6b3SRodney W. Grimes disable_intr(void)
895b81b6b3SRodney W. Grimes {
908966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
915b81b6b3SRodney W. Grimes }
925b81b6b3SRodney W. Grimes 
93004bedebSBruce Evans static __inline void
945b81b6b3SRodney W. Grimes enable_intr(void)
955b81b6b3SRodney W. Grimes {
96fadc51bdSBruce Evans 	__asm __volatile("sti");
975b81b6b3SRodney W. Grimes }
985b81b6b3SRodney W. Grimes 
99264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
100264c3d87SPeter Wemm 
101264c3d87SPeter Wemm static __inline int
102264c3d87SPeter Wemm ffs(int mask)
103264c3d87SPeter Wemm {
104264c3d87SPeter Wemm 	/*
105004bedebSBruce Evans 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
106004bedebSBruce Evans 	 * this inline or turn off the builtin.  The builtin is faster but
107c83b1328SBruce Evans 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
108c83b1328SBruce Evans 	 * versions.
109004bedebSBruce Evans 	 */
110c83b1328SBruce Evans 	 return (mask == 0 ? mask : bsfl((u_int)mask) + 1);
111004bedebSBruce Evans }
112004bedebSBruce Evans 
11313f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
11413f588f8SGarrett Wollman 
11513f588f8SGarrett Wollman static __inline int
11613f588f8SGarrett Wollman fls(int mask)
11713f588f8SGarrett Wollman {
118c83b1328SBruce Evans 	return (mask == 0 ? mask : bsrl((u_int)mask) + 1);
11913f588f8SGarrett Wollman }
12013f588f8SGarrett Wollman 
121004bedebSBruce Evans #if __GNUC__ < 2
122004bedebSBruce Evans 
123004bedebSBruce Evans #define	inb(port)		inbv(port)
124004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
125004bedebSBruce Evans 
126004bedebSBruce Evans #else /* __GNUC >= 2 */
127004bedebSBruce Evans 
128004bedebSBruce Evans /*
1298089a043SBruce Evans  * The following complications are to get around gcc not having a
1308089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1318089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1328089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1338089a043SBruce Evans  * the non-working version gets optimized away.
1348089a043SBruce Evans  *
135004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
136004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
137004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
138388dfa71SBruce Evans  *
139388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
140388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
141388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
142388dfa71SBruce Evans  * careful to avoid generating warnings.
143004bedebSBruce Evans  */
144388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
145004bedebSBruce Evans 	u_char	_data;							\
146388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
147388dfa71SBruce Evans 	    && (port) < 0x10000)					\
148004bedebSBruce Evans 		_data = inbc(port);					\
149004bedebSBruce Evans 	else								\
150004bedebSBruce Evans 		_data = inbv(port);					\
151004bedebSBruce Evans 	_data; })
152004bedebSBruce Evans 
153388dfa71SBruce Evans #define	outb(port, data) (						\
154388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
155388dfa71SBruce Evans 	&& (port) < 0x10000						\
156004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
157004bedebSBruce Evans 
158004bedebSBruce Evans static __inline u_char
159004bedebSBruce Evans inbc(u_int port)
160004bedebSBruce Evans {
161004bedebSBruce Evans 	u_char	data;
162004bedebSBruce Evans 
1638089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
164004bedebSBruce Evans 	return (data);
165004bedebSBruce Evans }
166004bedebSBruce Evans 
167004bedebSBruce Evans static __inline void
168004bedebSBruce Evans outbc(u_int port, u_char data)
169004bedebSBruce Evans {
1708089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
171004bedebSBruce Evans }
172004bedebSBruce Evans 
173004bedebSBruce Evans #endif /* __GNUC <= 2 */
174004bedebSBruce Evans 
175004bedebSBruce Evans static __inline u_char
176004bedebSBruce Evans inbv(u_int port)
177004bedebSBruce Evans {
178004bedebSBruce Evans 	u_char	data;
179004bedebSBruce Evans 	/*
180004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
181004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
182004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
183004bedebSBruce Evans 	 */
184004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
185004bedebSBruce Evans 	return (data);
186004bedebSBruce Evans }
187004bedebSBruce Evans 
18800be8601SBruce Evans static __inline u_int
189004bedebSBruce Evans inl(u_int port)
190004bedebSBruce Evans {
19100be8601SBruce Evans 	u_int	data;
192004bedebSBruce Evans 
193004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
194004bedebSBruce Evans 	return (data);
195004bedebSBruce Evans }
196004bedebSBruce Evans 
197004bedebSBruce Evans static __inline void
198004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
199004bedebSBruce Evans {
200004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
2013f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2023f9a462fSJohn Baldwin 			 : "d" (port)
203896763faSBruce Evans 			 : "memory");
204004bedebSBruce Evans }
205004bedebSBruce Evans 
206004bedebSBruce Evans static __inline void
207004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
208004bedebSBruce Evans {
209004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
2103f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2113f9a462fSJohn Baldwin 			 : "d" (port)
212896763faSBruce Evans 			 : "memory");
213004bedebSBruce Evans }
214004bedebSBruce Evans 
215004bedebSBruce Evans static __inline void
216004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
217004bedebSBruce Evans {
218004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
2193f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2203f9a462fSJohn Baldwin 			 : "d" (port)
221896763faSBruce Evans 			 : "memory");
222004bedebSBruce Evans }
223004bedebSBruce Evans 
224ece15d78SBruce Evans static __inline void
2254c024bbdSKATO Takenori invd(void)
2264c024bbdSKATO Takenori {
2274c024bbdSKATO Takenori 	__asm __volatile("invd");
2284c024bbdSKATO Takenori }
2294c024bbdSKATO Takenori 
230664a31e4SPeter Wemm #if defined(SMP) && defined(_KERNEL)
231477a642cSPeter Wemm 
232477a642cSPeter Wemm /*
233f48bbd5fSBruce Evans  * When using APIC IPI's, invlpg() is not simply the invlpg instruction
234f48bbd5fSBruce Evans  * (this is a bug) and the inlining cost is prohibitive since the call
235f40e6078SPeter Wemm  * executes into the IPI transmission system.
236477a642cSPeter Wemm  */
237a5e25da4SWarner Losh void	invlpg		__P((u_int addr));
238a5e25da4SWarner Losh void	invltlb		__P((void));
239477a642cSPeter Wemm 
2405498a452SJohn Dyson static __inline void
2415498a452SJohn Dyson cpu_invlpg(void *addr)
2425498a452SJohn Dyson {
2435498a452SJohn Dyson 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
2445498a452SJohn Dyson }
2455498a452SJohn Dyson 
2465931a9c2STor Egge static __inline void
2475931a9c2STor Egge cpu_invltlb(void)
2485931a9c2STor Egge {
24900be8601SBruce Evans 	u_int	temp;
2505931a9c2STor Egge 	/*
2515931a9c2STor Egge 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
2525931a9c2STor Egge 	 * is inlined.
2535931a9c2STor Egge 	 */
2545931a9c2STor Egge 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
2555931a9c2STor Egge 			 : : "memory");
2565931a9c2STor Egge #if defined(SWTCH_OPTIM_STATS)
2575931a9c2STor Egge 	++tlb_flush_count;
2585931a9c2STor Egge #endif
2595931a9c2STor Egge }
260f48bbd5fSBruce Evans 
261664a31e4SPeter Wemm #else /* !(SMP && _KERNEL) */
262477a642cSPeter Wemm 
2634c024bbdSKATO Takenori static __inline void
264471176aaSJohn Dyson invlpg(u_int addr)
265ece15d78SBruce Evans {
2665498a452SJohn Dyson 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
267ece15d78SBruce Evans }
268ece15d78SBruce Evans 
269ece15d78SBruce Evans static __inline void
270ece15d78SBruce Evans invltlb(void)
271ece15d78SBruce Evans {
27200be8601SBruce Evans 	u_int	temp;
273ece15d78SBruce Evans 	/*
274ece15d78SBruce Evans 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
275ece15d78SBruce Evans 	 * is inlined.
276ece15d78SBruce Evans 	 */
277ece15d78SBruce Evans 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
278ece15d78SBruce Evans 			 : : "memory");
279f48bbd5fSBruce Evans #ifdef SWTCH_OPTIM_STATS
28082566551SJohn Dyson 	++tlb_flush_count;
28182566551SJohn Dyson #endif
282ece15d78SBruce Evans }
2832c5d02ffSSteve Passe 
284664a31e4SPeter Wemm #endif /* SMP && _KERNEL */
285ece15d78SBruce Evans 
286004bedebSBruce Evans static __inline u_short
287004bedebSBruce Evans inw(u_int port)
288004bedebSBruce Evans {
289004bedebSBruce Evans 	u_short	data;
290004bedebSBruce Evans 
291004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
292004bedebSBruce Evans 	return (data);
293004bedebSBruce Evans }
294004bedebSBruce Evans 
295004bedebSBruce Evans static __inline void
296004bedebSBruce Evans outbv(u_int port, u_char data)
297004bedebSBruce Evans {
298004bedebSBruce Evans 	u_char	al;
299004bedebSBruce Evans 	/*
300004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
301004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
302004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
303004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
304004bedebSBruce Evans 	 */
305004bedebSBruce Evans 	al = data;
306004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
307004bedebSBruce Evans }
308004bedebSBruce Evans 
309004bedebSBruce Evans static __inline void
31000be8601SBruce Evans outl(u_int port, u_int data)
311004bedebSBruce Evans {
312004bedebSBruce Evans 	/*
313004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
314004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
315004bedebSBruce Evans 	 * assignment for them.
316004bedebSBruce Evans 	 */
317004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
318004bedebSBruce Evans }
319004bedebSBruce Evans 
320004bedebSBruce Evans static __inline void
321e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
322004bedebSBruce Evans {
323004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
3243f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3253f9a462fSJohn Baldwin 			 : "d" (port));
326004bedebSBruce Evans }
327004bedebSBruce Evans 
328004bedebSBruce Evans static __inline void
329e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
330004bedebSBruce Evans {
331004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
3323f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3333f9a462fSJohn Baldwin 			 : "d" (port));
334004bedebSBruce Evans }
335004bedebSBruce Evans 
336004bedebSBruce Evans static __inline void
337e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
338004bedebSBruce Evans {
339004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
3403f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3413f9a462fSJohn Baldwin 			 : "d" (port));
342004bedebSBruce Evans }
343004bedebSBruce Evans 
344004bedebSBruce Evans static __inline void
345004bedebSBruce Evans outw(u_int port, u_short data)
346004bedebSBruce Evans {
347004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
348004bedebSBruce Evans }
349004bedebSBruce Evans 
35000be8601SBruce Evans static __inline u_int
351004bedebSBruce Evans rcr2(void)
352004bedebSBruce Evans {
35300be8601SBruce Evans 	u_int	data;
354004bedebSBruce Evans 
355004bedebSBruce Evans 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
356004bedebSBruce Evans 	return (data);
357004bedebSBruce Evans }
358004bedebSBruce Evans 
35900be8601SBruce Evans static __inline u_int
360004bedebSBruce Evans read_eflags(void)
3615b81b6b3SRodney W. Grimes {
36200be8601SBruce Evans 	u_int	ef;
363004bedebSBruce Evans 
364004bedebSBruce Evans 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3658db02de8SPaul Richards 	return (ef);
3665b81b6b3SRodney W. Grimes }
3675b81b6b3SRodney W. Grimes 
36834221a45SDavid Malone static __inline void
36934221a45SDavid Malone do_cpuid(u_int ax, u_int *p)
37034221a45SDavid Malone {
37134221a45SDavid Malone 	__asm __volatile(
37234221a45SDavid Malone 	"cpuid"
37334221a45SDavid Malone 	: "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
37434221a45SDavid Malone 	:  "0" (ax)
37534221a45SDavid Malone 	);
37634221a45SDavid Malone }
37734221a45SDavid Malone 
37800be8601SBruce Evans static __inline u_int64_t
3795dbd168eSBruce Evans rdmsr(u_int msr)
3805dbd168eSBruce Evans {
38100be8601SBruce Evans 	u_int64_t rv;
3825dbd168eSBruce Evans 
38339413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3845dbd168eSBruce Evans 	return (rv);
3855dbd168eSBruce Evans }
3865dbd168eSBruce Evans 
38700be8601SBruce Evans static __inline u_int64_t
3885dbd168eSBruce Evans rdpmc(u_int pmc)
3895dbd168eSBruce Evans {
39000be8601SBruce Evans 	u_int64_t rv;
3915dbd168eSBruce Evans 
39239413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3935dbd168eSBruce Evans 	return (rv);
3945dbd168eSBruce Evans }
3955dbd168eSBruce Evans 
39600be8601SBruce Evans static __inline u_int64_t
3975dbd168eSBruce Evans rdtsc(void)
3985dbd168eSBruce Evans {
39900be8601SBruce Evans 	u_int64_t rv;
4005dbd168eSBruce Evans 
40139413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
4025dbd168eSBruce Evans 	return (rv);
4035dbd168eSBruce Evans }
4045dbd168eSBruce Evans 
405004bedebSBruce Evans static __inline void
4064c024bbdSKATO Takenori wbinvd(void)
4074c024bbdSKATO Takenori {
4084c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
4094c024bbdSKATO Takenori }
4104c024bbdSKATO Takenori 
4114c024bbdSKATO Takenori static __inline void
41200be8601SBruce Evans write_eflags(u_int ef)
4135b81b6b3SRodney W. Grimes {
414004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
4155b81b6b3SRodney W. Grimes }
4165b81b6b3SRodney W. Grimes 
417d69e8502SGarrett Wollman static __inline void
41800be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
419d69e8502SGarrett Wollman {
42039413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
421d69e8502SGarrett Wollman }
422d69e8502SGarrett Wollman 
4235206bca1SLuoqi Chen static __inline u_int
4245206bca1SLuoqi Chen rfs(void)
4255206bca1SLuoqi Chen {
4265206bca1SLuoqi Chen 	u_int sel;
427e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4285206bca1SLuoqi Chen 	return (sel);
4295206bca1SLuoqi Chen }
4305206bca1SLuoqi Chen 
4315206bca1SLuoqi Chen static __inline u_int
4325206bca1SLuoqi Chen rgs(void)
4335206bca1SLuoqi Chen {
4345206bca1SLuoqi Chen 	u_int sel;
435e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4365206bca1SLuoqi Chen 	return (sel);
4375206bca1SLuoqi Chen }
4385206bca1SLuoqi Chen 
4395206bca1SLuoqi Chen static __inline void
4405206bca1SLuoqi Chen load_fs(u_int sel)
4415206bca1SLuoqi Chen {
442e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4435206bca1SLuoqi Chen }
4445206bca1SLuoqi Chen 
4455206bca1SLuoqi Chen static __inline void
4465206bca1SLuoqi Chen load_gs(u_int sel)
4475206bca1SLuoqi Chen {
448e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4495206bca1SLuoqi Chen }
4505206bca1SLuoqi Chen 
451de8050f9SBrian S. Dean static __inline u_int
452de8050f9SBrian S. Dean rdr0(void)
453de8050f9SBrian S. Dean {
454de8050f9SBrian S. Dean 	u_int	data;
45580275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
456de8050f9SBrian S. Dean 	return (data);
457de8050f9SBrian S. Dean }
458de8050f9SBrian S. Dean 
4596eda157eSBrian S. Dean static __inline void
4606eda157eSBrian S. Dean load_dr0(u_int sel)
4616eda157eSBrian S. Dean {
4626eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr0" : : "r" (sel));
4636eda157eSBrian S. Dean }
4646eda157eSBrian S. Dean 
465de8050f9SBrian S. Dean static __inline u_int
466de8050f9SBrian S. Dean rdr1(void)
467de8050f9SBrian S. Dean {
468de8050f9SBrian S. Dean 	u_int	data;
46980275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
470de8050f9SBrian S. Dean 	return (data);
471de8050f9SBrian S. Dean }
472de8050f9SBrian S. Dean 
4736eda157eSBrian S. Dean static __inline void
4746eda157eSBrian S. Dean load_dr1(u_int sel)
4756eda157eSBrian S. Dean {
4766eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr1" : : "r" (sel));
4776eda157eSBrian S. Dean }
4786eda157eSBrian S. Dean 
479de8050f9SBrian S. Dean static __inline u_int
480de8050f9SBrian S. Dean rdr2(void)
481de8050f9SBrian S. Dean {
482de8050f9SBrian S. Dean 	u_int	data;
48380275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
484de8050f9SBrian S. Dean 	return (data);
485de8050f9SBrian S. Dean }
486de8050f9SBrian S. Dean 
4876eda157eSBrian S. Dean static __inline void
4886eda157eSBrian S. Dean load_dr2(u_int sel)
4896eda157eSBrian S. Dean {
4906eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr2" : : "r" (sel));
4916eda157eSBrian S. Dean }
4926eda157eSBrian S. Dean 
493de8050f9SBrian S. Dean static __inline u_int
494de8050f9SBrian S. Dean rdr3(void)
495de8050f9SBrian S. Dean {
496de8050f9SBrian S. Dean 	u_int	data;
49780275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
498de8050f9SBrian S. Dean 	return (data);
499de8050f9SBrian S. Dean }
500de8050f9SBrian S. Dean 
5016eda157eSBrian S. Dean static __inline void
5026eda157eSBrian S. Dean load_dr3(u_int sel)
5036eda157eSBrian S. Dean {
5046eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr3" : : "r" (sel));
5056eda157eSBrian S. Dean }
5066eda157eSBrian S. Dean 
5076eda157eSBrian S. Dean static __inline u_int
5086eda157eSBrian S. Dean rdr4(void)
5096eda157eSBrian S. Dean {
5106eda157eSBrian S. Dean 	u_int	data;
5116eda157eSBrian S. Dean 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
5126eda157eSBrian S. Dean 	return (data);
5136eda157eSBrian S. Dean }
5146eda157eSBrian S. Dean 
5156eda157eSBrian S. Dean static __inline void
5166eda157eSBrian S. Dean load_dr4(u_int sel)
5176eda157eSBrian S. Dean {
5186eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr4" : : "r" (sel));
5196eda157eSBrian S. Dean }
5206eda157eSBrian S. Dean 
5216eda157eSBrian S. Dean static __inline u_int
5226eda157eSBrian S. Dean rdr5(void)
5236eda157eSBrian S. Dean {
5246eda157eSBrian S. Dean 	u_int	data;
5256eda157eSBrian S. Dean 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
5266eda157eSBrian S. Dean 	return (data);
5276eda157eSBrian S. Dean }
5286eda157eSBrian S. Dean 
5296eda157eSBrian S. Dean static __inline void
5306eda157eSBrian S. Dean load_dr5(u_int sel)
5316eda157eSBrian S. Dean {
5326eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr5" : : "r" (sel));
5336eda157eSBrian S. Dean }
5346eda157eSBrian S. Dean 
535de8050f9SBrian S. Dean static __inline u_int
536de8050f9SBrian S. Dean rdr6(void)
537de8050f9SBrian S. Dean {
538de8050f9SBrian S. Dean 	u_int	data;
53980275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
540de8050f9SBrian S. Dean 	return (data);
541de8050f9SBrian S. Dean }
542de8050f9SBrian S. Dean 
5436eda157eSBrian S. Dean static __inline void
5446eda157eSBrian S. Dean load_dr6(u_int sel)
5456eda157eSBrian S. Dean {
5466eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr6" : : "r" (sel));
5476eda157eSBrian S. Dean }
5486eda157eSBrian S. Dean 
549de8050f9SBrian S. Dean static __inline u_int
550de8050f9SBrian S. Dean rdr7(void)
551de8050f9SBrian S. Dean {
552de8050f9SBrian S. Dean 	u_int	data;
55380275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
554de8050f9SBrian S. Dean 	return (data);
555de8050f9SBrian S. Dean }
556de8050f9SBrian S. Dean 
5576eda157eSBrian S. Dean static __inline void
5586eda157eSBrian S. Dean load_dr7(u_int sel)
5596eda157eSBrian S. Dean {
5606eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr7" : : "r" (sel));
5616eda157eSBrian S. Dean }
5626eda157eSBrian S. Dean 
563034dc442SJohn Baldwin static __inline critical_t
5647e1f6dfeSJohn Baldwin cpu_critical_enter(void)
565034dc442SJohn Baldwin {
566034dc442SJohn Baldwin 	critical_t eflags;
567034dc442SJohn Baldwin 
568034dc442SJohn Baldwin 	eflags = read_eflags();
569034dc442SJohn Baldwin 	disable_intr();
570034dc442SJohn Baldwin 	return (eflags);
571034dc442SJohn Baldwin }
572034dc442SJohn Baldwin 
573034dc442SJohn Baldwin static __inline void
5747e1f6dfeSJohn Baldwin cpu_critical_exit(critical_t eflags)
575034dc442SJohn Baldwin {
576034dc442SJohn Baldwin 	write_eflags(eflags);
577034dc442SJohn Baldwin }
578034dc442SJohn Baldwin 
579004bedebSBruce Evans #else /* !__GNUC__ */
5805b81b6b3SRodney W. Grimes 
581a5e25da4SWarner Losh int	breakpoint	__P((void));
582a5e25da4SWarner Losh u_int	bsfl		__P((u_int mask));
583a5e25da4SWarner Losh u_int	bsrl		__P((u_int mask));
584a5e25da4SWarner Losh void	disable_intr	__P((void));
58534221a45SDavid Malone void	do_cpuid	__P((u_int ax, u_int *p));
586a5e25da4SWarner Losh void	enable_intr	__P((void));
587a5e25da4SWarner Losh u_char	inb		__P((u_int port));
588a5e25da4SWarner Losh u_int	inl		__P((u_int port));
589a5e25da4SWarner Losh void	insb		__P((u_int port, void *addr, size_t cnt));
590a5e25da4SWarner Losh void	insl		__P((u_int port, void *addr, size_t cnt));
591a5e25da4SWarner Losh void	insw		__P((u_int port, void *addr, size_t cnt));
592a5e25da4SWarner Losh void	invd		__P((void));
593a5e25da4SWarner Losh void	invlpg		__P((u_int addr));
594a5e25da4SWarner Losh void	invltlb		__P((void));
595a5e25da4SWarner Losh u_short	inw		__P((u_int port));
596a5e25da4SWarner Losh void	outb		__P((u_int port, u_char data));
597a5e25da4SWarner Losh void	outl		__P((u_int port, u_int data));
598a5e25da4SWarner Losh void	outsb		__P((u_int port, void *addr, size_t cnt));
599a5e25da4SWarner Losh void	outsl		__P((u_int port, void *addr, size_t cnt));
600a5e25da4SWarner Losh void	outsw		__P((u_int port, void *addr, size_t cnt));
601a5e25da4SWarner Losh void	outw		__P((u_int port, u_short data));
602a5e25da4SWarner Losh u_int	rcr2		__P((void));
603a5e25da4SWarner Losh u_int64_t rdmsr		__P((u_int msr));
604a5e25da4SWarner Losh u_int64_t rdpmc		__P((u_int pmc));
605a5e25da4SWarner Losh u_int64_t rdtsc		__P((void));
606a5e25da4SWarner Losh u_int	read_eflags	__P((void));
607a5e25da4SWarner Losh void	wbinvd		__P((void));
608a5e25da4SWarner Losh void	write_eflags	__P((u_int ef));
609a5e25da4SWarner Losh void	wrmsr		__P((u_int msr, u_int64_t newval));
610a5e25da4SWarner Losh u_int	rfs		__P((void));
611a5e25da4SWarner Losh u_int	rgs		__P((void));
612a5e25da4SWarner Losh void	load_fs		__P((u_int sel));
613a5e25da4SWarner Losh void	load_gs		__P((u_int sel));
6147e1f6dfeSJohn Baldwin critical_t cpu_critical_enter __P((void));
6157e1f6dfeSJohn Baldwin void	cpu_critical_exit __P((critical_t eflags));
616004bedebSBruce Evans 
6175b81b6b3SRodney W. Grimes #endif	/* __GNUC__ */
6185b81b6b3SRodney W. Grimes 
619a5e25da4SWarner Losh void	load_cr0	__P((u_int cr0));
620a5e25da4SWarner Losh void	load_cr3	__P((u_int cr3));
621a5e25da4SWarner Losh void	load_cr4	__P((u_int cr4));
622a5e25da4SWarner Losh void	ltr		__P((u_short sel));
623a5e25da4SWarner Losh u_int	rcr0		__P((void));
624a5e25da4SWarner Losh u_int	rcr3		__P((void));
625a5e25da4SWarner Losh u_int	rcr4		__P((void));
626a5e25da4SWarner Losh void    reset_dbregs    __P((void));
62729d5de8aSWarner Losh __END_DECLS
6285b81b6b3SRodney W. Grimes 
629004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
630