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/i386/support.s

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.0/sys/i386/i386/support.s 103778 2002-09-22 04:45:21Z peter $
   34  */
   35 
   36 #include "opt_npx.h"
   37 
   38 #include <machine/asmacros.h>
   39 #include <machine/cputypes.h>
   40 #include <machine/pmap.h>
   41 #include <machine/specialreg.h>
   42 
   43 #include "assym.s"
   44 
   45 #define IDXSHIFT        10
   46 
   47         .data
   48         .globl  bcopy_vector
   49 bcopy_vector:
   50         .long   generic_bcopy
   51         .globl  bzero
   52 bzero:
   53         .long   generic_bzero
   54         .globl  copyin_vector
   55 copyin_vector:
   56         .long   generic_copyin
   57         .globl  copyout_vector
   58 copyout_vector:
   59         .long   generic_copyout
   60         .globl  ovbcopy_vector
   61 ovbcopy_vector:
   62         .long   generic_bcopy
   63 #if defined(I586_CPU) && defined(DEV_NPX)
   64 kernel_fpu_lock:
   65         .byte   0xfe
   66         .space  3
   67 #endif
   68 
   69         .text
   70 
   71 /*
   72  * bcopy family
   73  * void bzero(void *buf, u_int len)
   74  */
   75 
   76 ENTRY(generic_bzero)
   77         pushl   %edi
   78         movl    8(%esp),%edi
   79         movl    12(%esp),%ecx
   80         xorl    %eax,%eax
   81         shrl    $2,%ecx
   82         cld
   83         rep
   84         stosl
   85         movl    12(%esp),%ecx
   86         andl    $3,%ecx
   87         rep
   88         stosb
   89         popl    %edi
   90         ret
   91 
   92 #ifdef I486_CPU
   93 ENTRY(i486_bzero)
   94         movl    4(%esp),%edx
   95         movl    8(%esp),%ecx
   96         xorl    %eax,%eax
   97 /*
   98  * do 64 byte chunks first
   99  *
  100  * XXX this is probably over-unrolled at least for DX2's
  101  */
  102 2:
  103         cmpl    $64,%ecx
  104         jb      3f
  105         movl    %eax,(%edx)
  106         movl    %eax,4(%edx)
  107         movl    %eax,8(%edx)
  108         movl    %eax,12(%edx)
  109         movl    %eax,16(%edx)
  110         movl    %eax,20(%edx)
  111         movl    %eax,24(%edx)
  112         movl    %eax,28(%edx)
  113         movl    %eax,32(%edx)
  114         movl    %eax,36(%edx)
  115         movl    %eax,40(%edx)
  116         movl    %eax,44(%edx)
  117         movl    %eax,48(%edx)
  118         movl    %eax,52(%edx)
  119         movl    %eax,56(%edx)
  120         movl    %eax,60(%edx)
  121         addl    $64,%edx
  122         subl    $64,%ecx
  123         jnz     2b
  124         ret
  125 
  126 /*
  127  * do 16 byte chunks
  128  */
  129         SUPERALIGN_TEXT
  130 3:
  131         cmpl    $16,%ecx
  132         jb      4f
  133         movl    %eax,(%edx)
  134         movl    %eax,4(%edx)
  135         movl    %eax,8(%edx)
  136         movl    %eax,12(%edx)
  137         addl    $16,%edx
  138         subl    $16,%ecx
  139         jnz     3b
  140         ret
  141 
  142 /*
  143  * do 4 byte chunks
  144  */
  145         SUPERALIGN_TEXT
  146 4:
  147         cmpl    $4,%ecx
  148         jb      5f
  149         movl    %eax,(%edx)
  150         addl    $4,%edx
  151         subl    $4,%ecx
  152         jnz     4b
  153         ret
  154 
  155 /*
  156  * do 1 byte chunks
  157  * a jump table seems to be faster than a loop or more range reductions
  158  *
  159  * XXX need a const section for non-text
  160  */
  161         .data
  162 jtab:
  163         .long   do0
  164         .long   do1
  165         .long   do2
  166         .long   do3
  167 
  168         .text
  169         SUPERALIGN_TEXT
  170 5:
  171         jmp     *jtab(,%ecx,4)
  172 
  173         SUPERALIGN_TEXT
  174 do3:
  175         movw    %ax,(%edx)
  176         movb    %al,2(%edx)
  177         ret
  178 
  179         SUPERALIGN_TEXT
  180 do2:
  181         movw    %ax,(%edx)
  182         ret
  183 
  184         SUPERALIGN_TEXT
  185 do1:
  186         movb    %al,(%edx)
  187         ret
  188 
  189         SUPERALIGN_TEXT
  190 do0:
  191         ret
  192 #endif
  193 
  194 #if defined(I586_CPU) && defined(DEV_NPX)
  195 ENTRY(i586_bzero)
  196         movl    4(%esp),%edx
  197         movl    8(%esp),%ecx
  198 
  199         /*
  200          * The FPU register method is twice as fast as the integer register
  201          * method unless the target is in the L1 cache and we pre-allocate a
  202          * cache line for it (then the integer register method is 4-5 times
  203          * faster).  However, we never pre-allocate cache lines, since that
  204          * would make the integer method 25% or more slower for the common
  205          * case when the target isn't in either the L1 cache or the L2 cache.
  206          * Thus we normally use the FPU register method unless the overhead
  207          * would be too large.
  208          */
  209         cmpl    $256,%ecx       /* empirical; clts, fninit, smsw cost a lot */
  210         jb      intreg_i586_bzero
  211 
  212         /*
  213          * The FPU registers may belong to an application or to fastmove()
  214          * or to another invocation of bcopy() or ourself in a higher level
  215          * interrupt or trap handler.  Preserving the registers is
  216          * complicated since we avoid it if possible at all levels.  We
  217          * want to localize the complications even when that increases them.
  218          * Here the extra work involves preserving CR0_TS in TS.
  219          * `fpcurthread != NULL' is supposed to be the condition that all the
  220          * FPU resources belong to an application, but fpcurthread and CR0_TS
  221          * aren't set atomically enough for this condition to work in
  222          * interrupt handlers.
  223          *
  224          * Case 1: FPU registers belong to the application: we must preserve
  225          * the registers if we use them, so we only use the FPU register
  226          * method if the target size is large enough to amortize the extra
  227          * overhead for preserving them.  CR0_TS must be preserved although
  228          * it is very likely to end up as set.
  229          *
  230          * Case 2: FPU registers belong to fastmove(): fastmove() currently
  231          * makes the registers look like they belong to an application so
  232          * that cpu_switch() and savectx() don't have to know about it, so
  233          * this case reduces to case 1.
  234          *
  235          * Case 3: FPU registers belong to the kernel: don't use the FPU
  236          * register method.  This case is unlikely, and supporting it would
  237          * be more complicated and might take too much stack.
  238          *
  239          * Case 4: FPU registers don't belong to anyone: the FPU registers
  240          * don't need to be preserved, so we always use the FPU register
  241          * method.  CR0_TS must be preserved although it is very likely to
  242          * always end up as clear.
  243          */
  244         cmpl    $0,PCPU(FPCURTHREAD)
  245         je      i586_bz1
  246 
  247         /*
  248          * XXX don't use the FPU for cases 1 and 2, since preemptive
  249          * scheduling of ithreads broke these cases.  Note that we can
  250          * no longer get here from an interrupt handler, since the
  251          * context sitch to the interrupt handler will have saved the
  252          * FPU state.
  253          */
  254         jmp     intreg_i586_bzero
  255 
  256         cmpl    $256+184,%ecx           /* empirical; not quite 2*108 more */
  257         jb      intreg_i586_bzero
  258         sarb    $1,kernel_fpu_lock
  259         jc      intreg_i586_bzero
  260         smsw    %ax
  261         clts
  262         subl    $108,%esp
  263         fnsave  0(%esp)
  264         jmp     i586_bz2
  265 
  266 i586_bz1:
  267         sarb    $1,kernel_fpu_lock
  268         jc      intreg_i586_bzero
  269         smsw    %ax
  270         clts
  271         fninit                          /* XXX should avoid needing this */
  272 i586_bz2:
  273         fldz
  274 
  275         /*
  276          * Align to an 8 byte boundary (misalignment in the main loop would
  277          * cost a factor of >= 2).  Avoid jumps (at little cost if it is
  278          * already aligned) by always zeroing 8 bytes and using the part up
  279          * to the _next_ alignment position.
  280          */
  281         fstl    0(%edx)
  282         addl    %edx,%ecx               /* part of %ecx -= new_%edx - %edx */
  283         addl    $8,%edx
  284         andl    $~7,%edx
  285         subl    %edx,%ecx
  286 
  287         /*
  288          * Similarly align `len' to a multiple of 8.
  289          */
  290         fstl    -8(%edx,%ecx)
  291         decl    %ecx
  292         andl    $~7,%ecx
  293 
  294         /*
  295          * This wouldn't be any faster if it were unrolled, since the loop
  296          * control instructions are much faster than the fstl and/or done
  297          * in parallel with it so their overhead is insignificant.
  298          */
  299 fpureg_i586_bzero_loop:
  300         fstl    0(%edx)
  301         addl    $8,%edx
  302         subl    $8,%ecx
  303         cmpl    $8,%ecx
  304         jae     fpureg_i586_bzero_loop
  305 
  306         cmpl    $0,PCPU(FPCURTHREAD)
  307         je      i586_bz3
  308 
  309         /* XXX check that the condition for cases 1-2 stayed false. */
  310 i586_bzero_oops:
  311         int     $3
  312         jmp     i586_bzero_oops
  313 
  314         frstor  0(%esp)
  315         addl    $108,%esp
  316         lmsw    %ax
  317         movb    $0xfe,kernel_fpu_lock
  318         ret
  319 
  320 i586_bz3:
  321         fstp    %st(0)
  322         lmsw    %ax
  323         movb    $0xfe,kernel_fpu_lock
  324         ret
  325 
  326 intreg_i586_bzero:
  327         /*
  328          * `rep stos' seems to be the best method in practice for small
  329          * counts.  Fancy methods usually take too long to start up due
  330          * to cache and BTB misses.
  331          */
  332         pushl   %edi
  333         movl    %edx,%edi
  334         xorl    %eax,%eax
  335         shrl    $2,%ecx
  336         cld
  337         rep
  338         stosl
  339         movl    12(%esp),%ecx
  340         andl    $3,%ecx
  341         jne     1f
  342         popl    %edi
  343         ret
  344 
  345 1:
  346         rep
  347         stosb
  348         popl    %edi
  349         ret
  350 #endif /* I586_CPU && defined(DEV_NPX) */
  351 
  352 ENTRY(i686_pagezero)
  353         pushl   %edi
  354         pushl   %ebx
  355 
  356         movl    12(%esp), %edi
  357         movl    $1024, %ecx
  358         cld
  359 
  360         ALIGN_TEXT
  361 1:
  362         xorl    %eax, %eax
  363         repe
  364         scasl   
  365         jnz     2f
  366 
  367         popl    %ebx
  368         popl    %edi
  369         ret
  370 
  371         ALIGN_TEXT
  372 
  373 2:
  374         incl    %ecx
  375         subl    $4, %edi
  376 
  377         movl    %ecx, %edx
  378         cmpl    $16, %ecx
  379 
  380         jge     3f
  381 
  382         movl    %edi, %ebx
  383         andl    $0x3f, %ebx
  384         shrl    %ebx
  385         shrl    %ebx
  386         movl    $16, %ecx
  387         subl    %ebx, %ecx
  388 
  389 3:
  390         subl    %ecx, %edx
  391         rep
  392         stosl
  393 
  394         movl    %edx, %ecx
  395         testl   %edx, %edx
  396         jnz     1b
  397 
  398         popl    %ebx
  399         popl    %edi
  400         ret
  401 
  402 /* fillw(pat, base, cnt) */
  403 ENTRY(fillw)
  404         pushl   %edi
  405         movl    8(%esp),%eax
  406         movl    12(%esp),%edi
  407         movl    16(%esp),%ecx
  408         cld
  409         rep
  410         stosw
  411         popl    %edi
  412         ret
  413 
  414 ENTRY(bcopyb)
  415         pushl   %esi
  416         pushl   %edi
  417         movl    12(%esp),%esi
  418         movl    16(%esp),%edi
  419         movl    20(%esp),%ecx
  420         movl    %edi,%eax
  421         subl    %esi,%eax
  422         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
  423         jb      1f
  424         cld                                     /* nope, copy forwards */
  425         rep
  426         movsb
  427         popl    %edi
  428         popl    %esi
  429         ret
  430 
  431         ALIGN_TEXT
  432 1:
  433         addl    %ecx,%edi                       /* copy backwards. */
  434         addl    %ecx,%esi
  435         decl    %edi
  436         decl    %esi
  437         std
  438         rep
  439         movsb
  440         popl    %edi
  441         popl    %esi
  442         cld
  443         ret
  444 
  445 ENTRY(bcopy)
  446         MEXITCOUNT
  447         jmp     *bcopy_vector
  448 
  449 ENTRY(ovbcopy)
  450         MEXITCOUNT
  451         jmp     *ovbcopy_vector
  452 
  453 /*
  454  * generic_bcopy(src, dst, cnt)
  455  *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
  456  */
  457 ENTRY(generic_bcopy)
  458         pushl   %esi
  459         pushl   %edi
  460         movl    12(%esp),%esi
  461         movl    16(%esp),%edi
  462         movl    20(%esp),%ecx
  463 
  464         movl    %edi,%eax
  465         subl    %esi,%eax
  466         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
  467         jb      1f
  468 
  469         shrl    $2,%ecx                         /* copy by 32-bit words */
  470         cld                                     /* nope, copy forwards */
  471         rep
  472         movsl
  473         movl    20(%esp),%ecx
  474         andl    $3,%ecx                         /* any bytes left? */
  475         rep
  476         movsb
  477         popl    %edi
  478         popl    %esi
  479         ret
  480 
  481         ALIGN_TEXT
  482 1:
  483         addl    %ecx,%edi                       /* copy backwards */
  484         addl    %ecx,%esi
  485         decl    %edi
  486         decl    %esi
  487         andl    $3,%ecx                         /* any fractional bytes? */
  488         std
  489         rep
  490         movsb
  491         movl    20(%esp),%ecx                   /* copy remainder by 32-bit words */
  492         shrl    $2,%ecx
  493         subl    $3,%esi
  494         subl    $3,%edi
  495         rep
  496         movsl
  497         popl    %edi
  498         popl    %esi
  499         cld
  500         ret
  501 
  502 #if defined(I586_CPU) && defined(DEV_NPX)
  503 ENTRY(i586_bcopy)
  504         pushl   %esi
  505         pushl   %edi
  506         movl    12(%esp),%esi
  507         movl    16(%esp),%edi
  508         movl    20(%esp),%ecx
  509 
  510         movl    %edi,%eax
  511         subl    %esi,%eax
  512         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
  513         jb      1f
  514 
  515         cmpl    $1024,%ecx
  516         jb      small_i586_bcopy
  517 
  518         sarb    $1,kernel_fpu_lock
  519         jc      small_i586_bcopy
  520         cmpl    $0,PCPU(FPCURTHREAD)
  521         je      i586_bc1
  522 
  523         /* XXX turn off handling of cases 1-2, as above. */
  524         movb    $0xfe,kernel_fpu_lock
  525         jmp     small_i586_bcopy
  526 
  527         smsw    %dx
  528         clts
  529         subl    $108,%esp
  530         fnsave  0(%esp)
  531         jmp     4f
  532 
  533 i586_bc1:
  534         smsw    %dx
  535         clts
  536         fninit                          /* XXX should avoid needing this */
  537 
  538         ALIGN_TEXT
  539 4:
  540         pushl   %ecx
  541 #define DCACHE_SIZE     8192
  542         cmpl    $(DCACHE_SIZE-512)/2,%ecx
  543         jbe     2f
  544         movl    $(DCACHE_SIZE-512)/2,%ecx
  545 2:
  546         subl    %ecx,0(%esp)
  547         cmpl    $256,%ecx
  548         jb      5f                      /* XXX should prefetch if %ecx >= 32 */
  549         pushl   %esi
  550         pushl   %ecx
  551         ALIGN_TEXT
  552 3:
  553         movl    0(%esi),%eax
  554         movl    32(%esi),%eax
  555         movl    64(%esi),%eax
  556         movl    96(%esi),%eax
  557         movl    128(%esi),%eax
  558         movl    160(%esi),%eax
  559         movl    192(%esi),%eax
  560         movl    224(%esi),%eax
  561         addl    $256,%esi
  562         subl    $256,%ecx
  563         cmpl    $256,%ecx
  564         jae     3b
  565         popl    %ecx
  566         popl    %esi
  567 5:
  568         ALIGN_TEXT
  569 large_i586_bcopy_loop:
  570         fildq   0(%esi)
  571         fildq   8(%esi)
  572         fildq   16(%esi)
  573         fildq   24(%esi)
  574         fildq   32(%esi)
  575         fildq   40(%esi)
  576         fildq   48(%esi)
  577         fildq   56(%esi)
  578         fistpq  56(%edi)
  579         fistpq  48(%edi)
  580         fistpq  40(%edi)
  581         fistpq  32(%edi)
  582         fistpq  24(%edi)
  583         fistpq  16(%edi)
  584         fistpq  8(%edi)
  585         fistpq  0(%edi)
  586         addl    $64,%esi
  587         addl    $64,%edi
  588         subl    $64,%ecx
  589         cmpl    $64,%ecx
  590         jae     large_i586_bcopy_loop
  591         popl    %eax
  592         addl    %eax,%ecx
  593         cmpl    $64,%ecx
  594         jae     4b
  595 
  596         cmpl    $0,PCPU(FPCURTHREAD)
  597         je      i586_bc2
  598 
  599         /* XXX check that the condition for cases 1-2 stayed false. */
  600 i586_bcopy_oops:
  601         int     $3
  602         jmp     i586_bcopy_oops
  603 
  604         frstor  0(%esp)
  605         addl    $108,%esp
  606 i586_bc2:
  607         lmsw    %dx
  608         movb    $0xfe,kernel_fpu_lock
  609 
  610 /*
  611  * This is a duplicate of the main part of generic_bcopy.  See the comments
  612  * there.  Jumping into generic_bcopy would cost a whole 0-1 cycles and
  613  * would mess up high resolution profiling.
  614  */
  615         ALIGN_TEXT
  616 small_i586_bcopy:
  617         shrl    $2,%ecx
  618         cld
  619         rep
  620         movsl
  621         movl    20(%esp),%ecx
  622         andl    $3,%ecx
  623         rep
  624         movsb
  625         popl    %edi
  626         popl    %esi
  627         ret
  628 
  629         ALIGN_TEXT
  630 1:
  631         addl    %ecx,%edi
  632         addl    %ecx,%esi
  633         decl    %edi
  634         decl    %esi
  635         andl    $3,%ecx
  636         std
  637         rep
  638         movsb
  639         movl    20(%esp),%ecx
  640         shrl    $2,%ecx
  641         subl    $3,%esi
  642         subl    $3,%edi
  643         rep
  644         movsl
  645         popl    %edi
  646         popl    %esi
  647         cld
  648         ret
  649 #endif /* I586_CPU && defined(DEV_NPX) */
  650 
  651 /*
  652  * Note: memcpy does not support overlapping copies
  653  */
  654 ENTRY(memcpy)
  655         pushl   %edi
  656         pushl   %esi
  657         movl    12(%esp),%edi
  658         movl    16(%esp),%esi
  659         movl    20(%esp),%ecx
  660         movl    %edi,%eax
  661         shrl    $2,%ecx                         /* copy by 32-bit words */
  662         cld                                     /* nope, copy forwards */
  663         rep
  664         movsl
  665         movl    20(%esp),%ecx
  666         andl    $3,%ecx                         /* any bytes left? */
  667         rep
  668         movsb
  669         popl    %esi
  670         popl    %edi
  671         ret
  672 
  673 
  674 /*****************************************************************************/
  675 /* copyout and fubyte family                                                 */
  676 /*****************************************************************************/
  677 /*
  678  * Access user memory from inside the kernel. These routines and possibly
  679  * the math- and DOS emulators should be the only places that do this.
  680  *
  681  * We have to access the memory with user's permissions, so use a segment
  682  * selector with RPL 3. For writes to user space we have to additionally
  683  * check the PTE for write permission, because the 386 does not check
  684  * write permissions when we are executing with EPL 0. The 486 does check
  685  * this if the WP bit is set in CR0, so we can use a simpler version here.
  686  *
  687  * These routines set curpcb->onfault for the time they execute. When a
  688  * protection violation occurs inside the functions, the trap handler
  689  * returns to *curpcb->onfault instead of the function.
  690  */
  691 
  692 /*
  693  * copyout(from_kernel, to_user, len)  - MP SAFE (if not I386_CPU)
  694  */
  695 ENTRY(copyout)
  696         MEXITCOUNT
  697         jmp     *copyout_vector
  698 
  699 ENTRY(generic_copyout)
  700         movl    PCPU(CURPCB),%eax
  701         movl    $copyout_fault,PCB_ONFAULT(%eax)
  702         pushl   %esi
  703         pushl   %edi
  704         pushl   %ebx
  705         movl    16(%esp),%esi
  706         movl    20(%esp),%edi
  707         movl    24(%esp),%ebx
  708         testl   %ebx,%ebx                       /* anything to do? */
  709         jz      done_copyout
  710 
  711         /*
  712          * Check explicitly for non-user addresses.  If 486 write protection
  713          * is being used, this check is essential because we are in kernel
  714          * mode so the h/w does not provide any protection against writing
  715          * kernel addresses.
  716          */
  717 
  718         /*
  719          * First, prevent address wrapping.
  720          */
  721         movl    %edi,%eax
  722         addl    %ebx,%eax
  723         jc      copyout_fault
  724 /*
  725  * XXX STOP USING VM_MAXUSER_ADDRESS.
  726  * It is an end address, not a max, so every time it is used correctly it
  727  * looks like there is an off by one error, and of course it caused an off
  728  * by one error in several places.
  729  */
  730         cmpl    $VM_MAXUSER_ADDRESS,%eax
  731         ja      copyout_fault
  732 
  733 #ifdef I386_CPU
  734 
  735 /*
  736  * We have to check each PTE for user write permission.
  737  * The checking may cause a page fault, so it is important to set
  738  * up everything for return via copyout_fault before here.
  739  */
  740         /* compute number of pages */
  741         movl    %edi,%ecx
  742         andl    $PAGE_MASK,%ecx
  743         addl    %ebx,%ecx
  744         decl    %ecx
  745         shrl    $IDXSHIFT+2,%ecx
  746         incl    %ecx
  747 
  748         /* compute PTE offset for start address */
  749         movl    %edi,%edx
  750         shrl    $IDXSHIFT,%edx
  751         andb    $0xfc,%dl
  752 
  753 1:
  754         /* check PTE for each page */
  755         leal    PTmap(%edx),%eax
  756         shrl    $IDXSHIFT,%eax
  757         andb    $0xfc,%al
  758         testb   $PG_V,PTmap(%eax)               /* PTE page must be valid */
  759         je      4f
  760         movb    PTmap(%edx),%al
  761         andb    $PG_V|PG_RW|PG_U,%al            /* page must be valid and user writable */
  762         cmpb    $PG_V|PG_RW|PG_U,%al
  763         je      2f
  764 
  765 4:
  766         /* simulate a trap */
  767         pushl   %edx
  768         pushl   %ecx
  769         shll    $IDXSHIFT,%edx
  770         pushl   %edx
  771         call    trapwrite                       /* trapwrite(addr) */
  772         popl    %edx
  773         popl    %ecx
  774         popl    %edx
  775 
  776         testl   %eax,%eax                       /* if not ok, return EFAULT */
  777         jnz     copyout_fault
  778 
  779 2:
  780         addl    $4,%edx
  781         decl    %ecx
  782         jnz     1b                              /* check next page */
  783 #endif /* I386_CPU */
  784 
  785         /* bcopy(%esi, %edi, %ebx) */
  786         movl    %ebx,%ecx
  787 
  788 #if defined(I586_CPU) && defined(DEV_NPX)
  789         ALIGN_TEXT
  790 slow_copyout:
  791 #endif
  792         shrl    $2,%ecx
  793         cld
  794         rep
  795         movsl
  796         movb    %bl,%cl
  797         andb    $3,%cl
  798         rep
  799         movsb
  800 
  801 done_copyout:
  802         popl    %ebx
  803         popl    %edi
  804         popl    %esi
  805         xorl    %eax,%eax
  806         movl    PCPU(CURPCB),%edx
  807         movl    %eax,PCB_ONFAULT(%edx)
  808         ret
  809 
  810         ALIGN_TEXT
  811 copyout_fault:
  812         popl    %ebx
  813         popl    %edi
  814         popl    %esi
  815         movl    PCPU(CURPCB),%edx
  816         movl    $0,PCB_ONFAULT(%edx)
  817         movl    $EFAULT,%eax
  818         ret
  819 
  820 #if defined(I586_CPU) && defined(DEV_NPX)
  821 ENTRY(i586_copyout)
  822         /*
  823          * Duplicated from generic_copyout.  Could be done a bit better.
  824          */
  825         movl    PCPU(CURPCB),%eax
  826         movl    $copyout_fault,PCB_ONFAULT(%eax)
  827         pushl   %esi
  828         pushl   %edi
  829         pushl   %ebx
  830         movl    16(%esp),%esi
  831         movl    20(%esp),%edi
  832         movl    24(%esp),%ebx
  833         testl   %ebx,%ebx                       /* anything to do? */
  834         jz      done_copyout
  835 
  836         /*
  837          * Check explicitly for non-user addresses.  If 486 write protection
  838          * is being used, this check is essential because we are in kernel
  839          * mode so the h/w does not provide any protection against writing
  840          * kernel addresses.
  841          */
  842 
  843         /*
  844          * First, prevent address wrapping.
  845          */
  846         movl    %edi,%eax
  847         addl    %ebx,%eax
  848         jc      copyout_fault
  849 /*
  850  * XXX STOP USING VM_MAXUSER_ADDRESS.
  851  * It is an end address, not a max, so every time it is used correctly it
  852  * looks like there is an off by one error, and of course it caused an off
  853  * by one error in several places.
  854  */
  855         cmpl    $VM_MAXUSER_ADDRESS,%eax
  856         ja      copyout_fault
  857 
  858         /* bcopy(%esi, %edi, %ebx) */
  859 3:
  860         movl    %ebx,%ecx
  861         /*
  862          * End of duplicated code.
  863          */
  864 
  865         cmpl    $1024,%ecx
  866         jb      slow_copyout
  867 
  868         pushl   %ecx
  869         call    fastmove
  870         addl    $4,%esp
  871         jmp     done_copyout
  872 #endif /* I586_CPU && defined(DEV_NPX) */
  873 
  874 /*
  875  * copyin(from_user, to_kernel, len) - MP SAFE
  876  */
  877 ENTRY(copyin)
  878         MEXITCOUNT
  879         jmp     *copyin_vector
  880 
  881 ENTRY(generic_copyin)
  882         movl    PCPU(CURPCB),%eax
  883         movl    $copyin_fault,PCB_ONFAULT(%eax)
  884         pushl   %esi
  885         pushl   %edi
  886         movl    12(%esp),%esi                   /* caddr_t from */
  887         movl    16(%esp),%edi                   /* caddr_t to */
  888         movl    20(%esp),%ecx                   /* size_t  len */
  889 
  890         /*
  891          * make sure address is valid
  892          */
  893         movl    %esi,%edx
  894         addl    %ecx,%edx
  895         jc      copyin_fault
  896         cmpl    $VM_MAXUSER_ADDRESS,%edx
  897         ja      copyin_fault
  898 
  899 #if defined(I586_CPU) && defined(DEV_NPX)
  900         ALIGN_TEXT
  901 slow_copyin:
  902 #endif
  903         movb    %cl,%al
  904         shrl    $2,%ecx                         /* copy longword-wise */
  905         cld
  906         rep
  907         movsl
  908         movb    %al,%cl
  909         andb    $3,%cl                          /* copy remaining bytes */
  910         rep
  911         movsb
  912 
  913 #if defined(I586_CPU) && defined(DEV_NPX)
  914         ALIGN_TEXT
  915 done_copyin:
  916 #endif
  917         popl    %edi
  918         popl    %esi
  919         xorl    %eax,%eax
  920         movl    PCPU(CURPCB),%edx
  921         movl    %eax,PCB_ONFAULT(%edx)
  922         ret
  923 
  924         ALIGN_TEXT
  925 copyin_fault:
  926         popl    %edi
  927         popl    %esi
  928         movl    PCPU(CURPCB),%edx
  929         movl    $0,PCB_ONFAULT(%edx)
  930         movl    $EFAULT,%eax
  931         ret
  932 
  933 #if defined(I586_CPU) && defined(DEV_NPX)
  934 ENTRY(i586_copyin)
  935         /*
  936          * Duplicated from generic_copyin.  Could be done a bit better.
  937          */
  938         movl    PCPU(CURPCB),%eax
  939         movl    $copyin_fault,PCB_ONFAULT(%eax)
  940         pushl   %esi
  941         pushl   %edi
  942         movl    12(%esp),%esi                   /* caddr_t from */
  943         movl    16(%esp),%edi                   /* caddr_t to */
  944         movl    20(%esp),%ecx                   /* size_t  len */
  945 
  946         /*
  947          * make sure address is valid
  948          */
  949         movl    %esi,%edx
  950         addl    %ecx,%edx
  951         jc      copyin_fault
  952         cmpl    $VM_MAXUSER_ADDRESS,%edx
  953         ja      copyin_fault
  954         /*
  955          * End of duplicated code.
  956          */
  957 
  958         cmpl    $1024,%ecx
  959         jb      slow_copyin
  960 
  961         pushl   %ebx                    /* XXX prepare for fastmove_fault */
  962         pushl   %ecx
  963         call    fastmove
  964         addl    $8,%esp
  965         jmp     done_copyin
  966 #endif /* I586_CPU && defined(DEV_NPX) */
  967 
  968 #if defined(I586_CPU) && defined(DEV_NPX)
  969 /* fastmove(src, dst, len)
  970         src in %esi
  971         dst in %edi
  972         len in %ecx             XXX changed to on stack for profiling
  973         uses %eax and %edx for tmp. storage
  974  */
  975 /* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
  976 ENTRY(fastmove)
  977         pushl   %ebp
  978         movl    %esp,%ebp
  979         subl    $PCB_SAVEFPU_SIZE+3*4,%esp
  980 
  981         movl    8(%ebp),%ecx
  982         cmpl    $63,%ecx
  983         jbe     fastmove_tail
  984 
  985         testl   $7,%esi /* check if src addr is multiple of 8 */
  986         jnz     fastmove_tail
  987 
  988         testl   $7,%edi /* check if dst addr is multiple of 8 */
  989         jnz     fastmove_tail
  990 
  991         /* XXX grab FPU context atomically. */
  992         cli
  993 
  994 /* if (fpcurthread != NULL) { */
  995         cmpl    $0,PCPU(FPCURTHREAD)
  996         je      6f
  997 /*    fnsave(&curpcb->pcb_savefpu); */
  998         movl    PCPU(CURPCB),%eax
  999         fnsave  PCB_SAVEFPU(%eax)
 1000 /*   FPCURTHREAD = NULL; */
 1001         movl    $0,PCPU(FPCURTHREAD)
 1002 /* } */
 1003 6:
 1004 /* now we own the FPU. */
 1005 
 1006 /*
 1007  * The process' FP state is saved in the pcb, but if we get
 1008  * switched, the cpu_switch() will store our FP state in the
 1009  * pcb.  It should be possible to avoid all the copying for
 1010  * this, e.g., by setting a flag to tell cpu_switch() to
 1011  * save the state somewhere else.
 1012  */
 1013 /* tmp = curpcb->pcb_savefpu; */
 1014         movl    %ecx,-12(%ebp)
 1015         movl    %esi,-8(%ebp)
 1016         movl    %edi,-4(%ebp)
 1017         movl    %esp,%edi
 1018         movl    PCPU(CURPCB),%esi
 1019         addl    $PCB_SAVEFPU,%esi
 1020         cld
 1021         movl    $PCB_SAVEFPU_SIZE>>2,%ecx
 1022         rep
 1023         movsl
 1024         movl    -12(%ebp),%ecx
 1025         movl    -8(%ebp),%esi
 1026         movl    -4(%ebp),%edi
 1027 /* stop_emulating(); */
 1028         clts
 1029 /* fpcurthread = curthread; */
 1030         movl    PCPU(CURTHREAD),%eax
 1031         movl    %eax,PCPU(FPCURTHREAD)
 1032         movl    PCPU(CURPCB),%eax
 1033 
 1034         /* XXX end of atomic FPU context grab. */
 1035         sti
 1036 
 1037         movl    $fastmove_fault,PCB_ONFAULT(%eax)
 1038 4:
 1039         movl    %ecx,-12(%ebp)
 1040         cmpl    $1792,%ecx
 1041         jbe     2f
 1042         movl    $1792,%ecx
 1043 2:
 1044         subl    %ecx,-12(%ebp)
 1045         cmpl    $256,%ecx
 1046         jb      5f
 1047         movl    %ecx,-8(%ebp)
 1048         movl    %esi,-4(%ebp)
 1049         ALIGN_TEXT
 1050 3:
 1051         movl    0(%esi),%eax
 1052         movl    32(%esi),%eax
 1053         movl    64(%esi),%eax
 1054         movl    96(%esi),%eax
 1055         movl    128(%esi),%eax
 1056         movl    160(%esi),%eax
 1057         movl    192(%esi),%eax
 1058         movl    224(%esi),%eax
 1059         addl    $256,%esi
 1060         subl    $256,%ecx
 1061         cmpl    $256,%ecx
 1062         jae     3b
 1063         movl    -8(%ebp),%ecx
 1064         movl    -4(%ebp),%esi
 1065 5:
 1066         ALIGN_TEXT
 1067 fastmove_loop:
 1068         fildq   0(%esi)
 1069         fildq   8(%esi)
 1070         fildq   16(%esi)
 1071         fildq   24(%esi)
 1072         fildq   32(%esi)
 1073         fildq   40(%esi)
 1074         fildq   48(%esi)
 1075         fildq   56(%esi)
 1076         fistpq  56(%edi)
 1077         fistpq  48(%edi)
 1078         fistpq  40(%edi)
 1079         fistpq  32(%edi)
 1080         fistpq  24(%edi)
 1081         fistpq  16(%edi)
 1082         fistpq  8(%edi)
 1083         fistpq  0(%edi)
 1084         addl    $-64,%ecx
 1085         addl    $64,%esi
 1086         addl    $64,%edi
 1087         cmpl    $63,%ecx
 1088         ja      fastmove_loop
 1089         movl    -12(%ebp),%eax
 1090         addl    %eax,%ecx
 1091         cmpl    $64,%ecx
 1092         jae     4b
 1093 
 1094         /* XXX ungrab FPU context atomically. */
 1095         cli
 1096 
 1097 /* curpcb->pcb_savefpu = tmp; */
 1098         movl    %ecx,-12(%ebp)
 1099         movl    %esi,-8(%ebp)
 1100         movl    %edi,-4(%ebp)
 1101         movl    PCPU(CURPCB),%edi
 1102         addl    $PCB_SAVEFPU,%edi
 1103         movl    %esp,%esi
 1104         cld
 1105         movl    $PCB_SAVEFPU_SIZE>>2,%ecx
 1106         rep
 1107         movsl
 1108         movl    -12(%ebp),%ecx
 1109         movl    -8(%ebp),%esi
 1110         movl    -4(%ebp),%edi
 1111 
 1112 /* start_emulating(); */
 1113         smsw    %ax
 1114         orb     $CR0_TS,%al
 1115         lmsw    %ax
 1116 /* fpcurthread = NULL; */
 1117         movl    $0,PCPU(FPCURTHREAD)
 1118 
 1119         /* XXX end of atomic FPU context ungrab. */
 1120         sti
 1121 
 1122         ALIGN_TEXT
 1123 fastmove_tail:
 1124         movl    PCPU(CURPCB),%eax
 1125         movl    $fastmove_tail_fault,PCB_ONFAULT(%eax)
 1126 
 1127         movb    %cl,%al
 1128         shrl    $2,%ecx                         /* copy longword-wise */
 1129         cld
 1130         rep
 1131         movsl
 1132         movb    %al,%cl
 1133         andb    $3,%cl                          /* copy remaining bytes */
 1134         rep
 1135         movsb
 1136 
 1137         movl    %ebp,%esp
 1138         popl    %ebp
 1139         ret
 1140 
 1141         ALIGN_TEXT
 1142 fastmove_fault:
 1143         /* XXX ungrab FPU context atomically. */
 1144         cli
 1145 
 1146         movl    PCPU(CURPCB),%edi
 1147         addl    $PCB_SAVEFPU,%edi
 1148         movl    %esp,%esi
 1149         cld
 1150         movl    $PCB_SAVEFPU_SIZE>>2,%ecx
 1151         rep
 1152         movsl
 1153 
 1154         smsw    %ax
 1155         orb     $CR0_TS,%al
 1156         lmsw    %ax
 1157         movl    $0,PCPU(FPCURTHREAD)
 1158 
 1159         /* XXX end of atomic FPU context ungrab. */
 1160         sti
 1161 
 1162 fastmove_tail_fault:
 1163         movl    %ebp,%esp
 1164         popl    %ebp
 1165         addl    $8,%esp
 1166         popl    %ebx
 1167         popl    %edi
 1168         popl    %esi
 1169         movl    PCPU(CURPCB),%edx
 1170         movl    $0,PCB_ONFAULT(%edx)
 1171         movl    $EFAULT,%eax
 1172         ret
 1173 #endif /* I586_CPU && defined(DEV_NPX) */
 1174 
 1175 /*
 1176  * fu{byte,sword,word} - MP SAFE
 1177  *
 1178  *      Fetch a byte (sword, word) from user memory
 1179  */
 1180 ENTRY(fuword)
 1181         movl    PCPU(CURPCB),%ecx
 1182         movl    $fusufault,PCB_ONFAULT(%ecx)
 1183         movl    4(%esp),%edx                    /* from */
 1184 
 1185         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address is valid */
 1186         ja      fusufault
 1187 
 1188         movl    (%edx),%eax
 1189         movl    $0,PCB_ONFAULT(%ecx)
 1190         ret
 1191 
 1192 ENTRY(fuword32)
 1193         jmp     fuword
 1194 
 1195 /*
 1196  * These two routines are called from the profiling code, potentially
 1197  * at interrupt time. If they fail, that's okay, good things will
 1198  * happen later. Fail all the time for now - until the trap code is
 1199  * able to deal with this.
 1200  */
 1201 ALTENTRY(suswintr)
 1202 ENTRY(fuswintr)
 1203         movl    $-1,%eax
 1204         ret
 1205 
 1206 /*
 1207  * fuword16 - MP SAFE
 1208  */
 1209 ENTRY(fuword16)
 1210         movl    PCPU(CURPCB),%ecx
 1211         movl    $fusufault,PCB_ONFAULT(%ecx)
 1212         movl    4(%esp),%edx
 1213 
 1214         cmpl    $VM_MAXUSER_ADDRESS-2,%edx
 1215         ja      fusufault
 1216 
 1217         movzwl  (%edx),%eax
 1218         movl    $0,PCB_ONFAULT(%ecx)
 1219         ret
 1220 
 1221 /*
 1222  * fubyte - MP SAFE
 1223  */
 1224 ENTRY(fubyte)
 1225         movl    PCPU(CURPCB),%ecx
 1226         movl    $fusufault,PCB_ONFAULT(%ecx)
 1227         movl    4(%esp),%edx
 1228 
 1229         cmpl    $VM_MAXUSER_ADDRESS-1,%edx
 1230         ja      fusufault
 1231 
 1232         movzbl  (%edx),%eax
 1233         movl    $0,PCB_ONFAULT(%ecx)
 1234         ret
 1235 
 1236         ALIGN_TEXT
 1237 fusufault:
 1238         movl    PCPU(CURPCB),%ecx
 1239         xorl    %eax,%eax
 1240         movl    %eax,PCB_ONFAULT(%ecx)
 1241         decl    %eax
 1242         ret
 1243 
 1244 /*
 1245  * su{byte,sword,word} - MP SAFE (if not I386_CPU)
 1246  *
 1247  *      Write a byte (word, longword) to user memory
 1248  */
 1249 ENTRY(suword)
 1250         movl    PCPU(CURPCB),%ecx
 1251         movl    $fusufault,PCB_ONFAULT(%ecx)
 1252         movl    4(%esp),%edx
 1253 
 1254 #ifdef I386_CPU
 1255 
 1256         /* XXX - page boundary crossing is still not handled */
 1257         movl    %edx,%eax
 1258         shrl    $IDXSHIFT,%edx
 1259         andb    $0xfc,%dl
 1260 
 1261         leal    PTmap(%edx),%ecx
 1262         shrl    $IDXSHIFT,%ecx
 1263         andb    $0xfc,%cl
 1264         testb   $PG_V,PTmap(%ecx)               /* PTE page must be valid */
 1265         je      4f
 1266         movb    PTmap(%edx),%dl
 1267         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
 1268         cmpb    $PG_V|PG_RW|PG_U,%dl
 1269         je      1f
 1270 
 1271 4:
 1272         /* simulate a trap */
 1273         pushl   %eax
 1274         call    trapwrite
 1275         popl    %edx                            /* remove junk parameter from stack */
 1276         testl   %eax,%eax
 1277         jnz     fusufault
 1278 1:
 1279         movl    4(%esp),%edx
 1280 #endif
 1281 
 1282         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address validity */
 1283         ja      fusufault
 1284 
 1285         movl    8(%esp),%eax
 1286         movl    %eax,(%edx)
 1287         xorl    %eax,%eax
 1288         movl    PCPU(CURPCB),%ecx
 1289         movl    %eax,PCB_ONFAULT(%ecx)
 1290         ret
 1291 
 1292 ENTRY(suword32)
 1293         jmp     suword
 1294 
 1295 /*
 1296  * suword16 - MP SAFE (if not I386_CPU)
 1297  */
 1298 ENTRY(suword16)
 1299         movl    PCPU(CURPCB),%ecx
 1300         movl    $fusufault,PCB_ONFAULT(%ecx)
 1301         movl    4(%esp),%edx
 1302 
 1303 #ifdef I386_CPU
 1304 
 1305         /* XXX - page boundary crossing is still not handled */
 1306         movl    %edx,%eax
 1307         shrl    $IDXSHIFT,%edx
 1308         andb    $0xfc,%dl
 1309 
 1310         leal    PTmap(%edx),%ecx
 1311         shrl    $IDXSHIFT,%ecx
 1312         andb    $0xfc,%cl
 1313         testb   $PG_V,PTmap(%ecx)               /* PTE page must be valid */
 1314         je      4f
 1315         movb    PTmap(%edx),%dl
 1316         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
 1317         cmpb    $PG_V|PG_RW|PG_U,%dl
 1318         je      1f
 1319 
 1320 4:
 1321         /* simulate a trap */
 1322         pushl   %eax
 1323         call    trapwrite
 1324         popl    %edx                            /* remove junk parameter from stack */
 1325         testl   %eax,%eax
 1326         jnz     fusufault
 1327 1:
 1328         movl    4(%esp),%edx
 1329 #endif
 1330 
 1331         cmpl    $VM_MAXUSER_ADDRESS-2,%edx      /* verify address validity */
 1332         ja      fusufault
 1333 
 1334         movw    8(%esp),%ax
 1335         movw    %ax,(%edx)
 1336         xorl    %eax,%eax
 1337         movl    PCPU(CURPCB),%ecx               /* restore trashed register */
 1338         movl    %eax,PCB_ONFAULT(%ecx)
 1339         ret
 1340 
 1341 /*
 1342  * subyte - MP SAFE (if not I386_CPU)
 1343  */
 1344 ENTRY(subyte)
 1345         movl    PCPU(CURPCB),%ecx
 1346         movl    $fusufault,PCB_ONFAULT(%ecx)
 1347         movl    4(%esp),%edx
 1348 
 1349 #ifdef I386_CPU
 1350 
 1351         movl    %edx,%eax
 1352         shrl    $IDXSHIFT,%edx
 1353         andb    $0xfc,%dl
 1354 
 1355         leal    PTmap(%edx),%ecx
 1356         shrl    $IDXSHIFT,%ecx
 1357         andb    $0xfc,%cl
 1358         testb   $PG_V,PTmap(%ecx)               /* PTE page must be valid */
 1359         je      4f
 1360         movb    PTmap(%edx),%dl
 1361         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
 1362         cmpb    $PG_V|PG_RW|PG_U,%dl
 1363         je      1f
 1364 
 1365 4:
 1366         /* simulate a trap */
 1367         pushl   %eax
 1368         call    trapwrite
 1369         popl    %edx                            /* remove junk parameter from stack */
 1370         testl   %eax,%eax
 1371         jnz     fusufault
 1372 1:
 1373         movl    4(%esp),%edx
 1374 #endif
 1375 
 1376         cmpl    $VM_MAXUSER_ADDRESS-1,%edx      /* verify address validity */
 1377         ja      fusufault
 1378 
 1379         movb    8(%esp),%al
 1380         movb    %al,(%edx)
 1381         xorl    %eax,%eax
 1382         movl    PCPU(CURPCB),%ecx               /* restore trashed register */
 1383         movl    %eax,PCB_ONFAULT(%ecx)
 1384         ret
 1385 
 1386 /*
 1387  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
 1388  *
 1389  *      copy a string from from to to, stop when a 0 character is reached.
 1390  *      return ENAMETOOLONG if string is longer than maxlen, and
 1391  *      EFAULT on protection violations. If lencopied is non-zero,
 1392  *      return the actual length in *lencopied.
 1393  */
 1394 ENTRY(copyinstr)
 1395         pushl   %esi
 1396         pushl   %edi
 1397         movl    PCPU(CURPCB),%ecx
 1398         movl    $cpystrflt,PCB_ONFAULT(%ecx)
 1399 
 1400         movl    12(%esp),%esi                   /* %esi = from */
 1401         movl    16(%esp),%edi                   /* %edi = to */
 1402         movl    20(%esp),%edx                   /* %edx = maxlen */
 1403 
 1404         movl    $VM_MAXUSER_ADDRESS,%eax
 1405 
 1406         /* make sure 'from' is within bounds */
 1407         subl    %esi,%eax
 1408         jbe     cpystrflt
 1409 
 1410         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
 1411         cmpl    %edx,%eax
 1412         jae     1f
 1413         movl    %eax,%edx
 1414         movl    %eax,20(%esp)
 1415 1:
 1416         incl    %edx
 1417         cld
 1418 
 1419 2:
 1420         decl    %edx
 1421         jz      3f
 1422 
 1423         lodsb
 1424         stosb
 1425         orb     %al,%al
 1426         jnz     2b
 1427 
 1428         /* Success -- 0 byte reached */
 1429         decl    %edx
 1430         xorl    %eax,%eax
 1431         jmp     cpystrflt_x
 1432 3:
 1433         /* edx is zero - return ENAMETOOLONG or EFAULT */
 1434         cmpl    $VM_MAXUSER_ADDRESS,%esi
 1435         jae     cpystrflt
 1436 4:
 1437         movl    $ENAMETOOLONG,%eax
 1438         jmp     cpystrflt_x
 1439 
 1440 cpystrflt:
 1441         movl    $EFAULT,%eax
 1442 
 1443 cpystrflt_x:
 1444         /* set *lencopied and return %eax */
 1445         movl    PCPU(CURPCB),%ecx
 1446         movl    $0,PCB_ONFAULT(%ecx)
 1447         movl    20(%esp),%ecx
 1448         subl    %edx,%ecx
 1449         movl    24(%esp),%edx
 1450         testl   %edx,%edx
 1451         jz      1f
 1452         movl    %ecx,(%edx)
 1453 1:
 1454         popl    %edi
 1455         popl    %esi
 1456         ret
 1457 
 1458 
 1459 /*
 1460  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
 1461  */
 1462 ENTRY(copystr)
 1463         pushl   %esi
 1464         pushl   %edi
 1465 
 1466         movl    12(%esp),%esi                   /* %esi = from */
 1467         movl    16(%esp),%edi                   /* %edi = to */
 1468         movl    20(%esp),%edx                   /* %edx = maxlen */
 1469         incl    %edx
 1470         cld
 1471 1:
 1472         decl    %edx
 1473         jz      4f
 1474         lodsb
 1475         stosb
 1476         orb     %al,%al
 1477         jnz     1b
 1478 
 1479         /* Success -- 0 byte reached */
 1480         decl    %edx
 1481         xorl    %eax,%eax
 1482         jmp     6f
 1483 4:
 1484         /* edx is zero -- return ENAMETOOLONG */
 1485         movl    $ENAMETOOLONG,%eax
 1486 
 1487 6:
 1488         /* set *lencopied and return %eax */
 1489         movl    20(%esp),%ecx
 1490         subl    %edx,%ecx
 1491         movl    24(%esp),%edx
 1492         testl   %edx,%edx
 1493         jz      7f
 1494         movl    %ecx,(%edx)
 1495 7:
 1496         popl    %edi
 1497         popl    %esi
 1498         ret
 1499 
 1500 ENTRY(bcmp)
 1501         pushl   %edi
 1502         pushl   %esi
 1503         movl    12(%esp),%edi
 1504         movl    16(%esp),%esi
 1505         movl    20(%esp),%edx
 1506         xorl    %eax,%eax
 1507 
 1508         movl    %edx,%ecx
 1509         shrl    $2,%ecx
 1510         cld                                     /* compare forwards */
 1511         repe
 1512         cmpsl
 1513         jne     1f
 1514 
 1515         movl    %edx,%ecx
 1516         andl    $3,%ecx
 1517         repe
 1518         cmpsb
 1519         je      2f
 1520 1:
 1521         incl    %eax
 1522 2:
 1523         popl    %esi
 1524         popl    %edi
 1525         ret
 1526 
 1527 
 1528 /*
 1529  * Handling of special 386 registers and descriptor tables etc
 1530  */
 1531 /* void lgdt(struct region_descriptor *rdp); */
 1532 ENTRY(lgdt)
 1533         /* reload the descriptor table */
 1534         movl    4(%esp),%eax
 1535         lgdt    (%eax)
 1536 
 1537         /* flush the prefetch q */
 1538         jmp     1f
 1539         nop
 1540 1:
 1541         /* reload "stale" selectors */
 1542         movl    $KDSEL,%eax
 1543         mov     %ax,%ds
 1544         mov     %ax,%es
 1545         mov     %ax,%gs
 1546         mov     %ax,%ss
 1547         movl    $KPSEL,%eax
 1548         mov     %ax,%fs
 1549 
 1550         /* reload code selector by turning return into intersegmental return */
 1551         movl    (%esp),%eax
 1552         pushl   %eax
 1553         movl    $KCSEL,4(%esp)
 1554         lret
 1555 
 1556 /* ssdtosd(*ssdp,*sdp) */
 1557 ENTRY(ssdtosd)
 1558         pushl   %ebx
 1559         movl    8(%esp),%ecx
 1560         movl    8(%ecx),%ebx
 1561         shll    $16,%ebx
 1562         movl    (%ecx),%edx
 1563         roll    $16,%edx
 1564         movb    %dh,%bl
 1565         movb    %dl,%bh
 1566         rorl    $8,%ebx
 1567         movl    4(%ecx),%eax
 1568         movw    %ax,%dx
 1569         andl    $0xf0000,%eax
 1570         orl     %eax,%ebx
 1571         movl    12(%esp),%ecx
 1572         movl    %edx,(%ecx)
 1573         movl    %ebx,4(%ecx)
 1574         popl    %ebx
 1575         ret
 1576 
 1577 /* void reset_dbregs() */
 1578 ENTRY(reset_dbregs)
 1579         movl    $0,%eax
 1580         movl    %eax,%dr7     /* disable all breapoints first */
 1581         movl    %eax,%dr0
 1582         movl    %eax,%dr1
 1583         movl    %eax,%dr2
 1584         movl    %eax,%dr3
 1585         movl    %eax,%dr6
 1586         ret
 1587 
 1588 /*****************************************************************************/
 1589 /* setjump, longjump                                                         */
 1590 /*****************************************************************************/
 1591 
 1592 ENTRY(setjmp)
 1593         movl    4(%esp),%eax
 1594         movl    %ebx,(%eax)                     /* save ebx */
 1595         movl    %esp,4(%eax)                    /* save esp */
 1596         movl    %ebp,8(%eax)                    /* save ebp */
 1597         movl    %esi,12(%eax)                   /* save esi */
 1598         movl    %edi,16(%eax)                   /* save edi */
 1599         movl    (%esp),%edx                     /* get rta */
 1600         movl    %edx,20(%eax)                   /* save eip */
 1601         xorl    %eax,%eax                       /* return(0); */
 1602         ret
 1603 
 1604 ENTRY(longjmp)
 1605         movl    4(%esp),%eax
 1606         movl    (%eax),%ebx                     /* restore ebx */
 1607         movl    4(%eax),%esp                    /* restore esp */
 1608         movl    8(%eax),%ebp                    /* restore ebp */
 1609         movl    12(%eax),%esi                   /* restore esi */
 1610         movl    16(%eax),%edi                   /* restore edi */
 1611         movl    20(%eax),%edx                   /* get rta */
 1612         movl    %edx,(%esp)                     /* put in return frame */
 1613         xorl    %eax,%eax                       /* return(1); */
 1614         incl    %eax
 1615         ret
 1616 
 1617 /*
 1618  * Support for BB-profiling (gcc -a).  The kernbb program will extract
 1619  * the data from the kernel.
 1620  */
 1621 
 1622         .data
 1623         ALIGN_DATA
 1624         .globl bbhead
 1625 bbhead:
 1626         .long 0
 1627 
 1628         .text
 1629 NON_GPROF_ENTRY(__bb_init_func)
 1630         movl    4(%esp),%eax
 1631         movl    $1,(%eax)
 1632         movl    bbhead,%edx
 1633         movl    %edx,16(%eax)
 1634         movl    %eax,bbhead
 1635         NON_GPROF_RET

Cache object: 56584af9275fb7bac99facdb8e031861


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