1/* 2 * Copyright (c) 2012, 2015 ARM Limited 3 * All rights reserved 4 * 5 * The license below extends only to copyright in the software and shall 6 * not be construed as granting a license to any other intellectual 7 * property including but not limited to intellectual property relating 8 * to a hardware implementation of the functionality of the software 9 * licensed hereunder. You may use the software subject to the license 10 * terms below provided that you ensure that this notice is replicated 11 * unmodified and in its entirety in all distributions of the software, 12 * modified or unmodified, in source code or in binary form. 13 * 14 * Copyright (c) 2000-2005 The Regents of The University of Michigan 15 * Copyright (c) 2008 The Hewlett-Packard Development Company 16 * All rights reserved. 17 * 18 * Redistribution and use in source and binary forms, with or without 19 * modification, are permitted provided that the following conditions are 20 * met: redistributions of source code must retain the above copyright 21 * notice, this list of conditions and the following disclaimer; 22 * redistributions in binary form must reproduce the above copyright 23 * notice, this list of conditions and the following disclaimer in the 24 * documentation and/or other materials provided with the distribution; 25 * neither the name of the copyright holders nor the names of its 26 * contributors may be used to endorse or promote products derived from 27 * this software without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 30 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 31 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 32 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 33 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 34 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 35 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 36 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 37 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 38 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 39 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 40 * 41 * Authors: Nathan Binkert 42 */ 43 44#include "sim/init_signals.hh" 45 46#include <sys/types.h> 47#include <unistd.h> 48 49#include <csignal> 50#include <iostream> 51#include <string> 52 53#if defined(__FreeBSD__) 54#include <sys/param.h> 55 56#endif 57 58#include "base/atomicio.hh" 59#include "base/cprintf.hh" 60#include "base/logging.hh" 61#include "sim/async.hh" 62#include "sim/backtrace.hh" 63#include "sim/core.hh" 64#include "sim/eventq.hh" 65 66using namespace std; 67 68// Use an separate stack for fatal signal handlers 69static uint8_t fatalSigStack[2 * SIGSTKSZ]; 70 71static bool 72setupAltStack() 73{ 74 stack_t stack; 75#if defined(__FreeBSD__) && (__FreeBSD_version < 1100097) 76 stack.ss_sp = (char *)fatalSigStack; 77#else 78 stack.ss_sp = fatalSigStack; 79#endif 80 stack.ss_size = sizeof(fatalSigStack); 81 stack.ss_flags = 0; 82 83 return sigaltstack(&stack, NULL) == 0; 84} 85 86static void 87installSignalHandler(int signal, void (*handler)(int sigtype), 88 int flags = SA_RESTART) 89{ 90 struct sigaction sa; 91 92 memset(&sa, 0, sizeof(sa)); 93 sigemptyset(&sa.sa_mask); 94 sa.sa_handler = handler; 95 sa.sa_flags = flags; 96 97 if (sigaction(signal, &sa, NULL) == -1) 98 panic("Failed to setup handler for signal %i\n", signal); 99} 100 101static void 102raiseFatalSignal(int signo) 103{ 104 // The signal handler should have been reset and unmasked (it was 105 // registered with SA_RESETHAND | SA_NODEFER), just raise the 106 // signal again to invoke the default handler. 107 pthread_kill(pthread_self(), signo); 108 109 // Something is really wrong if the process is alive at this 110 // point, manually try to exit it. 111 STATIC_ERR("Failed to execute default signal handler!\n"); 112 _exit(127); 113} 114 115/// Stats signal handler. 116void 117dumpStatsHandler(int sigtype) 118{ 119 async_event = true; 120 async_statdump = true; 121 /* Wake up some event queue to handle event */ 122 getEventQueue(0)->wakeup(); 123} 124 125void 126dumprstStatsHandler(int sigtype) 127{ 128 async_event = true; 129 async_statdump = true; 130 async_statreset = true; 131 /* Wake up some event queue to handle event */ 132 getEventQueue(0)->wakeup(); 133} 134 135/// Exit signal handler. 136void 137exitNowHandler(int sigtype) 138{ 139 async_event = true; 140 async_exit = true; 141 /* Wake up some event queue to handle event */ 142 getEventQueue(0)->wakeup(); 143} 144 145/// Abort signal handler. 146void 147abortHandler(int sigtype) 148{ 149 const EventQueue *const eq(curEventQueue()); 150 if (eq) { 151 ccprintf(cerr, "Program aborted at tick %llu\n", eq->getCurTick()); 152 } else { 153 STATIC_ERR("Program aborted\n\n"); 154 } 155 156 print_backtrace(); 157 raiseFatalSignal(sigtype); 158} 159 160/// Segmentation fault signal handler. 161static void 162segvHandler(int sigtype) 163{ 164 STATIC_ERR("gem5 has encountered a segmentation fault!\n\n"); 165 166 print_backtrace(); 167 raiseFatalSignal(SIGSEGV); 168} 169 170// Handle SIGIO 171static void 172ioHandler(int sigtype) 173{ 174 async_event = true; 175 async_io = true; 176 /* Wake up some event queue to handle event */ 177 getEventQueue(0)->wakeup(); 178} 179 180/* 181 * M5 can do several special things when various signals are sent. 182 * None are mandatory. 183 */ 184void 185initSignals() 186{ 187 // Floating point exceptions may happen on misspeculated paths, so 188 // ignore them 189 signal(SIGFPE, SIG_IGN); 190 191 // Dump intermediate stats 192 installSignalHandler(SIGUSR1, dumpStatsHandler); 193 194 // Dump intermediate stats and reset them 195 installSignalHandler(SIGUSR2, dumprstStatsHandler); 196 197 // Exit cleanly on Interrupt (Ctrl-C) 198 installSignalHandler(SIGINT, exitNowHandler); 199 200 // Print the current cycle number and a backtrace on abort. Make 201 // sure the signal is unmasked and the handler reset when a signal 202 // is delivered to be able to invoke the default handler. 203 installSignalHandler(SIGABRT, abortHandler, SA_RESETHAND | SA_NODEFER); 204 205 // Setup a SIGSEGV handler with a private stack 206 if (setupAltStack()) { 207 installSignalHandler(SIGSEGV, segvHandler, 208 SA_RESETHAND | SA_NODEFER | SA_ONSTACK); 209 } else { 210 warn("Failed to setup stack for SIGSEGV handler, " 211 "using default signal handler.\n"); 212 } 213 214 // Install a SIGIO handler to handle asynchronous file IO. See the 215 // PollQueue class. 216 installSignalHandler(SIGIO, ioHandler); 217} 218 219