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/compat/ndis/winx64_wrap.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) 2005
    3  *      Bill Paul <wpaul@windriver.com>.  All rights reserved.
    4  *
    5  * Redistribution and use in source and binary forms, with or without
    6  * modification, are permitted provided that the following conditions
    7  * are met:
    8  * 1. Redistributions of source code must retain the above copyright
    9  *    notice, this list of conditions and the following disclaimer.
   10  * 2. Redistributions in binary form must reproduce the above copyright
   11  *    notice, this list of conditions and the following disclaimer in the
   12  *    documentation and/or other materials provided with the distribution.
   13  * 3. All advertising materials mentioning features or use of this software
   14  *    must display the following acknowledgement:
   15  *      This product includes software developed by Bill Paul.
   16  * 4. Neither the name of the author nor the names of any co-contributors
   17  *    may be used to endorse or promote products derived from this software
   18  *    without specific prior written permission.
   19  *
   20  * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND
   21  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   22  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
   23  * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR THE VOICES IN HIS HEAD
   24  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
   25  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
   26  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
   27  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
   28  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   29  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
   30  * THE POSSIBILITY OF SUCH DAMAGE.
   31  *
   32  * The x86_64 callback routines were written and graciously submitted
   33  * by Ville-Pertti Keinonen <will@exomi.com>.
   34  *
   35  * $FreeBSD$
   36  */
   37 
   38 #include <machine/asmacros.h>
   39 
   40 /*
   41  * Wrapper for handling up to 16 arguments. We can't really
   42  * know how many arguments the caller will pass us. I'm taking an
   43  * educated guess that we'll never get over 16. Handling too
   44  * few arguments is bad. Handling too many is inefficient, but
   45  * not fatal. If someone can think of a way to handle an arbitrary
   46  * number of arguments with more elegant code, freel free to let
   47  * me know.
   48  *
   49  * Standard amd64 calling conventions specify the following registers
   50  * to be used for passing the first 6 arguments:
   51  *
   52  *   %rdi, %rsi, %rdx, %rcx, %r8, %r9
   53  *
   54  * Further arguments are passed on the stack (the 7th argument is
   55  * located immediately after the return address).
   56  *
   57  * Windows x86_64 calling conventions only pass the first 4
   58  * arguments in registers:
   59  *
   60  *   %rcx, %rdx, %r8, %r9
   61  *
   62  * Even when arguments are passed in registers, the stack must have
   63  * space reserved for those arguments.  Thus the 5th argument (the
   64  * first non-register argument) is placed 32 bytes after the return
   65  * address.  Additionally, %rdi and %rsi must be preserved. (These
   66  * two registers are not scratch registers in the standard convention.)
   67  *
   68  * Note that in this template, we load a contrived 64 bit address into
   69  * %r11 to represent our jump address. This is to guarantee that the
   70  * assembler leaves enough room to patch in an absolute 64-bit address
   71  * later. The idea behind this code is that we want to avoid having to
   72  * manually create all the wrapper functions at compile time with
   73  * a bunch of macros. This is doable, but a) messy and b) requires
   74  * us to maintain two separate tables (one for the UNIX function
   75  * pointers and another with the wrappers). This means I'd have to
   76  * update two different tables each time I added a function.
   77  *
   78  * To avoid this, we create the wrappers at runtime instead. The
   79  * image patch tables now contain two pointers: one two the normal
   80  * routine, and a blank one for the wrapper. To construct a wrapper,
   81  * we allocate some memory and copy the template function into it,
   82  * then patch the function pointer for the routine we want to wrap
   83  * into the newly created wrapper. The subr_pe module can then
   84  * simply patch the wrapper routine into the jump table into the
   85  * windows image. As a bonus, the wrapper pointer not only serves
   86  * as the wrapper entry point address, it's also a data pointer
   87  * that we can pass to free() later when we unload the module.
   88  */
   89 
   90         .globl x86_64_wrap_call
   91         .globl x86_64_wrap_end
   92 
   93 ENTRY(x86_64_wrap)
   94         push    %rbp            # insure that the stack
   95         mov     %rsp,%rbp       # is 16-byte aligned
   96         and     $-16,%rsp       #
   97         subq    $96,%rsp        # allocate space on stack
   98         mov     %rsi,96-8(%rsp) # save %rsi
   99         mov     %rdi,96-16(%rsp)# save %rdi
  100         mov     %rcx,%r10       # temporarily save %rcx in scratch
  101         lea     56+8(%rbp),%rsi # source == old stack top (stack+56)
  102         mov     %rsp,%rdi       # destination == new stack top
  103         mov     $10,%rcx        # count == 10 quadwords
  104         rep
  105         movsq                   # copy old stack contents to new location
  106         mov     %r10,%rdi       # set up arg0 (%rcx -> %rdi)
  107         mov     %rdx,%rsi       # set up arg1 (%rdx -> %rsi)
  108         mov     %r8,%rdx        # set up arg2 (%r8 -> %rdx)
  109         mov     %r9,%rcx        # set up arg3 (%r9 -> %rcx)
  110         mov     40+8(%rbp),%r8  # set up arg4 (stack+40 -> %r8)
  111         mov     48+8(%rbp),%r9  # set up arg5 (stack+48 -> %r9)
  112         xor     %rax,%rax       # clear return value
  113 x86_64_wrap_call:
  114         mov     $0xFF00FF00FF00FF00,%r11
  115         callq   *%r11           # call routine
  116         mov     96-16(%rsp),%rdi# restore %rdi
  117         mov     96-8(%rsp),%rsi # restore %rsi
  118         leave                   # delete space on stack
  119         ret
  120 x86_64_wrap_end:
  121 
  122 /*
  123  * Functions for invoking x86_64 callbacks.  In each case, the first
  124  * argument is a pointer to the function.
  125  */
  126 
  127 ENTRY(x86_64_call1)
  128         subq    $40,%rsp
  129         mov     %rsi,%rcx
  130         call    *%rdi
  131         addq    $40,%rsp
  132         ret
  133 
  134 ENTRY(x86_64_call2)
  135         subq    $40,%rsp
  136         mov     %rsi,%rcx
  137         /* %rdx is already correct */
  138         call    *%rdi
  139         addq    $40,%rsp
  140         ret
  141 
  142 ENTRY(x86_64_call3)
  143         subq    $40,%rsp
  144         mov     %rcx,%r8
  145         mov     %rsi,%rcx
  146         call    *%rdi
  147         addq    $40,%rsp
  148         ret
  149 
  150 ENTRY(x86_64_call4)
  151         subq    $40,%rsp
  152         mov     %r8,%r9
  153         mov     %rcx,%r8
  154         mov     %rsi,%rcx
  155         call    *%rdi
  156         addq    $40,%rsp
  157         ret
  158 
  159 ENTRY(x86_64_call5)
  160         subq    $48,%rsp
  161         mov     %r9,32(%rsp)
  162         mov     %r8,%r9
  163         mov     %rcx,%r8
  164         mov     %rsi,%rcx
  165         call    *%rdi
  166         addq    $48,%rsp
  167         ret
  168 
  169 ENTRY(x86_64_call6)
  170         subq    $56,%rsp
  171         mov     56+8(%rsp),%rax
  172         mov     %r9,32(%rsp)
  173         mov     %rax,40(%rsp)
  174         mov     %r8,%r9
  175         mov     %rcx,%r8
  176         mov     %rsi,%rcx
  177         call    *%rdi
  178         addq    $56,%rsp
  179         ret

Cache object: 096faabdc3cec240c5cc5da131f1a827


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