Home | History | Annotate | Download | only in m_dispatch
      1 
      2 /*--------------------------------------------------------------------*/
      3 /*--- The core dispatch loop, for jumping to a code address.       ---*/
      4 /*---                                       dispatch-s390x-linux.S ---*/
      5 /*--------------------------------------------------------------------*/
      6 
      7 /*
      8   This file is part of Valgrind, a dynamic binary instrumentation
      9   framework.
     10 
     11   Copyright IBM Corp. 2010-2011
     12 
     13   This program is free software; you can redistribute it and/or
     14   modify it under the terms of the GNU General Public License as
     15   published by the Free Software Foundation; either version 2 of the
     16   License, or (at your option) any later version.
     17 
     18   This program is distributed in the hope that it will be useful, but
     19   WITHOUT ANY WARRANTY; without even the implied warranty of
     20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     21   General Public License for more details.
     22 
     23   You should have received a copy of the GNU General Public License
     24   along with this program; if not, write to the Free Software
     25   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
     26   02111-1307, USA.
     27 
     28   The GNU General Public License is contained in the file COPYING.
     29 */
     30 
     31 /* Contributed by Florian Krohm and Christian Borntraeger */
     32 
     33 #include "pub_core_basics_asm.h"
     34 #include "pub_core_dispatch_asm.h"
     35 #include "pub_core_transtab_asm.h"
     36 #include "libvex_guest_offsets.h"
     37 #include "libvex_s390x_common.h"
     38 
     39 #if defined(VGA_s390x)
     40 
     41 /*------------------------------------------------------------*/
     42 /*---                                                      ---*/
     43 /*--- The dispatch loop.  VG_(run_innerloop) is used to    ---*/
     44 /*--- run all translations except no-redir ones.           ---*/
     45 /*---                                                      ---*/
     46 /*------------------------------------------------------------*/
     47 
     48 /* Convenience definitions for readability */
     49 #undef  SP
     50 #define SP S390_REGNO_STACK_POINTER
     51 
     52 #undef  LR
     53 #define LR S390_REGNO_LINK_REGISTER
     54 
     55 /* Location of valgrind's saved FPC register */
     56 #define S390_LOC_SAVED_FPC_V S390_OFFSET_SAVED_FPC_V(SP)
     57 
     58 /* Location of saved guest state pointer */
     59 #define S390_LOC_SAVED_GSP S390_OFFSET_SAVED_GSP(SP)
     60 
     61 /* Location of saved R2 register */
     62 #define S390_LOC_SAVED_R2 S390_OFFSET_SAVED_R2(SP)
     63 
     64 /*----------------------------------------------------*/
     65 /*--- Preamble (set everything up)                 ---*/
     66 /*----------------------------------------------------*/
     67 
     68 /* signature:
     69 UWord VG_(run_innerloop) ( void* guest_state, UWord do_profiling );
     70 */
     71 
     72 .text
     73 .align   4
     74 .globl VG_(run_innerloop)
     75 VG_(run_innerloop):
     76         /* r2 holds address of guest_state */
     77         /* r3 holds do_profiling (a flag) */
     78 
     79         /* Save gprs   ABI: r6...r13 and r15 */
     80         stmg %r6,%r15,48(SP)
     81 
     82         /* New stack frame */
     83         aghi SP,-S390_INNERLOOP_FRAME_SIZE
     84 
     85         /* Save fprs:   ABI: f8...f15 */
     86         std  %f8,160+0(SP)
     87         std  %f9,160+8(SP)
     88         std  %f10,160+16(SP)
     89         std  %f11,160+24(SP)
     90         std  %f12,160+32(SP)
     91         std  %f13,160+40(SP)
     92         std  %f14,160+48(SP)
     93         std  %f15,160+56(SP)
     94 
     95         /* Load address of guest state into guest state register (r13) */
     96         lgr  %r13,%r2
     97 
     98         /* Store address of guest state pointer on stack.
     99            It will be needed later because upon return from a VEX translation
    100            r13 may contain a special value. So the old value will be used to
    101            determine whether r13 contains a special value. */
    102         stg  %r13,S390_LOC_SAVED_GSP
    103 
    104         /* Save valgrind's FPC on stack so run_innerloop_exit can restore
    105            it later . */
    106         stfpc S390_LOC_SAVED_FPC_V
    107 
    108         /* Load the FPC the way the client code wants it. I.e. pull the
    109            value from the guest state.
    110         lfpc OFFSET_s390x_fpc(%r13)
    111 
    112         /* Get the IA from the guest state */
    113         lg   %r2,OFFSET_s390x_IA(%r13)
    114 
    115         /* Get VG_(dispatch_ctr) -- a 32-bit value -- and store it in a reg */
    116         larl %r6,VG_(dispatch_ctr)
    117         l    S390_REGNO_DISPATCH_CTR,0(%r6)
    118 
    119         /* Fall into main loop (the right one) */
    120 
    121         /* r3 = 1 --> do_profiling. We may trash r3 later on. That's OK,
    122            because it's a volatile register (does not need to be preserved). */
    123         ltgr %r3,%r3
    124         je   run_innerloop__dispatch_unprofiled
    125         j    run_innerloop__dispatch_profiled
    126 
    127 /*----------------------------------------------------*/
    128 /*--- NO-PROFILING (standard) dispatcher           ---*/
    129 /*----------------------------------------------------*/
    130 
    131 run_innerloop__dispatch_unprofiled:
    132         /* Load the link register with the address the jitted code will
    133            return to when it's done executing. The link register is loaded
    134            exactly once per loop. This is safe, because the jitted code
    135            cannot possibly modify the LR. How else would it be able to return
    136            to the location in the LR otherwise? */
    137         basr LR,0
    138 
    139         /* Loop begins here */
    140 
    141         /* This is the story:
    142 
    143            r2  = IA = next guest address
    144            r12 = VG_(dispatch_ctr)
    145            r13 = guest state pointer or (upon return from guest code) some
    146                  special value
    147            r15 = stack pointer (as usual)
    148         */
    149 innermost_loop:
    150         /* Has the guest state pointer been messed with? If yes, exit.
    151            The mess is recognised by r13 containing an odd value. */
    152         tmll %r13,1
    153         jne  gsp_changed
    154 
    155         /* Save the jump address in the guest state */
    156         stg  %r2,OFFSET_s390x_IA(%r13)
    157 
    158 
    159 	/* Try a fast lookup in the translation cache:
    160            Compute offset (not index) into VT_(tt_fast):
    161 
    162            offset = VG_TT_FAST_HASH(addr) * sizeof(FastCacheEntry)
    163 
    164            with VG_TT_FAST_HASH(addr) == (addr >> 1) & VG_TT_FAST_MASK
    165            and  sizeof(FastCacheEntry) == 16
    166 
    167            offset = ((addr >> 1) & VG_TT_FAST_MASK) << 4
    168            which is
    169            offset = ((addr & (VG_TT_FAST_MASK << 1) ) << 3
    170         */
    171         larl  %r8, VG_(tt_fast)
    172         llill %r5,( VG_TT_FAST_MASK << 1) & 0xffff
    173 #if ((( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16 != 0)
    174         iilh %r5,(( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16
    175 #endif
    176         ngr  %r5,%r2
    177         sllg %r7,%r5,3
    178 
    179 	/* Are we out of timeslice?  If yes, defer to scheduler. */
    180         ahi  S390_REGNO_DISPATCH_CTR,-1
    181         jz   counter_is_zero
    182 
    183         lg   %r11, 8(%r8,%r7)      /* .host */
    184         cg   %r2,  0(%r8,%r7)      /* next guest address == .guest ? */
    185         jne  fast_lookup_failed
    186 
    187         /* Found a match.  Call .host.
    188            r11 is an address. There we will find the instrumented client code.
    189            That code may modify the guest state register r13. The client code
    190            will return to the beginning of this loop start by issuing br LR.
    191            We can simply branch to the host code */
    192         br %r11
    193 
    194 
    195 /*----------------------------------------------------*/
    196 /*--- PROFILING dispatcher (can be much slower)    ---*/
    197 /*----------------------------------------------------*/
    198 
    199 run_innerloop__dispatch_profiled:
    200         stg  %r2,S390_LOC_SAVED_R2
    201 
    202         /* Load the link register with the address the jitted code will
    203            return to when it's done executing. */
    204         bras LR,innermost_loop
    205 
    206         /* Jitted code returns here. Update profile counter for previous IA */
    207 
    208         llill %r5,( VG_TT_FAST_MASK << 1) & 0xffff
    209 #if ((( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16 != 0)
    210         iilh %r5,(( VG_TT_FAST_MASK << 1) & 0xffff0000) >> 16
    211 #endif
    212         ng   %r5,S390_LOC_SAVED_R2
    213         sllg %r7,%r5,2
    214 
    215         /* Increment bb profile counter */
    216         larl %r8, VG_(tt_fastN)
    217         lg   %r9,0(%r8,%r7)
    218         l    %r10,0(%r9)
    219         ahi  %r10,1
    220         st   %r10,0(%r9)
    221 
    222         j    run_innerloop__dispatch_profiled
    223 
    224 /*----------------------------------------------------*/
    225 /*--- exit points                                  ---*/
    226 /*----------------------------------------------------*/
    227 
    228 gsp_changed:
    229 	/* Someone messed with the gsp (in r13).  Have to
    230            defer to scheduler to resolve this.  The register
    231            holding VG_(dispatch_ctr) is not yet decremented,
    232            so no need to increment. */
    233 
    234         /* Update the IA in the guest state */
    235         lg  %r6,S390_LOC_SAVED_GSP       /* r6 = original guest state pointer */
    236         stg %r2,OFFSET_s390x_IA(%r6)
    237 
    238         /* Return the special guest state pointer value */
    239         lgr %r2, %r13
    240 	j   run_innerloop_exit
    241 
    242 
    243 counter_is_zero:
    244 	/* IA is up to date */
    245 
    246 	/* Back out decrement of the dispatch counter */
    247         ahi S390_REGNO_DISPATCH_CTR,1
    248 
    249         /* Set return value for the scheduler */
    250         lghi %r2,VG_TRC_INNER_COUNTERZERO
    251         j    run_innerloop_exit
    252 
    253 
    254 fast_lookup_failed:
    255 	/* IA is up to date */
    256 
    257 	/* Back out decrement of the dispatch counter */
    258         ahi S390_REGNO_DISPATCH_CTR,1
    259 
    260         /* Set return value for the scheduler */
    261         lghi %r2,VG_TRC_INNER_FASTMISS
    262         j    run_innerloop_exit
    263 
    264 
    265         /* All exits from the dispatcher go through here.
    266            When we come here r2 holds the return value. */
    267 run_innerloop_exit:
    268 
    269 	/* Restore valgrind's FPC, as client code may have changed it. */
    270         lfpc S390_LOC_SAVED_FPC_V
    271 
    272         /* Write ctr to VG_(dispatch_ctr) (=32bit value) */
    273         larl %r6,VG_(dispatch_ctr)
    274         st   S390_REGNO_DISPATCH_CTR,0(%r6)
    275 
    276         /* Restore callee-saved registers... */
    277 
    278         /* Floating-point regs */
    279         ld  %f8,160+0(SP)
    280         ld  %f9,160+8(SP)
    281         ld  %f10,160+16(SP)
    282         ld  %f11,160+24(SP)
    283         ld  %f12,160+32(SP)
    284         ld  %f13,160+40(SP)
    285         ld  %f14,160+48(SP)
    286         ld  %f15,160+56(SP)
    287 
    288         /* Remove atack frame */
    289         aghi SP,S390_INNERLOOP_FRAME_SIZE
    290 
    291         /* General-purpose regs. This also restores the original link
    292            register (r14) and stack pointer (r15). */
    293         lmg %r6,%r15,48(SP)
    294 
    295         /* Return */
    296         br  LR
    297 
    298 /*------------------------------------------------------------*/
    299 /*---                                                      ---*/
    300 /*--- A special dispatcher, for running no-redir           ---*/
    301 /*--- translations.  Just runs the given translation once. ---*/
    302 /*---                                                      ---*/
    303 /*------------------------------------------------------------*/
    304 
    305 /* signature:
    306 void VG_(run_a_noredir_translation) ( UWord* argblock );
    307 */
    308 
    309 /* Run a no-redir translation.  argblock points to 4 UWords, 2 to carry args
    310    and 2 to carry results:
    311       0: input:  ptr to translation
    312       1: input:  ptr to guest state
    313       2: output: next guest PC
    314       3: output: guest state pointer afterwards (== thread return code)
    315 */
    316 .text
    317 .align   4
    318 .globl VG_(run_a_noredir_translation)
    319 VG_(run_a_noredir_translation):
    320         stmg %r6,%r15,48(SP)
    321         aghi SP,-S390_INNERLOOP_FRAME_SIZE
    322         std  %f8,160+0(SP)
    323         std  %f9,160+8(SP)
    324         std  %f10,160+16(SP)
    325         std  %f11,160+24(SP)
    326         std  %f12,160+32(SP)
    327         std  %f13,160+40(SP)
    328         std  %f14,160+48(SP)
    329         std  %f15,160+56(SP)
    330 
    331         /* Load address of guest state into guest state register (r13) */
    332         lg   %r13,8(%r2)
    333 
    334         /* Get the IA */
    335         lg   %r11,0(%r2)
    336 
    337         /* save r2 (argblock) as it is clobbered */
    338 	stg  %r2,160+64(SP)
    339 
    340         /* the call itself */
    341         basr LR,%r11
    342 
    343         /* restore argblock */
    344 	lg   %r1,160+64(SP)
    345 	/* save the next guest PC */
    346 	stg  %r2,16(%r1)
    347 
    348 	/* save the guest state */
    349 	stg  %r13,24(%r1)
    350 
    351         /* Restore Floating-point regs */
    352         ld  %f8,160+0(SP)
    353         ld  %f9,160+8(SP)
    354         ld  %f10,160+16(SP)
    355         ld  %f11,160+24(SP)
    356         ld  %f12,160+32(SP)
    357         ld  %f13,160+40(SP)
    358         ld  %f14,160+48(SP)
    359         ld  %f15,160+56(SP)
    360 
    361         aghi SP,S390_INNERLOOP_FRAME_SIZE
    362 
    363         lmg %r6,%r15,48(SP)
    364 	br  %r14
    365 
    366 
    367 /* Let the linker know we don't need an executable stack */
    368 .section .note.GNU-stack,"",@progbits
    369 
    370 #endif /* VGA_s390x */
    371 
    372 /*--------------------------------------------------------------------*/
    373 /*--- end                                   dispatch-s390x-linux.S ---*/
    374 /*--------------------------------------------------------------------*/
    375