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

Cache object: 0a8e7641037ce58ba0a840c4dd6ff318


[ 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.