From: Ulrich Weigand Date: Mon, 17 May 2021 08:48:40 +0000 (+0200) Subject: [mono] Add thunking to s390x for calls that will be patched (#52783) X-Git-Tag: submit/tizen/20210909.063632~1359 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=9cb0ab915e971f6408aae662a8dec7fcf365930e;p=platform%2Fupstream%2Fdotnet%2Fruntime.git [mono] Add thunking to s390x for calls that will be patched (#52783) Merge https://github.com/mono/mono/pull/21052 into dotnet runtime. This fixes sporadic crashes due to code being patched non-atomically. --- diff --git a/src/mono/mono/mini/exceptions-s390x.c b/src/mono/mono/mini/exceptions-s390x.c index 0df2507..c79be65 100644 --- a/src/mono/mono/mini/exceptions-s390x.c +++ b/src/mono/mono/mini/exceptions-s390x.c @@ -61,7 +61,6 @@ #include "mini.h" #include "mini-s390x.h" -#include "support-s390x.h" #include "mini-runtime.h" #include "aot-runtime.h" #include "mono/utils/mono-tls-inline.h" @@ -119,7 +118,7 @@ mono_arch_get_call_filter (MonoTrampInfo **info, gboolean aot) inited = 1; /* call_filter (MonoContext *ctx, unsigned long eip, gpointer exc) */ - code = start = mono_global_codeman_reserve (512); + code = start = (guint8 *) mono_global_codeman_reserve (512); mono_add_unwind_op_def_cfa (unwind_ops, code, start, STK_BASE, S390_CFA_OFFSET); s390_stmg (code, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); @@ -314,7 +313,7 @@ mono_arch_get_throw_exception_generic (int size, MonoTrampInfo **info, int corli MonoJumpInfo *ji = NULL; GSList *unwind_ops = NULL; - code = start = mono_global_codeman_reserve(size); + code = start = (guint8 *) mono_global_codeman_reserve(size); mono_add_unwind_op_def_cfa (unwind_ops, code, start, STK_BASE, S390_CFA_OFFSET); s390_stmg (code, s390_r6, s390_r15, STK_BASE, S390_REG_SAVE_OFFSET); @@ -569,7 +568,7 @@ mono_arch_unwind_frame (MonoJitTlsData *jit_tls, memcpy(new_ctx->uc_mcontext.fpregs.fprs, (*lmf)->fregs, sizeof((*lmf)->fregs)); MONO_CONTEXT_SET_BP (new_ctx, (*lmf)->ebp); MONO_CONTEXT_SET_IP (new_ctx, (*lmf)->eip - 2); - *lmf = (*lmf)->previous_lmf; + *lmf = (struct MonoLMF *) (*lmf)->previous_lmf; return TRUE; } diff --git a/src/mono/mono/mini/mini-s390x.c b/src/mono/mono/mini/mini-s390x.c index e16cae8..9f27674 100644 --- a/src/mono/mono/mini/mini-s390x.c +++ b/src/mono/mono/mini/mini-s390x.c @@ -31,8 +31,9 @@ if (ins->inst_true_bb->native_offset) { \ s390_jcl (code, cond, displace); \ } \ } else { \ - mono_add_patch_info (cfg, code - cfg->native_code, \ - MONO_PATCH_INFO_BB, ins->inst_true_bb); \ + mono_add_patch_info_rel (cfg, code - cfg->native_code, \ + MONO_PATCH_INFO_BB, ins->inst_true_bb, \ + MONO_R_S390_RELINS); \ s390_jcl (code, cond, 0); \ } \ } @@ -49,8 +50,9 @@ if (ins->inst_target_bb->native_offset) { \ s390_jcl (code, S390_CC_UN, displace); \ } \ } else { \ - mono_add_patch_info (cfg, code - cfg->native_code, \ - MONO_PATCH_INFO_BB, ins->inst_target_bb); \ + mono_add_patch_info_rel (cfg, code - cfg->native_code, \ + MONO_PATCH_INFO_BB, ins->inst_target_bb, \ + MONO_R_S390_RELINS); \ s390_jcl (code, S390_CC_UN, 0); \ } \ } @@ -79,8 +81,9 @@ if (ins->inst_true_bb->native_offset) { \ } \ } else { \ s390_##cmp (code, ins->sreg1, ins->sreg2); \ - mono_add_patch_info (cfg, code - cfg->native_code, \ - MONO_PATCH_INFO_BB, ins->inst_true_bb); \ + mono_add_patch_info_rel (cfg, code - cfg->native_code, \ + MONO_PATCH_INFO_BB, ins->inst_true_bb, \ + MONO_R_S390_RELINS); \ s390_jcl (code, ins->sreg3, 0); \ } \ } @@ -119,8 +122,9 @@ if (ins->inst_true_bb->native_offset) { \ S390_SET (code, s390_r0, ins->backend.data); \ s390_##cmp (code, ins->sreg1, s390_r0); \ } \ - mono_add_patch_info (cfg, code - cfg->native_code, \ - MONO_PATCH_INFO_BB, ins->inst_true_bb); \ + mono_add_patch_info_rel (cfg, code - cfg->native_code, \ + MONO_PATCH_INFO_BB, ins->inst_true_bb, \ + MONO_R_S390_RELINS); \ s390_jcl (code, ins->sreg3, 0); \ } \ } @@ -255,7 +259,6 @@ if (ins->inst_true_bb->native_offset) { \ #include "mini-s390x.h" #include "cpu-s390x.h" -#include "support-s390x.h" #include "jit-icalls.h" #include "ir-emit.h" #include "mini-gc.h" @@ -341,6 +344,11 @@ static CallInfo * get_call_info (MonoMemPool *, MonoMethodSignature *); static guchar * emit_float_to_int (MonoCompile *, guchar *, int, int, int, gboolean); static __inline__ void emit_unwind_regs(MonoCompile *, guint8 *, int, int, long); static void compare_and_branch(MonoBasicBlock *, MonoInst *, int, gboolean); +static __inline__ guint8 * emit_call(MonoCompile *, guint8 *, MonoJumpInfoType, gconstpointer); +static guint8 * emit_thunk(guint8 *, gconstpointer); +static void create_thunk(MonoCompile *, guint8 *, guint8 *, gpointer); +static void update_thunk(MonoCompile *, guint8 *, gpointer); +static void emit_patch_full (MonoCompile *, MonoJumpInfo *, guint8 *, gpointer, int); /*========================= End of Prototypes ======================*/ @@ -2595,10 +2603,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_BREAK: { - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_JIT_ICALL_ID, - GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break)); - S390_CALL_TEMPLATE (code, s390_r14); + code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break)); } break; case OP_ADDCC: { @@ -3562,10 +3568,11 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_br (code, s390_r1); } } else { - mono_add_patch_info (cfg, code - cfg->native_code, + mono_add_patch_info_rel (cfg, code - cfg->native_code, MONO_PATCH_INFO_METHOD_JUMP, - call->method); + call->method, MONO_R_S390_THUNKED); S390_BR_TEMPLATE (code, s390_r1); + cfg->thunk_area += THUNK_SIZE; } } } @@ -3585,10 +3592,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_FCALL: { - call = (MonoCallInst*)ins; - - mono_call_add_patch_info (cfg, call, code - cfg->native_code); - S390_CALL_TEMPLATE (code, s390_r14); + MonoCallInst *call = (MonoCallInst *) ins; + const MonoJumpInfoTarget patch = mono_call_to_patch (call); + code = emit_call (cfg, code, patch.type, patch.target); if (!cfg->r4fp && call->signature->ret->type == MONO_TYPE_R4) s390_ldebr (code, s390_f0, s390_f0); } @@ -3599,9 +3605,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) case OP_VOIDCALL: case OP_RCALL: case OP_CALL: { - call = (MonoCallInst*)ins; - mono_call_add_patch_info (cfg, call, code - cfg->native_code); - S390_CALL_TEMPLATE (code, s390_r14); + MonoCallInst *call = (MonoCallInst *) ins; + const MonoJumpInfoTarget patch = mono_call_to_patch (call); + code = emit_call (cfg, code, patch.type, patch.target); } break; case OP_FCALL_REG: { @@ -3714,16 +3720,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) break; case OP_THROW: { s390_lgr (code, s390_r2, ins->sreg1); - mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, - GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_throw_exception)); - S390_CALL_TEMPLATE(code, s390_r14); + code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_throw_exception)); } break; case OP_RETHROW: { s390_lgr (code, s390_r2, ins->sreg1); - mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, - GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception)); - S390_CALL_TEMPLATE(code, s390_r14); + code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception)); } break; case OP_START_HANDLER: { @@ -3755,8 +3759,9 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) } break; case OP_CALL_HANDLER: { - mono_add_patch_info (cfg, code-cfg->native_code, - MONO_PATCH_INFO_BB, ins->inst_target_bb); + mono_add_patch_info_rel (cfg, code-cfg->native_code, + MONO_PATCH_INFO_BB, ins->inst_target_bb, + MONO_R_S390_DIRECT); s390_brasl (code, s390_r14, 0); for (GList *tmp = ins->inst_eh_blocks; tmp != bb->clause_holes; tmp = tmp->prev) mono_cfg_add_try_hole (cfg, ((MonoLeaveClause *) tmp->data)->clause, code, bb); @@ -3853,9 +3858,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_tm (code, ins->sreg1, byte_offset, bitmask); s390_jo (code, 0); CODEPTR(code, jump); - mono_add_patch_info (cfg, code-cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, - GUINT_TO_POINTER (MONO_JIT_ICALL_mono_generic_class_init)); - S390_CALL_TEMPLATE(code, s390_r14); + code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_generic_class_init)); PTRSLOT (code, jump); @@ -4668,9 +4672,8 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb) s390_ltg (code, s390_r0, 0, ins->sreg1, 0); s390_jz (code, 0); CODEPTR(code, br); - mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, - GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll)); - S390_CALL_TEMPLATE (code, s390_r14); + code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll)); PTRSLOT (code, br); break; } @@ -5335,14 +5338,62 @@ mono_arch_register_lowlevel_calls (void) /** * + * @brief Architecture-specific patching + * @param[in] @cfg - Compilation control block + * @param[in] @code - Start of code + * @param[in] @target - Target of patch + * @param[in] @relo - Relocation type + * + * Perform patching action + */ + +static void +emit_patch_full (MonoCompile *cfg, MonoJumpInfo *ji, guint8 *code, + gpointer target, int relo) +{ + guint8 *ip = ji->ip.i + code; + + switch (relo) { + case MONO_R_S390_RELINS : + target = S390_RELATIVE(target, ip); + ip += 2; + s390_patch_rel (ip, (guint64) target); + break; + case MONO_R_S390_THUNKED : + if (cfg) + create_thunk(cfg, ip, code, target); + else + update_thunk(cfg, code, target); + break; + case MONO_R_S390_DIRECT : + S390_EMIT_CALL (ip, target); + break; + case MONO_R_S390_ADDR : + s390_patch_addr (ip, (guint64) target); + break; + case MONO_R_S390_SWITCH : + S390_EMIT_LOAD (ip, target); + break; + case MONO_R_S390_REL : + target = S390_RELATIVE(target, ip); + s390_patch_rel (ip, (guint64) target); + break; + default : + g_assert_not_reached(); + } +} + +/*========================= End of Function ========================*/ + +/** + * * @brief Architecture-specific patching of instructions and data * * @param[in] @cfg - Compile control block * @param[in] @method - Current method - * @param[in] @code - Current innstruction pointer + * @param[in] @code - Current code block * @param[in] @ji - Jump information - * @param[in] @run_cctors - Whether class constructors need to be initialized - * @param[in] @error - Error control block + * @param[in] @target - Target of patch * * Process the patch data created during the instruction build process. * This resolves jumps, calls, variables etc. @@ -5351,33 +5402,28 @@ mono_arch_register_lowlevel_calls (void) void mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpointer target) { - unsigned char *ip = ji->ip.i + code; - gint64 displace; - switch (ji->type) { case MONO_PATCH_INFO_IP: case MONO_PATCH_INFO_LDSTR: case MONO_PATCH_INFO_TYPE_FROM_HANDLE: case MONO_PATCH_INFO_LDTOKEN: case MONO_PATCH_INFO_EXC: - s390_patch_addr (ip, (guint64) target); + emit_patch_full (cfg, ji, code, target, MONO_R_S390_ADDR); break; - case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR: - case MONO_PATCH_INFO_METHOD: - case MONO_PATCH_INFO_JIT_ICALL_ID: + case MONO_PATCH_INFO_BB: case MONO_PATCH_INFO_JIT_ICALL_ADDR: + case MONO_PATCH_INFO_JIT_ICALL_ID: + case MONO_PATCH_INFO_METHOD: + emit_patch_full (cfg, ji, code, target, ji->relocation); + break; + case MONO_PATCH_INFO_METHOD_JUMP: case MONO_PATCH_INFO_RGCTX_FETCH: - case MONO_PATCH_INFO_ABS: { - S390_EMIT_CALL (ip, target); + case MONO_PATCH_INFO_SPECIFIC_TRAMPOLINE_LAZY_FETCH_ADDR: + case MONO_PATCH_INFO_ABS: + emit_patch_full (cfg, ji, code, target, MONO_R_S390_THUNKED); break; - } case MONO_PATCH_INFO_SWITCH: - /*----------------------------------*/ - /* ip points at the basr r13,0/j +4 */ - /* instruction the vtable value */ - /* follows this (i.e. ip+6) */ - /*----------------------------------*/ - S390_EMIT_LOAD (ip, target); + emit_patch_full(cfg, ji, code, target, MONO_R_S390_SWITCH); break; case MONO_PATCH_INFO_METHODCONST: case MONO_PATCH_INFO_CLASS: @@ -5385,28 +5431,12 @@ mono_arch_patch_code_new (MonoCompile *cfg, guint8 *code, MonoJumpInfo *ji, gpoi case MONO_PATCH_INFO_FIELD: case MONO_PATCH_INFO_IID: case MONO_PATCH_INFO_EXC_NAME: - target = S390_RELATIVE(target, ip); - s390_patch_rel (ip, (guint64) target); - break; - case MONO_PATCH_INFO_R4: - case MONO_PATCH_INFO_R8: - g_assert_not_reached (); - break; - case MONO_PATCH_INFO_METHOD_JUMP: - displace = (gint64) S390_RELATIVE(target, ip); - if ((displace >= INT_MIN) && (displace <= INT_MAX)) - s390_jg (ip, (gint32) displace); - else { - S390_SET (ip, s390_r1, target); - s390_br (ip, s390_r1); - } + emit_patch_full(cfg, ji, code, target, MONO_R_S390_REL); break; case MONO_PATCH_INFO_NONE: break; default: - target = S390_RELATIVE(target, ip); - ip += 2; - s390_patch_rel (ip, (guint64) target); + emit_patch_full (cfg, ji, code, target, MONO_R_S390_RELINS); } } @@ -5675,10 +5705,8 @@ if ((strcmp(method->klass->name_space,"") == 0) && /* * On return from this call r2 have the address of the &lmf */ - mono_add_patch_info (cfg, code - cfg->native_code, - MONO_PATCH_INFO_JIT_ICALL_ID, - GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern)); - S390_CALL_TEMPLATE(code, s390_r1); + code = emit_call (cfg, code, MONO_PATCH_INFO_JIT_ICALL_ID, + GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern)); /* * Set lmf.lmf_addr = jit_tls->lmf @@ -5899,6 +5927,9 @@ mono_arch_emit_epilog (MonoCompile *cfg) /* Restore the unwind state to be the same as before the epilog */ mono_emit_unwind_op_restore_state (cfg, code); + /* Round up for start of any thunk entries */ + code = (guint8 *) ((((uintptr_t) code + 7) >> 3) << 3); + set_code_cursor (cfg, code); } @@ -5985,7 +6016,9 @@ mono_arch_emit_exceptions (MonoCompile *cfg) patch_info->type = MONO_PATCH_INFO_JIT_ICALL_ID; patch_info->data.jit_icall_id = MONO_JIT_ICALL_mono_arch_throw_corlib_exception; patch_info->ip.i = code - cfg->native_code; + patch_info->relocation = MONO_R_S390_THUNKED; S390_BR_TEMPLATE (code, s390_r1); + cfg->thunk_area += THUNK_SIZE; } break; } @@ -5994,6 +6027,10 @@ mono_arch_emit_exceptions (MonoCompile *cfg) break; } } + + /* Round up for start of any thunk entries */ + code = (guint8 *) ((((uintptr_t) code + 7) >> 3) << 3); + set_code_cursor (cfg, code); } @@ -7003,3 +7040,146 @@ mono_arch_load_function (MonoJitICallId jit_icall_id) } /*========================= End of Function ========================*/ + +/** + * + * @brief Emit call to thunked code + * + * @param[in] @cfg - configuration data + * @param[inout] @code - where to emit call + * @param[in] @call - call instruction + * @returns Pointer to next code area + * + */ + +static __inline__ guint8* +emit_call (MonoCompile *cfg, guint8 *code, MonoJumpInfoType type, gconstpointer target) +{ + mono_add_patch_info_rel (cfg, code-cfg->native_code, type, + target, MONO_R_S390_THUNKED); + S390_CALL_TEMPLATE (code, s390_r14); + cfg->thunk_area += THUNK_SIZE; + return code; +} + +/*========================= End of Function ========================*/ + +/** + * + * @brief Emit thunk for an indirect call + * + * @param[inout] @code - where to emit thunk + * @param[in] @target - thunk target + * @returns Pointer to next code area + * + */ + +static guint8* +emit_thunk (guint8 *code, gconstpointer target) +{ + *(guint64*)code = (guint64)target; + code += sizeof (guint64); + + return code; +} + +/*========================= End of Function ========================*/ + +/** + * + * @brief Create thunk + * + * @param[in] @cfg - Compiler configuration + * @param[inout] @code - where to emit thunk + * @param[in] @target - thunk target + * + * Create a new thunk + * + */ + +static void +create_thunk (MonoCompile *cfg, guint8 *ip, guint8 *code, gpointer target) +{ + guint8 *thunks; + int thunks_size; + + /* + * This can be called multiple times during JITting, + * save the current position in cfg->arch to avoid + * doing a O(n^2) search. + */ + if (!cfg->arch.thunks) { + cfg->arch.thunks = cfg->thunks; + cfg->arch.thunks_size = cfg->thunk_area; + } + thunks = (guint8 *) cfg->arch.thunks; + thunks_size = cfg->arch.thunks_size; + if (!thunks_size) { + g_print ("thunk failed %p->%p, thunk space=%d method %s", code, target, thunks_size, mono_method_full_name (cfg->method, TRUE)); + g_assert_not_reached (); + } + + g_assert (*(guint64 *)thunks == 0); + emit_thunk (thunks, target); + + cfg->arch.thunks += THUNK_SIZE; + cfg->arch.thunks_size -= THUNK_SIZE; + + S390_EMIT_CALL(ip, thunks); +} + +/*========================= End of Function ========================*/ + +/** + * + * @brief Update thunk + * + * @param[in] @cfg - Compiler configuration + * @param[inout] @code - where to emit thunk + * @param[in] @target - thunk target + * + * Update an existing thunk + * + */ + +static void +update_thunk (MonoCompile *cfg, guint8 *code, gpointer target) +{ + MonoJitInfo *ji; + MonoThunkJitInfo *info; + guint8 *thunks; + guint8 *orig_target; + guint8 *target_thunk; + int thunks_size; + + ji = mini_jit_info_table_find ((char*)code); + g_assert (ji); + info = mono_jit_info_get_thunk_info (ji); + g_assert (info); + + thunks = (guint8*)ji->code_start + info->thunks_offset; + thunks_size = info->thunks_size; + + /* + * We're pointing at the start of jump to thunk, + * but mono_arch_get_call_target expects we're pointing + * after the branch so we adjust + */ + orig_target = mono_arch_get_call_target (code + 6); + + target_thunk = NULL; + if (orig_target >= thunks && orig_target < thunks + thunks_size) { + /* The call already points to a thunk, because of trampolines etc. */ + target_thunk = orig_target; + } else { + g_print ("thunk failed %p->%p, thunk space=%d method %s", + code, target, thunks_size, + cfg ? mono_method_full_name (cfg->method, TRUE) + : mono_method_full_name (jinfo_get_method (ji), TRUE)); + g_assert_not_reached (); + } + + emit_thunk (target_thunk, target); +} + +/*========================= End of Function ========================*/ diff --git a/src/mono/mono/mini/mini-s390x.h b/src/mono/mono/mini/mini-s390x.h index 2b94792..d7d3566 100644 --- a/src/mono/mono/mini/mini-s390x.h +++ b/src/mono/mono/mini/mini-s390x.h @@ -38,6 +38,8 @@ typedef struct MonoCompileArch { int fpSize; /** Size of floating point save area */ MonoInst *ss_tramp_var; /** Single-step variable */ MonoInst *bp_tramp_var; /** Breakpoint variable */ + guint8 *thunks; /** Thunking area */ + int thunks_size; /** Size of thunking area */ } MonoCompileArch; typedef struct @@ -90,6 +92,17 @@ struct SeqPointInfo { #define S390_FP_SAVE_MASK 0xf0 +/* Thunk: 8 byte pointer */ +#define THUNK_SIZE 8 + +/* Relocation types */ +#define MONO_R_S390_RELINS 1 /* JGxx - relative jump */ +#define MONO_R_S390_THUNKED 2 /* Thunked call */ +#define MONO_R_S390_DIRECT 3 /* Direct call */ +#define MONO_R_S390_ADDR 4 /* Address */ +#define MONO_R_S390_SWITCH 5 /* Switch */ +#define MONO_R_S390_REL 6 /* Relative displacement */ + /*===============================================*/ /* Definitions used by mini-codegen.c */ /*===============================================*/ @@ -166,13 +179,13 @@ struct SeqPointInfo { #define MONO_ARCH_INIT_TOP_LMF_ENTRY(lmf) do { (lmf)->ebp = -1; } while (0) -/*------------------------------------------------------------------*/ -/* */ -/* Name - s390_patch_rel */ -/* */ -/* Function - Patch the code with a given offset. */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Patch the code with a given offset + * @param[in] @code - Area to patch + * @param[in] @target - Value to patch with + * + */ static void inline s390_patch_rel (guchar *code, guint64 target) @@ -186,13 +199,13 @@ s390_patch_rel (guchar *code, guint64 target) /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - s390_patch_addr */ -/* */ -/* Function - Patch the code with a given address. */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Patch the code with a given address + * @param[in] @code - Area to patch + * @param[in] @target - Address to patch with + * + */ static void inline s390_patch_addr (guchar *code, guint64 target) @@ -248,4 +261,92 @@ s390_patch_addr (guchar *code, guint64 target) /*========================= End of Function ========================*/ +#define S390_SET(loc, dr, v) \ + do { \ + guint64 val = (guint64) v; \ + if (s390_is_imm16(val)) { \ + s390_lghi(loc, dr, val); \ + } else if (s390_is_uimm16(val)) { \ + s390_llill(loc, dr, val); \ + } else if (s390_is_imm32(val)) { \ + s390_lgfi(loc, dr, val); \ + } else if (s390_is_uimm32(val)) { \ + s390_llilf(loc, dr, val); \ + } else { \ + guint32 hi = (val) >> 32; \ + guint32 lo = (val) & 0xffffffff; \ + s390_iihf(loc, dr, hi); \ + s390_iilf(loc, dr, lo); \ + } \ + } while (0) + +#define S390_LONG(loc, opy, op, r, ix, br, off) \ + if (s390_is_imm20(off)) { \ + s390_##opy (loc, r, ix, br, off); \ + } else { \ + if (ix == 0) { \ + S390_SET(loc, s390_r13, off); \ + s390_la (loc, s390_r13, s390_r13, br, 0); \ + } else { \ + s390_la (loc, s390_r13, ix, br, 0); \ + S390_SET (loc, s390_r0, off); \ + s390_agr (loc, s390_r13, s390_r0); \ + } \ + s390_##op (loc, r, 0, s390_r13, 0); \ + } + +#define S390_SET_MASK(loc, dr, v) \ + do { \ + if (s390_is_imm16 (v)) { \ + s390_lghi (loc, dr, v); \ + } else if (s390_is_imm32 (v)) { \ + s390_lgfi (loc, dr, v); \ + } else { \ + gint64 val = (gint64) v; \ + guint32 hi = (val) >> 32; \ + guint32 lo = (val) & 0xffffffff; \ + s390_iilf(loc, dr, lo); \ + s390_iihf(loc, dr, hi); \ + } \ + } while (0) + +#define S390_CALL_TEMPLATE(loc, r) \ + do { \ + s390_lgrl (loc, r, 0); \ + s390_basr (loc, s390_r14, r); \ + } while (0) + +#define S390_BR_TEMPLATE(loc, r) \ + do { \ + s390_lgrl (loc, r, 0); \ + s390_br (loc, r); \ + } while (0) + +#define S390_LOAD_TEMPLATE(loc, r) \ + do { \ + s390_iihf (loc, r, 0); \ + s390_iilf (loc, r, 0); \ + } while (0) + +#define S390_EMIT_CALL(loc, t) \ + do { \ + uintptr_t rel; \ + uintptr_t p = (uintptr_t) loc; \ + rel = ((uintptr_t) t - (uintptr_t) loc) >> 1; \ + p += 2; \ + *(guint32 *) p = rel; \ + } while (0) + +#define S390_EMIT_LOAD(loc, v) \ + do { \ + gint64 val = (gint64) v; \ + guint32 hi = (val) >> 32; \ + guint32 lo = (val) & 0xffffffff; \ + uintptr_t p = (uintptr_t) loc; \ + p += 2; \ + *(guint32 *) p = hi; \ + p += 6; \ + *(guint32 *) p = lo; \ + } while (0) + #endif /* __MONO_MINI_S390X_H__ */ diff --git a/src/mono/mono/mini/support-s390x.h b/src/mono/mono/mini/support-s390x.h deleted file mode 100644 index 8856f77..0000000 --- a/src/mono/mono/mini/support-s390x.h +++ /dev/null @@ -1,101 +0,0 @@ -/** - * \file - */ - -#ifndef __MONO_SUPPORT_S390X_H__ -#define __MONO_SUPPORT_S390X_H__ - -#define S390_SET(loc, dr, v) \ - do { \ - guint64 val = (guint64) v; \ - if (s390_is_imm16(val)) { \ - s390_lghi(loc, dr, val); \ - } else if (s390_is_uimm16(val)) { \ - s390_llill(loc, dr, val); \ - } else if (s390_is_imm32(val)) { \ - s390_lgfi(loc, dr, val); \ - } else if (s390_is_uimm32(val)) { \ - s390_llilf(loc, dr, val); \ - } else { \ - guint32 hi = (val) >> 32; \ - guint32 lo = (val) & 0xffffffff; \ - s390_iihf(loc, dr, hi); \ - s390_iilf(loc, dr, lo); \ - } \ - } while (0) - -#define S390_LONG(loc, opy, op, r, ix, br, off) \ - if (s390_is_imm20(off)) { \ - s390_##opy (loc, r, ix, br, off); \ - } else { \ - if (ix == 0) { \ - S390_SET(loc, s390_r13, off); \ - s390_la (loc, s390_r13, s390_r13, br, 0); \ - } else { \ - s390_la (loc, s390_r13, ix, br, 0); \ - S390_SET (loc, s390_r0, off); \ - s390_agr (loc, s390_r13, s390_r0); \ - } \ - s390_##op (loc, r, 0, s390_r13, 0); \ - } - -#define S390_SET_MASK(loc, dr, v) \ - do { \ - if (s390_is_imm16 (v)) { \ - s390_lghi (loc, dr, v); \ - } else if (s390_is_imm32 (v)) { \ - s390_lgfi (loc, dr, v); \ - } else { \ - gint64 val = (gint64) v; \ - guint32 hi = (val) >> 32; \ - guint32 lo = (val) & 0xffffffff; \ - s390_iilf(loc, dr, lo); \ - s390_iihf(loc, dr, hi); \ - } \ - } while (0) - -#define S390_CALL_TEMPLATE(loc, r) \ - do { \ - s390_iihf (loc, r, 0); \ - s390_iilf (loc, r, 0); \ - s390_basr (loc, s390_r14, r); \ - } while (0) - -#define S390_BR_TEMPLATE(loc, r) \ - do { \ - s390_iihf (loc, r, 0); \ - s390_iilf (loc, r, 0); \ - s390_br (loc, r); \ - } while (0) - -#define S390_LOAD_TEMPLATE(loc, r) \ - do { \ - s390_iihf (loc, r, 0); \ - s390_iilf (loc, r, 0); \ - } while (0) - -#define S390_EMIT_CALL(loc, t) \ - do { \ - gint64 val = (gint64) t; \ - guint32 hi = (val) >> 32; \ - guint32 lo = (val) & 0xffffffff; \ - uintptr_t p = (uintptr_t) loc; \ - p += 2; \ - *(guint32 *) p = hi; \ - p += 6; \ - *(guint32 *) p = lo; \ - } while (0) - -#define S390_EMIT_LOAD(loc, v) \ - do { \ - gint64 val = (gint64) v; \ - guint32 hi = (val) >> 32; \ - guint32 lo = (val) & 0xffffffff; \ - uintptr_t p = (uintptr_t) loc; \ - p += 2; \ - *(guint32 *) p = hi; \ - p += 6; \ - *(guint32 *) p = lo; \ - } while (0) - -#endif /* __MONO_SUPPORT_S390X_H__ */ diff --git a/src/mono/mono/mini/tramp-s390x.c b/src/mono/mono/mini/tramp-s390x.c index 9634169..d035295 100644 --- a/src/mono/mono/mini/tramp-s390x.c +++ b/src/mono/mono/mini/tramp-s390x.c @@ -50,7 +50,6 @@ #include "mini.h" #include "mini-s390x.h" #include "mini-runtime.h" -#include "support-s390x.h" #include "jit-icalls.h" #include "debugger-agent.h" #include "mono/utils/mono-tls-inline.h" @@ -245,43 +244,75 @@ mono_arch_create_sdb_trampoline (gboolean single_step, MonoTrampInfo **info, gbo return buf; } -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_patch_callsite */ -/* */ -/* Function - Patch a non-virtual callsite so it calls @addr. */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Locate the address of the thunk target + * + * @param[in] @code - Instruction following the branch and save + * @returns Address of the thunk code + * + * A thunk call is a sequence of: + * lgrl rx,tgt Load address of target (.-6) + * basr rx,rx Branch and save to that address (.), or, + * br r1 Jump to target (.) + * + * The target of that code is a thunk which: + * tgt: .quad target Destination + */ + +guint8 * +mono_arch_get_call_target (guint8 *code) +{ + guint8 *thunk; + guint32 rel; + + /* + * Determine thunk address by adding the relative offset + * in the lgrl to its location + */ + rel = *(guint32 *) ((uintptr_t) code - 4); + thunk = (guint8 *) ((uintptr_t) code - 6) + (rel * 2); + + return(thunk); +} + +/*========================= End of Function ========================*/ + +/** + * + * @brief Patch the callsite + * + * @param[in] @method_start - first instruction of method + * @param[in] @orig_code - Instruction following the branch and save + * @param[in] @addr - New value for target of call + * + * Patch a call. The call is either a 'thunked' call identified by the BASR R14,R14 + * instruction or a direct call + */ void mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr) { - gint32 displace; - unsigned short opcode; - - opcode = *((unsigned short *) (orig_code - 2)); - if (opcode == 0x0dee) { - /* This should be a 'iihf/iilf' sequence */ - S390_EMIT_CALL((orig_code - 14), addr); - mono_arch_flush_icache (orig_code - 14, 12); - } else { - /* This is the 'brasl' instruction */ - orig_code -= 4; - displace = ((gssize) addr - (gssize) (orig_code - 2)) / 2; - s390_patch_rel (orig_code, displace); - mono_arch_flush_icache (orig_code, 4); - } + guint64 *thunk; + + thunk = (guint64 *) mono_arch_get_call_target(orig_code - 2); + *thunk = (guint64) addr; } /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_patch_plt_entry. */ -/* */ -/* Function - Patch a PLT entry - unused as yet. */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Patch PLT entry (AOT only) + * + * @param[in] @code - Location of PLT + * @param[in] @got - Global Offset Table + * @param[in] @regs - Registers at the time + * @param[in] @addr - Target address + * + * Not reached on s390x until we have AOT support + * + */ void mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guint8 *addr) @@ -291,14 +322,17 @@ mono_arch_patch_plt_entry (guint8 *code, gpointer *got, host_mgreg_t *regs, guin /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_create_trampoline_code */ -/* */ -/* Function - Create the designated type of trampoline according*/ -/* to the 'tramp_type' parameter. */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Architecture-specific trampoline creation + * + * @param[in] @tramp_type - Type of trampoline + * @param[out] @info - Pointer to trampoline information + * @param[in] @aot - AOT indicator + * + * Create a generic trampoline + * + */ guchar* mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInfo **info, gboolean aot) @@ -520,13 +554,16 @@ mono_arch_create_generic_trampoline (MonoTrampolineType tramp_type, MonoTrampInf /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_invalidate_method */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Architecture-specific method invalidation + * + * @param[in] @func - Function to call + * @param[in] @func_arg - Argument to invalidation function + * + * Call an error routine so peple can fix their code + * + */ void mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) @@ -542,13 +579,18 @@ mono_arch_invalidate_method (MonoJitInfo *ji, void *func, gpointer func_arg) /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_create_specific_trampoline */ -/* */ -/* Function - Creates the given kind of specific trampoline */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Architecture-specific specific trampoline creation + * + * @param[in] @arg1 - Argument to trampoline being created + * @param[in] @tramp_type - Trampoline type + * @param[in] @domain - Mono Domain + * @param[out] @code_len - Length of trampoline created + * + * Create the specified kind of trampoline + * + */ gpointer mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_type, MonoMemoryManager *mem_manager, guint32 *code_len) @@ -591,13 +633,17 @@ mono_arch_create_specific_trampoline (gpointer arg1, MonoTrampolineType tramp_ty /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_create_rgctx_lazy_fetch_trampoline */ -/* */ -/* Function - */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Architecture-specific RGCTX lazy fetch trampoline + * + * @param[in] @slot - Instance + * @param[out] @info - Mono Trampoline Information + * @param[in] @aot - AOT indicator + * + * Create the specified kind of trampoline + * + */ gpointer mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info, gboolean aot) @@ -714,14 +760,16 @@ mono_arch_create_rgctx_lazy_fetch_trampoline (guint32 slot, MonoTrampInfo **info /*========================= End of Function ========================*/ -/*------------------------------------------------------------------*/ -/* */ -/* Name - mono_arch_get_static_rgctx_trampoline */ -/* */ -/* Function - Create a trampoline which sets RGCTX_REG to ARG */ -/* then jumps to ADDR. */ -/* */ -/*------------------------------------------------------------------*/ +/** + * + * @brief Architecture-specific static RGCTX lazy fetch trampoline + * + * @param[in] @arg - Argument to trampoline being created + * @param[out] @addr - Target + * + * Create a trampoline which sets RGCTX_REG to ARG + * then jumps to ADDR. + */ gpointer mono_arch_get_static_rgctx_trampoline (MonoMemoryManager *mem_manager, gpointer arg, gpointer addr)