The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/include/cpufunc.h

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 1993 The Regents of the University of California.
    3  * All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 4. Neither the name of the University nor the names of its contributors
   14  *    may be used to endorse or promote products derived from this software
   15  *    without specific prior written permission.
   16  *
   17  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   27  * SUCH DAMAGE.
   28  *
   29  * $FreeBSD: releng/5.4/sys/i386/include/cpufunc.h 146171 2005-05-13 00:12:57Z nectar $
   30  */
   31 
   32 /*
   33  * Functions to provide access to special i386 instructions.
   34  * This in included in sys/systm.h, and that file should be
   35  * used in preference to this.
   36  */
   37 
   38 #ifndef _MACHINE_CPUFUNC_H_
   39 #define _MACHINE_CPUFUNC_H_
   40 
   41 struct region_descriptor;
   42 
   43 #define readb(va)       (*(volatile u_int8_t *) (va))
   44 #define readw(va)       (*(volatile u_int16_t *) (va))
   45 #define readl(va)       (*(volatile u_int32_t *) (va))
   46 
   47 #define writeb(va, d)   (*(volatile u_int8_t *) (va) = (d))
   48 #define writew(va, d)   (*(volatile u_int16_t *) (va) = (d))
   49 #define writel(va, d)   (*(volatile u_int32_t *) (va) = (d))
   50 
   51 #if defined(__GNUC__) || defined(__INTEL_COMPILER)
   52 
   53 static __inline void
   54 breakpoint(void)
   55 {
   56         __asm __volatile("int $3");
   57 }
   58 
   59 static __inline u_int
   60 bsfl(u_int mask)
   61 {
   62         u_int   result;
   63 
   64         __asm __volatile("bsfl %1,%0" : "=r" (result) : "rm" (mask));
   65         return (result);
   66 }
   67 
   68 static __inline u_int
   69 bsrl(u_int mask)
   70 {
   71         u_int   result;
   72 
   73         __asm __volatile("bsrl %1,%0" : "=r" (result) : "rm" (mask));
   74         return (result);
   75 }
   76 
   77 static __inline void
   78 disable_intr(void)
   79 {
   80         __asm __volatile("cli" : : : "memory");
   81 }
   82 
   83 static __inline void
   84 do_cpuid(u_int ax, u_int *p)
   85 {
   86         __asm __volatile("cpuid"
   87                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
   88                          :  "" (ax));
   89 }
   90 
   91 static __inline void
   92 cpuid_count(u_int ax, u_int cx, u_int *p)
   93 {
   94         __asm __volatile("cpuid"
   95                          : "=a" (p[0]), "=b" (p[1]), "=c" (p[2]), "=d" (p[3])
   96                          :  "" (ax), "c" (cx));
   97 }
   98 
   99 static __inline void
  100 enable_intr(void)
  101 {
  102         __asm __volatile("sti");
  103 }
  104 
  105 #ifdef _KERNEL
  106 
  107 #define HAVE_INLINE_FFS
  108 
  109 static __inline int
  110 ffs(int mask)
  111 {
  112         /*
  113          * Note that gcc-2's builtin ffs would be used if we didn't declare
  114          * this inline or turn off the builtin.  The builtin is faster but
  115          * broken in gcc-2.4.5 and slower but working in gcc-2.5 and later
  116          * versions.
  117          */
  118          return (mask == 0 ? mask : (int)bsfl((u_int)mask) + 1);
  119 }
  120 
  121 #define HAVE_INLINE_FLS
  122 
  123 static __inline int
  124 fls(int mask)
  125 {
  126         return (mask == 0 ? mask : (int)bsrl((u_int)mask) + 1);
  127 }
  128 
  129 #endif /* _KERNEL */
  130 
  131 static __inline void
  132 halt(void)
  133 {
  134         __asm __volatile("hlt");
  135 }
  136 
  137 #if __GNUC__ < 2
  138 
  139 #define inb(port)               inbv(port)
  140 #define outb(port, data)        outbv(port, data)
  141 
  142 #else /* __GNUC >= 2 */
  143 
  144 /*
  145  * The following complications are to get around gcc not having a
  146  * constraint letter for the range 0..255.  We still put "d" in the
  147  * constraint because "i" isn't a valid constraint when the port
  148  * isn't constant.  This only matters for -O0 because otherwise
  149  * the non-working version gets optimized away.
  150  * 
  151  * Use an expression-statement instead of a conditional expression
  152  * because gcc-2.6.0 would promote the operands of the conditional
  153  * and produce poor code for "if ((inb(var) & const1) == const2)".
  154  *
  155  * The unnecessary test `(port) < 0x10000' is to generate a warning if
  156  * the `port' has type u_short or smaller.  Such types are pessimal.
  157  * This actually only works for signed types.  The range check is
  158  * careful to avoid generating warnings.
  159  */
  160 #define inb(port) __extension__ ({                                      \
  161         u_char  _data;                                                  \
  162         if (__builtin_constant_p(port) && ((port) & 0xffff) < 0x100     \
  163             && (port) < 0x10000)                                        \
  164                 _data = inbc(port);                                     \
  165         else                                                            \
  166                 _data = inbv(port);                                     \
  167         _data; })
  168 
  169 #define outb(port, data) (                                              \
  170         __builtin_constant_p(port) && ((port) & 0xffff) < 0x100         \
  171         && (port) < 0x10000                                             \
  172         ? outbc(port, data) : outbv(port, data))
  173 
  174 static __inline u_char
  175 inbc(u_int port)
  176 {
  177         u_char  data;
  178 
  179         __asm __volatile("inb %1,%0" : "=a" (data) : "id" ((u_short)(port)));
  180         return (data);
  181 }
  182 
  183 static __inline void
  184 outbc(u_int port, u_char data)
  185 {
  186         __asm __volatile("outb %0,%1" : : "a" (data), "id" ((u_short)(port)));
  187 }
  188 
  189 #endif /* __GNUC <= 2 */
  190 
  191 static __inline u_char
  192 inbv(u_int port)
  193 {
  194         u_char  data;
  195         /*
  196          * We use %%dx and not %1 here because i/o is done at %dx and not at
  197          * %edx, while gcc generates inferior code (movw instead of movl)
  198          * if we tell it to load (u_short) port.
  199          */
  200         __asm __volatile("inb %%dx,%0" : "=a" (data) : "d" (port));
  201         return (data);
  202 }
  203 
  204 static __inline u_int
  205 inl(u_int port)
  206 {
  207         u_int   data;
  208 
  209         __asm __volatile("inl %%dx,%0" : "=a" (data) : "d" (port));
  210         return (data);
  211 }
  212 
  213 static __inline void
  214 insb(u_int port, void *addr, size_t cnt)
  215 {
  216         __asm __volatile("cld; rep; insb"
  217                          : "+D" (addr), "+c" (cnt)
  218                          : "d" (port)
  219                          : "memory");
  220 }
  221 
  222 static __inline void
  223 insw(u_int port, void *addr, size_t cnt)
  224 {
  225         __asm __volatile("cld; rep; insw"
  226                          : "+D" (addr), "+c" (cnt)
  227                          : "d" (port)
  228                          : "memory");
  229 }
  230 
  231 static __inline void
  232 insl(u_int port, void *addr, size_t cnt)
  233 {
  234         __asm __volatile("cld; rep; insl"
  235                          : "+D" (addr), "+c" (cnt)
  236                          : "d" (port)
  237                          : "memory");
  238 }
  239 
  240 static __inline void
  241 invd(void)
  242 {
  243         __asm __volatile("invd");
  244 }
  245 
  246 static __inline u_short
  247 inw(u_int port)
  248 {
  249         u_short data;
  250 
  251         __asm __volatile("inw %%dx,%0" : "=a" (data) : "d" (port));
  252         return (data);
  253 }
  254 
  255 static __inline void
  256 outbv(u_int port, u_char data)
  257 {
  258         u_char  al;
  259         /*
  260          * Use an unnecessary assignment to help gcc's register allocator.
  261          * This make a large difference for gcc-1.40 and a tiny difference
  262          * for gcc-2.6.0.  For gcc-1.40, al had to be ``asm("ax")'' for
  263          * best results.  gcc-2.6.0 can't handle this.
  264          */
  265         al = data;
  266         __asm __volatile("outb %0,%%dx" : : "a" (al), "d" (port));
  267 }
  268 
  269 static __inline void
  270 outl(u_int port, u_int data)
  271 {
  272         /*
  273          * outl() and outw() aren't used much so we haven't looked at
  274          * possible micro-optimizations such as the unnecessary
  275          * assignment for them.
  276          */
  277         __asm __volatile("outl %0,%%dx" : : "a" (data), "d" (port));
  278 }
  279 
  280 static __inline void
  281 outsb(u_int port, const void *addr, size_t cnt)
  282 {
  283         __asm __volatile("cld; rep; outsb"
  284                          : "+S" (addr), "+c" (cnt)
  285                          : "d" (port));
  286 }
  287 
  288 static __inline void
  289 outsw(u_int port, const void *addr, size_t cnt)
  290 {
  291         __asm __volatile("cld; rep; outsw"
  292                          : "+S" (addr), "+c" (cnt)
  293                          : "d" (port));
  294 }
  295 
  296 static __inline void
  297 outsl(u_int port, const void *addr, size_t cnt)
  298 {
  299         __asm __volatile("cld; rep; outsl"
  300                          : "+S" (addr), "+c" (cnt)
  301                          : "d" (port));
  302 }
  303 
  304 static __inline void
  305 outw(u_int port, u_short data)
  306 {
  307         __asm __volatile("outw %0,%%dx" : : "a" (data), "d" (port));
  308 }
  309 
  310 static __inline void
  311 ia32_pause(void)
  312 {
  313         __asm __volatile("pause");
  314 }
  315 
  316 static __inline u_int
  317 read_eflags(void)
  318 {
  319         u_int   ef;
  320 
  321         __asm __volatile("pushfl; popl %0" : "=r" (ef));
  322         return (ef);
  323 }
  324 
  325 static __inline u_int64_t
  326 rdmsr(u_int msr)
  327 {
  328         u_int64_t rv;
  329 
  330         __asm __volatile("rdmsr" : "=A" (rv) : "c" (msr));
  331         return (rv);
  332 }
  333 
  334 static __inline u_int64_t
  335 rdpmc(u_int pmc)
  336 {
  337         u_int64_t rv;
  338 
  339         __asm __volatile("rdpmc" : "=A" (rv) : "c" (pmc));
  340         return (rv);
  341 }
  342 
  343 static __inline u_int64_t
  344 rdtsc(void)
  345 {
  346         u_int64_t rv;
  347 
  348         __asm __volatile("rdtsc" : "=A" (rv));
  349         return (rv);
  350 }
  351 
  352 static __inline void
  353 wbinvd(void)
  354 {
  355         __asm __volatile("wbinvd");
  356 }
  357 
  358 static __inline void
  359 write_eflags(u_int ef)
  360 {
  361         __asm __volatile("pushl %0; popfl" : : "r" (ef));
  362 }
  363 
  364 static __inline void
  365 wrmsr(u_int msr, u_int64_t newval)
  366 {
  367         __asm __volatile("wrmsr" : : "A" (newval), "c" (msr));
  368 }
  369 
  370 static __inline void
  371 load_cr0(u_int data)
  372 {
  373 
  374         __asm __volatile("movl %0,%%cr0" : : "r" (data));
  375 }
  376 
  377 static __inline u_int
  378 rcr0(void)
  379 {
  380         u_int   data;
  381 
  382         __asm __volatile("movl %%cr0,%0" : "=r" (data));
  383         return (data);
  384 }
  385 
  386 static __inline u_int
  387 rcr2(void)
  388 {
  389         u_int   data;
  390 
  391         __asm __volatile("movl %%cr2,%0" : "=r" (data));
  392         return (data);
  393 }
  394 
  395 static __inline void
  396 load_cr3(u_int data)
  397 {
  398 
  399         __asm __volatile("movl %0,%%cr3" : : "r" (data) : "memory");
  400 }
  401 
  402 static __inline u_int
  403 rcr3(void)
  404 {
  405         u_int   data;
  406 
  407         __asm __volatile("movl %%cr3,%0" : "=r" (data));
  408         return (data);
  409 }
  410 
  411 static __inline void
  412 load_cr4(u_int data)
  413 {
  414         __asm __volatile("movl %0,%%cr4" : : "r" (data));
  415 }
  416 
  417 static __inline u_int
  418 rcr4(void)
  419 {
  420         u_int   data;
  421 
  422         __asm __volatile("movl %%cr4,%0" : "=r" (data));
  423         return (data);
  424 }
  425 
  426 /*
  427  * Global TLB flush (except for thise for pages marked PG_G)
  428  */
  429 static __inline void
  430 invltlb(void)
  431 {
  432 
  433         load_cr3(rcr3());
  434 }
  435 
  436 /*
  437  * TLB flush for an individual page (even if it has PG_G).
  438  * Only works on 486+ CPUs (i386 does not have PG_G).
  439  */
  440 static __inline void
  441 invlpg(u_int addr)
  442 {
  443 
  444         __asm __volatile("invlpg %0" : : "m" (*(char *)addr) : "memory");
  445 }
  446 
  447 static __inline u_int
  448 rfs(void)
  449 {
  450         u_int sel;
  451         __asm __volatile("movl %%fs,%0" : "=rm" (sel));
  452         return (sel);
  453 }
  454 
  455 static __inline u_int
  456 rgs(void)
  457 {
  458         u_int sel;
  459         __asm __volatile("movl %%gs,%0" : "=rm" (sel));
  460         return (sel);
  461 }
  462 
  463 static __inline u_int
  464 rss(void)
  465 {
  466         u_int sel;
  467         __asm __volatile("movl %%ss,%0" : "=rm" (sel));
  468         return (sel);
  469 }
  470 
  471 static __inline void
  472 load_fs(u_int sel)
  473 {
  474         __asm __volatile("movl %0,%%fs" : : "rm" (sel));
  475 }
  476 
  477 static __inline void
  478 load_gs(u_int sel)
  479 {
  480         __asm __volatile("movl %0,%%gs" : : "rm" (sel));
  481 }
  482 
  483 static __inline void
  484 lidt(struct region_descriptor *addr)
  485 {
  486         __asm __volatile("lidt (%0)" : : "r" (addr));
  487 }
  488 
  489 static __inline void
  490 lldt(u_short sel)
  491 {
  492         __asm __volatile("lldt %0" : : "r" (sel));
  493 }
  494 
  495 static __inline void
  496 ltr(u_short sel)
  497 {
  498         __asm __volatile("ltr %0" : : "r" (sel));
  499 }
  500 
  501 static __inline u_int
  502 rdr0(void)
  503 {
  504         u_int   data;
  505         __asm __volatile("movl %%dr0,%0" : "=r" (data));
  506         return (data);
  507 }
  508 
  509 static __inline void
  510 load_dr0(u_int dr0)
  511 {
  512         __asm __volatile("movl %0,%%dr0" : : "r" (dr0));
  513 }
  514 
  515 static __inline u_int
  516 rdr1(void)
  517 {
  518         u_int   data;
  519         __asm __volatile("movl %%dr1,%0" : "=r" (data));
  520         return (data);
  521 }
  522 
  523 static __inline void
  524 load_dr1(u_int dr1)
  525 {
  526         __asm __volatile("movl %0,%%dr1" : : "r" (dr1));
  527 }
  528 
  529 static __inline u_int
  530 rdr2(void)
  531 {
  532         u_int   data;
  533         __asm __volatile("movl %%dr2,%0" : "=r" (data));
  534         return (data);
  535 }
  536 
  537 static __inline void
  538 load_dr2(u_int dr2)
  539 {
  540         __asm __volatile("movl %0,%%dr2" : : "r" (dr2));
  541 }
  542 
  543 static __inline u_int
  544 rdr3(void)
  545 {
  546         u_int   data;
  547         __asm __volatile("movl %%dr3,%0" : "=r" (data));
  548         return (data);
  549 }
  550 
  551 static __inline void
  552 load_dr3(u_int dr3)
  553 {
  554         __asm __volatile("movl %0,%%dr3" : : "r" (dr3));
  555 }
  556 
  557 static __inline u_int
  558 rdr4(void)
  559 {
  560         u_int   data;
  561         __asm __volatile("movl %%dr4,%0" : "=r" (data));
  562         return (data);
  563 }
  564 
  565 static __inline void
  566 load_dr4(u_int dr4)
  567 {
  568         __asm __volatile("movl %0,%%dr4" : : "r" (dr4));
  569 }
  570 
  571 static __inline u_int
  572 rdr5(void)
  573 {
  574         u_int   data;
  575         __asm __volatile("movl %%dr5,%0" : "=r" (data));
  576         return (data);
  577 }
  578 
  579 static __inline void
  580 load_dr5(u_int dr5)
  581 {
  582         __asm __volatile("movl %0,%%dr5" : : "r" (dr5));
  583 }
  584 
  585 static __inline u_int
  586 rdr6(void)
  587 {
  588         u_int   data;
  589         __asm __volatile("movl %%dr6,%0" : "=r" (data));
  590         return (data);
  591 }
  592 
  593 static __inline void
  594 load_dr6(u_int dr6)
  595 {
  596         __asm __volatile("movl %0,%%dr6" : : "r" (dr6));
  597 }
  598 
  599 static __inline u_int
  600 rdr7(void)
  601 {
  602         u_int   data;
  603         __asm __volatile("movl %%dr7,%0" : "=r" (data));
  604         return (data);
  605 }
  606 
  607 static __inline void
  608 load_dr7(u_int dr7)
  609 {
  610         __asm __volatile("movl %0,%%dr7" : : "r" (dr7));
  611 }
  612 
  613 static __inline register_t
  614 intr_disable(void)
  615 {
  616         register_t eflags;
  617 
  618         eflags = read_eflags();
  619         disable_intr();
  620         return (eflags);
  621 }
  622 
  623 static __inline void
  624 intr_restore(register_t eflags)
  625 {
  626         write_eflags(eflags);
  627 }
  628 
  629 #else /* !(__GNUC__ || __INTEL_COMPILER) */
  630 
  631 int     breakpoint(void);
  632 u_int   bsfl(u_int mask);
  633 u_int   bsrl(u_int mask);
  634 void    disable_intr(void);
  635 void    do_cpuid(u_int ax, u_int *p);
  636 void    enable_intr(void);
  637 void    halt(void);
  638 void    ia32_pause(void);
  639 u_char  inb(u_int port);
  640 u_int   inl(u_int port);
  641 void    insb(u_int port, void *addr, size_t cnt);
  642 void    insl(u_int port, void *addr, size_t cnt);
  643 void    insw(u_int port, void *addr, size_t cnt);
  644 register_t      intr_disable(void);
  645 void    intr_restore(register_t ef);
  646 void    invd(void);
  647 void    invlpg(u_int addr);
  648 void    invltlb(void);
  649 u_short inw(u_int port);
  650 void    lidt(struct region_descriptor *addr);
  651 void    lldt(u_short sel);
  652 void    load_cr0(u_int cr0);
  653 void    load_cr3(u_int cr3);
  654 void    load_cr4(u_int cr4);
  655 void    load_dr0(u_int dr0);
  656 void    load_dr1(u_int dr1);
  657 void    load_dr2(u_int dr2);
  658 void    load_dr3(u_int dr3);
  659 void    load_dr4(u_int dr4);
  660 void    load_dr5(u_int dr5);
  661 void    load_dr6(u_int dr6);
  662 void    load_dr7(u_int dr7);
  663 void    load_fs(u_int sel);
  664 void    load_gs(u_int sel);
  665 void    ltr(u_short sel);
  666 void    outb(u_int port, u_char data);
  667 void    outl(u_int port, u_int data);
  668 void    outsb(u_int port, const void *addr, size_t cnt);
  669 void    outsl(u_int port, const void *addr, size_t cnt);
  670 void    outsw(u_int port, const void *addr, size_t cnt);
  671 void    outw(u_int port, u_short data);
  672 u_int   rcr0(void);
  673 u_int   rcr2(void);
  674 u_int   rcr3(void);
  675 u_int   rcr4(void);
  676 u_int64_t rdmsr(u_int msr);
  677 u_int64_t rdpmc(u_int pmc);
  678 u_int   rdr0(void);
  679 u_int   rdr1(void);
  680 u_int   rdr2(void);
  681 u_int   rdr3(void);
  682 u_int   rdr4(void);
  683 u_int   rdr5(void);
  684 u_int   rdr6(void);
  685 u_int   rdr7(void);
  686 u_int64_t rdtsc(void);
  687 u_int   read_eflags(void);
  688 u_int   rfs(void);
  689 u_int   rgs(void);
  690 void    wbinvd(void);
  691 void    write_eflags(u_int ef);
  692 void    wrmsr(u_int msr, u_int64_t newval);
  693 
  694 #endif  /* __GNUC__ || __INTEL_COMPILER */
  695 
  696 void    reset_dbregs(void);
  697 
  698 #endif /* !_MACHINE_CPUFUNC_H_ */

Cache object: f56a3cc531736826baf299d454598280


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]


This page is part of the FreeBSD/Linux Linux Kernel Cross-Reference, and was automatically generated using a modified version of the LXR engine.