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 48*f5ac47f4SJung-uk Kim #define readb(va) (*(volatile uint8_t *) (va)) 49*f5ac47f4SJung-uk Kim #define readw(va) (*(volatile uint16_t *) (va)) 50*f5ac47f4SJung-uk Kim #define readl(va) (*(volatile uint32_t *) (va)) 51*f5ac47f4SJung-uk Kim #define readq(va) (*(volatile uint64_t *) (va)) 52e31fa854SDoug Rabson 53*f5ac47f4SJung-uk Kim #define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) 54*f5ac47f4SJung-uk Kim #define writew(va, d) (*(volatile uint16_t *) (va) = (d)) 55*f5ac47f4SJung-uk Kim #define writel(va, d) (*(volatile uint32_t *) (va) = (d)) 56*f5ac47f4SJung-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 1105b81b6b3SRodney W. Grimes disable_intr(void) 1115b81b6b3SRodney W. Grimes { 1128966b85cSJohn Dyson __asm __volatile("cli" : : : "memory"); 1135b81b6b3SRodney W. Grimes } 1145b81b6b3SRodney W. Grimes 115004bedebSBruce Evans static __inline void 116a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p) 117a983fdfeSDavid Malone { 118a983fdfeSDavid Malone __asm __volatile("cpuid" 119a983fdfeSDavid Malone : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 120a983fdfeSDavid Malone : "0" (ax)); 121a983fdfeSDavid Malone } 122a983fdfeSDavid Malone 123a983fdfeSDavid Malone static __inline void 124f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p) 125f6108b61SJacques Vidrine { 126f6108b61SJacques Vidrine __asm __volatile("cpuid" 127f6108b61SJacques Vidrine : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 128f6108b61SJacques Vidrine : "0" (ax), "c" (cx)); 129f6108b61SJacques Vidrine } 130f6108b61SJacques Vidrine 131f6108b61SJacques Vidrine static __inline void 1325b81b6b3SRodney W. Grimes enable_intr(void) 1335b81b6b3SRodney W. Grimes { 134fadc51bdSBruce Evans __asm __volatile("sti"); 1355b81b6b3SRodney W. Grimes } 1365b81b6b3SRodney W. Grimes 137a67ef0a7SBruce Evans #ifdef _KERNEL 138a67ef0a7SBruce Evans 139264c3d87SPeter Wemm #define HAVE_INLINE_FFS 140bc35f5dcSPaul Saab #define ffs(x) __builtin_ffs(x) 141176ce2b1SPeter Wemm 142176ce2b1SPeter Wemm #define HAVE_INLINE_FFSL 143176ce2b1SPeter Wemm 144176ce2b1SPeter Wemm static __inline int 145176ce2b1SPeter Wemm ffsl(long mask) 146176ce2b1SPeter Wemm { 147176ce2b1SPeter Wemm return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1); 148004bedebSBruce Evans } 149004bedebSBruce Evans 15013f588f8SGarrett Wollman #define HAVE_INLINE_FLS 15113f588f8SGarrett Wollman 15213f588f8SGarrett Wollman static __inline int 15313f588f8SGarrett Wollman fls(int mask) 15413f588f8SGarrett Wollman { 1557e622d3cSMark Murray return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 15613f588f8SGarrett Wollman } 15713f588f8SGarrett Wollman 158176ce2b1SPeter Wemm #define HAVE_INLINE_FLSL 159176ce2b1SPeter Wemm 160176ce2b1SPeter Wemm static __inline int 161176ce2b1SPeter Wemm flsl(long mask) 162176ce2b1SPeter Wemm { 163176ce2b1SPeter Wemm return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1); 164176ce2b1SPeter Wemm } 165176ce2b1SPeter Wemm 166a67ef0a7SBruce Evans #endif /* _KERNEL */ 167a67ef0a7SBruce Evans 168d7ee4425SMark Murray static __inline void 169d7ee4425SMark Murray halt(void) 170d7ee4425SMark Murray { 171d7ee4425SMark Murray __asm __volatile("hlt"); 172d7ee4425SMark Murray } 173d7ee4425SMark Murray 174004bedebSBruce Evans static __inline u_char 175e1048f76SEd Schouten inb(u_int port) 176004bedebSBruce Evans { 177004bedebSBruce Evans u_char data; 178004bedebSBruce Evans 179e1048f76SEd Schouten __asm volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); 180004bedebSBruce Evans return (data); 181004bedebSBruce Evans } 182004bedebSBruce Evans 18300be8601SBruce Evans static __inline u_int 184004bedebSBruce Evans inl(u_int port) 185004bedebSBruce Evans { 18600be8601SBruce Evans u_int data; 187004bedebSBruce Evans 188e1048f76SEd Schouten __asm volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); 189004bedebSBruce Evans return (data); 190004bedebSBruce Evans } 191004bedebSBruce Evans 192004bedebSBruce Evans static __inline void 19393d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count) 194004bedebSBruce Evans { 195004bedebSBruce Evans __asm __volatile("cld; rep; insb" 19693d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 1973f9a462fSJohn Baldwin : "d" (port) 198896763faSBruce Evans : "memory"); 199004bedebSBruce Evans } 200004bedebSBruce Evans 201004bedebSBruce Evans static __inline void 20293d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count) 203004bedebSBruce Evans { 204004bedebSBruce Evans __asm __volatile("cld; rep; insw" 20593d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2063f9a462fSJohn Baldwin : "d" (port) 207896763faSBruce Evans : "memory"); 208004bedebSBruce Evans } 209004bedebSBruce Evans 210004bedebSBruce Evans static __inline void 21193d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count) 212004bedebSBruce Evans { 213004bedebSBruce Evans __asm __volatile("cld; rep; insl" 21493d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2153f9a462fSJohn Baldwin : "d" (port) 216896763faSBruce Evans : "memory"); 217004bedebSBruce Evans } 218004bedebSBruce Evans 219ece15d78SBruce Evans static __inline void 2204c024bbdSKATO Takenori invd(void) 2214c024bbdSKATO Takenori { 2224c024bbdSKATO Takenori __asm __volatile("invd"); 2234c024bbdSKATO Takenori } 2244c024bbdSKATO Takenori 225004bedebSBruce Evans static __inline u_short 226004bedebSBruce Evans inw(u_int port) 227004bedebSBruce Evans { 228004bedebSBruce Evans u_short data; 229004bedebSBruce Evans 230e1048f76SEd Schouten __asm volatile("inw %w1, %0" : "=a" (data) : "Nd" (port)); 231004bedebSBruce Evans return (data); 232004bedebSBruce Evans } 233004bedebSBruce Evans 234004bedebSBruce Evans static __inline void 235e1048f76SEd Schouten outb(u_int port, u_char data) 236004bedebSBruce Evans { 237e1048f76SEd Schouten __asm volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); 238004bedebSBruce Evans } 239004bedebSBruce Evans 240004bedebSBruce Evans static __inline void 24100be8601SBruce Evans outl(u_int port, u_int data) 242004bedebSBruce Evans { 243e1048f76SEd Schouten __asm volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); 244004bedebSBruce Evans } 245004bedebSBruce Evans 246004bedebSBruce Evans static __inline void 24793d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count) 248004bedebSBruce Evans { 249004bedebSBruce Evans __asm __volatile("cld; rep; outsb" 25093d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2513f9a462fSJohn Baldwin : "d" (port)); 252004bedebSBruce Evans } 253004bedebSBruce Evans 254004bedebSBruce Evans static __inline void 25593d8be03SDavid E. O'Brien outsw(u_int port, const void *addr, size_t count) 256004bedebSBruce Evans { 257004bedebSBruce Evans __asm __volatile("cld; rep; outsw" 25893d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2593f9a462fSJohn Baldwin : "d" (port)); 260004bedebSBruce Evans } 261004bedebSBruce Evans 262004bedebSBruce Evans static __inline void 26393d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count) 264004bedebSBruce Evans { 265004bedebSBruce Evans __asm __volatile("cld; rep; outsl" 26693d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2673f9a462fSJohn Baldwin : "d" (port)); 268004bedebSBruce Evans } 269004bedebSBruce Evans 270004bedebSBruce Evans static __inline void 271004bedebSBruce Evans outw(u_int port, u_short data) 272004bedebSBruce Evans { 273e1048f76SEd Schouten __asm volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); 274004bedebSBruce Evans } 275004bedebSBruce Evans 2762be69f32SJohn Baldwin static __inline void 277206a3368SKonstantin Belousov mfence(void) 278206a3368SKonstantin Belousov { 279206a3368SKonstantin Belousov 280beb2c1f3SAndriy Gapon __asm __volatile("mfence" : : : "memory"); 281206a3368SKonstantin Belousov } 282206a3368SKonstantin Belousov 283206a3368SKonstantin Belousov static __inline void 2846b8c6989SJohn Baldwin ia32_pause(void) 2852be69f32SJohn Baldwin { 2862be69f32SJohn Baldwin __asm __volatile("pause"); 2872be69f32SJohn Baldwin } 2882be69f32SJohn Baldwin 289afa88623SPeter Wemm static __inline u_long 290afa88623SPeter Wemm read_rflags(void) 2915b81b6b3SRodney W. Grimes { 292afa88623SPeter Wemm u_long rf; 293004bedebSBruce Evans 294afa88623SPeter Wemm __asm __volatile("pushfq; popq %0" : "=r" (rf)); 295afa88623SPeter Wemm return (rf); 2965b81b6b3SRodney W. Grimes } 2975b81b6b3SRodney W. Grimes 298*f5ac47f4SJung-uk Kim static __inline uint64_t 2995dbd168eSBruce Evans rdmsr(u_int msr) 3005dbd168eSBruce Evans { 301*f5ac47f4SJung-uk Kim uint32_t low, high; 3025dbd168eSBruce Evans 303afa88623SPeter Wemm __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); 304*f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3055dbd168eSBruce Evans } 3065dbd168eSBruce Evans 307*f5ac47f4SJung-uk Kim static __inline uint64_t 3085dbd168eSBruce Evans rdpmc(u_int pmc) 3095dbd168eSBruce Evans { 310*f5ac47f4SJung-uk Kim uint32_t low, high; 3115dbd168eSBruce Evans 312afa88623SPeter Wemm __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc)); 313*f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3145dbd168eSBruce Evans } 3155dbd168eSBruce Evans 316*f5ac47f4SJung-uk Kim static __inline uint64_t 3175dbd168eSBruce Evans rdtsc(void) 3185dbd168eSBruce Evans { 319*f5ac47f4SJung-uk Kim uint32_t low, high; 3205dbd168eSBruce Evans 321afa88623SPeter Wemm __asm __volatile("rdtsc" : "=a" (low), "=d" (high)); 322*f5ac47f4SJung-uk Kim return (low | ((uint64_t)high << 32)); 3235dbd168eSBruce Evans } 3245dbd168eSBruce Evans 325004bedebSBruce Evans static __inline void 3264c024bbdSKATO Takenori wbinvd(void) 3274c024bbdSKATO Takenori { 3284c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3294c024bbdSKATO Takenori } 3304c024bbdSKATO Takenori 3314c024bbdSKATO Takenori static __inline void 332afa88623SPeter Wemm write_rflags(u_long rf) 3335b81b6b3SRodney W. Grimes { 334afa88623SPeter Wemm __asm __volatile("pushq %0; popfq" : : "r" (rf)); 3355b81b6b3SRodney W. Grimes } 3365b81b6b3SRodney W. Grimes 337d69e8502SGarrett Wollman static __inline void 338*f5ac47f4SJung-uk Kim wrmsr(u_int msr, uint64_t newval) 339d69e8502SGarrett Wollman { 340*f5ac47f4SJung-uk Kim uint32_t low, high; 341afa88623SPeter Wemm 342afa88623SPeter Wemm low = newval; 343afa88623SPeter Wemm high = newval >> 32; 344afa88623SPeter Wemm __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 345d69e8502SGarrett Wollman } 346d69e8502SGarrett Wollman 347f1b665c8SPeter Wemm static __inline void 348afa88623SPeter Wemm load_cr0(u_long data) 349f1b665c8SPeter Wemm { 350f1b665c8SPeter Wemm 351afa88623SPeter Wemm __asm __volatile("movq %0,%%cr0" : : "r" (data)); 352f1b665c8SPeter Wemm } 353f1b665c8SPeter Wemm 354afa88623SPeter Wemm static __inline u_long 355f1b665c8SPeter Wemm rcr0(void) 356f1b665c8SPeter Wemm { 357afa88623SPeter Wemm u_long data; 358f1b665c8SPeter Wemm 359afa88623SPeter Wemm __asm __volatile("movq %%cr0,%0" : "=r" (data)); 360f1b665c8SPeter Wemm return (data); 361f1b665c8SPeter Wemm } 362f1b665c8SPeter Wemm 363afa88623SPeter Wemm static __inline u_long 364f1b665c8SPeter Wemm rcr2(void) 365f1b665c8SPeter Wemm { 366afa88623SPeter Wemm u_long data; 367f1b665c8SPeter Wemm 368afa88623SPeter Wemm __asm __volatile("movq %%cr2,%0" : "=r" (data)); 369f1b665c8SPeter Wemm return (data); 370f1b665c8SPeter Wemm } 371f1b665c8SPeter Wemm 372f1b665c8SPeter Wemm static __inline void 373afa88623SPeter Wemm load_cr3(u_long data) 374f1b665c8SPeter Wemm { 375f1b665c8SPeter Wemm 376afa88623SPeter Wemm __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory"); 377f1b665c8SPeter Wemm } 378f1b665c8SPeter Wemm 379afa88623SPeter Wemm static __inline u_long 380f1b665c8SPeter Wemm rcr3(void) 381f1b665c8SPeter Wemm { 382afa88623SPeter Wemm u_long data; 383f1b665c8SPeter Wemm 384afa88623SPeter Wemm __asm __volatile("movq %%cr3,%0" : "=r" (data)); 385f1b665c8SPeter Wemm return (data); 386f1b665c8SPeter Wemm } 387f1b665c8SPeter Wemm 388f1b665c8SPeter Wemm static __inline void 389afa88623SPeter Wemm load_cr4(u_long data) 390f1b665c8SPeter Wemm { 391afa88623SPeter Wemm __asm __volatile("movq %0,%%cr4" : : "r" (data)); 392f1b665c8SPeter Wemm } 393f1b665c8SPeter Wemm 394afa88623SPeter Wemm static __inline u_long 395f1b665c8SPeter Wemm rcr4(void) 396f1b665c8SPeter Wemm { 397afa88623SPeter Wemm u_long data; 398f1b665c8SPeter Wemm 399afa88623SPeter Wemm __asm __volatile("movq %%cr4,%0" : "=r" (data)); 400f1b665c8SPeter Wemm return (data); 401f1b665c8SPeter Wemm } 402f1b665c8SPeter Wemm 403f1b665c8SPeter Wemm /* 404f1b665c8SPeter Wemm * Global TLB flush (except for thise for pages marked PG_G) 405f1b665c8SPeter Wemm */ 406f1b665c8SPeter Wemm static __inline void 407f1b665c8SPeter Wemm invltlb(void) 408f1b665c8SPeter Wemm { 409f1b665c8SPeter Wemm 410f1b665c8SPeter Wemm load_cr3(rcr3()); 411f1b665c8SPeter Wemm } 412f1b665c8SPeter Wemm 413f1b665c8SPeter Wemm /* 414f1b665c8SPeter Wemm * TLB flush for an individual page (even if it has PG_G). 415f1b665c8SPeter Wemm * Only works on 486+ CPUs (i386 does not have PG_G). 416f1b665c8SPeter Wemm */ 417f1b665c8SPeter Wemm static __inline void 418afa88623SPeter Wemm invlpg(u_long addr) 419f1b665c8SPeter Wemm { 420f1b665c8SPeter Wemm 421f1b665c8SPeter Wemm __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 422f1b665c8SPeter Wemm } 423f1b665c8SPeter Wemm 42427d4fea6SRoman Divacky static __inline u_short 4255206bca1SLuoqi Chen rfs(void) 4265206bca1SLuoqi Chen { 42727d4fea6SRoman Divacky u_short sel; 42827d4fea6SRoman Divacky __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 4295206bca1SLuoqi Chen return (sel); 4305206bca1SLuoqi Chen } 4315206bca1SLuoqi Chen 43227d4fea6SRoman Divacky static __inline u_short 4335206bca1SLuoqi Chen rgs(void) 4345206bca1SLuoqi Chen { 43527d4fea6SRoman Divacky u_short sel; 43627d4fea6SRoman Divacky __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 4375206bca1SLuoqi Chen return (sel); 4385206bca1SLuoqi Chen } 4395206bca1SLuoqi Chen 44027d4fea6SRoman Divacky static __inline u_short 441cd0149e3SPeter Wemm rss(void) 442cd0149e3SPeter Wemm { 44327d4fea6SRoman Divacky u_short sel; 44427d4fea6SRoman Divacky __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 445cd0149e3SPeter Wemm return (sel); 446cd0149e3SPeter Wemm } 447cd0149e3SPeter Wemm 4485206bca1SLuoqi Chen static __inline void 44927d4fea6SRoman Divacky load_ds(u_short sel) 450d85631c4SPeter Wemm { 45127d4fea6SRoman Divacky __asm __volatile("movw %0,%%ds" : : "rm" (sel)); 452d85631c4SPeter Wemm } 453d85631c4SPeter Wemm 454d85631c4SPeter Wemm static __inline void 45527d4fea6SRoman Divacky load_es(u_short sel) 456d85631c4SPeter Wemm { 45727d4fea6SRoman Divacky __asm __volatile("movw %0,%%es" : : "rm" (sel)); 458d85631c4SPeter Wemm } 459d85631c4SPeter Wemm 460beb2c1f3SAndriy Gapon static __inline void 46166247efaSJeff Roberson cpu_monitor(const void *addr, int extensions, int hints) 46266247efaSJeff Roberson { 46366247efaSJeff Roberson __asm __volatile("monitor;" 46466247efaSJeff Roberson : :"a" (addr), "c" (extensions), "d"(hints)); 46566247efaSJeff Roberson } 46666247efaSJeff Roberson 467beb2c1f3SAndriy Gapon static __inline void 46866247efaSJeff Roberson cpu_mwait(int extensions, int hints) 46966247efaSJeff Roberson { 47066247efaSJeff Roberson __asm __volatile("mwait;" : :"a" (hints), "c" (extensions)); 47166247efaSJeff Roberson } 47266247efaSJeff Roberson 473c0a54ff6SPeter Wemm #ifdef _KERNEL 474c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */ 475c0a54ff6SPeter Wemm #ifndef MSR_FSBASE 476c0a54ff6SPeter Wemm #define MSR_FSBASE 0xc0000100 477c0a54ff6SPeter Wemm #endif 478c0a54ff6SPeter Wemm static __inline void 47927d4fea6SRoman Divacky load_fs(u_short sel) 480c0a54ff6SPeter Wemm { 481c0a54ff6SPeter Wemm /* Preserve the fsbase value across the selector load */ 48227d4fea6SRoman Divacky __asm __volatile("rdmsr; movw %0,%%fs; wrmsr" 483db26a671SEd Schouten : : "rm" (sel), "c" (MSR_FSBASE) : "eax", "edx"); 484c0a54ff6SPeter Wemm } 485c0a54ff6SPeter Wemm 486c0a54ff6SPeter Wemm #ifndef MSR_GSBASE 487c0a54ff6SPeter Wemm #define MSR_GSBASE 0xc0000101 488c0a54ff6SPeter Wemm #endif 489c0a54ff6SPeter Wemm static __inline void 49027d4fea6SRoman Divacky load_gs(u_short sel) 491c0a54ff6SPeter Wemm { 492c0a54ff6SPeter Wemm /* 493c0a54ff6SPeter Wemm * Preserve the gsbase value across the selector load. 494c0a54ff6SPeter Wemm * Note that we have to disable interrupts because the gsbase 495c0a54ff6SPeter Wemm * being trashed happens to be the kernel gsbase at the time. 496c0a54ff6SPeter Wemm */ 49727d4fea6SRoman Divacky __asm __volatile("pushfq; cli; rdmsr; movw %0,%%gs; wrmsr; popfq" 498db26a671SEd Schouten : : "rm" (sel), "c" (MSR_GSBASE) : "eax", "edx"); 499c0a54ff6SPeter Wemm } 500c0a54ff6SPeter Wemm #else 501c0a54ff6SPeter Wemm /* Usable by userland */ 502d85631c4SPeter Wemm static __inline void 50327d4fea6SRoman Divacky load_fs(u_short sel) 5045206bca1SLuoqi Chen { 50527d4fea6SRoman Divacky __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 5065206bca1SLuoqi Chen } 5075206bca1SLuoqi Chen 5085206bca1SLuoqi Chen static __inline void 50927d4fea6SRoman Divacky load_gs(u_short sel) 5105206bca1SLuoqi Chen { 51127d4fea6SRoman Divacky __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 5125206bca1SLuoqi Chen } 513c0a54ff6SPeter Wemm #endif 5145206bca1SLuoqi Chen 515eb1443c8SPeter Wemm static __inline void 516eb1443c8SPeter Wemm lidt(struct region_descriptor *addr) 517eb1443c8SPeter Wemm { 518eb1443c8SPeter Wemm __asm __volatile("lidt (%0)" : : "r" (addr)); 519eb1443c8SPeter Wemm } 520eb1443c8SPeter Wemm 521eb1443c8SPeter Wemm static __inline void 522eb1443c8SPeter Wemm lldt(u_short sel) 523eb1443c8SPeter Wemm { 524eb1443c8SPeter Wemm __asm __volatile("lldt %0" : : "r" (sel)); 525eb1443c8SPeter Wemm } 526eb1443c8SPeter Wemm 527eb1443c8SPeter Wemm static __inline void 528eb1443c8SPeter Wemm ltr(u_short sel) 529eb1443c8SPeter Wemm { 530eb1443c8SPeter Wemm __asm __volatile("ltr %0" : : "r" (sel)); 531eb1443c8SPeter Wemm } 532eb1443c8SPeter Wemm 533*f5ac47f4SJung-uk Kim static __inline uint64_t 5341182b177SPeter Wemm rdr0(void) 5351182b177SPeter Wemm { 536*f5ac47f4SJung-uk Kim uint64_t data; 5371182b177SPeter Wemm __asm __volatile("movq %%dr0,%0" : "=r" (data)); 5381182b177SPeter Wemm return (data); 5391182b177SPeter Wemm } 5401182b177SPeter Wemm 5411182b177SPeter Wemm static __inline void 542*f5ac47f4SJung-uk Kim load_dr0(uint64_t dr0) 5431182b177SPeter Wemm { 5441182b177SPeter Wemm __asm __volatile("movq %0,%%dr0" : : "r" (dr0)); 5451182b177SPeter Wemm } 5461182b177SPeter Wemm 547*f5ac47f4SJung-uk Kim static __inline uint64_t 5481182b177SPeter Wemm rdr1(void) 5491182b177SPeter Wemm { 550*f5ac47f4SJung-uk Kim uint64_t data; 5511182b177SPeter Wemm __asm __volatile("movq %%dr1,%0" : "=r" (data)); 5521182b177SPeter Wemm return (data); 5531182b177SPeter Wemm } 5541182b177SPeter Wemm 5551182b177SPeter Wemm static __inline void 556*f5ac47f4SJung-uk Kim load_dr1(uint64_t dr1) 5571182b177SPeter Wemm { 5581182b177SPeter Wemm __asm __volatile("movq %0,%%dr1" : : "r" (dr1)); 5591182b177SPeter Wemm } 5601182b177SPeter Wemm 561*f5ac47f4SJung-uk Kim static __inline uint64_t 5621182b177SPeter Wemm rdr2(void) 5631182b177SPeter Wemm { 564*f5ac47f4SJung-uk Kim uint64_t data; 5651182b177SPeter Wemm __asm __volatile("movq %%dr2,%0" : "=r" (data)); 5661182b177SPeter Wemm return (data); 5671182b177SPeter Wemm } 5681182b177SPeter Wemm 5691182b177SPeter Wemm static __inline void 570*f5ac47f4SJung-uk Kim load_dr2(uint64_t dr2) 5711182b177SPeter Wemm { 5721182b177SPeter Wemm __asm __volatile("movq %0,%%dr2" : : "r" (dr2)); 5731182b177SPeter Wemm } 5741182b177SPeter Wemm 575*f5ac47f4SJung-uk Kim static __inline uint64_t 5761182b177SPeter Wemm rdr3(void) 5771182b177SPeter Wemm { 578*f5ac47f4SJung-uk Kim uint64_t data; 5791182b177SPeter Wemm __asm __volatile("movq %%dr3,%0" : "=r" (data)); 5801182b177SPeter Wemm return (data); 5811182b177SPeter Wemm } 5821182b177SPeter Wemm 5831182b177SPeter Wemm static __inline void 584*f5ac47f4SJung-uk Kim load_dr3(uint64_t dr3) 5851182b177SPeter Wemm { 5861182b177SPeter Wemm __asm __volatile("movq %0,%%dr3" : : "r" (dr3)); 5871182b177SPeter Wemm } 5881182b177SPeter Wemm 589*f5ac47f4SJung-uk Kim static __inline uint64_t 5901182b177SPeter Wemm rdr4(void) 5911182b177SPeter Wemm { 592*f5ac47f4SJung-uk Kim uint64_t data; 5931182b177SPeter Wemm __asm __volatile("movq %%dr4,%0" : "=r" (data)); 5941182b177SPeter Wemm return (data); 5951182b177SPeter Wemm } 5961182b177SPeter Wemm 5971182b177SPeter Wemm static __inline void 598*f5ac47f4SJung-uk Kim load_dr4(uint64_t dr4) 5991182b177SPeter Wemm { 6001182b177SPeter Wemm __asm __volatile("movq %0,%%dr4" : : "r" (dr4)); 6011182b177SPeter Wemm } 6021182b177SPeter Wemm 603*f5ac47f4SJung-uk Kim static __inline uint64_t 6041182b177SPeter Wemm rdr5(void) 6051182b177SPeter Wemm { 606*f5ac47f4SJung-uk Kim uint64_t data; 6071182b177SPeter Wemm __asm __volatile("movq %%dr5,%0" : "=r" (data)); 6081182b177SPeter Wemm return (data); 6091182b177SPeter Wemm } 6101182b177SPeter Wemm 6111182b177SPeter Wemm static __inline void 612*f5ac47f4SJung-uk Kim load_dr5(uint64_t dr5) 6131182b177SPeter Wemm { 6141182b177SPeter Wemm __asm __volatile("movq %0,%%dr5" : : "r" (dr5)); 6151182b177SPeter Wemm } 6161182b177SPeter Wemm 617*f5ac47f4SJung-uk Kim static __inline uint64_t 6181182b177SPeter Wemm rdr6(void) 6191182b177SPeter Wemm { 620*f5ac47f4SJung-uk Kim uint64_t data; 6211182b177SPeter Wemm __asm __volatile("movq %%dr6,%0" : "=r" (data)); 6221182b177SPeter Wemm return (data); 6231182b177SPeter Wemm } 6241182b177SPeter Wemm 6251182b177SPeter Wemm static __inline void 626*f5ac47f4SJung-uk Kim load_dr6(uint64_t dr6) 6271182b177SPeter Wemm { 6281182b177SPeter Wemm __asm __volatile("movq %0,%%dr6" : : "r" (dr6)); 6291182b177SPeter Wemm } 6301182b177SPeter Wemm 631*f5ac47f4SJung-uk Kim static __inline uint64_t 6321182b177SPeter Wemm rdr7(void) 6331182b177SPeter Wemm { 634*f5ac47f4SJung-uk Kim uint64_t data; 6351182b177SPeter Wemm __asm __volatile("movq %%dr7,%0" : "=r" (data)); 6361182b177SPeter Wemm return (data); 6371182b177SPeter Wemm } 6381182b177SPeter Wemm 6391182b177SPeter Wemm static __inline void 640*f5ac47f4SJung-uk Kim load_dr7(uint64_t dr7) 6411182b177SPeter Wemm { 6421182b177SPeter Wemm __asm __volatile("movq %0,%%dr7" : : "r" (dr7)); 6431182b177SPeter Wemm } 6441182b177SPeter Wemm 645ba74981eSWarner Losh static __inline register_t 646ba74981eSWarner Losh intr_disable(void) 647ba74981eSWarner Losh { 648afa88623SPeter Wemm register_t rflags; 649ba74981eSWarner Losh 650afa88623SPeter Wemm rflags = read_rflags(); 651ba74981eSWarner Losh disable_intr(); 652afa88623SPeter Wemm return (rflags); 653ba74981eSWarner Losh } 654ba74981eSWarner Losh 655ba74981eSWarner Losh static __inline void 656afa88623SPeter Wemm intr_restore(register_t rflags) 657ba74981eSWarner Losh { 658afa88623SPeter Wemm write_rflags(rflags); 659ba74981eSWarner Losh } 660ba74981eSWarner Losh 661a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 6625b81b6b3SRodney W. Grimes 663b63dc6adSAlfred Perlstein int breakpoint(void); 664b63dc6adSAlfred Perlstein u_int bsfl(u_int mask); 665b63dc6adSAlfred Perlstein u_int bsrl(u_int mask); 666b63dc6adSAlfred Perlstein void disable_intr(void); 667b63dc6adSAlfred Perlstein void do_cpuid(u_int ax, u_int *p); 668b63dc6adSAlfred Perlstein void enable_intr(void); 669d7ee4425SMark Murray void halt(void); 6704f6c19e5SPeter Wemm void ia32_pause(void); 671b63dc6adSAlfred Perlstein u_char inb(u_int port); 672b63dc6adSAlfred Perlstein u_int inl(u_int port); 67393d8be03SDavid E. O'Brien void insb(u_int port, void *addr, size_t count); 67493d8be03SDavid E. O'Brien void insl(u_int port, void *addr, size_t count); 67593d8be03SDavid E. O'Brien void insw(u_int port, void *addr, size_t count); 6764f6c19e5SPeter Wemm register_t intr_disable(void); 6774f6c19e5SPeter Wemm void intr_restore(register_t rf); 678b63dc6adSAlfred Perlstein void invd(void); 679b63dc6adSAlfred Perlstein void invlpg(u_int addr); 680b63dc6adSAlfred Perlstein void invltlb(void); 681b63dc6adSAlfred Perlstein u_short inw(u_int port); 682eb1443c8SPeter Wemm void lidt(struct region_descriptor *addr); 683eb1443c8SPeter Wemm void lldt(u_short sel); 6844f6c19e5SPeter Wemm void load_cr0(u_long cr0); 6854f6c19e5SPeter Wemm void load_cr3(u_long cr3); 6864f6c19e5SPeter Wemm void load_cr4(u_long cr4); 687*f5ac47f4SJung-uk Kim void load_dr0(uint64_t dr0); 688*f5ac47f4SJung-uk Kim void load_dr1(uint64_t dr1); 689*f5ac47f4SJung-uk Kim void load_dr2(uint64_t dr2); 690*f5ac47f4SJung-uk Kim void load_dr3(uint64_t dr3); 691*f5ac47f4SJung-uk Kim void load_dr4(uint64_t dr4); 692*f5ac47f4SJung-uk Kim void load_dr5(uint64_t dr5); 693*f5ac47f4SJung-uk Kim void load_dr6(uint64_t dr6); 694*f5ac47f4SJung-uk Kim void load_dr7(uint64_t dr7); 69527d4fea6SRoman Divacky void load_fs(u_short sel); 69627d4fea6SRoman Divacky void load_gs(u_short sel); 697eb1443c8SPeter Wemm void ltr(u_short sel); 698b63dc6adSAlfred Perlstein void outb(u_int port, u_char data); 699b63dc6adSAlfred Perlstein void outl(u_int port, u_int data); 70093d8be03SDavid E. O'Brien void outsb(u_int port, const void *addr, size_t count); 70193d8be03SDavid E. O'Brien void outsl(u_int port, const void *addr, size_t count); 70293d8be03SDavid E. O'Brien void outsw(u_int port, const void *addr, size_t count); 703b63dc6adSAlfred Perlstein void outw(u_int port, u_short data); 7044f6c19e5SPeter Wemm u_long rcr0(void); 7054f6c19e5SPeter Wemm u_long rcr2(void); 7064f6c19e5SPeter Wemm u_long rcr3(void); 7074f6c19e5SPeter Wemm u_long rcr4(void); 708*f5ac47f4SJung-uk Kim uint64_t rdmsr(u_int msr); 709*f5ac47f4SJung-uk Kim uint64_t rdpmc(u_int pmc); 710*f5ac47f4SJung-uk Kim uint64_t rdr0(void); 711*f5ac47f4SJung-uk Kim uint64_t rdr1(void); 712*f5ac47f4SJung-uk Kim uint64_t rdr2(void); 713*f5ac47f4SJung-uk Kim uint64_t rdr3(void); 714*f5ac47f4SJung-uk Kim uint64_t rdr4(void); 715*f5ac47f4SJung-uk Kim uint64_t rdr5(void); 716*f5ac47f4SJung-uk Kim uint64_t rdr6(void); 717*f5ac47f4SJung-uk Kim uint64_t rdr7(void); 718*f5ac47f4SJung-uk Kim uint64_t rdtsc(void); 719afa88623SPeter Wemm u_int read_rflags(void); 7204f6c19e5SPeter Wemm u_int rfs(void); 7214f6c19e5SPeter Wemm u_int rgs(void); 722b63dc6adSAlfred Perlstein void wbinvd(void); 723afa88623SPeter Wemm void write_rflags(u_int rf); 724*f5ac47f4SJung-uk Kim void wrmsr(u_int msr, uint64_t newval); 725004bedebSBruce Evans 726a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 7275b81b6b3SRodney W. Grimes 728b63dc6adSAlfred Perlstein void reset_dbregs(void); 729d74ac681SMatthew Dillon 730e085f869SStanislav Sedov #ifdef _KERNEL 731e085f869SStanislav Sedov int rdmsr_safe(u_int msr, uint64_t *val); 732e085f869SStanislav Sedov int wrmsr_safe(u_int msr, uint64_t newval); 733e085f869SStanislav Sedov #endif 734e085f869SStanislav Sedov 735004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 736