The Design and Implementation of the FreeBSD Operating System, Second Edition
Now available: The Design and Implementation of the FreeBSD Operating System (Second Edition)


[ source navigation ] [ diff markup ] [ identifier search ] [ freetext search ] [ file search ] [ list types ] [ track identifier ]

FreeBSD/Linux Kernel Cross Reference
sys/i386/i386/support.s

Version: -  FREEBSD  -  FREEBSD-13-STABLE  -  FREEBSD-13-0  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  l41  -  OPENBSD  -  linux-2.6  -  MK84  -  PLAN9  -  xnu-8792 
SearchContext: -  none  -  3  -  10 

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

Cache object: 8333f9860e21e99e8d01234a383adc02


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