cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

watchdog.c (4485B)


      1/*
      2 * Virtual hardware watchdog.
      3 *
      4 * Copyright (C) 2009 Red Hat Inc.
      5 *
      6 * This program is free software; you can redistribute it and/or
      7 * modify it under the terms of the GNU General Public License
      8 * as published by the Free Software Foundation; either version 2
      9 * of the License, or (at your option) any later version.
     10 *
     11 * This program is distributed in the hope that it will be useful,
     12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
     13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14 * GNU General Public License for more details.
     15 *
     16 * You should have received a copy of the GNU General Public License
     17 * along with this program; if not, see <http://www.gnu.org/licenses/>.
     18 *
     19 * By Richard W.M. Jones (rjones@redhat.com).
     20 */
     21
     22#include "qemu/osdep.h"
     23#include "qemu/option.h"
     24#include "qemu/config-file.h"
     25#include "qemu/queue.h"
     26#include "qapi/error.h"
     27#include "qapi/qapi-commands-run-state.h"
     28#include "qapi/qapi-events-run-state.h"
     29#include "sysemu/runstate.h"
     30#include "sysemu/watchdog.h"
     31#include "hw/nmi.h"
     32#include "qemu/help_option.h"
     33
     34static WatchdogAction watchdog_action = WATCHDOG_ACTION_RESET;
     35static QLIST_HEAD(, WatchdogTimerModel) watchdog_list;
     36
     37void watchdog_add_model(WatchdogTimerModel *model)
     38{
     39    QLIST_INSERT_HEAD(&watchdog_list, model, entry);
     40}
     41
     42/* Returns:
     43 *   0 = continue
     44 *   1 = exit program with error
     45 *   2 = exit program without error
     46 */
     47int select_watchdog(const char *p)
     48{
     49    WatchdogTimerModel *model;
     50    QemuOpts *opts;
     51
     52    /* -watchdog ? lists available devices and exits cleanly. */
     53    if (is_help_option(p)) {
     54        QLIST_FOREACH(model, &watchdog_list, entry) {
     55            fprintf(stderr, "\t%s\t%s\n",
     56                     model->wdt_name, model->wdt_description);
     57        }
     58        return 2;
     59    }
     60
     61    QLIST_FOREACH(model, &watchdog_list, entry) {
     62        if (strcasecmp(model->wdt_name, p) == 0) {
     63            /* add the device */
     64            opts = qemu_opts_create(qemu_find_opts("device"), NULL, 0,
     65                                    &error_abort);
     66            qemu_opt_set(opts, "driver", p, &error_abort);
     67            return 0;
     68        }
     69    }
     70
     71    fprintf(stderr, "Unknown -watchdog device. Supported devices are:\n");
     72    QLIST_FOREACH(model, &watchdog_list, entry) {
     73        fprintf(stderr, "\t%s\t%s\n",
     74                 model->wdt_name, model->wdt_description);
     75    }
     76    return 1;
     77}
     78
     79int select_watchdog_action(const char *p)
     80{
     81    int action;
     82    char *qapi_value;
     83
     84    qapi_value = g_ascii_strdown(p, -1);
     85    action = qapi_enum_parse(&WatchdogAction_lookup, qapi_value, -1, NULL);
     86    g_free(qapi_value);
     87    if (action < 0)
     88        return -1;
     89    qmp_watchdog_set_action(action, &error_abort);
     90    return 0;
     91}
     92
     93WatchdogAction get_watchdog_action(void)
     94{
     95    return watchdog_action;
     96}
     97
     98/* This actually performs the "action" once a watchdog has expired,
     99 * ie. reboot, shutdown, exit, etc.
    100 */
    101void watchdog_perform_action(void)
    102{
    103    switch (watchdog_action) {
    104    case WATCHDOG_ACTION_RESET:     /* same as 'system_reset' in monitor */
    105        qapi_event_send_watchdog(WATCHDOG_ACTION_RESET);
    106        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
    107        break;
    108
    109    case WATCHDOG_ACTION_SHUTDOWN:  /* same as 'system_powerdown' in monitor */
    110        qapi_event_send_watchdog(WATCHDOG_ACTION_SHUTDOWN);
    111        qemu_system_powerdown_request();
    112        break;
    113
    114    case WATCHDOG_ACTION_POWEROFF:  /* same as 'quit' command in monitor */
    115        qapi_event_send_watchdog(WATCHDOG_ACTION_POWEROFF);
    116        exit(0);
    117
    118    case WATCHDOG_ACTION_PAUSE:     /* same as 'stop' command in monitor */
    119        /* In a timer callback, when vm_stop calls qemu_clock_enable
    120         * you would get a deadlock.  Bypass the problem.
    121         */
    122        qemu_system_vmstop_request_prepare();
    123        qapi_event_send_watchdog(WATCHDOG_ACTION_PAUSE);
    124        qemu_system_vmstop_request(RUN_STATE_WATCHDOG);
    125        break;
    126
    127    case WATCHDOG_ACTION_DEBUG:
    128        qapi_event_send_watchdog(WATCHDOG_ACTION_DEBUG);
    129        fprintf(stderr, "watchdog: timer fired\n");
    130        break;
    131
    132    case WATCHDOG_ACTION_NONE:
    133        qapi_event_send_watchdog(WATCHDOG_ACTION_NONE);
    134        break;
    135
    136    case WATCHDOG_ACTION_INJECT_NMI:
    137        qapi_event_send_watchdog(WATCHDOG_ACTION_INJECT_NMI);
    138        nmi_monitor_handle(0, NULL);
    139        break;
    140
    141    default:
    142        assert(0);
    143    }
    144}
    145
    146void qmp_watchdog_set_action(WatchdogAction action, Error **errp)
    147{
    148    watchdog_action = action;
    149}