Skip to content

[Ppc64le] Added memory patch thunking for function calls #73616

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 8 commits into from
Aug 12, 2022
2 changes: 1 addition & 1 deletion src/mono/mono/mini/cpu-ppc.mdesc
Original file line number Diff line number Diff line change
Expand Up @@ -348,4 +348,4 @@ atomic_cas_i4: src1:b src2:i src3:i dest:i len:38

liverange_start: len:0
liverange_end: len:0
gc_safe_point: clob:c src1:i len:40
gc_safe_point: clob:c src1:i len:44
2 changes: 1 addition & 1 deletion src/mono/mono/mini/cpu-ppc64.mdesc
Original file line number Diff line number Diff line change
Expand Up @@ -417,4 +417,4 @@ atomic_cas_i8: src1:b src2:i src3:i dest:i len:38

liverange_start: len:0
liverange_end: len:0
gc_safe_point: clob:c src1:i len:40
gc_safe_point: clob:c src1:i len:44
64 changes: 61 additions & 3 deletions src/mono/mono/mini/mini-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -311,7 +311,12 @@ mono_ppc_is_direct_call_sequence (guint32 *code)
if (ppc_opcode (code [-2]) == 24 && ppc_opcode (code [-3]) == 31) /* mr/nop */
return is_load_sequence (&code [-8]);
else
#if !defined(PPC_USES_FUNCTION_DESCRIPTOR)
/* the memory patch thunk sequence for ppc64le is: lis/ori/sldi/oris/ori/ld/mtlr/blrl */
return is_load_sequence (&code [-7]);
#else
return is_load_sequence (&code [-6]);
#endif
}
return FALSE;
#else
Expand Down Expand Up @@ -2692,6 +2697,10 @@ emit_float_to_int (MonoCompile *cfg, guchar *code, int dreg, int sreg, int size,
static void
emit_thunk (guint8 *code, gconstpointer target)
{
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
*(guint64*)code = (guint64)target;
code += sizeof (guint64);
#else
guint8 *p = code;

/* 2 bytes on 32bit, 5 bytes on 64bit */
Expand All @@ -2701,6 +2710,7 @@ emit_thunk (guint8 *code, gconstpointer target)
ppc_bcctr (code, PPC_BR_ALWAYS, 0);

mono_arch_flush_icache (p, code - p);
#endif
}

static void
Expand Down Expand Up @@ -2731,9 +2741,14 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target)
}

g_assert (*(guint32*)thunks == 0);


emit_thunk (thunks, target);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_load_ptr_sequence (code, PPC_CALL_REG, thunks);
#else
ppc_patch (code, thunks);

#endif
cfg->arch.thunks += THUNK_SIZE;
cfg->arch.thunks_size -= THUNK_SIZE;
} else {
Expand All @@ -2753,7 +2768,9 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target)
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 {
}
#if (defined(TARGET_POWERPC64) && defined(PPC_USES_FUNCTION_DESCRIPTOR)) || !defined(TARGET_POWERPC64)
else {
for (p = thunks; p < thunks + thunks_size; p += THUNK_SIZE) {
if (((guint32 *) p) [0] == 0) {
/* Free entry */
Expand All @@ -2777,7 +2794,7 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target)
}
}
}

#endif
// g_print ("THUNK: %p %p %p\n", code, target, target_thunk);

if (!target_thunk) {
Expand All @@ -2787,7 +2804,9 @@ handle_thunk (MonoCompile *cfg, guchar *code, const guchar *target)
}

emit_thunk (target_thunk, target);
#if (defined(TARGET_POWERPC64) && defined(PPC_USES_FUNCTION_DESCRIPTOR)) || !defined(TARGET_POWERPC64)
ppc_patch (code, target_thunk);
#endif

