watchdog.c 3.7 KB
Newer Older
R
Richard W.M. Jones 已提交
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * Virtual hardware watchdog.
 *
 * Copyright (C) 2009 Red Hat Inc.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation; either version 2
 * of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * 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/>.
R
Richard W.M. Jones 已提交
18 19 20 21 22
 *
 * By Richard W.M. Jones (rjones@redhat.com).
 */

#include "qemu-common.h"
M
Markus Armbruster 已提交
23 24
#include "qemu-option.h"
#include "qemu-config.h"
B
Blue Swirl 已提交
25
#include "qemu-queue.h"
R
Richard W.M. Jones 已提交
26 27 28
#include "sysemu.h"
#include "hw/watchdog.h"

29 30 31 32 33 34 35 36 37
/* Possible values for action parameter. */
#define WDT_RESET        1	/* Hard reset. */
#define WDT_SHUTDOWN     2	/* Shutdown. */
#define WDT_POWEROFF     3	/* Quit. */
#define WDT_PAUSE        4	/* Pause. */
#define WDT_DEBUG        5	/* Prints a message and continues running. */
#define WDT_NONE         6	/* Do nothing. */

static int watchdog_action = WDT_RESET;
B
Blue Swirl 已提交
38
static QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list;
R
Richard W.M. Jones 已提交
39 40 41

void watchdog_add_model(WatchdogTimerModel *model)
{
B
Blue Swirl 已提交
42
    QLIST_INSERT_HEAD(&watchdog_list, model, entry);
R
Richard W.M. Jones 已提交
43 44 45 46 47 48 49 50 51 52
}

/* Returns:
 *   0 = continue
 *   1 = exit program with error
 *   2 = exit program without error
 */
int select_watchdog(const char *p)
{
    WatchdogTimerModel *model;
M
Markus Armbruster 已提交
53
    QemuOpts *opts;
R
Richard W.M. Jones 已提交
54 55 56

    /* -watchdog ? lists available devices and exits cleanly. */
    if (strcmp(p, "?") == 0) {
B
Blue Swirl 已提交
57
        QLIST_FOREACH(model, &watchdog_list, entry) {
R
Richard W.M. Jones 已提交
58 59 60 61 62 63
            fprintf(stderr, "\t%s\t%s\n",
                     model->wdt_name, model->wdt_description);
        }
        return 2;
    }

B
Blue Swirl 已提交
64
    QLIST_FOREACH(model, &watchdog_list, entry) {
R
Richard W.M. Jones 已提交
65
        if (strcasecmp(model->wdt_name, p) == 0) {
M
Markus Armbruster 已提交
66 67 68
            /* add the device */
            opts = qemu_opts_create(&qemu_device_opts, NULL, 0);
            qemu_opt_set(opts, "driver", p);
R
Richard W.M. Jones 已提交
69 70 71 72 73
            return 0;
        }
    }

    fprintf(stderr, "Unknown -watchdog device. Supported devices are:\n");
B
Blue Swirl 已提交
74
    QLIST_FOREACH(model, &watchdog_list, entry) {
R
Richard W.M. Jones 已提交
75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
        fprintf(stderr, "\t%s\t%s\n",
                 model->wdt_name, model->wdt_description);
    }
    return 1;
}

int select_watchdog_action(const char *p)
{
    if (strcasecmp(p, "reset") == 0)
        watchdog_action = WDT_RESET;
    else if (strcasecmp(p, "shutdown") == 0)
        watchdog_action = WDT_SHUTDOWN;
    else if (strcasecmp(p, "poweroff") == 0)
        watchdog_action = WDT_POWEROFF;
    else if (strcasecmp(p, "pause") == 0)
        watchdog_action = WDT_PAUSE;
    else if (strcasecmp(p, "debug") == 0)
        watchdog_action = WDT_DEBUG;
    else if (strcasecmp(p, "none") == 0)
        watchdog_action = WDT_NONE;
    else
        return -1;

    return 0;
}

/* This actually performs the "action" once a watchdog has expired,
 * ie. reboot, shutdown, exit, etc.
 */
void watchdog_perform_action(void)
{
    switch(watchdog_action) {
    case WDT_RESET:             /* same as 'system_reset' in monitor */
        qemu_system_reset_request();
        break;

    case WDT_SHUTDOWN:          /* same as 'system_powerdown' in monitor */
        qemu_system_powerdown_request();
        break;

    case WDT_POWEROFF:          /* same as 'quit' command in monitor */
        exit(0);
        break;

    case WDT_PAUSE:             /* same as 'stop' command in monitor */
        vm_stop(0);
        break;

    case WDT_DEBUG:
        fprintf(stderr, "watchdog: timer fired\n");
        break;

    case WDT_NONE:
        break;
    }
}