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 -- libvir-list mailing list libvir-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/libvir-list