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