13c4dd356SDavid Greenman /*- 251369649SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 351369649SPedro F. Giffuni * 43c4dd356SDavid Greenman * Copyright (c) 1993 The Regents of the University of California. 53c4dd356SDavid Greenman * All rights reserved. 63c4dd356SDavid Greenman * 73c4dd356SDavid Greenman * Redistribution and use in source and binary forms, with or without 83c4dd356SDavid Greenman * modification, are permitted provided that the following conditions 93c4dd356SDavid Greenman * are met: 103c4dd356SDavid Greenman * 1. Redistributions of source code must retain the above copyright 113c4dd356SDavid Greenman * notice, this list of conditions and the following disclaimer. 123c4dd356SDavid Greenman * 2. Redistributions in binary form must reproduce the above copyright 133c4dd356SDavid Greenman * notice, this list of conditions and the following disclaimer in the 143c4dd356SDavid Greenman * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 163c4dd356SDavid Greenman * may be used to endorse or promote products derived from this software 173c4dd356SDavid Greenman * without specific prior written permission. 183c4dd356SDavid Greenman * 193c4dd356SDavid Greenman * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 203c4dd356SDavid Greenman * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 213c4dd356SDavid Greenman * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 223c4dd356SDavid Greenman * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 233c4dd356SDavid Greenman * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 243c4dd356SDavid Greenman * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 253c4dd356SDavid Greenman * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 263c4dd356SDavid Greenman * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 273c4dd356SDavid Greenman * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 283c4dd356SDavid Greenman * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 293c4dd356SDavid Greenman * SUCH DAMAGE. 303c4dd356SDavid Greenman */ 313c4dd356SDavid Greenman 325b81b6b3SRodney W. Grimes /* 335b81b6b3SRodney W. Grimes * Functions to provide access to special i386 instructions. 34f5d9a10bSMark Murray * This in included in sys/systm.h, and that file should be 35f5d9a10bSMark Murray * used in preference to this. 365b81b6b3SRodney W. Grimes */ 375b81b6b3SRodney W. Grimes 386e393973SGarrett Wollman #ifndef _MACHINE_CPUFUNC_H_ 39004bedebSBruce Evans #define _MACHINE_CPUFUNC_H_ 406e393973SGarrett Wollman 41eb1443c8SPeter Wemm struct region_descriptor; 42d74ac681SMatthew Dillon 43f54c13eaSJung-uk Kim #define readb(va) (*(volatile uint8_t *) (va)) 44f54c13eaSJung-uk Kim #define readw(va) (*(volatile uint16_t *) (va)) 45f54c13eaSJung-uk Kim #define readl(va) (*(volatile uint32_t *) (va)) 46e31fa854SDoug Rabson 47f54c13eaSJung-uk Kim #define writeb(va, d) (*(volatile uint8_t *) (va) = (d)) 48f54c13eaSJung-uk Kim #define writew(va, d) (*(volatile uint16_t *) (va) = (d)) 49f54c13eaSJung-uk Kim #define writel(va, d) (*(volatile uint32_t *) (va) = (d)) 50e31fa854SDoug Rabson 515dbd168eSBruce Evans static __inline void 525dbd168eSBruce Evans breakpoint(void) 53004bedebSBruce Evans { 54004bedebSBruce Evans __asm __volatile("int $3"); 555b81b6b3SRodney W. Grimes } 565b81b6b3SRodney W. Grimes 576f240e18SConrad Meyer static __inline __pure2 u_int 58c83b1328SBruce Evans bsfl(u_int mask) 59c83b1328SBruce Evans { 60c83b1328SBruce Evans u_int result; 61c83b1328SBruce Evans 622b7ceeb0SEd Schouten __asm("bsfl %1,%0" : "=r" (result) : "rm" (mask) : "cc"); 63c83b1328SBruce Evans return (result); 64c83b1328SBruce Evans } 65c83b1328SBruce Evans 66004bedebSBruce Evans static __inline void 678a5ac5d5SKonstantin Belousov clflush(u_long addr) 688a5ac5d5SKonstantin Belousov { 698a5ac5d5SKonstantin Belousov 708a5ac5d5SKonstantin Belousov __asm __volatile("clflush %0" : : "m" (*(char *)addr)); 718a5ac5d5SKonstantin Belousov } 728a5ac5d5SKonstantin Belousov 738a5ac5d5SKonstantin Belousov static __inline void 743f8e0710SKonstantin Belousov clflushopt(u_long addr) 753f8e0710SKonstantin Belousov { 763f8e0710SKonstantin Belousov 7705f10487SKonstantin Belousov __asm __volatile(".byte 0x66;clflush %0" : : "m" (*(char *)addr)); 783f8e0710SKonstantin Belousov } 793f8e0710SKonstantin Belousov 803f8e0710SKonstantin Belousov static __inline void 81d706ec29SJohn Baldwin clts(void) 82d706ec29SJohn Baldwin { 83d706ec29SJohn Baldwin 84d706ec29SJohn Baldwin __asm __volatile("clts"); 85d706ec29SJohn Baldwin } 86d706ec29SJohn Baldwin 87d706ec29SJohn Baldwin static __inline void 885b81b6b3SRodney W. Grimes disable_intr(void) 895b81b6b3SRodney W. Grimes { 908966b85cSJohn Dyson __asm __volatile("cli" : : : "memory"); 915b81b6b3SRodney W. Grimes } 925b81b6b3SRodney W. Grimes 93642bb66bSKonstantin Belousov #ifdef _KERNEL 94004bedebSBruce Evans static __inline void 95a983fdfeSDavid Malone do_cpuid(u_int ax, u_int *p) 96a983fdfeSDavid Malone { 97a983fdfeSDavid Malone __asm __volatile("cpuid" 98a983fdfeSDavid Malone : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 99a983fdfeSDavid Malone : "0" (ax)); 100a983fdfeSDavid Malone } 101a983fdfeSDavid Malone 102a983fdfeSDavid Malone static __inline void 103f6108b61SJacques Vidrine cpuid_count(u_int ax, u_int cx, u_int *p) 104f6108b61SJacques Vidrine { 105f6108b61SJacques Vidrine __asm __volatile("cpuid" 106f6108b61SJacques Vidrine : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 107f6108b61SJacques Vidrine : "0" (ax), "c" (cx)); 108f6108b61SJacques Vidrine } 109642bb66bSKonstantin Belousov #else 110642bb66bSKonstantin Belousov static __inline void 111642bb66bSKonstantin Belousov do_cpuid(u_int ax, u_int *p) 112642bb66bSKonstantin Belousov { 113642bb66bSKonstantin Belousov __asm __volatile( 114642bb66bSKonstantin Belousov "pushl\t%%ebx\n\t" 115642bb66bSKonstantin Belousov "cpuid\n\t" 116642bb66bSKonstantin Belousov "movl\t%%ebx,%1\n\t" 117642bb66bSKonstantin Belousov "popl\t%%ebx" 118642bb66bSKonstantin Belousov : "=a" (p[0]), "=DS" (p[1]), "=c" (p[2]), "=d" (p[3]) 119642bb66bSKonstantin Belousov : "0" (ax)); 120642bb66bSKonstantin Belousov } 121642bb66bSKonstantin Belousov 122642bb66bSKonstantin Belousov static __inline void 123642bb66bSKonstantin Belousov cpuid_count(u_int ax, u_int cx, u_int *p) 124642bb66bSKonstantin Belousov { 125642bb66bSKonstantin Belousov __asm __volatile( 126642bb66bSKonstantin Belousov "pushl\t%%ebx\n\t" 127642bb66bSKonstantin Belousov "cpuid\n\t" 128642bb66bSKonstantin Belousov "movl\t%%ebx,%1\n\t" 129642bb66bSKonstantin Belousov "popl\t%%ebx" 130642bb66bSKonstantin Belousov : "=a" (p[0]), "=DS" (p[1]), "=c" (p[2]), "=d" (p[3]) 131642bb66bSKonstantin Belousov : "0" (ax), "c" (cx)); 132642bb66bSKonstantin Belousov } 133642bb66bSKonstantin Belousov #endif 134f6108b61SJacques Vidrine 135f6108b61SJacques Vidrine static __inline void 1365b81b6b3SRodney W. Grimes enable_intr(void) 1375b81b6b3SRodney W. Grimes { 138fadc51bdSBruce Evans __asm __volatile("sti"); 1395b81b6b3SRodney W. Grimes } 1405b81b6b3SRodney W. Grimes 141beb2c1f3SAndriy Gapon static __inline void 142f0b28f00SJung-uk Kim cpu_monitor(const void *addr, u_long extensions, u_int hints) 14366247efaSJeff Roberson { 144f0b28f00SJung-uk Kim __asm __volatile("monitor" 14566247efaSJeff Roberson : : "a" (addr), "c" (extensions), "d" (hints)); 14666247efaSJeff Roberson } 14766247efaSJeff Roberson 148beb2c1f3SAndriy Gapon static __inline void 149f0b28f00SJung-uk Kim cpu_mwait(u_long extensions, u_int hints) 15066247efaSJeff Roberson { 151f0b28f00SJung-uk Kim __asm __volatile("mwait" : : "a" (hints), "c" (extensions)); 15266247efaSJeff Roberson } 15366247efaSJeff Roberson 1548a5ac5d5SKonstantin Belousov static __inline void 1550220d04fSKonstantin Belousov lfence(void) 1560220d04fSKonstantin Belousov { 1570220d04fSKonstantin Belousov __asm __volatile("lfence" : : : "memory"); 1580220d04fSKonstantin Belousov } 1590220d04fSKonstantin Belousov 1600220d04fSKonstantin Belousov static __inline void 1618a5ac5d5SKonstantin Belousov mfence(void) 1628a5ac5d5SKonstantin Belousov { 1638a5ac5d5SKonstantin Belousov __asm __volatile("mfence" : : : "memory"); 1648a5ac5d5SKonstantin Belousov } 1658a5ac5d5SKonstantin Belousov 1665611aaa1SKonstantin Belousov static __inline void 1675611aaa1SKonstantin Belousov sfence(void) 1685611aaa1SKonstantin Belousov { 1695611aaa1SKonstantin Belousov __asm __volatile("sfence" : : : "memory"); 1705611aaa1SKonstantin Belousov } 1715611aaa1SKonstantin Belousov 172d7ee4425SMark Murray static __inline void 173d7ee4425SMark Murray halt(void) 174d7ee4425SMark Murray { 175d7ee4425SMark Murray __asm __volatile("hlt"); 176d7ee4425SMark Murray } 177d7ee4425SMark Murray 178004bedebSBruce Evans static __inline u_char 179e1048f76SEd Schouten inb(u_int port) 180004bedebSBruce Evans { 181004bedebSBruce Evans u_char data; 182004bedebSBruce Evans 1834854ae24SJung-uk Kim __asm __volatile("inb %w1, %0" : "=a" (data) : "Nd" (port)); 184004bedebSBruce Evans return (data); 185004bedebSBruce Evans } 186004bedebSBruce Evans 18700be8601SBruce Evans static __inline u_int 188004bedebSBruce Evans inl(u_int port) 189004bedebSBruce Evans { 19000be8601SBruce Evans u_int data; 191004bedebSBruce Evans 1924854ae24SJung-uk Kim __asm __volatile("inl %w1, %0" : "=a" (data) : "Nd" (port)); 193004bedebSBruce Evans return (data); 194004bedebSBruce Evans } 195004bedebSBruce Evans 196004bedebSBruce Evans static __inline void 19793d8be03SDavid E. O'Brien insb(u_int port, void *addr, size_t count) 198004bedebSBruce Evans { 199004bedebSBruce Evans __asm __volatile("cld; rep; insb" 20093d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2013f9a462fSJohn Baldwin : "d" (port) 202896763faSBruce Evans : "memory"); 203004bedebSBruce Evans } 204004bedebSBruce Evans 205004bedebSBruce Evans static __inline void 20693d8be03SDavid E. O'Brien insw(u_int port, void *addr, size_t count) 207004bedebSBruce Evans { 208004bedebSBruce Evans __asm __volatile("cld; rep; insw" 20993d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2103f9a462fSJohn Baldwin : "d" (port) 211896763faSBruce Evans : "memory"); 212004bedebSBruce Evans } 213004bedebSBruce Evans 214004bedebSBruce Evans static __inline void 21593d8be03SDavid E. O'Brien insl(u_int port, void *addr, size_t count) 216004bedebSBruce Evans { 217004bedebSBruce Evans __asm __volatile("cld; rep; insl" 21893d8be03SDavid E. O'Brien : "+D" (addr), "+c" (count) 2193f9a462fSJohn Baldwin : "d" (port) 220896763faSBruce Evans : "memory"); 221004bedebSBruce Evans } 222004bedebSBruce Evans 223ece15d78SBruce Evans static __inline void 2244c024bbdSKATO Takenori invd(void) 2254c024bbdSKATO Takenori { 2264c024bbdSKATO Takenori __asm __volatile("invd"); 2274c024bbdSKATO Takenori } 2284c024bbdSKATO Takenori 229004bedebSBruce Evans static __inline u_short 230004bedebSBruce Evans inw(u_int port) 231004bedebSBruce Evans { 232004bedebSBruce Evans u_short data; 233004bedebSBruce Evans 2344854ae24SJung-uk Kim __asm __volatile("inw %w1, %0" : "=a" (data) : "Nd" (port)); 235004bedebSBruce Evans return (data); 236004bedebSBruce Evans } 237004bedebSBruce Evans 238004bedebSBruce Evans static __inline void 239e1048f76SEd Schouten outb(u_int port, u_char data) 240004bedebSBruce Evans { 241e1048f76SEd Schouten __asm __volatile("outb %0, %w1" : : "a" (data), "Nd" (port)); 242004bedebSBruce Evans } 243004bedebSBruce Evans 244004bedebSBruce Evans static __inline void 24500be8601SBruce Evans outl(u_int port, u_int data) 246004bedebSBruce Evans { 2474854ae24SJung-uk Kim __asm __volatile("outl %0, %w1" : : "a" (data), "Nd" (port)); 248004bedebSBruce Evans } 249004bedebSBruce Evans 250004bedebSBruce Evans static __inline void 25193d8be03SDavid E. O'Brien outsb(u_int port, const void *addr, size_t count) 252004bedebSBruce Evans { 253004bedebSBruce Evans __asm __volatile("cld; rep; outsb" 25493d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2553f9a462fSJohn Baldwin : "d" (port)); 256004bedebSBruce Evans } 257004bedebSBruce Evans 258004bedebSBruce Evans static __inline void 25993d8be03SDavid E. O'Brien outsw(u_int port, const void *addr, size_t count) 260004bedebSBruce Evans { 261004bedebSBruce Evans __asm __volatile("cld; rep; outsw" 26293d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2633f9a462fSJohn Baldwin : "d" (port)); 264004bedebSBruce Evans } 265004bedebSBruce Evans 266004bedebSBruce Evans static __inline void 26793d8be03SDavid E. O'Brien outsl(u_int port, const void *addr, size_t count) 268004bedebSBruce Evans { 269004bedebSBruce Evans __asm __volatile("cld; rep; outsl" 27093d8be03SDavid E. O'Brien : "+S" (addr), "+c" (count) 2713f9a462fSJohn Baldwin : "d" (port)); 272004bedebSBruce Evans } 273004bedebSBruce Evans 274004bedebSBruce Evans static __inline void 275004bedebSBruce Evans outw(u_int port, u_short data) 276004bedebSBruce Evans { 2774854ae24SJung-uk Kim __asm __volatile("outw %0, %w1" : : "a" (data), "Nd" (port)); 278004bedebSBruce Evans } 279004bedebSBruce Evans 2802be69f32SJohn Baldwin static __inline void 2816b8c6989SJohn Baldwin ia32_pause(void) 2822be69f32SJohn Baldwin { 2832be69f32SJohn Baldwin __asm __volatile("pause"); 2842be69f32SJohn Baldwin } 2852be69f32SJohn Baldwin 28600be8601SBruce Evans static __inline u_int 287004bedebSBruce Evans read_eflags(void) 2885b81b6b3SRodney W. Grimes { 28900be8601SBruce Evans u_int ef; 290004bedebSBruce Evans 291004bedebSBruce Evans __asm __volatile("pushfl; popl %0" : "=r" (ef)); 2928db02de8SPaul Richards return (ef); 2935b81b6b3SRodney W. Grimes } 2945b81b6b3SRodney W. Grimes 2953b3f2813SNate Lawson static __inline uint64_t 2965dbd168eSBruce Evans rdmsr(u_int msr) 2975dbd168eSBruce Evans { 2983b3f2813SNate Lawson uint64_t rv; 2995dbd168eSBruce Evans 30039413503SMark Murray __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr)); 3015dbd168eSBruce Evans return (rv); 3025dbd168eSBruce Evans } 3035dbd168eSBruce Evans 3044c918926SKonstantin Belousov static __inline uint32_t 3054c918926SKonstantin Belousov rdmsr32(u_int msr) 3064c918926SKonstantin Belousov { 3074c918926SKonstantin Belousov uint32_t low; 3084c918926SKonstantin Belousov 3094c918926SKonstantin Belousov __asm __volatile("rdmsr" : "=a" (low) : "c" (msr) : "edx"); 3104c918926SKonstantin Belousov return (low); 3114c918926SKonstantin Belousov } 3124c918926SKonstantin Belousov 3133b3f2813SNate Lawson static __inline uint64_t 3145dbd168eSBruce Evans rdpmc(u_int pmc) 3155dbd168eSBruce Evans { 3163b3f2813SNate Lawson uint64_t rv; 3175dbd168eSBruce Evans 31839413503SMark Murray __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc)); 3195dbd168eSBruce Evans return (rv); 3205dbd168eSBruce Evans } 3215dbd168eSBruce Evans 3223b3f2813SNate Lawson static __inline uint64_t 3235dbd168eSBruce Evans rdtsc(void) 3245dbd168eSBruce Evans { 3253b3f2813SNate Lawson uint64_t rv; 3265dbd168eSBruce Evans 32739413503SMark Murray __asm __volatile("rdtsc" : "=A" (rv)); 3285dbd168eSBruce Evans return (rv); 3295dbd168eSBruce Evans } 3305dbd168eSBruce Evans 33115504639SMatt Macy static __inline uint64_t 332*652ae7b1SAdam Fenn rdtsc_ordered_lfence(void) 333*652ae7b1SAdam Fenn { 334*652ae7b1SAdam Fenn lfence(); 335*652ae7b1SAdam Fenn return (rdtsc()); 336*652ae7b1SAdam Fenn } 337*652ae7b1SAdam Fenn 338*652ae7b1SAdam Fenn static __inline uint64_t 339*652ae7b1SAdam Fenn rdtsc_ordered_mfence(void) 340*652ae7b1SAdam Fenn { 341*652ae7b1SAdam Fenn mfence(); 342*652ae7b1SAdam Fenn return (rdtsc()); 343*652ae7b1SAdam Fenn } 344*652ae7b1SAdam Fenn 345*652ae7b1SAdam Fenn static __inline uint64_t 34615504639SMatt Macy rdtscp(void) 34715504639SMatt Macy { 34815504639SMatt Macy uint64_t rv; 34915504639SMatt Macy 350f090f675SMark Johnston __asm __volatile("rdtscp" : "=A" (rv) : : "ecx"); 35115504639SMatt Macy return (rv); 35215504639SMatt Macy } 35315504639SMatt Macy 354908e2772SAdam Fenn static __inline uint64_t 355908e2772SAdam Fenn rdtscp_aux(uint32_t *aux) 356908e2772SAdam Fenn { 357908e2772SAdam Fenn uint64_t rv; 358908e2772SAdam Fenn 359908e2772SAdam Fenn __asm __volatile("rdtscp" : "=A" (rv), "=c" (*aux)); 360908e2772SAdam Fenn return (rv); 361908e2772SAdam Fenn } 362908e2772SAdam Fenn 3630e727642SJung-uk Kim static __inline uint32_t 3640e727642SJung-uk Kim rdtsc32(void) 3650e727642SJung-uk Kim { 3660e727642SJung-uk Kim uint32_t rv; 3670e727642SJung-uk Kim 3680e727642SJung-uk Kim __asm __volatile("rdtsc" : "=a" (rv) : : "edx"); 3690e727642SJung-uk Kim return (rv); 3700e727642SJung-uk Kim } 3710e727642SJung-uk Kim 37245974de8SKonstantin Belousov static __inline uint32_t 37345974de8SKonstantin Belousov rdtscp32(void) 37445974de8SKonstantin Belousov { 37545974de8SKonstantin Belousov uint32_t rv; 37645974de8SKonstantin Belousov 37745974de8SKonstantin Belousov __asm __volatile("rdtscp" : "=a" (rv) : : "ecx", "edx"); 37845974de8SKonstantin Belousov return (rv); 37945974de8SKonstantin Belousov } 38045974de8SKonstantin Belousov 381004bedebSBruce Evans static __inline void 3824c024bbdSKATO Takenori wbinvd(void) 3834c024bbdSKATO Takenori { 3844c024bbdSKATO Takenori __asm __volatile("wbinvd"); 3854c024bbdSKATO Takenori } 3864c024bbdSKATO Takenori 3874c024bbdSKATO Takenori static __inline void 38800be8601SBruce Evans write_eflags(u_int ef) 3895b81b6b3SRodney W. Grimes { 390004bedebSBruce Evans __asm __volatile("pushl %0; popfl" : : "r" (ef)); 3915b81b6b3SRodney W. Grimes } 3925b81b6b3SRodney W. Grimes 393d69e8502SGarrett Wollman static __inline void 3943b3f2813SNate Lawson wrmsr(u_int msr, uint64_t newval) 395d69e8502SGarrett Wollman { 39639413503SMark Murray __asm __volatile("wrmsr" : : "A" (newval), "c" (msr)); 397d69e8502SGarrett Wollman } 398d69e8502SGarrett Wollman 399f1b665c8SPeter Wemm static __inline void 400f1b665c8SPeter Wemm load_cr0(u_int data) 401f1b665c8SPeter Wemm { 402f1b665c8SPeter Wemm 403f1b665c8SPeter Wemm __asm __volatile("movl %0,%%cr0" : : "r" (data)); 404f1b665c8SPeter Wemm } 405f1b665c8SPeter Wemm 406f1b665c8SPeter Wemm static __inline u_int 407f1b665c8SPeter Wemm rcr0(void) 408f1b665c8SPeter Wemm { 409f1b665c8SPeter Wemm u_int data; 410f1b665c8SPeter Wemm 411f1b665c8SPeter Wemm __asm __volatile("movl %%cr0,%0" : "=r" (data)); 412f1b665c8SPeter Wemm return (data); 413f1b665c8SPeter Wemm } 414f1b665c8SPeter Wemm 415f1b665c8SPeter Wemm static __inline u_int 416f1b665c8SPeter Wemm rcr2(void) 417f1b665c8SPeter Wemm { 418f1b665c8SPeter Wemm u_int data; 419f1b665c8SPeter Wemm 420f1b665c8SPeter Wemm __asm __volatile("movl %%cr2,%0" : "=r" (data)); 421f1b665c8SPeter Wemm return (data); 422f1b665c8SPeter Wemm } 423f1b665c8SPeter Wemm 424f1b665c8SPeter Wemm static __inline void 425f1b665c8SPeter Wemm load_cr3(u_int data) 426f1b665c8SPeter Wemm { 427ed95805eSJohn Baldwin 428f1b665c8SPeter Wemm __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory"); 429f1b665c8SPeter Wemm } 430f1b665c8SPeter Wemm 431f1b665c8SPeter Wemm static __inline u_int 432f1b665c8SPeter Wemm rcr3(void) 433f1b665c8SPeter Wemm { 434f1b665c8SPeter Wemm u_int data; 435f1b665c8SPeter Wemm 436f1b665c8SPeter Wemm __asm __volatile("movl %%cr3,%0" : "=r" (data)); 437f1b665c8SPeter Wemm return (data); 438f1b665c8SPeter Wemm } 439f1b665c8SPeter Wemm 440f1b665c8SPeter Wemm static __inline void 441f1b665c8SPeter Wemm load_cr4(u_int data) 442f1b665c8SPeter Wemm { 443f1b665c8SPeter Wemm __asm __volatile("movl %0,%%cr4" : : "r" (data)); 444f1b665c8SPeter Wemm } 445f1b665c8SPeter Wemm 446f1b665c8SPeter Wemm static __inline u_int 447f1b665c8SPeter Wemm rcr4(void) 448f1b665c8SPeter Wemm { 449f1b665c8SPeter Wemm u_int data; 450f1b665c8SPeter Wemm 451f1b665c8SPeter Wemm __asm __volatile("movl %%cr4,%0" : "=r" (data)); 452f1b665c8SPeter Wemm return (data); 453f1b665c8SPeter Wemm } 454f1b665c8SPeter Wemm 455824fc460SJohn Baldwin static __inline uint64_t 456824fc460SJohn Baldwin rxcr(u_int reg) 457824fc460SJohn Baldwin { 458824fc460SJohn Baldwin u_int low, high; 459824fc460SJohn Baldwin 460824fc460SJohn Baldwin __asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg)); 461824fc460SJohn Baldwin return (low | ((uint64_t)high << 32)); 462824fc460SJohn Baldwin } 463824fc460SJohn Baldwin 464824fc460SJohn Baldwin static __inline void 465824fc460SJohn Baldwin load_xcr(u_int reg, uint64_t val) 466824fc460SJohn Baldwin { 467824fc460SJohn Baldwin u_int low, high; 468824fc460SJohn Baldwin 469824fc460SJohn Baldwin low = val; 470824fc460SJohn Baldwin high = val >> 32; 471824fc460SJohn Baldwin __asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (high)); 472824fc460SJohn Baldwin } 473824fc460SJohn Baldwin 474f1b665c8SPeter Wemm /* 475f1b665c8SPeter Wemm * Global TLB flush (except for thise for pages marked PG_G) 476f1b665c8SPeter Wemm */ 477f1b665c8SPeter Wemm static __inline void 478f1b665c8SPeter Wemm invltlb(void) 479f1b665c8SPeter Wemm { 480ed95805eSJohn Baldwin 481f1b665c8SPeter Wemm load_cr3(rcr3()); 482f1b665c8SPeter Wemm } 483f1b665c8SPeter Wemm 484f1b665c8SPeter Wemm /* 485f1b665c8SPeter Wemm * TLB flush for an individual page (even if it has PG_G). 486f1b665c8SPeter Wemm * Only works on 486+ CPUs (i386 does not have PG_G). 487f1b665c8SPeter Wemm */ 488f1b665c8SPeter Wemm static __inline void 489f1b665c8SPeter Wemm invlpg(u_int addr) 490f1b665c8SPeter Wemm { 491f1b665c8SPeter Wemm 492f1b665c8SPeter Wemm __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 493f1b665c8SPeter Wemm } 494f1b665c8SPeter Wemm 49527d4fea6SRoman Divacky static __inline u_short 4965206bca1SLuoqi Chen rfs(void) 4975206bca1SLuoqi Chen { 49827d4fea6SRoman Divacky u_short sel; 49927d4fea6SRoman Divacky __asm __volatile("movw %%fs,%0" : "=rm" (sel)); 5005206bca1SLuoqi Chen return (sel); 5015206bca1SLuoqi Chen } 5025206bca1SLuoqi Chen 5033b3f2813SNate Lawson static __inline uint64_t 5043b3f2813SNate Lawson rgdt(void) 5053b3f2813SNate Lawson { 5063b3f2813SNate Lawson uint64_t gdtr; 5073b3f2813SNate Lawson __asm __volatile("sgdt %0" : "=m" (gdtr)); 5083b3f2813SNate Lawson return (gdtr); 5093b3f2813SNate Lawson } 5103b3f2813SNate Lawson 51127d4fea6SRoman Divacky static __inline u_short 5125206bca1SLuoqi Chen rgs(void) 5135206bca1SLuoqi Chen { 51427d4fea6SRoman Divacky u_short sel; 51527d4fea6SRoman Divacky __asm __volatile("movw %%gs,%0" : "=rm" (sel)); 5165206bca1SLuoqi Chen return (sel); 5175206bca1SLuoqi Chen } 5185206bca1SLuoqi Chen 5193b3f2813SNate Lawson static __inline uint64_t 5203b3f2813SNate Lawson ridt(void) 5213b3f2813SNate Lawson { 5223b3f2813SNate Lawson uint64_t idtr; 5233b3f2813SNate Lawson __asm __volatile("sidt %0" : "=m" (idtr)); 5243b3f2813SNate Lawson return (idtr); 5253b3f2813SNate Lawson } 5263b3f2813SNate Lawson 5273b3f2813SNate Lawson static __inline u_short 5283b3f2813SNate Lawson rldt(void) 5293b3f2813SNate Lawson { 5303b3f2813SNate Lawson u_short ldtr; 5313b3f2813SNate Lawson __asm __volatile("sldt %0" : "=g" (ldtr)); 5323b3f2813SNate Lawson return (ldtr); 5333b3f2813SNate Lawson } 5343b3f2813SNate Lawson 53527d4fea6SRoman Divacky static __inline u_short 53660aa1737SMarcel Moolenaar rss(void) 53760aa1737SMarcel Moolenaar { 53827d4fea6SRoman Divacky u_short sel; 53927d4fea6SRoman Divacky __asm __volatile("movw %%ss,%0" : "=rm" (sel)); 54060aa1737SMarcel Moolenaar return (sel); 54160aa1737SMarcel Moolenaar } 54260aa1737SMarcel Moolenaar 5433b3f2813SNate Lawson static __inline u_short 5443b3f2813SNate Lawson rtr(void) 5453b3f2813SNate Lawson { 5463b3f2813SNate Lawson u_short tr; 5473b3f2813SNate Lawson __asm __volatile("str %0" : "=g" (tr)); 5483b3f2813SNate Lawson return (tr); 5493b3f2813SNate Lawson } 5503b3f2813SNate Lawson 5515206bca1SLuoqi Chen static __inline void 55227d4fea6SRoman Divacky load_fs(u_short sel) 5535206bca1SLuoqi Chen { 55427d4fea6SRoman Divacky __asm __volatile("movw %0,%%fs" : : "rm" (sel)); 5555206bca1SLuoqi Chen } 5565206bca1SLuoqi Chen 5575206bca1SLuoqi Chen static __inline void 55827d4fea6SRoman Divacky load_gs(u_short sel) 5595206bca1SLuoqi Chen { 56027d4fea6SRoman Divacky __asm __volatile("movw %0,%%gs" : : "rm" (sel)); 5615206bca1SLuoqi Chen } 5625206bca1SLuoqi Chen 563eb1443c8SPeter Wemm static __inline void 564eb1443c8SPeter Wemm lidt(struct region_descriptor *addr) 565eb1443c8SPeter Wemm { 566eb1443c8SPeter Wemm __asm __volatile("lidt (%0)" : : "r" (addr)); 567eb1443c8SPeter Wemm } 568eb1443c8SPeter Wemm 569eb1443c8SPeter Wemm static __inline void 570eb1443c8SPeter Wemm lldt(u_short sel) 571eb1443c8SPeter Wemm { 572eb1443c8SPeter Wemm __asm __volatile("lldt %0" : : "r" (sel)); 573eb1443c8SPeter Wemm } 574eb1443c8SPeter Wemm 575eb1443c8SPeter Wemm static __inline void 576eb1443c8SPeter Wemm ltr(u_short sel) 577eb1443c8SPeter Wemm { 578eb1443c8SPeter Wemm __asm __volatile("ltr %0" : : "r" (sel)); 579eb1443c8SPeter Wemm } 580eb1443c8SPeter Wemm 581de8050f9SBrian S. Dean static __inline u_int 582de8050f9SBrian S. Dean rdr0(void) 583de8050f9SBrian S. Dean { 584de8050f9SBrian S. Dean u_int data; 58580275388SBrian S. Dean __asm __volatile("movl %%dr0,%0" : "=r" (data)); 586de8050f9SBrian S. Dean return (data); 587de8050f9SBrian S. Dean } 588de8050f9SBrian S. Dean 5896eda157eSBrian S. Dean static __inline void 59007508f90SJohn Baldwin load_dr0(u_int dr0) 5916eda157eSBrian S. Dean { 59207508f90SJohn Baldwin __asm __volatile("movl %0,%%dr0" : : "r" (dr0)); 5936eda157eSBrian S. Dean } 5946eda157eSBrian S. Dean 595de8050f9SBrian S. Dean static __inline u_int 596de8050f9SBrian S. Dean rdr1(void) 597de8050f9SBrian S. Dean { 598de8050f9SBrian S. Dean u_int data; 59980275388SBrian S. Dean __asm __volatile("movl %%dr1,%0" : "=r" (data)); 600de8050f9SBrian S. Dean return (data); 601de8050f9SBrian S. Dean } 602de8050f9SBrian S. Dean 6036eda157eSBrian S. Dean static __inline void 60407508f90SJohn Baldwin load_dr1(u_int dr1) 6056eda157eSBrian S. Dean { 60607508f90SJohn Baldwin __asm __volatile("movl %0,%%dr1" : : "r" (dr1)); 6076eda157eSBrian S. Dean } 6086eda157eSBrian S. Dean 609de8050f9SBrian S. Dean static __inline u_int 610de8050f9SBrian S. Dean rdr2(void) 611de8050f9SBrian S. Dean { 612de8050f9SBrian S. Dean u_int data; 61380275388SBrian S. Dean __asm __volatile("movl %%dr2,%0" : "=r" (data)); 614de8050f9SBrian S. Dean return (data); 615de8050f9SBrian S. Dean } 616de8050f9SBrian S. Dean 6176eda157eSBrian S. Dean static __inline void 61807508f90SJohn Baldwin load_dr2(u_int dr2) 6196eda157eSBrian S. Dean { 62007508f90SJohn Baldwin __asm __volatile("movl %0,%%dr2" : : "r" (dr2)); 6216eda157eSBrian S. Dean } 6226eda157eSBrian S. Dean 623de8050f9SBrian S. Dean static __inline u_int 624de8050f9SBrian S. Dean rdr3(void) 625de8050f9SBrian S. Dean { 626de8050f9SBrian S. Dean u_int data; 62780275388SBrian S. Dean __asm __volatile("movl %%dr3,%0" : "=r" (data)); 628de8050f9SBrian S. Dean return (data); 629de8050f9SBrian S. Dean } 630de8050f9SBrian S. Dean 6316eda157eSBrian S. Dean static __inline void 63207508f90SJohn Baldwin load_dr3(u_int dr3) 6336eda157eSBrian S. Dean { 63407508f90SJohn Baldwin __asm __volatile("movl %0,%%dr3" : : "r" (dr3)); 6356eda157eSBrian S. Dean } 6366eda157eSBrian S. Dean 6376eda157eSBrian S. Dean static __inline u_int 638de8050f9SBrian S. Dean rdr6(void) 639de8050f9SBrian S. Dean { 640de8050f9SBrian S. Dean u_int data; 64180275388SBrian S. Dean __asm __volatile("movl %%dr6,%0" : "=r" (data)); 642de8050f9SBrian S. Dean return (data); 643de8050f9SBrian S. Dean } 644de8050f9SBrian S. Dean 6456eda157eSBrian S. Dean static __inline void 64607508f90SJohn Baldwin load_dr6(u_int dr6) 6476eda157eSBrian S. Dean { 64807508f90SJohn Baldwin __asm __volatile("movl %0,%%dr6" : : "r" (dr6)); 6496eda157eSBrian S. Dean } 6506eda157eSBrian S. Dean 651de8050f9SBrian S. Dean static __inline u_int 652de8050f9SBrian S. Dean rdr7(void) 653de8050f9SBrian S. Dean { 654de8050f9SBrian S. Dean u_int data; 65580275388SBrian S. Dean __asm __volatile("movl %%dr7,%0" : "=r" (data)); 656de8050f9SBrian S. Dean return (data); 657de8050f9SBrian S. Dean } 658de8050f9SBrian S. Dean 6596eda157eSBrian S. Dean static __inline void 66007508f90SJohn Baldwin load_dr7(u_int dr7) 6616eda157eSBrian S. Dean { 66207508f90SJohn Baldwin __asm __volatile("movl %0,%%dr7" : : "r" (dr7)); 6636eda157eSBrian S. Dean } 6646eda157eSBrian S. Dean 66538a9df71SJohn Baldwin static __inline u_char 66638a9df71SJohn Baldwin read_cyrix_reg(u_char reg) 66738a9df71SJohn Baldwin { 66838a9df71SJohn Baldwin outb(0x22, reg); 66938a9df71SJohn Baldwin return inb(0x23); 67038a9df71SJohn Baldwin } 67138a9df71SJohn Baldwin 67238a9df71SJohn Baldwin static __inline void 67338a9df71SJohn Baldwin write_cyrix_reg(u_char reg, u_char data) 67438a9df71SJohn Baldwin { 67538a9df71SJohn Baldwin outb(0x22, reg); 67638a9df71SJohn Baldwin outb(0x23, data); 67738a9df71SJohn Baldwin } 67838a9df71SJohn Baldwin 679ba74981eSWarner Losh static __inline register_t 680ba74981eSWarner Losh intr_disable(void) 681ba74981eSWarner Losh { 68218bad857SKip Macy register_t eflags; 683ba74981eSWarner Losh 684ba74981eSWarner Losh eflags = read_eflags(); 685ba74981eSWarner Losh disable_intr(); 686ba74981eSWarner Losh return (eflags); 687ba74981eSWarner Losh } 688ba74981eSWarner Losh 689ba74981eSWarner Losh static __inline void 690ba74981eSWarner Losh intr_restore(register_t eflags) 691ba74981eSWarner Losh { 692ba74981eSWarner Losh write_eflags(eflags); 693ba74981eSWarner Losh } 694ba74981eSWarner Losh 6955ddeaf67SKonstantin Belousov static __inline uint32_t 6965ddeaf67SKonstantin Belousov rdpkru(void) 6975ddeaf67SKonstantin Belousov { 6985ddeaf67SKonstantin Belousov uint32_t res; 6995ddeaf67SKonstantin Belousov 7005ddeaf67SKonstantin Belousov __asm __volatile("rdpkru" : "=a" (res) : "c" (0) : "edx"); 7015ddeaf67SKonstantin Belousov return (res); 7025ddeaf67SKonstantin Belousov } 7035ddeaf67SKonstantin Belousov 7045ddeaf67SKonstantin Belousov static __inline void 7055ddeaf67SKonstantin Belousov wrpkru(uint32_t mask) 7065ddeaf67SKonstantin Belousov { 7075ddeaf67SKonstantin Belousov 7085ddeaf67SKonstantin Belousov __asm __volatile("wrpkru" : : "a" (mask), "c" (0), "d" (0)); 7095ddeaf67SKonstantin Belousov } 7105ddeaf67SKonstantin Belousov 711b63dc6adSAlfred Perlstein void reset_dbregs(void); 712d74ac681SMatthew Dillon 713e085f869SStanislav Sedov #ifdef _KERNEL 714e085f869SStanislav Sedov int rdmsr_safe(u_int msr, uint64_t *val); 715e085f869SStanislav Sedov int wrmsr_safe(u_int msr, uint64_t newval); 716e085f869SStanislav Sedov #endif 717e085f869SStanislav Sedov 718004bedebSBruce Evans #endif /* !_MACHINE_CPUFUNC_H_ */ 719