xref: /freebsd/sys/amd64/include/cpufunc.h (revision 7e622d3c84bbed224e6bb483ef0ac3e9dbc6ebac)
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 
48d74ac681SMatthew Dillon struct thread;
49d74ac681SMatthew Dillon 
5029d5de8aSWarner Losh __BEGIN_DECLS
51e31fa854SDoug Rabson #define readb(va)	(*(volatile u_int8_t *) (va))
52e31fa854SDoug Rabson #define readw(va)	(*(volatile u_int16_t *) (va))
53e31fa854SDoug Rabson #define readl(va)	(*(volatile u_int32_t *) (va))
54e31fa854SDoug Rabson 
55e31fa854SDoug Rabson #define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
56e31fa854SDoug Rabson #define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
57e31fa854SDoug Rabson #define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
58e31fa854SDoug Rabson 
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
96a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
97a983fdfeSDavid Malone {
98a983fdfeSDavid Malone 	__asm __volatile("cpuid"
99a983fdfeSDavid Malone 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
100a983fdfeSDavid Malone 			 :  "0" (ax));
101a983fdfeSDavid Malone }
102a983fdfeSDavid Malone 
103a983fdfeSDavid Malone static __inline void
1045b81b6b3SRodney W. Grimes enable_intr(void)
1055b81b6b3SRodney W. Grimes {
106fadc51bdSBruce Evans 	__asm __volatile("sti");
1075b81b6b3SRodney W. Grimes }
1085b81b6b3SRodney W. Grimes 
109264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
110264c3d87SPeter Wemm 
111264c3d87SPeter Wemm static __inline int
112264c3d87SPeter Wemm ffs(int mask)
113264c3d87SPeter Wemm {
114264c3d87SPeter Wemm 	/*
115004bedebSBruce Evans 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
116004bedebSBruce Evans 	 * this inline or turn off the builtin.  The builtin is faster but
117c83b1328SBruce Evans 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
118c83b1328SBruce Evans 	 * versions.
119004bedebSBruce Evans 	 */
1207e622d3cSMark Murray 	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
121004bedebSBruce Evans }
122004bedebSBruce Evans 
12313f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
12413f588f8SGarrett Wollman 
12513f588f8SGarrett Wollman static __inline int
12613f588f8SGarrett Wollman fls(int mask)
12713f588f8SGarrett Wollman {
1287e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
12913f588f8SGarrett Wollman }
13013f588f8SGarrett Wollman 
131004bedebSBruce Evans #if __GNUC__ < 2
132004bedebSBruce Evans 
133004bedebSBruce Evans #define	inb(port)		inbv(port)
134004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
135004bedebSBruce Evans 
136004bedebSBruce Evans #else /* __GNUC >= 2 */
137004bedebSBruce Evans 
138004bedebSBruce Evans /*
1398089a043SBruce Evans  * The following complications are to get around gcc not having a
1408089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1418089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1428089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1438089a043SBruce Evans  * the non-working version gets optimized away.
1448089a043SBruce Evans  *
145004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
146004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
147004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
148388dfa71SBruce Evans  *
149388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
150388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
151388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
152388dfa71SBruce Evans  * careful to avoid generating warnings.
153004bedebSBruce Evans  */
154388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
155004bedebSBruce Evans 	u_char	_data;							\
156388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
157388dfa71SBruce Evans 	    && (port) < 0x10000)					\
158004bedebSBruce Evans 		_data = inbc(port);					\
159004bedebSBruce Evans 	else								\
160004bedebSBruce Evans 		_data = inbv(port);					\
161004bedebSBruce Evans 	_data; })
162004bedebSBruce Evans 
163388dfa71SBruce Evans #define	outb(port, data) (						\
164388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
165388dfa71SBruce Evans 	&& (port) < 0x10000						\
166004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
167004bedebSBruce Evans 
168004bedebSBruce Evans static __inline u_char
169004bedebSBruce Evans inbc(u_int port)
170004bedebSBruce Evans {
171004bedebSBruce Evans 	u_char	data;
172004bedebSBruce Evans 
1738089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
174004bedebSBruce Evans 	return (data);
175004bedebSBruce Evans }
176004bedebSBruce Evans 
177004bedebSBruce Evans static __inline void
178004bedebSBruce Evans outbc(u_int port, u_char data)
179004bedebSBruce Evans {
1808089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
181004bedebSBruce Evans }
182004bedebSBruce Evans 
183004bedebSBruce Evans #endif /* __GNUC <= 2 */
184004bedebSBruce Evans 
185004bedebSBruce Evans static __inline u_char
186004bedebSBruce Evans inbv(u_int port)
187004bedebSBruce Evans {
188004bedebSBruce Evans 	u_char	data;
189004bedebSBruce Evans 	/*
190004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
191004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
192004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
193004bedebSBruce Evans 	 */
194004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
195004bedebSBruce Evans 	return (data);
196004bedebSBruce Evans }
197004bedebSBruce Evans 
19800be8601SBruce Evans static __inline u_int
199004bedebSBruce Evans inl(u_int port)
200004bedebSBruce Evans {
20100be8601SBruce Evans 	u_int	data;
202004bedebSBruce Evans 
203004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
204004bedebSBruce Evans 	return (data);
205004bedebSBruce Evans }
206004bedebSBruce Evans 
207004bedebSBruce Evans static __inline void
208004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
209004bedebSBruce Evans {
210004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
2113f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2123f9a462fSJohn Baldwin 			 : "d" (port)
213896763faSBruce Evans 			 : "memory");
214004bedebSBruce Evans }
215004bedebSBruce Evans 
216004bedebSBruce Evans static __inline void
217004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
218004bedebSBruce Evans {
219004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
2203f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2213f9a462fSJohn Baldwin 			 : "d" (port)
222896763faSBruce Evans 			 : "memory");
223004bedebSBruce Evans }
224004bedebSBruce Evans 
225004bedebSBruce Evans static __inline void
226004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
227004bedebSBruce Evans {
228004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
2293f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2303f9a462fSJohn Baldwin 			 : "d" (port)
231896763faSBruce Evans 			 : "memory");
232004bedebSBruce Evans }
233004bedebSBruce Evans 
234ece15d78SBruce Evans static __inline void
2354c024bbdSKATO Takenori invd(void)
2364c024bbdSKATO Takenori {
2374c024bbdSKATO Takenori 	__asm __volatile("invd");
2384c024bbdSKATO Takenori }
2394c024bbdSKATO Takenori 
240004bedebSBruce Evans static __inline u_short
241004bedebSBruce Evans inw(u_int port)
242004bedebSBruce Evans {
243004bedebSBruce Evans 	u_short	data;
244004bedebSBruce Evans 
245004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
246004bedebSBruce Evans 	return (data);
247004bedebSBruce Evans }
248004bedebSBruce Evans 
249004bedebSBruce Evans static __inline void
250004bedebSBruce Evans outbv(u_int port, u_char data)
251004bedebSBruce Evans {
252004bedebSBruce Evans 	u_char	al;
253004bedebSBruce Evans 	/*
254004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
255004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
256004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
257004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
258004bedebSBruce Evans 	 */
259004bedebSBruce Evans 	al = data;
260004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
261004bedebSBruce Evans }
262004bedebSBruce Evans 
263004bedebSBruce Evans static __inline void
26400be8601SBruce Evans outl(u_int port, u_int data)
265004bedebSBruce Evans {
266004bedebSBruce Evans 	/*
267004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
268004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
269004bedebSBruce Evans 	 * assignment for them.
270004bedebSBruce Evans 	 */
271004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
272004bedebSBruce Evans }
273004bedebSBruce Evans 
274004bedebSBruce Evans static __inline void
275e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
276004bedebSBruce Evans {
277004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
2783f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
2793f9a462fSJohn Baldwin 			 : "d" (port));
280004bedebSBruce Evans }
281004bedebSBruce Evans 
282004bedebSBruce Evans static __inline void
283e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
284004bedebSBruce Evans {
285004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
2863f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
2873f9a462fSJohn Baldwin 			 : "d" (port));
288004bedebSBruce Evans }
289004bedebSBruce Evans 
290004bedebSBruce Evans static __inline void
291e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
292004bedebSBruce Evans {
293004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
2943f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
2953f9a462fSJohn Baldwin 			 : "d" (port));
296004bedebSBruce Evans }
297004bedebSBruce Evans 
298004bedebSBruce Evans static __inline void
299004bedebSBruce Evans outw(u_int port, u_short data)
300004bedebSBruce Evans {
301004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
302004bedebSBruce Evans }
303004bedebSBruce Evans 
3042be69f32SJohn Baldwin static __inline void
3056b8c6989SJohn Baldwin ia32_pause(void)
3062be69f32SJohn Baldwin {
3072be69f32SJohn Baldwin 	__asm __volatile("pause");
3082be69f32SJohn Baldwin }
3092be69f32SJohn Baldwin 
31000be8601SBruce Evans static __inline u_int
311004bedebSBruce Evans read_eflags(void)
3125b81b6b3SRodney W. Grimes {
31300be8601SBruce Evans 	u_int	ef;
314004bedebSBruce Evans 
315004bedebSBruce Evans 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3168db02de8SPaul Richards 	return (ef);
3175b81b6b3SRodney W. Grimes }
3185b81b6b3SRodney W. Grimes 
31900be8601SBruce Evans static __inline u_int64_t
3205dbd168eSBruce Evans rdmsr(u_int msr)
3215dbd168eSBruce Evans {
32200be8601SBruce Evans 	u_int64_t rv;
3235dbd168eSBruce Evans 
32439413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3255dbd168eSBruce Evans 	return (rv);
3265dbd168eSBruce Evans }
3275dbd168eSBruce Evans 
32800be8601SBruce Evans static __inline u_int64_t
3295dbd168eSBruce Evans rdpmc(u_int pmc)
3305dbd168eSBruce Evans {
33100be8601SBruce Evans 	u_int64_t rv;
3325dbd168eSBruce Evans 
33339413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3345dbd168eSBruce Evans 	return (rv);
3355dbd168eSBruce Evans }
3365dbd168eSBruce Evans 
33700be8601SBruce Evans static __inline u_int64_t
3385dbd168eSBruce Evans rdtsc(void)
3395dbd168eSBruce Evans {
34000be8601SBruce Evans 	u_int64_t rv;
3415dbd168eSBruce Evans 
34239413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
3435dbd168eSBruce Evans 	return (rv);
3445dbd168eSBruce Evans }
3455dbd168eSBruce Evans 
346004bedebSBruce Evans static __inline void
3474c024bbdSKATO Takenori wbinvd(void)
3484c024bbdSKATO Takenori {
3494c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3504c024bbdSKATO Takenori }
3514c024bbdSKATO Takenori 
3524c024bbdSKATO Takenori static __inline void
35300be8601SBruce Evans write_eflags(u_int ef)
3545b81b6b3SRodney W. Grimes {
355004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
3565b81b6b3SRodney W. Grimes }
3575b81b6b3SRodney W. Grimes 
358d69e8502SGarrett Wollman static __inline void
35900be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
360d69e8502SGarrett Wollman {
36139413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
362d69e8502SGarrett Wollman }
363d69e8502SGarrett Wollman 
364f1b665c8SPeter Wemm static __inline void
365f1b665c8SPeter Wemm load_cr0(u_int data)
366f1b665c8SPeter Wemm {
367f1b665c8SPeter Wemm 
368f1b665c8SPeter Wemm 	__asm __volatile("movl %0,%%cr0" : : "r" (data));
369f1b665c8SPeter Wemm }
370f1b665c8SPeter Wemm 
371f1b665c8SPeter Wemm static __inline u_int
372f1b665c8SPeter Wemm rcr0(void)
373f1b665c8SPeter Wemm {
374f1b665c8SPeter Wemm 	u_int	data;
375f1b665c8SPeter Wemm 
376f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr0,%0" : "=r" (data));
377f1b665c8SPeter Wemm 	return (data);
378f1b665c8SPeter Wemm }
379f1b665c8SPeter Wemm 
380f1b665c8SPeter Wemm static __inline u_int
381f1b665c8SPeter Wemm rcr2(void)
382f1b665c8SPeter Wemm {
383f1b665c8SPeter Wemm 	u_int	data;
384f1b665c8SPeter Wemm 
385f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
386f1b665c8SPeter Wemm 	return (data);
387f1b665c8SPeter Wemm }
388f1b665c8SPeter Wemm 
389f1b665c8SPeter Wemm static __inline void
390f1b665c8SPeter Wemm load_cr3(u_int data)
391f1b665c8SPeter Wemm {
392f1b665c8SPeter Wemm 
393f1b665c8SPeter Wemm 	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
394f1b665c8SPeter Wemm #if defined(SWTCH_OPTIM_STATS)
395f1b665c8SPeter Wemm 	++tlb_flush_count;
396f1b665c8SPeter Wemm #endif
397f1b665c8SPeter Wemm }
398f1b665c8SPeter Wemm 
399f1b665c8SPeter Wemm static __inline u_int
400f1b665c8SPeter Wemm rcr3(void)
401f1b665c8SPeter Wemm {
402f1b665c8SPeter Wemm 	u_int	data;
403f1b665c8SPeter Wemm 
404f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr3,%0" : "=r" (data));
405f1b665c8SPeter Wemm 	return (data);
406f1b665c8SPeter Wemm }
407f1b665c8SPeter Wemm 
408f1b665c8SPeter Wemm static __inline void
409f1b665c8SPeter Wemm load_cr4(u_int data)
410f1b665c8SPeter Wemm {
411f1b665c8SPeter Wemm 	__asm __volatile("movl %0,%%cr4" : : "r" (data));
412f1b665c8SPeter Wemm }
413f1b665c8SPeter Wemm 
414f1b665c8SPeter Wemm static __inline u_int
415f1b665c8SPeter Wemm rcr4(void)
416f1b665c8SPeter Wemm {
417f1b665c8SPeter Wemm 	u_int	data;
418f1b665c8SPeter Wemm 
419f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr4,%0" : "=r" (data));
420f1b665c8SPeter Wemm 	return (data);
421f1b665c8SPeter Wemm }
422f1b665c8SPeter Wemm 
423f1b665c8SPeter Wemm /*
424f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
425f1b665c8SPeter Wemm  */
426f1b665c8SPeter Wemm static __inline void
427f1b665c8SPeter Wemm invltlb(void)
428f1b665c8SPeter Wemm {
429f1b665c8SPeter Wemm 
430f1b665c8SPeter Wemm 	load_cr3(rcr3());
431f1b665c8SPeter Wemm }
432f1b665c8SPeter Wemm 
433f1b665c8SPeter Wemm /*
434f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
435f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
436f1b665c8SPeter Wemm  */
437f1b665c8SPeter Wemm static __inline void
438f1b665c8SPeter Wemm invlpg(u_int addr)
439f1b665c8SPeter Wemm {
440f1b665c8SPeter Wemm 
441f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
442f1b665c8SPeter Wemm }
443f1b665c8SPeter Wemm 
4445206bca1SLuoqi Chen static __inline u_int
4455206bca1SLuoqi Chen rfs(void)
4465206bca1SLuoqi Chen {
4475206bca1SLuoqi Chen 	u_int sel;
448e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4495206bca1SLuoqi Chen 	return (sel);
4505206bca1SLuoqi Chen }
4515206bca1SLuoqi Chen 
4525206bca1SLuoqi Chen static __inline u_int
4535206bca1SLuoqi Chen rgs(void)
4545206bca1SLuoqi Chen {
4555206bca1SLuoqi Chen 	u_int sel;
456e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4575206bca1SLuoqi Chen 	return (sel);
4585206bca1SLuoqi Chen }
4595206bca1SLuoqi Chen 
4605206bca1SLuoqi Chen static __inline void
4615206bca1SLuoqi Chen load_fs(u_int sel)
4625206bca1SLuoqi Chen {
463e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4645206bca1SLuoqi Chen }
4655206bca1SLuoqi Chen 
4665206bca1SLuoqi Chen static __inline void
4675206bca1SLuoqi Chen load_gs(u_int sel)
4685206bca1SLuoqi Chen {
469e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4705206bca1SLuoqi Chen }
4715206bca1SLuoqi Chen 
472de8050f9SBrian S. Dean static __inline u_int
473de8050f9SBrian S. Dean rdr0(void)
474de8050f9SBrian S. Dean {
475de8050f9SBrian S. Dean 	u_int	data;
47680275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
477de8050f9SBrian S. Dean 	return (data);
478de8050f9SBrian S. Dean }
479de8050f9SBrian S. Dean 
4806eda157eSBrian S. Dean static __inline void
48107508f90SJohn Baldwin load_dr0(u_int dr0)
4826eda157eSBrian S. Dean {
48307508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
4846eda157eSBrian S. Dean }
4856eda157eSBrian S. Dean 
486de8050f9SBrian S. Dean static __inline u_int
487de8050f9SBrian S. Dean rdr1(void)
488de8050f9SBrian S. Dean {
489de8050f9SBrian S. Dean 	u_int	data;
49080275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
491de8050f9SBrian S. Dean 	return (data);
492de8050f9SBrian S. Dean }
493de8050f9SBrian S. Dean 
4946eda157eSBrian S. Dean static __inline void
49507508f90SJohn Baldwin load_dr1(u_int dr1)
4966eda157eSBrian S. Dean {
49707508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
4986eda157eSBrian S. Dean }
4996eda157eSBrian S. Dean 
500de8050f9SBrian S. Dean static __inline u_int
501de8050f9SBrian S. Dean rdr2(void)
502de8050f9SBrian S. Dean {
503de8050f9SBrian S. Dean 	u_int	data;
50480275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
505de8050f9SBrian S. Dean 	return (data);
506de8050f9SBrian S. Dean }
507de8050f9SBrian S. Dean 
5086eda157eSBrian S. Dean static __inline void
50907508f90SJohn Baldwin load_dr2(u_int dr2)
5106eda157eSBrian S. Dean {
51107508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
5126eda157eSBrian S. Dean }
5136eda157eSBrian S. Dean 
514de8050f9SBrian S. Dean static __inline u_int
515de8050f9SBrian S. Dean rdr3(void)
516de8050f9SBrian S. Dean {
517de8050f9SBrian S. Dean 	u_int	data;
51880275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
519de8050f9SBrian S. Dean 	return (data);
520de8050f9SBrian S. Dean }
521de8050f9SBrian S. Dean 
5226eda157eSBrian S. Dean static __inline void
52307508f90SJohn Baldwin load_dr3(u_int dr3)
5246eda157eSBrian S. Dean {
52507508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
5266eda157eSBrian S. Dean }
5276eda157eSBrian S. Dean 
5286eda157eSBrian S. Dean static __inline u_int
5296eda157eSBrian S. Dean rdr4(void)
5306eda157eSBrian S. Dean {
5316eda157eSBrian S. Dean 	u_int	data;
5326eda157eSBrian S. Dean 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
5336eda157eSBrian S. Dean 	return (data);
5346eda157eSBrian S. Dean }
5356eda157eSBrian S. Dean 
5366eda157eSBrian S. Dean static __inline void
53707508f90SJohn Baldwin load_dr4(u_int dr4)
5386eda157eSBrian S. Dean {
53907508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
5406eda157eSBrian S. Dean }
5416eda157eSBrian S. Dean 
5426eda157eSBrian S. Dean static __inline u_int
5436eda157eSBrian S. Dean rdr5(void)
5446eda157eSBrian S. Dean {
5456eda157eSBrian S. Dean 	u_int	data;
5466eda157eSBrian S. Dean 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
5476eda157eSBrian S. Dean 	return (data);
5486eda157eSBrian S. Dean }
5496eda157eSBrian S. Dean 
5506eda157eSBrian S. Dean static __inline void
55107508f90SJohn Baldwin load_dr5(u_int dr5)
5526eda157eSBrian S. Dean {
55307508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
5546eda157eSBrian S. Dean }
5556eda157eSBrian S. Dean 
556de8050f9SBrian S. Dean static __inline u_int
557de8050f9SBrian S. Dean rdr6(void)
558de8050f9SBrian S. Dean {
559de8050f9SBrian S. Dean 	u_int	data;
56080275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
561de8050f9SBrian S. Dean 	return (data);
562de8050f9SBrian S. Dean }
563de8050f9SBrian S. Dean 
5646eda157eSBrian S. Dean static __inline void
56507508f90SJohn Baldwin load_dr6(u_int dr6)
5666eda157eSBrian S. Dean {
56707508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
5686eda157eSBrian S. Dean }
5696eda157eSBrian S. Dean 
570de8050f9SBrian S. Dean static __inline u_int
571de8050f9SBrian S. Dean rdr7(void)
572de8050f9SBrian S. Dean {
573de8050f9SBrian S. Dean 	u_int	data;
57480275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
575de8050f9SBrian S. Dean 	return (data);
576de8050f9SBrian S. Dean }
577de8050f9SBrian S. Dean 
5786eda157eSBrian S. Dean static __inline void
57907508f90SJohn Baldwin load_dr7(u_int dr7)
5806eda157eSBrian S. Dean {
58107508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
5826eda157eSBrian S. Dean }
5836eda157eSBrian S. Dean 
584ba74981eSWarner Losh static __inline register_t
585ba74981eSWarner Losh intr_disable(void)
586ba74981eSWarner Losh {
587ba74981eSWarner Losh 	register_t eflags;
588ba74981eSWarner Losh 
589ba74981eSWarner Losh 	eflags = read_eflags();
590ba74981eSWarner Losh 	disable_intr();
591ba74981eSWarner Losh 	return (eflags);
592ba74981eSWarner Losh }
593ba74981eSWarner Losh 
594ba74981eSWarner Losh static __inline void
595ba74981eSWarner Losh intr_restore(register_t eflags)
596ba74981eSWarner Losh {
597ba74981eSWarner Losh 	write_eflags(eflags);
598ba74981eSWarner Losh }
599ba74981eSWarner Losh 
600004bedebSBruce Evans #else /* !__GNUC__ */
6015b81b6b3SRodney W. Grimes 
602b63dc6adSAlfred Perlstein int	breakpoint(void);
603b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
604b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
605f1b665c8SPeter Wemm void	cpu_invlpg(u_int addr);
606f1b665c8SPeter Wemm void	cpu_invlpg_range(u_int start, u_int end);
607b63dc6adSAlfred Perlstein void	disable_intr(void);
608b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
609b63dc6adSAlfred Perlstein void	enable_intr(void);
610b63dc6adSAlfred Perlstein u_char	inb(u_int port);
611b63dc6adSAlfred Perlstein u_int	inl(u_int port);
612b63dc6adSAlfred Perlstein void	insb(u_int port, void *addr, size_t cnt);
613b63dc6adSAlfred Perlstein void	insl(u_int port, void *addr, size_t cnt);
614b63dc6adSAlfred Perlstein void	insw(u_int port, void *addr, size_t cnt);
615b63dc6adSAlfred Perlstein void	invd(void);
616b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
617f1b665c8SPeter Wemm void	invlpg_range(u_int start, u_int end);
618b63dc6adSAlfred Perlstein void	invltlb(void);
619b63dc6adSAlfred Perlstein u_short	inw(u_int port);
620f1b665c8SPeter Wemm void	load_cr0(u_int cr0);
621f1b665c8SPeter Wemm void	load_cr3(u_int cr3);
622f1b665c8SPeter Wemm void	load_cr4(u_int cr4);
623f1b665c8SPeter Wemm void	load_fs(u_int sel);
624f1b665c8SPeter Wemm void	load_gs(u_int sel);
625b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
626b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
627b63dc6adSAlfred Perlstein void	outsb(u_int port, void *addr, size_t cnt);
628b63dc6adSAlfred Perlstein void	outsl(u_int port, void *addr, size_t cnt);
629b63dc6adSAlfred Perlstein void	outsw(u_int port, void *addr, size_t cnt);
630b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
6316b8c6989SJohn Baldwin void	ia32_pause(void);
632f1b665c8SPeter Wemm u_int	rcr0(void);
633b63dc6adSAlfred Perlstein u_int	rcr2(void);
634f1b665c8SPeter Wemm u_int	rcr3(void);
635f1b665c8SPeter Wemm u_int	rcr4(void);
636f1b665c8SPeter Wemm u_int	rfs(void);
637f1b665c8SPeter Wemm u_int	rgs(void);
638b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr);
639b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc);
640b63dc6adSAlfred Perlstein u_int64_t rdtsc(void);
641b63dc6adSAlfred Perlstein u_int	read_eflags(void);
642b63dc6adSAlfred Perlstein void	wbinvd(void);
643b63dc6adSAlfred Perlstein void	write_eflags(u_int ef);
644b63dc6adSAlfred Perlstein void	wrmsr(u_int msr, u_int64_t newval);
6452be69f32SJohn Baldwin u_int	rdr0(void);
64607508f90SJohn Baldwin void	load_dr0(u_int dr0);
6472be69f32SJohn Baldwin u_int	rdr1(void);
64807508f90SJohn Baldwin void	load_dr1(u_int dr1);
6492be69f32SJohn Baldwin u_int	rdr2(void);
65007508f90SJohn Baldwin void	load_dr2(u_int dr2);
6512be69f32SJohn Baldwin u_int	rdr3(void);
65207508f90SJohn Baldwin void	load_dr3(u_int dr3);
6532be69f32SJohn Baldwin u_int	rdr4(void);
65407508f90SJohn Baldwin void	load_dr4(u_int dr4);
6552be69f32SJohn Baldwin u_int	rdr5(void);
65607508f90SJohn Baldwin void	load_dr5(u_int dr5);
6572be69f32SJohn Baldwin u_int	rdr6(void);
65807508f90SJohn Baldwin void	load_dr6(u_int dr6);
6592be69f32SJohn Baldwin u_int	rdr7(void);
66007508f90SJohn Baldwin void	load_dr7(u_int dr7);
6612be69f32SJohn Baldwin register_t	intr_disable(void);
6622be69f32SJohn Baldwin void	intr_restore(register_t ef);
663004bedebSBruce Evans 
6645b81b6b3SRodney W. Grimes #endif	/* __GNUC__ */
6655b81b6b3SRodney W. Grimes 
666b63dc6adSAlfred Perlstein void	ltr(u_short sel);
667b63dc6adSAlfred Perlstein void    reset_dbregs(void);
668d74ac681SMatthew Dillon 
66929d5de8aSWarner Losh __END_DECLS
6705b81b6b3SRodney W. Grimes 
671004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
672