mono_mini_arch_unlock ();
}
Expand Down Expand Up @@ -2875,6 +2894,9 @@ ppc_patch_full (MonoCompile *cfg, guchar *code, const guchar *target, gboolean i

if (prim == 15 || ins == 0x4e800021 || ins == 0x4e800020 || ins == 0x4e800420) {
#ifdef TARGET_POWERPC64
#if !defined(PPC_USES_FUNCTION_DESCRIPTOR)
handle_thunk (cfg, code, target);
#else
guint32 *seq = (guint32*)code;
guint32 *branch_ins;

Expand Down Expand Up @@ -2923,6 +2945,7 @@ ppc_patch_full (MonoCompile *cfg, guchar *code, const guchar *target, gboolean i
ppc_load_ptr_sequence (code, PPC_CALL_REG, target);
#endif
mono_arch_flush_icache ((guint8*)seq, 28);
#endif
#else
guint32 *seq;
/* the trampoline code will try to patch the blrl, blr, bcctr */
Expand Down Expand Up @@ -3349,6 +3372,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
mono_add_patch_info (cfg, code - cfg->native_code, MONO_PATCH_INFO_JIT_ICALL_ID, GUINT_TO_POINTER (MONO_JIT_ICALL_mono_break));
if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtlr (code, PPC_CALL_REG);
ppc_blrl (code);
} else {
Expand Down Expand Up @@ -3794,7 +3821,14 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
ppc_mtctr (code, ppc_r0);
ppc_bcctr (code, PPC_BR_ALWAYS, 0);
} else {
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_load_func (code, PPC_CALL_REG, 0);
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
ppc_mtctr (code, PPC_CALL_REG);
ppc_bcctr (code, PPC_BR_ALWAYS, 0);
#else
ppc_b (code, 0);
#endif
}
break;
}
Expand Down Expand Up @@ -3823,6 +3857,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
mono_call_add_patch_info (cfg, call, offset);
if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtlr (code, PPC_CALL_REG);
ppc_blrl (code);
} else {
Expand Down Expand Up @@ -3926,6 +3964,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
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));
if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtlr (code, PPC_CALL_REG);
ppc_blrl (code);
} else {
Expand All @@ -3940,6 +3982,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
GUINT_TO_POINTER (MONO_JIT_ICALL_mono_arch_rethrow_exception));
if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtlr (code, PPC_CALL_REG);
ppc_blrl (code);
} else {
Expand Down Expand Up @@ -4584,6 +4630,10 @@ mono_arch_output_basic_block (MonoCompile *cfg, MonoBasicBlock *bb)
GUINT_TO_POINTER (MONO_JIT_ICALL_mono_threads_state_poll));
if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtlr (code, PPC_CALL_REG);
ppc_blrl (code);
} else {
Expand Down Expand Up @@ -5185,6 +5235,10 @@ mono_arch_emit_prolog (MonoCompile *cfg)
GUINT_TO_POINTER (MONO_JIT_ICALL_mono_tls_get_lmf_addr_extern));
if ((FORCE_INDIR_CALL || cfg->method->dynamic) && !cfg->compile_aot) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtlr (code, PPC_CALL_REG);
ppc_blrl (code);
} else {
Expand Down Expand Up @@ -5466,6 +5520,10 @@ mono_arch_emit_exceptions (MonoCompile *cfg)
patch_info->ip.i = code - cfg->native_code;
if (FORCE_INDIR_CALL || cfg->method->dynamic) {
ppc_load_func (code, PPC_CALL_REG, 0);
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
ppc_ldr (code, PPC_CALL_REG, 0, PPC_CALL_REG);
cfg->thunk_area += THUNK_SIZE;
#endif
ppc_mtctr (code, PPC_CALL_REG);
ppc_bcctr (code, PPC_BR_ALWAYS, 0);
} else {
Expand Down
12 changes: 10 additions & 2 deletions src/mono/mono/mini/mini-ppc.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,16 @@
#define MONO_ARCH_CODE_ALIGNMENT 32

#ifdef TARGET_POWERPC64
#if !defined(PPC_USES_FUNCTION_DESCRIPTOR)
#define THUNK_SIZE 8
#define GET_MEMORY_SLOT_THUNK_ADDRESS(c) \
((guint64)(((c)) [0] & 0x0000ffff) << 48) \
+ ((guint64)(((c)) [1] & 0x0000ffff) << 32) \
+ ((guint64)(((c)) [3] & 0x0000ffff) << 16) \
+ (guint64)(((c)) [4] & 0x0000ffff)
#else
#define THUNK_SIZE ((2 + 5) * 4)
#endif
#else
#define THUNK_SIZE ((2 + 2) * 4)
#endif
Expand Down Expand Up @@ -118,8 +127,7 @@ typedef struct MonoCompileArch {
#else
#define MONO_ARCH_CALLEE_FREGS (0xff << ppc_f1)
#endif
#define MONO_ARCH_CALLEE_SAVED_FREGS (~(MONO_ARCH_CALLEE_FRE
GS | 1))
#define MONO_ARCH_CALLEE_SAVED_FREGS (~(MONO_ARCH_CALLEE_FREGS | 1))

#ifdef TARGET_POWERPC64
#define MONO_ARCH_INST_FIXED_REG(desc) (((desc) == 'a')? ppc_r3: \
Expand Down
12 changes: 11 additions & 1 deletion src/mono/mono/mini/tramp-ppc.c
Original file line number Diff line number Diff line change
Expand Up @@ -669,7 +669,17 @@ mono_arch_get_call_target (guint8 *code)
guint8 *target = code - 4 + (disp * 4);

return target;
} else {
}
#if defined(TARGET_POWERPC64) && !defined(PPC_USES_FUNCTION_DESCRIPTOR)
else if (((guint32*)(code - 32)) [0] >> 26 == 15) {
guint8 *thunk = GET_MEMORY_SLOT_THUNK_ADDRESS((guint32*)(code - 32));
return thunk;
} else if (((guint32*)(code - 4)) [0] >> 26 == 15) {
guint8 *thunk = GET_MEMORY_SLOT_THUNK_ADDRESS((guint32*)(code - 4));
return thunk;
}
#endif
else {
return NULL;
}
}
Expand Down