xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
       [not found] <20170428021317.24711-1-eblake@redhat.com>
@ 2017-04-28  2:13 ` Eric Blake
  2017-04-28  8:08   ` Dr. David Alan Gilbert
  2017-04-28 14:42   ` Markus Armbruster
  2017-04-28  2:13 ` [PATCH v5 3/4] shutdown: Add source information to SHUTDOWN and RESET Eric Blake
       [not found] ` <20170428021317.24711-4-eblake@redhat.com>
  2 siblings, 2 replies; 16+ messages in thread
From: Eric Blake @ 2017-04-28  2:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	Juan Quintela, armbru, alistair.francis, zhanghailiang,
	open list:X86, Anthony Perard, Paolo Bonzini,
	Dr. David Alan Gilbert, Richard Henderson

We want to track why a guest was shutdown; in particular, being able
to tell the difference between a guest request (such as ACPI request)
and host request (such as SIGINT) will prove useful to libvirt.
Since all requests eventually end up changing shutdown_requested in
vl.c, the logical change is to make that value track the reason,
rather than its current 0/1 contents.

Since command-line options control whether a reset request is turned
into a shutdown request instead, the same treatment is given to
reset_requested.

This patch adds a QAPI enum ShutdownCause that describes reasons
that a shutdown can be requested, and changes qemu_system_reset() to
pass the reason through, although for now it is not reported.  The
next patch will actually wire things up to modify events to report
data based on the reason, and to pass the correct enum value in from
various call-sites that can trigger a reset/shutdown.  Since QAPI
generates enums starting at 0, it's easier if we use a different
number as our sentinel that no request has happened yet.  Most of
the changes are in vl.c, but xen was using things externally.

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v4: s/ShutdownType/ShutdownCause/, no thanks to mingw header pollution
v3: new patch
---
 qapi-schema.json        | 23 +++++++++++++++++++++++
 include/sysemu/sysemu.h |  2 +-
 vl.c                    | 44 ++++++++++++++++++++++++++++----------------
 hw/i386/xen/xen-hvm.c   |  9 ++++++---
 migration/colo.c        |  2 +-
 migration/savevm.c      |  2 +-
 6 files changed, 60 insertions(+), 22 deletions(-)

diff --git a/qapi-schema.json b/qapi-schema.json
index 01b087f..a4ebdd1 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -2304,6 +2304,29 @@
 { 'command': 'system_powerdown' }

 ##
+# @ShutdownCause:
+#
+# Enumeration of various causes for shutdown.
+#
+# @host-qmp: Reaction to a QMP command, such as 'quit'
+# @host-signal: Reaction to a signal, such as SIGINT
+# @host-ui: Reaction to a UI event, such as closing the window
+# @host-replay: The host is replaying an earlier shutdown event
+# @host-error: Qemu encountered an error that prevents further use of the guest
+# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
+#                  other hardware-specific action
+# @guest-reset: The guest requested a reset, and the command line
+#               response to a reset is to instead trigger a shutdown
+# @guest-panic: The guest panicked, and the command line response to
+#               a panic is to trigger a shutdown
+#
+# Since: 2.10
+##
+{ 'enum': 'ShutdownCause',
+  'data': [ 'host-qmp', 'host-signal', 'host-ui', 'host-replay', 'host-error',
+            'guest-shutdown', 'guest-reset', 'guest-panic' ] }
+
+##
 # @cpu:
 #
 # This command is a nop that is only provided for the purposes of compatibility.
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 16175f7..00a907f 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -65,7 +65,7 @@ bool qemu_vmstop_requested(RunState *r);
 int qemu_shutdown_requested_get(void);
 int qemu_reset_requested_get(void);
 void qemu_system_killed(int signal, pid_t pid);
-void qemu_system_reset(bool report);
+void qemu_system_reset(bool report, int reason);
 void qemu_system_guest_panicked(GuestPanicInformation *info);
 size_t qemu_target_page_size(void);

diff --git a/vl.c b/vl.c
index 879786a..2b95b7f 100644
--- a/vl.c
+++ b/vl.c
@@ -1597,8 +1597,8 @@ void vm_state_notify(int running, RunState state)
     }
 }

-static int reset_requested;
-static int shutdown_requested, shutdown_signal;
+static int reset_requested = -1;
+static int shutdown_requested = -1, shutdown_signal;
 static pid_t shutdown_pid;
 static int powerdown_requested;
 static int debug_requested;
@@ -1624,7 +1624,7 @@ int qemu_reset_requested_get(void)

 static int qemu_shutdown_requested(void)
 {
-    return atomic_xchg(&shutdown_requested, 0);
+    return atomic_xchg(&shutdown_requested, -1);
 }

 static void qemu_kill_report(void)
@@ -1650,11 +1650,11 @@ static void qemu_kill_report(void)
 static int qemu_reset_requested(void)
 {
     int r = reset_requested;
-    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
-        reset_requested = 0;
+    if (r >= 0 && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
+        reset_requested = -1;
         return r;
     }
-    return false;
+    return -1;
 }

 static int qemu_suspend_requested(void)
@@ -1686,7 +1686,12 @@ static int qemu_debug_requested(void)
     return r;
 }

-void qemu_system_reset(bool report)
+/*
+ * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
+ * the @reason interpreted as ShutdownType for details.  Otherwise,
+ * @report is VMRESET_SILENT and @reason is ignored.
+ */
+void qemu_system_reset(bool report, int reason)
 {
     MachineClass *mc;

@@ -1700,6 +1705,7 @@ void qemu_system_reset(bool report)
         qemu_devices_reset();
     }
     if (report) {
+        assert(reason >= 0);
         qapi_event_send_reset(&error_abort);
     }
     cpu_synchronize_all_post_reset();
@@ -1738,9 +1744,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
 void qemu_system_reset_request(void)
 {
     if (no_reboot) {
-        shutdown_requested = 1;
+        /* FIXME - add a parameter to allow callers to specify reason */
+        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;
     } else {
-        reset_requested = 1;
+        reset_requested = SHUTDOWN_CAUSE_GUEST_RESET;
     }
     cpu_stop_current();
     qemu_notify_event();
@@ -1807,7 +1814,7 @@ void qemu_system_killed(int signal, pid_t pid)
     /* Cannot call qemu_system_shutdown_request directly because
      * we are in a signal handler.
      */
-    shutdown_requested = 1;
+    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
     qemu_notify_event();
 }

@@ -1815,7 +1822,8 @@ void qemu_system_shutdown_request(void)
 {
     trace_qemu_system_shutdown_request();
     replay_shutdown_request();
-    shutdown_requested = 1;
+    /* FIXME - add a parameter to allow callers to specify reason */
+    shutdown_requested = SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
     qemu_notify_event();
 }

@@ -1846,13 +1854,16 @@ void qemu_system_debug_request(void)
 static bool main_loop_should_exit(void)
 {
     RunState r;
+    int request;
+
     if (qemu_debug_requested()) {
         vm_stop(RUN_STATE_DEBUG);
     }
     if (qemu_suspend_requested()) {
         qemu_system_suspend();
     }
-    if (qemu_shutdown_requested()) {
+    request = qemu_shutdown_requested();
+    if (request >= 0) {
         qemu_kill_report();
         qapi_event_send_shutdown(&error_abort);
         if (no_shutdown) {
@@ -1861,9 +1872,10 @@ static bool main_loop_should_exit(void)
             return true;
         }
     }
-    if (qemu_reset_requested()) {
+    request = qemu_reset_requested();
+    if (request >= 0) {
         pause_all_vcpus();
-        qemu_system_reset(VMRESET_REPORT);
+        qemu_system_reset(VMRESET_REPORT, request);
         resume_all_vcpus();
         if (!runstate_check(RUN_STATE_RUNNING) &&
                 !runstate_check(RUN_STATE_INMIGRATE)) {
@@ -1872,7 +1884,7 @@ static bool main_loop_should_exit(void)
     }
     if (qemu_wakeup_requested()) {
         pause_all_vcpus();
-        qemu_system_reset(VMRESET_SILENT);
+        qemu_system_reset(VMRESET_SILENT, -1);
         notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
         wakeup_reason = QEMU_WAKEUP_REASON_NONE;
         resume_all_vcpus();
@@ -4684,7 +4696,7 @@ int main(int argc, char **argv, char **envp)
        reading from the other reads, because timer polling functions query
        clock values from the log. */
     replay_checkpoint(CHECKPOINT_RESET);
-    qemu_system_reset(VMRESET_SILENT);
+    qemu_system_reset(VMRESET_SILENT, -1);
     register_global_state();
     if (replay_mode != REPLAY_MODE_NONE) {
         replay_vmstate_init();
diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index b1c05ff..3a6484c 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -1089,11 +1089,14 @@ static void cpu_handle_ioreq(void *opaque)
          * causes Xen to powerdown the domain.
          */
         if (runstate_is_running()) {
-            if (qemu_shutdown_requested_get()) {
+            int request;
+
+            if (qemu_shutdown_requested_get() >= 0) {
                 destroy_hvm_domain(false);
             }
-            if (qemu_reset_requested_get()) {
-                qemu_system_reset(VMRESET_REPORT);
+            request = qemu_reset_requested_get();
+            if (request >= 0) {
+                qemu_system_reset(VMRESET_REPORT, request);
                 destroy_hvm_domain(true);
             }
         }
diff --git a/migration/colo.c b/migration/colo.c
index c19eb3f..17a5482 100644
--- a/migration/colo.c
+++ b/migration/colo.c
@@ -611,7 +611,7 @@ void *colo_process_incoming_thread(void *opaque)
         }

         qemu_mutex_lock_iothread();
-        qemu_system_reset(VMRESET_SILENT);
+        qemu_system_reset(VMRESET_SILENT, -1);
         vmstate_loading = true;
         if (qemu_loadvm_state(fb) < 0) {
             error_report("COLO: loadvm failed");
diff --git a/migration/savevm.c b/migration/savevm.c
index 03ae1bd..dcbaf00 100644
--- a/migration/savevm.c
+++ b/migration/savevm.c
@@ -2292,7 +2292,7 @@ int load_vmstate(const char *name)
         return -EINVAL;
     }

-    qemu_system_reset(VMRESET_SILENT);
+    qemu_system_reset(VMRESET_SILENT, -1);
     mis->from_src_file = f;

     aio_context_acquire(aio_context);
-- 
2.9.3


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* [PATCH v5 3/4] shutdown: Add source information to SHUTDOWN and RESET
       [not found] <20170428021317.24711-1-eblake@redhat.com>
  2017-04-28  2:13 ` [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request Eric Blake
@ 2017-04-28  2:13 ` Eric Blake
       [not found] ` <20170428021317.24711-4-eblake@redhat.com>
  2 siblings, 0 replies; 16+ messages in thread
From: Eric Blake @ 2017-04-28  2:13 UTC (permalink / raw)
  To: qemu-devel
  Cc: Peter Maydell, open list:Overall, Michael S. Tsirkin,
	Mark Cave-Ayland, Alexander Graf, Yongbok Kim, Gerd Hoffmann,
	Edgar E. Iglesias, Rob Herring, Stefano Stabellini,
	open list:Block layer core, Magnus Damm, armbru,
	Christian Borntraeger, Anthony Perard, open list:X86,
	Richard Henderson, Andrzej Zaborowski, Artyom Tarasenko,
	Eduardo Habkost, Stefan Weil, alistair.francis

Libvirt would like to be able to distinguish between a SHUTDOWN
event triggered solely by guest request and one triggered by a
SIGTERM or other action on the host.  While qemu_kill_report() is
already able to tell whether a shutdown was triggered by a host
signal (but NOT by a host UI event, such as clicking the X on
the window), that information was then lost after being printed
to stderr.  The previous patch prepped things to use an enum
internally; now it's time to wire it up through all callers, and
to extend the SHUTDOWN and RESET events to report the details.

Enhance the shutdown request path to take a parameter of which
way it is being triggered, and update ALL callers.  It would have
been less churn to keep the common case with no arguments as
meaning guest-triggered, and only modified the host-triggered
code paths, via a wrapper function, but then we'd still have to
audit that I didn't miss any host-triggered spots; changing the
signature forces us to double-check that I correctly categorized
all callers.

Since command line options can change whether a guest reset request
causes an actual reset vs. a shutdown, it's easy to also add the
information to the RESET event, even though libvirt has not yet
expressed a need to know that.

For the moment, we keep the enum ShutdownCause for internal use
only, and merely expose a single boolean of 'guest':true|false
to the QMP client; this is because we don't yet have evidence that
the further distinctions will be useful, or whether the addition
of new enum members would cause problems to clients coded to an
older version of the enum.

Update expected iotest outputs to match the new data.

Here is output from 'virsh qemu-monitor-event --loop' with the
patch installed:

event SHUTDOWN at 1492639680.731251 for domain fedora_13: {"guest":true}
event STOP at 1492639680.732116 for domain fedora_13: <null>
event SHUTDOWN at 1492639680.732830 for domain fedora_13: {"guest":false}

Note that libvirt runs qemu with -no-quit: the first SHUTDOWN event
was triggered by an action I took directly in the guest (shutdown -h),
at which point qemu stops the vcpus and waits for libvirt to do any
final cleanups; the second SHUTDOWN event is the result of libvirt
sending SIGTERM now that it has completed cleanup.

The replay driver needs a followup patch if we want to be able to
faithfully replay the difference between a host- and guest-initiated
shutdown (for now, the replayed event is always attributed to host).

See also https://bugzilla.redhat.com/1384007

Signed-off-by: Eric Blake <eblake@redhat.com>

---
v5: drop accidental addition of unrelated files
v4: s/ShutdownType/ShutdownCause/, no thanks to mingw header pollution
v3: retitle again, fix qemu-iotests, use enum rather than raw bool
in all callers
v2: retitle (was "event: Add signal information to SHUTDOWN"),
completely rework to post bool based on whether it is guest-initiated
v1: initial submission, exposing just Unix signals from host
---
 qapi/event.json             | 17 +++++++++++++----
 include/sysemu/sysemu.h     |  4 ++--
 vl.c                        | 22 +++++++++++-----------
 hw/acpi/core.c              |  4 ++--
 hw/arm/highbank.c           |  4 ++--
 hw/arm/integratorcp.c       |  2 +-
 hw/arm/musicpal.c           |  2 +-
 hw/arm/omap1.c              | 10 ++++++----
 hw/arm/omap2.c              |  2 +-
 hw/arm/spitz.c              |  2 +-
 hw/arm/stellaris.c          |  2 +-
 hw/arm/tosa.c               |  2 +-
 hw/i386/pc.c                |  2 +-
 hw/i386/xen/xen-hvm.c       |  2 +-
 hw/input/pckbd.c            |  4 ++--
 hw/ipmi/ipmi.c              |  4 ++--
 hw/isa/lpc_ich9.c           |  2 +-
 hw/mips/boston.c            |  2 +-
 hw/mips/mips_malta.c        |  2 +-
 hw/mips/mips_r4k.c          |  4 ++--
 hw/misc/arm_sysctl.c        |  8 ++++----
 hw/misc/cbus.c              |  2 +-
 hw/misc/macio/cuda.c        |  4 ++--
 hw/misc/slavio_misc.c       |  4 ++--
 hw/misc/zynq_slcr.c         |  2 +-
 hw/pci-host/apb.c           |  4 ++--
 hw/pci-host/bonito.c        |  2 +-
 hw/pci-host/piix.c          |  2 +-
 hw/ppc/e500.c               |  2 +-
 hw/ppc/mpc8544_guts.c       |  2 +-
 hw/ppc/ppc.c                |  2 +-
 hw/ppc/ppc405_uc.c          |  2 +-
 hw/ppc/spapr_hcall.c        |  2 +-
 hw/ppc/spapr_rtas.c         |  4 ++--
 hw/s390x/ipl.c              |  2 +-
 hw/sh4/r2d.c                |  2 +-
 hw/timer/etraxfs_timer.c    |  2 +-
 hw/timer/m48t59.c           |  4 ++--
 hw/timer/milkymist-sysctl.c |  4 ++--
 hw/timer/pxa2xx_timer.c     |  2 +-
 hw/watchdog/watchdog.c      |  2 +-
 hw/xenpv/xen_domainbuild.c  |  2 +-
 hw/xtensa/xtfpga.c          |  2 +-
 kvm-all.c                   |  6 +++---
 os-win32.c                  |  2 +-
 qmp.c                       |  4 ++--
 replay/replay.c             |  5 ++++-
 target/alpha/sys_helper.c   |  4 ++--
 target/arm/psci.c           |  4 ++--
 target/i386/excp_helper.c   |  2 +-
 target/i386/hax-all.c       |  6 +++---
 target/i386/helper.c        |  2 +-
 target/i386/kvm.c           |  2 +-
 target/s390x/helper.c       |  2 +-
 target/s390x/kvm.c          |  4 ++--
 target/s390x/misc_helper.c  |  4 ++--
 target/sparc/int32_helper.c |  2 +-
 ui/sdl.c                    |  2 +-
 ui/sdl2.c                   |  4 ++--
 tests/qemu-iotests/071.out  |  4 ++--
 tests/qemu-iotests/081.out  |  2 +-
 tests/qemu-iotests/087.out  | 12 ++++++------
 tests/qemu-iotests/094.out  |  2 +-
 tests/qemu-iotests/117.out  |  2 +-
 tests/qemu-iotests/119.out  |  2 +-
 tests/qemu-iotests/120.out  |  2 +-
 tests/qemu-iotests/140.out  |  2 +-
 tests/qemu-iotests/143.out  |  2 +-
 tests/qemu-iotests/156.out  |  2 +-
 trace-events                |  2 +-
 ui/cocoa.m                  |  2 +-
 71 files changed, 132 insertions(+), 118 deletions(-)

diff --git a/qapi/event.json b/qapi/event.json
index e80f3f4..6d22b02 100644
--- a/qapi/event.json
+++ b/qapi/event.json
@@ -10,6 +10,10 @@
 # Emitted when the virtual machine has shut down, indicating that qemu is
 # about to exit.
 #
+# @guest: If true, the shutdown was triggered by a guest request (such as
+# a guest-initiated ACPI shutdown request or other hardware-specific action)
+# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
+#
 # Note: If the command-line option "-no-shutdown" has been specified, qemu will
 # not exit, and a STOP event will eventually follow the SHUTDOWN event
 #
@@ -17,11 +21,11 @@
 #
 # Example:
 #
-# <- { "event": "SHUTDOWN",
+# <- { "event": "SHUTDOWN", "data": { "guest": true },
 #      "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
 #
 ##
-{ 'event': 'SHUTDOWN' }
+{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool' } }

 ##
 # @POWERDOWN:
@@ -44,15 +48,20 @@
 #
 # Emitted when the virtual machine is reset
 #
+# @guest: If true, the reset was triggered by a guest request (such as
+# a guest-initiated ACPI reboot request or other hardware-specific action)
+# rather than a host request (such as the QMP command system_reset).
+# (since 2.10)
+#
 # Since: 0.12.0
 #
 # Example:
 #
-# <- { "event": "RESET",
+# <- { "event": "RESET", "data": { "guest": false },
 #      "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
 #
 ##
-{ 'event': 'RESET' }
+{ 'event': 'RESET', 'data': { 'guest': 'bool' } }

 ##
 # @STOP:
diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
index 00a907f..ffbf9ac 100644
--- a/include/sysemu/sysemu.h
+++ b/include/sysemu/sysemu.h
@@ -49,13 +49,13 @@ typedef enum WakeupReason {
     QEMU_WAKEUP_REASON_OTHER,
 } WakeupReason;

-void qemu_system_reset_request(void);
+void qemu_system_reset_request(ShutdownCause reason);
 void qemu_system_suspend_request(void);
 void qemu_register_suspend_notifier(Notifier *notifier);
 void qemu_system_wakeup_request(WakeupReason reason);
 void qemu_system_wakeup_enable(WakeupReason reason, bool enabled);
 void qemu_register_wakeup_notifier(Notifier *notifier);
-void qemu_system_shutdown_request(void);
+void qemu_system_shutdown_request(ShutdownCause reason);
 void qemu_system_powerdown_request(void);
 void qemu_register_powerdown_notifier(Notifier *notifier);
 void qemu_system_debug_request(void);
diff --git a/vl.c b/vl.c
index 2b95b7f..0a933ba 100644
--- a/vl.c
+++ b/vl.c
@@ -1688,7 +1688,7 @@ static int qemu_debug_requested(void)

 /*
  * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
- * the @reason interpreted as ShutdownType for details.  Otherwise,
+ * the @reason interpreted as ShutdownCause for details.  Otherwise,
  * @report is VMRESET_SILENT and @reason is ignored.
  */
 void qemu_system_reset(bool report, int reason)
@@ -1706,7 +1706,8 @@ void qemu_system_reset(bool report, int reason)
     }
     if (report) {
         assert(reason >= 0);
-        qapi_event_send_reset(&error_abort);
+        qapi_event_send_reset(reason >= SHUTDOWN_CAUSE_GUEST_SHUTDOWN,
+                              &error_abort);
     }
     cpu_synchronize_all_post_reset();
 }
@@ -1724,7 +1725,7 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
     if (!no_shutdown) {
         qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
                                        !!info, info, &error_abort);
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
     }

     if (info) {
@@ -1741,11 +1742,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
     }
 }

-void qemu_system_reset_request(void)
+void qemu_system_reset_request(ShutdownCause reason)
 {
     if (no_reboot) {
-        /* FIXME - add a parameter to allow callers to specify reason */
-        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;
+        shutdown_requested = reason;
     } else {
         reset_requested = SHUTDOWN_CAUSE_GUEST_RESET;
     }
@@ -1818,12 +1818,11 @@ void qemu_system_killed(int signal, pid_t pid)
     qemu_notify_event();
 }

