diff options
-rw-r--r-- | kvm-all.c | 1 | ||||
-rw-r--r-- | qapi-schema.json | 24 | ||||
-rw-r--r-- | target/i386/cpu.c | 50 |
3 files changed, 75 insertions, 0 deletions
@@ -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++) { |