Commit 2da91b54 authored by Viktor Prutyanov's avatar Viktor Prutyanov Committed by Paolo Bonzini
Browse files

dump: add Windows dump format to dump-guest-memory

This patch adds Windows crashdumping feature. Now QEMU can produce ELF-dump
containing Windows crashdump header, which can help to convert to a valid
WinDbg-understandable crashdump file, or immediately create such file.
The crashdump will be obtained by joining physical memory dump and 8K header
exposed through vmcoreinfo/fw_cfg device by guest driver at BSOD time. Option
'-w' was added to dump-guest-memory command. At the moment, only x64
configuration is supported.
Suitable driver can be found at
https://github.com/virtio-win/kvm-guest-drivers-windows/tree/master/fwcfg64



Signed-off-by: default avatarViktor Prutyanov <viktor.prutyanov@virtuozzo.com>
Reviewed-by: default avatarMarc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20180517162342.4330-2-viktor.prutyanov@virtuozzo.com>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent 2266d443
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -143,6 +143,7 @@ obj-y += hw/
obj-y += memory.o
obj-y += memory_mapping.o
obj-y += dump.o
obj-$(TARGET_X86_64) += win_dump.o
obj-y += migration/ram.o
LIBS := $(libs_softmmu) $(LIBS)

+23 −1
Original line number Diff line number Diff line
@@ -29,6 +29,10 @@
#include "qemu/error-report.h"
#include "hw/misc/vmcoreinfo.h"

#ifdef TARGET_X86_64
#include "win_dump.h"
#endif

#include <zlib.h>
#ifdef CONFIG_LZO
#include <lzo/lzo1x.h>
@@ -1866,7 +1870,11 @@ static void dump_process(DumpState *s, Error **errp)
    Error *local_err = NULL;
    DumpQueryResult *result = NULL;

    if (s->has_format && s->format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
    if (s->has_format && s->format == DUMP_GUEST_MEMORY_FORMAT_WIN_DMP) {
#ifdef TARGET_X86_64
        create_win_dump(s, &local_err);
#endif
    } else if (s->has_format && s->format != DUMP_GUEST_MEMORY_FORMAT_ELF) {
        create_kdump_vmcore(s, &local_err);
    } else {
        create_vmcore(s, &local_err);
@@ -1970,6 +1978,13 @@ void qmp_dump_guest_memory(bool paging, const char *file,
    }
#endif

#ifndef TARGET_X86_64
    if (has_format && format == DUMP_GUEST_MEMORY_FORMAT_WIN_DMP) {
        error_setg(errp, "Windows dump is only available for x86-64");
        return;
    }
#endif

#if !defined(WIN32)
    if (strstart(file, "fd:", &p)) {
        fd = monitor_get_fd(cur_mon, p, errp);
@@ -2044,5 +2059,12 @@ DumpGuestMemoryCapability *qmp_query_dump_guest_memory_capability(Error **errp)
    item->value = DUMP_GUEST_MEMORY_FORMAT_KDUMP_SNAPPY;
#endif

    /* Windows dump is available only if target is x86_64 */
#ifdef TARGET_X86_64
    item->next = g_malloc0(sizeof(DumpGuestMemoryFormatList));
    item = item->next;
    item->value = DUMP_GUEST_MEMORY_FORMAT_WIN_DMP;
#endif

    return cap;
}
+8 −5
Original line number Diff line number Diff line
@@ -1136,30 +1136,33 @@ ETEXI

    {
        .name       = "dump-guest-memory",
        .args_type  = "paging:-p,detach:-d,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
        .params     = "[-p] [-d] [-z|-l|-s] filename [begin length]",
        .args_type  = "paging:-p,detach:-d,windmp:-w,zlib:-z,lzo:-l,snappy:-s,filename:F,begin:l?,length:l?",
        .params     = "[-p] [-d] [-z|-l|-s|-w] filename [begin length]",
        .help       = "dump guest memory into file 'filename'.\n\t\t\t"
                      "-p: do paging to get guest's memory mapping.\n\t\t\t"
                      "-d: return immediately (do not wait for completion).\n\t\t\t"
                      "-z: dump in kdump-compressed format, with zlib compression.\n\t\t\t"
                      "-l: dump in kdump-compressed format, with lzo compression.\n\t\t\t"
                      "-s: dump in kdump-compressed format, with snappy compression.\n\t\t\t"
                      "-w: dump in Windows crashdump format (can be used instead of ELF-dump converting),\n\t\t\t"
                      "    for Windows x64 guests with vmcoreinfo driver only.\n\t\t\t"
                      "begin: the starting physical address.\n\t\t\t"
                      "length: the memory size, in bytes.",
        .cmd        = hmp_dump_guest_memory,
    },


STEXI
@item dump-guest-memory [-p] @var{filename} @var{begin} @var{length}
@item dump-guest-memory [-z|-l|-s] @var{filename}
@item dump-guest-memory [-z|-l|-s|-w] @var{filename}
@findex dump-guest-memory
Dump guest memory to @var{protocol}. The file can be processed with crash or
gdb. Without -z|-l|-s, the dump format is ELF.
gdb. Without -z|-l|-s|-w, the dump format is ELF.
        -p: do paging to get guest's memory mapping.
        -z: dump in kdump-compressed format, with zlib compression.
        -l: dump in kdump-compressed format, with lzo compression.
        -s: dump in kdump-compressed format, with snappy compression.
        -w: dump in Windows crashdump format (can be used instead of ELF-dump converting),
            for Windows x64 guests with vmcoreinfo driver only
  filename: dump file name.
     begin: the starting physical address. It's optional, and should be
            specified together with length.
+7 −2
Original line number Diff line number Diff line
@@ -2014,6 +2014,7 @@ void hmp_device_del(Monitor *mon, const QDict *qdict)
void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
{
    Error *err = NULL;
    bool win_dmp = qdict_get_try_bool(qdict, "windmp", false);
    bool paging = qdict_get_try_bool(qdict, "paging", false);
    bool zlib = qdict_get_try_bool(qdict, "zlib", false);
    bool lzo = qdict_get_try_bool(qdict, "lzo", false);
@@ -2028,12 +2029,16 @@ void hmp_dump_guest_memory(Monitor *mon, const QDict *qdict)
    enum DumpGuestMemoryFormat dump_format = DUMP_GUEST_MEMORY_FORMAT_ELF;
    char *prot;

    if (zlib + lzo + snappy > 1) {
        error_setg(&err, "only one of '-z|-l|-s' can be set");
    if (zlib + lzo + snappy + win_dmp > 1) {
        error_setg(&err, "only one of '-z|-l|-s|-w' can be set");
        hmp_handle_error(mon, &err);
        return;
    }

    if (win_dmp) {
        dump_format = DUMP_GUEST_MEMORY_FORMAT_WIN_DMP;
    }

    if (zlib) {
        dump_format = DUMP_GUEST_MEMORY_FORMAT_KDUMP_ZLIB;
    }
+4 −1
Original line number Diff line number Diff line
@@ -1677,10 +1677,13 @@
#
# @kdump-snappy: kdump-compressed format with snappy-compressed
#
# @win-dmp: Windows full crashdump format,
#           can be used instead of ELF converting (since 2.13)
#
# Since: 2.0
##
{ 'enum': 'DumpGuestMemoryFormat',
  'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy' ] }
  'data': [ 'elf', 'kdump-zlib', 'kdump-lzo', 'kdump-snappy', 'win-dmp' ] }

##
# @dump-guest-memory:
Loading