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

Cache object: 2b38fdf16ff45762482946d1161f1a77


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