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

Cache object: 1d6f7c751b50251c955f06016b3148c4


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