1
0
Fork 0
mirror of https://github.com/VSadov/Satori.git synced 2025-06-10 18:11:04 +09:00

[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.
This commit is contained in:
Ulrich Weigand 2021-05-17 10:48:40 +02:00 committed by GitHub
parent f64f12aa83
commit 9cb0ab915e
Signed by: github
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 492 additions and 265 deletions

View file

@ -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;
}

View file

@ -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_RGCTX_FETCH:
case MONO_PATCH_INFO_ABS: {
S390_EMIT_CALL (ip, target);
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_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 ========================*/

View file

@ -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__ */

View file

@ -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__ */

View file

@ -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
*/
void
mono_arch_patch_callsite (guint8 *method_start, guint8 *orig_code, guint8 *addr)
guint8 *
mono_arch_get_call_target (guint8 *code)
{
gint32 displace;
unsigned short opcode;
guint8 *thunk;
guint32 rel;
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);
}
/*
* 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 ========================*/
/*------------------------------------------------------------------*/
/* */
/* Name - mono_arch_patch_plt_entry. */
/* */
/* Function - Patch a PLT entry - unused as yet. */
/* */
/*------------------------------------------------------------------*/
/**
*
* @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)
{
guint64 *thunk;
thunk = (guint64 *) mono_arch_get_call_target(orig_code - 2);
*thunk = (guint64) addr;
}
/*========================= End of Function ========================*/
/**
*
* @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)