diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index d7f2ec55..886964b1 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -405,7 +405,7 @@ void setup_x86_ap(void (*next_func)(void)) } void arch_show_interrupt_context(const void *reg); -void set_signal(int sig, void *regs); +void set_signal(int sig, void *regs, struct siginfo *info); void check_signal(unsigned long rc, void *regs); extern void tlb_flush_handler(int vector); @@ -452,10 +452,13 @@ void handle_interrupt(int vector, struct x86_regs *regs) void gpe_handler(struct x86_regs *regs) { + struct siginfo info; + kprintf("General protection fault (err: %lx, %lx:%lx)\n", regs->error, regs->cs, regs->rip); arch_show_interrupt_context(regs); - set_signal(SIGILL, regs); + memset(&info, '\0', sizeof info); + set_signal(SIGILL, regs, &info); check_signal(0, regs); check_need_resched(); // panic("GPF"); diff --git a/arch/x86/kernel/include/signal.h b/arch/x86/kernel/include/signal.h index 33820ce9..2d1a8717 100644 --- a/arch/x86/kernel/include/signal.h +++ b/arch/x86/kernel/include/signal.h @@ -36,13 +36,13 @@ struct sigaction { sigset_t sa_mask; }; -#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 +#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; @@ -71,6 +71,16 @@ typedef struct siginfo { int si_errno; /* If non-zero, an errno value associated with this signal, as defined in . */ int si_code; /* Signal code. */ +#define SI_USER 0 /* sent by kill, sigsend, raise */ +#define SI_KERNEL 0x80 /* sent by the kernel from somewhere */ +#define SI_QUEUE -1 /* sent by sigqueue */ +#define SI_TIMER __SI_CODE(__SI_TIMER,-2) /* sent by timer expiration */ +#define SI_MESGQ __SI_CODE(__SI_MESGQ,-3) /* sent by real time mesq state change + */ +#define SI_ASYNCIO -4 /* sent by AIO completion */ +#define SI_SIGIO -5 /* sent by queued SIGIO */ +#define SI_TKILL -6 /* sent by tkill system call */ +#define SI_DETHREAD -7 /* sent by execve() killing subsidiary threads */ union { int _pad[__SI_PAD_SIZE]; @@ -117,6 +127,29 @@ typedef struct siginfo { } _sifields; } siginfo_t; +struct signalfd_siginfo { + unsigned int ssi_signo; + int ssi_errno; + int ssi_code; + unsigned int ssi_pid; + unsigned int ssi_uid; + int ssi_fd; + unsigned int ssi_tid; + unsigned int ssi_band; + unsigned int ssi_overrun; + unsigned int ssi_trapno; + int ssi_status; + int ssi_int; + unsigned long ssi_ptr; + unsigned long ssi_utime; + unsigned long ssi_stime; + unsigned long ssi_addr; + unsigned short ssi_addr_lsb; + + char __pad[46]; +}; + + #define SIGHUP 1 #define SIGINT 2 #define SIGQUIT 3 diff --git a/arch/x86/kernel/include/syscall_list.h b/arch/x86/kernel/include/syscall_list.h index adc3a94e..7f95a451 100644 --- a/arch/x86/kernel/include/syscall_list.h +++ b/arch/x86/kernel/include/syscall_list.h @@ -84,6 +84,8 @@ SYSCALL_HANDLED(218, set_tid_address) SYSCALL_HANDLED(231, exit_group) SYSCALL_HANDLED(234, tgkill) SYSCALL_HANDLED(273, set_robust_list) +SYSCALL_HANDLED(282, signalfd) +SYSCALL_HANDLED(289, signalfd4) #ifdef DCFA_KMOD SYSCALL_HANDLED(303, mod_call) #endif diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index bdb5822a..aa82716e 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -135,6 +135,7 @@ struct sigsp { unsigned long sigrc; unsigned long sigmask; int ssflags; + siginfo_t info; }; SYSCALL_DECLARE(rt_sigreturn) @@ -157,7 +158,7 @@ SYSCALL_DECLARE(rt_sigreturn) } extern struct cpu_local_var *clv; -extern unsigned long do_kill(int pid, int tid, int sig); +extern unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info); extern void interrupt_syscall(int all, int pid); extern int num_processors; @@ -253,12 +254,17 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin } sigsp->sigmask = mask; sigsp->ssflags = ssflags; + memcpy(&sigsp->info, &pending->info, sizeof(siginfo_t)); usp = (unsigned long *)sigsp; usp--; *usp = (unsigned long)k->sa.sa_restorer; regs->rdi = (unsigned long)sig; + if(k->sa.sa_flags & SA_SIGINFO){ + regs->rsi = (unsigned long)&sigsp->info; + regs->rdx = 0; + } regs->rip = (unsigned long)k->sa.sa_handler; regs->rsp = (unsigned long)usp; @@ -374,7 +380,7 @@ check_signal(unsigned long rc, void *regs0) } unsigned long -do_kill(int pid, int tid, int sig) +do_kill(int pid, int tid, int sig, siginfo_t *info) { struct cpu_local_var *v; struct process *p; @@ -435,9 +441,9 @@ do_kill(int pid, int tid, int sig) ihk_mc_spinlock_unlock(&(v->runq_lock), irqstate); } for(i = 0; i < n; i++) - rc = do_kill(pids[i], -1, sig); + rc = do_kill(pids[i], -1, sig, info); if(sendme) - rc = do_kill(proc->pid, -1, sig); + rc = do_kill(proc->pid, -1, sig, info); kfree(pids); return rc; @@ -563,11 +569,12 @@ do_kill(int pid, int tid, int sig) if(pending == NULL){ doint = 1; pending = kmalloc(sizeof(struct sig_pending), IHK_MC_AP_NOWAIT); - pending->sigmask.__val[0] = mask; if(!pending){ rc = -ENOMEM; } else{ + pending->sigmask.__val[0] = mask; + memcpy(&pending->info, info, sizeof(siginfo_t)); list_add_tail(&pending->list, head); tproc->sigevent = 1; } @@ -625,7 +632,7 @@ do_kill(int pid, int tid, int sig) } void -set_signal(int sig, void *regs0) +set_signal(int sig, void *regs0, siginfo_t *info) { struct x86_regs *regs = regs0; struct process *proc = cpu_local_var(current); @@ -639,5 +646,5 @@ set_signal(int sig, void *regs0) terminate(0, sig | 0x80, (ihk_mc_user_context_t *)regs->rsp); } else - do_kill(proc->pid, proc->tid, sig); + do_kill(proc->pid, proc->tid, sig, info); } diff --git a/executer/include/uprotocol.h b/executer/include/uprotocol.h index 8a9b998b..5c630362 100644 --- a/executer/include/uprotocol.h +++ b/executer/include/uprotocol.h @@ -153,6 +153,7 @@ struct signal_desc { int pid; int tid; int sig; + char info[128]; }; #endif diff --git a/executer/kernel/control.c b/executer/kernel/control.c index 9e8ed75e..5857aeb7 100644 --- a/executer/kernel/control.c +++ b/executer/kernel/control.c @@ -270,27 +270,57 @@ static long mcexec_start_image(ihk_os_t os, return 0; } +static DECLARE_WAIT_QUEUE_HEAD(signalq); + static long mcexec_send_signal(ihk_os_t os, struct signal_desc *sigparam) { struct ikc_scd_packet isp; struct mcctrl_channel *c; struct mcctrl_usrdata *usrdata = ihk_host_os_get_usrdata(os); struct signal_desc sig; + struct mcctrl_signal msig[2]; + struct mcctrl_signal *msigp; + int rc; if (copy_from_user(&sig, sigparam, sizeof(struct signal_desc))) { return -EFAULT; } + + msigp = msig; + if(((unsigned long)msig & 0xfffffffffffff000L) != + ((unsigned long)(msig + 1) & 0xfffffffffffff000L)) + msigp++; + memset(msigp, '\0', sizeof msig); + msigp->sig = sig.sig; + msigp->pid = sig.pid; + msigp->tid = sig.tid; + memcpy(&msigp->info, &sig.info, 128); + c = usrdata->channels; isp.msg = SCD_MSG_SEND_SIGNAL; isp.ref = sig.cpu; isp.pid = sig.pid; - isp.arg = (long)sig.tid << 32 | (sig.sig & 0x00000000ffffffffL); + isp.arg = virt_to_phys(msigp); - mcctrl_ikc_send(os, sig.cpu, &isp); + if((rc = mcctrl_ikc_send(os, sig.cpu, &isp)) < 0){ + printk("mcexec_send_signal: mcctrl_ikc_send ret=%d\n", rc); + return rc; + } + wait_event_interruptible(signalq, msigp->cond != 0); return 0; } +void +sig_done(unsigned long arg, int err) +{ + struct mcctrl_signal *msigp; + + msigp = phys_to_virt(arg); + msigp->cond = 1; + wake_up_interruptible(&signalq); +} + static long mcexec_get_cpu(ihk_os_t os) { struct ihk_cpu_info *info; diff --git a/executer/kernel/ikc.c b/executer/kernel/ikc.c index 5612c77c..92aee2fd 100644 --- a/executer/kernel/ikc.c +++ b/executer/kernel/ikc.c @@ -44,6 +44,7 @@ int mcexec_syscall(struct mcctrl_channel *c, int pid, unsigned long arg); void procfs_create(void *__os, int ref, int osnum, int pid, unsigned long arg); void procfs_delete(void *__os, int osnum, unsigned long arg); void procfs_answer(unsigned long arg, int err); +void sig_done(unsigned long arg, int err); static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, void *__packet, void *__os) @@ -79,8 +80,11 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, case SCD_MSG_PROCFS_ANSWER: procfs_answer(pisp->arg, pisp->err); break; - } + case SCD_MSG_SEND_SIGNAL: + sig_done(pisp->arg, pisp->err); + break; + } return 0; } diff --git a/executer/kernel/mcctrl.h b/executer/kernel/mcctrl.h index 1abe4550..d4b0e810 100644 --- a/executer/kernel/mcctrl.h +++ b/executer/kernel/mcctrl.h @@ -145,6 +145,14 @@ struct mcctrl_usrdata { void **keys; }; +struct mcctrl_signal { + int cond; + int sig; + int pid; + int tid; + char info[128]; +}; + int mcctrl_ikc_send(ihk_os_t os, int cpu, struct ikc_scd_packet *pisp); int mcctrl_ikc_send_msg(ihk_os_t os, int cpu, int msg, int ref, unsigned long arg); int mcctrl_ikc_is_valid_thread(ihk_os_t os, int cpu); diff --git a/executer/user/mcexec.c b/executer/user/mcexec.c index 1822674a..f3cc9a8b 100644 --- a/executer/user/mcexec.c +++ b/executer/user/mcexec.c @@ -820,6 +820,7 @@ sendsig(int sig, siginfo_t *siginfo, void *context) sigdesc.pid = (int)pid; sigdesc.tid = remote_tid; sigdesc.sig = sig; + memcpy(&sigdesc.info, siginfo, 128); if (ioctl(fd, MCEXEC_UP_SEND_SIGNAL, &sigdesc) != 0) { perror("send_signal"); close(fd); diff --git a/kernel/host.c b/kernel/host.c index c5bb31ab..7061d055 100644 --- a/kernel/host.c +++ b/kernel/host.c @@ -496,7 +496,7 @@ static void syscall_channel_send(struct ihk_ikc_channel_desc *c, ihk_ikc_send(c, packet, 0); } -extern unsigned long do_kill(int, int, int); +extern unsigned long do_kill(int, int, int, struct siginfo *); extern void settid(struct process *proc, int mode, int newcpuid, int oldcpuid); extern void process_procfs_request(unsigned long rarg); @@ -508,6 +508,14 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, struct ikc_scd_packet pckt; int rc; struct process *proc; + struct mcctrl_signal { + int cond; + int sig; + int pid; + int tid; + struct siginfo info; + } *sp, info; + unsigned long pp; switch (packet->msg) { case SCD_MSG_INIT_CHANNEL_ACKED: @@ -540,8 +548,19 @@ static int syscall_packet_handler(struct ihk_ikc_channel_desc *c, //cpu_local_var(next) = (struct process *)packet->arg; return 0; case SCD_MSG_SEND_SIGNAL: - rc = do_kill((int)packet->pid, (int)(packet->arg >> 32), packet->arg & 0x00000000ffffffffL); - kprintf("SCD_MSG_SEND_SIGNAL: %lx, rc=%d\n", packet->arg, rc); + pp = ihk_mc_map_memory(NULL, packet->arg, sizeof(struct mcctrl_signal)); + sp = (struct mcctrl_signal *)ihk_mc_map_virtual(pp, 1, PTATTR_WRITABLE | PTATTR_ACTIVE); + memcpy(&info, sp, sizeof(struct mcctrl_signal)); + ihk_mc_unmap_virtual(sp, 1, 0); + ihk_mc_unmap_memory(NULL, pp, sizeof(struct mcctrl_signal)); + pckt.msg = SCD_MSG_SEND_SIGNAL; + pckt.err = 0; + pckt.ref = packet->ref; + pckt.arg = packet->arg; + syscall_channel_send(c, &pckt); + + rc = do_kill(info.pid, info.tid, info.sig, &info.info); + kprintf("SCD_MSG_SEND_SIGNAL: do_kill(pid=%d, tid=%d, sig=%d)=%d\n", info.pid, info.tid, info.sig, rc); return 0; case SCD_MSG_PROCFS_REQUEST: process_procfs_request(packet->arg); diff --git a/kernel/mem.c b/kernel/mem.c index 0ad1d0bc..5aea9dac 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -168,7 +168,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = { .priv = NULL, }; -void set_signal(int sig, void *regs); +void set_signal(int sig, void *regs, struct siginfo *info); void check_signal(unsigned long rc, void *regs); int gencore(struct process *, void *, struct coretable **, int *); void freecore(struct coretable **); @@ -371,16 +371,19 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs) error = page_fault_process(proc, fault_addr, reason); if (error) { + struct siginfo info; + kprintf("[%d]page_fault_handler(%p,%lx,%p):" "fault proc failed. %d\n", ihk_mc_get_processor_id(), fault_addr, reason, regs, error); unhandled_page_fault(proc, fault_addr, regs); + memset(&info, '\0', sizeof info); if (error == -ERANGE) { - set_signal(SIGBUS, regs); + set_signal(SIGBUS, regs, &info); } else { - set_signal(SIGSEGV, regs); + set_signal(SIGSEGV, regs, &info); } check_signal(0, regs); goto out; diff --git a/kernel/syscall.c b/kernel/syscall.c index 87d7132e..74d3aafa 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -95,7 +95,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = { void check_signal(unsigned long rc, void *regs); void do_signal(long rc, void *regs, struct process *proc, struct sig_pending *pending); -extern unsigned long do_kill(int pid, int tid, int sig); +extern unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info); int copy_from_user(struct process *, void *, const void *, size_t); int copy_to_user(struct process *, void *, const void *, size_t); void do_setpgid(int, int); @@ -460,7 +460,13 @@ terminate(int rc, int sig, ihk_mc_user_context_t *ctx) /* Signal parent if still attached */ ihk_mc_spinlock_lock_noirq(&ftn->parent->lock); if (ftn->parent->owner) { - do_kill(ftn->parent->owner->pid, -1, SIGCHLD); + struct siginfo info; + memset(&info, '\0', sizeof info); + info.si_signo = SIGCHLD; + info.si_code = sig? ((sig & 0x80)? 3: 2): 1; + info._sifields._sigchld.si_pid = proc->pid; + info._sifields._sigchld.si_status = ((rc & 0x00ff) << 8) | (sig & 0xff); + do_kill(ftn->parent->owner->pid, -1, SIGCHLD, &info); /* sigchld_parent(ftn->parent->owner, 0); */ @@ -1513,8 +1519,15 @@ SYSCALL_DECLARE(kill) { int pid = ihk_mc_syscall_arg0(ctx); int sig = ihk_mc_syscall_arg1(ctx); + struct process *proc = cpu_local_var(current); + struct siginfo info; - return do_kill(pid, -1, sig); + memset(&info, '\0', sizeof info); + info.si_signo = sig; + info.si_code = SI_USER; + info._sifields._kill.si_pid = proc->pid; + + return do_kill(pid, -1, sig, &info); } // see linux-2.6.34.13/kernel/signal.c @@ -1523,13 +1536,20 @@ SYSCALL_DECLARE(tgkill) int tgid = ihk_mc_syscall_arg0(ctx); int tid = ihk_mc_syscall_arg1(ctx); int sig = ihk_mc_syscall_arg2(ctx); + struct process *proc = cpu_local_var(current); + struct siginfo info; + + memset(&info, '\0', sizeof info); + info.si_signo = sig; + info.si_code = SI_TKILL; + info._sifields._kill.si_pid = proc->pid; if(tid <= 0) return -EINVAL; if(tgid <= 0 && tgid != -1) return -EINVAL; - return do_kill(tgid, tid, sig); + return do_kill(tgid, tid, sig, &info); } SYSCALL_DECLARE(setpgid) @@ -1650,6 +1670,16 @@ SYSCALL_DECLARE(rt_sigpending) return 0; } +SYSCALL_DECLARE(signalfd) +{ + return -EOPNOTSUPP; +} + +SYSCALL_DECLARE(signalfd4) +{ + return -EOPNOTSUPP; +} + SYSCALL_DECLARE(rt_sigtimedwait) { struct process *proc = cpu_local_var(current); @@ -1664,29 +1694,38 @@ SYSCALL_DECLARE(rt_sigtimedwait) if (sigsetsize > sizeof(sigset_t)) return -EINVAL; + if(set == NULL) + return -EFAULT; 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; + if(timeout) + if(copy_from_user(proc, wtimeout, timeout, sizeof wtimeout)) + return -EFAULT; + + + if(info) + if(copy_to_user(proc, info, &winfo, sizeof winfo)) + return -EFAULT; return -EOPNOTSUPP; } SYSCALL_DECLARE(rt_sigqueueinfo) { - 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; + void *winfo = (void *)ihk_mc_syscall_arg2(ctx); + struct process *proc = cpu_local_var(current); + struct siginfo info; - if(copy_from_user(proc, &winfo, info, sizeof winfo)) + if(pid <= 0) + return -ESRCH; + + if(copy_from_user(proc, &info, winfo, sizeof info)) return -EFAULT; - return -EOPNOTSUPP; + return do_kill(pid, -1, sig, &info); } static int