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