Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion dlls/ntdll/ntdll_misc.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,7 +181,6 @@ extern IMAGE_ARM64EC_METADATA *arm64ec_get_module_metadata( HMODULE module );
extern void arm64ec_update_hybrid_metadata( void *module, IMAGE_NT_HEADERS *nt,
const IMAGE_ARM64EC_METADATA *metadata );
extern void invoke_arm64ec_syscall(void);
extern void arm64ec_suspend_point(void);

extern void *__os_arm64x_check_call;
extern void *__os_arm64x_check_icall;
Expand Down
1 change: 0 additions & 1 deletion dlls/ntdll/signal_arm64ec.c
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,6 @@ static inline BOOL enter_syscall_callback(void)
static inline void leave_syscall_callback(void)
{
get_arm64ec_cpu_area()->InSyscallCallback = 0;
if (get_arm64ec_cpu_area()->SuspendDoorbell && *get_arm64ec_cpu_area()->SuspendDoorbell) arm64ec_suspend_point();
}

/**********************************************************************
Expand Down
8 changes: 0 additions & 8 deletions dlls/ntdll/signal_x86_64.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,14 +74,6 @@ __ASM_GLOBAL_FUNC( invoke_arm64ec_syscall,
"pushq %r10\n\t" /* and return to syscall thunk */
"ret" )

/**************************************************************************
* arm64ec_suspend_point
*
* x64 stub to support cooperative suspend when leaving a syscall callack.
*/
__ASM_GLOBAL_FUNC( arm64ec_suspend_point,
"ret" )

/*******************************************************************
* KiUserExceptionDispatcher (NTDLL.@)
*/
Expand Down
61 changes: 26 additions & 35 deletions dlls/ntdll/unix/signal_arm64.c
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,6 @@ struct syscall_frame

C_ASSERT( sizeof( struct syscall_frame ) == 0x330 );

static BOOL is_arm64ec_suspend_doorbell_valid(void)
{
return is_arm64ec() && NtCurrentTeb()->ChpeV2CpuAreaInfo && NtCurrentTeb()->ChpeV2CpuAreaInfo->SuspendDoorbell;
}

/***********************************************************************
* context_init_empty_xstate
Expand All @@ -241,6 +237,7 @@ void set_process_instrumentation_callback( void *callback )
if (callback) FIXME( "Not supported.\n" );
}


/***********************************************************************
* syscall_frame_fixup_for_fastpath
*
Expand Down Expand Up @@ -347,20 +344,22 @@ static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
NTSTATUS signal_set_full_context( CONTEXT *context )
{
struct syscall_frame *frame = get_syscall_frame();
NTSTATUS status = NtSetContextThread( GetCurrentThread(), context );
struct arm64_thread_data *arm64_data = arm64_thread_data();
NTSTATUS status;

if (is_arm64ec_suspend_doorbell_valid() && arm64_thread_data()->suspend_pending)
if (arm64_data->suspend_pending)
{
CONTEXT suspend_context;
sigset_t old_set;
pthread_sigmask( SIG_BLOCK, &server_block_set, &old_set );
*NtCurrentTeb()->ChpeV2CpuAreaInfo->SuspendDoorbell = 0;
arm64_thread_data()->suspend_pending = FALSE;
suspend_context.ContextFlags = CONTEXT_FULL | CONTEXT_EXCEPTION_REPORTING; /* TODO: check */
NtGetContextThread( GetCurrentThread(), &suspend_context );
wait_suspend( &suspend_context );
NtSetContextThread( GetCurrentThread(), &suspend_context );
arm64_data->suspend_pending = FALSE;
wait_suspend( context );
status = NtSetContextThread( GetCurrentThread(), context );
pthread_sigmask( SIG_SETMASK, &old_set, NULL );
}
else status = NtSetContextThread( GetCurrentThread(), context );

if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER) /* TODO: also check with susp */
if (!status && (context->ContextFlags & CONTEXT_INTEGER) == CONTEXT_INTEGER)
frame->restore_flags |= CONTEXT_INTEGER;