-void qemu_system_shutdown_request(void)
+void qemu_system_shutdown_request(ShutdownCause reason)
 {
-    trace_qemu_system_shutdown_request();
+    trace_qemu_system_shutdown_request(reason);
     replay_shutdown_request();
-    /* FIXME - add a parameter to allow callers to specify reason */
-    shutdown_requested = SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
+    shutdown_requested = reason;
     qemu_notify_event();
 }

@@ -1865,7 +1864,8 @@ static bool main_loop_should_exit(void)
     request = qemu_shutdown_requested();
     if (request >= 0) {
         qemu_kill_report();
-        qapi_event_send_shutdown(&error_abort);
+        qapi_event_send_shutdown(request >= SHUTDOWN_CAUSE_GUEST_SHUTDOWN,
+                                 &error_abort);
         if (no_shutdown) {
             vm_stop(RUN_STATE_SHUTDOWN);
         } else {
diff --git a/hw/acpi/core.c b/hw/acpi/core.c
index e890a5d..95fcac9 100644
--- a/hw/acpi/core.c
+++ b/hw/acpi/core.c
@@ -561,7 +561,7 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
         uint16_t sus_typ = (val >> 10) & 7;
         switch(sus_typ) {
         case 0: /* soft power off */
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
             break;
         case 1:
             qemu_system_suspend_request();
@@ -569,7 +569,7 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
         default:
             if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */
                 qapi_event_send_suspend_disk(&error_abort);
-                qemu_system_shutdown_request();
+                qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
             }
             break;
         }
diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
index 0a4508c..d209b97 100644
--- a/hw/arm/highbank.c
+++ b/hw/arm/highbank.c
@@ -108,9 +108,9 @@ static void hb_regs_write(void *opaque, hwaddr offset,

     if (offset == 0xf00) {
         if (value == 1 || value == 2) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         } else if (value == 3) {
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         }
     }

diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
index 5610ffc..ca3eca1 100644
--- a/hw/arm/integratorcp.c
+++ b/hw/arm/integratorcp.c
@@ -158,7 +158,7 @@ static void integratorcm_do_remap(IntegratorCMState *s)
 static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
 {
     if (value & 8) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     }
     if ((s->cm_ctrl ^ value) & 1) {
         /* (value & 1) != 0 means the green "MISC LED" is lit.
diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
index cbbca4e..9c710f7 100644
--- a/hw/arm/musicpal.c
+++ b/hw/arm/musicpal.c
@@ -898,7 +898,7 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,

     case MP_BOARD_RESET:
         if (value == MP_BOARD_RESET_MAGIC) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     }
diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
index b3cf0ec..54582bd 100644
--- a/hw/arm/omap1.c
+++ b/hw/arm/omap1.c
@@ -355,7 +355,7 @@ static void omap_wd_timer_write(void *opaque, hwaddr addr,
                 /* XXX: on T|E hardware somehow this has no effect,
                  * on Zire 71 it works as specified.  */
                 s->reset = 1;
-                qemu_system_reset_request();
+                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             }
         }
         s->last_wr = value & 0xff;
@@ -1545,8 +1545,10 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
     if (value & (1 << 11)) {                            /* SETARM_IDLE */
         cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
     }
-    if (!(value & (1 << 10)))				/* WKUP_MODE */
-        qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
+    if (!(value & (1 << 10))) {                         /* WKUP_MODE */
+        /* XXX: disable wakeup from IRQ */
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
+    }

 #define SET_CANIDLE(clock, bit)				\
     if (diff & (1 << bit)) {				\
@@ -1693,7 +1695,7 @@ static void omap_clkm_write(void *opaque, hwaddr addr,
         diff = s->clkm.arm_rstct1 ^ value;
         s->clkm.arm_rstct1 = value & 0x0007;
         if (value & 9) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             s->clkm.cold_start = 0xa;
         }
         if (diff & ~value & 4) {				/* DSP_RST */
diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
index cf1b4ba..8afb854 100644
--- a/hw/arm/omap2.c
+++ b/hw/arm/omap2.c
@@ -1610,7 +1610,7 @@ static void omap_prcm_write(void *opaque, hwaddr addr,
     case 0x450:	/* RM_RSTCTRL_WKUP */
         /* TODO: reset */
         if (value & 2)
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         break;
     case 0x454:	/* RM_RSTTIME_WKUP */
         s->rsttime_wkup = value & 0x1fff;
diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
index fe2d5a7..7e9f579 100644
--- a/hw/arm/spitz.c
+++ b/hw/arm/spitz.c
@@ -848,7 +848,7 @@ static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
 static void spitz_reset(void *opaque, int line, int level)
 {
     if (level) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     }
 }

diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
index ea7a809..cf6e7be 100644
--- a/hw/arm/stellaris.c
+++ b/hw/arm/stellaris.c
@@ -1197,7 +1197,7 @@ static
 void do_sys_reset(void *opaque, int n, int level)
 {
     if (level) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     }
 }

diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
index 9f58a23..2421b81 100644
--- a/hw/arm/tosa.c
+++ b/hw/arm/tosa.c
@@ -90,7 +90,7 @@ static void tosa_out_switch(void *opaque, int line, int level)
 static void tosa_reset(void *opaque, int line, int level)
 {
     if (level) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     }
 }

diff --git a/hw/i386/pc.c b/hw/i386/pc.c
index f3b372a..427f123 100644
--- a/hw/i386/pc.c
+++ b/hw/i386/pc.c
@@ -519,7 +519,7 @@ static void port92_write(void *opaque, hwaddr addr, uint64_t val,
     s->outport = val;
     qemu_set_irq(s->a20_out, (val >> 1) & 1);
     if ((val & 1) && !(oldval & 1)) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     }
 }

diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
index 3a6484c..70a1c1e 100644
--- a/hw/i386/xen/xen-hvm.c
+++ b/hw/i386/xen/xen-hvm.c
@@ -1398,7 +1398,7 @@ void xen_shutdown_fatal_error(const char *fmt, ...)
     va_end(ap);
     fprintf(stderr, "Will destroy the domain.\n");
     /* destroy the domain */
-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
 }

 void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
index d414288..c479f82 100644
--- a/hw/input/pckbd.c
+++ b/hw/input/pckbd.c
@@ -226,7 +226,7 @@ static void outport_write(KBDState *s, uint32_t val)
     s->outport = val;
     qemu_set_irq(s->a20_out, (val >> 1) & 1);
     if (!(val & 1)) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     }
 }

@@ -301,7 +301,7 @@ static void kbd_write_command(void *opaque, hwaddr addr,
         s->outport &= ~KBD_OUT_A20;
         break;
     case KBD_CCMD_RESET:
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         break;
     case KBD_CCMD_NO_OP:
         /* ignore that */
diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
index 5cf1caa..afafe14 100644
--- a/hw/ipmi/ipmi.c
+++ b/hw/ipmi/ipmi.c
@@ -44,14 +44,14 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
         if (checkonly) {
             return 0;
         }
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         return 0;

     case IPMI_POWEROFF_CHASSIS:
         if (checkonly) {
             return 0;
         }
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         return 0;

     case IPMI_SEND_NMI:
diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
index a0866c3..2b09354 100644
--- a/hw/isa/lpc_ich9.c
+++ b/hw/isa/lpc_ich9.c
@@ -606,7 +606,7 @@ static void ich9_rst_cnt_write(void *opaque, hwaddr addr, uint64_t val,
     ICH9LPCState *lpc = opaque;

     if (val & 4) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         return;
     }
     lpc->rst_cnt = val & 0xA; /* keep FULL_RST (bit 3) and SYS_RST (bit 1) */
diff --git a/hw/mips/boston.c b/hw/mips/boston.c
index 83f7b82..53d1e0c 100644
--- a/hw/mips/boston.c
+++ b/hw/mips/boston.c
@@ -232,7 +232,7 @@ static void boston_platreg_write(void *opaque, hwaddr addr,
         break;
     case PLAT_SOFTRST_CTL:
         if (val & PLAT_SOFTRST_CTL_SYSRESET) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     default:
diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
index 5dd177e..7814c39 100644
--- a/hw/mips/mips_malta.c
+++ b/hw/mips/mips_malta.c
@@ -470,7 +470,7 @@ static void malta_fpga_write(void *opaque, hwaddr addr,
     /* SOFTRES Register */
     case 0x00500:
         if (val == 0x42)
-            qemu_system_reset_request ();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         break;

     /* BRKRES Register */
diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
index 748586e..f4de9fc 100644
--- a/hw/mips/mips_r4k.c
+++ b/hw/mips/mips_r4k.c
@@ -53,9 +53,9 @@ static void mips_qemu_write (void *opaque, hwaddr addr,
                              uint64_t val, unsigned size)
 {
     if ((addr & 0xffff) == 0 && val == 42)
-        qemu_system_reset_request ();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     else if ((addr & 0xffff) == 4 && val == 42)
-        qemu_system_shutdown_request ();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 }

 static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
index 8524008..b20b44e 100644
--- a/hw/misc/arm_sysctl.c
+++ b/hw/misc/arm_sysctl.c
@@ -351,13 +351,13 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
         break;
     case SYS_CFG_SHUTDOWN:
         if (site == SYS_CFG_SITE_MB && device == 0) {
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
             return true;
         }
         break;
     case SYS_CFG_REBOOT:
         if (site == SYS_CFG_SITE_MB && device == 0) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             return true;
         }
         break;
@@ -429,7 +429,7 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
             if (s->lockval == LOCK_VALUE) {
                 s->resetlevel = val;
                 if (val & 0x100) {
-                    qemu_system_reset_request();
+                    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
                 }
             }
             break;
@@ -438,7 +438,7 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
             if (s->lockval == LOCK_VALUE) {
                 s->resetlevel = val;
                 if (val & 0x04) {
-                    qemu_system_reset_request();
+                    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
                 }
             }
             break;
diff --git a/hw/misc/cbus.c b/hw/misc/cbus.c
index 0c207e3..677274c 100644
--- a/hw/misc/cbus.c
+++ b/hw/misc/cbus.c
@@ -356,7 +356,7 @@ static inline void retu_write(CBusRetu *s, int reg, uint16_t val)

     case RETU_REG_WATCHDOG:
         if (val == 0 && (s->cc[0] & 2))
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         break;

     case RETU_REG_TXCR:
diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
index 05c02fb..008d8bd 100644
--- a/hw/misc/macio/cuda.c
+++ b/hw/misc/macio/cuda.c
@@ -612,7 +612,7 @@ static bool cuda_cmd_powerdown(CUDAState *s,
         return false;
     }

-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     return true;
 }

@@ -624,7 +624,7 @@ static bool cuda_cmd_reset_system(CUDAState *s,
         return false;
     }

-    qemu_system_reset_request();
+    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     return true;
 }

diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c
index edd5de0..18ff677 100644
--- a/hw/misc/slavio_misc.c
+++ b/hw/misc/slavio_misc.c
@@ -258,7 +258,7 @@ static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
         val &= AUX2_PWROFF;
     s->aux2 = val;
     if (val & AUX2_PWROFF)
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     slavio_misc_update_irq(s);
 }

@@ -338,7 +338,7 @@ static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
     case 0:
         if (val & SYS_RESET) {
             s->sysctrl = SYS_RESETSTAT;
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     default:
diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
index 7891219..44304d4 100644
--- a/hw/misc/zynq_slcr.c
+++ b/hw/misc/zynq_slcr.c
@@ -405,7 +405,7 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
     switch (offset) {
     case PSS_RST_CTRL:
         if (val & R_PSS_RST_CTRL_SOFT_RST) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     }
diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
index 653e711..83fc6a9 100644
--- a/hw/pci-host/apb.c
+++ b/hw/pci-host/apb.c
@@ -482,9 +482,9 @@ static void apb_config_writel (void *opaque, hwaddr addr,
             s->reset_control |= val & RESET_WMASK;
             if (val & SOFT_POR) {
                 s->nr_resets = 0;
-                qemu_system_reset_request();
+                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             } else if (val & SOFT_XIR) {
-                qemu_system_reset_request();
+                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             }
         }
         break;
diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
index 1999ece..b1d41d0 100644
--- a/hw/pci-host/bonito.c
+++ b/hw/pci-host/bonito.c
@@ -269,7 +269,7 @@ static void bonito_writel(void *opaque, hwaddr addr,
         }
         s->regs[saddr] = val;
         if (reset) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     case BONITO_INTENSET:
diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
index f9218aa..c1d6a85 100644
--- a/hw/pci-host/piix.c
+++ b/hw/pci-host/piix.c
@@ -638,7 +638,7 @@ static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
     PIIX3State *d = opaque;

     if (val & 4) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         return;
     }
     d->rcr = val & 2; /* keep System Reset type only */
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index f7df238..62f1857 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -774,7 +774,7 @@ static qemu_irq *ppce500_init_mpic(MachineState *machine, PPCE500Params *params,
 static void ppce500_power_off(void *opaque, int line, int on)
 {
     if (on) {
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     }
 }

diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
index ba69178..ce1254b 100644
--- a/hw/ppc/mpc8544_guts.c
+++ b/hw/ppc/mpc8544_guts.c
@@ -98,7 +98,7 @@ static void mpc8544_guts_write(void *opaque, hwaddr addr,
     switch (addr) {
     case MPC8544_GUTS_ADDR_RSTCR:
         if (value & MPC8544_GUTS_RSTCR_RESET) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     default:
diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
index 5f93083..224184d 100644
--- a/hw/ppc/ppc.c
+++ b/hw/ppc/ppc.c
@@ -412,7 +412,7 @@ static void ppce500_set_irq(void *opaque, int pin, int level)
             if (level) {
                 LOG_IRQ("%s: reset the PowerPC system\n",
                             __func__);
-                qemu_system_reset_request();
+                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             }
             break;
         case PPCE500_INPUT_RESET_CORE:
diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
index d5df94a..fc32e96 100644
--- a/hw/ppc/ppc405_uc.c
+++ b/hw/ppc/ppc405_uc.c
@@ -1807,7 +1807,7 @@ void ppc40x_chip_reset(PowerPCCPU *cpu)
 void ppc40x_system_reset(PowerPCCPU *cpu)
 {
     printf("Reset PowerPC system\n");
-    qemu_system_reset_request();
+    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 }

 void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
index 9f18f75..2735fe9 100644
--- a/hw/ppc/spapr_hcall.c
+++ b/hw/ppc/spapr_hcall.c
@@ -1166,7 +1166,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
     spapr_ovec_cleanup(ov5_updates);

     if (spapr->cas_reboot) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     } else {
         /* If ppc_spapr_reset() did not set up a HPT but one is necessary
          * (because the guest isn't going to use radix) then set it up here. */
diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
index 619f32c..128d993 100644
--- a/hw/ppc/spapr_rtas.c
+++ b/hw/ppc/spapr_rtas.c
@@ -110,7 +110,7 @@ static void rtas_power_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     cpu_stop_current();
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }
@@ -124,7 +124,7 @@ static void rtas_system_reboot(PowerPCCPU *cpu, sPAPRMachineState *spapr,
         rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
         return;
     }
-    qemu_system_reset_request();
+    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     rtas_st(rets, 0, RTAS_OUT_SUCCESS);
 }

diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
index 7978c7d..e5ab0ad 100644
--- a/hw/s390x/ipl.c
+++ b/hw/s390x/ipl.c
@@ -363,7 +363,7 @@ void s390_reipl_request(void)
     S390IPLState *ipl = get_ipl_device();

     ipl->reipl_requested = true;
-    qemu_system_reset_request();
+    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
 }

 void s390_ipl_prepare_cpu(S390CPU *cpu)
diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
index 8f520ce..e6fc74e 100644
--- a/hw/sh4/r2d.c
+++ b/hw/sh4/r2d.c
@@ -164,7 +164,7 @@ r2d_fpga_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size)
 	break;
     case PA_POWOFF:
         if (value & 1) {
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         }
         break;
     case PA_VERREG:
diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
index 8e18236..d13bc30 100644
--- a/hw/timer/etraxfs_timer.c
+++ b/hw/timer/etraxfs_timer.c
@@ -207,7 +207,7 @@ static void watchdog_hit(void *opaque)
         qemu_irq_raise(t->nmi);
     }
     else
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);

     t->wd_hits++;
 }
diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
index 474981a..4a064fb 100644
--- a/hw/timer/m48t59.c
+++ b/hw/timer/m48t59.c
@@ -1,7 +1,7 @@
 /*
  * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
  *
- * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
+ * Copyright (c) 2003-2005, 2007, 2017 Jocelyn Mayer
  * Copyright (c) 2013 Hervé Poussineau
  *
  * Permission is hereby granted, free of charge, to any person obtaining a copy
@@ -159,7 +159,7 @@ static void watchdog_cb (void *opaque)
 	NVRAM->buffer[0x1FF7] = 0x00;
 	NVRAM->buffer[0x1FFC] &= ~0x40;
         /* May it be a hw CPU Reset instead ? */
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     } else {
 	qemu_set_irq(NVRAM->IRQ, 1);
 	qemu_set_irq(NVRAM->IRQ, 0);
diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
index 4488590..93bc6e17 100644
--- a/hw/timer/milkymist-sysctl.c
+++ b/hw/timer/milkymist-sysctl.c
@@ -90,7 +90,7 @@ static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value)
     trace_milkymist_sysctl_icap_write(value);
     switch (value & 0xffff) {
     case 0x000e:
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         break;
     }
 }
@@ -195,7 +195,7 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
         s->regs[addr] = 1;
         break;
     case R_SYSTEM_ID:
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         break;

     case R_GPIO_IN:
diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
index 59002b4..68ba5a7 100644
--- a/hw/timer/pxa2xx_timer.c
+++ b/hw/timer/pxa2xx_timer.c
@@ -401,7 +401,7 @@ static void pxa2xx_timer_tick(void *opaque)
     if (t->num == 3)
         if (i->reset3 & 1) {
             i->reset3 = 0;
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
 }

diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
index 2aeaf1f..0c5c9cd 100644
--- a/hw/watchdog/watchdog.c
+++ b/hw/watchdog/watchdog.c
@@ -110,7 +110,7 @@ void watchdog_perform_action(void)
     switch (watchdog_action) {
     case WDT_RESET:             /* same as 'system_reset' in monitor */
         qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_RESET, &error_abort);
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         break;

     case WDT_SHUTDOWN:          /* same as 'system_powerdown' in monitor */
diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c
index 457a897..c89ced2 100644
--- a/hw/xenpv/xen_domainbuild.c
+++ b/hw/xenpv/xen_domainbuild.c
@@ -148,7 +148,7 @@ static void xen_domain_poll(void *opaque)
     return;

 quit:
-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 }

 static int xen_domain_watcher(void)
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index 11176e2..4636f8e 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -100,7 +100,7 @@ static void lx60_fpga_write(void *opaque, hwaddr addr,

     case 0x10: /*board reset*/
         if (val == 0xdead) {
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         }
         break;
     }
diff --git a/kvm-all.c b/kvm-all.c
index 90b8573..7df27c8 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -2052,7 +2052,7 @@ int kvm_cpu_exec(CPUState *cpu)
             break;
         case KVM_EXIT_SHUTDOWN:
             DPRINTF("shutdown\n");
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             ret = EXCP_INTERRUPT;
             break;
         case KVM_EXIT_UNKNOWN:
@@ -2066,11 +2066,11 @@ int kvm_cpu_exec(CPUState *cpu)
         case KVM_EXIT_SYSTEM_EVENT:
             switch (run->system_event.type) {
             case KVM_SYSTEM_EVENT_SHUTDOWN:
-                qemu_system_shutdown_request();
+                qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
                 ret = EXCP_INTERRUPT;
                 break;
             case KVM_SYSTEM_EVENT_RESET:
-                qemu_system_reset_request();
+                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
                 ret = EXCP_INTERRUPT;
                 break;
             case KVM_SYSTEM_EVENT_CRASH:
diff --git a/os-win32.c b/os-win32.c
index ae98574..586a7c7 100644
--- a/os-win32.c
+++ b/os-win32.c
@@ -52,7 +52,7 @@ int setenv(const char *name, const char *value, int overwrite)

 static BOOL WINAPI qemu_ctrl_handler(DWORD type)
 {
-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_SIGNAL);
     /* Windows 7 kills application when the function returns.
        Sleep here to give QEMU a try for closing.
        Sleep period is 10000ms because Windows kills the program
diff --git a/qmp.c b/qmp.c
index ab74cd7..95949d0 100644
--- a/qmp.c
+++ b/qmp.c
@@ -84,7 +84,7 @@ UuidInfo *qmp_query_uuid(Error **errp)
 void qmp_quit(Error **errp)
 {
     no_shutdown = 0;
-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP);
 }

 void qmp_stop(Error **errp)
@@ -105,7 +105,7 @@ void qmp_stop(Error **errp)

 void qmp_system_reset(Error **errp)
 {
-    qemu_system_reset_request();
+    qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP);
 }

 void qmp_system_powerdown(Error **erp)
diff --git a/replay/replay.c b/replay/replay.c
index f810628..55e82d9 100644
--- a/replay/replay.c
+++ b/replay/replay.c
@@ -51,7 +51,10 @@ bool replay_next_event_is(int event)
         switch (replay_state.data_kind) {
         case EVENT_SHUTDOWN:
             replay_finish_event();
-            qemu_system_shutdown_request();
+            /* TODO: track source of shutdown request, to replay a
+             * guest-initiated request rather than always claiming to
+             * be from the host? */
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_REPLAY);
             break;
         default:
             /* clock, time_t, checkpoint and other events */
