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. 385b81b6b3SRodney W. Grimes */ 395b81b6b3SRodney W. Grimes 406e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_ 41004bedebSBruce Evans #define _MACHINE_CPUFUNC_H_ 426e393973SGarrett Wollman 43e31fa854SDoug Rabson #define readb(va) (*(volatile u_int8_t *) (va)) 44e31fa854SDoug Rabson #define readw(va) (*(volatile u_int16_t *) (va)) 45e31fa854SDoug Rabson #define readl(va) (*(volatile u_int32_t *) (va)) 46e31fa854SDoug Rabson 47e31fa854SDoug Rabson #define writeb(va, d) (*(volatile u_int8_t *) (va) = (d)) 48e31fa854SDoug Rabson #define writew(va, d) (*(volatile u_int16_t *) (va) = (d)) 49e31fa854SDoug Rabson #define writel(va, d) (*(volatile u_int32_t *) (va) = (d)) 50e31fa854SDoug Rabson 515b81b6b3SRodney W. Grimes #ifdef __GNUC__ 525b81b6b3SRodney W. Grimes 532a32c15fSBruce Evans #ifdef SWTCH_OPTIM_STATS 542a32c15fSBruce Evans extern int tlb_flush_count; /* XXX */ 552a32c15fSBruce Evans #endif 562a32c15fSBruce Evans 575dbd168eSBruce Evans static __inline void 585dbd168eSBruce Evans breakpoint(void) 59004bedebSBruce Evans { 60004bedebSBruce Evans __asm __volatile("int $3"); 615b81b6b3SRodney W. Grimes } 625b81b6b3SRodney W. Grimes 63c83b1328SBruce Evans static __inline u_int 64c83b1328SBruce Evans bsfl(u_int mask) 65c83b1328SBruce Evans { 66c83b1328SBruce Evans u_int result; 67c83b1328SBruce Evans 68c83b1328SBruce Evans __asm __volatile("bsfl %0,%0" : "=r" (result) : "0" (mask)); 69c83b1328SBruce Evans return (result); 70c83b1328SBruce Evans } 71c83b1328SBruce Evans 72c83b1328SBruce Evans static __inline u_int 73c83b1328SBruce Evans bsrl(u_int mask) 74c83b1328SBruce Evans { 75c83b1328SBruce Evans u_int result; 76c83b1328SBruce Evans 77c83b1328SBruce Evans __asm __volatile("bsrl %0,%0" : "=r" (result) : "0" (mask)); 78c83b1328SBruce Evans return (result); 79c83b1328SBruce Evans } 80c83b1328SBruce Evans 81004bedebSBruce Evans static __inline void 825b81b6b3SRodney W. Grimes disable_intr(void) 835b81b6b3SRodney W. Grimes { 848966b85cSJohn Dyson __asm __volatile("cli" : : : "memory"); 855b81b6b3SRodney W. Grimes } 865b81b6b3SRodney W. Grimes 87004bedebSBruce Evans static __inline void 885b81b6b3SRodney W. Grimes enable_intr(void) 895b81b6b3SRodney W. Grimes { 90fadc51bdSBruce Evans __asm __volatile("sti"); 915b81b6b3SRodney W. Grimes } 925b81b6b3SRodney W. Grimes 93264c3d87SPeter Wemm #define HAVE_INLINE_FFS 94264c3d87SPeter Wemm 95264c3d87SPeter Wemm static __inline int 96264c3d87SPeter Wemm ffs(int mask) 97264c3d87SPeter Wemm { 98264c3d87SPeter Wemm /* 99004bedebSBruce Evans * Note that gcc-2's builtin ffs would be used if we didn't declare 100004bedebSBruce Evans * this inline or turn off the builtin. The builtin is faster but 101c83b1328SBruce Evans * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later 102c83b1328SBruce Evans * versions. 103004bedebSBruce Evans */ 104c83b1328SBruce Evans return (mask == 0 ? mask : bsfl((u_int)mask) + 1); 105004bedebSBruce Evans } 106004bedebSBruce Evans 10713f588f8SGarrett Wollman #define HAVE_INLINE_FLS 10813f588f8SGarrett Wollman 10913f588f8SGarrett Wollman static __inline int 11013f588f8SGarrett Wollman fls(int mask) 11113f588f8SGarrett Wollman { 112c83b1328SBruce Evans return (mask == 0 ? mask : bsrl((u_int)mask) + 1); 11313f588f8SGarrett Wollman } 11413f588f8SGarrett Wollman 115004bedebSBruce Evans #if __GNUC__ < 2 116004bedebSBruce Evans 117004bedebSBruce Evans #define inb(port) inbv(port) 118004bedebSBruce Evans #define outb(port, data) outbv(port, data) 119004bedebSBruce Evans 120004bedebSBruce Evans #else /* __GNUC >= 2 */ 121004bedebSBruce Evans 122004bedebSBruce Evans /* 1238089a043SBruce Evans * The following complications are to get around gcc not having a 1248089a043SBruce Evans * constraint letter for the range 0..255. We still put "d" in the 1258089a043SBruce Evans * constraint because "i" isn't a valid constraint when the port 1268089a043SBruce Evans * isn't constant. This only matters for -O0 because otherwise 1278089a043SBruce Evans * the non-working version gets optimized away. 1288089a043SBruce Evans * 129004bedebSBruce Evans * Use an expression-statement instead of a conditional expression 130004bedebSBruce Evans * because gcc-2.6.0 would promote the operands of the conditional 131004bedebSBruce Evans * and produce poor code for "if ((inb(var) & const1) == const2)". 132388dfa71SBruce Evans * 133388dfa71SBruce Evans * The unnecessary test `(port) < 0x10000' is to generate a warning if 134388dfa71SBruce Evans * the `port' has type u_short or smaller. Such types are pessimal. 135388dfa71SBruce Evans * This actually only works for signed types. The range check is 136388dfa71SBruce Evans * careful to avoid generating warnings. 137004bedebSBruce Evans */ 138388dfa71SBruce Evans #define inb(port) __extension__ ({ \ 139004bedebSBruce Evans u_char _data; \ 140388dfa71SBruce Evans if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 141388dfa71SBruce Evans && (port) < 0x10000) \ 142004bedebSBruce Evans _data = inbc(port); \ 143004bedebSBruce Evans else \ 144004bedebSBruce Evans _data = inbv(port); \ 145004bedebSBruce Evans _data; }) 146004bedebSBruce Evans 147388dfa71SBruce Evans #define outb(port, data) ( \ 148388dfa71SBruce Evans __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 149388dfa71SBruce Evans && (port) < 0x10000 \ 150004bedebSBruce Evans ? outbc(port, data) : outbv(port, data)) 151004bedebSBruce Evans 152004bedebSBruce Evans static __inline u_char 153004bedebSBruce Evans inbc(u_int port) 154004bedebSBruce Evans { 155004bedebSBruce Evans u_char data; 156004bedebSBruce Evans 1578089a043SBruce Evans __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); 158004bedebSBruce Evans return (data); 159004bedebSBruce Evans } 160004bedebSBruce Evans 161004bedebSBruce Evans static __inline void 162004bedebSBruce Evans outbc(u_int port, u_char data) 163004bedebSBruce Evans { 1648089a043SBruce Evans __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port))); 165004bedebSBruce Evans } 166004bedebSBruce Evans 167004bedebSBruce Evans #endif /* __GNUC <= 2 */ 168004bedebSBruce Evans 169004bedebSBruce Evans static __inline u_char 170004bedebSBruce Evans inbv(u_int port) 171004bedebSBruce Evans { 172004bedebSBruce Evans u_char data; 173004bedebSBruce Evans /* 174004bedebSBruce Evans * We use %%dx and not %1 here because i/o is done at %dx and not at 175004bedebSBruce Evans * %edx, while gcc generates inferior code (movw instead of movl) 176004bedebSBruce Evans * if we tell it to load (u_short) port. 177004bedebSBruce Evans */ 178004bedebSBruce Evans __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 179004bedebSBruce Evans return (data); 180004bedebSBruce Evans } 181004bedebSBruce Evans 18200be8601SBruce Evans static __inline u_int 183004bedebSBruce Evans inl(u_int port) 184004bedebSBruce Evans { 18500be8601SBruce Evans u_int data; 186004bedebSBruce Evans 187004bedebSBruce Evans __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); 188004bedebSBruce Evans return (data); 189004bedebSBruce Evans } 190004bedebSBruce Evans 191004bedebSBruce Evans static __inline void 192004bedebSBruce Evans insb(u_int port, void *addr, size_t cnt) 193004bedebSBruce Evans { 194004bedebSBruce Evans __asm __volatile("cld; rep; insb" 195896763faSBruce Evans : "=D" (addr), "=c" (cnt) 196896763faSBruce Evans : "0" (addr), "1" (cnt), "d" (port) 197896763faSBruce Evans : "memory"); 198004bedebSBruce Evans } 199004bedebSBruce Evans 200004bedebSBruce Evans static __inline void 201004bedebSBruce Evans insw(u_int port, void *addr, size_t cnt) 202004bedebSBruce Evans { 203004bedebSBruce Evans __asm __volatile("cld; rep; insw" 204896763faSBruce Evans : "=D" (addr), "=c" (cnt) 205896763faSBruce Evans : "0" (addr), "1" (cnt), "d" (port) 206896763faSBruce Evans : "memory"); 207004bedebSBruce Evans } 208004bedebSBruce Evans 209004bedebSBruce Evans static __inline void 210004bedebSBruce Evans insl(u_int port, void *addr, size_t cnt) 211004bedebSBruce Evans { 212004bedebSBruce Evans __asm __volatile("cld; rep; insl" 213896763faSBruce Evans : "=D" (addr), "=c" (cnt) 214896763faSBruce Evans : "0" (addr), "1" (cnt), "d" (port) 215896763faSBruce Evans : "memory"); 216004bedebSBruce Evans } 217004bedebSBruce Evans 218ece15d78SBruce Evans static __inline void 2194c024bbdSKATO Takenori invd(void) 2204c024bbdSKATO Takenori { 2214c024bbdSKATO Takenori __asm __volatile("invd"); 2224c024bbdSKATO Takenori } 2234c024bbdSKATO Takenori 224664a31e4SPeter Wemm #if defined(SMP) && defined(_KERNEL) 225477a642cSPeter Wemm 226477a642cSPeter Wemm /* 227f48bbd5fSBruce Evans * When using APIC IPI's, invlpg() is not simply the invlpg instruction 228f48bbd5fSBruce Evans * (this is a bug) and the inlining cost is prohibitive since the call 229f40e6078SPeter Wemm * executes into the IPI transmission system. 230477a642cSPeter Wemm */ 231477a642cSPeter Wemm void invlpg __P((u_int addr)); 232477a642cSPeter Wemm void invltlb __P((void)); 233477a642cSPeter Wemm 2345498a452SJohn Dyson static __inline void 2355498a452SJohn Dyson cpu_invlpg(void *addr) 2365498a452SJohn Dyson { 2375498a452SJohn Dyson __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 2385498a452SJohn Dyson } 2395498a452SJohn Dyson 2405931a9c2STor Egge static __inline void 2415931a9c2STor Egge cpu_invltlb(void) 2425931a9c2STor Egge { 24300be8601SBruce Evans u_int temp; 2445931a9c2STor Egge /* 2455931a9c2STor Egge * This should be implemented as load_cr3(rcr3()) when load_cr3() 2465931a9c2STor Egge * is inlined. 2475931a9c2STor Egge */ 2485931a9c2STor Egge __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp) 2495931a9c2STor Egge : : "memory"); 2505931a9c2STor Egge #if defined(SWTCH_OPTIM_STATS) 2515931a9c2STor Egge ++tlb_flush_count; 2525931a9c2STor Egge #endif 2535931a9c2STor Egge } 254f48bbd5fSBruce Evans 255664a31e4SPeter Wemm #else /* !(SMP && _KERNEL) */ 256477a642cSPeter Wemm 2574c024bbdSKATO Takenori static __inline void 258471176aaSJohn Dyson invlpg(u_int addr) 259ece15d78SBruce Evans { 2605498a452SJohn Dyson __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 261ece15d78SBruce Evans } 262ece15d78SBruce Evans 263ece15d78SBruce Evans static __inline void 264ece15d78SBruce Evans invltlb(void) 265ece15d78SBruce Evans { 26600be8601SBruce Evans u_int temp; 267ece15d78SBruce Evans /* 268ece15d78SBruce Evans * This should be implemented as load_cr3(rcr3()) when load_cr3() 269ece15d78SBruce Evans * is inlined. 270ece15d78SBruce Evans */ 271ece15d78SBruce Evans __asm __volatile("movl %%cr3, %0; movl %0, %%cr3" : "=r" (temp) 272ece15d78SBruce Evans : : "memory"); 273f48bbd5fSBruce Evans #ifdef SWTCH_OPTIM_STATS 27482566551SJohn Dyson ++tlb_flush_count; 27582566551SJohn Dyson #endif 276ece15d78SBruce Evans } 2772c5d02ffSSteve Passe 278664a31e4SPeter Wemm #endif /* SMP && _KERNEL */ 279ece15d78SBruce Evans 280004bedebSBruce Evans static __inline u_short 281004bedebSBruce Evans inw(u_int port) 282004bedebSBruce Evans { 283004bedebSBruce Evans u_short data; 284004bedebSBruce Evans 285004bedebSBruce Evans __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port)); 286004bedebSBruce Evans return (data); 287004bedebSBruce Evans } 288004bedebSBruce Evans 289004bedebSBruce Evans static __inline void 290004bedebSBruce Evans outbv(u_int port, u_char data) 291004bedebSBruce Evans { 292004bedebSBruce Evans u_char al; 293004bedebSBruce Evans /* 294004bedebSBruce Evans * Use an unnecessary assignment to help gcc's register allocator. 295004bedebSBruce Evans * This make a large difference for gcc-1.40 and a tiny difference 296004bedebSBruce Evans * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for 297004bedebSBruce Evans * best results. gcc-2.6.0 can't handle this. 298004bedebSBruce Evans */ 299004bedebSBruce Evans al = data; 300004bedebSBruce Evans __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 301004bedebSBruce Evans } 302004bedebSBruce Evans 303004bedebSBruce Evans static __inline void 30400be8601SBruce Evans outl(u_int port, u_int data) 305004bedebSBruce Evans { 306004bedebSBruce Evans /* 307004bedebSBruce Evans * outl() and outw() aren't used much so we haven't looked at 308004bedebSBruce Evans * possible micro-optimizations such as the unnecessary 309004bedebSBruce Evans * assignment for them. 310004bedebSBruce Evans */ 311004bedebSBruce Evans __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); 312004bedebSBruce Evans } 313004bedebSBruce Evans 314004bedebSBruce Evans static __inline void 315e1a1bba4SJustin T. Gibbs outsb(u_int port, const void *addr, size_t cnt) 316004bedebSBruce Evans { 317004bedebSBruce Evans __asm __volatile("cld; rep; outsb" 318896763faSBruce Evans : "=S" (addr), "=c" (cnt) 319896763faSBruce Evans : "0" (addr), "1" (cnt), "d" (port)); 320004bedebSBruce Evans } 321004bedebSBruce Evans 322004bedebSBruce Evans static __inline void 323e1a1bba4SJustin T. Gibbs outsw(u_int port, const void *addr, size_t cnt) 324004bedebSBruce Evans { 325004bedebSBruce Evans __asm __volatile("cld; rep; outsw" 326896763faSBruce Evans : "=S" (addr), "=c" (cnt) 327896763faSBruce Evans : "0" (addr), "1" (cnt), "d" (port)); 328004bedebSBruce Evans } 329004bedebSBruce Evans 330004bedebSBruce Evans static __inline void 331e1a1bba4SJustin T. Gibbs outsl(u_int port, const void *addr, size_t cnt) 332004bedebSBruce Evans { 333004bedebSBruce Evans __asm __volatile("cld; rep; outsl" 334896763faSBruce Evans : "=S" (addr), "=c" (cnt) 335896763faSBruce Evans : "0" (addr), "1" (cnt), "d" (port)); 336004bedebSBruce Evans } 337004bedebSBruce Evans 338004bedebSBruce Evans static __inline void 339004bedebSBruce Evans outw(u_int port, u_short data) 340004bedebSBruce Evans { 341004bedebSBruce Evans __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port)); 342004bedebSBruce Evans } 343004bedebSBruce Evans 34400be8601SBruce Evans static __inline u_int 345004bedebSBruce Evans rcr2(void) 346004bedebSBruce Evans { 34700be8601SBruce Evans u_int data; 348004bedebSBruce Evans 349004bedebSBruce Evans __asm __volatile("movl %%cr2,%0" : "=r" (data)); 350004bedebSBruce Evans return (data); 351004bedebSBruce Evans } 352004bedebSBruce Evans 35300be8601SBruce Evans static __inline u_int 354004bedebSBruce Evans read_eflags(void) 3555b81b6b3SRodney W. Grimes { 35600be8601SBruce Evans u_int ef; 357004bedebSBruce Evans 358004bedebSBruce Evans __asm __volatile("pushfl; popl %0" : "=r" (ef)); 3598db02de8SPaul Richards return (ef); 3605b81b6b3SRodney W. Grimes } 3615b81b6b3SRodney W. Grimes 36200be8601SBruce Evans static __inline u_int64_t 3635dbd168eSBruce Evans rdmsr(u_int msr) 3645dbd168eSBruce Evans { 36500be8601SBruce Evans u_int64_t rv; 3665dbd168eSBruce Evans 36739413503SMark Murray __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr)); 3685dbd168eSBruce Evans return (rv); 3695dbd168eSBruce Evans } 3705dbd168eSBruce Evans 37100be8601SBruce Evans static __inline u_int64_t 3725dbd168eSBruce Evans rdpmc(u_int pmc) 3735dbd168eSBruce Evans { 37400be8601SBruce Evans u_int64_t rv; 3755dbd168eSBruce Evans 37639413503SMark Murray __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc)); 3775dbd168eSBruce Evans return (rv); 3785dbd168eSBruce Evans } 3795dbd168eSBruce Evans 38000be8601SBruce Evans static __inline u_int64_t 3815dbd168eSBruce Evans rdtsc(void) 3825dbd168eSBruce Evans { 38300be8601SBruce Evans u_int64_t rv; 3845dbd168eSBruce Evans 38539413503SMark Murray __asm __volatile("rdtsc" : "=A" (rv)); 3865dbd168eSBruce Evans return (rv); 3875dbd168eSBruce Evans } 3885dbd168eSBruce Evans 389004bedebSBruce Evans static __inline void 3904c024bbdSKATO Takenori wbinvd(void) 3914c024bbdSKATO Takenori { 3924c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3934c024bbdSKATO Takenori } 3944c024bbdSKATO Takenori 3954c024bbdSKATO Takenori static __inline void 39600be8601SBruce Evans write_eflags(u_int ef) 3975b81b6b3SRodney W. Grimes { 398004bedebSBruce Evans __asm __volatile("pushl %0; popfl" : : "r" (ef)); 3995b81b6b3SRodney W. Grimes } 4005b81b6b3SRodney W. Grimes 401d69e8502SGarrett Wollman static __inline void 40200be8601SBruce Evans wrmsr(u_int msr, u_int64_t newval) 403d69e8502SGarrett Wollman { 40439413503SMark Murray __asm __volatile("wrmsr" : : "A" (newval), "c" (msr)); 405d69e8502SGarrett Wollman } 406d69e8502SGarrett Wollman 4075206bca1SLuoqi Chen static __inline u_int 4085206bca1SLuoqi Chen rfs(void) 4095206bca1SLuoqi Chen { 4105206bca1SLuoqi Chen u_int sel; 411e870e9b2SLuoqi Chen __asm __volatile("movl %%fs,%0" : "=rm" (sel)); 4125206bca1SLuoqi Chen return (sel); 4135206bca1SLuoqi Chen } 4145206bca1SLuoqi Chen 4155206bca1SLuoqi Chen static __inline u_int 4165206bca1SLuoqi Chen rgs(void) 4175206bca1SLuoqi Chen { 4185206bca1SLuoqi Chen u_int sel; 419e870e9b2SLuoqi Chen __asm __volatile("movl %%gs,%0" : "=rm" (sel)); 4205206bca1SLuoqi Chen return (sel); 4215206bca1SLuoqi Chen } 4225206bca1SLuoqi Chen 4235206bca1SLuoqi Chen static __inline void 4245206bca1SLuoqi Chen load_fs(u_int sel) 4255206bca1SLuoqi Chen { 426e870e9b2SLuoqi Chen __asm __volatile("movl %0,%%fs" : : "rm" (sel)); 4275206bca1SLuoqi Chen } 4285206bca1SLuoqi Chen 4295206bca1SLuoqi Chen static __inline void 4305206bca1SLuoqi Chen load_gs(u_int sel) 4315206bca1SLuoqi Chen { 432e870e9b2SLuoqi Chen __asm __volatile("movl %0,%%gs" : : "rm" (sel)); 4335206bca1SLuoqi Chen } 4345206bca1SLuoqi Chen 435de8050f9SBrian S. Dean static __inline u_int 436de8050f9SBrian S. Dean rdr0(void) 437de8050f9SBrian S. Dean { 438de8050f9SBrian S. Dean u_int data; 43980275388SBrian S. Dean __asm __volatile("movl %%dr0,%0" : "=r" (data)); 440de8050f9SBrian S. Dean return (data); 441de8050f9SBrian S. Dean } 442de8050f9SBrian S. Dean 443de8050f9SBrian S. Dean static __inline u_int 444de8050f9SBrian S. Dean rdr1(void) 445de8050f9SBrian S. Dean { 446de8050f9SBrian S. Dean u_int data; 44780275388SBrian S. Dean __asm __volatile("movl %%dr1,%0" : "=r" (data)); 448de8050f9SBrian S. Dean return (data); 449de8050f9SBrian S. Dean } 450de8050f9SBrian S. Dean 451de8050f9SBrian S. Dean static __inline u_int 452de8050f9SBrian S. Dean rdr2(void) 453de8050f9SBrian S. Dean { 454de8050f9SBrian S. Dean u_int data; 45580275388SBrian S. Dean __asm __volatile("movl %%dr2,%0" : "=r" (data)); 456de8050f9SBrian S. Dean return (data); 457de8050f9SBrian S. Dean } 458de8050f9SBrian S. Dean 459de8050f9SBrian S. Dean static __inline u_int 460de8050f9SBrian S. Dean rdr3(void) 461de8050f9SBrian S. Dean { 462de8050f9SBrian S. Dean u_int data; 46380275388SBrian S. Dean __asm __volatile("movl %%dr3,%0" : "=r" (data)); 464de8050f9SBrian S. Dean return (data); 465de8050f9SBrian S. Dean } 466de8050f9SBrian S. Dean 467de8050f9SBrian S. Dean static __inline u_int 468de8050f9SBrian S. Dean rdr6(void) 469de8050f9SBrian S. Dean { 470de8050f9SBrian S. Dean u_int data; 47180275388SBrian S. Dean __asm __volatile("movl %%dr6,%0" : "=r" (data)); 472de8050f9SBrian S. Dean return (data); 473de8050f9SBrian S. Dean } 474de8050f9SBrian S. Dean 475de8050f9SBrian S. Dean static __inline u_int 476de8050f9SBrian S. Dean rdr7(void) 477de8050f9SBrian S. Dean { 478de8050f9SBrian S. Dean u_int data; 47980275388SBrian S. Dean __asm __volatile("movl %%dr7,%0" : "=r" (data)); 480de8050f9SBrian S. Dean return (data); 481de8050f9SBrian S. Dean } 482de8050f9SBrian S. Dean 483034dc442SJohn Baldwin static __inline critical_t 484034dc442SJohn Baldwin critical_enter(void) 485034dc442SJohn Baldwin { 486034dc442SJohn Baldwin critical_t eflags; 487034dc442SJohn Baldwin 488034dc442SJohn Baldwin eflags = read_eflags(); 489034dc442SJohn Baldwin disable_intr(); 490034dc442SJohn Baldwin return (eflags); 491034dc442SJohn Baldwin } 492034dc442SJohn Baldwin 493034dc442SJohn Baldwin static __inline void 494034dc442SJohn Baldwin critical_exit(critical_t eflags) 495034dc442SJohn Baldwin { 496034dc442SJohn Baldwin write_eflags(eflags); 497034dc442SJohn Baldwin } 498034dc442SJohn Baldwin 499004bedebSBruce Evans #else /* !__GNUC__ */ 5005b81b6b3SRodney W. Grimes 5015dbd168eSBruce Evans int breakpoint __P((void)); 502c83b1328SBruce Evans u_int bsfl __P((u_int mask)); 503c83b1328SBruce Evans u_int bsrl __P((u_int mask)); 5045b81b6b3SRodney W. Grimes void disable_intr __P((void)); 5055b81b6b3SRodney W. Grimes void enable_intr __P((void)); 5065b81b6b3SRodney W. Grimes u_char inb __P((u_int port)); 50700be8601SBruce Evans u_int inl __P((u_int port)); 508004bedebSBruce Evans void insb __P((u_int port, void *addr, size_t cnt)); 509004bedebSBruce Evans void insl __P((u_int port, void *addr, size_t cnt)); 510004bedebSBruce Evans void insw __P((u_int port, void *addr, size_t cnt)); 5114c024bbdSKATO Takenori void invd __P((void)); 512ece15d78SBruce Evans void invlpg __P((u_int addr)); 513ece15d78SBruce Evans void invltlb __P((void)); 514004bedebSBruce Evans u_short inw __P((u_int port)); 515004bedebSBruce Evans void outb __P((u_int port, u_char data)); 51600be8601SBruce Evans void outl __P((u_int port, u_int data)); 517004bedebSBruce Evans void outsb __P((u_int port, void *addr, size_t cnt)); 518004bedebSBruce Evans void outsl __P((u_int port, void *addr, size_t cnt)); 519004bedebSBruce Evans void outsw __P((u_int port, void *addr, size_t cnt)); 520004bedebSBruce Evans void outw __P((u_int port, u_short data)); 52100be8601SBruce Evans u_int rcr2 __P((void)); 52200be8601SBruce Evans u_int64_t rdmsr __P((u_int msr)); 52300be8601SBruce Evans u_int64_t rdpmc __P((u_int pmc)); 52400be8601SBruce Evans u_int64_t rdtsc __P((void)); 52500be8601SBruce Evans u_int read_eflags __P((void)); 5264c024bbdSKATO Takenori void wbinvd __P((void)); 52700be8601SBruce Evans void write_eflags __P((u_int ef)); 52800be8601SBruce Evans void wrmsr __P((u_int msr, u_int64_t newval)); 5295206bca1SLuoqi Chen u_int rfs __P((void)); 5305206bca1SLuoqi Chen u_int rgs __P((void)); 5315206bca1SLuoqi Chen void load_fs __P((u_int sel)); 5325206bca1SLuoqi Chen void load_gs __P((u_int sel)); 533034dc442SJohn Baldwin critical_t critical_enter __P((void)); 534034dc442SJohn Baldwin void critical_exit __P((critical_t eflags)); 535004bedebSBruce Evans 5365b81b6b3SRodney W. Grimes #endif /* __GNUC__ */ 5375b81b6b3SRodney W. Grimes 53800be8601SBruce Evans void load_cr0 __P((u_int cr0)); 53900be8601SBruce Evans void load_cr3 __P((u_int cr3)); 54000be8601SBruce Evans void load_cr4 __P((u_int cr4)); 541004bedebSBruce Evans void ltr __P((u_short sel)); 542aaf08d94SGarrett Wollman u_int rcr0 __P((void)); 54300be8601SBruce Evans u_int rcr3 __P((void)); 54400be8601SBruce Evans u_int rcr4 __P((void)); 545de8050f9SBrian S. Dean void load_dr6 __P((u_int dr6)); 546de8050f9SBrian S. Dean void reset_dbregs __P((void)); 5475b81b6b3SRodney W. Grimes 548004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 549