From 1ff4cf68c22fd268d629c30141dc3d58f8923347 Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Thu, 16 Jul 2015 16:33:14 +0900 Subject: [PATCH] support SA_RESTART flag and restart syscall --- arch/x86/kernel/cpu.c | 10 ++-- arch/x86/kernel/include/syscall_list.h | 13 +++++ arch/x86/kernel/syscall.c | 76 +++++++++++++++++++++----- kernel/mem.c | 4 +- kernel/syscall.c | 4 +- 5 files changed, 85 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index 18e255d2..82167273 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -604,7 +604,7 @@ void setup_x86_ap(void (*next_func)(void)) void arch_show_interrupt_context(const void *reg); void set_signal(int sig, void *regs, struct siginfo *info); -void check_signal(unsigned long rc, void *regs); +void check_signal(unsigned long, void *, int); extern void tlb_flush_handler(int vector); void handle_interrupt(int vector, struct x86_user_context *regs) @@ -678,7 +678,7 @@ void handle_interrupt(int vector, struct x86_user_context *regs) } } - check_signal(0, regs); + check_signal(0, regs, 0); check_need_resched(); } @@ -691,7 +691,7 @@ void gpe_handler(struct x86_user_context *regs) panic("gpe_handler"); } set_signal(SIGSEGV, regs, NULL); - check_signal(0, regs); + check_signal(0, regs, 0); check_need_resched(); // panic("GPF"); } @@ -719,7 +719,7 @@ void debug_handler(struct x86_user_context *regs) memset(&info, '\0', sizeof info); info.si_code = si_code; set_signal(SIGTRAP, regs, &info); - check_signal(0, regs); + check_signal(0, regs, 0); check_need_resched(); } @@ -736,7 +736,7 @@ void int3_handler(struct x86_user_context *regs) memset(&info, '\0', sizeof info); info.si_code = TRAP_BRKPT; set_signal(SIGTRAP, regs, &info); - check_signal(0, regs); + check_signal(0, regs, 0); check_need_resched(); } diff --git a/arch/x86/kernel/include/syscall_list.h b/arch/x86/kernel/include/syscall_list.h index ca9d08e8..5c356af1 100644 --- a/arch/x86/kernel/include/syscall_list.h +++ b/arch/x86/kernel/include/syscall_list.h @@ -26,6 +26,7 @@ SYSCALL_DELEGATED(2, open) SYSCALL_HANDLED(3, close) SYSCALL_DELEGATED(4, stat) SYSCALL_DELEGATED(5, fstat) +SYSCALL_DELEGATED(7, poll) SYSCALL_DELEGATED(8, lseek) SYSCALL_HANDLED(9, mmap) SYSCALL_HANDLED(10, mprotect) @@ -39,6 +40,7 @@ SYSCALL_DELEGATED(17, pread64) SYSCALL_DELEGATED(18, pwrite64) SYSCALL_DELEGATED(20, writev) SYSCALL_DELEGATED(21, access) +SYSCALL_DELEGATED(23, select) SYSCALL_HANDLED(24, sched_yield) SYSCALL_HANDLED(25, mremap) SYSCALL_HANDLED(26, msync) @@ -48,6 +50,7 @@ SYSCALL_HANDLED(29, shmget) SYSCALL_HANDLED(30, shmat) SYSCALL_HANDLED(31, shmctl) SYSCALL_HANDLED(34, pause) +SYSCALL_DELEGATED(35, nanosleep) SYSCALL_HANDLED(39, getpid) SYSCALL_HANDLED(56, clone) SYSCALL_DELEGATED(57, fork) @@ -57,7 +60,10 @@ SYSCALL_HANDLED(60, exit) SYSCALL_HANDLED(61, wait4) SYSCALL_HANDLED(62, kill) SYSCALL_DELEGATED(63, uname) +SYSCALL_DELEGATED(65, semop) SYSCALL_HANDLED(67, shmdt) +SYSCALL_DELEGATED(69, msgsnd) +SYSCALL_DELEGATED(70, msgrcv) SYSCALL_DELEGATED(72, fcntl) SYSCALL_DELEGATED(79, getcwd) SYSCALL_DELEGATED(89, readlink) @@ -104,18 +110,25 @@ SYSCALL_DELEGATED(201, time) SYSCALL_HANDLED(202, futex) SYSCALL_HANDLED(203, sched_setaffinity) SYSCALL_HANDLED(204, sched_getaffinity) +SYSCALL_DELEGATED(208, io_getevents) SYSCALL_HANDLED(216, remap_file_pages) SYSCALL_DELEGATED(217, getdents64) SYSCALL_HANDLED(218, set_tid_address) +SYSCALL_DELEGATED(220, semtimedop) +SYSCALL_DELEGATED(230, clock_nanosleep) SYSCALL_HANDLED(231, exit_group) +SYSCALL_DELEGATED(232, epoll_wait) SYSCALL_HANDLED(234, tgkill) SYSCALL_HANDLED(237, mbind) SYSCALL_HANDLED(238, set_mempolicy) SYSCALL_HANDLED(239, get_mempolicy) SYSCALL_HANDLED(247, waitid) SYSCALL_HANDLED(256, migrate_pages) +SYSCALL_DELEGATED(270, pselect6) +SYSCALL_DELEGATED(271, ppoll) SYSCALL_HANDLED(273, set_robust_list) SYSCALL_HANDLED(279, move_pages) +SYSCALL_DELEGATED(281, epoll_pwait) SYSCALL_HANDLED(282, signalfd) SYSCALL_HANDLED(289, signalfd4) #ifdef DCFA_KMOD diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index edc44d6b..b292ac1c 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -30,6 +30,7 @@ int copy_from_user(void *dst, const void *src, size_t siz); int copy_to_user(void *dst, const void *src, size_t siz); int write_process_vm(struct process_vm *vm, void *dst, const void *src, size_t siz); long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact); +long syscall(int num, ihk_mc_user_context_t *ctx); extern void save_fp_regs(struct process *proc); //#define DEBUG_PRINT_SC @@ -152,6 +153,8 @@ struct sigsp { unsigned long sigrc; unsigned long sigmask; int ssflags; + int num; + int restart; siginfo_t info; }; @@ -160,18 +163,19 @@ SYSCALL_DECLARE(rt_sigreturn) struct process *proc = cpu_local_var(current); struct x86_user_context *regs; struct sigsp *sigsp; - long rc = -EFAULT; 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))) + return -EFAULT; proc->sigmask.__val[0] = sigsp->sigmask; proc->sigstack.ss_flags = sigsp->ssflags; - if(copy_from_user(regs, &sigsp->regs, sizeof(struct x86_user_context))) - return rc; - copy_from_user(&rc, &sigsp->sigrc, sizeof(long)); - return rc; + if(sigsp->restart){ + return syscall(sigsp->num, (ihk_mc_user_context_t *)regs); + } + return sigsp->sigrc; } extern struct cpu_local_var *clv; @@ -495,9 +499,41 @@ void ptrace_report_signal(struct process *proc, int sig) schedule(); dkprintf("ptrace_report_signal,wake up\n"); } +static int +isrestart(int num, unsigned long rc, int sig, int restart) +{ + if(num == 0 || rc != -EINTR) + return 0; + switch(num){ + case __NR_pause: + case __NR_rt_sigsuspend: + case __NR_rt_sigtimedwait: +// case __NR_rt_sigwaitinfo: + case __NR_epoll_wait: + case __NR_epoll_pwait: + case __NR_poll: + case __NR_ppoll: + case __NR_select: + case __NR_pselect6: + case __NR_msgrcv: + case __NR_msgsnd: + case __NR_semop: + case __NR_semtimedop: + case __NR_clock_nanosleep: + case __NR_nanosleep: +// case __NR_usleep: + case __NR_io_getevents: + return 0; + } + if(sig == SIGCHLD) + return 1; + if(restart) + return 1; + return 0; +} void -do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending) +do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pending *pending, int num) { struct x86_user_context *regs = regs0; struct k_sigaction *k; @@ -564,6 +600,10 @@ do_signal(unsigned long rc, void *regs0, struct process *proc, struct sig_pendin } 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; @@ -697,6 +737,9 @@ getsigpending(struct process *proc, int delflag){ struct sig_pending *pending; __sigset_t w; int irqstate; + __sigset_t x; + int sig; + struct k_sigaction *k; w = proc->sigmask.__val[0]; @@ -705,11 +748,18 @@ getsigpending(struct process *proc, int delflag){ for(;;){ irqstate = ihk_mc_spinlock_lock(lock); list_for_each_entry_safe(pending, next, head, list){ - if(!(pending->sigmask.__val[0] & w)){ - if(delflag) - list_del(&pending->list); - ihk_mc_spinlock_unlock(lock, irqstate); - return pending; + for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1); + k = proc->sighandler->action + sig - 1; + if(delflag || + (sig != SIGCHLD && sig != SIGURG) || + (k->sa.sa_handler != (void *)1 && + k->sa.sa_handler != NULL)){ + if(!(pending->sigmask.__val[0] & w)){ + if(delflag) + list_del(&pending->list); + ihk_mc_spinlock_unlock(lock, irqstate); + return pending; + } } } ihk_mc_spinlock_unlock(lock, irqstate); @@ -730,7 +780,7 @@ hassigpending(struct process *proc) } void -check_signal(unsigned long rc, void *regs0) +check_signal(unsigned long rc, void *regs0, int num) { struct x86_user_context *regs = regs0; struct process *proc; @@ -770,7 +820,7 @@ check_signal(unsigned long rc, void *regs0) return; } - do_signal(rc, regs, proc, pending); + do_signal(rc, regs, proc, pending, num); } } diff --git a/kernel/mem.c b/kernel/mem.c index fbed4f43..b0aa458a 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -171,7 +171,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = { }; void set_signal(int sig, void *regs, struct siginfo *info); -void check_signal(unsigned long rc, void *regs); +void check_signal(unsigned long, void *, int); int gencore(struct process *, void *, struct coretable **, int *); void freecore(struct coretable **); @@ -416,7 +416,7 @@ static void page_fault_handler(void *fault_addr, uint64_t reason, void *regs) info._sifields._sigfault.si_addr = fault_addr; set_signal(SIGSEGV, regs, &info); } - check_signal(0, regs); + check_signal(0, regs, 0); goto out; } diff --git a/kernel/syscall.c b/kernel/syscall.c index b67d7e52..b9c3c415 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -94,7 +94,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = { #undef SYSCALL_DELEGATED }; -void check_signal(unsigned long rc, void *regs); +void check_signal(unsigned long, void *, int); 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, struct siginfo *info, int ptracecont); extern struct sigpending *hassigpending(struct process *proc); @@ -6059,7 +6059,7 @@ long syscall(int num, ihk_mc_user_context_t *ctx) l = syscall_generic_forwarding(num, ctx); } - check_signal(l, NULL); + check_signal(l, NULL, num); check_need_resched(); if (cpu_local_var(current)->ftn->ptrace) {