diff options
Diffstat (limited to 'sys/arch/amd64')
-rw-r--r-- | sys/arch/amd64/amd64/trap.c | 39 |
1 files changed, 39 insertions, 0 deletions
diff --git a/sys/arch/amd64/amd64/trap.c b/sys/arch/amd64/amd64/trap.c index 7615140..85e7bca 100644 --- a/sys/arch/amd64/amd64/trap.c +++ b/sys/arch/amd64/amd64/trap.c @@ -33,6 +33,8 @@ #include <sys/panic.h> #include <sys/syslog.h> #include <sys/syscall.h> +#include <sys/sched.h> +#include <sys/proc.h> #include <machine/trap.h> #include <machine/frame.h> #include <machine/intr.h> @@ -86,6 +88,36 @@ regdump(struct trapframe *tf) tf->rbp, tf->rsp, tf->rip); } +static void +trap_user(struct trapframe *tf) +{ + struct proc *td = this_td(); + sigset_t sigset; + + sigemptyset(&sigset); + + switch (tf->trapno) { + case TRAP_PROTFLT: + case TRAP_PAGEFLT: + sigaddset(&sigset, SIGSEGV); + break; + case TRAP_ARITH_ERR: + sigaddset(&sigset, SIGFPE); + break; + default: + kprintf("Got unknown user trap %d\n", tf->trapno); + sigaddset(&sigset, SIGKILL); + break; + } + + /* + * Send the signal then flush the signal queue right + * away as these types of events are critical. + */ + sendsig(td, &sigset); + dispatch_signals(td); +} + void trap_syscall(struct trapframe *tf) { @@ -114,6 +146,13 @@ trap_handler(struct trapframe *tf) } pr_error("Got %s\n", trap_type[tf->trapno]); + + /* Handle traps from userland */ + if (ISSET(tf->cs, 3)) { + trap_user(tf); + return; + } + regdump(tf); panic("Fatal trap - halting\n"); } |