xref: /freebsd/sys/amd64/include/cpufunc.h (revision 07508f90b69a7935a537673fee103fdfbca97956)
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 	 */
120c83b1328SBruce Evans 	 return (mask == 0 ? mask : 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 {
128c83b1328SBruce Evans 	return (mask == 0 ? mask : 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 
240d1693e17SPeter Wemm #if defined(SMP) && defined(_KERNEL)
241d1693e17SPeter Wemm 
242d1693e17SPeter Wemm /*
243d1693e17SPeter Wemm  * When using APIC IPI's, invlpg() is not simply the invlpg instruction
244d1693e17SPeter Wemm  * (this is a bug) and the inlining cost is prohibitive since the call
245d1693e17SPeter Wemm  * executes into the IPI transmission system.
246d1693e17SPeter Wemm  */
247b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
248b63dc6adSAlfred Perlstein void	invltlb(void);
249d1693e17SPeter Wemm 
250d1693e17SPeter Wemm static __inline void
251d1693e17SPeter Wemm cpu_invlpg(void *addr)
252d1693e17SPeter Wemm {
253d1693e17SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
254d1693e17SPeter Wemm }
255d1693e17SPeter Wemm 
256d1693e17SPeter Wemm static __inline void
257d1693e17SPeter Wemm cpu_invltlb(void)
258d1693e17SPeter Wemm {
259d1693e17SPeter Wemm 	u_int	temp;
260d1693e17SPeter Wemm 	/*
261d1693e17SPeter Wemm 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
262d1693e17SPeter Wemm 	 * is inlined.
263d1693e17SPeter Wemm 	 */
264d1693e17SPeter Wemm 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
265d1693e17SPeter Wemm 			 : : "memory");
266d1693e17SPeter Wemm #if defined(SWTCH_OPTIM_STATS)
267d1693e17SPeter Wemm 	++tlb_flush_count;
268d1693e17SPeter Wemm #endif
269d1693e17SPeter Wemm }
270d1693e17SPeter Wemm 
271d1693e17SPeter Wemm #else /* !(SMP && _KERNEL) */
272d1693e17SPeter Wemm 
273d1693e17SPeter Wemm static __inline void
274d1693e17SPeter Wemm invlpg(u_int addr)
275d1693e17SPeter Wemm {
276d1693e17SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
277d1693e17SPeter Wemm }
278d1693e17SPeter Wemm 
279d1693e17SPeter Wemm static __inline void
280d1693e17SPeter Wemm invltlb(void)
281d1693e17SPeter Wemm {
282d1693e17SPeter Wemm 	u_int	temp;
283d1693e17SPeter Wemm 	/*
284d1693e17SPeter Wemm 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
285d1693e17SPeter Wemm 	 * is inlined.
286d1693e17SPeter Wemm 	 */
287d1693e17SPeter Wemm 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
288d1693e17SPeter Wemm 			 : : "memory");
289d1693e17SPeter Wemm #ifdef SWTCH_OPTIM_STATS
290d1693e17SPeter Wemm 	++tlb_flush_count;
291d1693e17SPeter Wemm #endif
292d1693e17SPeter Wemm }
293d1693e17SPeter Wemm 
294d1693e17SPeter Wemm #endif /* SMP && _KERNEL */
295d1693e17SPeter Wemm 
296004bedebSBruce Evans static __inline u_short
297004bedebSBruce Evans inw(u_int port)
298004bedebSBruce Evans {
299004bedebSBruce Evans 	u_short	data;
300004bedebSBruce Evans 
301004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
302004bedebSBruce Evans 	return (data);
303004bedebSBruce Evans }
304004bedebSBruce Evans 
305004bedebSBruce Evans static __inline void
306004bedebSBruce Evans outbv(u_int port, u_char data)
307004bedebSBruce Evans {
308004bedebSBruce Evans 	u_char	al;
309004bedebSBruce Evans 	/*
310004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
311004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
312004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
313004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
314004bedebSBruce Evans 	 */
315004bedebSBruce Evans 	al = data;
316004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
317004bedebSBruce Evans }
318004bedebSBruce Evans 
319004bedebSBruce Evans static __inline void
32000be8601SBruce Evans outl(u_int port, u_int data)
321004bedebSBruce Evans {
322004bedebSBruce Evans 	/*
323004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
324004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
325004bedebSBruce Evans 	 * assignment for them.
326004bedebSBruce Evans 	 */
327004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
328004bedebSBruce Evans }
329004bedebSBruce Evans 
330004bedebSBruce Evans static __inline void
331e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
332004bedebSBruce Evans {
333004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
3343f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3353f9a462fSJohn Baldwin 			 : "d" (port));
336004bedebSBruce Evans }
337004bedebSBruce Evans 
338004bedebSBruce Evans static __inline void
339e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
340004bedebSBruce Evans {
341004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
3423f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3433f9a462fSJohn Baldwin 			 : "d" (port));
344004bedebSBruce Evans }
345004bedebSBruce Evans 
346004bedebSBruce Evans static __inline void
347e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
348004bedebSBruce Evans {
349004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
3503f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3513f9a462fSJohn Baldwin 			 : "d" (port));
352004bedebSBruce Evans }
353004bedebSBruce Evans 
354004bedebSBruce Evans static __inline void
355004bedebSBruce Evans outw(u_int port, u_short data)
356004bedebSBruce Evans {
357004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
358004bedebSBruce Evans }
359004bedebSBruce Evans 
3602be69f32SJohn Baldwin static __inline void
3612be69f32SJohn Baldwin pause(void)
3622be69f32SJohn Baldwin {
3632be69f32SJohn Baldwin 	__asm __volatile("pause");
3642be69f32SJohn Baldwin }
3652be69f32SJohn Baldwin 
36600be8601SBruce Evans static __inline u_int
367d1693e17SPeter Wemm rcr2(void)
368d1693e17SPeter Wemm {
369d1693e17SPeter Wemm 	u_int	data;
370d1693e17SPeter Wemm 
371d1693e17SPeter Wemm 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
372d1693e17SPeter Wemm 	return (data);
373d1693e17SPeter Wemm }
374d1693e17SPeter Wemm 
375d1693e17SPeter Wemm static __inline u_int
376004bedebSBruce Evans read_eflags(void)
3775b81b6b3SRodney W. Grimes {
37800be8601SBruce Evans 	u_int	ef;
379004bedebSBruce Evans 
380004bedebSBruce Evans 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3818db02de8SPaul Richards 	return (ef);
3825b81b6b3SRodney W. Grimes }
3835b81b6b3SRodney W. Grimes 
38400be8601SBruce Evans static __inline u_int64_t
3855dbd168eSBruce Evans rdmsr(u_int msr)
3865dbd168eSBruce Evans {
38700be8601SBruce Evans 	u_int64_t rv;
3885dbd168eSBruce Evans 
38939413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3905dbd168eSBruce Evans 	return (rv);
3915dbd168eSBruce Evans }
3925dbd168eSBruce Evans 
39300be8601SBruce Evans static __inline u_int64_t
3945dbd168eSBruce Evans rdpmc(u_int pmc)
3955dbd168eSBruce Evans {
39600be8601SBruce Evans 	u_int64_t rv;
3975dbd168eSBruce Evans 
39839413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3995dbd168eSBruce Evans 	return (rv);
4005dbd168eSBruce Evans }
4015dbd168eSBruce Evans 
40200be8601SBruce Evans static __inline u_int64_t
4035dbd168eSBruce Evans rdtsc(void)
4045dbd168eSBruce Evans {
40500be8601SBruce Evans 	u_int64_t rv;
4065dbd168eSBruce Evans 
40739413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
4085dbd168eSBruce Evans 	return (rv);
4095dbd168eSBruce Evans }
4105dbd168eSBruce Evans 
411004bedebSBruce Evans static __inline void
4124c024bbdSKATO Takenori wbinvd(void)
4134c024bbdSKATO Takenori {
4144c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
4154c024bbdSKATO Takenori }
4164c024bbdSKATO Takenori 
4174c024bbdSKATO Takenori static __inline void
41800be8601SBruce Evans write_eflags(u_int ef)
4195b81b6b3SRodney W. Grimes {
420004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
4215b81b6b3SRodney W. Grimes }
4225b81b6b3SRodney W. Grimes 
423d69e8502SGarrett Wollman static __inline void
42400be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
425d69e8502SGarrett Wollman {
42639413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
427d69e8502SGarrett Wollman }
428d69e8502SGarrett Wollman 
4295206bca1SLuoqi Chen static __inline u_int
4305206bca1SLuoqi Chen rfs(void)
4315206bca1SLuoqi Chen {
4325206bca1SLuoqi Chen 	u_int sel;
433e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4345206bca1SLuoqi Chen 	return (sel);
4355206bca1SLuoqi Chen }
4365206bca1SLuoqi Chen 
4375206bca1SLuoqi Chen static __inline u_int
4385206bca1SLuoqi Chen rgs(void)
4395206bca1SLuoqi Chen {
4405206bca1SLuoqi Chen 	u_int sel;
441e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4425206bca1SLuoqi Chen 	return (sel);
4435206bca1SLuoqi Chen }
4445206bca1SLuoqi Chen 
4455206bca1SLuoqi Chen static __inline void
4465206bca1SLuoqi Chen load_fs(u_int sel)
4475206bca1SLuoqi Chen {
448e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4495206bca1SLuoqi Chen }
4505206bca1SLuoqi Chen 
4515206bca1SLuoqi Chen static __inline void
4525206bca1SLuoqi Chen load_gs(u_int sel)
4535206bca1SLuoqi Chen {
454e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4555206bca1SLuoqi Chen }
4565206bca1SLuoqi Chen 
457de8050f9SBrian S. Dean static __inline u_int
458de8050f9SBrian S. Dean rdr0(void)
459de8050f9SBrian S. Dean {
460de8050f9SBrian S. Dean 	u_int	data;
46180275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
462de8050f9SBrian S. Dean 	return (data);
463de8050f9SBrian S. Dean }
464de8050f9SBrian S. Dean 
4656eda157eSBrian S. Dean static __inline void
46607508f90SJohn Baldwin load_dr0(u_int dr0)
4676eda157eSBrian S. Dean {
46807508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr0" : : "r" (dr0));
4696eda157eSBrian S. Dean }
4706eda157eSBrian S. Dean 
471de8050f9SBrian S. Dean static __inline u_int
472de8050f9SBrian S. Dean rdr1(void)
473de8050f9SBrian S. Dean {
474de8050f9SBrian S. Dean 	u_int	data;
47580275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
476de8050f9SBrian S. Dean 	return (data);
477de8050f9SBrian S. Dean }
478de8050f9SBrian S. Dean 
4796eda157eSBrian S. Dean static __inline void
48007508f90SJohn Baldwin load_dr1(u_int dr1)
4816eda157eSBrian S. Dean {
48207508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr1" : : "r" (dr1));
4836eda157eSBrian S. Dean }
4846eda157eSBrian S. Dean 
485de8050f9SBrian S. Dean static __inline u_int
486de8050f9SBrian S. Dean rdr2(void)
487de8050f9SBrian S. Dean {
488de8050f9SBrian S. Dean 	u_int	data;
48980275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
490de8050f9SBrian S. Dean 	return (data);
491de8050f9SBrian S. Dean }
492de8050f9SBrian S. Dean 
4936eda157eSBrian S. Dean static __inline void
49407508f90SJohn Baldwin load_dr2(u_int dr2)
4956eda157eSBrian S. Dean {
49607508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr2" : : "r" (dr2));
4976eda157eSBrian S. Dean }
4986eda157eSBrian S. Dean 
499de8050f9SBrian S. Dean static __inline u_int
500de8050f9SBrian S. Dean rdr3(void)
501de8050f9SBrian S. Dean {
502de8050f9SBrian S. Dean 	u_int	data;
50380275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
504de8050f9SBrian S. Dean 	return (data);
505de8050f9SBrian S. Dean }
506de8050f9SBrian S. Dean 
5076eda157eSBrian S. Dean static __inline void
50807508f90SJohn Baldwin load_dr3(u_int dr3)
5096eda157eSBrian S. Dean {
51007508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr3" : : "r" (dr3));
5116eda157eSBrian S. Dean }
5126eda157eSBrian S. Dean 
5136eda157eSBrian S. Dean static __inline u_int
5146eda157eSBrian S. Dean rdr4(void)
5156eda157eSBrian S. Dean {
5166eda157eSBrian S. Dean 	u_int	data;
5176eda157eSBrian S. Dean 	__asm __volatile("movl %%dr4,%0" : "=r" (data));
5186eda157eSBrian S. Dean 	return (data);
5196eda157eSBrian S. Dean }
5206eda157eSBrian S. Dean 
5216eda157eSBrian S. Dean static __inline void
52207508f90SJohn Baldwin load_dr4(u_int dr4)
5236eda157eSBrian S. Dean {
52407508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr4" : : "r" (dr4));
5256eda157eSBrian S. Dean }
5266eda157eSBrian S. Dean 
5276eda157eSBrian S. Dean static __inline u_int
5286eda157eSBrian S. Dean rdr5(void)
5296eda157eSBrian S. Dean {
5306eda157eSBrian S. Dean 	u_int	data;
5316eda157eSBrian S. Dean 	__asm __volatile("movl %%dr5,%0" : "=r" (data));
5326eda157eSBrian S. Dean 	return (data);
5336eda157eSBrian S. Dean }
5346eda157eSBrian S. Dean 
5356eda157eSBrian S. Dean static __inline void
53607508f90SJohn Baldwin load_dr5(u_int dr5)
5376eda157eSBrian S. Dean {
53807508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr5" : : "r" (dr5));
5396eda157eSBrian S. Dean }
5406eda157eSBrian S. Dean 
541de8050f9SBrian S. Dean static __inline u_int
542de8050f9SBrian S. Dean rdr6(void)
543de8050f9SBrian S. Dean {
544de8050f9SBrian S. Dean 	u_int	data;
54580275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
546de8050f9SBrian S. Dean 	return (data);
547de8050f9SBrian S. Dean }
548de8050f9SBrian S. Dean 
5496eda157eSBrian S. Dean static __inline void
55007508f90SJohn Baldwin load_dr6(u_int dr6)
5516eda157eSBrian S. Dean {
55207508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr6" : : "r" (dr6));
5536eda157eSBrian S. Dean }
5546eda157eSBrian S. Dean 
555de8050f9SBrian S. Dean static __inline u_int
556de8050f9SBrian S. Dean rdr7(void)
557de8050f9SBrian S. Dean {
558de8050f9SBrian S. Dean 	u_int	data;
55980275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
560de8050f9SBrian S. Dean 	return (data);
561de8050f9SBrian S. Dean }
562de8050f9SBrian S. Dean 
5636eda157eSBrian S. Dean static __inline void
56407508f90SJohn Baldwin load_dr7(u_int dr7)
5656eda157eSBrian S. Dean {
56607508f90SJohn Baldwin 	__asm __volatile("movl %0,%%dr7" : : "r" (dr7));
5676eda157eSBrian S. Dean }
5686eda157eSBrian S. Dean 
569ba74981eSWarner Losh static __inline register_t
570ba74981eSWarner Losh intr_disable(void)
571ba74981eSWarner Losh {
572ba74981eSWarner Losh 	register_t eflags;
573ba74981eSWarner Losh 
574ba74981eSWarner Losh 	eflags = read_eflags();
575ba74981eSWarner Losh 	disable_intr();
576ba74981eSWarner Losh 	return (eflags);
577ba74981eSWarner Losh }
578ba74981eSWarner Losh 
579ba74981eSWarner Losh static __inline void
580ba74981eSWarner Losh intr_restore(register_t eflags)
581ba74981eSWarner Losh {
582ba74981eSWarner Losh 	write_eflags(eflags);
583ba74981eSWarner Losh }
584ba74981eSWarner Losh 
585004bedebSBruce Evans #else /* !__GNUC__ */
5865b81b6b3SRodney W. Grimes 
587b63dc6adSAlfred Perlstein int	breakpoint(void);
588b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
589b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
590b63dc6adSAlfred Perlstein void	disable_intr(void);
591b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
592b63dc6adSAlfred Perlstein void	enable_intr(void);
593b63dc6adSAlfred Perlstein u_char	inb(u_int port);
594b63dc6adSAlfred Perlstein u_int	inl(u_int port);
595b63dc6adSAlfred Perlstein void	insb(u_int port, void *addr, size_t cnt);
596b63dc6adSAlfred Perlstein void	insl(u_int port, void *addr, size_t cnt);
597b63dc6adSAlfred Perlstein void	insw(u_int port, void *addr, size_t cnt);
598b63dc6adSAlfred Perlstein void	invd(void);
599b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
600b63dc6adSAlfred Perlstein void	invltlb(void);
601b63dc6adSAlfred Perlstein u_short	inw(u_int port);
602b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
603b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
604b63dc6adSAlfred Perlstein void	outsb(u_int port, void *addr, size_t cnt);
605b63dc6adSAlfred Perlstein void	outsl(u_int port, void *addr, size_t cnt);
606b63dc6adSAlfred Perlstein void	outsw(u_int port, void *addr, size_t cnt);
607b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
6082be69f32SJohn Baldwin void	pause(void);
609b63dc6adSAlfred Perlstein u_int	rcr2(void);
610b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr);
611b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc);
612b63dc6adSAlfred Perlstein u_int64_t rdtsc(void);
613b63dc6adSAlfred Perlstein u_int	read_eflags(void);
614b63dc6adSAlfred Perlstein void	wbinvd(void);
615b63dc6adSAlfred Perlstein void	write_eflags(u_int ef);
616b63dc6adSAlfred Perlstein void	wrmsr(u_int msr, u_int64_t newval);
617b63dc6adSAlfred Perlstein u_int	rfs(void);
618b63dc6adSAlfred Perlstein u_int	rgs(void);
619b63dc6adSAlfred Perlstein void	load_fs(u_int sel);
620b63dc6adSAlfred Perlstein void	load_gs(u_int sel);
6212be69f32SJohn Baldwin u_int	rdr0(void);
62207508f90SJohn Baldwin void	load_dr0(u_int dr0);
6232be69f32SJohn Baldwin u_int	rdr1(void);
62407508f90SJohn Baldwin void	load_dr1(u_int dr1);
6252be69f32SJohn Baldwin u_int	rdr2(void);
62607508f90SJohn Baldwin void	load_dr2(u_int dr2);
6272be69f32SJohn Baldwin u_int	rdr3(void);
62807508f90SJohn Baldwin void	load_dr3(u_int dr3);
6292be69f32SJohn Baldwin u_int	rdr4(void);
63007508f90SJohn Baldwin void	load_dr4(u_int dr4);
6312be69f32SJohn Baldwin u_int	rdr5(void);
63207508f90SJohn Baldwin void	load_dr5(u_int dr5);
6332be69f32SJohn Baldwin u_int	rdr6(void);
63407508f90SJohn Baldwin void	load_dr6(u_int dr6);
6352be69f32SJohn Baldwin u_int	rdr7(void);
63607508f90SJohn Baldwin void	load_dr7(u_int dr7);
6372be69f32SJohn Baldwin register_t	intr_disable(void);
6382be69f32SJohn Baldwin void	intr_restore(register_t ef);
639004bedebSBruce Evans 
6405b81b6b3SRodney W. Grimes #endif	/* __GNUC__ */
6415b81b6b3SRodney W. Grimes 
642b63dc6adSAlfred Perlstein void	load_cr0(u_int cr0);
643b63dc6adSAlfred Perlstein void	load_cr3(u_int cr3);
644b63dc6adSAlfred Perlstein void	load_cr4(u_int cr4);
645b63dc6adSAlfred Perlstein void	ltr(u_short sel);
646b63dc6adSAlfred Perlstein u_int	rcr0(void);
647b63dc6adSAlfred Perlstein u_int	rcr3(void);
648b63dc6adSAlfred Perlstein u_int	rcr4(void);
649b63dc6adSAlfred Perlstein void    reset_dbregs(void);
650d74ac681SMatthew Dillon 
65129d5de8aSWarner Losh __END_DECLS
6525b81b6b3SRodney W. Grimes 
653004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
654