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