cpufunc.h revision 181911
1193323Sed/*- 2193323Sed * Copyright (c) 1993 The Regents of the University of California. 3193323Sed * All rights reserved. 4193323Sed * 5193323Sed * Redistribution and use in source and binary forms, with or without 6193323Sed * modification, are permitted provided that the following conditions 7193323Sed * are met: 8193323Sed * 1. Redistributions of source code must retain the above copyright 9193323Sed * notice, this list of conditions and the following disclaimer. 10193323Sed * 2. Redistributions in binary form must reproduce the above copyright 11249423Sdim * notice, this list of conditions and the following disclaimer in the 12193323Sed * documentation and/or other materials provided with the distribution. 13193323Sed * 4. Neither the name of the University nor the names of its contributors 14193323Sed * may be used to endorse or promote products derived from this software 15193323Sed * without specific prior written permission. 16234353Sdim * 17205407Srdivacky * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 18198090Srdivacky * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 19249423Sdim * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 20193323Sed * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 21193323Sed * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 22193323Sed * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 23193323Sed * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 24193323Sed * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 25193323Sed * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 26212904Sdim * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 27212904Sdim * SUCH DAMAGE. 28212904Sdim * 29212904Sdim * $FreeBSD: head/sys/i386/include/cpufunc.h 181911 2008-08-20 09:16:46Z kmacy $ 30212904Sdim */ 31234353Sdim 32212904Sdim/* 33212904Sdim * Functions to provide access to special i386 instructions. 34212904Sdim * This in included in sys/systm.h, and that file should be 35212904Sdim * used in preference to this. 36212904Sdim */ 37212904Sdim 38212904Sdim#ifndef _MACHINE_CPUFUNC_H_ 39243830Sdim#define _MACHINE_CPUFUNC_H_ 40243830Sdim 41243830Sdim#ifndef _SYS_CDEFS_H_ 42243830Sdim#error this file needs sys/cdefs.h as a prerequisite 43243830Sdim#endif 44243830Sdim 45243830Sdim#ifdef XEN 46243830Sdimextern void xen_cli(void); 47212904Sdimextern void xen_sti(void); 48193323Sedextern void xen_load_cr3(u_int data); 49193323Sedextern void xen_tlb_flush(void); 50193323Sedextern void xen_invlpg(u_int addr); 51193323Sedextern int xen_save_and_cli(void); 52193323Sedextern void xen_restore_flags(u_int eflags); 53193323Sed#endif 54288943Sdim 55288943Sdimstruct region_descriptor; 56193323Sed 57226633Sdim#define readb(va) (*(volatile u_int8_t *) (va)) 58226633Sdim#define readw(va) (*(volatile u_int16_t *) (va)) 59193323Sed#define readl(va) (*(volatile u_int32_t *) (va)) 60193323Sed 61193323Sed#define writeb(va, d) (*(volatile u_int8_t *) (va) = (d)) 62193323Sed#define writew(va, d) (*(volatile u_int16_t *) (va) = (d)) 63193323Sed#define writel(va, d) (*(volatile u_int32_t *) (va) = (d)) 64193323Sed 65193323Sed#if defined(__GNUCLIKE_ASM) && defined(__CC_SUPPORTS___INLINE) 66193323Sed 67193323Sedstatic __inline void 68193323Sedbreakpoint(void) 69193323Sed{ 70193323Sed __asm __volatile("int $3"); 71193323Sed} 72193323Sed 73193323Sedstatic __inline u_int 74193323Sedbsfl(u_int mask) 75198090Srdivacky{ 76193323Sed u_int result; 77193323Sed 78193323Sed __asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask)); 79193323Sed return (result); 80193323Sed} 81193323Sed 82193323Sedstatic __inline u_int 83223017Sdimbsrl(u_int mask) 84193323Sed{ 85193323Sed u_int result; 86193323Sed 87198090Srdivacky __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask)); 88198090Srdivacky return (result); 89193323Sed} 90193323Sed 91193323Sedstatic __inline void 92193323Seddisable_intr(void) 93193323Sed{ 94198090Srdivacky#ifdef XEN 95193323Sed xen_cli(); 96193323Sed#else 97193323Sed __asm __volatile("cli" : : : "memory"); 98193323Sed#endif 99193323Sed} 100193323Sed 101193323Sedstatic __inline void 102218893Sdimdo_cpuid(u_int ax, u_int *p) 103218893Sdim{ 104288943Sdim __asm __volatile("cpuid" 105288943Sdim : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 106251662Sdim : "0" (ax)); 107218893Sdim} 108218893Sdim 109218893Sdimstatic __inline void 110218893Sdimcpuid_count(u_int ax, u_int cx, u_int *p) 111218893Sdim{ 112218893Sdim __asm __volatile("cpuid" 113218893Sdim : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3]) 114288943Sdim : "0" (ax), "c" (cx)); 115218893Sdim} 116218893Sdim 117218893Sdimstatic __inline void 118218893Sdimenable_intr(void) 119218893Sdim{ 120218893Sdim#ifdef XEN 121218893Sdim xen_sti(); 122193323Sed#else 123193323Sed __asm __volatile("sti"); 124193323Sed#endif 125193323Sed} 126193323Sed 127218893Sdimstatic inline void 128218893Sdimcpu_monitor(const void *addr, int extensions, int hints) 129193323Sed{ 130193323Sed __asm __volatile("monitor;" 131193323Sed : :"a" (addr), "c" (extensions), "d"(hints)); 132193323Sed} 133193323Sed 134193323Sedstatic inline void 135193323Sedcpu_mwait(int extensions, int hints) 136193323Sed{ 137193323Sed __asm __volatile("mwait;" : :"a" (hints), "c" (extensions)); 138193323Sed} 139221345Sdim 140221345Sdim#ifdef _KERNEL 141221345Sdim 142221345Sdim#define HAVE_INLINE_FFS 143221345Sdim 144193323Sedstatic __inline int 145193323Sedffs(int mask) 146193323Sed{ 147212904Sdim /* 148193323Sed * Note that gcc-2's builtin ffs would be used if we didn't declare 149193323Sed * this inline or turn off the builtin. The builtin is faster but 150193323Sed * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later 151193323Sed * versions. 152249423Sdim */ 153212904Sdim return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1); 154193323Sed} 155193323Sed 156212904Sdim#define HAVE_INLINE_FLS 157212904Sdim 158212904Sdimstatic __inline int 159212904Sdimfls(int mask) 160212904Sdim{ 161212904Sdim return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1); 162243830Sdim} 163243830Sdim 164249423Sdim#endif /* _KERNEL */ 165243830Sdim 166243830Sdimstatic __inline void 167243830Sdimhalt(void) 168243830Sdim{ 169243830Sdim __asm __volatile("hlt"); 170243830Sdim} 171243830Sdim 172205407Srdivacky#if !defined(__GNUCLIKE_BUILTIN_CONSTANT_P) || __GNUCLIKE_ASM < 3 173205407Srdivacky 174205407Srdivacky#define inb(port) inbv(port) 175205407Srdivacky#define outb(port, data) outbv(port, data) 176205407Srdivacky 177205407Srdivacky#else /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3 */ 178205407Srdivacky 179205407Srdivacky/* 180205407Srdivacky * The following complications are to get around gcc not having a 181193323Sed * constraint letter for the range 0..255. We still put "d" in the 182193323Sed * constraint because "i" isn't a valid constraint when the port 183193323Sed * isn't constant. This only matters for -O0 because otherwise 184193323Sed * the non-working version gets optimized away. 185193323Sed * 186193323Sed * Use an expression-statement instead of a conditional expression 187193323Sed * because gcc-2.6.0 would promote the operands of the conditional 188193323Sed * and produce poor code for "if ((inb(var) & const1) == const2)". 189193323Sed * 190193323Sed * The unnecessary test `(port) < 0x10000' is to generate a warning if 191193323Sed * the `port' has type u_short or smaller. Such types are pessimal. 192193323Sed * This actually only works for signed types. The range check is 193193323Sed * careful to avoid generating warnings. 194276479Sdim */ 195193323Sed#define inb(port) __extension__ ({ \ 196193323Sed u_char _data; \ 197193323Sed if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 198193323Sed && (port) < 0x10000) \ 199193323Sed _data = inbc(port); \ 200193323Sed else \ 201193323Sed _data = inbv(port); \ 202193323Sed _data; }) 203193323Sed 204193323Sed#define outb(port, data) ( \ 205193323Sed __builtin_constant_p(port) && ((port) & 0xffff) < 0x100 \ 206193323Sed && (port) < 0x10000 \ 207193323Sed ? outbc(port, data) : outbv(port, data)) 208193323Sed 209212904Sdimstatic __inline u_char 210193323Sedinbc(u_int port) 211212904Sdim{ 212193323Sed u_char data; 213193323Sed 214193323Sed __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port))); 215210299Sed return (data); 216210299Sed} 217210299Sed 218210299Sedstatic __inline void 219210299Sedoutbc(u_int port, u_char data) 220210299Sed{ 221210299Sed __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port))); 222210299Sed} 223193323Sed 224193323Sed#endif /* __GNUCLIKE_BUILTIN_CONSTANT_P && __GNUCLIKE_ASM >= 3*/ 225193323Sed 226288943Sdimstatic __inline u_char 227288943Sdiminbv(u_int port) 228193323Sed{ 229193323Sed u_char data; 230193323Sed /* 231193323Sed * We use %%dx and not %1 here because i/o is done at %dx and not at 232210299Sed * %edx, while gcc generates inferior code (movw instead of movl) 233210299Sed * if we tell it to load (u_short) port. 234193323Sed */ 235296417Sdim __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port)); 236296417Sdim return (data); 237296417Sdim} 238296417Sdim 239296417Sdimstatic __inline u_int 240296417Sdiminl(u_int port) 241296417Sdim{ 242296417Sdim u_int data; 243296417Sdim 244296417Sdim __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port)); 245296417Sdim return (data); 246296417Sdim} 247296417Sdim 248296417Sdimstatic __inline void 249296417Sdiminsb(u_int port, void *addr, size_t cnt) 250296417Sdim{ 251296417Sdim __asm __volatile("cld; rep; insb" 252296417Sdim : "+D" (addr), "+c" (cnt) 253296417Sdim : "d" (port) 254193323Sed : "memory"); 255210299Sed} 256193323Sed 257296417Sdimstatic __inline void 258193323Sedinsw(u_int port, void *addr, size_t cnt) 259193323Sed{ 260193323Sed __asm __volatile("cld; rep; insw" 261193323Sed : "+D" (addr), "+c" (cnt) 262193323Sed : "d" (port) 263193323Sed : "memory"); 264193323Sed} 265193323Sed 266193323Sedstatic __inline void 267193323Sedinsl(u_int port, void *addr, size_t cnt) 268193323Sed{ 269193323Sed __asm __volatile("cld; rep; insl" 270193323Sed : "+D" (addr), "+c" (cnt) 271193323Sed : "d" (port) 272193323Sed : "memory"); 273193323Sed} 274193323Sed 275193323Sedstatic __inline void 276193323Sedinvd(void) 277210299Sed{ 278210299Sed __asm __volatile("invd"); 279193323Sed} 280193323Sed 281212904Sdimstatic __inline u_short 282193323Sedinw(u_int port) 283193323Sed{ 284193323Sed u_short data; 285193323Sed 286193323Sed __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port)); 287193323Sed return (data); 288276479Sdim} 289193323Sed 290193323Sedstatic __inline void 291212904Sdimoutbv(u_int port, u_char data) 292212904Sdim{ 293212904Sdim u_char al; 294212904Sdim /* 295193323Sed * Use an unnecessary assignment to help gcc's register allocator. 296193323Sed * This make a large difference for gcc-1.40 and a tiny difference 297193323Sed * for gcc-2.6.0. For gcc-1.40, al had to be ``asm("ax")'' for 298210299Sed * best results. gcc-2.6.0 can't handle this. 299193323Sed */ 300193323Sed al = data; 301193323Sed __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port)); 302193323Sed} 303193323Sed 304193323Sedstatic __inline void 305193323Sedoutl(u_int port, u_int data) 306193323Sed{ 307234353Sdim /* 308234353Sdim * outl() and outw() aren't used much so we haven't looked at 309193323Sed * possible micro-optimizations such as the unnecessary 310193323Sed * assignment for them. 311276479Sdim */ 312193323Sed __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port)); 313212904Sdim} 314193323Sed 315234353Sdimstatic __inline void 316193323Sedoutsb(u_int port, const void *addr, size_t cnt) 317212904Sdim{ 318193323Sed __asm __volatile("cld; rep; outsb" 319193323Sed : "+S" (addr), "+c" (cnt) 320193323Sed : "d" (port)); 321193323Sed} 322193323Sed 323193323Sedstatic __inline void 324276479Sdimoutsw(u_int port, const void *addr, size_t cnt) 325193323Sed{ 326193323Sed __asm __volatile("cld; rep; outsw" 327193323Sed : "+S" (addr), "+c" (cnt) 328193323Sed : "d" (port)); 329193323Sed} 330193323Sed 331276479Sdimstatic __inline void 332193323Sedoutsl(u_int port, const void *addr, size_t cnt) 333193323Sed{ 334193323Sed __asm __volatile("cld; rep; outsl" 335212904Sdim : "+S" (addr), "+c" (cnt) 336212904Sdim : "d" (port)); 337193323Sed} 338193323Sed 339193323Sedstatic __inline void 340193323Sedoutw(u_int port, u_short data) 341193323Sed{ 342193323Sed __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port)); 343193323Sed} 344193323Sed 345193323Sedstatic __inline void 346193323Sedia32_pause(void) 347193323Sed{ 348193323Sed __asm __volatile("pause"); 349276479Sdim} 350193323Sed 351193323Sedstatic __inline u_int 352193323Sedread_eflags(void) 353193323Sed{ 354193323Sed u_int ef; 355193323Sed 356193323Sed __asm __volatile("pushfl; popl %0" : "=r" (ef)); 357193323Sed return (ef); 358193323Sed} 359193323Sed 360193323Sedstatic __inline uint64_t 361193323Sedrdmsr(u_int msr) 362193323Sed{ 363276479Sdim uint64_t rv; 364193323Sed 365193323Sed __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr)); 366276479Sdim return (rv); 367193323Sed} 368193323Sed 369193323Sedstatic __inline uint64_t 370193323Sedrdpmc(u_int pmc) 371193323Sed{ 372193323Sed uint64_t rv; 373193323Sed 374193323Sed __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc)); 375193323Sed return (rv); 376193323Sed} 377193323Sed 378193323Sedstatic __inline uint64_t 379193323Sedrdtsc(void) 380193323Sed{ 381193323Sed uint64_t rv; 382193323Sed 383193323Sed __asm __volatile("rdtsc" : "=A" (rv)); 384193323Sed return (rv); 385193323Sed} 386193323Sed 387193323Sedstatic __inline void 388193323Sedwbinvd(void) 389193323Sed{ 390193323Sed __asm __volatile("wbinvd"); 391193323Sed} 392193323Sed 393193323Sedstatic __inline void 394193323Sedwrite_eflags(u_int ef) 395193323Sed{ 396193323Sed __asm __volatile("pushl %0; popfl" : : "r" (ef)); 397193323Sed} 398193323Sed 399193323Sedstatic __inline void 400193323Sedwrmsr(u_int msr, uint64_t newval) 401193323Sed{ 402212904Sdim __asm __volatile("wrmsr" : : "A" (newval), "c" (msr)); 403193323Sed} 404193323Sed 405193323Sedstatic __inline void 406193323Sedload_cr0(u_int data) 407193323Sed{ 408193323Sed 409193323Sed __asm __volatile("movl %0,%%cr0" : : "r" (data)); 410193323Sed} 411193323Sed 412193323Sedstatic __inline u_int 413193323Sedrcr0(void) 414193323Sed{ 415193323Sed u_int data; 416276479Sdim 417193323Sed __asm __volatile("movl %%cr0,%0" : "=r" (data)); 418193323Sed return (data); 419193323Sed} 420193323Sed 421193323Sedstatic __inline u_int 422193323Sedrcr2(void) 423193323Sed{ 424193323Sed u_int data; 425193323Sed 426193323Sed __asm __volatile("movl %%cr2,%0" : "=r" (data)); 427193323Sed return (data); 428193323Sed} 429193323Sed 430193323Sedstatic __inline void 431193323Sedload_cr3(u_int data) 432193323Sed{ 433193323Sed#ifdef XEN 434193323Sed xen_load_cr3(data); 435193323Sed#else 436276479Sdim __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory"); 437193323Sed#endif 438193323Sed} 439193323Sed 440193323Sedstatic __inline u_int 441193323Sedrcr3(void) 442193323Sed{ 443193323Sed u_int data; 444193323Sed 445193323Sed __asm __volatile("movl %%cr3,%0" : "=r" (data)); 446276479Sdim return (data); 447193323Sed} 448 449static __inline void 450load_cr4(u_int data) 451{ 452 __asm __volatile("movl %0,%%cr4" : : "r" (data)); 453} 454 455static __inline u_int 456rcr4(void) 457{ 458 u_int data; 459 460 __asm __volatile("movl %%cr4,%0" : "=r" (data)); 461 return (data); 462} 463 464/* 465 * Global TLB flush (except for thise for pages marked PG_G) 466 */ 467static __inline void 468invltlb(void) 469{ 470#ifdef XEN 471 xen_tlb_flush(); 472#else 473 load_cr3(rcr3()); 474#endif 475} 476 477/* 478 * TLB flush for an individual page (even if it has PG_G). 479 * Only works on 486+ CPUs (i386 does not have PG_G). 480 */ 481static __inline void 482invlpg(u_int addr) 483{ 484 485#ifdef XEN 486 xen_invlpg(addr); 487#else 488 __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory"); 489#endif 490} 491 492static __inline u_int 493rfs(void) 494{ 495 u_int sel; 496 __asm __volatile("movl %%fs,%0" : "=rm" (sel)); 497 return (sel); 498} 499 500static __inline uint64_t 501rgdt(void) 502{ 503 uint64_t gdtr; 504 __asm __volatile("sgdt %0" : "=m" (gdtr)); 505 return (gdtr); 506} 507 508static __inline u_int 509rgs(void) 510{ 511 u_int sel; 512 __asm __volatile("movl %%gs,%0" : "=rm" (sel)); 513 return (sel); 514} 515 516static __inline uint64_t 517ridt(void) 518{ 519 uint64_t idtr; 520 __asm __volatile("sidt %0" : "=m" (idtr)); 521 return (idtr); 522} 523 524static __inline u_short 525rldt(void) 526{ 527 u_short ldtr; 528 __asm __volatile("sldt %0" : "=g" (ldtr)); 529 return (ldtr); 530} 531 532static __inline u_int 533rss(void) 534{ 535 u_int sel; 536 __asm __volatile("movl %%ss,%0" : "=rm" (sel)); 537 return (sel); 538} 539 540static __inline u_short 541rtr(void) 542{ 543 u_short tr; 544 __asm __volatile("str %0" : "=g" (tr)); 545 return (tr); 546} 547 548static __inline void 549load_fs(u_int sel) 550{ 551 __asm __volatile("movl %0,%%fs" : : "rm" (sel)); 552} 553 554static __inline void 555load_gs(u_int sel) 556{ 557 __asm __volatile("movl %0,%%gs" : : "rm" (sel)); 558} 559 560static __inline void 561lidt(struct region_descriptor *addr) 562{ 563 __asm __volatile("lidt (%0)" : : "r" (addr)); 564} 565 566static __inline void 567lldt(u_short sel) 568{ 569 __asm __volatile("lldt %0" : : "r" (sel)); 570} 571 572static __inline void 573ltr(u_short sel) 574{ 575 __asm __volatile("ltr %0" : : "r" (sel)); 576} 577 578static __inline u_int 579rdr0(void) 580{ 581 u_int data; 582 __asm __volatile("movl %%dr0,%0" : "=r" (data)); 583 return (data); 584} 585 586static __inline void 587load_dr0(u_int dr0) 588{ 589 __asm __volatile("movl %0,%%dr0" : : "r" (dr0)); 590} 591 592static __inline u_int 593rdr1(void) 594{ 595 u_int data; 596 __asm __volatile("movl %%dr1,%0" : "=r" (data)); 597 return (data); 598} 599 600static __inline void 601load_dr1(u_int dr1) 602{ 603 __asm __volatile("movl %0,%%dr1" : : "r" (dr1)); 604} 605 606static __inline u_int 607rdr2(void) 608{ 609 u_int data; 610 __asm __volatile("movl %%dr2,%0" : "=r" (data)); 611 return (data); 612} 613 614static __inline void 615load_dr2(u_int dr2) 616{ 617 __asm __volatile("movl %0,%%dr2" : : "r" (dr2)); 618} 619 620static __inline u_int 621rdr3(void) 622{ 623 u_int data; 624 __asm __volatile("movl %%dr3,%0" : "=r" (data)); 625 return (data); 626} 627 628static __inline void 629load_dr3(u_int dr3) 630{ 631 __asm __volatile("movl %0,%%dr3" : : "r" (dr3)); 632} 633 634static __inline u_int 635rdr4(void) 636{ 637 u_int data; 638 __asm __volatile("movl %%dr4,%0" : "=r" (data)); 639 return (data); 640} 641 642static __inline void 643load_dr4(u_int dr4) 644{ 645 __asm __volatile("movl %0,%%dr4" : : "r" (dr4)); 646} 647 648static __inline u_int 649rdr5(void) 650{ 651 u_int data; 652 __asm __volatile("movl %%dr5,%0" : "=r" (data)); 653 return (data); 654} 655 656static __inline void 657load_dr5(u_int dr5) 658{ 659 __asm __volatile("movl %0,%%dr5" : : "r" (dr5)); 660} 661 662static __inline u_int 663rdr6(void) 664{ 665 u_int data; 666 __asm __volatile("movl %%dr6,%0" : "=r" (data)); 667 return (data); 668} 669 670static __inline void 671load_dr6(u_int dr6) 672{ 673 __asm __volatile("movl %0,%%dr6" : : "r" (dr6)); 674} 675 676static __inline u_int 677rdr7(void) 678{ 679 u_int data; 680 __asm __volatile("movl %%dr7,%0" : "=r" (data)); 681 return (data); 682} 683 684static __inline void 685load_dr7(u_int dr7) 686{ 687 __asm __volatile("movl %0,%%dr7" : : "r" (dr7)); 688} 689 690static __inline register_t 691intr_disable(void) 692{ 693 register_t eflags; 694 695#ifdef XEN 696 eflags = xen_save_and_cli(); 697#else 698 eflags = read_eflags(); 699 disable_intr(); 700#endif 701 return (eflags); 702} 703 704static __inline void 705intr_restore(register_t eflags) 706{ 707#ifdef XEN 708 xen_restore_flags(eflags); 709#else 710 write_eflags(eflags); 711#endif 712} 713 714#else /* !(__GNUCLIKE_ASM && __CC_SUPPORTS___INLINE) */ 715 716int breakpoint(void); 717u_int bsfl(u_int mask); 718u_int bsrl(u_int mask); 719void disable_intr(void); 720void do_cpuid(u_int ax, u_int *p); 721void enable_intr(void); 722void halt(void); 723void ia32_pause(void); 724u_char inb(u_int port); 725u_int inl(u_int port); 726void insb(u_int port, void *addr, size_t cnt); 727void insl(u_int port, void *addr, size_t cnt); 728void insw(u_int port, void *addr, size_t cnt); 729register_t intr_disable(void); 730void intr_restore(register_t ef); 731void invd(void); 732void invlpg(u_int addr); 733void invltlb(void); 734u_short inw(u_int port); 735void lidt(struct region_descriptor *addr); 736void lldt(u_short sel); 737void load_cr0(u_int cr0); 738void load_cr3(u_int cr3); 739void load_cr4(u_int cr4); 740void load_dr0(u_int dr0); 741void load_dr1(u_int dr1); 742void load_dr2(u_int dr2); 743void load_dr3(u_int dr3); 744void load_dr4(u_int dr4); 745void load_dr5(u_int dr5); 746void load_dr6(u_int dr6); 747void load_dr7(u_int dr7); 748void load_fs(u_int sel); 749void load_gs(u_int sel); 750void ltr(u_short sel); 751void outb(u_int port, u_char data); 752void outl(u_int port, u_int data); 753void outsb(u_int port, const void *addr, size_t cnt); 754void outsl(u_int port, const void *addr, size_t cnt); 755void outsw(u_int port, const void *addr, size_t cnt); 756void outw(u_int port, u_short data); 757u_int rcr0(void); 758u_int rcr2(void); 759u_int rcr3(void); 760u_int rcr4(void); 761uint64_t rdmsr(u_int msr); 762uint64_t rdpmc(u_int pmc); 763u_int rdr0(void); 764u_int rdr1(void); 765u_int rdr2(void); 766u_int rdr3(void); 767u_int rdr4(void); 768u_int rdr5(void); 769u_int rdr6(void); 770u_int rdr7(void); 771uint64_t rdtsc(void); 772u_int read_eflags(void); 773u_int rfs(void); 774uint64_t rgdt(void); 775u_int rgs(void); 776uint64_t ridt(void); 777u_short rldt(void); 778u_short rtr(void); 779void wbinvd(void); 780void write_eflags(u_int ef); 781void wrmsr(u_int msr, uint64_t newval); 782 783#endif /* __GNUCLIKE_ASM && __CC_SUPPORTS___INLINE */ 784 785void reset_dbregs(void); 786 787#ifdef _KERNEL 788int rdmsr_safe(u_int msr, uint64_t *val); 789int wrmsr_safe(u_int msr, uint64_t newval); 790#endif 791 792#endif /* !_MACHINE_CPUFUNC_H_ */ 793