[libvirt] [PATCH 3/4] qemu: monitor: Extract additional info from GUEST_PANICKED event

Peter Krempa pkrempa at redhat.com
Tue Mar 21 07:47:49 UTC 2017


For certain kinds of panic notifiers (notably hyper-v) qemu is able to
report some data regarding the crash passed from the guest.

Make the data accessible to the callback in qemu so that it can be
processed further.
---
 src/qemu/qemu_monitor.c      | 15 ++++++++++--
 src/qemu/qemu_monitor.h      | 32 ++++++++++++++++++++++++-
 src/qemu/qemu_monitor_json.c | 56 ++++++++++++++++++++++++++++++++++++++++++--
 src/qemu/qemu_process.c      |  2 ++
 4 files changed, 100 insertions(+), 5 deletions(-)

diff --git a/src/qemu/qemu_monitor.c b/src/qemu/qemu_monitor.c
index 79da47237..4a7e71e8f 100644
--- a/src/qemu/qemu_monitor.c
+++ b/src/qemu/qemu_monitor.c
@@ -1359,11 +1359,12 @@ qemuMonitorEmitResume(qemuMonitorPtr mon)


 int
-qemuMonitorEmitGuestPanic(qemuMonitorPtr mon)
+qemuMonitorEmitGuestPanic(qemuMonitorPtr mon,
+                          qemuMonitorEventPanicInfoPtr info)
 {
     int ret = -1;
     VIR_DEBUG("mon=%p", mon);
-    QEMU_MONITOR_CALLBACK(mon, ret, domainGuestPanic, mon->vm);
+    QEMU_MONITOR_CALLBACK(mon, ret, domainGuestPanic, mon->vm, info);
     return ret;
 }

@@ -4184,3 +4185,13 @@ qemuMonitorQueryQMPSchema(qemuMonitorPtr mon)

     return qemuMonitorJSONQueryQMPSchema(mon);
 }
+
+
+void
+qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfoPtr info)
+{
+    if (!info)
+        return;
+
+    VIR_FREE(info);
+}
diff --git a/src/qemu/qemu_monitor.h b/src/qemu/qemu_monitor.h
index c3d3f2fb3..c4d247e79 100644
--- a/src/qemu/qemu_monitor.h
+++ b/src/qemu/qemu_monitor.h
@@ -70,6 +70,34 @@ struct _qemuMonitorMessage {
     void *passwordOpaque;
 };

