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