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 110*d706ec29SJohn Baldwin clts(void) 111*d706ec29SJohn Baldwin { 112*d706ec29SJohn Baldwin 113*d706ec29SJohn Baldwin __asm __volatile("clts"); 114*d706ec29SJohn Baldwin } 115*d706ec29SJohn Baldwin 116*d706ec29SJohn 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 293206a3368SKonstantin Belousov mfence(void) 294206a3368SKonstantin Belousov { 295206a3368SKonstantin Belousov 296beb2c1f3SAndriy Gapon __asm __volatile("mfence" : : : "memory"); 297206a3368SKonstantin Belousov } 298206a3368SKonstantin Belousov 299206a3368SKonstantin Belousov static __inline void 3006b8c6989SJohn Baldwin ia32_pause(void) 3012be69f32SJohn Baldwin { 3022be69f32SJohn Baldwin __asm __volatile("pause"); 3032be69f32SJohn Baldwin } 3042be69f32SJohn Baldwin 305afa88623SPeter Wemm static __inline u_long 306afa88623SPeter Wemm read_rflags(void) 3075b81b6b3SRodney W. Grimes { 308afa88623SPeter Wemm u_long rf; 309004bedebSBruce Evans 310afa88623SPeter Wemm __asm __volatile("pushfq; popq %0" : "=r" (rf)); 311afa88623SPeter Wemm return (rf); 3125b81b6b3SRodney W. Grimes } 3135b81b6b3SRodney W. Grimes 314f5ac47f4SJung-uk Kim static __inline uint64_t 3155dbd168eSBruce Evans rdmsr(u_int msr) 3165dbd168eSBruce Evans { 317f5ac47f4SJung-uk Kim uint32_t low, high; 3185dbd168eSBruce Evans 319afa88623SPeter Wemm __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); 320f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3215dbd168eSBruce Evans } 3225dbd168eSBruce Evans 323f5ac47f4SJung-uk Kim static __inline uint64_t 3245dbd168eSBruce Evans rdpmc(u_int pmc) 3255dbd168eSBruce Evans { 326f5ac47f4SJung-uk Kim uint32_t low, high; 3275dbd168eSBruce Evans 328afa88623SPeter Wemm __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc)); 329f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3305dbd168eSBruce Evans } 3315dbd168eSBruce Evans 332f5ac47f4SJung-uk Kim static __inline uint64_t 3335dbd168eSBruce Evans rdtsc(void) 3345dbd168eSBruce Evans { 335f5ac47f4SJung-uk Kim uint32_t low, high; 3365dbd168eSBruce Evans 337afa88623SPeter Wemm __asm __volatile("rdtsc" : "=a" (low), "=d" (high)); 338f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3395dbd168eSBruce Evans } 3405dbd168eSBruce Evans 3410e727642SJung-uk Kim static __inline uint32_t 3420e727642SJung-uk Kim rdtsc32(void) 3430e727642SJung-uk Kim { 3440e727642SJung-uk Kim uint32_t rv; 3450e727642SJung-uk Kim 3460e727642SJung-uk Kim __asm __volatile("rdtsc" : "=a" (rv) : : "edx"); 3470e727642SJung-uk Kim return (rv); 3480e727642SJung-uk Kim } 3490e727642SJung-uk Kim 350004bedebSBruce Evans static __inline void 3514c024bbdSKATO Takenori wbinvd(void) 3524c024bbdSKATO Takenori { 3534c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3544c024bbdSKATO Takenori } 3554c024bbdSKATO Takenori 3564c024bbdSKATO Takenori static __inline void 357afa88623SPeter Wemm write_rflags(u_long rf) 3585b81b6b3SRodney W. Grimes { 359afa88623SPeter Wemm __asm __volatile("pushq %0; popfq" : : "r" (rf)); 3605b81b6b3SRodney W. Grimes } 3615b81b6b3SRodney W. Grimes 362d69e8502SGarrett Wollman static __inline void 363f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval) 364d69e8502SGarrett Wollman { 365f5ac47f4SJung-uk Kim uint32_t low, high; 366afa88623SPeter Wemm 367afa88623SPeter Wemm low = newval; 368afa88623SPeter Wemm high = newval >> 32; 369afa88623SPeter Wemm __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 370d69e8502SGarrett Wollman } 371d69e8502SGarrett Wollman 372f1b665c8SPeter Wemm static __inline void 373afa88623SPeter Wemm load_cr0(u_long data) 374f1b665c8SPeter Wemm { 375f1b665c8SPeter Wemm 376afa88623SPeter Wemm __asm __volatile("movq %0,%%cr0" : : "r" (data)); 377f1b665c8SPeter Wemm } 378f1b665c8SPeter Wemm 379afa88623SPeter Wemm static __inline u_long 380f1b665c8SPeter Wemm rcr0(void) 381f1b665c8SPeter Wemm { 382afa88623SPeter Wemm u_long data; 383f1b665c8SPeter Wemm 384afa88623SPeter Wemm __asm __volatile("movq %%cr0,%0" : "=r" (data)); 385f1b665c8SPeter Wemm return (data); 386f1b665c8SPeter Wemm } 387f1b665c8SPeter Wemm 388afa88623SPeter Wemm static __inline u_long 389f1b665c8SPeter Wemm rcr2(void) 390f1b665c8SPeter Wemm { 391afa88623SPeter Wemm u_long data; 392f1b665c8SPeter Wemm 393afa88623SPeter Wemm __asm __volatile("movq %%cr2,%0" : "=r" (data)); 394f1b665c8SPeter Wemm return (data); 395f1b665c8SPeter Wemm } 396f1b665c8SPeter Wemm 397f1b665c8SPeter Wemm static __inline void 398afa88623SPeter Wemm load_cr3(u_long data) 399f1b665c8SPeter Wemm { 400f1b665c8SPeter Wemm 401afa88623SPeter Wemm __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory"); 402f1b665c8SPeter Wemm } 403f1b665c8SPeter Wemm 404afa88623SPeter Wemm static __inline u_long 405f1b665c8SPeter Wemm rcr3(void) 406f1b665c8SPeter Wemm { 407afa88623SPeter Wemm u_long data; 408f1b665c8SPeter Wemm 409afa88623SPeter Wemm __asm __volatile("movq %%cr3,%0" : "=r" (data)); 410f1b665c8SPeter Wemm return (data); 411f1b665c8SPeter Wemm } 412f1b665c8SPeter Wemm 413f1b665c8SPeter Wemm static __inline void 414afa88623SPeter Wemm load_cr4(u_long data) 415f1b665c8SPeter Wemm { 416afa88623SPeter Wemm __asm __volatile("movq %0,%%cr4" : : "r" (data)); 417f1b665c8SPeter Wemm } 418f1b665c8SPeter Wemm 419afa88623SPeter Wemm static __inline u_long 420f1b665c8SPeter Wemm rcr4(void) 421f1b665c8SPeter Wemm { 422afa88623SPeter Wemm u_long data; 423f1b665c8SPeter Wemm 424afa88623SPeter Wemm __asm __volatile("movq %%cr4,%0" : "=r" (data)); 425f1b665c8SPeter Wemm return (data); 426f1b665c8SPeter Wemm } 427f1b665c8SPeter Wemm 4287574a595SJohn Baldwin static __inline u_long 4297574a595SJohn Baldwin rxcr(u_int reg) 4307574a595SJohn Baldwin { 4317574a595SJohn Baldwin u_int low, high; 4327574a595SJohn Baldwin 4337574a595SJohn Baldwin __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 4347574a595SJohn Baldwin return (low | ((uint64_t)high << 32)); 4357574a595SJohn Baldwin } 4367574a595SJohn Baldwin 4377574a595SJohn Baldwin static __inline void 4387574a595SJohn Baldwin load_xcr(u_int reg, u_long val) 4397574a595SJohn Baldwin { 4407574a595SJohn Baldwin u_int low, high; 4417574a595SJohn Baldwin 4427574a595SJohn Baldwin low = val; 4437574a595SJohn Baldwin high = val >> 32; 4447574a595SJohn Baldwin __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 4457574a595SJohn Baldwin } 4467574a595SJohn Baldwin 447f1b665c8SPeter Wemm /* 448f1b665c8SPeter Wemm * Global TLB flush (except for thise for pages marked PG_G) 449f1b665c8SPeter Wemm */ 450f1b665c8SPeter Wemm static __inline void 451f1b665c8SPeter Wemm invltlb(void) 452f1b665c8SPeter Wemm { 453f1b665c8SPeter Wemm 454f1b665c8SPeter Wemm load_cr3(rcr3()); 455f1b665c8SPeter Wemm } 456f1b665c8SPeter Wemm 457f1b665c8SPeter Wemm /* 458f1b665c8SPeter Wemm * TLB flush for an individual page (even if it has PG_G). 459f1b665c8SPeter Wemm * Only works on 486+ CPUs (i386 does not have PG_G). 460f1b665c8SPeter Wemm */ 461f1b665c8SPeter Wemm static __inline void 462afa88623SPeter Wemm invlpg(u_long addr) 463f1b665c8SPeter Wemm { 464f1b665c8SPeter Wemm 465f1b665c8SPeter Wemm __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 466f1b665c8SPeter Wemm } 467f1b665c8SPeter Wemm 46827d4fea6SRoman Divacky static __inline u_short 4695206bca1SLuoqi Chen rfs(void) 4705206bca1SLuoqi Chen { 47127d4fea6SRoman Divacky u_short sel; 47227d4fea6SRoman Divacky __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 4735206bca1SLuoqi Chen return (sel); 4745206bca1SLuoqi Chen } 4755206bca1SLuoqi Chen 47627d4fea6SRoman Divacky static __inline u_short 4775206bca1SLuoqi Chen rgs(void) 4785206bca1SLuoqi Chen { 47927d4fea6SRoman Divacky u_short sel; 48027d4fea6SRoman Divacky __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 4815206bca1SLuoqi Chen return (sel); 4825206bca1SLuoqi Chen } 4835206bca1SLuoqi Chen 48427d4fea6SRoman Divacky static __inline u_short 485cd0149e3SPeter Wemm rss(void) 486cd0149e3SPeter Wemm { 48727d4fea6SRoman Divacky u_short sel; 48827d4fea6SRoman Divacky __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 489cd0149e3SPeter Wemm return (sel); 490cd0149e3SPeter Wemm } 491cd0149e3SPeter Wemm 4925206bca1SLuoqi Chen static __inline void 49327d4fea6SRoman Divacky load_ds(u_short sel) 494d85631c4SPeter Wemm { 49527d4fea6SRoman Divacky __asm __volatile("movw %0,%%ds" : : "rm" (sel)); 496d85631c4SPeter Wemm } 497d85631c4SPeter Wemm 498d85631c4SPeter Wemm static __inline void 49927d4fea6SRoman Divacky load_es(u_short sel) 500d85631c4SPeter Wemm { 50127d4fea6SRoman Divacky __asm __volatile("movw %0,%%es" : : "rm" (sel)); 502d85631c4SPeter Wemm } 503d85631c4SPeter Wemm 504beb2c1f3SAndriy Gapon static __inline void 505f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints) 50666247efaSJeff Roberson { 507f0b28f00SJung-uk Kim 508f0b28f00SJung-uk Kim __asm __volatile("monitor" 50966247efaSJeff Roberson : : "a" (addr), "c" (extensions), "d" (hints)); 51066247efaSJeff Roberson } 51166247efaSJeff Roberson 512beb2c1f3SAndriy Gapon static __inline void 513f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints) 51466247efaSJeff Roberson { 515f0b28f00SJung-uk Kim 516f0b28f00SJung-uk Kim __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); 51766247efaSJeff Roberson } 51866247efaSJeff Roberson 519c0a54ff6SPeter Wemm #ifdef _KERNEL 520c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */ 521c0a54ff6SPeter Wemm #ifndef MSR_FSBASE 522c0a54ff6SPeter Wemm #define MSR_FSBASE 0xc0000100 523c0a54ff6SPeter Wemm #endif 524c0a54ff6SPeter Wemm static __inline void 52527d4fea6SRoman Divacky load_fs(u_short sel) 526c0a54ff6SPeter Wemm { 527c0a54ff6SPeter Wemm /* Preserve the fsbase value across the selector load */ 52827d4fea6SRoman Divacky __asm __volatile("rdmsr; movw %0,%%fs; wrmsr" 529db26a671SEd Schouten : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx"); 530c0a54ff6SPeter Wemm } 531c0a54ff6SPeter Wemm 532c0a54ff6SPeter Wemm #ifndef MSR_GSBASE 533c0a54ff6SPeter Wemm #define MSR_GSBASE 0xc0000101 534c0a54ff6SPeter Wemm #endif 535c0a54ff6SPeter Wemm static __inline void 53627d4fea6SRoman Divacky load_gs(u_short sel) 537c0a54ff6SPeter Wemm { 538c0a54ff6SPeter Wemm /* 539c0a54ff6SPeter Wemm * Preserve the gsbase value across the selector load. 540c0a54ff6SPeter Wemm * Note that we have to disable interrupts because the gsbase 541c0a54ff6SPeter Wemm * being trashed happens to be the kernel gsbase at the time. 542c0a54ff6SPeter Wemm */ 54327d4fea6SRoman Divacky __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq" 544db26a671SEd Schouten : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx"); 545c0a54ff6SPeter Wemm } 546c0a54ff6SPeter Wemm #else 547c0a54ff6SPeter Wemm /* Usable by userland */ 548d85631c4SPeter Wemm static __inline void 54927d4fea6SRoman Divacky load_fs(u_short sel) 5505206bca1SLuoqi Chen { 55127d4fea6SRoman Divacky __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 5525206bca1SLuoqi Chen } 5535206bca1SLuoqi Chen 5545206bca1SLuoqi Chen static __inline void 55527d4fea6SRoman Divacky load_gs(u_short sel) 5565206bca1SLuoqi Chen { 55727d4fea6SRoman Divacky __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 5585206bca1SLuoqi Chen } 559c0a54ff6SPeter Wemm #endif 5605206bca1SLuoqi Chen 561eb1443c8SPeter Wemm static __inline void 562eb1443c8SPeter Wemm lidt(struct region_descriptor *addr) 563eb1443c8SPeter Wemm { 564eb1443c8SPeter Wemm __asm __volatile("lidt (%0)" : : "r" (addr)); 565eb1443c8SPeter Wemm } 566eb1443c8SPeter Wemm 567eb1443c8SPeter Wemm static __inline void 568eb1443c8SPeter Wemm lldt(u_short sel) 569eb1443c8SPeter Wemm { 570eb1443c8SPeter Wemm __asm __volatile("lldt %0" : : "r" (sel)); 571eb1443c8SPeter Wemm } 572eb1443c8SPeter Wemm 573eb1443c8SPeter Wemm static __inline void 574eb1443c8SPeter Wemm ltr(u_short sel) 575eb1443c8SPeter Wemm { 576eb1443c8SPeter Wemm __asm __volatile("ltr %0" : : "r" (sel)); 577eb1443c8SPeter Wemm } 578eb1443c8SPeter Wemm 579f5ac47f4SJung-uk Kim static __inline uint64_t 5801182b177SPeter Wemm rdr0(void) 5811182b177SPeter Wemm { 582f5ac47f4SJung-uk Kim uint64_t data; 5831182b177SPeter Wemm __asm __volatile("movq %%dr0,%0" : "=r" (data)); 5841182b177SPeter Wemm return (data); 5851182b177SPeter Wemm } 5861182b177SPeter Wemm 5871182b177SPeter Wemm static __inline void 588f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0) 5891182b177SPeter Wemm { 5901182b177SPeter Wemm __asm __volatile("movq %0,%%dr0" : : "r" (dr0)); 5911182b177SPeter Wemm } 5921182b177SPeter Wemm 593f5ac47f4SJung-uk Kim static __inline uint64_t 5941182b177SPeter Wemm rdr1(void) 5951182b177SPeter Wemm { 596f5ac47f4SJung-uk Kim uint64_t data; 5971182b177SPeter Wemm __asm __volatile("movq %%dr1,%0" : "=r" (data)); 5981182b177SPeter Wemm return (data); 5991182b177SPeter Wemm } 6001182b177SPeter Wemm 6011182b177SPeter Wemm static __inline void 602f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1) 6031182b177SPeter Wemm { 6041182b177SPeter Wemm __asm __volatile("movq %0,%%dr1" : : "r" (dr1)); 6051182b177SPeter Wemm } 6061182b177SPeter Wemm 607f5ac47f4SJung-uk Kim static __inline uint64_t 6081182b177SPeter Wemm rdr2(void) 6091182b177SPeter Wemm { 610f5ac47f4SJung-uk Kim uint64_t data; 6111182b177SPeter Wemm __asm __volatile("movq %%dr2,%0" : "=r" (data)); 6121182b177SPeter Wemm return (data); 6131182b177SPeter Wemm } 6141182b177SPeter Wemm 6151182b177SPeter Wemm static __inline void 616f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2) 6171182b177SPeter Wemm { 6181182b177SPeter Wemm __asm __volatile("movq %0,%%dr2" : : "r" (dr2)); 6191182b177SPeter Wemm } 6201182b177SPeter Wemm 621f5ac47f4SJung-uk Kim static __inline uint64_t 6221182b177SPeter Wemm rdr3(void) 6231182b177SPeter Wemm { 624f5ac47f4SJung-uk Kim uint64_t data; 6251182b177SPeter Wemm __asm __volatile("movq %%dr3,%0" : "=r" (data)); 6261182b177SPeter Wemm return (data); 6271182b177SPeter Wemm } 6281182b177SPeter Wemm 6291182b177SPeter Wemm static __inline void 630f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3) 6311182b177SPeter Wemm { 6321182b177SPeter Wemm __asm __volatile("movq %0,%%dr3" : : "r" (dr3)); 6331182b177SPeter Wemm } 6341182b177SPeter Wemm 635f5ac47f4SJung-uk Kim static __inline uint64_t 6361182b177SPeter Wemm rdr4(void) 6371182b177SPeter Wemm { 638f5ac47f4SJung-uk Kim uint64_t data; 6391182b177SPeter Wemm __asm __volatile("movq %%dr4,%0" : "=r" (data)); 6401182b177SPeter Wemm return (data); 6411182b177SPeter Wemm } 6421182b177SPeter Wemm 6431182b177SPeter Wemm static __inline void 644f5ac47f4SJung-uk Kim load_dr4(uint64_t dr4) 6451182b177SPeter Wemm { 6461182b177SPeter Wemm __asm __volatile("movq %0,%%dr4" : : "r" (dr4)); 6471182b177SPeter Wemm } 6481182b177SPeter Wemm 649f5ac47f4SJung-uk Kim static __inline uint64_t 6501182b177SPeter Wemm rdr5(void) 6511182b177SPeter Wemm { 652f5ac47f4SJung-uk Kim uint64_t data; 6531182b177SPeter Wemm __asm __volatile("movq %%dr5,%0" : "=r" (data)); 6541182b177SPeter Wemm return (data); 6551182b177SPeter Wemm } 6561182b177SPeter Wemm 6571182b177SPeter Wemm static __inline void 658f5ac47f4SJung-uk Kim load_dr5(uint64_t dr5) 6591182b177SPeter Wemm { 6601182b177SPeter Wemm __asm __volatile("movq %0,%%dr5" : : "r" (dr5)); 6611182b177SPeter Wemm } 6621182b177SPeter Wemm 663f5ac47f4SJung-uk Kim static __inline uint64_t 6641182b177SPeter Wemm rdr6(void) 6651182b177SPeter Wemm { 666f5ac47f4SJung-uk Kim uint64_t data; 6671182b177SPeter Wemm __asm __volatile("movq %%dr6,%0" : "=r" (data)); 6681182b177SPeter Wemm return (data); 6691182b177SPeter Wemm } 6701182b177SPeter Wemm 6711182b177SPeter Wemm static __inline void 672f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6) 6731182b177SPeter Wemm { 6741182b177SPeter Wemm __asm __volatile("movq %0,%%dr6" : : "r" (dr6)); 6751182b177SPeter Wemm } 6761182b177SPeter Wemm 677f5ac47f4SJung-uk Kim static __inline uint64_t 6781182b177SPeter Wemm rdr7(void) 6791182b177SPeter Wemm { 680f5ac47f4SJung-uk Kim uint64_t data; 6811182b177SPeter Wemm __asm __volatile("movq %%dr7,%0" : "=r" (data)); 6821182b177SPeter Wemm return (data); 6831182b177SPeter Wemm } 6841182b177SPeter Wemm 6851182b177SPeter Wemm static __inline void 686f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7) 6871182b177SPeter Wemm { 6881182b177SPeter Wemm __asm __volatile("movq %0,%%dr7" : : "r" (dr7)); 6891182b177SPeter Wemm } 6901182b177SPeter Wemm 691ba74981eSWarner Losh static __inline register_t 692ba74981eSWarner Losh intr_disable(void) 693ba74981eSWarner Losh { 694afa88623SPeter Wemm register_t rflags; 695ba74981eSWarner Losh 696afa88623SPeter Wemm rflags = read_rflags(); 697ba74981eSWarner Losh disable_intr(); 698afa88623SPeter Wemm return (rflags); 699ba74981eSWarner Losh } 700ba74981eSWarner Losh 701ba74981eSWarner Losh static __inline void 702afa88623SPeter Wemm intr_restore(register_t rflags) 703ba74981eSWarner Losh { 704afa88623SPeter Wemm write_rflags(rflags); 705ba74981eSWarner Losh } 706ba74981eSWarner Losh 707a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 7085b81b6b3SRodney W. Grimes 709b63dc6adSAlfred Perlstein int breakpoint(void); 710b63dc6adSAlfred Perlstein u_int bsfl(u_int mask); 711b63dc6adSAlfred Perlstein u_int bsrl(u_int mask); 712*d706ec29SJohn Baldwin void clflush(u_long addr); 713*d706ec29SJohn Baldwin void clts(void); 714*d706ec29SJohn Baldwin void cpuid_count(u_int ax, u_int cx, u_int *p); 715b63dc6adSAlfred Perlstein void disable_intr(void); 716b63dc6adSAlfred Perlstein void do_cpuid(u_int ax, u_int *p); 717b63dc6adSAlfred Perlstein void enable_intr(void); 718d7ee4425SMark Murray void halt(void); 7194f6c19e5SPeter Wemm void ia32_pause(void); 720b63dc6adSAlfred Perlstein u_char inb(u_int port); 721b63dc6adSAlfred Perlstein u_int inl(u_int port); 72293d8be03SDavid E. O'Brien void insb(u_int port, void *addr, size_t count); 72393d8be03SDavid E. O'Brien void insl(u_int port, void *addr, size_t count); 72493d8be03SDavid E. O'Brien void insw(u_int port, void *addr, size_t count); 7254f6c19e5SPeter Wemm register_t intr_disable(void); 7264f6c19e5SPeter Wemm void intr_restore(register_t rf); 727b63dc6adSAlfred Perlstein void invd(void); 728b63dc6adSAlfred Perlstein void invlpg(u_int addr); 729b63dc6adSAlfred Perlstein void invltlb(void); 730b63dc6adSAlfred Perlstein u_short inw(u_int port); 731eb1443c8SPeter Wemm void lidt(struct region_descriptor *addr); 732eb1443c8SPeter Wemm void lldt(u_short sel); 7334f6c19e5SPeter Wemm void load_cr0(u_long cr0); 7344f6c19e5SPeter Wemm void load_cr3(u_long cr3); 7354f6c19e5SPeter Wemm void load_cr4(u_long cr4); 736f5ac47f4SJung-uk Kim void load_dr0(uint64_t dr0); 737f5ac47f4SJung-uk Kim void load_dr1(uint64_t dr1); 738f5ac47f4SJung-uk Kim void load_dr2(uint64_t dr2); 739f5ac47f4SJung-uk Kim void load_dr3(uint64_t dr3); 740f5ac47f4SJung-uk Kim void load_dr4(uint64_t dr4); 741f5ac47f4SJung-uk Kim void load_dr5(uint64_t dr5); 742f5ac47f4SJung-uk Kim void load_dr6(uint64_t dr6); 743f5ac47f4SJung-uk Kim void load_dr7(uint64_t dr7); 74427d4fea6SRoman Divacky void load_fs(u_short sel); 74527d4fea6SRoman Divacky void load_gs(u_short sel); 746eb1443c8SPeter Wemm void ltr(u_short sel); 747b63dc6adSAlfred Perlstein void outb(u_int port, u_char data); 748b63dc6adSAlfred Perlstein void outl(u_int port, u_int data); 74993d8be03SDavid E. O'Brien void outsb(u_int port, const void *addr, size_t count); 75093d8be03SDavid E. O'Brien void outsl(u_int port, const void *addr, size_t count); 75193d8be03SDavid E. O'Brien void outsw(u_int port, const void *addr, size_t count); 752b63dc6adSAlfred Perlstein void outw(u_int port, u_short data); 7534f6c19e5SPeter Wemm u_long rcr0(void); 7544f6c19e5SPeter Wemm u_long rcr2(void); 7554f6c19e5SPeter Wemm u_long rcr3(void); 7564f6c19e5SPeter Wemm u_long rcr4(void); 757f5ac47f4SJung-uk Kim uint64_t rdmsr(u_int msr); 758f5ac47f4SJung-uk Kim uint64_t rdpmc(u_int pmc); 759f5ac47f4SJung-uk Kim uint64_t rdr0(void); 760f5ac47f4SJung-uk Kim uint64_t rdr1(void); 761f5ac47f4SJung-uk Kim uint64_t rdr2(void); 762f5ac47f4SJung-uk Kim uint64_t rdr3(void); 763f5ac47f4SJung-uk Kim uint64_t rdr4(void); 764f5ac47f4SJung-uk Kim uint64_t rdr5(void); 765f5ac47f4SJung-uk Kim uint64_t rdr6(void); 766f5ac47f4SJung-uk Kim uint64_t rdr7(void); 767f5ac47f4SJung-uk Kim uint64_t rdtsc(void); 768a61dd1bdSJohn Baldwin u_long read_rflags(void); 7694f6c19e5SPeter Wemm u_int rfs(void); 7704f6c19e5SPeter Wemm u_int rgs(void); 771b63dc6adSAlfred Perlstein void wbinvd(void); 772afa88623SPeter Wemm void write_rflags(u_int rf); 773f5ac47f4SJung-uk Kim void wrmsr(u_int msr, uint64_t newval); 774004bedebSBruce Evans 775a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 7765b81b6b3SRodney W. Grimes 777b63dc6adSAlfred Perlstein void reset_dbregs(void); 778d74ac681SMatthew Dillon 779e085f869SStanislav Sedov #ifdef _KERNEL 780e085f869SStanislav Sedov int rdmsr_safe(u_int msr, uint64_t *val); 781e085f869SStanislav Sedov int wrmsr_safe(u_int msr, uint64_t newval); 782e085f869SStanislav Sedov #endif 783e085f869SStanislav Sedov 784004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 785