From 221f2c05177435938a13b6670d44bb66581a012b Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Fri, 26 Jul 2013 11:53:00 +0900 Subject: [PATCH] support SIGSEGV(page fault) and SIGILL(general protection error) --- arch/x86/kernel/cpu.c | 5 +- arch/x86/kernel/include/signal.h | 36 ++++++++++++++ arch/x86/kernel/syscall.c | 81 ++++++++++++++++++++++++++++++ kernel/mem.c | 6 ++- kernel/syscall.c | 84 +++++++++++++++----------------- 5 files changed, 163 insertions(+), 49 deletions(-) diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index c3b37677..a649f950 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -373,12 +373,15 @@ void handle_interrupt(int vector, struct x86_regs *regs) } } +void sigill(void *); + 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); - panic("GPF"); + sigill(regs); + // panic("GPF"); } void x86_issue_ipi(unsigned int apicid, unsigned int low) diff --git a/arch/x86/kernel/include/signal.h b/arch/x86/kernel/include/signal.h index 6a35e5b6..ea3fcf99 100644 --- a/arch/x86/kernel/include/signal.h +++ b/arch/x86/kernel/include/signal.h @@ -16,3 +16,39 @@ struct sigaction { struct k_sigaction { struct sigaction sa; }; + +#define SIGHUP 1 +#define SIGINT 2 +#define SIGQUIT 3 +#define SIGILL 4 +#define SIGTRAP 5 +#define SIGABRT 6 +#define SIGIOT 6 +#define SIGBUS 7 +#define SIGFPE 8 +#define SIGKILL 9 +#define SIGUSR1 10 +#define SIGSEGV 11 +#define SIGUSR2 12 +#define SIGPIPE 13 +#define SIGALRM 14 +#define SIGTERM 15 +#define SIGSTKFLT 16 +#define SIGCHLD 17 +#define SIGCONT 18 +#define SIGSTOP 19 +#define SIGTSTP 20 +#define SIGTTIN 21 +#define SIGTTOU 22 +#define SIGURG 23 +#define SIGXCPU 24 +#define SIGXFSZ 25 +#define SIGVTALRM 26 +#define SIGPROF 27 +#define SIGWINCH 28 +#define SIGIO 29 +#define SIGPOLL SIGIO +#define SIGPWR 30 +#define SIGSYS 31 +#define SIGUNUSED 31 +#define SIGRTMIN 32 diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index b534c306..a1e36ab9 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -6,6 +6,10 @@ #include #include #include +#include +#include + +void terminate(int, int, ihk_mc_user_context_t *); //#define DEBUG_PRINT_SC @@ -67,3 +71,80 @@ int obtain_clone_cpuid() { ihk_mc_spinlock_unlock_noirq(&cpuid_head_lock); return cpuid; } + +SYSCALL_DECLARE(rt_sigreturn) +{ + struct process *proc = cpu_local_var(current); + char *kspbottom; + asm volatile ("movq %%gs:132,%0" : "=r" (kspbottom)); + memcpy(kspbottom - 120, proc->sigstack, 120); + + return proc->sigrc; +} + +void +check_signal(unsigned long rc, unsigned long *regs) +{ + struct process *proc = cpu_local_var(current); + struct k_sigaction *k; + int sig = proc->signal; + + proc->signal = 0; + if(sig){ + if(regs == NULL){ /* call from syscall */ + asm volatile ("movq %%gs:132,%0" : "=r" (regs)); + regs -= 16; + } + else{ + rc = regs[9]; /* rax */ + } + + k = proc->sighandler->action + sig - 1; + + if(k->sa.sa_handler == (void *)1){ + return; + } + else if(k->sa.sa_handler){ + unsigned long *usp; /* user stack */ + long w; + + usp = (void *)regs[14]; + memcpy(proc->sigstack, regs, 128); + proc->sigrc = rc; + usp--; + *usp = (unsigned long)k->sa.sa_restorer; + w = 56 + 3; + asm volatile ("pushq %0" :: "r" (w)); + asm volatile ("pushq %0" :: "r" (usp)); + w = 1 << 9; + asm volatile ("pushq %0" :: "r" (w)); + w = 48 + 3; + asm volatile ("pushq %0" :: "r" (w)); + asm volatile ("pushq %0" :: "r" (k->sa.sa_handler)); + asm volatile ("iretq"); + } + else{ + if(sig == SIGCHLD || sig == SIGURG) + return; + terminate(0, sig, (ihk_mc_user_context_t *)regs[14]); + } + } +} + +void +sigsegv(unsigned long *regs) +{ + struct process *proc = cpu_local_var(current); + + proc->signal = SIGSEGV; + check_signal(0, regs); +} + +void +sigill(unsigned long *regs) +{ + struct process *proc = cpu_local_var(current); + + proc->signal = SIGILL; + check_signal(0, regs); +} diff --git a/kernel/mem.c b/kernel/mem.c index b36dfcca..401d38ee 100644 --- a/kernel/mem.c +++ b/kernel/mem.c @@ -141,7 +141,7 @@ static struct ihk_mc_interrupt_handler query_free_mem_handler = { .priv = NULL, }; - +void sigsegv(void *); static void page_fault_handler(unsigned long address, void *regs, unsigned long rbp) @@ -226,7 +226,9 @@ static void page_fault_handler(unsigned long address, void *regs, } #endif - panic(""); + sigsegv(regs); + + //panic("mem fault"); } static void page_allocator_init(void) diff --git a/kernel/syscall.c b/kernel/syscall.c index 997bb967..b213d017 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -66,6 +66,8 @@ static char *syscall_name[] MCKERNEL_UNUSED = { #undef SYSCALL_DELEGATED }; +void check_signal(unsigned long rc, unsigned long *regs); + #ifdef DCFA_KMOD static void do_mod_exit(int status); #endif @@ -145,9 +147,41 @@ SYSCALL_DECLARE(open) SYSCALL_FOOTER; } +void +terminate(int rc, int sig, ihk_mc_user_context_t *ctx) +{ + struct syscall_request request IHK_DMA_ALIGN; + struct process *proc = cpu_local_var(current); + + request.number = __NR_exit_group; + +#ifdef DCFA_KMOD + do_mod_exit(rc); +#endif + + /* XXX: send SIGKILL to all threads in this process */ + + do_syscall(&request, ctx); + +#define IS_DETACHED_PROCESS(proc) (1) /* should be implemented in the future */ + proc->status = PS_ZOMBIE; + if (IS_DETACHED_PROCESS(proc)) { + /* release a reference for wait(2) */ + proc->status = PS_EXITED; + free_process(proc); + } + + schedule(); +} + SYSCALL_DECLARE(exit_group) { +#if 0 SYSCALL_HEADER; +#endif + + terminate((int)ihk_mc_syscall_arg0(ctx), 0, ctx); +#if 0 struct process *proc = cpu_local_var(current); #ifdef DCFA_KMOD @@ -168,6 +202,8 @@ SYSCALL_DECLARE(exit_group) schedule(); +#endif + return 0; } @@ -806,7 +842,7 @@ SYSCALL_DECLARE(rt_sigaction) int sig = ihk_mc_syscall_arg0(ctx); const struct sigaction *act = (const struct sigaction *)ihk_mc_syscall_arg1(ctx); struct sigaction *oact = (struct sigaction *)ihk_mc_syscall_arg2(ctx); - size_t sigsetsize = ihk_mc_syscall_arg3(ctx); + //size_t sigsetsize = ihk_mc_syscall_arg3(ctx); struct k_sigaction new_sa, old_sa; int rc; @@ -822,50 +858,6 @@ SYSCALL_DECLARE(rt_sigaction) return rc; } -static void -check_signal(unsigned long rc) -{ - struct process *proc = cpu_local_var(current); - struct k_sigaction *k; - int sig = proc->signal; - - proc->signal = 0; - if(sig){ - k = proc->sighandler->action + sig - 1; - if(k->sa.sa_handler){ - unsigned long *usp; /* user stack */ - char *kspbottom; - long w; - asm volatile ("movq %%gs:24,%0" : "=r" (usp)); - asm volatile ("movq %%gs:132,%0" : "=r" (kspbottom)); - memcpy(proc->sigstack, kspbottom - 120, 120); - proc->sigrc = rc; - usp--; - *usp = (unsigned long)k->sa.sa_restorer; - w = 56 + 3; - asm volatile ("pushq %0" :: "r" (w)); - asm volatile ("pushq %0" :: "r" (usp)); - w = 1 << 9; - asm volatile ("pushq %0" :: "r" (w)); - w = 48 + 3; - asm volatile ("pushq %0" :: "r" (w)); - asm volatile ("pushq %0" :: "r" (k->sa.sa_handler)); - asm volatile ("iretq"); - } - } -} - -SYSCALL_DECLARE(rt_sigreturn) -{ - struct process *proc = cpu_local_var(current); - char *kspbottom; - asm volatile ("movq %%gs:132,%0" : "=r" (kspbottom)); - memcpy(kspbottom - 120, proc->sigstack, 120); - - return proc->sigrc; -} - - SYSCALL_DECLARE(rt_sigprocmask) { // kprintf("sys_rt_sigprocmask called. returning zero...\n"); @@ -1198,7 +1190,7 @@ long syscall(int num, ihk_mc_user_context_t *ctx) l = syscall_generic_forwarding(num, ctx); } - check_signal(l); + check_signal(l, NULL); return l; }