xref: /freebsd/sys/amd64/include/cpufunc.h (revision 111c7fc2fe21356a637f89fa58c407958f05ad93)
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  */
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 
39cca19272SBrooks Davis #ifdef __i386__
40cca19272SBrooks Davis #include <i386/cpufunc.h>
41cca19272SBrooks Davis #else /* !__i386__ */
42cca19272SBrooks Davis 
436e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_
44004bedebSBruce Evans #define	_MACHINE_CPUFUNC_H_
456e393973SGarrett Wollman 
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 
585dbd168eSBruce Evans static __inline void
breakpoint(void)595dbd168eSBruce Evans breakpoint(void)
60004bedebSBruce Evans {
61004bedebSBruce Evans 	__asm __volatile("int $3");
625b81b6b3SRodney W. Grimes }
635b81b6b3SRodney W. Grimes 
64aae89f6fSMateusz Guzik #define	bsfl(mask)	__builtin_ctz(mask)
65c83b1328SBruce Evans 
66aae89f6fSMateusz Guzik #define	bsfq(mask)	__builtin_ctzl(mask)
67c83b1328SBruce Evans 
68004bedebSBruce Evans static __inline void
clflush(u_long addr)69206a3368SKonstantin Belousov clflush(u_long addr)
70206a3368SKonstantin Belousov {
71206a3368SKonstantin Belousov 
72206a3368SKonstantin Belousov 	__asm __volatile("clflush %0" : : "m" (*(char *)addr));
73206a3368SKonstantin Belousov }
74206a3368SKonstantin Belousov 
75206a3368SKonstantin Belousov static __inline void
clflushopt(u_long addr)763f8e0710SKonstantin Belousov clflushopt(u_long addr)
773f8e0710SKonstantin Belousov {
783f8e0710SKonstantin Belousov 
793f8e0710SKonstantin Belousov 	__asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr));
803f8e0710SKonstantin Belousov }
813f8e0710SKonstantin Belousov 
823f8e0710SKonstantin Belousov static __inline void
clwb(u_long addr)839d5d89b2SKonstantin Belousov clwb(u_long addr)
849d5d89b2SKonstantin Belousov {
859d5d89b2SKonstantin Belousov 
869d5d89b2SKonstantin Belousov 	__asm __volatile("clwb %0" : : "m" (*(char *)addr));
879d5d89b2SKonstantin Belousov }
889d5d89b2SKonstantin Belousov 
899d5d89b2SKonstantin Belousov static __inline void
clts(void)90d706ec29SJohn Baldwin clts(void)
91d706ec29SJohn Baldwin {
92d706ec29SJohn Baldwin 
93d706ec29SJohn Baldwin 	__asm __volatile("clts");
94d706ec29SJohn Baldwin }
95d706ec29SJohn Baldwin 
96d706ec29SJohn Baldwin static __inline void
disable_intr(void)975b81b6b3SRodney W. Grimes disable_intr(void)
985b81b6b3SRodney W. Grimes {
998966b85cSJohn Dyson 	__asm __volatile("cli" : : : "memory");
1005b81b6b3SRodney W. Grimes }
1015b81b6b3SRodney W. Grimes 
102004bedebSBruce Evans static __inline void
do_cpuid(u_int ax,u_int * p)103a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p)
104a983fdfeSDavid Malone {
105a983fdfeSDavid Malone 	__asm __volatile("cpuid"
106a983fdfeSDavid Malone 	    : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
107a983fdfeSDavid Malone 	    :  "0" (ax));
108a983fdfeSDavid Malone }
109a983fdfeSDavid Malone 
110a983fdfeSDavid Malone static __inline void
cpuid_count(u_int ax,u_int cx,u_int * p)111f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p)
112f6108b61SJacques Vidrine {
113f6108b61SJacques Vidrine 	__asm __volatile("cpuid"
114f6108b61SJacques Vidrine 	    : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
115f6108b61SJacques Vidrine 	    :  "0" (ax), "c" (cx));
116f6108b61SJacques Vidrine }
117f6108b61SJacques Vidrine 
118f6108b61SJacques Vidrine static __inline void
enable_intr(void)1195b81b6b3SRodney W. Grimes enable_intr(void)
1205b81b6b3SRodney W. Grimes {
121fadc51bdSBruce Evans 	__asm __volatile("sti");
1225b81b6b3SRodney W. Grimes }
1235b81b6b3SRodney W. Grimes 
124d7ee4425SMark Murray static __inline void
halt(void)125d7ee4425SMark Murray halt(void)
126d7ee4425SMark Murray {
127d7ee4425SMark Murray 	__asm __volatile("hlt");
128d7ee4425SMark Murray }
129d7ee4425SMark Murray 
130004bedebSBruce Evans static __inline u_char
inb(u_int port)131e1048f76SEd Schouten inb(u_int port)
132004bedebSBruce Evans {
133004bedebSBruce Evans 	u_char	data;
134004bedebSBruce Evans 
1354854ae24SJung-uk Kim 	__asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port));
136004bedebSBruce Evans 	return (data);
137004bedebSBruce Evans }
138004bedebSBruce Evans 
13900be8601SBruce Evans static __inline u_int
inl(u_int port)140004bedebSBruce Evans inl(u_int port)
141004bedebSBruce Evans {
14200be8601SBruce Evans 	u_int	data;
143004bedebSBruce Evans 
1444854ae24SJung-uk Kim 	__asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port));
145004bedebSBruce Evans 	return (data);
146004bedebSBruce Evans }
147004bedebSBruce Evans 
148004bedebSBruce Evans static __inline void
insb(u_int port,void * addr,size_t count)14993d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count)
150004bedebSBruce Evans {
151fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insb"
15293d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
1533f9a462fSJohn Baldwin 			 : "d" (port)
154896763faSBruce Evans 			 : "memory");
155004bedebSBruce Evans }
156004bedebSBruce Evans 
157004bedebSBruce Evans static __inline void
insw(u_int port,void * addr,size_t count)15893d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count)
159004bedebSBruce Evans {
160fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insw"
16193d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
1623f9a462fSJohn Baldwin 			 : "d" (port)
163896763faSBruce Evans 			 : "memory");
164004bedebSBruce Evans }
165004bedebSBruce Evans 
166004bedebSBruce Evans static __inline void
insl(u_int port,void * addr,size_t count)16793d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count)
168004bedebSBruce Evans {
169fa43c5d4SMateusz Guzik 	__asm __volatile("rep; insl"
17093d8be03SDavid E. O'Brien 			 : "+D" (addr), "+c" (count)
1713f9a462fSJohn Baldwin 			 : "d" (port)
172896763faSBruce Evans 			 : "memory");
173004bedebSBruce Evans }
174004bedebSBruce Evans 
175ece15d78SBruce Evans static __inline void
invd(void)1764c024bbdSKATO Takenori invd(void)
1774c024bbdSKATO Takenori {
1784c024bbdSKATO Takenori 	__asm __volatile("invd");
1794c024bbdSKATO Takenori }
1804c024bbdSKATO Takenori 
181004bedebSBruce Evans static __inline u_short
inw(u_int port)182004bedebSBruce Evans inw(u_int port)
183004bedebSBruce Evans {
184004bedebSBruce Evans 	u_short	data;
185004bedebSBruce Evans 
1864854ae24SJung-uk Kim 	__asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port));
187004bedebSBruce Evans 	return (data);
188004bedebSBruce Evans }
189004bedebSBruce Evans 
190004bedebSBruce Evans static __inline void
outb(u_int port,u_char data)191e1048f76SEd Schouten outb(u_int port, u_char data)
192004bedebSBruce Evans {
1934854ae24SJung-uk Kim 	__asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port));
194004bedebSBruce Evans }
195004bedebSBruce Evans 
196004bedebSBruce Evans static __inline void
outl(u_int port,u_int data)19700be8601SBruce Evans outl(u_int port, u_int data)
198004bedebSBruce Evans {
1994854ae24SJung-uk Kim 	__asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port));
200004bedebSBruce Evans }
201004bedebSBruce Evans 
202004bedebSBruce Evans static __inline void
outsb(u_int port,const void * addr,size_t count)20393d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count)
204004bedebSBruce Evans {
205fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsb"
20693d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2073f9a462fSJohn Baldwin 			 : "d" (port));
208004bedebSBruce Evans }
209004bedebSBruce Evans 
210004bedebSBruce Evans static __inline void
outsw(u_int port,const void * addr,size_t count)21193d8be03SDavid E. O'Brien outsw(u_int port, const void *addr, size_t count)
212004bedebSBruce Evans {
213fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsw"
21493d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2153f9a462fSJohn Baldwin 			 : "d" (port));
216004bedebSBruce Evans }
217004bedebSBruce Evans 
218004bedebSBruce Evans static __inline void
outsl(u_int port,const void * addr,size_t count)21993d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count)
220004bedebSBruce Evans {
221fa43c5d4SMateusz Guzik 	__asm __volatile("rep; outsl"
22293d8be03SDavid E. O'Brien 			 : "+S" (addr), "+c" (count)
2233f9a462fSJohn Baldwin 			 : "d" (port));
224004bedebSBruce Evans }
225004bedebSBruce Evans 
226004bedebSBruce Evans static __inline void
outw(u_int port,u_short data)227004bedebSBruce Evans outw(u_int port, u_short data)
228004bedebSBruce Evans {
2294854ae24SJung-uk Kim 	__asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port));
230004bedebSBruce Evans }
231004bedebSBruce Evans 
2322bde6e35SAlan Cox static __inline u_long
popcntq(u_long mask)2332bde6e35SAlan Cox popcntq(u_long mask)
2342bde6e35SAlan Cox {
2352bde6e35SAlan Cox 	u_long result;
2362bde6e35SAlan Cox 
2372bde6e35SAlan Cox 	__asm __volatile("popcntq %1,%0" : "=r" (result) : "rm" (mask));
2382bde6e35SAlan Cox 	return (result);
2392bde6e35SAlan Cox }
2402bde6e35SAlan Cox 
2412be69f32SJohn Baldwin static __inline void
lfence(void)2420220d04fSKonstantin Belousov lfence(void)
2430220d04fSKonstantin Belousov {
2440220d04fSKonstantin Belousov 
2450220d04fSKonstantin Belousov 	__asm __volatile("lfence" : : : "memory");
2460220d04fSKonstantin Belousov }
2470220d04fSKonstantin Belousov 
2480220d04fSKonstantin Belousov static __inline void
mfence(void)249206a3368SKonstantin Belousov mfence(void)
250206a3368SKonstantin Belousov {
251206a3368SKonstantin Belousov 
252beb2c1f3SAndriy Gapon 	__asm __volatile("mfence" : : : "memory");
253206a3368SKonstantin Belousov }
254206a3368SKonstantin Belousov 
255206a3368SKonstantin Belousov static __inline void
sfence(void)2565611aaa1SKonstantin Belousov sfence(void)
2575611aaa1SKonstantin Belousov {
2585611aaa1SKonstantin Belousov 
2595611aaa1SKonstantin Belousov 	__asm __volatile("sfence" : : : "memory");
2605611aaa1SKonstantin Belousov }
2615611aaa1SKonstantin Belousov 
2625611aaa1SKonstantin Belousov static __inline void
ia32_pause(void)2636b8c6989SJohn Baldwin ia32_pause(void)
2642be69f32SJohn Baldwin {
2652be69f32SJohn Baldwin 	__asm __volatile("pause");
2662be69f32SJohn Baldwin }
2672be69f32SJohn Baldwin 
268afa88623SPeter Wemm static __inline u_long
read_rflags(void)269afa88623SPeter Wemm read_rflags(void)
2705b81b6b3SRodney W. Grimes {
271afa88623SPeter Wemm 	u_long	rf;
272004bedebSBruce Evans 
273afa88623SPeter Wemm 	__asm __volatile("pushfq; popq %0" : "=r" (rf));
274afa88623SPeter Wemm 	return (rf);
2755b81b6b3SRodney W. Grimes }
2765b81b6b3SRodney W. Grimes 
277f5ac47f4SJung-uk Kim static __inline uint64_t
rdmsr(u_int msr)2785dbd168eSBruce Evans rdmsr(u_int msr)
2795dbd168eSBruce Evans {
280f5ac47f4SJung-uk Kim 	uint32_t low, high;
2815dbd168eSBruce Evans 
282afa88623SPeter Wemm 	__asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr));
283f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
2845dbd168eSBruce Evans }
2855dbd168eSBruce Evans 
2864c918926SKonstantin Belousov static __inline uint32_t
rdmsr32(u_int msr)2874c918926SKonstantin Belousov rdmsr32(u_int msr)
2884c918926SKonstantin Belousov {
2894c918926SKonstantin Belousov 	uint32_t low;
2904c918926SKonstantin Belousov 
2914c918926SKonstantin Belousov 	__asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "rdx");
2924c918926SKonstantin Belousov 	return (low);
2934c918926SKonstantin Belousov }
2944c918926SKonstantin Belousov 
295f5ac47f4SJung-uk Kim static __inline uint64_t
rdpmc(u_int pmc)2965dbd168eSBruce Evans rdpmc(u_int pmc)
2975dbd168eSBruce Evans {
298f5ac47f4SJung-uk Kim 	uint32_t low, high;
2995dbd168eSBruce Evans 
300afa88623SPeter Wemm 	__asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc));
301f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3025dbd168eSBruce Evans }
3035dbd168eSBruce Evans 
304f5ac47f4SJung-uk Kim static __inline uint64_t
rdtsc(void)3055dbd168eSBruce Evans rdtsc(void)
3065dbd168eSBruce Evans {
307f5ac47f4SJung-uk Kim 	uint32_t low, high;
3085dbd168eSBruce Evans 
309afa88623SPeter Wemm 	__asm __volatile("rdtsc" : "=a" (low), "=d" (high));
310f5ac47f4SJung-uk Kim 	return (low | ((uint64_t)high << 32));
3115dbd168eSBruce Evans }
3125dbd168eSBruce Evans 
31315504639SMatt Macy static __inline uint64_t
rdtsc_ordered_lfence(void)314652ae7b1SAdam Fenn rdtsc_ordered_lfence(void)
315652ae7b1SAdam Fenn {
316652ae7b1SAdam Fenn 	lfence();
317652ae7b1SAdam Fenn 	return (rdtsc());
318652ae7b1SAdam Fenn }
319652ae7b1SAdam Fenn 
320652ae7b1SAdam Fenn static __inline uint64_t
rdtsc_ordered_mfence(void)321652ae7b1SAdam Fenn rdtsc_ordered_mfence(void)
322652ae7b1SAdam Fenn {
323652ae7b1SAdam Fenn 	mfence();
324652ae7b1SAdam Fenn 	return (rdtsc());
325652ae7b1SAdam Fenn }
326652ae7b1SAdam Fenn 
327652ae7b1SAdam Fenn static __inline uint64_t
rdtscp(void)32815504639SMatt Macy rdtscp(void)
32915504639SMatt Macy {
33015504639SMatt Macy 	uint32_t low, high;
33115504639SMatt Macy 
332f090f675SMark Johnston 	__asm __volatile("rdtscp" : "=a" (low), "=d" (high) : : "ecx");
33315504639SMatt Macy 	return (low | ((uint64_t)high << 32));
33415504639SMatt Macy }
33515504639SMatt Macy 
336908e2772SAdam Fenn static __inline uint64_t
rdtscp_aux(uint32_t * aux)337908e2772SAdam Fenn rdtscp_aux(uint32_t *aux)
338908e2772SAdam Fenn {
339908e2772SAdam Fenn 	uint32_t low, high;
340908e2772SAdam Fenn 
341908e2772SAdam Fenn 	__asm __volatile("rdtscp" : "=a" (low), "=d" (high), "=c" (*aux));
342908e2772SAdam Fenn 	return (low | ((uint64_t)high << 32));
343908e2772SAdam Fenn }
344908e2772SAdam Fenn 
3450e727642SJung-uk Kim static __inline uint32_t
rdtsc32(void)3460e727642SJung-uk Kim rdtsc32(void)
3470e727642SJung-uk Kim {
3480e727642SJung-uk Kim 	uint32_t rv;
3490e727642SJung-uk Kim 
3500e727642SJung-uk Kim 	__asm __volatile("rdtsc" : "=a" (rv) : : "edx");
3510e727642SJung-uk Kim 	return (rv);
3520e727642SJung-uk Kim }
3530e727642SJung-uk Kim 
35445974de8SKonstantin Belousov static __inline uint32_t
rdtscp32(void)35545974de8SKonstantin Belousov rdtscp32(void)
35645974de8SKonstantin Belousov {
35745974de8SKonstantin Belousov 	uint32_t rv;
35845974de8SKonstantin Belousov 
35945974de8SKonstantin Belousov 	__asm __volatile("rdtscp" : "=a" (rv) : : "ecx", "edx");
36045974de8SKonstantin Belousov 	return (rv);
36145974de8SKonstantin Belousov }
36245974de8SKonstantin Belousov 
363004bedebSBruce Evans static __inline void
wbinvd(void)3644c024bbdSKATO Takenori wbinvd(void)
3654c024bbdSKATO Takenori {
3664c024bbdSKATO Takenori 	__asm __volatile("wbinvd");
3674c024bbdSKATO Takenori }
3684c024bbdSKATO Takenori 
3694c024bbdSKATO Takenori static __inline void
write_rflags(u_long rf)370afa88623SPeter Wemm write_rflags(u_long rf)
3715b81b6b3SRodney W. Grimes {
372afa88623SPeter Wemm 	__asm __volatile("pushq %0;  popfq" : : "r" (rf));
3735b81b6b3SRodney W. Grimes }
3745b81b6b3SRodney W. Grimes 
375d69e8502SGarrett Wollman static __inline void
wrmsr(u_int msr,uint64_t newval)376f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval)
377d69e8502SGarrett Wollman {
378f5ac47f4SJung-uk Kim 	uint32_t low, high;
379afa88623SPeter Wemm 
380afa88623SPeter Wemm 	low = newval;
381afa88623SPeter Wemm 	high = newval >> 32;
382afa88623SPeter Wemm 	__asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr));
383d69e8502SGarrett Wollman }
384d69e8502SGarrett Wollman 
385f1b665c8SPeter Wemm static __inline void
load_cr0(u_long data)386afa88623SPeter Wemm load_cr0(u_long data)
387f1b665c8SPeter Wemm {
388f1b665c8SPeter Wemm 
389afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr0" : : "r" (data));
390f1b665c8SPeter Wemm }
391f1b665c8SPeter Wemm 
392afa88623SPeter Wemm static __inline u_long
rcr0(void)393f1b665c8SPeter Wemm rcr0(void)
394f1b665c8SPeter Wemm {
395afa88623SPeter Wemm 	u_long	data;
396f1b665c8SPeter Wemm 
397afa88623SPeter Wemm 	__asm __volatile("movq %%cr0,%0" : "=r" (data));
398f1b665c8SPeter Wemm 	return (data);
399f1b665c8SPeter Wemm }
400f1b665c8SPeter Wemm 
401afa88623SPeter Wemm static __inline u_long
rcr2(void)402f1b665c8SPeter Wemm rcr2(void)
403f1b665c8SPeter Wemm {
404afa88623SPeter Wemm 	u_long	data;
405f1b665c8SPeter Wemm 
406afa88623SPeter Wemm 	__asm __volatile("movq %%cr2,%0" : "=r" (data));
407f1b665c8SPeter Wemm 	return (data);
408f1b665c8SPeter Wemm }
409f1b665c8SPeter Wemm 
410f1b665c8SPeter Wemm static __inline void
load_cr3(u_long data)411afa88623SPeter Wemm load_cr3(u_long data)
412f1b665c8SPeter Wemm {
413f1b665c8SPeter Wemm 
414afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory");
415f1b665c8SPeter Wemm }
416f1b665c8SPeter Wemm 
417afa88623SPeter Wemm static __inline u_long
rcr3(void)418f1b665c8SPeter Wemm rcr3(void)
419f1b665c8SPeter Wemm {
420afa88623SPeter Wemm 	u_long	data;
421f1b665c8SPeter Wemm 
422afa88623SPeter Wemm 	__asm __volatile("movq %%cr3,%0" : "=r" (data));
423f1b665c8SPeter Wemm 	return (data);
424f1b665c8SPeter Wemm }
425f1b665c8SPeter Wemm 
426f1b665c8SPeter Wemm static __inline void
load_cr4(u_long data)427afa88623SPeter Wemm load_cr4(u_long data)
428f1b665c8SPeter Wemm {
429afa88623SPeter Wemm 	__asm __volatile("movq %0,%%cr4" : : "r" (data));
430f1b665c8SPeter Wemm }
431f1b665c8SPeter Wemm 
432afa88623SPeter Wemm static __inline u_long
rcr4(void)433f1b665c8SPeter Wemm rcr4(void)
434f1b665c8SPeter Wemm {
435afa88623SPeter Wemm 	u_long	data;
436f1b665c8SPeter Wemm 
437afa88623SPeter Wemm 	__asm __volatile("movq %%cr4,%0" : "=r" (data));
438f1b665c8SPeter Wemm 	return (data);
439f1b665c8SPeter Wemm }
440f1b665c8SPeter Wemm 
4417574a595SJohn Baldwin static __inline u_long
rxcr(u_int reg)4427574a595SJohn Baldwin rxcr(u_int reg)
4437574a595SJohn Baldwin {
4447574a595SJohn Baldwin 	u_int low, high;
4457574a595SJohn Baldwin 
4467574a595SJohn Baldwin 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
4477574a595SJohn Baldwin 	return (low | ((uint64_t)high << 32));
4487574a595SJohn Baldwin }
4497574a595SJohn Baldwin 
4507574a595SJohn Baldwin static __inline void
load_xcr(u_int reg,u_long val)4517574a595SJohn Baldwin load_xcr(u_int reg, u_long val)
4527574a595SJohn Baldwin {
4537574a595SJohn Baldwin 	u_int low, high;
4547574a595SJohn Baldwin 
4557574a595SJohn Baldwin 	low = val;
4567574a595SJohn Baldwin 	high = val >> 32;
4577574a595SJohn Baldwin 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high));
4587574a595SJohn Baldwin }
4597574a595SJohn Baldwin 
460f1b665c8SPeter Wemm /*
461f1b665c8SPeter Wemm  * Global TLB flush (except for thise for pages marked PG_G)
462f1b665c8SPeter Wemm  */
463f1b665c8SPeter Wemm static __inline void
invltlb(void)464f1b665c8SPeter Wemm invltlb(void)
465f1b665c8SPeter Wemm {
466f1b665c8SPeter Wemm 
467f1b665c8SPeter Wemm 	load_cr3(rcr3());
468f1b665c8SPeter Wemm }
469f1b665c8SPeter Wemm 
470e44af46eSJustin T. Gibbs #ifndef CR4_PGE
471e44af46eSJustin T. Gibbs #define	CR4_PGE	0x00000080	/* Page global enable */
472e44af46eSJustin T. Gibbs #endif
473e44af46eSJustin T. Gibbs 
474e44af46eSJustin T. Gibbs /*
475e44af46eSJustin T. Gibbs  * Perform the guaranteed invalidation of all TLB entries.  This
476e44af46eSJustin T. Gibbs  * includes the global entries, and entries in all PCIDs, not only the
477e44af46eSJustin T. Gibbs  * current context.  The function works both on non-PCID CPUs and CPUs
478e44af46eSJustin T. Gibbs  * with the PCID turned off or on.  See IA-32 SDM Vol. 3a 4.10.4.1
479e44af46eSJustin T. Gibbs  * Operations that Invalidate TLBs and Paging-Structure Caches.
480e44af46eSJustin T. Gibbs  */
481e44af46eSJustin T. Gibbs static __inline void
invltlb_glob(void)48227691a24SKonstantin Belousov invltlb_glob(void)
483e44af46eSJustin T. Gibbs {
484e44af46eSJustin T. Gibbs 	uint64_t cr4;
485e44af46eSJustin T. Gibbs 
486e44af46eSJustin T. Gibbs 	cr4 = rcr4();
487e44af46eSJustin T. Gibbs 	load_cr4(cr4 & ~CR4_PGE);
488e44af46eSJustin T. Gibbs 	/*
489e44af46eSJustin T. Gibbs 	 * Although preemption at this point could be detrimental to
490e44af46eSJustin T. Gibbs 	 * performance, it would not lead to an error.  PG_G is simply
491e44af46eSJustin T. Gibbs 	 * ignored if CR4.PGE is clear.  Moreover, in case this block
492e44af46eSJustin T. Gibbs 	 * is re-entered, the load_cr4() either above or below will
493e44af46eSJustin T. Gibbs 	 * modify CR4.PGE flushing the TLB.
494e44af46eSJustin T. Gibbs 	 */
495e44af46eSJustin T. Gibbs 	load_cr4(cr4 | CR4_PGE);
496e44af46eSJustin T. Gibbs }
497e44af46eSJustin T. Gibbs 
498f1b665c8SPeter Wemm /*
499f1b665c8SPeter Wemm  * TLB flush for an individual page (even if it has PG_G).
500f1b665c8SPeter Wemm  * Only works on 486+ CPUs (i386 does not have PG_G).
501f1b665c8SPeter Wemm  */
502f1b665c8SPeter Wemm static __inline void
invlpg(u_long addr)503afa88623SPeter Wemm invlpg(u_long addr)
504f1b665c8SPeter Wemm {
505f1b665c8SPeter Wemm 
506f1b665c8SPeter Wemm 	__asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
507f1b665c8SPeter Wemm }
508f1b665c8SPeter Wemm 
5095f5703efSKonstantin Belousov #define	INVPCID_ADDR	0
5105f5703efSKonstantin Belousov #define	INVPCID_CTX	1
5115f5703efSKonstantin Belousov #define	INVPCID_CTXGLOB	2
5125f5703efSKonstantin Belousov #define	INVPCID_ALLCTX	3
5135f5703efSKonstantin Belousov 
5145f5703efSKonstantin Belousov struct invpcid_descr {
5155f5703efSKonstantin Belousov 	uint64_t	pcid:12 __packed;
5165f5703efSKonstantin Belousov 	uint64_t	pad:52 __packed;
5175f5703efSKonstantin Belousov 	uint64_t	addr;
5185f5703efSKonstantin Belousov } __packed;
5195f5703efSKonstantin Belousov 
5205f5703efSKonstantin Belousov static __inline void
invpcid(struct invpcid_descr * d,int type)5215f5703efSKonstantin Belousov invpcid(struct invpcid_descr *d, int type)
5225f5703efSKonstantin Belousov {
5235f5703efSKonstantin Belousov 
524a546448bSKonstantin Belousov 	__asm __volatile("invpcid (%0),%1"
525a546448bSKonstantin Belousov 	    : : "r" (d), "r" ((u_long)type) : "memory");
5265f5703efSKonstantin Belousov }
5275f5703efSKonstantin Belousov 
528*111c7fc2SKonstantin Belousov #define	INVLPGB_VA		0x0001
529*111c7fc2SKonstantin Belousov #define	INVLPGB_PCID		0x0002
530*111c7fc2SKonstantin Belousov #define	INVLPGB_ASID		0x0004
531*111c7fc2SKonstantin Belousov #define	INVLPGB_GLOB		0x0008
532*111c7fc2SKonstantin Belousov #define	INVLPGB_FIN		0x0010
533*111c7fc2SKonstantin Belousov #define	INVLPGB_NEST		0x0020
534*111c7fc2SKonstantin Belousov 
535*111c7fc2SKonstantin Belousov #define	INVLPGB_DESCR(asid, pcid)	(((pcid) << 16) | (asid))
536*111c7fc2SKonstantin Belousov 
537*111c7fc2SKonstantin Belousov #define	INVLPGB_2M_CNT		(1u << 31)
538*111c7fc2SKonstantin Belousov 
539*111c7fc2SKonstantin Belousov static __inline void
invlpgb(uint64_t rax,uint32_t edx,uint32_t ecx)540*111c7fc2SKonstantin Belousov invlpgb(uint64_t rax, uint32_t edx, uint32_t ecx)
541*111c7fc2SKonstantin Belousov {
542*111c7fc2SKonstantin Belousov 	__asm __volatile("invlpgb" : : "a" (rax), "d" (edx), "c" (ecx));
543*111c7fc2SKonstantin Belousov }
544*111c7fc2SKonstantin Belousov 
545*111c7fc2SKonstantin Belousov static __inline void
tlbsync(void)546*111c7fc2SKonstantin Belousov tlbsync(void)
547*111c7fc2SKonstantin Belousov {
548*111c7fc2SKonstantin Belousov 	__asm __volatile("tlbsync");
549*111c7fc2SKonstantin Belousov }
550*111c7fc2SKonstantin Belousov 
55127d4fea6SRoman Divacky static __inline u_short
rfs(void)5525206bca1SLuoqi Chen rfs(void)
5535206bca1SLuoqi Chen {
55427d4fea6SRoman Divacky 	u_short sel;
55527d4fea6SRoman Divacky 	__asm __volatile("movw %%fs,%0" : "=rm" (sel));
5565206bca1SLuoqi Chen 	return (sel);
5575206bca1SLuoqi Chen }
5585206bca1SLuoqi Chen 
55927d4fea6SRoman Divacky static __inline u_short
rgs(void)5605206bca1SLuoqi Chen rgs(void)
5615206bca1SLuoqi Chen {
56227d4fea6SRoman Divacky 	u_short sel;
56327d4fea6SRoman Divacky 	__asm __volatile("movw %%gs,%0" : "=rm" (sel));
5645206bca1SLuoqi Chen 	return (sel);
5655206bca1SLuoqi Chen }
5665206bca1SLuoqi Chen 
56727d4fea6SRoman Divacky static __inline u_short
rss(void)568cd0149e3SPeter Wemm rss(void)
569cd0149e3SPeter Wemm {
57027d4fea6SRoman Divacky 	u_short sel;
57127d4fea6SRoman Divacky 	__asm __volatile("movw %%ss,%0" : "=rm" (sel));
572cd0149e3SPeter Wemm 	return (sel);
573cd0149e3SPeter Wemm }
574cd0149e3SPeter Wemm 
5755206bca1SLuoqi Chen static __inline void
load_ds(u_short sel)57627d4fea6SRoman Divacky load_ds(u_short sel)
577d85631c4SPeter Wemm {
57827d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%ds" : : "rm" (sel));
579d85631c4SPeter Wemm }
580d85631c4SPeter Wemm 
581d85631c4SPeter Wemm static __inline void
load_es(u_short sel)58227d4fea6SRoman Divacky load_es(u_short sel)
583d85631c4SPeter Wemm {
58427d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%es" : : "rm" (sel));
585d85631c4SPeter Wemm }
586d85631c4SPeter Wemm 
587beb2c1f3SAndriy Gapon static __inline void
cpu_monitor(const void * addr,u_long extensions,u_int hints)588f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints)
58966247efaSJeff Roberson {
590f0b28f00SJung-uk Kim 
591f0b28f00SJung-uk Kim 	__asm __volatile("monitor"
59266247efaSJeff Roberson 	    : : "a" (addr), "c" (extensions), "d" (hints));
59366247efaSJeff Roberson }
59466247efaSJeff Roberson 
595beb2c1f3SAndriy Gapon static __inline void
cpu_mwait(u_long extensions,u_int hints)596f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints)
59766247efaSJeff Roberson {
598f0b28f00SJung-uk Kim 
599f0b28f00SJung-uk Kim 	__asm __volatile("mwait" : : "a" (hints), "c" (extensions));
60066247efaSJeff Roberson }
60166247efaSJeff Roberson 
6025ddeaf67SKonstantin Belousov static __inline uint32_t
rdpkru(void)6035ddeaf67SKonstantin Belousov rdpkru(void)
6045ddeaf67SKonstantin Belousov {
6055ddeaf67SKonstantin Belousov 	uint32_t res;
6065ddeaf67SKonstantin Belousov 
6075ddeaf67SKonstantin Belousov 	__asm __volatile("rdpkru" :  "=a" (res) : "c" (0) : "edx");
6085ddeaf67SKonstantin Belousov 	return (res);
6095ddeaf67SKonstantin Belousov }
6105ddeaf67SKonstantin Belousov 
6115ddeaf67SKonstantin Belousov static __inline void
wrpkru(uint32_t mask)6125ddeaf67SKonstantin Belousov wrpkru(uint32_t mask)
6135ddeaf67SKonstantin Belousov {
6145ddeaf67SKonstantin Belousov 
6155ddeaf67SKonstantin Belousov 	__asm __volatile("wrpkru" :  : "a" (mask),  "c" (0), "d" (0));
6165ddeaf67SKonstantin Belousov }
6175ddeaf67SKonstantin Belousov 
618c0a54ff6SPeter Wemm #ifdef _KERNEL
619c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */
620c0a54ff6SPeter Wemm #ifndef	MSR_FSBASE
621c0a54ff6SPeter Wemm #define	MSR_FSBASE	0xc0000100
622c0a54ff6SPeter Wemm #endif
623c0a54ff6SPeter Wemm static __inline void
load_fs(u_short sel)62427d4fea6SRoman Divacky load_fs(u_short sel)
625c0a54ff6SPeter Wemm {
626c0a54ff6SPeter Wemm 	/* Preserve the fsbase value across the selector load */
62727d4fea6SRoman Divacky 	__asm __volatile("rdmsr; movw %0,%%fs; wrmsr"
628db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx");
629c0a54ff6SPeter Wemm }
630c0a54ff6SPeter Wemm 
631c0a54ff6SPeter Wemm #ifndef	MSR_GSBASE
632c0a54ff6SPeter Wemm #define	MSR_GSBASE	0xc0000101
633c0a54ff6SPeter Wemm #endif
634c0a54ff6SPeter Wemm static __inline void
load_gs(u_short sel)63527d4fea6SRoman Divacky load_gs(u_short sel)
636c0a54ff6SPeter Wemm {
637c0a54ff6SPeter Wemm 	/*
638c0a54ff6SPeter Wemm 	 * Preserve the gsbase value across the selector load.
639c0a54ff6SPeter Wemm 	 * Note that we have to disable interrupts because the gsbase
640c0a54ff6SPeter Wemm 	 * being trashed happens to be the kernel gsbase at the time.
641c0a54ff6SPeter Wemm 	 */
64227d4fea6SRoman Divacky 	__asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq"
643db26a671SEd Schouten 	    : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx");
644c0a54ff6SPeter Wemm }
645c0a54ff6SPeter Wemm #else
646c0a54ff6SPeter Wemm /* Usable by userland */
647d85631c4SPeter Wemm static __inline void
load_fs(u_short sel)64827d4fea6SRoman Divacky load_fs(u_short sel)
6495206bca1SLuoqi Chen {
65027d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%fs" : : "rm" (sel));
6515206bca1SLuoqi Chen }
6525206bca1SLuoqi Chen 
6535206bca1SLuoqi Chen static __inline void
load_gs(u_short sel)65427d4fea6SRoman Divacky load_gs(u_short sel)
6555206bca1SLuoqi Chen {
65627d4fea6SRoman Divacky 	__asm __volatile("movw %0,%%gs" : : "rm" (sel));
6575206bca1SLuoqi Chen }
658c0a54ff6SPeter Wemm #endif
6595206bca1SLuoqi Chen 
6600fd7ea1fSKonstantin Belousov static __inline uint64_t
rdfsbase(void)6610fd7ea1fSKonstantin Belousov rdfsbase(void)
6620fd7ea1fSKonstantin Belousov {
6630fd7ea1fSKonstantin Belousov 	uint64_t x;
6640fd7ea1fSKonstantin Belousov 
6650fd7ea1fSKonstantin Belousov 	__asm __volatile("rdfsbase %0" : "=r" (x));
6660fd7ea1fSKonstantin Belousov 	return (x);
6670fd7ea1fSKonstantin Belousov }
6680fd7ea1fSKonstantin Belousov 
6690fd7ea1fSKonstantin Belousov static __inline void
wrfsbase(uint64_t x)6700fd7ea1fSKonstantin Belousov wrfsbase(uint64_t x)
6710fd7ea1fSKonstantin Belousov {
6720fd7ea1fSKonstantin Belousov 
6730fd7ea1fSKonstantin Belousov 	__asm __volatile("wrfsbase %0" : : "r" (x));
6740fd7ea1fSKonstantin Belousov }
6750fd7ea1fSKonstantin Belousov 
6760fd7ea1fSKonstantin Belousov static __inline uint64_t
rdgsbase(void)6770fd7ea1fSKonstantin Belousov rdgsbase(void)
6780fd7ea1fSKonstantin Belousov {
6790fd7ea1fSKonstantin Belousov 	uint64_t x;
6800fd7ea1fSKonstantin Belousov 
6810fd7ea1fSKonstantin Belousov 	__asm __volatile("rdgsbase %0" : "=r" (x));
6820fd7ea1fSKonstantin Belousov 	return (x);
6830fd7ea1fSKonstantin Belousov }
6840fd7ea1fSKonstantin Belousov 
6850fd7ea1fSKonstantin Belousov static __inline void
wrgsbase(uint64_t x)6860fd7ea1fSKonstantin Belousov wrgsbase(uint64_t x)
6870fd7ea1fSKonstantin Belousov {
6880fd7ea1fSKonstantin Belousov 
6890fd7ea1fSKonstantin Belousov 	__asm __volatile("wrgsbase %0" : : "r" (x));
6900fd7ea1fSKonstantin Belousov }
6910fd7ea1fSKonstantin Belousov 
692eb1443c8SPeter Wemm static __inline void
bare_lgdt(struct region_descriptor * addr)693c1538a13SKonstantin Belousov bare_lgdt(struct region_descriptor *addr)
694c1538a13SKonstantin Belousov {
695c1538a13SKonstantin Belousov 	__asm __volatile("lgdt (%0)" : : "r" (addr));
696c1538a13SKonstantin Belousov }
697c1538a13SKonstantin Belousov 
698c1538a13SKonstantin Belousov static __inline void
sgdt(struct region_descriptor * addr)699c1538a13SKonstantin Belousov sgdt(struct region_descriptor *addr)
700c1538a13SKonstantin Belousov {
701c1538a13SKonstantin Belousov 	char *loc;
702c1538a13SKonstantin Belousov 
703c1538a13SKonstantin Belousov 	loc = (char *)addr;
704c1538a13SKonstantin Belousov 	__asm __volatile("sgdt %0" : "=m" (*loc) : : "memory");
705c1538a13SKonstantin Belousov }
706c1538a13SKonstantin Belousov 
707c1538a13SKonstantin Belousov static __inline void
lidt(struct region_descriptor * addr)708eb1443c8SPeter Wemm lidt(struct region_descriptor *addr)
709eb1443c8SPeter Wemm {
710eb1443c8SPeter Wemm 	__asm __volatile("lidt (%0)" : : "r" (addr));
711eb1443c8SPeter Wemm }
712eb1443c8SPeter Wemm 
713eb1443c8SPeter Wemm static __inline void
sidt(struct region_descriptor * addr)714c1538a13SKonstantin Belousov sidt(struct region_descriptor *addr)
715c1538a13SKonstantin Belousov {
716c1538a13SKonstantin Belousov 	char *loc;
717c1538a13SKonstantin Belousov 
718c1538a13SKonstantin Belousov 	loc = (char *)addr;
719c1538a13SKonstantin Belousov 	__asm __volatile("sidt %0" : "=m" (*loc) : : "memory");
720c1538a13SKonstantin Belousov }
721c1538a13SKonstantin Belousov 
722c1538a13SKonstantin Belousov static __inline void
lldt(u_short sel)723eb1443c8SPeter Wemm lldt(u_short sel)
724eb1443c8SPeter Wemm {
725eb1443c8SPeter Wemm 	__asm __volatile("lldt %0" : : "r" (sel));
726eb1443c8SPeter Wemm }
727eb1443c8SPeter Wemm 
728b843f9beSJohn Baldwin static __inline u_short
sldt(void)729b843f9beSJohn Baldwin sldt(void)
730b843f9beSJohn Baldwin {
731b843f9beSJohn Baldwin 	u_short sel;
732b843f9beSJohn Baldwin 
733b843f9beSJohn Baldwin 	__asm __volatile("sldt %0" : "=r" (sel));
734b843f9beSJohn Baldwin 	return (sel);
735b843f9beSJohn Baldwin }
736b843f9beSJohn Baldwin 
737eb1443c8SPeter Wemm static __inline void
ltr(u_short sel)738eb1443c8SPeter Wemm ltr(u_short sel)
739eb1443c8SPeter Wemm {
740eb1443c8SPeter Wemm 	__asm __volatile("ltr %0" : : "r" (sel));
741eb1443c8SPeter Wemm }
742eb1443c8SPeter Wemm 
743c1538a13SKonstantin Belousov static __inline uint32_t
read_tr(void)744c1538a13SKonstantin Belousov read_tr(void)
745c1538a13SKonstantin Belousov {
746c1538a13SKonstantin Belousov 	u_short sel;
747c1538a13SKonstantin Belousov 
748c1538a13SKonstantin Belousov 	__asm __volatile("str %0" : "=r" (sel));
749c1538a13SKonstantin Belousov 	return (sel);
750c1538a13SKonstantin Belousov }
751c1538a13SKonstantin Belousov 
752f5ac47f4SJung-uk Kim static __inline uint64_t
rdr0(void)7531182b177SPeter Wemm rdr0(void)
7541182b177SPeter Wemm {
755f5ac47f4SJung-uk Kim 	uint64_t data;
7561182b177SPeter Wemm 	__asm __volatile("movq %%dr0,%0" : "=r" (data));
7571182b177SPeter Wemm 	return (data);
7581182b177SPeter Wemm }
7591182b177SPeter Wemm 
7601182b177SPeter Wemm static __inline void
load_dr0(uint64_t dr0)761f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0)
7621182b177SPeter Wemm {
7631182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr0" : : "r" (dr0));
7641182b177SPeter Wemm }
7651182b177SPeter Wemm 
766f5ac47f4SJung-uk Kim static __inline uint64_t
rdr1(void)7671182b177SPeter Wemm rdr1(void)
7681182b177SPeter Wemm {
769f5ac47f4SJung-uk Kim 	uint64_t data;
7701182b177SPeter Wemm 	__asm __volatile("movq %%dr1,%0" : "=r" (data));
7711182b177SPeter Wemm 	return (data);
7721182b177SPeter Wemm }
7731182b177SPeter Wemm 
7741182b177SPeter Wemm static __inline void
load_dr1(uint64_t dr1)775f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1)
7761182b177SPeter Wemm {
7771182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr1" : : "r" (dr1));
7781182b177SPeter Wemm }
7791182b177SPeter Wemm 
780f5ac47f4SJung-uk Kim static __inline uint64_t
rdr2(void)7811182b177SPeter Wemm rdr2(void)
7821182b177SPeter Wemm {
783f5ac47f4SJung-uk Kim 	uint64_t data;
7841182b177SPeter Wemm 	__asm __volatile("movq %%dr2,%0" : "=r" (data));
7851182b177SPeter Wemm 	return (data);
7861182b177SPeter Wemm }
7871182b177SPeter Wemm 
7881182b177SPeter Wemm static __inline void
load_dr2(uint64_t dr2)789f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2)
7901182b177SPeter Wemm {
7911182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr2" : : "r" (dr2));
7921182b177SPeter Wemm }
7931182b177SPeter Wemm 
794f5ac47f4SJung-uk Kim static __inline uint64_t
rdr3(void)7951182b177SPeter Wemm rdr3(void)
7961182b177SPeter Wemm {
797f5ac47f4SJung-uk Kim 	uint64_t data;
7981182b177SPeter Wemm 	__asm __volatile("movq %%dr3,%0" : "=r" (data));
7991182b177SPeter Wemm 	return (data);
8001182b177SPeter Wemm }
8011182b177SPeter Wemm 
8021182b177SPeter Wemm static __inline void
load_dr3(uint64_t dr3)803f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3)
8041182b177SPeter Wemm {
8051182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr3" : : "r" (dr3));
8061182b177SPeter Wemm }
8071182b177SPeter Wemm 
808f5ac47f4SJung-uk Kim static __inline uint64_t
rdr6(void)8091182b177SPeter Wemm rdr6(void)
8101182b177SPeter Wemm {
811f5ac47f4SJung-uk Kim 	uint64_t data;
8121182b177SPeter Wemm 	__asm __volatile("movq %%dr6,%0" : "=r" (data));
8131182b177SPeter Wemm 	return (data);
8141182b177SPeter Wemm }
8151182b177SPeter Wemm 
8161182b177SPeter Wemm static __inline void
load_dr6(uint64_t dr6)817f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6)
8181182b177SPeter Wemm {
8191182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr6" : : "r" (dr6));
8201182b177SPeter Wemm }
8211182b177SPeter Wemm 
822f5ac47f4SJung-uk Kim static __inline uint64_t
rdr7(void)8231182b177SPeter Wemm rdr7(void)
8241182b177SPeter Wemm {
825f5ac47f4SJung-uk Kim 	uint64_t data;
8261182b177SPeter Wemm 	__asm __volatile("movq %%dr7,%0" : "=r" (data));
8271182b177SPeter Wemm 	return (data);
8281182b177SPeter Wemm }
8291182b177SPeter Wemm 
8301182b177SPeter Wemm static __inline void
load_dr7(uint64_t dr7)831f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7)
8321182b177SPeter Wemm {
8331182b177SPeter Wemm 	__asm __volatile("movq %0,%%dr7" : : "r" (dr7));
8341182b177SPeter Wemm }
8351182b177SPeter Wemm 
836ba74981eSWarner Losh static __inline register_t
intr_disable(void)837ba74981eSWarner Losh intr_disable(void)
838ba74981eSWarner Losh {
839afa88623SPeter Wemm 	register_t rflags;
840ba74981eSWarner Losh 
841afa88623SPeter Wemm 	rflags = read_rflags();
842ba74981eSWarner Losh 	disable_intr();
843afa88623SPeter Wemm 	return (rflags);
844ba74981eSWarner Losh }
845ba74981eSWarner Losh 
846ba74981eSWarner Losh static __inline void
intr_restore(register_t rflags)847afa88623SPeter Wemm intr_restore(register_t rflags)
848ba74981eSWarner Losh {
849afa88623SPeter Wemm 	write_rflags(rflags);
850ba74981eSWarner Losh }
851ba74981eSWarner Losh 
8525f7b9ff2SKonstantin Belousov static __inline void
stac(void)8535f7b9ff2SKonstantin Belousov stac(void)
8545f7b9ff2SKonstantin Belousov {
8555f7b9ff2SKonstantin Belousov 
8565f7b9ff2SKonstantin Belousov 	__asm __volatile("stac" : : : "cc");
8575f7b9ff2SKonstantin Belousov }
8585f7b9ff2SKonstantin Belousov 
8595f7b9ff2SKonstantin Belousov static __inline void
clac(void)8605f7b9ff2SKonstantin Belousov clac(void)
8615f7b9ff2SKonstantin Belousov {
8625f7b9ff2SKonstantin Belousov 
8635f7b9ff2SKonstantin Belousov 	__asm __volatile("clac" : : : "cc");
8645f7b9ff2SKonstantin Belousov }
8655f7b9ff2SKonstantin Belousov 
8662164af29SRuslan Bukin enum {
8672164af29SRuslan Bukin 	SGX_ECREATE	= 0x0,
8682164af29SRuslan Bukin 	SGX_EADD	= 0x1,
8692164af29SRuslan Bukin 	SGX_EINIT	= 0x2,
8702164af29SRuslan Bukin 	SGX_EREMOVE	= 0x3,
8712164af29SRuslan Bukin 	SGX_EDGBRD	= 0x4,
8722164af29SRuslan Bukin 	SGX_EDGBWR	= 0x5,
8732164af29SRuslan Bukin 	SGX_EEXTEND	= 0x6,
8742164af29SRuslan Bukin 	SGX_ELDU	= 0x8,
8752164af29SRuslan Bukin 	SGX_EBLOCK	= 0x9,
8762164af29SRuslan Bukin 	SGX_EPA		= 0xA,
8772164af29SRuslan Bukin 	SGX_EWB		= 0xB,
8782164af29SRuslan Bukin 	SGX_ETRACK	= 0xC,
8792164af29SRuslan Bukin };
8802164af29SRuslan Bukin 
8812164af29SRuslan Bukin enum {
8822164af29SRuslan Bukin 	SGX_PT_SECS = 0x00,
8832164af29SRuslan Bukin 	SGX_PT_TCS  = 0x01,
8842164af29SRuslan Bukin 	SGX_PT_REG  = 0x02,
8852164af29SRuslan Bukin 	SGX_PT_VA   = 0x03,
8862164af29SRuslan Bukin 	SGX_PT_TRIM = 0x04,
8872164af29SRuslan Bukin };
8882164af29SRuslan Bukin 
8892164af29SRuslan Bukin int sgx_encls(uint32_t eax, uint64_t rbx, uint64_t rcx, uint64_t rdx);
8902164af29SRuslan Bukin 
8912164af29SRuslan Bukin static __inline int
sgx_ecreate(void * pginfo,void * secs)8922164af29SRuslan Bukin sgx_ecreate(void *pginfo, void *secs)
8932164af29SRuslan Bukin {
8942164af29SRuslan Bukin 
8952164af29SRuslan Bukin 	return (sgx_encls(SGX_ECREATE, (uint64_t)pginfo,
8962164af29SRuslan Bukin 	    (uint64_t)secs, 0));
8972164af29SRuslan Bukin }
8982164af29SRuslan Bukin 
8992164af29SRuslan Bukin static __inline int
sgx_eadd(void * pginfo,void * epc)9002164af29SRuslan Bukin sgx_eadd(void *pginfo, void *epc)
9012164af29SRuslan Bukin {
9022164af29SRuslan Bukin 
9032164af29SRuslan Bukin 	return (sgx_encls(SGX_EADD, (uint64_t)pginfo,
9042164af29SRuslan Bukin 	    (uint64_t)epc, 0));
9052164af29SRuslan Bukin }
9062164af29SRuslan Bukin 
9072164af29SRuslan Bukin static __inline int
sgx_einit(void * sigstruct,void * secs,void * einittoken)9082164af29SRuslan Bukin sgx_einit(void *sigstruct, void *secs, void *einittoken)
9092164af29SRuslan Bukin {
9102164af29SRuslan Bukin 
9112164af29SRuslan Bukin 	return (sgx_encls(SGX_EINIT, (uint64_t)sigstruct,
9122164af29SRuslan Bukin 	    (uint64_t)secs, (uint64_t)einittoken));
9132164af29SRuslan Bukin }
9142164af29SRuslan Bukin 
9152164af29SRuslan Bukin static __inline int
sgx_eextend(void * secs,void * epc)9162164af29SRuslan Bukin sgx_eextend(void *secs, void *epc)
9172164af29SRuslan Bukin {
9182164af29SRuslan Bukin 
9192164af29SRuslan Bukin 	return (sgx_encls(SGX_EEXTEND, (uint64_t)secs,
9202164af29SRuslan Bukin 	    (uint64_t)epc, 0));
9212164af29SRuslan Bukin }
9222164af29SRuslan Bukin 
9232164af29SRuslan Bukin static __inline int
sgx_epa(void * epc)9242164af29SRuslan Bukin sgx_epa(void *epc)
9252164af29SRuslan Bukin {
9262164af29SRuslan Bukin 
9272164af29SRuslan Bukin 	return (sgx_encls(SGX_EPA, SGX_PT_VA, (uint64_t)epc, 0));
9282164af29SRuslan Bukin }
9292164af29SRuslan Bukin 
9302164af29SRuslan Bukin static __inline int
sgx_eldu(uint64_t rbx,uint64_t rcx,uint64_t rdx)9312164af29SRuslan Bukin sgx_eldu(uint64_t rbx, uint64_t rcx,
9322164af29SRuslan Bukin     uint64_t rdx)
9332164af29SRuslan Bukin {
9342164af29SRuslan Bukin 
9352164af29SRuslan Bukin 	return (sgx_encls(SGX_ELDU, rbx, rcx, rdx));
9362164af29SRuslan Bukin }
9372164af29SRuslan Bukin 
9382164af29SRuslan Bukin static __inline int
sgx_eremove(void * epc)9392164af29SRuslan Bukin sgx_eremove(void *epc)
9402164af29SRuslan Bukin {
9412164af29SRuslan Bukin 
9422164af29SRuslan Bukin 	return (sgx_encls(SGX_EREMOVE, 0, (uint64_t)epc, 0));
9432164af29SRuslan Bukin }
9442164af29SRuslan Bukin 
945b63dc6adSAlfred Perlstein void	reset_dbregs(void);
946d74ac681SMatthew Dillon 
947e085f869SStanislav Sedov #ifdef _KERNEL
948e085f869SStanislav Sedov int	rdmsr_safe(u_int msr, uint64_t *val);
949e085f869SStanislav Sedov int	wrmsr_safe(u_int msr, uint64_t newval);
950e085f869SStanislav Sedov #endif
951e085f869SStanislav Sedov 
952004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */
953cca19272SBrooks Davis 
954cca19272SBrooks Davis #endif /* __i386__ */
955