1*4a5d661aSToomas Soome /*- 2*4a5d661aSToomas Soome * Copyright (c) 1993 The Regents of the University of California. 3*4a5d661aSToomas Soome * All rights reserved. 4*4a5d661aSToomas Soome * 5*4a5d661aSToomas Soome * Redistribution and use in source and binary forms, with or without 6*4a5d661aSToomas Soome * modification, are permitted provided that the following conditions 7*4a5d661aSToomas Soome * are met: 8*4a5d661aSToomas Soome * 1. Redistributions of source code must retain the above copyright 9*4a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer. 10*4a5d661aSToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 11*4a5d661aSToomas Soome * notice, this list of conditions and the following disclaimer in the 12*4a5d661aSToomas Soome * documentation and/or other materials provided with the distribution. 13*4a5d661aSToomas Soome * 4. Neither the name of the University nor the names of its contributors 14*4a5d661aSToomas Soome * may be used to endorse or promote products derived from this software 15*4a5d661aSToomas Soome * without specific prior written permission. 16*4a5d661aSToomas Soome * 17*4a5d661aSToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18*4a5d661aSToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19*4a5d661aSToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20*4a5d661aSToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21*4a5d661aSToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22*4a5d661aSToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23*4a5d661aSToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24*4a5d661aSToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25*4a5d661aSToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26*4a5d661aSToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27*4a5d661aSToomas Soome * SUCH DAMAGE. 28*4a5d661aSToomas Soome * 29*4a5d661aSToomas Soome * $FreeBSD$ 30*4a5d661aSToomas Soome */ 31*4a5d661aSToomas Soome 32*4a5d661aSToomas Soome /* 33*4a5d661aSToomas Soome * Functions to provide access to special i386 instructions. 34*4a5d661aSToomas Soome * This in included in sys/systm.h, and that file should be 35*4a5d661aSToomas Soome * used in preference to this. 36*4a5d661aSToomas Soome */ 37*4a5d661aSToomas Soome 38*4a5d661aSToomas Soome #ifndef _MACHINE_CPUFUNC_H_ 39*4a5d661aSToomas Soome #define _MACHINE_CPUFUNC_H_ 40*4a5d661aSToomas Soome 41*4a5d661aSToomas Soome #ifndef _SYS_CDEFS_H_ 42*4a5d661aSToomas Soome #error this file needs sys/cdefs.h as a prerequisite 43*4a5d661aSToomas Soome #endif 44*4a5d661aSToomas Soome 45*4a5d661aSToomas Soome struct region_descriptor; 46*4a5d661aSToomas Soome 47*4a5d661aSToomas Soome #define readb(va) (*(volatile uint8_t *) (va)) 48*4a5d661aSToomas Soome #define readw(va) (*(volatile uint16_t *) (va)) 49*4a5d661aSToomas Soome #define readl(va) (*(volatile uint32_t *) (va)) 50*4a5d661aSToomas Soome 51*4a5d661aSToomas Soome #define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) 52*4a5d661aSToomas Soome #define writew(va, d) (*(volatile uint16_t *) (va) = (d)) 53*4a5d661aSToomas Soome #define writel(va, d) (*(volatile uint32_t *) (va) = (d)) 54*4a5d661aSToomas Soome 55*4a5d661aSToomas Soome #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE) 56*4a5d661aSToomas Soome 57*4a5d661aSToomas Soome static __inline void 58*4a5d661aSToomas Soome breakpoint(void) 59*4a5d661aSToomas Soome { 60*4a5d661aSToomas Soome __asm __volatile("int $3"); 61*4a5d661aSToomas Soome } 62*4a5d661aSToomas Soome 63*4a5d661aSToomas Soome static __inline u_int 64*4a5d661aSToomas Soome bsfl(u_int mask) 65*4a5d661aSToomas Soome { 66*4a5d661aSToomas Soome u_int result; 67*4a5d661aSToomas Soome 68*4a5d661aSToomas Soome __asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); 69*4a5d661aSToomas Soome return (result); 70*4a5d661aSToomas Soome } 71*4a5d661aSToomas Soome 72*4a5d661aSToomas Soome static __inline u_int 73*4a5d661aSToomas Soome bsrl(u_int mask) 74*4a5d661aSToomas Soome { 75*4a5d661aSToomas Soome u_int result; 76*4a5d661aSToomas Soome 77*4a5d661aSToomas Soome __asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); 78*4a5d661aSToomas Soome return (result); 79*4a5d661aSToomas Soome } 80*4a5d661aSToomas Soome 81*4a5d661aSToomas Soome static __inline void 82*4a5d661aSToomas Soome clflush(u_long addr) 83*4a5d661aSToomas Soome { 84*4a5d661aSToomas Soome 85*4a5d661aSToomas Soome __asm __volatile("clflush %0" : : "m" (*(char *)addr)); 86*4a5d661aSToomas Soome } 87*4a5d661aSToomas Soome 88*4a5d661aSToomas Soome static __inline void 89*4a5d661aSToomas Soome clflushopt(u_long addr) 90*4a5d661aSToomas Soome { 91*4a5d661aSToomas Soome 92*4a5d661aSToomas Soome __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); 93*4a5d661aSToomas Soome } 94*4a5d661aSToomas Soome 95*4a5d661aSToomas Soome static __inline void 96*4a5d661aSToomas Soome clts(void) 97*4a5d661aSToomas Soome { 98*4a5d661aSToomas Soome 99*4a5d661aSToomas Soome __asm __volatile("clts"); 100*4a5d661aSToomas Soome } 101*4a5d661aSToomas Soome 102*4a5d661aSToomas Soome static __inline void 103*4a5d661aSToomas Soome disable_intr(void) 104*4a5d661aSToomas Soome { 105*4a5d661aSToomas Soome 106*4a5d661aSToomas Soome __asm __volatile("cli" : : : "memory"); 107*4a5d661aSToomas Soome } 108*4a5d661aSToomas Soome 109*4a5d661aSToomas Soome static __inline void 110*4a5d661aSToomas Soome do_cpuid(u_int ax, u_int *p) 111*4a5d661aSToomas Soome { 112*4a5d661aSToomas Soome __asm __volatile("cpuid" 113*4a5d661aSToomas Soome : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 114*4a5d661aSToomas Soome : "0" (ax)); 115*4a5d661aSToomas Soome } 116*4a5d661aSToomas Soome 117*4a5d661aSToomas Soome static __inline void 118*4a5d661aSToomas Soome cpuid_count(u_int ax, u_int cx, u_int *p) 119*4a5d661aSToomas Soome { 120*4a5d661aSToomas Soome __asm __volatile("cpuid" 121*4a5d661aSToomas Soome : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 122*4a5d661aSToomas Soome : "0" (ax), "c" (cx)); 123*4a5d661aSToomas Soome } 124*4a5d661aSToomas Soome 125*4a5d661aSToomas Soome static __inline void 126*4a5d661aSToomas Soome enable_intr(void) 127*4a5d661aSToomas Soome { 128*4a5d661aSToomas Soome 129*4a5d661aSToomas Soome __asm __volatile("sti"); 130*4a5d661aSToomas Soome } 131*4a5d661aSToomas Soome 132*4a5d661aSToomas Soome static __inline void 133*4a5d661aSToomas Soome cpu_monitor(const void *addr, u_long extensions, u_int hints) 134*4a5d661aSToomas Soome { 135*4a5d661aSToomas Soome 136*4a5d661aSToomas Soome __asm __volatile("monitor" 137*4a5d661aSToomas Soome : : "a" (addr), "c" (extensions), "d" (hints)); 138*4a5d661aSToomas Soome } 139*4a5d661aSToomas Soome 140*4a5d661aSToomas Soome static __inline void 141*4a5d661aSToomas Soome cpu_mwait(u_long extensions, u_int hints) 142*4a5d661aSToomas Soome { 143*4a5d661aSToomas Soome 144*4a5d661aSToomas Soome __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); 145*4a5d661aSToomas Soome } 146*4a5d661aSToomas Soome 147*4a5d661aSToomas Soome static __inline void 148*4a5d661aSToomas Soome lfence(void) 149*4a5d661aSToomas Soome { 150*4a5d661aSToomas Soome 151*4a5d661aSToomas Soome __asm __volatile("lfence" : : : "memory"); 152*4a5d661aSToomas Soome } 153*4a5d661aSToomas Soome 154*4a5d661aSToomas Soome static __inline void 155*4a5d661aSToomas Soome mfence(void) 156*4a5d661aSToomas Soome { 157*4a5d661aSToomas Soome 158*4a5d661aSToomas Soome __asm __volatile("mfence" : : : "memory"); 159*4a5d661aSToomas Soome } 160*4a5d661aSToomas Soome 161*4a5d661aSToomas Soome #ifdef _KERNEL 162*4a5d661aSToomas Soome 163*4a5d661aSToomas Soome #define HAVE_INLINE_FFS 164*4a5d661aSToomas Soome 165*4a5d661aSToomas Soome static __inline int 166*4a5d661aSToomas Soome ffs(int mask) 167*4a5d661aSToomas Soome { 168*4a5d661aSToomas Soome /* 169*4a5d661aSToomas Soome * Note that gcc-2's builtin ffs would be used if we didn't declare 170*4a5d661aSToomas Soome * this inline or turn off the builtin. The builtin is faster but 171*4a5d661aSToomas Soome * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later 172*4a5d661aSToomas Soome * versions. 173*4a5d661aSToomas Soome */ 174*4a5d661aSToomas Soome return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1); 175*4a5d661aSToomas Soome } 176*4a5d661aSToomas Soome 177*4a5d661aSToomas Soome #define HAVE_INLINE_FFSL 178*4a5d661aSToomas Soome 179*4a5d661aSToomas Soome static __inline int 180*4a5d661aSToomas Soome ffsl(long mask) 181*4a5d661aSToomas Soome { 182*4a5d661aSToomas Soome return (ffs((int)mask)); 183*4a5d661aSToomas Soome } 184*4a5d661aSToomas Soome 185*4a5d661aSToomas Soome #define HAVE_INLINE_FLS 186*4a5d661aSToomas Soome 187*4a5d661aSToomas Soome static __inline int 188*4a5d661aSToomas Soome fls(int mask) 189*4a5d661aSToomas Soome { 190*4a5d661aSToomas Soome return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 191*4a5d661aSToomas Soome } 192*4a5d661aSToomas Soome 193*4a5d661aSToomas Soome #define HAVE_INLINE_FLSL 194*4a5d661aSToomas Soome 195*4a5d661aSToomas Soome static __inline int 196*4a5d661aSToomas Soome flsl(long mask) 197*4a5d661aSToomas Soome { 198*4a5d661aSToomas Soome return (fls((int)mask)); 199*4a5d661aSToomas Soome } 200*4a5d661aSToomas Soome 201*4a5d661aSToomas Soome #endif /* _KERNEL */ 202*4a5d661aSToomas Soome 203*4a5d661aSToomas Soome static __inline void 204*4a5d661aSToomas Soome halt(void) 205*4a5d661aSToomas Soome { 206*4a5d661aSToomas Soome __asm __volatile("hlt"); 207*4a5d661aSToomas Soome } 208*4a5d661aSToomas Soome 209*4a5d661aSToomas Soome static __inline u_char 210*4a5d661aSToomas Soome inb(u_int port) 211*4a5d661aSToomas Soome { 212*4a5d661aSToomas Soome u_char data; 213*4a5d661aSToomas Soome 214*4a5d661aSToomas Soome __asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); 215*4a5d661aSToomas Soome return (data); 216*4a5d661aSToomas Soome } 217*4a5d661aSToomas Soome 218*4a5d661aSToomas Soome static __inline u_int 219*4a5d661aSToomas Soome inl(u_int port) 220*4a5d661aSToomas Soome { 221*4a5d661aSToomas Soome u_int data; 222*4a5d661aSToomas Soome 223*4a5d661aSToomas Soome __asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); 224*4a5d661aSToomas Soome return (data); 225*4a5d661aSToomas Soome } 226*4a5d661aSToomas Soome 227*4a5d661aSToomas Soome static __inline void 228*4a5d661aSToomas Soome insb(u_int port, void *addr, size_t count) 229*4a5d661aSToomas Soome { 230*4a5d661aSToomas Soome __asm __volatile("cld; rep; insb" 231*4a5d661aSToomas Soome : "+D" (addr), "+c" (count) 232*4a5d661aSToomas Soome : "d" (port) 233*4a5d661aSToomas Soome : "memory"); 234*4a5d661aSToomas Soome } 235*4a5d661aSToomas Soome 236*4a5d661aSToomas Soome static __inline void 237*4a5d661aSToomas Soome insw(u_int port, void *addr, size_t count) 238*4a5d661aSToomas Soome { 239*4a5d661aSToomas Soome __asm __volatile("cld; rep; insw" 240*4a5d661aSToomas Soome : "+D" (addr), "+c" (count) 241*4a5d661aSToomas Soome : "d" (port) 242*4a5d661aSToomas Soome : "memory"); 243*4a5d661aSToomas Soome } 244*4a5d661aSToomas Soome 245*4a5d661aSToomas Soome static __inline void 246*4a5d661aSToomas Soome insl(u_int port, void *addr, size_t count) 247*4a5d661aSToomas Soome { 248*4a5d661aSToomas Soome __asm __volatile("cld; rep; insl" 249*4a5d661aSToomas Soome : "+D" (addr), "+c" (count) 250*4a5d661aSToomas Soome : "d" (port) 251*4a5d661aSToomas Soome : "memory"); 252*4a5d661aSToomas Soome } 253*4a5d661aSToomas Soome 254*4a5d661aSToomas Soome static __inline void 255*4a5d661aSToomas Soome invd(void) 256*4a5d661aSToomas Soome { 257*4a5d661aSToomas Soome __asm __volatile("invd"); 258*4a5d661aSToomas Soome } 259*4a5d661aSToomas Soome 260*4a5d661aSToomas Soome static __inline u_short 261*4a5d661aSToomas Soome inw(u_int port) 262*4a5d661aSToomas Soome { 263*4a5d661aSToomas Soome u_short data; 264*4a5d661aSToomas Soome 265*4a5d661aSToomas Soome __asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port)); 266*4a5d661aSToomas Soome return (data); 267*4a5d661aSToomas Soome } 268*4a5d661aSToomas Soome 269*4a5d661aSToomas Soome static __inline void 270*4a5d661aSToomas Soome outb(u_int port, u_char data) 271*4a5d661aSToomas Soome { 272*4a5d661aSToomas Soome __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); 273*4a5d661aSToomas Soome } 274*4a5d661aSToomas Soome 275*4a5d661aSToomas Soome static __inline void 276*4a5d661aSToomas Soome outl(u_int port, u_int data) 277*4a5d661aSToomas Soome { 278*4a5d661aSToomas Soome __asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); 279*4a5d661aSToomas Soome } 280*4a5d661aSToomas Soome 281*4a5d661aSToomas Soome static __inline void 282*4a5d661aSToomas Soome outsb(u_int port, const void *addr, size_t count) 283*4a5d661aSToomas Soome { 284*4a5d661aSToomas Soome __asm __volatile("cld; rep; outsb" 285*4a5d661aSToomas Soome : "+S" (addr), "+c" (count) 286*4a5d661aSToomas Soome : "d" (port)); 287*4a5d661aSToomas Soome } 288*4a5d661aSToomas Soome 289*4a5d661aSToomas Soome static __inline void 290*4a5d661aSToomas Soome outsw(u_int port, const void *addr, size_t count) 291*4a5d661aSToomas Soome { 292*4a5d661aSToomas Soome __asm __volatile("cld; rep; outsw" 293*4a5d661aSToomas Soome : "+S" (addr), "+c" (count) 294*4a5d661aSToomas Soome : "d" (port)); 295*4a5d661aSToomas Soome } 296*4a5d661aSToomas Soome 297*4a5d661aSToomas Soome static __inline void 298*4a5d661aSToomas Soome outsl(u_int port, const void *addr, size_t count) 299*4a5d661aSToomas Soome { 300*4a5d661aSToomas Soome __asm __volatile("cld; rep; outsl" 301*4a5d661aSToomas Soome : "+S" (addr), "+c" (count) 302*4a5d661aSToomas Soome : "d" (port)); 303*4a5d661aSToomas Soome } 304*4a5d661aSToomas Soome 305*4a5d661aSToomas Soome static __inline void 306*4a5d661aSToomas Soome outw(u_int port, u_short data) 307*4a5d661aSToomas Soome { 308*4a5d661aSToomas Soome __asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); 309*4a5d661aSToomas Soome } 310*4a5d661aSToomas Soome 311*4a5d661aSToomas Soome static __inline void 312*4a5d661aSToomas Soome ia32_pause(void) 313*4a5d661aSToomas Soome { 314*4a5d661aSToomas Soome __asm __volatile("pause"); 315*4a5d661aSToomas Soome } 316*4a5d661aSToomas Soome 317*4a5d661aSToomas Soome static __inline u_int 318*4a5d661aSToomas Soome read_eflags(void) 319*4a5d661aSToomas Soome { 320*4a5d661aSToomas Soome u_int ef; 321*4a5d661aSToomas Soome 322*4a5d661aSToomas Soome __asm __volatile("pushfl; popl %0" : "=r" (ef)); 323*4a5d661aSToomas Soome return (ef); 324*4a5d661aSToomas Soome } 325*4a5d661aSToomas Soome 326*4a5d661aSToomas Soome static __inline uint64_t 327*4a5d661aSToomas Soome rdmsr(u_int msr) 328*4a5d661aSToomas Soome { 329*4a5d661aSToomas Soome uint64_t rv; 330*4a5d661aSToomas Soome 331*4a5d661aSToomas Soome __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr)); 332*4a5d661aSToomas Soome return (rv); 333*4a5d661aSToomas Soome } 334*4a5d661aSToomas Soome 335*4a5d661aSToomas Soome static __inline uint32_t 336*4a5d661aSToomas Soome rdmsr32(u_int msr) 337*4a5d661aSToomas Soome { 338*4a5d661aSToomas Soome uint32_t low; 339*4a5d661aSToomas Soome 340*4a5d661aSToomas Soome __asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "edx"); 341*4a5d661aSToomas Soome return (low); 342*4a5d661aSToomas Soome } 343*4a5d661aSToomas Soome 344*4a5d661aSToomas Soome static __inline uint64_t 345*4a5d661aSToomas Soome rdpmc(u_int pmc) 346*4a5d661aSToomas Soome { 347*4a5d661aSToomas Soome uint64_t rv; 348*4a5d661aSToomas Soome 349*4a5d661aSToomas Soome __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc)); 350*4a5d661aSToomas Soome return (rv); 351*4a5d661aSToomas Soome } 352*4a5d661aSToomas Soome 353*4a5d661aSToomas Soome static __inline uint64_t 354*4a5d661aSToomas Soome rdtsc(void) 355*4a5d661aSToomas Soome { 356*4a5d661aSToomas Soome uint64_t rv; 357*4a5d661aSToomas Soome 358*4a5d661aSToomas Soome __asm __volatile("rdtsc" : "=A" (rv)); 359*4a5d661aSToomas Soome return (rv); 360*4a5d661aSToomas Soome } 361*4a5d661aSToomas Soome 362*4a5d661aSToomas Soome static __inline uint32_t 363*4a5d661aSToomas Soome rdtsc32(void) 364*4a5d661aSToomas Soome { 365*4a5d661aSToomas Soome uint32_t rv; 366*4a5d661aSToomas Soome 367*4a5d661aSToomas Soome __asm __volatile("rdtsc" : "=a" (rv) : : "edx"); 368*4a5d661aSToomas Soome return (rv); 369*4a5d661aSToomas Soome } 370*4a5d661aSToomas Soome 371*4a5d661aSToomas Soome static __inline void 372*4a5d661aSToomas Soome wbinvd(void) 373*4a5d661aSToomas Soome { 374*4a5d661aSToomas Soome __asm __volatile("wbinvd"); 375*4a5d661aSToomas Soome } 376*4a5d661aSToomas Soome 377*4a5d661aSToomas Soome static __inline void 378*4a5d661aSToomas Soome write_eflags(u_int ef) 379*4a5d661aSToomas Soome { 380*4a5d661aSToomas Soome __asm __volatile("pushl %0; popfl" : : "r" (ef)); 381*4a5d661aSToomas Soome } 382*4a5d661aSToomas Soome 383*4a5d661aSToomas Soome static __inline void 384*4a5d661aSToomas Soome wrmsr(u_int msr, uint64_t newval) 385*4a5d661aSToomas Soome { 386*4a5d661aSToomas Soome __asm __volatile("wrmsr" : : "A" (newval), "c" (msr)); 387*4a5d661aSToomas Soome } 388*4a5d661aSToomas Soome 389*4a5d661aSToomas Soome static __inline void 390*4a5d661aSToomas Soome load_cr0(u_int data) 391*4a5d661aSToomas Soome { 392*4a5d661aSToomas Soome 393*4a5d661aSToomas Soome __asm __volatile("movl %0,%%cr0" : : "r" (data)); 394*4a5d661aSToomas Soome } 395*4a5d661aSToomas Soome 396*4a5d661aSToomas Soome static __inline u_int 397*4a5d661aSToomas Soome rcr0(void) 398*4a5d661aSToomas Soome { 399*4a5d661aSToomas Soome u_int data; 400*4a5d661aSToomas Soome 401*4a5d661aSToomas Soome __asm __volatile("movl %%cr0,%0" : "=r" (data)); 402*4a5d661aSToomas Soome return (data); 403*4a5d661aSToomas Soome } 404*4a5d661aSToomas Soome 405*4a5d661aSToomas Soome static __inline u_int 406*4a5d661aSToomas Soome rcr2(void) 407*4a5d661aSToomas Soome { 408*4a5d661aSToomas Soome u_int data; 409*4a5d661aSToomas Soome 410*4a5d661aSToomas Soome __asm __volatile("movl %%cr2,%0" : "=r" (data)); 411*4a5d661aSToomas Soome return (data); 412*4a5d661aSToomas Soome } 413*4a5d661aSToomas Soome 414*4a5d661aSToomas Soome static __inline void 415*4a5d661aSToomas Soome load_cr3(u_int data) 416*4a5d661aSToomas Soome { 417*4a5d661aSToomas Soome 418*4a5d661aSToomas Soome __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory"); 419*4a5d661aSToomas Soome } 420*4a5d661aSToomas Soome 421*4a5d661aSToomas Soome static __inline u_int 422*4a5d661aSToomas Soome rcr3(void) 423*4a5d661aSToomas Soome { 424*4a5d661aSToomas Soome u_int data; 425*4a5d661aSToomas Soome 426*4a5d661aSToomas Soome __asm __volatile("movl %%cr3,%0" : "=r" (data)); 427*4a5d661aSToomas Soome return (data); 428*4a5d661aSToomas Soome } 429*4a5d661aSToomas Soome 430*4a5d661aSToomas Soome static __inline void 431*4a5d661aSToomas Soome load_cr4(u_int data) 432*4a5d661aSToomas Soome { 433*4a5d661aSToomas Soome __asm __volatile("movl %0,%%cr4" : : "r" (data)); 434*4a5d661aSToomas Soome } 435*4a5d661aSToomas Soome 436*4a5d661aSToomas Soome static __inline u_int 437*4a5d661aSToomas Soome rcr4(void) 438*4a5d661aSToomas Soome { 439*4a5d661aSToomas Soome u_int data; 440*4a5d661aSToomas Soome 441*4a5d661aSToomas Soome __asm __volatile("movl %%cr4,%0" : "=r" (data)); 442*4a5d661aSToomas Soome return (data); 443*4a5d661aSToomas Soome } 444*4a5d661aSToomas Soome 445*4a5d661aSToomas Soome static __inline uint64_t 446*4a5d661aSToomas Soome rxcr(u_int reg) 447*4a5d661aSToomas Soome { 448*4a5d661aSToomas Soome u_int low, high; 449*4a5d661aSToomas Soome 450*4a5d661aSToomas Soome __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 451*4a5d661aSToomas Soome return (low | ((uint64_t)high << 32)); 452*4a5d661aSToomas Soome } 453*4a5d661aSToomas Soome 454*4a5d661aSToomas Soome static __inline void 455*4a5d661aSToomas Soome load_xcr(u_int reg, uint64_t val) 456*4a5d661aSToomas Soome { 457*4a5d661aSToomas Soome u_int low, high; 458*4a5d661aSToomas Soome 459*4a5d661aSToomas Soome low = val; 460*4a5d661aSToomas Soome high = val >> 32; 461*4a5d661aSToomas Soome __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 462*4a5d661aSToomas Soome } 463*4a5d661aSToomas Soome 464*4a5d661aSToomas Soome /* 465*4a5d661aSToomas Soome * Global TLB flush (except for thise for pages marked PG_G) 466*4a5d661aSToomas Soome */ 467*4a5d661aSToomas Soome static __inline void 468*4a5d661aSToomas Soome invltlb(void) 469*4a5d661aSToomas Soome { 470*4a5d661aSToomas Soome 471*4a5d661aSToomas Soome load_cr3(rcr3()); 472*4a5d661aSToomas Soome } 473*4a5d661aSToomas Soome 474*4a5d661aSToomas Soome /* 475*4a5d661aSToomas Soome * TLB flush for an individual page (even if it has PG_G). 476*4a5d661aSToomas Soome * Only works on 486+ CPUs (i386 does not have PG_G). 477*4a5d661aSToomas Soome */ 478*4a5d661aSToomas Soome static __inline void 479*4a5d661aSToomas Soome invlpg(u_int addr) 480*4a5d661aSToomas Soome { 481*4a5d661aSToomas Soome 482*4a5d661aSToomas Soome __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 483*4a5d661aSToomas Soome } 484*4a5d661aSToomas Soome 485*4a5d661aSToomas Soome static __inline u_short 486*4a5d661aSToomas Soome rfs(void) 487*4a5d661aSToomas Soome { 488*4a5d661aSToomas Soome u_short sel; 489*4a5d661aSToomas Soome __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 490*4a5d661aSToomas Soome return (sel); 491*4a5d661aSToomas Soome } 492*4a5d661aSToomas Soome 493*4a5d661aSToomas Soome static __inline uint64_t 494*4a5d661aSToomas Soome rgdt(void) 495*4a5d661aSToomas Soome { 496*4a5d661aSToomas Soome uint64_t gdtr; 497*4a5d661aSToomas Soome __asm __volatile("sgdt %0" : "=m" (gdtr)); 498*4a5d661aSToomas Soome return (gdtr); 499*4a5d661aSToomas Soome } 500*4a5d661aSToomas Soome 501*4a5d661aSToomas Soome static __inline u_short 502*4a5d661aSToomas Soome rgs(void) 503*4a5d661aSToomas Soome { 504*4a5d661aSToomas Soome u_short sel; 505*4a5d661aSToomas Soome __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 506*4a5d661aSToomas Soome return (sel); 507*4a5d661aSToomas Soome } 508*4a5d661aSToomas Soome 509*4a5d661aSToomas Soome static __inline uint64_t 510*4a5d661aSToomas Soome ridt(void) 511*4a5d661aSToomas Soome { 512*4a5d661aSToomas Soome uint64_t idtr; 513*4a5d661aSToomas Soome __asm __volatile("sidt %0" : "=m" (idtr)); 514*4a5d661aSToomas Soome return (idtr); 515*4a5d661aSToomas Soome } 516*4a5d661aSToomas Soome 517*4a5d661aSToomas Soome static __inline u_short 518*4a5d661aSToomas Soome rldt(void) 519*4a5d661aSToomas Soome { 520*4a5d661aSToomas Soome u_short ldtr; 521*4a5d661aSToomas Soome __asm __volatile("sldt %0" : "=g" (ldtr)); 522*4a5d661aSToomas Soome return (ldtr); 523*4a5d661aSToomas Soome } 524*4a5d661aSToomas Soome 525*4a5d661aSToomas Soome static __inline u_short 526*4a5d661aSToomas Soome rss(void) 527*4a5d661aSToomas Soome { 528*4a5d661aSToomas Soome u_short sel; 529*4a5d661aSToomas Soome __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 530*4a5d661aSToomas Soome return (sel); 531*4a5d661aSToomas Soome } 532*4a5d661aSToomas Soome 533*4a5d661aSToomas Soome static __inline u_short 534*4a5d661aSToomas Soome rtr(void) 535*4a5d661aSToomas Soome { 536*4a5d661aSToomas Soome u_short tr; 537*4a5d661aSToomas Soome __asm __volatile("str %0" : "=g" (tr)); 538*4a5d661aSToomas Soome return (tr); 539*4a5d661aSToomas Soome } 540*4a5d661aSToomas Soome 541*4a5d661aSToomas Soome static __inline void 542*4a5d661aSToomas Soome load_fs(u_short sel) 543*4a5d661aSToomas Soome { 544*4a5d661aSToomas Soome __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 545*4a5d661aSToomas Soome } 546*4a5d661aSToomas Soome 547*4a5d661aSToomas Soome static __inline void 548*4a5d661aSToomas Soome load_gs(u_short sel) 549*4a5d661aSToomas Soome { 550*4a5d661aSToomas Soome __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 551*4a5d661aSToomas Soome } 552*4a5d661aSToomas Soome 553*4a5d661aSToomas Soome static __inline void 554*4a5d661aSToomas Soome lidt(struct region_descriptor *addr) 555*4a5d661aSToomas Soome { 556*4a5d661aSToomas Soome __asm __volatile("lidt (%0)" : : "r" (addr)); 557*4a5d661aSToomas Soome } 558*4a5d661aSToomas Soome 559*4a5d661aSToomas Soome static __inline void 560*4a5d661aSToomas Soome lldt(u_short sel) 561*4a5d661aSToomas Soome { 562*4a5d661aSToomas Soome __asm __volatile("lldt %0" : : "r" (sel)); 563*4a5d661aSToomas Soome } 564*4a5d661aSToomas Soome 565*4a5d661aSToomas Soome static __inline void 566*4a5d661aSToomas Soome ltr(u_short sel) 567*4a5d661aSToomas Soome { 568*4a5d661aSToomas Soome __asm __volatile("ltr %0" : : "r" (sel)); 569*4a5d661aSToomas Soome } 570*4a5d661aSToomas Soome 571*4a5d661aSToomas Soome static __inline u_int 572*4a5d661aSToomas Soome rdr0(void) 573*4a5d661aSToomas Soome { 574*4a5d661aSToomas Soome u_int data; 575*4a5d661aSToomas Soome __asm __volatile("movl %%dr0,%0" : "=r" (data)); 576*4a5d661aSToomas Soome return (data); 577*4a5d661aSToomas Soome } 578*4a5d661aSToomas Soome 579*4a5d661aSToomas Soome static __inline void 580*4a5d661aSToomas Soome load_dr0(u_int dr0) 581*4a5d661aSToomas Soome { 582*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr0" : : "r" (dr0)); 583*4a5d661aSToomas Soome } 584*4a5d661aSToomas Soome 585*4a5d661aSToomas Soome static __inline u_int 586*4a5d661aSToomas Soome rdr1(void) 587*4a5d661aSToomas Soome { 588*4a5d661aSToomas Soome u_int data; 589*4a5d661aSToomas Soome __asm __volatile("movl %%dr1,%0" : "=r" (data)); 590*4a5d661aSToomas Soome return (data); 591*4a5d661aSToomas Soome } 592*4a5d661aSToomas Soome 593*4a5d661aSToomas Soome static __inline void 594*4a5d661aSToomas Soome load_dr1(u_int dr1) 595*4a5d661aSToomas Soome { 596*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr1" : : "r" (dr1)); 597*4a5d661aSToomas Soome } 598*4a5d661aSToomas Soome 599*4a5d661aSToomas Soome static __inline u_int 600*4a5d661aSToomas Soome rdr2(void) 601*4a5d661aSToomas Soome { 602*4a5d661aSToomas Soome u_int data; 603*4a5d661aSToomas Soome __asm __volatile("movl %%dr2,%0" : "=r" (data)); 604*4a5d661aSToomas Soome return (data); 605*4a5d661aSToomas Soome } 606*4a5d661aSToomas Soome 607*4a5d661aSToomas Soome static __inline void 608*4a5d661aSToomas Soome load_dr2(u_int dr2) 609*4a5d661aSToomas Soome { 610*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr2" : : "r" (dr2)); 611*4a5d661aSToomas Soome } 612*4a5d661aSToomas Soome 613*4a5d661aSToomas Soome static __inline u_int 614*4a5d661aSToomas Soome rdr3(void) 615*4a5d661aSToomas Soome { 616*4a5d661aSToomas Soome u_int data; 617*4a5d661aSToomas Soome __asm __volatile("movl %%dr3,%0" : "=r" (data)); 618*4a5d661aSToomas Soome return (data); 619*4a5d661aSToomas Soome } 620*4a5d661aSToomas Soome 621*4a5d661aSToomas Soome static __inline void 622*4a5d661aSToomas Soome load_dr3(u_int dr3) 623*4a5d661aSToomas Soome { 624*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr3" : : "r" (dr3)); 625*4a5d661aSToomas Soome } 626*4a5d661aSToomas Soome 627*4a5d661aSToomas Soome static __inline u_int 628*4a5d661aSToomas Soome rdr4(void) 629*4a5d661aSToomas Soome { 630*4a5d661aSToomas Soome u_int data; 631*4a5d661aSToomas Soome __asm __volatile("movl %%dr4,%0" : "=r" (data)); 632*4a5d661aSToomas Soome return (data); 633*4a5d661aSToomas Soome } 634*4a5d661aSToomas Soome 635*4a5d661aSToomas Soome static __inline void 636*4a5d661aSToomas Soome load_dr4(u_int dr4) 637*4a5d661aSToomas Soome { 638*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr4" : : "r" (dr4)); 639*4a5d661aSToomas Soome } 640*4a5d661aSToomas Soome 641*4a5d661aSToomas Soome static __inline u_int 642*4a5d661aSToomas Soome rdr5(void) 643*4a5d661aSToomas Soome { 644*4a5d661aSToomas Soome u_int data; 645*4a5d661aSToomas Soome __asm __volatile("movl %%dr5,%0" : "=r" (data)); 646*4a5d661aSToomas Soome return (data); 647*4a5d661aSToomas Soome } 648*4a5d661aSToomas Soome 649*4a5d661aSToomas Soome static __inline void 650*4a5d661aSToomas Soome load_dr5(u_int dr5) 651*4a5d661aSToomas Soome { 652*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr5" : : "r" (dr5)); 653*4a5d661aSToomas Soome } 654*4a5d661aSToomas Soome 655*4a5d661aSToomas Soome static __inline u_int 656*4a5d661aSToomas Soome rdr6(void) 657*4a5d661aSToomas Soome { 658*4a5d661aSToomas Soome u_int data; 659*4a5d661aSToomas Soome __asm __volatile("movl %%dr6,%0" : "=r" (data)); 660*4a5d661aSToomas Soome return (data); 661*4a5d661aSToomas Soome } 662*4a5d661aSToomas Soome 663*4a5d661aSToomas Soome static __inline void 664*4a5d661aSToomas Soome load_dr6(u_int dr6) 665*4a5d661aSToomas Soome { 666*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr6" : : "r" (dr6)); 667*4a5d661aSToomas Soome } 668*4a5d661aSToomas Soome 669*4a5d661aSToomas Soome static __inline u_int 670*4a5d661aSToomas Soome rdr7(void) 671*4a5d661aSToomas Soome { 672*4a5d661aSToomas Soome u_int data; 673*4a5d661aSToomas Soome __asm __volatile("movl %%dr7,%0" : "=r" (data)); 674*4a5d661aSToomas Soome return (data); 675*4a5d661aSToomas Soome } 676*4a5d661aSToomas Soome 677*4a5d661aSToomas Soome static __inline void 678*4a5d661aSToomas Soome load_dr7(u_int dr7) 679*4a5d661aSToomas Soome { 680*4a5d661aSToomas Soome __asm __volatile("movl %0,%%dr7" : : "r" (dr7)); 681*4a5d661aSToomas Soome } 682*4a5d661aSToomas Soome 683*4a5d661aSToomas Soome static __inline u_char 684*4a5d661aSToomas Soome read_cyrix_reg(u_char reg) 685*4a5d661aSToomas Soome { 686*4a5d661aSToomas Soome outb(0x22, reg); 687*4a5d661aSToomas Soome return inb(0x23); 688*4a5d661aSToomas Soome } 689*4a5d661aSToomas Soome 690*4a5d661aSToomas Soome static __inline void 691*4a5d661aSToomas Soome write_cyrix_reg(u_char reg, u_char data) 692*4a5d661aSToomas Soome { 693*4a5d661aSToomas Soome outb(0x22, reg); 694*4a5d661aSToomas Soome outb(0x23, data); 695*4a5d661aSToomas Soome } 696*4a5d661aSToomas Soome 697*4a5d661aSToomas Soome static __inline register_t 698*4a5d661aSToomas Soome intr_disable(void) 699*4a5d661aSToomas Soome { 700*4a5d661aSToomas Soome register_t eflags; 701*4a5d661aSToomas Soome 702*4a5d661aSToomas Soome eflags = read_eflags(); 703*4a5d661aSToomas Soome disable_intr(); 704*4a5d661aSToomas Soome return (eflags); 705*4a5d661aSToomas Soome } 706*4a5d661aSToomas Soome 707*4a5d661aSToomas Soome static __inline void 708*4a5d661aSToomas Soome intr_restore(register_t eflags) 709*4a5d661aSToomas Soome { 710*4a5d661aSToomas Soome write_eflags(eflags); 711*4a5d661aSToomas Soome } 712*4a5d661aSToomas Soome 713*4a5d661aSToomas Soome #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 714*4a5d661aSToomas Soome 715*4a5d661aSToomas Soome int breakpoint(void); 716*4a5d661aSToomas Soome u_int bsfl(u_int mask); 717*4a5d661aSToomas Soome u_int bsrl(u_int mask); 718*4a5d661aSToomas Soome void clflush(u_long addr); 719*4a5d661aSToomas Soome void clts(void); 720*4a5d661aSToomas Soome void cpuid_count(u_int ax, u_int cx, u_int *p); 721*4a5d661aSToomas Soome void disable_intr(void); 722*4a5d661aSToomas Soome void do_cpuid(u_int ax, u_int *p); 723*4a5d661aSToomas Soome void enable_intr(void); 724*4a5d661aSToomas Soome void halt(void); 725*4a5d661aSToomas Soome void ia32_pause(void); 726*4a5d661aSToomas Soome u_char inb(u_int port); 727*4a5d661aSToomas Soome u_int inl(u_int port); 728*4a5d661aSToomas Soome void insb(u_int port, void *addr, size_t count); 729*4a5d661aSToomas Soome void insl(u_int port, void *addr, size_t count); 730*4a5d661aSToomas Soome void insw(u_int port, void *addr, size_t count); 731*4a5d661aSToomas Soome register_t intr_disable(void); 732*4a5d661aSToomas Soome void intr_restore(register_t ef); 733*4a5d661aSToomas Soome void invd(void); 734*4a5d661aSToomas Soome void invlpg(u_int addr); 735*4a5d661aSToomas Soome void invltlb(void); 736*4a5d661aSToomas Soome u_short inw(u_int port); 737*4a5d661aSToomas Soome void lidt(struct region_descriptor *addr); 738*4a5d661aSToomas Soome void lldt(u_short sel); 739*4a5d661aSToomas Soome void load_cr0(u_int cr0); 740*4a5d661aSToomas Soome void load_cr3(u_int cr3); 741*4a5d661aSToomas Soome void load_cr4(u_int cr4); 742*4a5d661aSToomas Soome void load_dr0(u_int dr0); 743*4a5d661aSToomas Soome void load_dr1(u_int dr1); 744*4a5d661aSToomas Soome void load_dr2(u_int dr2); 745*4a5d661aSToomas Soome void load_dr3(u_int dr3); 746*4a5d661aSToomas Soome void load_dr4(u_int dr4); 747*4a5d661aSToomas Soome void load_dr5(u_int dr5); 748*4a5d661aSToomas Soome void load_dr6(u_int dr6); 749*4a5d661aSToomas Soome void load_dr7(u_int dr7); 750*4a5d661aSToomas Soome void load_fs(u_short sel); 751*4a5d661aSToomas Soome void load_gs(u_short sel); 752*4a5d661aSToomas Soome void ltr(u_short sel); 753*4a5d661aSToomas Soome void outb(u_int port, u_char data); 754*4a5d661aSToomas Soome void outl(u_int port, u_int data); 755*4a5d661aSToomas Soome void outsb(u_int port, const void *addr, size_t count); 756*4a5d661aSToomas Soome void outsl(u_int port, const void *addr, size_t count); 757*4a5d661aSToomas Soome void outsw(u_int port, const void *addr, size_t count); 758*4a5d661aSToomas Soome void outw(u_int port, u_short data); 759*4a5d661aSToomas Soome u_int rcr0(void); 760*4a5d661aSToomas Soome u_int rcr2(void); 761*4a5d661aSToomas Soome u_int rcr3(void); 762*4a5d661aSToomas Soome u_int rcr4(void); 763*4a5d661aSToomas Soome uint64_t rdmsr(u_int msr); 764*4a5d661aSToomas Soome uint64_t rdpmc(u_int pmc); 765*4a5d661aSToomas Soome u_int rdr0(void); 766*4a5d661aSToomas Soome u_int rdr1(void); 767*4a5d661aSToomas Soome u_int rdr2(void); 768*4a5d661aSToomas Soome u_int rdr3(void); 769*4a5d661aSToomas Soome u_int rdr4(void); 770*4a5d661aSToomas Soome u_int rdr5(void); 771*4a5d661aSToomas Soome u_int rdr6(void); 772*4a5d661aSToomas Soome u_int rdr7(void); 773*4a5d661aSToomas Soome uint64_t rdtsc(void); 774*4a5d661aSToomas Soome u_char read_cyrix_reg(u_char reg); 775*4a5d661aSToomas Soome u_int read_eflags(void); 776*4a5d661aSToomas Soome u_int rfs(void); 777*4a5d661aSToomas Soome uint64_t rgdt(void); 778*4a5d661aSToomas Soome u_int rgs(void); 779*4a5d661aSToomas Soome uint64_t ridt(void); 780*4a5d661aSToomas Soome u_short rldt(void); 781*4a5d661aSToomas Soome u_short rtr(void); 782*4a5d661aSToomas Soome void wbinvd(void); 783*4a5d661aSToomas Soome void write_cyrix_reg(u_char reg, u_char data); 784*4a5d661aSToomas Soome void write_eflags(u_int ef); 785*4a5d661aSToomas Soome void wrmsr(u_int msr, uint64_t newval); 786*4a5d661aSToomas Soome 787*4a5d661aSToomas Soome #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 788*4a5d661aSToomas Soome 789*4a5d661aSToomas Soome void reset_dbregs(void); 790*4a5d661aSToomas Soome 791*4a5d661aSToomas Soome #ifdef _KERNEL 792*4a5d661aSToomas Soome int rdmsr_safe(u_int msr, uint64_t *val); 793*4a5d661aSToomas Soome int wrmsr_safe(u_int msr, uint64_t newval); 794*4a5d661aSToomas Soome #endif 795*4a5d661aSToomas Soome 796*4a5d661aSToomas Soome #endif /* !_MACHINE_CPUFUNC_H_ */ 797