xref: /freebsd/sys/amd64/include/cpufunc.h (revision 3f9a462fb91c4f75b6163133abf9f91f75f039d9)
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 
36800be8601SBruce Evans static __inline u_int64_t
3695dbd168eSBruce Evans rdmsr(u_int msr)
3705dbd168eSBruce Evans {
37100be8601SBruce Evans 	u_int64_t rv;
3725dbd168eSBruce Evans 
37339413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3745dbd168eSBruce Evans 	return (rv);
3755dbd168eSBruce Evans }
3765dbd168eSBruce Evans 
37700be8601SBruce Evans static __inline u_int64_t
3785dbd168eSBruce Evans rdpmc(u_int pmc)
3795dbd168eSBruce Evans {
38000be8601SBruce Evans 	u_int64_t rv;
3815dbd168eSBruce Evans 
38239413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3835dbd168eSBruce Evans 	return (rv);
3845dbd168eSBruce Evans }
3855dbd168eSBruce Evans 
38600be8601SBruce Evans static __inline u_int64_t
3875dbd168eSBruce Evans rdtsc(void)
3885dbd168eSBruce Evans {
38900be8601SBruce Evans 	u_int64_t rv;
3905dbd168eSBruce Evans 
39139413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
3925dbd168eSBruce Evans 	return (rv);
3935dbd168eSBruce Evans }
3945dbd168eSBruce Evans 
395004bedebSBruce Evans static __inline void
3964c024bbdSKATO Takenori wbinvd(void)
3974c024bbdSKATO Takenori {
3984c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3994c024bbdSKATO Takenori }
4004c024bbdSKATO Takenori 
4014c024bbdSKATO Takenori static __inline void
40200be8601SBruce Evans write_eflags(u_int ef)
4035b81b6b3SRodney W. Grimes {
404004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
4055b81b6b3SRodney W. Grimes }
4065b81b6b3SRodney W. Grimes 
407d69e8502SGarrett Wollman static __inline void
40800be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
409d69e8502SGarrett Wollman {
41039413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
411d69e8502SGarrett Wollman }
412d69e8502SGarrett Wollman 
4135206bca1SLuoqi Chen static __inline u_int
4145206bca1SLuoqi Chen rfs(void)
4155206bca1SLuoqi Chen {
4165206bca1SLuoqi Chen 	u_int sel;
417e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4185206bca1SLuoqi Chen 	return (sel);
4195206bca1SLuoqi Chen }
4205206bca1SLuoqi Chen 
4215206bca1SLuoqi Chen static __inline u_int
4225206bca1SLuoqi Chen rgs(void)
4235206bca1SLuoqi Chen {
4245206bca1SLuoqi Chen 	u_int sel;
425e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4265206bca1SLuoqi Chen 	return (sel);
4275206bca1SLuoqi Chen }
4285206bca1SLuoqi Chen 
4295206bca1SLuoqi Chen static __inline void
4305206bca1SLuoqi Chen load_fs(u_int sel)
4315206bca1SLuoqi Chen {
432e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4335206bca1SLuoqi Chen }
4345206bca1SLuoqi Chen 
4355206bca1SLuoqi Chen static __inline void
4365206bca1SLuoqi Chen load_gs(u_int sel)
4375206bca1SLuoqi Chen {
438e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4395206bca1SLuoqi Chen }
4405206bca1SLuoqi Chen 
441de8050f9SBrian S. Dean static __inline u_int
442de8050f9SBrian S. Dean rdr0(void)
443de8050f9SBrian S. Dean {
444de8050f9SBrian S. Dean 	u_int	data;
44580275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
446de8050f9SBrian S. Dean 	return (data);
447de8050f9SBrian S. Dean }
448de8050f9SBrian S. Dean 
4496eda157eSBrian S. Dean static __inline void
4506eda157eSBrian S. Dean load_dr0(u_int sel)
4516eda157eSBrian S. Dean {
4526eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr0" : : "r" (sel));
4536eda157eSBrian S. Dean }
4546eda157eSBrian S. Dean 
455de8050f9SBrian S. Dean static __inline u_int
456de8050f9SBrian S. Dean rdr1(void)
457de8050f9SBrian S. Dean {
458de8050f9SBrian S. Dean 	u_int	data;
45980275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
460de8050f9SBrian S. Dean 	return (data);
461de8050f9SBrian S. Dean }
462de8050f9SBrian S. Dean 
4636eda157eSBrian S. Dean static __inline void
4646eda157eSBrian S. Dean load_dr1(u_int sel)
4656eda157eSBrian S. Dean {
4666eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr1" : : "r" (sel));
4676eda157eSBrian S. Dean }
4686eda157eSBrian S. Dean 
469de8050f9SBrian S. Dean static __inline u_int
470de8050f9SBrian S. Dean rdr2(void)
471de8050f9SBrian S. Dean {
472de8050f9SBrian S. Dean 	u_int	data;
47380275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
474de8050f9SBrian S. Dean 	return (data);
475de8050f9SBrian S. Dean }
476de8050f9SBrian S. Dean 
4776eda157eSBrian S. Dean static __inline void
4786eda157eSBrian S. Dean load_dr2(u_int sel)
4796eda157eSBrian S. Dean {
4806eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr2" : : "r" (sel));
4816eda157eSBrian S. Dean }
4826eda157eSBrian S. Dean 
483de8050f9SBrian S. Dean static __inline u_int
484de8050f9SBrian S. Dean rdr3(void)
485de8050f9SBrian S. Dean {
486de8050f9SBrian S. Dean 	u_int	data;
48780275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
488de8050f9SBrian S. Dean 	return (data);
489de8050f9SBrian S. Dean }
490de8050f9SBrian S. Dean 
4916eda157eSBrian S. Dean static __inline void
4926eda157eSBrian S. Dean load_dr3(u_int sel)
4936eda157eSBrian S. Dean {
4946eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr3" : : "r" (sel));
4956eda157eSBrian S. Dean }
4966eda157eSBrian S. Dean 
4976eda157eSBrian S. Dean static __inline u_int
4986eda157eSBrian S. Dean rdr4(void)
4996eda157eSBrian S. Dean {
5006eda157eSBrian S. Dean 	u_int	data;
5016eda157eSBrian S. Dean 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
5026eda157eSBrian S. Dean 	return (data);
5036eda157eSBrian S. Dean }
5046eda157eSBrian S. Dean 
5056eda157eSBrian S. Dean static __inline void
5066eda157eSBrian S. Dean load_dr4(u_int sel)
5076eda157eSBrian S. Dean {
5086eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr4" : : "r" (sel));
5096eda157eSBrian S. Dean }
5106eda157eSBrian S. Dean 
5116eda157eSBrian S. Dean static __inline u_int
5126eda157eSBrian S. Dean rdr5(void)
5136eda157eSBrian S. Dean {
5146eda157eSBrian S. Dean 	u_int	data;
5156eda157eSBrian S. Dean 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
5166eda157eSBrian S. Dean 	return (data);
5176eda157eSBrian S. Dean }
5186eda157eSBrian S. Dean 
5196eda157eSBrian S. Dean static __inline void
5206eda157eSBrian S. Dean load_dr5(u_int sel)
5216eda157eSBrian S. Dean {
5226eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr5" : : "r" (sel));
5236eda157eSBrian S. Dean }
5246eda157eSBrian S. Dean 
525de8050f9SBrian S. Dean static __inline u_int
526de8050f9SBrian S. Dean rdr6(void)
527de8050f9SBrian S. Dean {
528de8050f9SBrian S. Dean 	u_int	data;
52980275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
530de8050f9SBrian S. Dean 	return (data);
531de8050f9SBrian S. Dean }
532de8050f9SBrian S. Dean 
5336eda157eSBrian S. Dean static __inline void
5346eda157eSBrian S. Dean load_dr6(u_int sel)
5356eda157eSBrian S. Dean {
5366eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr6" : : "r" (sel));
5376eda157eSBrian S. Dean }
5386eda157eSBrian S. Dean 
539de8050f9SBrian S. Dean static __inline u_int
540de8050f9SBrian S. Dean rdr7(void)
541de8050f9SBrian S. Dean {
542de8050f9SBrian S. Dean 	u_int	data;
54380275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
544de8050f9SBrian S. Dean 	return (data);
545de8050f9SBrian S. Dean }
546de8050f9SBrian S. Dean 
5476eda157eSBrian S. Dean static __inline void
5486eda157eSBrian S. Dean load_dr7(u_int sel)
5496eda157eSBrian S. Dean {
5506eda157eSBrian S. Dean 	__asm __volatile("movl %0,%%dr7" : : "r" (sel));
5516eda157eSBrian S. Dean }
5526eda157eSBrian S. Dean 
553034dc442SJohn Baldwin static __inline critical_t
5547e1f6dfeSJohn Baldwin cpu_critical_enter(void)
555034dc442SJohn Baldwin {
556034dc442SJohn Baldwin 	critical_t eflags;
557034dc442SJohn Baldwin 
558034dc442SJohn Baldwin 	eflags = read_eflags();
559034dc442SJohn Baldwin 	disable_intr();
560034dc442SJohn Baldwin 	return (eflags);
561034dc442SJohn Baldwin }
562034dc442SJohn Baldwin 
563034dc442SJohn Baldwin static __inline void
5647e1f6dfeSJohn Baldwin cpu_critical_exit(critical_t eflags)
565034dc442SJohn Baldwin {
566034dc442SJohn Baldwin 	write_eflags(eflags);
567034dc442SJohn Baldwin }
568034dc442SJohn Baldwin 
569004bedebSBruce Evans #else /* !__GNUC__ */
5705b81b6b3SRodney W. Grimes 
571a5e25da4SWarner Losh int	breakpoint	__P((void));
572a5e25da4SWarner Losh u_int	bsfl		__P((u_int mask));
573a5e25da4SWarner Losh u_int	bsrl		__P((u_int mask));
574a5e25da4SWarner Losh void	disable_intr	__P((void));
575a5e25da4SWarner Losh void	enable_intr	__P((void));
576a5e25da4SWarner Losh u_char	inb		__P((u_int port));
577a5e25da4SWarner Losh u_int	inl		__P((u_int port));
578a5e25da4SWarner Losh void	insb		__P((u_int port, void *addr, size_t cnt));
579a5e25da4SWarner Losh void	insl		__P((u_int port, void *addr, size_t cnt));
580a5e25da4SWarner Losh void	insw		__P((u_int port, void *addr, size_t cnt));
581a5e25da4SWarner Losh void	invd		__P((void));
582a5e25da4SWarner Losh void	invlpg		__P((u_int addr));
583a5e25da4SWarner Losh void	invltlb		__P((void));
584a5e25da4SWarner Losh u_short	inw		__P((u_int port));
585a5e25da4SWarner Losh void	outb		__P((u_int port, u_char data));
586a5e25da4SWarner Losh void	outl		__P((u_int port, u_int data));
587a5e25da4SWarner Losh void	outsb		__P((u_int port, void *addr, size_t cnt));
588a5e25da4SWarner Losh void	outsl		__P((u_int port, void *addr, size_t cnt));
589a5e25da4SWarner Losh void	outsw		__P((u_int port, void *addr, size_t cnt));
590a5e25da4SWarner Losh void	outw		__P((u_int port, u_short data));
591a5e25da4SWarner Losh u_int	rcr2		__P((void));
592a5e25da4SWarner Losh u_int64_t rdmsr		__P((u_int msr));
593a5e25da4SWarner Losh u_int64_t rdpmc		__P((u_int pmc));
594a5e25da4SWarner Losh u_int64_t rdtsc		__P((void));
595a5e25da4SWarner Losh u_int	read_eflags	__P((void));
596a5e25da4SWarner Losh void	wbinvd		__P((void));
597a5e25da4SWarner Losh void	write_eflags	__P((u_int ef));
598a5e25da4SWarner Losh void	wrmsr		__P((u_int msr, u_int64_t newval));
599a5e25da4SWarner Losh u_int	rfs		__P((void));
600a5e25da4SWarner Losh u_int	rgs		__P((void));
601a5e25da4SWarner Losh void	load_fs		__P((u_int sel));
602a5e25da4SWarner Losh void	load_gs		__P((u_int sel));
6037e1f6dfeSJohn Baldwin critical_t cpu_critical_enter __P((void));
6047e1f6dfeSJohn Baldwin void	cpu_critical_exit __P((critical_t eflags));
605004bedebSBruce Evans 
6065b81b6b3SRodney W. Grimes #endif	/* __GNUC__ */
6075b81b6b3SRodney W. Grimes 
608a5e25da4SWarner Losh void	load_cr0	__P((u_int cr0));
609a5e25da4SWarner Losh void	load_cr3	__P((u_int cr3));
610a5e25da4SWarner Losh void	load_cr4	__P((u_int cr4));
611a5e25da4SWarner Losh void	ltr		__P((u_short sel));
612a5e25da4SWarner Losh u_int	rcr0		__P((void));
613a5e25da4SWarner Losh u_int	rcr3		__P((void));
614a5e25da4SWarner Losh u_int	rcr4		__P((void));
615a5e25da4SWarner Losh void    reset_dbregs    __P((void));
61629d5de8aSWarner Losh __END_DECLS
6175b81b6b3SRodney W. Grimes 
618004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
619