xref: /freebsd/sys/amd64/include/cpufunc.h (revision 908e277230ef1a80589f85687f5b422b0e863e79)
13c4dd356SDavid Greenman /*-
251369649SPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
351369649SPedro F. Giffuni  *
4fcfe57d6SPeter Wemm  * Copyright (c) 2003 Peter Wemm.
53c4dd356SDavid Greenman  * Copyright (c) 1993 The Regents of the University of California.
63c4dd356SDavid Greenman  * All rights reserved.
73c4dd356SDavid Greenman  *
83c4dd356SDavid Greenman  * Redistribution and use in source and binary forms, with or without
93c4dd356SDavid Greenman  * modification, are permitted provided that the following conditions
103c4dd356SDavid Greenman  * are met:
113c4dd356SDavid Greenman  * 1. Redistributions of source code must retain the above copyright
123c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer.
133c4dd356SDavid Greenman  * 2. Redistributions in binary form must reproduce the above copyright
143c4dd356SDavid Greenman  *    notice, this list of conditions and the following disclaimer in the
153c4dd356SDavid Greenman  *    documentation and/or other materials provided with the distribution.
16fbbd9655SWarner Losh  * 3. Neither the name of the University nor the names of its contributors
173c4dd356SDavid Greenman  *    may be used to endorse or promote products derived from this software
183c4dd356SDavid Greenman  *    without specific prior written permission.
193c4dd356SDavid Greenman  *
203c4dd356SDavid Greenman  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
213c4dd356SDavid Greenman  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
223c4dd356SDavid Greenman  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
233c4dd356SDavid Greenman  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
243c4dd356SDavid Greenman  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
253c4dd356SDavid Greenman  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
263c4dd356SDavid Greenman  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
273c4dd356SDavid Greenman  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
283c4dd356SDavid Greenman  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
293c4dd356SDavid Greenman  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
303c4dd356SDavid Greenman  * SUCH DAMAGE.
313c4dd356SDavid Greenman  *
32c3aac50fSPeter Wemm  * $FreeBSD$
333c4dd356SDavid Greenman  */
343c4dd356SDavid Greenman 
355b81b6b3SRodney W. Grimes /*
365b81b6b3SRodney W. Grimes  * Functions to provide access to special i386 instructions.
37f5d9a10bSMark Murray  * This in included in sys/systm.h, and that file should be
38f5d9a10bSMark Murray  * used in preference to this.
395b81b6b3SRodney W. Grimes  */
405b81b6b3SRodney W. Grimes 
416e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
42004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
436e393973SGarrett Wollman 
44a5f50ef9SJoerg Wunsch #ifndef _SYS_CDEFS_H_
45a5f50ef9SJoerg Wunsch #error this file needs sys/cdefs.h as a prerequisite
46a5f50ef9SJoerg Wunsch #endif
47a5f50ef9SJoerg Wunsch 
48eb1443c8SPeter Wemm struct region_descriptor;
49d74ac681SMatthew Dillon 
50f5ac47f4SJung-uk Kim #define readb(va)	(*(volatile uint8_t *) (va))
51f5ac47f4SJung-uk Kim #define readw(va)	(*(volatile uint16_t *) (va))
52f5ac47f4SJung-uk Kim #define readl(va)	(*(volatile uint32_t *) (va))
53f5ac47f4SJung-uk Kim #define readq(va)	(*(volatile uint64_t *) (va))
54e31fa854SDoug Rabson 
55f5ac47f4SJung-uk Kim #define writeb(va, d)	(*(volatile uint8_t *) (va) = (d))
56f5ac47f4SJung-uk Kim #define writew(va, d)	(*(volatile uint16_t *) (va) = (d))
57f5ac47f4SJung-uk Kim #define writel(va, d)	(*(volatile uint32_t *) (va) = (d))
58f5ac47f4SJung-uk Kim #define writeq(va, d)	(*(volatile uint64_t *) (va) = (d))
59e31fa854SDoug Rabson 
60a5f50ef9SJoerg Wunsch #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE)
615b81b6b3SRodney W. Grimes 
625dbd168eSBruce Evans static __inline void
635dbd168eSBruce Evans breakpoint(void)
64004bedebSBruce Evans {
65004bedebSBruce Evans 	__asm __volatile("int $3");
665b81b6b3SRodney W. Grimes }
675b81b6b3SRodney W. Grimes 
68aae89f6fSMateusz Guzik #define	bsfl(mask)	__builtin_ctz(mask)
69c83b1328SBruce Evans 
70aae89f6fSMateusz Guzik #define	bsfq(mask)	__builtin_ctzl(mask)
71c83b1328SBruce Evans 
72aae89f6fSMateusz Guzik #define	bsrl(mask)	(__builtin_clz(mask) ^ 0x1f)
73176ce2b1SPeter Wemm 
74aae89f6fSMateusz Guzik #define	bsrq(mask)	(__builtin_clzl(mask) ^ 0x3f)
75176ce2b1SPeter Wemm 
76004bedebSBruce Evans static __inline void
77206a3368SKonstantin Belousov clflush(u_long addr)
78206a3368SKonstantin Belousov {
79206a3368SKonstantin Belousov 
80206a3368SKonstantin Belousov 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
81206a3368SKonstantin Belousov }
82206a3368SKonstantin Belousov 
83206a3368SKonstantin Belousov static __inline void
843f8e0710SKonstantin Belousov clflushopt(u_long addr)
853f8e0710SKonstantin Belousov {
863f8e0710SKonstantin Belousov 
873f8e0710SKonstantin Belousov 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
883f8e0710SKonstantin Belousov }
893f8e0710SKonstantin Belousov 
903f8e0710SKonstantin Belousov static __inline void
919d5d89b2SKonstantin Belousov clwb(u_long addr)
929d5d89b2SKonstantin Belousov {
939d5d89b2SKonstantin Belousov 
949d5d89b2SKonstantin Belousov 	__asm __volatile("clwb %0" : : "m" (*(char *)addr));
959d5d89b2SKonstantin Belousov }
969d5d89b2SKonstantin Belousov 
979d5d89b2SKonstantin Belousov static __inline void
98d706ec29SJohn Baldwin clts(void)
99d706ec29SJohn Baldwin {
100d706ec29SJohn Baldwin 
101d706ec29SJohn Baldwin 	__asm __volatile("clts");
102d706ec29SJohn Baldwin }
103d706ec29SJohn Baldwin 
104d706ec29SJohn Baldwin static __inline void
1055b81b6b3SRodney W. Grimes disable_intr(void)
1065b81b6b3SRodney W. Grimes {
1078966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
1085b81b6b3SRodney W. Grimes }
1095b81b6b3SRodney W. Grimes 
110004bedebSBruce Evans static __inline void
111a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
112a983fdfeSDavid Malone {
113a983fdfeSDavid Malone 	__asm __volatile("cpuid"
114a983fdfeSDavid Malone 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
115a983fdfeSDavid Malone 			 :  "0" (ax));
116a983fdfeSDavid Malone }
117a983fdfeSDavid Malone 
118a983fdfeSDavid Malone static __inline void
119f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p)
120f6108b61SJacques Vidrine {
121f6108b61SJacques Vidrine 	__asm __volatile("cpuid"
122f6108b61SJacques Vidrine 			 : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
123f6108b61SJacques Vidrine 			 :  "0" (ax), "c" (cx));
124f6108b61SJacques Vidrine }
125f6108b61SJacques Vidrine 
126f6108b61SJacques Vidrine static __inline void
1275b81b6b3SRodney W. Grimes enable_intr(void)
1285b81b6b3SRodney W. Grimes {
129fadc51bdSBruce Evans 	__asm __volatile("sti");
1305b81b6b3SRodney W. Grimes }
1315b81b6b3SRodney W. Grimes 
132a67ef0a7SBruce Evans #ifdef _KERNEL
133a67ef0a7SBruce Evans 
134264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
135bc35f5dcSPaul Saab #define	ffs(x)		__builtin_ffs(x)
136176ce2b1SPeter Wemm 
137176ce2b1SPeter Wemm #define	HAVE_INLINE_FFSL
13837bd3aa6SMateusz Guzik #define	ffsl(x)		__builtin_ffsl(x)
139004bedebSBruce Evans 
140f25e50cfSAndriy Gapon #define	HAVE_INLINE_FFSLL
14137bd3aa6SMateusz Guzik #define	ffsll(x)	__builtin_ffsll(x)
142f25e50cfSAndriy Gapon 
14313f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
14413f588f8SGarrett Wollman 
1456f240e18SConrad Meyer static __inline __pure2 int
14613f588f8SGarrett Wollman fls(int mask)
14713f588f8SGarrett Wollman {
1487e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
14913f588f8SGarrett Wollman }
15013f588f8SGarrett Wollman 
151176ce2b1SPeter Wemm #define	HAVE_INLINE_FLSL
152176ce2b1SPeter Wemm 
1536f240e18SConrad Meyer static __inline __pure2 int
154176ce2b1SPeter Wemm flsl(long mask)
155176ce2b1SPeter Wemm {
156176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
157176ce2b1SPeter Wemm }
158176ce2b1SPeter Wemm 
159f25e50cfSAndriy Gapon #define	HAVE_INLINE_FLSLL
160f25e50cfSAndriy Gapon 
1616f240e18SConrad Meyer static __inline __pure2 int
162f25e50cfSAndriy Gapon flsll(long long mask)
163f25e50cfSAndriy Gapon {
164f25e50cfSAndriy Gapon 	return (flsl((long)mask));
165f25e50cfSAndriy Gapon }
166f25e50cfSAndriy Gapon 
167a67ef0a7SBruce Evans #endif /* _KERNEL */
168a67ef0a7SBruce Evans 
169d7ee4425SMark Murray static __inline void
170d7ee4425SMark Murray halt(void)
171d7ee4425SMark Murray {
172d7ee4425SMark Murray 	__asm __volatile("hlt");
173d7ee4425SMark Murray }
174d7ee4425SMark Murray 
175004bedebSBruce Evans static __inline u_char
176e1048f76SEd Schouten inb(u_int port)
177004bedebSBruce Evans {
178004bedebSBruce Evans 	u_char	data;
179004bedebSBruce Evans 
1804854ae24SJung-uk Kim 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
181004bedebSBruce Evans 	return (data);
182004bedebSBruce Evans }
183004bedebSBruce Evans 
18400be8601SBruce Evans static __inline u_int
185004bedebSBruce Evans inl(u_int port)
186004bedebSBruce Evans {
18700be8601SBruce Evans 	u_int	data;
188004bedebSBruce Evans 
1894854ae24SJung-uk Kim 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
190004bedebSBruce Evans 	return (data);
191004bedebSBruce Evans }
192004bedebSBruce Evans 
193004bedebSBruce Evans static __inline void
19493d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count)
195004bedebSBruce Evans {
196fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insb"
19793d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
1983f9a462fSJohn Baldwin 			 : "d" (port)
199896763faSBruce Evans 			 : "memory");
200004bedebSBruce Evans }
201004bedebSBruce Evans 
202004bedebSBruce Evans static __inline void
20393d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count)
204004bedebSBruce Evans {
205fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insw"
20693d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2073f9a462fSJohn Baldwin 			 : "d" (port)
208896763faSBruce Evans 			 : "memory");
209004bedebSBruce Evans }
210004bedebSBruce Evans 
211004bedebSBruce Evans static __inline void
21293d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count)
213004bedebSBruce Evans {
214fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insl"
21593d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2163f9a462fSJohn Baldwin 			 : "d" (port)
217896763faSBruce Evans 			 : "memory");
218004bedebSBruce Evans }
219004bedebSBruce Evans 
220ece15d78SBruce Evans static __inline void
2214c024bbdSKATO Takenori invd(void)
2224c024bbdSKATO Takenori {
2234c024bbdSKATO Takenori 	__asm __volatile("invd");
2244c024bbdSKATO Takenori }
2254c024bbdSKATO Takenori 
226004bedebSBruce Evans static __inline u_short
227004bedebSBruce Evans inw(u_int port)
228004bedebSBruce Evans {
229004bedebSBruce Evans 	u_short	data;
230004bedebSBruce Evans 
2314854ae24SJung-uk Kim 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
232004bedebSBruce Evans 	return (data);
233004bedebSBruce Evans }
234004bedebSBruce Evans 
235004bedebSBruce Evans static __inline void
236e1048f76SEd Schouten outb(u_int port, u_char data)
237004bedebSBruce Evans {
2384854ae24SJung-uk Kim 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
239004bedebSBruce Evans }
240004bedebSBruce Evans 
241004bedebSBruce Evans static __inline void
24200be8601SBruce Evans outl(u_int port, u_int data)
243004bedebSBruce Evans {
2444854ae24SJung-uk Kim 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
245004bedebSBruce Evans }
246004bedebSBruce Evans 
247004bedebSBruce Evans static __inline void
24893d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count)
249004bedebSBruce Evans {
250fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsb"
25193d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2523f9a462fSJohn Baldwin 			 : "d" (port));
253004bedebSBruce Evans }
254004bedebSBruce Evans 
255004bedebSBruce Evans static __inline void
25693d8be03SDavid E. O'Brien outsw(u_int port, const void *addr, size_t count)
257004bedebSBruce Evans {
258fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsw"
25993d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2603f9a462fSJohn Baldwin 			 : "d" (port));
261004bedebSBruce Evans }
262004bedebSBruce Evans 
263004bedebSBruce Evans static __inline void
26493d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count)
265004bedebSBruce Evans {
266fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsl"
26793d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2683f9a462fSJohn Baldwin 			 : "d" (port));
269004bedebSBruce Evans }
270004bedebSBruce Evans 
271004bedebSBruce Evans static __inline void
272004bedebSBruce Evans outw(u_int port, u_short data)
273004bedebSBruce Evans {
2744854ae24SJung-uk Kim 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
275004bedebSBruce Evans }
276004bedebSBruce Evans 
2772bde6e35SAlan Cox static __inline u_long
2782bde6e35SAlan Cox popcntq(u_long mask)
2792bde6e35SAlan Cox {
2802bde6e35SAlan Cox 	u_long result;
2812bde6e35SAlan Cox 
2822bde6e35SAlan Cox 	__asm __volatile("popcntq %1,%0" : "=r" (result) : "rm" (mask));
2832bde6e35SAlan Cox 	return (result);
2842bde6e35SAlan Cox }
2852bde6e35SAlan Cox 
2862be69f32SJohn Baldwin static __inline void
2870220d04fSKonstantin Belousov lfence(void)
2880220d04fSKonstantin Belousov {
2890220d04fSKonstantin Belousov 
2900220d04fSKonstantin Belousov 	__asm __volatile("lfence" : : : "memory");
2910220d04fSKonstantin Belousov }
2920220d04fSKonstantin Belousov 
2930220d04fSKonstantin Belousov static __inline void
294206a3368SKonstantin Belousov mfence(void)
295206a3368SKonstantin Belousov {
296206a3368SKonstantin Belousov 
297beb2c1f3SAndriy Gapon 	__asm __volatile("mfence" : : : "memory");
298206a3368SKonstantin Belousov }
299206a3368SKonstantin Belousov 
300206a3368SKonstantin Belousov static __inline void
3015611aaa1SKonstantin Belousov sfence(void)
3025611aaa1SKonstantin Belousov {
3035611aaa1SKonstantin Belousov 
3045611aaa1SKonstantin Belousov 	__asm __volatile("sfence" : : : "memory");
3055611aaa1SKonstantin Belousov }
3065611aaa1SKonstantin Belousov 
3075611aaa1SKonstantin Belousov static __inline void
3086b8c6989SJohn Baldwin ia32_pause(void)
3092be69f32SJohn Baldwin {
3102be69f32SJohn Baldwin 	__asm __volatile("pause");
3112be69f32SJohn Baldwin }
3122be69f32SJohn Baldwin 
313afa88623SPeter Wemm static __inline u_long
314afa88623SPeter Wemm read_rflags(void)
3155b81b6b3SRodney W. Grimes {
316afa88623SPeter Wemm 	u_long	rf;
317004bedebSBruce Evans 
318afa88623SPeter Wemm 	__asm __volatile("pushfq; popq %0" : "=r" (rf));
319afa88623SPeter Wemm 	return (rf);
3205b81b6b3SRodney W. Grimes }
3215b81b6b3SRodney W. Grimes 
322f5ac47f4SJung-uk Kim static __inline uint64_t
3235dbd168eSBruce Evans rdmsr(u_int msr)
3245dbd168eSBruce Evans {
325f5ac47f4SJung-uk Kim 	uint32_t low, high;
3265dbd168eSBruce Evans 
327afa88623SPeter Wemm 	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
328f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3295dbd168eSBruce Evans }
3305dbd168eSBruce Evans 
3314c918926SKonstantin Belousov static __inline uint32_t
3324c918926SKonstantin Belousov rdmsr32(u_int msr)
3334c918926SKonstantin Belousov {
3344c918926SKonstantin Belousov 	uint32_t low;
3354c918926SKonstantin Belousov 
3364c918926SKonstantin Belousov 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "rdx");
3374c918926SKonstantin Belousov 	return (low);
3384c918926SKonstantin Belousov }
3394c918926SKonstantin Belousov 
340f5ac47f4SJung-uk Kim static __inline uint64_t
3415dbd168eSBruce Evans rdpmc(u_int pmc)
3425dbd168eSBruce Evans {
343f5ac47f4SJung-uk Kim 	uint32_t low, high;
3445dbd168eSBruce Evans 
345afa88623SPeter Wemm 	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
346f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3475dbd168eSBruce Evans }
3485dbd168eSBruce Evans 
349f5ac47f4SJung-uk Kim static __inline uint64_t
3505dbd168eSBruce Evans rdtsc(void)
3515dbd168eSBruce Evans {
352f5ac47f4SJung-uk Kim 	uint32_t low, high;
3535dbd168eSBruce Evans 
354afa88623SPeter Wemm 	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
355f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3565dbd168eSBruce Evans }
3575dbd168eSBruce Evans 
35815504639SMatt Macy static __inline uint64_t
35915504639SMatt Macy rdtscp(void)
36015504639SMatt Macy {
36115504639SMatt Macy 	uint32_t low, high;
36215504639SMatt Macy 
363f090f675SMark Johnston 	__asm __volatile("rdtscp" : "=a" (low), "=d" (high) : : "ecx");
36415504639SMatt Macy 	return (low | ((uint64_t)high << 32));
36515504639SMatt Macy }
36615504639SMatt Macy 
367*908e2772SAdam Fenn static __inline uint64_t
368*908e2772SAdam Fenn rdtscp_aux(uint32_t *aux)
369*908e2772SAdam Fenn {
370*908e2772SAdam Fenn 	uint32_t low, high;
371*908e2772SAdam Fenn 
372*908e2772SAdam Fenn 	__asm __volatile("rdtscp" : "=a" (low), "=d" (high), "=c" (*aux));
373*908e2772SAdam Fenn 	return (low | ((uint64_t)high << 32));
374*908e2772SAdam Fenn }
375*908e2772SAdam Fenn 
3760e727642SJung-uk Kim static __inline uint32_t
3770e727642SJung-uk Kim rdtsc32(void)
3780e727642SJung-uk Kim {
3790e727642SJung-uk Kim 	uint32_t rv;
3800e727642SJung-uk Kim 
3810e727642SJung-uk Kim 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
3820e727642SJung-uk Kim 	return (rv);
3830e727642SJung-uk Kim }
3840e727642SJung-uk Kim 
38545974de8SKonstantin Belousov static __inline uint32_t
38645974de8SKonstantin Belousov rdtscp32(void)
38745974de8SKonstantin Belousov {
38845974de8SKonstantin Belousov 	uint32_t rv;
38945974de8SKonstantin Belousov 
39045974de8SKonstantin Belousov 	__asm __volatile("rdtscp" : "=a" (rv) : : "ecx", "edx");
39145974de8SKonstantin Belousov 	return (rv);
39245974de8SKonstantin Belousov }
39345974de8SKonstantin Belousov 
394004bedebSBruce Evans static __inline void
3954c024bbdSKATO Takenori wbinvd(void)
3964c024bbdSKATO Takenori {
3974c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3984c024bbdSKATO Takenori }
3994c024bbdSKATO Takenori 
4004c024bbdSKATO Takenori static __inline void
401afa88623SPeter Wemm write_rflags(u_long rf)
4025b81b6b3SRodney W. Grimes {
403afa88623SPeter Wemm 	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
4045b81b6b3SRodney W. Grimes }
4055b81b6b3SRodney W. Grimes 
406d69e8502SGarrett Wollman static __inline void
407f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval)
408d69e8502SGarrett Wollman {
409f5ac47f4SJung-uk Kim 	uint32_t low, high;
410afa88623SPeter Wemm 
411afa88623SPeter Wemm 	low = newval;
412afa88623SPeter Wemm 	high = newval >> 32;
413afa88623SPeter Wemm 	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
414d69e8502SGarrett Wollman }
415d69e8502SGarrett Wollman 
416f1b665c8SPeter Wemm static __inline void
417afa88623SPeter Wemm load_cr0(u_long data)
418f1b665c8SPeter Wemm {
419f1b665c8SPeter Wemm 
420afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr0" : : "r" (data));
421f1b665c8SPeter Wemm }
422f1b665c8SPeter Wemm 
423afa88623SPeter Wemm static __inline u_long
424f1b665c8SPeter Wemm rcr0(void)
425f1b665c8SPeter Wemm {
426afa88623SPeter Wemm 	u_long	data;
427f1b665c8SPeter Wemm 
428afa88623SPeter Wemm 	__asm __volatile("movq %%cr0,%0" : "=r" (data));
429f1b665c8SPeter Wemm 	return (data);
430f1b665c8SPeter Wemm }
431f1b665c8SPeter Wemm 
432afa88623SPeter Wemm static __inline u_long
433f1b665c8SPeter Wemm rcr2(void)
434f1b665c8SPeter Wemm {
435afa88623SPeter Wemm 	u_long	data;
436f1b665c8SPeter Wemm 
437afa88623SPeter Wemm 	__asm __volatile("movq %%cr2,%0" : "=r" (data));
438f1b665c8SPeter Wemm 	return (data);
439f1b665c8SPeter Wemm }
440f1b665c8SPeter Wemm 
441f1b665c8SPeter Wemm static __inline void
442afa88623SPeter Wemm load_cr3(u_long data)
443f1b665c8SPeter Wemm {
444f1b665c8SPeter Wemm 
445afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
446f1b665c8SPeter Wemm }
447f1b665c8SPeter Wemm 
448afa88623SPeter Wemm static __inline u_long
449f1b665c8SPeter Wemm rcr3(void)
450f1b665c8SPeter Wemm {
451afa88623SPeter Wemm 	u_long	data;
452f1b665c8SPeter Wemm 
453afa88623SPeter Wemm 	__asm __volatile("movq %%cr3,%0" : "=r" (data));
454f1b665c8SPeter Wemm 	return (data);
455f1b665c8SPeter Wemm }
456f1b665c8SPeter Wemm 
457f1b665c8SPeter Wemm static __inline void
458afa88623SPeter Wemm load_cr4(u_long data)
459f1b665c8SPeter Wemm {
460afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr4" : : "r" (data));
461f1b665c8SPeter Wemm }
462f1b665c8SPeter Wemm 
463afa88623SPeter Wemm static __inline u_long
464f1b665c8SPeter Wemm rcr4(void)
465f1b665c8SPeter Wemm {
466afa88623SPeter Wemm 	u_long	data;
467f1b665c8SPeter Wemm 
468afa88623SPeter Wemm 	__asm __volatile("movq %%cr4,%0" : "=r" (data));
469f1b665c8SPeter Wemm 	return (data);
470f1b665c8SPeter Wemm }
471f1b665c8SPeter Wemm 
4727574a595SJohn Baldwin static __inline u_long
4737574a595SJohn Baldwin rxcr(u_int reg)
4747574a595SJohn Baldwin {
4757574a595SJohn Baldwin 	u_int low, high;
4767574a595SJohn Baldwin 
4777574a595SJohn Baldwin 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
4787574a595SJohn Baldwin 	return (low | ((uint64_t)high << 32));
4797574a595SJohn Baldwin }
4807574a595SJohn Baldwin 
4817574a595SJohn Baldwin static __inline void
4827574a595SJohn Baldwin load_xcr(u_int reg, u_long val)
4837574a595SJohn Baldwin {
4847574a595SJohn Baldwin 	u_int low, high;
4857574a595SJohn Baldwin 
4867574a595SJohn Baldwin 	low = val;
4877574a595SJohn Baldwin 	high = val >> 32;
4887574a595SJohn Baldwin 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
4897574a595SJohn Baldwin }
4907574a595SJohn Baldwin 
491f1b665c8SPeter Wemm /*
492f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
493f1b665c8SPeter Wemm  */
494f1b665c8SPeter Wemm static __inline void
495f1b665c8SPeter Wemm invltlb(void)
496f1b665c8SPeter Wemm {
497f1b665c8SPeter Wemm 
498f1b665c8SPeter Wemm 	load_cr3(rcr3());
499f1b665c8SPeter Wemm }
500f1b665c8SPeter Wemm 
501e44af46eSJustin T. Gibbs #ifndef CR4_PGE
502e44af46eSJustin T. Gibbs #define	CR4_PGE	0x00000080	/* Page global enable */
503e44af46eSJustin T. Gibbs #endif
504e44af46eSJustin T. Gibbs 
505e44af46eSJustin T. Gibbs /*
506e44af46eSJustin T. Gibbs  * Perform the guaranteed invalidation of all TLB entries.  This
507e44af46eSJustin T. Gibbs  * includes the global entries, and entries in all PCIDs, not only the
508e44af46eSJustin T. Gibbs  * current context.  The function works both on non-PCID CPUs and CPUs
509e44af46eSJustin T. Gibbs  * with the PCID turned off or on.  See IA-32 SDM Vol. 3a 4.10.4.1
510e44af46eSJustin T. Gibbs  * Operations that Invalidate TLBs and Paging-Structure Caches.
511e44af46eSJustin T. Gibbs  */
512e44af46eSJustin T. Gibbs static __inline void
51327691a24SKonstantin Belousov invltlb_glob(void)
514e44af46eSJustin T. Gibbs {
515e44af46eSJustin T. Gibbs 	uint64_t cr4;
516e44af46eSJustin T. Gibbs 
517e44af46eSJustin T. Gibbs 	cr4 = rcr4();
518e44af46eSJustin T. Gibbs 	load_cr4(cr4 & ~CR4_PGE);
519e44af46eSJustin T. Gibbs 	/*
520e44af46eSJustin T. Gibbs 	 * Although preemption at this point could be detrimental to
521e44af46eSJustin T. Gibbs 	 * performance, it would not lead to an error.  PG_G is simply
522e44af46eSJustin T. Gibbs 	 * ignored if CR4.PGE is clear.  Moreover, in case this block
523e44af46eSJustin T. Gibbs 	 * is re-entered, the load_cr4() either above or below will
524e44af46eSJustin T. Gibbs 	 * modify CR4.PGE flushing the TLB.
525e44af46eSJustin T. Gibbs 	 */
526e44af46eSJustin T. Gibbs 	load_cr4(cr4 | CR4_PGE);
527e44af46eSJustin T. Gibbs }
528e44af46eSJustin T. Gibbs 
529f1b665c8SPeter Wemm /*
530f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
531f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
532f1b665c8SPeter Wemm  */
533f1b665c8SPeter Wemm static __inline void
534afa88623SPeter Wemm invlpg(u_long addr)
535f1b665c8SPeter Wemm {
536f1b665c8SPeter Wemm 
537f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
538f1b665c8SPeter Wemm }
539f1b665c8SPeter Wemm 
5405f5703efSKonstantin Belousov #define	INVPCID_ADDR	0
5415f5703efSKonstantin Belousov #define	INVPCID_CTX	1
5425f5703efSKonstantin Belousov #define	INVPCID_CTXGLOB	2
5435f5703efSKonstantin Belousov #define	INVPCID_ALLCTX	3
5445f5703efSKonstantin Belousov 
5455f5703efSKonstantin Belousov struct invpcid_descr {
5465f5703efSKonstantin Belousov 	uint64_t	pcid:12 __packed;
5475f5703efSKonstantin Belousov 	uint64_t	pad:52 __packed;
5485f5703efSKonstantin Belousov 	uint64_t	addr;
5495f5703efSKonstantin Belousov } __packed;
5505f5703efSKonstantin Belousov 
5515f5703efSKonstantin Belousov static __inline void
5525f5703efSKonstantin Belousov invpcid(struct invpcid_descr *d, int type)
5535f5703efSKonstantin Belousov {
5545f5703efSKonstantin Belousov 
555a546448bSKonstantin Belousov 	__asm __volatile("invpcid (%0),%1"
556a546448bSKonstantin Belousov 	    : : "r" (d), "r" ((u_long)type) : "memory");
5575f5703efSKonstantin Belousov }
5585f5703efSKonstantin Belousov 
55927d4fea6SRoman Divacky static __inline u_short
5605206bca1SLuoqi Chen rfs(void)
5615206bca1SLuoqi Chen {
56227d4fea6SRoman Divacky 	u_short sel;
56327d4fea6SRoman Divacky 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
5645206bca1SLuoqi Chen 	return (sel);
5655206bca1SLuoqi Chen }
5665206bca1SLuoqi Chen 
56727d4fea6SRoman Divacky static __inline u_short
5685206bca1SLuoqi Chen rgs(void)
5695206bca1SLuoqi Chen {
57027d4fea6SRoman Divacky 	u_short sel;
57127d4fea6SRoman Divacky 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
5725206bca1SLuoqi Chen 	return (sel);
5735206bca1SLuoqi Chen }
5745206bca1SLuoqi Chen 
57527d4fea6SRoman Divacky static __inline u_short
576cd0149e3SPeter Wemm rss(void)
577cd0149e3SPeter Wemm {
57827d4fea6SRoman Divacky 	u_short sel;
57927d4fea6SRoman Divacky 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
580cd0149e3SPeter Wemm 	return (sel);
581cd0149e3SPeter Wemm }
582cd0149e3SPeter Wemm 
5835206bca1SLuoqi Chen static __inline void
58427d4fea6SRoman Divacky load_ds(u_short sel)
585d85631c4SPeter Wemm {
58627d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%ds" : : "rm" (sel));
587d85631c4SPeter Wemm }
588d85631c4SPeter Wemm 
589d85631c4SPeter Wemm static __inline void
59027d4fea6SRoman Divacky load_es(u_short sel)
591d85631c4SPeter Wemm {
59227d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%es" : : "rm" (sel));
593d85631c4SPeter Wemm }
594d85631c4SPeter Wemm 
595beb2c1f3SAndriy Gapon static __inline void
596f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints)
59766247efaSJeff Roberson {
598f0b28f00SJung-uk Kim 
599f0b28f00SJung-uk Kim 	__asm __volatile("monitor"
60066247efaSJeff Roberson 	    : : "a" (addr), "c" (extensions), "d" (hints));
60166247efaSJeff Roberson }
60266247efaSJeff Roberson 
603beb2c1f3SAndriy Gapon static __inline void
604f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints)
60566247efaSJeff Roberson {
606f0b28f00SJung-uk Kim 
607f0b28f00SJung-uk Kim 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
60866247efaSJeff Roberson }
60966247efaSJeff Roberson 
6105ddeaf67SKonstantin Belousov static __inline uint32_t
6115ddeaf67SKonstantin Belousov rdpkru(void)
6125ddeaf67SKonstantin Belousov {
6135ddeaf67SKonstantin Belousov 	uint32_t res;
6145ddeaf67SKonstantin Belousov 
6155ddeaf67SKonstantin Belousov 	__asm __volatile("rdpkru" :  "=a" (res) : "c" (0) : "edx");
6165ddeaf67SKonstantin Belousov 	return (res);
6175ddeaf67SKonstantin Belousov }
6185ddeaf67SKonstantin Belousov 
6195ddeaf67SKonstantin Belousov static __inline void
6205ddeaf67SKonstantin Belousov wrpkru(uint32_t mask)
6215ddeaf67SKonstantin Belousov {
6225ddeaf67SKonstantin Belousov 
6235ddeaf67SKonstantin Belousov 	__asm __volatile("wrpkru" :  : "a" (mask),  "c" (0), "d" (0));
6245ddeaf67SKonstantin Belousov }
6255ddeaf67SKonstantin Belousov 
626c0a54ff6SPeter Wemm #ifdef _KERNEL
627c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */
628c0a54ff6SPeter Wemm #ifndef	MSR_FSBASE
629c0a54ff6SPeter Wemm #define	MSR_FSBASE	0xc0000100
630c0a54ff6SPeter Wemm #endif
631c0a54ff6SPeter Wemm static __inline void
63227d4fea6SRoman Divacky load_fs(u_short sel)
633c0a54ff6SPeter Wemm {
634c0a54ff6SPeter Wemm 	/* Preserve the fsbase value across the selector load */
63527d4fea6SRoman Divacky 	__asm __volatile("rdmsr; movw %0,%%fs; wrmsr"
636db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
637c0a54ff6SPeter Wemm }
638c0a54ff6SPeter Wemm 
639c0a54ff6SPeter Wemm #ifndef	MSR_GSBASE
640c0a54ff6SPeter Wemm #define	MSR_GSBASE	0xc0000101
641c0a54ff6SPeter Wemm #endif
642c0a54ff6SPeter Wemm static __inline void
64327d4fea6SRoman Divacky load_gs(u_short sel)
644c0a54ff6SPeter Wemm {
645c0a54ff6SPeter Wemm 	/*
646c0a54ff6SPeter Wemm 	 * Preserve the gsbase value across the selector load.
647c0a54ff6SPeter Wemm 	 * Note that we have to disable interrupts because the gsbase
648c0a54ff6SPeter Wemm 	 * being trashed happens to be the kernel gsbase at the time.
649c0a54ff6SPeter Wemm 	 */
65027d4fea6SRoman Divacky 	__asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
651db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
652c0a54ff6SPeter Wemm }
653c0a54ff6SPeter Wemm #else
654c0a54ff6SPeter Wemm /* Usable by userland */
655d85631c4SPeter Wemm static __inline void
65627d4fea6SRoman Divacky load_fs(u_short sel)
6575206bca1SLuoqi Chen {
65827d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
6595206bca1SLuoqi Chen }
6605206bca1SLuoqi Chen 
6615206bca1SLuoqi Chen static __inline void
66227d4fea6SRoman Divacky load_gs(u_short sel)
6635206bca1SLuoqi Chen {
66427d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
6655206bca1SLuoqi Chen }
666c0a54ff6SPeter Wemm #endif
6675206bca1SLuoqi Chen 
6680fd7ea1fSKonstantin Belousov static __inline uint64_t
6690fd7ea1fSKonstantin Belousov rdfsbase(void)
6700fd7ea1fSKonstantin Belousov {
6710fd7ea1fSKonstantin Belousov 	uint64_t x;
6720fd7ea1fSKonstantin Belousov 
6730fd7ea1fSKonstantin Belousov 	__asm __volatile("rdfsbase %0" : "=r" (x));
6740fd7ea1fSKonstantin Belousov 	return (x);
6750fd7ea1fSKonstantin Belousov }
6760fd7ea1fSKonstantin Belousov 
6770fd7ea1fSKonstantin Belousov static __inline void
6780fd7ea1fSKonstantin Belousov wrfsbase(uint64_t x)
6790fd7ea1fSKonstantin Belousov {
6800fd7ea1fSKonstantin Belousov 
6810fd7ea1fSKonstantin Belousov 	__asm __volatile("wrfsbase %0" : : "r" (x));
6820fd7ea1fSKonstantin Belousov }
6830fd7ea1fSKonstantin Belousov 
6840fd7ea1fSKonstantin Belousov static __inline uint64_t
6850fd7ea1fSKonstantin Belousov rdgsbase(void)
6860fd7ea1fSKonstantin Belousov {
6870fd7ea1fSKonstantin Belousov 	uint64_t x;
6880fd7ea1fSKonstantin Belousov 
6890fd7ea1fSKonstantin Belousov 	__asm __volatile("rdgsbase %0" : "=r" (x));
6900fd7ea1fSKonstantin Belousov 	return (x);
6910fd7ea1fSKonstantin Belousov }
6920fd7ea1fSKonstantin Belousov 
6930fd7ea1fSKonstantin Belousov static __inline void
6940fd7ea1fSKonstantin Belousov wrgsbase(uint64_t x)
6950fd7ea1fSKonstantin Belousov {
6960fd7ea1fSKonstantin Belousov 
6970fd7ea1fSKonstantin Belousov 	__asm __volatile("wrgsbase %0" : : "r" (x));
6980fd7ea1fSKonstantin Belousov }
6990fd7ea1fSKonstantin Belousov 
700eb1443c8SPeter Wemm static __inline void
701c1538a13SKonstantin Belousov bare_lgdt(struct region_descriptor *addr)
702c1538a13SKonstantin Belousov {
703c1538a13SKonstantin Belousov 	__asm __volatile("lgdt (%0)" : : "r" (addr));
704c1538a13SKonstantin Belousov }
705c1538a13SKonstantin Belousov 
706c1538a13SKonstantin Belousov static __inline void
707c1538a13SKonstantin Belousov sgdt(struct region_descriptor *addr)
708c1538a13SKonstantin Belousov {
709c1538a13SKonstantin Belousov 	char *loc;
710c1538a13SKonstantin Belousov 
711c1538a13SKonstantin Belousov 	loc = (char *)addr;
712c1538a13SKonstantin Belousov 	__asm __volatile("sgdt %0" : "=m" (*loc) : : "memory");
713c1538a13SKonstantin Belousov }
714c1538a13SKonstantin Belousov 
715c1538a13SKonstantin Belousov static __inline void
716eb1443c8SPeter Wemm lidt(struct region_descriptor *addr)
717eb1443c8SPeter Wemm {
718eb1443c8SPeter Wemm 	__asm __volatile("lidt (%0)" : : "r" (addr));
719eb1443c8SPeter Wemm }
720eb1443c8SPeter Wemm 
721eb1443c8SPeter Wemm static __inline void
722c1538a13SKonstantin Belousov sidt(struct region_descriptor *addr)
723c1538a13SKonstantin Belousov {
724c1538a13SKonstantin Belousov 	char *loc;
725c1538a13SKonstantin Belousov 
726c1538a13SKonstantin Belousov 	loc = (char *)addr;
727c1538a13SKonstantin Belousov 	__asm __volatile("sidt %0" : "=m" (*loc) : : "memory");
728c1538a13SKonstantin Belousov }
729c1538a13SKonstantin Belousov 
730c1538a13SKonstantin Belousov static __inline void
731eb1443c8SPeter Wemm lldt(u_short sel)
732eb1443c8SPeter Wemm {
733eb1443c8SPeter Wemm 	__asm __volatile("lldt %0" : : "r" (sel));
734eb1443c8SPeter Wemm }
735eb1443c8SPeter Wemm 
736b843f9beSJohn Baldwin static __inline u_short
737b843f9beSJohn Baldwin sldt(void)
738b843f9beSJohn Baldwin {
739b843f9beSJohn Baldwin 	u_short sel;
740b843f9beSJohn Baldwin 
741b843f9beSJohn Baldwin 	__asm __volatile("sldt %0" : "=r" (sel));
742b843f9beSJohn Baldwin 	return (sel);
743b843f9beSJohn Baldwin }
744b843f9beSJohn Baldwin 
745eb1443c8SPeter Wemm static __inline void
746eb1443c8SPeter Wemm ltr(u_short sel)
747eb1443c8SPeter Wemm {
748eb1443c8SPeter Wemm 	__asm __volatile("ltr %0" : : "r" (sel));
749eb1443c8SPeter Wemm }
750eb1443c8SPeter Wemm 
751c1538a13SKonstantin Belousov static __inline uint32_t
752c1538a13SKonstantin Belousov read_tr(void)
753c1538a13SKonstantin Belousov {
754c1538a13SKonstantin Belousov 	u_short sel;
755c1538a13SKonstantin Belousov 
756c1538a13SKonstantin Belousov 	__asm __volatile("str %0" : "=r" (sel));
757c1538a13SKonstantin Belousov 	return (sel);
758c1538a13SKonstantin Belousov }
759c1538a13SKonstantin Belousov 
760f5ac47f4SJung-uk Kim static __inline uint64_t
7611182b177SPeter Wemm rdr0(void)
7621182b177SPeter Wemm {
763f5ac47f4SJung-uk Kim 	uint64_t data;
7641182b177SPeter Wemm 	__asm __volatile("movq %%dr0,%0" : "=r" (data));
7651182b177SPeter Wemm 	return (data);
7661182b177SPeter Wemm }
7671182b177SPeter Wemm 
7681182b177SPeter Wemm static __inline void
769f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0)
7701182b177SPeter Wemm {
7711182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
7721182b177SPeter Wemm }
7731182b177SPeter Wemm 
774f5ac47f4SJung-uk Kim static __inline uint64_t
7751182b177SPeter Wemm rdr1(void)
7761182b177SPeter Wemm {
777f5ac47f4SJung-uk Kim 	uint64_t data;
7781182b177SPeter Wemm 	__asm __volatile("movq %%dr1,%0" : "=r" (data));
7791182b177SPeter Wemm 	return (data);
7801182b177SPeter Wemm }
7811182b177SPeter Wemm 
7821182b177SPeter Wemm static __inline void
783f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1)
7841182b177SPeter Wemm {
7851182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
7861182b177SPeter Wemm }
7871182b177SPeter Wemm 
788f5ac47f4SJung-uk Kim static __inline uint64_t
7891182b177SPeter Wemm rdr2(void)
7901182b177SPeter Wemm {
791f5ac47f4SJung-uk Kim 	uint64_t data;
7921182b177SPeter Wemm 	__asm __volatile("movq %%dr2,%0" : "=r" (data));
7931182b177SPeter Wemm 	return (data);
7941182b177SPeter Wemm }
7951182b177SPeter Wemm 
7961182b177SPeter Wemm static __inline void
797f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2)
7981182b177SPeter Wemm {
7991182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
8001182b177SPeter Wemm }
8011182b177SPeter Wemm 
802f5ac47f4SJung-uk Kim static __inline uint64_t
8031182b177SPeter Wemm rdr3(void)
8041182b177SPeter Wemm {
805f5ac47f4SJung-uk Kim 	uint64_t data;
8061182b177SPeter Wemm 	__asm __volatile("movq %%dr3,%0" : "=r" (data));
8071182b177SPeter Wemm 	return (data);
8081182b177SPeter Wemm }
8091182b177SPeter Wemm 
8101182b177SPeter Wemm static __inline void
811f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3)
8121182b177SPeter Wemm {
8131182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
8141182b177SPeter Wemm }
8151182b177SPeter Wemm 
816f5ac47f4SJung-uk Kim static __inline uint64_t
8171182b177SPeter Wemm rdr6(void)
8181182b177SPeter Wemm {
819f5ac47f4SJung-uk Kim 	uint64_t data;
8201182b177SPeter Wemm 	__asm __volatile("movq %%dr6,%0" : "=r" (data));
8211182b177SPeter Wemm 	return (data);
8221182b177SPeter Wemm }
8231182b177SPeter Wemm 
8241182b177SPeter Wemm static __inline void
825f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6)
8261182b177SPeter Wemm {
8271182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
8281182b177SPeter Wemm }
8291182b177SPeter Wemm 
830f5ac47f4SJung-uk Kim static __inline uint64_t
8311182b177SPeter Wemm rdr7(void)
8321182b177SPeter Wemm {
833f5ac47f4SJung-uk Kim 	uint64_t data;
8341182b177SPeter Wemm 	__asm __volatile("movq %%dr7,%0" : "=r" (data));
8351182b177SPeter Wemm 	return (data);
8361182b177SPeter Wemm }
8371182b177SPeter Wemm 
8381182b177SPeter Wemm static __inline void
839f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7)
8401182b177SPeter Wemm {
8411182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
8421182b177SPeter Wemm }
8431182b177SPeter Wemm 
844ba74981eSWarner Losh static __inline register_t
845ba74981eSWarner Losh intr_disable(void)
846ba74981eSWarner Losh {
847afa88623SPeter Wemm 	register_t rflags;
848ba74981eSWarner Losh 
849afa88623SPeter Wemm 	rflags = read_rflags();
850ba74981eSWarner Losh 	disable_intr();
851afa88623SPeter Wemm 	return (rflags);
852ba74981eSWarner Losh }
853ba74981eSWarner Losh 
854ba74981eSWarner Losh static __inline void
855afa88623SPeter Wemm intr_restore(register_t rflags)
856ba74981eSWarner Losh {
857afa88623SPeter Wemm 	write_rflags(rflags);
858ba74981eSWarner Losh }
859ba74981eSWarner Losh 
8605f7b9ff2SKonstantin Belousov static __inline void
8615f7b9ff2SKonstantin Belousov stac(void)
8625f7b9ff2SKonstantin Belousov {
8635f7b9ff2SKonstantin Belousov 
8645f7b9ff2SKonstantin Belousov 	__asm __volatile("stac" : : : "cc");
8655f7b9ff2SKonstantin Belousov }
8665f7b9ff2SKonstantin Belousov 
8675f7b9ff2SKonstantin Belousov static __inline void
8685f7b9ff2SKonstantin Belousov clac(void)
8695f7b9ff2SKonstantin Belousov {
8705f7b9ff2SKonstantin Belousov 
8715f7b9ff2SKonstantin Belousov 	__asm __volatile("clac" : : : "cc");
8725f7b9ff2SKonstantin Belousov }
8735f7b9ff2SKonstantin Belousov 
8742164af29SRuslan Bukin enum {
8752164af29SRuslan Bukin 	SGX_ECREATE	= 0x0,
8762164af29SRuslan Bukin 	SGX_EADD	= 0x1,
8772164af29SRuslan Bukin 	SGX_EINIT	= 0x2,
8782164af29SRuslan Bukin 	SGX_EREMOVE	= 0x3,
8792164af29SRuslan Bukin 	SGX_EDGBRD	= 0x4,
8802164af29SRuslan Bukin 	SGX_EDGBWR	= 0x5,
8812164af29SRuslan Bukin 	SGX_EEXTEND	= 0x6,
8822164af29SRuslan Bukin 	SGX_ELDU	= 0x8,
8832164af29SRuslan Bukin 	SGX_EBLOCK	= 0x9,
8842164af29SRuslan Bukin 	SGX_EPA		= 0xA,
8852164af29SRuslan Bukin 	SGX_EWB		= 0xB,
8862164af29SRuslan Bukin 	SGX_ETRACK	= 0xC,
8872164af29SRuslan Bukin };
8882164af29SRuslan Bukin 
8892164af29SRuslan Bukin enum {
8902164af29SRuslan Bukin 	SGX_PT_SECS = 0x00,
8912164af29SRuslan Bukin 	SGX_PT_TCS  = 0x01,
8922164af29SRuslan Bukin 	SGX_PT_REG  = 0x02,
8932164af29SRuslan Bukin 	SGX_PT_VA   = 0x03,
8942164af29SRuslan Bukin 	SGX_PT_TRIM = 0x04,
8952164af29SRuslan Bukin };
8962164af29SRuslan Bukin 
8972164af29SRuslan Bukin int sgx_encls(uint32_t eax, uint64_t rbx, uint64_t rcx, uint64_t rdx);
8982164af29SRuslan Bukin 
8992164af29SRuslan Bukin static __inline int
9002164af29SRuslan Bukin sgx_ecreate(void *pginfo, void *secs)
9012164af29SRuslan Bukin {
9022164af29SRuslan Bukin 
9032164af29SRuslan Bukin 	return (sgx_encls(SGX_ECREATE, (uint64_t)pginfo,
9042164af29SRuslan Bukin 	    (uint64_t)secs, 0));
9052164af29SRuslan Bukin }
9062164af29SRuslan Bukin 
9072164af29SRuslan Bukin static __inline int
9082164af29SRuslan Bukin sgx_eadd(void *pginfo, void *epc)
9092164af29SRuslan Bukin {
9102164af29SRuslan Bukin 
9112164af29SRuslan Bukin 	return (sgx_encls(SGX_EADD, (uint64_t)pginfo,
9122164af29SRuslan Bukin 	    (uint64_t)epc, 0));
9132164af29SRuslan Bukin }
9142164af29SRuslan Bukin 
9152164af29SRuslan Bukin static __inline int
9162164af29SRuslan Bukin sgx_einit(void *sigstruct, void *secs, void *einittoken)
9172164af29SRuslan Bukin {
9182164af29SRuslan Bukin 
9192164af29SRuslan Bukin 	return (sgx_encls(SGX_EINIT, (uint64_t)sigstruct,
9202164af29SRuslan Bukin 	    (uint64_t)secs, (uint64_t)einittoken));
9212164af29SRuslan Bukin }
9222164af29SRuslan Bukin 
9232164af29SRuslan Bukin static __inline int
9242164af29SRuslan Bukin sgx_eextend(void *secs, void *epc)
9252164af29SRuslan Bukin {
9262164af29SRuslan Bukin 
9272164af29SRuslan Bukin 	return (sgx_encls(SGX_EEXTEND, (uint64_t)secs,
9282164af29SRuslan Bukin 	    (uint64_t)epc, 0));
9292164af29SRuslan Bukin }
9302164af29SRuslan Bukin 
9312164af29SRuslan Bukin static __inline int
9322164af29SRuslan Bukin sgx_epa(void *epc)
9332164af29SRuslan Bukin {
9342164af29SRuslan Bukin 
9352164af29SRuslan Bukin 	return (sgx_encls(SGX_EPA, SGX_PT_VA, (uint64_t)epc, 0));
9362164af29SRuslan Bukin }
9372164af29SRuslan Bukin 
9382164af29SRuslan Bukin static __inline int
9392164af29SRuslan Bukin sgx_eldu(uint64_t rbx, uint64_t rcx,
9402164af29SRuslan Bukin     uint64_t rdx)
9412164af29SRuslan Bukin {
9422164af29SRuslan Bukin 
9432164af29SRuslan Bukin 	return (sgx_encls(SGX_ELDU, rbx, rcx, rdx));
9442164af29SRuslan Bukin }
9452164af29SRuslan Bukin 
9462164af29SRuslan Bukin static __inline int
9472164af29SRuslan Bukin sgx_eremove(void *epc)
9482164af29SRuslan Bukin {
9492164af29SRuslan Bukin 
9502164af29SRuslan Bukin 	return (sgx_encls(SGX_EREMOVE, 0, (uint64_t)epc, 0));
9512164af29SRuslan Bukin }
9522164af29SRuslan Bukin 
953a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */
9545b81b6b3SRodney W. Grimes 
955b63dc6adSAlfred Perlstein int	breakpoint(void);
956b63dc6adSAlfred Perlstein u_int	bsfl(u_int mask);
957b63dc6adSAlfred Perlstein u_int	bsrl(u_int mask);
958d706ec29SJohn Baldwin void	clflush(u_long addr);
959d706ec29SJohn Baldwin void	clts(void);
960d706ec29SJohn Baldwin void	cpuid_count(u_int ax, u_int cx, u_int *p);
961b63dc6adSAlfred Perlstein void	disable_intr(void);
962b63dc6adSAlfred Perlstein void	do_cpuid(u_int ax, u_int *p);
963b63dc6adSAlfred Perlstein void	enable_intr(void);
964d7ee4425SMark Murray void	halt(void);
9654f6c19e5SPeter Wemm void	ia32_pause(void);
966b63dc6adSAlfred Perlstein u_char	inb(u_int port);
967b63dc6adSAlfred Perlstein u_int	inl(u_int port);
96893d8be03SDavid E. O'Brien void	insb(u_int port, void *addr, size_t count);
96993d8be03SDavid E. O'Brien void	insl(u_int port, void *addr, size_t count);
97093d8be03SDavid E. O'Brien void	insw(u_int port, void *addr, size_t count);
9714f6c19e5SPeter Wemm register_t	intr_disable(void);
9724f6c19e5SPeter Wemm void	intr_restore(register_t rf);
973b63dc6adSAlfred Perlstein void	invd(void);
974b63dc6adSAlfred Perlstein void	invlpg(u_int addr);
975b63dc6adSAlfred Perlstein void	invltlb(void);
976b63dc6adSAlfred Perlstein u_short	inw(u_int port);
977eb1443c8SPeter Wemm void	lidt(struct region_descriptor *addr);
978eb1443c8SPeter Wemm void	lldt(u_short sel);
9794f6c19e5SPeter Wemm void	load_cr0(u_long cr0);
9804f6c19e5SPeter Wemm void	load_cr3(u_long cr3);
9814f6c19e5SPeter Wemm void	load_cr4(u_long cr4);
982f5ac47f4SJung-uk Kim void	load_dr0(uint64_t dr0);
983f5ac47f4SJung-uk Kim void	load_dr1(uint64_t dr1);
984f5ac47f4SJung-uk Kim void	load_dr2(uint64_t dr2);
985f5ac47f4SJung-uk Kim void	load_dr3(uint64_t dr3);
986f5ac47f4SJung-uk Kim void	load_dr6(uint64_t dr6);
987f5ac47f4SJung-uk Kim void	load_dr7(uint64_t dr7);
98827d4fea6SRoman Divacky void	load_fs(u_short sel);
98927d4fea6SRoman Divacky void	load_gs(u_short sel);
990eb1443c8SPeter Wemm void	ltr(u_short sel);
991b63dc6adSAlfred Perlstein void	outb(u_int port, u_char data);
992b63dc6adSAlfred Perlstein void	outl(u_int port, u_int data);
99393d8be03SDavid E. O'Brien void	outsb(u_int port, const void *addr, size_t count);
99493d8be03SDavid E. O'Brien void	outsl(u_int port, const void *addr, size_t count);
99593d8be03SDavid E. O'Brien void	outsw(u_int port, const void *addr, size_t count);
996b63dc6adSAlfred Perlstein void	outw(u_int port, u_short data);
9974f6c19e5SPeter Wemm u_long	rcr0(void);
9984f6c19e5SPeter Wemm u_long	rcr2(void);
9994f6c19e5SPeter Wemm u_long	rcr3(void);
10004f6c19e5SPeter Wemm u_long	rcr4(void);
1001f5ac47f4SJung-uk Kim uint64_t rdmsr(u_int msr);
10024c918926SKonstantin Belousov uint32_t rdmsr32(u_int msr);
1003f5ac47f4SJung-uk Kim uint64_t rdpmc(u_int pmc);
1004f5ac47f4SJung-uk Kim uint64_t rdr0(void);
1005f5ac47f4SJung-uk Kim uint64_t rdr1(void);
1006f5ac47f4SJung-uk Kim uint64_t rdr2(void);
1007f5ac47f4SJung-uk Kim uint64_t rdr3(void);
1008f5ac47f4SJung-uk Kim uint64_t rdr6(void);
1009f5ac47f4SJung-uk Kim uint64_t rdr7(void);
1010f5ac47f4SJung-uk Kim uint64_t rdtsc(void);
1011a61dd1bdSJohn Baldwin u_long	read_rflags(void);
10124f6c19e5SPeter Wemm u_int	rfs(void);
10134f6c19e5SPeter Wemm u_int	rgs(void);
1014b63dc6adSAlfred Perlstein void	wbinvd(void);
1015afa88623SPeter Wemm void	write_rflags(u_int rf);
1016f5ac47f4SJung-uk Kim void	wrmsr(u_int msr, uint64_t newval);
1017004bedebSBruce Evans 
1018a5f50ef9SJoerg Wunsch #endif	/* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */
10195b81b6b3SRodney W. Grimes 
1020b63dc6adSAlfred Perlstein void	reset_dbregs(void);
1021d74ac681SMatthew Dillon 
1022e085f869SStanislav Sedov #ifdef _KERNEL
1023e085f869SStanislav Sedov int	rdmsr_safe(u_int msr, uint64_t *val);
1024e085f869SStanislav Sedov int	wrmsr_safe(u_int msr, uint64_t newval);
1025e085f869SStanislav Sedov #endif
1026e085f869SStanislav Sedov 
1027004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
1028