ntdll: Use assembly wrapper for unixlib calls on ARM64EC.

Instead of using indirect C calls, which need to go through the call dispatcher.
This commit is contained in:
Jacek Caban 2024-05-16 13:03:22 +02:00 committed by Alexandre Julliard
parent 127650c293
commit 434702fdc9
5 changed files with 62 additions and 2 deletions

View file

@ -1723,6 +1723,7 @@
@ stdcall __wine_ctrl_routine(ptr)
@ extern -private __wine_syscall_dispatcher
@ extern -private __wine_unix_call_dispatcher
@ extern -private -arch=arm64ec __wine_unix_call_dispatcher_arm64ec
@ extern -private __wine_unixlib_handle
# Debugging

View file

@ -2227,6 +2227,22 @@ ULONG WINAPI RtlWalkFrameChain( void **buffer, ULONG count, ULONG flags )
}
/*************************************************************************
* __wine_unix_call_arm64ec
*/
NTSTATUS __attribute__((naked)) __wine_unix_call_arm64ec( unixlib_handle_t handle, unsigned int code, void *args )
{
asm( ".seh_proc \"#__wine_unix_call_arm64ec\"\n\t"
".seh_endprologue\n\t"
"adrp x16, __wine_unix_call_dispatcher_arm64ec\n\t"
"ldr x16, [x16, #:lo12:__wine_unix_call_dispatcher_arm64ec]\n\t"
"br x16\n\t"
".seh_endproc" );
}
NTSTATUS (WINAPI *__wine_unix_call_dispatcher_arm64ec)( unixlib_handle_t, unsigned int, void * ) = __wine_unix_call_arm64ec;
static int code_match( BYTE *code, const BYTE *seq, size_t len )
{
for ( ; len; len--, code++, seq++) if (*seq && *code != *seq) return 0;
@ -2262,7 +2278,6 @@ void *check_call( void **target, void *exit_thunk, void *dest )
for (;;)
{
if (dest == __wine_unix_call_dispatcher) return dest;
if (RtlIsEcCode( (ULONG_PTR)dest )) return dest;
if (code_match( dest, jmp_sequence, sizeof(jmp_sequence) ))
{

View file

@ -1517,6 +1517,7 @@ static void load_ntdll_functions( HMODULE module )
{
void **p__wine_syscall_dispatcher;
void **p__wine_unix_call_dispatcher;
void **p__wine_unix_call_dispatcher_arm64ec = NULL;
unixlib_handle_t *p__wine_unixlib_handle;
const IMAGE_EXPORT_DIRECTORY *exports;
@ -1539,9 +1540,19 @@ static void load_ntdll_functions( HMODULE module )
GET_FUNC( __wine_syscall_dispatcher );
GET_FUNC( __wine_unix_call_dispatcher );
GET_FUNC( __wine_unixlib_handle );
if (is_arm64ec())
{
GET_FUNC( __wine_unix_call_dispatcher_arm64ec );
}
*p__wine_syscall_dispatcher = __wine_syscall_dispatcher;
*p__wine_unix_call_dispatcher = __wine_unix_call_dispatcher;
*p__wine_unixlib_handle = (UINT_PTR)unix_call_funcs;
if (p__wine_unix_call_dispatcher_arm64ec)
{
/* redirect __wine_unix_call_dispatcher to __wine_unix_call_dispatcher_arm64ec */
*p__wine_unix_call_dispatcher = *p__wine_unix_call_dispatcher_arm64ec;
*p__wine_unix_call_dispatcher_arm64ec = __wine_unix_call_dispatcher;
}
else *p__wine_unix_call_dispatcher = __wine_unix_call_dispatcher;
#undef GET_FUNC
}

View file

@ -64,6 +64,31 @@ static NTSTATUS WINAPI unix_call_init( unixlib_handle_t handle, unsigned int cod
unixlib_handle_t __wine_unixlib_handle = 0;
NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * ) = unix_call_init;
#ifdef __arm64ec__
static NTSTATUS WINAPI unix_call_init_arm64ec( unixlib_handle_t handle, unsigned int code, void *args );
static __attribute__((used)) NTSTATUS (WINAPI *__wine_unix_call_dispatcher_arm64ec)( unixlib_handle_t, unsigned int, void * ) = unix_call_init_arm64ec;
static NTSTATUS WINAPI unix_call_init_arm64ec( unixlib_handle_t handle, unsigned int code, void *args )
{
InterlockedExchangePointer( (void **)&__wine_unix_call_dispatcher_arm64ec,
get_dispatcher( "__wine_unix_call_dispatcher_arm64ec" ));
return __wine_unix_call_arm64ec( handle, code, args );
}
NTSTATUS __attribute__((naked)) __wine_unix_call_arm64ec( unixlib_handle_t handle, unsigned int code, void *args )
{
asm( ".seh_proc \"#__wine_unix_call_arm64ec\"\n\t"
".seh_endprologue\n\t"
"adrp x16, __wine_unix_call_dispatcher_arm64ec\n\t"
"ldr x16, [x16, #:lo12:__wine_unix_call_dispatcher_arm64ec]\n\t"
"br x16\n\t"
".seh_endproc" );
}
#endif
NTSTATUS WINAPI __wine_init_unix_call(void)
{
return NtQueryVirtualMemory( GetCurrentProcess(), image_base(), MemoryWineUnixFuncs,

View file

@ -262,10 +262,18 @@ extern unixlib_handle_t __wine_unixlib_handle;
extern NTSTATUS (WINAPI *__wine_unix_call_dispatcher)( unixlib_handle_t, unsigned int, void * );
extern NTSTATUS WINAPI __wine_init_unix_call(void);
#ifdef __arm64ec__
NTSTATUS __wine_unix_call_arm64ec( unixlib_handle_t handle, unsigned int code, void *args );
static inline NTSTATUS __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args )
{
return __wine_unix_call_arm64ec( handle, code, args );
}
#else
static inline NTSTATUS __wine_unix_call( unixlib_handle_t handle, unsigned int code, void *args )
{
return __wine_unix_call_dispatcher( handle, code, args );
}
#endif
#define WINE_UNIX_CALL(code,args) __wine_unix_call( __wine_unixlib_handle, (code), (args) )