13c4dd356SDavid Greenman /*- 23c4dd356SDavid Greenman * Copyright (c) 1993 The Regents of the University of California. 33c4dd356SDavid Greenman * All rights reserved. 43c4dd356SDavid Greenman * 53c4dd356SDavid Greenman * Redistribution and use in source and binary forms, with or without 63c4dd356SDavid Greenman * modification, are permitted provided that the following conditions 73c4dd356SDavid Greenman * are met: 83c4dd356SDavid Greenman * 1. Redistributions of source code must retain the above copyright 93c4dd356SDavid Greenman * notice, this list of conditions and the following disclaimer. 103c4dd356SDavid Greenman * 2. Redistributions in binary form must reproduce the above copyright 113c4dd356SDavid Greenman * notice, this list of conditions and the following disclaimer in the 123c4dd356SDavid Greenman * documentation and/or other materials provided with the distribution. 133c4dd356SDavid Greenman * 3. All advertising materials mentioning features or use of this software 143c4dd356SDavid Greenman * must display the following acknowledgement: 153c4dd356SDavid Greenman * This product includes software developed by the University of 163c4dd356SDavid Greenman * California, Berkeley and its contributors. 173c4dd356SDavid Greenman * 4. Neither the name of the University nor the names of its contributors 183c4dd356SDavid Greenman * may be used to endorse or promote products derived from this software 193c4dd356SDavid Greenman * without specific prior written permission. 203c4dd356SDavid Greenman * 213c4dd356SDavid Greenman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 223c4dd356SDavid Greenman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 233c4dd356SDavid Greenman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 243c4dd356SDavid Greenman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 253c4dd356SDavid Greenman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 263c4dd356SDavid Greenman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 273c4dd356SDavid Greenman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 283c4dd356SDavid Greenman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 293c4dd356SDavid Greenman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 303c4dd356SDavid Greenman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 313c4dd356SDavid Greenman * SUCH DAMAGE. 323c4dd356SDavid Greenman * 33c3aac50fSPeter Wemm * $FreeBSD$ 343c4dd356SDavid Greenman */ 353c4dd356SDavid Greenman 365b81b6b3SRodney W. Grimes /* 375b81b6b3SRodney W. Grimes * Functions to provide access to special i386 instructions. 38f5d9a10bSMark Murray * This in included in sys/systm.h, and that file should be 39f5d9a10bSMark Murray * used in preference to this. 405b81b6b3SRodney W. Grimes */ 415b81b6b3SRodney W. Grimes 426e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_ 43004bedebSBruce Evans #define _MACHINE_CPUFUNC_H_ 446e393973SGarrett Wollman 4529d5de8aSWarner Losh #include <sys/cdefs.h> 467e1f6dfeSJohn Baldwin #include <machine/psl.h> 4729d5de8aSWarner Losh 48d74ac681SMatthew Dillon struct thread; 49eb1443c8SPeter Wemm struct region_descriptor; 50d74ac681SMatthew Dillon 5129d5de8aSWarner Losh __BEGIN_DECLS 52e31fa854SDoug Rabson #define readb(va) (*(volatile u_int8_t *) (va)) 53e31fa854SDoug Rabson #define readw(va) (*(volatile u_int16_t *) (va)) 54e31fa854SDoug Rabson #define readl(va) (*(volatile u_int32_t *) (va)) 55afa88623SPeter Wemm #define readq(va) (*(volatile u_int64_t *) (va)) 56e31fa854SDoug Rabson 57e31fa854SDoug Rabson #define writeb(va, d) (*(volatile u_int8_t *) (va) = (d)) 58e31fa854SDoug Rabson #define writew(va, d) (*(volatile u_int16_t *) (va) = (d)) 59e31fa854SDoug Rabson #define writel(va, d) (*(volatile u_int32_t *) (va) = (d)) 60afa88623SPeter Wemm #define writeq(va, d) (*(volatile u_int64_t *) (va) = (d)) 61e31fa854SDoug Rabson 625b81b6b3SRodney W. Grimes #ifdef __GNUC__ 635b81b6b3SRodney W. Grimes 645dbd168eSBruce Evans static __inline void 655dbd168eSBruce Evans breakpoint(void) 66004bedebSBruce Evans { 67004bedebSBruce Evans __asm __volatile("int $3"); 685b81b6b3SRodney W. Grimes } 695b81b6b3SRodney W. Grimes 70c83b1328SBruce Evans static __inline u_int 71c83b1328SBruce Evans bsfl(u_int mask) 72c83b1328SBruce Evans { 73c83b1328SBruce Evans u_int result; 74c83b1328SBruce Evans 753f9a462fSJohn Baldwin __asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask)); 76c83b1328SBruce Evans return (result); 77c83b1328SBruce Evans } 78c83b1328SBruce Evans 79c83b1328SBruce Evans static __inline u_int 80c83b1328SBruce Evans bsrl(u_int mask) 81c83b1328SBruce Evans { 82c83b1328SBruce Evans u_int result; 83c83b1328SBruce Evans 843f9a462fSJohn Baldwin __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask)); 85c83b1328SBruce Evans return (result); 86c83b1328SBruce Evans } 87c83b1328SBruce Evans 88004bedebSBruce Evans static __inline void 895b81b6b3SRodney W. Grimes disable_intr(void) 905b81b6b3SRodney W. Grimes { 918966b85cSJohn Dyson __asm __volatile("cli" : : : "memory"); 925b81b6b3SRodney W. Grimes } 935b81b6b3SRodney W. Grimes 94004bedebSBruce Evans static __inline void 95a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p) 96a983fdfeSDavid Malone { 97a983fdfeSDavid Malone __asm __volatile("cpuid" 98a983fdfeSDavid Malone : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 99a983fdfeSDavid Malone : "0" (ax)); 100a983fdfeSDavid Malone } 101a983fdfeSDavid Malone 102a983fdfeSDavid Malone static __inline void 1035b81b6b3SRodney W. Grimes enable_intr(void) 1045b81b6b3SRodney W. Grimes { 105fadc51bdSBruce Evans __asm __volatile("sti"); 1065b81b6b3SRodney W. Grimes } 1075b81b6b3SRodney W. Grimes 108264c3d87SPeter Wemm #define HAVE_INLINE_FFS 109264c3d87SPeter Wemm 110264c3d87SPeter Wemm static __inline int 111264c3d87SPeter Wemm ffs(int mask) 112264c3d87SPeter Wemm { 113264c3d87SPeter Wemm /* 114004bedebSBruce Evans * Note that gcc-2's builtin ffs would be used if we didn't declare 115004bedebSBruce Evans * this inline or turn off the builtin. The builtin is faster but 116c83b1328SBruce Evans * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later 117c83b1328SBruce Evans * versions. 118004bedebSBruce Evans */ 1197e622d3cSMark Murray return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1); 120004bedebSBruce Evans } 121004bedebSBruce Evans 12213f588f8SGarrett Wollman #define HAVE_INLINE_FLS 12313f588f8SGarrett Wollman 12413f588f8SGarrett Wollman static __inline int 12513f588f8SGarrett Wollman fls(int mask) 12613f588f8SGarrett Wollman { 1277e622d3cSMark Murray return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 12813f588f8SGarrett Wollman } 12913f588f8SGarrett Wollman 130d7ee4425SMark Murray static __inline void 131d7ee4425SMark Murray halt(void) 132d7ee4425SMark Murray { 133d7ee4425SMark Murray __asm __volatile("hlt"); 134d7ee4425SMark Murray } 135d7ee4425SMark Murray 136004bedebSBruce Evans #if __GNUC__ < 2 137004bedebSBruce Evans 138004bedebSBruce Evans #define inb(port) inbv(port) 139004bedebSBruce Evans #define outb(port, data) outbv(port, data) 140004bedebSBruce Evans 141004bedebSBruce Evans #else /* __GNUC >= 2 */ 142004bedebSBruce Evans 143004bedebSBruce Evans /* 1448089a043SBruce Evans * The following complications are to get around gcc not having a 1458089a043SBruce Evans * constraint letter for the range 0..255. We still put "d" in the 1468089a043SBruce Evans * constraint because "i" isn't a valid constraint when the port 1478089a043SBruce Evans * isn't constant. This only matters for -O0 because otherwise 1488089a043SBruce Evans * the non-working version gets optimized away. 1498089a043SBruce Evans * 150004bedebSBruce Evans * Use an expression-statement instead of a conditional expression 151004bedebSBruce Evans * because gcc-2.6.0 would promote the operands of the conditional 152004bedebSBruce Evans * and produce poor code for "if ((inb(var) & const1) == const2)". 153388dfa71SBruce Evans * 154388dfa71SBruce Evans * The unnecessary test `(port) < 0x10000' is to generate a warning if 155388dfa71SBruce Evans * the `port' has type u_short or smaller. Such types are pessimal. 156388dfa71SBruce Evans * This actually only works for signed types. The range check is 157388dfa71SBruce Evans * careful to avoid generating warnings. 158004bedebSBruce Evans */ 159388dfa71SBruce Evans #define inb(port) __extension__ ({ \ 160004bedebSBruce Evans u_char _data; \ 161388dfa71SBruce Evans if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 162388dfa71SBruce Evans && (port) < 0x10000) \ 163004bedebSBruce Evans _data = inbc(port); \ 164004bedebSBruce Evans else \ 165004bedebSBruce Evans _data = inbv(port); \ 166004bedebSBruce Evans _data; }) 167004bedebSBruce Evans 168388dfa71SBruce Evans #define outb(port, data) ( \ 169388dfa71SBruce Evans __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 170388dfa71SBruce Evans && (port) < 0x10000 \ 171004bedebSBruce Evans ? outbc(port, data) : outbv(port, data)) 172004bedebSBruce Evans 173004bedebSBruce Evans static __inline u_char 174004bedebSBruce Evans inbc(u_int port) 175004bedebSBruce Evans { 176004bedebSBruce Evans u_char data; 177004bedebSBruce Evans 1788089a043SBruce Evans __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); 179004bedebSBruce Evans return (data); 180004bedebSBruce Evans } 181004bedebSBruce Evans 182004bedebSBruce Evans static __inline void 183004bedebSBruce Evans outbc(u_int port, u_char data) 184004bedebSBruce Evans { 1858089a043SBruce Evans __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port))); 186004bedebSBruce Evans } 187004bedebSBruce Evans 188004bedebSBruce Evans #endif /* __GNUC <= 2 */ 189004bedebSBruce Evans 190004bedebSBruce Evans static __inline u_char 191004bedebSBruce Evans inbv(u_int port) 192004bedebSBruce Evans { 193004bedebSBruce Evans u_char data; 194004bedebSBruce Evans /* 195004bedebSBruce Evans * We use %%dx and not %1 here because i/o is done at %dx and not at 196004bedebSBruce Evans * %edx, while gcc generates inferior code (movw instead of movl) 197004bedebSBruce Evans * if we tell it to load (u_short) port. 198004bedebSBruce Evans */ 199004bedebSBruce Evans __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 200004bedebSBruce Evans return (data); 201004bedebSBruce Evans } 202004bedebSBruce Evans 20300be8601SBruce Evans static __inline u_int 204004bedebSBruce Evans inl(u_int port) 205004bedebSBruce Evans { 20600be8601SBruce Evans u_int data; 207004bedebSBruce Evans 208004bedebSBruce Evans __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); 209004bedebSBruce Evans return (data); 210004bedebSBruce Evans } 211004bedebSBruce Evans 212004bedebSBruce Evans static __inline void 213004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt) 214004bedebSBruce Evans { 215004bedebSBruce Evans __asm __volatile("cld; rep; insb" 2163f9a462fSJohn Baldwin : "+D" (addr), "+c" (cnt) 2173f9a462fSJohn Baldwin : "d" (port) 218896763faSBruce Evans : "memory"); 219004bedebSBruce Evans } 220004bedebSBruce Evans 221004bedebSBruce Evans static __inline void 222004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt) 223004bedebSBruce Evans { 224004bedebSBruce Evans __asm __volatile("cld; rep; insw" 2253f9a462fSJohn Baldwin : "+D" (addr), "+c" (cnt) 2263f9a462fSJohn Baldwin : "d" (port) 227896763faSBruce Evans : "memory"); 228004bedebSBruce Evans } 229004bedebSBruce Evans 230004bedebSBruce Evans static __inline void 231004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt) 232004bedebSBruce Evans { 233004bedebSBruce Evans __asm __volatile("cld; rep; insl" 2343f9a462fSJohn Baldwin : "+D" (addr), "+c" (cnt) 2353f9a462fSJohn Baldwin : "d" (port) 236896763faSBruce Evans : "memory"); 237004bedebSBruce Evans } 238004bedebSBruce Evans 239ece15d78SBruce Evans static __inline void 2404c024bbdSKATO Takenori invd(void) 2414c024bbdSKATO Takenori { 2424c024bbdSKATO Takenori __asm __volatile("invd"); 2434c024bbdSKATO Takenori } 2444c024bbdSKATO Takenori 245004bedebSBruce Evans static __inline u_short 246004bedebSBruce Evans inw(u_int port) 247004bedebSBruce Evans { 248004bedebSBruce Evans u_short data; 249004bedebSBruce Evans 250004bedebSBruce Evans __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port)); 251004bedebSBruce Evans return (data); 252004bedebSBruce Evans } 253004bedebSBruce Evans 254004bedebSBruce Evans static __inline void 255004bedebSBruce Evans outbv(u_int port, u_char data) 256004bedebSBruce Evans { 257004bedebSBruce Evans u_char al; 258004bedebSBruce Evans /* 259004bedebSBruce Evans * Use an unnecessary assignment to help gcc's register allocator. 260004bedebSBruce Evans * This make a large difference for gcc-1.40 and a tiny difference 261004bedebSBruce Evans * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for 262004bedebSBruce Evans * best results. gcc-2.6.0 can't handle this. 263004bedebSBruce Evans */ 264004bedebSBruce Evans al = data; 265004bedebSBruce Evans __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 266004bedebSBruce Evans } 267004bedebSBruce Evans 268004bedebSBruce Evans static __inline void 26900be8601SBruce Evans outl(u_int port, u_int data) 270004bedebSBruce Evans { 271004bedebSBruce Evans /* 272004bedebSBruce Evans * outl() and outw() aren't used much so we haven't looked at 273004bedebSBruce Evans * possible micro-optimizations such as the unnecessary 274004bedebSBruce Evans * assignment for them. 275004bedebSBruce Evans */ 276004bedebSBruce Evans __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); 277004bedebSBruce Evans } 278004bedebSBruce Evans 279004bedebSBruce Evans static __inline void 280e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt) 281004bedebSBruce Evans { 282004bedebSBruce Evans __asm __volatile("cld; rep; outsb" 2833f9a462fSJohn Baldwin : "+S" (addr), "+c" (cnt) 2843f9a462fSJohn Baldwin : "d" (port)); 285004bedebSBruce Evans } 286004bedebSBruce Evans 287004bedebSBruce Evans static __inline void 288e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt) 289004bedebSBruce Evans { 290004bedebSBruce Evans __asm __volatile("cld; rep; outsw" 2913f9a462fSJohn Baldwin : "+S" (addr), "+c" (cnt) 2923f9a462fSJohn Baldwin : "d" (port)); 293004bedebSBruce Evans } 294004bedebSBruce Evans 295004bedebSBruce Evans static __inline void 296e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt) 297004bedebSBruce Evans { 298004bedebSBruce Evans __asm __volatile("cld; rep; outsl" 2993f9a462fSJohn Baldwin : "+S" (addr), "+c" (cnt) 3003f9a462fSJohn Baldwin : "d" (port)); 301004bedebSBruce Evans } 302004bedebSBruce Evans 303004bedebSBruce Evans static __inline void 304004bedebSBruce Evans outw(u_int port, u_short data) 305004bedebSBruce Evans { 306004bedebSBruce Evans __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port)); 307004bedebSBruce Evans } 308004bedebSBruce Evans 3092be69f32SJohn Baldwin static __inline void 3106b8c6989SJohn Baldwin ia32_pause(void) 3112be69f32SJohn Baldwin { 3122be69f32SJohn Baldwin __asm __volatile("pause"); 3132be69f32SJohn Baldwin } 3142be69f32SJohn Baldwin 315afa88623SPeter Wemm static __inline u_long 316afa88623SPeter Wemm read_rflags(void) 3175b81b6b3SRodney W. Grimes { 318afa88623SPeter Wemm u_long rf; 319004bedebSBruce Evans 320afa88623SPeter Wemm __asm __volatile("pushfq; popq %0" : "=r" (rf)); 321afa88623SPeter Wemm return (rf); 3225b81b6b3SRodney W. Grimes } 3235b81b6b3SRodney W. Grimes 32400be8601SBruce Evans static __inline u_int64_t 3255dbd168eSBruce Evans rdmsr(u_int msr) 3265dbd168eSBruce Evans { 327afa88623SPeter Wemm u_int32_t low, high; 3285dbd168eSBruce Evans 329afa88623SPeter Wemm __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); 330afa88623SPeter Wemm return (low | ((u_int64_t)high << 32)); 3315dbd168eSBruce Evans } 3325dbd168eSBruce Evans 33300be8601SBruce Evans static __inline u_int64_t 3345dbd168eSBruce Evans rdpmc(u_int pmc) 3355dbd168eSBruce Evans { 336afa88623SPeter Wemm u_int32_t low, high; 3375dbd168eSBruce Evans 338afa88623SPeter Wemm __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc)); 339afa88623SPeter Wemm return (low | ((u_int64_t)high << 32)); 3405dbd168eSBruce Evans } 3415dbd168eSBruce Evans 34200be8601SBruce Evans static __inline u_int64_t 3435dbd168eSBruce Evans rdtsc(void) 3445dbd168eSBruce Evans { 345afa88623SPeter Wemm u_int32_t low, high; 3465dbd168eSBruce Evans 347afa88623SPeter Wemm __asm __volatile("rdtsc" : "=a" (low), "=d" (high)); 348afa88623SPeter Wemm return (low | ((u_int64_t)high << 32)); 3495dbd168eSBruce Evans } 3505dbd168eSBruce Evans 351004bedebSBruce Evans static __inline void 3524c024bbdSKATO Takenori wbinvd(void) 3534c024bbdSKATO Takenori { 3544c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3554c024bbdSKATO Takenori } 3564c024bbdSKATO Takenori 3574c024bbdSKATO Takenori static __inline void 358afa88623SPeter Wemm write_rflags(u_long rf) 3595b81b6b3SRodney W. Grimes { 360afa88623SPeter Wemm __asm __volatile("pushq %0; popfq" : : "r" (rf)); 3615b81b6b3SRodney W. Grimes } 3625b81b6b3SRodney W. Grimes 363d69e8502SGarrett Wollman static __inline void 36400be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval) 365d69e8502SGarrett Wollman { 366afa88623SPeter Wemm u_int32_t low, high; 367afa88623SPeter Wemm 368afa88623SPeter Wemm low = newval; 369afa88623SPeter Wemm high = newval >> 32; 370afa88623SPeter Wemm __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 371d69e8502SGarrett Wollman } 372d69e8502SGarrett Wollman 373f1b665c8SPeter Wemm static __inline void 374afa88623SPeter Wemm load_cr0(u_long data) 375f1b665c8SPeter Wemm { 376f1b665c8SPeter Wemm 377afa88623SPeter Wemm __asm __volatile("movq %0,%%cr0" : : "r" (data)); 378f1b665c8SPeter Wemm } 379f1b665c8SPeter Wemm 380afa88623SPeter Wemm static __inline u_long 381f1b665c8SPeter Wemm rcr0(void) 382f1b665c8SPeter Wemm { 383afa88623SPeter Wemm u_long data; 384f1b665c8SPeter Wemm 385afa88623SPeter Wemm __asm __volatile("movq %%cr0,%0" : "=r" (data)); 386f1b665c8SPeter Wemm return (data); 387f1b665c8SPeter Wemm } 388f1b665c8SPeter Wemm 389afa88623SPeter Wemm static __inline u_long 390f1b665c8SPeter Wemm rcr2(void) 391f1b665c8SPeter Wemm { 392afa88623SPeter Wemm u_long data; 393f1b665c8SPeter Wemm 394afa88623SPeter Wemm __asm __volatile("movq %%cr2,%0" : "=r" (data)); 395f1b665c8SPeter Wemm return (data); 396f1b665c8SPeter Wemm } 397f1b665c8SPeter Wemm 398f1b665c8SPeter Wemm static __inline void 399afa88623SPeter Wemm load_cr3(u_long data) 400f1b665c8SPeter Wemm { 401f1b665c8SPeter Wemm 402afa88623SPeter Wemm __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory"); 403f1b665c8SPeter Wemm } 404f1b665c8SPeter Wemm 405afa88623SPeter Wemm static __inline u_long 406f1b665c8SPeter Wemm rcr3(void) 407f1b665c8SPeter Wemm { 408afa88623SPeter Wemm u_long data; 409f1b665c8SPeter Wemm 410afa88623SPeter Wemm __asm __volatile("movq %%cr3,%0" : "=r" (data)); 411f1b665c8SPeter Wemm return (data); 412f1b665c8SPeter Wemm } 413f1b665c8SPeter Wemm 414f1b665c8SPeter Wemm static __inline void 415afa88623SPeter Wemm load_cr4(u_long data) 416f1b665c8SPeter Wemm { 417afa88623SPeter Wemm __asm __volatile("movq %0,%%cr4" : : "r" (data)); 418f1b665c8SPeter Wemm } 419f1b665c8SPeter Wemm 420afa88623SPeter Wemm static __inline u_long 421f1b665c8SPeter Wemm rcr4(void) 422f1b665c8SPeter Wemm { 423afa88623SPeter Wemm u_long data; 424f1b665c8SPeter Wemm 425afa88623SPeter Wemm __asm __volatile("movq %%cr4,%0" : "=r" (data)); 426f1b665c8SPeter Wemm return (data); 427f1b665c8SPeter Wemm } 428f1b665c8SPeter Wemm 429f1b665c8SPeter Wemm /* 430f1b665c8SPeter Wemm * Global TLB flush (except for thise for pages marked PG_G) 431f1b665c8SPeter Wemm */ 432f1b665c8SPeter Wemm static __inline void 433f1b665c8SPeter Wemm invltlb(void) 434f1b665c8SPeter Wemm { 435f1b665c8SPeter Wemm 436f1b665c8SPeter Wemm load_cr3(rcr3()); 437f1b665c8SPeter Wemm } 438f1b665c8SPeter Wemm 439f1b665c8SPeter Wemm /* 440f1b665c8SPeter Wemm * TLB flush for an individual page (even if it has PG_G). 441f1b665c8SPeter Wemm * Only works on 486+ CPUs (i386 does not have PG_G). 442f1b665c8SPeter Wemm */ 443f1b665c8SPeter Wemm static __inline void 444afa88623SPeter Wemm invlpg(u_long addr) 445f1b665c8SPeter Wemm { 446f1b665c8SPeter Wemm 447f1b665c8SPeter Wemm __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 448f1b665c8SPeter Wemm } 449f1b665c8SPeter Wemm 4505206bca1SLuoqi Chen static __inline u_int 4515206bca1SLuoqi Chen rfs(void) 4525206bca1SLuoqi Chen { 453d1fc2022SDavid Xu u_int sel; 454d1fc2022SDavid Xu __asm __volatile("movl %%fs,%0" : "=rm" (sel)); 4555206bca1SLuoqi Chen return (sel); 4565206bca1SLuoqi Chen } 4575206bca1SLuoqi Chen 4585206bca1SLuoqi Chen static __inline u_int 4595206bca1SLuoqi Chen rgs(void) 4605206bca1SLuoqi Chen { 461d1fc2022SDavid Xu u_int sel; 462d1fc2022SDavid Xu __asm __volatile("movl %%gs,%0" : "=rm" (sel)); 4635206bca1SLuoqi Chen return (sel); 4645206bca1SLuoqi Chen } 4655206bca1SLuoqi Chen 4665206bca1SLuoqi Chen static __inline void 467d85631c4SPeter Wemm load_ds(u_int sel) 468d85631c4SPeter Wemm { 469d85631c4SPeter Wemm __asm __volatile("movl %0,%%ds" : : "rm" (sel)); 470d85631c4SPeter Wemm } 471d85631c4SPeter Wemm 472d85631c4SPeter Wemm static __inline void 473d85631c4SPeter Wemm load_es(u_int sel) 474d85631c4SPeter Wemm { 475d85631c4SPeter Wemm __asm __volatile("movl %0,%%es" : : "rm" (sel)); 476d85631c4SPeter Wemm } 477d85631c4SPeter Wemm 478d85631c4SPeter Wemm static __inline void 4795206bca1SLuoqi Chen load_fs(u_int sel) 4805206bca1SLuoqi Chen { 481e870e9b2SLuoqi Chen __asm __volatile("movl %0,%%fs" : : "rm" (sel)); 4825206bca1SLuoqi Chen } 4835206bca1SLuoqi Chen 4845206bca1SLuoqi Chen static __inline void 4855206bca1SLuoqi Chen load_gs(u_int sel) 4865206bca1SLuoqi Chen { 487e870e9b2SLuoqi Chen __asm __volatile("movl %0,%%gs" : : "rm" (sel)); 4885206bca1SLuoqi Chen } 4895206bca1SLuoqi Chen 490eb1443c8SPeter Wemm /* void lidt(struct region_descriptor *addr); */ 491eb1443c8SPeter Wemm static __inline void 492eb1443c8SPeter Wemm lidt(struct region_descriptor *addr) 493eb1443c8SPeter Wemm { 494eb1443c8SPeter Wemm __asm __volatile("lidt (%0)" : : "r" (addr)); 495eb1443c8SPeter Wemm } 496eb1443c8SPeter Wemm 497eb1443c8SPeter Wemm /* void lldt(u_short sel); */ 498eb1443c8SPeter Wemm static __inline void 499eb1443c8SPeter Wemm lldt(u_short sel) 500eb1443c8SPeter Wemm { 501eb1443c8SPeter Wemm __asm __volatile("lldt %0" : : "r" (sel)); 502eb1443c8SPeter Wemm } 503eb1443c8SPeter Wemm 504eb1443c8SPeter Wemm /* void ltr(u_short sel); */ 505eb1443c8SPeter Wemm static __inline void 506eb1443c8SPeter Wemm ltr(u_short sel) 507eb1443c8SPeter Wemm { 508eb1443c8SPeter Wemm __asm __volatile("ltr %0" : : "r" (sel)); 509eb1443c8SPeter Wemm } 510eb1443c8SPeter Wemm 511ba74981eSWarner Losh static __inline register_t 512ba74981eSWarner Losh intr_disable(void) 513ba74981eSWarner Losh { 514afa88623SPeter Wemm register_t rflags; 515ba74981eSWarner Losh 516afa88623SPeter Wemm rflags = read_rflags(); 517ba74981eSWarner Losh disable_intr(); 518afa88623SPeter Wemm return (rflags); 519ba74981eSWarner Losh } 520ba74981eSWarner Losh 521ba74981eSWarner Losh static __inline void 522afa88623SPeter Wemm intr_restore(register_t rflags) 523ba74981eSWarner Losh { 524afa88623SPeter Wemm write_rflags(rflags); 525ba74981eSWarner Losh } 526ba74981eSWarner Losh 527004bedebSBruce Evans #else /* !__GNUC__ */ 5285b81b6b3SRodney W. Grimes 529b63dc6adSAlfred Perlstein int breakpoint(void); 530b63dc6adSAlfred Perlstein u_int bsfl(u_int mask); 531b63dc6adSAlfred Perlstein u_int bsrl(u_int mask); 532afa88623SPeter Wemm void cpu_invlpg(u_long addr); 533afa88623SPeter Wemm void cpu_invlpg_range(u_long start, u_long end); 534b63dc6adSAlfred Perlstein void disable_intr(void); 535b63dc6adSAlfred Perlstein void do_cpuid(u_int ax, u_int *p); 536b63dc6adSAlfred Perlstein void enable_intr(void); 537d7ee4425SMark Murray void halt(void); 538b63dc6adSAlfred Perlstein u_char inb(u_int port); 539b63dc6adSAlfred Perlstein u_int inl(u_int port); 540b63dc6adSAlfred Perlstein void insb(u_int port, void *addr, size_t cnt); 541b63dc6adSAlfred Perlstein void insl(u_int port, void *addr, size_t cnt); 542b63dc6adSAlfred Perlstein void insw(u_int port, void *addr, size_t cnt); 543b63dc6adSAlfred Perlstein void invd(void); 544b63dc6adSAlfred Perlstein void invlpg(u_int addr); 545f1b665c8SPeter Wemm void invlpg_range(u_int start, u_int end); 546b63dc6adSAlfred Perlstein void invltlb(void); 547b63dc6adSAlfred Perlstein u_short inw(u_int port); 548f1b665c8SPeter Wemm void load_cr0(u_int cr0); 549f1b665c8SPeter Wemm void load_cr3(u_int cr3); 550f1b665c8SPeter Wemm void load_cr4(u_int cr4); 551f1b665c8SPeter Wemm void load_fs(u_int sel); 552f1b665c8SPeter Wemm void load_gs(u_int sel); 553eb1443c8SPeter Wemm struct region_descriptor; 554eb1443c8SPeter Wemm void lidt(struct region_descriptor *addr); 555eb1443c8SPeter Wemm void lldt(u_short sel); 556eb1443c8SPeter Wemm void ltr(u_short sel); 557b63dc6adSAlfred Perlstein void outb(u_int port, u_char data); 558b63dc6adSAlfred Perlstein void outl(u_int port, u_int data); 559b63dc6adSAlfred Perlstein void outsb(u_int port, void *addr, size_t cnt); 560b63dc6adSAlfred Perlstein void outsl(u_int port, void *addr, size_t cnt); 561b63dc6adSAlfred Perlstein void outsw(u_int port, void *addr, size_t cnt); 562b63dc6adSAlfred Perlstein void outw(u_int port, u_short data); 5636b8c6989SJohn Baldwin void ia32_pause(void); 564f1b665c8SPeter Wemm u_int rcr0(void); 565b63dc6adSAlfred Perlstein u_int rcr2(void); 566f1b665c8SPeter Wemm u_int rcr3(void); 567f1b665c8SPeter Wemm u_int rcr4(void); 568f1b665c8SPeter Wemm u_int rfs(void); 569f1b665c8SPeter Wemm u_int rgs(void); 570b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr); 571b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc); 572b63dc6adSAlfred Perlstein u_int64_t rdtsc(void); 573afa88623SPeter Wemm u_int read_rflags(void); 574b63dc6adSAlfred Perlstein void wbinvd(void); 575afa88623SPeter Wemm void write_rflags(u_int rf); 576b63dc6adSAlfred Perlstein void wrmsr(u_int msr, u_int64_t newval); 57707508f90SJohn Baldwin void load_dr7(u_int dr7); 5782be69f32SJohn Baldwin register_t intr_disable(void); 579afa88623SPeter Wemm void intr_restore(register_t rf); 580004bedebSBruce Evans 5815b81b6b3SRodney W. Grimes #endif /* __GNUC__ */ 5825b81b6b3SRodney W. Grimes 583b63dc6adSAlfred Perlstein void reset_dbregs(void); 584d74ac681SMatthew Dillon 58529d5de8aSWarner Losh __END_DECLS 5865b81b6b3SRodney W. Grimes 587004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 588