xref: /freebsd/sys/amd64/include/cpufunc.h (revision 034dc442ad1898c8211261bb7596faa03eacff02)
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 
43e31fa854SDoug Rabson #define readb(va)	(*(volatile u_int8_t *) (va))
44e31fa854SDoug Rabson #define readw(va)	(*(volatile u_int16_t *) (va))
45e31fa854SDoug Rabson #define readl(va)	(*(volatile u_int32_t *) (va))
46e31fa854SDoug Rabson 
47e31fa854SDoug Rabson #define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
48e31fa854SDoug Rabson #define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
49e31fa854SDoug Rabson #define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
50e31fa854SDoug Rabson 
515b81b6b3SRodney W. Grimes #ifdef	__GNUC__
525b81b6b3SRodney W. Grimes 
532a32c15fSBruce Evans #ifdef SWTCH_OPTIM_STATS
542a32c15fSBruce Evans extern	int	tlb_flush_count;	/* XXX */
552a32c15fSBruce Evans #endif
562a32c15fSBruce Evans 
575dbd168eSBruce Evans static __inline void
585dbd168eSBruce Evans breakpoint(void)
59004bedebSBruce Evans {
60004bedebSBruce Evans 	__asm __volatile("int $3");
615b81b6b3SRodney W. Grimes }
625b81b6b3SRodney W. Grimes 
63c83b1328SBruce Evans static __inline u_int
64c83b1328SBruce Evans bsfl(u_int mask)
65c83b1328SBruce Evans {
66c83b1328SBruce Evans 	u_int	result;
67c83b1328SBruce Evans 
68c83b1328SBruce Evans 	__asm __volatile("bsfl %0,%0" : "=r" (result) : "0" (mask));
69c83b1328SBruce Evans 	return (result);
70c83b1328SBruce Evans }
71c83b1328SBruce Evans 
72c83b1328SBruce Evans static __inline u_int
73c83b1328SBruce Evans bsrl(u_int mask)
74c83b1328SBruce Evans {
75c83b1328SBruce Evans 	u_int	result;
76c83b1328SBruce Evans 
77c83b1328SBruce Evans 	__asm __volatile("bsrl %0,%0" : "=r" (result) : "0" (mask));
78c83b1328SBruce Evans 	return (result);
79c83b1328SBruce Evans }
80c83b1328SBruce Evans 
81004bedebSBruce Evans static __inline void
825b81b6b3SRodney W. Grimes disable_intr(void)
835b81b6b3SRodney W. Grimes {
848966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
855b81b6b3SRodney W. Grimes }
865b81b6b3SRodney W. Grimes 
87004bedebSBruce Evans static __inline void
885b81b6b3SRodney W. Grimes enable_intr(void)
895b81b6b3SRodney W. Grimes {
90fadc51bdSBruce Evans 	__asm __volatile("sti");
915b81b6b3SRodney W. Grimes }
925b81b6b3SRodney W. Grimes 
93264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
94264c3d87SPeter Wemm 
95264c3d87SPeter Wemm static __inline int
96264c3d87SPeter Wemm ffs(int mask)
97264c3d87SPeter Wemm {
98264c3d87SPeter Wemm 	/*
99004bedebSBruce Evans 	 * Note that gcc-2's builtin ffs would be used if we didn't declare
100004bedebSBruce Evans 	 * this inline or turn off the builtin.  The builtin is faster but
101c83b1328SBruce Evans 	 * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
102c83b1328SBruce Evans 	 * versions.
103004bedebSBruce Evans 	 */
104c83b1328SBruce Evans 	 return (mask == 0 ? mask : bsfl((u_int)mask) + 1);
105004bedebSBruce Evans }
106004bedebSBruce Evans 
10713f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
10813f588f8SGarrett Wollman 
10913f588f8SGarrett Wollman static __inline int
11013f588f8SGarrett Wollman fls(int mask)
11113f588f8SGarrett Wollman {
112c83b1328SBruce Evans 	return (mask == 0 ? mask : bsrl((u_int)mask) + 1);
11313f588f8SGarrett Wollman }
11413f588f8SGarrett Wollman 
115004bedebSBruce Evans #if __GNUC__ < 2
116004bedebSBruce Evans 
117004bedebSBruce Evans #define	inb(port)		inbv(port)
118004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
119004bedebSBruce Evans 
120004bedebSBruce Evans #else /* __GNUC >= 2 */
121004bedebSBruce Evans 
122004bedebSBruce Evans /*
1238089a043SBruce Evans  * The following complications are to get around gcc not having a
1248089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1258089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1268089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1278089a043SBruce Evans  * the non-working version gets optimized away.
1288089a043SBruce Evans  *
129004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
130004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
131004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
132388dfa71SBruce Evans  *
133388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
134388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
135388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
136388dfa71SBruce Evans  * careful to avoid generating warnings.
137004bedebSBruce Evans  */
138388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
139004bedebSBruce Evans 	u_char	_data;							\
140388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
141388dfa71SBruce Evans 	    && (port) < 0x10000)					\
142004bedebSBruce Evans 		_data = inbc(port);					\
143004bedebSBruce Evans 	else								\
144004bedebSBruce Evans 		_data = inbv(port);					\
145004bedebSBruce Evans 	_data; })
146004bedebSBruce Evans 
147388dfa71SBruce Evans #define	outb(port, data) (						\
148388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
149388dfa71SBruce Evans 	&& (port) < 0x10000						\
150004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
151004bedebSBruce Evans 
152004bedebSBruce Evans static __inline u_char
153004bedebSBruce Evans inbc(u_int port)
154004bedebSBruce Evans {
155004bedebSBruce Evans 	u_char	data;
156004bedebSBruce Evans 
1578089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
158004bedebSBruce Evans 	return (data);
159004bedebSBruce Evans }
160004bedebSBruce Evans 
161004bedebSBruce Evans static __inline void
162004bedebSBruce Evans outbc(u_int port, u_char data)
163004bedebSBruce Evans {
1648089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
165004bedebSBruce Evans }
166004bedebSBruce Evans 
167004bedebSBruce Evans #endif /* __GNUC <= 2 */
168004bedebSBruce Evans 
169004bedebSBruce Evans static __inline u_char
170004bedebSBruce Evans inbv(u_int port)
171004bedebSBruce Evans {
172004bedebSBruce Evans 	u_char	data;
173004bedebSBruce Evans 	/*
174004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
175004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
176004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
177004bedebSBruce Evans 	 */
178004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
179004bedebSBruce Evans 	return (data);
180004bedebSBruce Evans }
181004bedebSBruce Evans 
18200be8601SBruce Evans static __inline u_int
183004bedebSBruce Evans inl(u_int port)
184004bedebSBruce Evans {
18500be8601SBruce Evans 	u_int	data;
186004bedebSBruce Evans 
187004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
188004bedebSBruce Evans 	return (data);
189004bedebSBruce Evans }
190004bedebSBruce Evans 
191004bedebSBruce Evans static __inline void
192004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
193004bedebSBruce Evans {
194004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
195896763faSBruce Evans 			 : "=D" (addr), "=c" (cnt)
196896763faSBruce Evans 			 :  "0" (addr),  "1" (cnt), "d" (port)
197896763faSBruce Evans 			 : "memory");
198004bedebSBruce Evans }
199004bedebSBruce Evans 
200004bedebSBruce Evans static __inline void
201004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
202004bedebSBruce Evans {
203004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
204896763faSBruce Evans 			 : "=D" (addr), "=c" (cnt)
205896763faSBruce Evans 			 :  "0" (addr),  "1" (cnt), "d" (port)
206896763faSBruce Evans 			 : "memory");
207004bedebSBruce Evans }
208004bedebSBruce Evans 
209004bedebSBruce Evans static __inline void
210004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
211004bedebSBruce Evans {
212004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
213896763faSBruce Evans 			 : "=D" (addr), "=c" (cnt)
214896763faSBruce Evans 			 :  "0" (addr),  "1" (cnt), "d" (port)
215896763faSBruce Evans 			 : "memory");
216004bedebSBruce Evans }
217004bedebSBruce Evans 
218ece15d78SBruce Evans static __inline void
2194c024bbdSKATO Takenori invd(void)
2204c024bbdSKATO Takenori {
2214c024bbdSKATO Takenori 	__asm __volatile("invd");
2224c024bbdSKATO Takenori }
2234c024bbdSKATO Takenori 
224664a31e4SPeter Wemm #if defined(SMP) && defined(_KERNEL)
225477a642cSPeter Wemm 
226477a642cSPeter Wemm /*
227f48bbd5fSBruce Evans  * When using APIC IPI's, invlpg() is not simply the invlpg instruction
228f48bbd5fSBruce Evans  * (this is a bug) and the inlining cost is prohibitive since the call
229f40e6078SPeter Wemm  * executes into the IPI transmission system.
230477a642cSPeter Wemm  */
231477a642cSPeter Wemm void	invlpg		__P((u_int addr));
232477a642cSPeter Wemm void	invltlb		__P((void));
233477a642cSPeter Wemm 
2345498a452SJohn Dyson static __inline void
2355498a452SJohn Dyson cpu_invlpg(void *addr)
2365498a452SJohn Dyson {
2375498a452SJohn Dyson 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
2385498a452SJohn Dyson }
2395498a452SJohn Dyson 
2405931a9c2STor Egge static __inline void
2415931a9c2STor Egge cpu_invltlb(void)
2425931a9c2STor Egge {
24300be8601SBruce Evans 	u_int	temp;
2445931a9c2STor Egge 	/*
2455931a9c2STor Egge 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
2465931a9c2STor Egge 	 * is inlined.
2475931a9c2STor Egge 	 */
2485931a9c2STor Egge 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
2495931a9c2STor Egge 			 : : "memory");
2505931a9c2STor Egge #if defined(SWTCH_OPTIM_STATS)
2515931a9c2STor Egge 	++tlb_flush_count;
2525931a9c2STor Egge #endif
2535931a9c2STor Egge }
254f48bbd5fSBruce Evans 
255664a31e4SPeter Wemm #else /* !(SMP && _KERNEL) */
256477a642cSPeter Wemm 
2574c024bbdSKATO Takenori static __inline void
258471176aaSJohn Dyson invlpg(u_int addr)
259ece15d78SBruce Evans {
2605498a452SJohn Dyson 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
261ece15d78SBruce Evans }
262ece15d78SBruce Evans 
263ece15d78SBruce Evans static __inline void
264ece15d78SBruce Evans invltlb(void)
265ece15d78SBruce Evans {
26600be8601SBruce Evans 	u_int	temp;
267ece15d78SBruce Evans 	/*
268ece15d78SBruce Evans 	 * This should be implemented as load_cr3(rcr3()) when load_cr3()
269ece15d78SBruce Evans 	 * is inlined.
270ece15d78SBruce Evans 	 */
271ece15d78SBruce Evans 	__asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp)
272ece15d78SBruce Evans 			 : : "memory");
273f48bbd5fSBruce Evans #ifdef SWTCH_OPTIM_STATS
27482566551SJohn Dyson 	++tlb_flush_count;
27582566551SJohn Dyson #endif
276ece15d78SBruce Evans }
2772c5d02ffSSteve Passe 
278664a31e4SPeter Wemm #endif /* SMP && _KERNEL */
279ece15d78SBruce Evans 
280004bedebSBruce Evans static __inline u_short
281004bedebSBruce Evans inw(u_int port)
282004bedebSBruce Evans {
283004bedebSBruce Evans 	u_short	data;
284004bedebSBruce Evans 
285004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
286004bedebSBruce Evans 	return (data);
287004bedebSBruce Evans }
288004bedebSBruce Evans 
289004bedebSBruce Evans static __inline void
290004bedebSBruce Evans outbv(u_int port, u_char data)
291004bedebSBruce Evans {
292004bedebSBruce Evans 	u_char	al;
293004bedebSBruce Evans 	/*
294004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
295004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
296004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
297004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
298004bedebSBruce Evans 	 */
299004bedebSBruce Evans 	al = data;
300004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
301004bedebSBruce Evans }
302004bedebSBruce Evans 
303004bedebSBruce Evans static __inline void
30400be8601SBruce Evans outl(u_int port, u_int data)
305004bedebSBruce Evans {
306004bedebSBruce Evans 	/*
307004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
308004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
309004bedebSBruce Evans 	 * assignment for them.
310004bedebSBruce Evans 	 */
311004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
312004bedebSBruce Evans }
313004bedebSBruce Evans 
314004bedebSBruce Evans static __inline void
315e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
316004bedebSBruce Evans {
317004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
318896763faSBruce Evans 			 : "=S" (addr), "=c" (cnt)
319896763faSBruce Evans 			 :  "0" (addr),  "1" (cnt), "d" (port));
320004bedebSBruce Evans }
321004bedebSBruce Evans 
322004bedebSBruce Evans static __inline void
323e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
324004bedebSBruce Evans {
325004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
326896763faSBruce Evans 			 : "=S" (addr), "=c" (cnt)
327896763faSBruce Evans 			 :  "0" (addr),  "1" (cnt), "d" (port));
328004bedebSBruce Evans }
329004bedebSBruce Evans 
330004bedebSBruce Evans static __inline void
331e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
332004bedebSBruce Evans {
333004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
334896763faSBruce Evans 			 : "=S" (addr), "=c" (cnt)
335896763faSBruce Evans 			 :  "0" (addr),  "1" (cnt), "d" (port));
336004bedebSBruce Evans }
337004bedebSBruce Evans 
338004bedebSBruce Evans static __inline void
339004bedebSBruce Evans outw(u_int port, u_short data)
340004bedebSBruce Evans {
341004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
342004bedebSBruce Evans }
343004bedebSBruce Evans 
34400be8601SBruce Evans static __inline u_int
345004bedebSBruce Evans rcr2(void)
346004bedebSBruce Evans {
34700be8601SBruce Evans 	u_int	data;
348004bedebSBruce Evans 
349004bedebSBruce Evans 	__asm __volatile("movl %%cr2,%0" : "=r" (data));
350004bedebSBruce Evans 	return (data);
351004bedebSBruce Evans }
352004bedebSBruce Evans 
35300be8601SBruce Evans static __inline u_int
354004bedebSBruce Evans read_eflags(void)
3555b81b6b3SRodney W. Grimes {
35600be8601SBruce Evans 	u_int	ef;
357004bedebSBruce Evans 
358004bedebSBruce Evans 	__asm __volatile("pushfl; popl %0" : "=r" (ef));
3598db02de8SPaul Richards 	return (ef);
3605b81b6b3SRodney W. Grimes }
3615b81b6b3SRodney W. Grimes 
36200be8601SBruce Evans static __inline u_int64_t
3635dbd168eSBruce Evans rdmsr(u_int msr)
3645dbd168eSBruce Evans {
36500be8601SBruce Evans 	u_int64_t rv;
3665dbd168eSBruce Evans 
36739413503SMark Murray 	__asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
3685dbd168eSBruce Evans 	return (rv);
3695dbd168eSBruce Evans }
3705dbd168eSBruce Evans 
37100be8601SBruce Evans static __inline u_int64_t
3725dbd168eSBruce Evans rdpmc(u_int pmc)
3735dbd168eSBruce Evans {
37400be8601SBruce Evans 	u_int64_t rv;
3755dbd168eSBruce Evans 
37639413503SMark Murray 	__asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
3775dbd168eSBruce Evans 	return (rv);
3785dbd168eSBruce Evans }
3795dbd168eSBruce Evans 
38000be8601SBruce Evans static __inline u_int64_t
3815dbd168eSBruce Evans rdtsc(void)
3825dbd168eSBruce Evans {
38300be8601SBruce Evans 	u_int64_t rv;
3845dbd168eSBruce Evans 
38539413503SMark Murray 	__asm __volatile("rdtsc" : "=A" (rv));
3865dbd168eSBruce Evans 	return (rv);
3875dbd168eSBruce Evans }
3885dbd168eSBruce Evans 
389004bedebSBruce Evans static __inline void
3904c024bbdSKATO Takenori wbinvd(void)
3914c024bbdSKATO Takenori {
3924c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3934c024bbdSKATO Takenori }
3944c024bbdSKATO Takenori 
3954c024bbdSKATO Takenori static __inline void
39600be8601SBruce Evans write_eflags(u_int ef)
3975b81b6b3SRodney W. Grimes {
398004bedebSBruce Evans 	__asm __volatile("pushl %0; popfl" : : "r" (ef));
3995b81b6b3SRodney W. Grimes }
4005b81b6b3SRodney W. Grimes 
401d69e8502SGarrett Wollman static __inline void
40200be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
403d69e8502SGarrett Wollman {
40439413503SMark Murray 	__asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
405d69e8502SGarrett Wollman }
406d69e8502SGarrett Wollman 
4075206bca1SLuoqi Chen static __inline u_int
4085206bca1SLuoqi Chen rfs(void)
4095206bca1SLuoqi Chen {
4105206bca1SLuoqi Chen 	u_int sel;
411e870e9b2SLuoqi Chen 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4125206bca1SLuoqi Chen 	return (sel);
4135206bca1SLuoqi Chen }
4145206bca1SLuoqi Chen 
4155206bca1SLuoqi Chen static __inline u_int
4165206bca1SLuoqi Chen rgs(void)
4175206bca1SLuoqi Chen {
4185206bca1SLuoqi Chen 	u_int sel;
419e870e9b2SLuoqi Chen 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4205206bca1SLuoqi Chen 	return (sel);
4215206bca1SLuoqi Chen }
4225206bca1SLuoqi Chen 
4235206bca1SLuoqi Chen static __inline void
4245206bca1SLuoqi Chen load_fs(u_int sel)
4255206bca1SLuoqi Chen {
426e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
4275206bca1SLuoqi Chen }
4285206bca1SLuoqi Chen 
4295206bca1SLuoqi Chen static __inline void
4305206bca1SLuoqi Chen load_gs(u_int sel)
4315206bca1SLuoqi Chen {
432e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
4335206bca1SLuoqi Chen }
4345206bca1SLuoqi Chen 
435de8050f9SBrian S. Dean static __inline u_int
436de8050f9SBrian S. Dean rdr0(void)
437de8050f9SBrian S. Dean {
438de8050f9SBrian S. Dean 	u_int	data;
43980275388SBrian S. Dean 	__asm __volatile("movl %%dr0,%0" : "=r" (data));
440de8050f9SBrian S. Dean 	return (data);
441de8050f9SBrian S. Dean }
442de8050f9SBrian S. Dean 
443de8050f9SBrian S. Dean static __inline u_int
444de8050f9SBrian S. Dean rdr1(void)
445de8050f9SBrian S. Dean {
446de8050f9SBrian S. Dean 	u_int	data;
44780275388SBrian S. Dean 	__asm __volatile("movl %%dr1,%0" : "=r" (data));
448de8050f9SBrian S. Dean 	return (data);
449de8050f9SBrian S. Dean }
450de8050f9SBrian S. Dean 
451de8050f9SBrian S. Dean static __inline u_int
452de8050f9SBrian S. Dean rdr2(void)
453de8050f9SBrian S. Dean {
454de8050f9SBrian S. Dean 	u_int	data;
45580275388SBrian S. Dean 	__asm __volatile("movl %%dr2,%0" : "=r" (data));
456de8050f9SBrian S. Dean 	return (data);
457de8050f9SBrian S. Dean }
458de8050f9SBrian S. Dean 
459de8050f9SBrian S. Dean static __inline u_int
460de8050f9SBrian S. Dean rdr3(void)
461de8050f9SBrian S. Dean {
462de8050f9SBrian S. Dean 	u_int	data;
46380275388SBrian S. Dean 	__asm __volatile("movl %%dr3,%0" : "=r" (data));
464de8050f9SBrian S. Dean 	return (data);
465de8050f9SBrian S. Dean }
466de8050f9SBrian S. Dean 
467de8050f9SBrian S. Dean static __inline u_int
468de8050f9SBrian S. Dean rdr6(void)
469de8050f9SBrian S. Dean {
470de8050f9SBrian S. Dean 	u_int	data;
47180275388SBrian S. Dean 	__asm __volatile("movl %%dr6,%0" : "=r" (data));
472de8050f9SBrian S. Dean 	return (data);
473de8050f9SBrian S. Dean }
474de8050f9SBrian S. Dean 
475de8050f9SBrian S. Dean static __inline u_int
476de8050f9SBrian S. Dean rdr7(void)
477de8050f9SBrian S. Dean {
478de8050f9SBrian S. Dean 	u_int	data;
47980275388SBrian S. Dean 	__asm __volatile("movl %%dr7,%0" : "=r" (data));
480de8050f9SBrian S. Dean 	return (data);
481de8050f9SBrian S. Dean }
482de8050f9SBrian S. Dean 
483034dc442SJohn Baldwin static __inline critical_t
484034dc442SJohn Baldwin critical_enter(void)
485034dc442SJohn Baldwin {
486034dc442SJohn Baldwin 	critical_t eflags;
487034dc442SJohn Baldwin 
488034dc442SJohn Baldwin 	eflags = read_eflags();
489034dc442SJohn Baldwin 	disable_intr();
490034dc442SJohn Baldwin 	return (eflags);
491034dc442SJohn Baldwin }
492034dc442SJohn Baldwin 
493034dc442SJohn Baldwin static __inline void
494034dc442SJohn Baldwin critical_exit(critical_t eflags)
495034dc442SJohn Baldwin {
496034dc442SJohn Baldwin 	write_eflags(eflags);
497034dc442SJohn Baldwin }
498034dc442SJohn Baldwin 
499004bedebSBruce Evans #else /* !__GNUC__ */
5005b81b6b3SRodney W. Grimes 
5015dbd168eSBruce Evans int	breakpoint	__P((void));
502c83b1328SBruce Evans u_int	bsfl		__P((u_int mask));
503c83b1328SBruce Evans u_int	bsrl		__P((u_int mask));
5045b81b6b3SRodney W. Grimes void	disable_intr	__P((void));
5055b81b6b3SRodney W. Grimes void	enable_intr	__P((void));
5065b81b6b3SRodney W. Grimes u_char	inb		__P((u_int port));
50700be8601SBruce Evans u_int	inl		__P((u_int port));
508004bedebSBruce Evans void	insb		__P((u_int port, void *addr, size_t cnt));
509004bedebSBruce Evans void	insl		__P((u_int port, void *addr, size_t cnt));
510004bedebSBruce Evans void	insw		__P((u_int port, void *addr, size_t cnt));
5114c024bbdSKATO Takenori void	invd		__P((void));
512ece15d78SBruce Evans void	invlpg		__P((u_int addr));
513ece15d78SBruce Evans void	invltlb		__P((void));
514004bedebSBruce Evans u_short	inw		__P((u_int port));
515004bedebSBruce Evans void	outb		__P((u_int port, u_char data));
51600be8601SBruce Evans void	outl		__P((u_int port, u_int data));
517004bedebSBruce Evans void	outsb		__P((u_int port, void *addr, size_t cnt));
518004bedebSBruce Evans void	outsl		__P((u_int port, void *addr, size_t cnt));
519004bedebSBruce Evans void	outsw		__P((u_int port, void *addr, size_t cnt));
520004bedebSBruce Evans void	outw		__P((u_int port, u_short data));
52100be8601SBruce Evans u_int	rcr2		__P((void));
52200be8601SBruce Evans u_int64_t rdmsr		__P((u_int msr));
52300be8601SBruce Evans u_int64_t rdpmc		__P((u_int pmc));
52400be8601SBruce Evans u_int64_t rdtsc		__P((void));
52500be8601SBruce Evans u_int	read_eflags	__P((void));
5264c024bbdSKATO Takenori void	wbinvd		__P((void));
52700be8601SBruce Evans void	write_eflags	__P((u_int ef));
52800be8601SBruce Evans void	wrmsr		__P((u_int msr, u_int64_t newval));
5295206bca1SLuoqi Chen u_int	rfs		__P((void));
5305206bca1SLuoqi Chen u_int	rgs		__P((void));
5315206bca1SLuoqi Chen void	load_fs		__P((u_int sel));
5325206bca1SLuoqi Chen void	load_gs		__P((u_int sel));
533034dc442SJohn Baldwin critical_t critical_enter __P((void));
534034dc442SJohn Baldwin void	critical_exit	__P((critical_t eflags));
535004bedebSBruce Evans 
5365b81b6b3SRodney W. Grimes #endif	/* __GNUC__ */
5375b81b6b3SRodney W. Grimes 
53800be8601SBruce Evans void	load_cr0	__P((u_int cr0));
53900be8601SBruce Evans void	load_cr3	__P((u_int cr3));
54000be8601SBruce Evans void	load_cr4	__P((u_int cr4));
541004bedebSBruce Evans void	ltr		__P((u_short sel));
542aaf08d94SGarrett Wollman u_int	rcr0		__P((void));
54300be8601SBruce Evans u_int	rcr3		__P((void));
54400be8601SBruce Evans u_int	rcr4		__P((void));
545de8050f9SBrian S. Dean void    load_dr6        __P((u_int dr6));
546de8050f9SBrian S. Dean void    reset_dbregs    __P((void));
5475b81b6b3SRodney W. Grimes 
548004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
549