1 2 /* 3 * Copyright (c) 2006 The DragonFly Project. All rights reserved. 4 * 5 * This code is derived from software contributed to The DragonFly Project 6 * by Matthew Dillon <dillon@backplane.com> 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in 16 * the documentation and/or other materials provided with the 17 * distribution. 18 * 3. Neither the name of The DragonFly Project nor the names of its 19 * contributors may be used to endorse or promote products derived 20 * from this software without specific, prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 23 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 24 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 25 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 26 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 27 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 28 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 29 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 30 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 31 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 32 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * $DragonFly: src/sys/platform/vkernel/i386/exception.c,v 1.11 2008/04/28 07:05:09 dillon Exp $ 36 */ 37 38 #include "opt_ddb.h" 39 #include <sys/types.h> 40 #include <sys/systm.h> 41 #include <sys/reboot.h> 42 #include <sys/kernel.h> 43 #include <sys/kthread.h> 44 #include <sys/reboot.h> 45 #include <ddb/ddb.h> 46 47 #include <sys/thread2.h> 48 49 #include <machine/trap.h> 50 #include <machine/md_var.h> 51 #include <machine/segments.h> 52 #include <machine/cpu.h> 53 #include <machine/smp.h> 54 55 #include <err.h> 56 #include <signal.h> 57 #include <unistd.h> 58 59 int _ucodesel = GSEL(GUCODE_SEL, SEL_UPL); 60 int _udatasel = GSEL(GUDATA_SEL, SEL_UPL); 61 62 static void exc_segfault(int signo, siginfo_t *info, void *ctx); 63 #ifdef DDB 64 static void exc_debugger(int signo, siginfo_t *info, void *ctx); 65 #endif 66 67 #ifdef SMP 68 69 /* 70 * IPIs are 'fast' interrupts, so we deal with them directly from our 71 * signal handler. 72 * 73 * WARNING: Signals are not physically disabled here so we have to enter 74 * our critical section before bumping gd_intr_nesting_level or another 75 * interrupt can come along and get really confused. 76 */ 77 static 78 void 79 ipisig(int nada, siginfo_t *info, void *ctxp) 80 { 81 globaldata_t gd = mycpu; 82 thread_t td = gd->gd_curthread; 83 84 if (td->td_critcount == 0) { 85 ++td->td_critcount; 86 ++gd->gd_intr_nesting_level; 87 lwkt_process_ipiq(); 88 --gd->gd_intr_nesting_level; 89 --td->td_critcount; 90 } else { 91 need_ipiq(); 92 } 93 } 94 95 /* 96 * Unconditionally stop or restart a cpu. 97 * 98 * Note: cpu_mask_all_signals() masks all signals except SIGXCPU itself. 99 * SIGXCPU itself is blocked on entry to stopsig() by the signal handler 100 * itself. 101 * 102 * WARNING: Signals are not physically disabled here so we have to enter 103 * our critical section before bumping gd_intr_nesting_level or another 104 * interrupt can come along and get really confused. 105 */ 106 static 107 void 108 stopsig(int nada, siginfo_t *info, void *ctxp) 109 { 110 globaldata_t gd = mycpu; 111 thread_t td = gd->gd_curthread; 112 sigset_t ss; 113 114 sigemptyset(&ss); 115 sigaddset(&ss, SIGALRM); 116 sigaddset(&ss, SIGIO); 117 sigaddset(&ss, SIGQUIT); 118 sigaddset(&ss, SIGUSR1); 119 sigaddset(&ss, SIGUSR2); 120 sigaddset(&ss, SIGTERM); 121 sigaddset(&ss, SIGWINCH); 122 123 ++td->td_critcount; 124 ++gd->gd_intr_nesting_level; 125 while (stopped_cpus & gd->gd_cpumask) { 126 sigsuspend(&ss); 127 } 128 --gd->gd_intr_nesting_level; 129 --td->td_critcount; 130 } 131 132 #endif 133 134 #if 0 135 136 /* 137 * SIGIO is used by cothreads to signal back into the virtual kernel. 138 */ 139 static 140 void 141 iosig(int nada, siginfo_t *info, void *ctxp) 142 { 143 signalintr(4); 144 } 145 146 #endif 147 148 void 149 init_exceptions(void) 150 { 151 struct sigaction sa; 152 153 bzero(&sa, sizeof(sa)); 154 sa.sa_sigaction = exc_segfault; 155 sa.sa_flags |= SA_SIGINFO | SA_NODEFER; 156 sigemptyset(&sa.sa_mask); 157 sigaction(SIGBUS, &sa, NULL); 158 sigaction(SIGSEGV, &sa, NULL); 159 sigaction(SIGTRAP, &sa, NULL); 160 sigaction(SIGFPE, &sa, NULL); 161 162 #ifdef DDB 163 sa.sa_sigaction = exc_debugger; 164 sigaction(SIGQUIT, &sa, NULL); 165 #endif 166 #ifdef SMP 167 sa.sa_sigaction = ipisig; 168 sigaction(SIGUSR1, &sa, NULL); 169 sa.sa_sigaction = stopsig; 170 sigaction(SIGXCPU, &sa, NULL); 171 #endif 172 #if 0 173 sa.sa_sigaction = iosig; 174 sigaction(SIGIO, &sa, NULL); 175 #endif 176 } 177 178 /* 179 * This function handles a segmentation fault. 180 * 181 * XXX We assume that trapframe is a subset of ucontext. It is as of 182 * this writing. 183 */ 184 static void 185 exc_segfault(int signo, siginfo_t *info, void *ctxp) 186 { 187 ucontext_t *ctx = ctxp; 188 189 #if 0 190 kprintf("CAUGHT SIG %d RIP %08lx ERR %08lx TRAPNO %ld " 191 "err %ld addr %08lx\n", 192 signo, 193 ctx->uc_mcontext.mc_rip, 194 ctx->uc_mcontext.mc_err, 195 ctx->uc_mcontext.mc_trapno & 0xFFFF, 196 ctx->uc_mcontext.mc_trapno >> 16, 197 ctx->uc_mcontext.mc_addr); 198 #endif 199 kern_trap((struct trapframe *)&ctx->uc_mcontext.mc_rdi); 200 splz(); 201 } 202 203 #ifdef DDB 204 205 static void 206 exc_debugger(int signo, siginfo_t *info, void *ctx) 207 { 208 Debugger("interrupt from console"); 209 } 210 211 #endif 212