diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index cc3ae2f6..6c78c206 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -368,7 +368,7 @@ void setup_x86_ap(void (*next_func)(void)) } void arch_show_interrupt_context(const void *reg); -void set_signal(int, void *, int); +void set_signal(int, void *); void check_signal(long, void *); void handle_interrupt(int vector, struct x86_regs *regs) @@ -409,7 +409,7 @@ void gpe_handler(struct x86_regs *regs) kprintf("General protection fault (err: %lx, %lx:%lx)\n", regs->error, regs->cs, regs->rip); arch_show_interrupt_context(regs); - set_signal(SIGILL, regs, 1); + set_signal(SIGILL, regs); check_signal(0, regs); // panic("GPF"); } diff --git a/arch/x86/kernel/include/signal.h b/arch/x86/kernel/include/signal.h index 8636c1d4..8de34ce6 100644 --- a/arch/x86/kernel/include/signal.h +++ b/arch/x86/kernel/include/signal.h @@ -33,6 +33,16 @@ 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]; + +}; +//// + struct k_sigaction { struct sigaction sa; }; diff --git a/arch/x86/kernel/include/syscall_list.h b/arch/x86/kernel/include/syscall_list.h index af5f543c..bf393624 100644 --- a/arch/x86/kernel/include/syscall_list.h +++ b/arch/x86/kernel/include/syscall_list.h @@ -41,6 +41,7 @@ SYSCALL_DELEGATED(20, writev) SYSCALL_DELEGATED(21, access) SYSCALL_HANDLED(24, sched_yield) SYSCALL_HANDLED(28, madvise) +SYSCALL_HANDLED(34, pause) SYSCALL_HANDLED(39, getpid) SYSCALL_HANDLED(56, clone) SYSCALL_HANDLED(59, execve) diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 30347d7b..20d0cac4 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -95,6 +95,8 @@ SYSCALL_DECLARE(rt_sigreturn) regs -= 16; memcpy(regs, proc->sigstack, 128); + proc->sigmask.__val[0] = proc->supmask.__val[0]; + return proc->sigrc; } @@ -104,58 +106,18 @@ extern void interrupt_syscall(int all); extern int num_processors; void -check_signal(unsigned long rc, unsigned long *regs) +do_signal(unsigned long rc, unsigned long *regs, struct process *proc, struct sig_pending *pending) { - struct process *proc; struct k_sigaction *k; int sig; - struct sig_pending *pending; - struct sig_pending *next; - struct list_head *head; - ihk_spinlock_t *lock; __sigset_t w; int irqstate; - if(clv == NULL) - return; - proc = cpu_local_var(current); - if(proc == NULL || proc->pid == 0) - return; - - w = proc->sigmask.__val[0]; - lock = &proc->sigshared->lock; - head = &proc->sigshared->sigpending; - pending = NULL; - irqstate = ihk_mc_spinlock_lock(lock); - list_for_each_entry_safe(pending, next, head, list){ - if(!(pending->sigmask.__val[0] & w)){ - list_del(&pending->list); - break; - } - } - if(&pending->list == head) - pending = NULL; - ihk_mc_spinlock_unlock(lock, irqstate); - - if(!pending){ - lock = &proc->sigpendinglock; - head = &proc->sigpending; - irqstate = ihk_mc_spinlock_lock(lock); - list_for_each_entry_safe(pending, next, head, list){ - if(!(pending->sigmask.__val[0] & w)){ - list_del(&pending->list); - break; - } - } - if(&pending->list == head) - pending = NULL; - ihk_mc_spinlock_unlock(lock, irqstate); - } - if(!pending) - return; - for(w = pending->sigmask.__val[0], sig = 0; w; sig++, w >>= 1); + if(sig == SIGKILL || sig == SIGTERM) + terminate(0, sig, (ihk_mc_user_context_t *)regs[14]); + irqstate = ihk_mc_spinlock_lock(&proc->sighandler->lock); if(regs == NULL){ /* call from syscall */ asm volatile ("movq %%gs:132,%0" : "=r" (regs)); @@ -174,14 +136,6 @@ check_signal(unsigned long rc, unsigned long *regs) else if(k->sa.sa_handler){ unsigned long *usp; /* user stack */ - if(regs[14] & 0x8000000000000000){ // kernel addr - int flag = ihk_mc_spinlock_lock(lock); - list_add(&pending->list, head); - ihk_mc_spinlock_unlock(lock, flag); - ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); - return; - } - usp = (void *)regs[14]; memcpy(proc->sigstack, regs, 128); proc->sigrc = rc; @@ -192,6 +146,7 @@ check_signal(unsigned long rc, unsigned long *regs) regs[11] = (unsigned long)k->sa.sa_handler; regs[14] = (unsigned long)usp; kfree(pending); + proc->sigmask.__val[0] |= pending->sigmask.__val[0]; ihk_mc_spinlock_unlock(&proc->sighandler->lock, irqstate); } else{ @@ -203,6 +158,63 @@ check_signal(unsigned long rc, unsigned long *regs) } } +void +check_signal(unsigned long rc, unsigned long *regs) +{ + struct process *proc; + struct sig_pending *pending; + struct sig_pending *next; + struct list_head *head; + ihk_spinlock_t *lock; + __sigset_t w; + int irqstate; + + if(clv == NULL) + return; + proc = cpu_local_var(current); + if(proc == NULL || proc->pid == 0) + return; + + if(regs != NULL && (regs[14] & 0x8000000000000000)) + return; + + for(;;){ + w = proc->sigmask.__val[0]; + lock = &proc->sigshared->lock; + head = &proc->sigshared->sigpending; + pending = NULL; + irqstate = ihk_mc_spinlock_lock(lock); + list_for_each_entry_safe(pending, next, head, list){ + if(!(pending->sigmask.__val[0] & w)){ + list_del(&pending->list); + break; + } + } + if(&pending->list == head) + pending = NULL; + ihk_mc_spinlock_unlock(lock, irqstate); + + if(!pending){ + lock = &proc->sigpendinglock; + head = &proc->sigpending; + irqstate = ihk_mc_spinlock_lock(lock); + list_for_each_entry_safe(pending, next, head, list){ + if(!(pending->sigmask.__val[0] & w)){ + list_del(&pending->list); + break; + } + } + if(&pending->list == head) + pending = NULL; + ihk_mc_spinlock_unlock(lock, irqstate); + } + if(!pending) + return; + + do_signal(rc, regs, proc, pending); + } +} + unsigned long do_kill(int pid, int tid, int sig) { @@ -284,6 +296,7 @@ do_kill(int pid, int tid, int sig) } else{ list_add_tail(&pending->list, head); + proc->sigevent = 1; } } if(tid == -1){ @@ -297,17 +310,16 @@ do_kill(int pid, int tid, int sig) } void -set_signal(int sig, unsigned long *regs, int nonmaskable) +set_signal(int sig, unsigned long *regs) { struct process *proc = cpu_local_var(current); if(proc == NULL || proc->pid == 0) return; - if(__sigmask(sig) & proc->sigmask.__val[0]){ - if(nonmaskable){ - terminate(0, sig, (ihk_mc_user_context_t *)regs[14]); - } - } - do_kill(proc->pid, proc->tid, sig); + if((__sigmask(sig) & proc->sigmask.__val[0]) || + (regs[14] & 0x8000000000000000)) + terminate(0, sig, (ihk_mc_user_context_t *)regs[14]); + else + do_kill(proc->pid, proc->tid, sig); } diff --git a/kernel/mem.c b/kernel/mem.c index 8c05258a..cfe4decf 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -164,7 +164,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = { .priv = NULL, }; -void set_signal(int, unsigned long *, int); +void set_signal(int, unsigned long *); void check_signal(long, unsigned long *); static void unhandled_page_fault(struct process *proc, void *fault_addr, void *regs) @@ -234,10 +234,10 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs) reason, regs, error); unhandled_page_fault(proc, fault_addr, regs); if (error == -ERANGE) { - set_signal(SIGBUS, regs, 1); + set_signal(SIGBUS, regs); } else { - set_signal(SIGSEGV, regs, 1); + set_signal(SIGSEGV, regs); } check_signal(0, regs); goto out; diff --git a/kernel/syscall.c b/kernel/syscall.c index 30b301f7..60c95959 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -93,6 +93,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = { }; void check_signal(long rc, unsigned long *regs); +void do_signal(long rc, unsigned long *regs, struct process *proc, struct sig_pending *pending); int copy_from_user(struct process *, void *, const void *, size_t); int copy_to_user(struct process *, void *, const void *, size_t); @@ -1154,37 +1155,132 @@ SYSCALL_DECLARE(rt_sigpending) SYSCALL_DECLARE(rt_sigtimedwait) { -/* -sigset_t * -siginfo_t * -struct timespec * -size_t -*/ - return 0; + struct process *proc = cpu_local_var(current); + const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg0(ctx); + siginfo_t *info = (siginfo_t *)ihk_mc_syscall_arg1(ctx); + void *timeout = (void *)ihk_mc_syscall_arg2(ctx); + size_t sigsetsize = (size_t)ihk_mc_syscall_arg3(ctx); + siginfo_t winfo; + __sigset_t wset; + long wtimeout[2]; + + if (sigsetsize > sizeof(sigset_t)) + return -EINVAL; + + memset(&winfo, '\0', sizeof winfo); + if(copy_from_user(proc, &wset, set, sizeof wset)) + return -EFAULT; + if(copy_from_user(proc, wtimeout, timeout, sizeof wtimeout)) + return -EFAULT; + if(copy_to_user(proc, info, &winfo, sizeof winfo)) + return -EFAULT; + + return -EOPNOTSUPP; } SYSCALL_DECLARE(rt_sigqueueinfo) { -/* -pid_t -int -siginfo_t * -*/ - return 0; + struct process *proc = cpu_local_var(current); + int pid = (int)ihk_mc_syscall_arg0(ctx); + int sig = (int)ihk_mc_syscall_arg1(ctx); + siginfo_t *info = (siginfo_t *)ihk_mc_syscall_arg2(ctx); + siginfo_t winfo; + + if(copy_from_user(proc, &winfo, info, sizeof winfo)) + return -EFAULT; + + return -EOPNOTSUPP; +} + +static int +do_sigsuspend(struct process *proc, const sigset_t *set) +{ + __sigset_t wset; + int flag; + struct sig_pending *pending; + struct list_head *head; + ihk_spinlock_t *lock; + + wset = set->__val[0]; + wset &= ~__sigmask(SIGKILL); + wset &= ~__sigmask(SIGTERM); + proc->sigmask.__val[0] = wset; + + for(;;){ + while(proc->sigevent == 0); + proc->sigevent = 0; + + lock = &proc->sigshared->lock; + head = &proc->sigshared->sigpending; + flag = ihk_mc_spinlock_lock(lock); + list_for_each_entry(pending, head, list){ + if(!(pending->sigmask.__val[0] & wset)) + break; + } + + if(&pending->list == head){ + ihk_mc_spinlock_unlock(lock, flag); + + lock = &proc->sigpendinglock; + head = &proc->sigpending; + flag = ihk_mc_spinlock_lock(lock); + list_for_each_entry(pending, head, list){ + if(!(pending->sigmask.__val[0] & wset)) + break; + } + } + if(&pending->list == head){ + ihk_mc_spinlock_unlock(lock, flag); + continue; + } + + list_del(&pending->list); + ihk_mc_spinlock_unlock(lock, flag); + do_signal(-EINTR, NULL, proc, pending); + break; + } + return -EINTR; +} + + +SYSCALL_DECLARE(pause) +{ + struct process *proc = cpu_local_var(current); + + return do_sigsuspend(proc, &proc->sigmask); } SYSCALL_DECLARE(rt_sigsuspend) { -/* -sigset_t * -size_t -*/ - return 0; + struct process *proc = cpu_local_var(current); + const sigset_t *set = (const sigset_t *)ihk_mc_syscall_arg0(ctx); + size_t sigsetsize = (size_t)ihk_mc_syscall_arg1(ctx); + sigset_t wset; + + if (sigsetsize > sizeof(sigset_t)) + return -EINVAL; + if(copy_from_user(proc, &wset, set, sizeof wset)) + return -EFAULT; + + return do_sigsuspend(proc, &wset); } SYSCALL_DECLARE(sigaltstack) { - return 0; + struct process *proc = cpu_local_var(current); + const stack_t *ss = (const stack_t *)ihk_mc_syscall_arg0(ctx); + 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)) + return -EFAULT; + if(ss) + if(copy_from_user(proc, &wss, ss, sizeof wss)) + return -EFAULT; + + return -EOPNOTSUPP; } SYSCALL_DECLARE(madvise)