Module: wine Branch: master Commit: 3bd8af0eb6a6d665ef6b3feb4dafe0d26e602aa1 URL: https://gitlab.winehq.org/wine/wine/-/commit/3bd8af0eb6a6d665ef6b3feb4dafe0d...
Author: Alexandre Julliard julliard@winehq.org Date: Tue Jul 16 12:25:37 2024 +0200
ntdll: Implement KiUserEmulationDispatcher on ARM64EC.
---
dlls/ntdll/ntdll.spec | 1 + dlls/ntdll/signal_arm64ec.c | 18 ++++++++++++++++++ dlls/ntdll/unix/loader.c | 3 +++ dlls/ntdll/unix/signal_arm64.c | 13 ++++++++++++- dlls/ntdll/unix/unix_private.h | 8 ++++++++ 5 files changed, 42 insertions(+), 1 deletion(-)
diff --git a/dlls/ntdll/ntdll.spec b/dlls/ntdll/ntdll.spec index 78afe2f49f5..85aa48eacb5 100644 --- a/dlls/ntdll/ntdll.spec +++ b/dlls/ntdll/ntdll.spec @@ -71,6 +71,7 @@ @ stdcall -norelay KiUserApcDispatcher(ptr long long long ptr) @ stdcall -norelay KiUserCallbackDispatcher(long ptr long) @ stdcall -norelay -arch=arm,arm64,arm64ec KiUserCallbackDispatcherReturn() +@ stdcall -norelay -arch=arm64ec KiUserEmulationDispatcher(ptr) @ stdcall -norelay KiUserExceptionDispatcher(ptr ptr) # @ stub LdrAccessOutOfProcessResource @ stdcall LdrAccessResource(long ptr ptr ptr) diff --git a/dlls/ntdll/signal_arm64ec.c b/dlls/ntdll/signal_arm64ec.c index 20eb5ff662e..e44ac9fc467 100644 --- a/dlls/ntdll/signal_arm64ec.c +++ b/dlls/ntdll/signal_arm64ec.c @@ -44,6 +44,7 @@ static void (WINAPI *pBTCpu64FlushInstructionCache)(const void*,SIZE_T); static BOOLEAN (WINAPI *pBTCpu64IsProcessorFeaturePresent)(UINT); static void (WINAPI *pBTCpu64NotifyMemoryDirty)(void*,SIZE_T); static void (WINAPI *pBTCpu64NotifyReadFile)(HANDLE,void*,SIZE_T,BOOL,NTSTATUS); +static void (WINAPI *pBeginSimulation)(void); static void (WINAPI *pFlushInstructionCacheHeavy)(const void*,SIZE_T); static NTSTATUS (WINAPI *pNotifyMapViewOfSection)(void*,void*,void*,SIZE_T,ULONG,ULONG); static void (WINAPI *pNotifyMemoryAlloc)(void*,SIZE_T,ULONG,ULONG,BOOL,NTSTATUS); @@ -157,6 +158,7 @@ NTSTATUS arm64ec_process_init( HMODULE module ) GET_PTR( BTCpu64IsProcessorFeaturePresent ); GET_PTR( BTCpu64NotifyMemoryDirty ); GET_PTR( BTCpu64NotifyReadFile ); + GET_PTR( BeginSimulation ); GET_PTR( FlushInstructionCacheHeavy ); GET_PTR( NotifyMapViewOfSection ); GET_PTR( NotifyMemoryAlloc ); @@ -1030,6 +1032,22 @@ NTSTATUS call_seh_handlers( EXCEPTION_RECORD *rec, CONTEXT *orig_context ) }
+/******************************************************************* + * KiUserEmulationDispatcher (NTDLL.@) + */ +void dispatch_emulation( ARM64_NT_CONTEXT *arm_ctx ) +{ + context_arm_to_x64( get_arm64ec_cpu_area()->ContextAmd64, arm_ctx ); + pBeginSimulation(); +} +__ASM_GLOBAL_FUNC( "#KiUserEmulationDispatcher", + ".seh_context\n\t" + ".seh_endprologue\n\t" + "mov x0, sp\n\t" /* context */ + "bl dispatch_emulation\n\t" + "brk #1" ) + + /******************************************************************* * KiUserExceptionDispatcher (NTDLL.@) */ diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 19fbfb2b68c..1267469bf37 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -111,6 +111,7 @@ void *pKiRaiseUserExceptionDispatcher = NULL; void *pKiUserExceptionDispatcher = NULL; void *pKiUserApcDispatcher = NULL; void *pKiUserCallbackDispatcher = NULL; +void *pKiUserEmulationDispatcher = NULL; void *pLdrInitializeThunk = NULL; void *pRtlUserThreadStart = NULL; void *p__wine_ctrl_routine = NULL; @@ -1576,6 +1577,7 @@ static void load_ntdll_functions( HMODULE module ) if (is_arm64ec()) { GET_FUNC( __wine_unix_call_dispatcher_arm64ec ); + GET_FUNC( KiUserEmulationDispatcher ); } *p__wine_syscall_dispatcher = __wine_syscall_dispatcher; *p__wine_unixlib_handle = (UINT_PTR)unix_call_funcs; @@ -1669,6 +1671,7 @@ static void redirect_ntdll_functions( HMODULE module ) REDIRECT( KiUserExceptionDispatcher ); REDIRECT( KiUserApcDispatcher ); REDIRECT( KiUserCallbackDispatcher ); + REDIRECT( KiUserEmulationDispatcher ); REDIRECT( LdrInitializeThunk ); REDIRECT( RtlUserThreadStart ); #undef REDIRECT diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c index 667bc1108cf..b54fa30a318 100644 --- a/dlls/ntdll/unix/signal_arm64.c +++ b/dlls/ntdll/unix/signal_arm64.c @@ -320,10 +320,21 @@ static void restore_context( const CONTEXT *context, ucontext_t *sigcontext ) */ NTSTATUS signal_set_full_context( CONTEXT *context ) { + struct syscall_frame *frame = arm64_thread_data()->syscall_frame; NTSTATUS status = NtSetContextThread( GetCurrentThread(), context );
if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) - arm64_thread_data()->syscall_frame->restore_flags |= CONTEXT_INTEGER; + frame->restore_flags |= CONTEXT_INTEGER; + + if (is_arm64ec() && !is_ec_code( frame->pc )) + { + CONTEXT *user_context = (CONTEXT *)((frame->sp - sizeof(CONTEXT)) & ~15); + + user_context->ContextFlags = CONTEXT_FULL; + NtGetContextThread( GetCurrentThread(), user_context ); + frame->sp = (ULONG_PTR)user_context; + frame->pc = (ULONG_PTR)pKiUserEmulationDispatcher; + } return status; }
diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index 6cd88a5acc0..91267f66e76 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -147,6 +147,7 @@ extern void *pKiRaiseUserExceptionDispatcher; extern void *pKiUserExceptionDispatcher; extern void *pKiUserApcDispatcher; extern void *pKiUserCallbackDispatcher; +extern void *pKiUserEmulationDispatcher; extern void *pLdrInitializeThunk; extern void *pRtlUserThreadStart; extern void *p__wine_ctrl_routine; @@ -415,6 +416,13 @@ static inline BOOL is_inside_signal_stack( void *ptr ) (char *)ptr < (char *)get_signal_stack() + signal_stack_size); }
+static inline BOOL is_ec_code( ULONG_PTR ptr ) +{ + const UINT64 *map = (const UINT64 *)peb->EcCodeBitMap; + ULONG_PTR page = ptr / page_size; + return (map[page / 64] >> (page & 63)) & 1; +} + static inline void mutex_lock( pthread_mutex_t *mutex ) { if (!process_exiting) pthread_mutex_lock( mutex );