+typedef enum {
+    QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_NONE = 0,
+    QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV,
+
+    QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_LAST
+} qemuMonitorEventPanicInfoType;
+
+typedef struct _qemuMonitorEventPanicInfoHyperv qemuMonitorEventPanicInfoHyperv;
+typedef qemuMonitorEventPanicInfoHyperv *qemuMonitorEventPanicInfoHypervPtr;
+struct _qemuMonitorEventPanicInfoHyperv {
+    /* Hyper-V specific guest panic information (HV crash MSRs) */
+    unsigned long long arg1;
+    unsigned long long arg2;
+    unsigned long long arg3;
+    unsigned long long arg4;
+    unsigned long long arg5;
+};
+
+typedef struct _qemuMonitorEventPanicInfo qemuMonitorEventPanicInfo;
+typedef qemuMonitorEventPanicInfo *qemuMonitorEventPanicInfoPtr;
+struct _qemuMonitorEventPanicInfo {
+    qemuMonitorEventPanicInfoType type;
+    union {
+        qemuMonitorEventPanicInfoHyperv hyperv;
+    } data;
+};
+
+void qemuMonitorEventPanicInfoFree(qemuMonitorEventPanicInfoPtr info);

 typedef void (*qemuMonitorDestroyCallback)(qemuMonitorPtr mon,
                                            virDomainObjPtr vm,
@@ -167,6 +195,7 @@ typedef int (*qemuMonitorDomainPMSuspendDiskCallback)(qemuMonitorPtr mon,
                                                       void *opaque);
 typedef int (*qemuMonitorDomainGuestPanicCallback)(qemuMonitorPtr mon,
                                                    virDomainObjPtr vm,
+                                                   qemuMonitorEventPanicInfoPtr info,
                                                    void *opaque);
 typedef int (*qemuMonitorDomainDeviceDeletedCallback)(qemuMonitorPtr mon,
                                                       virDomainObjPtr vm,
@@ -337,7 +366,8 @@ int qemuMonitorEmitBlockJob(qemuMonitorPtr mon,
 int qemuMonitorEmitBalloonChange(qemuMonitorPtr mon,
                                  unsigned long long actual);
 int qemuMonitorEmitPMSuspendDisk(qemuMonitorPtr mon);
-int qemuMonitorEmitGuestPanic(qemuMonitorPtr mon);
+int qemuMonitorEmitGuestPanic(qemuMonitorPtr mon,
+                              qemuMonitorEventPanicInfoPtr info);
 int qemuMonitorEmitDeviceDeleted(qemuMonitorPtr mon,
                                  const char *devAlias);
 int qemuMonitorEmitNicRxFilterChanged(qemuMonitorPtr mon,
diff --git a/src/qemu/qemu_monitor_json.c b/src/qemu/qemu_monitor_json.c
index 553544aea..d75748bd8 100644
--- a/src/qemu/qemu_monitor_json.c
+++ b/src/qemu/qemu_monitor_json.c
@@ -546,11 +546,63 @@ static void qemuMonitorJSONHandleResume(qemuMonitorPtr mon, virJSONValuePtr data
     qemuMonitorEmitResume(mon);
 }

-static void qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon, virJSONValuePtr data ATTRIBUTE_UNUSED)
+
+static qemuMonitorEventPanicInfoPtr
+qemuMonitorJSONGuestPanicExtractInfoHyperv(virJSONValuePtr data)
+{
+    qemuMonitorEventPanicInfoPtr ret;
+
+    if (VIR_ALLOC(ret) < 0)
+        return NULL;
+
+    ret->type = QEMU_MONITOR_EVENT_PANIC_INFO_TYPE_HYPERV;
+
+    if (virJSONValueObjectGetNumberUlong(data, "arg1", &ret->data.hyperv.arg1) < 0 ||
+        virJSONValueObjectGetNumberUlong(data, "arg2", &ret->data.hyperv.arg2) < 0 ||
+        virJSONValueObjectGetNumberUlong(data, "arg3", &ret->data.hyperv.arg3) < 0 ||
+        virJSONValueObjectGetNumberUlong(data, "arg4", &ret->data.hyperv.arg4) < 0 ||
+        virJSONValueObjectGetNumberUlong(data, "arg5", &ret->data.hyperv.arg5) < 0) {
+        virReportError(VIR_ERR_INTERNAL_ERROR, "%s",
+                       _("malformed hyperv panic data"));
+        goto error;
+    }
+
+    return ret;
+
+ error:
+    qemuMonitorEventPanicInfoFree(ret);
+    return NULL;
+}
+
+
+static qemuMonitorEventPanicInfoPtr
+qemuMonitorJSONGuestPanicExtractInfo(virJSONValuePtr data)
 {
-    qemuMonitorEmitGuestPanic(mon);
+    const char *type = virJSONValueObjectGetString(data, "type");
+
+    if (STREQ_NULLABLE(type, "hyper-v"))
+        return qemuMonitorJSONGuestPanicExtractInfoHyperv(data);
+
+    virReportError(VIR_ERR_INTERNAL_ERROR,
+                   _("unknown panic info type '%s'"), NULLSTR(type));
+    return NULL;
 }

+
+static void
+qemuMonitorJSONHandleGuestPanic(qemuMonitorPtr mon,
+                                virJSONValuePtr data)
+{
+    virJSONValuePtr infojson = virJSONValueObjectGetObject(data, "info");
+    qemuMonitorEventPanicInfoPtr info = NULL;
+
+    if (infojson)
+        info = qemuMonitorJSONGuestPanicExtractInfo(infojson);
+
+    qemuMonitorEmitGuestPanic(mon, info);
+}
+
+
 static void qemuMonitorJSONHandleRTCChange(qemuMonitorPtr mon, virJSONValuePtr data)
 {
     long long offset = 0;
diff --git a/src/qemu/qemu_process.c b/src/qemu/qemu_process.c
index ec0e36d2e..6a73dd464 100644
--- a/src/qemu/qemu_process.c
+++ b/src/qemu/qemu_process.c
@@ -1297,6 +1297,7 @@ qemuProcessHandlePMSuspendDisk(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
 static int
 qemuProcessHandleGuestPanic(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
                             virDomainObjPtr vm,
+                            qemuMonitorEventPanicInfoPtr info,
                             void *opaque)
 {
     virQEMUDriverPtr driver = opaque;
@@ -1309,6 +1310,7 @@ qemuProcessHandleGuestPanic(qemuMonitorPtr mon ATTRIBUTE_UNUSED,
     processEvent->eventType = QEMU_PROCESS_EVENT_GUESTPANIC;
     processEvent->action = vm->def->onCrash;
     processEvent->vm = vm;
+    processEvent->data = info;
     /* Hold an extra reference because we can't allow 'vm' to be
      * deleted before handling guest panic event is finished.
      */
-- 
2.12.0




More information about the libvir-list mailing list