diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 46913927..d0b96b83 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -161,12 +161,41 @@ fault: } struct sigsp { - struct x86_user_context regs; + unsigned long flags; + void *link; + stack_t sigstack; + unsigned long regs[23]; +#define _r8 regs[0] +#define _r9 regs[1] +#define _r10 regs[2] +#define _r11 regs[3] +#define _r12 regs[4] +#define _r13 regs[5] +#define _r14 regs[6] +#define _r15 regs[7] +#define _rdi regs[8] +#define _rsi regs[9] +#define _rbp regs[10] +#define _rbx regs[11] +#define _rdx regs[12] +#define _rax regs[13] +#define _rcx regs[14] +#define _rsp regs[15] +#define _rip regs[16] +#define _rflags regs[17] +#define _csgsfs regs[18] +#define _error regs[19] +#define _trapno regs[20] +#define _oldmask regs[21] +#define _cr2 regs[22] + void *fpregs; + unsigned long reserve[8]; + unsigned long sigrc; unsigned long sigmask; - int ssflags; int num; int restart; + unsigned long ss; siginfo_t info; }; @@ -174,16 +203,38 @@ SYSCALL_DECLARE(rt_sigreturn) { struct thread *thread = cpu_local_var(current); struct x86_user_context *regs; + struct sigsp ksigsp; struct sigsp *sigsp; asm("movq %%gs:132, %0" : "=r" (regs)); --regs; sigsp = (struct sigsp *)regs->gpr.rsp; - if(copy_from_user(regs, &sigsp->regs, sizeof(struct x86_user_context))) + if(copy_from_user(&ksigsp, sigsp, sizeof ksigsp)) return -EFAULT; - thread->sigmask.__val[0] = sigsp->sigmask; - thread->sigstack.ss_flags = sigsp->ssflags; + + regs->gpr.r15 = ksigsp._r15; + regs->gpr.r14 = ksigsp._r14; + regs->gpr.r13 = ksigsp._r13; + regs->gpr.r12 = ksigsp._r12; + regs->gpr.rbp = ksigsp._rbp; + regs->gpr.rbx = ksigsp._rbx; + regs->gpr.r11 = ksigsp._r11; + regs->gpr.r10 = ksigsp._r10; + regs->gpr.r9 = ksigsp._r9; + regs->gpr.r8 = ksigsp._r8; + regs->gpr.rax = ksigsp._rax; + regs->gpr.rcx = ksigsp._rcx; + regs->gpr.rdx = ksigsp._rdx; + regs->gpr.rsi = ksigsp._rsi; + regs->gpr.rdi = ksigsp._rdi; + regs->gpr.error = ksigsp._error; + regs->gpr.rip = ksigsp._rip; + regs->gpr.rflags = ksigsp._rflags; + regs->gpr.rsp = ksigsp._rsp; + thread->sigmask.__val[0] = ksigsp._oldmask; + + memcpy(&thread->sigstack, &ksigsp.sigstack, sizeof(stack_t)); if(sigsp->restart){ return syscall(sigsp->num, (ihk_mc_user_context_t *)regs); } @@ -567,9 +618,8 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi } else if(k->sa.sa_handler){ unsigned long *usp; /* user stack */ + struct sigsp ksigsp; struct sigsp *sigsp; - int ssflags = thread->sigstack.ss_flags; - unsigned long mask = (unsigned long)thread->sigmask.__val[0]; if((k->sa.sa_flags & SA_ONSTACK) && !(thread->sigstack.ss_flags & SS_DISABLE) && @@ -584,31 +634,56 @@ do_signal(unsigned long rc, void *regs0, struct thread *thread, struct sig_pendi } sigsp = ((struct sigsp *)usp) - 1; sigsp = (struct sigsp *)((unsigned long)sigsp & 0xfffffffffffffff0UL); - if(write_process_vm(thread->vm, &sigsp->regs, regs, sizeof(struct x86_user_context)) || - write_process_vm(thread->vm, &sigsp->sigrc, &rc, sizeof(long))){ + memset(&ksigsp, '\0', sizeof ksigsp); + + ksigsp._r15 = regs->gpr.r15; + ksigsp._r14 = regs->gpr.r14; + ksigsp._r13 = regs->gpr.r13; + ksigsp._r12 = regs->gpr.r12; + ksigsp._rbp = regs->gpr.rbp; + ksigsp._rbx = regs->gpr.rbx; + ksigsp._r11 = regs->gpr.r11; + ksigsp._r10 = regs->gpr.r10; + ksigsp._r9 = regs->gpr.r9; + ksigsp._r8 = regs->gpr.r8; + ksigsp._rax = regs->gpr.rax; + ksigsp._rcx = regs->gpr.rcx; + ksigsp._rdx = regs->gpr.rdx; + ksigsp._rsi = regs->gpr.rsi; + ksigsp._rdi = regs->gpr.rdi; + ksigsp._error = regs->gpr.error; + ksigsp._rip = regs->gpr.rip; + ksigsp._rflags = regs->gpr.rflags; + ksigsp._rsp = regs->gpr.rsp; + ksigsp._cr2 = (unsigned long)pending->info._sifields._sigfault.si_addr; + ksigsp._oldmask = thread->sigmask.__val[0]; + + memcpy(&ksigsp.sigstack, &thread->sigstack, sizeof(stack_t)); + ksigsp.sigrc = rc; + ksigsp.num = num; + ksigsp.restart = isrestart(num, rc, sig, k->sa.sa_flags & SA_RESTART); + if(num != 0 && rc == -EINTR && sig == SIGCHLD) + ksigsp.restart = 1; + memcpy(&ksigsp.info, &pending->info, sizeof(siginfo_t)); + + if(copy_to_user(sigsp, &ksigsp, sizeof ksigsp)){ kfree(pending); ihk_mc_spinlock_unlock(&thread->sigcommon->lock, irqstate); kprintf("do_signal,write_process_vm failed\n"); terminate(0, sig); return; } - sigsp->sigmask = mask; - sigsp->ssflags = ssflags; - sigsp->num = num; - sigsp->restart = isrestart(num, rc, sig, k->sa.sa_flags & SA_RESTART); - if(num != 0 && rc == -EINTR && sig == SIGCHLD) - sigsp->restart = 1; - memcpy(&sigsp->info, &pending->info, sizeof(siginfo_t)); + + + usp = (unsigned long *)sigsp; usp--; *usp = (unsigned long)k->sa.sa_restorer; regs->gpr.rdi = (unsigned long)sig; - if(k->sa.sa_flags & SA_SIGINFO){ - regs->gpr.rsi = (unsigned long)&sigsp->info; - regs->gpr.rdx = 0; - } + regs->gpr.rsi = (unsigned long)&sigsp->info; + regs->gpr.rdx = (unsigned long)sigsp; regs->gpr.rip = (unsigned long)k->sa.sa_handler; regs->gpr.rsp = (unsigned long)usp;