110453SAndrew.Bardsley@arm.com/*
211235Sandreas.sandberg@arm.com * Copyright (c) 2012, 2015 ARM Limited
310453SAndrew.Bardsley@arm.com * All rights reserved
410453SAndrew.Bardsley@arm.com *
510453SAndrew.Bardsley@arm.com * The license below extends only to copyright in the software and shall
610453SAndrew.Bardsley@arm.com * not be construed as granting a license to any other intellectual
710453SAndrew.Bardsley@arm.com * property including but not limited to intellectual property relating
810453SAndrew.Bardsley@arm.com * to a hardware implementation of the functionality of the software
910453SAndrew.Bardsley@arm.com * licensed hereunder.  You may use the software subject to the license
1010453SAndrew.Bardsley@arm.com * terms below provided that you ensure that this notice is replicated
1110453SAndrew.Bardsley@arm.com * unmodified and in its entirety in all distributions of the software,
1210453SAndrew.Bardsley@arm.com * modified or unmodified, in source code or in binary form.
1310453SAndrew.Bardsley@arm.com *
1410453SAndrew.Bardsley@arm.com * Copyright (c) 2000-2005 The Regents of The University of Michigan
1510453SAndrew.Bardsley@arm.com * Copyright (c) 2008 The Hewlett-Packard Development Company
1610453SAndrew.Bardsley@arm.com * All rights reserved.
1710453SAndrew.Bardsley@arm.com *
1810453SAndrew.Bardsley@arm.com * Redistribution and use in source and binary forms, with or without
1910453SAndrew.Bardsley@arm.com * modification, are permitted provided that the following conditions are
2010453SAndrew.Bardsley@arm.com * met: redistributions of source code must retain the above copyright
2110453SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer;
2210453SAndrew.Bardsley@arm.com * redistributions in binary form must reproduce the above copyright
2310453SAndrew.Bardsley@arm.com * notice, this list of conditions and the following disclaimer in the
2410453SAndrew.Bardsley@arm.com * documentation and/or other materials provided with the distribution;
2510453SAndrew.Bardsley@arm.com * neither the name of the copyright holders nor the names of its
2610453SAndrew.Bardsley@arm.com * contributors may be used to endorse or promote products derived from
2710453SAndrew.Bardsley@arm.com * this software without specific prior written permission.
2810453SAndrew.Bardsley@arm.com *
2910453SAndrew.Bardsley@arm.com * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3010453SAndrew.Bardsley@arm.com * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3110453SAndrew.Bardsley@arm.com * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
3210453SAndrew.Bardsley@arm.com * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3310453SAndrew.Bardsley@arm.com * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
3410453SAndrew.Bardsley@arm.com * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
3510453SAndrew.Bardsley@arm.com * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
3610453SAndrew.Bardsley@arm.com * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
3710453SAndrew.Bardsley@arm.com * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
3810453SAndrew.Bardsley@arm.com * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
3910453SAndrew.Bardsley@arm.com * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
4010453SAndrew.Bardsley@arm.com *
4110453SAndrew.Bardsley@arm.com * Authors: Nathan Binkert
4210453SAndrew.Bardsley@arm.com */
4310453SAndrew.Bardsley@arm.com
4411235Sandreas.sandberg@arm.com#include "sim/init_signals.hh"
4511235Sandreas.sandberg@arm.com
4611235Sandreas.sandberg@arm.com#include <sys/types.h>
4711235Sandreas.sandberg@arm.com#include <unistd.h>
4811235Sandreas.sandberg@arm.com
4910453SAndrew.Bardsley@arm.com#include <csignal>
5010453SAndrew.Bardsley@arm.com#include <iostream>
5110453SAndrew.Bardsley@arm.com#include <string>
5210453SAndrew.Bardsley@arm.com
5312203Sbaz21@cam.ac.uk#if defined(__FreeBSD__)
5412203Sbaz21@cam.ac.uk#include <sys/param.h>
5512203Sbaz21@cam.ac.uk
5612203Sbaz21@cam.ac.uk#endif
5712203Sbaz21@cam.ac.uk
5811235Sandreas.sandberg@arm.com#include "base/atomicio.hh"
5910453SAndrew.Bardsley@arm.com#include "base/cprintf.hh"
6012334Sgabeblack@google.com#include "base/logging.hh"
6110453SAndrew.Bardsley@arm.com#include "sim/async.hh"
6211235Sandreas.sandberg@arm.com#include "sim/backtrace.hh"
6310453SAndrew.Bardsley@arm.com#include "sim/core.hh"
6410476Sandreas.hansson@arm.com#include "sim/eventq.hh"
6510453SAndrew.Bardsley@arm.com
6610453SAndrew.Bardsley@arm.comusing namespace std;
6710453SAndrew.Bardsley@arm.com
6811235Sandreas.sandberg@arm.com// Use an separate stack for fatal signal handlers
6911235Sandreas.sandberg@arm.comstatic uint8_t fatalSigStack[2 * SIGSTKSZ];
7011235Sandreas.sandberg@arm.com
7111235Sandreas.sandberg@arm.comstatic bool
7211235Sandreas.sandberg@arm.comsetupAltStack()
7311235Sandreas.sandberg@arm.com{
7411235Sandreas.sandberg@arm.com    stack_t stack;
7512203Sbaz21@cam.ac.uk#if defined(__FreeBSD__) && (__FreeBSD_version < 1100097)
7612203Sbaz21@cam.ac.uk    stack.ss_sp = (char *)fatalSigStack;
7712203Sbaz21@cam.ac.uk#else
7811235Sandreas.sandberg@arm.com    stack.ss_sp = fatalSigStack;
7912203Sbaz21@cam.ac.uk#endif
8011235Sandreas.sandberg@arm.com    stack.ss_size = sizeof(fatalSigStack);
8111235Sandreas.sandberg@arm.com    stack.ss_flags = 0;
8211235Sandreas.sandberg@arm.com
8311235Sandreas.sandberg@arm.com    return sigaltstack(&stack, NULL) == 0;
8411235Sandreas.sandberg@arm.com}
8511235Sandreas.sandberg@arm.com
8611235Sandreas.sandberg@arm.comstatic void
8711235Sandreas.sandberg@arm.cominstallSignalHandler(int signal, void (*handler)(int sigtype),
8811235Sandreas.sandberg@arm.com                     int flags = SA_RESTART)
8911235Sandreas.sandberg@arm.com{
9011235Sandreas.sandberg@arm.com    struct sigaction sa;
9111235Sandreas.sandberg@arm.com
9211235Sandreas.sandberg@arm.com    memset(&sa, 0, sizeof(sa));
9311235Sandreas.sandberg@arm.com    sigemptyset(&sa.sa_mask);
9411235Sandreas.sandberg@arm.com    sa.sa_handler = handler;
9511235Sandreas.sandberg@arm.com    sa.sa_flags = flags;
9611235Sandreas.sandberg@arm.com
9711235Sandreas.sandberg@arm.com    if (sigaction(signal, &sa, NULL) == -1)
9811235Sandreas.sandberg@arm.com        panic("Failed to setup handler for signal %i\n", signal);
9911235Sandreas.sandberg@arm.com}
10011235Sandreas.sandberg@arm.com
10111235Sandreas.sandberg@arm.comstatic void
10211235Sandreas.sandberg@arm.comraiseFatalSignal(int signo)
10311235Sandreas.sandberg@arm.com{
10411235Sandreas.sandberg@arm.com    // The signal handler should have been reset and unmasked (it was
10511235Sandreas.sandberg@arm.com    // registered with SA_RESETHAND | SA_NODEFER), just raise the
10611235Sandreas.sandberg@arm.com    // signal again to invoke the default handler.
10711235Sandreas.sandberg@arm.com    pthread_kill(pthread_self(), signo);
10811235Sandreas.sandberg@arm.com
10911235Sandreas.sandberg@arm.com    // Something is really wrong if the process is alive at this
11011235Sandreas.sandberg@arm.com    // point, manually try to exit it.
11111235Sandreas.sandberg@arm.com    STATIC_ERR("Failed to execute default signal handler!\n");
11211235Sandreas.sandberg@arm.com    _exit(127);
11311235Sandreas.sandberg@arm.com}
11411235Sandreas.sandberg@arm.com
11510453SAndrew.Bardsley@arm.com/// Stats signal handler.
11610453SAndrew.Bardsley@arm.comvoid
11710453SAndrew.Bardsley@arm.comdumpStatsHandler(int sigtype)
11810453SAndrew.Bardsley@arm.com{
11910453SAndrew.Bardsley@arm.com    async_event = true;
12010453SAndrew.Bardsley@arm.com    async_statdump = true;
12110476Sandreas.hansson@arm.com    /* Wake up some event queue to handle event */
12210476Sandreas.hansson@arm.com    getEventQueue(0)->wakeup();
12310453SAndrew.Bardsley@arm.com}
12410453SAndrew.Bardsley@arm.com
12510453SAndrew.Bardsley@arm.comvoid
12610453SAndrew.Bardsley@arm.comdumprstStatsHandler(int sigtype)
12710453SAndrew.Bardsley@arm.com{
12810453SAndrew.Bardsley@arm.com    async_event = true;
12910453SAndrew.Bardsley@arm.com    async_statdump = true;
13010453SAndrew.Bardsley@arm.com    async_statreset = true;
13110476Sandreas.hansson@arm.com    /* Wake up some event queue to handle event */
13210476Sandreas.hansson@arm.com    getEventQueue(0)->wakeup();
13310453SAndrew.Bardsley@arm.com}
13410453SAndrew.Bardsley@arm.com
13510453SAndrew.Bardsley@arm.com/// Exit signal handler.
13610453SAndrew.Bardsley@arm.comvoid
13710453SAndrew.Bardsley@arm.comexitNowHandler(int sigtype)
13810453SAndrew.Bardsley@arm.com{
13910453SAndrew.Bardsley@arm.com    async_event = true;
14010453SAndrew.Bardsley@arm.com    async_exit = true;
14110476Sandreas.hansson@arm.com    /* Wake up some event queue to handle event */
14210476Sandreas.hansson@arm.com    getEventQueue(0)->wakeup();
14310453SAndrew.Bardsley@arm.com}
14410453SAndrew.Bardsley@arm.com
14510453SAndrew.Bardsley@arm.com/// Abort signal handler.
14610453SAndrew.Bardsley@arm.comvoid
14710453SAndrew.Bardsley@arm.comabortHandler(int sigtype)
14810453SAndrew.Bardsley@arm.com{
14911235Sandreas.sandberg@arm.com    const EventQueue *const eq(curEventQueue());
15011235Sandreas.sandberg@arm.com    if (eq) {
15111235Sandreas.sandberg@arm.com        ccprintf(cerr, "Program aborted at tick %llu\n", eq->getCurTick());
15211235Sandreas.sandberg@arm.com    } else {
15311235Sandreas.sandberg@arm.com        STATIC_ERR("Program aborted\n\n");
15411235Sandreas.sandberg@arm.com    }
15511235Sandreas.sandberg@arm.com
15611235Sandreas.sandberg@arm.com    print_backtrace();
15711235Sandreas.sandberg@arm.com    raiseFatalSignal(sigtype);
15811235Sandreas.sandberg@arm.com}
15911235Sandreas.sandberg@arm.com
16011235Sandreas.sandberg@arm.com/// Segmentation fault signal handler.
16111235Sandreas.sandberg@arm.comstatic void
16211235Sandreas.sandberg@arm.comsegvHandler(int sigtype)
16311235Sandreas.sandberg@arm.com{
16411235Sandreas.sandberg@arm.com    STATIC_ERR("gem5 has encountered a segmentation fault!\n\n");
16511235Sandreas.sandberg@arm.com
16611235Sandreas.sandberg@arm.com    print_backtrace();
16711235Sandreas.sandberg@arm.com    raiseFatalSignal(SIGSEGV);
16810453SAndrew.Bardsley@arm.com}
16910453SAndrew.Bardsley@arm.com
17010453SAndrew.Bardsley@arm.com// Handle SIGIO
17110453SAndrew.Bardsley@arm.comstatic void
17210453SAndrew.Bardsley@arm.comioHandler(int sigtype)
17310453SAndrew.Bardsley@arm.com{
17410453SAndrew.Bardsley@arm.com    async_event = true;
17510453SAndrew.Bardsley@arm.com    async_io = true;
17610476Sandreas.hansson@arm.com    /* Wake up some event queue to handle event */
17710476Sandreas.hansson@arm.com    getEventQueue(0)->wakeup();
17810453SAndrew.Bardsley@arm.com}
17910453SAndrew.Bardsley@arm.com
18010453SAndrew.Bardsley@arm.com/*
18110453SAndrew.Bardsley@arm.com * M5 can do several special things when various signals are sent.
18210453SAndrew.Bardsley@arm.com * None are mandatory.
18310453SAndrew.Bardsley@arm.com */
18410453SAndrew.Bardsley@arm.comvoid
18510453SAndrew.Bardsley@arm.cominitSignals()
18610453SAndrew.Bardsley@arm.com{
18710453SAndrew.Bardsley@arm.com    // Floating point exceptions may happen on misspeculated paths, so
18810453SAndrew.Bardsley@arm.com    // ignore them
18910453SAndrew.Bardsley@arm.com    signal(SIGFPE, SIG_IGN);
19010453SAndrew.Bardsley@arm.com
19110453SAndrew.Bardsley@arm.com    // Dump intermediate stats
19210453SAndrew.Bardsley@arm.com    installSignalHandler(SIGUSR1, dumpStatsHandler);
19310453SAndrew.Bardsley@arm.com
19410453SAndrew.Bardsley@arm.com    // Dump intermediate stats and reset them
19510453SAndrew.Bardsley@arm.com    installSignalHandler(SIGUSR2, dumprstStatsHandler);
19610453SAndrew.Bardsley@arm.com
19710453SAndrew.Bardsley@arm.com    // Exit cleanly on Interrupt (Ctrl-C)
19810453SAndrew.Bardsley@arm.com    installSignalHandler(SIGINT, exitNowHandler);
19910453SAndrew.Bardsley@arm.com
20011235Sandreas.sandberg@arm.com    // Print the current cycle number and a backtrace on abort. Make
20111235Sandreas.sandberg@arm.com    // sure the signal is unmasked and the handler reset when a signal
20211235Sandreas.sandberg@arm.com    // is delivered to be able to invoke the default handler.
20311235Sandreas.sandberg@arm.com    installSignalHandler(SIGABRT, abortHandler, SA_RESETHAND | SA_NODEFER);
20411235Sandreas.sandberg@arm.com
20511235Sandreas.sandberg@arm.com    // Setup a SIGSEGV handler with a private stack
20611235Sandreas.sandberg@arm.com    if (setupAltStack()) {
20711235Sandreas.sandberg@arm.com        installSignalHandler(SIGSEGV, segvHandler,
20811235Sandreas.sandberg@arm.com                             SA_RESETHAND | SA_NODEFER | SA_ONSTACK);
20911235Sandreas.sandberg@arm.com    } else {
21011235Sandreas.sandberg@arm.com        warn("Failed to setup stack for SIGSEGV handler, "
21111235Sandreas.sandberg@arm.com             "using default signal handler.\n");
21211235Sandreas.sandberg@arm.com    }
21310453SAndrew.Bardsley@arm.com
21410453SAndrew.Bardsley@arm.com    // Install a SIGIO handler to handle asynchronous file IO. See the
21510453SAndrew.Bardsley@arm.com    // PollQueue class.
21610453SAndrew.Bardsley@arm.com    installSignalHandler(SIGIO, ioHandler);
21710453SAndrew.Bardsley@arm.com}
21810453SAndrew.Bardsley@arm.com
219