diff --git a/target/alpha/sys_helper.c b/target/alpha/sys_helper.c
index 652195d..ac22323 100644
--- a/target/alpha/sys_helper.c
+++ b/target/alpha/sys_helper.c
@@ -60,9 +60,9 @@ void helper_tb_flush(CPUAlphaState *env)
 void helper_halt(uint64_t restart)
 {
     if (restart) {
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
     } else {
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
     }
 }

diff --git a/target/arm/psci.c b/target/arm/psci.c
index ade9fe2..fc34b26 100644
--- a/target/arm/psci.c
+++ b/target/arm/psci.c
@@ -137,7 +137,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
         }
         break;
     case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         /* QEMU reset and shutdown are async requests, but PSCI
          * mandates that we never return from the reset/shutdown
          * call, so power the CPU off now so it doesn't execute
@@ -145,7 +145,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
          */
         goto cpu_off;
     case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         goto cpu_off;
     case QEMU_PSCI_0_1_FN_CPU_ON:
     case QEMU_PSCI_0_2_FN_CPU_ON:
diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c
index ee596c6..b769772 100644
--- a/target/i386/excp_helper.c
+++ b/target/i386/excp_helper.c
@@ -59,7 +59,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code,

         qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");

-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         return EXCP_HLT;
     }
 #endif
diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
index ef13015..7346931 100644
--- a/target/i386/hax-all.c
+++ b/target/i386/hax-all.c
@@ -540,14 +540,14 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
         /* Guest state changed, currently only for shutdown */
         case HAX_EXIT_STATECHANGE:
             fprintf(stdout, "VCPU shutdown request\n");
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
             hax_vcpu_sync_state(env, 0);
             ret = 1;
             break;
         case HAX_EXIT_UNKNOWN_VMEXIT:
             fprintf(stderr, "Unknown VMX exit %x from guest\n",
                     ht->_exit_reason);
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             hax_vcpu_sync_state(env, 0);
             cpu_dump_state(cpu, stderr, fprintf, 0);
             ret = -1;
@@ -578,7 +578,7 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
             break;
         default:
             fprintf(stderr, "Unknown exit %x from HAX\n", ht->_exit_status);
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             hax_vcpu_sync_state(env, 0);
             cpu_dump_state(cpu, stderr, fprintf, 0);
             ret = 1;
diff --git a/target/i386/helper.c b/target/i386/helper.c
index f11cac6..ee7eff2 100644
--- a/target/i386/helper.c
+++ b/target/i386/helper.c
@@ -1212,7 +1212,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
                            " triple fault\n",
                            cs->cpu_index);
             qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             return;
         }
         if (banks[1] & MCI_STATUS_VAL) {
diff --git a/target/i386/kvm.c b/target/i386/kvm.c
index 55865db..cfd7695 100644
--- a/target/i386/kvm.c
+++ b/target/i386/kvm.c
@@ -2930,7 +2930,7 @@ int kvm_arch_process_async_events(CPUState *cs)

         if (env->exception_injected == EXCP08_DBLE) {
             /* this means triple fault */
-            qemu_system_reset_request();
+            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
             cs->exit_request = 1;
             return 0;
         }
diff --git a/target/s390x/helper.c b/target/s390x/helper.c
index 68bd2f9..d2bb9aa 100644
--- a/target/s390x/helper.c
+++ b/target/s390x/helper.c
@@ -266,7 +266,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
         S390CPU *cpu = s390_env_get_cpu(env);
         if (s390_cpu_halt(cpu) == 0) {
 #ifndef CONFIG_USER_ONLY
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 #endif
         }
     }
diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
index 1a249d8..284f5ef 100644
--- a/target/s390x/kvm.c
+++ b/target/s390x/kvm.c
@@ -1929,7 +1929,7 @@ static int handle_intercept(S390CPU *cpu)
             cpu_synchronize_state(cs);
             if (s390_cpu_halt(cpu) == 0) {
                 if (is_special_wait_psw(cs)) {
-                    qemu_system_shutdown_request();
+                    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
                 } else {
                     qemu_system_guest_panicked(NULL);
                 }
@@ -1938,7 +1938,7 @@ static int handle_intercept(S390CPU *cpu)
             break;
         case ICPT_CPU_STOP:
             if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
-                qemu_system_shutdown_request();
+                qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
             }
             if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
                 kvm_s390_store_status(cpu, KVM_S390_STORE_STATUS_DEF_ADDR,
diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
index eca8244..768043e 100644
--- a/target/s390x/misc_helper.c
+++ b/target/s390x/misc_helper.c
@@ -533,11 +533,11 @@ uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
         break;
 #if !defined(CONFIG_USER_ONLY)
     case SIGP_RESTART:
-        qemu_system_reset_request();
+        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
         cpu_loop_exit(CPU(s390_env_get_cpu(env)));
         break;
     case SIGP_STOP:
-        qemu_system_shutdown_request();
+        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         cpu_loop_exit(CPU(s390_env_get_cpu(env)));
         break;
 #endif
diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
index 09afe13..eec9a4d 100644
--- a/target/sparc/int32_helper.c
+++ b/target/sparc/int32_helper.c
@@ -109,7 +109,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
     if (env->psret == 0) {
         if (cs->exception_index == 0x80 &&
             env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
         } else {
             cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state",
                       cs->exception_index);
diff --git a/ui/sdl.c b/ui/sdl.c
index 37c21a0..bd51ffd 100644
--- a/ui/sdl.c
+++ b/ui/sdl.c
@@ -837,7 +837,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
         case SDL_QUIT:
             if (!no_quit) {
                 no_shutdown = 0;
-                qemu_system_shutdown_request();
+                qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
             }
             break;
         case SDL_MOUSEMOTION:
diff --git a/ui/sdl2.c b/ui/sdl2.c
index faf9bdf..e092636 100644
--- a/ui/sdl2.c
+++ b/ui/sdl2.c
@@ -568,7 +568,7 @@ static void handle_windowevent(SDL_Event *ev)
     case SDL_WINDOWEVENT_CLOSE:
         if (!no_quit) {
             no_shutdown = 0;
-            qemu_system_shutdown_request();
+            qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
         }
         break;
     case SDL_WINDOWEVENT_SHOWN:
@@ -611,7 +611,7 @@ void sdl2_poll_events(struct sdl2_console *scon)
         case SDL_QUIT:
             if (!no_quit) {
                 no_shutdown = 0;
-                qemu_system_shutdown_request();
+                qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
             }
             break;
         case SDL_MOUSEMOTION:
diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
index dd879f1..1d5e28d 100644
--- a/tests/qemu-iotests/071.out
+++ b/tests/qemu-iotests/071.out
@@ -46,7 +46,7 @@ QMP_VERSION
 read failed: Input/output error
 {"return": ""}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}


 === Testing blkverify on existing block device ===
@@ -85,7 +85,7 @@ wrote 512/512 bytes at offset 0
 read failed: Input/output error
 {"return": ""}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
 QEMU_PROG: Failed to flush the L2 table cache: Input/output error
 QEMU_PROG: Failed to flush the refcount block cache: Input/output error

diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
index 97df69d..2533c31 100644
--- a/tests/qemu-iotests/081.out
+++ b/tests/qemu-iotests/081.out
@@ -36,7 +36,7 @@ read 10485760/10485760 bytes at offset 0
 10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": ""}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}


 == using quorum rewrite corrupted mode ==
diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
index dc6baf9..59c5208 100644
--- a/tests/qemu-iotests/087.out
+++ b/tests/qemu-iotests/087.out
@@ -8,7 +8,7 @@ QMP_VERSION
 {"return": {}}
 {"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}


 === Duplicate ID ===
@@ -19,7 +19,7 @@ QMP_VERSION
 {"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
 {"error": {"class": "GenericError", "desc": "Duplicate node name"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}


 === aio=native without O_DIRECT ===
@@ -29,7 +29,7 @@ QMP_VERSION
 {"return": {}}
 {"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}


 === Encrypted image ===
@@ -40,14 +40,14 @@ QMP_VERSION
 {"return": {}}
 {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}

 Testing:
 QMP_VERSION
 {"return": {}}
 {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}


 === Missing driver ===
@@ -58,6 +58,6 @@ QMP_VERSION
 {"return": {}}
 {"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}

 *** done
diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out
index b66dc07..f52baff 100644
--- a/tests/qemu-iotests/094.out
+++ b/tests/qemu-iotests/094.out
@@ -7,5 +7,5 @@ Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
 {"return": {}}
 {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
 *** done
diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
index f52dc1a..851e214 100644
--- a/tests/qemu-iotests/117.out
+++ b/tests/qemu-iotests/117.out
@@ -7,7 +7,7 @@ wrote 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": ""}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
 No errors were found on the image.
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/tests/qemu-iotests/119.out b/tests/qemu-iotests/119.out
index 58e7114..a8743b8 100644
--- a/tests/qemu-iotests/119.out
+++ b/tests/qemu-iotests/119.out
@@ -6,6 +6,6 @@ read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": ""}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}

 *** done
diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
index 9131b1b..1af1aeb 100644
--- a/tests/qemu-iotests/120.out
+++ b/tests/qemu-iotests/120.out
@@ -6,7 +6,7 @@ wrote 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 {"return": ""}
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
 read 65536/65536 bytes at offset 0
diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
index 6c04456..0689b2b 100644
--- a/tests/qemu-iotests/140.out
+++ b/tests/qemu-iotests/140.out
@@ -10,5 +10,5 @@ read 65536/65536 bytes at offset 0
 {"return": {}}
 can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: No export with name 'drv' available
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
 *** done
diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
index d24ad20..0978b89 100644
--- a/tests/qemu-iotests/143.out
+++ b/tests/qemu-iotests/143.out
@@ -3,5 +3,5 @@ QA output created by 143
 {"return": {}}
 can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: No export with name 'no_such_export' available
 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
 *** done
diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
index 3af82ae..f96a564 100644
--- a/tests/qemu-iotests/156.out
+++ b/tests/qemu-iotests/156.out
@@ -34,7 +34,7 @@ read 65536/65536 bytes at offset 196608
 {"return": ""}

 {"return": {}}
-{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
+{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}

 read 65536/65536 bytes at offset 0
 64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
diff --git a/trace-events b/trace-events
index e582d63..433865f 100644
--- a/trace-events
+++ b/trace-events
@@ -38,7 +38,7 @@ vm_state_notify(int running, int reason) "running %d reason %d"
 load_file(const char *name, const char *path) "name %s location %s"
 runstate_set(int new_state) "new state %d"
 system_wakeup_request(int reason) "reason=%d"
-qemu_system_shutdown_request(void) ""
+qemu_system_shutdown_request(int reason) "reason=%d"
 qemu_system_powerdown_request(void) ""

 # spice-qemu-char.c
diff --git a/ui/cocoa.m b/ui/cocoa.m
index 207555e..f89f686 100644
--- a/ui/cocoa.m
+++ b/ui/cocoa.m
@@ -934,7 +934,7 @@ QemuCocoaView *cocoaView;
 {
     COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n");

-    qemu_system_shutdown_request();
+    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
     exit(0);
 }

-- 
2.9.3


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply related	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28  2:13 ` [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request Eric Blake
@ 2017-04-28  8:08   ` Dr. David Alan Gilbert
  2017-04-28 14:35     ` Eric Blake
  2017-04-28 14:45     ` [Qemu-devel] " Markus Armbruster
  2017-04-28 14:42   ` Markus Armbruster
  1 sibling, 2 replies; 16+ messages in thread
From: Dr. David Alan Gilbert @ 2017-04-28  8:08 UTC (permalink / raw)
  To: Eric Blake
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson

* Eric Blake (eblake@redhat.com) wrote:
> We want to track why a guest was shutdown; in particular, being able
> to tell the difference between a guest request (such as ACPI request)
> and host request (such as SIGINT) will prove useful to libvirt.
> Since all requests eventually end up changing shutdown_requested in
> vl.c, the logical change is to make that value track the reason,
> rather than its current 0/1 contents.
> 
> Since command-line options control whether a reset request is turned
> into a shutdown request instead, the same treatment is given to
> reset_requested.
> 
> This patch adds a QAPI enum ShutdownCause that describes reasons
> that a shutdown can be requested, and changes qemu_system_reset() to
> pass the reason through, although for now it is not reported.  The
> next patch will actually wire things up to modify events to report
> data based on the reason, and to pass the correct enum value in from
> various call-sites that can trigger a reset/shutdown.  Since QAPI
> generates enums starting at 0, it's easier if we use a different
> number as our sentinel that no request has happened yet.  Most of
> the changes are in vl.c, but xen was using things externally.
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>
> 
> ---
> v4: s/ShutdownType/ShutdownCause/, no thanks to mingw header pollution
> v3: new patch
> ---
>  qapi-schema.json        | 23 +++++++++++++++++++++++
>  include/sysemu/sysemu.h |  2 +-
>  vl.c                    | 44 ++++++++++++++++++++++++++++----------------
>  hw/i386/xen/xen-hvm.c   |  9 ++++++---
>  migration/colo.c        |  2 +-
>  migration/savevm.c      |  2 +-
>  6 files changed, 60 insertions(+), 22 deletions(-)
> 
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 01b087f..a4ebdd1 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2304,6 +2304,29 @@
>  { 'command': 'system_powerdown' }
> 
>  ##
> +# @ShutdownCause:
> +#
> +# Enumeration of various causes for shutdown.
> +#
> +# @host-qmp: Reaction to a QMP command, such as 'quit'
> +# @host-signal: Reaction to a signal, such as SIGINT
> +# @host-ui: Reaction to a UI event, such as closing the window
> +# @host-replay: The host is replaying an earlier shutdown event
> +# @host-error: Qemu encountered an error that prevents further use of the guest
> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
> +#                  other hardware-specific action
> +# @guest-reset: The guest requested a reset, and the command line
> +#               response to a reset is to instead trigger a shutdown
> +# @guest-panic: The guest panicked, and the command line response to
> +#               a panic is to trigger a shutdown

It's a little coarse grained;  is there anyway to pass platform specific information
for debug?  I ask because I spent a while debugging a few bugs with unexpected
resets and had to figure out which of x86's many reset causes triggered it.

Dave

> +# Since: 2.10
> +##
> +{ 'enum': 'ShutdownCause',
> +  'data': [ 'host-qmp', 'host-signal', 'host-ui', 'host-replay', 'host-error',
> +            'guest-shutdown', 'guest-reset', 'guest-panic' ] }
> +
> +##
>  # @cpu:
>  #
>  # This command is a nop that is only provided for the purposes of compatibility.
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 16175f7..00a907f 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -65,7 +65,7 @@ bool qemu_vmstop_requested(RunState *r);
>  int qemu_shutdown_requested_get(void);
>  int qemu_reset_requested_get(void);
>  void qemu_system_killed(int signal, pid_t pid);
> -void qemu_system_reset(bool report);
> +void qemu_system_reset(bool report, int reason);
>  void qemu_system_guest_panicked(GuestPanicInformation *info);
>  size_t qemu_target_page_size(void);
> 
> diff --git a/vl.c b/vl.c
> index 879786a..2b95b7f 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1597,8 +1597,8 @@ void vm_state_notify(int running, RunState state)
>      }
>  }
> 
> -static int reset_requested;
> -static int shutdown_requested, shutdown_signal;
> +static int reset_requested = -1;
> +static int shutdown_requested = -1, shutdown_signal;
>  static pid_t shutdown_pid;
>  static int powerdown_requested;
>  static int debug_requested;
> @@ -1624,7 +1624,7 @@ int qemu_reset_requested_get(void)
> 
>  static int qemu_shutdown_requested(void)
>  {
> -    return atomic_xchg(&shutdown_requested, 0);
> +    return atomic_xchg(&shutdown_requested, -1);
>  }
> 
>  static void qemu_kill_report(void)
> @@ -1650,11 +1650,11 @@ static void qemu_kill_report(void)
>  static int qemu_reset_requested(void)
>  {
>      int r = reset_requested;
> -    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> -        reset_requested = 0;
> +    if (r >= 0 && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> +        reset_requested = -1;
>          return r;
>      }
> -    return false;
> +    return -1;
>  }
> 
>  static int qemu_suspend_requested(void)
> @@ -1686,7 +1686,12 @@ static int qemu_debug_requested(void)
>      return r;
>  }
> 
> -void qemu_system_reset(bool report)
> +/*
> + * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
> + * the @reason interpreted as ShutdownType for details.  Otherwise,
> + * @report is VMRESET_SILENT and @reason is ignored.
> + */
> +void qemu_system_reset(bool report, int reason)
>  {
>      MachineClass *mc;
> 
> @@ -1700,6 +1705,7 @@ void qemu_system_reset(bool report)
>          qemu_devices_reset();
>      }
>      if (report) {
> +        assert(reason >= 0);
>          qapi_event_send_reset(&error_abort);
>      }
>      cpu_synchronize_all_post_reset();
> @@ -1738,9 +1744,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
>  void qemu_system_reset_request(void)
>  {
>      if (no_reboot) {
> -        shutdown_requested = 1;
> +        /* FIXME - add a parameter to allow callers to specify reason */
> +        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;
>      } else {
> -        reset_requested = 1;
> +        reset_requested = SHUTDOWN_CAUSE_GUEST_RESET;
>      }
>      cpu_stop_current();
>      qemu_notify_event();
> @@ -1807,7 +1814,7 @@ void qemu_system_killed(int signal, pid_t pid)
>      /* Cannot call qemu_system_shutdown_request directly because
>       * we are in a signal handler.
>       */
> -    shutdown_requested = 1;
> +    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
>      qemu_notify_event();
>  }
> 
> @@ -1815,7 +1822,8 @@ void qemu_system_shutdown_request(void)
>  {
>      trace_qemu_system_shutdown_request();
>      replay_shutdown_request();
> -    shutdown_requested = 1;
> +    /* FIXME - add a parameter to allow callers to specify reason */
> +    shutdown_requested = SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
>      qemu_notify_event();
>  }
> 
> @@ -1846,13 +1854,16 @@ void qemu_system_debug_request(void)
>  static bool main_loop_should_exit(void)
>  {
>      RunState r;
> +    int request;
> +
>      if (qemu_debug_requested()) {
>          vm_stop(RUN_STATE_DEBUG);
>      }
>      if (qemu_suspend_requested()) {
>          qemu_system_suspend();
>      }
> -    if (qemu_shutdown_requested()) {
> +    request = qemu_shutdown_requested();
> +    if (request >= 0) {
>          qemu_kill_report();
>          qapi_event_send_shutdown(&error_abort);
>          if (no_shutdown) {
> @@ -1861,9 +1872,10 @@ static bool main_loop_should_exit(void)
>              return true;
>          }
>      }
> -    if (qemu_reset_requested()) {
> +    request = qemu_reset_requested();
> +    if (request >= 0) {
>          pause_all_vcpus();
> -        qemu_system_reset(VMRESET_REPORT);
> +        qemu_system_reset(VMRESET_REPORT, request);
>          resume_all_vcpus();
>          if (!runstate_check(RUN_STATE_RUNNING) &&
>                  !runstate_check(RUN_STATE_INMIGRATE)) {
> @@ -1872,7 +1884,7 @@ static bool main_loop_should_exit(void)
>      }
>      if (qemu_wakeup_requested()) {
>          pause_all_vcpus();
> -        qemu_system_reset(VMRESET_SILENT);
> +        qemu_system_reset(VMRESET_SILENT, -1);
>          notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
>          wakeup_reason = QEMU_WAKEUP_REASON_NONE;
>          resume_all_vcpus();
> @@ -4684,7 +4696,7 @@ int main(int argc, char **argv, char **envp)
>         reading from the other reads, because timer polling functions query
>         clock values from the log. */
>      replay_checkpoint(CHECKPOINT_RESET);
> -    qemu_system_reset(VMRESET_SILENT);
> +    qemu_system_reset(VMRESET_SILENT, -1);
>      register_global_state();
>      if (replay_mode != REPLAY_MODE_NONE) {
>          replay_vmstate_init();
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index b1c05ff..3a6484c 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -1089,11 +1089,14 @@ static void cpu_handle_ioreq(void *opaque)
>           * causes Xen to powerdown the domain.
>           */
>          if (runstate_is_running()) {
> -            if (qemu_shutdown_requested_get()) {
> +            int request;
> +
> +            if (qemu_shutdown_requested_get() >= 0) {
>                  destroy_hvm_domain(false);
>              }
> -            if (qemu_reset_requested_get()) {
> -                qemu_system_reset(VMRESET_REPORT);
> +            request = qemu_reset_requested_get();
> +            if (request >= 0) {
> +                qemu_system_reset(VMRESET_REPORT, request);
>                  destroy_hvm_domain(true);
>              }
>          }
> diff --git a/migration/colo.c b/migration/colo.c
> index c19eb3f..17a5482 100644
> --- a/migration/colo.c
> +++ b/migration/colo.c
> @@ -611,7 +611,7 @@ void *colo_process_incoming_thread(void *opaque)
>          }
> 
>          qemu_mutex_lock_iothread();
> -        qemu_system_reset(VMRESET_SILENT);
> +        qemu_system_reset(VMRESET_SILENT, -1);
>          vmstate_loading = true;
>          if (qemu_loadvm_state(fb) < 0) {
>              error_report("COLO: loadvm failed");
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 03ae1bd..dcbaf00 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -2292,7 +2292,7 @@ int load_vmstate(const char *name)
>          return -EINVAL;
>      }
> 
> -    qemu_system_reset(VMRESET_SILENT);
> +    qemu_system_reset(VMRESET_SILENT, -1);
>      mis->from_src_file = f;
> 
>      aio_context_acquire(aio_context);
> -- 
> 2.9.3
> 
--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28  8:08   ` Dr. David Alan Gilbert
@ 2017-04-28 14:35     ` Eric Blake
  2017-04-28 15:27       ` Dr. David Alan Gilbert
  2017-04-28 14:45     ` [Qemu-devel] " Markus Armbruster
  1 sibling, 1 reply; 16+ messages in thread
From: Eric Blake @ 2017-04-28 14:35 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson


[-- Attachment #1.1.1: Type: text/plain, Size: 2594 bytes --]

On 04/28/2017 03:08 AM, Dr. David Alan Gilbert wrote:
> * Eric Blake (eblake@redhat.com) wrote:
>> We want to track why a guest was shutdown; in particular, being able
>> to tell the difference between a guest request (such as ACPI request)
>> and host request (such as SIGINT) will prove useful to libvirt.
>> Since all requests eventually end up changing shutdown_requested in
>> vl.c, the logical change is to make that value track the reason,
>> rather than its current 0/1 contents.
>>

>>  ##
>> +# @ShutdownCause:
>> +#
>> +# Enumeration of various causes for shutdown.
>> +#
>> +# @host-qmp: Reaction to a QMP command, such as 'quit'
>> +# @host-signal: Reaction to a signal, such as SIGINT
>> +# @host-ui: Reaction to a UI event, such as closing the window
>> +# @host-replay: The host is replaying an earlier shutdown event
>> +# @host-error: Qemu encountered an error that prevents further use of the guest
>> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
>> +#                  other hardware-specific action
>> +# @guest-reset: The guest requested a reset, and the command line
>> +#               response to a reset is to instead trigger a shutdown
>> +# @guest-panic: The guest panicked, and the command line response to
>> +#               a panic is to trigger a shutdown
> 
> It's a little coarse grained;  is there anyway to pass platform specific information
> for debug?  I ask because I spent a while debugging a few bugs with unexpected
> resets and had to figure out which of x86's many reset causes triggered it.

I'm open to any followup patches that add further enum values and
adjusts the various callers (patch 3 shows how MANY callers use
qemu_system_shutdown_request).  But I don't think it's necessarily in
scope for this series - remember, my goal here was merely to distinguish
between host- and guest-triggered resets (which libvirt and higher
management tasks want to know), rather than which of multiple reset
paths was taken (I agree that it is useful during a qemu debug session -
but that's a different audience).  I also don't consider myself an
expert in the many ways that x86 can reset - it was easy to blindly
rewrite qemu_system_shutdown_request() into
qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN) based solely
on directory, but it would be harder to distinguish which of the
multiple files should have which finer-grained cause.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28  2:13 ` [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request Eric Blake
  2017-04-28  8:08   ` Dr. David Alan Gilbert
@ 2017-04-28 14:42   ` Markus Armbruster
  2017-04-28 22:34     ` Eric Blake
  1 sibling, 1 reply; 16+ messages in thread
From: Markus Armbruster @ 2017-04-28 14:42 UTC (permalink / raw)
  To: Eric Blake
  Cc: Stefano Stabellini, Eduardo Habkost, Juan Quintela,
	Michael S. Tsirkin, qemu-devel, alistair.francis, Paolo Bonzini,
	Anthony Perard, open list:X86, Richard Henderson,
	Dr. David Alan Gilbert, zhanghailiang

Eric Blake <eblake@redhat.com> writes:

> We want to track why a guest was shutdown; in particular, being able
> to tell the difference between a guest request (such as ACPI request)
> and host request (such as SIGINT) will prove useful to libvirt.
> Since all requests eventually end up changing shutdown_requested in
> vl.c, the logical change is to make that value track the reason,
> rather than its current 0/1 contents.
>
> Since command-line options control whether a reset request is turned
> into a shutdown request instead, the same treatment is given to
> reset_requested.
>
> This patch adds a QAPI enum ShutdownCause that describes reasons
> that a shutdown can be requested, and changes qemu_system_reset() to
> pass the reason through, although for now it is not reported.  The
> next patch will actually wire things up to modify events to report
> data based on the reason, and to pass the correct enum value in from
> various call-sites that can trigger a reset/shutdown.  Since QAPI
> generates enums starting at 0, it's easier if we use a different
> number as our sentinel that no request has happened yet.  Most of
> the changes are in vl.c, but xen was using things externally.
>
> Signed-off-by: Eric Blake <eblake@redhat.com>
>
> ---
> v4: s/ShutdownType/ShutdownCause/, no thanks to mingw header pollution
> v3: new patch
> ---
>  qapi-schema.json        | 23 +++++++++++++++++++++++
>  include/sysemu/sysemu.h |  2 +-
>  vl.c                    | 44 ++++++++++++++++++++++++++++----------------
>  hw/i386/xen/xen-hvm.c   |  9 ++++++---
>  migration/colo.c        |  2 +-
>  migration/savevm.c      |  2 +-
>  6 files changed, 60 insertions(+), 22 deletions(-)
>
> diff --git a/qapi-schema.json b/qapi-schema.json
> index 01b087f..a4ebdd1 100644
> --- a/qapi-schema.json
> +++ b/qapi-schema.json
> @@ -2304,6 +2304,29 @@
>  { 'command': 'system_powerdown' }
>
>  ##
> +# @ShutdownCause:
> +#
> +# Enumeration of various causes for shutdown.
> +#
> +# @host-qmp: Reaction to a QMP command, such as 'quit'
> +# @host-signal: Reaction to a signal, such as SIGINT
> +# @host-ui: Reaction to a UI event, such as closing the window
> +# @host-replay: The host is replaying an earlier shutdown event
> +# @host-error: Qemu encountered an error that prevents further use of the guest
> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
> +#                  other hardware-specific action
> +# @guest-reset: The guest requested a reset, and the command line
> +#               response to a reset is to instead trigger a shutdown
> +# @guest-panic: The guest panicked, and the command line response to
> +#               a panic is to trigger a shutdown
> +#
> +# Since: 2.10
> +##
> +{ 'enum': 'ShutdownCause',
> +  'data': [ 'host-qmp', 'host-signal', 'host-ui', 'host-replay', 'host-error',
> +            'guest-shutdown', 'guest-reset', 'guest-panic' ] }
> +
> +##
>  # @cpu:
>  #
>  # This command is a nop that is only provided for the purposes of compatibility.
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 16175f7..00a907f 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -65,7 +65,7 @@ bool qemu_vmstop_requested(RunState *r);
>  int qemu_shutdown_requested_get(void);
>  int qemu_reset_requested_get(void);
>  void qemu_system_killed(int signal, pid_t pid);
> -void qemu_system_reset(bool report);
> +void qemu_system_reset(bool report, int reason);
>  void qemu_system_guest_panicked(GuestPanicInformation *info);
>  size_t qemu_target_page_size(void);
>
> diff --git a/vl.c b/vl.c
> index 879786a..2b95b7f 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1597,8 +1597,8 @@ void vm_state_notify(int running, RunState state)
>      }
>  }
>
> -static int reset_requested;
> -static int shutdown_requested, shutdown_signal;
> +static int reset_requested = -1;
> +static int shutdown_requested = -1, shutdown_signal;

Peeking ahead, I see that shutdown_requested and reset_requested take
ShutdownCause values and -1.  The latter means "no shutdown requested".
What about adding 'none' to ShutdownCause, with value 0, und use that
instead of literal -1?  Would avoid the unusual "negative means false,
non-negative means true".

PATCH 4 exposes ShutdownCause in event SHUTDOWN, and 'none' must not
occur there.  However, if we ever add a query-shutdown to go with this
event, we will need 'none' there.

I'd be tempted to reshuffle declarations here, because shutdown_signal's
int is a different one than reset_requested's and shutdown_requested,
and the latter two's "negative means false, non-negative means true" is
unusual enough to justify a comment.

>  static pid_t shutdown_pid;
>  static int powerdown_requested;
>  static int debug_requested;
> @@ -1624,7 +1624,7 @@ int qemu_reset_requested_get(void)
>
>  static int qemu_shutdown_requested(void)
>  {
> -    return atomic_xchg(&shutdown_requested, 0);
> +    return atomic_xchg(&shutdown_requested, -1);
>  }

Hmm.  In case we stick to literal -1: consider splitting this patch into
a part that changes @shutdown_requested from zero/non-zero to
negative/non-negative, and a part that uses ShutdownCause for the
non-negative values.

>
>  static void qemu_kill_report(void)
> @@ -1650,11 +1650,11 @@ static void qemu_kill_report(void)
>  static int qemu_reset_requested(void)
>  {
>      int r = reset_requested;
> -    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> -        reset_requested = 0;
> +    if (r >= 0 && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
> +        reset_requested = -1;
>          return r;
>      }
> -    return false;
> +    return -1;

"return false" in a function returning int smells, good riddance.

>  }
>
>  static int qemu_suspend_requested(void)
> @@ -1686,7 +1686,12 @@ static int qemu_debug_requested(void)
>      return r;
>  }
>
> -void qemu_system_reset(bool report)
> +/*
> + * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
> + * the @reason interpreted as ShutdownType for details.  Otherwise,
> + * @report is VMRESET_SILENT and @reason is ignored.
> + */
> +void qemu_system_reset(bool report, int reason)

Why int reason and not ShutdownCause?  Hmm, peeking ahead, I see you
pass -1 with VMRESET_SILENT.  Yet another place where you use int for
type ShutdownCause + { -1 }.  Adding 'none' to ShutdownCause looks
even more attractive to me now.

>  {
>      MachineClass *mc;
>
> @@ -1700,6 +1705,7 @@ void qemu_system_reset(bool report)
>          qemu_devices_reset();
>      }
>      if (report) {
> +        assert(reason >= 0);
>          qapi_event_send_reset(&error_abort);
>      }
>      cpu_synchronize_all_post_reset();
> @@ -1738,9 +1744,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
>  void qemu_system_reset_request(void)
>  {
>      if (no_reboot) {
> -        shutdown_requested = 1;
> +        /* FIXME - add a parameter to allow callers to specify reason */

FIXME addressed in the next patch.  Mention in this one's commit
message?

> +        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;
>      } else {
> -        reset_requested = 1;
> +        reset_requested = SHUTDOWN_CAUSE_GUEST_RESET;
>      }
>      cpu_stop_current();
>      qemu_notify_event();
> @@ -1807,7 +1814,7 @@ void qemu_system_killed(int signal, pid_t pid)
>      /* Cannot call qemu_system_shutdown_request directly because
>       * we are in a signal handler.
>       */
> -    shutdown_requested = 1;
> +    shutdown_requested = SHUTDOWN_CAUSE_HOST_SIGNAL;
>      qemu_notify_event();
>  }
>
> @@ -1815,7 +1822,8 @@ void qemu_system_shutdown_request(void)
>  {
>      trace_qemu_system_shutdown_request();
>      replay_shutdown_request();
> -    shutdown_requested = 1;
> +    /* FIXME - add a parameter to allow callers to specify reason */

Likewise.

> +    shutdown_requested = SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
>      qemu_notify_event();
>  }
>
> @@ -1846,13 +1854,16 @@ void qemu_system_debug_request(void)
>  static bool main_loop_should_exit(void)
>  {
>      RunState r;
> +    int request;
> +
>      if (qemu_debug_requested()) {
>          vm_stop(RUN_STATE_DEBUG);
>      }
>      if (qemu_suspend_requested()) {
>          qemu_system_suspend();
>      }
> -    if (qemu_shutdown_requested()) {
> +    request = qemu_shutdown_requested();
> +    if (request >= 0) {
>          qemu_kill_report();
>          qapi_event_send_shutdown(&error_abort);
>          if (no_shutdown) {
> @@ -1861,9 +1872,10 @@ static bool main_loop_should_exit(void)
>              return true;
>          }
>      }
> -    if (qemu_reset_requested()) {
> +    request = qemu_reset_requested();
> +    if (request >= 0) {
>          pause_all_vcpus();
> -        qemu_system_reset(VMRESET_REPORT);
> +        qemu_system_reset(VMRESET_REPORT, request);
>          resume_all_vcpus();
>          if (!runstate_check(RUN_STATE_RUNNING) &&
>                  !runstate_check(RUN_STATE_INMIGRATE)) {
> @@ -1872,7 +1884,7 @@ static bool main_loop_should_exit(void)
>      }
>      if (qemu_wakeup_requested()) {
>          pause_all_vcpus();
> -        qemu_system_reset(VMRESET_SILENT);
> +        qemu_system_reset(VMRESET_SILENT, -1);
>          notifier_list_notify(&wakeup_notifiers, &wakeup_reason);
>          wakeup_reason = QEMU_WAKEUP_REASON_NONE;
>          resume_all_vcpus();
> @@ -4684,7 +4696,7 @@ int main(int argc, char **argv, char **envp)
>         reading from the other reads, because timer polling functions query
>         clock values from the log. */
>      replay_checkpoint(CHECKPOINT_RESET);
> -    qemu_system_reset(VMRESET_SILENT);
> +    qemu_system_reset(VMRESET_SILENT, -1);
>      register_global_state();
>      if (replay_mode != REPLAY_MODE_NONE) {
>          replay_vmstate_init();
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index b1c05ff..3a6484c 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -1089,11 +1089,14 @@ static void cpu_handle_ioreq(void *opaque)
>           * causes Xen to powerdown the domain.
>           */
>          if (runstate_is_running()) {
> -            if (qemu_shutdown_requested_get()) {
> +            int request;
> +
> +            if (qemu_shutdown_requested_get() >= 0) {
>                  destroy_hvm_domain(false);
>              }
> -            if (qemu_reset_requested_get()) {
> -                qemu_system_reset(VMRESET_REPORT);
> +            request = qemu_reset_requested_get();
> +            if (request >= 0) {
> +                qemu_system_reset(VMRESET_REPORT, request);
>                  destroy_hvm_domain(true);
>              }
>          }
> diff --git a/migration/colo.c b/migration/colo.c
> index c19eb3f..17a5482 100644
> --- a/migration/colo.c
> +++ b/migration/colo.c
> @@ -611,7 +611,7 @@ void *colo_process_incoming_thread(void *opaque)
>          }
>
>          qemu_mutex_lock_iothread();
> -        qemu_system_reset(VMRESET_SILENT);
> +        qemu_system_reset(VMRESET_SILENT, -1);
>          vmstate_loading = true;
>          if (qemu_loadvm_state(fb) < 0) {
>              error_report("COLO: loadvm failed");
> diff --git a/migration/savevm.c b/migration/savevm.c
> index 03ae1bd..dcbaf00 100644
> --- a/migration/savevm.c
> +++ b/migration/savevm.c
> @@ -2292,7 +2292,7 @@ int load_vmstate(const char *name)
>          return -EINVAL;
>      }
>
> -    qemu_system_reset(VMRESET_SILENT);
> +    qemu_system_reset(VMRESET_SILENT, -1);
>      mis->from_src_file = f;
>
>      aio_context_acquire(aio_context);

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28  8:08   ` Dr. David Alan Gilbert
  2017-04-28 14:35     ` Eric Blake
@ 2017-04-28 14:45     ` Markus Armbruster
  1 sibling, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2017-04-28 14:45 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Stefano Stabellini, Eduardo Habkost, Juan Quintela,
	Michael S. Tsirkin, qemu-devel, alistair.francis, Paolo Bonzini,
	Anthony Perard, open list:X86, Richard Henderson, Eric Blake,
	zhanghailiang

"Dr. David Alan Gilbert" <dgilbert@redhat.com> writes:

> * Eric Blake (eblake@redhat.com) wrote:
>> We want to track why a guest was shutdown; in particular, being able
>> to tell the difference between a guest request (such as ACPI request)
>> and host request (such as SIGINT) will prove useful to libvirt.
>> Since all requests eventually end up changing shutdown_requested in
>> vl.c, the logical change is to make that value track the reason,
>> rather than its current 0/1 contents.
>> 
>> Since command-line options control whether a reset request is turned
>> into a shutdown request instead, the same treatment is given to
>> reset_requested.
>> 
>> This patch adds a QAPI enum ShutdownCause that describes reasons
>> that a shutdown can be requested, and changes qemu_system_reset() to
>> pass the reason through, although for now it is not reported.  The
>> next patch will actually wire things up to modify events to report
>> data based on the reason, and to pass the correct enum value in from
>> various call-sites that can trigger a reset/shutdown.  Since QAPI
>> generates enums starting at 0, it's easier if we use a different
>> number as our sentinel that no request has happened yet.  Most of
>> the changes are in vl.c, but xen was using things externally.
>> 
>> Signed-off-by: Eric Blake <eblake@redhat.com>
>> 
>> ---
>> v4: s/ShutdownType/ShutdownCause/, no thanks to mingw header pollution
>> v3: new patch
>> ---
>>  qapi-schema.json        | 23 +++++++++++++++++++++++
>>  include/sysemu/sysemu.h |  2 +-
>>  vl.c                    | 44 ++++++++++++++++++++++++++++----------------
>>  hw/i386/xen/xen-hvm.c   |  9 ++++++---
>>  migration/colo.c        |  2 +-
>>  migration/savevm.c      |  2 +-
>>  6 files changed, 60 insertions(+), 22 deletions(-)
>> 
>> diff --git a/qapi-schema.json b/qapi-schema.json
>> index 01b087f..a4ebdd1 100644
>> --- a/qapi-schema.json
>> +++ b/qapi-schema.json
>> @@ -2304,6 +2304,29 @@
>>  { 'command': 'system_powerdown' }
>> 
>>  ##
>> +# @ShutdownCause:
>> +#
>> +# Enumeration of various causes for shutdown.
>> +#
>> +# @host-qmp: Reaction to a QMP command, such as 'quit'
>> +# @host-signal: Reaction to a signal, such as SIGINT
>> +# @host-ui: Reaction to a UI event, such as closing the window
>> +# @host-replay: The host is replaying an earlier shutdown event
>> +# @host-error: Qemu encountered an error that prevents further use of the guest
>> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
>> +#                  other hardware-specific action
>> +# @guest-reset: The guest requested a reset, and the command line
>> +#               response to a reset is to instead trigger a shutdown
>> +# @guest-panic: The guest panicked, and the command line response to
>> +#               a panic is to trigger a shutdown
>
> It's a little coarse grained;  is there anyway to pass platform specific information
> for debug?  I ask because I spent a while debugging a few bugs with unexpected
> resets and had to figure out which of x86's many reset causes triggered it.

Asking for more help with debugging is fair, but I think the need is
better served by tracepoints than by exposing even more detail in QMP,
where compatibility promises apply.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v5 3/4] shutdown: Add source information to SHUTDOWN and RESET
       [not found] ` <20170428021317.24711-4-eblake@redhat.com>
@ 2017-04-28 15:01   ` Markus Armbruster
  2017-05-01  3:58   ` David Gibson
       [not found]   ` <87h918bmpz.fsf@dusky.pond.sub.org>
  2 siblings, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2017-04-28 15:01 UTC (permalink / raw)
  To: Eric Blake
  Cc: Peter Maydell, open list:Overall, Michael S. Tsirkin,
	Mark Cave-Ayland, qemu-devel, Cornelia Hu ck, Gerd Hoffmann,
	Edgar E. Iglesias, Rob Herring, Stefano Stabellini,
	open list:Block layer core, Magnus Damm, Alexander Graf,
	Christian Borntraeger, Anthony Perard, open list:X86,
	David Gibson, Artyom Tarasenko, Eduardo Habkost, Stefan Weil,
	alistair.francis

Eric Blake <eblake@redhat.com> writes:

> Libvirt would like to be able to distinguish between a SHUTDOWN
> event triggered solely by guest request and one triggered by a
> SIGTERM or other action on the host.  While qemu_kill_report() is
> already able to tell whether a shutdown was triggered by a host
> signal (but NOT by a host UI event, such as clicking the X on
> the window), that information was then lost after being printed
> to stderr.  The previous patch prepped things to use an enum
> internally; now it's time to wire it up through all callers, and
> to extend the SHUTDOWN and RESET events to report the details.
>
> Enhance the shutdown request path to take a parameter of which
> way it is being triggered, and update ALL callers.  It would have
> been less churn to keep the common case with no arguments as
> meaning guest-triggered, and only modified the host-triggered
> code paths, via a wrapper function, but then we'd still have to
> audit that I didn't miss any host-triggered spots; changing the
> signature forces us to double-check that I correctly categorized
> all callers.
>
> Since command line options can change whether a guest reset request
> causes an actual reset vs. a shutdown, it's easy to also add the
> information to the RESET event, even though libvirt has not yet
> expressed a need to know that.
>
> For the moment, we keep the enum ShutdownCause for internal use
> only, and merely expose a single boolean of 'guest':true|false
> to the QMP client; this is because we don't yet have evidence that
> the further distinctions will be useful, or whether the addition
> of new enum members would cause problems to clients coded to an
> older version of the enum.
>
> Update expected iotest outputs to match the new data.
>
> Here is output from 'virsh qemu-monitor-event --loop' with the
> patch installed:
>
> event SHUTDOWN at 1492639680.731251 for domain fedora_13: {"guest":true}
> event STOP at 1492639680.732116 for domain fedora_13: <null>
> event SHUTDOWN at 1492639680.732830 for domain fedora_13: {"guest":false}
>
> Note that libvirt runs qemu with -no-quit: the first SHUTDOWN event
> was triggered by an action I took directly in the guest (shutdown -h),
> at which point qemu stops the vcpus and waits for libvirt to do any
> final cleanups; the second SHUTDOWN event is the result of libvirt
> sending SIGTERM now that it has completed cleanup.
>
> The replay driver needs a followup patch if we want to be able to
> faithfully replay the difference between a host- and guest-initiated
> shutdown (for now, the replayed event is always attributed to host).

I'd prefer to get this right from the start, but that requires input
from replay guys.

Scandalously, replay/ is not covered by MAINTAINERS.
scripts/get_maintainers.pl blames it on Pavel Dovgalyuk (cc'ed), and git
shows recent activity.  Pavel, please post a suitable patch to
MAINTAINERS, and please help us figure out what to do about replaying
reset here.

> See also https://bugzilla.redhat.com/1384007
>
> Signed-off-by: Eric Blake <eblake@redhat.com>

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 14:35     ` Eric Blake
@ 2017-04-28 15:27       ` Dr. David Alan Gilbert
  2017-04-28 15:57         ` Eric Blake
  0 siblings, 1 reply; 16+ messages in thread
From: Dr. David Alan Gilbert @ 2017-04-28 15:27 UTC (permalink / raw)
  To: Eric Blake
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson

* Eric Blake (eblake@redhat.com) wrote:
> On 04/28/2017 03:08 AM, Dr. David Alan Gilbert wrote:
> > * Eric Blake (eblake@redhat.com) wrote:
> >> We want to track why a guest was shutdown; in particular, being able
> >> to tell the difference between a guest request (such as ACPI request)
> >> and host request (such as SIGINT) will prove useful to libvirt.
> >> Since all requests eventually end up changing shutdown_requested in
> >> vl.c, the logical change is to make that value track the reason,
> >> rather than its current 0/1 contents.
> >>
> 
> >>  ##
> >> +# @ShutdownCause:
> >> +#
> >> +# Enumeration of various causes for shutdown.
> >> +#
> >> +# @host-qmp: Reaction to a QMP command, such as 'quit'
> >> +# @host-signal: Reaction to a signal, such as SIGINT
> >> +# @host-ui: Reaction to a UI event, such as closing the window
> >> +# @host-replay: The host is replaying an earlier shutdown event
> >> +# @host-error: Qemu encountered an error that prevents further use of the guest
> >> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
> >> +#                  other hardware-specific action
> >> +# @guest-reset: The guest requested a reset, and the command line
> >> +#               response to a reset is to instead trigger a shutdown
> >> +# @guest-panic: The guest panicked, and the command line response to
> >> +#               a panic is to trigger a shutdown
> > 
> > It's a little coarse grained;  is there anyway to pass platform specific information
> > for debug?  I ask because I spent a while debugging a few bugs with unexpected
> > resets and had to figure out which of x86's many reset causes triggered it.
> 
> I'm open to any followup patches that add further enum values and
> adjusts the various callers (patch 3 shows how MANY callers use
> qemu_system_shutdown_request).  But I don't think it's necessarily in
> scope for this series - remember, my goal here was merely to distinguish
> between host- and guest-triggered resets (which libvirt and higher
> management tasks want to know)

Yep, that's fine.

> rather than which of multiple reset
> paths was taken (I agree that it is useful during a qemu debug session -
> but that's a different audience).  I also don't consider myself an
> expert in the many ways that x86 can reset - it was easy to blindly
> rewrite qemu_system_shutdown_request() into
> qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN) based solely
> on directory, but it would be harder to distinguish which of the
> multiple files should have which finer-grained cause.

Yes, I'm also not an expert on x86 resets - but when I was debugging
I just added a tag in every place it called the reset code.

At a higher level, using your tags, I'm not sure where a reset triggered
by a fault detected by the hypervisor lives - e.g. an x86 triple fault
where the guest screws up so badly that it just gets reset.  Is
that a guest-reset or a guest-panic or what - neither case
was actually asked for by the guest itself.

Dave


> 
> -- 
> Eric Blake, Principal Software Engineer
> Red Hat, Inc.           +1-919-301-3266
> Virtualization:  qemu.org | libvirt.org
> 



--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 15:27       ` Dr. David Alan Gilbert
@ 2017-04-28 15:57         ` Eric Blake
  2017-04-28 16:09           ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 16+ messages in thread
From: Eric Blake @ 2017-04-28 15:57 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson


[-- Attachment #1.1.1: Type: text/plain, Size: 1843 bytes --]

On 04/28/2017 10:27 AM, Dr. David Alan Gilbert wrote:

>>>> +# Enumeration of various causes for shutdown.
>>>> +#
>>>> +# @host-qmp: Reaction to a QMP command, such as 'quit'
>>>> +# @host-signal: Reaction to a signal, such as SIGINT
>>>> +# @host-ui: Reaction to a UI event, such as closing the window
>>>> +# @host-replay: The host is replaying an earlier shutdown event
>>>> +# @host-error: Qemu encountered an error that prevents further use of the guest
>>>> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
>>>> +#                  other hardware-specific action
>>>> +# @guest-reset: The guest requested a reset, and the command line
>>>> +#               response to a reset is to instead trigger a shutdown
>>>> +# @guest-panic: The guest panicked, and the command line response to
>>>> +#               a panic is to trigger a shutdown
>>>

> At a higher level, using your tags, I'm not sure where a reset triggered
> by a fault detected by the hypervisor lives - e.g. an x86 triple fault
> where the guest screws up so badly that it just gets reset.  Is
> that a guest-reset or a guest-panic or what - neither case
> was actually asked for by the guest itself.

Wouldn't that be host-error (qemu detected an error that prevents
further execution of the guest without a reset - and a triple fault
seems to fall into the category of the guest getting itself wedged
rather than actually trying to reset)?  Except patch 3 only used
SHUTDOWN_TYPE_HOST_ERROR in the xen portion of the patch.

So if any x86 expert has an opinion on where triple-fault handling is
emulated, and what category should be used there, I'm welcome to
tweaking this series.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 15:57         ` Eric Blake
@ 2017-04-28 16:09           ` Dr. David Alan Gilbert
  2017-04-28 18:05             ` Eric Blake
  0 siblings, 1 reply; 16+ messages in thread
From: Dr. David Alan Gilbert @ 2017-04-28 16:09 UTC (permalink / raw)
  To: Eric Blake
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson

* Eric Blake (eblake@redhat.com) wrote:
> On 04/28/2017 10:27 AM, Dr. David Alan Gilbert wrote:
> 
> >>>> +# Enumeration of various causes for shutdown.
> >>>> +#
> >>>> +# @host-qmp: Reaction to a QMP command, such as 'quit'
> >>>> +# @host-signal: Reaction to a signal, such as SIGINT
> >>>> +# @host-ui: Reaction to a UI event, such as closing the window
> >>>> +# @host-replay: The host is replaying an earlier shutdown event
> >>>> +# @host-error: Qemu encountered an error that prevents further use of the guest
> >>>> +# @guest-shutdown: The guest requested a shutdown, such as via ACPI or
> >>>> +#                  other hardware-specific action
> >>>> +# @guest-reset: The guest requested a reset, and the command line
> >>>> +#               response to a reset is to instead trigger a shutdown
> >>>> +# @guest-panic: The guest panicked, and the command line response to
> >>>> +#               a panic is to trigger a shutdown
> >>>
> 
> > At a higher level, using your tags, I'm not sure where a reset triggered
> > by a fault detected by the hypervisor lives - e.g. an x86 triple fault
> > where the guest screws up so badly that it just gets reset.  Is
> > that a guest-reset or a guest-panic or what - neither case
> > was actually asked for by the guest itself.
> 
> Wouldn't that be host-error (qemu detected an error that prevents
> further execution of the guest without a reset - and a triple fault
> seems to fall into the category of the guest getting itself wedged
> rather than actually trying to reset)?  Except patch 3 only used
> SHUTDOWN_TYPE_HOST_ERROR in the xen portion of the patch.
> 
> So if any x86 expert has an opinion on where triple-fault handling is
> emulated, and what category should be used there, I'm welcome to
> tweaking this series.

It's pretty much on the border anyway, I don't think it matters too
much; it sounds perfectly reasonable.

Dave

> -- 
> Eric Blake, Principal Software Engineer
> Red Hat, Inc.           +1-919-301-3266
> Virtualization:  qemu.org | libvirt.org
> 



--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 16:09           ` Dr. David Alan Gilbert
@ 2017-04-28 18:05             ` Eric Blake
  2017-04-28 18:13               ` Dr. David Alan Gilbert
  0 siblings, 1 reply; 16+ messages in thread
From: Eric Blake @ 2017-04-28 18:05 UTC (permalink / raw)
  To: Dr. David Alan Gilbert
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson


[-- Attachment #1.1.1: Type: text/plain, Size: 1598 bytes --]

On 04/28/2017 11:09 AM, Dr. David Alan Gilbert wrote:

>>> At a higher level, using your tags, I'm not sure where a reset triggered
>>> by a fault detected by the hypervisor lives - e.g. an x86 triple fault
>>> where the guest screws up so badly that it just gets reset.  Is
>>> that a guest-reset or a guest-panic or what - neither case
>>> was actually asked for by the guest itself.
>>
>> Wouldn't that be host-error (qemu detected an error that prevents
>> further execution of the guest without a reset - and a triple fault
>> seems to fall into the category of the guest getting itself wedged
>> rather than actually trying to reset)?  Except patch 3 only used
>> SHUTDOWN_TYPE_HOST_ERROR in the xen portion of the patch.
>>
>> So if any x86 expert has an opinion on where triple-fault handling is
>> emulated, and what category should be used there, I'm welcome to
>> tweaking this series.
> 
> It's pretty much on the border anyway, I don't think it matters too
> much; it sounds perfectly reasonable.

Actually, reading
https://blogs.msdn.microsoft.com/larryosterman/2005/02/08/faster-syscall-trap-redux/
makes it sound like the triple-fault = reset is exploited by existing OS
(dating back to days of targetting 286 machines), so it is bare-metal
behavior that we have to faithfully emulate as a guest-triggered reset,
and not something where the guest has wedged itself to the point where
qemu can no longer execute the guest.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 18:05             ` Eric Blake
@ 2017-04-28 18:13               ` Dr. David Alan Gilbert
  0 siblings, 0 replies; 16+ messages in thread
From: Dr. David Alan Gilbert @ 2017-04-28 18:13 UTC (permalink / raw)
  To: Eric Blake
  Cc: Stefano Stabellini, berrange, Eduardo Habkost, Michael S. Tsirkin,
	armbru, Juan Quintela, qemu-devel, alistair.francis,
	zhanghailiang, open list:X86, Anthony Perard, Paolo Bonzini,
	Richard Henderson

* Eric Blake (eblake@redhat.com) wrote:
> On 04/28/2017 11:09 AM, Dr. David Alan Gilbert wrote:
> 
> >>> At a higher level, using your tags, I'm not sure where a reset triggered
> >>> by a fault detected by the hypervisor lives - e.g. an x86 triple fault
> >>> where the guest screws up so badly that it just gets reset.  Is
> >>> that a guest-reset or a guest-panic or what - neither case
> >>> was actually asked for by the guest itself.
> >>
> >> Wouldn't that be host-error (qemu detected an error that prevents
> >> further execution of the guest without a reset - and a triple fault
> >> seems to fall into the category of the guest getting itself wedged
> >> rather than actually trying to reset)?  Except patch 3 only used
> >> SHUTDOWN_TYPE_HOST_ERROR in the xen portion of the patch.
> >>
> >> So if any x86 expert has an opinion on where triple-fault handling is
> >> emulated, and what category should be used there, I'm welcome to
> >> tweaking this series.
> > 
> > It's pretty much on the border anyway, I don't think it matters too
> > much; it sounds perfectly reasonable.
> 
> Actually, reading
> https://blogs.msdn.microsoft.com/larryosterman/2005/02/08/faster-syscall-trap-redux/
> makes it sound like the triple-fault = reset is exploited by existing OS
> (dating back to days of targetting 286 machines), so it is bare-metal
> behavior that we have to faithfully emulate as a guest-triggered reset,
> and not something where the guest has wedged itself to the point where
> qemu can no longer execute the guest.

The point is it's both :-)
A lot of x86 reset code tries four or five different ways to invoke
a reset and if all else fails they triple fault.

Dave

> -- 
> Eric Blake, Principal Software Engineer
> Red Hat, Inc.           +1-919-301-3266
> Virtualization:  qemu.org | libvirt.org
> 



--
Dr. David Alan Gilbert / dgilbert@redhat.com / Manchester, UK

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 14:42   ` Markus Armbruster
@ 2017-04-28 22:34     ` Eric Blake
  2017-05-02 11:47       ` Markus Armbruster
  0 siblings, 1 reply; 16+ messages in thread
From: Eric Blake @ 2017-04-28 22:34 UTC (permalink / raw)
  To: Markus Armbruster
  Cc: Stefano Stabellini, Eduardo Habkost, Juan Quintela,
	Michael S. Tsirkin, qemu-devel, alistair.francis, Paolo Bonzini,
	Anthony Perard, open list:X86, Richard Henderson,
	Dr. David Alan Gilbert, zhanghailiang


[-- Attachment #1.1.1: Type: text/plain, Size: 7456 bytes --]

On 04/28/2017 09:42 AM, Markus Armbruster wrote:
> Eric Blake <eblake@redhat.com> writes:
> 
>> We want to track why a guest was shutdown; in particular, being able
>> to tell the difference between a guest request (such as ACPI request)
>> and host request (such as SIGINT) will prove useful to libvirt.
>> Since all requests eventually end up changing shutdown_requested in
>> vl.c, the logical change is to make that value track the reason,
>> rather than its current 0/1 contents.
>>
>> Since command-line options control whether a reset request is turned
>> into a shutdown request instead, the same treatment is given to
>> reset_requested.
>>
>> This patch adds a QAPI enum ShutdownCause that describes reasons
>> that a shutdown can be requested, and changes qemu_system_reset() to
>> pass the reason through, although for now it is not reported.  The
>> next patch will actually wire things up to modify events to report
>> data based on the reason, and to pass the correct enum value in from
>> various call-sites that can trigger a reset/shutdown.  Since QAPI
>> generates enums starting at 0, it's easier if we use a different
>> number as our sentinel that no request has happened yet.  Most of
>> the changes are in vl.c, but xen was using things externally.
>>

>> -static int reset_requested;
>> -static int shutdown_requested, shutdown_signal;
>> +static int reset_requested = -1;
>> +static int shutdown_requested = -1, shutdown_signal;
> 
> Peeking ahead, I see that shutdown_requested and reset_requested take
> ShutdownCause values and -1.  The latter means "no shutdown requested".
> What about adding 'none' to ShutdownCause, with value 0, und use that
> instead of literal -1?  Would avoid the unusual "negative means false,
> non-negative means true".

Works nicely if the enum is internal-use only.  Gets a bit more awkward
if the enum is exposed to the end-user.

The fact that I let QAPI generate the enum in patch 3 is evidence that
I'm leaning towards exposing it to the end user (patch 4); if we want to
keep it internal-only, a better place for the enum might be in sysemu.h
(where we also have the weird '#define VMRESET_SILENT false' '#define
VMRESET_REPORT true' to name a boolean parameter).

> 
> PATCH 4 exposes ShutdownCause in event SHUTDOWN, and 'none' must not
> occur there.  However, if we ever add a query-shutdown to go with this
> event, we will need 'none' there.

So, query-shutdown would basically be: what is the last-reported
shutdown event (normally none, when the guest is still running; but if,
like libvirt, you start qemu -no-shutdown, it can then be the cause of
why we are in a shutdown/stopped state while waiting for final cleanup)?

How important/likely is such an event?  (Hmm, from libvirt's
perspective, events are usually reliable, but can be lost; if we can
restart libvirtd and reconnect to a qemu process that is hanging on to
life only because no one has cleaned it up yet, query-shutdown does seem
like a useful thing for libvirt to have at the time it reconnects to
that qemu process).

We could always include 'none' in the QAPI enum, then document in
'SHUTDOWN' and 'RESET' events that the cause will never be 'none'.  Doc
hacks like that feel a little unclean, but not so horrible as to be
unforgivable.

> 
> I'd be tempted to reshuffle declarations here, because shutdown_signal's
> int is a different one than reset_requested's and shutdown_requested,
> and the latter two's "negative means false, non-negative means true" is
> unusual enough to justify a comment.
...
> 
> Hmm.  In case we stick to literal -1: consider splitting this patch into
> a part that changes @shutdown_requested from zero/non-zero to
> negative/non-negative, and a part that uses ShutdownCause for the
> non-negative values.


You're definitely right that if the enum doesn't have a nice none=0
state, then reshuffling to the magic -1 as no request is awkward enough
to be done alone.

But part of the answer is also dependent on whether we want PATCH 4 or
not (or, as you brought up, the possibility of a query-shutdown command
with even more persistent storage of the last-reported event).


>> @@ -1650,11 +1650,11 @@ static void qemu_kill_report(void)
>>  static int qemu_reset_requested(void)
>>  {
>>      int r = reset_requested;
>> -    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
>> -        reset_requested = 0;
>> +    if (r >= 0 && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
>> +        reset_requested = -1;
>>          return r;
>>      }
>> -    return false;
>> +    return -1;
> 
> "return false" in a function returning int smells, good riddance.
> 

In one of my earlier drafts of the patch, I even tried to change the
return type from int to bool, but decided that keeping it as int worked
best (if I have to use the -1/cause dichotomy).  But you're also right
that with a 'none' value in the enum, I could directly return ShutdownCause.

>>  }
>>
>>  static int qemu_suspend_requested(void)
>> @@ -1686,7 +1686,12 @@ static int qemu_debug_requested(void)
>>      return r;
>>  }
>>
>> -void qemu_system_reset(bool report)
>> +/*
>> + * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
>> + * the @reason interpreted as ShutdownType for details.  Otherwise,
>> + * @report is VMRESET_SILENT and @reason is ignored.
>> + */
>> +void qemu_system_reset(bool report, int reason)
> 
> Why int reason and not ShutdownCause?  Hmm, peeking ahead, I see you
> pass -1 with VMRESET_SILENT.  Yet another place where you use int for
> type ShutdownCause + { -1 }.  Adding 'none' to ShutdownCause looks
> even more attractive to me now.

Yeah, it's getting to be that way to me to, even if it just means that I
may have volunteered myself into writing a query-shutdown QMP command.

>> @@ -1738,9 +1744,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
>>  void qemu_system_reset_request(void)
>>  {
>>      if (no_reboot) {
>> -        shutdown_requested = 1;
>> +        /* FIXME - add a parameter to allow callers to specify reason */
> 
> FIXME addressed in the next patch.  Mention in this one's commit
> message?

Sure. Something like "Mark a couple of places as FIXME where we have to
guess a value to use; a later patch will fix things to supply a correct
value".

> 
>> +        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;

I've also debated about splitting patch 3 into two parts: the event
member additions (affecting .json and vl.c) and the parameter additions
(affecting all other call-sites).  If I add the event parameter first,
then supplying a bogus value to the event means extra churn to qemu
iotests output files unless I change THIS line of code to guess
SHUTDOWN_CAUSE_HOST_QMP; the other option is to wire up parameter
passing first and event reporting last.

I'll wait for more inputs before respinning this series (I already did a
poor enough job slamming mailboxes by sending 3 iterations of the series
in one day).  As you mention, I'd still like to hear ideas for the
replay side of things, and I wouldn't mind if Dan has any ideas from the
libvirt/upper-layer stack usage side of things on the fate of patch 4.

-- 
Eric Blake, Principal Software Engineer
Red Hat, Inc.           +1-919-301-3266
Virtualization:  qemu.org | libvirt.org


[-- Attachment #1.2: OpenPGP digital signature --]
[-- Type: application/pgp-signature, Size: 604 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [PATCH v5 3/4] shutdown: Add source information to SHUTDOWN and RESET
       [not found] ` <20170428021317.24711-4-eblake@redhat.com>
  2017-04-28 15:01   ` [Qemu-devel] " Markus Armbruster
@ 2017-05-01  3:58   ` David Gibson
       [not found]   ` <87h918bmpz.fsf@dusky.pond.sub.org>
  2 siblings, 0 replies; 16+ messages in thread
From: David Gibson @ 2017-05-01  3:58 UTC (permalink / raw)
  To: Eric Blake
  Cc: Peter Maydell, open list:Overall, Michael S. Tsirkin,
	Mark Cave-Ayland, qemu-devel, Alexander Graf, Yongbok Kim,
	Gerd Hoffmann, Edgar E. Iglesias, Rob Herring, Stefano Stabellini,
	open list:Block layer core, Magnus Damm, armbru,
	Christian Borntraeger, Anthony Perard, open list:X86,
	Andrzej Zaborowski, Artyom Tarasenko, Eduardo Habkost,
	Stefan Weil, alistair.francis, Calxeda 


[-- Attachment #1.1: Type: text/plain, Size: 58582 bytes --]

On Thu, Apr 27, 2017 at 09:13:16PM -0500, Eric Blake wrote:
> Libvirt would like to be able to distinguish between a SHUTDOWN
> event triggered solely by guest request and one triggered by a
> SIGTERM or other action on the host.  While qemu_kill_report() is
> already able to tell whether a shutdown was triggered by a host
> signal (but NOT by a host UI event, such as clicking the X on
> the window), that information was then lost after being printed
> to stderr.  The previous patch prepped things to use an enum
> internally; now it's time to wire it up through all callers, and
> to extend the SHUTDOWN and RESET events to report the details.
> 
> Enhance the shutdown request path to take a parameter of which
> way it is being triggered, and update ALL callers.  It would have
> been less churn to keep the common case with no arguments as
> meaning guest-triggered, and only modified the host-triggered
> code paths, via a wrapper function, but then we'd still have to
> audit that I didn't miss any host-triggered spots; changing the
> signature forces us to double-check that I correctly categorized
> all callers.
> 
> Since command line options can change whether a guest reset request
> causes an actual reset vs. a shutdown, it's easy to also add the
> information to the RESET event, even though libvirt has not yet
> expressed a need to know that.
> 
> For the moment, we keep the enum ShutdownCause for internal use
> only, and merely expose a single boolean of 'guest':true|false
> to the QMP client; this is because we don't yet have evidence that
> the further distinctions will be useful, or whether the addition
> of new enum members would cause problems to clients coded to an
> older version of the enum.
> 
> Update expected iotest outputs to match the new data.
> 
> Here is output from 'virsh qemu-monitor-event --loop' with the
> patch installed:
> 
> event SHUTDOWN at 1492639680.731251 for domain fedora_13: {"guest":true}
> event STOP at 1492639680.732116 for domain fedora_13: <null>
> event SHUTDOWN at 1492639680.732830 for domain fedora_13: {"guest":false}
> 
> Note that libvirt runs qemu with -no-quit: the first SHUTDOWN event
> was triggered by an action I took directly in the guest (shutdown -h),
> at which point qemu stops the vcpus and waits for libvirt to do any
> final cleanups; the second SHUTDOWN event is the result of libvirt
> sending SIGTERM now that it has completed cleanup.
> 
> The replay driver needs a followup patch if we want to be able to
> faithfully replay the difference between a host- and guest-initiated
> shutdown (for now, the replayed event is always attributed to host).
> 
> See also https://bugzilla.redhat.com/1384007
> 
> Signed-off-by: Eric Blake <eblake@redhat.com>

ppc parts

Acked-by: David Gibson <david@gibson.dropbear.id.au>

> 
> ---
> v5: drop accidental addition of unrelated files
> v4: s/ShutdownType/ShutdownCause/, no thanks to mingw header pollution
> v3: retitle again, fix qemu-iotests, use enum rather than raw bool
> in all callers
> v2: retitle (was "event: Add signal information to SHUTDOWN"),
> completely rework to post bool based on whether it is guest-initiated
> v1: initial submission, exposing just Unix signals from host
> ---
>  qapi/event.json             | 17 +++++++++++++----
>  include/sysemu/sysemu.h     |  4 ++--
>  vl.c                        | 22 +++++++++++-----------
>  hw/acpi/core.c              |  4 ++--
>  hw/arm/highbank.c           |  4 ++--
>  hw/arm/integratorcp.c       |  2 +-
>  hw/arm/musicpal.c           |  2 +-
>  hw/arm/omap1.c              | 10 ++++++----
>  hw/arm/omap2.c              |  2 +-
>  hw/arm/spitz.c              |  2 +-
>  hw/arm/stellaris.c          |  2 +-
>  hw/arm/tosa.c               |  2 +-
>  hw/i386/pc.c                |  2 +-
>  hw/i386/xen/xen-hvm.c       |  2 +-
>  hw/input/pckbd.c            |  4 ++--
>  hw/ipmi/ipmi.c              |  4 ++--
>  hw/isa/lpc_ich9.c           |  2 +-
>  hw/mips/boston.c            |  2 +-
>  hw/mips/mips_malta.c        |  2 +-
>  hw/mips/mips_r4k.c          |  4 ++--
>  hw/misc/arm_sysctl.c        |  8 ++++----
>  hw/misc/cbus.c              |  2 +-
>  hw/misc/macio/cuda.c        |  4 ++--
>  hw/misc/slavio_misc.c       |  4 ++--
>  hw/misc/zynq_slcr.c         |  2 +-
>  hw/pci-host/apb.c           |  4 ++--
>  hw/pci-host/bonito.c        |  2 +-
>  hw/pci-host/piix.c          |  2 +-
>  hw/ppc/e500.c               |  2 +-
>  hw/ppc/mpc8544_guts.c       |  2 +-
>  hw/ppc/ppc.c                |  2 +-
>  hw/ppc/ppc405_uc.c          |  2 +-
>  hw/ppc/spapr_hcall.c        |  2 +-
>  hw/ppc/spapr_rtas.c         |  4 ++--
>  hw/s390x/ipl.c              |  2 +-
>  hw/sh4/r2d.c                |  2 +-
>  hw/timer/etraxfs_timer.c    |  2 +-
>  hw/timer/m48t59.c           |  4 ++--
>  hw/timer/milkymist-sysctl.c |  4 ++--
>  hw/timer/pxa2xx_timer.c     |  2 +-
>  hw/watchdog/watchdog.c      |  2 +-
>  hw/xenpv/xen_domainbuild.c  |  2 +-
>  hw/xtensa/xtfpga.c          |  2 +-
>  kvm-all.c                   |  6 +++---
>  os-win32.c                  |  2 +-
>  qmp.c                       |  4 ++--
>  replay/replay.c             |  5 ++++-
>  target/alpha/sys_helper.c   |  4 ++--
>  target/arm/psci.c           |  4 ++--
>  target/i386/excp_helper.c   |  2 +-
>  target/i386/hax-all.c       |  6 +++---
>  target/i386/helper.c        |  2 +-
>  target/i386/kvm.c           |  2 +-
>  target/s390x/helper.c       |  2 +-
>  target/s390x/kvm.c          |  4 ++--
>  target/s390x/misc_helper.c  |  4 ++--
>  target/sparc/int32_helper.c |  2 +-
>  ui/sdl.c                    |  2 +-
>  ui/sdl2.c                   |  4 ++--
>  tests/qemu-iotests/071.out  |  4 ++--
>  tests/qemu-iotests/081.out  |  2 +-
>  tests/qemu-iotests/087.out  | 12 ++++++------
>  tests/qemu-iotests/094.out  |  2 +-
>  tests/qemu-iotests/117.out  |  2 +-
>  tests/qemu-iotests/119.out  |  2 +-
>  tests/qemu-iotests/120.out  |  2 +-
>  tests/qemu-iotests/140.out  |  2 +-
>  tests/qemu-iotests/143.out  |  2 +-
>  tests/qemu-iotests/156.out  |  2 +-
>  trace-events                |  2 +-
>  ui/cocoa.m                  |  2 +-
>  71 files changed, 132 insertions(+), 118 deletions(-)
> 
> diff --git a/qapi/event.json b/qapi/event.json
> index e80f3f4..6d22b02 100644
> --- a/qapi/event.json
> +++ b/qapi/event.json
> @@ -10,6 +10,10 @@
>  # Emitted when the virtual machine has shut down, indicating that qemu is
>  # about to exit.
>  #
> +# @guest: If true, the shutdown was triggered by a guest request (such as
> +# a guest-initiated ACPI shutdown request or other hardware-specific action)
> +# rather than a host request (such as sending qemu a SIGINT). (since 2.10)
> +#
>  # Note: If the command-line option "-no-shutdown" has been specified, qemu will
>  # not exit, and a STOP event will eventually follow the SHUTDOWN event
>  #
> @@ -17,11 +21,11 @@
>  #
>  # Example:
>  #
> -# <- { "event": "SHUTDOWN",
> +# <- { "event": "SHUTDOWN", "data": { "guest": true },
>  #      "timestamp": { "seconds": 1267040730, "microseconds": 682951 } }
>  #
>  ##
> -{ 'event': 'SHUTDOWN' }
> +{ 'event': 'SHUTDOWN', 'data': { 'guest': 'bool' } }
> 
>  ##
>  # @POWERDOWN:
> @@ -44,15 +48,20 @@
>  #
>  # Emitted when the virtual machine is reset
>  #
> +# @guest: If true, the reset was triggered by a guest request (such as
> +# a guest-initiated ACPI reboot request or other hardware-specific action)
> +# rather than a host request (such as the QMP command system_reset).
> +# (since 2.10)
> +#
>  # Since: 0.12.0
>  #
>  # Example:
>  #
> -# <- { "event": "RESET",
> +# <- { "event": "RESET", "data": { "guest": false },
>  #      "timestamp": { "seconds": 1267041653, "microseconds": 9518 } }
>  #
>  ##
> -{ 'event': 'RESET' }
> +{ 'event': 'RESET', 'data': { 'guest': 'bool' } }
> 
>  ##
>  # @STOP:
> diff --git a/include/sysemu/sysemu.h b/include/sysemu/sysemu.h
> index 00a907f..ffbf9ac 100644
> --- a/include/sysemu/sysemu.h
> +++ b/include/sysemu/sysemu.h
> @@ -49,13 +49,13 @@ typedef enum WakeupReason {
>      QEMU_WAKEUP_REASON_OTHER,
>  } WakeupReason;
> 
> -void qemu_system_reset_request(void);
> +void qemu_system_reset_request(ShutdownCause reason);
>  void qemu_system_suspend_request(void);
>  void qemu_register_suspend_notifier(Notifier *notifier);
>  void qemu_system_wakeup_request(WakeupReason reason);
>  void qemu_system_wakeup_enable(WakeupReason reason, bool enabled);
>  void qemu_register_wakeup_notifier(Notifier *notifier);
> -void qemu_system_shutdown_request(void);
> +void qemu_system_shutdown_request(ShutdownCause reason);
>  void qemu_system_powerdown_request(void);
>  void qemu_register_powerdown_notifier(Notifier *notifier);
>  void qemu_system_debug_request(void);
> diff --git a/vl.c b/vl.c
> index 2b95b7f..0a933ba 100644
> --- a/vl.c
> +++ b/vl.c
> @@ -1688,7 +1688,7 @@ static int qemu_debug_requested(void)
> 
>  /*
>   * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
> - * the @reason interpreted as ShutdownType for details.  Otherwise,
> + * the @reason interpreted as ShutdownCause for details.  Otherwise,
>   * @report is VMRESET_SILENT and @reason is ignored.
>   */
>  void qemu_system_reset(bool report, int reason)
> @@ -1706,7 +1706,8 @@ void qemu_system_reset(bool report, int reason)
>      }
>      if (report) {
>          assert(reason >= 0);
> -        qapi_event_send_reset(&error_abort);
> +        qapi_event_send_reset(reason >= SHUTDOWN_CAUSE_GUEST_SHUTDOWN,
> +                              &error_abort);
>      }
>      cpu_synchronize_all_post_reset();
>  }
> @@ -1724,7 +1725,7 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
>      if (!no_shutdown) {
>          qapi_event_send_guest_panicked(GUEST_PANIC_ACTION_POWEROFF,
>                                         !!info, info, &error_abort);
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_PANIC);
>      }
> 
>      if (info) {
> @@ -1741,11 +1742,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
>      }
>  }
> 
> -void qemu_system_reset_request(void)
> +void qemu_system_reset_request(ShutdownCause reason)
>  {
>      if (no_reboot) {
> -        /* FIXME - add a parameter to allow callers to specify reason */
> -        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;
> +        shutdown_requested = reason;
>      } else {
>          reset_requested = SHUTDOWN_CAUSE_GUEST_RESET;
>      }
> @@ -1818,12 +1818,11 @@ void qemu_system_killed(int signal, pid_t pid)
>      qemu_notify_event();
>  }
> 
> -void qemu_system_shutdown_request(void)
> +void qemu_system_shutdown_request(ShutdownCause reason)
>  {
> -    trace_qemu_system_shutdown_request();
> +    trace_qemu_system_shutdown_request(reason);
>      replay_shutdown_request();
> -    /* FIXME - add a parameter to allow callers to specify reason */
> -    shutdown_requested = SHUTDOWN_CAUSE_GUEST_SHUTDOWN;
> +    shutdown_requested = reason;
>      qemu_notify_event();
>  }
> 
> @@ -1865,7 +1864,8 @@ static bool main_loop_should_exit(void)
>      request = qemu_shutdown_requested();
>      if (request >= 0) {
>          qemu_kill_report();
> -        qapi_event_send_shutdown(&error_abort);
> +        qapi_event_send_shutdown(request >= SHUTDOWN_CAUSE_GUEST_SHUTDOWN,
> +                                 &error_abort);
>          if (no_shutdown) {
>              vm_stop(RUN_STATE_SHUTDOWN);
>          } else {
> diff --git a/hw/acpi/core.c b/hw/acpi/core.c
> index e890a5d..95fcac9 100644
> --- a/hw/acpi/core.c
> +++ b/hw/acpi/core.c
> @@ -561,7 +561,7 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
>          uint16_t sus_typ = (val >> 10) & 7;
>          switch(sus_typ) {
>          case 0: /* soft power off */
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>              break;
>          case 1:
>              qemu_system_suspend_request();
> @@ -569,7 +569,7 @@ static void acpi_pm1_cnt_write(ACPIREGS *ar, uint16_t val)
>          default:
>              if (sus_typ == ar->pm1.cnt.s4_val) { /* S4 request */
>                  qapi_event_send_suspend_disk(&error_abort);
> -                qemu_system_shutdown_request();
> +                qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>              }
>              break;
>          }
> diff --git a/hw/arm/highbank.c b/hw/arm/highbank.c
> index 0a4508c..d209b97 100644
> --- a/hw/arm/highbank.c
> +++ b/hw/arm/highbank.c
> @@ -108,9 +108,9 @@ static void hb_regs_write(void *opaque, hwaddr offset,
> 
>      if (offset == 0xf00) {
>          if (value == 1 || value == 2) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          } else if (value == 3) {
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          }
>      }
> 
> diff --git a/hw/arm/integratorcp.c b/hw/arm/integratorcp.c
> index 5610ffc..ca3eca1 100644
> --- a/hw/arm/integratorcp.c
> +++ b/hw/arm/integratorcp.c
> @@ -158,7 +158,7 @@ static void integratorcm_do_remap(IntegratorCMState *s)
>  static void integratorcm_set_ctrl(IntegratorCMState *s, uint32_t value)
>  {
>      if (value & 8) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      }
>      if ((s->cm_ctrl ^ value) & 1) {
>          /* (value & 1) != 0 means the green "MISC LED" is lit.
> diff --git a/hw/arm/musicpal.c b/hw/arm/musicpal.c
> index cbbca4e..9c710f7 100644
> --- a/hw/arm/musicpal.c
> +++ b/hw/arm/musicpal.c
> @@ -898,7 +898,7 @@ static void mv88w8618_pit_write(void *opaque, hwaddr offset,
> 
>      case MP_BOARD_RESET:
>          if (value == MP_BOARD_RESET_MAGIC) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      }
> diff --git a/hw/arm/omap1.c b/hw/arm/omap1.c
> index b3cf0ec..54582bd 100644
> --- a/hw/arm/omap1.c
> +++ b/hw/arm/omap1.c
> @@ -355,7 +355,7 @@ static void omap_wd_timer_write(void *opaque, hwaddr addr,
>                  /* XXX: on T|E hardware somehow this has no effect,
>                   * on Zire 71 it works as specified.  */
>                  s->reset = 1;
> -                qemu_system_reset_request();
> +                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              }
>          }
>          s->last_wr = value & 0xff;
> @@ -1545,8 +1545,10 @@ static inline void omap_clkm_idlect1_update(struct omap_mpu_state_s *s,
>      if (value & (1 << 11)) {                            /* SETARM_IDLE */
>          cpu_interrupt(CPU(s->cpu), CPU_INTERRUPT_HALT);
>      }
> -    if (!(value & (1 << 10)))				/* WKUP_MODE */
> -        qemu_system_shutdown_request();	/* XXX: disable wakeup from IRQ */
> +    if (!(value & (1 << 10))) {                         /* WKUP_MODE */
> +        /* XXX: disable wakeup from IRQ */
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
> +    }
> 
>  #define SET_CANIDLE(clock, bit)				\
>      if (diff & (1 << bit)) {				\
> @@ -1693,7 +1695,7 @@ static void omap_clkm_write(void *opaque, hwaddr addr,
>          diff = s->clkm.arm_rstct1 ^ value;
>          s->clkm.arm_rstct1 = value & 0x0007;
>          if (value & 9) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              s->clkm.cold_start = 0xa;
>          }
>          if (diff & ~value & 4) {				/* DSP_RST */
> diff --git a/hw/arm/omap2.c b/hw/arm/omap2.c
> index cf1b4ba..8afb854 100644
> --- a/hw/arm/omap2.c
> +++ b/hw/arm/omap2.c
> @@ -1610,7 +1610,7 @@ static void omap_prcm_write(void *opaque, hwaddr addr,
>      case 0x450:	/* RM_RSTCTRL_WKUP */
>          /* TODO: reset */
>          if (value & 2)
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          break;
>      case 0x454:	/* RM_RSTTIME_WKUP */
>          s->rsttime_wkup = value & 0x1fff;
> diff --git a/hw/arm/spitz.c b/hw/arm/spitz.c
> index fe2d5a7..7e9f579 100644
> --- a/hw/arm/spitz.c
> +++ b/hw/arm/spitz.c
> @@ -848,7 +848,7 @@ static void spitz_lcd_hsync_handler(void *opaque, int line, int level)
>  static void spitz_reset(void *opaque, int line, int level)
>  {
>      if (level) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      }
>  }
> 
> diff --git a/hw/arm/stellaris.c b/hw/arm/stellaris.c
> index ea7a809..cf6e7be 100644
> --- a/hw/arm/stellaris.c
> +++ b/hw/arm/stellaris.c
> @@ -1197,7 +1197,7 @@ static
>  void do_sys_reset(void *opaque, int n, int level)
>  {
>      if (level) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      }
>  }
> 
> diff --git a/hw/arm/tosa.c b/hw/arm/tosa.c
> index 9f58a23..2421b81 100644
> --- a/hw/arm/tosa.c
> +++ b/hw/arm/tosa.c
> @@ -90,7 +90,7 @@ static void tosa_out_switch(void *opaque, int line, int level)
>  static void tosa_reset(void *opaque, int line, int level)
>  {
>      if (level) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      }
>  }
> 
> diff --git a/hw/i386/pc.c b/hw/i386/pc.c
> index f3b372a..427f123 100644
> --- a/hw/i386/pc.c
> +++ b/hw/i386/pc.c
> @@ -519,7 +519,7 @@ static void port92_write(void *opaque, hwaddr addr, uint64_t val,
>      s->outport = val;
>      qemu_set_irq(s->a20_out, (val >> 1) & 1);
>      if ((val & 1) && !(oldval & 1)) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      }
>  }
> 
> diff --git a/hw/i386/xen/xen-hvm.c b/hw/i386/xen/xen-hvm.c
> index 3a6484c..70a1c1e 100644
> --- a/hw/i386/xen/xen-hvm.c
> +++ b/hw/i386/xen/xen-hvm.c
> @@ -1398,7 +1398,7 @@ void xen_shutdown_fatal_error(const char *fmt, ...)
>      va_end(ap);
>      fprintf(stderr, "Will destroy the domain.\n");
>      /* destroy the domain */
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_ERROR);
>  }
> 
>  void xen_hvm_modified_memory(ram_addr_t start, ram_addr_t length)
> diff --git a/hw/input/pckbd.c b/hw/input/pckbd.c
> index d414288..c479f82 100644
> --- a/hw/input/pckbd.c
> +++ b/hw/input/pckbd.c
> @@ -226,7 +226,7 @@ static void outport_write(KBDState *s, uint32_t val)
>      s->outport = val;
>      qemu_set_irq(s->a20_out, (val >> 1) & 1);
>      if (!(val & 1)) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      }
>  }
> 
> @@ -301,7 +301,7 @@ static void kbd_write_command(void *opaque, hwaddr addr,
>          s->outport &= ~KBD_OUT_A20;
>          break;
>      case KBD_CCMD_RESET:
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          break;
>      case KBD_CCMD_NO_OP:
>          /* ignore that */
> diff --git a/hw/ipmi/ipmi.c b/hw/ipmi/ipmi.c
> index 5cf1caa..afafe14 100644
> --- a/hw/ipmi/ipmi.c
> +++ b/hw/ipmi/ipmi.c
> @@ -44,14 +44,14 @@ static int ipmi_do_hw_op(IPMIInterface *s, enum ipmi_op op, int checkonly)
>          if (checkonly) {
>              return 0;
>          }
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          return 0;
> 
>      case IPMI_POWEROFF_CHASSIS:
>          if (checkonly) {
>              return 0;
>          }
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          return 0;
> 
>      case IPMI_SEND_NMI:
> diff --git a/hw/isa/lpc_ich9.c b/hw/isa/lpc_ich9.c
> index a0866c3..2b09354 100644
> --- a/hw/isa/lpc_ich9.c
> +++ b/hw/isa/lpc_ich9.c
> @@ -606,7 +606,7 @@ static void ich9_rst_cnt_write(void *opaque, hwaddr addr, uint64_t val,
>      ICH9LPCState *lpc = opaque;
> 
>      if (val & 4) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          return;
>      }
>      lpc->rst_cnt = val & 0xA; /* keep FULL_RST (bit 3) and SYS_RST (bit 1) */
> diff --git a/hw/mips/boston.c b/hw/mips/boston.c
> index 83f7b82..53d1e0c 100644
> --- a/hw/mips/boston.c
> +++ b/hw/mips/boston.c
> @@ -232,7 +232,7 @@ static void boston_platreg_write(void *opaque, hwaddr addr,
>          break;
>      case PLAT_SOFTRST_CTL:
>          if (val & PLAT_SOFTRST_CTL_SYSRESET) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      default:
> diff --git a/hw/mips/mips_malta.c b/hw/mips/mips_malta.c
> index 5dd177e..7814c39 100644
> --- a/hw/mips/mips_malta.c
> +++ b/hw/mips/mips_malta.c
> @@ -470,7 +470,7 @@ static void malta_fpga_write(void *opaque, hwaddr addr,
>      /* SOFTRES Register */
>      case 0x00500:
>          if (val == 0x42)
> -            qemu_system_reset_request ();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          break;
> 
>      /* BRKRES Register */
> diff --git a/hw/mips/mips_r4k.c b/hw/mips/mips_r4k.c
> index 748586e..f4de9fc 100644
> --- a/hw/mips/mips_r4k.c
> +++ b/hw/mips/mips_r4k.c
> @@ -53,9 +53,9 @@ static void mips_qemu_write (void *opaque, hwaddr addr,
>                               uint64_t val, unsigned size)
>  {
>      if ((addr & 0xffff) == 0 && val == 42)
> -        qemu_system_reset_request ();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      else if ((addr & 0xffff) == 4 && val == 42)
> -        qemu_system_shutdown_request ();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>  }
> 
>  static uint64_t mips_qemu_read (void *opaque, hwaddr addr,
> diff --git a/hw/misc/arm_sysctl.c b/hw/misc/arm_sysctl.c
> index 8524008..b20b44e 100644
> --- a/hw/misc/arm_sysctl.c
> +++ b/hw/misc/arm_sysctl.c
> @@ -351,13 +351,13 @@ static bool vexpress_cfgctrl_write(arm_sysctl_state *s, unsigned int dcc,
>          break;
>      case SYS_CFG_SHUTDOWN:
>          if (site == SYS_CFG_SITE_MB && device == 0) {
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>              return true;
>          }
>          break;
>      case SYS_CFG_REBOOT:
>          if (site == SYS_CFG_SITE_MB && device == 0) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              return true;
>          }
>          break;
> @@ -429,7 +429,7 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
>              if (s->lockval == LOCK_VALUE) {
>                  s->resetlevel = val;
>                  if (val & 0x100) {
> -                    qemu_system_reset_request();
> +                    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>                  }
>              }
>              break;
> @@ -438,7 +438,7 @@ static void arm_sysctl_write(void *opaque, hwaddr offset,
>              if (s->lockval == LOCK_VALUE) {
>                  s->resetlevel = val;
>                  if (val & 0x04) {
> -                    qemu_system_reset_request();
> +                    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>                  }
>              }
>              break;
> diff --git a/hw/misc/cbus.c b/hw/misc/cbus.c
> index 0c207e3..677274c 100644
> --- a/hw/misc/cbus.c
> +++ b/hw/misc/cbus.c
> @@ -356,7 +356,7 @@ static inline void retu_write(CBusRetu *s, int reg, uint16_t val)
> 
>      case RETU_REG_WATCHDOG:
>          if (val == 0 && (s->cc[0] & 2))
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          break;
> 
>      case RETU_REG_TXCR:
> diff --git a/hw/misc/macio/cuda.c b/hw/misc/macio/cuda.c
> index 05c02fb..008d8bd 100644
> --- a/hw/misc/macio/cuda.c
> +++ b/hw/misc/macio/cuda.c
> @@ -612,7 +612,7 @@ static bool cuda_cmd_powerdown(CUDAState *s,
>          return false;
>      }
> 
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>      return true;
>  }
> 
> @@ -624,7 +624,7 @@ static bool cuda_cmd_reset_system(CUDAState *s,
>          return false;
>      }
> 
> -    qemu_system_reset_request();
> +    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      return true;
>  }
> 
> diff --git a/hw/misc/slavio_misc.c b/hw/misc/slavio_misc.c
> index edd5de0..18ff677 100644
> --- a/hw/misc/slavio_misc.c
> +++ b/hw/misc/slavio_misc.c
> @@ -258,7 +258,7 @@ static void slavio_aux2_mem_writeb(void *opaque, hwaddr addr,
>          val &= AUX2_PWROFF;
>      s->aux2 = val;
>      if (val & AUX2_PWROFF)
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>      slavio_misc_update_irq(s);
>  }
> 
> @@ -338,7 +338,7 @@ static void slavio_sysctrl_mem_writel(void *opaque, hwaddr addr,
>      case 0:
>          if (val & SYS_RESET) {
>              s->sysctrl = SYS_RESETSTAT;
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      default:
> diff --git a/hw/misc/zynq_slcr.c b/hw/misc/zynq_slcr.c
> index 7891219..44304d4 100644
> --- a/hw/misc/zynq_slcr.c
> +++ b/hw/misc/zynq_slcr.c
> @@ -405,7 +405,7 @@ static void zynq_slcr_write(void *opaque, hwaddr offset,
>      switch (offset) {
>      case PSS_RST_CTRL:
>          if (val & R_PSS_RST_CTRL_SOFT_RST) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      }
> diff --git a/hw/pci-host/apb.c b/hw/pci-host/apb.c
> index 653e711..83fc6a9 100644
> --- a/hw/pci-host/apb.c
> +++ b/hw/pci-host/apb.c
> @@ -482,9 +482,9 @@ static void apb_config_writel (void *opaque, hwaddr addr,
>              s->reset_control |= val & RESET_WMASK;
>              if (val & SOFT_POR) {
>                  s->nr_resets = 0;
> -                qemu_system_reset_request();
> +                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              } else if (val & SOFT_XIR) {
> -                qemu_system_reset_request();
> +                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              }
>          }
>          break;
> diff --git a/hw/pci-host/bonito.c b/hw/pci-host/bonito.c
> index 1999ece..b1d41d0 100644
> --- a/hw/pci-host/bonito.c
> +++ b/hw/pci-host/bonito.c
> @@ -269,7 +269,7 @@ static void bonito_writel(void *opaque, hwaddr addr,
>          }
>          s->regs[saddr] = val;
>          if (reset) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      case BONITO_INTENSET:
> diff --git a/hw/pci-host/piix.c b/hw/pci-host/piix.c
> index f9218aa..c1d6a85 100644
> --- a/hw/pci-host/piix.c
> +++ b/hw/pci-host/piix.c
> @@ -638,7 +638,7 @@ static void rcr_write(void *opaque, hwaddr addr, uint64_t val, unsigned len)
>      PIIX3State *d = opaque;
> 
>      if (val & 4) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          return;
>      }
>      d->rcr = val & 2; /* keep System Reset type only */
> diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
> index f7df238..62f1857 100644
> --- a/hw/ppc/e500.c
> +++ b/hw/ppc/e500.c
> @@ -774,7 +774,7 @@ static qemu_irq *ppce500_init_mpic(MachineState *machine, PPCE500Params *params,
>  static void ppce500_power_off(void *opaque, int line, int on)
>  {
>      if (on) {
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>      }
>  }
> 
> diff --git a/hw/ppc/mpc8544_guts.c b/hw/ppc/mpc8544_guts.c
> index ba69178..ce1254b 100644
> --- a/hw/ppc/mpc8544_guts.c
> +++ b/hw/ppc/mpc8544_guts.c
> @@ -98,7 +98,7 @@ static void mpc8544_guts_write(void *opaque, hwaddr addr,
>      switch (addr) {
>      case MPC8544_GUTS_ADDR_RSTCR:
>          if (value & MPC8544_GUTS_RSTCR_RESET) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      default:
> diff --git a/hw/ppc/ppc.c b/hw/ppc/ppc.c
> index 5f93083..224184d 100644
> --- a/hw/ppc/ppc.c
> +++ b/hw/ppc/ppc.c
> @@ -412,7 +412,7 @@ static void ppce500_set_irq(void *opaque, int pin, int level)
>              if (level) {
>                  LOG_IRQ("%s: reset the PowerPC system\n",
>                              __func__);
> -                qemu_system_reset_request();
> +                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              }
>              break;
>          case PPCE500_INPUT_RESET_CORE:
> diff --git a/hw/ppc/ppc405_uc.c b/hw/ppc/ppc405_uc.c
> index d5df94a..fc32e96 100644
> --- a/hw/ppc/ppc405_uc.c
> +++ b/hw/ppc/ppc405_uc.c
> @@ -1807,7 +1807,7 @@ void ppc40x_chip_reset(PowerPCCPU *cpu)
>  void ppc40x_system_reset(PowerPCCPU *cpu)
>  {
>      printf("Reset PowerPC system\n");
> -    qemu_system_reset_request();
> +    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>  }
> 
>  void store_40x_dbcr0 (CPUPPCState *env, uint32_t val)
> diff --git a/hw/ppc/spapr_hcall.c b/hw/ppc/spapr_hcall.c
> index 9f18f75..2735fe9 100644
> --- a/hw/ppc/spapr_hcall.c
> +++ b/hw/ppc/spapr_hcall.c
> @@ -1166,7 +1166,7 @@ static target_ulong h_client_architecture_support(PowerPCCPU *cpu,
>      spapr_ovec_cleanup(ov5_updates);
> 
>      if (spapr->cas_reboot) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      } else {
>          /* If ppc_spapr_reset() did not set up a HPT but one is necessary
>           * (because the guest isn't going to use radix) then set it up here. */
> diff --git a/hw/ppc/spapr_rtas.c b/hw/ppc/spapr_rtas.c
> index 619f32c..128d993 100644
> --- a/hw/ppc/spapr_rtas.c
> +++ b/hw/ppc/spapr_rtas.c
> @@ -110,7 +110,7 @@ static void rtas_power_off(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>      cpu_stop_current();
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> @@ -124,7 +124,7 @@ static void rtas_system_reboot(PowerPCCPU *cpu, sPAPRMachineState *spapr,
>          rtas_st(rets, 0, RTAS_OUT_PARAM_ERROR);
>          return;
>      }
> -    qemu_system_reset_request();
> +    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      rtas_st(rets, 0, RTAS_OUT_SUCCESS);
>  }
> 
> diff --git a/hw/s390x/ipl.c b/hw/s390x/ipl.c
> index 7978c7d..e5ab0ad 100644
> --- a/hw/s390x/ipl.c
> +++ b/hw/s390x/ipl.c
> @@ -363,7 +363,7 @@ void s390_reipl_request(void)
>      S390IPLState *ipl = get_ipl_device();
> 
>      ipl->reipl_requested = true;
> -    qemu_system_reset_request();
> +    qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>  }
> 
>  void s390_ipl_prepare_cpu(S390CPU *cpu)
> diff --git a/hw/sh4/r2d.c b/hw/sh4/r2d.c
> index 8f520ce..e6fc74e 100644
> --- a/hw/sh4/r2d.c
> +++ b/hw/sh4/r2d.c
> @@ -164,7 +164,7 @@ r2d_fpga_write(void *opaque, hwaddr addr, uint64_t value, unsigned int size)
>  	break;
>      case PA_POWOFF:
>          if (value & 1) {
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          }
>          break;
>      case PA_VERREG:
> diff --git a/hw/timer/etraxfs_timer.c b/hw/timer/etraxfs_timer.c
> index 8e18236..d13bc30 100644
> --- a/hw/timer/etraxfs_timer.c
> +++ b/hw/timer/etraxfs_timer.c
> @@ -207,7 +207,7 @@ static void watchdog_hit(void *opaque)
>          qemu_irq_raise(t->nmi);
>      }
>      else
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
> 
>      t->wd_hits++;
>  }
> diff --git a/hw/timer/m48t59.c b/hw/timer/m48t59.c
> index 474981a..4a064fb 100644
> --- a/hw/timer/m48t59.c
> +++ b/hw/timer/m48t59.c
> @@ -1,7 +1,7 @@
>  /*
>   * QEMU M48T59 and M48T08 NVRAM emulation for PPC PREP and Sparc platforms
>   *
> - * Copyright (c) 2003-2005, 2007 Jocelyn Mayer
> + * Copyright (c) 2003-2005, 2007, 2017 Jocelyn Mayer
>   * Copyright (c) 2013 Hervé Poussineau
>   *
>   * Permission is hereby granted, free of charge, to any person obtaining a copy
> @@ -159,7 +159,7 @@ static void watchdog_cb (void *opaque)
>  	NVRAM->buffer[0x1FF7] = 0x00;
>  	NVRAM->buffer[0x1FFC] &= ~0x40;
>          /* May it be a hw CPU Reset instead ? */
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      } else {
>  	qemu_set_irq(NVRAM->IRQ, 1);
>  	qemu_set_irq(NVRAM->IRQ, 0);
> diff --git a/hw/timer/milkymist-sysctl.c b/hw/timer/milkymist-sysctl.c
> index 4488590..93bc6e17 100644
> --- a/hw/timer/milkymist-sysctl.c
> +++ b/hw/timer/milkymist-sysctl.c
> @@ -90,7 +90,7 @@ static void sysctl_icap_write(MilkymistSysctlState *s, uint32_t value)
>      trace_milkymist_sysctl_icap_write(value);
>      switch (value & 0xffff) {
>      case 0x000e:
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          break;
>      }
>  }
> @@ -195,7 +195,7 @@ static void sysctl_write(void *opaque, hwaddr addr, uint64_t value,
>          s->regs[addr] = 1;
>          break;
>      case R_SYSTEM_ID:
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          break;
> 
>      case R_GPIO_IN:
> diff --git a/hw/timer/pxa2xx_timer.c b/hw/timer/pxa2xx_timer.c
> index 59002b4..68ba5a7 100644
> --- a/hw/timer/pxa2xx_timer.c
> +++ b/hw/timer/pxa2xx_timer.c
> @@ -401,7 +401,7 @@ static void pxa2xx_timer_tick(void *opaque)
>      if (t->num == 3)
>          if (i->reset3 & 1) {
>              i->reset3 = 0;
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>  }
> 
> diff --git a/hw/watchdog/watchdog.c b/hw/watchdog/watchdog.c
> index 2aeaf1f..0c5c9cd 100644
> --- a/hw/watchdog/watchdog.c
> +++ b/hw/watchdog/watchdog.c
> @@ -110,7 +110,7 @@ void watchdog_perform_action(void)
>      switch (watchdog_action) {
>      case WDT_RESET:             /* same as 'system_reset' in monitor */
>          qapi_event_send_watchdog(WATCHDOG_EXPIRATION_ACTION_RESET, &error_abort);
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          break;
> 
>      case WDT_SHUTDOWN:          /* same as 'system_powerdown' in monitor */
> diff --git a/hw/xenpv/xen_domainbuild.c b/hw/xenpv/xen_domainbuild.c
> index 457a897..c89ced2 100644
> --- a/hw/xenpv/xen_domainbuild.c
> +++ b/hw/xenpv/xen_domainbuild.c
> @@ -148,7 +148,7 @@ static void xen_domain_poll(void *opaque)
>      return;
> 
>  quit:
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>  }
> 
>  static int xen_domain_watcher(void)
> diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
> index 11176e2..4636f8e 100644
> --- a/hw/xtensa/xtfpga.c
> +++ b/hw/xtensa/xtfpga.c
> @@ -100,7 +100,7 @@ static void lx60_fpga_write(void *opaque, hwaddr addr,
> 
>      case 0x10: /*board reset*/
>          if (val == 0xdead) {
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          }
>          break;
>      }
> diff --git a/kvm-all.c b/kvm-all.c
> index 90b8573..7df27c8 100644
> --- a/kvm-all.c
> +++ b/kvm-all.c
> @@ -2052,7 +2052,7 @@ int kvm_cpu_exec(CPUState *cpu)
>              break;
>          case KVM_EXIT_SHUTDOWN:
>              DPRINTF("shutdown\n");
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              ret = EXCP_INTERRUPT;
>              break;
>          case KVM_EXIT_UNKNOWN:
> @@ -2066,11 +2066,11 @@ int kvm_cpu_exec(CPUState *cpu)
>          case KVM_EXIT_SYSTEM_EVENT:
>              switch (run->system_event.type) {
>              case KVM_SYSTEM_EVENT_SHUTDOWN:
> -                qemu_system_shutdown_request();
> +                qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>                  ret = EXCP_INTERRUPT;
>                  break;
>              case KVM_SYSTEM_EVENT_RESET:
> -                qemu_system_reset_request();
> +                qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>                  ret = EXCP_INTERRUPT;
>                  break;
>              case KVM_SYSTEM_EVENT_CRASH:
> diff --git a/os-win32.c b/os-win32.c
> index ae98574..586a7c7 100644
> --- a/os-win32.c
> +++ b/os-win32.c
> @@ -52,7 +52,7 @@ int setenv(const char *name, const char *value, int overwrite)
> 
>  static BOOL WINAPI qemu_ctrl_handler(DWORD type)
>  {
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_SIGNAL);
>      /* Windows 7 kills application when the function returns.
>         Sleep here to give QEMU a try for closing.
>         Sleep period is 10000ms because Windows kills the program
> diff --git a/qmp.c b/qmp.c
> index ab74cd7..95949d0 100644
> --- a/qmp.c
> +++ b/qmp.c
> @@ -84,7 +84,7 @@ UuidInfo *qmp_query_uuid(Error **errp)
>  void qmp_quit(Error **errp)
>  {
>      no_shutdown = 0;
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP);
>  }
> 
>  void qmp_stop(Error **errp)
> @@ -105,7 +105,7 @@ void qmp_stop(Error **errp)
> 
>  void qmp_system_reset(Error **errp)
>  {
> -    qemu_system_reset_request();
> +    qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP);
>  }
> 
>  void qmp_system_powerdown(Error **erp)
> diff --git a/replay/replay.c b/replay/replay.c
> index f810628..55e82d9 100644
> --- a/replay/replay.c
> +++ b/replay/replay.c
> @@ -51,7 +51,10 @@ bool replay_next_event_is(int event)
>          switch (replay_state.data_kind) {
>          case EVENT_SHUTDOWN:
>              replay_finish_event();
> -            qemu_system_shutdown_request();
> +            /* TODO: track source of shutdown request, to replay a
> +             * guest-initiated request rather than always claiming to
> +             * be from the host? */
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_REPLAY);
>              break;
>          default:
>              /* clock, time_t, checkpoint and other events */
> diff --git a/target/alpha/sys_helper.c b/target/alpha/sys_helper.c
> index 652195d..ac22323 100644
> --- a/target/alpha/sys_helper.c
> +++ b/target/alpha/sys_helper.c
> @@ -60,9 +60,9 @@ void helper_tb_flush(CPUAlphaState *env)
>  void helper_halt(uint64_t restart)
>  {
>      if (restart) {
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>      } else {
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>      }
>  }
> 
> diff --git a/target/arm/psci.c b/target/arm/psci.c
> index ade9fe2..fc34b26 100644
> --- a/target/arm/psci.c
> +++ b/target/arm/psci.c
> @@ -137,7 +137,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
>          }
>          break;
>      case QEMU_PSCI_0_2_FN_SYSTEM_RESET:
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          /* QEMU reset and shutdown are async requests, but PSCI
>           * mandates that we never return from the reset/shutdown
>           * call, so power the CPU off now so it doesn't execute
> @@ -145,7 +145,7 @@ void arm_handle_psci_call(ARMCPU *cpu)
>           */
>          goto cpu_off;
>      case QEMU_PSCI_0_2_FN_SYSTEM_OFF:
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          goto cpu_off;
>      case QEMU_PSCI_0_1_FN_CPU_ON:
>      case QEMU_PSCI_0_2_FN_CPU_ON:
> diff --git a/target/i386/excp_helper.c b/target/i386/excp_helper.c
> index ee596c6..b769772 100644
> --- a/target/i386/excp_helper.c
> +++ b/target/i386/excp_helper.c
> @@ -59,7 +59,7 @@ static int check_exception(CPUX86State *env, int intno, int *error_code,
> 
>          qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
> 
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          return EXCP_HLT;
>      }
>  #endif
> diff --git a/target/i386/hax-all.c b/target/i386/hax-all.c
> index ef13015..7346931 100644
> --- a/target/i386/hax-all.c
> +++ b/target/i386/hax-all.c
> @@ -540,14 +540,14 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
>          /* Guest state changed, currently only for shutdown */
>          case HAX_EXIT_STATECHANGE:
>              fprintf(stdout, "VCPU shutdown request\n");
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>              hax_vcpu_sync_state(env, 0);
>              ret = 1;
>              break;
>          case HAX_EXIT_UNKNOWN_VMEXIT:
>              fprintf(stderr, "Unknown VMX exit %x from guest\n",
>                      ht->_exit_reason);
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              hax_vcpu_sync_state(env, 0);
>              cpu_dump_state(cpu, stderr, fprintf, 0);
>              ret = -1;
> @@ -578,7 +578,7 @@ static int hax_vcpu_hax_exec(CPUArchState *env)
>              break;
>          default:
>              fprintf(stderr, "Unknown exit %x from HAX\n", ht->_exit_status);
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              hax_vcpu_sync_state(env, 0);
>              cpu_dump_state(cpu, stderr, fprintf, 0);
>              ret = 1;
> diff --git a/target/i386/helper.c b/target/i386/helper.c
> index f11cac6..ee7eff2 100644
> --- a/target/i386/helper.c
> +++ b/target/i386/helper.c
> @@ -1212,7 +1212,7 @@ static void do_inject_x86_mce(CPUState *cs, run_on_cpu_data data)
>                             " triple fault\n",
>                             cs->cpu_index);
>              qemu_log_mask(CPU_LOG_RESET, "Triple fault\n");
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              return;
>          }
>          if (banks[1] & MCI_STATUS_VAL) {
> diff --git a/target/i386/kvm.c b/target/i386/kvm.c
> index 55865db..cfd7695 100644
> --- a/target/i386/kvm.c
> +++ b/target/i386/kvm.c
> @@ -2930,7 +2930,7 @@ int kvm_arch_process_async_events(CPUState *cs)
> 
>          if (env->exception_injected == EXCP08_DBLE) {
>              /* this means triple fault */
> -            qemu_system_reset_request();
> +            qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>              cs->exit_request = 1;
>              return 0;
>          }
> diff --git a/target/s390x/helper.c b/target/s390x/helper.c
> index 68bd2f9..d2bb9aa 100644
> --- a/target/s390x/helper.c
> +++ b/target/s390x/helper.c
> @@ -266,7 +266,7 @@ void load_psw(CPUS390XState *env, uint64_t mask, uint64_t addr)
>          S390CPU *cpu = s390_env_get_cpu(env);
>          if (s390_cpu_halt(cpu) == 0) {
>  #ifndef CONFIG_USER_ONLY
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>  #endif
>          }
>      }
> diff --git a/target/s390x/kvm.c b/target/s390x/kvm.c
> index 1a249d8..284f5ef 100644
> --- a/target/s390x/kvm.c
> +++ b/target/s390x/kvm.c
> @@ -1929,7 +1929,7 @@ static int handle_intercept(S390CPU *cpu)
>              cpu_synchronize_state(cs);
>              if (s390_cpu_halt(cpu) == 0) {
>                  if (is_special_wait_psw(cs)) {
> -                    qemu_system_shutdown_request();
> +                    qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>                  } else {
>                      qemu_system_guest_panicked(NULL);
>                  }
> @@ -1938,7 +1938,7 @@ static int handle_intercept(S390CPU *cpu)
>              break;
>          case ICPT_CPU_STOP:
>              if (s390_cpu_set_state(CPU_STATE_STOPPED, cpu) == 0) {
> -                qemu_system_shutdown_request();
> +                qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>              }
>              if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
>                  kvm_s390_store_status(cpu, KVM_S390_STORE_STATUS_DEF_ADDR,
> diff --git a/target/s390x/misc_helper.c b/target/s390x/misc_helper.c
> index eca8244..768043e 100644
> --- a/target/s390x/misc_helper.c
> +++ b/target/s390x/misc_helper.c
> @@ -533,11 +533,11 @@ uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
>          break;
>  #if !defined(CONFIG_USER_ONLY)
>      case SIGP_RESTART:
> -        qemu_system_reset_request();
> +        qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
>          cpu_loop_exit(CPU(s390_env_get_cpu(env)));
>          break;
>      case SIGP_STOP:
> -        qemu_system_shutdown_request();
> +        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          cpu_loop_exit(CPU(s390_env_get_cpu(env)));
>          break;
>  #endif
> diff --git a/target/sparc/int32_helper.c b/target/sparc/int32_helper.c
> index 09afe13..eec9a4d 100644
> --- a/target/sparc/int32_helper.c
> +++ b/target/sparc/int32_helper.c
> @@ -109,7 +109,7 @@ void sparc_cpu_do_interrupt(CPUState *cs)
>      if (env->psret == 0) {
>          if (cs->exception_index == 0x80 &&
>              env->def->features & CPU_FEATURE_TA0_SHUTDOWN) {
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
>          } else {
>              cpu_abort(cs, "Trap 0x%02x while interrupts disabled, Error state",
>                        cs->exception_index);
> diff --git a/ui/sdl.c b/ui/sdl.c
> index 37c21a0..bd51ffd 100644
> --- a/ui/sdl.c
> +++ b/ui/sdl.c
> @@ -837,7 +837,7 @@ static void sdl_refresh(DisplayChangeListener *dcl)
>          case SDL_QUIT:
>              if (!no_quit) {
>                  no_shutdown = 0;
> -                qemu_system_shutdown_request();
> +                qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
>              }
>              break;
>          case SDL_MOUSEMOTION:
> diff --git a/ui/sdl2.c b/ui/sdl2.c
> index faf9bdf..e092636 100644
> --- a/ui/sdl2.c
> +++ b/ui/sdl2.c
> @@ -568,7 +568,7 @@ static void handle_windowevent(SDL_Event *ev)
>      case SDL_WINDOWEVENT_CLOSE:
>          if (!no_quit) {
>              no_shutdown = 0;
> -            qemu_system_shutdown_request();
> +            qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
>          }
>          break;
>      case SDL_WINDOWEVENT_SHOWN:
> @@ -611,7 +611,7 @@ void sdl2_poll_events(struct sdl2_console *scon)
>          case SDL_QUIT:
>              if (!no_quit) {
>                  no_shutdown = 0;
> -                qemu_system_shutdown_request();
> +                qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
>              }
>              break;
>          case SDL_MOUSEMOTION:
> diff --git a/tests/qemu-iotests/071.out b/tests/qemu-iotests/071.out
> index dd879f1..1d5e28d 100644
> --- a/tests/qemu-iotests/071.out
> +++ b/tests/qemu-iotests/071.out
> @@ -46,7 +46,7 @@ QMP_VERSION
>  read failed: Input/output error
>  {"return": ""}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
> 
>  === Testing blkverify on existing block device ===
> @@ -85,7 +85,7 @@ wrote 512/512 bytes at offset 0
>  read failed: Input/output error
>  {"return": ""}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
>  QEMU_PROG: Failed to flush the L2 table cache: Input/output error
>  QEMU_PROG: Failed to flush the refcount block cache: Input/output error
> 
> diff --git a/tests/qemu-iotests/081.out b/tests/qemu-iotests/081.out
> index 97df69d..2533c31 100644
> --- a/tests/qemu-iotests/081.out
> +++ b/tests/qemu-iotests/081.out
> @@ -36,7 +36,7 @@ read 10485760/10485760 bytes at offset 0
>  10 MiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  {"return": ""}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
> 
>  == using quorum rewrite corrupted mode ==
> diff --git a/tests/qemu-iotests/087.out b/tests/qemu-iotests/087.out
> index dc6baf9..59c5208 100644
> --- a/tests/qemu-iotests/087.out
> +++ b/tests/qemu-iotests/087.out
> @@ -8,7 +8,7 @@ QMP_VERSION
>  {"return": {}}
>  {"error": {"class": "GenericError", "desc": "'node-name' must be specified for the root node"}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
> 
>  === Duplicate ID ===
> @@ -19,7 +19,7 @@ QMP_VERSION
>  {"error": {"class": "GenericError", "desc": "node-name=disk is conflicting with a device id"}}
>  {"error": {"class": "GenericError", "desc": "Duplicate node name"}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
> 
>  === aio=native without O_DIRECT ===
> @@ -29,7 +29,7 @@ QMP_VERSION
>  {"return": {}}
>  {"error": {"class": "GenericError", "desc": "aio=native was specified, but it requires cache.direct=on, which was not specified."}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
> 
>  === Encrypted image ===
> @@ -40,14 +40,14 @@ QMP_VERSION
>  {"return": {}}
>  {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
>  Testing:
>  QMP_VERSION
>  {"return": {}}
>  {"error": {"class": "GenericError", "desc": "Use of AES-CBC encrypted IMGFMT images is no longer supported in system emulators"}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
> 
>  === Missing driver ===
> @@ -58,6 +58,6 @@ QMP_VERSION
>  {"return": {}}
>  {"error": {"class": "GenericError", "desc": "Parameter 'driver' is missing"}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
>  *** done
> diff --git a/tests/qemu-iotests/094.out b/tests/qemu-iotests/094.out
> index b66dc07..f52baff 100644
> --- a/tests/qemu-iotests/094.out
> +++ b/tests/qemu-iotests/094.out
> @@ -7,5 +7,5 @@ Formatting 'TEST_DIR/source.IMGFMT', fmt=IMGFMT size=67108864
>  {"return": {}}
>  {"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "BLOCK_JOB_COMPLETED", "data": {"device": "src", "len": 67108864, "offset": 67108864, "speed": 0, "type": "mirror"}}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
>  *** done
> diff --git a/tests/qemu-iotests/117.out b/tests/qemu-iotests/117.out
> index f52dc1a..851e214 100644
> --- a/tests/qemu-iotests/117.out
> +++ b/tests/qemu-iotests/117.out
> @@ -7,7 +7,7 @@ wrote 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  {"return": ""}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
>  No errors were found on the image.
>  read 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> diff --git a/tests/qemu-iotests/119.out b/tests/qemu-iotests/119.out
> index 58e7114..a8743b8 100644
> --- a/tests/qemu-iotests/119.out
> +++ b/tests/qemu-iotests/119.out
> @@ -6,6 +6,6 @@ read 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  {"return": ""}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
>  *** done
> diff --git a/tests/qemu-iotests/120.out b/tests/qemu-iotests/120.out
> index 9131b1b..1af1aeb 100644
> --- a/tests/qemu-iotests/120.out
> +++ b/tests/qemu-iotests/120.out
> @@ -6,7 +6,7 @@ wrote 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  {"return": ""}
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
>  read 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
>  read 65536/65536 bytes at offset 0
> diff --git a/tests/qemu-iotests/140.out b/tests/qemu-iotests/140.out
> index 6c04456..0689b2b 100644
> --- a/tests/qemu-iotests/140.out
> +++ b/tests/qemu-iotests/140.out
> @@ -10,5 +10,5 @@ read 65536/65536 bytes at offset 0
>  {"return": {}}
>  can't open device nbd+unix:///drv?socket=TEST_DIR/nbd: No export with name 'drv' available
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
>  *** done
> diff --git a/tests/qemu-iotests/143.out b/tests/qemu-iotests/143.out
> index d24ad20..0978b89 100644
> --- a/tests/qemu-iotests/143.out
> +++ b/tests/qemu-iotests/143.out
> @@ -3,5 +3,5 @@ QA output created by 143
>  {"return": {}}
>  can't open device nbd+unix:///no_such_export?socket=TEST_DIR/nbd: No export with name 'no_such_export' available
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
>  *** done
> diff --git a/tests/qemu-iotests/156.out b/tests/qemu-iotests/156.out
> index 3af82ae..f96a564 100644
> --- a/tests/qemu-iotests/156.out
> +++ b/tests/qemu-iotests/156.out
> @@ -34,7 +34,7 @@ read 65536/65536 bytes at offset 196608
>  {"return": ""}
> 
>  {"return": {}}
> -{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN"}
> +{"timestamp": {"seconds":  TIMESTAMP, "microseconds":  TIMESTAMP}, "event": "SHUTDOWN", "data": {"guest": false}}
> 
>  read 65536/65536 bytes at offset 0
>  64 KiB, X ops; XX:XX:XX.X (XXX YYY/sec and XXX ops/sec)
> diff --git a/trace-events b/trace-events
> index e582d63..433865f 100644
> --- a/trace-events
> +++ b/trace-events
> @@ -38,7 +38,7 @@ vm_state_notify(int running, int reason) "running %d reason %d"
>  load_file(const char *name, const char *path) "name %s location %s"
>  runstate_set(int new_state) "new state %d"
>  system_wakeup_request(int reason) "reason=%d"
> -qemu_system_shutdown_request(void) ""
> +qemu_system_shutdown_request(int reason) "reason=%d"
>  qemu_system_powerdown_request(void) ""
> 
>  # spice-qemu-char.c
> diff --git a/ui/cocoa.m b/ui/cocoa.m
> index 207555e..f89f686 100644
> --- a/ui/cocoa.m
> +++ b/ui/cocoa.m
> @@ -934,7 +934,7 @@ QemuCocoaView *cocoaView;
>  {
>      COCOA_DEBUG("QemuCocoaAppController: applicationWillTerminate\n");
> 
> -    qemu_system_shutdown_request();
> +    qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_UI);
>      exit(0);
>  }
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 127 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v5 3/4] shutdown: Add source information to SHUTDOWN and RESET
       [not found]   ` <87h918bmpz.fsf@dusky.pond.sub.org>
@ 2017-05-02  8:13     ` Pavel Dovgalyuk
  0 siblings, 0 replies; 16+ messages in thread
From: Pavel Dovgalyuk @ 2017-05-02  8:13 UTC (permalink / raw)
  To: 'Markus Armbruster', 'Eric Blake'
  Cc: 'Peter Maydell', 'open list:Overall',
	'Michael S. Tsirkin', 'Mark Cave-Ayland',
	qemu-devel, 'Cor nelia Hu ck', 'Gerd Hoffmann',
	'Edgar E. Iglesias', 'Rob Herring',
	'Stefano Stabellini',
	'open list:Block layer core', 'Magnus Damm',
	'Alexander Graf', 'Christian Borntraeger',
	'Anthony Perard', 'open list:X86',
	'David Gibson', 'Artyom Tarasenko',
	'Eduardo Habkost', 'Stefan Weil',
	alistair.francis

> From: Markus Armbruster [mailto:armbru@redhat.com]
> 
> Scandalously, replay/ is not covered by MAINTAINERS.

Here it is.
http://lists.nongnu.org/archive/html/qemu-devel/2017-05/msg00080.html

I'll try to figure out the SHUTDOWN problem.

Pavel Dovgalyuk


_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

* Re: [Qemu-devel] [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request
  2017-04-28 22:34     ` Eric Blake
@ 2017-05-02 11:47       ` Markus Armbruster
  0 siblings, 0 replies; 16+ messages in thread
From: Markus Armbruster @ 2017-05-02 11:47 UTC (permalink / raw)
  To: Eric Blake
  Cc: Stefano Stabellini, Eduardo Habkost, Michael S. Tsirkin,
	Juan Quintela, qemu-devel, alistair.francis, zhanghailiang,
	open list:X86, Anthony Perard, Paolo Bonzini,
	Dr. David Alan Gilbert, Richard Henderson

Eric Blake <eblake@redhat.com> writes:

> On 04/28/2017 09:42 AM, Markus Armbruster wrote:
>> Eric Blake <eblake@redhat.com> writes:
>> 
>>> We want to track why a guest was shutdown; in particular, being able
>>> to tell the difference between a guest request (such as ACPI request)
>>> and host request (such as SIGINT) will prove useful to libvirt.
>>> Since all requests eventually end up changing shutdown_requested in
>>> vl.c, the logical change is to make that value track the reason,
>>> rather than its current 0/1 contents.
>>>
>>> Since command-line options control whether a reset request is turned
>>> into a shutdown request instead, the same treatment is given to
>>> reset_requested.
>>>
>>> This patch adds a QAPI enum ShutdownCause that describes reasons
>>> that a shutdown can be requested, and changes qemu_system_reset() to
>>> pass the reason through, although for now it is not reported.  The
>>> next patch will actually wire things up to modify events to report
>>> data based on the reason, and to pass the correct enum value in from
>>> various call-sites that can trigger a reset/shutdown.  Since QAPI
>>> generates enums starting at 0, it's easier if we use a different
>>> number as our sentinel that no request has happened yet.  Most of
>>> the changes are in vl.c, but xen was using things externally.
>>>
>
>>> -static int reset_requested;
>>> -static int shutdown_requested, shutdown_signal;
>>> +static int reset_requested = -1;
>>> +static int shutdown_requested = -1, shutdown_signal;
>> 
>> Peeking ahead, I see that shutdown_requested and reset_requested take
>> ShutdownCause values and -1.  The latter means "no shutdown requested".
>> What about adding 'none' to ShutdownCause, with value 0, und use that
>> instead of literal -1?  Would avoid the unusual "negative means false,
>> non-negative means true".
>
> Works nicely if the enum is internal-use only.  Gets a bit more awkward
> if the enum is exposed to the end-user.
>
> The fact that I let QAPI generate the enum in patch 3 is evidence that
> I'm leaning towards exposing it to the end user (patch 4); if we want to
> keep it internal-only, a better place for the enum might be in sysemu.h

Yes, unless you need the generated ShutdownCause_lookup[].

> (where we also have the weird '#define VMRESET_SILENT false' '#define
> VMRESET_REPORT true' to name a boolean parameter).

Some people believe such defines make code more readable, others hate
them.  Regardless, they're unusual in QEMU.  Unusual is best avoided.

>> PATCH 4 exposes ShutdownCause in event SHUTDOWN, and 'none' must not
>> occur there.  However, if we ever add a query-shutdown to go with this
>> event, we will need 'none' there.
>
> So, query-shutdown would basically be: what is the last-reported
> shutdown event (normally none, when the guest is still running; but if,
> like libvirt, you start qemu -no-shutdown, it can then be the cause of
> why we are in a shutdown/stopped state while waiting for final cleanup)?

Sounds right.

> How important/likely is such an event?  (Hmm, from libvirt's
> perspective, events are usually reliable, but can be lost; if we can
> restart libvirtd and reconnect to a qemu process that is hanging on to
> life only because no one has cleaned it up yet, query-shutdown does seem
> like a useful thing for libvirt to have at the time it reconnects to
> that qemu process).

Rule of thumb: if we need an event, we probably need a query, too.

> We could always include 'none' in the QAPI enum, then document in
> 'SHUTDOWN' and 'RESET' events that the cause will never be 'none'.

Yes.

>                                                                     Doc
> hacks like that feel a little unclean, but not so horrible as to be
> unforgivable.

I wouldn't call it an unclean hack.  For me, it's coping with an
insufficiently expressive type system: we can't define ShutdownCause + {
'none' } as a supertype of ShutdownCause.

Even if we could, I'm not sure it would be worth the bother.

>> I'd be tempted to reshuffle declarations here, because shutdown_signal's
>> int is a different one than reset_requested's and shutdown_requested,
>> and the latter two's "negative means false, non-negative means true" is
>> unusual enough to justify a comment.
> ...
>> 
>> Hmm.  In case we stick to literal -1: consider splitting this patch into
>> a part that changes @shutdown_requested from zero/non-zero to
>> negative/non-negative, and a part that uses ShutdownCause for the
>> non-negative values.
>
>
> You're definitely right that if the enum doesn't have a nice none=0
> state, then reshuffling to the magic -1 as no request is awkward enough
> to be done alone.
>
> But part of the answer is also dependent on whether we want PATCH 4 or
> not (or, as you brought up, the possibility of a query-shutdown command
> with even more persistent storage of the last-reported event).

Yes.

>>> @@ -1650,11 +1650,11 @@ static void qemu_kill_report(void)
>>>  static int qemu_reset_requested(void)
>>>  {
>>>      int r = reset_requested;
>>> -    if (r && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
>>> -        reset_requested = 0;
>>> +    if (r >= 0 && replay_checkpoint(CHECKPOINT_RESET_REQUESTED)) {
>>> +        reset_requested = -1;
>>>          return r;
>>>      }
>>> -    return false;
>>> +    return -1;
>> 
>> "return false" in a function returning int smells, good riddance.
>> 
>
> In one of my earlier drafts of the patch, I even tried to change the
> return type from int to bool, but decided that keeping it as int worked
> best (if I have to use the -1/cause dichotomy).  But you're also right
> that with a 'none' value in the enum, I could directly return ShutdownCause.
>
>>>  }
>>>
>>>  static int qemu_suspend_requested(void)
>>> @@ -1686,7 +1686,12 @@ static int qemu_debug_requested(void)
>>>      return r;
>>>  }
>>>
>>> -void qemu_system_reset(bool report)
>>> +/*
>>> + * Reset the VM. If @report is VMRESET_REPORT, issue an event, using
>>> + * the @reason interpreted as ShutdownType for details.  Otherwise,
>>> + * @report is VMRESET_SILENT and @reason is ignored.
>>> + */
>>> +void qemu_system_reset(bool report, int reason)
>> 
>> Why int reason and not ShutdownCause?  Hmm, peeking ahead, I see you
>> pass -1 with VMRESET_SILENT.  Yet another place where you use int for
>> type ShutdownCause + { -1 }.  Adding 'none' to ShutdownCause looks
>> even more attractive to me now.
>
> Yeah, it's getting to be that way to me to, even if it just means that I
> may have volunteered myself into writing a query-shutdown QMP command.

The reward for doing good work is more work.

>>> @@ -1738,9 +1744,10 @@ void qemu_system_guest_panicked(GuestPanicInformation *info)
>>>  void qemu_system_reset_request(void)
>>>  {
>>>      if (no_reboot) {
>>> -        shutdown_requested = 1;
>>> +        /* FIXME - add a parameter to allow callers to specify reason */
>> 
>> FIXME addressed in the next patch.  Mention in this one's commit
>> message?
>
> Sure. Something like "Mark a couple of places as FIXME where we have to
> guess a value to use; a later patch will fix things to supply a correct
> value".

Works for me, provided the meaning of "value" is clear from context.

>> 
>>> +        shutdown_requested = SHUTDOWN_CAUSE_GUEST_RESET;
>
> I've also debated about splitting patch 3 into two parts: the event
> member additions (affecting .json and vl.c) and the parameter additions
> (affecting all other call-sites).  If I add the event parameter first,
> then supplying a bogus value to the event means extra churn to qemu
> iotests output files unless I change THIS line of code to guess
> SHUTDOWN_CAUSE_HOST_QMP; the other option is to wire up parameter
> passing first and event reporting last.
>
> I'll wait for more inputs before respinning this series (I already did a
> poor enough job slamming mailboxes by sending 3 iterations of the series
> in one day).  As you mention, I'd still like to hear ideas for the

Your v3 and v4 cost me no time, don't worry.

> replay side of things, and I wouldn't mind if Dan has any ideas from the
> libvirt/upper-layer stack usage side of things on the fate of patch 4.

Okay.

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xen.org
https://lists.xen.org/xen-devel

^ permalink raw reply	[flat|nested] 16+ messages in thread

end of thread, other threads:[~2017-05-02 11:47 UTC | newest]

Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <20170428021317.24711-1-eblake@redhat.com>
2017-04-28  2:13 ` [PATCH v5 2/4] shutdown: Prepare for use of an enum in reset/shutdown_request Eric Blake
2017-04-28  8:08   ` Dr. David Alan Gilbert
2017-04-28 14:35     ` Eric Blake
2017-04-28 15:27       ` Dr. David Alan Gilbert
2017-04-28 15:57         ` Eric Blake
2017-04-28 16:09           ` Dr. David Alan Gilbert
2017-04-28 18:05             ` Eric Blake
2017-04-28 18:13               ` Dr. David Alan Gilbert
2017-04-28 14:45     ` [Qemu-devel] " Markus Armbruster
2017-04-28 14:42   ` Markus Armbruster
2017-04-28 22:34     ` Eric Blake
2017-05-02 11:47       ` Markus Armbruster
2017-04-28  2:13 ` [PATCH v5 3/4] shutdown: Add source information to SHUTDOWN and RESET Eric Blake
     [not found] ` <20170428021317.24711-4-eblake@redhat.com>
2017-04-28 15:01   ` [Qemu-devel] " Markus Armbruster
2017-05-01  3:58   ` David Gibson
     [not found]   ` <87h918bmpz.fsf@dusky.pond.sub.org>
2017-05-02  8:13     ` [Qemu-devel] " Pavel Dovgalyuk

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).