if (is_arm64ec() && !is_ec_code( frame->pc ))
Expand Down Expand Up @@ -451,20 +450,12 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
{
struct syscall_frame *frame = get_syscall_frame();
DWORD needed_flags = context->ContextFlags & ~CONTEXT_ARM64;
THREAD_BASIC_INFORMATION info;
NTSTATUS ret;
BOOL self;

NtQueryInformationThread( handle, ThreadBasicInformation, &info, sizeof(info), NULL );
self = HandleToULong( info.ClientId.UniqueThread ) == GetCurrentThreadId();
BOOL self = (handle == GetCurrentThread());

if (!self)
{
/* Avoid exposing JIT code pointers to other processes on ARM64EC */
if (is_arm64ec()) NtSuspendThread( handle, NULL );
ret = get_thread_context( handle, context, &self, IMAGE_FILE_MACHINE_ARM64 );
if (is_arm64ec()) NtResumeThread( handle, NULL );
return ret;
NTSTATUS ret = get_thread_context( handle, context, &self, IMAGE_FILE_MACHINE_ARM64 );
if (ret || !self) return ret;
}

if (needed_flags & CONTEXT_INTEGER)
Expand Down Expand Up @@ -1345,17 +1336,20 @@ static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext )
static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext )
{
ucontext_t *ucontext = sigcontext;
CHPE_V2_CPU_AREA_INFO *chpe;
CONTEXT context;

if (is_arm64ec_suspend_doorbell_valid() &&
(NtCurrentTeb()->ChpeV2CpuAreaInfo->InSimulation || NtCurrentTeb()->ChpeV2CpuAreaInfo->InSyscallCallback))
if ((chpe = NtCurrentTeb()->ChpeV2CpuAreaInfo) && chpe->InSimulation && chpe->SuspendDoorbell)
{
*NtCurrentTeb()->ChpeV2CpuAreaInfo->SuspendDoorbell = 1;
arm64_thread_data()->suspend_pending = TRUE;
return;
NTSTATUS status = server_select( NULL, 0, SELECT_INTERRUPTIBLE | SELECT_COOPERATIVE_SUSPEND,
0, NULL, NULL );
if (status == STATUS_THREAD_WAS_SUSPENDED)
{
*chpe->SuspendDoorbell = -1;
arm64_thread_data()->suspend_pending = TRUE;
}
}

if (is_inside_syscall( SP_sig(ucontext) ))
else if (is_inside_syscall( SP_sig(ucontext) ))
{
context.ContextFlags = CONTEXT_FULL | CONTEXT_EXCEPTION_REQUEST;
NtGetContextThread( GetCurrentThread(), &context );
Expand Down Expand Up @@ -1510,14 +1504,11 @@ void syscall_dispatcher_return_slowpath(void)
*/
void init_syscall_frame( LPTHREAD_START_ROUTINE entry, void *arg, BOOL suspend, TEB *teb )
{
struct ntdll_thread_data *thread_data = (struct ntdll_thread_data *)&teb->GdiTebBatch;
struct syscall_frame *frame = thread_data->syscall_frame;
struct syscall_frame *frame = ((struct ntdll_thread_data *)&teb->GdiTebBatch)->syscall_frame;
CONTEXT *ctx, context = { CONTEXT_ALL };
I386_CONTEXT *i386_context;
ARM_CONTEXT *arm_context;

((struct arm64_thread_data *)(thread_data->cpu_data))->suspend_pending = FALSE;

context.X0 = (DWORD64)entry;
context.X1 = (DWORD64)arg;
context.X18 = (DWORD64)teb;
Expand Down
5 changes: 3 additions & 2 deletions include/wine/server_protocol.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 3 additions & 2 deletions server/protocol.def
Original file line number Diff line number Diff line change
Expand Up @@ -1463,8 +1463,9 @@ struct cpu_topology_override
VARARG(call,apc_call); /* APC call arguments */
VARARG(contexts,contexts); /* suspend context(s) */
@END
#define SELECT_ALERTABLE 1
#define SELECT_INTERRUPTIBLE 2
#define SELECT_ALERTABLE 1
#define SELECT_INTERRUPTIBLE 2
#define SELECT_COOPERATIVE_SUSPEND 4


/* Create an event */
Expand Down
1 change: 1 addition & 0 deletions server/request_trace.h

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 12 additions & 2 deletions server/thread.c
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ struct context
struct object obj; /* object header */
struct object *sync; /* sync object for wait/signal */
unsigned int status; /* status of the context */
int cooperative;/* waiting for the cooperative suspend */
struct context_data regs[2]; /* context data */
};
#define CTX_NATIVE 0 /* context for native machine */
Expand Down Expand Up @@ -446,6 +447,7 @@ static inline void init_thread_structure( struct thread *thread )

static inline int is_thread_suspended( struct thread *thread )
{
if (thread->context && thread->context->cooperative) return 0;
if (thread->suspend) return 1;
return !thread->bypass_proc_suspend && thread->process->suspend;
}
Expand Down Expand Up @@ -486,8 +488,9 @@ static struct context *create_thread_context( struct thread *thread )
{
struct context *context;
if (!(context = alloc_object( &context_ops ))) return NULL;
context->sync = NULL;
context->status = STATUS_PENDING;
context->sync = NULL;
context->status = STATUS_PENDING;
context->cooperative = 0;
memset( &context->regs, 0, sizeof(context->regs) );
context->regs[CTX_NATIVE].machine = native_machine;

Expand Down Expand Up @@ -1193,6 +1196,12 @@ static int check_wait( struct thread *thread )
if ((wait->flags & SELECT_INTERRUPTIBLE) && !list_empty( &thread->system_apc ))
return STATUS_KERNEL_APC;

if ((wait->flags & SELECT_COOPERATIVE_SUSPEND) && thread->context)
{
thread->context->cooperative = 1;
return STATUS_THREAD_WAS_SUSPENDED;
}

/* Suspended threads may not acquire locks, but they can run system APCs */
if (is_thread_suspended( thread )) return -1;

Expand Down Expand Up @@ -2058,6 +2067,7 @@ DECL_HANDLER(select)
copy_context( &ctx->regs[CTX_WOW], wow_context, wow_context->flags & ~ctx->regs[CTX_WOW].flags );
}
ctx->status = STATUS_SUCCESS;
ctx->cooperative = 0;
current->suspend_cookie = req->cookie;
signal_sync( ctx->sync );
}
Expand Down
Loading