xref: /qemu/hw/watchdog/watchdog.c (revision 32cad1ffb81dcecf6f4a8af56d6e5892682839b1)
19dd986ccSRichard W.M. Jones /*
29dd986ccSRichard W.M. Jones  * Virtual hardware watchdog.
39dd986ccSRichard W.M. Jones  *
49dd986ccSRichard W.M. Jones  * Copyright (C) 2009 Red Hat Inc.
59dd986ccSRichard W.M. Jones  *
69dd986ccSRichard W.M. Jones  * This program is free software; you can redistribute it and/or
79dd986ccSRichard W.M. Jones  * modify it under the terms of the GNU General Public License
89dd986ccSRichard W.M. Jones  * as published by the Free Software Foundation; either version 2
99dd986ccSRichard W.M. Jones  * of the License, or (at your option) any later version.
109dd986ccSRichard W.M. Jones  *
119dd986ccSRichard W.M. Jones  * This program is distributed in the hope that it will be useful,
129dd986ccSRichard W.M. Jones  * but WITHOUT ANY WARRANTY; without even the implied warranty of
139dd986ccSRichard W.M. Jones  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
149dd986ccSRichard W.M. Jones  * GNU General Public License for more details.
159dd986ccSRichard W.M. Jones  *
169dd986ccSRichard W.M. Jones  * You should have received a copy of the GNU General Public License
178167ee88SBlue Swirl  * along with this program; if not, see <http://www.gnu.org/licenses/>.
189dd986ccSRichard W.M. Jones  *
199dd986ccSRichard W.M. Jones  * By Richard W.M. Jones (rjones@redhat.com).
209dd986ccSRichard W.M. Jones  */
219dd986ccSRichard W.M. Jones 
220430891cSPeter Maydell #include "qemu/osdep.h"
231de7afc9SPaolo Bonzini #include "qemu/option.h"
241de7afc9SPaolo Bonzini #include "qemu/config-file.h"
251de7afc9SPaolo Bonzini #include "qemu/queue.h"
26e688df6bSMarkus Armbruster #include "qapi/error.h"
27112ed241SMarkus Armbruster #include "qapi/qapi-commands-run-state.h"
289af23989SMarkus Armbruster #include "qapi/qapi-events-run-state.h"
29*32cad1ffSPhilippe Mathieu-Daudé #include "system/runstate.h"
30*32cad1ffSPhilippe Mathieu-Daudé #include "system/watchdog.h"
31795dc6e4SMao Chuan Li #include "hw/nmi.h"
32f348b6d1SVeronia Bahaa #include "qemu/help_option.h"
336f10a29eSDaniel P. Berrangé #include "trace.h"
349dd986ccSRichard W.M. Jones 
354c7f4426SMichal Privoznik static WatchdogAction watchdog_action = WATCHDOG_ACTION_RESET;
369dd986ccSRichard W.M. Jones 
374c7f4426SMichal Privoznik WatchdogAction get_watchdog_action(void)
380d035b6cSBo Tu {
390d035b6cSBo Tu     return watchdog_action;
400d035b6cSBo Tu }
410d035b6cSBo Tu 
429dd986ccSRichard W.M. Jones /* This actually performs the "action" once a watchdog has expired,
439dd986ccSRichard W.M. Jones  * ie. reboot, shutdown, exit, etc.
449dd986ccSRichard W.M. Jones  */
459dd986ccSRichard W.M. Jones void watchdog_perform_action(void)
469dd986ccSRichard W.M. Jones {
476f10a29eSDaniel P. Berrangé     trace_watchdog_perform_action(watchdog_action);
486f10a29eSDaniel P. Berrangé 
499dd986ccSRichard W.M. Jones     switch (watchdog_action) {
504c7f4426SMichal Privoznik     case WATCHDOG_ACTION_RESET:     /* same as 'system_reset' in monitor */
513ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_RESET);
52cf83f140SEric Blake         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
539dd986ccSRichard W.M. Jones         break;
549dd986ccSRichard W.M. Jones 
554c7f4426SMichal Privoznik     case WATCHDOG_ACTION_SHUTDOWN:  /* same as 'system_powerdown' in monitor */
563ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_SHUTDOWN);
579dd986ccSRichard W.M. Jones         qemu_system_powerdown_request();
589dd986ccSRichard W.M. Jones         break;
599dd986ccSRichard W.M. Jones 
604c7f4426SMichal Privoznik     case WATCHDOG_ACTION_POWEROFF:  /* same as 'quit' command in monitor */
613ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_POWEROFF);
629dd986ccSRichard W.M. Jones         exit(0);
639dd986ccSRichard W.M. Jones 
644c7f4426SMichal Privoznik     case WATCHDOG_ACTION_PAUSE:     /* same as 'stop' command in monitor */
6530e5210aSPaolo Bonzini         /* In a timer callback, when vm_stop calls qemu_clock_enable
6630e5210aSPaolo Bonzini          * you would get a deadlock.  Bypass the problem.
6730e5210aSPaolo Bonzini          */
6830e5210aSPaolo Bonzini         qemu_system_vmstop_request_prepare();
693ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_PAUSE);
7030e5210aSPaolo Bonzini         qemu_system_vmstop_request(RUN_STATE_WATCHDOG);
719dd986ccSRichard W.M. Jones         break;
729dd986ccSRichard W.M. Jones 
734c7f4426SMichal Privoznik     case WATCHDOG_ACTION_DEBUG:
743ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_DEBUG);
759dd986ccSRichard W.M. Jones         fprintf(stderr, "watchdog: timer fired\n");
769dd986ccSRichard W.M. Jones         break;
779dd986ccSRichard W.M. Jones 
784c7f4426SMichal Privoznik     case WATCHDOG_ACTION_NONE:
793ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_NONE);
809dd986ccSRichard W.M. Jones         break;
81795dc6e4SMao Chuan Li 
824c7f4426SMichal Privoznik     case WATCHDOG_ACTION_INJECT_NMI:
833ab72385SPeter Xu         qapi_event_send_watchdog(WATCHDOG_ACTION_INJECT_NMI);
84f7e981f2SBandan Das         nmi_monitor_handle(0, NULL);
85795dc6e4SMao Chuan Li         break;
864c7f4426SMichal Privoznik 
874c7f4426SMichal Privoznik     default:
8874ee21a8SPierrick Bouvier         g_assert_not_reached();
899dd986ccSRichard W.M. Jones     }
909dd986ccSRichard W.M. Jones }
91f0df84c6SMichal Privoznik 
92f0df84c6SMichal Privoznik void qmp_watchdog_set_action(WatchdogAction action, Error **errp)
93f0df84c6SMichal Privoznik {
94f0df84c6SMichal Privoznik     watchdog_action = action;
956f10a29eSDaniel P. Berrangé     trace_watchdog_set_action(watchdog_action);
96f0df84c6SMichal Privoznik }
97