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 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) && NNPX > 0
   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 #if defined(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) && NNPX > 0
  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          * `npxproc != NULL' is supposed to be the condition that all the
  220          * FPU resources belong to an application, but npxproc 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,_npxproc
  245         je      i586_bz1
  246         cmpl    $256+184,%ecx           /* empirical; not quite 2*108 more */
  247         jb      intreg_i586_bzero
  248         sarb    $1,kernel_fpu_lock
  249         jc      intreg_i586_bzero
  250         smsw    %ax
  251         clts
  252         subl    $108,%esp
  253         fnsave  0(%esp)
  254         jmp     i586_bz2
  255 
  256 i586_bz1:
  257         sarb    $1,kernel_fpu_lock
  258         jc      intreg_i586_bzero
  259         smsw    %ax
  260         clts
  261         fninit                          /* XXX should avoid needing this */
  262 i586_bz2:
  263         fldz
  264 
  265         /*
  266          * Align to an 8 byte boundary (misalignment in the main loop would
  267          * cost a factor of >= 2).  Avoid jumps (at little cost if it is
  268          * already aligned) by always zeroing 8 bytes and using the part up
  269          * to the _next_ alignment position.
  270          */
  271         fstl    0(%edx)
  272         addl    %edx,%ecx               /* part of %ecx -= new_%edx - %edx */
  273         addl    $8,%edx
  274         andl    $~7,%edx
  275         subl    %edx,%ecx
  276 
  277         /*
  278          * Similarly align `len' to a multiple of 8.
  279          */
  280         fstl    -8(%edx,%ecx)
  281         decl    %ecx
  282         andl    $~7,%ecx
  283 
  284         /*
  285          * This wouldn't be any faster if it were unrolled, since the loop
  286          * control instructions are much faster than the fstl and/or done
  287          * in parallel with it so their overhead is insignificant.
  288          */
  289 fpureg_i586_bzero_loop:
  290         fstl    0(%edx)
  291         addl    $8,%edx
  292         subl    $8,%ecx
  293         cmpl    $8,%ecx
  294         jae     fpureg_i586_bzero_loop
  295 
  296         cmpl    $0,_npxproc
  297         je      i586_bz3
  298         frstor  0(%esp)
  299         addl    $108,%esp
  300         lmsw    %ax
  301         movb    $0xfe,kernel_fpu_lock
  302         ret
  303 
  304 i586_bz3:
  305         fstp    %st(0)
  306         lmsw    %ax
  307         movb    $0xfe,kernel_fpu_lock
  308         ret
  309 
  310 intreg_i586_bzero:
  311         /*
  312          * `rep stos' seems to be the best method in practice for small
  313          * counts.  Fancy methods usually take too long to start up due
  314          * to cache and BTB misses.
  315          */
  316         pushl   %edi
  317         movl    %edx,%edi
  318         xorl    %eax,%eax
  319         shrl    $2,%ecx
  320         cld
  321         rep
  322         stosl
  323         movl    12(%esp),%ecx
  324         andl    $3,%ecx
  325         jne     1f
  326         popl    %edi
  327         ret
  328 
  329 1:
  330         rep
  331         stosb
  332         popl    %edi
  333         ret
  334 #endif /* I586_CPU && NNPX > 0 */
  335 
  336 ENTRY(i686_pagezero)
  337         pushl   %edi
  338         pushl   %ebx
  339 
  340         movl    12(%esp), %edi
  341         movl    $1024, %ecx
  342         cld
  343 
  344         ALIGN_TEXT
  345 1:
  346         xorl    %eax, %eax
  347         repe
  348         scasl   
  349         jnz     2f
  350 
  351         popl    %ebx
  352         popl    %edi
  353         ret
  354 
  355         ALIGN_TEXT
  356 
  357 2:
  358         incl    %ecx
  359         subl    $4, %edi
  360 
  361         movl    %ecx, %edx
  362         cmpl    $16, %ecx
  363 
  364         jge     3f
  365 
  366         movl    %edi, %ebx
  367         andl    $0x3f, %ebx
  368         shrl    %ebx
  369         shrl    %ebx
  370         movl    $16, %ecx
  371         subl    %ebx, %ecx
  372 
  373 3:
  374         subl    %ecx, %edx
  375         rep
  376         stosl
  377 
  378         movl    %edx, %ecx
  379         testl   %edx, %edx
  380         jnz     1b
  381 
  382         popl    %ebx
  383         popl    %edi
  384         ret
  385 
  386 /* fillw(pat, base, cnt) */
  387 ENTRY(fillw)
  388         pushl   %edi
  389         movl    8(%esp),%eax
  390         movl    12(%esp),%edi
  391         movl    16(%esp),%ecx
  392         cld
  393         rep
  394         stosw
  395         popl    %edi
  396         ret
  397 
  398 ENTRY(bcopyb)
  399         pushl   %esi
  400         pushl   %edi
  401         movl    12(%esp),%esi
  402         movl    16(%esp),%edi
  403         movl    20(%esp),%ecx
  404         movl    %edi,%eax
  405         subl    %esi,%eax
  406         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
  407         jb      1f
  408         cld                                     /* nope, copy forwards */
  409         rep
  410         movsb
  411         popl    %edi
  412         popl    %esi
  413         ret
  414 
  415         ALIGN_TEXT
  416 1:
  417         addl    %ecx,%edi                       /* copy backwards. */
  418         addl    %ecx,%esi
  419         decl    %edi
  420         decl    %esi
  421         std
  422         rep
  423         movsb
  424         popl    %edi
  425         popl    %esi
  426         cld
  427         ret
  428 
  429 ENTRY(bcopy)
  430         MEXITCOUNT
  431         jmp     *_bcopy_vector
  432 
  433 ENTRY(ovbcopy)
  434         MEXITCOUNT
  435         jmp     *_ovbcopy_vector
  436 
  437 /*
  438  * generic_bcopy(src, dst, cnt)
  439  *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
  440  */
  441 ENTRY(generic_bcopy)
  442         pushl   %esi
  443         pushl   %edi
  444         movl    12(%esp),%esi
  445         movl    16(%esp),%edi
  446         movl    20(%esp),%ecx
  447 
  448         movl    %edi,%eax
  449         subl    %esi,%eax
  450         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
  451         jb      1f
  452 
  453         shrl    $2,%ecx                         /* copy by 32-bit words */
  454         cld                                     /* nope, copy forwards */
  455         rep
  456         movsl
  457         movl    20(%esp),%ecx
  458         andl    $3,%ecx                         /* any bytes left? */
  459         rep
  460         movsb
  461         popl    %edi
  462         popl    %esi
  463         ret
  464 
  465         ALIGN_TEXT
  466 1:
  467         addl    %ecx,%edi                       /* copy backwards */
  468         addl    %ecx,%esi
  469         decl    %edi
  470         decl    %esi
  471         andl    $3,%ecx                         /* any fractional bytes? */
  472         std
  473         rep
  474         movsb
  475         movl    20(%esp),%ecx                   /* copy remainder by 32-bit words */
  476         shrl    $2,%ecx
  477         subl    $3,%esi
  478         subl    $3,%edi
  479         rep
  480         movsl
  481         popl    %edi
  482         popl    %esi
  483         cld
  484         ret
  485 
  486 #if defined(I586_CPU) && NNPX > 0
  487 ENTRY(i586_bcopy)
  488         pushl   %esi
  489         pushl   %edi
  490         movl    12(%esp),%esi
  491         movl    16(%esp),%edi
  492         movl    20(%esp),%ecx
  493 
  494         movl    %edi,%eax
  495         subl    %esi,%eax
  496         cmpl    %ecx,%eax                       /* overlapping && src < dst? */
  497         jb      1f
  498 
  499         cmpl    $1024,%ecx
  500         jb      small_i586_bcopy
  501 
  502         sarb    $1,kernel_fpu_lock
  503         jc      small_i586_bcopy
  504         cmpl    $0,_npxproc
  505         je      i586_bc1
  506         smsw    %dx
  507         clts
  508         subl    $108,%esp
  509         fnsave  0(%esp)
  510         jmp     4f
  511 
  512 i586_bc1:
  513         smsw    %dx
  514         clts
  515         fninit                          /* XXX should avoid needing this */
  516 
  517         ALIGN_TEXT
  518 4:
  519         pushl   %ecx
  520 #define DCACHE_SIZE     8192
  521         cmpl    $(DCACHE_SIZE-512)/2,%ecx
  522         jbe     2f
  523         movl    $(DCACHE_SIZE-512)/2,%ecx
  524 2:
  525         subl    %ecx,0(%esp)
  526         cmpl    $256,%ecx
  527         jb      5f                      /* XXX should prefetch if %ecx >= 32 */
  528         pushl   %esi
  529         pushl   %ecx
  530         ALIGN_TEXT
  531 3:
  532         movl    0(%esi),%eax
  533         movl    32(%esi),%eax
  534         movl    64(%esi),%eax
  535         movl    96(%esi),%eax
  536         movl    128(%esi),%eax
  537         movl    160(%esi),%eax
  538         movl    192(%esi),%eax
  539         movl    224(%esi),%eax
  540         addl    $256,%esi
  541         subl    $256,%ecx
  542         cmpl    $256,%ecx
  543         jae     3b
  544         popl    %ecx
  545         popl    %esi
  546 5:
  547         ALIGN_TEXT
  548 large_i586_bcopy_loop:
  549         fildq   0(%esi)
  550         fildq   8(%esi)
  551         fildq   16(%esi)
  552         fildq   24(%esi)
  553         fildq   32(%esi)
  554         fildq   40(%esi)
  555         fildq   48(%esi)
  556         fildq   56(%esi)
  557         fistpq  56(%edi)
  558         fistpq  48(%edi)
  559         fistpq  40(%edi)
  560         fistpq  32(%edi)
  561         fistpq  24(%edi)
  562         fistpq  16(%edi)
  563         fistpq  8(%edi)
  564         fistpq  0(%edi)
  565         addl    $64,%esi
  566         addl    $64,%edi
  567         subl    $64,%ecx
  568         cmpl    $64,%ecx
  569         jae     large_i586_bcopy_loop
  570         popl    %eax
  571         addl    %eax,%ecx
  572         cmpl    $64,%ecx
  573         jae     4b
  574 
  575         cmpl    $0,_npxproc
  576         je      i586_bc2
  577         frstor  0(%esp)
  578         addl    $108,%esp
  579 i586_bc2:
  580         lmsw    %dx
  581         movb    $0xfe,kernel_fpu_lock
  582 
  583 /*
  584  * This is a duplicate of the main part of generic_bcopy.  See the comments
  585  * there.  Jumping into generic_bcopy would cost a whole 0-1 cycles and
  586  * would mess up high resolution profiling.
  587  */
  588         ALIGN_TEXT
  589 small_i586_bcopy:
  590         shrl    $2,%ecx
  591         cld
  592         rep
  593         movsl
  594         movl    20(%esp),%ecx
  595         andl    $3,%ecx
  596         rep
  597         movsb
  598         popl    %edi
  599         popl    %esi
  600         ret
  601 
  602         ALIGN_TEXT
  603 1:
  604         addl    %ecx,%edi
  605         addl    %ecx,%esi
  606         decl    %edi
  607         decl    %esi
  608         andl    $3,%ecx
  609         std
  610         rep
  611         movsb
  612         movl    20(%esp),%ecx
  613         shrl    $2,%ecx
  614         subl    $3,%esi
  615         subl    $3,%edi
  616         rep
  617         movsl
  618         popl    %edi
  619         popl    %esi
  620         cld
  621         ret
  622 #endif /* I586_CPU && NNPX > 0 */
  623 
  624 /*
  625  * Note: memcpy does not support overlapping copies
  626  */
  627 ENTRY(memcpy)
  628         pushl   %edi
  629         pushl   %esi
  630         movl    12(%esp),%edi
  631         movl    16(%esp),%esi
  632         movl    20(%esp),%ecx
  633         movl    %edi,%eax
  634         shrl    $2,%ecx                         /* copy by 32-bit words */
  635         cld                                     /* nope, copy forwards */
  636         rep
  637         movsl
  638         movl    20(%esp),%ecx
  639         andl    $3,%ecx                         /* any bytes left? */
  640         rep
  641         movsb
  642         popl    %esi
  643         popl    %edi
  644         ret
  645 
  646 
  647 /*****************************************************************************/
  648 /* copyout and fubyte family                                                 */
  649 /*****************************************************************************/
  650 /*
  651  * Access user memory from inside the kernel. These routines and possibly
  652  * the math- and DOS emulators should be the only places that do this.
  653  *
  654  * We have to access the memory with user's permissions, so use a segment
  655  * selector with RPL 3. For writes to user space we have to additionally
  656  * check the PTE for write permission, because the 386 does not check
  657  * write permissions when we are executing with EPL 0. The 486 does check
  658  * this if the WP bit is set in CR0, so we can use a simpler version here.
  659  *
  660  * These routines set curpcb->onfault for the time they execute. When a
  661  * protection violation occurs inside the functions, the trap handler
  662  * returns to *curpcb->onfault instead of the function.
  663  */
  664 
  665 /*
  666  * copyout(from_kernel, to_user, len)  - MP SAFE (if not I386_CPU)
  667  */
  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 /*
  853  * copyin(from_user, to_kernel, len) - MP SAFE
  854  */
  855 ENTRY(copyin)
  856         MEXITCOUNT
  857         jmp     *_copyin_vector
  858 
  859 ENTRY(generic_copyin)
  860         movl    _curpcb,%eax
  861         movl    $copyin_fault,PCB_ONFAULT(%eax)
  862         pushl   %esi
  863         pushl   %edi
  864         movl    12(%esp),%esi                   /* caddr_t from */
  865         movl    16(%esp),%edi                   /* caddr_t to */
  866         movl    20(%esp),%ecx                   /* size_t  len */
  867 
  868         /*
  869          * make sure address is valid
  870          */
  871         movl    %esi,%edx
  872         addl    %ecx,%edx
  873         jc      copyin_fault
  874         cmpl    $VM_MAXUSER_ADDRESS,%edx
  875         ja      copyin_fault
  876 
  877 #if defined(I586_CPU) && NNPX > 0
  878         ALIGN_TEXT
  879 slow_copyin:
  880 #endif
  881         movb    %cl,%al
  882         shrl    $2,%ecx                         /* copy longword-wise */
  883         cld
  884         rep
  885         movsl
  886         movb    %al,%cl
  887         andb    $3,%cl                          /* copy remaining bytes */
  888         rep
  889         movsb
  890 
  891 #if defined(I586_CPU) && NNPX > 0
  892         ALIGN_TEXT
  893 done_copyin:
  894 #endif
  895         popl    %edi
  896         popl    %esi
  897         xorl    %eax,%eax
  898         movl    _curpcb,%edx
  899         movl    %eax,PCB_ONFAULT(%edx)
  900         ret
  901 
  902         ALIGN_TEXT
  903 copyin_fault:
  904         popl    %edi
  905         popl    %esi
  906         movl    _curpcb,%edx
  907         movl    $0,PCB_ONFAULT(%edx)
  908         movl    $EFAULT,%eax
  909         ret
  910 
  911 #if defined(I586_CPU) && NNPX > 0
  912 ENTRY(i586_copyin)
  913         /*
  914          * Duplicated from generic_copyin.  Could be done a bit better.
  915          */
  916         movl    _curpcb,%eax
  917         movl    $copyin_fault,PCB_ONFAULT(%eax)
  918         pushl   %esi
  919         pushl   %edi
  920         movl    12(%esp),%esi                   /* caddr_t from */
  921         movl    16(%esp),%edi                   /* caddr_t to */
  922         movl    20(%esp),%ecx                   /* size_t  len */
  923 
  924         /*
  925          * make sure address is valid
  926          */
  927         movl    %esi,%edx
  928         addl    %ecx,%edx
  929         jc      copyin_fault
  930         cmpl    $VM_MAXUSER_ADDRESS,%edx
  931         ja      copyin_fault
  932         /*
  933          * End of duplicated code.
  934          */
  935 
  936         cmpl    $1024,%ecx
  937         jb      slow_copyin
  938 
  939         pushl   %ebx                    /* XXX prepare for fastmove_fault */
  940         pushl   %ecx
  941         call    _fastmove
  942         addl    $8,%esp
  943         jmp     done_copyin
  944 #endif /* I586_CPU && NNPX > 0 */
  945 
  946 #if defined(I586_CPU) && NNPX > 0
  947 /* fastmove(src, dst, len)
  948         src in %esi
  949         dst in %edi
  950         len in %ecx             XXX changed to on stack for profiling
  951         uses %eax and %edx for tmp. storage
  952  */
  953 /* XXX use ENTRY() to get profiling.  fastmove() is actually a non-entry. */
  954 ENTRY(fastmove)
  955         pushl   %ebp
  956         movl    %esp,%ebp
  957         subl    $PCB_SAVE87_SIZE+3*4,%esp
  958 
  959         movl    8(%ebp),%ecx
  960         cmpl    $63,%ecx
  961         jbe     fastmove_tail
  962 
  963         testl   $7,%esi /* check if src addr is multiple of 8 */
  964         jnz     fastmove_tail
  965 
  966         testl   $7,%edi /* check if dst addr is multiple of 8 */
  967         jnz     fastmove_tail
  968 
  969 /* if (npxproc != NULL) { */
  970         cmpl    $0,_npxproc
  971         je      6f
  972 /*    fnsave(&curpcb->pcb_savefpu); */
  973         movl    _curpcb,%eax
  974         fnsave  PCB_SAVEFPU(%eax)
  975 /*   npxproc = NULL; */
  976         movl    $0,_npxproc
  977 /* } */
  978 6:
  979 /* now we own the FPU. */
  980 
  981 /*
  982  * The process' FP state is saved in the pcb, but if we get
  983  * switched, the cpu_switch() will store our FP state in the
  984  * pcb.  It should be possible to avoid all the copying for
  985  * this, e.g., by setting a flag to tell cpu_switch() to
  986  * save the state somewhere else.
  987  */
  988 /* tmp = curpcb->pcb_savefpu; */
  989         movl    %ecx,-12(%ebp)
  990         movl    %esi,-8(%ebp)
  991         movl    %edi,-4(%ebp)
  992         movl    %esp,%edi
  993         movl    _curpcb,%esi
  994         addl    $PCB_SAVEFPU,%esi
  995         cld
  996         movl    $PCB_SAVE87_SIZE>>2,%ecx
  997         rep
  998         movsl
  999         movl    -12(%ebp),%ecx
 1000         movl    -8(%ebp),%esi
 1001         movl    -4(%ebp),%edi
 1002 /* stop_emulating(); */
 1003         clts
 1004 /* npxproc = curproc; */
 1005         movl    _curproc,%eax
 1006         movl    %eax,_npxproc
 1007         movl    _curpcb,%eax
 1008         movl    $fastmove_fault,PCB_ONFAULT(%eax)
 1009 4:
 1010         movl    %ecx,-12(%ebp)
 1011         cmpl    $1792,%ecx
 1012         jbe     2f
 1013         movl    $1792,%ecx
 1014 2:
 1015         subl    %ecx,-12(%ebp)
 1016         cmpl    $256,%ecx
 1017         jb      5f
 1018         movl    %ecx,-8(%ebp)
 1019         movl    %esi,-4(%ebp)
 1020         ALIGN_TEXT
 1021 3:
 1022         movl    0(%esi),%eax
 1023         movl    32(%esi),%eax
 1024         movl    64(%esi),%eax
 1025         movl    96(%esi),%eax
 1026         movl    128(%esi),%eax
 1027         movl    160(%esi),%eax
 1028         movl    192(%esi),%eax
 1029         movl    224(%esi),%eax
 1030         addl    $256,%esi
 1031         subl    $256,%ecx
 1032         cmpl    $256,%ecx
 1033         jae     3b
 1034         movl    -8(%ebp),%ecx
 1035         movl    -4(%ebp),%esi
 1036 5:
 1037         ALIGN_TEXT
 1038 fastmove_loop:
 1039         fildq   0(%esi)
 1040         fildq   8(%esi)
 1041         fildq   16(%esi)
 1042         fildq   24(%esi)
 1043         fildq   32(%esi)
 1044         fildq   40(%esi)
 1045         fildq   48(%esi)
 1046         fildq   56(%esi)
 1047         fistpq  56(%edi)
 1048         fistpq  48(%edi)
 1049         fistpq  40(%edi)
 1050         fistpq  32(%edi)
 1051         fistpq  24(%edi)
 1052         fistpq  16(%edi)
 1053         fistpq  8(%edi)
 1054         fistpq  0(%edi)
 1055         addl    $-64,%ecx
 1056         addl    $64,%esi
 1057         addl    $64,%edi
 1058         cmpl    $63,%ecx
 1059         ja      fastmove_loop
 1060         movl    -12(%ebp),%eax
 1061         addl    %eax,%ecx
 1062         cmpl    $64,%ecx
 1063         jae     4b
 1064 
 1065 /* curpcb->pcb_savefpu = tmp; */
 1066         movl    %ecx,-12(%ebp)
 1067         movl    %esi,-8(%ebp)
 1068         movl    %edi,-4(%ebp)
 1069         movl    _curpcb,%edi
 1070         addl    $PCB_SAVEFPU,%edi
 1071         movl    %esp,%esi
 1072         cld
 1073         movl    $PCB_SAVE87_SIZE>>2,%ecx
 1074         rep
 1075         movsl
 1076         movl    -12(%ebp),%ecx
 1077         movl    -8(%ebp),%esi
 1078         movl    -4(%ebp),%edi
 1079 
 1080 /* start_emulating(); */
 1081         smsw    %ax
 1082         orb     $CR0_TS,%al
 1083         lmsw    %ax
 1084 /* npxproc = NULL; */
 1085         movl    $0,_npxproc
 1086 
 1087         ALIGN_TEXT
 1088 fastmove_tail:
 1089         movl    _curpcb,%eax
 1090         movl    $fastmove_tail_fault,PCB_ONFAULT(%eax)
 1091 
 1092         movb    %cl,%al
 1093         shrl    $2,%ecx                         /* copy longword-wise */
 1094         cld
 1095         rep
 1096         movsl
 1097         movb    %al,%cl
 1098         andb    $3,%cl                          /* copy remaining bytes */
 1099         rep
 1100         movsb
 1101 
 1102         movl    %ebp,%esp
 1103         popl    %ebp
 1104         ret
 1105 
 1106         ALIGN_TEXT
 1107 fastmove_fault:
 1108         movl    _curpcb,%edi
 1109         addl    $PCB_SAVEFPU,%edi
 1110         movl    %esp,%esi
 1111         cld
 1112         movl    $PCB_SAVE87_SIZE>>2,%ecx
 1113         rep
 1114         movsl
 1115 
 1116         smsw    %ax
 1117         orb     $CR0_TS,%al
 1118         lmsw    %ax
 1119         movl    $0,_npxproc
 1120 
 1121 fastmove_tail_fault:
 1122         movl    %ebp,%esp
 1123         popl    %ebp
 1124         addl    $8,%esp
 1125         popl    %ebx
 1126         popl    %edi
 1127         popl    %esi
 1128         movl    _curpcb,%edx
 1129         movl    $0,PCB_ONFAULT(%edx)
 1130         movl    $EFAULT,%eax
 1131         ret
 1132 #endif /* I586_CPU && NNPX > 0 */
 1133 
 1134 /*
 1135  * fu{byte,sword,word} - MP SAFE
 1136  *
 1137  *      Fetch a byte (sword, word) from user memory
 1138  */
 1139 ENTRY(fuword)
 1140         movl    _curpcb,%ecx
 1141         movl    $fusufault,PCB_ONFAULT(%ecx)
 1142         movl    4(%esp),%edx                    /* from */
 1143 
 1144         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address is valid */
 1145         ja      fusufault
 1146 
 1147         movl    (%edx),%eax
 1148         movl    $0,PCB_ONFAULT(%ecx)
 1149         ret
 1150 
 1151 /*
 1152  * These two routines are called from the profiling code, potentially
 1153  * at interrupt time. If they fail, that's okay, good things will
 1154  * happen later. Fail all the time for now - until the trap code is
 1155  * able to deal with this.
 1156  */
 1157 ALTENTRY(suswintr)
 1158 ENTRY(fuswintr)
 1159         movl    $-1,%eax
 1160         ret
 1161 
 1162 /*
 1163  * fusword - MP SAFE
 1164  */
 1165 ENTRY(fusword)
 1166         movl    _curpcb,%ecx
 1167         movl    $fusufault,PCB_ONFAULT(%ecx)
 1168         movl    4(%esp),%edx
 1169 
 1170         cmpl    $VM_MAXUSER_ADDRESS-2,%edx
 1171         ja      fusufault
 1172 
 1173         movzwl  (%edx),%eax
 1174         movl    $0,PCB_ONFAULT(%ecx)
 1175         ret
 1176 
 1177 /*
 1178  * fubyte - MP SAFE
 1179  */
 1180 ENTRY(fubyte)
 1181         movl    _curpcb,%ecx
 1182         movl    $fusufault,PCB_ONFAULT(%ecx)
 1183         movl    4(%esp),%edx
 1184 
 1185         cmpl    $VM_MAXUSER_ADDRESS-1,%edx
 1186         ja      fusufault
 1187 
 1188         movzbl  (%edx),%eax
 1189         movl    $0,PCB_ONFAULT(%ecx)
 1190         ret
 1191 
 1192         ALIGN_TEXT
 1193 fusufault:
 1194         movl    _curpcb,%ecx
 1195         xorl    %eax,%eax
 1196         movl    %eax,PCB_ONFAULT(%ecx)
 1197         decl    %eax
 1198         ret
 1199 
 1200 /*
 1201  * su{byte,sword,word} - MP SAFE (if not I386_CPU)
 1202  *
 1203  *      Write a byte (word, longword) to user memory
 1204  */
 1205 ENTRY(suword)
 1206         movl    _curpcb,%ecx
 1207         movl    $fusufault,PCB_ONFAULT(%ecx)
 1208         movl    4(%esp),%edx
 1209 
 1210 #if defined(I386_CPU)
 1211 
 1212 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
 1213         cmpl    $CPUCLASS_386,_cpu_class
 1214         jne     2f                              /* we only have to set the right segment selector */
 1215 #endif /* I486_CPU || I586_CPU || I686_CPU */
 1216 
 1217         /* XXX - page boundary crossing is still not handled */
 1218         movl    %edx,%eax
 1219         shrl    $IDXSHIFT,%edx
 1220         andb    $0xfc,%dl
 1221 
 1222         leal    _PTmap(%edx),%ecx
 1223         shrl    $IDXSHIFT,%ecx
 1224         andb    $0xfc,%cl
 1225         testb   $PG_V,_PTmap(%ecx)              /* PTE page must be valid */
 1226         je      4f
 1227         movb    _PTmap(%edx),%dl
 1228         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
 1229         cmpb    $PG_V|PG_RW|PG_U,%dl
 1230         je      1f
 1231 
 1232 4:
 1233         /* simulate a trap */
 1234         pushl   %eax
 1235         call    _trapwrite
 1236         popl    %edx                            /* remove junk parameter from stack */
 1237         testl   %eax,%eax
 1238         jnz     fusufault
 1239 1:
 1240         movl    4(%esp),%edx
 1241 #endif
 1242 
 1243 2:
 1244         cmpl    $VM_MAXUSER_ADDRESS-4,%edx      /* verify address validity */
 1245         ja      fusufault
 1246 
 1247         movl    8(%esp),%eax
 1248         movl    %eax,(%edx)
 1249         xorl    %eax,%eax
 1250         movl    _curpcb,%ecx
 1251         movl    %eax,PCB_ONFAULT(%ecx)
 1252         ret
 1253 
 1254 /*
 1255  * susword - MP SAFE (if not I386_CPU)
 1256  */
 1257 ENTRY(susword)
 1258         movl    _curpcb,%ecx
 1259         movl    $fusufault,PCB_ONFAULT(%ecx)
 1260         movl    4(%esp),%edx
 1261 
 1262 #if defined(I386_CPU)
 1263 
 1264 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
 1265         cmpl    $CPUCLASS_386,_cpu_class
 1266         jne     2f
 1267 #endif /* I486_CPU || I586_CPU || I686_CPU */
 1268 
 1269         /* XXX - page boundary crossing is still not handled */
 1270         movl    %edx,%eax
 1271         shrl    $IDXSHIFT,%edx
 1272         andb    $0xfc,%dl
 1273 
 1274         leal    _PTmap(%edx),%ecx
 1275         shrl    $IDXSHIFT,%ecx
 1276         andb    $0xfc,%cl
 1277         testb   $PG_V,_PTmap(%ecx)              /* PTE page must be valid */
 1278         je      4f
 1279         movb    _PTmap(%edx),%dl
 1280         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
 1281         cmpb    $PG_V|PG_RW|PG_U,%dl
 1282         je      1f
 1283 
 1284 4:
 1285         /* simulate a trap */
 1286         pushl   %eax
 1287         call    _trapwrite
 1288         popl    %edx                            /* remove junk parameter from stack */
 1289         testl   %eax,%eax
 1290         jnz     fusufault
 1291 1:
 1292         movl    4(%esp),%edx
 1293 #endif
 1294 
 1295 2:
 1296         cmpl    $VM_MAXUSER_ADDRESS-2,%edx      /* verify address validity */
 1297         ja      fusufault
 1298 
 1299         movw    8(%esp),%ax
 1300         movw    %ax,(%edx)
 1301         xorl    %eax,%eax
 1302         movl    _curpcb,%ecx                    /* restore trashed register */
 1303         movl    %eax,PCB_ONFAULT(%ecx)
 1304         ret
 1305 
 1306 /*
 1307  * su[i]byte - MP SAFE (if not I386_CPU)
 1308  */
 1309 ALTENTRY(suibyte)
 1310 ENTRY(subyte)
 1311         movl    _curpcb,%ecx
 1312         movl    $fusufault,PCB_ONFAULT(%ecx)
 1313         movl    4(%esp),%edx
 1314 
 1315 #if defined(I386_CPU)
 1316 
 1317 #if defined(I486_CPU) || defined(I586_CPU) || defined(I686_CPU)
 1318         cmpl    $CPUCLASS_386,_cpu_class
 1319         jne     2f
 1320 #endif /* I486_CPU || I586_CPU || I686_CPU */
 1321 
 1322         movl    %edx,%eax
 1323         shrl    $IDXSHIFT,%edx
 1324         andb    $0xfc,%dl
 1325 
 1326         leal    _PTmap(%edx),%ecx
 1327         shrl    $IDXSHIFT,%ecx
 1328         andb    $0xfc,%cl
 1329         testb   $PG_V,_PTmap(%ecx)              /* PTE page must be valid */
 1330         je      4f
 1331         movb    _PTmap(%edx),%dl
 1332         andb    $PG_V|PG_RW|PG_U,%dl            /* page must be valid and user writable */
 1333         cmpb    $PG_V|PG_RW|PG_U,%dl
 1334         je      1f
 1335 
 1336 4:
 1337         /* simulate a trap */
 1338         pushl   %eax
 1339         call    _trapwrite
 1340         popl    %edx                            /* remove junk parameter from stack */
 1341         testl   %eax,%eax
 1342         jnz     fusufault
 1343 1:
 1344         movl    4(%esp),%edx
 1345 #endif
 1346 
 1347 2:
 1348         cmpl    $VM_MAXUSER_ADDRESS-1,%edx      /* verify address validity */
 1349         ja      fusufault
 1350 
 1351         movb    8(%esp),%al
 1352         movb    %al,(%edx)
 1353         xorl    %eax,%eax
 1354         movl    _curpcb,%ecx                    /* restore trashed register */
 1355         movl    %eax,PCB_ONFAULT(%ecx)
 1356         ret
 1357 
 1358 /*
 1359  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
 1360  *
 1361  *      copy a string from from to to, stop when a 0 character is reached.
 1362  *      return ENAMETOOLONG if string is longer than maxlen, and
 1363  *      EFAULT on protection violations. If lencopied is non-zero,
 1364  *      return the actual length in *lencopied.
 1365  */
 1366 ENTRY(copyinstr)
 1367         pushl   %esi
 1368         pushl   %edi
 1369         movl    _curpcb,%ecx
 1370         movl    $cpystrflt,PCB_ONFAULT(%ecx)
 1371 
 1372         movl    12(%esp),%esi                   /* %esi = from */
 1373         movl    16(%esp),%edi                   /* %edi = to */
 1374         movl    20(%esp),%edx                   /* %edx = maxlen */
 1375 
 1376         movl    $VM_MAXUSER_ADDRESS,%eax
 1377 
 1378         /* make sure 'from' is within bounds */
 1379         subl    %esi,%eax
 1380         jbe     cpystrflt
 1381 
 1382         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
 1383         cmpl    %edx,%eax
 1384         jae     1f
 1385         movl    %eax,%edx
 1386         movl    %eax,20(%esp)
 1387 1:
 1388         incl    %edx
 1389         cld
 1390 
 1391 2:
 1392         decl    %edx
 1393         jz      3f
 1394 
 1395         lodsb
 1396         stosb
 1397         orb     %al,%al
 1398         jnz     2b
 1399 
 1400         /* Success -- 0 byte reached */
 1401         decl    %edx
 1402         xorl    %eax,%eax
 1403         jmp     cpystrflt_x
 1404 3:
 1405         /* edx is zero - return ENAMETOOLONG or EFAULT */
 1406         cmpl    $VM_MAXUSER_ADDRESS,%esi
 1407         jae     cpystrflt
 1408 4:
 1409         movl    $ENAMETOOLONG,%eax
 1410         jmp     cpystrflt_x
 1411 
 1412 cpystrflt:
 1413         movl    $EFAULT,%eax
 1414 
 1415 cpystrflt_x:
 1416         /* set *lencopied and return %eax */
 1417         movl    _curpcb,%ecx
 1418         movl    $0,PCB_ONFAULT(%ecx)
 1419         movl    20(%esp),%ecx
 1420         subl    %edx,%ecx
 1421         movl    24(%esp),%edx
 1422         testl   %edx,%edx
 1423         jz      1f
 1424         movl    %ecx,(%edx)
 1425 1:
 1426         popl    %edi
 1427         popl    %esi
 1428         ret
 1429 
 1430 
 1431 /*
 1432  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
 1433  */
 1434 ENTRY(copystr)
 1435         pushl   %esi
 1436         pushl   %edi
 1437 
 1438         movl    12(%esp),%esi                   /* %esi = from */
 1439         movl    16(%esp),%edi                   /* %edi = to */
 1440         movl    20(%esp),%edx                   /* %edx = maxlen */
 1441         incl    %edx
 1442         cld
 1443 1:
 1444         decl    %edx
 1445         jz      4f
 1446         lodsb
 1447         stosb
 1448         orb     %al,%al
 1449         jnz     1b
 1450 
 1451         /* Success -- 0 byte reached */
 1452         decl    %edx
 1453         xorl    %eax,%eax
 1454         jmp     6f
 1455 4:
 1456         /* edx is zero -- return ENAMETOOLONG */
 1457         movl    $ENAMETOOLONG,%eax
 1458 
 1459 6:
 1460         /* set *lencopied and return %eax */
 1461         movl    20(%esp),%ecx
 1462         subl    %edx,%ecx
 1463         movl    24(%esp),%edx
 1464         testl   %edx,%edx
 1465         jz      7f
 1466         movl    %ecx,(%edx)
 1467 7:
 1468         popl    %edi
 1469         popl    %esi
 1470         ret
 1471 
 1472 ENTRY(bcmp)
 1473         pushl   %edi
 1474         pushl   %esi
 1475         movl    12(%esp),%edi
 1476         movl    16(%esp),%esi
 1477         movl    20(%esp),%edx
 1478         xorl    %eax,%eax
 1479 
 1480         movl    %edx,%ecx
 1481         shrl    $2,%ecx
 1482         cld                                     /* compare forwards */
 1483         repe
 1484         cmpsl
 1485         jne     1f
 1486 
 1487         movl    %edx,%ecx
 1488         andl    $3,%ecx
 1489         repe
 1490         cmpsb
 1491         je      2f
 1492 1:
 1493         incl    %eax
 1494 2:
 1495         popl    %esi
 1496         popl    %edi
 1497         ret
 1498 
 1499 
 1500 /*
 1501  * Handling of special 386 registers and descriptor tables etc
 1502  */
 1503 /* void lgdt(struct region_descriptor *rdp); */
 1504 ENTRY(lgdt)
 1505         /* reload the descriptor table */
 1506         movl    4(%esp),%eax
 1507         lgdt    (%eax)
 1508 
 1509         /* flush the prefetch q */
 1510         jmp     1f
 1511         nop
 1512 1:
 1513         /* reload "stale" selectors */
 1514         movl    $KDSEL,%eax
 1515         mov     %ax,%ds
 1516         mov     %ax,%es
 1517         mov     %ax,%gs
 1518         mov     %ax,%ss
 1519 #ifdef SMP
 1520         movl    $KPSEL,%eax
 1521 #endif
 1522         mov     %ax,%fs
 1523 
 1524         /* reload code selector by turning return into intersegmental return */
 1525         movl    (%esp),%eax
 1526         pushl   %eax
 1527         movl    $KCSEL,4(%esp)
 1528         lret
 1529 
 1530 /*
 1531  * void lidt(struct region_descriptor *rdp);
 1532  */
 1533 ENTRY(lidt)
 1534         movl    4(%esp),%eax
 1535         lidt    (%eax)
 1536         ret
 1537 
 1538 /*
 1539  * void lldt(u_short sel)
 1540  */
 1541 ENTRY(lldt)
 1542         lldt    4(%esp)
 1543         ret
 1544 
 1545 /*
 1546  * void ltr(u_short sel)
 1547  */
 1548 ENTRY(ltr)
 1549         ltr     4(%esp)
 1550         ret
 1551 
 1552 /* ssdtosd(*ssdp,*sdp) */
 1553 ENTRY(ssdtosd)
 1554         pushl   %ebx
 1555         movl    8(%esp),%ecx
 1556         movl    8(%ecx),%ebx
 1557         shll    $16,%ebx
 1558         movl    (%ecx),%edx
 1559         roll    $16,%edx
 1560         movb    %dh,%bl
 1561         movb    %dl,%bh
 1562         rorl    $8,%ebx
 1563         movl    4(%ecx),%eax
 1564         movw    %ax,%dx
 1565         andl    $0xf0000,%eax
 1566         orl     %eax,%ebx
 1567         movl    12(%esp),%ecx
 1568         movl    %edx,(%ecx)
 1569         movl    %ebx,4(%ecx)
 1570         popl    %ebx
 1571         ret
 1572 
 1573 /* load_cr0(cr0) */
 1574 ENTRY(load_cr0)
 1575         movl    4(%esp),%eax
 1576         movl    %eax,%cr0
 1577         ret
 1578 
 1579 /* rcr0() */
 1580 ENTRY(rcr0)
 1581         movl    %cr0,%eax
 1582         ret
 1583 
 1584 /* rcr3() */
 1585 ENTRY(rcr3)
 1586         movl    %cr3,%eax
 1587         ret
 1588 
 1589 /* void load_cr3(caddr_t cr3) */
 1590 ENTRY(load_cr3)
 1591 #if defined(SWTCH_OPTIM_STATS)
 1592         incl    _tlb_flush_count
 1593 #endif
 1594         movl    4(%esp),%eax
 1595         movl    %eax,%cr3
 1596         ret
 1597 
 1598 /* rcr4() */
 1599 ENTRY(rcr4)
 1600         movl    %cr4,%eax
 1601         ret
 1602 
 1603 /* void load_cr4(caddr_t cr4) */
 1604 ENTRY(load_cr4)
 1605         movl    4(%esp),%eax
 1606         movl    %eax,%cr4
 1607         ret
 1608 
 1609 /* void reset_dbregs() */
 1610 ENTRY(reset_dbregs)
 1611         movl    $0,%eax
 1612         movl    %eax,%dr7     /* disable all breapoints first */
 1613         movl    %eax,%dr0
 1614         movl    %eax,%dr1
 1615         movl    %eax,%dr2
 1616         movl    %eax,%dr3
 1617         movl    %eax,%dr6
 1618         ret
 1619 
 1620 /*****************************************************************************/
 1621 /* setjump, longjump                                                         */
 1622 /*****************************************************************************/
 1623 
 1624 ENTRY(setjmp)
 1625         movl    4(%esp),%eax
 1626         movl    %ebx,(%eax)                     /* save ebx */
 1627         movl    %esp,4(%eax)                    /* save esp */
 1628         movl    %ebp,8(%eax)                    /* save ebp */
 1629         movl    %esi,12(%eax)                   /* save esi */
 1630         movl    %edi,16(%eax)                   /* save edi */
 1631         movl    (%esp),%edx                     /* get rta */
 1632         movl    %edx,20(%eax)                   /* save eip */
 1633         xorl    %eax,%eax                       /* return(0); */
 1634         ret
 1635 
 1636 ENTRY(longjmp)
 1637         movl    4(%esp),%eax
 1638         movl    (%eax),%ebx                     /* restore ebx */
 1639         movl    4(%eax),%esp                    /* restore esp */
 1640         movl    8(%eax),%ebp                    /* restore ebp */
 1641         movl    12(%eax),%esi                   /* restore esi */
 1642         movl    16(%eax),%edi                   /* restore edi */
 1643         movl    20(%eax),%edx                   /* get rta */
 1644         movl    %edx,(%esp)                     /* put in return frame */
 1645         xorl    %eax,%eax                       /* return(1); */
 1646         incl    %eax
 1647         ret
 1648 
 1649 /*
 1650  * Support for BB-profiling (gcc -a).  The kernbb program will extract
 1651  * the data from the kernel.
 1652  */
 1653 
 1654         .data
 1655         ALIGN_DATA
 1656         .globl bbhead
 1657 bbhead:
 1658         .long 0
 1659 
 1660         .text
 1661 NON_GPROF_ENTRY(__bb_init_func)
 1662         movl    4(%esp),%eax
 1663         movl    $1,(%eax)
 1664         movl    bbhead,%edx
 1665         movl    %edx,16(%eax)
 1666         movl    %eax,bbhead
 1667         .byte   0xc3                            /* avoid macro for `ret' */

Cache object: 000e4b42805f7602f58d3dd13b23a493


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