diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 74ae5273941..d298afe05de 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -88,6 +88,11 @@ WINE_DECLARE_DEBUG_CHANNEL(seh); #include "dwarf.h" +#ifdef __APPLE__ +/* CW Hack 23427 */ +static BOOL sequoia_or_later = FALSE; +#endif + static USHORT cs32_sel; /* selector for %cs in 32-bit mode */ static USHORT cs64_sel; /* selector for %cs in 64-bit mode */ static USHORT ds64_sel; /* selector for %ds/%es/%ss in 64-bit mode */ @@ -2005,6 +2010,41 @@ static inline BOOL handle_cet_nop( ucontext_t *sigcontext, CONTEXT *context ) } return FALSE; } + +/*********************************************************************** + * emulate_xgetbv + * + * Check if the fault location is an Intel XGETBV instruction for xcr0 and + * emulate it if so. Actual Intel hardware supports this instruction, so this + * will only take effect under Rosetta. + * CW HACK 23427 + */ +static inline BOOL emulate_xgetbv( ucontext_t *sigcontext, CONTEXT *context ) +{ + BYTE instr[3]; + unsigned int len = virtual_uninterrupted_read_memory( (BYTE *)context->Rip, instr, sizeof(instr) ); + + /* Prefixed xgetbv is illegal, so no need to check. */ + if (len < 3 || instr[0] != 0x0f || instr[1] != 0x01 || instr[2] != 0xd0 || + (RCX_sig(sigcontext) & 0xffffffff) != 0 /* only handling xcr0 (ecx==0) */) + { + return FALSE; + } + + RDX_sig(sigcontext) = 0; + if (sequoia_or_later) + { + /* Arguably we should only claim AVX support if ROSETTA_ADVERTISE_AVX is + set, but presumably apps will also check cpuid. */ + RAX_sig(sigcontext) = 0xe7; /* fpu/mmx, sse, avx, full avx-512 */ + } + else + RAX_sig(sigcontext) = 0x07; /* fpu/mmx, sse */ + + RIP_sig(sigcontext) += 3; + TRACE_(seh)( "emulated an XGETBV instruction\n" ); + return TRUE; +} #endif /*********************************************************************** @@ -2354,6 +2394,8 @@ static void segv_handler( int signal, siginfo_t *siginfo, void *sigcontext ) #ifdef __APPLE__ /* CW HACK 20186 */ if (handle_cet_nop( ucontext, &context.c )) return; + /* CW HACK 23427 */ + if (emulate_xgetbv( ucontext, &context.c )) return; #endif rec.ExceptionCode = EXCEPTION_ILLEGAL_INSTRUCTION; break; @@ -2802,6 +2844,12 @@ void signal_init_process(void) signal_alloc_thread( NtCurrentTeb() ); +#ifdef __APPLE__ + /* CW Hack 23427: __builtin_available presumably isn't signal-safe. */ + if (__builtin_available( macOS 15.0, * )) + sequoia_or_later = TRUE; +#endif + sig_act.sa_mask = server_block_set; sig_act.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK;