From patchwork Thu Feb 9 15:13:24 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "Denis V. Lunev" X-Patchwork-Id: 9564853 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 480C96020C for ; Thu, 9 Feb 2017 15:18:52 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 32C4E28533 for ; Thu, 9 Feb 2017 15:18:52 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 24B4D28535; Thu, 9 Feb 2017 15:18:52 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.9 required=2.0 tests=BAYES_00,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 55A1B28533 for ; Thu, 9 Feb 2017 15:18:51 +0000 (UTC) Received: from localhost ([::1]:38472 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cbqUj-0000pf-Uw for patchwork-qemu-devel@patchwork.kernel.org; Thu, 09 Feb 2017 10:18:50 -0500 Received: from eggs.gnu.org ([2001:4830:134:3::10]:46388) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1cbqPz-0004v4-VJ for qemu-devel@nongnu.org; Thu, 09 Feb 2017 10:13:57 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1cbqPy-0007bc-DG for qemu-devel@nongnu.org; Thu, 09 Feb 2017 10:13:55 -0500 Received: from mailhub.sw.ru ([195.214.232.25]:41261 helo=relay.sw.ru) by eggs.gnu.org with esmtps (TLS1.0:DHE_RSA_AES_256_CBC_SHA1:32) (Exim 4.71) (envelope-from ) id 1cbqPx-0007bK-Sv for qemu-devel@nongnu.org; Thu, 09 Feb 2017 10:13:54 -0500 Received: from iris.sw.ru (msk-vpn.virtuozzo.com [195.214.232.6]) by relay.sw.ru (8.13.4/8.13.4) with ESMTP id v19FDQTP028293; Thu, 9 Feb 2017 18:13:28 +0300 (MSK) From: "Denis V. Lunev" To: qemu-devel@nongnu.org Date: Thu, 9 Feb 2017 18:13:24 +0300 Message-Id: <1486653206-14553-2-git-send-email-den@openvz.org> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1486653206-14553-1-git-send-email-den@openvz.org> References: <1486653206-14553-1-git-send-email-den@openvz.org> X-detected-operating-system: by eggs.gnu.org: OpenBSD 3.x [fuzzy] X-Received-From: 195.214.232.25 Subject: [Qemu-devel] [PATCH v2 1/3] i386/cpu: add crash-information QOM property X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Anton Nefedov , Eduardo Habkost , Marcelo Tosatti , Markus Armbruster , Paolo Bonzini , "Denis V . Lunev" , Richard Henderson Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP From: Anton Nefedov 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 Signed-off-by: Denis V. Lunev CC: Paolo Bonzini CC: Marcelo Tosatti CC: Richard Henderson CC: Eduardo Habkost CC: Eric Blake CC: Markus Armbruster --- include/sysemu/kvm.h | 2 ++ kvm-all.c | 1 + qapi-schema.json | 24 +++++++++++++++++++++++ stubs/Makefile.objs | 1 + stubs/kvm-crash.c | 8 ++++++++ target/i386/cpu.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++++++++ target/i386/cpu.h | 3 +++ target/i386/kvm.c | 41 +++++++++++++++++++++++++++++++++++++++ 8 files changed, 134 insertions(+) create mode 100644 stubs/kvm-crash.c diff --git a/include/sysemu/kvm.h b/include/sysemu/kvm.h index 3045ee7..02a363d 100644 --- a/include/sysemu/kvm.h +++ b/include/sysemu/kvm.h @@ -527,4 +527,6 @@ int kvm_set_one_reg(CPUState *cs, uint64_t id, void *source); */ int kvm_get_one_reg(CPUState *cs, uint64_t id, void *target); int kvm_get_max_memslots(void); + +void kvm_arch_save_crash_info(CPUState *cpu); #endif diff --git a/kvm-all.c b/kvm-all.c index a27c880..abfe92d 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_arch_save_crash_info(cpu); qemu_mutex_lock_iothread(); qemu_system_guest_panicked(); qemu_mutex_unlock_iothread(); diff --git a/qapi-schema.json b/qapi-schema.json index cbdffdd..9cb6ac5 100644 --- a/qapi-schema.json +++ b/qapi-schema.json @@ -5846,6 +5846,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/stubs/Makefile.objs b/stubs/Makefile.objs index a187295..3b1632a 100644 --- a/stubs/Makefile.objs +++ b/stubs/Makefile.objs @@ -35,3 +35,4 @@ stub-obj-y += qmp_pc_dimm_device_list.o stub-obj-y += target-monitor-defs.o stub-obj-y += target-get-monitor-def.o stub-obj-y += pc_madt_cpu_entry.o +stub-obj-y += kvm-crash.o diff --git a/stubs/kvm-crash.c b/stubs/kvm-crash.c new file mode 100644 index 0000000..b2f502d --- /dev/null +++ b/stubs/kvm-crash.c @@ -0,0 +1,8 @@ +#include "qemu/osdep.h" +#include "qemu-common.h" +#include "sysemu/kvm.h" + +void kvm_arch_save_crash_info(CPUState *cs) +{ + return; +} diff --git a/target/i386/cpu.c b/target/i386/cpu.c index eb49980..275e236 100644 --- a/target/i386/cpu.c +++ b/target/i386/cpu.c @@ -3495,6 +3495,57 @@ 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 = cpu->hv_msr_crash_params[0]; + panic_info_hv->arg2 = cpu->hv_msr_crash_params[1]; + panic_info_hv->arg3 = cpu->hv_msr_crash_params[2]; + panic_info_hv->arg4 = cpu->hv_msr_crash_params[3]; + panic_info_hv->arg5 = cpu->hv_msr_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); + + if (panic_info->type == GUEST_PANIC_INFORMATION_KIND_HYPER_V) { + g_free(panic_info->u.hyper_v.data); + } + g_free(panic_info); +} + static void x86_cpu_initfn(Object *obj) { CPUState *cs = CPU(obj); @@ -3530,6 +3581,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++) { diff --git a/target/i386/cpu.h b/target/i386/cpu.h index 4d788d5..38c8da9 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -1258,6 +1258,9 @@ struct X86CPU { /* Number of physical address bits supported */ uint32_t phys_bits; + /* Hyper-V crash MSRs */ + uint64_t hv_msr_crash_params[HV_X64_MSR_CRASH_PARAMS]; + /* in order to simplify APIC support, we leave this pointer to the user */ struct DeviceState *apic_state; diff --git a/target/i386/kvm.c b/target/i386/kvm.c index 27fd050..2427c4a 100644 --- a/target/i386/kvm.c +++ b/target/i386/kvm.c @@ -2054,6 +2054,36 @@ static int kvm_get_sregs(X86CPU *cpu) return 0; } +static int kvm_read_msr_hv_crash(X86CPU *cpu, uint64_t *buf) +{ + int i, ret; + struct { + struct kvm_msrs info; + struct kvm_msr_entry entries[HV_X64_MSR_CRASH_PARAMS]; + } msr_data; + + if (!has_msr_hv_crash) { + return -ENOSYS; + } + + for (i = 0; i < HV_X64_MSR_CRASH_PARAMS; i++) { + msr_data.entries[i].index = HV_X64_MSR_CRASH_P0 + i; + } + msr_data.info.nmsrs = HV_X64_MSR_CRASH_PARAMS; + + ret = kvm_vcpu_ioctl(CPU(cpu), KVM_GET_MSRS, &msr_data); + if (ret < 0) { + return ret; + } + + for (i = 0; i < ret; i++) { + const struct kvm_msr_entry *msr = msr_data.entries + i; + buf[msr->index - HV_X64_MSR_CRASH_P0] = msr->data; + } + + return 0; +} + static int kvm_get_msrs(X86CPU *cpu) { CPUX86State *env = &cpu->env; @@ -2801,6 +2831,17 @@ int kvm_arch_get_registers(CPUState *cs) return ret; } +void kvm_arch_save_crash_info(CPUState *cs) +{ + if (has_msr_hv_crash) { + X86CPU *cpu = X86_CPU(cs); + int ret = kvm_read_msr_hv_crash(cpu, cpu->hv_msr_crash_params); + if (ret < 0) { + fprintf(stderr, "Failed to get HV crash parameters\n"); + } + } +} + void kvm_arch_pre_run(CPUState *cpu, struct kvm_run *run) { X86CPU *x86_cpu = X86_CPU(cpu);