diff --git a/kernel-src/include/x86-64/arch/signal.h b/kernel-src/include/x86-64/arch/signal.h index 76ce003d..d97d2381 100644 --- a/kernel-src/include/x86-64/arch/signal.h +++ b/kernel-src/include/x86-64/arch/signal.h @@ -93,5 +93,35 @@ static inline void arch_sigframe_prepare_mcontext(sigframe_t *sigframe) { memcpy(fpu_state, extracontext->fx, 512); } +static inline void arch_sigframe_get_context_from_mcontext(sigframe_t *sigframe) { + context_t *context = &sigframe->context; + extracontext_t *extracontext = &sigframe->extracontext; + unsigned long *gregs = sigframe->mcontext.gregs; + uint8_t *fpu_state = sigframe->mcontext.fpu_state; + + context->r8 = gregs[MCONTEXT_REG_R8]; + context->r9 = gregs[MCONTEXT_REG_R9]; + context->r10 = gregs[MCONTEXT_REG_R10]; + context->r11 = gregs[MCONTEXT_REG_R11]; + context->r12 = gregs[MCONTEXT_REG_R12]; + context->r13 = gregs[MCONTEXT_REG_R13]; + context->r14 = gregs[MCONTEXT_REG_R14]; + context->r15 = gregs[MCONTEXT_REG_R15]; + context->rdi = gregs[MCONTEXT_REG_RDI]; + context->rsi = gregs[MCONTEXT_REG_RSI]; + context->rbp = gregs[MCONTEXT_REG_RBP]; + context->rbx = gregs[MCONTEXT_REG_RBX]; + context->rdx = gregs[MCONTEXT_REG_RDX]; + context->rax = gregs[MCONTEXT_REG_RAX]; + context->rcx = gregs[MCONTEXT_REG_RCX]; + context->rsp = gregs[MCONTEXT_REG_RSP]; + context->rip = gregs[MCONTEXT_REG_RIP]; + context->rflags = gregs[MCONTEXT_REG_EFL]; + context->error = gregs[MCONTEXT_REG_ERR]; + context->cr2 = gregs[MCONTEXT_REG_CR2]; + + memcpy(extracontext->fx, fpu_state, 512); +} + #endif diff --git a/kernel-src/sys/syscalls/sigreturn.c b/kernel-src/sys/syscalls/sigreturn.c index 3aba707a..8116e9fa 100644 --- a/kernel-src/sys/syscalls/sigreturn.c +++ b/kernel-src/sys/syscalls/sigreturn.c @@ -3,6 +3,10 @@ #include #include +#ifdef __x86_64__ +#include +#endif + // this expects CTX_SP to be pointing to the signal frame __attribute__((noreturn)) void syscall_sigreturn(context_t *context) { sigframe_t sigframe; @@ -16,7 +20,15 @@ __attribute__((noreturn)) void syscall_sigreturn(context_t *context) { signal_altstack(current_thread(), &sigframe.oldstack, NULL); signal_changemask(current_thread(), SIG_SETMASK, &sigframe.oldmask, NULL); + arch_sigframe_get_context_from_mcontext(&sigframe); + __assert(ARCH_CONTEXT_ISUSER(&sigframe.context)); + + #ifdef __x86_64__ + // XXX is this behavior correct? ucontext doesnt seem to save it on linux and so it will not be saved + sigframe.extracontext.gsbase = rdmsr(MSR_KERNELGSBASE); + sigframe.extracontext.fsbase = rdmsr(MSR_FSBASE); + #endif memcpy(¤t_thread()->extracontext, &sigframe.extracontext, sizeof(extracontext_t)); ARCH_CONTEXT_THREADLOAD(current_thread(), context);