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/amd64/amd64/support.S

Version: -  FREEBSD  -  FREEBSD-12-STABLE  -  FREEBSD-12-0  -  FREEBSD-11-STABLE  -  FREEBSD-11-2  -  FREEBSD-11-1  -  FREEBSD-11-0  -  FREEBSD-10-STABLE  -  FREEBSD-10-4  -  FREEBSD-10-3  -  FREEBSD-10-2  -  FREEBSD-10-1  -  FREEBSD-10-0  -  FREEBSD-9-STABLE  -  FREEBSD-9-3  -  FREEBSD-9-2  -  FREEBSD-9-1  -  FREEBSD-9-0  -  FREEBSD-8-STABLE  -  FREEBSD-8-4  -  FREEBSD-8-3  -  FREEBSD-8-2  -  FREEBSD-8-1  -  FREEBSD-8-0  -  FREEBSD-7-STABLE  -  FREEBSD-7-4  -  FREEBSD-7-3  -  FREEBSD-7-2  -  FREEBSD-7-1  -  FREEBSD-7-0  -  FREEBSD-6-STABLE  -  FREEBSD-6-4  -  FREEBSD-6-3  -  FREEBSD-6-2  -  FREEBSD-6-1  -  FREEBSD-6-0  -  FREEBSD-5-STABLE  -  FREEBSD-5-5  -  FREEBSD-5-4  -  FREEBSD-5-3  -  FREEBSD-5-2  -  FREEBSD-5-1  -  FREEBSD-5-0  -  FREEBSD-4-STABLE  -  FREEBSD-3-STABLE  -  FREEBSD22  -  linux-2.6  -  linux-2.4.22  -  MK83  -  MK84  -  PLAN9  -  DFBSD  -  NETBSD  -  NETBSD5  -  NETBSD4  -  NETBSD3  -  NETBSD20  -  OPENBSD  -  xnu-517  -  xnu-792  -  xnu-792.6.70  -  xnu-1228  -  xnu-1456.1.26  -  xnu-1699.24.8  -  xnu-2050.18.24  -  OPENSOLARIS  -  minix-3-1-1 
SearchContext: -  none  -  3  -  10 

    1 /*-
    2  * Copyright (c) 2003 Peter Wemm.
    3  * Copyright (c) 1993 The Regents of the University of California.
    4  * All rights reserved.
    5  *
    6  * Redistribution and use in source and binary forms, with or without
    7  * modification, are permitted provided that the following conditions
    8  * are met:
    9  * 1. Redistributions of source code must retain the above copyright
   10  *    notice, this list of conditions and the following disclaimer.
   11  * 2. Redistributions in binary form must reproduce the above copyright
   12  *    notice, this list of conditions and the following disclaimer in the
   13  *    documentation and/or other materials provided with the distribution.
   14  * 4. Neither the name of the University nor the names of its contributors
   15  *    may be used to endorse or promote products derived from this software
   16  *    without specific prior written permission.
   17  *
   18  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
   19  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   20  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   21  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
   22  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
   23  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
   24  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   25  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
   26  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
   27  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   28  * SUCH DAMAGE.
   29  *
   30  * $FreeBSD: releng/10.2/sys/amd64/amd64/support.S 274844 2014-11-22 09:38:18Z kib $
   31  */
   32 
   33 #include "opt_ddb.h"
   34 
   35 #include <machine/asmacros.h>
   36 #include <machine/intr_machdep.h>
   37 #include <machine/pmap.h>
   38 
   39 #include "assym.s"
   40 
   41         .text
   42 
   43 /*
   44  * bcopy family
   45  * void bzero(void *buf, u_int len)
   46  */
   47 
   48 /* done */
   49 ENTRY(bzero)
   50         PUSH_FRAME_POINTER
   51         movq    %rsi,%rcx
   52         xorl    %eax,%eax
   53         shrq    $3,%rcx
   54         cld
   55         rep
   56         stosq
   57         movq    %rsi,%rcx
   58         andq    $7,%rcx
   59         rep
   60         stosb
   61         POP_FRAME_POINTER
   62         ret
   63 END(bzero)
   64 
   65 /* Address: %rdi */
   66 ENTRY(pagezero)
   67         PUSH_FRAME_POINTER
   68         movq    $-PAGE_SIZE,%rdx
   69         subq    %rdx,%rdi
   70         xorl    %eax,%eax
   71 1:
   72         movnti  %rax,(%rdi,%rdx)
   73         movnti  %rax,8(%rdi,%rdx)
   74         movnti  %rax,16(%rdi,%rdx)
   75         movnti  %rax,24(%rdi,%rdx)
   76         addq    $32,%rdx
   77         jne     1b
   78         sfence
   79         POP_FRAME_POINTER
   80         ret
   81 END(pagezero)
   82 
   83 ENTRY(bcmp)
   84         PUSH_FRAME_POINTER
   85         movq    %rdx,%rcx
   86         shrq    $3,%rcx
   87         cld                                     /* compare forwards */
   88         repe
   89         cmpsq
   90         jne     1f
   91 
   92         movq    %rdx,%rcx
   93         andq    $7,%rcx
   94         repe
   95         cmpsb
   96 1:
   97         setne   %al
   98         movsbl  %al,%eax
   99         POP_FRAME_POINTER
  100         ret
  101 END(bcmp)
  102 
  103 /*
  104  * bcopy(src, dst, cnt)
  105  *       rdi, rsi, rdx
  106  *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
  107  */
  108 ENTRY(bcopy)
  109         PUSH_FRAME_POINTER
  110         xchgq   %rsi,%rdi
  111         movq    %rdx,%rcx
  112 
  113         movq    %rdi,%rax
  114         subq    %rsi,%rax
  115         cmpq    %rcx,%rax                       /* overlapping && src < dst? */
  116         jb      1f
  117 
  118         shrq    $3,%rcx                         /* copy by 64-bit words */
  119         cld                                     /* nope, copy forwards */
  120         rep
  121         movsq
  122         movq    %rdx,%rcx
  123         andq    $7,%rcx                         /* any bytes left? */
  124         rep
  125         movsb
  126         POP_FRAME_POINTER
  127         ret
  128 
  129         /* ALIGN_TEXT */
  130 1:
  131         addq    %rcx,%rdi                       /* copy backwards */
  132         addq    %rcx,%rsi
  133         decq    %rdi
  134         decq    %rsi
  135         andq    $7,%rcx                         /* any fractional bytes? */
  136         std
  137         rep
  138         movsb
  139         movq    %rdx,%rcx                       /* copy remainder by 32-bit words */
  140         shrq    $3,%rcx
  141         subq    $7,%rsi
  142         subq    $7,%rdi
  143         rep
  144         movsq
  145         cld
  146         POP_FRAME_POINTER
  147         ret
  148 END(bcopy)
  149 
  150 /*
  151  * Note: memcpy does not support overlapping copies
  152  */
  153 ENTRY(memcpy)
  154         PUSH_FRAME_POINTER
  155         movq    %rdx,%rcx
  156         shrq    $3,%rcx                         /* copy by 64-bit words */
  157         cld                                     /* copy forwards */
  158         rep
  159         movsq
  160         movq    %rdx,%rcx
  161         andq    $7,%rcx                         /* any bytes left? */
  162         rep
  163         movsb
  164         POP_FRAME_POINTER
  165         ret
  166 END(memcpy)
  167 
  168 /*
  169  * pagecopy(%rdi=from, %rsi=to)
  170  */
  171 ENTRY(pagecopy)
  172         PUSH_FRAME_POINTER
  173         movq    $-PAGE_SIZE,%rax
  174         movq    %rax,%rdx
  175         subq    %rax,%rdi
  176         subq    %rax,%rsi
  177 1:
  178         prefetchnta (%rdi,%rax)
  179         addq    $64,%rax
  180         jne     1b
  181 2:
  182         movq    (%rdi,%rdx),%rax
  183         movnti  %rax,(%rsi,%rdx)
  184         movq    8(%rdi,%rdx),%rax
  185         movnti  %rax,8(%rsi,%rdx)
  186         movq    16(%rdi,%rdx),%rax
  187         movnti  %rax,16(%rsi,%rdx)
  188         movq    24(%rdi,%rdx),%rax
  189         movnti  %rax,24(%rsi,%rdx)
  190         addq    $32,%rdx
  191         jne     2b
  192         sfence
  193         POP_FRAME_POINTER
  194         ret
  195 END(pagecopy)
  196 
  197 /* fillw(pat, base, cnt) */
  198 /*       %rdi,%rsi, %rdx */
  199 ENTRY(fillw)
  200         PUSH_FRAME_POINTER
  201         movq    %rdi,%rax
  202         movq    %rsi,%rdi
  203         movq    %rdx,%rcx
  204         cld
  205         rep
  206         stosw
  207         POP_FRAME_POINTER
  208         ret
  209 END(fillw)
  210 
  211 /*****************************************************************************/
  212 /* copyout and fubyte family                                                 */
  213 /*****************************************************************************/
  214 /*
  215  * Access user memory from inside the kernel. These routines should be
  216  * the only places that do this.
  217  *
  218  * These routines set curpcb->pcb_onfault for the time they execute. When a
  219  * protection violation occurs inside the functions, the trap handler
  220  * returns to *curpcb->pcb_onfault instead of the function.
  221  */
  222 
  223 /*
  224  * copyout(from_kernel, to_user, len)  - MP SAFE
  225  *         %rdi,        %rsi,    %rdx
  226  */
  227 ENTRY(copyout)
  228         PUSH_FRAME_POINTER
  229         movq    PCPU(CURPCB),%rax
  230         movq    $copyout_fault,PCB_ONFAULT(%rax)
  231         testq   %rdx,%rdx                       /* anything to do? */
  232         jz      done_copyout
  233 
  234         /*
  235          * Check explicitly for non-user addresses.  If 486 write protection
  236          * is being used, this check is essential because we are in kernel
  237          * mode so the h/w does not provide any protection against writing
  238          * kernel addresses.
  239          */
  240 
  241         /*
  242          * First, prevent address wrapping.
  243          */
  244         movq    %rsi,%rax
  245         addq    %rdx,%rax
  246         jc      copyout_fault
  247 /*
  248  * XXX STOP USING VM_MAXUSER_ADDRESS.
  249  * It is an end address, not a max, so every time it is used correctly it
  250  * looks like there is an off by one error, and of course it caused an off
  251  * by one error in several places.
  252  */
  253         movq    $VM_MAXUSER_ADDRESS,%rcx
  254         cmpq    %rcx,%rax
  255         ja      copyout_fault
  256 
  257         xchgq   %rdi,%rsi
  258         /* bcopy(%rsi, %rdi, %rdx) */
  259         movq    %rdx,%rcx
  260 
  261         shrq    $3,%rcx
  262         cld
  263         rep
  264         movsq
  265         movb    %dl,%cl
  266         andb    $7,%cl
  267         rep
  268         movsb
  269 
  270 done_copyout:
  271         xorl    %eax,%eax
  272         movq    PCPU(CURPCB),%rdx
  273         movq    %rax,PCB_ONFAULT(%rdx)
  274         POP_FRAME_POINTER
  275         ret
  276 
  277         ALIGN_TEXT
  278 copyout_fault:
  279         movq    PCPU(CURPCB),%rdx
  280         movq    $0,PCB_ONFAULT(%rdx)
  281         movq    $EFAULT,%rax
  282         POP_FRAME_POINTER
  283         ret
  284 END(copyout)
  285 
  286 /*
  287  * copyin(from_user, to_kernel, len) - MP SAFE
  288  *        %rdi,      %rsi,      %rdx
  289  */
  290 ENTRY(copyin)
  291         PUSH_FRAME_POINTER
  292         movq    PCPU(CURPCB),%rax
  293         movq    $copyin_fault,PCB_ONFAULT(%rax)
  294         testq   %rdx,%rdx                       /* anything to do? */
  295         jz      done_copyin
  296 
  297         /*
  298          * make sure address is valid
  299          */
  300         movq    %rdi,%rax
  301         addq    %rdx,%rax
  302         jc      copyin_fault
  303         movq    $VM_MAXUSER_ADDRESS,%rcx
  304         cmpq    %rcx,%rax
  305         ja      copyin_fault
  306 
  307         xchgq   %rdi,%rsi
  308         movq    %rdx,%rcx
  309         movb    %cl,%al
  310         shrq    $3,%rcx                         /* copy longword-wise */
  311         cld
  312         rep
  313         movsq
  314         movb    %al,%cl
  315         andb    $7,%cl                          /* copy remaining bytes */
  316         rep
  317         movsb
  318 
  319 done_copyin:
  320         xorl    %eax,%eax
  321         movq    PCPU(CURPCB),%rdx
  322         movq    %rax,PCB_ONFAULT(%rdx)
  323         POP_FRAME_POINTER
  324         ret
  325 
  326         ALIGN_TEXT
  327 copyin_fault:
  328         movq    PCPU(CURPCB),%rdx
  329         movq    $0,PCB_ONFAULT(%rdx)
  330         movq    $EFAULT,%rax
  331         POP_FRAME_POINTER
  332         ret
  333 END(copyin)
  334 
  335 /*
  336  * casueword32.  Compare and set user integer.  Returns -1 on fault,
  337  *        0 if access was successful.  Old value is written to *oldp.
  338  *        dst = %rdi, old = %esi, oldp = %rdx, new = %ecx
  339  */
  340 ENTRY(casueword32)
  341         PUSH_FRAME_POINTER
  342         movq    PCPU(CURPCB),%r8
  343         movq    $fusufault,PCB_ONFAULT(%r8)
  344 
  345         movq    $VM_MAXUSER_ADDRESS-4,%rax
  346         cmpq    %rax,%rdi                       /* verify address is valid */
  347         ja      fusufault
  348 
  349         movl    %esi,%eax                       /* old */
  350 #ifdef SMP
  351         lock
  352 #endif
  353         cmpxchgl %ecx,(%rdi)                    /* new = %ecx */
  354 
  355         /*
  356          * The old value is in %eax.  If the store succeeded it will be the
  357          * value we expected (old) from before the store, otherwise it will
  358          * be the current value.  Save %eax into %esi to prepare the return
  359          * value.
  360          */
  361         movl    %eax,%esi
  362         xorl    %eax,%eax
  363         movq    %rax,PCB_ONFAULT(%r8)
  364 
  365         /*
  366          * Access the oldp after the pcb_onfault is cleared, to correctly
  367          * catch corrupted pointer.
  368          */
  369         movl    %esi,(%rdx)                     /* oldp = %rdx */
  370         POP_FRAME_POINTER
  371         ret
  372 END(casueword32)
  373 
  374 /*
  375  * casueword.  Compare and set user long.  Returns -1 on fault,
  376  *        0 if access was successful.  Old value is written to *oldp.
  377  *        dst = %rdi, old = %rsi, oldp = %rdx, new = %rcx
  378  */
  379 ENTRY(casueword)
  380         PUSH_FRAME_POINTER
  381         movq    PCPU(CURPCB),%r8
  382         movq    $fusufault,PCB_ONFAULT(%r8)
  383 
  384         movq    $VM_MAXUSER_ADDRESS-4,%rax
  385         cmpq    %rax,%rdi                       /* verify address is valid */
  386         ja      fusufault
  387 
  388         movq    %rsi,%rax                       /* old */
  389 #ifdef SMP
  390         lock
  391 #endif
  392         cmpxchgq %rcx,(%rdi)                    /* new = %rcx */
  393 
  394         /*
  395          * The old value is in %rax.  If the store succeeded it will be the
  396          * value we expected (old) from before the store, otherwise it will
  397          * be the current value.
  398          */
  399         movq    %rax,%rsi
  400         xorl    %eax,%eax
  401         movq    %rax,PCB_ONFAULT(%r8)
  402         movq    %rsi,(%rdx)
  403         POP_FRAME_POINTER
  404         ret
  405 END(casueword)
  406 
  407 /*
  408  * Fetch (load) a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit
  409  * byte from user memory.
  410  * addr = %rdi, valp = %rsi
  411  */
  412 
  413 ALTENTRY(fueword64)
  414 ENTRY(fueword)
  415         PUSH_FRAME_POINTER
  416         movq    PCPU(CURPCB),%rcx
  417         movq    $fusufault,PCB_ONFAULT(%rcx)
  418 
  419         movq    $VM_MAXUSER_ADDRESS-8,%rax
  420         cmpq    %rax,%rdi                       /* verify address is valid */
  421         ja      fusufault
  422 
  423         xorl    %eax,%eax
  424         movq    (%rdi),%r11
  425         movq    %rax,PCB_ONFAULT(%rcx)
  426         movq    %r11,(%rsi)
  427         POP_FRAME_POINTER
  428         ret
  429 END(fueword64)
  430 END(fueword)
  431 
  432 ENTRY(fueword32)
  433         PUSH_FRAME_POINTER
  434         movq    PCPU(CURPCB),%rcx
  435         movq    $fusufault,PCB_ONFAULT(%rcx)
  436 
  437         movq    $VM_MAXUSER_ADDRESS-4,%rax
  438         cmpq    %rax,%rdi                       /* verify address is valid */
  439         ja      fusufault
  440 
  441         xorl    %eax,%eax
  442         movl    (%rdi),%r11d
  443         movq    %rax,PCB_ONFAULT(%rcx)
  444         movl    %r11d,(%rsi)
  445         POP_FRAME_POINTER
  446         ret
  447 END(fueword32)
  448 
  449 /*
  450  * fuswintr() and suswintr() are specialized variants of fuword16() and
  451  * suword16(), respectively.  They are called from the profiling code,
  452  * potentially at interrupt time.  If they fail, that's okay; good things
  453  * will happen later.  They always fail for now, until the trap code is
  454  * able to deal with this.
  455  */
  456 ALTENTRY(suswintr)
  457 ENTRY(fuswintr)
  458         movq    $-1,%rax
  459         ret
  460 END(suswintr)
  461 END(fuswintr)
  462 
  463 ENTRY(fuword16)
  464         PUSH_FRAME_POINTER
  465         movq    PCPU(CURPCB),%rcx
  466         movq    $fusufault,PCB_ONFAULT(%rcx)
  467 
  468         movq    $VM_MAXUSER_ADDRESS-2,%rax
  469         cmpq    %rax,%rdi
  470         ja      fusufault
  471 
  472         movzwl  (%rdi),%eax
  473         movq    $0,PCB_ONFAULT(%rcx)
  474         POP_FRAME_POINTER
  475         ret
  476 END(fuword16)
  477 
  478 ENTRY(fubyte)
  479         PUSH_FRAME_POINTER
  480         movq    PCPU(CURPCB),%rcx
  481         movq    $fusufault,PCB_ONFAULT(%rcx)
  482 
  483         movq    $VM_MAXUSER_ADDRESS-1,%rax
  484         cmpq    %rax,%rdi
  485         ja      fusufault
  486 
  487         movzbl  (%rdi),%eax
  488         movq    $0,PCB_ONFAULT(%rcx)
  489         POP_FRAME_POINTER
  490         ret
  491 END(fubyte)
  492 
  493         ALIGN_TEXT
  494 fusufault:
  495         movq    PCPU(CURPCB),%rcx
  496         xorl    %eax,%eax
  497         movq    %rax,PCB_ONFAULT(%rcx)
  498         decq    %rax
  499         POP_FRAME_POINTER
  500         ret
  501 
  502 /*
  503  * Store a 64-bit word, a 32-bit word, a 16-bit word, or an 8-bit byte to
  504  * user memory.  All these functions are MPSAFE.
  505  * addr = %rdi, value = %rsi
  506  */
  507 ALTENTRY(suword64)
  508 ENTRY(suword)
  509         PUSH_FRAME_POINTER
  510         movq    PCPU(CURPCB),%rcx
  511         movq    $fusufault,PCB_ONFAULT(%rcx)
  512 
  513         movq    $VM_MAXUSER_ADDRESS-8,%rax
  514         cmpq    %rax,%rdi                       /* verify address validity */
  515         ja      fusufault
  516 
  517         movq    %rsi,(%rdi)
  518         xorl    %eax,%eax
  519         movq    PCPU(CURPCB),%rcx
  520         movq    %rax,PCB_ONFAULT(%rcx)
  521         POP_FRAME_POINTER
  522         ret
  523 END(suword64)
  524 END(suword)
  525 
  526 ENTRY(suword32)
  527         PUSH_FRAME_POINTER
  528         movq    PCPU(CURPCB),%rcx
  529         movq    $fusufault,PCB_ONFAULT(%rcx)
  530 
  531         movq    $VM_MAXUSER_ADDRESS-4,%rax
  532         cmpq    %rax,%rdi                       /* verify address validity */
  533         ja      fusufault
  534 
  535         movl    %esi,(%rdi)
  536         xorl    %eax,%eax
  537         movq    PCPU(CURPCB),%rcx
  538         movq    %rax,PCB_ONFAULT(%rcx)
  539         POP_FRAME_POINTER
  540         ret
  541 END(suword32)
  542 
  543 ENTRY(suword16)
  544         PUSH_FRAME_POINTER
  545         movq    PCPU(CURPCB),%rcx
  546         movq    $fusufault,PCB_ONFAULT(%rcx)
  547 
  548         movq    $VM_MAXUSER_ADDRESS-2,%rax
  549         cmpq    %rax,%rdi                       /* verify address validity */
  550         ja      fusufault
  551 
  552         movw    %si,(%rdi)
  553         xorl    %eax,%eax
  554         movq    PCPU(CURPCB),%rcx               /* restore trashed register */
  555         movq    %rax,PCB_ONFAULT(%rcx)
  556         POP_FRAME_POINTER
  557         ret
  558 END(suword16)
  559 
  560 ENTRY(subyte)
  561         PUSH_FRAME_POINTER
  562         movq    PCPU(CURPCB),%rcx
  563         movq    $fusufault,PCB_ONFAULT(%rcx)
  564 
  565         movq    $VM_MAXUSER_ADDRESS-1,%rax
  566         cmpq    %rax,%rdi                       /* verify address validity */
  567         ja      fusufault
  568 
  569         movl    %esi,%eax
  570         movb    %al,(%rdi)
  571         xorl    %eax,%eax
  572         movq    PCPU(CURPCB),%rcx               /* restore trashed register */
  573         movq    %rax,PCB_ONFAULT(%rcx)
  574         POP_FRAME_POINTER
  575         ret
  576 END(subyte)
  577 
  578 /*
  579  * copyinstr(from, to, maxlen, int *lencopied) - MP SAFE
  580  *           %rdi, %rsi, %rdx, %rcx
  581  *
  582  *      copy a string from from to to, stop when a 0 character is reached.
  583  *      return ENAMETOOLONG if string is longer than maxlen, and
  584  *      EFAULT on protection violations. If lencopied is non-zero,
  585  *      return the actual length in *lencopied.
  586  */
  587 ENTRY(copyinstr)
  588         PUSH_FRAME_POINTER
  589         movq    %rdx,%r8                        /* %r8 = maxlen */
  590         movq    %rcx,%r9                        /* %r9 = *len */
  591         xchgq   %rdi,%rsi                       /* %rdi = from, %rsi = to */
  592         movq    PCPU(CURPCB),%rcx
  593         movq    $cpystrflt,PCB_ONFAULT(%rcx)
  594 
  595         movq    $VM_MAXUSER_ADDRESS,%rax
  596 
  597         /* make sure 'from' is within bounds */
  598         subq    %rsi,%rax
  599         jbe     cpystrflt
  600 
  601         /* restrict maxlen to <= VM_MAXUSER_ADDRESS-from */
  602         cmpq    %rdx,%rax
  603         jae     1f
  604         movq    %rax,%rdx
  605         movq    %rax,%r8
  606 1:
  607         incq    %rdx
  608         cld
  609 
  610 2:
  611         decq    %rdx
  612         jz      3f
  613 
  614         lodsb
  615         stosb
  616         orb     %al,%al
  617         jnz     2b
  618 
  619         /* Success -- 0 byte reached */
  620         decq    %rdx
  621         xorl    %eax,%eax
  622         jmp     cpystrflt_x
  623 3:
  624         /* rdx is zero - return ENAMETOOLONG or EFAULT */
  625         movq    $VM_MAXUSER_ADDRESS,%rax
  626         cmpq    %rax,%rsi
  627         jae     cpystrflt
  628 4:
  629         movq    $ENAMETOOLONG,%rax
  630         jmp     cpystrflt_x
  631 
  632 cpystrflt:
  633         movq    $EFAULT,%rax
  634 
  635 cpystrflt_x:
  636         /* set *lencopied and return %eax */
  637         movq    PCPU(CURPCB),%rcx
  638         movq    $0,PCB_ONFAULT(%rcx)
  639 
  640         testq   %r9,%r9
  641         jz      1f
  642         subq    %rdx,%r8
  643         movq    %r8,(%r9)
  644 1:
  645         POP_FRAME_POINTER
  646         ret
  647 END(copyinstr)
  648 
  649 /*
  650  * copystr(from, to, maxlen, int *lencopied) - MP SAFE
  651  *         %rdi, %rsi, %rdx, %rcx
  652  */
  653 ENTRY(copystr)
  654         PUSH_FRAME_POINTER
  655         movq    %rdx,%r8                        /* %r8 = maxlen */
  656 
  657         xchgq   %rdi,%rsi
  658         incq    %rdx
  659         cld
  660 1:
  661         decq    %rdx
  662         jz      4f
  663         lodsb
  664         stosb
  665         orb     %al,%al
  666         jnz     1b
  667 
  668         /* Success -- 0 byte reached */
  669         decq    %rdx
  670         xorl    %eax,%eax
  671         jmp     6f
  672 4:
  673         /* rdx is zero -- return ENAMETOOLONG */
  674         movq    $ENAMETOOLONG,%rax
  675 
  676 6:
  677 
  678         testq   %rcx,%rcx
  679         jz      7f
  680         /* set *lencopied and return %rax */
  681         subq    %rdx,%r8
  682         movq    %r8,(%rcx)
  683 7:
  684         POP_FRAME_POINTER
  685         ret
  686 END(copystr)
  687 
  688 /*
  689  * Handling of special amd64 registers and descriptor tables etc
  690  * %rdi
  691  */
  692 /* void lgdt(struct region_descriptor *rdp); */
  693 ENTRY(lgdt)
  694         /* reload the descriptor table */
  695         lgdt    (%rdi)
  696 
  697         /* flush the prefetch q */
  698         jmp     1f
  699         nop
  700 1:
  701         movl    $KDSEL,%eax
  702         movl    %eax,%ds
  703         movl    %eax,%es
  704         movl    %eax,%fs        /* Beware, use wrmsr to set 64 bit base */
  705         movl    %eax,%gs
  706         movl    %eax,%ss
  707 
  708         /* reload code selector by turning return into intersegmental return */
  709         popq    %rax
  710         pushq   $KCSEL
  711         pushq   %rax
  712         MEXITCOUNT
  713         lretq
  714 END(lgdt)
  715 
  716 /*****************************************************************************/
  717 /* setjump, longjump                                                         */
  718 /*****************************************************************************/
  719 
  720 ENTRY(setjmp)
  721         movq    %rbx,0(%rdi)                    /* save rbx */
  722         movq    %rsp,8(%rdi)                    /* save rsp */
  723         movq    %rbp,16(%rdi)                   /* save rbp */
  724         movq    %r12,24(%rdi)                   /* save r12 */
  725         movq    %r13,32(%rdi)                   /* save r13 */
  726         movq    %r14,40(%rdi)                   /* save r14 */
  727         movq    %r15,48(%rdi)                   /* save r15 */
  728         movq    0(%rsp),%rdx                    /* get rta */
  729         movq    %rdx,56(%rdi)                   /* save rip */
  730         xorl    %eax,%eax                       /* return(0); */
  731         ret
  732 END(setjmp)
  733 
  734 ENTRY(longjmp)
  735         movq    0(%rdi),%rbx                    /* restore rbx */
  736         movq    8(%rdi),%rsp                    /* restore rsp */
  737         movq    16(%rdi),%rbp                   /* restore rbp */
  738         movq    24(%rdi),%r12                   /* restore r12 */
  739         movq    32(%rdi),%r13                   /* restore r13 */
  740         movq    40(%rdi),%r14                   /* restore r14 */
  741         movq    48(%rdi),%r15                   /* restore r15 */
  742         movq    56(%rdi),%rdx                   /* get rta */
  743         movq    %rdx,0(%rsp)                    /* put in return frame */
  744         xorl    %eax,%eax                       /* return(1); */
  745         incl    %eax
  746         ret
  747 END(longjmp)
  748 
  749 /*
  750  * Support for reading MSRs in the safe manner.
  751  */
  752 ENTRY(rdmsr_safe)
  753 /* int rdmsr_safe(u_int msr, uint64_t *data) */
  754         PUSH_FRAME_POINTER
  755         movq    PCPU(CURPCB),%r8
  756         movq    $msr_onfault,PCB_ONFAULT(%r8)
  757         movl    %edi,%ecx
  758         rdmsr                   /* Read MSR pointed by %ecx. Returns
  759                                    hi byte in edx, lo in %eax */
  760         salq    $32,%rdx        /* sign-shift %rdx left */
  761         movl    %eax,%eax       /* zero-extend %eax -> %rax */
  762         orq     %rdx,%rax
  763         movq    %rax,(%rsi)
  764         xorq    %rax,%rax
  765         movq    %rax,PCB_ONFAULT(%r8)
  766         POP_FRAME_POINTER
  767         ret
  768 
  769 /*
  770  * Support for writing MSRs in the safe manner.
  771  */
  772 ENTRY(wrmsr_safe)
  773 /* int wrmsr_safe(u_int msr, uint64_t data) */
  774         PUSH_FRAME_POINTER
  775         movq    PCPU(CURPCB),%r8
  776         movq    $msr_onfault,PCB_ONFAULT(%r8)
  777         movl    %edi,%ecx
  778         movl    %esi,%eax
  779         sarq    $32,%rsi
  780         movl    %esi,%edx
  781         wrmsr                   /* Write MSR pointed by %ecx. Accepts
  782                                    hi byte in edx, lo in %eax. */
  783         xorq    %rax,%rax
  784         movq    %rax,PCB_ONFAULT(%r8)
  785         POP_FRAME_POINTER
  786         ret
  787 
  788 /*
  789  * MSR operations fault handler
  790  */
  791         ALIGN_TEXT
  792 msr_onfault:
  793         movq    $0,PCB_ONFAULT(%r8)
  794         movl    $EFAULT,%eax
  795         POP_FRAME_POINTER
  796         ret

Cache object: b6db62649b7f79857f6d0e6539759633


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