diff options
author | Rodrigo Kumpera <kumpera@users.noreply.github.com> | 2017-02-23 01:20:17 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2017-02-23 01:20:17 +0300 |
commit | 0c07e908c50f946b26c07385036a1db553314ae7 (patch) | |
tree | 0fd690e165aa8d5de4674b5e34528283443255d4 | |
parent | 2f2562bed82a36361a041074422cd0647f2eba49 (diff) | |
parent | fe6d9dd2124ca33afde79169222dab83dc882efc (diff) |
Merge pull request #4352 from evincarofautumn/fix-xmm-scanning-mac-4.2mono-4.2.0-branch
Backport Mac 64 SIMD fixes to 4.2
-rw-r--r-- | mono/metadata/sgen-os-mach.c | 11 | ||||
-rw-r--r-- | mono/mini/mini-darwin.c | 11 | ||||
-rw-r--r-- | mono/utils/mach-support-amd64.c | 36 | ||||
-rw-r--r-- | mono/utils/mach-support-arm.c | 28 | ||||
-rw-r--r-- | mono/utils/mach-support-unknown.c | 19 | ||||
-rw-r--r-- | mono/utils/mach-support-x86.c | 61 | ||||
-rw-r--r-- | mono/utils/mach-support.h | 10 | ||||
-rw-r--r-- | mono/utils/mono-context.c | 40 | ||||
-rw-r--r-- | mono/utils/mono-context.h | 160 | ||||
-rw-r--r-- | mono/utils/mono-sigcontext.h | 21 | ||||
-rw-r--r-- | mono/utils/mono-threads-mach.c | 19 |
11 files changed, 338 insertions, 78 deletions
diff --git a/mono/metadata/sgen-os-mach.c b/mono/metadata/sgen-os-mach.c index eee4d837d3f..c57b06179c4 100644 --- a/mono/metadata/sgen-os-mach.c +++ b/mono/metadata/sgen-os-mach.c @@ -49,8 +49,8 @@ sgen_resume_thread (SgenThreadInfo *info) gboolean sgen_suspend_thread (SgenThreadInfo *info) { - mach_msg_type_number_t num_state; - thread_state_t state; + mach_msg_type_number_t num_state, num_fpstate; + thread_state_t state, fpstate; kern_return_t ret; ucontext_t ctx; mcontext_t mctx; @@ -58,17 +58,20 @@ sgen_suspend_thread (SgenThreadInfo *info) gpointer stack_start; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); + fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); ret = thread_suspend (info->client_info.info.native_handle); if (ret != KERN_SUCCESS) return FALSE; - ret = mono_mach_arch_get_thread_state (info->client_info.info.native_handle, state, &num_state); + do { + ret = mono_mach_arch_get_thread_states (info->client_info.info.native_handle, state, &num_state, fpstate, &num_fpstate); + } while (ret == KERN_ABORTED); if (ret != KERN_SUCCESS) return FALSE; - mono_mach_arch_thread_state_to_mcontext (state, mctx); + mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx); ctx.uc_mcontext = mctx; info->client_info.stopped_domain = mono_thread_info_tls_get (info, TLS_KEY_DOMAIN); diff --git a/mono/mini/mini-darwin.c b/mono/mini/mini-darwin.c index 9c1e46ed829..f07fc5ea01c 100644 --- a/mono/mini/mini-darwin.c +++ b/mono/mini/mini-darwin.c @@ -298,8 +298,8 @@ gboolean mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo *info) { kern_return_t ret; - mach_msg_type_number_t num_state; - thread_state_t state; + mach_msg_type_number_t num_state, num_fpstate; + thread_state_t state, fpstate; ucontext_t ctx; mcontext_t mctx; MonoJitTlsData *jit_tls; @@ -315,13 +315,16 @@ mono_thread_state_init_from_handle (MonoThreadUnwindState *tctx, MonoThreadInfo tctx->unwind_data [MONO_UNWIND_DATA_JIT_TLS] = NULL; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); + fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); - ret = mono_mach_arch_get_thread_state (info->native_handle, state, &num_state); + do { + ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate); + } while (ret == KERN_ABORTED); if (ret != KERN_SUCCESS) return FALSE; - mono_mach_arch_thread_state_to_mcontext (state, mctx); + mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx); ctx.uc_mcontext = mctx; mono_sigctx_to_monoctx (&ctx, &tctx->ctx); diff --git a/mono/utils/mach-support-amd64.c b/mono/utils/mach-support-amd64.c index 7944e2c986b..42a66d541ce 100644 --- a/mono/utils/mach-support-amd64.c +++ b/mono/utils/mach-support-amd64.c @@ -56,21 +56,23 @@ mono_mach_arch_get_mcontext_size () } void -mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) +mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context) { x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state; + x86_float_state64_t *arch_fpstate = (x86_float_state64_t *) fpstate; struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context; - ctx->__ss = *arch_state; + ctx->__fs = *arch_fpstate; } void -mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) +mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate) { x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state; + x86_float_state64_t *arch_fpstate = (x86_float_state64_t *) fpstate; struct __darwin_mcontext64 *ctx = (struct __darwin_mcontext64 *) context; - *arch_state = ctx->__ss; + *arch_fpstate = ctx->__fs; } int @@ -79,23 +81,39 @@ mono_mach_arch_get_thread_state_size () return sizeof (x86_thread_state64_t); } +int +mono_mach_arch_get_thread_fpstate_size () +{ + return sizeof (x86_float_state64_t); +} + kern_return_t -mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count) +mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) { - x86_thread_state64_t *arch_state = (x86_thread_state64_t *) state; + x86_thread_state64_t *arch_state = (x86_thread_state64_t *)state; + x86_float_state64_t *arch_fpstate = (x86_float_state64_t *)fpstate; kern_return_t ret; *count = x86_THREAD_STATE64_COUNT; + *fpcount = x86_FLOAT_STATE64_COUNT; - ret = thread_get_state (thread, x86_THREAD_STATE64, (thread_state_t) arch_state, count); + ret = thread_get_state (thread, x86_THREAD_STATE64, (thread_state_t)arch_state, count); + if (ret != KERN_SUCCESS) + return ret; + ret = thread_get_state (thread, x86_FLOAT_STATE64, (thread_state_t)arch_fpstate, fpcount); return ret; } kern_return_t -mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count) +mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount) { - return thread_set_state (thread, x86_THREAD_STATE64, state, count); + kern_return_t ret; + ret = thread_set_state (thread, x86_THREAD_STATE64, state, count); + if (ret != KERN_SUCCESS) + return ret; + ret = thread_set_state (thread, x86_FLOAT_STATE64, fpstate, fpcount); + return ret; } void * diff --git a/mono/utils/mach-support-arm.c b/mono/utils/mach-support-arm.c index cdf701cd8f4..9e04ddc508c 100644 --- a/mono/utils/mach-support-arm.c +++ b/mono/utils/mach-support-arm.c @@ -82,7 +82,7 @@ mono_mach_arch_get_mcontext_size () } void -mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) +mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context) { #ifdef TARGET_ARM64 arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; @@ -98,7 +98,7 @@ mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) } void -mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) +mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate) { #ifdef TARGET_ARM64 arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; @@ -113,6 +113,20 @@ mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) #endif } +void +mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context) +{ + int i; + arm_thread_state_t *arch_state = (arm_thread_state_t *) state; + for (i = 0; i < 13; ++i) + context->regs [i] = arch_state->__r [i]; + context->regs [ARMREG_R13] = arch_state->__sp; + context->regs [ARMREG_R14] = arch_state->__lr; + context->regs [ARMREG_R15] = arch_state->__pc; + context->pc = arch_state->__pc; + context->cpsr = arch_state->__cpsr; +} + int mono_mach_arch_get_thread_state_size () { @@ -123,8 +137,14 @@ mono_mach_arch_get_thread_state_size () #endif } +int +mono_mach_arch_get_thread_fpstate_size () +{ + return sizeof (arm_neon_state_t); +} + kern_return_t -mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count) +mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) { #ifdef TARGET_ARM64 arm_unified_thread_state_t *arch_state = (arm_unified_thread_state_t *) state; @@ -145,7 +165,7 @@ mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mac } kern_return_t -mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count) +mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount) { #ifdef TARGET_ARM64 return thread_set_state (thread, ARM_UNIFIED_THREAD_STATE, state, count); diff --git a/mono/utils/mach-support-unknown.c b/mono/utils/mach-support-unknown.c index 9fece227216..88eb187da44 100644 --- a/mono/utils/mach-support-unknown.c +++ b/mono/utils/mach-support-unknown.c @@ -35,17 +35,22 @@ mono_mach_arch_get_mcontext_size () } void -mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) +mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context) { g_assert_not_reached (); } void -mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) +mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate) { g_assert_not_reached (); } +void +mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context) +{ + g_assert_not_reached (); +} int mono_mach_arch_get_thread_state_size () @@ -53,14 +58,20 @@ mono_mach_arch_get_thread_state_size () g_assert_not_reached (); } +int +mono_mach_arch_get_thread_fpstate_size () +{ + g_assert_not_reached (); +} + kern_return_t -mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count) +mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) { g_assert_not_reached (); } kern_return_t -mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count) +mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount) { g_assert_not_reached (); } diff --git a/mono/utils/mach-support-x86.c b/mono/utils/mach-support-x86.c index 967aeb7abcf..7535b253a4b 100644 --- a/mono/utils/mach-support-x86.c +++ b/mono/utils/mach-support-x86.c @@ -16,6 +16,9 @@ #include "utils/mono-sigcontext.h" #include "mach-support.h" +// For reg numbers +#include <mono/arch/amd64/amd64-codegen.h> + /* Known offsets used for TLS storage*/ /* All OSX versions up to 10.8 */ @@ -55,21 +58,47 @@ mono_mach_arch_get_mcontext_size () } void -mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context) +mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context) { x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; + x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate; struct __darwin_mcontext32 *ctx = (struct __darwin_mcontext32 *) context; - ctx->__ss = *arch_state; + ctx->__fs = *arch_fpstate; } void -mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state) +mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate) { x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; + x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate; struct __darwin_mcontext32 *ctx = (struct __darwin_mcontext32 *) context; - *arch_state = ctx->__ss; + *arch_fpstate = ctx->__fs; +} + +void +mono_mach_arch_thread_states_to_mono_context (thread_state_t state, thread_state_t fpstate, MonoContext *context) +{ + x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; + x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) state; + context->eax = arch_state->__eax; + context->ebx = arch_state->__ebx; + context->ecx = arch_state->__ecx; + context->edx = arch_state->__edx; + context->ebp = arch_state->__ebp; + context->esp = arch_state->__esp; + context->esi = arch_state->__edi; + context->edi = arch_state->__esi; + context->eip = arch_state->__eip; + context->fregs [X86_XMM0] = arch_fpstate->__fpu_xmm0; + context->fregs [X86_XMM1] = arch_fpstate->__fpu_xmm1; + context->fregs [X86_XMM2] = arch_fpstate->__fpu_xmm2; + context->fregs [X86_XMM3] = arch_fpstate->__fpu_xmm3; + context->fregs [X86_XMM4] = arch_fpstate->__fpu_xmm4; + context->fregs [X86_XMM5] = arch_fpstate->__fpu_xmm5; + context->fregs [X86_XMM6] = arch_fpstate->__fpu_xmm6; + context->fregs [X86_XMM7] = arch_fpstate->__fpu_xmm7; } int @@ -78,23 +107,39 @@ mono_mach_arch_get_thread_state_size () return sizeof (x86_thread_state32_t); } +int +mono_mach_arch_get_thread_fpstate_size () +{ + return sizeof (x86_float_state32_t); +} + kern_return_t -mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count) +mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount) { x86_thread_state32_t *arch_state = (x86_thread_state32_t *) state; + x86_float_state32_t *arch_fpstate = (x86_float_state32_t *) fpstate; kern_return_t ret; *count = x86_THREAD_STATE32_COUNT; + *fpcount = x86_FLOAT_STATE32_COUNT; - ret = thread_get_state (thread, x86_THREAD_STATE32, (thread_state_t) arch_state, count); + ret = thread_get_state (thread, x86_THREAD_STATE32, (thread_state_t)arch_state, count); + if (ret != KERN_SUCCESS) + return ret; + ret = thread_get_state (thread, x86_FLOAT_STATE32, (thread_state_t)arch_fpstate, fpcount); return ret; } kern_return_t -mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count) +mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount) { - return thread_set_state (thread, x86_THREAD_STATE32, state, count); + kern_return_t ret; + ret = thread_set_state (thread, x86_THREAD_STATE32, state, count); + if (ret != KERN_SUCCESS) + return ret; + ret = thread_set_state (thread, x86_FLOAT_STATE32, fpstate, fpcount); + return ret; } void * diff --git a/mono/utils/mach-support.h b/mono/utils/mach-support.h index 940cf0356a0..4ce00952c0a 100644 --- a/mono/utils/mach-support.h +++ b/mono/utils/mach-support.h @@ -28,14 +28,16 @@ void *mono_mach_arch_get_sp (thread_state_t state); void mono_mach_init (pthread_key_t key); int mono_mach_arch_get_mcontext_size (void); -void mono_mach_arch_thread_state_to_mcontext (thread_state_t state, void *context); -void mono_mach_arch_mcontext_to_thread_state (void *context, thread_state_t state); +void mono_mach_arch_thread_states_to_mcontext (thread_state_t state, thread_state_t fpstate, void *context); +void mono_mach_arch_mcontext_to_thread_states (void *context, thread_state_t state, thread_state_t fpstate); +/* FIXME: Should return size_t, not int. */ int mono_mach_arch_get_thread_state_size (void); +int mono_mach_arch_get_thread_fpstate_size (void); kern_return_t mono_mach_get_threads (thread_act_array_t *threads, guint32 *count); kern_return_t mono_mach_free_threads (thread_act_array_t threads, guint32 count); -kern_return_t mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count); -kern_return_t mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count); +kern_return_t mono_mach_arch_get_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count, thread_state_t fpstate, mach_msg_type_number_t *fpcount); +kern_return_t mono_mach_arch_set_thread_states (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count, thread_state_t fpstate, mach_msg_type_number_t fpcount); void *mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key); void *mono_mach_get_tls_address_from_thread (pthread_t thread, pthread_key_t key); diff --git a/mono/utils/mono-context.c b/mono/utils/mono-context.c index a05c7bab76d..c3c173518a3 100644 --- a/mono/utils/mono-context.c +++ b/mono/utils/mono-context.c @@ -163,6 +163,26 @@ mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx) mctx->gregs [AMD64_R14] = UCONTEXT_REG_R14 (ctx); mctx->gregs [AMD64_R15] = UCONTEXT_REG_R15 (ctx); mctx->gregs [AMD64_RIP] = UCONTEXT_REG_RIP (ctx); + +#ifdef UCONTEXT_REG_XMM + mctx->fregs [0] = UCONTEXT_REG_XMM0 (ctx); + mctx->fregs [1] = UCONTEXT_REG_XMM1 (ctx); + mctx->fregs [2] = UCONTEXT_REG_XMM2 (ctx); + mctx->fregs [3] = UCONTEXT_REG_XMM3 (ctx); + mctx->fregs [4] = UCONTEXT_REG_XMM4 (ctx); + mctx->fregs [5] = UCONTEXT_REG_XMM5 (ctx); + mctx->fregs [6] = UCONTEXT_REG_XMM6 (ctx); + mctx->fregs [7] = UCONTEXT_REG_XMM7 (ctx); + mctx->fregs [8] = UCONTEXT_REG_XMM8 (ctx); + mctx->fregs [9] = UCONTEXT_REG_XMM9 (ctx); + mctx->fregs [10] = UCONTEXT_REG_XMM10 (ctx); + mctx->fregs [11] = UCONTEXT_REG_XMM11 (ctx); + mctx->fregs [12] = UCONTEXT_REG_XMM12 (ctx); + mctx->fregs [13] = UCONTEXT_REG_XMM13 (ctx); + mctx->fregs [14] = UCONTEXT_REG_XMM14 (ctx); + mctx->fregs [15] = UCONTEXT_REG_XMM15 (ctx); +#endif + #elif defined(HOST_WIN32) CONTEXT *context = (CONTEXT*)sigctx; @@ -233,6 +253,26 @@ mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx) UCONTEXT_REG_R14 (ctx) = mctx->gregs [AMD64_R14]; UCONTEXT_REG_R15 (ctx) = mctx->gregs [AMD64_R15]; UCONTEXT_REG_RIP (ctx) = mctx->gregs [AMD64_RIP]; + +#ifdef UCONTEXT_REG_XMM + UCONTEXT_REG_XMM0 (ctx) = mctx->fregs [0]; + UCONTEXT_REG_XMM1 (ctx) = mctx->fregs [1]; + UCONTEXT_REG_XMM2 (ctx) = mctx->fregs [2]; + UCONTEXT_REG_XMM3 (ctx) = mctx->fregs [3]; + UCONTEXT_REG_XMM4 (ctx) = mctx->fregs [4]; + UCONTEXT_REG_XMM5 (ctx) = mctx->fregs [5]; + UCONTEXT_REG_XMM6 (ctx) = mctx->fregs [6]; + UCONTEXT_REG_XMM7 (ctx) = mctx->fregs [7]; + UCONTEXT_REG_XMM8 (ctx) = mctx->fregs [8]; + UCONTEXT_REG_XMM9 (ctx) = mctx->fregs [9]; + UCONTEXT_REG_XMM10 (ctx) = mctx->fregs [10]; + UCONTEXT_REG_XMM11 (ctx) = mctx->fregs [11]; + UCONTEXT_REG_XMM12 (ctx) = mctx->fregs [12]; + UCONTEXT_REG_XMM13 (ctx) = mctx->fregs [13]; + UCONTEXT_REG_XMM14 (ctx) = mctx->fregs [14]; + UCONTEXT_REG_XMM15 (ctx) = mctx->fregs [15]; +#endif + #elif defined(HOST_WIN32) CONTEXT *context = (CONTEXT*)sigctx; diff --git a/mono/utils/mono-context.h b/mono/utils/mono-context.h index 55d75bda44d..188c0b3f7a3 100644 --- a/mono/utils/mono-context.h +++ b/mono/utils/mono-context.h @@ -21,6 +21,13 @@ #include <ucontext.h> #endif +#define MONO_CONTEXT_OFFSET(field, index, field_type) \ + "i" (offsetof (MonoContext, field) + (index) * sizeof (field_type)) + +#if defined(__APPLE__) +typedef struct __darwin_xmm_reg MonoContextSimdReg; +#endif + /* * General notes about mono-context. * Each arch defines a MonoContext struct with all GPR regs + IP/PC. @@ -90,6 +97,8 @@ struct sigcontext { # define SC_ESI esi #endif +#include <mono/arch/x86/x86-codegen.h> + typedef struct { mgreg_t eax; mgreg_t ebx; @@ -100,6 +109,9 @@ typedef struct { mgreg_t esi; mgreg_t edi; mgreg_t eip; +#ifdef __APPLE__ + MonoContextSimdReg fregs [X86_XMM_NREG]; +#endif } MonoContext; #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->eip = (mgreg_t)(ip); } while (0); @@ -132,18 +144,26 @@ typedef struct { #else #define MONO_CONTEXT_GET_CURRENT(ctx) \ __asm__ __volatile__( \ - "movl $0x0, 0x00(%0)\n" \ - "mov %%ebx, 0x04(%0)\n" \ - "mov %%ecx, 0x08(%0)\n" \ - "mov %%edx, 0x0c(%0)\n" \ - "mov %%ebp, 0x10(%0)\n" \ - "mov %%esp, 0x14(%0)\n" \ - "mov %%esi, 0x18(%0)\n" \ - "mov %%edi, 0x1c(%0)\n" \ + "movl $0x0, %c[eax](%0)\n" \ + "mov %%ebx, %c[ebx](%0)\n" \ + "mov %%ecx, %c[ecx](%0)\n" \ + "mov %%edx, %c[edx](%0)\n" \ + "mov %%ebp, %c[ebp](%0)\n" \ + "mov %%esp, %c[esp](%0)\n" \ + "mov %%esi, %c[esi](%0)\n" \ + "mov %%edi, %c[edi](%0)\n" \ "call 1f\n" \ "1: pop 0x20(%0)\n" \ : \ - : "a" (&(ctx)) \ + : "a" (&(ctx)), \ + [eax] MONO_CONTEXT_OFFSET (eax, 0, mgreg_t), \ + [ebx] MONO_CONTEXT_OFFSET (ebx, 0, mgreg_t), \ + [ecx] MONO_CONTEXT_OFFSET (ecx, 0, mgreg_t), \ + [edx] MONO_CONTEXT_OFFSET (edx, 0, mgreg_t), \ + [ebp] MONO_CONTEXT_OFFSET (ebp, 0, mgreg_t), \ + [esp] MONO_CONTEXT_OFFSET (esp, 0, mgreg_t), \ + [esi] MONO_CONTEXT_OFFSET (esi, 0, mgreg_t), \ + [edi] MONO_CONTEXT_OFFSET (edi, 0, mgreg_t) \ : "memory") #endif @@ -163,7 +183,11 @@ typedef struct { typedef struct { mgreg_t gregs [AMD64_NREG]; +#ifdef __APPLE__ + MonoContextSimdReg fregs [AMD64_XMM_NREG]; +#else double fregs [AMD64_XMM_NREG]; +#endif } MonoContext; #define MONO_CONTEXT_SET_IP(ctx,ip) do { (ctx)->gregs [AMD64_RIP] = (mgreg_t)(ip); } while (0); @@ -204,30 +228,100 @@ extern void mono_context_get_current (void *); : "a" ((int64_t)&(ctx)) \ : "rdx", "memory") #else -#define MONO_CONTEXT_GET_CURRENT(ctx) \ - __asm__ __volatile__( \ - "movq $0x0, 0x00(%0)\n" \ - "movq %%rbx, 0x08(%0)\n" \ - "movq %%rcx, 0x10(%0)\n" \ - "movq %%rdx, 0x18(%0)\n" \ - "movq %%rbp, 0x20(%0)\n" \ - "movq %%rsp, 0x28(%0)\n" \ - "movq %%rsi, 0x30(%0)\n" \ - "movq %%rdi, 0x38(%0)\n" \ - "movq %%r8, 0x40(%0)\n" \ - "movq %%r9, 0x48(%0)\n" \ - "movq %%r10, 0x50(%0)\n" \ - "movq %%r11, 0x58(%0)\n" \ - "movq %%r12, 0x60(%0)\n" \ - "movq %%r13, 0x68(%0)\n" \ - "movq %%r14, 0x70(%0)\n" \ - "movq %%r15, 0x78(%0)\n" \ - /* "leaq (%%rip), %%rdx\n" is not understood by icc */ \ - ".byte 0x48, 0x8d, 0x15, 0x00, 0x00, 0x00, 0x00\n" \ - "movq %%rdx, 0x80(%0)\n" \ - : \ - : "a" (&(ctx)) \ - : "rdx", "memory") + +#define MONO_CONTEXT_GET_CURRENT_GREGS(ctx) \ + do { \ + __asm__ __volatile__( \ + "movq $0x0, %c[rax](%0)\n" \ + "movq %%rcx, %c[rcx](%0)\n" \ + "movq %%rdx, %c[rdx](%0)\n" \ + "movq %%rbx, %c[rbx](%0)\n" \ + "movq %%rsp, %c[rsp](%0)\n" \ + "movq %%rbp, %c[rbp](%0)\n" \ + "movq %%rsi, %c[rsi](%0)\n" \ + "movq %%rdi, %c[rdi](%0)\n" \ + "movq %%r8, %c[r8](%0)\n" \ + "movq %%r9, %c[r9](%0)\n" \ + "movq %%r10, %c[r10](%0)\n" \ + "movq %%r11, %c[r11](%0)\n" \ + "movq %%r12, %c[r12](%0)\n" \ + "movq %%r13, %c[r13](%0)\n" \ + "movq %%r14, %c[r14](%0)\n" \ + "movq %%r15, %c[r15](%0)\n" \ + /* "leaq (%%rip), %%rdx\n" is not understood by icc */ \ + ".byte 0x48, 0x8d, 0x15, 0x00, 0x00, 0x00, 0x00\n" \ + "movq %%rdx, %c[rip](%0)\n" \ + : \ + : "a" (&(ctx)), \ + [rax] MONO_CONTEXT_OFFSET (gregs, AMD64_RAX, mgreg_t), \ + [rcx] MONO_CONTEXT_OFFSET (gregs, AMD64_RCX, mgreg_t), \ + [rdx] MONO_CONTEXT_OFFSET (gregs, AMD64_RDX, mgreg_t), \ + [rbx] MONO_CONTEXT_OFFSET (gregs, AMD64_RBX, mgreg_t), \ + [rsp] MONO_CONTEXT_OFFSET (gregs, AMD64_RSP, mgreg_t), \ + [rbp] MONO_CONTEXT_OFFSET (gregs, AMD64_RBP, mgreg_t), \ + [rsi] MONO_CONTEXT_OFFSET (gregs, AMD64_RSI, mgreg_t), \ + [rdi] MONO_CONTEXT_OFFSET (gregs, AMD64_RDI, mgreg_t), \ + [r8] MONO_CONTEXT_OFFSET (gregs, AMD64_R8, mgreg_t), \ + [r9] MONO_CONTEXT_OFFSET (gregs, AMD64_R9, mgreg_t), \ + [r10] MONO_CONTEXT_OFFSET (gregs, AMD64_R10, mgreg_t), \ + [r11] MONO_CONTEXT_OFFSET (gregs, AMD64_R11, mgreg_t), \ + [r12] MONO_CONTEXT_OFFSET (gregs, AMD64_R12, mgreg_t), \ + [r13] MONO_CONTEXT_OFFSET (gregs, AMD64_R13, mgreg_t), \ + [r14] MONO_CONTEXT_OFFSET (gregs, AMD64_R14, mgreg_t), \ + [r15] MONO_CONTEXT_OFFSET (gregs, AMD64_R15, mgreg_t), \ + [rip] MONO_CONTEXT_OFFSET (gregs, AMD64_RIP, mgreg_t) \ + : "rdx", "memory"); \ + } while (0) + +#ifdef UCONTEXT_REG_XMM +#define MONO_CONTEXT_GET_CURRENT_FREGS(ctx) \ + do { \ + __asm__ __volatile__ ( \ + "movups %%xmm0, %c[xmm0](%0)\n" \ + "movups %%xmm1, %c[xmm1](%0)\n" \ + "movups %%xmm2, %c[xmm2](%0)\n" \ + "movups %%xmm3, %c[xmm3](%0)\n" \ + "movups %%xmm4, %c[xmm4](%0)\n" \ + "movups %%xmm5, %c[xmm5](%0)\n" \ + "movups %%xmm6, %c[xmm6](%0)\n" \ + "movups %%xmm7, %c[xmm7](%0)\n" \ + "movups %%xmm8, %c[xmm8](%0)\n" \ + "movups %%xmm9, %c[xmm9](%0)\n" \ + "movups %%xmm10, %c[xmm10](%0)\n" \ + "movups %%xmm11, %c[xmm11](%0)\n" \ + "movups %%xmm12, %c[xmm12](%0)\n" \ + "movups %%xmm12, %c[xmm12](%0)\n" \ + "movups %%xmm14, %c[xmm14](%0)\n" \ + "movups %%xmm15, %c[xmm15](%0)\n" \ + : \ + : "a" (&(ctx)), \ + [xmm0] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM0, MonoContextSimdReg), \ + [xmm1] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM1, MonoContextSimdReg), \ + [xmm2] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM2, MonoContextSimdReg), \ + [xmm3] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM3, MonoContextSimdReg), \ + [xmm4] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM4, MonoContextSimdReg), \ + [xmm5] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM5, MonoContextSimdReg), \ + [xmm6] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM6, MonoContextSimdReg), \ + [xmm7] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM7, MonoContextSimdReg), \ + [xmm8] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM8, MonoContextSimdReg), \ + [xmm9] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM9, MonoContextSimdReg), \ + [xmm10] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM10, MonoContextSimdReg), \ + [xmm11] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM11, MonoContextSimdReg), \ + [xmm12] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM12, MonoContextSimdReg), \ + [xmm13] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM13, MonoContextSimdReg), \ + [xmm14] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM14, MonoContextSimdReg), \ + [xmm15] MONO_CONTEXT_OFFSET (fregs, AMD64_XMM15, MonoContextSimdReg)); \ + } while (0) +#else +#define MONO_CONTEXT_GET_CURRENT_FREGS(ctx) +#endif + +#define MONO_CONTEXT_GET_CURRENT(ctx) \ + do { \ + MONO_CONTEXT_GET_CURRENT_GREGS(ctx); \ + MONO_CONTEXT_GET_CURRENT_FREGS(ctx); \ + } while (0) + #endif #define MONO_ARCH_HAS_MONO_CONTEXT 1 diff --git a/mono/utils/mono-sigcontext.h b/mono/utils/mono-sigcontext.h index de4f6c45b75..6d47813802b 100644 --- a/mono/utils/mono-sigcontext.h +++ b/mono/utils/mono-sigcontext.h @@ -173,6 +173,23 @@ typedef struct ucontext { #define UCONTEXT_REG_R13(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r13) #define UCONTEXT_REG_R14(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r14) #define UCONTEXT_REG_R15(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__ss.__r15) + #define UCONTEXT_REG_XMM + #define UCONTEXT_REG_XMM0(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm0) + #define UCONTEXT_REG_XMM1(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm1) + #define UCONTEXT_REG_XMM2(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm2) + #define UCONTEXT_REG_XMM3(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm3) + #define UCONTEXT_REG_XMM4(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm4) + #define UCONTEXT_REG_XMM5(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm5) + #define UCONTEXT_REG_XMM6(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm6) + #define UCONTEXT_REG_XMM7(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm7) + #define UCONTEXT_REG_XMM8(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm8) + #define UCONTEXT_REG_XMM9(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm9) + #define UCONTEXT_REG_XMM10(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm10) + #define UCONTEXT_REG_XMM11(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm11) + #define UCONTEXT_REG_XMM12(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm12) + #define UCONTEXT_REG_XMM13(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm13) + #define UCONTEXT_REG_XMM14(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm14) + #define UCONTEXT_REG_XMM15(ctx) (((ucontext_t*)(ctx))->uc_mcontext->__fs.__fpu_xmm15) #elif defined(__FreeBSD__) || defined(__FreeBSD_kernel__) #define UCONTEXT_REG_RAX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rax) #define UCONTEXT_REG_RBX(ctx) (((ucontext_t*)(ctx))->uc_mcontext.mc_rbx) @@ -224,8 +241,8 @@ typedef struct ucontext { #define UCONTEXT_REG_R13(ctx) (((ucontext_t*)(ctx))->sc_r13) #define UCONTEXT_REG_R14(ctx) (((ucontext_t*)(ctx))->sc_r14) #define UCONTEXT_REG_R15(ctx) (((ucontext_t*)(ctx))->sc_r15) -#else -#define UCONTEXT_GREGS(ctx) ((guint64*)&(((ucontext_t*)(ctx))->uc_mcontext.gregs)) +#elif !defined(HOST_WIN32) + #define UCONTEXT_GREGS(ctx) ((guint64*)&(((ucontext_t*)(ctx))->uc_mcontext.gregs)) #endif #ifdef UCONTEXT_GREGS diff --git a/mono/utils/mono-threads-mach.c b/mono/utils/mono-threads-mach.c index fc884e7a055..66af94c24b1 100644 --- a/mono/utils/mono-threads-mach.c +++ b/mono/utils/mono-threads-mach.c @@ -116,8 +116,8 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) if (info->async_target) { MonoContext tmp = info->thread_saved_state [ASYNC_SUSPEND_STATE_INDEX].ctx; - mach_msg_type_number_t num_state; - thread_state_t state; + mach_msg_type_number_t num_state, num_fpstate; + thread_state_t state, fpstate; ucontext_t uctx; mcontext_t mctx; @@ -126,13 +126,17 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) info->async_target = (void (*)(void *)) info->user_data; state = (thread_state_t) alloca (mono_mach_arch_get_thread_state_size ()); + fpstate = (thread_state_t) alloca (mono_mach_arch_get_thread_fpstate_size ()); mctx = (mcontext_t) alloca (mono_mach_arch_get_mcontext_size ()); - ret = mono_mach_arch_get_thread_state (info->native_handle, state, &num_state); + do { + ret = mono_mach_arch_get_thread_states (info->native_handle, state, &num_state, fpstate, &num_fpstate); + } while (ret == KERN_ABORTED); + if (ret != KERN_SUCCESS) return FALSE; - mono_mach_arch_thread_state_to_mcontext (state, mctx); + mono_mach_arch_thread_states_to_mcontext (state, fpstate, mctx); #ifdef TARGET_ARM64 g_assert_not_reached (); #else @@ -140,9 +144,12 @@ mono_threads_core_begin_async_resume (MonoThreadInfo *info) #endif mono_monoctx_to_sigctx (&tmp, &uctx); - mono_mach_arch_mcontext_to_thread_state (mctx, state); + mono_mach_arch_mcontext_to_thread_states (mctx, state, fpstate); + + do { + ret = mono_mach_arch_set_thread_states (info->native_handle, state, num_state, fpstate, num_fpstate); + } while (ret == KERN_ABORTED); - ret = mono_mach_arch_set_thread_state (info->native_handle, state, num_state); if (ret != KERN_SUCCESS) return FALSE; } |