Home | History | Annotate | Download | only in m_dispatch
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
      4 /*---                                       dispatch-arm64-linux.S ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8   This file is part of Valgrind, a dynamic binary instrumentation
      9   framework.
     10 
     11   Copyright (C) 2013-2013 OpenWorks
     12       info (at) open-works.net
     13 
     14   This program is free software; you can redistribute it and/or
     15   modify it under the terms of the GNU General Public License as
     16   published by the Free Software Foundation; either version 2 of the
     17   License, or (at your option) any later version.
     18 
     19   This program is distributed in the hope that it will be useful, but
     20   WITHOUT ANY WARRANTY; without even the implied warranty of
     21   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     22   General Public License for more details.
     23 
     24   You should have received a copy of the GNU General Public License
     25   along with this program; if not, write to the Free Software
     26   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     27   02111-1307, USA.
     28 
     29   The GNU General Public License is contained in the file COPYING.
     30 */
     31 
     32 #if defined(VGP_arm64_linux)
     33 
     34 #include "pub_core_basics_asm.h"
     35 #include "pub_core_dispatch_asm.h"
     36 #include "pub_core_transtab_asm.h"
     37 #include "libvex_guest_offsets.h"	/* for OFFSET_arm_R* */
     38 
     39 
     40 /*------------------------------------------------------------*/
     41 /*---                                                      ---*/
     42 /*--- The dispatch loop.  VG_(disp_run_translations) is    ---*/
     43 /*--- used to run all translations,                        ---*/
     44 /*--- including no-redir ones.                             ---*/
     45 /*---                                                      ---*/
     46 /*------------------------------------------------------------*/
     47 
     48 /*----------------------------------------------------*/
     49 /*--- Entry and preamble (set everything up)       ---*/
     50 /*----------------------------------------------------*/
     51 
     52 /* signature:
     53 void VG_(disp_run_translations)( UWord* two_words,
     54                                  void*  guest_state,
     55                                  Addr   host_addr );
     56 */
     57 .text
     58 .global VG_(disp_run_translations)
     59 VG_(disp_run_translations):
     60         /* x0  holds two_words
     61            x1  holds guest_state
     62            x2  holds host_addr
     63         */
     64         /* Push the callee-saved registers.  Unclear if x19/x20 are
     65            callee-saved, but be on the safe side.  Note this sequence
     66            maintains 16-alignment of sp.  Also save x0 since it will
     67            be needed in the postamble. */
     68         stp  x29, x30, [sp, #-16]!
     69         stp  x27, x28, [sp, #-16]!
     70         stp  x25, x26, [sp, #-16]!
     71         stp  x23, x24, [sp, #-16]!
     72         stp  x21, x22, [sp, #-16]!
     73         stp  x19, x20, [sp, #-16]!
     74         stp  x0,  xzr, [sp, #-16]!
     75 
     76         /* set FPSCR to vex-required default value */
     77         // FIXME
     78         // mov  r4, #0
     79         // fmxr fpscr, r4
     80 
     81        	/* Set up the guest state pointer */
     82         mov x21, x1
     83 
     84         /* and jump into the code cache.  Chained translations in
     85            the code cache run, until for whatever reason, they can't
     86            continue.  When that happens, the translation in question
     87            will jump (or call) to one of the continuation points
     88            VG_(cp_...) below. */
     89         br x2
     90         /* NOTREACHED */
     91 
     92 /*----------------------------------------------------*/
     93 /*--- Postamble and exit.                          ---*/
     94 /*----------------------------------------------------*/
     95 
     96 postamble:
     97         /* At this point, r1 and r2 contain two
     98            words to be returned to the caller.  r1
     99            holds a TRC value, and r2 optionally may
    100            hold another word (for CHAIN_ME exits, the
    101            address of the place to patch.) */
    102 
    103         /* We're leaving.  Check that nobody messed with
    104            FPSCR in ways we don't expect. */
    105         // FIXME
    106         // fmrx r4, fpscr
    107         // bic  r4, #0xF8000000 /* mask out NZCV and QC */
    108         // bic  r4, #0x0000009F /* mask out IDC,IXC,UFC,OFC,DZC,IOC */
    109         // cmp  r4, #0
    110         // beq  remove_frame /* we're OK */
    111         /* otherwise we have an invariant violation */
    112         // movw r1, #VG_TRC_INVARIANT_FAILED
    113         // movw r2, #0
    114         /* fall through */
    115 
    116 remove_frame:
    117         /* Restore int regs, including importantly x0 (two_words),
    118            but not x1 */
    119         ldp  x0,  xzr, [sp], #16
    120         ldp  x19, x20, [sp], #16
    121         ldp  x21, x22, [sp], #16
    122         ldp  x23, x24, [sp], #16
    123         ldp  x25, x26, [sp], #16
    124         ldp  x27, x28, [sp], #16
    125         ldp  x29, x30, [sp], #16
    126 
    127         /* Stash return values */
    128         str  x1, [x0, #0]
    129         str  x2, [x0, #8]
    130         ret
    131 
    132 /*----------------------------------------------------*/
    133 /*--- Continuation points                          ---*/
    134 /*----------------------------------------------------*/
    135 
    136 /* ------ Chain me to slow entry point ------ */
    137 .global VG_(disp_cp_chain_me_to_slowEP)
    138 VG_(disp_cp_chain_me_to_slowEP):
    139         /* We got called.  The return address indicates
    140            where the patching needs to happen.  Collect
    141            the return address and, exit back to C land,
    142            handing the caller the pair (Chain_me_S, RA) */
    143         mov  x1, #VG_TRC_CHAIN_ME_TO_SLOW_EP
    144         mov  x2, x30 // 30 == LR
    145         /* 4 = movw x9, disp_cp_chain_me_to_slowEP[15:0]
    146            4 = movk x9, disp_cp_chain_me_to_slowEP[31:16], lsl 16
    147            4 = movk x9, disp_cp_chain_me_to_slowEP[47:32], lsl 32
    148            4 = movk x9, disp_cp_chain_me_to_slowEP[63:48], lsl 48
    149            4 = blr  x9
    150         */
    151         sub  x2, x2, #4+4+4+4+4
    152         b    postamble
    153 
    154 /* ------ Chain me to fast entry point ------ */
    155 .global VG_(disp_cp_chain_me_to_fastEP)
    156 VG_(disp_cp_chain_me_to_fastEP):
    157         /* We got called.  The return address indicates
    158            where the patching needs to happen.  Collect
    159            the return address and, exit back to C land,
    160            handing the caller the pair (Chain_me_F, RA) */
    161         mov  x1, #VG_TRC_CHAIN_ME_TO_FAST_EP
    162         mov  x2, x30 // 30 == LR
    163         /* 4 = movw x9, disp_cp_chain_me_to_fastEP[15:0]
    164            4 = movk x9, disp_cp_chain_me_to_fastEP[31:16], lsl 16
    165            4 = movk x9, disp_cp_chain_me_to_fastEP[47:32], lsl 32
    166            4 = movk x9, disp_cp_chain_me_to_fastEP[63:48], lsl 48
    167            4 = blr  x9
    168         */
    169         sub  x2, x2, #4+4+4+4+4
    170         b    postamble
    171 
    172 /* ------ Indirect but boring jump ------ */
    173 .global VG_(disp_cp_xindir)
    174 VG_(disp_cp_xindir):
    175 	/* Where are we going? */
    176         ldr  x0, [x21, #OFFSET_arm64_PC]
    177 
    178         /* stats only */
    179         adrp x1,           VG_(stats__n_xindirs_32)
    180         add  x1, x1, :lo12:VG_(stats__n_xindirs_32)
    181         ldr  w2, [x1, #0]
    182         add  w2, w2, #1
    183         str  w2, [x1, #0]
    184 
    185         /* try a fast lookup in the translation cache */
    186         // x0 = next guest, x1,x2,x3,x4 scratch
    187         mov  x1, #VG_TT_FAST_MASK       // x1 = VG_TT_FAST_MASK
    188 	and  x2, x1, x0, LSR #2         // x2 = entry # = (x1 & (x0 >> 2))
    189 
    190         adrp x4,           VG_(tt_fast)
    191         add  x4, x4, :lo12:VG_(tt_fast) // x4 = &VG_(tt_fast)
    192 
    193 	add  x1, x4, x2, LSL #4         // r1 = &tt_fast[entry#]
    194 
    195         ldp  x4, x5, [x1, #0]           // x4 = .guest, x5 = .host
    196 
    197 	cmp  x4, x0
    198 
    199         // jump to host if lookup succeeded
    200         bne  fast_lookup_failed
    201 	br   x5
    202         /*NOTREACHED*/
    203 
    204 fast_lookup_failed:
    205         /* RM ME -- stats only */
    206         adrp x1,           VG_(stats__n_xindir_misses_32)
    207         add  x1, x1, :lo12:VG_(stats__n_xindir_misses_32)
    208         ldr  w2, [x1, #0]
    209         add  w2, w2, #1
    210         str  w2, [x1, #0]
    211 
    212 	mov  x1, #VG_TRC_INNER_FASTMISS
    213         mov  x2, #0
    214 	b    postamble
    215 
    216 /* ------ Assisted jump ------ */
    217 .global VG_(disp_cp_xassisted)
    218 VG_(disp_cp_xassisted):
    219         /* x21 contains the TRC */
    220         mov  x1, x21
    221         mov  x2, #0
    222         b    postamble
    223 
    224 /* ------ Event check failed ------ */
    225 .global VG_(disp_cp_evcheck_fail)
    226 VG_(disp_cp_evcheck_fail):
    227        	mov  x1, #VG_TRC_INNER_COUNTERZERO
    228         mov  x2, #0
    229 	b    postamble
    230 
    231 
    232 .size VG_(disp_run_translations), .-VG_(disp_run_translations)
    233 
    234 /* Let the linker know we don't need an executable stack */
    235 .section .note.GNU-stack,"",%progbits
    236 
    237 #endif // defined(VGP_arm64_linux)
    238 
    239 /*--------------------------------------------------------------------*/
    240 /*--- end                                   dispatch-arm64-linux.S ---*/
    241 /*--------------------------------------------------------------------*/
    242