support SA_RESTART flag and restart syscall

This commit is contained in:
Tomoki Shirasawa
2015-07-16 16:33:14 +09:00
parent 1bc84d3feb
commit 1ff4cf68c2
5 changed files with 85 additions and 22 deletions

View File

@@ -604,7 +604,7 @@ void setup_x86_ap(void (*next_func)(void))
void arch_show_interrupt_context(const void *reg); void arch_show_interrupt_context(const void *reg);
void set_signal(int sig, void *regs, struct siginfo *info); 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); extern void tlb_flush_handler(int vector);
void handle_interrupt(int vector, struct x86_user_context *regs) 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(); check_need_resched();
} }
@@ -691,7 +691,7 @@ void gpe_handler(struct x86_user_context *regs)
panic("gpe_handler"); panic("gpe_handler");
} }
set_signal(SIGSEGV, regs, NULL); set_signal(SIGSEGV, regs, NULL);
check_signal(0, regs); check_signal(0, regs, 0);
check_need_resched(); check_need_resched();
// panic("GPF"); // panic("GPF");
} }
@@ -719,7 +719,7 @@ void debug_handler(struct x86_user_context *regs)
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_code = si_code; info.si_code = si_code;
set_signal(SIGTRAP, regs, &info); set_signal(SIGTRAP, regs, &info);
check_signal(0, regs); check_signal(0, regs, 0);
check_need_resched(); check_need_resched();
} }
@@ -736,7 +736,7 @@ void int3_handler(struct x86_user_context *regs)
memset(&info, '\0', sizeof info); memset(&info, '\0', sizeof info);
info.si_code = TRAP_BRKPT; info.si_code = TRAP_BRKPT;
set_signal(SIGTRAP, regs, &info); set_signal(SIGTRAP, regs, &info);
check_signal(0, regs); check_signal(0, regs, 0);
check_need_resched(); check_need_resched();
} }

View File

