xref: /freebsd/sys/amd64/include/cpufunc.h (revision cca19272611dac7ac1ac3ae4c457ce5cb6c38cff)
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 
41*cca19272SBrooks Davis #ifdef __i386__
42*cca19272SBrooks Davis #include <i386/cpufunc.h>
43*cca19272SBrooks Davis #else /* !__i386__ */
44*cca19272SBrooks Davis 
456e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
46004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
476e393973SGarrett Wollman 
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 
605dbd168eSBruce Evans static __inline void
615dbd168eSBruce Evans breakpoint(void)
62004bedebSBruce Evans {
63004bedebSBruce Evans 	__asm __volatile("int $3");
645b81b6b3SRodney W. Grimes }
655b81b6b3SRodney W. Grimes 
66aae89f6fSMateusz Guzik #define	bsfl(mask)	__builtin_ctz(mask)
67c83b1328SBruce Evans 
68aae89f6fSMateusz Guzik #define	bsfq(mask)	__builtin_ctzl(mask)
69c83b1328SBruce Evans 
70aae89f6fSMateusz Guzik #define	bsrl(mask)	(__builtin_clz(mask) ^ 0x1f)
71176ce2b1SPeter Wemm 
72aae89f6fSMateusz Guzik #define	bsrq(mask)	(__builtin_clzl(mask) ^ 0x3f)
73176ce2b1SPeter Wemm 
74004bedebSBruce Evans static __inline void
75206a3368SKonstantin Belousov clflush(u_long addr)
76206a3368SKonstantin Belousov {
77206a3368SKonstantin Belousov 
78206a3368SKonstantin Belousov 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
79206a3368SKonstantin Belousov }
80206a3368SKonstantin Belousov 
81206a3368SKonstantin Belousov static __inline void
823f8e0710SKonstantin Belousov clflushopt(u_long addr)
833f8e0710SKonstantin Belousov {
843f8e0710SKonstantin Belousov 
853f8e0710SKonstantin Belousov 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
863f8e0710SKonstantin Belousov }
873f8e0710SKonstantin Belousov 
883f8e0710SKonstantin Belousov static __inline void
899d5d89b2SKonstantin Belousov clwb(u_long addr)
909d5d89b2SKonstantin Belousov {
919d5d89b2SKonstantin Belousov 
929d5d89b2SKonstantin Belousov 	__asm __volatile("clwb %0" : : "m" (*(char *)addr));
939d5d89b2SKonstantin Belousov }
949d5d89b2SKonstantin Belousov 
959d5d89b2SKonstantin Belousov static __inline void
96d706ec29SJohn Baldwin clts(void)
97d706ec29SJohn Baldwin {
98d706ec29SJohn Baldwin 
99d706ec29SJohn Baldwin 	__asm __volatile("clts");
100d706ec29SJohn Baldwin }
101d706ec29SJohn Baldwin 
102d706ec29SJohn Baldwin 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
117f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p)
118f6108b61SJacques Vidrine {
119f6108b61SJacques Vidrine 	__asm __volatile("cpuid"
120f6108b61SJacques Vidrine 	    : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
121f6108b61SJacques Vidrine 	    :  "0" (ax), "c" (cx));
122f6108b61SJacques Vidrine }
123f6108b61SJacques Vidrine 
124f6108b61SJacques Vidrine static __inline void
1255b81b6b3SRodney W. Grimes enable_intr(void)
1265b81b6b3SRodney W. Grimes {
127fadc51bdSBruce Evans 	__asm __volatile("sti");
1285b81b6b3SRodney W. Grimes }
1295b81b6b3SRodney W. Grimes 
130a67ef0a7SBruce Evans #ifdef _KERNEL
131a67ef0a7SBruce Evans 
132264c3d87SPeter Wemm #define	HAVE_INLINE_FFS
133bc35f5dcSPaul Saab #define	ffs(x)		__builtin_ffs(x)
134176ce2b1SPeter Wemm 
135176ce2b1SPeter Wemm #define	HAVE_INLINE_FFSL
13637bd3aa6SMateusz Guzik #define	ffsl(x)		__builtin_ffsl(x)
137004bedebSBruce Evans 
138f25e50cfSAndriy Gapon #define	HAVE_INLINE_FFSLL
13937bd3aa6SMateusz Guzik #define	ffsll(x)	__builtin_ffsll(x)
140f25e50cfSAndriy Gapon 
14113f588f8SGarrett Wollman #define	HAVE_INLINE_FLS
14213f588f8SGarrett Wollman 
1436f240e18SConrad Meyer static __inline __pure2 int
14413f588f8SGarrett Wollman fls(int mask)
14513f588f8SGarrett Wollman {
1467e622d3cSMark Murray 	return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
14713f588f8SGarrett Wollman }
14813f588f8SGarrett Wollman 
149176ce2b1SPeter Wemm #define	HAVE_INLINE_FLSL
150176ce2b1SPeter Wemm 
1516f240e18SConrad Meyer static __inline __pure2 int
152176ce2b1SPeter Wemm flsl(long mask)
153176ce2b1SPeter Wemm {
154176ce2b1SPeter Wemm 	return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1);
155176ce2b1SPeter Wemm }
156176ce2b1SPeter Wemm 
157f25e50cfSAndriy Gapon #define	HAVE_INLINE_FLSLL
158f25e50cfSAndriy Gapon 
1596f240e18SConrad Meyer static __inline __pure2 int
160f25e50cfSAndriy Gapon flsll(long long mask)
161f25e50cfSAndriy Gapon {
162f25e50cfSAndriy Gapon 	return (flsl((long)mask));
163f25e50cfSAndriy Gapon }
164f25e50cfSAndriy Gapon 
165a67ef0a7SBruce Evans #endif /* _KERNEL */
166a67ef0a7SBruce Evans 
167d7ee4425SMark Murray static __inline void
168d7ee4425SMark Murray halt(void)
169d7ee4425SMark Murray {
170d7ee4425SMark Murray 	__asm __volatile("hlt");
171d7ee4425SMark Murray }
172d7ee4425SMark Murray 
173004bedebSBruce Evans static __inline u_char
174e1048f76SEd Schouten inb(u_int port)
175004bedebSBruce Evans {
176004bedebSBruce Evans 	u_char	data;
177004bedebSBruce Evans 
1784854ae24SJung-uk Kim 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
179004bedebSBruce Evans 	return (data);
180004bedebSBruce Evans }
181004bedebSBruce Evans 
18200be8601SBruce Evans static __inline u_int
183004bedebSBruce Evans inl(u_int port)
184004bedebSBruce Evans {
18500be8601SBruce Evans 	u_int	data;
186004bedebSBruce Evans 
1874854ae24SJung-uk Kim 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
188004bedebSBruce Evans 	return (data);
189004bedebSBruce Evans }
190004bedebSBruce Evans 
191004bedebSBruce Evans static __inline void
19293d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count)
193004bedebSBruce Evans {
194fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insb"
19593d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
1963f9a462fSJohn Baldwin 			 : "d" (port)
197896763faSBruce Evans 			 : "memory");
198004bedebSBruce Evans }
199004bedebSBruce Evans 
200004bedebSBruce Evans static __inline void
20193d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count)
202004bedebSBruce Evans {
203fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insw"
20493d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2053f9a462fSJohn Baldwin 			 : "d" (port)
206896763faSBruce Evans 			 : "memory");
207004bedebSBruce Evans }
208004bedebSBruce Evans 
209004bedebSBruce Evans static __inline void
21093d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count)
211004bedebSBruce Evans {
212fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insl"
21393d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
2143f9a462fSJohn Baldwin 			 : "d" (port)
215896763faSBruce Evans 			 : "memory");
216004bedebSBruce Evans }
217004bedebSBruce Evans 
218ece15d78SBruce Evans static __inline void
2194c024bbdSKATO Takenori invd(void)
2204c024bbdSKATO Takenori {
2214c024bbdSKATO Takenori 	__asm __volatile("invd");
2224c024bbdSKATO Takenori }
2234c024bbdSKATO Takenori 
224004bedebSBruce Evans static __inline u_short
225004bedebSBruce Evans inw(u_int port)
226004bedebSBruce Evans {
227004bedebSBruce Evans 	u_short	data;
228004bedebSBruce Evans 
2294854ae24SJung-uk Kim 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
230004bedebSBruce Evans 	return (data);
231004bedebSBruce Evans }
232004bedebSBruce Evans 
233004bedebSBruce Evans static __inline void
234e1048f76SEd Schouten outb(u_int port, u_char data)
235004bedebSBruce Evans {
2364854ae24SJung-uk Kim 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
237004bedebSBruce Evans }
238004bedebSBruce Evans 
239004bedebSBruce Evans static __inline void
24000be8601SBruce Evans outl(u_int port, u_int data)
241004bedebSBruce Evans {
2424854ae24SJung-uk Kim 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
243004bedebSBruce Evans }
244004bedebSBruce Evans 
245004bedebSBruce Evans static __inline void
24693d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count)
247004bedebSBruce Evans {
248fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsb"
24993d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2503f9a462fSJohn Baldwin 			 : "d" (port));
251004bedebSBruce Evans }
252004bedebSBruce Evans 
253004bedebSBruce Evans static __inline void
25493d8be03SDavid E. O'Brien outsw(u_int port, const void *addr, size_t count)
255004bedebSBruce Evans {
256fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsw"
25793d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2583f9a462fSJohn Baldwin 			 : "d" (port));
259004bedebSBruce Evans }
260004bedebSBruce Evans 
261004bedebSBruce Evans static __inline void
26293d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count)
263004bedebSBruce Evans {
264fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsl"
26593d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2663f9a462fSJohn Baldwin 			 : "d" (port));
267004bedebSBruce Evans }
268004bedebSBruce Evans 
269004bedebSBruce Evans static __inline void
270004bedebSBruce Evans outw(u_int port, u_short data)
271004bedebSBruce Evans {
2724854ae24SJung-uk Kim 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
273004bedebSBruce Evans }
274004bedebSBruce Evans 
2752bde6e35SAlan Cox static __inline u_long
2762bde6e35SAlan Cox popcntq(u_long mask)
2772bde6e35SAlan Cox {
2782bde6e35SAlan Cox 	u_long result;
2792bde6e35SAlan Cox 
2802bde6e35SAlan Cox 	__asm __volatile("popcntq %1,%0" : "=r" (result) : "rm" (mask));
2812bde6e35SAlan Cox 	return (result);
2822bde6e35SAlan Cox }
2832bde6e35SAlan Cox 
2842be69f32SJohn Baldwin static __inline void
2850220d04fSKonstantin Belousov lfence(void)
2860220d04fSKonstantin Belousov {
2870220d04fSKonstantin Belousov 
2880220d04fSKonstantin Belousov 	__asm __volatile("lfence" : : : "memory");
2890220d04fSKonstantin Belousov }
2900220d04fSKonstantin Belousov 
2910220d04fSKonstantin Belousov static __inline void
292206a3368SKonstantin Belousov mfence(void)
293206a3368SKonstantin Belousov {
294206a3368SKonstantin Belousov 
295beb2c1f3SAndriy Gapon 	__asm __volatile("mfence" : : : "memory");
296206a3368SKonstantin Belousov }
297206a3368SKonstantin Belousov 
298206a3368SKonstantin Belousov static __inline void
2995611aaa1SKonstantin Belousov sfence(void)
3005611aaa1SKonstantin Belousov {
3015611aaa1SKonstantin Belousov 
3025611aaa1SKonstantin Belousov 	__asm __volatile("sfence" : : : "memory");
3035611aaa1SKonstantin Belousov }
3045611aaa1SKonstantin Belousov 
3055611aaa1SKonstantin Belousov static __inline void
3066b8c6989SJohn Baldwin ia32_pause(void)
3072be69f32SJohn Baldwin {
3082be69f32SJohn Baldwin 	__asm __volatile("pause");
3092be69f32SJohn Baldwin }
3102be69f32SJohn Baldwin 
311afa88623SPeter Wemm static __inline u_long
312afa88623SPeter Wemm read_rflags(void)
3135b81b6b3SRodney W. Grimes {
314afa88623SPeter Wemm 	u_long	rf;
315004bedebSBruce Evans 
316afa88623SPeter Wemm 	__asm __volatile("pushfq; popq %0" : "=r" (rf));
317afa88623SPeter Wemm 	return (rf);
3185b81b6b3SRodney W. Grimes }
3195b81b6b3SRodney W. Grimes 
320f5ac47f4SJung-uk Kim static __inline uint64_t
3215dbd168eSBruce Evans rdmsr(u_int msr)
3225dbd168eSBruce Evans {
323f5ac47f4SJung-uk Kim 	uint32_t low, high;
3245dbd168eSBruce Evans 
325afa88623SPeter Wemm 	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
326f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3275dbd168eSBruce Evans }
3285dbd168eSBruce Evans 
3294c918926SKonstantin Belousov static __inline uint32_t
3304c918926SKonstantin Belousov rdmsr32(u_int msr)
3314c918926SKonstantin Belousov {
3324c918926SKonstantin Belousov 	uint32_t low;
3334c918926SKonstantin Belousov 
3344c918926SKonstantin Belousov 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "rdx");
3354c918926SKonstantin Belousov 	return (low);
3364c918926SKonstantin Belousov }
3374c918926SKonstantin Belousov 
338f5ac47f4SJung-uk Kim static __inline uint64_t
3395dbd168eSBruce Evans rdpmc(u_int pmc)
3405dbd168eSBruce Evans {
341f5ac47f4SJung-uk Kim 	uint32_t low, high;
3425dbd168eSBruce Evans 
343afa88623SPeter Wemm 	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
344f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3455dbd168eSBruce Evans }
3465dbd168eSBruce Evans 
347f5ac47f4SJung-uk Kim static __inline uint64_t
3485dbd168eSBruce Evans rdtsc(void)
3495dbd168eSBruce Evans {
350f5ac47f4SJung-uk Kim 	uint32_t low, high;
3515dbd168eSBruce Evans 
352afa88623SPeter Wemm 	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
353f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3545dbd168eSBruce Evans }
3555dbd168eSBruce Evans 
35615504639SMatt Macy static __inline uint64_t
357652ae7b1SAdam Fenn rdtsc_ordered_lfence(void)
358652ae7b1SAdam Fenn {
359652ae7b1SAdam Fenn 	lfence();
360652ae7b1SAdam Fenn 	return (rdtsc());
361652ae7b1SAdam Fenn }
362652ae7b1SAdam Fenn 
363652ae7b1SAdam Fenn static __inline uint64_t
364652ae7b1SAdam Fenn rdtsc_ordered_mfence(void)
365652ae7b1SAdam Fenn {
366652ae7b1SAdam Fenn 	mfence();
367652ae7b1SAdam Fenn 	return (rdtsc());
368652ae7b1SAdam Fenn }
369652ae7b1SAdam Fenn 
370652ae7b1SAdam Fenn static __inline uint64_t
37115504639SMatt Macy rdtscp(void)
37215504639SMatt Macy {
37315504639SMatt Macy 	uint32_t low, high;
37415504639SMatt Macy 
375f090f675SMark Johnston 	__asm __volatile("rdtscp" : "=a" (low), "=d" (high) : : "ecx");
37615504639SMatt Macy 	return (low | ((uint64_t)high << 32));
37715504639SMatt Macy }
37815504639SMatt Macy 
379908e2772SAdam Fenn static __inline uint64_t
380908e2772SAdam Fenn rdtscp_aux(uint32_t *aux)
381908e2772SAdam Fenn {
382908e2772SAdam Fenn 	uint32_t low, high;
383908e2772SAdam Fenn 
384908e2772SAdam Fenn 	__asm __volatile("rdtscp" : "=a" (low), "=d" (high), "=c" (*aux));
385908e2772SAdam Fenn 	return (low | ((uint64_t)high << 32));
386908e2772SAdam Fenn }
387908e2772SAdam Fenn 
3880e727642SJung-uk Kim static __inline uint32_t
3890e727642SJung-uk Kim rdtsc32(void)
3900e727642SJung-uk Kim {
3910e727642SJung-uk Kim 	uint32_t rv;
3920e727642SJung-uk Kim 
3930e727642SJung-uk Kim 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
3940e727642SJung-uk Kim 	return (rv);
3950e727642SJung-uk Kim }
3960e727642SJung-uk Kim 
39745974de8SKonstantin Belousov static __inline uint32_t
39845974de8SKonstantin Belousov rdtscp32(void)
39945974de8SKonstantin Belousov {
40045974de8SKonstantin Belousov 	uint32_t rv;
40145974de8SKonstantin Belousov 
40245974de8SKonstantin Belousov 	__asm __volatile("rdtscp" : "=a" (rv) : : "ecx", "edx");
40345974de8SKonstantin Belousov 	return (rv);
40445974de8SKonstantin Belousov }
40545974de8SKonstantin Belousov 
406004bedebSBruce Evans static __inline void
4074c024bbdSKATO Takenori wbinvd(void)
4084c024bbdSKATO Takenori {
4094c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
4104c024bbdSKATO Takenori }
4114c024bbdSKATO Takenori 
4124c024bbdSKATO Takenori static __inline void
413afa88623SPeter Wemm write_rflags(u_long rf)
4145b81b6b3SRodney W. Grimes {
415afa88623SPeter Wemm 	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
4165b81b6b3SRodney W. Grimes }
4175b81b6b3SRodney W. Grimes 
418d69e8502SGarrett Wollman static __inline void
419f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval)
420d69e8502SGarrett Wollman {
421f5ac47f4SJung-uk Kim 	uint32_t low, high;
422afa88623SPeter Wemm 
423afa88623SPeter Wemm 	low = newval;
424afa88623SPeter Wemm 	high = newval >> 32;
425afa88623SPeter Wemm 	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
426d69e8502SGarrett Wollman }
427d69e8502SGarrett Wollman 
428f1b665c8SPeter Wemm static __inline void
429afa88623SPeter Wemm load_cr0(u_long data)
430f1b665c8SPeter Wemm {
431f1b665c8SPeter Wemm 
432afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr0" : : "r" (data));
433f1b665c8SPeter Wemm }
434f1b665c8SPeter Wemm 
435afa88623SPeter Wemm static __inline u_long
436f1b665c8SPeter Wemm rcr0(void)
437f1b665c8SPeter Wemm {
438afa88623SPeter Wemm 	u_long	data;
439f1b665c8SPeter Wemm 
440afa88623SPeter Wemm 	__asm __volatile("movq %%cr0,%0" : "=r" (data));
441f1b665c8SPeter Wemm 	return (data);
442f1b665c8SPeter Wemm }
443f1b665c8SPeter Wemm 
444afa88623SPeter Wemm static __inline u_long
445f1b665c8SPeter Wemm rcr2(void)
446f1b665c8SPeter Wemm {
447afa88623SPeter Wemm 	u_long	data;
448f1b665c8SPeter Wemm 
449afa88623SPeter Wemm 	__asm __volatile("movq %%cr2,%0" : "=r" (data));
450f1b665c8SPeter Wemm 	return (data);
451f1b665c8SPeter Wemm }
452f1b665c8SPeter Wemm 
453f1b665c8SPeter Wemm static __inline void
454afa88623SPeter Wemm load_cr3(u_long data)
455f1b665c8SPeter Wemm {
456f1b665c8SPeter Wemm 
457afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
458f1b665c8SPeter Wemm }
459f1b665c8SPeter Wemm 
460afa88623SPeter Wemm static __inline u_long
461f1b665c8SPeter Wemm rcr3(void)
462f1b665c8SPeter Wemm {
463afa88623SPeter Wemm 	u_long	data;
464f1b665c8SPeter Wemm 
465afa88623SPeter Wemm 	__asm __volatile("movq %%cr3,%0" : "=r" (data));
466f1b665c8SPeter Wemm 	return (data);
467f1b665c8SPeter Wemm }
468f1b665c8SPeter Wemm 
469f1b665c8SPeter Wemm static __inline void
470afa88623SPeter Wemm load_cr4(u_long data)
471f1b665c8SPeter Wemm {
472afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr4" : : "r" (data));
473f1b665c8SPeter Wemm }
474f1b665c8SPeter Wemm 
475afa88623SPeter Wemm static __inline u_long
476f1b665c8SPeter Wemm rcr4(void)
477f1b665c8SPeter Wemm {
478afa88623SPeter Wemm 	u_long	data;
479f1b665c8SPeter Wemm 
480afa88623SPeter Wemm 	__asm __volatile("movq %%cr4,%0" : "=r" (data));
481f1b665c8SPeter Wemm 	return (data);
482f1b665c8SPeter Wemm }
483f1b665c8SPeter Wemm 
4847574a595SJohn Baldwin static __inline u_long
4857574a595SJohn Baldwin rxcr(u_int reg)
4867574a595SJohn Baldwin {
4877574a595SJohn Baldwin 	u_int low, high;
4887574a595SJohn Baldwin 
4897574a595SJohn Baldwin 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
4907574a595SJohn Baldwin 	return (low | ((uint64_t)high << 32));
4917574a595SJohn Baldwin }
4927574a595SJohn Baldwin 
4937574a595SJohn Baldwin static __inline void
4947574a595SJohn Baldwin load_xcr(u_int reg, u_long val)
4957574a595SJohn Baldwin {
4967574a595SJohn Baldwin 	u_int low, high;
4977574a595SJohn Baldwin 
4987574a595SJohn Baldwin 	low = val;
4997574a595SJohn Baldwin 	high = val >> 32;
5007574a595SJohn Baldwin 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
5017574a595SJohn Baldwin }
5027574a595SJohn Baldwin 
503f1b665c8SPeter Wemm /*
504f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
505f1b665c8SPeter Wemm  */
506f1b665c8SPeter Wemm static __inline void
507f1b665c8SPeter Wemm invltlb(void)
508f1b665c8SPeter Wemm {
509f1b665c8SPeter Wemm 
510f1b665c8SPeter Wemm 	load_cr3(rcr3());
511f1b665c8SPeter Wemm }
512f1b665c8SPeter Wemm 
513e44af46eSJustin T. Gibbs #ifndef CR4_PGE
514e44af46eSJustin T. Gibbs #define	CR4_PGE	0x00000080	/* Page global enable */
515e44af46eSJustin T. Gibbs #endif
516e44af46eSJustin T. Gibbs 
517e44af46eSJustin T. Gibbs /*
518e44af46eSJustin T. Gibbs  * Perform the guaranteed invalidation of all TLB entries.  This
519e44af46eSJustin T. Gibbs  * includes the global entries, and entries in all PCIDs, not only the
520e44af46eSJustin T. Gibbs  * current context.  The function works both on non-PCID CPUs and CPUs
521e44af46eSJustin T. Gibbs  * with the PCID turned off or on.  See IA-32 SDM Vol. 3a 4.10.4.1
522e44af46eSJustin T. Gibbs  * Operations that Invalidate TLBs and Paging-Structure Caches.
523e44af46eSJustin T. Gibbs  */
524e44af46eSJustin T. Gibbs static __inline void
52527691a24SKonstantin Belousov invltlb_glob(void)
526e44af46eSJustin T. Gibbs {
527e44af46eSJustin T. Gibbs 	uint64_t cr4;
528e44af46eSJustin T. Gibbs 
529e44af46eSJustin T. Gibbs 	cr4 = rcr4();
530e44af46eSJustin T. Gibbs 	load_cr4(cr4 & ~CR4_PGE);
531e44af46eSJustin T. Gibbs 	/*
532e44af46eSJustin T. Gibbs 	 * Although preemption at this point could be detrimental to
533e44af46eSJustin T. Gibbs 	 * performance, it would not lead to an error.  PG_G is simply
534e44af46eSJustin T. Gibbs 	 * ignored if CR4.PGE is clear.  Moreover, in case this block
535e44af46eSJustin T. Gibbs 	 * is re-entered, the load_cr4() either above or below will
536e44af46eSJustin T. Gibbs 	 * modify CR4.PGE flushing the TLB.
537e44af46eSJustin T. Gibbs 	 */
538e44af46eSJustin T. Gibbs 	load_cr4(cr4 | CR4_PGE);
539e44af46eSJustin T. Gibbs }
540e44af46eSJustin T. Gibbs 
541f1b665c8SPeter Wemm /*
542f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
543f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
544f1b665c8SPeter Wemm  */
545f1b665c8SPeter Wemm static __inline void
546afa88623SPeter Wemm invlpg(u_long addr)
547f1b665c8SPeter Wemm {
548f1b665c8SPeter Wemm 
549f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
550f1b665c8SPeter Wemm }
551f1b665c8SPeter Wemm 
5525f5703efSKonstantin Belousov #define	INVPCID_ADDR	0
5535f5703efSKonstantin Belousov #define	INVPCID_CTX	1
5545f5703efSKonstantin Belousov #define	INVPCID_CTXGLOB	2
5555f5703efSKonstantin Belousov #define	INVPCID_ALLCTX	3
5565f5703efSKonstantin Belousov 
5575f5703efSKonstantin Belousov struct invpcid_descr {
5585f5703efSKonstantin Belousov 	uint64_t	pcid:12 __packed;
5595f5703efSKonstantin Belousov 	uint64_t	pad:52 __packed;
5605f5703efSKonstantin Belousov 	uint64_t	addr;
5615f5703efSKonstantin Belousov } __packed;
5625f5703efSKonstantin Belousov 
5635f5703efSKonstantin Belousov static __inline void
5645f5703efSKonstantin Belousov invpcid(struct invpcid_descr *d, int type)
5655f5703efSKonstantin Belousov {
5665f5703efSKonstantin Belousov 
567a546448bSKonstantin Belousov 	__asm __volatile("invpcid (%0),%1"
568a546448bSKonstantin Belousov 	    : : "r" (d), "r" ((u_long)type) : "memory");
5695f5703efSKonstantin Belousov }
5705f5703efSKonstantin Belousov 
57127d4fea6SRoman Divacky static __inline u_short
5725206bca1SLuoqi Chen rfs(void)
5735206bca1SLuoqi Chen {
57427d4fea6SRoman Divacky 	u_short sel;
57527d4fea6SRoman Divacky 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
5765206bca1SLuoqi Chen 	return (sel);
5775206bca1SLuoqi Chen }
5785206bca1SLuoqi Chen 
57927d4fea6SRoman Divacky static __inline u_short
5805206bca1SLuoqi Chen rgs(void)
5815206bca1SLuoqi Chen {
58227d4fea6SRoman Divacky 	u_short sel;
58327d4fea6SRoman Divacky 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
5845206bca1SLuoqi Chen 	return (sel);
5855206bca1SLuoqi Chen }
5865206bca1SLuoqi Chen 
58727d4fea6SRoman Divacky static __inline u_short
588cd0149e3SPeter Wemm rss(void)
589cd0149e3SPeter Wemm {
59027d4fea6SRoman Divacky 	u_short sel;
59127d4fea6SRoman Divacky 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
592cd0149e3SPeter Wemm 	return (sel);
593cd0149e3SPeter Wemm }
594cd0149e3SPeter Wemm 
5955206bca1SLuoqi Chen static __inline void
59627d4fea6SRoman Divacky load_ds(u_short sel)
597d85631c4SPeter Wemm {
59827d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%ds" : : "rm" (sel));
599d85631c4SPeter Wemm }
600d85631c4SPeter Wemm 
601d85631c4SPeter Wemm static __inline void
60227d4fea6SRoman Divacky load_es(u_short sel)
603d85631c4SPeter Wemm {
60427d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%es" : : "rm" (sel));
605d85631c4SPeter Wemm }
606d85631c4SPeter Wemm 
607beb2c1f3SAndriy Gapon static __inline void
608f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints)
60966247efaSJeff Roberson {
610f0b28f00SJung-uk Kim 
611f0b28f00SJung-uk Kim 	__asm __volatile("monitor"
61266247efaSJeff Roberson 	    : : "a" (addr), "c" (extensions), "d" (hints));
61366247efaSJeff Roberson }
61466247efaSJeff Roberson 
615beb2c1f3SAndriy Gapon static __inline void
616f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints)
61766247efaSJeff Roberson {
618f0b28f00SJung-uk Kim 
619f0b28f00SJung-uk Kim 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
62066247efaSJeff Roberson }
62166247efaSJeff Roberson 
6225ddeaf67SKonstantin Belousov static __inline uint32_t
6235ddeaf67SKonstantin Belousov rdpkru(void)
6245ddeaf67SKonstantin Belousov {
6255ddeaf67SKonstantin Belousov 	uint32_t res;
6265ddeaf67SKonstantin Belousov 
6275ddeaf67SKonstantin Belousov 	__asm __volatile("rdpkru" :  "=a" (res) : "c" (0) : "edx");
6285ddeaf67SKonstantin Belousov 	return (res);
6295ddeaf67SKonstantin Belousov }
6305ddeaf67SKonstantin Belousov 
6315ddeaf67SKonstantin Belousov static __inline void
6325ddeaf67SKonstantin Belousov wrpkru(uint32_t mask)
6335ddeaf67SKonstantin Belousov {
6345ddeaf67SKonstantin Belousov 
6355ddeaf67SKonstantin Belousov 	__asm __volatile("wrpkru" :  : "a" (mask),  "c" (0), "d" (0));
6365ddeaf67SKonstantin Belousov }
6375ddeaf67SKonstantin Belousov 
638c0a54ff6SPeter Wemm #ifdef _KERNEL
639c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */
640c0a54ff6SPeter Wemm #ifndef	MSR_FSBASE
641c0a54ff6SPeter Wemm #define	MSR_FSBASE	0xc0000100
642c0a54ff6SPeter Wemm #endif
643c0a54ff6SPeter Wemm static __inline void
64427d4fea6SRoman Divacky load_fs(u_short sel)
645c0a54ff6SPeter Wemm {
646c0a54ff6SPeter Wemm 	/* Preserve the fsbase value across the selector load */
64727d4fea6SRoman Divacky 	__asm __volatile("rdmsr; movw %0,%%fs; wrmsr"
648db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
649c0a54ff6SPeter Wemm }
650c0a54ff6SPeter Wemm 
651c0a54ff6SPeter Wemm #ifndef	MSR_GSBASE
652c0a54ff6SPeter Wemm #define	MSR_GSBASE	0xc0000101
653c0a54ff6SPeter Wemm #endif
654c0a54ff6SPeter Wemm static __inline void
65527d4fea6SRoman Divacky load_gs(u_short sel)
656c0a54ff6SPeter Wemm {
657c0a54ff6SPeter Wemm 	/*
658c0a54ff6SPeter Wemm 	 * Preserve the gsbase value across the selector load.
659c0a54ff6SPeter Wemm 	 * Note that we have to disable interrupts because the gsbase
660c0a54ff6SPeter Wemm 	 * being trashed happens to be the kernel gsbase at the time.
661c0a54ff6SPeter Wemm 	 */
66227d4fea6SRoman Divacky 	__asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
663db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
664c0a54ff6SPeter Wemm }
665c0a54ff6SPeter Wemm #else
666c0a54ff6SPeter Wemm /* Usable by userland */
667d85631c4SPeter Wemm static __inline void
66827d4fea6SRoman Divacky load_fs(u_short sel)
6695206bca1SLuoqi Chen {
67027d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
6715206bca1SLuoqi Chen }
6725206bca1SLuoqi Chen 
6735206bca1SLuoqi Chen static __inline void
67427d4fea6SRoman Divacky load_gs(u_short sel)
6755206bca1SLuoqi Chen {
67627d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
6775206bca1SLuoqi Chen }
678c0a54ff6SPeter Wemm #endif
6795206bca1SLuoqi Chen 
6800fd7ea1fSKonstantin Belousov static __inline uint64_t
6810fd7ea1fSKonstantin Belousov rdfsbase(void)
6820fd7ea1fSKonstantin Belousov {
6830fd7ea1fSKonstantin Belousov 	uint64_t x;
6840fd7ea1fSKonstantin Belousov 
6850fd7ea1fSKonstantin Belousov 	__asm __volatile("rdfsbase %0" : "=r" (x));
6860fd7ea1fSKonstantin Belousov 	return (x);
6870fd7ea1fSKonstantin Belousov }
6880fd7ea1fSKonstantin Belousov 
6890fd7ea1fSKonstantin Belousov static __inline void
6900fd7ea1fSKonstantin Belousov wrfsbase(uint64_t x)
6910fd7ea1fSKonstantin Belousov {
6920fd7ea1fSKonstantin Belousov 
6930fd7ea1fSKonstantin Belousov 	__asm __volatile("wrfsbase %0" : : "r" (x));
6940fd7ea1fSKonstantin Belousov }
6950fd7ea1fSKonstantin Belousov 
6960fd7ea1fSKonstantin Belousov static __inline uint64_t
6970fd7ea1fSKonstantin Belousov rdgsbase(void)
6980fd7ea1fSKonstantin Belousov {
6990fd7ea1fSKonstantin Belousov 	uint64_t x;
7000fd7ea1fSKonstantin Belousov 
7010fd7ea1fSKonstantin Belousov 	__asm __volatile("rdgsbase %0" : "=r" (x));
7020fd7ea1fSKonstantin Belousov 	return (x);
7030fd7ea1fSKonstantin Belousov }
7040fd7ea1fSKonstantin Belousov 
7050fd7ea1fSKonstantin Belousov static __inline void
7060fd7ea1fSKonstantin Belousov wrgsbase(uint64_t x)
7070fd7ea1fSKonstantin Belousov {
7080fd7ea1fSKonstantin Belousov 
7090fd7ea1fSKonstantin Belousov 	__asm __volatile("wrgsbase %0" : : "r" (x));
7100fd7ea1fSKonstantin Belousov }
7110fd7ea1fSKonstantin Belousov 
712eb1443c8SPeter Wemm static __inline void
713c1538a13SKonstantin Belousov bare_lgdt(struct region_descriptor *addr)
714c1538a13SKonstantin Belousov {
715c1538a13SKonstantin Belousov 	__asm __volatile("lgdt (%0)" : : "r" (addr));
716c1538a13SKonstantin Belousov }
717c1538a13SKonstantin Belousov 
718c1538a13SKonstantin Belousov static __inline void
719c1538a13SKonstantin Belousov sgdt(struct region_descriptor *addr)
720c1538a13SKonstantin Belousov {
721c1538a13SKonstantin Belousov 	char *loc;
722c1538a13SKonstantin Belousov 
723c1538a13SKonstantin Belousov 	loc = (char *)addr;
724c1538a13SKonstantin Belousov 	__asm __volatile("sgdt %0" : "=m" (*loc) : : "memory");
725c1538a13SKonstantin Belousov }
726c1538a13SKonstantin Belousov 
727c1538a13SKonstantin Belousov static __inline void
728eb1443c8SPeter Wemm lidt(struct region_descriptor *addr)
729eb1443c8SPeter Wemm {
730eb1443c8SPeter Wemm 	__asm __volatile("lidt (%0)" : : "r" (addr));
731eb1443c8SPeter Wemm }
732eb1443c8SPeter Wemm 
733eb1443c8SPeter Wemm static __inline void
734c1538a13SKonstantin Belousov sidt(struct region_descriptor *addr)
735c1538a13SKonstantin Belousov {
736c1538a13SKonstantin Belousov 	char *loc;
737c1538a13SKonstantin Belousov 
738c1538a13SKonstantin Belousov 	loc = (char *)addr;
739c1538a13SKonstantin Belousov 	__asm __volatile("sidt %0" : "=m" (*loc) : : "memory");
740c1538a13SKonstantin Belousov }
741c1538a13SKonstantin Belousov 
742c1538a13SKonstantin Belousov static __inline void
743eb1443c8SPeter Wemm lldt(u_short sel)
744eb1443c8SPeter Wemm {
745eb1443c8SPeter Wemm 	__asm __volatile("lldt %0" : : "r" (sel));
746eb1443c8SPeter Wemm }
747eb1443c8SPeter Wemm 
748b843f9beSJohn Baldwin static __inline u_short
749b843f9beSJohn Baldwin sldt(void)
750b843f9beSJohn Baldwin {
751b843f9beSJohn Baldwin 	u_short sel;
752b843f9beSJohn Baldwin 
753b843f9beSJohn Baldwin 	__asm __volatile("sldt %0" : "=r" (sel));
754b843f9beSJohn Baldwin 	return (sel);
755b843f9beSJohn Baldwin }
756b843f9beSJohn Baldwin 
757eb1443c8SPeter Wemm static __inline void
758eb1443c8SPeter Wemm ltr(u_short sel)
759eb1443c8SPeter Wemm {
760eb1443c8SPeter Wemm 	__asm __volatile("ltr %0" : : "r" (sel));
761eb1443c8SPeter Wemm }
762eb1443c8SPeter Wemm 
763c1538a13SKonstantin Belousov static __inline uint32_t
764c1538a13SKonstantin Belousov read_tr(void)
765c1538a13SKonstantin Belousov {
766c1538a13SKonstantin Belousov 	u_short sel;
767c1538a13SKonstantin Belousov 
768c1538a13SKonstantin Belousov 	__asm __volatile("str %0" : "=r" (sel));
769c1538a13SKonstantin Belousov 	return (sel);
770c1538a13SKonstantin Belousov }
771c1538a13SKonstantin Belousov 
772f5ac47f4SJung-uk Kim static __inline uint64_t
7731182b177SPeter Wemm rdr0(void)
7741182b177SPeter Wemm {
775f5ac47f4SJung-uk Kim 	uint64_t data;
7761182b177SPeter Wemm 	__asm __volatile("movq %%dr0,%0" : "=r" (data));
7771182b177SPeter Wemm 	return (data);
7781182b177SPeter Wemm }
7791182b177SPeter Wemm 
7801182b177SPeter Wemm static __inline void
781f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0)
7821182b177SPeter Wemm {
7831182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
7841182b177SPeter Wemm }
7851182b177SPeter Wemm 
786f5ac47f4SJung-uk Kim static __inline uint64_t
7871182b177SPeter Wemm rdr1(void)
7881182b177SPeter Wemm {
789f5ac47f4SJung-uk Kim 	uint64_t data;
7901182b177SPeter Wemm 	__asm __volatile("movq %%dr1,%0" : "=r" (data));
7911182b177SPeter Wemm 	return (data);
7921182b177SPeter Wemm }
7931182b177SPeter Wemm 
7941182b177SPeter Wemm static __inline void
795f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1)
7961182b177SPeter Wemm {
7971182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
7981182b177SPeter Wemm }
7991182b177SPeter Wemm 
800f5ac47f4SJung-uk Kim static __inline uint64_t
8011182b177SPeter Wemm rdr2(void)
8021182b177SPeter Wemm {
803f5ac47f4SJung-uk Kim 	uint64_t data;
8041182b177SPeter Wemm 	__asm __volatile("movq %%dr2,%0" : "=r" (data));
8051182b177SPeter Wemm 	return (data);
8061182b177SPeter Wemm }
8071182b177SPeter Wemm 
8081182b177SPeter Wemm static __inline void
809f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2)
8101182b177SPeter Wemm {
8111182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
8121182b177SPeter Wemm }
8131182b177SPeter Wemm 
814f5ac47f4SJung-uk Kim static __inline uint64_t
8151182b177SPeter Wemm rdr3(void)
8161182b177SPeter Wemm {
817f5ac47f4SJung-uk Kim 	uint64_t data;
8181182b177SPeter Wemm 	__asm __volatile("movq %%dr3,%0" : "=r" (data));
8191182b177SPeter Wemm 	return (data);
8201182b177SPeter Wemm }
8211182b177SPeter Wemm 
8221182b177SPeter Wemm static __inline void
823f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3)
8241182b177SPeter Wemm {
8251182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
8261182b177SPeter Wemm }
8271182b177SPeter Wemm 
828f5ac47f4SJung-uk Kim static __inline uint64_t
8291182b177SPeter Wemm rdr6(void)
8301182b177SPeter Wemm {
831f5ac47f4SJung-uk Kim 	uint64_t data;
8321182b177SPeter Wemm 	__asm __volatile("movq %%dr6,%0" : "=r" (data));
8331182b177SPeter Wemm 	return (data);
8341182b177SPeter Wemm }
8351182b177SPeter Wemm 
8361182b177SPeter Wemm static __inline void
837f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6)
8381182b177SPeter Wemm {
8391182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
8401182b177SPeter Wemm }
8411182b177SPeter Wemm 
842f5ac47f4SJung-uk Kim static __inline uint64_t
8431182b177SPeter Wemm rdr7(void)
8441182b177SPeter Wemm {
845f5ac47f4SJung-uk Kim 	uint64_t data;
8461182b177SPeter Wemm 	__asm __volatile("movq %%dr7,%0" : "=r" (data));
8471182b177SPeter Wemm 	return (data);
8481182b177SPeter Wemm }
8491182b177SPeter Wemm 
8501182b177SPeter Wemm static __inline void
851f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7)
8521182b177SPeter Wemm {
8531182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
8541182b177SPeter Wemm }
8551182b177SPeter Wemm 
856ba74981eSWarner Losh static __inline register_t
857ba74981eSWarner Losh intr_disable(void)
858ba74981eSWarner Losh {
859afa88623SPeter Wemm 	register_t rflags;
860ba74981eSWarner Losh 
861afa88623SPeter Wemm 	rflags = read_rflags();
862ba74981eSWarner Losh 	disable_intr();
863afa88623SPeter Wemm 	return (rflags);
864ba74981eSWarner Losh }
865ba74981eSWarner Losh 
866ba74981eSWarner Losh static __inline void
867afa88623SPeter Wemm intr_restore(register_t rflags)
868ba74981eSWarner Losh {
869afa88623SPeter Wemm 	write_rflags(rflags);
870ba74981eSWarner Losh }
871ba74981eSWarner Losh 
8725f7b9ff2SKonstantin Belousov static __inline void
8735f7b9ff2SKonstantin Belousov stac(void)
8745f7b9ff2SKonstantin Belousov {
8755f7b9ff2SKonstantin Belousov 
8765f7b9ff2SKonstantin Belousov 	__asm __volatile("stac" : : : "cc");
8775f7b9ff2SKonstantin Belousov }
8785f7b9ff2SKonstantin Belousov 
8795f7b9ff2SKonstantin Belousov static __inline void
8805f7b9ff2SKonstantin Belousov clac(void)
8815f7b9ff2SKonstantin Belousov {
8825f7b9ff2SKonstantin Belousov 
8835f7b9ff2SKonstantin Belousov 	__asm __volatile("clac" : : : "cc");
8845f7b9ff2SKonstantin Belousov }
8855f7b9ff2SKonstantin Belousov 
8862164af29SRuslan Bukin enum {
8872164af29SRuslan Bukin 	SGX_ECREATE	= 0x0,
8882164af29SRuslan Bukin 	SGX_EADD	= 0x1,
8892164af29SRuslan Bukin 	SGX_EINIT	= 0x2,
8902164af29SRuslan Bukin 	SGX_EREMOVE	= 0x3,
8912164af29SRuslan Bukin 	SGX_EDGBRD	= 0x4,
8922164af29SRuslan Bukin 	SGX_EDGBWR	= 0x5,
8932164af29SRuslan Bukin 	SGX_EEXTEND	= 0x6,
8942164af29SRuslan Bukin 	SGX_ELDU	= 0x8,
8952164af29SRuslan Bukin 	SGX_EBLOCK	= 0x9,
8962164af29SRuslan Bukin 	SGX_EPA		= 0xA,
8972164af29SRuslan Bukin 	SGX_EWB		= 0xB,
8982164af29SRuslan Bukin 	SGX_ETRACK	= 0xC,
8992164af29SRuslan Bukin };
9002164af29SRuslan Bukin 
9012164af29SRuslan Bukin enum {
9022164af29SRuslan Bukin 	SGX_PT_SECS = 0x00,
9032164af29SRuslan Bukin 	SGX_PT_TCS  = 0x01,
9042164af29SRuslan Bukin 	SGX_PT_REG  = 0x02,
9052164af29SRuslan Bukin 	SGX_PT_VA   = 0x03,
9062164af29SRuslan Bukin 	SGX_PT_TRIM = 0x04,
9072164af29SRuslan Bukin };
9082164af29SRuslan Bukin 
9092164af29SRuslan Bukin int sgx_encls(uint32_t eax, uint64_t rbx, uint64_t rcx, uint64_t rdx);
9102164af29SRuslan Bukin 
9112164af29SRuslan Bukin static __inline int
9122164af29SRuslan Bukin sgx_ecreate(void *pginfo, void *secs)
9132164af29SRuslan Bukin {
9142164af29SRuslan Bukin 
9152164af29SRuslan Bukin 	return (sgx_encls(SGX_ECREATE, (uint64_t)pginfo,
9162164af29SRuslan Bukin 	    (uint64_t)secs, 0));
9172164af29SRuslan Bukin }
9182164af29SRuslan Bukin 
9192164af29SRuslan Bukin static __inline int
9202164af29SRuslan Bukin sgx_eadd(void *pginfo, void *epc)
9212164af29SRuslan Bukin {
9222164af29SRuslan Bukin 
9232164af29SRuslan Bukin 	return (sgx_encls(SGX_EADD, (uint64_t)pginfo,
9242164af29SRuslan Bukin 	    (uint64_t)epc, 0));
9252164af29SRuslan Bukin }
9262164af29SRuslan Bukin 
9272164af29SRuslan Bukin static __inline int
9282164af29SRuslan Bukin sgx_einit(void *sigstruct, void *secs, void *einittoken)
9292164af29SRuslan Bukin {
9302164af29SRuslan Bukin 
9312164af29SRuslan Bukin 	return (sgx_encls(SGX_EINIT, (uint64_t)sigstruct,
9322164af29SRuslan Bukin 	    (uint64_t)secs, (uint64_t)einittoken));
9332164af29SRuslan Bukin }
9342164af29SRuslan Bukin 
9352164af29SRuslan Bukin static __inline int
9362164af29SRuslan Bukin sgx_eextend(void *secs, void *epc)
9372164af29SRuslan Bukin {
9382164af29SRuslan Bukin 
9392164af29SRuslan Bukin 	return (sgx_encls(SGX_EEXTEND, (uint64_t)secs,
9402164af29SRuslan Bukin 	    (uint64_t)epc, 0));
9412164af29SRuslan Bukin }
9422164af29SRuslan Bukin 
9432164af29SRuslan Bukin static __inline int
9442164af29SRuslan Bukin sgx_epa(void *epc)
9452164af29SRuslan Bukin {
9462164af29SRuslan Bukin 
9472164af29SRuslan Bukin 	return (sgx_encls(SGX_EPA, SGX_PT_VA, (uint64_t)epc, 0));
9482164af29SRuslan Bukin }
9492164af29SRuslan Bukin 
9502164af29SRuslan Bukin static __inline int
9512164af29SRuslan Bukin sgx_eldu(uint64_t rbx, uint64_t rcx,
9522164af29SRuslan Bukin     uint64_t rdx)
9532164af29SRuslan Bukin {
9542164af29SRuslan Bukin 
9552164af29SRuslan Bukin 	return (sgx_encls(SGX_ELDU, rbx, rcx, rdx));
9562164af29SRuslan Bukin }
9572164af29SRuslan Bukin 
9582164af29SRuslan Bukin static __inline int
9592164af29SRuslan Bukin sgx_eremove(void *epc)
9602164af29SRuslan Bukin {
9612164af29SRuslan Bukin 
9622164af29SRuslan Bukin 	return (sgx_encls(SGX_EREMOVE, 0, (uint64_t)epc, 0));
9632164af29SRuslan Bukin }
9642164af29SRuslan Bukin 
965b63dc6adSAlfred Perlstein void	reset_dbregs(void);
966d74ac681SMatthew Dillon 
967e085f869SStanislav Sedov #ifdef _KERNEL
968e085f869SStanislav Sedov int	rdmsr_safe(u_int msr, uint64_t *val);
969e085f869SStanislav Sedov int	wrmsr_safe(u_int msr, uint64_t newval);
970e085f869SStanislav Sedov #endif
971e085f869SStanislav Sedov 
972004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
973*cca19272SBrooks Davis 
974*cca19272SBrooks Davis #endif /* __i386__ */
975