xref: /freebsd/sys/amd64/include/cpufunc.h (revision 0fd7ea1f218d56021257cbeba9908c77ff9d3ff7)
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.
14fbbd9655SWarner Losh  * 3. 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 
48f5ac47f4SJung-uk Kim #define readb(va)	(*(volatile uint8_t *) (va))
49f5ac47f4SJung-uk Kim #define readw(va)	(*(volatile uint16_t *) (va))
50f5ac47f4SJung-uk Kim #define readl(va)	(*(volatile uint32_t *) (va))
51f5ac47f4SJung-uk Kim #define readq(va)	(*(volatile uint64_t *) (va))
52e31fa854SDoug Rabson 
53f5ac47f4SJung-uk Kim #define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
54f5ac47f4SJung-uk Kim #define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
55f5ac47f4SJung-uk Kim #define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
56f5ac47f4SJung-uk Kim #define writeq(va, d)	(*(volatile uint64_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 
666f240e18SConrad Meyer static __inline __pure2 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 
756f240e18SConrad Meyer static __inline __pure2 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 
846f240e18SConrad Meyer static __inline __pure2 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 
936f240e18SConrad Meyer static __inline __pure2 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
103206a3368SKonstantin Belousov clflush(u_long addr)
104206a3368SKonstantin Belousov {
105206a3368SKonstantin Belousov 
106206a3368SKonstantin Belousov 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
107206a3368SKonstantin Belousov }
108206a3368SKonstantin Belousov 
109206a3368SKonstantin Belousov static __inline void
1103f8e0710SKonstantin Belousov clflushopt(u_long addr)
1113f8e0710SKonstantin Belousov {
1123f8e0710SKonstantin Belousov 
1133f8e0710SKonstantin Belousov 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
1143f8e0710SKonstantin Belousov }
1153f8e0710SKonstantin Belousov 
1163f8e0710SKonstantin Belousov static __inline void
117d706ec29SJohn Baldwin clts(void)
118d706ec29SJohn Baldwin {
119d706ec29SJohn Baldwin 
120d706ec29SJohn Baldwin 	__asm __volatile("clts");
121d706ec29SJohn Baldwin }
122d706ec29SJohn Baldwin 
123d706ec29SJohn Baldwin static __inline void
1245b81b6b3SRodney W. Grimes disable_intr(void)
1255b81b6b3SRodney W. Grimes {
1268966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
1275b81b6b3SRodney W. Grimes }
1285b81b6b3SRodney W. Grimes 
129004bedebSBruce Evans static __inline void
130a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
131a983fdfeSDavid Malone {
132a983fdfeSDavid Malone 	__asm __volatile("cpuid"
133a983fdfeSDavid Malone 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
134a983fdfeSDavid Malone 			 :  "0" (ax));
135a983fdfeSDavid Malone }
136a983fdfeSDavid Malone 
137a983fdfeSDavid Malone static __inline void
138f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p)
139f6108b61SJacques Vidrine {
140f6108b61SJacques Vidrine 	__asm __volatile("cpuid"
141f6108b61SJacques Vidrine 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
142f6108b61SJacques Vidrine 			 :  "0" (ax), "c" (cx));
143f6108b61SJacques Vidrine }
144f6108b61SJacques Vidrine 
145f6108b61SJacques Vidrine static __inline void
1465b81b6b3SRodney W. Grimes enable_intr(void)
1475b81b6b3SRodney W. Grimes {
148fadc51bdSBruce Evans 	__asm __volatile("sti");
1495b81b6b3SRodney W. Grimes }
1505b81b6b3SRodney W. Grimes 
151a67ef0a7SBruce Evans #ifdef _KERNEL
152a67ef0a7SBruce Evans 
153264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
154bc35f5dcSPaul Saab #define        ffs(x)  __builtin_ffs(x)
155176ce2b1SPeter Wemm 
156176ce2b1SPeter Wemm #define	HAVE_INLINE_FFSL
157176ce2b1SPeter Wemm 
1586f240e18SConrad Meyer static __inline __pure2 int
159176ce2b1SPeter Wemm ffsl(long mask)
160176ce2b1SPeter Wemm {
161176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1);
162004bedebSBruce Evans }
163004bedebSBruce Evans 
164f25e50cfSAndriy Gapon #define	HAVE_INLINE_FFSLL
165f25e50cfSAndriy Gapon 
1666f240e18SConrad Meyer static __inline __pure2 int
167f25e50cfSAndriy Gapon ffsll(long long mask)
168f25e50cfSAndriy Gapon {
169f25e50cfSAndriy Gapon 	return (ffsl((long)mask));
170f25e50cfSAndriy Gapon }
171f25e50cfSAndriy Gapon 
17213f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
17313f588f8SGarrett Wollman 
1746f240e18SConrad Meyer static __inline __pure2 int
17513f588f8SGarrett Wollman fls(int mask)
17613f588f8SGarrett Wollman {
1777e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
17813f588f8SGarrett Wollman }
17913f588f8SGarrett Wollman 
180176ce2b1SPeter Wemm #define	HAVE_INLINE_FLSL
181176ce2b1SPeter Wemm 
1826f240e18SConrad Meyer static __inline __pure2 int
183176ce2b1SPeter Wemm flsl(long mask)
184176ce2b1SPeter Wemm {
185176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
186176ce2b1SPeter Wemm }
187176ce2b1SPeter Wemm 
188f25e50cfSAndriy Gapon #define	HAVE_INLINE_FLSLL
189f25e50cfSAndriy Gapon 
1906f240e18SConrad Meyer static __inline __pure2 int
191f25e50cfSAndriy Gapon flsll(long long mask)
192f25e50cfSAndriy Gapon {
193f25e50cfSAndriy Gapon 	return (flsl((long)mask));
194f25e50cfSAndriy Gapon }
195f25e50cfSAndriy Gapon 
196a67ef0a7SBruce Evans #endif /* _KERNEL */
197a67ef0a7SBruce Evans 
198d7ee4425SMark Murray static __inline void
199d7ee4425SMark Murray halt(void)
200d7ee4425SMark Murray {
201d7ee4425SMark Murray 	__asm __volatile("hlt");
202d7ee4425SMark Murray }
203d7ee4425SMark Murray 
204004bedebSBruce Evans static __inline u_char
205e1048f76SEd Schouten inb(u_int port)
206004bedebSBruce Evans {
207004bedebSBruce Evans 	u_char	data;
208004bedebSBruce Evans 
2094854ae24SJung-uk Kim 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
210004bedebSBruce Evans 	return (data);
211004bedebSBruce Evans }
212004bedebSBruce Evans 
21300be8601SBruce Evans static __inline u_int
214004bedebSBruce Evans inl(u_int port)
215004bedebSBruce Evans {
21600be8601SBruce Evans 	u_int	data;
217004bedebSBruce Evans 
2184854ae24SJung-uk Kim 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
219004bedebSBruce Evans 	return (data);
220004bedebSBruce Evans }
221004bedebSBruce Evans 
222004bedebSBruce Evans static __inline void
22393d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count)
224004bedebSBruce Evans {
225004bedebSBruce Evans 	__asm __volatile("cld; rep; insb"
22693d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2273f9a462fSJohn Baldwin 			 : "d" (port)
228896763faSBruce Evans 			 : "memory");
229004bedebSBruce Evans }
230004bedebSBruce Evans 
231004bedebSBruce Evans static __inline void
23293d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count)
233004bedebSBruce Evans {
234004bedebSBruce Evans 	__asm __volatile("cld; rep; insw"
23593d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2363f9a462fSJohn Baldwin 			 : "d" (port)
237896763faSBruce Evans 			 : "memory");
238004bedebSBruce Evans }
239004bedebSBruce Evans 
240004bedebSBruce Evans static __inline void
24193d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count)
242004bedebSBruce Evans {
243004bedebSBruce Evans 	__asm __volatile("cld; rep; insl"
24493d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2453f9a462fSJohn Baldwin 			 : "d" (port)
246896763faSBruce Evans 			 : "memory");
247004bedebSBruce Evans }
248004bedebSBruce Evans 
249ece15d78SBruce Evans static __inline void
2504c024bbdSKATO Takenori invd(void)
2514c024bbdSKATO Takenori {
2524c024bbdSKATO Takenori 	__asm __volatile("invd");
2534c024bbdSKATO Takenori }
2544c024bbdSKATO Takenori 
255004bedebSBruce Evans static __inline u_short
256004bedebSBruce Evans inw(u_int port)
257004bedebSBruce Evans {
258004bedebSBruce Evans 	u_short	data;
259004bedebSBruce Evans 
2604854ae24SJung-uk Kim 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
261004bedebSBruce Evans 	return (data);
262004bedebSBruce Evans }
263004bedebSBruce Evans 
264004bedebSBruce Evans static __inline void
265e1048f76SEd Schouten outb(u_int port, u_char data)
266004bedebSBruce Evans {
2674854ae24SJung-uk Kim 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
268004bedebSBruce Evans }
269004bedebSBruce Evans 
270004bedebSBruce Evans static __inline void
27100be8601SBruce Evans outl(u_int port, u_int data)
272004bedebSBruce Evans {
2734854ae24SJung-uk Kim 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
274004bedebSBruce Evans }
275004bedebSBruce Evans 
276004bedebSBruce Evans static __inline void
27793d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count)
278004bedebSBruce Evans {
279004bedebSBruce Evans 	__asm __volatile("cld; rep; outsb"
28093d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2813f9a462fSJohn Baldwin 			 : "d" (port));
282004bedebSBruce Evans }
283004bedebSBruce Evans 
284004bedebSBruce Evans static __inline void
28593d8be03SDavid E. O'Brien outsw(u_int port, const void *addr, size_t count)
286004bedebSBruce Evans {
287004bedebSBruce Evans 	__asm __volatile("cld; rep; outsw"
28893d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2893f9a462fSJohn Baldwin 			 : "d" (port));
290004bedebSBruce Evans }
291004bedebSBruce Evans 
292004bedebSBruce Evans static __inline void
29393d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count)
294004bedebSBruce Evans {
295004bedebSBruce Evans 	__asm __volatile("cld; rep; outsl"
29693d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2973f9a462fSJohn Baldwin 			 : "d" (port));
298004bedebSBruce Evans }
299004bedebSBruce Evans 
300004bedebSBruce Evans static __inline void
301004bedebSBruce Evans outw(u_int port, u_short data)
302004bedebSBruce Evans {
3034854ae24SJung-uk Kim 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
304004bedebSBruce Evans }
305004bedebSBruce Evans 
3062bde6e35SAlan Cox static __inline u_long
3072bde6e35SAlan Cox popcntq(u_long mask)
3082bde6e35SAlan Cox {
3092bde6e35SAlan Cox 	u_long result;
3102bde6e35SAlan Cox 
3112bde6e35SAlan Cox 	__asm __volatile("popcntq %1,%0" : "=r" (result) : "rm" (mask));
3122bde6e35SAlan Cox 	return (result);
3132bde6e35SAlan Cox }
3142bde6e35SAlan Cox 
3152be69f32SJohn Baldwin static __inline void
3160220d04fSKonstantin Belousov lfence(void)
3170220d04fSKonstantin Belousov {
3180220d04fSKonstantin Belousov 
3190220d04fSKonstantin Belousov 	__asm __volatile("lfence" : : : "memory");
3200220d04fSKonstantin Belousov }
3210220d04fSKonstantin Belousov 
3220220d04fSKonstantin Belousov static __inline void
323206a3368SKonstantin Belousov mfence(void)
324206a3368SKonstantin Belousov {
325206a3368SKonstantin Belousov 
326beb2c1f3SAndriy Gapon 	__asm __volatile("mfence" : : : "memory");
327206a3368SKonstantin Belousov }
328206a3368SKonstantin Belousov 
329206a3368SKonstantin Belousov static __inline void
3305611aaa1SKonstantin Belousov sfence(void)
3315611aaa1SKonstantin Belousov {
3325611aaa1SKonstantin Belousov 
3335611aaa1SKonstantin Belousov 	__asm __volatile("sfence" : : : "memory");
3345611aaa1SKonstantin Belousov }
3355611aaa1SKonstantin Belousov 
3365611aaa1SKonstantin Belousov static __inline void
3376b8c6989SJohn Baldwin ia32_pause(void)
3382be69f32SJohn Baldwin {
3392be69f32SJohn Baldwin 	__asm __volatile("pause");
3402be69f32SJohn Baldwin }
3412be69f32SJohn Baldwin 
342afa88623SPeter Wemm static __inline u_long
343afa88623SPeter Wemm read_rflags(void)
3445b81b6b3SRodney W. Grimes {
345afa88623SPeter Wemm 	u_long	rf;
346004bedebSBruce Evans 
347afa88623SPeter Wemm 	__asm __volatile("pushfq; popq %0" : "=r" (rf));
348afa88623SPeter Wemm 	return (rf);
3495b81b6b3SRodney W. Grimes }
3505b81b6b3SRodney W. Grimes 
351f5ac47f4SJung-uk Kim static __inline uint64_t
3525dbd168eSBruce Evans rdmsr(u_int msr)
3535dbd168eSBruce Evans {
354f5ac47f4SJung-uk Kim 	uint32_t low, high;
3555dbd168eSBruce Evans 
356afa88623SPeter Wemm 	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
357f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3585dbd168eSBruce Evans }
3595dbd168eSBruce Evans 
3604c918926SKonstantin Belousov static __inline uint32_t
3614c918926SKonstantin Belousov rdmsr32(u_int msr)
3624c918926SKonstantin Belousov {
3634c918926SKonstantin Belousov 	uint32_t low;
3644c918926SKonstantin Belousov 
3654c918926SKonstantin Belousov 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "rdx");
3664c918926SKonstantin Belousov 	return (low);
3674c918926SKonstantin Belousov }
3684c918926SKonstantin Belousov 
369f5ac47f4SJung-uk Kim static __inline uint64_t
3705dbd168eSBruce Evans rdpmc(u_int pmc)
3715dbd168eSBruce Evans {
372f5ac47f4SJung-uk Kim 	uint32_t low, high;
3735dbd168eSBruce Evans 
374afa88623SPeter Wemm 	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
375f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3765dbd168eSBruce Evans }
3775dbd168eSBruce Evans 
378f5ac47f4SJung-uk Kim static __inline uint64_t
3795dbd168eSBruce Evans rdtsc(void)
3805dbd168eSBruce Evans {
381f5ac47f4SJung-uk Kim 	uint32_t low, high;
3825dbd168eSBruce Evans 
383afa88623SPeter Wemm 	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
384f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3855dbd168eSBruce Evans }
3865dbd168eSBruce Evans 
3870e727642SJung-uk Kim static __inline uint32_t
3880e727642SJung-uk Kim rdtsc32(void)
3890e727642SJung-uk Kim {
3900e727642SJung-uk Kim 	uint32_t rv;
3910e727642SJung-uk Kim 
3920e727642SJung-uk Kim 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
3930e727642SJung-uk Kim 	return (rv);
3940e727642SJung-uk Kim }
3950e727642SJung-uk Kim 
396004bedebSBruce Evans static __inline void
3974c024bbdSKATO Takenori wbinvd(void)
3984c024bbdSKATO Takenori {
3994c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
4004c024bbdSKATO Takenori }
4014c024bbdSKATO Takenori 
4024c024bbdSKATO Takenori static __inline void
403afa88623SPeter Wemm write_rflags(u_long rf)
4045b81b6b3SRodney W. Grimes {
405afa88623SPeter Wemm 	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
4065b81b6b3SRodney W. Grimes }
4075b81b6b3SRodney W. Grimes 
408d69e8502SGarrett Wollman static __inline void
409f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval)
410d69e8502SGarrett Wollman {
411f5ac47f4SJung-uk Kim 	uint32_t low, high;
412afa88623SPeter Wemm 
413afa88623SPeter Wemm 	low = newval;
414afa88623SPeter Wemm 	high = newval >> 32;
415afa88623SPeter Wemm 	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
416d69e8502SGarrett Wollman }
417d69e8502SGarrett Wollman 
418f1b665c8SPeter Wemm static __inline void
419afa88623SPeter Wemm load_cr0(u_long data)
420f1b665c8SPeter Wemm {
421f1b665c8SPeter Wemm 
422afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr0" : : "r" (data));
423f1b665c8SPeter Wemm }
424f1b665c8SPeter Wemm 
425afa88623SPeter Wemm static __inline u_long
426f1b665c8SPeter Wemm rcr0(void)
427f1b665c8SPeter Wemm {
428afa88623SPeter Wemm 	u_long	data;
429f1b665c8SPeter Wemm 
430afa88623SPeter Wemm 	__asm __volatile("movq %%cr0,%0" : "=r" (data));
431f1b665c8SPeter Wemm 	return (data);
432f1b665c8SPeter Wemm }
433f1b665c8SPeter Wemm 
434afa88623SPeter Wemm static __inline u_long
435f1b665c8SPeter Wemm rcr2(void)
436f1b665c8SPeter Wemm {
437afa88623SPeter Wemm 	u_long	data;
438f1b665c8SPeter Wemm 
439afa88623SPeter Wemm 	__asm __volatile("movq %%cr2,%0" : "=r" (data));
440f1b665c8SPeter Wemm 	return (data);
441f1b665c8SPeter Wemm }
442f1b665c8SPeter Wemm 
443f1b665c8SPeter Wemm static __inline void
444afa88623SPeter Wemm load_cr3(u_long data)
445f1b665c8SPeter Wemm {
446f1b665c8SPeter Wemm 
447afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
448f1b665c8SPeter Wemm }
449f1b665c8SPeter Wemm 
450afa88623SPeter Wemm static __inline u_long
451f1b665c8SPeter Wemm rcr3(void)
452f1b665c8SPeter Wemm {
453afa88623SPeter Wemm 	u_long	data;
454f1b665c8SPeter Wemm 
455afa88623SPeter Wemm 	__asm __volatile("movq %%cr3,%0" : "=r" (data));
456f1b665c8SPeter Wemm 	return (data);
457f1b665c8SPeter Wemm }
458f1b665c8SPeter Wemm 
459f1b665c8SPeter Wemm static __inline void
460afa88623SPeter Wemm load_cr4(u_long data)
461f1b665c8SPeter Wemm {
462afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr4" : : "r" (data));
463f1b665c8SPeter Wemm }
464f1b665c8SPeter Wemm 
465afa88623SPeter Wemm static __inline u_long
466f1b665c8SPeter Wemm rcr4(void)
467f1b665c8SPeter Wemm {
468afa88623SPeter Wemm 	u_long	data;
469f1b665c8SPeter Wemm 
470afa88623SPeter Wemm 	__asm __volatile("movq %%cr4,%0" : "=r" (data));
471f1b665c8SPeter Wemm 	return (data);
472f1b665c8SPeter Wemm }
473f1b665c8SPeter Wemm 
4747574a595SJohn Baldwin static __inline u_long
4757574a595SJohn Baldwin rxcr(u_int reg)
4767574a595SJohn Baldwin {
4777574a595SJohn Baldwin 	u_int low, high;
4787574a595SJohn Baldwin 
4797574a595SJohn Baldwin 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
4807574a595SJohn Baldwin 	return (low | ((uint64_t)high << 32));
4817574a595SJohn Baldwin }
4827574a595SJohn Baldwin 
4837574a595SJohn Baldwin static __inline void
4847574a595SJohn Baldwin load_xcr(u_int reg, u_long val)
4857574a595SJohn Baldwin {
4867574a595SJohn Baldwin 	u_int low, high;
4877574a595SJohn Baldwin 
4887574a595SJohn Baldwin 	low = val;
4897574a595SJohn Baldwin 	high = val >> 32;
4907574a595SJohn Baldwin 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
4917574a595SJohn Baldwin }
4927574a595SJohn Baldwin 
493f1b665c8SPeter Wemm /*
494f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
495f1b665c8SPeter Wemm  */
496f1b665c8SPeter Wemm static __inline void
497f1b665c8SPeter Wemm invltlb(void)
498f1b665c8SPeter Wemm {
499f1b665c8SPeter Wemm 
500f1b665c8SPeter Wemm 	load_cr3(rcr3());
501f1b665c8SPeter Wemm }
502f1b665c8SPeter Wemm 
503e44af46eSJustin T. Gibbs #ifndef CR4_PGE
504e44af46eSJustin T. Gibbs #define	CR4_PGE	0x00000080	/* Page global enable */
505e44af46eSJustin T. Gibbs #endif
506e44af46eSJustin T. Gibbs 
507e44af46eSJustin T. Gibbs /*
508e44af46eSJustin T. Gibbs  * Perform the guaranteed invalidation of all TLB entries.  This
509e44af46eSJustin T. Gibbs  * includes the global entries, and entries in all PCIDs, not only the
510e44af46eSJustin T. Gibbs  * current context.  The function works both on non-PCID CPUs and CPUs
511e44af46eSJustin T. Gibbs  * with the PCID turned off or on.  See IA-32 SDM Vol. 3a 4.10.4.1
512e44af46eSJustin T. Gibbs  * Operations that Invalidate TLBs and Paging-Structure Caches.
513e44af46eSJustin T. Gibbs  */
514e44af46eSJustin T. Gibbs static __inline void
51527691a24SKonstantin Belousov invltlb_glob(void)
516e44af46eSJustin T. Gibbs {
517e44af46eSJustin T. Gibbs 	uint64_t cr4;
518e44af46eSJustin T. Gibbs 
519e44af46eSJustin T. Gibbs 	cr4 = rcr4();
520e44af46eSJustin T. Gibbs 	load_cr4(cr4 & ~CR4_PGE);
521e44af46eSJustin T. Gibbs 	/*
522e44af46eSJustin T. Gibbs 	 * Although preemption at this point could be detrimental to
523e44af46eSJustin T. Gibbs 	 * performance, it would not lead to an error.  PG_G is simply
524e44af46eSJustin T. Gibbs 	 * ignored if CR4.PGE is clear.  Moreover, in case this block
525e44af46eSJustin T. Gibbs 	 * is re-entered, the load_cr4() either above or below will
526e44af46eSJustin T. Gibbs 	 * modify CR4.PGE flushing the TLB.
527e44af46eSJustin T. Gibbs 	 */
528e44af46eSJustin T. Gibbs 	load_cr4(cr4 | CR4_PGE);
529e44af46eSJustin T. Gibbs }
530e44af46eSJustin T. Gibbs 
531f1b665c8SPeter Wemm /*
532f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
533f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
534f1b665c8SPeter Wemm  */
535f1b665c8SPeter Wemm static __inline void
536afa88623SPeter Wemm invlpg(u_long addr)
537f1b665c8SPeter Wemm {
538f1b665c8SPeter Wemm 
539f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
540f1b665c8SPeter Wemm }
541f1b665c8SPeter Wemm 
5425f5703efSKonstantin Belousov #define	INVPCID_ADDR	0
5435f5703efSKonstantin Belousov #define	INVPCID_CTX	1
5445f5703efSKonstantin Belousov #define	INVPCID_CTXGLOB	2
5455f5703efSKonstantin Belousov #define	INVPCID_ALLCTX	3
5465f5703efSKonstantin Belousov 
5475f5703efSKonstantin Belousov struct invpcid_descr {
5485f5703efSKonstantin Belousov 	uint64_t	pcid:12 __packed;
5495f5703efSKonstantin Belousov 	uint64_t	pad:52 __packed;
5505f5703efSKonstantin Belousov 	uint64_t	addr;
5515f5703efSKonstantin Belousov } __packed;
5525f5703efSKonstantin Belousov 
5535f5703efSKonstantin Belousov static __inline void
5545f5703efSKonstantin Belousov invpcid(struct invpcid_descr *d, int type)
5555f5703efSKonstantin Belousov {
5565f5703efSKonstantin Belousov 
557a546448bSKonstantin Belousov 	__asm __volatile("invpcid (%0),%1"
558a546448bSKonstantin Belousov 	    : : "r" (d), "r" ((u_long)type) : "memory");
5595f5703efSKonstantin Belousov }
5605f5703efSKonstantin Belousov 
56127d4fea6SRoman Divacky static __inline u_short
5625206bca1SLuoqi Chen rfs(void)
5635206bca1SLuoqi Chen {
56427d4fea6SRoman Divacky 	u_short sel;
56527d4fea6SRoman Divacky 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
5665206bca1SLuoqi Chen 	return (sel);
5675206bca1SLuoqi Chen }
5685206bca1SLuoqi Chen 
56927d4fea6SRoman Divacky static __inline u_short
5705206bca1SLuoqi Chen rgs(void)
5715206bca1SLuoqi Chen {
57227d4fea6SRoman Divacky 	u_short sel;
57327d4fea6SRoman Divacky 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
5745206bca1SLuoqi Chen 	return (sel);
5755206bca1SLuoqi Chen }
5765206bca1SLuoqi Chen 
57727d4fea6SRoman Divacky static __inline u_short
578cd0149e3SPeter Wemm rss(void)
579cd0149e3SPeter Wemm {
58027d4fea6SRoman Divacky 	u_short sel;
58127d4fea6SRoman Divacky 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
582cd0149e3SPeter Wemm 	return (sel);
583cd0149e3SPeter Wemm }
584cd0149e3SPeter Wemm 
5855206bca1SLuoqi Chen static __inline void
58627d4fea6SRoman Divacky load_ds(u_short sel)
587d85631c4SPeter Wemm {
58827d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%ds" : : "rm" (sel));
589d85631c4SPeter Wemm }
590d85631c4SPeter Wemm 
591d85631c4SPeter Wemm static __inline void
59227d4fea6SRoman Divacky load_es(u_short sel)
593d85631c4SPeter Wemm {
59427d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%es" : : "rm" (sel));
595d85631c4SPeter Wemm }
596d85631c4SPeter Wemm 
597beb2c1f3SAndriy Gapon static __inline void
598f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints)
59966247efaSJeff Roberson {
600f0b28f00SJung-uk Kim 
601f0b28f00SJung-uk Kim 	__asm __volatile("monitor"
60266247efaSJeff Roberson 	    : : "a" (addr), "c" (extensions), "d" (hints));
60366247efaSJeff Roberson }
60466247efaSJeff Roberson 
605beb2c1f3SAndriy Gapon static __inline void
606f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints)
60766247efaSJeff Roberson {
608f0b28f00SJung-uk Kim 
609f0b28f00SJung-uk Kim 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
61066247efaSJeff Roberson }
61166247efaSJeff Roberson 
612c0a54ff6SPeter Wemm #ifdef _KERNEL
613c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */
614c0a54ff6SPeter Wemm #ifndef	MSR_FSBASE
615c0a54ff6SPeter Wemm #define	MSR_FSBASE	0xc0000100
616c0a54ff6SPeter Wemm #endif
617c0a54ff6SPeter Wemm static __inline void
61827d4fea6SRoman Divacky load_fs(u_short sel)
619c0a54ff6SPeter Wemm {
620c0a54ff6SPeter Wemm 	/* Preserve the fsbase value across the selector load */
62127d4fea6SRoman Divacky 	__asm __volatile("rdmsr; movw %0,%%fs; wrmsr"
622db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
623c0a54ff6SPeter Wemm }
624c0a54ff6SPeter Wemm 
625c0a54ff6SPeter Wemm #ifndef	MSR_GSBASE
626c0a54ff6SPeter Wemm #define	MSR_GSBASE	0xc0000101
627c0a54ff6SPeter Wemm #endif
628c0a54ff6SPeter Wemm static __inline void
62927d4fea6SRoman Divacky load_gs(u_short sel)
630c0a54ff6SPeter Wemm {
631c0a54ff6SPeter Wemm 	/*
632c0a54ff6SPeter Wemm 	 * Preserve the gsbase value across the selector load.
633c0a54ff6SPeter Wemm 	 * Note that we have to disable interrupts because the gsbase
634c0a54ff6SPeter Wemm 	 * being trashed happens to be the kernel gsbase at the time.
635c0a54ff6SPeter Wemm 	 */
63627d4fea6SRoman Divacky 	__asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
637db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
638c0a54ff6SPeter Wemm }
639c0a54ff6SPeter Wemm #else
640c0a54ff6SPeter Wemm /* Usable by userland */
641d85631c4SPeter Wemm static __inline void
64227d4fea6SRoman Divacky load_fs(u_short sel)
6435206bca1SLuoqi Chen {
64427d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
6455206bca1SLuoqi Chen }
6465206bca1SLuoqi Chen 
6475206bca1SLuoqi Chen static __inline void
64827d4fea6SRoman Divacky load_gs(u_short sel)
6495206bca1SLuoqi Chen {
65027d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
6515206bca1SLuoqi Chen }
652c0a54ff6SPeter Wemm #endif
6535206bca1SLuoqi Chen 
654*0fd7ea1fSKonstantin Belousov static __inline uint64_t
655*0fd7ea1fSKonstantin Belousov rdfsbase(void)
656*0fd7ea1fSKonstantin Belousov {
657*0fd7ea1fSKonstantin Belousov 	uint64_t x;
658*0fd7ea1fSKonstantin Belousov 
659*0fd7ea1fSKonstantin Belousov 	__asm __volatile("rdfsbase %0" : "=r" (x));
660*0fd7ea1fSKonstantin Belousov 	return (x);
661*0fd7ea1fSKonstantin Belousov }
662*0fd7ea1fSKonstantin Belousov 
663*0fd7ea1fSKonstantin Belousov static __inline void
664*0fd7ea1fSKonstantin Belousov wrfsbase(uint64_t x)
665*0fd7ea1fSKonstantin Belousov {
666*0fd7ea1fSKonstantin Belousov 
667*0fd7ea1fSKonstantin Belousov 	__asm __volatile("wrfsbase %0" : : "r" (x));
668*0fd7ea1fSKonstantin Belousov }
669*0fd7ea1fSKonstantin Belousov 
670*0fd7ea1fSKonstantin Belousov static __inline uint64_t
671*0fd7ea1fSKonstantin Belousov rdgsbase(void)
672*0fd7ea1fSKonstantin Belousov {
673*0fd7ea1fSKonstantin Belousov 	uint64_t x;
674*0fd7ea1fSKonstantin Belousov 
675*0fd7ea1fSKonstantin Belousov 	__asm __volatile("rdgsbase %0" : "=r" (x));
676*0fd7ea1fSKonstantin Belousov 	return (x);
677*0fd7ea1fSKonstantin Belousov }
678*0fd7ea1fSKonstantin Belousov 
679*0fd7ea1fSKonstantin Belousov static __inline void
680*0fd7ea1fSKonstantin Belousov wrgsbase(uint64_t x)
681*0fd7ea1fSKonstantin Belousov {
682*0fd7ea1fSKonstantin Belousov 
683*0fd7ea1fSKonstantin Belousov 	__asm __volatile("wrgsbase %0" : : "r" (x));
684*0fd7ea1fSKonstantin Belousov }
685*0fd7ea1fSKonstantin Belousov 
686eb1443c8SPeter Wemm static __inline void
687c1538a13SKonstantin Belousov bare_lgdt(struct region_descriptor *addr)
688c1538a13SKonstantin Belousov {
689c1538a13SKonstantin Belousov 	__asm __volatile("lgdt (%0)" : : "r" (addr));
690c1538a13SKonstantin Belousov }
691c1538a13SKonstantin Belousov 
692c1538a13SKonstantin Belousov static __inline void
693c1538a13SKonstantin Belousov sgdt(struct region_descriptor *addr)
694c1538a13SKonstantin Belousov {
695c1538a13SKonstantin Belousov 	char *loc;
696c1538a13SKonstantin Belousov 
697c1538a13SKonstantin Belousov 	loc = (char *)addr;
698c1538a13SKonstantin Belousov 	__asm __volatile("sgdt %0" : "=m" (*loc) : : "memory");
699c1538a13SKonstantin Belousov }
700c1538a13SKonstantin Belousov 
701c1538a13SKonstantin Belousov static __inline void
702eb1443c8SPeter Wemm lidt(struct region_descriptor *addr)
703eb1443c8SPeter Wemm {
704eb1443c8SPeter Wemm 	__asm __volatile("lidt (%0)" : : "r" (addr));
705eb1443c8SPeter Wemm }
706eb1443c8SPeter Wemm 
707eb1443c8SPeter Wemm static __inline void
708c1538a13SKonstantin Belousov sidt(struct region_descriptor *addr)
709c1538a13SKonstantin Belousov {
710c1538a13SKonstantin Belousov 	char *loc;
711c1538a13SKonstantin Belousov 
712c1538a13SKonstantin Belousov 	loc = (char *)addr;
713c1538a13SKonstantin Belousov 	__asm __volatile("sidt %0" : "=m" (*loc) : : "memory");
714c1538a13SKonstantin Belousov }
715c1538a13SKonstantin Belousov 
716c1538a13SKonstantin Belousov static __inline void
717eb1443c8SPeter Wemm lldt(u_short sel)
718eb1443c8SPeter Wemm {
719eb1443c8SPeter Wemm 	__asm __volatile("lldt %0" : : "r" (sel));
720eb1443c8SPeter Wemm }
721eb1443c8SPeter Wemm 
722eb1443c8SPeter Wemm static __inline void
723eb1443c8SPeter Wemm ltr(u_short sel)
724eb1443c8SPeter Wemm {
725eb1443c8SPeter Wemm 	__asm __volatile("ltr %0" : : "r" (sel));
726eb1443c8SPeter Wemm }
727eb1443c8SPeter Wemm 
728c1538a13SKonstantin Belousov static __inline uint32_t
729c1538a13SKonstantin Belousov read_tr(void)
730c1538a13SKonstantin Belousov {
731c1538a13SKonstantin Belousov 	u_short sel;
732c1538a13SKonstantin Belousov 
733c1538a13SKonstantin Belousov 	__asm __volatile("str %0" : "=r" (sel));
734c1538a13SKonstantin Belousov 	return (sel);
735c1538a13SKonstantin Belousov }
736c1538a13SKonstantin Belousov 
737f5ac47f4SJung-uk Kim static __inline uint64_t
7381182b177SPeter Wemm rdr0(void)
7391182b177SPeter Wemm {
740f5ac47f4SJung-uk Kim 	uint64_t data;
7411182b177SPeter Wemm 	__asm __volatile("movq %%dr0,%0" : "=r" (data));
7421182b177SPeter Wemm 	return (data);
7431182b177SPeter Wemm }
7441182b177SPeter Wemm 
7451182b177SPeter Wemm static __inline void
746f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0)
7471182b177SPeter Wemm {
7481182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
7491182b177SPeter Wemm }
7501182b177SPeter Wemm 
751f5ac47f4SJung-uk Kim static __inline uint64_t
7521182b177SPeter Wemm rdr1(void)
7531182b177SPeter Wemm {
754f5ac47f4SJung-uk Kim 	uint64_t data;
7551182b177SPeter Wemm 	__asm __volatile("movq %%dr1,%0" : "=r" (data));
7561182b177SPeter Wemm 	return (data);
7571182b177SPeter Wemm }
7581182b177SPeter Wemm 
7591182b177SPeter Wemm static __inline void
760f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1)
7611182b177SPeter Wemm {
7621182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
7631182b177SPeter Wemm }
7641182b177SPeter Wemm 
765f5ac47f4SJung-uk Kim static __inline uint64_t
7661182b177SPeter Wemm rdr2(void)
7671182b177SPeter Wemm {
768f5ac47f4SJung-uk Kim 	uint64_t data;
7691182b177SPeter Wemm 	__asm __volatile("movq %%dr2,%0" : "=r" (data));
7701182b177SPeter Wemm 	return (data);
7711182b177SPeter Wemm }
7721182b177SPeter Wemm 
7731182b177SPeter Wemm static __inline void
774f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2)
7751182b177SPeter Wemm {
7761182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
7771182b177SPeter Wemm }
7781182b177SPeter Wemm 
779f5ac47f4SJung-uk Kim static __inline uint64_t
7801182b177SPeter Wemm rdr3(void)
7811182b177SPeter Wemm {
782f5ac47f4SJung-uk Kim 	uint64_t data;
7831182b177SPeter Wemm 	__asm __volatile("movq %%dr3,%0" : "=r" (data));
7841182b177SPeter Wemm 	return (data);
7851182b177SPeter Wemm }
7861182b177SPeter Wemm 
7871182b177SPeter Wemm static __inline void
788f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3)
7891182b177SPeter Wemm {
7901182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
7911182b177SPeter Wemm }
7921182b177SPeter Wemm 
793f5ac47f4SJung-uk Kim static __inline uint64_t
7941182b177SPeter Wemm rdr6(void)
7951182b177SPeter Wemm {
796f5ac47f4SJung-uk Kim 	uint64_t data;
7971182b177SPeter Wemm 	__asm __volatile("movq %%dr6,%0" : "=r" (data));
7981182b177SPeter Wemm 	return (data);
7991182b177SPeter Wemm }
8001182b177SPeter Wemm 
8011182b177SPeter Wemm static __inline void
802f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6)
8031182b177SPeter Wemm {
8041182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
8051182b177SPeter Wemm }
8061182b177SPeter Wemm 
807f5ac47f4SJung-uk Kim static __inline uint64_t
8081182b177SPeter Wemm rdr7(void)
8091182b177SPeter Wemm {
810f5ac47f4SJung-uk Kim 	uint64_t data;
8111182b177SPeter Wemm 	__asm __volatile("movq %%dr7,%0" : "=r" (data));
8121182b177SPeter Wemm 	return (data);
8131182b177SPeter Wemm }
8141182b177SPeter Wemm 
8151182b177SPeter Wemm static __inline void
816f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7)
8171182b177SPeter Wemm {
8181182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
8191182b177SPeter Wemm }
8201182b177SPeter Wemm 
821ba74981eSWarner Losh static __inline register_t
822ba74981eSWarner Losh intr_disable(void)
823ba74981eSWarner Losh {
824afa88623SPeter Wemm 	register_t rflags;
825ba74981eSWarner Losh 
826afa88623SPeter Wemm 	rflags = read_rflags();
827ba74981eSWarner Losh 	disable_intr();
828afa88623SPeter Wemm 	return (rflags);
829ba74981eSWarner Losh }
830ba74981eSWarner Losh 
831ba74981eSWarner Losh static __inline void
832afa88623SPeter Wemm intr_restore(register_t rflags)
833ba74981eSWarner Losh {
834afa88623SPeter Wemm 	write_rflags(rflags);
835ba74981eSWarner Losh }
836ba74981eSWarner Losh 
837a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
8385b81b6b3SRodney W. Grimes 
839b63dc6adSAlfred Perlstein int	breakpoint(void);
840b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
841b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
842d706ec29SJohn Baldwin void	clflush(u_long addr);
843d706ec29SJohn Baldwin void	clts(void);
844d706ec29SJohn Baldwin void	cpuid_count(u_int ax, u_int cx, u_int *p);
845b63dc6adSAlfred Perlstein void	disable_intr(void);
846b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
847b63dc6adSAlfred Perlstein void	enable_intr(void);
848d7ee4425SMark Murray void	halt(void);
8494f6c19e5SPeter Wemm void	ia32_pause(void);
850b63dc6adSAlfred Perlstein u_char	inb(u_int port);
851b63dc6adSAlfred Perlstein u_int	inl(u_int port);
85293d8be03SDavid E. O'Brien void	insb(u_int port, void *addr, size_t count);
85393d8be03SDavid E. O'Brien void	insl(u_int port, void *addr, size_t count);
85493d8be03SDavid E. O'Brien void	insw(u_int port, void *addr, size_t count);
8554f6c19e5SPeter Wemm register_t	intr_disable(void);
8564f6c19e5SPeter Wemm void	intr_restore(register_t rf);
857b63dc6adSAlfred Perlstein void	invd(void);
858b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
859b63dc6adSAlfred Perlstein void	invltlb(void);
860b63dc6adSAlfred Perlstein u_short	inw(u_int port);
861eb1443c8SPeter Wemm void	lidt(struct region_descriptor *addr);
862eb1443c8SPeter Wemm void	lldt(u_short sel);
8634f6c19e5SPeter Wemm void	load_cr0(u_long cr0);
8644f6c19e5SPeter Wemm void	load_cr3(u_long cr3);
8654f6c19e5SPeter Wemm void	load_cr4(u_long cr4);
866f5ac47f4SJung-uk Kim void	load_dr0(uint64_t dr0);
867f5ac47f4SJung-uk Kim void	load_dr1(uint64_t dr1);
868f5ac47f4SJung-uk Kim void	load_dr2(uint64_t dr2);
869f5ac47f4SJung-uk Kim void	load_dr3(uint64_t dr3);
870f5ac47f4SJung-uk Kim void	load_dr6(uint64_t dr6);
871f5ac47f4SJung-uk Kim void	load_dr7(uint64_t dr7);
87227d4fea6SRoman Divacky void	load_fs(u_short sel);
87327d4fea6SRoman Divacky void	load_gs(u_short sel);
874eb1443c8SPeter Wemm void	ltr(u_short sel);
875b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
876b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
87793d8be03SDavid E. O'Brien void	outsb(u_int port, const void *addr, size_t count);
87893d8be03SDavid E. O'Brien void	outsl(u_int port, const void *addr, size_t count);
87993d8be03SDavid E. O'Brien void	outsw(u_int port, const void *addr, size_t count);
880b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
8814f6c19e5SPeter Wemm u_long	rcr0(void);
8824f6c19e5SPeter Wemm u_long	rcr2(void);
8834f6c19e5SPeter Wemm u_long	rcr3(void);
8844f6c19e5SPeter Wemm u_long	rcr4(void);
885f5ac47f4SJung-uk Kim uint64_t rdmsr(u_int msr);
8864c918926SKonstantin Belousov uint32_t rdmsr32(u_int msr);
887f5ac47f4SJung-uk Kim uint64_t rdpmc(u_int pmc);
888f5ac47f4SJung-uk Kim uint64_t rdr0(void);
889f5ac47f4SJung-uk Kim uint64_t rdr1(void);
890f5ac47f4SJung-uk Kim uint64_t rdr2(void);
891f5ac47f4SJung-uk Kim uint64_t rdr3(void);
892f5ac47f4SJung-uk Kim uint64_t rdr6(void);
893f5ac47f4SJung-uk Kim uint64_t rdr7(void);
894f5ac47f4SJung-uk Kim uint64_t rdtsc(void);
895a61dd1bdSJohn Baldwin u_long	read_rflags(void);
8964f6c19e5SPeter Wemm u_int	rfs(void);
8974f6c19e5SPeter Wemm u_int	rgs(void);
898b63dc6adSAlfred Perlstein void	wbinvd(void);
899afa88623SPeter Wemm void	write_rflags(u_int rf);
900f5ac47f4SJung-uk Kim void	wrmsr(u_int msr, uint64_t newval);
901004bedebSBruce Evans 
902a5f50ef9SJoerg Wunsch #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
9035b81b6b3SRodney W. Grimes 
904b63dc6adSAlfred Perlstein void	reset_dbregs(void);
905d74ac681SMatthew Dillon 
906e085f869SStanislav Sedov #ifdef _KERNEL
907e085f869SStanislav Sedov int	rdmsr_safe(u_int msr, uint64_t *val);
908e085f869SStanislav Sedov int	wrmsr_safe(u_int msr, uint64_t newval);
909e085f869SStanislav Sedov #endif
910e085f869SStanislav Sedov 
911004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
912