@@ -26,6 +26,7 @@ SYSCALL_DELEGATED(2, open)
SYSCALL_HANDLED(3, close) SYSCALL_HANDLED(3, close)
SYSCALL_DELEGATED(4, stat) SYSCALL_DELEGATED(4, stat)
SYSCALL_DELEGATED(5, fstat) SYSCALL_DELEGATED(5, fstat)
SYSCALL_DELEGATED(7, poll)
SYSCALL_DELEGATED(8, lseek) SYSCALL_DELEGATED(8, lseek)
SYSCALL_HANDLED(9, mmap) SYSCALL_HANDLED(9, mmap)
SYSCALL_HANDLED(10, mprotect) SYSCALL_HANDLED(10, mprotect)
@@ -39,6 +40,7 @@ SYSCALL_DELEGATED(17, pread64)
SYSCALL_DELEGATED(18, pwrite64) SYSCALL_DELEGATED(18, pwrite64)
SYSCALL_DELEGATED(20, writev) SYSCALL_DELEGATED(20, writev)
SYSCALL_DELEGATED(21, access) SYSCALL_DELEGATED(21, access)
SYSCALL_DELEGATED(23, select)
SYSCALL_HANDLED(24, sched_yield) SYSCALL_HANDLED(24, sched_yield)
SYSCALL_HANDLED(25, mremap) SYSCALL_HANDLED(25, mremap)
SYSCALL_HANDLED(26, msync) SYSCALL_HANDLED(26, msync)
@@ -48,6 +50,7 @@ SYSCALL_HANDLED(29, shmget)
SYSCALL_HANDLED(30, shmat) SYSCALL_HANDLED(30, shmat)
SYSCALL_HANDLED(31, shmctl) SYSCALL_HANDLED(31, shmctl)
SYSCALL_HANDLED(34, pause) SYSCALL_HANDLED(34, pause)
SYSCALL_DELEGATED(35, nanosleep)
SYSCALL_HANDLED(39, getpid) SYSCALL_HANDLED(39, getpid)
SYSCALL_HANDLED(56, clone) SYSCALL_HANDLED(56, clone)
SYSCALL_DELEGATED(57, fork) SYSCALL_DELEGATED(57, fork)
@@ -57,7 +60,10 @@ SYSCALL_HANDLED(60, exit)
SYSCALL_HANDLED(61, wait4) SYSCALL_HANDLED(61, wait4)
SYSCALL_HANDLED(62, kill) SYSCALL_HANDLED(62, kill)
SYSCALL_DELEGATED(63, uname) SYSCALL_DELEGATED(63, uname)
SYSCALL_DELEGATED(65, semop)
SYSCALL_HANDLED(67, shmdt) SYSCALL_HANDLED(67, shmdt)
SYSCALL_DELEGATED(69, msgsnd)
SYSCALL_DELEGATED(70, msgrcv)
SYSCALL_DELEGATED(72, fcntl) SYSCALL_DELEGATED(72, fcntl)
SYSCALL_DELEGATED(79, getcwd) SYSCALL_DELEGATED(79, getcwd)
SYSCALL_DELEGATED(89, readlink) SYSCALL_DELEGATED(89, readlink)
@@ -104,18 +110,25 @@ SYSCALL_DELEGATED(201, time)
SYSCALL_HANDLED(202, futex) SYSCALL_HANDLED(202, futex)
SYSCALL_HANDLED(203, sched_setaffinity) SYSCALL_HANDLED(203, sched_setaffinity)
SYSCALL_HANDLED(204, sched_getaffinity) SYSCALL_HANDLED(204, sched_getaffinity)
SYSCALL_DELEGATED(208, io_getevents)
SYSCALL_HANDLED(216, remap_file_pages) SYSCALL_HANDLED(216, remap_file_pages)
SYSCALL_DELEGATED(217, getdents64) SYSCALL_DELEGATED(217, getdents64)
SYSCALL_HANDLED(218, set_tid_address) SYSCALL_HANDLED(218, set_tid_address)
SYSCALL_DELEGATED(220, semtimedop)
SYSCALL_DELEGATED(230, clock_nanosleep)
SYSCALL_HANDLED(231, exit_group) SYSCALL_HANDLED(231, exit_group)
SYSCALL_DELEGATED(232, epoll_wait)
SYSCALL_HANDLED(234, tgkill) SYSCALL_HANDLED(234, tgkill)
SYSCALL_HANDLED(237, mbind) SYSCALL_HANDLED(237, mbind)
SYSCALL_HANDLED(238, set_mempolicy) SYSCALL_HANDLED(238, set_mempolicy)
SYSCALL_HANDLED(239, get_mempolicy) SYSCALL_HANDLED(239, get_mempolicy)
SYSCALL_HANDLED(247, waitid) SYSCALL_HANDLED(247, waitid)
SYSCALL_HANDLED(256, migrate_pages) SYSCALL_HANDLED(256, migrate_pages)
SYSCALL_DELEGATED(270, pselect6)
SYSCALL_DELEGATED(271, ppoll)
SYSCALL_HANDLED(273, set_robust_list) SYSCALL_HANDLED(273, set_robust_list)
SYSCALL_HANDLED(279, move_pages) SYSCALL_HANDLED(279, move_pages)
SYSCALL_DELEGATED(281, epoll_pwait)
SYSCALL_HANDLED(282, signalfd) SYSCALL_HANDLED(282, signalfd)
SYSCALL_HANDLED(289, signalfd4) SYSCALL_HANDLED(289, signalfd4)
#ifdef DCFA_KMOD #ifdef DCFA_KMOD

View File

