1199767f8SToomas Soome /*- 2199767f8SToomas Soome * Copyright (c) 1993 The Regents of the University of California. 3199767f8SToomas Soome * All rights reserved. 4199767f8SToomas Soome * 5199767f8SToomas Soome * Redistribution and use in source and binary forms, with or without 6199767f8SToomas Soome * modification, are permitted provided that the following conditions 7199767f8SToomas Soome * are met: 8199767f8SToomas Soome * 1. Redistributions of source code must retain the above copyright 9199767f8SToomas Soome * notice, this list of conditions and the following disclaimer. 10199767f8SToomas Soome * 2. Redistributions in binary form must reproduce the above copyright 11199767f8SToomas Soome * notice, this list of conditions and the following disclaimer in the 12199767f8SToomas Soome * documentation and/or other materials provided with the distribution. 13199767f8SToomas Soome * 4. Neither the name of the University nor the names of its contributors 14199767f8SToomas Soome * may be used to endorse or promote products derived from this software 15199767f8SToomas Soome * without specific prior written permission. 16199767f8SToomas Soome * 17199767f8SToomas Soome * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18199767f8SToomas Soome * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19199767f8SToomas Soome * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20199767f8SToomas Soome * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21199767f8SToomas Soome * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22199767f8SToomas Soome * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23199767f8SToomas Soome * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24199767f8SToomas Soome * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25199767f8SToomas Soome * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26199767f8SToomas Soome * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27199767f8SToomas Soome * SUCH DAMAGE. 28199767f8SToomas Soome * 29199767f8SToomas Soome * $FreeBSD$ 30199767f8SToomas Soome */ 31199767f8SToomas Soome 32199767f8SToomas Soome /* 33199767f8SToomas Soome * Functions to provide access to special i386 instructions. 34199767f8SToomas Soome * This in included in sys/systm.h, and that file should be 35199767f8SToomas Soome * used in preference to this. 36199767f8SToomas Soome */ 37199767f8SToomas Soome 38199767f8SToomas Soome #ifndef _MACHINE_CPUFUNC_H_ 39199767f8SToomas Soome #define _MACHINE_CPUFUNC_H_ 40199767f8SToomas Soome 41199767f8SToomas Soome #ifndef _SYS_CDEFS_H_ 42199767f8SToomas Soome #error this file needs sys/cdefs.h as a prerequisite 43199767f8SToomas Soome #endif 44199767f8SToomas Soome 45199767f8SToomas Soome struct region_descriptor; 46199767f8SToomas Soome 47199767f8SToomas Soome #define readb(va) (*(volatile uint8_t *) (va)) 48199767f8SToomas Soome #define readw(va) (*(volatile uint16_t *) (va)) 49199767f8SToomas Soome #define readl(va) (*(volatile uint32_t *) (va)) 50199767f8SToomas Soome 51199767f8SToomas Soome #define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) 52199767f8SToomas Soome #define writew(va, d) (*(volatile uint16_t *) (va) = (d)) 53199767f8SToomas Soome #define writel(va, d) (*(volatile uint32_t *) (va) = (d)) 54199767f8SToomas Soome 55199767f8SToomas Soome #if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE) 56199767f8SToomas Soome 57199767f8SToomas Soome static __inline void 58199767f8SToomas Soome breakpoint(void) 59199767f8SToomas Soome { 60199767f8SToomas Soome __asm __volatile("int $3"); 61199767f8SToomas Soome } 62199767f8SToomas Soome 63199767f8SToomas Soome static __inline u_int 64199767f8SToomas Soome bsfl(u_int mask) 65199767f8SToomas Soome { 66199767f8SToomas Soome u_int result; 67199767f8SToomas Soome 68199767f8SToomas Soome __asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); 69199767f8SToomas Soome return (result); 70199767f8SToomas Soome } 71199767f8SToomas Soome 72199767f8SToomas Soome static __inline u_int 73199767f8SToomas Soome bsrl(u_int mask) 74199767f8SToomas Soome { 75199767f8SToomas Soome u_int result; 76199767f8SToomas Soome 77199767f8SToomas Soome __asm("bsrl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); 78199767f8SToomas Soome return (result); 79199767f8SToomas Soome } 80199767f8SToomas Soome 81199767f8SToomas Soome static __inline void 82199767f8SToomas Soome clflush(u_long addr) 83199767f8SToomas Soome { 84199767f8SToomas Soome 85199767f8SToomas Soome __asm __volatile("clflush %0" : : "m" (*(char *)addr)); 86199767f8SToomas Soome } 87199767f8SToomas Soome 88199767f8SToomas Soome static __inline void 89199767f8SToomas Soome clflushopt(u_long addr) 90199767f8SToomas Soome { 91199767f8SToomas Soome 92199767f8SToomas Soome __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); 93199767f8SToomas Soome } 94199767f8SToomas Soome 95199767f8SToomas Soome static __inline void 96199767f8SToomas Soome clts(void) 97199767f8SToomas Soome { 98199767f8SToomas Soome 99199767f8SToomas Soome __asm __volatile("clts"); 100199767f8SToomas Soome } 101199767f8SToomas Soome 102199767f8SToomas Soome static __inline void 103199767f8SToomas Soome disable_intr(void) 104199767f8SToomas Soome { 105199767f8SToomas Soome 106199767f8SToomas Soome __asm __volatile("cli" : : : "memory"); 107199767f8SToomas Soome } 108199767f8SToomas Soome 109199767f8SToomas Soome static __inline void 110199767f8SToomas Soome do_cpuid(u_int ax, u_int *p) 111199767f8SToomas Soome { 112*6efcf43cSToomas Soome __asm __volatile("pushl %%ebx \n\t" 113*6efcf43cSToomas Soome "cpuid \n\t" 114*6efcf43cSToomas Soome "movl %%ebx, %1 \n\t" 115*6efcf43cSToomas Soome "popl %%ebx \n\t" 116*6efcf43cSToomas Soome : "=a" (p[0]), "=m" (p[1]), "=c" (p[2]), "=d" (p[3]) 117*6efcf43cSToomas Soome : "0" (ax)); 118199767f8SToomas Soome } 119199767f8SToomas Soome 120199767f8SToomas Soome static __inline void 121199767f8SToomas Soome cpuid_count(u_int ax, u_int cx, u_int *p) 122199767f8SToomas Soome { 123199767f8SToomas Soome __asm __volatile("cpuid" 124199767f8SToomas Soome : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 125199767f8SToomas Soome : "0" (ax), "c" (cx)); 126199767f8SToomas Soome } 127199767f8SToomas Soome 128199767f8SToomas Soome static __inline void 129199767f8SToomas Soome enable_intr(void) 130199767f8SToomas Soome { 131199767f8SToomas Soome 132199767f8SToomas Soome __asm __volatile("sti"); 133199767f8SToomas Soome } 134199767f8SToomas Soome 135199767f8SToomas Soome static __inline void 136199767f8SToomas Soome cpu_monitor(const void *addr, u_long extensions, u_int hints) 137199767f8SToomas Soome { 138199767f8SToomas Soome 139199767f8SToomas Soome __asm __volatile("monitor" 140199767f8SToomas Soome : : "a" (addr), "c" (extensions), "d" (hints)); 141199767f8SToomas Soome } 142199767f8SToomas Soome 143199767f8SToomas Soome static __inline void 144199767f8SToomas Soome cpu_mwait(u_long extensions, u_int hints) 145199767f8SToomas Soome { 146199767f8SToomas Soome 147199767f8SToomas Soome __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); 148199767f8SToomas Soome } 149199767f8SToomas Soome 150199767f8SToomas Soome static __inline void 151199767f8SToomas Soome lfence(void) 152199767f8SToomas Soome { 153199767f8SToomas Soome 154199767f8SToomas Soome __asm __volatile("lfence" : : : "memory"); 155199767f8SToomas Soome } 156199767f8SToomas Soome 157199767f8SToomas Soome static __inline void 158199767f8SToomas Soome mfence(void) 159199767f8SToomas Soome { 160199767f8SToomas Soome 161199767f8SToomas Soome __asm __volatile("mfence" : : : "memory"); 162199767f8SToomas Soome } 163199767f8SToomas Soome 164199767f8SToomas Soome #ifdef _KERNEL 165199767f8SToomas Soome 166199767f8SToomas Soome #define HAVE_INLINE_FFS 167199767f8SToomas Soome 168199767f8SToomas Soome static __inline int 169199767f8SToomas Soome ffs(int mask) 170199767f8SToomas Soome { 171199767f8SToomas Soome /* 172199767f8SToomas Soome * Note that gcc-2's builtin ffs would be used if we didn't declare 173199767f8SToomas Soome * this inline or turn off the builtin. The builtin is faster but 174199767f8SToomas Soome * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later 175199767f8SToomas Soome * versions. 176199767f8SToomas Soome */ 177199767f8SToomas Soome return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1); 178199767f8SToomas Soome } 179199767f8SToomas Soome 180199767f8SToomas Soome #define HAVE_INLINE_FFSL 181199767f8SToomas Soome 182199767f8SToomas Soome static __inline int 183199767f8SToomas Soome ffsl(long mask) 184199767f8SToomas Soome { 185199767f8SToomas Soome return (ffs((int)mask)); 186199767f8SToomas Soome } 187199767f8SToomas Soome 188199767f8SToomas Soome #define HAVE_INLINE_FLS 189199767f8SToomas Soome 190199767f8SToomas Soome static __inline int 191199767f8SToomas Soome fls(int mask) 192199767f8SToomas Soome { 193199767f8SToomas Soome return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 194199767f8SToomas Soome } 195199767f8SToomas Soome 196199767f8SToomas Soome #define HAVE_INLINE_FLSL 197199767f8SToomas Soome 198199767f8SToomas Soome static __inline int 199199767f8SToomas Soome flsl(long mask) 200199767f8SToomas Soome { 201199767f8SToomas Soome return (fls((int)mask)); 202199767f8SToomas Soome } 203199767f8SToomas Soome 204199767f8SToomas Soome #endif /* _KERNEL */ 205199767f8SToomas Soome 206199767f8SToomas Soome static __inline void 207199767f8SToomas Soome halt(void) 208199767f8SToomas Soome { 209199767f8SToomas Soome __asm __volatile("hlt"); 210199767f8SToomas Soome } 211199767f8SToomas Soome 212199767f8SToomas Soome static __inline u_char 213199767f8SToomas Soome inb(u_int port) 214199767f8SToomas Soome { 215199767f8SToomas Soome u_char data; 216199767f8SToomas Soome 217199767f8SToomas Soome __asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); 218199767f8SToomas Soome return (data); 219199767f8SToomas Soome } 220199767f8SToomas Soome 221199767f8SToomas Soome static __inline u_int 222199767f8SToomas Soome inl(u_int port) 223199767f8SToomas Soome { 224199767f8SToomas Soome u_int data; 225199767f8SToomas Soome 226199767f8SToomas Soome __asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); 227199767f8SToomas Soome return (data); 228199767f8SToomas Soome } 229199767f8SToomas Soome 230199767f8SToomas Soome static __inline void 231199767f8SToomas Soome insb(u_int port, void *addr, size_t count) 232199767f8SToomas Soome { 233199767f8SToomas Soome __asm __volatile("cld; rep; insb" 234199767f8SToomas Soome : "+D" (addr), "+c" (count) 235199767f8SToomas Soome : "d" (port) 236199767f8SToomas Soome : "memory"); 237199767f8SToomas Soome } 238199767f8SToomas Soome 239199767f8SToomas Soome static __inline void 240199767f8SToomas Soome insw(u_int port, void *addr, size_t count) 241199767f8SToomas Soome { 242199767f8SToomas Soome __asm __volatile("cld; rep; insw" 243199767f8SToomas Soome : "+D" (addr), "+c" (count) 244199767f8SToomas Soome : "d" (port) 245199767f8SToomas Soome : "memory"); 246199767f8SToomas Soome } 247199767f8SToomas Soome 248199767f8SToomas Soome static __inline void 249199767f8SToomas Soome insl(u_int port, void *addr, size_t count) 250199767f8SToomas Soome { 251199767f8SToomas Soome __asm __volatile("cld; rep; insl" 252199767f8SToomas Soome : "+D" (addr), "+c" (count) 253199767f8SToomas Soome : "d" (port) 254199767f8SToomas Soome : "memory"); 255199767f8SToomas Soome } 256199767f8SToomas Soome 257199767f8SToomas Soome static __inline void 258199767f8SToomas Soome invd(void) 259199767f8SToomas Soome { 260199767f8SToomas Soome __asm __volatile("invd"); 261199767f8SToomas Soome } 262199767f8SToomas Soome 263199767f8SToomas Soome static __inline u_short 264199767f8SToomas Soome inw(u_int port) 265199767f8SToomas Soome { 266199767f8SToomas Soome u_short data; 267199767f8SToomas Soome 268199767f8SToomas Soome __asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port)); 269199767f8SToomas Soome return (data); 270199767f8SToomas Soome } 271199767f8SToomas Soome 272199767f8SToomas Soome static __inline void 273199767f8SToomas Soome outb(u_int port, u_char data) 274199767f8SToomas Soome { 275199767f8SToomas Soome __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); 276199767f8SToomas Soome } 277199767f8SToomas Soome 278199767f8SToomas Soome static __inline void 279199767f8SToomas Soome outl(u_int port, u_int data) 280199767f8SToomas Soome { 281199767f8SToomas Soome __asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); 282199767f8SToomas Soome } 283199767f8SToomas Soome 284199767f8SToomas Soome static __inline void 285199767f8SToomas Soome outsb(u_int port, const void *addr, size_t count) 286199767f8SToomas Soome { 287199767f8SToomas Soome __asm __volatile("cld; rep; outsb" 288199767f8SToomas Soome : "+S" (addr), "+c" (count) 289199767f8SToomas Soome : "d" (port)); 290199767f8SToomas Soome } 291199767f8SToomas Soome 292199767f8SToomas Soome static __inline void 293199767f8SToomas Soome outsw(u_int port, const void *addr, size_t count) 294199767f8SToomas Soome { 295199767f8SToomas Soome __asm __volatile("cld; rep; outsw" 296199767f8SToomas Soome : "+S" (addr), "+c" (count) 297199767f8SToomas Soome : "d" (port)); 298199767f8SToomas Soome } 299199767f8SToomas Soome 300199767f8SToomas Soome static __inline void 301199767f8SToomas Soome outsl(u_int port, const void *addr, size_t count) 302199767f8SToomas Soome { 303199767f8SToomas Soome __asm __volatile("cld; rep; outsl" 304199767f8SToomas Soome : "+S" (addr), "+c" (count) 305199767f8SToomas Soome : "d" (port)); 306199767f8SToomas Soome } 307199767f8SToomas Soome 308199767f8SToomas Soome static __inline void 309199767f8SToomas Soome outw(u_int port, u_short data) 310199767f8SToomas Soome { 311199767f8SToomas Soome __asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); 312199767f8SToomas Soome } 313199767f8SToomas Soome 314199767f8SToomas Soome static __inline void 315199767f8SToomas Soome ia32_pause(void) 316199767f8SToomas Soome { 317199767f8SToomas Soome __asm __volatile("pause"); 318199767f8SToomas Soome } 319199767f8SToomas Soome 320199767f8SToomas Soome static __inline u_int 321199767f8SToomas Soome read_eflags(void) 322199767f8SToomas Soome { 323199767f8SToomas Soome u_int ef; 324199767f8SToomas Soome 325199767f8SToomas Soome __asm __volatile("pushfl; popl %0" : "=r" (ef)); 326199767f8SToomas Soome return (ef); 327199767f8SToomas Soome } 328199767f8SToomas Soome 329199767f8SToomas Soome static __inline uint64_t 330199767f8SToomas Soome rdmsr(u_int msr) 331199767f8SToomas Soome { 332199767f8SToomas Soome uint64_t rv; 333199767f8SToomas Soome 334199767f8SToomas Soome __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr)); 335199767f8SToomas Soome return (rv); 336199767f8SToomas Soome } 337199767f8SToomas Soome 338199767f8SToomas Soome static __inline uint32_t 339199767f8SToomas Soome rdmsr32(u_int msr) 340199767f8SToomas Soome { 341199767f8SToomas Soome uint32_t low; 342199767f8SToomas Soome 343199767f8SToomas Soome __asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "edx"); 344199767f8SToomas Soome return (low); 345199767f8SToomas Soome } 346199767f8SToomas Soome 347199767f8SToomas Soome static __inline uint64_t 348199767f8SToomas Soome rdpmc(u_int pmc) 349199767f8SToomas Soome { 350199767f8SToomas Soome uint64_t rv; 351199767f8SToomas Soome 352199767f8SToomas Soome __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc)); 353199767f8SToomas Soome return (rv); 354199767f8SToomas Soome } 355199767f8SToomas Soome 356199767f8SToomas Soome static __inline uint64_t 357199767f8SToomas Soome rdtsc(void) 358199767f8SToomas Soome { 359199767f8SToomas Soome uint64_t rv; 360199767f8SToomas Soome 361199767f8SToomas Soome __asm __volatile("rdtsc" : "=A" (rv)); 362199767f8SToomas Soome return (rv); 363199767f8SToomas Soome } 364199767f8SToomas Soome 365199767f8SToomas Soome static __inline uint32_t 366199767f8SToomas Soome rdtsc32(void) 367199767f8SToomas Soome { 368199767f8SToomas Soome uint32_t rv; 369199767f8SToomas Soome 370199767f8SToomas Soome __asm __volatile("rdtsc" : "=a" (rv) : : "edx"); 371199767f8SToomas Soome return (rv); 372199767f8SToomas Soome } 373199767f8SToomas Soome 374199767f8SToomas Soome static __inline void 375199767f8SToomas Soome wbinvd(void) 376199767f8SToomas Soome { 377199767f8SToomas Soome __asm __volatile("wbinvd"); 378199767f8SToomas Soome } 379199767f8SToomas Soome 380199767f8SToomas Soome static __inline void 381199767f8SToomas Soome write_eflags(u_int ef) 382199767f8SToomas Soome { 383199767f8SToomas Soome __asm __volatile("pushl %0; popfl" : : "r" (ef)); 384199767f8SToomas Soome } 385199767f8SToomas Soome 386199767f8SToomas Soome static __inline void 387199767f8SToomas Soome wrmsr(u_int msr, uint64_t newval) 388199767f8SToomas Soome { 389199767f8SToomas Soome __asm __volatile("wrmsr" : : "A" (newval), "c" (msr)); 390199767f8SToomas Soome } 391199767f8SToomas Soome 392199767f8SToomas Soome static __inline void 393199767f8SToomas Soome load_cr0(u_int data) 394199767f8SToomas Soome { 395199767f8SToomas Soome 396199767f8SToomas Soome __asm __volatile("movl %0,%%cr0" : : "r" (data)); 397199767f8SToomas Soome } 398199767f8SToomas Soome 399199767f8SToomas Soome static __inline u_int 400199767f8SToomas Soome rcr0(void) 401199767f8SToomas Soome { 402199767f8SToomas Soome u_int data; 403199767f8SToomas Soome 404199767f8SToomas Soome __asm __volatile("movl %%cr0,%0" : "=r" (data)); 405199767f8SToomas Soome return (data); 406199767f8SToomas Soome } 407199767f8SToomas Soome 408199767f8SToomas Soome static __inline u_int 409199767f8SToomas Soome rcr2(void) 410199767f8SToomas Soome { 411199767f8SToomas Soome u_int data; 412199767f8SToomas Soome 413199767f8SToomas Soome __asm __volatile("movl %%cr2,%0" : "=r" (data)); 414199767f8SToomas Soome return (data); 415199767f8SToomas Soome } 416199767f8SToomas Soome 417199767f8SToomas Soome static __inline void 418199767f8SToomas Soome load_cr3(u_int data) 419199767f8SToomas Soome { 420199767f8SToomas Soome 421199767f8SToomas Soome __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory"); 422199767f8SToomas Soome } 423199767f8SToomas Soome 424199767f8SToomas Soome static __inline u_int 425199767f8SToomas Soome rcr3(void) 426199767f8SToomas Soome { 427199767f8SToomas Soome u_int data; 428199767f8SToomas Soome 429199767f8SToomas Soome __asm __volatile("movl %%cr3,%0" : "=r" (data)); 430199767f8SToomas Soome return (data); 431199767f8SToomas Soome } 432199767f8SToomas Soome 433199767f8SToomas Soome static __inline void 434199767f8SToomas Soome load_cr4(u_int data) 435199767f8SToomas Soome { 436199767f8SToomas Soome __asm __volatile("movl %0,%%cr4" : : "r" (data)); 437199767f8SToomas Soome } 438199767f8SToomas Soome 439199767f8SToomas Soome static __inline u_int 440199767f8SToomas Soome rcr4(void) 441199767f8SToomas Soome { 442199767f8SToomas Soome u_int data; 443199767f8SToomas Soome 444199767f8SToomas Soome __asm __volatile("movl %%cr4,%0" : "=r" (data)); 445199767f8SToomas Soome return (data); 446199767f8SToomas Soome } 447199767f8SToomas Soome 448199767f8SToomas Soome static __inline uint64_t 449199767f8SToomas Soome rxcr(u_int reg) 450199767f8SToomas Soome { 451199767f8SToomas Soome u_int low, high; 452199767f8SToomas Soome 453199767f8SToomas Soome __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 454199767f8SToomas Soome return (low | ((uint64_t)high << 32)); 455199767f8SToomas Soome } 456199767f8SToomas Soome 457199767f8SToomas Soome static __inline void 458199767f8SToomas Soome load_xcr(u_int reg, uint64_t val) 459199767f8SToomas Soome { 460199767f8SToomas Soome u_int low, high; 461199767f8SToomas Soome 462199767f8SToomas Soome low = val; 463199767f8SToomas Soome high = val >> 32; 464199767f8SToomas Soome __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 465199767f8SToomas Soome } 466199767f8SToomas Soome 467199767f8SToomas Soome /* 468199767f8SToomas Soome * Global TLB flush (except for thise for pages marked PG_G) 469199767f8SToomas Soome */ 470199767f8SToomas Soome static __inline void 471199767f8SToomas Soome invltlb(void) 472199767f8SToomas Soome { 473199767f8SToomas Soome 474199767f8SToomas Soome load_cr3(rcr3()); 475199767f8SToomas Soome } 476199767f8SToomas Soome 477199767f8SToomas Soome /* 478199767f8SToomas Soome * TLB flush for an individual page (even if it has PG_G). 479199767f8SToomas Soome * Only works on 486+ CPUs (i386 does not have PG_G). 480199767f8SToomas Soome */ 481199767f8SToomas Soome static __inline void 482199767f8SToomas Soome invlpg(u_int addr) 483199767f8SToomas Soome { 484199767f8SToomas Soome 485199767f8SToomas Soome __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 486199767f8SToomas Soome } 487199767f8SToomas Soome 488199767f8SToomas Soome static __inline u_short 489199767f8SToomas Soome rfs(void) 490199767f8SToomas Soome { 491199767f8SToomas Soome u_short sel; 492199767f8SToomas Soome __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 493199767f8SToomas Soome return (sel); 494199767f8SToomas Soome } 495199767f8SToomas Soome 496199767f8SToomas Soome static __inline uint64_t 497199767f8SToomas Soome rgdt(void) 498199767f8SToomas Soome { 499199767f8SToomas Soome uint64_t gdtr; 500199767f8SToomas Soome __asm __volatile("sgdt %0" : "=m" (gdtr)); 501199767f8SToomas Soome return (gdtr); 502199767f8SToomas Soome } 503199767f8SToomas Soome 504199767f8SToomas Soome static __inline u_short 505199767f8SToomas Soome rgs(void) 506199767f8SToomas Soome { 507199767f8SToomas Soome u_short sel; 508199767f8SToomas Soome __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 509199767f8SToomas Soome return (sel); 510199767f8SToomas Soome } 511199767f8SToomas Soome 512199767f8SToomas Soome static __inline uint64_t 513199767f8SToomas Soome ridt(void) 514199767f8SToomas Soome { 515199767f8SToomas Soome uint64_t idtr; 516199767f8SToomas Soome __asm __volatile("sidt %0" : "=m" (idtr)); 517199767f8SToomas Soome return (idtr); 518199767f8SToomas Soome } 519199767f8SToomas Soome 520199767f8SToomas Soome static __inline u_short 521199767f8SToomas Soome rldt(void) 522199767f8SToomas Soome { 523199767f8SToomas Soome u_short ldtr; 524199767f8SToomas Soome __asm __volatile("sldt %0" : "=g" (ldtr)); 525199767f8SToomas Soome return (ldtr); 526199767f8SToomas Soome } 527199767f8SToomas Soome 528199767f8SToomas Soome static __inline u_short 529199767f8SToomas Soome rss(void) 530199767f8SToomas Soome { 531199767f8SToomas Soome u_short sel; 532199767f8SToomas Soome __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 533199767f8SToomas Soome return (sel); 534199767f8SToomas Soome } 535199767f8SToomas Soome 536199767f8SToomas Soome static __inline u_short 537199767f8SToomas Soome rtr(void) 538199767f8SToomas Soome { 539199767f8SToomas Soome u_short tr; 540199767f8SToomas Soome __asm __volatile("str %0" : "=g" (tr)); 541199767f8SToomas Soome return (tr); 542199767f8SToomas Soome } 543199767f8SToomas Soome 544199767f8SToomas Soome static __inline void 545199767f8SToomas Soome load_fs(u_short sel) 546199767f8SToomas Soome { 547199767f8SToomas Soome __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 548199767f8SToomas Soome } 549199767f8SToomas Soome 550199767f8SToomas Soome static __inline void 551199767f8SToomas Soome load_gs(u_short sel) 552199767f8SToomas Soome { 553199767f8SToomas Soome __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 554199767f8SToomas Soome } 555199767f8SToomas Soome 556199767f8SToomas Soome static __inline void 557199767f8SToomas Soome lidt(struct region_descriptor *addr) 558199767f8SToomas Soome { 559199767f8SToomas Soome __asm __volatile("lidt (%0)" : : "r" (addr)); 560199767f8SToomas Soome } 561199767f8SToomas Soome 562199767f8SToomas Soome static __inline void 563199767f8SToomas Soome lldt(u_short sel) 564199767f8SToomas Soome { 565199767f8SToomas Soome __asm __volatile("lldt %0" : : "r" (sel)); 566199767f8SToomas Soome } 567199767f8SToomas Soome 568199767f8SToomas Soome static __inline void 569199767f8SToomas Soome ltr(u_short sel) 570199767f8SToomas Soome { 571199767f8SToomas Soome __asm __volatile("ltr %0" : : "r" (sel)); 572199767f8SToomas Soome } 573199767f8SToomas Soome 574199767f8SToomas Soome static __inline u_int 575199767f8SToomas Soome rdr0(void) 576199767f8SToomas Soome { 577199767f8SToomas Soome u_int data; 578199767f8SToomas Soome __asm __volatile("movl %%dr0,%0" : "=r" (data)); 579199767f8SToomas Soome return (data); 580199767f8SToomas Soome } 581199767f8SToomas Soome 582199767f8SToomas Soome static __inline void 583199767f8SToomas Soome load_dr0(u_int dr0) 584199767f8SToomas Soome { 585199767f8SToomas Soome __asm __volatile("movl %0,%%dr0" : : "r" (dr0)); 586199767f8SToomas Soome } 587199767f8SToomas Soome 588199767f8SToomas Soome static __inline u_int 589199767f8SToomas Soome rdr1(void) 590199767f8SToomas Soome { 591199767f8SToomas Soome u_int data; 592199767f8SToomas Soome __asm __volatile("movl %%dr1,%0" : "=r" (data)); 593199767f8SToomas Soome return (data); 594199767f8SToomas Soome } 595199767f8SToomas Soome 596199767f8SToomas Soome static __inline void 597199767f8SToomas Soome load_dr1(u_int dr1) 598199767f8SToomas Soome { 599199767f8SToomas Soome __asm __volatile("movl %0,%%dr1" : : "r" (dr1)); 600199767f8SToomas Soome } 601199767f8SToomas Soome 602199767f8SToomas Soome static __inline u_int 603199767f8SToomas Soome rdr2(void) 604199767f8SToomas Soome { 605199767f8SToomas Soome u_int data; 606199767f8SToomas Soome __asm __volatile("movl %%dr2,%0" : "=r" (data)); 607199767f8SToomas Soome return (data); 608199767f8SToomas Soome } 609199767f8SToomas Soome 610199767f8SToomas Soome static __inline void 611199767f8SToomas Soome load_dr2(u_int dr2) 612199767f8SToomas Soome { 613199767f8SToomas Soome __asm __volatile("movl %0,%%dr2" : : "r" (dr2)); 614199767f8SToomas Soome } 615199767f8SToomas Soome 616199767f8SToomas Soome static __inline u_int 617199767f8SToomas Soome rdr3(void) 618199767f8SToomas Soome { 619199767f8SToomas Soome u_int data; 620199767f8SToomas Soome __asm __volatile("movl %%dr3,%0" : "=r" (data)); 621199767f8SToomas Soome return (data); 622199767f8SToomas Soome } 623199767f8SToomas Soome 624199767f8SToomas Soome static __inline void 625199767f8SToomas Soome load_dr3(u_int dr3) 626199767f8SToomas Soome { 627199767f8SToomas Soome __asm __volatile("movl %0,%%dr3" : : "r" (dr3)); 628199767f8SToomas Soome } 629199767f8SToomas Soome 630199767f8SToomas Soome static __inline u_int 631199767f8SToomas Soome rdr4(void) 632199767f8SToomas Soome { 633199767f8SToomas Soome u_int data; 634199767f8SToomas Soome __asm __volatile("movl %%dr4,%0" : "=r" (data)); 635199767f8SToomas Soome return (data); 636199767f8SToomas Soome } 637199767f8SToomas Soome 638199767f8SToomas Soome static __inline void 639199767f8SToomas Soome load_dr4(u_int dr4) 640199767f8SToomas Soome { 641199767f8SToomas Soome __asm __volatile("movl %0,%%dr4" : : "r" (dr4)); 642199767f8SToomas Soome } 643199767f8SToomas Soome 644199767f8SToomas Soome static __inline u_int 645199767f8SToomas Soome rdr5(void) 646199767f8SToomas Soome { 647199767f8SToomas Soome u_int data; 648199767f8SToomas Soome __asm __volatile("movl %%dr5,%0" : "=r" (data)); 649199767f8SToomas Soome return (data); 650199767f8SToomas Soome } 651199767f8SToomas Soome 652199767f8SToomas Soome static __inline void 653199767f8SToomas Soome load_dr5(u_int dr5) 654199767f8SToomas Soome { 655199767f8SToomas Soome __asm __volatile("movl %0,%%dr5" : : "r" (dr5)); 656199767f8SToomas Soome } 657199767f8SToomas Soome 658199767f8SToomas Soome static __inline u_int 659199767f8SToomas Soome rdr6(void) 660199767f8SToomas Soome { 661199767f8SToomas Soome u_int data; 662199767f8SToomas Soome __asm __volatile("movl %%dr6,%0" : "=r" (data)); 663199767f8SToomas Soome return (data); 664199767f8SToomas Soome } 665199767f8SToomas Soome 666199767f8SToomas Soome static __inline void 667199767f8SToomas Soome load_dr6(u_int dr6) 668199767f8SToomas Soome { 669199767f8SToomas Soome __asm __volatile("movl %0,%%dr6" : : "r" (dr6)); 670199767f8SToomas Soome } 671199767f8SToomas Soome 672199767f8SToomas Soome static __inline u_int 673199767f8SToomas Soome rdr7(void) 674199767f8SToomas Soome { 675199767f8SToomas Soome u_int data; 676199767f8SToomas Soome __asm __volatile("movl %%dr7,%0" : "=r" (data)); 677199767f8SToomas Soome return (data); 678199767f8SToomas Soome } 679199767f8SToomas Soome 680199767f8SToomas Soome static __inline void 681199767f8SToomas Soome load_dr7(u_int dr7) 682199767f8SToomas Soome { 683199767f8SToomas Soome __asm __volatile("movl %0,%%dr7" : : "r" (dr7)); 684199767f8SToomas Soome } 685199767f8SToomas Soome 686199767f8SToomas Soome static __inline u_char 687199767f8SToomas Soome read_cyrix_reg(u_char reg) 688199767f8SToomas Soome { 689199767f8SToomas Soome outb(0x22, reg); 690199767f8SToomas Soome return inb(0x23); 691199767f8SToomas Soome } 692199767f8SToomas Soome 693199767f8SToomas Soome static __inline void 694199767f8SToomas Soome write_cyrix_reg(u_char reg, u_char data) 695199767f8SToomas Soome { 696199767f8SToomas Soome outb(0x22, reg); 697199767f8SToomas Soome outb(0x23, data); 698199767f8SToomas Soome } 699199767f8SToomas Soome 700199767f8SToomas Soome static __inline register_t 701199767f8SToomas Soome intr_disable(void) 702199767f8SToomas Soome { 703199767f8SToomas Soome register_t eflags; 704199767f8SToomas Soome 705199767f8SToomas Soome eflags = read_eflags(); 706199767f8SToomas Soome disable_intr(); 707199767f8SToomas Soome return (eflags); 708199767f8SToomas Soome } 709199767f8SToomas Soome 710199767f8SToomas Soome static __inline void 711199767f8SToomas Soome intr_restore(register_t eflags) 712199767f8SToomas Soome { 713199767f8SToomas Soome write_eflags(eflags); 714199767f8SToomas Soome } 715199767f8SToomas Soome 716199767f8SToomas Soome #else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 717199767f8SToomas Soome 718199767f8SToomas Soome int breakpoint(void); 719199767f8SToomas Soome u_int bsfl(u_int mask); 720199767f8SToomas Soome u_int bsrl(u_int mask); 721199767f8SToomas Soome void clflush(u_long addr); 722199767f8SToomas Soome void clts(void); 723199767f8SToomas Soome void cpuid_count(u_int ax, u_int cx, u_int *p); 724199767f8SToomas Soome void disable_intr(void); 725199767f8SToomas Soome void do_cpuid(u_int ax, u_int *p); 726199767f8SToomas Soome void enable_intr(void); 727199767f8SToomas Soome void halt(void); 728199767f8SToomas Soome void ia32_pause(void); 729199767f8SToomas Soome u_char inb(u_int port); 730199767f8SToomas Soome u_int inl(u_int port); 731199767f8SToomas Soome void insb(u_int port, void *addr, size_t count); 732199767f8SToomas Soome void insl(u_int port, void *addr, size_t count); 733199767f8SToomas Soome void insw(u_int port, void *addr, size_t count); 734199767f8SToomas Soome register_t intr_disable(void); 735199767f8SToomas Soome void intr_restore(register_t ef); 736199767f8SToomas Soome void invd(void); 737199767f8SToomas Soome void invlpg(u_int addr); 738199767f8SToomas Soome void invltlb(void); 739199767f8SToomas Soome u_short inw(u_int port); 740199767f8SToomas Soome void lidt(struct region_descriptor *addr); 741199767f8SToomas Soome void lldt(u_short sel); 742199767f8SToomas Soome void load_cr0(u_int cr0); 743199767f8SToomas Soome void load_cr3(u_int cr3); 744199767f8SToomas Soome void load_cr4(u_int cr4); 745199767f8SToomas Soome void load_dr0(u_int dr0); 746199767f8SToomas Soome void load_dr1(u_int dr1); 747199767f8SToomas Soome void load_dr2(u_int dr2); 748199767f8SToomas Soome void load_dr3(u_int dr3); 749199767f8SToomas Soome void load_dr4(u_int dr4); 750199767f8SToomas Soome void load_dr5(u_int dr5); 751199767f8SToomas Soome void load_dr6(u_int dr6); 752199767f8SToomas Soome void load_dr7(u_int dr7); 753199767f8SToomas Soome void load_fs(u_short sel); 754199767f8SToomas Soome void load_gs(u_short sel); 755199767f8SToomas Soome void ltr(u_short sel); 756199767f8SToomas Soome void outb(u_int port, u_char data); 757199767f8SToomas Soome void outl(u_int port, u_int data); 758199767f8SToomas Soome void outsb(u_int port, const void *addr, size_t count); 759199767f8SToomas Soome void outsl(u_int port, const void *addr, size_t count); 760199767f8SToomas Soome void outsw(u_int port, const void *addr, size_t count); 761199767f8SToomas Soome void outw(u_int port, u_short data); 762199767f8SToomas Soome u_int rcr0(void); 763199767f8SToomas Soome u_int rcr2(void); 764199767f8SToomas Soome u_int rcr3(void); 765199767f8SToomas Soome u_int rcr4(void); 766199767f8SToomas Soome uint64_t rdmsr(u_int msr); 767199767f8SToomas Soome uint64_t rdpmc(u_int pmc); 768199767f8SToomas Soome u_int rdr0(void); 769199767f8SToomas Soome u_int rdr1(void); 770199767f8SToomas Soome u_int rdr2(void); 771199767f8SToomas Soome u_int rdr3(void); 772199767f8SToomas Soome u_int rdr4(void); 773199767f8SToomas Soome u_int rdr5(void); 774199767f8SToomas Soome u_int rdr6(void); 775199767f8SToomas Soome u_int rdr7(void); 776199767f8SToomas Soome uint64_t rdtsc(void); 777199767f8SToomas Soome u_char read_cyrix_reg(u_char reg); 778199767f8SToomas Soome u_int read_eflags(void); 779199767f8SToomas Soome u_int rfs(void); 780199767f8SToomas Soome uint64_t rgdt(void); 781199767f8SToomas Soome u_int rgs(void); 782199767f8SToomas Soome uint64_t ridt(void); 783199767f8SToomas Soome u_short rldt(void); 784199767f8SToomas Soome u_short rtr(void); 785199767f8SToomas Soome void wbinvd(void); 786199767f8SToomas Soome void write_cyrix_reg(u_char reg, u_char data); 787199767f8SToomas Soome void write_eflags(u_int ef); 788199767f8SToomas Soome void wrmsr(u_int msr, uint64_t newval); 789199767f8SToomas Soome 790199767f8SToomas Soome #endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 791199767f8SToomas Soome 792199767f8SToomas Soome void reset_dbregs(void); 793199767f8SToomas Soome 794199767f8SToomas Soome #ifdef _KERNEL 795199767f8SToomas Soome int rdmsr_safe(u_int msr, uint64_t *val); 796199767f8SToomas Soome int wrmsr_safe(u_int msr, uint64_t newval); 797199767f8SToomas Soome #endif 798199767f8SToomas Soome 799199767f8SToomas Soome #endif /* !_MACHINE_CPUFUNC_H_ */ 800