diff --git a/arch/x86/kernel/include/signal.h b/arch/x86/kernel/include/signal.h index 8de34ce6..23735056 100644 --- a/arch/x86/kernel/include/signal.h +++ b/arch/x86/kernel/include/signal.h @@ -33,31 +33,28 @@ struct sigaction { sigset_t sa_mask; }; -//// work in progress -struct sigbackup { - unsigned long rc; // return code of rt_sigreturn (rax) - void *uctx; - sigset_t mask; - double fpregs[16]; - -}; -//// +#define SA_NOCLDSTOP 0x00000001u +#define SA_NOCLDWAIT 0x00000002u +#define SA_NODEFER 0x40000000u +#define SA_ONSTACK 0x08000000u +#define SA_RESETHAND 0x80000000u +#define SA_RESTART 0x10000000u +#define SA_SIGINFO 0x00000004u struct k_sigaction { struct sigaction sa; }; -struct sigstack { - void *ss_sp; - int ss_onstack; -}; - typedef struct sigaltstack { void *ss_sp; int ss_flags; size_t ss_size; } stack_t; +#define MINSIGSTKSZ 2048 +#define SS_ONSTACK 1 +#define SS_DISABLE 2 + typedef union sigval { int sival_int; void *sival_ptr; diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 2caad76e..21259603 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -121,6 +121,8 @@ fault: struct sigsp { struct x86_regs regs; unsigned long sigrc; + unsigned long sigmask; + int ssflags; }; SYSCALL_DECLARE(rt_sigreturn) @@ -133,8 +135,9 @@ SYSCALL_DECLARE(rt_sigreturn) asm("movq %%gs:132, %0" : "=r" (regs)); --regs; - proc->sigmask.__val[0] = proc->supmask.__val[0]; sigsp = (struct sigsp *)regs->rsp; + proc->sigmask.__val[0] = sigsp->sigmask; + proc->sigstack.ss_flags = sigsp->ssflags; if(copy_from_user(proc, regs, &sigsp->regs, sizeof(struct x86_regs))) return rc; copy_from_user(proc, &rc, &sigsp->sigrc, sizeof(long)); @@ -178,8 +181,20 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin else if(k->sa.sa_handler){ unsigned long *usp; /* user stack */ struct sigsp *sigsp; + int ssflags = proc->sigstack.ss_flags; + unsigned long mask = (unsigned long)proc->sigmask.__val[0]; - usp = (unsigned long *)regs->rsp; + if((k->sa.sa_flags & SA_ONSTACK) && + !(proc->sigstack.ss_flags & SS_DISABLE) && + !(proc->sigstack.ss_flags & SS_ONSTACK)){ + unsigned long lsp; + lsp = ((unsigned long)(((char *)proc->sigstack.ss_sp) + proc->sigstack.ss_size)) & 0xfffffffffffffff8UL; + usp = (unsigned long *)lsp; + proc->sigstack.ss_flags |= SS_ONSTACK; + } + else{ + usp = (unsigned long *)regs->rsp; + } sigsp = ((struct sigsp *)usp) - 1; if(copy_to_user(proc, &sigsp->regs, regs, sizeof(struct x86_regs)) || copy_to_user(proc, &sigsp->sigrc, &rc, sizeof(long))){ @@ -188,6 +203,8 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin terminate(0, sig, (ihk_mc_user_context_t *)regs->rsp); return; } + sigsp->sigmask = mask; + sigsp->ssflags = ssflags; usp = (unsigned long *)sigsp; usp--; @@ -197,8 +214,8 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin regs->rip = (unsigned long)k->sa.sa_handler; regs->rsp = (unsigned long)usp; - kfree(pending); proc->sigmask.__val[0] |= pending->sigmask.__val[0]; + kfree(pending); ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); } else{ @@ -342,7 +359,7 @@ do_kill(int pid, int tid, int sig) mask = __sigmask(sig); pending = NULL; rc = 0; - if(sig < 34){ + if(sig < 33){ // SIGRTMIN - SIGRTMAX list_for_each_entry(pending, head, list){ if(pending->sigmask.__val[0] == mask) break; diff --git a/kernel/include/process.h b/kernel/include/process.h index 0f6e63c4..5bc99fea 100644 --- a/kernel/include/process.h +++ b/kernel/include/process.h @@ -173,7 +173,7 @@ struct process { int tid; volatile int sigevent; sigset_t sigmask; - sigset_t supmask; + stack_t sigstack; ihk_spinlock_t sigpendinglock; struct list_head sigpending; struct sig_shared *sigshared; diff --git a/kernel/process.c b/kernel/process.c index 3a9a6314..89f17126 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -148,6 +148,10 @@ struct process *create_process(unsigned long user_pc) ihk_mc_spinlock_init(&proc->sigpendinglock); INIT_LIST_HEAD(&proc->sigpending); + proc->sigstack.ss_sp = NULL; + proc->sigstack.ss_flags = SS_DISABLE; + proc->sigstack.ss_size = 0; + ihk_mc_init_user_process(&proc->ctx, &proc->uctx, ((char *)proc) + KERNEL_STACK_NR_PAGES * PAGE_SIZE, user_pc, 0); @@ -218,7 +222,11 @@ struct process *clone_process(struct process *org, unsigned long pc, if (clone_flags & CLONE_VM) { ihk_atomic_inc(&org->vm->refcount); proc->vm = org->vm; - + + proc->sigstack.ss_sp = NULL; + proc->sigstack.ss_flags = SS_DISABLE; + proc->sigstack.ss_size = 0; + proc->sighandler = org->sighandler; ihk_atomic_inc(&org->sighandler->use); diff --git a/kernel/syscall.c b/kernel/syscall.c index 5dd7b94c..f2ccc583 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -1424,7 +1424,6 @@ SYSCALL_DECLARE(rt_sigprocmask) break; } } - proc->supmask = proc->sigmask; ihk_mc_spinlock_unlock(&proc->sighandler->lock, flag); return 0; fault: @@ -1587,15 +1586,28 @@ SYSCALL_DECLARE(sigaltstack) stack_t *oss = (stack_t *)ihk_mc_syscall_arg1(ctx); stack_t wss; - memset(&wss, '\0', sizeof wss); if(oss) - if(copy_to_user(proc, oss, &wss, sizeof wss)) + if(copy_to_user(proc, oss, &proc->sigstack, sizeof wss)) return -EFAULT; - if(ss) + if(ss){ if(copy_from_user(proc, &wss, ss, sizeof wss)) return -EFAULT; + if(wss.ss_flags != 0 && wss.ss_flags != SS_DISABLE) + return -EINVAL; + if(wss.ss_flags == SS_DISABLE){ + proc->sigstack.ss_sp = NULL; + proc->sigstack.ss_flags = SS_DISABLE; + proc->sigstack.ss_size = 0; + } + else{ + if(wss.ss_size < MINSIGSTKSZ) + return -ENOMEM; - return -EOPNOTSUPP; + memcpy(&proc->sigstack, &wss, sizeof wss); + } + } + + return 0; } SYSCALL_DECLARE(madvise)