@@ -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 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); 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 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); extern void save_fp_regs(struct process *proc);
//#define DEBUG_PRINT_SC //#define DEBUG_PRINT_SC
@@ -152,6 +153,8 @@ struct sigsp {
unsigned long sigrc; unsigned long sigrc;
unsigned long sigmask; unsigned long sigmask;
int ssflags; int ssflags;
int num;
int restart;
siginfo_t info; siginfo_t info;
}; };
@@ -160,18 +163,19 @@ SYSCALL_DECLARE(rt_sigreturn)
struct process *proc = cpu_local_var(current); struct process *proc = cpu_local_var(current);
struct x86_user_context *regs; struct x86_user_context *regs;
struct sigsp *sigsp; struct sigsp *sigsp;
long rc = -EFAULT;
asm("movq %%gs:132, %0" : "=r" (regs)); asm("movq %%gs:132, %0" : "=r" (regs));
--regs; --regs;
sigsp = (struct sigsp *)regs->gpr.rsp; 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->sigmask.__val[0] = sigsp->sigmask;
proc->sigstack.ss_flags = sigsp->ssflags; proc->sigstack.ss_flags = sigsp->ssflags;
if(copy_from_user(regs, &sigsp->regs, sizeof(struct x86_user_context))) if(sigsp->restart){
return rc; return syscall(sigsp->num, (ihk_mc_user_context_t *)regs);
copy_from_user(&rc, &sigsp->sigrc, sizeof(long)); }
return rc; return sigsp->sigrc;
} }
extern struct cpu_local_var *clv; extern struct cpu_local_var *clv;
@@ -495,9 +499,41 @@ void ptrace_report_signal(struct process *proc, int sig)
schedule(); schedule();
dkprintf("ptrace_report_signal,wake up\n"); 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 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 x86_user_context *regs = regs0;
struct k_sigaction *k; 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->sigmask = mask;
sigsp->ssflags = ssflags; 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)); memcpy(&sigsp->info, &pending->info, sizeof(siginfo_t));
usp = (unsigned long *)sigsp; usp = (unsigned long *)sigsp;
@@ -697,6 +737,9 @@ getsigpending(struct process *proc, int delflag){
struct sig_pending *pending; struct sig_pending *pending;
__sigset_t w; __sigset_t w;
int irqstate; int irqstate;
__sigset_t x;
int sig;
struct k_sigaction *k;
w = proc->sigmask.__val[0]; w = proc->sigmask.__val[0];
@@ -705,11 +748,18 @@ getsigpending(struct process *proc, int delflag){
for(;;){ for(;;){
irqstate = ihk_mc_spinlock_lock(lock); irqstate = ihk_mc_spinlock_lock(lock);
list_for_each_entry_safe(pending, next, head, list){ list_for_each_entry_safe(pending, next, head, list){
if(!(pending->sigmask.__val[0] & w)){ for(x = pending->sigmask.__val[0], sig = 0; x; sig++, x >>= 1);
if(delflag) k = proc->sighandler->action + sig - 1;
list_del(&pending->list); if(delflag ||
ihk_mc_spinlock_unlock(lock, irqstate); (sig != SIGCHLD && sig != SIGURG) ||
return pending; (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); ihk_mc_spinlock_unlock(lock, irqstate);
@@ -730,7 +780,7 @@ hassigpending(struct process *proc)
} }
void void
check_signal(unsigned long rc, void *regs0) check_signal(unsigned long rc, void *regs0, int num)
{ {
struct x86_user_context *regs = regs0; struct x86_user_context *regs = regs0;
struct process *proc; struct process *proc;
@@ -770,7 +820,7 @@ check_signal(unsigned long rc, void *regs0)
return; return;
} }
do_signal(rc, regs, proc, pending); do_signal(rc, regs, proc, pending, num);
} }
} }

View File

@@ -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 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 *); int gencore(struct process *, void *, struct coretable **, int *);
void freecore(struct coretable **); 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; info._sifields._sigfault.si_addr = fault_addr;
set_signal(SIGSEGV, regs, &info); set_signal(SIGSEGV, regs, &info);
} }
check_signal(0, regs); check_signal(0, regs, 0);
goto out; goto out;
} }

View File

@@ -94,7 +94,7 @@ static char *syscall_name[] MCKERNEL_UNUSED = {
#undef SYSCALL_DELEGATED #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); 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 unsigned long do_kill(int pid, int tid, int sig, struct siginfo *info, int ptracecont);
extern struct sigpending *hassigpending(struct process *proc); 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); l = syscall_generic_forwarding(num, ctx);
} }
check_signal(l, NULL); check_signal(l, NULL, num);
check_need_resched(); check_need_resched();
if (cpu_local_var(current)->ftn->ptrace) { if (cpu_local_var(current)->ftn->ptrace) {