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

Cache object: 668926f54bd4fb7d90efefaf70e772c7


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