15d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* 25d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Virtual hardware watchdog. 35d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 45d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * Copyright (C) 2009 Red Hat Inc. 55d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 65d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This program is free software; you can redistribute it and/or 75d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * modify it under the terms of the GNU General Public License 85d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * as published by the Free Software Foundation; either version 2 95d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * of the License, or (at your option) any later version. 105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * This program is distributed in the hope that it will be useful, 125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * but WITHOUT ANY WARRANTY; without even the implied warranty of 135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * GNU General Public License for more details. 155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * You should have received a copy of the GNU General Public License 17a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner * along with this program; if not, see <http://www.gnu.org/licenses/>. 185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * By Richard W.M. Jones (rjones@redhat.com). 205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "qemu-common.h" 23a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner#include "qemu-queue.h" 245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "sysemu.h" 255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#include "hw/watchdog.h" 265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 27a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turnerstatic QLIST_HEAD(watchdog_list, WatchdogTimerModel) watchdog_list; 285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid watchdog_add_model(WatchdogTimerModel *model) 305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 31a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_INSERT_HEAD(&watchdog_list, model, entry); 325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* Returns: 355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 0 = continue 365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 1 = exit program with error 375d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * 2 = exit program without error 385d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 395d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint select_watchdog(const char *p) 405d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 415d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner WatchdogTimerModel *model; 425d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 435d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (watchdog) { 445d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, 455d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner "qemu: only one watchdog option may be given\n"); 465d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 475d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 485d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 495d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner /* -watchdog ? lists available devices and exits cleanly. */ 505d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcmp(p, "?") == 0) { 51a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_FOREACH(model, &watchdog_list, entry) { 525d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "\t%s\t%s\n", 535d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner model->wdt_name, model->wdt_description); 545d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 555d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 2; 565d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 575d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 58a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_FOREACH(model, &watchdog_list, entry) { 595d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcasecmp(model->wdt_name, p) == 0) { 605d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog = model; 615d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 625d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 635d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 645d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 655d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "Unknown -watchdog device. Supported devices are:\n"); 66a5d412078b8e7478d81df03710eacc7a21096ba2David 'Digit' Turner QLIST_FOREACH(model, &watchdog_list, entry) { 675d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "\t%s\t%s\n", 685d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner model->wdt_name, model->wdt_description); 695d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 705d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 1; 715d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 725d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 735d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnerint select_watchdog_action(const char *p) 745d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 755d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (strcasecmp(p, "reset") == 0) 765d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog_action = WDT_RESET; 775d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strcasecmp(p, "shutdown") == 0) 785d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog_action = WDT_SHUTDOWN; 795d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strcasecmp(p, "poweroff") == 0) 805d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog_action = WDT_POWEROFF; 815d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strcasecmp(p, "pause") == 0) 825d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog_action = WDT_PAUSE; 835d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strcasecmp(p, "debug") == 0) 845d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog_action = WDT_DEBUG; 855d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else if (strcasecmp(p, "none") == 0) 865d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog_action = WDT_NONE; 875d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner else 885d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return -1; 895d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 905d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner return 0; 915d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 925d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 935d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner/* This actually performs the "action" once a watchdog has expired, 945d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner * ie. reboot, shutdown, exit, etc. 955d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner */ 965d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid watchdog_perform_action(void) 975d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 985d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner switch(watchdog_action) { 995d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WDT_RESET: /* same as 'system_reset' in monitor */ 1005d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_system_reset_request(); 1015d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1025d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1035d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WDT_SHUTDOWN: /* same as 'system_powerdown' in monitor */ 1045d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner qemu_system_powerdown_request(); 1055d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1065d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1075d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WDT_POWEROFF: /* same as 'quit' command in monitor */ 1085d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner exit(0); 1095d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1105d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1115d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WDT_PAUSE: /* same as 'stop' command in monitor */ 1125d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner vm_stop(0); 1135d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1145d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1155d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WDT_DEBUG: 1165d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner fprintf(stderr, "watchdog: timer fired\n"); 1175d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1185d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1195d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner case WDT_NONE: 1205d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner break; 1215d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner } 1225d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1235d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1245d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid watchdog_pc_init(PCIBus *pci_bus) 1255d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1265d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner if (watchdog) 1275d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner watchdog->wdt_pc_init(pci_bus); 1285d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 1295d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner 1305d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turnervoid register_watchdogs(void) 1315d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner{ 1325d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#if 0 1335d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner wdt_ib700_init(); 1345d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner wdt_i6300esb_init(); 1355d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner#endif 1365d8f37ad78fc66901af50c762029a501561f3b23David 'Digit' Turner} 137