xref: /freebsd/sys/amd64/include/cpufunc.h (revision a5f50ef9e43b28e15a7e2a2aec73754456619f17)
13c4dd356SDavid Greenman /*-
2fcfe57d6SPeter Wemm  * Copyright (c) 2003 Peter Wemm.
33c4dd356SDavid Greenman  * Copyright (c) 1993 The Regents of the University of California.
43c4dd356SDavid Greenman  * All rights reserved.
53c4dd356SDavid Greenman  *
63c4dd356SDavid Greenman  * Redistribution and use in source and binary forms, with or without
73c4dd356SDavid Greenman  * modification, are permitted provided that the following conditions
83c4dd356SDavid Greenman  * are met:
93c4dd356SDavid Greenman  * 1. Redistributions of source code must retain the above copyright
103c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer.
113c4dd356SDavid Greenman  * 2. Redistributions in binary form must reproduce the above copyright
123c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer in the
133c4dd356SDavid Greenman  *    documentation and/or other materials provided with the distribution.
143c4dd356SDavid Greenman  * 4. Neither the name of the University nor the names of its contributors
153c4dd356SDavid Greenman  *    may be used to endorse or promote products derived from this software
163c4dd356SDavid Greenman  *    without specific prior written permission.
173c4dd356SDavid Greenman  *
183c4dd356SDavid Greenman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
193c4dd356SDavid Greenman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
203c4dd356SDavid Greenman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
213c4dd356SDavid Greenman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
223c4dd356SDavid Greenman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
233c4dd356SDavid Greenman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
243c4dd356SDavid Greenman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
253c4dd356SDavid Greenman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
263c4dd356SDavid Greenman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
273c4dd356SDavid Greenman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
283c4dd356SDavid Greenman  * SUCH DAMAGE.
293c4dd356SDavid Greenman  *
30c3aac50fSPeter Wemm  * $FreeBSD$
313c4dd356SDavid Greenman  */
323c4dd356SDavid Greenman 
335b81b6b3SRodney W. Grimes /*
345b81b6b3SRodney W. Grimes  * Functions to provide access to special i386 instructions.
35f5d9a10bSMark Murray  * This in included in sys/systm.h, and that file should be
36f5d9a10bSMark Murray  * used in preference to this.
375b81b6b3SRodney W. Grimes  */
385b81b6b3SRodney W. Grimes 
396e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
40004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
416e393973SGarrett Wollman 
42a5f50ef9SJoerg Wunsch #ifndef _SYS_CDEFS_H_
43a5f50ef9SJoerg Wunsch #error this file needs sys/cdefs.h as a prerequisite
44a5f50ef9SJoerg Wunsch #endif
45a5f50ef9SJoerg Wunsch 
46eb1443c8SPeter Wemm struct region_descriptor;
47d74ac681SMatthew Dillon 
48e31fa854SDoug Rabson #define readb(va)	(*(volatile u_int8_t *) (va))
49e31fa854SDoug Rabson #define readw(va)	(*(volatile u_int16_t *) (va))
50e31fa854SDoug Rabson #define readl(va)	(*(volatile u_int32_t *) (va))
51afa88623SPeter Wemm #define readq(va)	(*(volatile u_int64_t *) (va))
52e31fa854SDoug Rabson 
53e31fa854SDoug Rabson #define writeb(va, d)	(*(volatile u_int8_t *) (va) = (d))
54e31fa854SDoug Rabson #define writew(va, d)	(*(volatile u_int16_t *) (va) = (d))
55e31fa854SDoug Rabson #define writel(va, d)	(*(volatile u_int32_t *) (va) = (d))
56afa88623SPeter Wemm #define writeq(va, d)	(*(volatile u_int64_t *) (va) = (d))
57e31fa854SDoug Rabson 
58a5f50ef9SJoerg Wunsch #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
595b81b6b3SRodney W. Grimes 
605dbd168eSBruce Evans static __inline void
615dbd168eSBruce Evans breakpoint(void)
62004bedebSBruce Evans {
63004bedebSBruce Evans 	__asm __volatile("int $3");
645b81b6b3SRodney W. Grimes }
655b81b6b3SRodney W. Grimes 
66c83b1328SBruce Evans static __inline u_int
67c83b1328SBruce Evans bsfl(u_int mask)
68c83b1328SBruce Evans {
69c83b1328SBruce Evans 	u_int	result;
70c83b1328SBruce Evans 
713f9a462fSJohn Baldwin 	__asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
72c83b1328SBruce Evans 	return (result);
73c83b1328SBruce Evans }
74c83b1328SBruce Evans 
75176ce2b1SPeter Wemm static __inline u_long
76176ce2b1SPeter Wemm bsfq(u_long mask)
77176ce2b1SPeter Wemm {
78176ce2b1SPeter Wemm 	u_long	result;
79176ce2b1SPeter Wemm 
80176ce2b1SPeter Wemm 	__asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask));
81176ce2b1SPeter Wemm 	return (result);
82176ce2b1SPeter Wemm }
83176ce2b1SPeter Wemm 
84c83b1328SBruce Evans static __inline u_int
85c83b1328SBruce Evans bsrl(u_int mask)
86c83b1328SBruce Evans {
87c83b1328SBruce Evans 	u_int	result;
88c83b1328SBruce Evans 
893f9a462fSJohn Baldwin 	__asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
90c83b1328SBruce Evans 	return (result);
91c83b1328SBruce Evans }
92c83b1328SBruce Evans 
93176ce2b1SPeter Wemm static __inline u_long
94176ce2b1SPeter Wemm bsrq(u_long mask)
95176ce2b1SPeter Wemm {
96176ce2b1SPeter Wemm 	u_long	result;
97176ce2b1SPeter Wemm 
98176ce2b1SPeter Wemm 	__asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask));
99176ce2b1SPeter Wemm 	return (result);
100176ce2b1SPeter Wemm }
101176ce2b1SPeter Wemm 
102004bedebSBruce Evans static __inline void
1035b81b6b3SRodney W. Grimes disable_intr(void)
1045b81b6b3SRodney W. Grimes {
1058966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
1065b81b6b3SRodney W. Grimes }
1075b81b6b3SRodney W. Grimes 
108004bedebSBruce Evans static __inline void
109a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
110a983fdfeSDavid Malone {
111a983fdfeSDavid Malone 	__asm __volatile("cpuid"
112a983fdfeSDavid Malone 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
113a983fdfeSDavid Malone 			 :  "0" (ax));
114a983fdfeSDavid Malone }
115a983fdfeSDavid Malone 
116a983fdfeSDavid Malone static __inline void
1175b81b6b3SRodney W. Grimes enable_intr(void)
1185b81b6b3SRodney W. Grimes {
119fadc51bdSBruce Evans 	__asm __volatile("sti");
1205b81b6b3SRodney W. Grimes }
1215b81b6b3SRodney W. Grimes 
122a67ef0a7SBruce Evans #ifdef _KERNEL
123a67ef0a7SBruce Evans 
124264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
125bc35f5dcSPaul Saab #define        ffs(x)  __builtin_ffs(x)
126176ce2b1SPeter Wemm 
127176ce2b1SPeter Wemm #define	HAVE_INLINE_FFSL
128176ce2b1SPeter Wemm 
129176ce2b1SPeter Wemm static __inline int
130176ce2b1SPeter Wemm ffsl(long mask)
131176ce2b1SPeter Wemm {
132176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1);
133004bedebSBruce Evans }
134004bedebSBruce Evans 
13513f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
13613f588f8SGarrett Wollman 
13713f588f8SGarrett Wollman static __inline int
13813f588f8SGarrett Wollman fls(int mask)
13913f588f8SGarrett Wollman {
1407e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
14113f588f8SGarrett Wollman }
14213f588f8SGarrett Wollman 
143176ce2b1SPeter Wemm #define	HAVE_INLINE_FLSL
144176ce2b1SPeter Wemm 
145176ce2b1SPeter Wemm static __inline int
146176ce2b1SPeter Wemm flsl(long mask)
147176ce2b1SPeter Wemm {
148176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
149176ce2b1SPeter Wemm }
150176ce2b1SPeter Wemm 
151a67ef0a7SBruce Evans #endif /* _KERNEL */
152a67ef0a7SBruce Evans 
153d7ee4425SMark Murray static __inline void
154d7ee4425SMark Murray halt(void)
155d7ee4425SMark Murray {
156d7ee4425SMark Murray 	__asm __volatile("hlt");
157d7ee4425SMark Murray }
158d7ee4425SMark Murray 
159a5f50ef9SJoerg Wunsch #if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3
160004bedebSBruce Evans 
161004bedebSBruce Evans #define	inb(port)		inbv(port)
162004bedebSBruce Evans #define	outb(port, data)	outbv(port, data)
163004bedebSBruce Evans 
164a5f50ef9SJoerg Wunsch #else /* __GNUCLIKE_BUILTIN_CONSTANT_P  && __GNUCLIKE_ASM >= 3 */
165004bedebSBruce Evans 
166004bedebSBruce Evans /*
1678089a043SBruce Evans  * The following complications are to get around gcc not having a
1688089a043SBruce Evans  * constraint letter for the range 0..255.  We still put "d" in the
1698089a043SBruce Evans  * constraint because "i" isn't a valid constraint when the port
1708089a043SBruce Evans  * isn't constant.  This only matters for -O0 because otherwise
1718089a043SBruce Evans  * the non-working version gets optimized away.
1728089a043SBruce Evans  *
173004bedebSBruce Evans  * Use an expression-statement instead of a conditional expression
174004bedebSBruce Evans  * because gcc-2.6.0 would promote the operands of the conditional
175004bedebSBruce Evans  * and produce poor code for "if ((inb(var) & const1) == const2)".
176388dfa71SBruce Evans  *
177388dfa71SBruce Evans  * The unnecessary test `(port) < 0x10000' is to generate a warning if
178388dfa71SBruce Evans  * the `port' has type u_short or smaller.  Such types are pessimal.
179388dfa71SBruce Evans  * This actually only works for signed types.  The range check is
180388dfa71SBruce Evans  * careful to avoid generating warnings.
181004bedebSBruce Evans  */
182388dfa71SBruce Evans #define	inb(port) __extension__ ({					\
183004bedebSBruce Evans 	u_char	_data;							\
184388dfa71SBruce Evans 	if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100	\
185388dfa71SBruce Evans 	    && (port) < 0x10000)					\
186004bedebSBruce Evans 		_data = inbc(port);					\
187004bedebSBruce Evans 	else								\
188004bedebSBruce Evans 		_data = inbv(port);					\
189004bedebSBruce Evans 	_data; })
190004bedebSBruce Evans 
191388dfa71SBruce Evans #define	outb(port, data) (						\
192388dfa71SBruce Evans 	__builtin_constant_p(port) && ((port) & 0xffff) < 0x100		\
193388dfa71SBruce Evans 	&& (port) < 0x10000						\
194004bedebSBruce Evans 	? outbc(port, data) : outbv(port, data))
195004bedebSBruce Evans 
196004bedebSBruce Evans static __inline u_char
197004bedebSBruce Evans inbc(u_int port)
198004bedebSBruce Evans {
199004bedebSBruce Evans 	u_char	data;
200004bedebSBruce Evans 
2018089a043SBruce Evans 	__asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
202004bedebSBruce Evans 	return (data);
203004bedebSBruce Evans }
204004bedebSBruce Evans 
205004bedebSBruce Evans static __inline void
206004bedebSBruce Evans outbc(u_int port, u_char data)
207004bedebSBruce Evans {
2088089a043SBruce Evans 	__asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
209004bedebSBruce Evans }
210004bedebSBruce Evans 
211a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_BUILTIN_CONSTANT_P */
212004bedebSBruce Evans 
213004bedebSBruce Evans static __inline u_char
214004bedebSBruce Evans inbv(u_int port)
215004bedebSBruce Evans {
216004bedebSBruce Evans 	u_char	data;
217004bedebSBruce Evans 	/*
218004bedebSBruce Evans 	 * We use %%dx and not %1 here because i/o is done at %dx and not at
219004bedebSBruce Evans 	 * %edx, while gcc generates inferior code (movw instead of movl)
220004bedebSBruce Evans 	 * if we tell it to load (u_short) port.
221004bedebSBruce Evans 	 */
222004bedebSBruce Evans 	__asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
223004bedebSBruce Evans 	return (data);
224004bedebSBruce Evans }
225004bedebSBruce Evans 
22600be8601SBruce Evans static __inline u_int
227004bedebSBruce Evans inl(u_int port)
228004bedebSBruce Evans {
22900be8601SBruce Evans 	u_int	data;
230004bedebSBruce Evans 
231004bedebSBruce Evans 	__asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
232004bedebSBruce Evans 	return (data);
233004bedebSBruce Evans }
234004bedebSBruce Evans 
235004bedebSBruce Evans static __inline void
236004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt)
237004bedebSBruce Evans {
238004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
2393f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2403f9a462fSJohn Baldwin 			 : "d" (port)
241896763faSBruce Evans 			 : "memory");
242004bedebSBruce Evans }
243004bedebSBruce Evans 
244004bedebSBruce Evans static __inline void
245004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt)
246004bedebSBruce Evans {
247004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
2483f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2493f9a462fSJohn Baldwin 			 : "d" (port)
250896763faSBruce Evans 			 : "memory");
251004bedebSBruce Evans }
252004bedebSBruce Evans 
253004bedebSBruce Evans static __inline void
254004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt)
255004bedebSBruce Evans {
256004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
2573f9a462fSJohn Baldwin 			 : "+D" (addr), "+c" (cnt)
2583f9a462fSJohn Baldwin 			 : "d" (port)
259896763faSBruce Evans 			 : "memory");
260004bedebSBruce Evans }
261004bedebSBruce Evans 
262ece15d78SBruce Evans static __inline void
2634c024bbdSKATO Takenori invd(void)
2644c024bbdSKATO Takenori {
2654c024bbdSKATO Takenori 	__asm __volatile("invd");
2664c024bbdSKATO Takenori }
2674c024bbdSKATO Takenori 
268004bedebSBruce Evans static __inline u_short
269004bedebSBruce Evans inw(u_int port)
270004bedebSBruce Evans {
271004bedebSBruce Evans 	u_short	data;
272004bedebSBruce Evans 
273004bedebSBruce Evans 	__asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
274004bedebSBruce Evans 	return (data);
275004bedebSBruce Evans }
276004bedebSBruce Evans 
277004bedebSBruce Evans static __inline void
278004bedebSBruce Evans outbv(u_int port, u_char data)
279004bedebSBruce Evans {
280004bedebSBruce Evans 	u_char	al;
281004bedebSBruce Evans 	/*
282004bedebSBruce Evans 	 * Use an unnecessary assignment to help gcc's register allocator.
283004bedebSBruce Evans 	 * This make a large difference for gcc-1.40 and a tiny difference
284004bedebSBruce Evans 	 * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
285004bedebSBruce Evans 	 * best results.  gcc-2.6.0 can't handle this.
286004bedebSBruce Evans 	 */
287004bedebSBruce Evans 	al = data;
288004bedebSBruce Evans 	__asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
289004bedebSBruce Evans }
290004bedebSBruce Evans 
291004bedebSBruce Evans static __inline void
29200be8601SBruce Evans outl(u_int port, u_int data)
293004bedebSBruce Evans {
294004bedebSBruce Evans 	/*
295004bedebSBruce Evans 	 * outl() and outw() aren't used much so we haven't looked at
296004bedebSBruce Evans 	 * possible micro-optimizations such as the unnecessary
297004bedebSBruce Evans 	 * assignment for them.
298004bedebSBruce Evans 	 */
299004bedebSBruce Evans 	__asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
300004bedebSBruce Evans }
301004bedebSBruce Evans 
302004bedebSBruce Evans static __inline void
303e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt)
304004bedebSBruce Evans {
305004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
3063f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3073f9a462fSJohn Baldwin 			 : "d" (port));
308004bedebSBruce Evans }
309004bedebSBruce Evans 
310004bedebSBruce Evans static __inline void
311e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt)
312004bedebSBruce Evans {
313004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
3143f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3153f9a462fSJohn Baldwin 			 : "d" (port));
316004bedebSBruce Evans }
317004bedebSBruce Evans 
318004bedebSBruce Evans static __inline void
319e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt)
320004bedebSBruce Evans {
321004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
3223f9a462fSJohn Baldwin 			 : "+S" (addr), "+c" (cnt)
3233f9a462fSJohn Baldwin 			 : "d" (port));
324004bedebSBruce Evans }
325004bedebSBruce Evans 
326004bedebSBruce Evans static __inline void
327004bedebSBruce Evans outw(u_int port, u_short data)
328004bedebSBruce Evans {
329004bedebSBruce Evans 	__asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
330004bedebSBruce Evans }
331004bedebSBruce Evans 
3322be69f32SJohn Baldwin static __inline void
3336b8c6989SJohn Baldwin ia32_pause(void)
3342be69f32SJohn Baldwin {
3352be69f32SJohn Baldwin 	__asm __volatile("pause");
3362be69f32SJohn Baldwin }
3372be69f32SJohn Baldwin 
338afa88623SPeter Wemm static __inline u_long
339afa88623SPeter Wemm read_rflags(void)
3405b81b6b3SRodney W. Grimes {
341afa88623SPeter Wemm 	u_long	rf;
342004bedebSBruce Evans 
343afa88623SPeter Wemm 	__asm __volatile("pushfq; popq %0" : "=r" (rf));
344afa88623SPeter Wemm 	return (rf);
3455b81b6b3SRodney W. Grimes }
3465b81b6b3SRodney W. Grimes 
34700be8601SBruce Evans static __inline u_int64_t
3485dbd168eSBruce Evans rdmsr(u_int msr)
3495dbd168eSBruce Evans {
350afa88623SPeter Wemm 	u_int32_t low, high;
3515dbd168eSBruce Evans 
352afa88623SPeter Wemm 	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
353afa88623SPeter Wemm 	return (low | ((u_int64_t)high << 32));
3545dbd168eSBruce Evans }
3555dbd168eSBruce Evans 
35600be8601SBruce Evans static __inline u_int64_t
3575dbd168eSBruce Evans rdpmc(u_int pmc)
3585dbd168eSBruce Evans {
359afa88623SPeter Wemm 	u_int32_t low, high;
3605dbd168eSBruce Evans 
361afa88623SPeter Wemm 	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
362afa88623SPeter Wemm 	return (low | ((u_int64_t)high << 32));
3635dbd168eSBruce Evans }
3645dbd168eSBruce Evans 
36500be8601SBruce Evans static __inline u_int64_t
3665dbd168eSBruce Evans rdtsc(void)
3675dbd168eSBruce Evans {
368afa88623SPeter Wemm 	u_int32_t low, high;
3695dbd168eSBruce Evans 
370afa88623SPeter Wemm 	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
371afa88623SPeter Wemm 	return (low | ((u_int64_t)high << 32));
3725dbd168eSBruce Evans }
3735dbd168eSBruce Evans 
374004bedebSBruce Evans static __inline void
3754c024bbdSKATO Takenori wbinvd(void)
3764c024bbdSKATO Takenori {
3774c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3784c024bbdSKATO Takenori }
3794c024bbdSKATO Takenori 
3804c024bbdSKATO Takenori static __inline void
381afa88623SPeter Wemm write_rflags(u_long rf)
3825b81b6b3SRodney W. Grimes {
383afa88623SPeter Wemm 	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
3845b81b6b3SRodney W. Grimes }
3855b81b6b3SRodney W. Grimes 
386d69e8502SGarrett Wollman static __inline void
38700be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval)
388d69e8502SGarrett Wollman {
389afa88623SPeter Wemm 	u_int32_t low, high;
390afa88623SPeter Wemm 
391afa88623SPeter Wemm 	low = newval;
392afa88623SPeter Wemm 	high = newval >> 32;
393afa88623SPeter Wemm 	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
394d69e8502SGarrett Wollman }
395d69e8502SGarrett Wollman 
396f1b665c8SPeter Wemm static __inline void
397afa88623SPeter Wemm load_cr0(u_long data)
398f1b665c8SPeter Wemm {
399f1b665c8SPeter Wemm 
400afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr0" : : "r" (data));
401f1b665c8SPeter Wemm }
402f1b665c8SPeter Wemm 
403afa88623SPeter Wemm static __inline u_long
404f1b665c8SPeter Wemm rcr0(void)
405f1b665c8SPeter Wemm {
406afa88623SPeter Wemm 	u_long	data;
407f1b665c8SPeter Wemm 
408afa88623SPeter Wemm 	__asm __volatile("movq %%cr0,%0" : "=r" (data));
409f1b665c8SPeter Wemm 	return (data);
410f1b665c8SPeter Wemm }
411f1b665c8SPeter Wemm 
412afa88623SPeter Wemm static __inline u_long
413f1b665c8SPeter Wemm rcr2(void)
414f1b665c8SPeter Wemm {
415afa88623SPeter Wemm 	u_long	data;
416f1b665c8SPeter Wemm 
417afa88623SPeter Wemm 	__asm __volatile("movq %%cr2,%0" : "=r" (data));
418f1b665c8SPeter Wemm 	return (data);
419f1b665c8SPeter Wemm }
420f1b665c8SPeter Wemm 
421f1b665c8SPeter Wemm static __inline void
422afa88623SPeter Wemm load_cr3(u_long data)
423f1b665c8SPeter Wemm {
424f1b665c8SPeter Wemm 
425afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
426f1b665c8SPeter Wemm }
427f1b665c8SPeter Wemm 
428afa88623SPeter Wemm static __inline u_long
429f1b665c8SPeter Wemm rcr3(void)
430f1b665c8SPeter Wemm {
431afa88623SPeter Wemm 	u_long	data;
432f1b665c8SPeter Wemm 
433afa88623SPeter Wemm 	__asm __volatile("movq %%cr3,%0" : "=r" (data));
434f1b665c8SPeter Wemm 	return (data);
435f1b665c8SPeter Wemm }
436f1b665c8SPeter Wemm 
437f1b665c8SPeter Wemm static __inline void
438afa88623SPeter Wemm load_cr4(u_long data)
439f1b665c8SPeter Wemm {
440afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr4" : : "r" (data));
441f1b665c8SPeter Wemm }
442f1b665c8SPeter Wemm 
443afa88623SPeter Wemm static __inline u_long
444f1b665c8SPeter Wemm rcr4(void)
445f1b665c8SPeter Wemm {
446afa88623SPeter Wemm 	u_long	data;
447f1b665c8SPeter Wemm 
448afa88623SPeter Wemm 	__asm __volatile("movq %%cr4,%0" : "=r" (data));
449f1b665c8SPeter Wemm 	return (data);
450f1b665c8SPeter Wemm }
451f1b665c8SPeter Wemm 
452f1b665c8SPeter Wemm /*
453f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
454f1b665c8SPeter Wemm  */
455f1b665c8SPeter Wemm static __inline void
456f1b665c8SPeter Wemm invltlb(void)
457f1b665c8SPeter Wemm {
458f1b665c8SPeter Wemm 
459f1b665c8SPeter Wemm 	load_cr3(rcr3());
460f1b665c8SPeter Wemm }
461f1b665c8SPeter Wemm 
462f1b665c8SPeter Wemm /*
463f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
464f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
465f1b665c8SPeter Wemm  */
466f1b665c8SPeter Wemm static __inline void
467afa88623SPeter Wemm invlpg(u_long addr)
468f1b665c8SPeter Wemm {
469f1b665c8SPeter Wemm 
470f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
471f1b665c8SPeter Wemm }
472f1b665c8SPeter Wemm 
4735206bca1SLuoqi Chen static __inline u_int
4745206bca1SLuoqi Chen rfs(void)
4755206bca1SLuoqi Chen {
476d1fc2022SDavid Xu 	u_int sel;
477d1fc2022SDavid Xu 	__asm __volatile("movl %%fs,%0" : "=rm" (sel));
4785206bca1SLuoqi Chen 	return (sel);
4795206bca1SLuoqi Chen }
4805206bca1SLuoqi Chen 
4815206bca1SLuoqi Chen static __inline u_int
4825206bca1SLuoqi Chen rgs(void)
4835206bca1SLuoqi Chen {
484d1fc2022SDavid Xu 	u_int sel;
485d1fc2022SDavid Xu 	__asm __volatile("movl %%gs,%0" : "=rm" (sel));
4865206bca1SLuoqi Chen 	return (sel);
4875206bca1SLuoqi Chen }
4885206bca1SLuoqi Chen 
489cd0149e3SPeter Wemm static __inline u_int
490cd0149e3SPeter Wemm rss(void)
491cd0149e3SPeter Wemm {
492cd0149e3SPeter Wemm 	u_int sel;
493cd0149e3SPeter Wemm 	__asm __volatile("movl %%ss,%0" : "=rm" (sel));
494cd0149e3SPeter Wemm 	return (sel);
495cd0149e3SPeter Wemm }
496cd0149e3SPeter Wemm 
4975206bca1SLuoqi Chen static __inline void
498d85631c4SPeter Wemm load_ds(u_int sel)
499d85631c4SPeter Wemm {
500d85631c4SPeter Wemm 	__asm __volatile("movl %0,%%ds" : : "rm" (sel));
501d85631c4SPeter Wemm }
502d85631c4SPeter Wemm 
503d85631c4SPeter Wemm static __inline void
504d85631c4SPeter Wemm load_es(u_int sel)
505d85631c4SPeter Wemm {
506d85631c4SPeter Wemm 	__asm __volatile("movl %0,%%es" : : "rm" (sel));
507d85631c4SPeter Wemm }
508d85631c4SPeter Wemm 
509c0a54ff6SPeter Wemm #ifdef _KERNEL
510c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */
511c0a54ff6SPeter Wemm #ifndef	MSR_FSBASE
512c0a54ff6SPeter Wemm #define	MSR_FSBASE	0xc0000100
513c0a54ff6SPeter Wemm #endif
514c0a54ff6SPeter Wemm static __inline void
515c0a54ff6SPeter Wemm load_fs(u_int sel)
516c0a54ff6SPeter Wemm {
517c0a54ff6SPeter Wemm 	register u_int32_t fsbase __asm("ecx");
518c0a54ff6SPeter Wemm 
519c0a54ff6SPeter Wemm 	/* Preserve the fsbase value across the selector load */
520c0a54ff6SPeter Wemm 	fsbase = MSR_FSBASE;
521c0a54ff6SPeter Wemm         __asm __volatile("rdmsr; movl %0,%%fs; wrmsr"
522c0a54ff6SPeter Wemm             : : "rm" (sel), "c" (fsbase) : "eax", "edx");
523c0a54ff6SPeter Wemm }
524c0a54ff6SPeter Wemm 
525c0a54ff6SPeter Wemm #ifndef	MSR_GSBASE
526c0a54ff6SPeter Wemm #define	MSR_GSBASE	0xc0000101
527c0a54ff6SPeter Wemm #endif
528c0a54ff6SPeter Wemm static __inline void
529c0a54ff6SPeter Wemm load_gs(u_int sel)
530c0a54ff6SPeter Wemm {
531c0a54ff6SPeter Wemm 	register u_int32_t gsbase __asm("ecx");
532c0a54ff6SPeter Wemm 
533c0a54ff6SPeter Wemm 	/*
534c0a54ff6SPeter Wemm 	 * Preserve the gsbase value across the selector load.
535c0a54ff6SPeter Wemm 	 * Note that we have to disable interrupts because the gsbase
536c0a54ff6SPeter Wemm 	 * being trashed happens to be the kernel gsbase at the time.
537c0a54ff6SPeter Wemm 	 */
538c0a54ff6SPeter Wemm 	gsbase = MSR_GSBASE;
539c0a54ff6SPeter Wemm         __asm __volatile("pushfq; cli; rdmsr; movl %0,%%gs; wrmsr; popfq"
540c0a54ff6SPeter Wemm             : : "rm" (sel), "c" (gsbase) : "eax", "edx");
541c0a54ff6SPeter Wemm }
542c0a54ff6SPeter Wemm #else
543c0a54ff6SPeter Wemm /* Usable by userland */
544d85631c4SPeter Wemm static __inline void
5455206bca1SLuoqi Chen load_fs(u_int sel)
5465206bca1SLuoqi Chen {
547e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%fs" : : "rm" (sel));
5485206bca1SLuoqi Chen }
5495206bca1SLuoqi Chen 
5505206bca1SLuoqi Chen static __inline void
5515206bca1SLuoqi Chen load_gs(u_int sel)
5525206bca1SLuoqi Chen {
553e870e9b2SLuoqi Chen 	__asm __volatile("movl %0,%%gs" : : "rm" (sel));
5545206bca1SLuoqi Chen }
555c0a54ff6SPeter Wemm #endif
5565206bca1SLuoqi Chen 
557eb1443c8SPeter Wemm static __inline void
558eb1443c8SPeter Wemm lidt(struct region_descriptor *addr)
559eb1443c8SPeter Wemm {
560eb1443c8SPeter Wemm 	__asm __volatile("lidt (%0)" : : "r" (addr));
561eb1443c8SPeter Wemm }
562eb1443c8SPeter Wemm 
563eb1443c8SPeter Wemm static __inline void
564eb1443c8SPeter Wemm lldt(u_short sel)
565eb1443c8SPeter Wemm {
566eb1443c8SPeter Wemm 	__asm __volatile("lldt %0" : : "r" (sel));
567eb1443c8SPeter Wemm }
568eb1443c8SPeter Wemm 
569eb1443c8SPeter Wemm static __inline void
570eb1443c8SPeter Wemm ltr(u_short sel)
571eb1443c8SPeter Wemm {
572eb1443c8SPeter Wemm 	__asm __volatile("ltr %0" : : "r" (sel));
573eb1443c8SPeter Wemm }
574eb1443c8SPeter Wemm 
5751182b177SPeter Wemm static __inline u_int64_t
5761182b177SPeter Wemm rdr0(void)
5771182b177SPeter Wemm {
5781182b177SPeter Wemm 	u_int64_t data;
5791182b177SPeter Wemm 	__asm __volatile("movq %%dr0,%0" : "=r" (data));
5801182b177SPeter Wemm 	return (data);
5811182b177SPeter Wemm }
5821182b177SPeter Wemm 
5831182b177SPeter Wemm static __inline void
5841182b177SPeter Wemm load_dr0(u_int64_t dr0)
5851182b177SPeter Wemm {
5861182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
5871182b177SPeter Wemm }
5881182b177SPeter Wemm 
5891182b177SPeter Wemm static __inline u_int64_t
5901182b177SPeter Wemm rdr1(void)
5911182b177SPeter Wemm {
5921182b177SPeter Wemm 	u_int64_t data;
5931182b177SPeter Wemm 	__asm __volatile("movq %%dr1,%0" : "=r" (data));
5941182b177SPeter Wemm 	return (data);
5951182b177SPeter Wemm }
5961182b177SPeter Wemm 
5971182b177SPeter Wemm static __inline void
5981182b177SPeter Wemm load_dr1(u_int64_t dr1)
5991182b177SPeter Wemm {
6001182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
6011182b177SPeter Wemm }
6021182b177SPeter Wemm 
6031182b177SPeter Wemm static __inline u_int64_t
6041182b177SPeter Wemm rdr2(void)
6051182b177SPeter Wemm {
6061182b177SPeter Wemm 	u_int64_t data;
6071182b177SPeter Wemm 	__asm __volatile("movq %%dr2,%0" : "=r" (data));
6081182b177SPeter Wemm 	return (data);
6091182b177SPeter Wemm }
6101182b177SPeter Wemm 
6111182b177SPeter Wemm static __inline void
6121182b177SPeter Wemm load_dr2(u_int64_t dr2)
6131182b177SPeter Wemm {
6141182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
6151182b177SPeter Wemm }
6161182b177SPeter Wemm 
6171182b177SPeter Wemm static __inline u_int64_t
6181182b177SPeter Wemm rdr3(void)
6191182b177SPeter Wemm {
6201182b177SPeter Wemm 	u_int64_t data;
6211182b177SPeter Wemm 	__asm __volatile("movq %%dr3,%0" : "=r" (data));
6221182b177SPeter Wemm 	return (data);
6231182b177SPeter Wemm }
6241182b177SPeter Wemm 
6251182b177SPeter Wemm static __inline void
6261182b177SPeter Wemm load_dr3(u_int64_t dr3)
6271182b177SPeter Wemm {
6281182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
6291182b177SPeter Wemm }
6301182b177SPeter Wemm 
6311182b177SPeter Wemm static __inline u_int64_t
6321182b177SPeter Wemm rdr4(void)
6331182b177SPeter Wemm {
6341182b177SPeter Wemm 	u_int64_t data;
6351182b177SPeter Wemm 	__asm __volatile("movq %%dr4,%0" : "=r" (data));
6361182b177SPeter Wemm 	return (data);
6371182b177SPeter Wemm }
6381182b177SPeter Wemm 
6391182b177SPeter Wemm static __inline void
6401182b177SPeter Wemm load_dr4(u_int64_t dr4)
6411182b177SPeter Wemm {
6421182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr4" : : "r" (dr4));
6431182b177SPeter Wemm }
6441182b177SPeter Wemm 
6451182b177SPeter Wemm static __inline u_int64_t
6461182b177SPeter Wemm rdr5(void)
6471182b177SPeter Wemm {
6481182b177SPeter Wemm 	u_int64_t data;
6491182b177SPeter Wemm 	__asm __volatile("movq %%dr5,%0" : "=r" (data));
6501182b177SPeter Wemm 	return (data);
6511182b177SPeter Wemm }
6521182b177SPeter Wemm 
6531182b177SPeter Wemm static __inline void
6541182b177SPeter Wemm load_dr5(u_int64_t dr5)
6551182b177SPeter Wemm {
6561182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr5" : : "r" (dr5));
6571182b177SPeter Wemm }
6581182b177SPeter Wemm 
6591182b177SPeter Wemm static __inline u_int64_t
6601182b177SPeter Wemm rdr6(void)
6611182b177SPeter Wemm {
6621182b177SPeter Wemm 	u_int64_t data;
6631182b177SPeter Wemm 	__asm __volatile("movq %%dr6,%0" : "=r" (data));
6641182b177SPeter Wemm 	return (data);
6651182b177SPeter Wemm }
6661182b177SPeter Wemm 
6671182b177SPeter Wemm static __inline void
6681182b177SPeter Wemm load_dr6(u_int64_t dr6)
6691182b177SPeter Wemm {
6701182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
6711182b177SPeter Wemm }
6721182b177SPeter Wemm 
6731182b177SPeter Wemm static __inline u_int64_t
6741182b177SPeter Wemm rdr7(void)
6751182b177SPeter Wemm {
6761182b177SPeter Wemm 	u_int64_t data;
6771182b177SPeter Wemm 	__asm __volatile("movq %%dr7,%0" : "=r" (data));
6781182b177SPeter Wemm 	return (data);
6791182b177SPeter Wemm }
6801182b177SPeter Wemm 
6811182b177SPeter Wemm static __inline void
6821182b177SPeter Wemm load_dr7(u_int64_t dr7)
6831182b177SPeter Wemm {
6841182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
6851182b177SPeter Wemm }
6861182b177SPeter Wemm 
687ba74981eSWarner Losh static __inline register_t
688ba74981eSWarner Losh intr_disable(void)
689ba74981eSWarner Losh {
690afa88623SPeter Wemm 	register_t rflags;
691ba74981eSWarner Losh 
692afa88623SPeter Wemm 	rflags = read_rflags();
693ba74981eSWarner Losh 	disable_intr();
694afa88623SPeter Wemm 	return (rflags);
695ba74981eSWarner Losh }
696ba74981eSWarner Losh 
697ba74981eSWarner Losh static __inline void
698afa88623SPeter Wemm intr_restore(register_t rflags)
699ba74981eSWarner Losh {
700afa88623SPeter Wemm 	write_rflags(rflags);
701ba74981eSWarner Losh }
702ba74981eSWarner Losh 
703a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
7045b81b6b3SRodney W. Grimes 
705b63dc6adSAlfred Perlstein int	breakpoint(void);
706b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
707b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
708b63dc6adSAlfred Perlstein void	disable_intr(void);
709b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
710b63dc6adSAlfred Perlstein void	enable_intr(void);
711d7ee4425SMark Murray void	halt(void);
7124f6c19e5SPeter Wemm void	ia32_pause(void);
713b63dc6adSAlfred Perlstein u_char	inb(u_int port);
714b63dc6adSAlfred Perlstein u_int	inl(u_int port);
715b63dc6adSAlfred Perlstein void	insb(u_int port, void *addr, size_t cnt);
716b63dc6adSAlfred Perlstein void	insl(u_int port, void *addr, size_t cnt);
717b63dc6adSAlfred Perlstein void	insw(u_int port, void *addr, size_t cnt);
7184f6c19e5SPeter Wemm register_t	intr_disable(void);
7194f6c19e5SPeter Wemm void	intr_restore(register_t rf);
720b63dc6adSAlfred Perlstein void	invd(void);
721b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
722b63dc6adSAlfred Perlstein void	invltlb(void);
723b63dc6adSAlfred Perlstein u_short	inw(u_int port);
724eb1443c8SPeter Wemm void	lidt(struct region_descriptor *addr);
725eb1443c8SPeter Wemm void	lldt(u_short sel);
7264f6c19e5SPeter Wemm void	load_cr0(u_long cr0);
7274f6c19e5SPeter Wemm void	load_cr3(u_long cr3);
7284f6c19e5SPeter Wemm void	load_cr4(u_long cr4);
7294f6c19e5SPeter Wemm void	load_dr0(u_int64_t dr0);
7304f6c19e5SPeter Wemm void	load_dr1(u_int64_t dr1);
7314f6c19e5SPeter Wemm void	load_dr2(u_int64_t dr2);
7324f6c19e5SPeter Wemm void	load_dr3(u_int64_t dr3);
7334f6c19e5SPeter Wemm void	load_dr4(u_int64_t dr4);
7344f6c19e5SPeter Wemm void	load_dr5(u_int64_t dr5);
7354f6c19e5SPeter Wemm void	load_dr6(u_int64_t dr6);
7364f6c19e5SPeter Wemm void	load_dr7(u_int64_t dr7);
7374f6c19e5SPeter Wemm void	load_fs(u_int sel);
7384f6c19e5SPeter Wemm void	load_gs(u_int sel);
739eb1443c8SPeter Wemm void	ltr(u_short sel);
740b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
741b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
7421bcf24eeSLukas Ertl void	outsb(u_int port, const void *addr, size_t cnt);
7431bcf24eeSLukas Ertl void	outsl(u_int port, const void *addr, size_t cnt);
7441bcf24eeSLukas Ertl void	outsw(u_int port, const void *addr, size_t cnt);
745b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
7464f6c19e5SPeter Wemm u_long	rcr0(void);
7474f6c19e5SPeter Wemm u_long	rcr2(void);
7484f6c19e5SPeter Wemm u_long	rcr3(void);
7494f6c19e5SPeter Wemm u_long	rcr4(void);
750b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr);
751b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc);
7524f6c19e5SPeter Wemm u_int64_t rdr0(void);
7534f6c19e5SPeter Wemm u_int64_t rdr1(void);
7544f6c19e5SPeter Wemm u_int64_t rdr2(void);
7554f6c19e5SPeter Wemm u_int64_t rdr3(void);
7564f6c19e5SPeter Wemm u_int64_t rdr4(void);
7574f6c19e5SPeter Wemm u_int64_t rdr5(void);
7584f6c19e5SPeter Wemm u_int64_t rdr6(void);
7594f6c19e5SPeter Wemm u_int64_t rdr7(void);
760b63dc6adSAlfred Perlstein u_int64_t rdtsc(void);
761afa88623SPeter Wemm u_int	read_rflags(void);
7624f6c19e5SPeter Wemm u_int	rfs(void);
7634f6c19e5SPeter Wemm u_int	rgs(void);
764b63dc6adSAlfred Perlstein void	wbinvd(void);
765afa88623SPeter Wemm void	write_rflags(u_int rf);
766b63dc6adSAlfred Perlstein void	wrmsr(u_int msr, u_int64_t newval);
767004bedebSBruce Evans 
768a5f50ef9SJoerg Wunsch #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
7695b81b6b3SRodney W. Grimes 
770b63dc6adSAlfred Perlstein void	reset_dbregs(void);
771d74ac681SMatthew Dillon 
772004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
773