From c6e120e2d2f909d95f95839fa99fccf811fdb3c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Duval?= Date: Tue, 15 May 2018 21:19:38 +0200 Subject: [PATCH] kernel/x86_64: add setup_compat_signal_frame. * add compatibility signal types. Change-Id: I665020234be0ba2ccbb33bdbc338c11a214ab6e8 --- headers/private/kernel/arch/thread.h | 6 + headers/private/kernel/arch/x86/arch_thread.h | 24 ++ .../kernel/compat/arch/x86/signal_compat.h | 113 +++++++++ .../private/kernel/compat/ksignal_compat.h | 164 ++++++++++++++ headers/private/kernel/compat/signal_compat.h | 22 ++ src/system/kernel/arch/x86/64/thread.cpp | 214 ++++++++++++++++-- src/system/kernel/signal.cpp | 63 ++++++ 7 files changed, 593 insertions(+), 13 deletions(-) create mode 100644 headers/private/kernel/compat/arch/x86/signal_compat.h create mode 100644 headers/private/kernel/compat/ksignal_compat.h create mode 100644 headers/private/kernel/compat/signal_compat.h diff --git a/headers/private/kernel/arch/thread.h b/headers/private/kernel/arch/thread.h index b19066a520..5556073300 100644 --- a/headers/private/kernel/arch/thread.h +++ b/headers/private/kernel/arch/thread.h @@ -31,6 +31,12 @@ bool arch_on_signal_stack(Thread *thread); status_t arch_setup_signal_frame(Thread *thread, struct sigaction *action, struct signal_frame_data *signalFrameData); int64 arch_restore_signal_frame(struct signal_frame_data* signalFrameData); +#ifdef _COMPAT_MODE +status_t arch_setup_compat_signal_frame(Thread *thread, + struct sigaction *action, struct compat_signal_frame_data *signalFrameData); +int64 arch_restore_compat_signal_frame( + struct compat_signal_frame_data* signalFrameData); +#endif void arch_store_fork_frame(struct arch_fork_arg *arg); void arch_restore_fork_frame(struct arch_fork_arg *arg); diff --git a/headers/private/kernel/arch/x86/arch_thread.h b/headers/private/kernel/arch/x86/arch_thread.h index 3689d0b44b..2415110df8 100644 --- a/headers/private/kernel/arch/x86/arch_thread.h +++ b/headers/private/kernel/arch/x86/arch_thread.h @@ -51,6 +51,30 @@ arch_thread_set_current_thread(Thread* t) } +#ifdef _COMPAT_MODE + + +static inline void +arch_thread_set_ds(unsigned short ds) +{ + asm volatile("mov %0, %%ds" : : "r" (ds) : "memory"); +} + + +static inline void +arch_thread_set_es(unsigned short es) +{ + asm volatile("mov %0, %%es" : : "r" (es) : "memory"); +} + +// override empty macro +#undef arch_syscall_64_bit_return_value +void arch_syscall_64_bit_return_value(void); + + +#endif // _COMPAT_MODE + + #else // __x86_64__ diff --git a/headers/private/kernel/compat/arch/x86/signal_compat.h b/headers/private/kernel/compat/arch/x86/signal_compat.h new file mode 100644 index 0000000000..8fe645d44c --- /dev/null +++ b/headers/private/kernel/compat/arch/x86/signal_compat.h @@ -0,0 +1,113 @@ +/* + * Copyright 2018, Haiku Inc. All rights reserved. + * + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_COMPAT_ARCH_SIGNAL_H +#define _KERNEL_COMPAT_ARCH_SIGNAL_H + + +typedef struct packed_fp_stack { + unsigned char st0[10]; + unsigned char st1[10]; + unsigned char st2[10]; + unsigned char st3[10]; + unsigned char st4[10]; + unsigned char st5[10]; + unsigned char st6[10]; + unsigned char st7[10]; +} packed_fp_stack; + +typedef struct packed_mmx_regs { + unsigned char mm0[10]; + unsigned char mm1[10]; + unsigned char mm2[10]; + unsigned char mm3[10]; + unsigned char mm4[10]; + unsigned char mm5[10]; + unsigned char mm6[10]; + unsigned char mm7[10]; +} packed_mmx_regs; + +typedef struct xmmx_regs { + unsigned char xmm0[16]; + unsigned char xmm1[16]; + unsigned char xmm2[16]; + unsigned char xmm3[16]; + unsigned char xmm4[16]; + unsigned char xmm5[16]; + unsigned char xmm6[16]; + unsigned char xmm7[16]; +} xmmx_regs; + +typedef struct compat_stack_t { + uint32 ss_sp; + uint32 ss_size; + int ss_flags; +} compat_stack_t; + +typedef struct compat_old_extended_regs { + unsigned short fp_control; + unsigned short _reserved1; + unsigned short fp_status; + unsigned short _reserved2; + unsigned short fp_tag; + unsigned short _reserved3; + uint32 fp_eip; + unsigned short fp_cs; + unsigned short fp_opcode; + uint32 fp_datap; + unsigned short fp_ds; + unsigned short _reserved4; + union { + packed_fp_stack fp; + packed_mmx_regs mmx; + } fp_mmx; +} compat_old_extended_regs; + +typedef struct compat_new_extended_regs { + unsigned short fp_control; + unsigned short fp_status; + unsigned short fp_tag; + unsigned short fp_opcode; + uint32 fp_eip; + unsigned short fp_cs; + unsigned short res_14_15; + uint32 fp_datap; + unsigned short fp_ds; + unsigned short _reserved_22_23; + uint32 mxcsr; + uint32 _reserved_28_31; + union { + fp_stack fp; + mmx_regs mmx; + } fp_mmx; + xmmx_regs xmmx; + unsigned char _reserved_288_511[224]; +} compat_new_extended_regs; + +typedef struct compat_extended_regs { + union { + compat_old_extended_regs old_format; + compat_new_extended_regs new_format; + } state; + uint32 format; +} compat_extended_regs; + +struct compat_vregs { + uint32 eip; + uint32 eflags; + uint32 eax; + uint32 ecx; + uint32 edx; + uint32 esp; + uint32 ebp; + uint32 _reserved_1; + compat_extended_regs xregs; + uint32 edi; + uint32 esi; + uint32 ebx; +}; + + +#endif // _KERNEL_COMPAT_ARCH_SIGNAL_H diff --git a/headers/private/kernel/compat/ksignal_compat.h b/headers/private/kernel/compat/ksignal_compat.h new file mode 100644 index 0000000000..6b3ee64a38 --- /dev/null +++ b/headers/private/kernel/compat/ksignal_compat.h @@ -0,0 +1,164 @@ +/* + * Copyright 2018, Haiku Inc. All rights reserved. + * + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_COMPAT_KSIGNAL_H +#define _KERNEL_COMPAT_KSIGNAL_H + + +#include +#include + + +typedef struct compat_vregs compat_mcontext_t; + +typedef struct __compat_ucontext_t { + uint32 uc_link; + sigset_t uc_sigmask; + compat_stack_t uc_stack; + compat_mcontext_t uc_mcontext; +} _PACKED compat_ucontext_t; + +union compat_sigval { + int sival_int; + uint32 sival_ptr; +}; + + +typedef struct __compat_siginfo_t { + int si_signo; /* signal number */ + int si_code; /* signal code */ + int si_errno; /* if non zero, an error number associated with + this signal */ + pid_t si_pid; /* sending process ID */ + uid_t si_uid; /* real user ID of sending process */ + uint32 si_addr; /* address of faulting instruction */ + int si_status; /* exit value or signal */ + uint32 si_band; /* band event for SIGPOLL */ + union compat_sigval si_value; /* signal value */ +} compat_siginfo_t; + +struct compat_signal_frame_data { + compat_siginfo_t info; + compat_ucontext_t context; + uint32 user_data; + uint32 handler; + bool siginfo_handler; + char _pad[3]; + int32 thread_flags; + uint64 syscall_restart_return_value; + uint8 syscall_restart_parameters[SYSCALL_RESTART_PARAMETER_SIZE]; + uint32 commpage_address; +} _PACKED; + + +static_assert(sizeof(compat_stack_t) == 12, + "size of compat_stack_t mismatch"); +static_assert(sizeof(compat_mcontext_t) == 560, + "size of compat_mcontext_t mismatch"); +static_assert(sizeof(compat_ucontext_t) == 584, + "size of compat_ucontext_t mismatch"); +static_assert(sizeof(compat_siginfo_t) == 36, + "size of compat_siginfo_t mismatch"); +static_assert(sizeof(struct compat_signal_frame_data) == 680, + "size of compat_signal_frame_data mismatch"); + + +inline status_t +copy_ref_var_from_user(union sigval* userSigval, union sigval &sigval) +{ + if (!IS_USER_ADDRESS(userSigval)) + return B_BAD_ADDRESS; + Thread* thread = thread_get_current_thread(); + bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0; + if (compatMode) { + compat_sigval compat_sigval; + if (user_memcpy(&compat_sigval, userSigval, sizeof(compat_sigval)) + < B_OK) { + return B_BAD_ADDRESS; + } + sigval.sival_ptr = (void*)(addr_t)compat_sigval.sival_ptr; + } else if (user_memcpy(&sigval, userSigval, sizeof(union sigval)) < B_OK) { + return B_BAD_ADDRESS; + } + return B_OK; +} + + +inline status_t +copy_ref_var_to_user(siginfo_t &info, siginfo_t* userInfo) +{ + if (!IS_USER_ADDRESS(userInfo)) + return B_BAD_ADDRESS; + Thread* thread = thread_get_current_thread(); + bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0; + if (compatMode) { + compat_siginfo_t compat_info; + compat_info.si_signo = info.si_signo; + compat_info.si_code = info.si_code; + compat_info.si_errno = info.si_errno; + compat_info.si_pid = info.si_pid; + compat_info.si_uid = info.si_uid; + compat_info.si_addr = (addr_t)info.si_addr; + compat_info.si_status = info.si_status; + compat_info.si_band = info.si_band; + compat_info.si_value.sival_ptr = (addr_t)info.si_value.sival_ptr; + if (user_memcpy(userInfo, &compat_info, sizeof(compat_info)) + < B_OK) { + return B_BAD_ADDRESS; + } + } else if (user_memcpy(userInfo, &info, sizeof(info)) < B_OK) { + return B_BAD_ADDRESS; + } + return B_OK; +} + + +inline status_t +copy_ref_var_from_user(stack_t* userStack, stack_t &stack) +{ + if (!IS_USER_ADDRESS(userStack)) + return B_BAD_ADDRESS; + Thread* thread = thread_get_current_thread(); + bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0; + if (compatMode) { + compat_stack_t compatStack; + if (user_memcpy(&compatStack, userStack, sizeof(compatStack)) + < B_OK) { + return B_BAD_ADDRESS; + } + stack.ss_sp = (void*)(addr_t)compatStack.ss_sp; + stack.ss_size = compatStack.ss_size; + stack.ss_flags = compatStack.ss_flags; + } else if (user_memcpy(&stack, userStack, sizeof(stack_t)) < B_OK) { + return B_BAD_ADDRESS; + } + return B_OK; +} + + +inline status_t +copy_ref_var_to_user(stack_t &stack, stack_t* userStack) +{ + if (!IS_USER_ADDRESS(userStack)) + return B_BAD_ADDRESS; + Thread* thread = thread_get_current_thread(); + bool compatMode = (thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0; + if (compatMode) { + compat_stack_t compatStack; + compatStack.ss_sp = (addr_t)stack.ss_sp; + compatStack.ss_size = stack.ss_size; + compatStack.ss_flags = stack.ss_flags; + if (user_memcpy(userStack, &compatStack, sizeof(compatStack)) + < B_OK) { + return B_BAD_ADDRESS; + } + } else if (user_memcpy(userStack, &stack, sizeof(stack)) < B_OK) { + return B_BAD_ADDRESS; + } + return B_OK; +} + + +#endif // _KERNEL_COMPAT_KSIGNAL_H diff --git a/headers/private/kernel/compat/signal_compat.h b/headers/private/kernel/compat/signal_compat.h new file mode 100644 index 0000000000..07a4686296 --- /dev/null +++ b/headers/private/kernel/compat/signal_compat.h @@ -0,0 +1,22 @@ +/* + * Copyright 2018, Haiku Inc. All rights reserved. + * + * Distributed under the terms of the MIT License. + */ +#ifndef _KERNEL_COMPAT_SIGNAL_H +#define _KERNEL_COMPAT_SIGNAL_H + + +struct compat_sigaction { + union { + uint32 sa_handler; + uint32 sa_sigaction; + }; + sigset_t sa_mask; + int sa_flags; + uint32 sa_userdata; /* will be passed to the signal + handler, BeOS extension */ +} _PACKED; + + +#endif // _KERNEL_COMPAT_SIGNAL_H diff --git a/src/system/kernel/arch/x86/64/thread.cpp b/src/system/kernel/arch/x86/64/thread.cpp index a29697a03f..7a6a35d724 100644 --- a/src/system/kernel/arch/x86/64/thread.cpp +++ b/src/system/kernel/arch/x86/64/thread.cpp @@ -18,6 +18,9 @@ #include #include #include +#ifdef _COMPAT_MODE +# include +#endif #include #include #include @@ -88,11 +91,33 @@ x86_restart_syscall(iframe* frame) } +#ifdef _COMPAT_MODE + + +static inline void +set_fs_register(uint32 segment) +{ + asm("movl %0,%%fs" :: "r" (segment)); +} + + +#endif // _COMPAT_MODE + + void x86_set_tls_context(Thread* thread) { - // Set FS segment base address to the TLS segment. - x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); +#ifdef _COMPAT_MODE + if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) { + unsigned index = x86_64_set_user_tls_segment_base( + smp_get_current_cpu(), thread->user_local_storage); + set_fs_register((index << 3) | DPL_USER); + } else +#endif + { + // Set FS segment base address to the TLS segment. + x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); + } } @@ -109,6 +134,24 @@ arch_randomize_stack_pointer(addr_t value) } +#ifdef _COMPAT_MODE + + +static addr_t +arch_compat_randomize_stack_pointer(addr_t value) +{ + STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1); + value -= random_value() & (B_PAGE_SIZE - 1); + return (value & ~addr_t(0xf)) - 4; + // This means, result % 16 == 12, which is what esp should adhere to + // when a function is entered for the stack to be considered aligned to + // 16 byte. +} + + +#endif // _COMPAT_MODE + + static uint8* get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action, size_t spaceNeeded) @@ -218,27 +261,55 @@ arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " "stackTop %#lx\n", entry, args1, args2, stackTop); - stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr)); - // Copy the address of the stub that calls exit_thread() when the thread // entry function returns to the top of the stack to act as the return // address. The stub is inside commpage. addr_t commPageAddress = (addr_t)thread->team->commpage_address; - set_ac(); - codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] - + commPageAddress; - clear_ac(); - if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) + +#ifdef _COMPAT_MODE + if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) { + uint32 args[3]; + stackTop = arch_compat_randomize_stack_pointer(stackTop - sizeof(args)); + + set_ac(); + args[0] = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] + + commPageAddress; + clear_ac(); + args[1] = (uint32)(addr_t)args1; + args[2] = (uint32)(addr_t)args2; + if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK) + return B_BAD_ADDRESS; + + } else +#endif + { + stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr)); + + set_ac(); + codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] + + commPageAddress; + clear_ac(); + if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) != B_OK) - return B_BAD_ADDRESS; + return B_BAD_ADDRESS; + } // Prepare the user iframe. iframe frame = {}; frame.type = IFRAME_TYPE_SYSCALL; - frame.si = (uint64)args2; - frame.di = (uint64)args1; frame.ip = entry; - frame.cs = USER_CODE_SELECTOR; +#ifdef _COMPAT_MODE + if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) { + frame.cs = USER32_CODE_SELECTOR; + arch_thread_set_ds(USER_DATA_SELECTOR); + arch_thread_set_es(USER_DATA_SELECTOR); + } else +#endif + { + frame.si = (uint64)args2; + frame.di = (uint64)args1; + frame.cs = USER_CODE_SELECTOR; + } frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); frame.sp = stackTop; @@ -394,3 +465,120 @@ arch_restore_signal_frame(struct signal_frame_data* signalFrameData) // restored. return frame->ax; } + + +#ifdef _COMPAT_MODE + +status_t +arch_setup_compat_signal_frame(Thread* thread, struct sigaction* action, + struct compat_signal_frame_data* signalFrameData) +{ + iframe* frame = x86_get_current_iframe(); + if (!IFRAME_IS_USER(frame)) { + panic("arch_setup_compat_signal_frame(): No user iframe!"); + return B_BAD_VALUE; + } + + // Store the register state. + signalFrameData->context.uc_mcontext.eax = frame->ax; + signalFrameData->context.uc_mcontext.ebx = frame->bx; + signalFrameData->context.uc_mcontext.ecx = frame->cx; + signalFrameData->context.uc_mcontext.edx = frame->dx; + signalFrameData->context.uc_mcontext.edi = frame->di; + signalFrameData->context.uc_mcontext.esi = frame->si; + signalFrameData->context.uc_mcontext.ebp = frame->bp; + signalFrameData->context.uc_mcontext.esp = frame->user_sp; + signalFrameData->context.uc_mcontext.eip = frame->ip; + signalFrameData->context.uc_mcontext.eflags = frame->flags; + x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); + + // Fill in signalFrameData->context.uc_stack. + stack_t stack; + signal_get_user_stack(frame->user_sp, &stack); + signalFrameData->context.uc_stack.ss_sp = (addr_t)stack.ss_sp; + signalFrameData->context.uc_stack.ss_size = stack.ss_size; + signalFrameData->context.uc_stack.ss_flags = stack.ss_flags; + + // Store syscall_restart_return_value. + signalFrameData->syscall_restart_return_value = frame->orig_rax; + + // Get the stack to use and copy the frame data to it. + uint32 stackFrame[2]; + uint8* userStack = get_signal_stack(thread, frame, action, + sizeof(*signalFrameData) + sizeof(stackFrame)); + + compat_signal_frame_data* userSignalFrameData + = (compat_signal_frame_data*)(userStack + sizeof(stackFrame)); + + if (user_memcpy(userSignalFrameData, signalFrameData, + sizeof(*signalFrameData)) != B_OK) { + return B_BAD_ADDRESS; + } + + // prepare the user stack frame for a function call to the signal handler + // wrapper function + stackFrame[0] = frame->ip; + stackFrame[1] = (addr_t)userSignalFrameData; + // parameter: pointer to signal frame data + + if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK) + return B_BAD_ADDRESS; + + // Update Thread::user_signal_context, now that everything seems to have + // gone fine. + thread->user_signal_context = (ucontext_t*)&userSignalFrameData->context; + + // Set up the iframe to execute the signal handler wrapper on our prepared + // stack. First argument points to the frame data. + addr_t* commPageAddress = (addr_t*)thread->team->commpage_address; + frame->user_sp = (addr_t)userStack; + set_ac(); + + // from x86/arch_commpage_defs.h +#define COMPAT_COMMPAGE_ENTRY_X86_SIGNAL_HANDLER \ + (COMMPAGE_ENTRY_FIRST_ARCH_SPECIFIC + 3) + frame->ip = commPageAddress[COMPAT_COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] + + (addr_t)commPageAddress; + clear_ac(); + + return B_OK; +} + + +int64 +arch_restore_compat_signal_frame(struct compat_signal_frame_data* signalFrameData) +{ + iframe* frame = x86_get_current_iframe(); + + frame->orig_rax = signalFrameData->syscall_restart_return_value; + frame->ax = signalFrameData->context.uc_mcontext.eax; + frame->bx = signalFrameData->context.uc_mcontext.ebx; + frame->cx = signalFrameData->context.uc_mcontext.ecx; + frame->dx = signalFrameData->context.uc_mcontext.edx; + frame->di = signalFrameData->context.uc_mcontext.edi; + frame->si = signalFrameData->context.uc_mcontext.esi; + frame->bp = signalFrameData->context.uc_mcontext.ebp; + frame->user_sp = signalFrameData->context.uc_mcontext.esp; + frame->ip = signalFrameData->context.uc_mcontext.eip; + frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS) + | (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS); + + x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); + + // The syscall return code overwrites frame->ax with the return value of + // the syscall, need to return it here to ensure the correct value is + // restored. + return frame->ax; +} + + +void +arch_syscall_64_bit_return_value(void) +{ + Thread* thread = thread_get_current_thread(); + if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) + atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN); +} + +#endif // _COMPAT_MODE + diff --git a/src/system/kernel/signal.cpp b/src/system/kernel/signal.cpp index cea1c3168e..3f96d7918d 100644 --- a/src/system/kernel/signal.cpp +++ b/src/system/kernel/signal.cpp @@ -13,6 +13,9 @@ #include +#ifdef _COMPAT_MODE +# include +#endif #include #include @@ -908,6 +911,61 @@ setup_signal_frame(Thread* thread, struct sigaction* action, Signal* signal, } +#ifdef _COMPAT_MODE + +static status_t +setup_compat_signal_frame(Thread* thread, struct sigaction* action, Signal* signal, + sigset_t signalMask) +{ + // prepare the data, we need to copy onto the user stack + struct compat_signal_frame_data frameData; + + // signal info + frameData.info.si_signo = signal->Number(); + frameData.info.si_code = signal->SignalCode(); + frameData.info.si_errno = signal->ErrorCode(); + frameData.info.si_pid = signal->SendingProcess(); + frameData.info.si_uid = signal->SendingUser(); + frameData.info.si_addr = (addr_t)signal->Address(); + frameData.info.si_status = signal->Status(); + frameData.info.si_band = signal->PollBand(); + frameData.info.si_value.sival_ptr = (addr_t)signal->UserValue().sival_ptr; + + // context + frameData.context.uc_link = (addr_t)thread->user_signal_context; + frameData.context.uc_sigmask = signalMask; + // uc_stack and uc_mcontext are filled in by the architecture specific code. + + // user data + frameData.user_data = (addr_t)action->sa_userdata; + + // handler function + frameData.siginfo_handler = (action->sa_flags & SA_SIGINFO) != 0; + frameData.handler = frameData.siginfo_handler + ? (addr_t)action->sa_sigaction : (addr_t)action->sa_handler; + + // thread flags -- save the and clear the thread's syscall restart related + // flags + frameData.thread_flags = atomic_and(&thread->flags, + ~(THREAD_FLAGS_RESTART_SYSCALL | THREAD_FLAGS_64_BIT_SYSCALL_RETURN)); + + // syscall restart related fields + memcpy(frameData.syscall_restart_parameters, + thread->syscall_restart.parameters, + sizeof(frameData.syscall_restart_parameters)); + + // commpage address + frameData.commpage_address = (addr_t)thread->team->commpage_address; + + // syscall_restart_return_value is filled in by the architecture specific + // code. + + return arch_setup_compat_signal_frame(thread, action, &frameData); +} + +#endif // _COMPAT_MODE + + /*! Actually handles pending signals -- i.e. the thread will exit, a custom signal handler is prepared, or whatever the signal demands. The function will not return, when a deadly signal is encountered. The @@ -1258,6 +1316,11 @@ handle_signals(Thread* thread) locker.Unlock(); +#ifdef _COMPAT_MODE + if ((thread->flags & THREAD_FLAGS_COMPAT_MODE) != 0) + setup_compat_signal_frame(thread, &handler, signal, oldBlockMask); + else +#endif setup_signal_frame(thread, &handler, signal, oldBlockMask); // Reset sigsuspend_original_unblocked_mask. It would have been set by