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