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

Cache object: 0effd8ce85865f14feec53458e021828


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