From patchwork Wed Nov 16 08:27:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Wen Congyang X-Patchwork-Id: 125951 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [140.186.70.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by ozlabs.org (Postfix) with ESMTPS id 2909BB6F9C for ; Wed, 16 Nov 2011 19:26:48 +1100 (EST) Received: from localhost ([::1]:38121 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RQapP-0004nr-Cn for incoming@patchwork.ozlabs.org; Wed, 16 Nov 2011 03:26:43 -0500 Received: from eggs.gnu.org ([140.186.70.92]:53012) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RQapH-0004nm-QX for qemu-devel@nongnu.org; Wed, 16 Nov 2011 03:26:38 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1RQapF-00060C-7u for qemu-devel@nongnu.org; Wed, 16 Nov 2011 03:26:35 -0500 Received: from [222.73.24.84] (port=53244 helo=song.cn.fujitsu.com) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1RQap9-0005x0-Kc for qemu-devel@nongnu.org; Wed, 16 Nov 2011 03:26:33 -0500 Received: from tang.cn.fujitsu.com (tang.cn.fujitsu.com [10.167.250.3]) by song.cn.fujitsu.com (Postfix) with ESMTP id 36982170118; Wed, 16 Nov 2011 16:26:05 +0800 (CST) Received: from mailserver.fnst.cn.fujitsu.com (tang.cn.fujitsu.com [127.0.0.1]) by tang.cn.fujitsu.com (8.14.3/8.13.1) with ESMTP id pAG8Q0Ci019092; Wed, 16 Nov 2011 16:26:04 +0800 Received: from [10.167.225.226] ([10.167.225.226]) by mailserver.fnst.cn.fujitsu.com (Lotus Domino Release 8.5.1FP4) with ESMTP id 2011111616255417-117246 ; Wed, 16 Nov 2011 16:25:54 +0800 Message-ID: <4EC373F8.6080300@cn.fujitsu.com> Date: Wed, 16 Nov 2011 16:27:36 +0800 From: Wen Congyang User-Agent: Mozilla/5.0 (X11; U; Linux x86_64; en-US; rv:1.9.1.9) Gecko/20100413 Fedora/3.0.4-2.fc13 Thunderbird/3.0.4 MIME-Version: 1.0 To: qemu-devel , Jan Kiszka , Dave Anderson X-MIMETrack: Itemize by SMTP Server on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2011-11-16 16:25:54, Serialize by Router on mailserver/fnst(Release 8.5.1FP4|July 25, 2010) at 2011-11-16 16:25:58, Serialize complete at 2011-11-16 16:25:58 X-detected-operating-system: by eggs.gnu.org: FreeBSD 6.x (1) X-Received-From: 222.73.24.84 Subject: [Qemu-devel] [RFC] dump memory when host pci device is used by guest X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.14 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Hi, all 'virsh dump' can not work when host pci device is used by guest. We have discussed this issue here: http://lists.nongnu.org/archive/html/qemu-devel/2011-10/msg00736.html We have determined to introduce a new command dump to dump memory. The core file's format can be elf. I created a kdump-elf vmcore, and found that it can be used by both crash and gdb: # gdb /usr/lib/debug/lib/modules/2.6.32-71.el6.x86_64/vmlinux /work/core/vmcore GNU gdb (GDB) Red Hat Enterprise Linux (7.2-48.el6) Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /usr/lib/debug/lib/modules/2.6.32-71.el6.x86_64/vmlinux...done. [New Thread 1691] [New
] #0 sysrq_handle_crash (key=99, tty=0x0) at drivers/char/sysrq.c:130 130 drivers/char/sysrq.c: No such file or directory. in drivers/char/sysrq.c (gdb) bt #0 sysrq_handle_crash (key=99, tty=0x0) at drivers/char/sysrq.c:130 #1 0xffffffff8130d822 in __handle_sysrq (key=99, tty=0x0, check_mask=) at drivers/char/sysrq.c:521 #2 0xffffffff8130d8de in write_sysrq_trigger (file=, buf=, count=2, ppos=) at drivers/char/sysrq.c:599 #3 0xffffffff811cf31e in proc_reg_write (file=, buf=0x7fdabafea000
, count=2, ppos=) at fs/proc/inode.c:207 #4 0xffffffff8116c818 in vfs_write (file=0xffff88003c7bb740, buf=0x7fdabafea000
, count=, pos=0xffff88003767ff48) at fs/read_write.c:347 #5 0xffffffff8116d251 in sys_write (fd=, buf=0x7fdabafea000
, count=2) at fs/read_write.c:399 #6 0xffffffff81013172 in ?? () at arch/x86/kernel/entry_64.S:487 #7 0x0000000000000246 in ?? () #8 0x00000000ffffffff in ?? () #9 0x00007fdabafde700 in ?? () #10 0x000000000000000a in ?? () #11 0x0000000000000001 in ?? () #12 0x0000000000000002 in ?? () #13 0x0000000000000001 in ?? () #14 0x00000030f80d4230 in ?? () #15 0x0000000000000033 in ?? () #16 0x0000000000010206 in ?? () #17 0x00007fff8a126470 in ?? () #18 0x000000000000002b in ?? () #19 0xffff8800374f5000 in ?? () #20 0xffff88003c6f9000 in ?? () #21 0x0000000000000080 in ?? () #22 0xffff880037680080 in ?? () #23 0xffffffff00000014 in ?? () #24 0x0000000000000000 in ?? () (gdb) q # crash -s /usr/lib/debug/lib/modules/2.6.32-71.el6.x86_64/vmlinux /work/core/vmcore crash> bt PID: 1691 TASK: ffff88003711d520 CPU: 0 COMMAND: "bash" #0 [ffff88003767fae0] machine_kexec at ffffffff8103695b #1 [ffff88003767fb40] crash_kexec at ffffffff810b8f08 #2 [ffff88003767fc10] oops_end at ffffffff814cbbd0 #3 [ffff88003767fc40] no_context at ffffffff8104651b #4 [ffff88003767fc90] __bad_area_nosemaphore at ffffffff810467a5 #5 [ffff88003767fce0] bad_area at ffffffff810468ce #6 [ffff88003767fd10] do_page_fault at ffffffff814cd740 #7 [ffff88003767fd60] page_fault at ffffffff814caf45 [exception RIP: sysrq_handle_crash+22] RIP: ffffffff8130d566 RSP: ffff88003767fe18 RFLAGS: 00010096 RAX: 0000000000000010 RBX: 0000000000000063 RCX: 0000000000000000 RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000063 RBP: ffff88003767fe18 R8: 0000000000000000 R9: ffffffff815106c0 R10: 0000000000000001 R11: 0000000000000000 R12: 0000000000000000 R13: ffffffff8179e6c0 R14: 0000000000000286 R15: 0000000000000007 ORIG_RAX: ffffffffffffffff CS: 0010 SS: 0018 #8 [ffff88003767fe20] __handle_sysrq at ffffffff8130d822 #9 [ffff88003767fe70] write_sysrq_trigger at ffffffff8130d8de #10 [ffff88003767fea0] proc_reg_write at ffffffff811cf31e #11 [ffff88003767fef0] vfs_write at ffffffff8116c818 #12 [ffff88003767ff30] sys_write at ffffffff8116d251 #13 [ffff88003767ff80] system_call_fastpath at ffffffff81013172 RIP: 00000030f80d4230 RSP: 00007fff8a126470 RFLAGS: 00010206 RAX: 0000000000000001 RBX: ffffffff81013172 RCX: 0000000000000400 RDX: 0000000000000002 RSI: 00007fdabafea000 RDI: 0000000000000001 RBP: 00007fdabafea000 R8: 000000000000000a R9: 00007fdabafde700 R10: 00000000ffffffff R11: 0000000000000246 R12: 0000000000000002 R13: 00000030f8379780 R14: 0000000000000002 R15: 00000030f8379780 ORIG_RAX: 0000000000000001 CS: 0033 SS: 002b crash> I wrote a sample(not finished). It only can works on x86_64(both host and guest) I use it to create a core file: # readelf -h /tmp/vm2.save ELF Header: Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 Class: ELF64 Data: 2's complement, little endian Version: 1 (current) OS/ABI: UNIX - System V ABI Version: 0 Type: CORE (Core file) Machine: Advanced Micro Devices X86-64 Version: 0x1 Entry point address: 0x0 Start of program headers: 64 (bytes into file) Start of section headers: 0 (bytes into file) Flags: 0x0 Size of this header: 64 (bytes) Size of program headers: 56 (bytes) Number of program headers: 9 Size of section headers: 0 (bytes) Number of section headers: 0 Section header string table index: 0 # readelf -l /tmp/vm2.save Elf file type is CORE (Core file) Entry point 0x0 There are 9 program headers, starting at offset 64 Program Headers: Type Offset VirtAddr PhysAddr FileSiz MemSiz Flags Align NOTE 0x0000000000000238 0x0000000000000000 0x0000000000000000 0x00000000000002c8 0x00000000000002c8 0 LOAD 0x0000000000000500 0xffffffff81000000 0x0000000001000000 0x000000001f000000 0x000000001f000000 0 LOAD 0x000000001f000500 0x0000000000000000 0x0000000000000000 0x0000000001000000 0x0000000001000000 0 LOAD 0x0000000020000500 0x0000000000000000 0x0000000020000000 0x0000000000020000 0x0000000000020000 0 LOAD 0x0000000020020500 0x0000000000000000 0x0000000020870000 0x0000000000010000 0x0000000000010000 0 LOAD 0x0000000020030500 0x0000000000000000 0x0000000020850000 0x0000000000020000 0x0000000000020000 0 LOAD 0x0000000020050500 0x0000000000000000 0x0000000020840000 0x0000000000010000 0x0000000000010000 0 LOAD 0x0000000020060500 0x0000000000000000 0x0000000020040000 0x0000000000800000 0x0000000000800000 0 LOAD 0x0000000020860500 0x0000000000000000 0x0000000020020000 0x0000000000020000 0x0000000000020000 0 I can use crash to anaylze the file, but I can not use gdb to anaylze it. # gdb /usr/lib/debug/lib/modules/2.6.32-71.el6.x86_64/vmlinux /tmp/vm2.save GNU gdb (GDB) Red Hat Enterprise Linux (7.2-48.el6) Copyright (C) 2010 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "x86_64-redhat-linux-gnu". For bug reporting instructions, please see: ... Reading symbols from /usr/lib/debug/lib/modules/2.6.32-71.el6.x86_64/vmlinux...done. [New
] [New
] #0 0x8103be8b00000000 in ?? () (gdb) bt #0 0x8103be8b00000000 in ?? () Cannot access memory at address 0x8170dec800000000 (gdb) q My first and the most important question is that: Is there necessary to continue this work? The attachment is the sample patch. Thanks Wen Congyang From bdb3daaeb2743a14df2cab364622e2f47ae25093 Mon Sep 17 00:00:00 2001 From: Wen Congyang Date: Wed, 16 Nov 2011 16:06:10 +0800 Subject: [PATCH] dump sample --- Makefile.target | 1 + dump.c | 377 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ dump.h | 1 + hmp-commands.hx | 16 +++ monitor.c | 3 + qmp-commands.hx | 24 ++++ 6 files changed, 422 insertions(+), 0 deletions(-) create mode 100644 dump.c create mode 100644 dump.h diff --git a/Makefile.target b/Makefile.target index a111521..95d48a5 100644 --- a/Makefile.target +++ b/Makefile.target @@ -84,6 +84,7 @@ libobj-y += cpu_init.o endif libobj-$(TARGET_SPARC) += int32_helper.o libobj-$(TARGET_SPARC64) += int64_helper.o +libobj-y += dump.o libobj-y += disas.o libobj-$(CONFIG_TCI_DIS) += tci-dis.o diff --git a/dump.c b/dump.c new file mode 100644 index 0000000..bdec246 --- /dev/null +++ b/dump.c @@ -0,0 +1,377 @@ +/* + * QEMU live dump + * + * Copyright Fujitsu, Corp. 2011 + * + * Authors: + * + * This work is licensed under the terms of the GNU GPL, version 2. See + * the COPYING file in the top-level directory. + * + */ + +#include "qemu-common.h" +#include +#include +#include +#include "cpu.h" +#include "cpu-all.h" +#include "targphys.h" +#include "monitor.h" +#include "kvm.h" +#include "dump.h" +#include "sysemu.h" + +#ifdef TARGET_X86_64 +typedef struct { + target_ulong r15,r14,r13,r12,rbp,rbx,r11,r10; + target_ulong r9,r8,rax,rcx,rdx,rsi,rdi,orig_rax; + target_ulong rip,cs,eflags; + target_ulong rsp,ss; + target_ulong fs_base, gs_base; + target_ulong ds,es,fs,gs; +} x86_64_user_regs_struct; + +static int write_elf64_note(Monitor *mon, int fd, CPUState *env, + target_phys_addr_t *offset) +{ + x86_64_user_regs_struct regs; + Elf64_Nhdr *note; + char *buf; + int descsz, note_size, name_size = 5; + const char *name = "CORE"; + int ret; + + regs.r15 = env->regs[15]; + regs.r14 = env->regs[14]; + regs.r13 = env->regs[13]; + regs.r12 = env->regs[12]; + regs.r11 = env->regs[11]; + regs.r10 = env->regs[10]; + regs.r9 = env->regs[9]; + regs.r8 = env->regs[8]; + regs.rbp = env->regs[R_EBP]; + regs.rsp = env->regs[R_ESP]; + regs.rdi = env->regs[R_EDI]; + regs.rsi = env->regs[R_ESI]; + regs.rdx = env->regs[R_EDX]; + regs.rcx = env->regs[R_ECX]; + regs.rbx = env->regs[R_EBX]; + regs.rax = env->regs[R_EAX]; + regs.rip = env->eip; + regs.eflags = env->eflags; + + /* FIXME */ + regs.orig_rax = 0; + regs.cs = 0; + regs.ss = 0; + regs.fs_base = 0; + regs.gs_base = 0; + regs.ds = 0; + regs.es = 0; + regs.fs = 0; + regs.gs = 0; + + descsz = sizeof(prstatus_t) - sizeof(elf_gregset_t) + + sizeof(x86_64_user_regs_struct); + note_size = ((sizeof(Elf64_Nhdr) + 3) / 4 + (name_size + 3) / 4 + + (descsz +3) / 4) * 4; + note = g_malloc(note_size); + + note->n_namesz = name_size; + note->n_descsz = descsz; + note->n_type = NT_PRSTATUS; + buf = (char *)note; + buf += ((sizeof(Elf64_Nhdr) + 3) / 4) * 4; + memcpy(buf, name, name_size); + buf += ((name_size + 3) / 4) * 4; + buf += descsz - sizeof(x86_64_user_regs_struct) - sizeof(int); + memcpy(buf, ®s, sizeof(x86_64_user_regs_struct)); + + lseek(fd, *offset, SEEK_SET); + ret = write(fd, note, note_size); + g_free(note); + if (ret < 0) { + monitor_printf(mon, "dump: failed to write elf prstatus.\n"); + return -1; + } + + *offset += note_size; + + return 0; +} +#endif + +typedef struct { + uint32_t ebx, ecx, edx, esi, edi, ebp, eax; + unsigned short ds, __ds, es, __es; + unsigned short fs, __fs, gs, __gs; + uint32_t orig_eax, eip; + unsigned short cs, __cs; + uint32_t eflags, esp; + unsigned short ss, __ss; +} x86_user_regs_struct; + +static int write_elf32_note(Monitor *mon, int fd, CPUState *env, + target_phys_addr_t *offset) +{ + /* TODO */ + return 0; +} + +static target_ulong get_phys_base_addr(CPUState *env, target_ulong *base_vaddr) +{ + int i; + target_ulong kernel_base = -1; + target_ulong last, mask; + + for (i = 30, last = -1; (kernel_base == -1) && (i >= 20); i--) { + mask = ~((1LL << i) - 1); + *base_vaddr = env->idt.base & mask; + if (*base_vaddr == last) { + continue; + } + + kernel_base = cpu_get_phys_page_debug(env, *base_vaddr); + last = *base_vaddr; + } + + return kernel_base; +} + +static int write_elf_header(Monitor *mon, int fd, int phdr_num, bool lma) +{ + Elf64_Ehdr elf_header; + int ret; + + memset(&elf_header, 0, sizeof(Elf64_Ehdr)); + memcpy(&elf_header, ELFMAG, 4); + elf_header.e_ident[EI_CLASS] = ELFCLASS64; + elf_header.e_ident[EI_DATA] = ELFDATA2LSB; /* FIXME */ + elf_header.e_ident[EI_VERSION] = EV_CURRENT; + elf_header.e_type = ET_CORE; + elf_header.e_machine = lma ? EM_X86_64: EM_386; + elf_header.e_version = EV_CURRENT; + elf_header.e_ehsize = sizeof(elf_header); + elf_header.e_phoff = sizeof(Elf64_Ehdr); + elf_header.e_phentsize = sizeof(Elf64_Phdr); + elf_header.e_phnum = phdr_num; + + lseek(fd, 0, SEEK_SET); + ret = write(fd, &elf_header, sizeof(elf_header)); + if (ret < 0) { + monitor_printf(mon, "dump: failed to write elf header.\n"); + return -1; + } + + return 0; +} + +static int write_elf_load(Monitor *mon, int fd, RAMBlock *block, int phdr_index, + target_phys_addr_t *offset, target_ulong base_vaddr) +{ + Elf64_Phdr phdr; + off_t phdr_offset; + int ret; + + memset(&phdr, 0, sizeof(Elf64_Phdr)); + phdr.p_type = PT_LOAD; + phdr.p_offset = *offset; + phdr.p_paddr = block->offset; + phdr.p_filesz = block->length; + phdr.p_memsz = block->length; + phdr.p_vaddr = base_vaddr; + + phdr_offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * phdr_index; + lseek(fd, phdr_offset, SEEK_SET); + ret = write(fd, &phdr, sizeof(Elf64_Phdr)); + if (ret < 0) { + monitor_printf(mon, "dump: failed to write program header table.\n"); + return -1; + } + + lseek(fd, *offset, SEEK_SET); + ret = write(fd, block->host, block->length); + if (ret < 0) { + monitor_printf(mon, "dump: failed to write program segment.\n"); + return -1; + } + *offset += block->length; + + return 0; +} + +static int write_elf_notes(Monitor *mon, int fd, int phdr_index, + target_phys_addr_t *offset, bool lma) +{ + CPUState *env; + int ret; + target_phys_addr_t begin = *offset; + Elf64_Phdr phdr; + off_t phdr_offset; + + for (env = first_cpu; env != NULL; env = env->next_cpu) { +#ifdef TARGET_X86_64 + if (lma) { + ret = write_elf64_note(mon, fd, env, offset); + } else { +#endif + ret = write_elf32_note(mon, fd, env, offset); +#ifdef TARGET_X86_64 + } +#endif + + if (ret < 0) { + monitor_printf(mon, "dump: failed to write elf notes.\n"); + return -1; + } + } + + memset(&phdr, 0, sizeof(Elf64_Phdr)); + phdr.p_type = PT_NOTE; + phdr.p_offset = begin; + phdr.p_paddr = 0; + phdr.p_filesz = *offset - begin; + phdr.p_memsz = *offset - begin; + phdr.p_vaddr = 0; + + phdr_offset = sizeof(Elf64_Ehdr); + lseek(fd, phdr_offset, SEEK_SET); + ret = write(fd, &phdr, sizeof(Elf64_Phdr)); + if (ret < 0) { + monitor_printf(mon, "dump: failed to write program header table.\n"); + return -1; + } + + return 0; +} + +static int create_vmcore(Monitor *mon, int fd) +{ + CPUState *env; + target_ulong kernel_base = -1, base_vaddr; + target_phys_addr_t offset; + int phdr_num, phdr_index; + RAMBlock *block; + bool lma = false; + int ret; + + for (env = first_cpu; env != NULL; env = env->next_cpu) { + cpu_synchronize_state(env); + } + +#ifdef TARGET_X86_64 + lma = !!(first_cpu->hflags & HF_LMA_MASK); + if (lma) { + kernel_base = get_phys_base_addr(first_cpu, &base_vaddr); + if (kernel_base == -1) { + monitor_printf(mon, "fd_dump: can not get phys_base\n"); + return -1; + } + } +#endif + + phdr_num = 1; /* PT_NOTE */ + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (lma && kernel_base > block->offset && + kernel_base < (block->offset + block->length)) { + phdr_num++; + } + phdr_num++; + } + + ret = write_elf_header(mon, fd, phdr_num, lma); + if (ret < 0) + return -1; + + phdr_index = 0; + offset = sizeof(Elf64_Ehdr) + sizeof(Elf64_Phdr) * phdr_num; + + ret = write_elf_notes(mon, fd, phdr_index++, &offset, lma); + if (ret < 0) + return -1; + +#ifdef TARGET_X86_64 + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (lma && kernel_base >= block->offset && + kernel_base < (block->offset + block->length)) { + if (kernel_base > block->offset) { + RAMBlock temp_block; + + temp_block.host = block->host + (kernel_base-block->offset); + temp_block.offset = kernel_base; + temp_block.length = block->length - (kernel_base-block->offset); + ret = write_elf_load(mon, fd, &temp_block, phdr_index++, &offset, + base_vaddr); + if (ret < 0) + return -1; + + temp_block.host = block->host; + temp_block.offset = block->offset; + temp_block.length = kernel_base-block->offset; + ret = write_elf_load(mon, fd, &temp_block, phdr_index++, + &offset, 0); + if (ret < 0) + return -1; + } else { + ret = write_elf_load(mon, fd, block, phdr_index++, &offset, + base_vaddr); + if (ret < 0) + return -1; + } + break; + } + } +#endif + + QLIST_FOREACH(block, &ram_list.blocks, next) { + if (lma && kernel_base >= block->offset && + kernel_base < (block->offset + block->length)) { + continue; + } + + ret = write_elf_load(mon, fd, block, phdr_index++, &offset, 0); + if (ret < 0) + return -1; + } + + return 0; +} + +int do_dump(Monitor *mon, const QDict *qdict, QObject **ret_data) +{ + const char *file = qdict_get_str(qdict, "file"); + const char *p; + int fd = -1; + +#if !defined(WIN32) + if (strstart(file, "fd:", &p)) { + fd = monitor_get_fd(mon, p); + if (fd == -1) { + monitor_printf(mon, "fd_dump: invalid file descriptor" + " identifier\n"); + return -1; + } + } +#endif + + if (strstart(file, "file:", &p)) { + fd = open(p, O_WRONLY | O_CREAT | O_TRUNC | O_BINARY); + if (fd < 0) { + monitor_printf(mon, "fd_dump: failed to open %s\n", p); + return -1; + } + } + + if (fd == -1) { + monitor_printf(mon, "unknown dump protocol: %s\n", file); + return -1; + } + + vm_stop(RUN_STATE_PAUSED); + if (create_vmcore(mon, fd) < 0) + return -1; + + return 0; +} + diff --git a/dump.h b/dump.h new file mode 100644 index 0000000..b5d9eb4 --- /dev/null +++ b/dump.h @@ -0,0 +1 @@ +int do_dump(Monitor *mon, const QDict *qdict, QObject **ret_data); diff --git a/hmp-commands.hx b/hmp-commands.hx index 089c1ac..ebbce8c 100644 --- a/hmp-commands.hx +++ b/hmp-commands.hx @@ -772,6 +772,22 @@ Migrate to @var{uri} (using -d to not wait for completion). ETEXI { + .name = "dump", + .args_type = "file:s", + .params = "file", + .help = "dump to file", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_dump, + }, + + +STEXI +@item dump @var{file} +@findex dump +Dump to @var{file}. +ETEXI + + { .name = "migrate_cancel", .args_type = "", .params = "", diff --git a/monitor.c b/monitor.c index 5ea35de..5df35e0 100644 --- a/monitor.c +++ b/monitor.c @@ -73,6 +73,9 @@ #endif #include "hw/lm32_pic.h" +/* for dump */ +#include "dump.h" + //#define DEBUG //#define DEBUG_COMPLETION diff --git a/qmp-commands.hx b/qmp-commands.hx index 97975a5..5cf21c5 100644 --- a/qmp-commands.hx +++ b/qmp-commands.hx @@ -485,6 +485,30 @@ Notes: EQMP { + .name = "dump", + .args_type = "file:s", + .params = "file", + .help = "dump to file", + .user_print = monitor_user_noop, + .mhandler.cmd_new = do_dump, + }, + +SQMP +dump +------- + +Dump to file. + +Arguments: None. + +Example: + +-> { "execute": "dump", "arguments": { "file": "fd:dump" } } +<- { "return": {} } + +EQMP + + { .name = "migrate_cancel", .args_type = "", .params = "", -- 1.7.1