summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAnton Nefedov <anton.nefedov@virtuozzo.com>2017-02-14 09:25:22 +0300
committerPaolo Bonzini <pbonzini@redhat.com>2017-02-16 15:30:49 +0100
commitd187e08dc4d0793dab1a9747b72b17a1cf0d3e43 (patch)
tree47aeca102072692fe6acdd251324f5da77b0aeee
parentd9e73d32a891a4d9d9b14dcdd27490ec2d13026a (diff)
downloadqemu-d187e08dc4d0793dab1a9747b72b17a1cf0d3e43.tar.gz
i386/cpu: add crash-information QOM property
Windows reports BSOD parameters through Hyper-V crash MSRs. This information is very useful for initial crash analysis and thus it would be nice to have a way to fetch it. Signed-off-by: Anton Nefedov <anton.nefedov@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> Message-Id: <1487053524-18674-2-git-send-email-den@openvz.org> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r--kvm-all.c1
-rw-r--r--qapi-schema.json24
-rw-r--r--target/i386/cpu.c50
3 files changed, 75 insertions, 0 deletions
diff --git a/kvm-all.c b/kvm-all.c
index a27c880c05..64f46c8ee7 100644
--- a/kvm-all.c
+++ b/kvm-all.c
@@ -2000,6 +2000,7 @@ int kvm_cpu_exec(CPUState *cpu)
ret = EXCP_INTERRUPT;
break;
case KVM_SYSTEM_EVENT_CRASH:
+ kvm_cpu_synchronize_state(cpu);
qemu_mutex_lock_iothread();
qemu_system_guest_panicked();
qemu_mutex_unlock_iothread();
diff --git a/qapi-schema.json b/qapi-schema.json
index 5edb08d621..baa0d263d6 100644
--- a/qapi-schema.json
+++ b/qapi-schema.json
@@ -5871,6 +5871,30 @@
'data': [ 'pause', 'poweroff' ] }
##
+# @GuestPanicInformation:
+#
+# Information about a guest panic
+#
+# Since: 2.9
+##
+{'union': 'GuestPanicInformation',
+ 'data': { 'hyper-v': 'GuestPanicInformationHyperV' } }
+
+##
+# @GuestPanicInformationHyperV:
+#
+# Hyper-V specific guest panic information (HV crash MSRs)
+#
+# Since: 2.9
+##
+{'struct': 'GuestPanicInformationHyperV',
+ 'data': { 'arg1': 'uint64',
+ 'arg2': 'uint64',
+ 'arg3': 'uint64',
+ 'arg4': 'uint64',
+ 'arg5': 'uint64' } }
+
+##
# @rtc-reset-reinjection:
#
# This command will reset the RTC interrupt reinjection backlog.
diff --git a/target/i386/cpu.c b/target/i386/cpu.c
index eb49980ef1..71aa91fd16 100644
--- a/target/i386/cpu.c
+++ b/target/i386/cpu.c
@@ -3495,6 +3495,53 @@ static void x86_cpu_register_feature_bit_props(X86CPU *cpu,
x86_cpu_register_bit_prop(cpu, name, &cpu->env.features[w], bitnr);
}
+static GuestPanicInformation *x86_cpu_get_crash_info(CPUState *cs)
+{
+ X86CPU *cpu = X86_CPU(cs);
+ CPUX86State *env = &cpu->env;
+ GuestPanicInformation *panic_info = NULL;
+
+ if (env->features[FEAT_HYPERV_EDX] & HV_X64_GUEST_CRASH_MSR_AVAILABLE) {
+ GuestPanicInformationHyperV *panic_info_hv =
+ g_malloc0(sizeof(GuestPanicInformationHyperV));
+ panic_info = g_malloc0(sizeof(GuestPanicInformation));
+
+ panic_info->type = GUEST_PANIC_INFORMATION_KIND_HYPER_V;
+ panic_info->u.hyper_v.data = panic_info_hv;
+
+ assert(HV_X64_MSR_CRASH_PARAMS >= 5);
+ panic_info_hv->arg1 = env->msr_hv_crash_params[0];
+ panic_info_hv->arg2 = env->msr_hv_crash_params[1];
+ panic_info_hv->arg3 = env->msr_hv_crash_params[2];
+ panic_info_hv->arg4 = env->msr_hv_crash_params[3];
+ panic_info_hv->arg5 = env->msr_hv_crash_params[4];
+ }
+
+ return panic_info;
+}
+static void x86_cpu_get_crash_info_qom(Object *obj, Visitor *v,
+ const char *name, void *opaque,
+ Error **errp)
+{
+ CPUState *cs = CPU(obj);
+ GuestPanicInformation *panic_info;
+
+ if (!cs->crash_occurred) {
+ error_setg(errp, "No crash occured");
+ return;
+ }
+
+ panic_info = x86_cpu_get_crash_info(cs);
+ if (panic_info == NULL) {
+ error_setg(errp, "No crash information");
+ return;
+ }
+
+ visit_type_GuestPanicInformation(v, "crash-information", &panic_info,
+ errp);
+ qapi_free_GuestPanicInformation(panic_info);
+}
+
static void x86_cpu_initfn(Object *obj)
{
CPUState *cs = CPU(obj);
@@ -3530,6 +3577,9 @@ static void x86_cpu_initfn(Object *obj)
x86_cpu_get_feature_words,
NULL, NULL, (void *)cpu->filtered_features, NULL);
+ object_property_add(obj, "crash-information", "GuestPanicInformation",
+ x86_cpu_get_crash_info_qom, NULL, NULL, NULL, NULL);
+
cpu->hyperv_spinlock_attempts = HYPERV_SPINLOCK_NEVER_RETRY;
for (w = 0; w < FEATURE_WORDS; w++) {