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

Cache object: 7fe6b844481cbfa1ef67db08e6af7c7f


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