13c4dd356SDavid Greenman /*- 2fcfe57d6SPeter Wemm * Copyright (c) 2003 Peter Wemm. 33c4dd356SDavid Greenman * Copyright (c) 1993 The Regents of the University of California. 43c4dd356SDavid Greenman * All rights reserved. 53c4dd356SDavid Greenman * 63c4dd356SDavid Greenman * Redistribution and use in source and binary forms, with or without 73c4dd356SDavid Greenman * modification, are permitted provided that the following conditions 83c4dd356SDavid Greenman * are met: 93c4dd356SDavid Greenman * 1. Redistributions of source code must retain the above copyright 103c4dd356SDavid Greenman * notice, this list of conditions and the following disclaimer. 113c4dd356SDavid Greenman * 2. Redistributions in binary form must reproduce the above copyright 123c4dd356SDavid Greenman * notice, this list of conditions and the following disclaimer in the 133c4dd356SDavid Greenman * documentation and/or other materials provided with the distribution. 143c4dd356SDavid Greenman * 4. Neither the name of the University nor the names of its contributors 153c4dd356SDavid Greenman * may be used to endorse or promote products derived from this software 163c4dd356SDavid Greenman * without specific prior written permission. 173c4dd356SDavid Greenman * 183c4dd356SDavid Greenman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 193c4dd356SDavid Greenman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 203c4dd356SDavid Greenman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 213c4dd356SDavid Greenman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 223c4dd356SDavid Greenman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 233c4dd356SDavid Greenman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 243c4dd356SDavid Greenman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 253c4dd356SDavid Greenman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 263c4dd356SDavid Greenman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 273c4dd356SDavid Greenman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 283c4dd356SDavid Greenman * SUCH DAMAGE. 293c4dd356SDavid Greenman * 30c3aac50fSPeter Wemm * $FreeBSD$ 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 396e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_ 40004bedebSBruce Evans #define _MACHINE_CPUFUNC_H_ 416e393973SGarrett Wollman 42a5f50ef9SJoerg Wunsch #ifndef _SYS_CDEFS_H_ 43a5f50ef9SJoerg Wunsch #error this file needs sys/cdefs.h as a prerequisite 44a5f50ef9SJoerg Wunsch #endif 45a5f50ef9SJoerg Wunsch 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 58a5f50ef9SJoerg Wunsch #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE) 595b81b6b3SRodney W. Grimes 605dbd168eSBruce Evans static __inline void 615dbd168eSBruce Evans breakpoint(void) 62004bedebSBruce Evans { 63004bedebSBruce Evans __asm __volatile("int $3"); 645b81b6b3SRodney W. Grimes } 655b81b6b3SRodney W. Grimes 66c83b1328SBruce Evans static __inline u_int 67c83b1328SBruce Evans bsfl(u_int mask) 68c83b1328SBruce Evans { 69c83b1328SBruce Evans u_int result; 70c83b1328SBruce Evans 713f9a462fSJohn Baldwin __asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask)); 72c83b1328SBruce Evans return (result); 73c83b1328SBruce Evans } 74c83b1328SBruce Evans 75176ce2b1SPeter Wemm static __inline u_long 76176ce2b1SPeter Wemm bsfq(u_long mask) 77176ce2b1SPeter Wemm { 78176ce2b1SPeter Wemm u_long result; 79176ce2b1SPeter Wemm 80176ce2b1SPeter Wemm __asm __volatile("bsfq %1,%0" : "=r" (result) : "rm" (mask)); 81176ce2b1SPeter Wemm return (result); 82176ce2b1SPeter Wemm } 83176ce2b1SPeter Wemm 84c83b1328SBruce Evans static __inline u_int 85c83b1328SBruce Evans bsrl(u_int mask) 86c83b1328SBruce Evans { 87c83b1328SBruce Evans u_int result; 88c83b1328SBruce Evans 893f9a462fSJohn Baldwin __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask)); 90c83b1328SBruce Evans return (result); 91c83b1328SBruce Evans } 92c83b1328SBruce Evans 93176ce2b1SPeter Wemm static __inline u_long 94176ce2b1SPeter Wemm bsrq(u_long mask) 95176ce2b1SPeter Wemm { 96176ce2b1SPeter Wemm u_long result; 97176ce2b1SPeter Wemm 98176ce2b1SPeter Wemm __asm __volatile("bsrq %1,%0" : "=r" (result) : "rm" (mask)); 99176ce2b1SPeter Wemm return (result); 100176ce2b1SPeter Wemm } 101176ce2b1SPeter Wemm 102004bedebSBruce Evans static __inline void 103206a3368SKonstantin Belousov clflush(u_long addr) 104206a3368SKonstantin Belousov { 105206a3368SKonstantin Belousov 106206a3368SKonstantin Belousov __asm __volatile("clflush %0" : : "m" (*(char *)addr)); 107206a3368SKonstantin Belousov } 108206a3368SKonstantin Belousov 109206a3368SKonstantin Belousov static __inline void 110d706ec29SJohn Baldwin clts(void) 111d706ec29SJohn Baldwin { 112d706ec29SJohn Baldwin 113d706ec29SJohn Baldwin __asm __volatile("clts"); 114d706ec29SJohn Baldwin } 115d706ec29SJohn Baldwin 116d706ec29SJohn Baldwin static __inline void 1175b81b6b3SRodney W. Grimes disable_intr(void) 1185b81b6b3SRodney W. Grimes { 1198966b85cSJohn Dyson __asm __volatile("cli" : : : "memory"); 1205b81b6b3SRodney W. Grimes } 1215b81b6b3SRodney W. Grimes 122004bedebSBruce Evans static __inline void 123a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p) 124a983fdfeSDavid Malone { 125a983fdfeSDavid Malone __asm __volatile("cpuid" 126a983fdfeSDavid Malone : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 127a983fdfeSDavid Malone : "0" (ax)); 128a983fdfeSDavid Malone } 129a983fdfeSDavid Malone 130a983fdfeSDavid Malone static __inline void 131f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p) 132f6108b61SJacques Vidrine { 133f6108b61SJacques Vidrine __asm __volatile("cpuid" 134f6108b61SJacques Vidrine : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 135f6108b61SJacques Vidrine : "0" (ax), "c" (cx)); 136f6108b61SJacques Vidrine } 137f6108b61SJacques Vidrine 138f6108b61SJacques Vidrine static __inline void 1395b81b6b3SRodney W. Grimes enable_intr(void) 1405b81b6b3SRodney W. Grimes { 141fadc51bdSBruce Evans __asm __volatile("sti"); 1425b81b6b3SRodney W. Grimes } 1435b81b6b3SRodney W. Grimes 144a67ef0a7SBruce Evans #ifdef _KERNEL 145a67ef0a7SBruce Evans 146264c3d87SPeter Wemm #define HAVE_INLINE_FFS 147bc35f5dcSPaul Saab #define ffs(x) __builtin_ffs(x) 148176ce2b1SPeter Wemm 149176ce2b1SPeter Wemm #define HAVE_INLINE_FFSL 150176ce2b1SPeter Wemm 151176ce2b1SPeter Wemm static __inline int 152176ce2b1SPeter Wemm ffsl(long mask) 153176ce2b1SPeter Wemm { 154176ce2b1SPeter Wemm return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1); 155004bedebSBruce Evans } 156004bedebSBruce Evans 15713f588f8SGarrett Wollman #define HAVE_INLINE_FLS 15813f588f8SGarrett Wollman 15913f588f8SGarrett Wollman static __inline int 16013f588f8SGarrett Wollman fls(int mask) 16113f588f8SGarrett Wollman { 1627e622d3cSMark Murray return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 16313f588f8SGarrett Wollman } 16413f588f8SGarrett Wollman 165176ce2b1SPeter Wemm #define HAVE_INLINE_FLSL 166176ce2b1SPeter Wemm 167176ce2b1SPeter Wemm static __inline int 168176ce2b1SPeter Wemm flsl(long mask) 169176ce2b1SPeter Wemm { 170176ce2b1SPeter Wemm return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1); 171176ce2b1SPeter Wemm } 172176ce2b1SPeter Wemm 173a67ef0a7SBruce Evans #endif /* _KERNEL */ 174a67ef0a7SBruce Evans 175d7ee4425SMark Murray static __inline void 176d7ee4425SMark Murray halt(void) 177d7ee4425SMark Murray { 178d7ee4425SMark Murray __asm __volatile("hlt"); 179d7ee4425SMark Murray } 180d7ee4425SMark Murray 181004bedebSBruce Evans static __inline u_char 182e1048f76SEd Schouten inb(u_int port) 183004bedebSBruce Evans { 184004bedebSBruce Evans u_char data; 185004bedebSBruce Evans 1864854ae24SJung-uk Kim __asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); 187004bedebSBruce Evans return (data); 188004bedebSBruce Evans } 189004bedebSBruce Evans 19000be8601SBruce Evans static __inline u_int 191004bedebSBruce Evans inl(u_int port) 192004bedebSBruce Evans { 19300be8601SBruce Evans u_int data; 194004bedebSBruce Evans 1954854ae24SJung-uk Kim __asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); 196004bedebSBruce Evans return (data); 197004bedebSBruce Evans } 198004bedebSBruce Evans 199004bedebSBruce Evans static __inline void 20093d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count) 201004bedebSBruce Evans { 202004bedebSBruce Evans __asm __volatile("cld; rep; insb" 20393d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2043f9a462fSJohn Baldwin : "d" (port) 205896763faSBruce Evans : "memory"); 206004bedebSBruce Evans } 207004bedebSBruce Evans 208004bedebSBruce Evans static __inline void 20993d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count) 210004bedebSBruce Evans { 211004bedebSBruce Evans __asm __volatile("cld; rep; insw" 21293d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2133f9a462fSJohn Baldwin : "d" (port) 214896763faSBruce Evans : "memory"); 215004bedebSBruce Evans } 216004bedebSBruce Evans 217004bedebSBruce Evans static __inline void 21893d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count) 219004bedebSBruce Evans { 220004bedebSBruce Evans __asm __volatile("cld; rep; insl" 22193d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2223f9a462fSJohn Baldwin : "d" (port) 223896763faSBruce Evans : "memory"); 224004bedebSBruce Evans } 225004bedebSBruce Evans 226ece15d78SBruce Evans static __inline void 2274c024bbdSKATO Takenori invd(void) 2284c024bbdSKATO Takenori { 2294c024bbdSKATO Takenori __asm __volatile("invd"); 2304c024bbdSKATO Takenori } 2314c024bbdSKATO Takenori 232004bedebSBruce Evans static __inline u_short 233004bedebSBruce Evans inw(u_int port) 234004bedebSBruce Evans { 235004bedebSBruce Evans u_short data; 236004bedebSBruce Evans 2374854ae24SJung-uk Kim __asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port)); 238004bedebSBruce Evans return (data); 239004bedebSBruce Evans } 240004bedebSBruce Evans 241004bedebSBruce Evans static __inline void 242e1048f76SEd Schouten outb(u_int port, u_char data) 243004bedebSBruce Evans { 2444854ae24SJung-uk Kim __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); 245004bedebSBruce Evans } 246004bedebSBruce Evans 247004bedebSBruce Evans static __inline void 24800be8601SBruce Evans outl(u_int port, u_int data) 249004bedebSBruce Evans { 2504854ae24SJung-uk Kim __asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); 251004bedebSBruce Evans } 252004bedebSBruce Evans 253004bedebSBruce Evans static __inline void 25493d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count) 255004bedebSBruce Evans { 256004bedebSBruce Evans __asm __volatile("cld; rep; outsb" 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 outsw(u_int port, const void *addr, size_t count) 263004bedebSBruce Evans { 264004bedebSBruce Evans __asm __volatile("cld; rep; outsw" 26593d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2663f9a462fSJohn Baldwin : "d" (port)); 267004bedebSBruce Evans } 268004bedebSBruce Evans 269004bedebSBruce Evans static __inline void 27093d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count) 271004bedebSBruce Evans { 272004bedebSBruce Evans __asm __volatile("cld; rep; outsl" 27393d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2743f9a462fSJohn Baldwin : "d" (port)); 275004bedebSBruce Evans } 276004bedebSBruce Evans 277004bedebSBruce Evans static __inline void 278004bedebSBruce Evans outw(u_int port, u_short data) 279004bedebSBruce Evans { 2804854ae24SJung-uk Kim __asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); 281004bedebSBruce Evans } 282004bedebSBruce Evans 2832bde6e35SAlan Cox static __inline u_long 2842bde6e35SAlan Cox popcntq(u_long mask) 2852bde6e35SAlan Cox { 2862bde6e35SAlan Cox u_long result; 2872bde6e35SAlan Cox 2882bde6e35SAlan Cox __asm __volatile("popcntq %1,%0" : "=r" (result) : "rm" (mask)); 2892bde6e35SAlan Cox return (result); 2902bde6e35SAlan Cox } 2912bde6e35SAlan Cox 2922be69f32SJohn Baldwin static __inline void 293*0220d04fSKonstantin Belousov lfence(void) 294*0220d04fSKonstantin Belousov { 295*0220d04fSKonstantin Belousov 296*0220d04fSKonstantin Belousov __asm __volatile("lfence" : : : "memory"); 297*0220d04fSKonstantin Belousov } 298*0220d04fSKonstantin Belousov 299*0220d04fSKonstantin Belousov static __inline void 300206a3368SKonstantin Belousov mfence(void) 301206a3368SKonstantin Belousov { 302206a3368SKonstantin Belousov 303beb2c1f3SAndriy Gapon __asm __volatile("mfence" : : : "memory"); 304206a3368SKonstantin Belousov } 305206a3368SKonstantin Belousov 306206a3368SKonstantin Belousov static __inline void 3076b8c6989SJohn Baldwin ia32_pause(void) 3082be69f32SJohn Baldwin { 3092be69f32SJohn Baldwin __asm __volatile("pause"); 3102be69f32SJohn Baldwin } 3112be69f32SJohn Baldwin 312afa88623SPeter Wemm static __inline u_long 313afa88623SPeter Wemm read_rflags(void) 3145b81b6b3SRodney W. Grimes { 315afa88623SPeter Wemm u_long rf; 316004bedebSBruce Evans 317afa88623SPeter Wemm __asm __volatile("pushfq; popq %0" : "=r" (rf)); 318afa88623SPeter Wemm return (rf); 3195b81b6b3SRodney W. Grimes } 3205b81b6b3SRodney W. Grimes 321f5ac47f4SJung-uk Kim static __inline uint64_t 3225dbd168eSBruce Evans rdmsr(u_int msr) 3235dbd168eSBruce Evans { 324f5ac47f4SJung-uk Kim uint32_t low, high; 3255dbd168eSBruce Evans 326afa88623SPeter Wemm __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); 327f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3285dbd168eSBruce Evans } 3295dbd168eSBruce Evans 330f5ac47f4SJung-uk Kim static __inline uint64_t 3315dbd168eSBruce Evans rdpmc(u_int pmc) 3325dbd168eSBruce Evans { 333f5ac47f4SJung-uk Kim uint32_t low, high; 3345dbd168eSBruce Evans 335afa88623SPeter Wemm __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc)); 336f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3375dbd168eSBruce Evans } 3385dbd168eSBruce Evans 339f5ac47f4SJung-uk Kim static __inline uint64_t 3405dbd168eSBruce Evans rdtsc(void) 3415dbd168eSBruce Evans { 342f5ac47f4SJung-uk Kim uint32_t low, high; 3435dbd168eSBruce Evans 344afa88623SPeter Wemm __asm __volatile("rdtsc" : "=a" (low), "=d" (high)); 345f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3465dbd168eSBruce Evans } 3475dbd168eSBruce Evans 3480e727642SJung-uk Kim static __inline uint32_t 3490e727642SJung-uk Kim rdtsc32(void) 3500e727642SJung-uk Kim { 3510e727642SJung-uk Kim uint32_t rv; 3520e727642SJung-uk Kim 3530e727642SJung-uk Kim __asm __volatile("rdtsc" : "=a" (rv) : : "edx"); 3540e727642SJung-uk Kim return (rv); 3550e727642SJung-uk Kim } 3560e727642SJung-uk Kim 357004bedebSBruce Evans static __inline void 3584c024bbdSKATO Takenori wbinvd(void) 3594c024bbdSKATO Takenori { 3604c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3614c024bbdSKATO Takenori } 3624c024bbdSKATO Takenori 3634c024bbdSKATO Takenori static __inline void 364afa88623SPeter Wemm write_rflags(u_long rf) 3655b81b6b3SRodney W. Grimes { 366afa88623SPeter Wemm __asm __volatile("pushq %0; popfq" : : "r" (rf)); 3675b81b6b3SRodney W. Grimes } 3685b81b6b3SRodney W. Grimes 369d69e8502SGarrett Wollman static __inline void 370f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval) 371d69e8502SGarrett Wollman { 372f5ac47f4SJung-uk Kim uint32_t low, high; 373afa88623SPeter Wemm 374afa88623SPeter Wemm low = newval; 375afa88623SPeter Wemm high = newval >> 32; 376afa88623SPeter Wemm __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 377d69e8502SGarrett Wollman } 378d69e8502SGarrett Wollman 379f1b665c8SPeter Wemm static __inline void 380afa88623SPeter Wemm load_cr0(u_long data) 381f1b665c8SPeter Wemm { 382f1b665c8SPeter Wemm 383afa88623SPeter Wemm __asm __volatile("movq %0,%%cr0" : : "r" (data)); 384f1b665c8SPeter Wemm } 385f1b665c8SPeter Wemm 386afa88623SPeter Wemm static __inline u_long 387f1b665c8SPeter Wemm rcr0(void) 388f1b665c8SPeter Wemm { 389afa88623SPeter Wemm u_long data; 390f1b665c8SPeter Wemm 391afa88623SPeter Wemm __asm __volatile("movq %%cr0,%0" : "=r" (data)); 392f1b665c8SPeter Wemm return (data); 393f1b665c8SPeter Wemm } 394f1b665c8SPeter Wemm 395afa88623SPeter Wemm static __inline u_long 396f1b665c8SPeter Wemm rcr2(void) 397f1b665c8SPeter Wemm { 398afa88623SPeter Wemm u_long data; 399f1b665c8SPeter Wemm 400afa88623SPeter Wemm __asm __volatile("movq %%cr2,%0" : "=r" (data)); 401f1b665c8SPeter Wemm return (data); 402f1b665c8SPeter Wemm } 403f1b665c8SPeter Wemm 404f1b665c8SPeter Wemm static __inline void 405afa88623SPeter Wemm load_cr3(u_long data) 406f1b665c8SPeter Wemm { 407f1b665c8SPeter Wemm 408afa88623SPeter Wemm __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory"); 409f1b665c8SPeter Wemm } 410f1b665c8SPeter Wemm 411afa88623SPeter Wemm static __inline u_long 412f1b665c8SPeter Wemm rcr3(void) 413f1b665c8SPeter Wemm { 414afa88623SPeter Wemm u_long data; 415f1b665c8SPeter Wemm 416afa88623SPeter Wemm __asm __volatile("movq %%cr3,%0" : "=r" (data)); 417f1b665c8SPeter Wemm return (data); 418f1b665c8SPeter Wemm } 419f1b665c8SPeter Wemm 420f1b665c8SPeter Wemm static __inline void 421afa88623SPeter Wemm load_cr4(u_long data) 422f1b665c8SPeter Wemm { 423afa88623SPeter Wemm __asm __volatile("movq %0,%%cr4" : : "r" (data)); 424f1b665c8SPeter Wemm } 425f1b665c8SPeter Wemm 426afa88623SPeter Wemm static __inline u_long 427f1b665c8SPeter Wemm rcr4(void) 428f1b665c8SPeter Wemm { 429afa88623SPeter Wemm u_long data; 430f1b665c8SPeter Wemm 431afa88623SPeter Wemm __asm __volatile("movq %%cr4,%0" : "=r" (data)); 432f1b665c8SPeter Wemm return (data); 433f1b665c8SPeter Wemm } 434f1b665c8SPeter Wemm 4357574a595SJohn Baldwin static __inline u_long 4367574a595SJohn Baldwin rxcr(u_int reg) 4377574a595SJohn Baldwin { 4387574a595SJohn Baldwin u_int low, high; 4397574a595SJohn Baldwin 4407574a595SJohn Baldwin __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 4417574a595SJohn Baldwin return (low | ((uint64_t)high << 32)); 4427574a595SJohn Baldwin } 4437574a595SJohn Baldwin 4447574a595SJohn Baldwin static __inline void 4457574a595SJohn Baldwin load_xcr(u_int reg, u_long val) 4467574a595SJohn Baldwin { 4477574a595SJohn Baldwin u_int low, high; 4487574a595SJohn Baldwin 4497574a595SJohn Baldwin low = val; 4507574a595SJohn Baldwin high = val >> 32; 4517574a595SJohn Baldwin __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 4527574a595SJohn Baldwin } 4537574a595SJohn Baldwin 454f1b665c8SPeter Wemm /* 455f1b665c8SPeter Wemm * Global TLB flush (except for thise for pages marked PG_G) 456f1b665c8SPeter Wemm */ 457f1b665c8SPeter Wemm static __inline void 458f1b665c8SPeter Wemm invltlb(void) 459f1b665c8SPeter Wemm { 460f1b665c8SPeter Wemm 461f1b665c8SPeter Wemm load_cr3(rcr3()); 462f1b665c8SPeter Wemm } 463f1b665c8SPeter Wemm 464f1b665c8SPeter Wemm /* 465f1b665c8SPeter Wemm * TLB flush for an individual page (even if it has PG_G). 466f1b665c8SPeter Wemm * Only works on 486+ CPUs (i386 does not have PG_G). 467f1b665c8SPeter Wemm */ 468f1b665c8SPeter Wemm static __inline void 469afa88623SPeter Wemm invlpg(u_long addr) 470f1b665c8SPeter Wemm { 471f1b665c8SPeter Wemm 472f1b665c8SPeter Wemm __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 473f1b665c8SPeter Wemm } 474f1b665c8SPeter Wemm 47527d4fea6SRoman Divacky static __inline u_short 4765206bca1SLuoqi Chen rfs(void) 4775206bca1SLuoqi Chen { 47827d4fea6SRoman Divacky u_short sel; 47927d4fea6SRoman Divacky __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 4805206bca1SLuoqi Chen return (sel); 4815206bca1SLuoqi Chen } 4825206bca1SLuoqi Chen 48327d4fea6SRoman Divacky static __inline u_short 4845206bca1SLuoqi Chen rgs(void) 4855206bca1SLuoqi Chen { 48627d4fea6SRoman Divacky u_short sel; 48727d4fea6SRoman Divacky __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 4885206bca1SLuoqi Chen return (sel); 4895206bca1SLuoqi Chen } 4905206bca1SLuoqi Chen 49127d4fea6SRoman Divacky static __inline u_short 492cd0149e3SPeter Wemm rss(void) 493cd0149e3SPeter Wemm { 49427d4fea6SRoman Divacky u_short sel; 49527d4fea6SRoman Divacky __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 496cd0149e3SPeter Wemm return (sel); 497cd0149e3SPeter Wemm } 498cd0149e3SPeter Wemm 4995206bca1SLuoqi Chen static __inline void 50027d4fea6SRoman Divacky load_ds(u_short sel) 501d85631c4SPeter Wemm { 50227d4fea6SRoman Divacky __asm __volatile("movw %0,%%ds" : : "rm" (sel)); 503d85631c4SPeter Wemm } 504d85631c4SPeter Wemm 505d85631c4SPeter Wemm static __inline void 50627d4fea6SRoman Divacky load_es(u_short sel) 507d85631c4SPeter Wemm { 50827d4fea6SRoman Divacky __asm __volatile("movw %0,%%es" : : "rm" (sel)); 509d85631c4SPeter Wemm } 510d85631c4SPeter Wemm 511beb2c1f3SAndriy Gapon static __inline void 512f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints) 51366247efaSJeff Roberson { 514f0b28f00SJung-uk Kim 515f0b28f00SJung-uk Kim __asm __volatile("monitor" 51666247efaSJeff Roberson : : "a" (addr), "c" (extensions), "d" (hints)); 51766247efaSJeff Roberson } 51866247efaSJeff Roberson 519beb2c1f3SAndriy Gapon static __inline void 520f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints) 52166247efaSJeff Roberson { 522f0b28f00SJung-uk Kim 523f0b28f00SJung-uk Kim __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); 52466247efaSJeff Roberson } 52566247efaSJeff Roberson 526c0a54ff6SPeter Wemm #ifdef _KERNEL 527c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */ 528c0a54ff6SPeter Wemm #ifndef MSR_FSBASE 529c0a54ff6SPeter Wemm #define MSR_FSBASE 0xc0000100 530c0a54ff6SPeter Wemm #endif 531c0a54ff6SPeter Wemm static __inline void 53227d4fea6SRoman Divacky load_fs(u_short sel) 533c0a54ff6SPeter Wemm { 534c0a54ff6SPeter Wemm /* Preserve the fsbase value across the selector load */ 53527d4fea6SRoman Divacky __asm __volatile("rdmsr; movw %0,%%fs; wrmsr" 536db26a671SEd Schouten : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx"); 537c0a54ff6SPeter Wemm } 538c0a54ff6SPeter Wemm 539c0a54ff6SPeter Wemm #ifndef MSR_GSBASE 540c0a54ff6SPeter Wemm #define MSR_GSBASE 0xc0000101 541c0a54ff6SPeter Wemm #endif 542c0a54ff6SPeter Wemm static __inline void 54327d4fea6SRoman Divacky load_gs(u_short sel) 544c0a54ff6SPeter Wemm { 545c0a54ff6SPeter Wemm /* 546c0a54ff6SPeter Wemm * Preserve the gsbase value across the selector load. 547c0a54ff6SPeter Wemm * Note that we have to disable interrupts because the gsbase 548c0a54ff6SPeter Wemm * being trashed happens to be the kernel gsbase at the time. 549c0a54ff6SPeter Wemm */ 55027d4fea6SRoman Divacky __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq" 551db26a671SEd Schouten : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx"); 552c0a54ff6SPeter Wemm } 553c0a54ff6SPeter Wemm #else 554c0a54ff6SPeter Wemm /* Usable by userland */ 555d85631c4SPeter Wemm static __inline void 55627d4fea6SRoman Divacky load_fs(u_short sel) 5575206bca1SLuoqi Chen { 55827d4fea6SRoman Divacky __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 5595206bca1SLuoqi Chen } 5605206bca1SLuoqi Chen 5615206bca1SLuoqi Chen static __inline void 56227d4fea6SRoman Divacky load_gs(u_short sel) 5635206bca1SLuoqi Chen { 56427d4fea6SRoman Divacky __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 5655206bca1SLuoqi Chen } 566c0a54ff6SPeter Wemm #endif 5675206bca1SLuoqi Chen 568eb1443c8SPeter Wemm static __inline void 569eb1443c8SPeter Wemm lidt(struct region_descriptor *addr) 570eb1443c8SPeter Wemm { 571eb1443c8SPeter Wemm __asm __volatile("lidt (%0)" : : "r" (addr)); 572eb1443c8SPeter Wemm } 573eb1443c8SPeter Wemm 574eb1443c8SPeter Wemm static __inline void 575eb1443c8SPeter Wemm lldt(u_short sel) 576eb1443c8SPeter Wemm { 577eb1443c8SPeter Wemm __asm __volatile("lldt %0" : : "r" (sel)); 578eb1443c8SPeter Wemm } 579eb1443c8SPeter Wemm 580eb1443c8SPeter Wemm static __inline void 581eb1443c8SPeter Wemm ltr(u_short sel) 582eb1443c8SPeter Wemm { 583eb1443c8SPeter Wemm __asm __volatile("ltr %0" : : "r" (sel)); 584eb1443c8SPeter Wemm } 585eb1443c8SPeter Wemm 586f5ac47f4SJung-uk Kim static __inline uint64_t 5871182b177SPeter Wemm rdr0(void) 5881182b177SPeter Wemm { 589f5ac47f4SJung-uk Kim uint64_t data; 5901182b177SPeter Wemm __asm __volatile("movq %%dr0,%0" : "=r" (data)); 5911182b177SPeter Wemm return (data); 5921182b177SPeter Wemm } 5931182b177SPeter Wemm 5941182b177SPeter Wemm static __inline void 595f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0) 5961182b177SPeter Wemm { 5971182b177SPeter Wemm __asm __volatile("movq %0,%%dr0" : : "r" (dr0)); 5981182b177SPeter Wemm } 5991182b177SPeter Wemm 600f5ac47f4SJung-uk Kim static __inline uint64_t 6011182b177SPeter Wemm rdr1(void) 6021182b177SPeter Wemm { 603f5ac47f4SJung-uk Kim uint64_t data; 6041182b177SPeter Wemm __asm __volatile("movq %%dr1,%0" : "=r" (data)); 6051182b177SPeter Wemm return (data); 6061182b177SPeter Wemm } 6071182b177SPeter Wemm 6081182b177SPeter Wemm static __inline void 609f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1) 6101182b177SPeter Wemm { 6111182b177SPeter Wemm __asm __volatile("movq %0,%%dr1" : : "r" (dr1)); 6121182b177SPeter Wemm } 6131182b177SPeter Wemm 614f5ac47f4SJung-uk Kim static __inline uint64_t 6151182b177SPeter Wemm rdr2(void) 6161182b177SPeter Wemm { 617f5ac47f4SJung-uk Kim uint64_t data; 6181182b177SPeter Wemm __asm __volatile("movq %%dr2,%0" : "=r" (data)); 6191182b177SPeter Wemm return (data); 6201182b177SPeter Wemm } 6211182b177SPeter Wemm 6221182b177SPeter Wemm static __inline void 623f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2) 6241182b177SPeter Wemm { 6251182b177SPeter Wemm __asm __volatile("movq %0,%%dr2" : : "r" (dr2)); 6261182b177SPeter Wemm } 6271182b177SPeter Wemm 628f5ac47f4SJung-uk Kim static __inline uint64_t 6291182b177SPeter Wemm rdr3(void) 6301182b177SPeter Wemm { 631f5ac47f4SJung-uk Kim uint64_t data; 6321182b177SPeter Wemm __asm __volatile("movq %%dr3,%0" : "=r" (data)); 6331182b177SPeter Wemm return (data); 6341182b177SPeter Wemm } 6351182b177SPeter Wemm 6361182b177SPeter Wemm static __inline void 637f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3) 6381182b177SPeter Wemm { 6391182b177SPeter Wemm __asm __volatile("movq %0,%%dr3" : : "r" (dr3)); 6401182b177SPeter Wemm } 6411182b177SPeter Wemm 642f5ac47f4SJung-uk Kim static __inline uint64_t 6431182b177SPeter Wemm rdr4(void) 6441182b177SPeter Wemm { 645f5ac47f4SJung-uk Kim uint64_t data; 6461182b177SPeter Wemm __asm __volatile("movq %%dr4,%0" : "=r" (data)); 6471182b177SPeter Wemm return (data); 6481182b177SPeter Wemm } 6491182b177SPeter Wemm 6501182b177SPeter Wemm static __inline void 651f5ac47f4SJung-uk Kim load_dr4(uint64_t dr4) 6521182b177SPeter Wemm { 6531182b177SPeter Wemm __asm __volatile("movq %0,%%dr4" : : "r" (dr4)); 6541182b177SPeter Wemm } 6551182b177SPeter Wemm 656f5ac47f4SJung-uk Kim static __inline uint64_t 6571182b177SPeter Wemm rdr5(void) 6581182b177SPeter Wemm { 659f5ac47f4SJung-uk Kim uint64_t data; 6601182b177SPeter Wemm __asm __volatile("movq %%dr5,%0" : "=r" (data)); 6611182b177SPeter Wemm return (data); 6621182b177SPeter Wemm } 6631182b177SPeter Wemm 6641182b177SPeter Wemm static __inline void 665f5ac47f4SJung-uk Kim load_dr5(uint64_t dr5) 6661182b177SPeter Wemm { 6671182b177SPeter Wemm __asm __volatile("movq %0,%%dr5" : : "r" (dr5)); 6681182b177SPeter Wemm } 6691182b177SPeter Wemm 670f5ac47f4SJung-uk Kim static __inline uint64_t 6711182b177SPeter Wemm rdr6(void) 6721182b177SPeter Wemm { 673f5ac47f4SJung-uk Kim uint64_t data; 6741182b177SPeter Wemm __asm __volatile("movq %%dr6,%0" : "=r" (data)); 6751182b177SPeter Wemm return (data); 6761182b177SPeter Wemm } 6771182b177SPeter Wemm 6781182b177SPeter Wemm static __inline void 679f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6) 6801182b177SPeter Wemm { 6811182b177SPeter Wemm __asm __volatile("movq %0,%%dr6" : : "r" (dr6)); 6821182b177SPeter Wemm } 6831182b177SPeter Wemm 684f5ac47f4SJung-uk Kim static __inline uint64_t 6851182b177SPeter Wemm rdr7(void) 6861182b177SPeter Wemm { 687f5ac47f4SJung-uk Kim uint64_t data; 6881182b177SPeter Wemm __asm __volatile("movq %%dr7,%0" : "=r" (data)); 6891182b177SPeter Wemm return (data); 6901182b177SPeter Wemm } 6911182b177SPeter Wemm 6921182b177SPeter Wemm static __inline void 693f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7) 6941182b177SPeter Wemm { 6951182b177SPeter Wemm __asm __volatile("movq %0,%%dr7" : : "r" (dr7)); 6961182b177SPeter Wemm } 6971182b177SPeter Wemm 698ba74981eSWarner Losh static __inline register_t 699ba74981eSWarner Losh intr_disable(void) 700ba74981eSWarner Losh { 701afa88623SPeter Wemm register_t rflags; 702ba74981eSWarner Losh 703afa88623SPeter Wemm rflags = read_rflags(); 704ba74981eSWarner Losh disable_intr(); 705afa88623SPeter Wemm return (rflags); 706ba74981eSWarner Losh } 707ba74981eSWarner Losh 708ba74981eSWarner Losh static __inline void 709afa88623SPeter Wemm intr_restore(register_t rflags) 710ba74981eSWarner Losh { 711afa88623SPeter Wemm write_rflags(rflags); 712ba74981eSWarner Losh } 713ba74981eSWarner Losh 714a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 7155b81b6b3SRodney W. Grimes 716b63dc6adSAlfred Perlstein int breakpoint(void); 717b63dc6adSAlfred Perlstein u_int bsfl(u_int mask); 718b63dc6adSAlfred Perlstein u_int bsrl(u_int mask); 719d706ec29SJohn Baldwin void clflush(u_long addr); 720d706ec29SJohn Baldwin void clts(void); 721d706ec29SJohn Baldwin void cpuid_count(u_int ax, u_int cx, u_int *p); 722b63dc6adSAlfred Perlstein void disable_intr(void); 723b63dc6adSAlfred Perlstein void do_cpuid(u_int ax, u_int *p); 724b63dc6adSAlfred Perlstein void enable_intr(void); 725d7ee4425SMark Murray void halt(void); 7264f6c19e5SPeter Wemm void ia32_pause(void); 727b63dc6adSAlfred Perlstein u_char inb(u_int port); 728b63dc6adSAlfred Perlstein u_int inl(u_int port); 72993d8be03SDavid E. O'Brien void insb(u_int port, void *addr, size_t count); 73093d8be03SDavid E. O'Brien void insl(u_int port, void *addr, size_t count); 73193d8be03SDavid E. O'Brien void insw(u_int port, void *addr, size_t count); 7324f6c19e5SPeter Wemm register_t intr_disable(void); 7334f6c19e5SPeter Wemm void intr_restore(register_t rf); 734b63dc6adSAlfred Perlstein void invd(void); 735b63dc6adSAlfred Perlstein void invlpg(u_int addr); 736b63dc6adSAlfred Perlstein void invltlb(void); 737b63dc6adSAlfred Perlstein u_short inw(u_int port); 738eb1443c8SPeter Wemm void lidt(struct region_descriptor *addr); 739eb1443c8SPeter Wemm void lldt(u_short sel); 7404f6c19e5SPeter Wemm void load_cr0(u_long cr0); 7414f6c19e5SPeter Wemm void load_cr3(u_long cr3); 7424f6c19e5SPeter Wemm void load_cr4(u_long cr4); 743f5ac47f4SJung-uk Kim void load_dr0(uint64_t dr0); 744f5ac47f4SJung-uk Kim void load_dr1(uint64_t dr1); 745f5ac47f4SJung-uk Kim void load_dr2(uint64_t dr2); 746f5ac47f4SJung-uk Kim void load_dr3(uint64_t dr3); 747f5ac47f4SJung-uk Kim void load_dr4(uint64_t dr4); 748f5ac47f4SJung-uk Kim void load_dr5(uint64_t dr5); 749f5ac47f4SJung-uk Kim void load_dr6(uint64_t dr6); 750f5ac47f4SJung-uk Kim void load_dr7(uint64_t dr7); 75127d4fea6SRoman Divacky void load_fs(u_short sel); 75227d4fea6SRoman Divacky void load_gs(u_short sel); 753eb1443c8SPeter Wemm void ltr(u_short sel); 754b63dc6adSAlfred Perlstein void outb(u_int port, u_char data); 755b63dc6adSAlfred Perlstein void outl(u_int port, u_int data); 75693d8be03SDavid E. O'Brien void outsb(u_int port, const void *addr, size_t count); 75793d8be03SDavid E. O'Brien void outsl(u_int port, const void *addr, size_t count); 75893d8be03SDavid E. O'Brien void outsw(u_int port, const void *addr, size_t count); 759b63dc6adSAlfred Perlstein void outw(u_int port, u_short data); 7604f6c19e5SPeter Wemm u_long rcr0(void); 7614f6c19e5SPeter Wemm u_long rcr2(void); 7624f6c19e5SPeter Wemm u_long rcr3(void); 7634f6c19e5SPeter Wemm u_long rcr4(void); 764f5ac47f4SJung-uk Kim uint64_t rdmsr(u_int msr); 765f5ac47f4SJung-uk Kim uint64_t rdpmc(u_int pmc); 766f5ac47f4SJung-uk Kim uint64_t rdr0(void); 767f5ac47f4SJung-uk Kim uint64_t rdr1(void); 768f5ac47f4SJung-uk Kim uint64_t rdr2(void); 769f5ac47f4SJung-uk Kim uint64_t rdr3(void); 770f5ac47f4SJung-uk Kim uint64_t rdr4(void); 771f5ac47f4SJung-uk Kim uint64_t rdr5(void); 772f5ac47f4SJung-uk Kim uint64_t rdr6(void); 773f5ac47f4SJung-uk Kim uint64_t rdr7(void); 774f5ac47f4SJung-uk Kim uint64_t rdtsc(void); 775a61dd1bdSJohn Baldwin u_long read_rflags(void); 7764f6c19e5SPeter Wemm u_int rfs(void); 7774f6c19e5SPeter Wemm u_int rgs(void); 778b63dc6adSAlfred Perlstein void wbinvd(void); 779afa88623SPeter Wemm void write_rflags(u_int rf); 780f5ac47f4SJung-uk Kim void wrmsr(u_int msr, uint64_t newval); 781004bedebSBruce Evans 782a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 7835b81b6b3SRodney W. Grimes 784b63dc6adSAlfred Perlstein void reset_dbregs(void); 785d74ac681SMatthew Dillon 786e085f869SStanislav Sedov #ifdef _KERNEL 787e085f869SStanislav Sedov int rdmsr_safe(u_int msr, uint64_t *val); 788e085f869SStanislav Sedov int wrmsr_safe(u_int msr, uint64_t newval); 789e085f869SStanislav Sedov #endif 790e085f869SStanislav Sedov 791004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 792