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 48e31fa854SDoug Rabson #define readb(va) (*(volatile u_int8_t *) (va)) 49e31fa854SDoug Rabson #define readw(va) (*(volatile u_int16_t *) (va)) 50e31fa854SDoug Rabson #define readl(va) (*(volatile u_int32_t *) (va)) 51afa88623SPeter Wemm #define readq(va) (*(volatile u_int64_t *) (va)) 52e31fa854SDoug Rabson 53e31fa854SDoug Rabson #define writeb(va, d) (*(volatile u_int8_t *) (va) = (d)) 54e31fa854SDoug Rabson #define writew(va, d) (*(volatile u_int16_t *) (va) = (d)) 55e31fa854SDoug Rabson #define writel(va, d) (*(volatile u_int32_t *) (va) = (d)) 56afa88623SPeter Wemm #define writeq(va, d) (*(volatile u_int64_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 1035b81b6b3SRodney W. Grimes disable_intr(void) 1045b81b6b3SRodney W. Grimes { 1058966b85cSJohn Dyson __asm __volatile("cli" : : : "memory"); 1065b81b6b3SRodney W. Grimes } 1075b81b6b3SRodney W. Grimes 108004bedebSBruce Evans static __inline void 109a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p) 110a983fdfeSDavid Malone { 111a983fdfeSDavid Malone __asm __volatile("cpuid" 112a983fdfeSDavid Malone : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 113a983fdfeSDavid Malone : "0" (ax)); 114a983fdfeSDavid Malone } 115a983fdfeSDavid Malone 116a983fdfeSDavid Malone static __inline void 1175b81b6b3SRodney W. Grimes enable_intr(void) 1185b81b6b3SRodney W. Grimes { 119fadc51bdSBruce Evans __asm __volatile("sti"); 1205b81b6b3SRodney W. Grimes } 1215b81b6b3SRodney W. Grimes 122a67ef0a7SBruce Evans #ifdef _KERNEL 123a67ef0a7SBruce Evans 124264c3d87SPeter Wemm #define HAVE_INLINE_FFS 125bc35f5dcSPaul Saab #define ffs(x) __builtin_ffs(x) 126176ce2b1SPeter Wemm 127176ce2b1SPeter Wemm #define HAVE_INLINE_FFSL 128176ce2b1SPeter Wemm 129176ce2b1SPeter Wemm static __inline int 130176ce2b1SPeter Wemm ffsl(long mask) 131176ce2b1SPeter Wemm { 132176ce2b1SPeter Wemm return (mask == 0 ? mask : (int)bsfq((u_long)mask) + 1); 133004bedebSBruce Evans } 134004bedebSBruce Evans 13513f588f8SGarrett Wollman #define HAVE_INLINE_FLS 13613f588f8SGarrett Wollman 13713f588f8SGarrett Wollman static __inline int 13813f588f8SGarrett Wollman fls(int mask) 13913f588f8SGarrett Wollman { 1407e622d3cSMark Murray return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 14113f588f8SGarrett Wollman } 14213f588f8SGarrett Wollman 143176ce2b1SPeter Wemm #define HAVE_INLINE_FLSL 144176ce2b1SPeter Wemm 145176ce2b1SPeter Wemm static __inline int 146176ce2b1SPeter Wemm flsl(long mask) 147176ce2b1SPeter Wemm { 148176ce2b1SPeter Wemm return (mask == 0 ? mask : (int)bsrq((u_long)mask) + 1); 149176ce2b1SPeter Wemm } 150176ce2b1SPeter Wemm 151a67ef0a7SBruce Evans #endif /* _KERNEL */ 152a67ef0a7SBruce Evans 153d7ee4425SMark Murray static __inline void 154d7ee4425SMark Murray halt(void) 155d7ee4425SMark Murray { 156d7ee4425SMark Murray __asm __volatile("hlt"); 157d7ee4425SMark Murray } 158d7ee4425SMark Murray 159a5f50ef9SJoerg Wunsch #if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3 160004bedebSBruce Evans 161004bedebSBruce Evans #define inb(port) inbv(port) 162004bedebSBruce Evans #define outb(port, data) outbv(port, data) 163004bedebSBruce Evans 164a5f50ef9SJoerg Wunsch #else /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3 */ 165004bedebSBruce Evans 166004bedebSBruce Evans /* 1678089a043SBruce Evans * The following complications are to get around gcc not having a 1688089a043SBruce Evans * constraint letter for the range 0..255. We still put "d" in the 1698089a043SBruce Evans * constraint because "i" isn't a valid constraint when the port 1708089a043SBruce Evans * isn't constant. This only matters for -O0 because otherwise 1718089a043SBruce Evans * the non-working version gets optimized away. 1728089a043SBruce Evans * 173004bedebSBruce Evans * Use an expression-statement instead of a conditional expression 174004bedebSBruce Evans * because gcc-2.6.0 would promote the operands of the conditional 175004bedebSBruce Evans * and produce poor code for "if ((inb(var) & const1) == const2)". 176388dfa71SBruce Evans * 177388dfa71SBruce Evans * The unnecessary test `(port) < 0x10000' is to generate a warning if 178388dfa71SBruce Evans * the `port' has type u_short or smaller. Such types are pessimal. 179388dfa71SBruce Evans * This actually only works for signed types. The range check is 180388dfa71SBruce Evans * careful to avoid generating warnings. 181004bedebSBruce Evans */ 182388dfa71SBruce Evans #define inb(port) __extension__ ({ \ 183004bedebSBruce Evans u_char _data; \ 184388dfa71SBruce Evans if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 185388dfa71SBruce Evans && (port) < 0x10000) \ 186004bedebSBruce Evans _data = inbc(port); \ 187004bedebSBruce Evans else \ 188004bedebSBruce Evans _data = inbv(port); \ 189004bedebSBruce Evans _data; }) 190004bedebSBruce Evans 191388dfa71SBruce Evans #define outb(port, data) ( \ 192388dfa71SBruce Evans __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 193388dfa71SBruce Evans && (port) < 0x10000 \ 194004bedebSBruce Evans ? outbc(port, data) : outbv(port, data)) 195004bedebSBruce Evans 196004bedebSBruce Evans static __inline u_char 197004bedebSBruce Evans inbc(u_int port) 198004bedebSBruce Evans { 199004bedebSBruce Evans u_char data; 200004bedebSBruce Evans 2018089a043SBruce Evans __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); 202004bedebSBruce Evans return (data); 203004bedebSBruce Evans } 204004bedebSBruce Evans 205004bedebSBruce Evans static __inline void 206004bedebSBruce Evans outbc(u_int port, u_char data) 207004bedebSBruce Evans { 2088089a043SBruce Evans __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port))); 209004bedebSBruce Evans } 210004bedebSBruce Evans 211a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_BUILTIN_CONSTANT_P */ 212004bedebSBruce Evans 213004bedebSBruce Evans static __inline u_char 214004bedebSBruce Evans inbv(u_int port) 215004bedebSBruce Evans { 216004bedebSBruce Evans u_char data; 217004bedebSBruce Evans /* 218004bedebSBruce Evans * We use %%dx and not %1 here because i/o is done at %dx and not at 219004bedebSBruce Evans * %edx, while gcc generates inferior code (movw instead of movl) 220004bedebSBruce Evans * if we tell it to load (u_short) port. 221004bedebSBruce Evans */ 222004bedebSBruce Evans __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 223004bedebSBruce Evans return (data); 224004bedebSBruce Evans } 225004bedebSBruce Evans 22600be8601SBruce Evans static __inline u_int 227004bedebSBruce Evans inl(u_int port) 228004bedebSBruce Evans { 22900be8601SBruce Evans u_int data; 230004bedebSBruce Evans 231004bedebSBruce Evans __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); 232004bedebSBruce Evans return (data); 233004bedebSBruce Evans } 234004bedebSBruce Evans 235004bedebSBruce Evans static __inline void 236004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt) 237004bedebSBruce Evans { 238004bedebSBruce Evans __asm __volatile("cld; rep; insb" 2393f9a462fSJohn Baldwin : "+D" (addr), "+c" (cnt) 2403f9a462fSJohn Baldwin : "d" (port) 241896763faSBruce Evans : "memory"); 242004bedebSBruce Evans } 243004bedebSBruce Evans 244004bedebSBruce Evans static __inline void 245004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt) 246004bedebSBruce Evans { 247004bedebSBruce Evans __asm __volatile("cld; rep; insw" 2483f9a462fSJohn Baldwin : "+D" (addr), "+c" (cnt) 2493f9a462fSJohn Baldwin : "d" (port) 250896763faSBruce Evans : "memory"); 251004bedebSBruce Evans } 252004bedebSBruce Evans 253004bedebSBruce Evans static __inline void 254004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt) 255004bedebSBruce Evans { 256004bedebSBruce Evans __asm __volatile("cld; rep; insl" 2573f9a462fSJohn Baldwin : "+D" (addr), "+c" (cnt) 2583f9a462fSJohn Baldwin : "d" (port) 259896763faSBruce Evans : "memory"); 260004bedebSBruce Evans } 261004bedebSBruce Evans 262ece15d78SBruce Evans static __inline void 2634c024bbdSKATO Takenori invd(void) 2644c024bbdSKATO Takenori { 2654c024bbdSKATO Takenori __asm __volatile("invd"); 2664c024bbdSKATO Takenori } 2674c024bbdSKATO Takenori 268004bedebSBruce Evans static __inline u_short 269004bedebSBruce Evans inw(u_int port) 270004bedebSBruce Evans { 271004bedebSBruce Evans u_short data; 272004bedebSBruce Evans 273004bedebSBruce Evans __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port)); 274004bedebSBruce Evans return (data); 275004bedebSBruce Evans } 276004bedebSBruce Evans 277004bedebSBruce Evans static __inline void 278004bedebSBruce Evans outbv(u_int port, u_char data) 279004bedebSBruce Evans { 280004bedebSBruce Evans u_char al; 281004bedebSBruce Evans /* 282004bedebSBruce Evans * Use an unnecessary assignment to help gcc's register allocator. 283004bedebSBruce Evans * This make a large difference for gcc-1.40 and a tiny difference 284004bedebSBruce Evans * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for 285004bedebSBruce Evans * best results. gcc-2.6.0 can't handle this. 286004bedebSBruce Evans */ 287004bedebSBruce Evans al = data; 288004bedebSBruce Evans __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 289004bedebSBruce Evans } 290004bedebSBruce Evans 291004bedebSBruce Evans static __inline void 29200be8601SBruce Evans outl(u_int port, u_int data) 293004bedebSBruce Evans { 294004bedebSBruce Evans /* 295004bedebSBruce Evans * outl() and outw() aren't used much so we haven't looked at 296004bedebSBruce Evans * possible micro-optimizations such as the unnecessary 297004bedebSBruce Evans * assignment for them. 298004bedebSBruce Evans */ 299004bedebSBruce Evans __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); 300004bedebSBruce Evans } 301004bedebSBruce Evans 302004bedebSBruce Evans static __inline void 303e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt) 304004bedebSBruce Evans { 305004bedebSBruce Evans __asm __volatile("cld; rep; outsb" 3063f9a462fSJohn Baldwin : "+S" (addr), "+c" (cnt) 3073f9a462fSJohn Baldwin : "d" (port)); 308004bedebSBruce Evans } 309004bedebSBruce Evans 310004bedebSBruce Evans static __inline void 311e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt) 312004bedebSBruce Evans { 313004bedebSBruce Evans __asm __volatile("cld; rep; outsw" 3143f9a462fSJohn Baldwin : "+S" (addr), "+c" (cnt) 3153f9a462fSJohn Baldwin : "d" (port)); 316004bedebSBruce Evans } 317004bedebSBruce Evans 318004bedebSBruce Evans static __inline void 319e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt) 320004bedebSBruce Evans { 321004bedebSBruce Evans __asm __volatile("cld; rep; outsl" 3223f9a462fSJohn Baldwin : "+S" (addr), "+c" (cnt) 3233f9a462fSJohn Baldwin : "d" (port)); 324004bedebSBruce Evans } 325004bedebSBruce Evans 326004bedebSBruce Evans static __inline void 327004bedebSBruce Evans outw(u_int port, u_short data) 328004bedebSBruce Evans { 329004bedebSBruce Evans __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port)); 330004bedebSBruce Evans } 331004bedebSBruce Evans 3322be69f32SJohn Baldwin static __inline void 3336b8c6989SJohn Baldwin ia32_pause(void) 3342be69f32SJohn Baldwin { 3352be69f32SJohn Baldwin __asm __volatile("pause"); 3362be69f32SJohn Baldwin } 3372be69f32SJohn Baldwin 338afa88623SPeter Wemm static __inline u_long 339afa88623SPeter Wemm read_rflags(void) 3405b81b6b3SRodney W. Grimes { 341afa88623SPeter Wemm u_long rf; 342004bedebSBruce Evans 343afa88623SPeter Wemm __asm __volatile("pushfq; popq %0" : "=r" (rf)); 344afa88623SPeter Wemm return (rf); 3455b81b6b3SRodney W. Grimes } 3465b81b6b3SRodney W. Grimes 34700be8601SBruce Evans static __inline u_int64_t 3485dbd168eSBruce Evans rdmsr(u_int msr) 3495dbd168eSBruce Evans { 350afa88623SPeter Wemm u_int32_t low, high; 3515dbd168eSBruce Evans 352afa88623SPeter Wemm __asm __volatile("rdmsr" : "=a" (low), "=d" (high) : "c" (msr)); 353afa88623SPeter Wemm return (low | ((u_int64_t)high << 32)); 3545dbd168eSBruce Evans } 3555dbd168eSBruce Evans 35600be8601SBruce Evans static __inline u_int64_t 3575dbd168eSBruce Evans rdpmc(u_int pmc) 3585dbd168eSBruce Evans { 359afa88623SPeter Wemm u_int32_t low, high; 3605dbd168eSBruce Evans 361afa88623SPeter Wemm __asm __volatile("rdpmc" : "=a" (low), "=d" (high) : "c" (pmc)); 362afa88623SPeter Wemm return (low | ((u_int64_t)high << 32)); 3635dbd168eSBruce Evans } 3645dbd168eSBruce Evans 36500be8601SBruce Evans static __inline u_int64_t 3665dbd168eSBruce Evans rdtsc(void) 3675dbd168eSBruce Evans { 368afa88623SPeter Wemm u_int32_t low, high; 3695dbd168eSBruce Evans 370afa88623SPeter Wemm __asm __volatile("rdtsc" : "=a" (low), "=d" (high)); 371afa88623SPeter Wemm return (low | ((u_int64_t)high << 32)); 3725dbd168eSBruce Evans } 3735dbd168eSBruce Evans 374004bedebSBruce Evans static __inline void 3754c024bbdSKATO Takenori wbinvd(void) 3764c024bbdSKATO Takenori { 3774c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3784c024bbdSKATO Takenori } 3794c024bbdSKATO Takenori 3804c024bbdSKATO Takenori static __inline void 381afa88623SPeter Wemm write_rflags(u_long rf) 3825b81b6b3SRodney W. Grimes { 383afa88623SPeter Wemm __asm __volatile("pushq %0; popfq" : : "r" (rf)); 3845b81b6b3SRodney W. Grimes } 3855b81b6b3SRodney W. Grimes 386d69e8502SGarrett Wollman static __inline void 38700be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval) 388d69e8502SGarrett Wollman { 389afa88623SPeter Wemm u_int32_t low, high; 390afa88623SPeter Wemm 391afa88623SPeter Wemm low = newval; 392afa88623SPeter Wemm high = newval >> 32; 393afa88623SPeter Wemm __asm __volatile("wrmsr" : : "a" (low), "d" (high), "c" (msr)); 394d69e8502SGarrett Wollman } 395d69e8502SGarrett Wollman 396f1b665c8SPeter Wemm static __inline void 397afa88623SPeter Wemm load_cr0(u_long data) 398f1b665c8SPeter Wemm { 399f1b665c8SPeter Wemm 400afa88623SPeter Wemm __asm __volatile("movq %0,%%cr0" : : "r" (data)); 401f1b665c8SPeter Wemm } 402f1b665c8SPeter Wemm 403afa88623SPeter Wemm static __inline u_long 404f1b665c8SPeter Wemm rcr0(void) 405f1b665c8SPeter Wemm { 406afa88623SPeter Wemm u_long data; 407f1b665c8SPeter Wemm 408afa88623SPeter Wemm __asm __volatile("movq %%cr0,%0" : "=r" (data)); 409f1b665c8SPeter Wemm return (data); 410f1b665c8SPeter Wemm } 411f1b665c8SPeter Wemm 412afa88623SPeter Wemm static __inline u_long 413f1b665c8SPeter Wemm rcr2(void) 414f1b665c8SPeter Wemm { 415afa88623SPeter Wemm u_long data; 416f1b665c8SPeter Wemm 417afa88623SPeter Wemm __asm __volatile("movq %%cr2,%0" : "=r" (data)); 418f1b665c8SPeter Wemm return (data); 419f1b665c8SPeter Wemm } 420f1b665c8SPeter Wemm 421f1b665c8SPeter Wemm static __inline void 422afa88623SPeter Wemm load_cr3(u_long data) 423f1b665c8SPeter Wemm { 424f1b665c8SPeter Wemm 425afa88623SPeter Wemm __asm __volatile("movq %0,%%cr3" : : "r" (data) : "memory"); 426f1b665c8SPeter Wemm } 427f1b665c8SPeter Wemm 428afa88623SPeter Wemm static __inline u_long 429f1b665c8SPeter Wemm rcr3(void) 430f1b665c8SPeter Wemm { 431afa88623SPeter Wemm u_long data; 432f1b665c8SPeter Wemm 433afa88623SPeter Wemm __asm __volatile("movq %%cr3,%0" : "=r" (data)); 434f1b665c8SPeter Wemm return (data); 435f1b665c8SPeter Wemm } 436f1b665c8SPeter Wemm 437f1b665c8SPeter Wemm static __inline void 438afa88623SPeter Wemm load_cr4(u_long data) 439f1b665c8SPeter Wemm { 440afa88623SPeter Wemm __asm __volatile("movq %0,%%cr4" : : "r" (data)); 441f1b665c8SPeter Wemm } 442f1b665c8SPeter Wemm 443afa88623SPeter Wemm static __inline u_long 444f1b665c8SPeter Wemm rcr4(void) 445f1b665c8SPeter Wemm { 446afa88623SPeter Wemm u_long data; 447f1b665c8SPeter Wemm 448afa88623SPeter Wemm __asm __volatile("movq %%cr4,%0" : "=r" (data)); 449f1b665c8SPeter Wemm return (data); 450f1b665c8SPeter Wemm } 451f1b665c8SPeter Wemm 452f1b665c8SPeter Wemm /* 453f1b665c8SPeter Wemm * Global TLB flush (except for thise for pages marked PG_G) 454f1b665c8SPeter Wemm */ 455f1b665c8SPeter Wemm static __inline void 456f1b665c8SPeter Wemm invltlb(void) 457f1b665c8SPeter Wemm { 458f1b665c8SPeter Wemm 459f1b665c8SPeter Wemm load_cr3(rcr3()); 460f1b665c8SPeter Wemm } 461f1b665c8SPeter Wemm 462f1b665c8SPeter Wemm /* 463f1b665c8SPeter Wemm * TLB flush for an individual page (even if it has PG_G). 464f1b665c8SPeter Wemm * Only works on 486+ CPUs (i386 does not have PG_G). 465f1b665c8SPeter Wemm */ 466f1b665c8SPeter Wemm static __inline void 467afa88623SPeter Wemm invlpg(u_long addr) 468f1b665c8SPeter Wemm { 469f1b665c8SPeter Wemm 470f1b665c8SPeter Wemm __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 471f1b665c8SPeter Wemm } 472f1b665c8SPeter Wemm 4735206bca1SLuoqi Chen static __inline u_int 4745206bca1SLuoqi Chen rfs(void) 4755206bca1SLuoqi Chen { 476d1fc2022SDavid Xu u_int sel; 477d1fc2022SDavid Xu __asm __volatile("movl %%fs,%0" : "=rm" (sel)); 4785206bca1SLuoqi Chen return (sel); 4795206bca1SLuoqi Chen } 4805206bca1SLuoqi Chen 4815206bca1SLuoqi Chen static __inline u_int 4825206bca1SLuoqi Chen rgs(void) 4835206bca1SLuoqi Chen { 484d1fc2022SDavid Xu u_int sel; 485d1fc2022SDavid Xu __asm __volatile("movl %%gs,%0" : "=rm" (sel)); 4865206bca1SLuoqi Chen return (sel); 4875206bca1SLuoqi Chen } 4885206bca1SLuoqi Chen 489cd0149e3SPeter Wemm static __inline u_int 490cd0149e3SPeter Wemm rss(void) 491cd0149e3SPeter Wemm { 492cd0149e3SPeter Wemm u_int sel; 493cd0149e3SPeter Wemm __asm __volatile("movl %%ss,%0" : "=rm" (sel)); 494cd0149e3SPeter Wemm return (sel); 495cd0149e3SPeter Wemm } 496cd0149e3SPeter Wemm 4975206bca1SLuoqi Chen static __inline void 498d85631c4SPeter Wemm load_ds(u_int sel) 499d85631c4SPeter Wemm { 500d85631c4SPeter Wemm __asm __volatile("movl %0,%%ds" : : "rm" (sel)); 501d85631c4SPeter Wemm } 502d85631c4SPeter Wemm 503d85631c4SPeter Wemm static __inline void 504d85631c4SPeter Wemm load_es(u_int sel) 505d85631c4SPeter Wemm { 506d85631c4SPeter Wemm __asm __volatile("movl %0,%%es" : : "rm" (sel)); 507d85631c4SPeter Wemm } 508d85631c4SPeter Wemm 509c0a54ff6SPeter Wemm #ifdef _KERNEL 510c0a54ff6SPeter Wemm /* This is defined in <machine/specialreg.h> but is too painful to get to */ 511c0a54ff6SPeter Wemm #ifndef MSR_FSBASE 512c0a54ff6SPeter Wemm #define MSR_FSBASE 0xc0000100 513c0a54ff6SPeter Wemm #endif 514c0a54ff6SPeter Wemm static __inline void 515c0a54ff6SPeter Wemm load_fs(u_int sel) 516c0a54ff6SPeter Wemm { 517c0a54ff6SPeter Wemm register u_int32_t fsbase __asm("ecx"); 518c0a54ff6SPeter Wemm 519c0a54ff6SPeter Wemm /* Preserve the fsbase value across the selector load */ 520c0a54ff6SPeter Wemm fsbase = MSR_FSBASE; 521c0a54ff6SPeter Wemm __asm __volatile("rdmsr; movl %0,%%fs; wrmsr" 522c0a54ff6SPeter Wemm : : "rm" (sel), "c" (fsbase) : "eax", "edx"); 523c0a54ff6SPeter Wemm } 524c0a54ff6SPeter Wemm 525c0a54ff6SPeter Wemm #ifndef MSR_GSBASE 526c0a54ff6SPeter Wemm #define MSR_GSBASE 0xc0000101 527c0a54ff6SPeter Wemm #endif 528c0a54ff6SPeter Wemm static __inline void 529c0a54ff6SPeter Wemm load_gs(u_int sel) 530c0a54ff6SPeter Wemm { 531c0a54ff6SPeter Wemm register u_int32_t gsbase __asm("ecx"); 532c0a54ff6SPeter Wemm 533c0a54ff6SPeter Wemm /* 534c0a54ff6SPeter Wemm * Preserve the gsbase value across the selector load. 535c0a54ff6SPeter Wemm * Note that we have to disable interrupts because the gsbase 536c0a54ff6SPeter Wemm * being trashed happens to be the kernel gsbase at the time. 537c0a54ff6SPeter Wemm */ 538c0a54ff6SPeter Wemm gsbase = MSR_GSBASE; 539c0a54ff6SPeter Wemm __asm __volatile("pushfq; cli; rdmsr; movl %0,%%gs; wrmsr; popfq" 540c0a54ff6SPeter Wemm : : "rm" (sel), "c" (gsbase) : "eax", "edx"); 541c0a54ff6SPeter Wemm } 542c0a54ff6SPeter Wemm #else 543c0a54ff6SPeter Wemm /* Usable by userland */ 544d85631c4SPeter Wemm static __inline void 5455206bca1SLuoqi Chen load_fs(u_int sel) 5465206bca1SLuoqi Chen { 547e870e9b2SLuoqi Chen __asm __volatile("movl %0,%%fs" : : "rm" (sel)); 5485206bca1SLuoqi Chen } 5495206bca1SLuoqi Chen 5505206bca1SLuoqi Chen static __inline void 5515206bca1SLuoqi Chen load_gs(u_int sel) 5525206bca1SLuoqi Chen { 553e870e9b2SLuoqi Chen __asm __volatile("movl %0,%%gs" : : "rm" (sel)); 5545206bca1SLuoqi Chen } 555c0a54ff6SPeter Wemm #endif 5565206bca1SLuoqi Chen 557eb1443c8SPeter Wemm static __inline void 558eb1443c8SPeter Wemm lidt(struct region_descriptor *addr) 559eb1443c8SPeter Wemm { 560eb1443c8SPeter Wemm __asm __volatile("lidt (%0)" : : "r" (addr)); 561eb1443c8SPeter Wemm } 562eb1443c8SPeter Wemm 563eb1443c8SPeter Wemm static __inline void 564eb1443c8SPeter Wemm lldt(u_short sel) 565eb1443c8SPeter Wemm { 566eb1443c8SPeter Wemm __asm __volatile("lldt %0" : : "r" (sel)); 567eb1443c8SPeter Wemm } 568eb1443c8SPeter Wemm 569eb1443c8SPeter Wemm static __inline void 570eb1443c8SPeter Wemm ltr(u_short sel) 571eb1443c8SPeter Wemm { 572eb1443c8SPeter Wemm __asm __volatile("ltr %0" : : "r" (sel)); 573eb1443c8SPeter Wemm } 574eb1443c8SPeter Wemm 5751182b177SPeter Wemm static __inline u_int64_t 5761182b177SPeter Wemm rdr0(void) 5771182b177SPeter Wemm { 5781182b177SPeter Wemm u_int64_t data; 5791182b177SPeter Wemm __asm __volatile("movq %%dr0,%0" : "=r" (data)); 5801182b177SPeter Wemm return (data); 5811182b177SPeter Wemm } 5821182b177SPeter Wemm 5831182b177SPeter Wemm static __inline void 5841182b177SPeter Wemm load_dr0(u_int64_t dr0) 5851182b177SPeter Wemm { 5861182b177SPeter Wemm __asm __volatile("movq %0,%%dr0" : : "r" (dr0)); 5871182b177SPeter Wemm } 5881182b177SPeter Wemm 5891182b177SPeter Wemm static __inline u_int64_t 5901182b177SPeter Wemm rdr1(void) 5911182b177SPeter Wemm { 5921182b177SPeter Wemm u_int64_t data; 5931182b177SPeter Wemm __asm __volatile("movq %%dr1,%0" : "=r" (data)); 5941182b177SPeter Wemm return (data); 5951182b177SPeter Wemm } 5961182b177SPeter Wemm 5971182b177SPeter Wemm static __inline void 5981182b177SPeter Wemm load_dr1(u_int64_t dr1) 5991182b177SPeter Wemm { 6001182b177SPeter Wemm __asm __volatile("movq %0,%%dr1" : : "r" (dr1)); 6011182b177SPeter Wemm } 6021182b177SPeter Wemm 6031182b177SPeter Wemm static __inline u_int64_t 6041182b177SPeter Wemm rdr2(void) 6051182b177SPeter Wemm { 6061182b177SPeter Wemm u_int64_t data; 6071182b177SPeter Wemm __asm __volatile("movq %%dr2,%0" : "=r" (data)); 6081182b177SPeter Wemm return (data); 6091182b177SPeter Wemm } 6101182b177SPeter Wemm 6111182b177SPeter Wemm static __inline void 6121182b177SPeter Wemm load_dr2(u_int64_t dr2) 6131182b177SPeter Wemm { 6141182b177SPeter Wemm __asm __volatile("movq %0,%%dr2" : : "r" (dr2)); 6151182b177SPeter Wemm } 6161182b177SPeter Wemm 6171182b177SPeter Wemm static __inline u_int64_t 6181182b177SPeter Wemm rdr3(void) 6191182b177SPeter Wemm { 6201182b177SPeter Wemm u_int64_t data; 6211182b177SPeter Wemm __asm __volatile("movq %%dr3,%0" : "=r" (data)); 6221182b177SPeter Wemm return (data); 6231182b177SPeter Wemm } 6241182b177SPeter Wemm 6251182b177SPeter Wemm static __inline void 6261182b177SPeter Wemm load_dr3(u_int64_t dr3) 6271182b177SPeter Wemm { 6281182b177SPeter Wemm __asm __volatile("movq %0,%%dr3" : : "r" (dr3)); 6291182b177SPeter Wemm } 6301182b177SPeter Wemm 6311182b177SPeter Wemm static __inline u_int64_t 6321182b177SPeter Wemm rdr4(void) 6331182b177SPeter Wemm { 6341182b177SPeter Wemm u_int64_t data; 6351182b177SPeter Wemm __asm __volatile("movq %%dr4,%0" : "=r" (data)); 6361182b177SPeter Wemm return (data); 6371182b177SPeter Wemm } 6381182b177SPeter Wemm 6391182b177SPeter Wemm static __inline void 6401182b177SPeter Wemm load_dr4(u_int64_t dr4) 6411182b177SPeter Wemm { 6421182b177SPeter Wemm __asm __volatile("movq %0,%%dr4" : : "r" (dr4)); 6431182b177SPeter Wemm } 6441182b177SPeter Wemm 6451182b177SPeter Wemm static __inline u_int64_t 6461182b177SPeter Wemm rdr5(void) 6471182b177SPeter Wemm { 6481182b177SPeter Wemm u_int64_t data; 6491182b177SPeter Wemm __asm __volatile("movq %%dr5,%0" : "=r" (data)); 6501182b177SPeter Wemm return (data); 6511182b177SPeter Wemm } 6521182b177SPeter Wemm 6531182b177SPeter Wemm static __inline void 6541182b177SPeter Wemm load_dr5(u_int64_t dr5) 6551182b177SPeter Wemm { 6561182b177SPeter Wemm __asm __volatile("movq %0,%%dr5" : : "r" (dr5)); 6571182b177SPeter Wemm } 6581182b177SPeter Wemm 6591182b177SPeter Wemm static __inline u_int64_t 6601182b177SPeter Wemm rdr6(void) 6611182b177SPeter Wemm { 6621182b177SPeter Wemm u_int64_t data; 6631182b177SPeter Wemm __asm __volatile("movq %%dr6,%0" : "=r" (data)); 6641182b177SPeter Wemm return (data); 6651182b177SPeter Wemm } 6661182b177SPeter Wemm 6671182b177SPeter Wemm static __inline void 6681182b177SPeter Wemm load_dr6(u_int64_t dr6) 6691182b177SPeter Wemm { 6701182b177SPeter Wemm __asm __volatile("movq %0,%%dr6" : : "r" (dr6)); 6711182b177SPeter Wemm } 6721182b177SPeter Wemm 6731182b177SPeter Wemm static __inline u_int64_t 6741182b177SPeter Wemm rdr7(void) 6751182b177SPeter Wemm { 6761182b177SPeter Wemm u_int64_t data; 6771182b177SPeter Wemm __asm __volatile("movq %%dr7,%0" : "=r" (data)); 6781182b177SPeter Wemm return (data); 6791182b177SPeter Wemm } 6801182b177SPeter Wemm 6811182b177SPeter Wemm static __inline void 6821182b177SPeter Wemm load_dr7(u_int64_t dr7) 6831182b177SPeter Wemm { 6841182b177SPeter Wemm __asm __volatile("movq %0,%%dr7" : : "r" (dr7)); 6851182b177SPeter Wemm } 6861182b177SPeter Wemm 687ba74981eSWarner Losh static __inline register_t 688ba74981eSWarner Losh intr_disable(void) 689ba74981eSWarner Losh { 690afa88623SPeter Wemm register_t rflags; 691ba74981eSWarner Losh 692afa88623SPeter Wemm rflags = read_rflags(); 693ba74981eSWarner Losh disable_intr(); 694afa88623SPeter Wemm return (rflags); 695ba74981eSWarner Losh } 696ba74981eSWarner Losh 697ba74981eSWarner Losh static __inline void 698afa88623SPeter Wemm intr_restore(register_t rflags) 699ba74981eSWarner Losh { 700afa88623SPeter Wemm write_rflags(rflags); 701ba74981eSWarner Losh } 702ba74981eSWarner Losh 703a5f50ef9SJoerg Wunsch #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 7045b81b6b3SRodney W. Grimes 705b63dc6adSAlfred Perlstein int breakpoint(void); 706b63dc6adSAlfred Perlstein u_int bsfl(u_int mask); 707b63dc6adSAlfred Perlstein u_int bsrl(u_int mask); 708b63dc6adSAlfred Perlstein void disable_intr(void); 709b63dc6adSAlfred Perlstein void do_cpuid(u_int ax, u_int *p); 710b63dc6adSAlfred Perlstein void enable_intr(void); 711d7ee4425SMark Murray void halt(void); 7124f6c19e5SPeter Wemm void ia32_pause(void); 713b63dc6adSAlfred Perlstein u_char inb(u_int port); 714b63dc6adSAlfred Perlstein u_int inl(u_int port); 715b63dc6adSAlfred Perlstein void insb(u_int port, void *addr, size_t cnt); 716b63dc6adSAlfred Perlstein void insl(u_int port, void *addr, size_t cnt); 717b63dc6adSAlfred Perlstein void insw(u_int port, void *addr, size_t cnt); 7184f6c19e5SPeter Wemm register_t intr_disable(void); 7194f6c19e5SPeter Wemm void intr_restore(register_t rf); 720b63dc6adSAlfred Perlstein void invd(void); 721b63dc6adSAlfred Perlstein void invlpg(u_int addr); 722b63dc6adSAlfred Perlstein void invltlb(void); 723b63dc6adSAlfred Perlstein u_short inw(u_int port); 724eb1443c8SPeter Wemm void lidt(struct region_descriptor *addr); 725eb1443c8SPeter Wemm void lldt(u_short sel); 7264f6c19e5SPeter Wemm void load_cr0(u_long cr0); 7274f6c19e5SPeter Wemm void load_cr3(u_long cr3); 7284f6c19e5SPeter Wemm void load_cr4(u_long cr4); 7294f6c19e5SPeter Wemm void load_dr0(u_int64_t dr0); 7304f6c19e5SPeter Wemm void load_dr1(u_int64_t dr1); 7314f6c19e5SPeter Wemm void load_dr2(u_int64_t dr2); 7324f6c19e5SPeter Wemm void load_dr3(u_int64_t dr3); 7334f6c19e5SPeter Wemm void load_dr4(u_int64_t dr4); 7344f6c19e5SPeter Wemm void load_dr5(u_int64_t dr5); 7354f6c19e5SPeter Wemm void load_dr6(u_int64_t dr6); 7364f6c19e5SPeter Wemm void load_dr7(u_int64_t dr7); 7374f6c19e5SPeter Wemm void load_fs(u_int sel); 7384f6c19e5SPeter Wemm void load_gs(u_int sel); 739eb1443c8SPeter Wemm void ltr(u_short sel); 740b63dc6adSAlfred Perlstein void outb(u_int port, u_char data); 741b63dc6adSAlfred Perlstein void outl(u_int port, u_int data); 7421bcf24eeSLukas Ertl void outsb(u_int port, const void *addr, size_t cnt); 7431bcf24eeSLukas Ertl void outsl(u_int port, const void *addr, size_t cnt); 7441bcf24eeSLukas Ertl void outsw(u_int port, const void *addr, size_t cnt); 745b63dc6adSAlfred Perlstein void outw(u_int port, u_short data); 7464f6c19e5SPeter Wemm u_long rcr0(void); 7474f6c19e5SPeter Wemm u_long rcr2(void); 7484f6c19e5SPeter Wemm u_long rcr3(void); 7494f6c19e5SPeter Wemm u_long rcr4(void); 750b63dc6adSAlfred Perlstein u_int64_t rdmsr(u_int msr); 751b63dc6adSAlfred Perlstein u_int64_t rdpmc(u_int pmc); 7524f6c19e5SPeter Wemm u_int64_t rdr0(void); 7534f6c19e5SPeter Wemm u_int64_t rdr1(void); 7544f6c19e5SPeter Wemm u_int64_t rdr2(void); 7554f6c19e5SPeter Wemm u_int64_t rdr3(void); 7564f6c19e5SPeter Wemm u_int64_t rdr4(void); 7574f6c19e5SPeter Wemm u_int64_t rdr5(void); 7584f6c19e5SPeter Wemm u_int64_t rdr6(void); 7594f6c19e5SPeter Wemm u_int64_t rdr7(void); 760b63dc6adSAlfred Perlstein u_int64_t rdtsc(void); 761afa88623SPeter Wemm u_int read_rflags(void); 7624f6c19e5SPeter Wemm u_int rfs(void); 7634f6c19e5SPeter Wemm u_int rgs(void); 764b63dc6adSAlfred Perlstein void wbinvd(void); 765afa88623SPeter Wemm void write_rflags(u_int rf); 766b63dc6adSAlfred Perlstein void wrmsr(u_int msr, u_int64_t newval); 767004bedebSBruce Evans 768a5f50ef9SJoerg Wunsch #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 7695b81b6b3SRodney W. Grimes 770b63dc6adSAlfred Perlstein void reset_dbregs(void); 771d74ac681SMatthew Dillon 772004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 773