xref: /freebsd/sys/amd64/include/cpufunc.h (revision d7ee442578211dd170da9a05e5bcf6bdc75a3d16)
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 
615dbd168eSBruce Evans static __inline void
625dbd168eSBruce Evans breakpoint(void)
63004bedebSBruce Evans {
64004bedebSBruce Evans 	__asm __volatile("int $3");
655b81b6b3SRodney W. Grimes }
665b81b6b3SRodney W. Grimes 
67c83b1328SBruce Evans static __inline u_int
68c83b1328SBruce Evans bsfl(u_int mask)
69c83b1328SBruce Evans {
70c83b1328SBruce Evans 	u_int	result;
71c83b1328SBruce Evans 
723f9a462fSJohn Baldwin 	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
73c83b1328SBruce Evans 	return (result);
74c83b1328SBruce Evans }
75c83b1328SBruce Evans 
76c83b1328SBruce Evans static __inline u_int
77c83b1328SBruce Evans bsrl(u_int mask)
78c83b1328SBruce Evans {
79c83b1328SBruce Evans 	u_int	result;
80c83b1328SBruce Evans 
813f9a462fSJohn Baldwin 	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
82c83b1328SBruce Evans 	return (result);
83c83b1328SBruce Evans }
84c83b1328SBruce Evans 
85004bedebSBruce Evans static __inline void
865b81b6b3SRodney W. Grimes disable_intr(void)
875b81b6b3SRodney W. Grimes {
888966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
895b81b6b3SRodney W. Grimes }
905b81b6b3SRodney W. Grimes 
91004bedebSBruce Evans static __inline void
92a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
93a983fdfeSDavid Malone {
94a983fdfeSDavid Malone 	__asm __volatile("cpuid"
95a983fdfeSDavid Malone 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
96a983fdfeSDavid Malone 			 :  "0" (ax));
97a983fdfeSDavid Malone }
98a983fdfeSDavid Malone 
99a983fdfeSDavid Malone static __inline void
1005b81b6b3SRodney W. Grimes enable_intr(void)
1015b81b6b3SRodney W. Grimes {
102fadc51bdSBruce Evans 	__asm __volatile("sti");
1035b81b6b3SRodney W. Grimes }
1045b81b6b3SRodney W. Grimes 
105264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
106264c3d87SPeter Wemm 
107264c3d87SPeter Wemm static __inline int
108264c3d87SPeter Wemm ffs(int mask)
109264c3d87SPeter Wemm {
110264c3d87SPeter Wemm 	/*
111004bedebSBruce Evans 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
112004bedebSBruce Evans 	 * this inline or turn off the builtin.  The builtin is faster but
113c83b1328SBruce Evans 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
114c83b1328SBruce Evans 	 * versions.
115004bedebSBruce Evans 	 */
1167e622d3cSMark Murray 	 return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
117004bedebSBruce Evans }
118004bedebSBruce Evans 
11913f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
12013f588f8SGarrett Wollman 
12113f588f8SGarrett Wollman static __inline int
12213f588f8SGarrett Wollman fls(int mask)
12313f588f8SGarrett Wollman {
1247e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
12513f588f8SGarrett Wollman }
12613f588f8SGarrett Wollman 
127d7ee4425SMark Murray static __inline void
128d7ee4425SMark Murray halt(void)
129d7ee4425SMark Murray {
130d7ee4425SMark Murray 	__asm __volatile("hlt");
131d7ee4425SMark Murray }
132d7ee4425SMark Murray 
133004bedebSBruce Evans #if __GNUC__ < 2
134004bedebSBruce Evans 
135004bedebSBruce Evans #define	inb(port)		inbv(port)
136004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
137004bedebSBruce Evans 
138004bedebSBruce Evans #else /* __GNUC >= 2 */
139004bedebSBruce Evans 
140004bedebSBruce Evans /*
1418089a043SBruce Evans  * The following complications are to get around gcc not having a
1428089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1438089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1448089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1458089a043SBruce Evans  * the non-working version gets optimized away.
1468089a043SBruce Evans  *
147004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
148004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
149004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
150388dfa71SBruce Evans  *
151388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
152388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
153388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
154388dfa71SBruce Evans  * careful to avoid generating warnings.
155004bedebSBruce Evans  */
156388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
157004bedebSBruce Evans 	u_char	_data;							\
158388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
159388dfa71SBruce Evans 	    && (port) < 0x10000)					\
160004bedebSBruce Evans 		_data = inbc(port);					\
161004bedebSBruce Evans 	else								\
162004bedebSBruce Evans 		_data = inbv(port);					\
163004bedebSBruce Evans 	_data; })
164004bedebSBruce Evans 
165388dfa71SBruce Evans #define	outb(port, data) (						\
166388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
167388dfa71SBruce Evans 	&& (port) < 0x10000						\
168004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
169004bedebSBruce Evans 
170004bedebSBruce Evans static __inline u_char
171004bedebSBruce Evans inbc(u_int port)
172004bedebSBruce Evans {
173004bedebSBruce Evans 	u_char	data;
174004bedebSBruce Evans 
1758089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
176004bedebSBruce Evans 	return (data);
177004bedebSBruce Evans }
178004bedebSBruce Evans 
179004bedebSBruce Evans static __inline void
180004bedebSBruce Evans outbc(u_int port, u_char data)
181004bedebSBruce Evans {
1828089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
183004bedebSBruce Evans }
184004bedebSBruce Evans 
185004bedebSBruce Evans #endif /* __GNUC <= 2 */
186004bedebSBruce Evans 
187004bedebSBruce Evans static __inline u_char
188004bedebSBruce Evans inbv(u_int port)
189004bedebSBruce Evans {
190004bedebSBruce Evans 	u_char	data;
191004bedebSBruce Evans 	/*
192004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
193004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
194004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
195004bedebSBruce Evans 	 */
196004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
197004bedebSBruce Evans 	return (data);
198004bedebSBruce Evans }
199004bedebSBruce Evans 
20000be8601SBruce Evans static __inline u_int
201004bedebSBruce Evans inl(u_int port)
202004bedebSBruce Evans {
20300be8601SBruce Evans 	u_int	data;
204004bedebSBruce Evans 
205004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
206004bedebSBruce Evans 	return (data);
207004bedebSBruce Evans }
208004bedebSBruce Evans 
209004bedebSBruce Evans static __inline void
210004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
211004bedebSBruce Evans {
212004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
2133f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2143f9a462fSJohn Baldwin 			 : "d" (port)
215896763faSBruce Evans 			 : "memory");
216004bedebSBruce Evans }
217004bedebSBruce Evans 
218004bedebSBruce Evans static __inline void
219004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
220004bedebSBruce Evans {
221004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
2223f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2233f9a462fSJohn Baldwin 			 : "d" (port)
224896763faSBruce Evans 			 : "memory");
225004bedebSBruce Evans }
226004bedebSBruce Evans 
227004bedebSBruce Evans static __inline void
228004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
229004bedebSBruce Evans {
230004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
2313f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2323f9a462fSJohn Baldwin 			 : "d" (port)
233896763faSBruce Evans 			 : "memory");
234004bedebSBruce Evans }
235004bedebSBruce Evans 
236ece15d78SBruce Evans static __inline void
2374c024bbdSKATO Takenori invd(void)
2384c024bbdSKATO Takenori {
2394c024bbdSKATO Takenori 	__asm __volatile("invd");
2404c024bbdSKATO Takenori }
2414c024bbdSKATO Takenori 
242004bedebSBruce Evans static __inline u_short
243004bedebSBruce Evans inw(u_int port)
244004bedebSBruce Evans {
245004bedebSBruce Evans 	u_short	data;
246004bedebSBruce Evans 
247004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
248004bedebSBruce Evans 	return (data);
249004bedebSBruce Evans }
250004bedebSBruce Evans 
251004bedebSBruce Evans static __inline void
252004bedebSBruce Evans outbv(u_int port, u_char data)
253004bedebSBruce Evans {
254004bedebSBruce Evans 	u_char	al;
255004bedebSBruce Evans 	/*
256004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
257004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
258004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
259004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
260004bedebSBruce Evans 	 */
261004bedebSBruce Evans 	al = data;
262004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
263004bedebSBruce Evans }
264004bedebSBruce Evans 
265004bedebSBruce Evans static __inline void
26600be8601SBruce Evans outl(u_int port, u_int data)
267004bedebSBruce Evans {
268004bedebSBruce Evans 	/*
269004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
270004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
271004bedebSBruce Evans 	 * assignment for them.
272004bedebSBruce Evans 	 */
273004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
274004bedebSBruce Evans }
275004bedebSBruce Evans 
276004bedebSBruce Evans static __inline void
277e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
278004bedebSBruce Evans {
279004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
2803f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
2813f9a462fSJohn Baldwin 			 : "d" (port));
282004bedebSBruce Evans }
283004bedebSBruce Evans 
284004bedebSBruce Evans static __inline void
285e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
286004bedebSBruce Evans {
287004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
2883f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
2893f9a462fSJohn Baldwin 			 : "d" (port));
290004bedebSBruce Evans }
291004bedebSBruce Evans 
292004bedebSBruce Evans static __inline void
293e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
294004bedebSBruce Evans {
295004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
2963f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
2973f9a462fSJohn Baldwin 			 : "d" (port));
298004bedebSBruce Evans }
299004bedebSBruce Evans 
300004bedebSBruce Evans static __inline void
301004bedebSBruce Evans outw(u_int port, u_short data)
302004bedebSBruce Evans {
303004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
304004bedebSBruce Evans }
305004bedebSBruce Evans 
3062be69f32SJohn Baldwin static __inline void
3076b8c6989SJohn Baldwin ia32_pause(void)
3082be69f32SJohn Baldwin {
3092be69f32SJohn Baldwin 	__asm __volatile("pause");
3102be69f32SJohn Baldwin }
3112be69f32SJohn Baldwin 
31200be8601SBruce Evans static __inline u_int
313004bedebSBruce Evans read_eflags(void)
3145b81b6b3SRodney W. Grimes {
31500be8601SBruce Evans 	u_int	ef;
316004bedebSBruce Evans 
317004bedebSBruce Evans 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3188db02de8SPaul Richards 	return (ef);
3195b81b6b3SRodney W. Grimes }
3205b81b6b3SRodney W. Grimes 
32100be8601SBruce Evans static __inline u_int64_t
3225dbd168eSBruce Evans rdmsr(u_int msr)
3235dbd168eSBruce Evans {
32400be8601SBruce Evans 	u_int64_t rv;
3255dbd168eSBruce Evans 
32639413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3275dbd168eSBruce Evans 	return (rv);
3285dbd168eSBruce Evans }
3295dbd168eSBruce Evans 
33000be8601SBruce Evans static __inline u_int64_t
3315dbd168eSBruce Evans rdpmc(u_int pmc)
3325dbd168eSBruce Evans {
33300be8601SBruce Evans 	u_int64_t rv;
3345dbd168eSBruce Evans 
33539413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3365dbd168eSBruce Evans 	return (rv);
3375dbd168eSBruce Evans }
3385dbd168eSBruce Evans 
33900be8601SBruce Evans static __inline u_int64_t
3405dbd168eSBruce Evans rdtsc(void)
3415dbd168eSBruce Evans {
34200be8601SBruce Evans 	u_int64_t rv;
3435dbd168eSBruce Evans 
34439413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
3455dbd168eSBruce Evans 	return (rv);
3465dbd168eSBruce Evans }
3475dbd168eSBruce Evans 
348004bedebSBruce Evans static __inline void
3494c024bbdSKATO Takenori wbinvd(void)
3504c024bbdSKATO Takenori {
3514c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3524c024bbdSKATO Takenori }
3534c024bbdSKATO Takenori 
3544c024bbdSKATO Takenori static __inline void
35500be8601SBruce Evans write_eflags(u_int ef)
3565b81b6b3SRodney W. Grimes {
357004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
3585b81b6b3SRodney W. Grimes }
3595b81b6b3SRodney W. Grimes 
360d69e8502SGarrett Wollman static __inline void
36100be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
362d69e8502SGarrett Wollman {
36339413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
364d69e8502SGarrett Wollman }
365d69e8502SGarrett Wollman 
366f1b665c8SPeter Wemm static __inline void
367f1b665c8SPeter Wemm load_cr0(u_int data)
368f1b665c8SPeter Wemm {
369f1b665c8SPeter Wemm 
370f1b665c8SPeter Wemm 	__asm __volatile("movl %0,%%cr0" : : "r" (data));
371f1b665c8SPeter Wemm }
372f1b665c8SPeter Wemm 
373f1b665c8SPeter Wemm static __inline u_int
374f1b665c8SPeter Wemm rcr0(void)
375f1b665c8SPeter Wemm {
376f1b665c8SPeter Wemm 	u_int	data;
377f1b665c8SPeter Wemm 
378f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr0,%0" : "=r" (data));
379f1b665c8SPeter Wemm 	return (data);
380f1b665c8SPeter Wemm }
381f1b665c8SPeter Wemm 
382f1b665c8SPeter Wemm static __inline u_int
383f1b665c8SPeter Wemm rcr2(void)
384f1b665c8SPeter Wemm {
385f1b665c8SPeter Wemm 	u_int	data;
386f1b665c8SPeter Wemm 
387f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
388f1b665c8SPeter Wemm 	return (data);
389f1b665c8SPeter Wemm }
390f1b665c8SPeter Wemm 
391f1b665c8SPeter Wemm static __inline void
392f1b665c8SPeter Wemm load_cr3(u_int data)
393f1b665c8SPeter Wemm {
394f1b665c8SPeter Wemm 
395f1b665c8SPeter Wemm 	__asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
396f1b665c8SPeter Wemm }
397f1b665c8SPeter Wemm 
398f1b665c8SPeter Wemm static __inline u_int
399f1b665c8SPeter Wemm rcr3(void)
400f1b665c8SPeter Wemm {
401f1b665c8SPeter Wemm 	u_int	data;
402f1b665c8SPeter Wemm 
403f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr3,%0" : "=r" (data));
404f1b665c8SPeter Wemm 	return (data);
405f1b665c8SPeter Wemm }
406f1b665c8SPeter Wemm 
407f1b665c8SPeter Wemm static __inline void
408f1b665c8SPeter Wemm load_cr4(u_int data)
409f1b665c8SPeter Wemm {
410f1b665c8SPeter Wemm 	__asm __volatile("movl %0,%%cr4" : : "r" (data));
411f1b665c8SPeter Wemm }
412f1b665c8SPeter Wemm 
413f1b665c8SPeter Wemm static __inline u_int
414f1b665c8SPeter Wemm rcr4(void)
415f1b665c8SPeter Wemm {
416f1b665c8SPeter Wemm 	u_int	data;
417f1b665c8SPeter Wemm 
418f1b665c8SPeter Wemm 	__asm __volatile("movl %%cr4,%0" : "=r" (data));
419f1b665c8SPeter Wemm 	return (data);
420f1b665c8SPeter Wemm }
421f1b665c8SPeter Wemm 
422f1b665c8SPeter Wemm /*
423f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
424f1b665c8SPeter Wemm  */
425f1b665c8SPeter Wemm static __inline void
426f1b665c8SPeter Wemm invltlb(void)
427f1b665c8SPeter Wemm {
428f1b665c8SPeter Wemm 
429f1b665c8SPeter Wemm 	load_cr3(rcr3());
430f1b665c8SPeter Wemm }
431f1b665c8SPeter Wemm 
432f1b665c8SPeter Wemm /*
433f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
434f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
435f1b665c8SPeter Wemm  */
436f1b665c8SPeter Wemm static __inline void
437f1b665c8SPeter Wemm invlpg(u_int addr)
438f1b665c8SPeter Wemm {
439f1b665c8SPeter Wemm 
440f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
441f1b665c8SPeter Wemm }
442f1b665c8SPeter Wemm 
4435206bca1SLuoqi Chen static __inline u_int
4445206bca1SLuoqi Chen rfs(void)
4455206bca1SLuoqi Chen {
4465206bca1SLuoqi Chen 	u_int sel;
447e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4485206bca1SLuoqi Chen 	return (sel);
4495206bca1SLuoqi Chen }
4505206bca1SLuoqi Chen 
4515206bca1SLuoqi Chen static __inline u_int
4525206bca1SLuoqi Chen rgs(void)
4535206bca1SLuoqi Chen {
4545206bca1SLuoqi Chen 	u_int sel;
455e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4565206bca1SLuoqi Chen 	return (sel);
4575206bca1SLuoqi Chen }
4585206bca1SLuoqi Chen 
4595206bca1SLuoqi Chen static __inline void
4605206bca1SLuoqi Chen load_fs(u_int sel)
4615206bca1SLuoqi Chen {
462e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4635206bca1SLuoqi Chen }
4645206bca1SLuoqi Chen 
4655206bca1SLuoqi Chen static __inline void
4665206bca1SLuoqi Chen load_gs(u_int sel)
4675206bca1SLuoqi Chen {
468e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4695206bca1SLuoqi Chen }
4705206bca1SLuoqi Chen 
471de8050f9SBrian S. Dean static __inline u_int
472de8050f9SBrian S. Dean rdr0(void)
473de8050f9SBrian S. Dean {
474de8050f9SBrian S. Dean 	u_int	data;
47580275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
476de8050f9SBrian S. Dean 	return (data);
477de8050f9SBrian S. Dean }
478de8050f9SBrian S. Dean 
4796eda157eSBrian S. Dean static __inline void
48007508f90SJohn Baldwin load_dr0(u_int dr0)
4816eda157eSBrian S. Dean {
48207508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
4836eda157eSBrian S. Dean }
4846eda157eSBrian S. Dean 
485de8050f9SBrian S. Dean static __inline u_int
486de8050f9SBrian S. Dean rdr1(void)
487de8050f9SBrian S. Dean {
488de8050f9SBrian S. Dean 	u_int	data;
48980275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
490de8050f9SBrian S. Dean 	return (data);
491de8050f9SBrian S. Dean }
492de8050f9SBrian S. Dean 
4936eda157eSBrian S. Dean static __inline void
49407508f90SJohn Baldwin load_dr1(u_int dr1)
4956eda157eSBrian S. Dean {
49607508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
4976eda157eSBrian S. Dean }
4986eda157eSBrian S. Dean 
499de8050f9SBrian S. Dean static __inline u_int
500de8050f9SBrian S. Dean rdr2(void)
501de8050f9SBrian S. Dean {
502de8050f9SBrian S. Dean 	u_int	data;
50380275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
504de8050f9SBrian S. Dean 	return (data);
505de8050f9SBrian S. Dean }
506de8050f9SBrian S. Dean 
5076eda157eSBrian S. Dean static __inline void
50807508f90SJohn Baldwin load_dr2(u_int dr2)
5096eda157eSBrian S. Dean {
51007508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
5116eda157eSBrian S. Dean }
5126eda157eSBrian S. Dean 
513de8050f9SBrian S. Dean static __inline u_int
514de8050f9SBrian S. Dean rdr3(void)
515de8050f9SBrian S. Dean {
516de8050f9SBrian S. Dean 	u_int	data;
51780275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
518de8050f9SBrian S. Dean 	return (data);
519de8050f9SBrian S. Dean }
520de8050f9SBrian S. Dean 
5216eda157eSBrian S. Dean static __inline void
52207508f90SJohn Baldwin load_dr3(u_int dr3)
5236eda157eSBrian S. Dean {
52407508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
5256eda157eSBrian S. Dean }
5266eda157eSBrian S. Dean 
5276eda157eSBrian S. Dean static __inline u_int
5286eda157eSBrian S. Dean rdr4(void)
5296eda157eSBrian S. Dean {
5306eda157eSBrian S. Dean 	u_int	data;
5316eda157eSBrian S. Dean 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
5326eda157eSBrian S. Dean 	return (data);
5336eda157eSBrian S. Dean }
5346eda157eSBrian S. Dean 
5356eda157eSBrian S. Dean static __inline void
53607508f90SJohn Baldwin load_dr4(u_int dr4)
5376eda157eSBrian S. Dean {
53807508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
5396eda157eSBrian S. Dean }
5406eda157eSBrian S. Dean 
5416eda157eSBrian S. Dean static __inline u_int
5426eda157eSBrian S. Dean rdr5(void)
5436eda157eSBrian S. Dean {
5446eda157eSBrian S. Dean 	u_int	data;
5456eda157eSBrian S. Dean 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
5466eda157eSBrian S. Dean 	return (data);
5476eda157eSBrian S. Dean }
5486eda157eSBrian S. Dean 
5496eda157eSBrian S. Dean static __inline void
55007508f90SJohn Baldwin load_dr5(u_int dr5)
5516eda157eSBrian S. Dean {
55207508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
5536eda157eSBrian S. Dean }
5546eda157eSBrian S. Dean 
555de8050f9SBrian S. Dean static __inline u_int
556de8050f9SBrian S. Dean rdr6(void)
557de8050f9SBrian S. Dean {
558de8050f9SBrian S. Dean 	u_int	data;
55980275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
560de8050f9SBrian S. Dean 	return (data);
561de8050f9SBrian S. Dean }
562de8050f9SBrian S. Dean 
5636eda157eSBrian S. Dean static __inline void
56407508f90SJohn Baldwin load_dr6(u_int dr6)
5656eda157eSBrian S. Dean {
56607508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
5676eda157eSBrian S. Dean }
5686eda157eSBrian S. Dean 
569de8050f9SBrian S. Dean static __inline u_int
570de8050f9SBrian S. Dean rdr7(void)
571de8050f9SBrian S. Dean {
572de8050f9SBrian S. Dean 	u_int	data;
57380275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
574de8050f9SBrian S. Dean 	return (data);
575de8050f9SBrian S. Dean }
576de8050f9SBrian S. Dean 
5776eda157eSBrian S. Dean static __inline void
57807508f90SJohn Baldwin load_dr7(u_int dr7)
5796eda157eSBrian S. Dean {
58007508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
5816eda157eSBrian S. Dean }
5826eda157eSBrian S. Dean 
583ba74981eSWarner Losh static __inline register_t
584ba74981eSWarner Losh intr_disable(void)
585ba74981eSWarner Losh {
586ba74981eSWarner Losh 	register_t eflags;
587ba74981eSWarner Losh 
588ba74981eSWarner Losh 	eflags = read_eflags();
589ba74981eSWarner Losh 	disable_intr();
590ba74981eSWarner Losh 	return (eflags);
591ba74981eSWarner Losh }
592ba74981eSWarner Losh 
593ba74981eSWarner Losh static __inline void
594ba74981eSWarner Losh intr_restore(register_t eflags)
595ba74981eSWarner Losh {
596ba74981eSWarner Losh 	write_eflags(eflags);
597ba74981eSWarner Losh }
598ba74981eSWarner Losh 
599004bedebSBruce Evans #else /* !__GNUC__ */
6005b81b6b3SRodney W. Grimes 
601b63dc6adSAlfred Perlstein int	breakpoint(void);
602b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
603b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
604f1b665c8SPeter Wemm void	cpu_invlpg(u_int addr);
605f1b665c8SPeter Wemm void	cpu_invlpg_range(u_int start, u_int end);
606b63dc6adSAlfred Perlstein void	disable_intr(void);
607b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
608b63dc6adSAlfred Perlstein void	enable_intr(void);
609d7ee4425SMark Murray void	halt(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