Skip to contentSkip to conversation

introducing a new, dedicated memory dump mechanism

RFC PATCH Superseded Wen Congyang 4 participants 38 messages Mar 2, 2012 – Mar 12, 2012 Kbuild

v8 of 15 Superseded Latest is v15 →

lore
Share & tools
lore
#0 lore raw

v8 cover introducing a new, dedicated memory dump mechanism

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

The last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg04228.html

We have determined to introduce a new command dump to dump memory. The core file's format can be elf.

Note:
1. The guest should be x86 or x86_64. The other arch is not supported now.
2. If you use old gdb, gdb may crash. I use gdb-7.3.1, and it does not crash.
3. If the OS is in the second kernel, gdb may not work well, and crash can work by specifying '--machdep phys_addr=xxx' in the command line. The reason is that the second kernel will update the page table, and we can not get the page table for the first kernel.
4. The cpu's state is stored in QEMU note. You neet to modify crash to use it to calculate phys_base.
5. If the guest OS is 32 bit and the memory size is larger than 4G, the vmcore is elf64 format. You should use the gdb which is built with --enable-64-bit-bfd.
6. This patchset is based on the upstream tree, and apply one patch that is still in Luiz Capitulino's tree, because I use the API qemu_get_fd() in this patchset.

Changes from v7 to v8:
1. addressed Hatayama's comments

Changes from v6 to v7:
1. addressed Jan's comments
2. fix some bugs
3. store cpu's state into the vmcore

Changes from v5 to v6:
1. allow user to dump a fraction of the memory
2. fix some bugs

Changes from v4 to v5:
1. convert the new command dump to QAPI

Changes from v3 to v4:
1. support it to run asynchronously
2. add API to cancel dumping and query dumping progress
3. add API to control dumping speed
4. auto cancel dumping when the user resumes vm, and the status is failed.

Changes from v2 to v3:
1. address Jan Kiszka's comment

Changes from v1 to v2:
1. fix virt addr in the vmcore.

Wen Congyang (16):
Add API to create memory mapping list
Add API to check whether a physical address is I/O address implement cpu_get_memory_mapping()
Add API to check whether paging mode is enabled
Add API to get memory mapping
Add API to get memory mapping without do paging
target-i386: Add API to write elf notes to core file
target-i386: Add API to write cpu status to core file
target-i386: add API to get dump info
make gdb_id() generally avialable
introduce a new monitor command 'dump' to dump guest's memory support to cancel the current dumping
support to query dumping status
run dump at the background
support detached dump
allow user to dump a fraction of the memory

 Makefile.target                   |    3 +
 configure                         |    8 +
 cpu-all.h                         |   66 +++
 cpu-common.h                      |    2 +
 dump.c                            |  980 +++++++++++++++++++++++++++++++++++++
 dump.h                            |   23 +
 elf.h                             |    5 +
 exec.c                            |   11 +
 gdbstub.c                         |    9 -
 gdbstub.h                         |    9 +
 hmp-commands.hx                   |   44 ++
 hmp.c                             |   89 ++++
 hmp.h                             |    3 +
 memory_mapping.c                  |  290 +++++++++++
 memory_mapping.h                  |   60 +++
 monitor.c                         |    7 +
 qapi-schema.json                  |   58 +++
 qmp-commands.hx                   |  110 +++++
 target-i386/arch_dump.c           |  433 ++++++++++++++++
 target-i386/arch_memory_mapping.c |  271 ++++++++++
 vl.c                              |    5 +-
 21 files changed, 2475 insertions(+), 11 deletions(-)
 create mode 100644 dump.c
 create mode 100644 dump.h
 create mode 100644 memory_mapping.c
 create mode 100644 memory_mapping.h
 create mode 100644 target-i386/arch_dump.c
 create mode 100644 target-i386/arch_memory_mapping.c
#1 lore raw

RFC PATCH v8 1/16 Add API to create memory mapping list

The memory mapping list stores virtual address and physical address mapping. The virtual address and physical address are contiguous in the mapping. The folloing patch will use this information to create PT_LOAD in the vmcore.

---
 Makefile.target  |    1 +
 memory_mapping.c |  166 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |   47 +++++++++++++++
 3 files changed, 214 insertions(+), 0 deletions(-)
 create mode 100644 memory_mapping.c
 create mode 100644 memory_mapping.h
Makefile.target +1 -0
index 68a5641..9227e4e 100644
@@ -208,6 +208,7 @@ obj-$(CONFIG_KVM) += kvm.o kvm-all.o
 obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o
+obj-y += memory_mapping.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
memory_mapping.c new file +166 -0

166 lines not on this page · raw message

memory_mapping.h new file +47 -0

47 lines not on this page · raw message

Signature · 1 line
1.7.1
#2 lore raw

RFC PATCH v8 2/16 Add API to check whether a physical address is I/O address

In reply to Wen Congyang

This API will be used in the following patch.

---
 cpu-common.h |    2 ++
 exec.c       |   11 +++++++++++
 2 files changed, 13 insertions(+), 0 deletions(-)
cpu-common.h +2 -0
index a40c57d..fde3e5d 100644
@@ -71,6 +71,8 @@ void cpu_physical_memory_unmap(void *buffer, target_phys_addr_t len,
 void *cpu_register_map_client(void *opaque, void (*callback)(void *opaque));
 void cpu_unregister_map_client(void *cookie);
 
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr);
+
 /* Coalesced MMIO regions are areas where write operations can be reordered.
  * This usually implies that write operations are side-effect free.  This allows
  * batching which can make a major impact on performance when using
exec.c +11 -0
index b81677a..2114dd5 100644
@@ -4435,3 +4435,14 @@ bool virtio_is_big_endian(void)
 #undef env
 
 #endif
+
+bool cpu_physical_memory_is_io(target_phys_addr_t phys_addr)
+{
+    ram_addr_t pd;
+    PhysPageDesc p;
+
+    p = phys_page_find(phys_addr >> TARGET_PAGE_BITS);
+    pd = p.phys_offset;
+
+    return !is_ram_rom_romd(pd);
+}
Signature · 1 line
1.7.1
#3 lore raw

RFC PATCH v8 3/16 implement cpu_get_memory_mapping()

In reply to Wen Congyang

Walk cpu's page table and collect all virtual address and physical address mapping. Then, add these mapping into memory mapping list. If the guest does not use paging, it will do nothing.

---
 Makefile.target                   |    1 +
 configure                         |    4 +
 cpu-all.h                         |   10 ++
 target-i386/arch_memory_mapping.c |  266 +++++++++++++++++++++++++++++++++++++
 4 files changed, 281 insertions(+), 0 deletions(-)
 create mode 100644 target-i386/arch_memory_mapping.c
Makefile.target +1 -0
index 9227e4e..a87e678 100644
@@ -84,6 +84,7 @@ libobj-y += op_helper.o helper.o
 ifeq ($(TARGET_BASE_ARCH), i386)
 libobj-y += cpuid.o
 endif
+libobj-$(CONFIG_HAVE_GET_MEMORY_MAPPING) += arch_memory_mapping.o
 libobj-$(TARGET_SPARC64) += vis_helper.o
 libobj-$(CONFIG_NEED_MMU) += mmu.o
 libobj-$(TARGET_ARM) += neon_helper.o iwmmxt_helper.o
configure +4 -0
index fb0e18e..61821fc 100755
@@ -3643,6 +3643,10 @@ case "$target_arch2" in
       fi
     fi
 esac
+case "$target_arch2" in
+  i386|x86_64)
+    echo "CONFIG_HAVE_GET_MEMORY_MAPPING=y" >> $config_target_mak
+esac
 if test "$target_arch2" = "ppc64" -a "$fdt" = "yes"; then
   echo "CONFIG_PSERIES=y" >> $config_target_mak
 fi
cpu-all.h +10 -0
index e2c3c49..cb72680 100644
@@ -22,6 +22,7 @@
 #include "qemu-common.h"
 #include "qemu-tls.h"
 #include "cpu-common.h"
+#include "memory_mapping.h"
 
 /* some important defines:
  *
@@ -523,4 +524,13 @@ void dump_exec_info(FILE *f, fprintf_function cpu_fprintf);
 int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
                         uint8_t *buf, int len, int is_write);
 
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+int cpu_get_memory_mapping(MemoryMappingList *list, CPUState *env);
+#else
+static inline int cpu_get_memory_mapping(MemoryMappingList *list, CPUState *env)
+{
+    return -1;
+}
+#endif
+
 #endif /* CPU_ALL_H */
target-i386/arch_memory_mapping.c new file +266 -0

266 lines not on this page · raw message

Signature · 1 line
1.7.1
#4 lore raw

RFC PATCH v8 4/16 Add API to check whether paging mode is enabled

In reply to Wen Congyang
---
 cpu-all.h                         |    6 ++++++
 target-i386/arch_memory_mapping.c |    7 ++++++-
 2 files changed, 12 insertions(+), 1 deletions(-)
cpu-all.h +6 -0
index cb72680..01c3c23 100644
@@ -526,11 +526,17 @@ int cpu_memory_rw_debug(CPUState *env, target_ulong addr,
 
 #if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
 int cpu_get_memory_mapping(MemoryMappingList *list, CPUState *env);
+bool cpu_paging_enabled(CPUState *env);
 #else
 static inline int cpu_get_memory_mapping(MemoryMappingList *list, CPUState *env)
 {
     return -1;
 }
+
+static inline bool cpu_paging_enabled(CPUState *env)
+{
+    return true;
+}
 #endif
 
 #endif /* CPU_ALL_H */
target-i386/arch_memory_mapping.c +6 -1
index 10d9b2c..824f293 100644
@@ -233,7 +233,7 @@ static void walk_pml4e(MemoryMappingList *list,
 
 int cpu_get_memory_mapping(MemoryMappingList *list, CPUState *env)
 {
-    if (!(env->cr[0] & CR0_PG_MASK)) {
+    if (!cpu_paging_enabled(env)) {
         /* paging is disabled */
         return 0;
     }
@@ -264,3 +264,8 @@ int cpu_get_memory_mapping(MemoryMappingList *list, CPUState *env)
 
     return 0;
 }
+
+bool cpu_paging_enabled(CPUState *env)
+{
+    return env->cr[0] & CR0_PG_MASK;
+}
Signature · 1 line
1.7.1
#5 lore raw

RFC PATCH v8 5/16 Add API to get memory mapping

In reply to Wen Congyang

Add API to get all virtual address and physical address mapping. If there is no virtual address for some physical address, the virtual address is 0.

---
 memory_mapping.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |    8 +++++
 2 files changed, 96 insertions(+), 0 deletions(-)
memory_mapping.c +88 -0
index 718f271..f74c5d0 100644
@@ -164,3 +164,91 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUState *env;
+    MemoryMapping *memory_mapping;
+    RAMBlock *block;
+    ram_addr_t offset, length, m_length;
+    target_phys_addr_t m_phys_addr;
+    int ret;
+    bool paging_mode;
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+    paging_mode = cpu_paging_enabled(first_cpu);
+    if (paging_mode) {
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+    }
+#else
+    return -2;
+#endif
+
+    /*
+     * some memory may be not in the memory mapping's list:
+     * 1. the guest doesn't use paging
+     * 2. the guest is in 2nd kernel, and the memory used by 1st kernel is not
+     *    in paging table
+     * add them into memory mapping's list
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        offset = block->offset;
+        length = block->length;
+
+        if (!paging_mode) {
+            create_new_memory_mapping(list, offset, offset, length);
+            continue;
+        }
+
+        QTAILQ_FOREACH(memory_mapping, &list->head, next) {
+            m_phys_addr = memory_mapping->phys_addr;
+            m_length = memory_mapping->length;
+
+            if (offset + length <= m_phys_addr) {
+                /*
+                 * memory_mapping's list does not conatin the region
+                 * [offset, offset+length)
+                 */
+                create_new_memory_mapping(list, offset, 0, length);
+                length = 0;
+                break;
+            }
+
+            if (m_phys_addr + m_length <= offset) {
+                continue;
+            }
+
+            if (m_phys_addr > offset) {
+                /*
+                 * memory_mapping's list does not conatin the region
+                 * [offset, memory_mapping->phys_addr)
+                 */
+                create_new_memory_mapping(list, offset, 0,
+                                          m_phys_addr - offset);
+            }
+
+            if (offset + length <= m_phys_addr + m_length) {
+                length = 0;
+                break;
+            }
+
+            length -= m_phys_addr + m_length - offset;
+            offset = m_phys_addr + m_length;
+        }
+
+        if (length > 0) {
+            /*
+             * memory_mapping's list does not conatin the region
+             * [offset, memory_mapping->phys_addr)
+             */
+            create_new_memory_mapping(list, offset, 0, length);
+        }
+    }
+
+    return 0;
+}
memory_mapping.h +8 -0
index 836b047..ebd7cf6 100644
@@ -44,4 +44,12 @@ void memory_mapping_list_free(MemoryMappingList *list);
 
 void memory_mapping_list_init(MemoryMappingList *list);
 
+/*
+ * Return value:
+ *    0: success
+ *   -1: failed
+ *   -2: unsupported
+ */
+int qemu_get_guest_memory_mapping(MemoryMappingList *list);
+
 #endif
Signature · 1 line
1.7.1
#6 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

Quoted 41 lines

Add API to get all virtual address and physical address mapping. If there is no virtual address for some physical address, the virtual address is 0.

---
 memory_mapping.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |    8 +++++
 2 files changed, 96 insertions(+), 0 deletions(-)
memory_mapping.c +23 -0
index 718f271..f74c5d0 100644
@@ -164,3 +164,91 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUState *env;
+    MemoryMapping *memory_mapping;
+    RAMBlock *block;
+    ram_addr_t offset, length, m_length;
+    target_phys_addr_t m_phys_addr;
+    int ret;
+    bool paging_mode;
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+    paging_mode = cpu_paging_enabled(first_cpu);
+    if (paging_mode) {
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+    }
+#else
+    return -2;

memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 199

Quoted 10 lines
memory_mapping.c +10 -0
+#endif
+
+    /*
+     * some memory may be not in the memory mapping's list:
+     * 1. the guest doesn't use paging
+     * 2. the guest is in 2nd kernel, and the memory used by 1st kernel is not
+     *    in paging table
+     * add them into memory mapping's list
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Thanks.
HATAYAMA, Daisuke

#7 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 52 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

Quoted 48 lines

Add API to get all virtual address and physical address mapping. If there is no virtual address for some physical address, the virtual address is 0.

---
 memory_mapping.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |    8 +++++
 2 files changed, 96 insertions(+), 0 deletions(-)
memory_mapping.c +30 -0
index 718f271..f74c5d0 100644
@@ -164,3 +164,91 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUState *env;
+    MemoryMapping *memory_mapping;
+    RAMBlock *block;
+    ram_addr_t offset, length, m_length;
+    target_phys_addr_t m_phys_addr;
+    int ret;
+    bool paging_mode;
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+    paging_mode = cpu_paging_enabled(first_cpu);
+    if (paging_mode) {
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+    }
+#else
+    return -2;
+#endif
+
+    /*
+     * some memory may be not in the memory mapping's list:
+     * 1. the guest doesn't use paging
+     * 2. the guest is in 2nd kernel, and the memory used by 1st kernel is not
+     *    in paging table
Quoted 8 lines

memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 199

Quoted 3 lines
memory_mapping.c +3 -0
+     * add them into memory mapping's list
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

The part is unnecessary if you use gdb. But it is necessary if you use crash.

Thanks
Wen Congyang

Quoted 5 lines

Thanks.
HATAYAMA, Daisuke

#8 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 62 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 52 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

Quoted 48 lines

Add API to get all virtual address and physical address mapping. If there is no virtual address for some physical address, the virtual address is 0.

---
 memory_mapping.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |    8 +++++
 2 files changed, 96 insertions(+), 0 deletions(-)
memory_mapping.c +30 -0
index 718f271..f74c5d0 100644
@@ -164,3 +164,91 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUState *env;
+    MemoryMapping *memory_mapping;
+    RAMBlock *block;
+    ram_addr_t offset, length, m_length;
+    target_phys_addr_t m_phys_addr;
+    int ret;
+    bool paging_mode;
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+    paging_mode = cpu_paging_enabled(first_cpu);
+    if (paging_mode) {
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+    }
+#else
+    return -2;
+#endif
+
+    /*
+     * some memory may be not in the memory mapping's list:
+     * 1. the guest doesn't use paging
+     * 2. the guest is in 2nd kernel, and the memory used by 1st kernel is not
+     *    in paging table
Quoted 8 lines

memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 199

Quoted 3 lines
memory_mapping.c +3 -0
+     * add them into memory mapping's list
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Thanks.
HATAYAMA, Daisuke

#9 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 66 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 62 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 60 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

Quoted 41 lines

Add API to get all virtual address and physical address mapping. If there is no virtual address for some physical address, the virtual address is 0.

---
 memory_mapping.c |   88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 memory_mapping.h |    8 +++++
 2 files changed, 96 insertions(+), 0 deletions(-)
memory_mapping.c +23 -0
index 718f271..f74c5d0 100644
@@ -164,3 +164,91 @@ void memory_mapping_list_init(MemoryMappingList *list)
     list->last_mapping = NULL;
     QTAILQ_INIT(&list->head);
 }
+
+int qemu_get_guest_memory_mapping(MemoryMappingList *list)
+{
+    CPUState *env;
+    MemoryMapping *memory_mapping;
+    RAMBlock *block;
+    ram_addr_t offset, length, m_length;
+    target_phys_addr_t m_phys_addr;
+    int ret;
+    bool paging_mode;
+
+#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING)
+    paging_mode = cpu_paging_enabled(first_cpu);
+    if (paging_mode) {
+        for (env = first_cpu; env != NULL; env = env->next_cpu) {
+            ret = cpu_get_memory_mapping(list, env);
+            if (ret < 0) {
+                return -1;
+            }
+        }
+    }
+#else
+    return -2;

memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 199

Quoted 10 lines
memory_mapping.c +10 -0
+#endif
+
+    /*
+     * some memory may be not in the memory mapping's list:
+     * 1. the guest doesn't use paging
+     * 2. the guest is in 2nd kernel, and the memory used by 1st kernel is not
+     *    in paging table
+     * add them into memory mapping's list
+     */
+    QLIST_FOREACH(block, &ram_list.blocks, next) {

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Thanks
Wen Congyang

Quoted 5 lines

Thanks.
HATAYAMA, Daisuke

#10 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 27 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 1 line
Quoted 8 lines
Quoted 5 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

Thanks.
HATAYAMA, Daisuke

#11 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 37 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 33 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Quoted 6 lines
Quoted 2 lines

Sorry, I donot understand what do you want to say.

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

Thanks
Wen Congyang

Quoted 5 lines

Thanks.
HATAYAMA, Daisuke

#12 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 10:26:56 +0800

Quoted 41 lines

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 40 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 35 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Quoted 8 lines
Quoted 3 lines

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

As I said several times, crash users don't use paging mode. Users of the paging mode is gdb only just as you say. So, the paging path needs to collect part referenced by page table only since the other part is invisible to gdb.

Thanks.
HATAYAMA, Daisuke

#13 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

Quoted 54 lines · HATAYAMA Daisuke

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 10:26:56 +0800

Quoted 41 lines

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 40 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 35 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Quoted 8 lines
Quoted 3 lines

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

Quoted 4 lines

As I said several times, crash users don't use paging mode. Users of the paging mode is gdb only just as you say. So, the paging path needs to collect part referenced by page table only since the other part is invisible to gdb.

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#14 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

At 03/09/2012 05:41 PM, Jan Kiszka Wrote:

Quoted 60 lines · HATAYAMA Daisuke
Quoted 54 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 10:26:56 +0800

Quoted 41 lines

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 40 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 35 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Quoted 8 lines
Quoted 3 lines

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

Quoted 4 lines

As I said several times, crash users don't use paging mode. Users of the paging mode is gdb only just as you say. So, the paging path needs to collect part referenced by page table only since the other part is invisible to gdb.

Quoted 4 lines

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

Thanks
Wen Congyang

Quoted 3 lines

Jan

#15 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

Quoted 61 lines · Wen Congyang

At 03/09/2012 05:41 PM, Jan Kiszka Wrote:

Quoted 60 lines · HATAYAMA Daisuke
Quoted 58 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 10:26:56 +0800

Quoted 41 lines

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 40 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 35 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Quoted 8 lines
Quoted 3 lines

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

As I said several times, crash users don't use paging mode. Users of the paging mode is gdb only just as you say. So, the paging path needs to collect part referenced by page table only since the other part is invisible to gdb.

Quoted 7 lines
Quoted 4 lines

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

And this would be unfortunate if you do not want to use crash for analyzing (I'm working on gdb python scripts which will make gdb - one day - at least as powerful as crash). If paging mode has the same information that non-paging mode has, I would even suggest to drop it.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#16 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

Quoted 5 lines · Jan Kiszka
Quoted 5 lines
Quoted 4 lines

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

Quoted 7 lines
Quoted 2 lines

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

And this would be unfortunate if you do not want to use crash for analyzing (I'm working on gdb python scripts which will make gdb - one day - at least as powerful as crash). If paging mode has the same information that non-paging mode has, I would even suggest to drop it.

Err, with "it" = "non-paging mode".

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#17 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: Jan Kiszka <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 11:06:30 +0100

Quoted 9 lines · Jan Kiszka
Quoted 8 lines
Quoted 7 lines
Quoted 4 lines

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

Quoted 8 lines
Quoted 4 lines

And this would be unfortunate if you do not want to use crash for analyzing (I'm working on gdb python scripts which will make gdb - one day - at least as powerful as crash). If paging mode has the same information that non-paging mode has, I would even suggest to drop it.

Err, with "it" = "non-paging mode".

Jan

Paging at default is not good idea. Performing paging in qemu has risk.

- Guest machine is not always in the state where paging mode is enabled. Also, CR3 doesn't always refer to page table.

- If guest machine is in catastrophic state, its memory data could be corrupted. Then, we cannot trust such corrupted page table.

# In this point, managing PT_LOAD program headers based on such # potencially corruppted data has risk.

The idea of yours that performing paging in debugger side is better than doing in qemu.

Thanks.
HATAYAMA, Daisuke

#18 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

Quoted 18 lines · HATAYAMA Daisuke

From: Jan Kiszka <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 11:06:30 +0100

Quoted 14 lines · Jan Kiszka
Quoted 12 lines
Quoted 7 lines
Quoted 4 lines

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

And this would be unfortunate if you do not want to use crash for analyzing (I'm working on gdb python scripts which will make gdb - one day - at least as powerful as crash). If paging mode has the same information that non-paging mode has, I would even suggest to drop it.

Quoted 8 lines
Quoted 3 lines

Err, with "it" = "non-paging mode".

Jan

Paging at default is not good idea. Performing paging in qemu has risk.

- Guest machine is not always in the state where paging mode is enabled. Also, CR3 doesn't always refer to page table.

That's detectable and means physical == linear address.

Quoted 3 lines

- If guest machine is in catastrophic state, its memory data could be corrupted. Then, we cannot trust such corrupted page table.

OK, here I agree.

Quoted 6 lines

# In this point, managing PT_LOAD program headers based on such # potencially corruppted data has risk.

The idea of yours that performing paging in debugger side is better than doing in qemu.

Another alternative is to add guest-awareness to the dump code. If we detect (or get told) that the target is a Linux kernel, at least the linear kernel mapping can be written reliably.

But also the fact that there can be as many different page tables as active processors means that paging likely needs a second thought and more awareness of the debugger.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#19 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: Jan Kiszka <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 14:24:41 +0100

Quoted 21 lines · HATAYAMA Daisuke
Quoted 20 lines

From: Jan Kiszka <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 11:06:30 +0100

Quoted 16 lines · Jan Kiszka
Quoted 5 lines
Quoted 5 lines
Quoted 4 lines

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

Quoted 7 lines
Quoted 2 lines

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

And this would be unfortunate if you do not want to use crash for analyzing (I'm working on gdb python scripts which will make gdb - one day - at least as powerful as crash). If paging mode has the same information that non-paging mode has, I would even suggest to drop it.

Err, with "it" = "non-paging mode".

Quoted 9 lines
Quoted 6 lines
Quoted 1 line

Jan

Paging at default is not good idea. Performing paging in qemu has risk.

- Guest machine is not always in the state where paging mode is enabled. Also, CR3 doesn't always refer to page table.

That's detectable and means physical == linear address.

CR0 itself is one of the guest's resources. There's still the issue whether to trust CR0 or not.

The assumption behind my idea is the host is running in a good condition but the quest in a bad condition. So we can use qemu dump, which is the host's feature.

Only checking if CR3 refers to page table correctly is considerably complicated. CR3 can have any physical address. There's no hint such as magic number to check it's invalid. So, to check if CR3 correctly points at page table, the only way is to check if we can see the data through actually performing paging for some virtual address. The virtual address would be better if it's more typical one, but it tends to be guest specific, and I think it's not suitable for qemu due to OS dependency.
# Of course, this story is done out of the assumption that the data

# could be corrupted.
Quoted 13 lines
Quoted 3 lines

- If guest machine is in catastrophic state, its memory data could be corrupted. Then, we cannot trust such corrupted page table.

OK, here I agree.

Quoted 6 lines

# In this point, managing PT_LOAD program headers based on such # potencially corruppted data has risk.

The idea of yours that performing paging in debugger side is better than doing in qemu.

Quoted 7 lines

Another alternative is to add guest-awareness to the dump code. If we detect (or get told) that the target is a Linux kernel, at least the linear kernel mapping can be written reliably.

But also the fact that there can be as many different page tables as active processors means that paging likely needs a second thought and more awareness of the debugger.

Also, it seems to me that the lacking feature of gdb used to dumpfile compared with used to running guest is paging only. Paging is a feature in architecture, which is unlikely to change in the future. It's better in maintainability than introducing OS-level dependency.

Thanks.
HATAYAMA, Daisuke

#20 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

From: HATAYAMA Daisuke <[email protected]>
Subject: Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Mon, 12 Mar 2012 15:16:55 +0900 ( )

Quoted 4 lines

The assumption behind my idea is the host is running in a good condition but the quest in a bad condition. So we can use qemu dump, which is the host's feature.

There's also the situation that a guest is running in a good condition and users can recognize that its data is obviously not corrupted. For such situation, it's natural for qemu dump to have paging mode to some amount.

Thanks.
HATAYAMA, Daisuke

#21 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

In reply to Jan Kiszka

At 03/09/2012 06:05 PM, Jan Kiszka Wrote:

Quoted 67 lines · Wen Congyang
Quoted 66 lines

At 03/09/2012 05:41 PM, Jan Kiszka Wrote:

Quoted 64 lines · HATAYAMA Daisuke
Quoted 54 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 10:26:56 +0800

Quoted 41 lines

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 40 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 35 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Quoted 8 lines
Quoted 3 lines

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

Quoted 4 lines

As I said several times, crash users don't use paging mode. Users of the paging mode is gdb only just as you say. So, the paging path needs to collect part referenced by page table only since the other part is invisible to gdb.

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

Quoted 7 lines
Quoted 2 lines

If this logic is not remvoed, crash can work both with and without paging. But the default value is 'off' now, because the option is '-p'.

And this would be unfortunate if you do not want to use crash for analyzing (I'm working on gdb python scripts which will make gdb - one day - at least as powerful as crash). If paging mode has the same information that non-paging mode has, I would even suggest to drop it.

I donot have any knowledge about gdb python scripts. But is it OK to work without virtual address in PT_LOAD?

Thanks
Wen Congyang

Quoted 3 lines

Jan

#22 lore raw

Re: [Qemu-devel] [RFC][PATCH 05/16 v8] Add API to get memory mapping

In reply to HATAYAMA Daisuke
Quoted 54 lines · HATAYAMA Daisuke

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 10:26:56 +0800

Quoted 41 lines

At 03/09/2012 10:05 AM, HATAYAMA Daisuke Wrote:

Quoted 40 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 09 Mar 2012 09:46:31 +0800

Quoted 35 lines

At 03/09/2012 08:40 AM, HATAYAMA Daisuke Wrote:

Quoted 16 lines

From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Thu, 08 Mar 2012 16:52:29 +0800

Quoted 12 lines

At 03/07/2012 11:27 PM, HATAYAMA Daisuke Wrote:

Quoted 10 lines

From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 05/16 v8] Add API to get memory mapping
Date: Fri, 02 Mar 2012 18:18:23 +0800

How does the memory portion referenced by PT_LOAD program headers with p_vaddr == 0 looks through gdb? If we cannot access such portions, part not referenced by the page table CR3 has is unnecessary, isn't it?

Quoted 6 lines
Quoted 2 lines

The part is unnecessary if you use gdb. But it is necessary if you use crash.

crash users would not use paging option because even if without using it, we can see all memory well, so the paging option is only for gdb users.

Yes, the paging option is only for gdb users. The default value if off.

Quoted 6 lines

It looks to me that the latter part only complicates the logic. If instead, collecting virtual addresses only, way of handling PT_LOAD entries become simpler, for example, they no longer need to be physically contiguous in a single entry, and reviewing and maintaince becomes easy.

Sorry, I donot understand what do you want to say.

Quoted 8 lines
Quoted 3 lines

The processing that adds part not referenced by page table to vmcore is meaningless for gdb. crash doesn't require it. So, it only complicates the current logic.

If the paging mode is on, we can also use crash to analyze the vmcore. As the comment methioned, the memory used by the 1st kernel may be not referenced by the page table, so we neet this logic.

Quoted 4 lines

As I said several times, crash users don't use paging mode. Users of the paging mode is gdb only just as you say. So, the paging path needs to collect part referenced by page table only since the other part is invisible to gdb.

If crash can work both with and without paging, it should be default *on* to avoid writing cores that can later on only be analyzed with that tool. Still not sure, though, if that changes the requirement on what memory regions should be written in that mode.

Jan

Signature · 2 lines
Siemens AG, Corporate Technology, CT T DE IT 1
Corporate Competence Center Embedded Linux
#23 lore raw

RFC PATCH v8 6/16 Add API to get memory mapping without doing paging

In reply to Wen Congyang

Get memory mapping with doing paing is for gdb. crash does not need these information.

---
 memory_mapping.c |    9 +++++++++
 memory_mapping.h |    3 +++
 2 files changed, 12 insertions(+), 0 deletions(-)
memory_mapping.c +9 -0
index f74c5d0..7f4193d 100644
@@ -252,3 +252,12 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)
 
     return 0;
 }
+
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
+{
+    RAMBlock *block;
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        create_new_memory_mapping(list, block->offset, 0, block->length);
+    }
+}
memory_mapping.h +3 -0
index ebd7cf6..50b1f25 100644
@@ -52,4 +52,7 @@ void memory_mapping_list_init(MemoryMappingList *list);
  */
 int qemu_get_guest_memory_mapping(MemoryMappingList *list);
 
+/* get guest's memory mapping without do paging(virtual address is 0). */
+void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
+
 #endif
Signature · 1 line
1.7.1
#24 lore raw

RFC PATCH v8 7/16 target-i386: Add API to write elf notes to core file

In reply to Wen Congyang

The core file contains register's value. These APIs write registers to core file, and them will be called in the following patch.

---
 Makefile.target         |    1 +
 configure               |    4 +
 cpu-all.h               |   23 +++++
 target-i386/arch_dump.c |  249 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 277 insertions(+), 0 deletions(-)
 create mode 100644 target-i386/arch_dump.c
Makefile.target +1 -0
index a87e678..cfd3113 100644
@@ -210,6 +210,7 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o
 obj-y += memory_mapping.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
configure +4 -0
index 61821fc..bcbd5d1 100755
@@ -3662,6 +3662,10 @@ if test "$target_softmmu" = "yes" ; then
   if test "$smartcard_nss" = "yes" ; then
     echo "subdir-$target: subdir-libcacard" >> $config_host_mak
   fi
+  case "$target_arch2" in
+    i386|x86_64)
+      echo "CONFIG_HAVE_CORE_DUMP=y" >> $config_target_mak
+  esac
 fi
 if test "$target_user_only" = "yes" ; then
   echo "CONFIG_USER_ONLY=y" >> $config_target_mak
cpu-all.h +23 -0
index 01c3c23..e476401 100644
@@ -539,4 +539,27 @@ static inline bool cpu_paging_enabled(CPUState *env)
 }
 #endif
 
+typedef int (*write_core_dump_function)
+    (target_phys_addr_t offset, void *buf, size_t size, void *opaque);
+#if defined(CONFIG_HAVE_CORE_DUMP)
+int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid,
+                         target_phys_addr_t *offset, void *opaque);
+int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid,
+                         target_phys_addr_t *offset, void *opaque);
+#else
+static inline int cpu_write_elf64_note(write_core_dump_function f,
+                                       CPUState *env, int cpuid,
+                                       target_phys_addr_t *offset, void *opaque)
+{
+    return -1;
+}
+
+static inline int cpu_write_elf32_note(write_core_dump_function f,
+                                       CPUState *env, int cpuid,
+                                       target_phys_addr_t *offset, void *opaque)
+{
+    return -1;
+}
+#endif
+
 #endif /* CPU_ALL_H */
target-i386/arch_dump.c new file +249 -0

249 lines not on this page · raw message

Signature · 1 line
1.7.1
#25 lore raw

RFC PATCH v8 8/16 target-i386: Add API to write cpu status to core file

In reply to Wen Congyang

The core file has register's value. But it does not include all register. Store the cpu status into QEMU note, and the user can get more information from vmcore. If you change QEMUCPUState, please count up QEMUCPUSTATE_VERSION.

---
 cpu-all.h               |   20 ++++++
 target-i386/arch_dump.c |  150 +++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 170 insertions(+), 0 deletions(-)
cpu-all.h +20 -0
index e476401..6c36d73 100644
@@ -546,6 +546,10 @@ int cpu_write_elf64_note(write_core_dump_function f, CPUState *env, int cpuid,
                          target_phys_addr_t *offset, void *opaque);
 int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid,
                          target_phys_addr_t *offset, void *opaque);
+int cpu_write_elf64_qemunote(write_core_dump_function f, CPUState *env,
+                             target_phys_addr_t *offset, void *opaque);
+int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env,
+                             target_phys_addr_t *offset, void *opaque);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUState *env, int cpuid,
@@ -560,6 +564,22 @@ static inline int cpu_write_elf32_note(write_core_dump_function f,
 {
     return -1;
 }
+
+static inline int cpu_write_elf64_qemunote(write_core_dump_function f,
+                                           CPUState *env,
+                                           target_phys_addr_t *offset,
+                                           void *opaque);
+{
+    return -1;
+}
+
+static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
+                                           CPUState *env,
+                                           target_phys_addr_t *offset,
+                                           void *opaque)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
target-i386/arch_dump.c +150 -0

153 lines not on this page · raw message

Signature · 1 line
1.7.1
#26 lore raw

RFC PATCH v8 9/16 target-i386: add API to get dump info

In reply to Wen Congyang

Dump info contains: endian, class and architecture. The next patch will use these information to create vmcore.

---
 cpu-all.h               |    7 +++++++
 dump.h                  |   23 +++++++++++++++++++++++
 target-i386/arch_dump.c |   34 ++++++++++++++++++++++++++++++++++
 3 files changed, 64 insertions(+), 0 deletions(-)
 create mode 100644 dump.h
cpu-all.h +7 -0
index 6c36d73..a8566a9 100644
@@ -23,6 +23,7 @@
 #include "qemu-tls.h"
 #include "cpu-common.h"
 #include "memory_mapping.h"
+#include "dump.h"
 
 /* some important defines:
  *
@@ -550,6 +551,7 @@ int cpu_write_elf64_qemunote(write_core_dump_function f, CPUState *env,
                              target_phys_addr_t *offset, void *opaque);
 int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env,
                              target_phys_addr_t *offset, void *opaque);
+int cpu_get_dump_info(ArchDumpInfo *info);
 #else
 static inline int cpu_write_elf64_note(write_core_dump_function f,
                                        CPUState *env, int cpuid,
@@ -580,6 +582,11 @@ static inline int cpu_write_elf32_qemunote(write_core_dump_function f,
 {
     return -1;
 }
+
+static inline int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    return -1;
+}
 #endif
 
 #endif /* CPU_ALL_H */
dump.h new file +23 -0
new file mode 100644
index 0000000..28340cf
@@ -0,0 +1,23 @@
+/*
+ * QEMU dump
+ *
+ * Copyright Fujitsu, Corp. 2011, 2012
+ *
+ * Authors:
+ *     Wen Congyang <[email protected]>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2. See
+ * the COPYING file in the top-level directory.
+ *
+ */
+
+#ifndef DUMP_H
+#define DUMP_H
+
+typedef struct ArchDumpInfo {
+    int d_machine;  /* Architecture */
+    int d_endian;   /* ELFDATA2LSB or ELFDATA2MSB */
+    int d_class;    /* ELFCLASS32 or ELFCLASS64 */
+} ArchDumpInfo;
+
+#endif
target-i386/arch_dump.c +34 -0
index 274bbec..1518df7 100644
@@ -13,6 +13,7 @@
 
 #include "cpu.h"
 #include "cpu-all.h"
+#include "dump.h"
 #include "elf.h"
 
 #ifdef TARGET_X86_64
@@ -397,3 +398,36 @@ int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env,
 {
     return cpu_write_qemu_note(f, env, offset, opaque, 0);
 }
+
+int cpu_get_dump_info(ArchDumpInfo *info)
+{
+    bool lma = false;
+    RAMBlock *block;
+
+#ifdef TARGET_X86_64
+    lma = !!(first_cpu->hflags & HF_LMA_MASK);
+#endif
+
+    if (lma) {
+        info->d_machine = EM_X86_64;
+    } else {
+        info->d_machine = EM_386;
+    }
+    info->d_endian = ELFDATA2LSB;
+
+    if (lma) {
+        info->d_class = ELFCLASS64;
+    } else {
+        info->d_class = ELFCLASS32;
+
+        QLIST_FOREACH(block, &ram_list.blocks, next) {
+            if (block->offset + block->length > UINT_MAX) {
+                /* The memory size is greater than 4G */
+                info->d_class = ELFCLASS64;
+                break;
+            }
+        }
+    }
+
+    return 0;
+}
Signature · 1 line
1.7.1
#27 lore raw

RFC PATCH v8 10/16 make gdb_id() generally avialable

In reply to Wen Congyang

The following patch also needs this API, so make it generally avialable

---
 gdbstub.c |    9 ---------
 gdbstub.h |    9 +++++++++
 2 files changed, 9 insertions(+), 9 deletions(-)
gdbstub.c +0 -9
index 7d470b6..046b036 100644
@@ -1939,15 +1939,6 @@ static void gdb_set_cpu_pc(GDBState *s, target_ulong pc)
 #endif
 }
 
-static inline int gdb_id(CPUState *env)
-{
-#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
-    return env->host_tid;
-#else
-    return env->cpu_index + 1;
-#endif
-}
-
 static CPUState *find_cpu(uint32_t thread_id)
 {
     CPUState *env;
gdbstub.h +9 -0
index d82334f..f30bfe8 100644
@@ -30,6 +30,15 @@ void gdb_register_coprocessor(CPUState *env,
                               gdb_reg_cb get_reg, gdb_reg_cb set_reg,
                               int num_regs, const char *xml, int g_pos);
 
+static inline int gdb_id(CPUState *env)
+{
+#if defined(CONFIG_USER_ONLY) && defined(CONFIG_USE_NPTL)
+    return env->host_tid;
+#else
+    return env->cpu_index + 1;
+#endif
+}
+
 #endif
 
 #ifdef CONFIG_USER_ONLY
Signature · 1 line
1.7.1
#28 lore raw

RFC PATCH v8 11/16 introduce a new monitor command 'dump' to dump guest's memory

In reply to Wen Congyang

The command's usage:
dump [-p] file
file should be start with "file:"(the file's path) or "fd:"(the fd's name). If you want to use gdb to analyse the core, please specify -p option.

---
 Makefile.target  |    2 +-
 dump.c           |  714 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 elf.h            |    5 +
 hmp-commands.hx  |   21 ++
 hmp.c            |   10 +
 hmp.h            |    1 +
 qapi-schema.json |   14 +
 qmp-commands.hx  |   34 +++
 8 files changed, 800 insertions(+), 1 deletions(-)
 create mode 100644 dump.c
Makefile.target +1 -1
index cfd3113..4ae59f5 100644
@@ -210,7 +210,7 @@ obj-$(CONFIG_NO_KVM) += kvm-stub.o
 obj-$(CONFIG_VGA) += vga.o
 obj-y += memory.o savevm.o
 obj-y += memory_mapping.o
-obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o
+obj-$(CONFIG_HAVE_CORE_DUMP) += arch_dump.o dump.o
 LIBS+=-lz
 
 obj-i386-$(CONFIG_KVM) += hyperv.o
dump.c new file +714 -0

714 lines not on this page · raw message

elf.h +5 -0
index 2e05d34..6a10657 100644
@@ -1000,6 +1000,11 @@ typedef struct elf64_sym {
 
 #define EI_NIDENT	16
 
+/* Special value for e_phnum.  This indicates that the real number of
+   program headers is too large to fit into e_phnum.  Instead the real
+   value is in the field sh_info of section 0.  */
+#define PN_XNUM         0xffff
+
 typedef struct elf32_hdr{
   unsigned char	e_ident[EI_NIDENT];
   Elf32_Half	e_type;
hmp-commands.hx +21 -0
index 64b3656..9a1e696 100644
@@ -880,6 +880,27 @@ server will ask the spice/vnc client to automatically reconnect using the
 new parameters (if specified) once the vm migration finished successfully.
 ETEXI
 
+#if defined(CONFIG_HAVE_CORE_DUMP)
+    {
+        .name       = "dump",
+        .args_type  = "paging:-p,file:s",
+        .params     = "[-p] file",
+        .help       = "dump to file",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd = hmp_dump,
+    },
+
+
+STEXI
+@item dump [-p] @var{file}
+@findex dump
+Dump to @var{file}. The file can be processed with crash or gdb.
+    file: destination file(started with "file:") or destination file descriptor
+          (started with "fd:")
+  paging: do paging to get guest's memory mapping
+ETEXI
+#endif
+
     {
         .name       = "snapshot_blkdev",
         .args_type  = "device:B,snapshot-file:s?,format:s?",
hmp.c +10 -0
index 3a54455..a27f6c5 100644
@@ -856,3 +856,13 @@ void hmp_block_job_cancel(Monitor *mon, const QDict *qdict)
 
     hmp_handle_error(mon, &error);
 }
+
+void hmp_dump(Monitor *mon, const QDict *qdict)
+{
+    Error *errp = NULL;
+    int paging = qdict_get_try_bool(qdict, "paging", 0);
+    const char *file = qdict_get_str(qdict, "file");
+
+    qmp_dump(!!paging, file, &errp);
+    hmp_handle_error(mon, &errp);
+}
hmp.h +1 -0
index 5409464..b055e50 100644
@@ -59,5 +59,6 @@ void hmp_block_set_io_throttle(Monitor *mon, const QDict *qdict);
 void hmp_block_stream(Monitor *mon, const QDict *qdict);
 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
+void hmp_dump(Monitor *mon, const QDict *qdict);
 
 #endif
qapi-schema.json +14 -0
index 5f293c4..8b51b1d 100644
@@ -1631,3 +1631,17 @@
 { 'command': 'qom-list-types',
   'data': { '*implements': 'str', '*abstract': 'bool' },
   'returns': [ 'ObjectTypeInfo' ] }
+
+##
+# @dump
+#
+# Dump guest's memory to vmcore.
+#
+# @paging: if true, do paging to get guest's memory mapping
+# @file: the filename or file descriptor of the vmcore.
+#
+# Returns: nothing on success
+#
+# Since: 1.1
+##
+{ 'command': 'dump', 'data': { 'paging': 'bool', 'file': 'str' } }
qmp-commands.hx +34 -0
index 0c9bfac..c877987 100644
@@ -586,6 +586,40 @@ Example:
 
 EQMP
 
+#if defined(CONFIG_HAVE_CORE_DUMP)
+    {
+        .name       = "dump",
+        .args_type  = "paging:-p,file:s",
+        .params     = "[-p] file",
+        .help       = "dump to file",
+        .user_print = monitor_user_noop,
+        .mhandler.cmd_new = qmp_marshal_input_dump,
+    },
+
+SQMP
+dump
+
+
+Dump to file. The file can be processed with crash or gdb.
+
+Arguments:
+
+- "paging": do paging to get guest's memory mapping (json-bool)
+- "file": destination file(started with "file:") or destination file descriptor
+          (started with "fd:") (json-string)
+
+Example:
+
+-> { "execute": "dump", "arguments": { "file": "fd:dump" } }
+<- { "return": {} }
+
+Notes:
+
+(1) All boolean arguments default to false
+
+EQMP
+#endif
+
     {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
Signature · 1 line
1.7.1
#29 lore raw

RFC PATCH v8 12/16 support to cancel the current dumping

In reply to Wen Congyang

Add API to allow the user to cancel the current dumping.

---
 dump.c           |   12 ++++++++++++
 hmp-commands.hx  |   14 ++++++++++++++
 hmp.c            |    5 +++++
 hmp.h            |    1 +
 qapi-schema.json |   13 +++++++++++++
 qmp-commands.hx  |   21 +++++++++++++++++++++
 6 files changed, 66 insertions(+), 0 deletions(-)
dump.c +12 -0
index 42e1681..dab0c84 100644
@@ -712,3 +712,15 @@ void qmp_dump(bool paging, const char *file, Error **errp)
         error_set(errp, QERR_IO_ERROR);
     }
 }
+
+void qmp_dump_cancel(Error **errp)
+{
+    DumpState *s = dump_get_current();
+
+    if (s->state != DUMP_STATE_ACTIVE) {
+        return;
+    }
+
+    s->state = DUMP_STATE_CANCELLED;
+    dump_cleanup(s);
+}
hmp-commands.hx +14 -0
index 9a1e696..63193ec 100644
@@ -902,6 +902,20 @@ ETEXI
 #endif
 
     {
+        .name       = "dump_cancel",
+        .args_type  = "",
+        .params     = "",
+        .help       = "cancel the current VM dumping",
+        .mhandler.cmd = hmp_dump_cancel,
+    },
+
+STEXI
+@item dump_cancel
+@findex dump_cancel
+Cancel the current VM dumping.
+ETEXI
+
+    {
         .name       = "snapshot_blkdev",
         .args_type  = "device:B,snapshot-file:s?,format:s?",
         .params     = "device [new-image-file] [format]",
hmp.c +5 -0
index a27f6c5..d427e49 100644
@@ -866,3 +866,8 @@ void hmp_dump(Monitor *mon, const QDict *qdict)
     qmp_dump(!!paging, file, &errp);
     hmp_handle_error(mon, &errp);
 }
+
+void hmp_dump_cancel(Monitor *mon, const QDict *qdict)
+{
+    qmp_dump_cancel(NULL);
+}
hmp.h +1 -0
index b055e50..75c6c1d 100644
@@ -60,5 +60,6 @@ void hmp_block_stream(Monitor *mon, const QDict *qdict);
 void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
 void hmp_dump(Monitor *mon, const QDict *qdict);
+void hmp_dump_cancel(Monitor *mon, const QDict *qdict);
 
 #endif
qapi-schema.json +13 -0
index 8b51b1d..d40ba69 100644
@@ -1645,3 +1645,16 @@
 # Since: 1.1
 ##
 { 'command': 'dump', 'data': { 'paging': 'bool', 'file': 'str' } }
+
+##
+# @dump_cancel
+#
+# Cancel the current executing dumping process.
+#
+# Returns: nothing on success
+#
+# Notes: This command succeeds even if there is no dumping process running.
+#
+# Since: 1.1
+##
+{ 'command': 'dump_cancel' }
qmp-commands.hx +21 -0
index c877987..1b36262 100644
@@ -621,6 +621,27 @@ EQMP
 #endif
 
     {
+        .name       = "dump_cancel",
+        .args_type  = "",
+        .mhandler.cmd_new = qmp_marshal_input_dump_cancel,
+    },
+
+SQMP
+dump_cancel
+
+
+Cancel the current dumping.
+
+Arguments: None.
+
+Example:
+
+-> { "execute": "dump_cancel" }
+<- { "return": {} }
+
+EQMP
+
+    {
         .name       = "netdev_add",
         .args_type  = "netdev:O",
         .params     = "[user|tap|socket],id=str[,prop=value][,...]",
Signature · 1 line
1.7.1
#30 lore raw

RFC PATCH v8 13/16 support to query dumping status

In reply to Wen Congyang

Add API to allow the user to query dumping status.

---
 dump.c           |   32 ++++++++++++++++++++++++++++++++
 hmp-commands.hx  |    2 ++
 hmp.c            |   17 +++++++++++++++++
 hmp.h            |    1 +
 monitor.c        |    7 +++++++
 qapi-schema.json |   26 ++++++++++++++++++++++++++
 qmp-commands.hx  |   49 +++++++++++++++++++++++++++++++++++++++++++++++++
 7 files changed, 134 insertions(+), 0 deletions(-)
dump.c +32 -0
index dab0c84..d569867 100644
@@ -724,3 +724,35 @@ void qmp_dump_cancel(Error **errp)
     s->state = DUMP_STATE_CANCELLED;
     dump_cleanup(s);
 }
+
+DumpInfo *qmp_query_dump(Error **errp)
+{
+    DumpInfo *info = g_malloc0(sizeof(*info));
+    DumpState *s = dump_get_current();
+
+    switch (s->state) {
+    case DUMP_STATE_SETUP:
+        /* no migration has happened ever */
+        break;
+    case DUMP_STATE_ACTIVE:
+        info->has_status = true;
+        info->status = g_strdup("active");
+        break;
+    case DUMP_STATE_COMPLETED:
+        info->has_status = true;
+        info->status = g_strdup("completed");
+        break;
+    case DUMP_STATE_ERROR:
+        info->has_status = true;
+        info->status = g_strdup("failed");
+        info->has_error = true;
+        info->error = g_strdup(s->error);
+        break;
+    case DUMP_STATE_CANCELLED:
+        info->has_status = true;
+        info->status = g_strdup("cancelled");
+        break;
+    }
+
+    return info;
+}
hmp-commands.hx +2 -0
index 63193ec..b936bb7 100644
@@ -1435,6 +1435,8 @@ show device tree
 show qdev device model list
 @item info roms
 show roms
+@item info dump
+show dumping status
 @end table
 ETEXI
 
hmp.c +17 -0
index d427e49..81dd23d 100644
@@ -871,3 +871,20 @@ void hmp_dump_cancel(Monitor *mon, const QDict *qdict)
 {
     qmp_dump_cancel(NULL);
 }
+
+void hmp_info_dump(Monitor *mon)
+{
+    DumpInfo *info;
+
+    info = qmp_query_dump(NULL);
+
+    if (info->has_status) {
+        monitor_printf(mon, "Dumping status: %s\n", info->status);
+    }
+
+    if (info->has_error) {
+        monitor_printf(mon, "Dumping failed reason: %s\n", info->error);
+    }
+
+    qapi_free_DumpInfo(info);
+}
hmp.h +1 -0
index 75c6c1d..3d105a9 100644
@@ -61,5 +61,6 @@ void hmp_block_job_set_speed(Monitor *mon, const QDict *qdict);
 void hmp_block_job_cancel(Monitor *mon, const QDict *qdict);
 void hmp_dump(Monitor *mon, const QDict *qdict);
 void hmp_dump_cancel(Monitor *mon, const QDict *qdict);
+void hmp_info_dump(Monitor *mon);
 
 #endif
monitor.c +7 -0
index 96af5e0..f240895 100644
@@ -2603,6 +2603,13 @@ static mon_cmd_t info_cmds[] = {
         .mhandler.info = do_trace_print_events,
     },
     {
+        .name       = "dump",
+        .args_type  = "",
+        .params     = "",
+        .help       = "show dumping status",
+        .mhandler.info = hmp_info_dump,
+    },
+    {
         .name       = NULL,
     },
 };
qapi-schema.json +26 -0
index d40ba69..41428ed 100644
@@ -1658,3 +1658,29 @@
 # Since: 1.1
 ##
 { 'command': 'dump_cancel' }
+
+##
+# @DumpInfo
+#
+# Information about current migration process.
+#
+# @status: #optional string describing the current dumping status.
+#          As of 1,1 this can be 'active', 'completed', 'failed' or
+#          'cancelled'. If this field is not returned, no migration process
+#          has been initiated
+#
+# Since: 1.1
+##
+{ 'type': 'DumpInfo',
+  'data': { '*status': 'str', '*error': 'str' } }
+
+##
+# @query-dump
+#
+# Returns information about current dumping process.
+#
+# Returns: @DumpInfo
+#
+# Since: 1.1
+##
+{ 'command': 'query-dump', 'returns': 'DumpInfo' }
qmp-commands.hx +49 -0

61 lines not on this page · raw message

Signature · 1 line
1.7.1
#31 lore raw

RFC PATCH v8 14/16 run dump at the background

In reply to Wen Congyang

The new monitor command dump may take long time to finish. So we need run it at the background.

---
 dump.c |  168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------
 vl.c   |    5 +-
 2 files changed, 150 insertions(+), 23 deletions(-)
dump.c +147 -21
index d569867..4c8038d 100644
@@ -80,9 +80,21 @@ typedef struct DumpState {
     bool resume;
     char *error;
     target_phys_addr_t memory_offset;
+
+    /*
+     * Return value:
+     * -2: EAGAIN
+     * -1: error
+     *  0: success
+     */
     write_core_dump_function f;
     void (*cleanup)(void *opaque);
+    int (*dump_begin_iterate)(struct DumpState *, void *opaque);
     void *opaque;
+    RAMBlock *block;
+    ram_addr_t start;
+    target_phys_addr_t offset;
+    VMChangeStateEntry *handler;
 } DumpState;
 
 static DumpState *dump_get_current(void)
@@ -100,6 +112,12 @@ static int dump_cleanup(DumpState *s)
 
     memory_mapping_list_free(&s->list);
     s->cleanup(s->opaque);
+
+    if (s->handler) {
+        qemu_del_vm_change_state_handler(s->handler);
+        s->handler = NULL;
+    }
+
     if (s->resume) {
         vm_start();
     }
@@ -373,40 +391,70 @@ static int write_elf_section(DumpState *s, target_phys_addr_t *offset, int type)
     return 0;
 }
 
+/*
+ * Return value:
+ *     -2: blocked
+ *     -1: failed
+ *      0: sucess
+ */
 static int write_data(DumpState *s, void *buf, int length,
                       target_phys_addr_t *offset)
 {
     int ret;
 
     ret = s->f(*offset, buf, length, s->opaque);
-    if (ret < 0) {
+    if (ret == -1) {
         dump_error(s, "dump: failed to save memory.\n");
         return -1;
     }
 
+    if (ret == -2) {
+        return -2;
+    }
+
     *offset += length;
     return 0;
 }
 
 /* write the memroy to vmcore. 1 page per I/O. */
-static int write_memory(DumpState *s, RAMBlock *block,
-                        target_phys_addr_t *offset)
+static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
+                        target_phys_addr_t *offset, int64_t *size,
+                        int64_t deadline)
 {
     int i, ret;
+    int64_t writen_size = 0;
+    int64_t time;
 
-    for (i = 0; i < block->length / TARGET_PAGE_SIZE; i++) {
-        ret = write_data(s, block->host + i * TARGET_PAGE_SIZE,
+    *size = block->length - start;
+    for (i = 0; i < *size / TARGET_PAGE_SIZE; i++) {
+        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
                          TARGET_PAGE_SIZE, offset);
         if (ret < 0) {
-            return -1;
+            *size = writen_size;
+            return ret;
+        }
+
+        writen_size += TARGET_PAGE_SIZE;
+        time = qemu_get_clock_ms(rt_clock);
+        if (time >= deadline) {
+            /* time out */
+            *size = writen_size;
+            return -2;
         }
     }
 
-    if ((block->length % TARGET_PAGE_SIZE) != 0) {
-        ret = write_data(s, block->host + i * TARGET_PAGE_SIZE,
-                         block->length % TARGET_PAGE_SIZE, offset);
+    if ((*size % TARGET_PAGE_SIZE) != 0) {
+        ret = write_data(s, block->host + start + i * TARGET_PAGE_SIZE,
+                         *size % TARGET_PAGE_SIZE, offset);
         if (ret < 0) {
-            return -1;
+            *size = writen_size;
+            return ret;
+        }
+
+        time = qemu_get_clock_ms(rt_clock);
+        if (time >= deadline) {
+            /* time out */
+            return -2;
         }
     }
 
@@ -501,6 +549,7 @@ static int dump_begin(DumpState *s)
     }
 
     s->memory_offset = offset;
+    s->offset = offset;
     return 0;
 }
 
@@ -528,22 +577,65 @@ static int dump_completed(DumpState *s)
     return 0;
 }
 
-/* write all memory to vmcore */
-static int dump_iterate(DumpState *s)
+static int get_next_block(DumpState *s, RAMBlock *block)
+{
+    while (1) {
+        block = QLIST_NEXT(block, next);
+        if (!block) {
+            /* no more block */
+            return 1;
+        }
+
+        s->start = 0;
+        s->block = block;
+
+        return 0;
+    }
+}
+
+/* write memory to vmcore */
+static void dump_iterate(void *opaque)
 {
+    DumpState *s = opaque;
     RAMBlock *block;
-    target_phys_addr_t offset = s->memory_offset;
+    target_phys_addr_t offset = s->offset;
+    int64_t size;
+    int64_t deadline, now;
     int ret;
 
-    /* write all memory to vmcore */
-    QLIST_FOREACH(block, &ram_list.blocks, next) {
-        ret = write_memory(s, block, &offset);
-        if (ret < 0) {
-            return -1;
+    now = qemu_get_clock_ms(rt_clock);
+    deadline = now + 5;
+    while(1) {
+        block = s->block;
+        ret = write_memory(s, block, s->start, &offset, &size, deadline);
+        if (ret == -1) {
+            return;
+        }
+
+        if (ret == -2) {
+            break;
+        }
+
+        ret = get_next_block(s, block);
+        if (ret == 1) {
+            dump_completed(s);
+            return;
         }
     }
 
-    return dump_completed(s);
+    if (size == block->length - s->start) {
+        ret = get_next_block(s, block);
+        if (ret == 1) {
+            dump_completed(s);
+            return;
+        }
+    } else {
+        s->start += size;
+    }
+
+    s->offset = offset;
+
+    return;
 }
 
 static int create_vmcore(DumpState *s)
@@ -555,7 +647,7 @@ static int create_vmcore(DumpState *s)
         return -1;
     }
 
-    ret = dump_iterate(s);
+    ret = s->dump_begin_iterate(s, s->opaque);
     if (ret < 0) {
         return -1;
     }
@@ -563,6 +655,17 @@ static int create_vmcore(DumpState *s)
     return 0;
 }
 
+static void dump_vm_state_change(void *opaque, int running, RunState state)
+{
+    DumpState *s = opaque;
+
+    if (running) {
+        qmp_dump_cancel(NULL);
+        s->state = DUMP_STATE_ERROR;
+        s->error = g_strdup("vm state is changed to run\n");
+    }
+}
+
 static DumpState *dump_init(bool paging, Error **errp)
 {
     CPUState *env;
@@ -580,6 +683,9 @@ static DumpState *dump_init(bool paging, Error **errp)
         g_free(s->error);
         s->error = NULL;
     }
+    s->block = QLIST_FIRST(&ram_list.blocks);
+    s->start = 0;
+    s->handler = qemu_add_vm_change_state_handler(dump_vm_state_change, s);
 
     /*
      * get dump info: endian, class and architecture.
@@ -639,14 +745,24 @@ static int fd_write_vmcore(target_phys_addr_t offset, void *buf, size_t size,
 
     ret = lseek(fd, offset, SEEK_SET);
     if (ret < 0) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            return -2;
+        }
         return -1;
     }
 
     ret = write(fd, buf, size);
-    if (ret != size) {
+    if (ret < 0) {
+        if (errno == EAGAIN || errno == EWOULDBLOCK) {
+            return -2;
+        }
         return -1;
     }
 
+    if (ret != size) {
+        return -2;
+    }
+
     return 0;
 }
 
@@ -655,10 +771,18 @@ static void fd_cleanup(void *opaque)
     int fd = (int)(intptr_t)opaque;
 
     if (fd != -1) {
+        qemu_set_fd_handler(fd, NULL, NULL, NULL);
         close(fd);
     }
 }
 
+static int fd_dump_begin_iterate(DumpState *s, void *opaque)
+{
+    int fd = (int)(intptr_t)opaque;
+
+    return qemu_set_fd_handler(fd, NULL, dump_iterate, s);
+}
+
 static DumpState *dump_init_fd(int fd, bool paging, Error **errp)
 {
     DumpState *s = dump_init(paging, errp);
@@ -669,7 +793,9 @@ static DumpState *dump_init_fd(int fd, bool paging, Error **errp)
 
     s->f = fd_write_vmcore;
     s->cleanup = fd_cleanup;
+    s->dump_begin_iterate = fd_dump_begin_iterate;
     s->opaque = (void *)(intptr_t)fd;
+    fcntl(fd, F_SETFL, O_NONBLOCK);
 
     return s;
 }
vl.c +3 -2
index 4a77696..0f31906 100644
@@ -1249,11 +1249,12 @@ void qemu_del_vm_change_state_handler(VMChangeStateEntry *e)
 
 void vm_state_notify(int running, RunState state)
 {
-    VMChangeStateEntry *e;
+    VMChangeStateEntry *e, *next;
 
     trace_vm_state_notify(running, state);
 
-    for (e = vm_change_state_head.lh_first; e; e = e->entries.le_next) {
+    /* e->cb() may remove itself */
+    QLIST_FOREACH_SAFE(e, &vm_change_state_head, entries, next) {
         e->cb(e->opaque, running, state);
     }
 }
Signature · 1 line
1.7.1
#32 lore raw

RFC PATCH v8 15/16 support detached dump

In reply to Wen Congyang

Let the user to choose whether to block other monitor command while dumping.

---
 dump.c           |    2 +-
 hmp-commands.hx  |    9 +++++----
 hmp.c            |   49 +++++++++++++++++++++++++++++++++++++++++++++++--
 qapi-schema.json |    4 +++-
 qmp-commands.hx  |    6 ++++--
 5 files changed, 60 insertions(+), 10 deletions(-)
dump.c +1 -1
index 4c8038d..40eefb9 100644
@@ -800,7 +800,7 @@ static DumpState *dump_init_fd(int fd, bool paging, Error **errp)
     return s;
 }
 
-void qmp_dump(bool paging, const char *file, Error **errp)
+void qmp_dump(bool detach, bool paging, const char *file, Error **errp)
 {
     const char *p;
     int fd = -1;
hmp-commands.hx +5 -4
index b936bb7..fd6f9f1 100644
@@ -883,21 +883,22 @@ ETEXI
 #if defined(CONFIG_HAVE_CORE_DUMP)
     {
         .name       = "dump",
-        .args_type  = "paging:-p,file:s",
-        .params     = "[-p] file",
-        .help       = "dump to file",
+        .args_type  = "detach:-d,paging:-p,file:s",
+        .params     = "[-d] [-p] file",
+        .help       = "dump to file (using -d to not wait for completion)",
         .user_print = monitor_user_noop,
         .mhandler.cmd = hmp_dump,
     },
 
 
 STEXI
-@item dump [-p] @var{file}
+@item dump [-d] [-p] @var{file}
 @findex dump
 Dump to @var{file}. The file can be processed with crash or gdb.
     file: destination file(started with "file:") or destination file descriptor
           (started with "fd:")
   paging: do paging to get guest's memory mapping
+      -d: donot wait for completion.
 ETEXI
 #endif
 
hmp.c +47 -2

61 lines not on this page · raw message

qapi-schema.json +3 -1
index 41428ed..bd258cb 100644
@@ -1637,6 +1637,7 @@
 #
 # Dump guest's memory to vmcore.
 #
+# @detach: detached dumping.
 # @paging: if true, do paging to get guest's memory mapping
 # @file: the filename or file descriptor of the vmcore.
 #
@@ -1644,7 +1645,8 @@
 #
 # Since: 1.1
 ##
-{ 'command': 'dump', 'data': { 'paging': 'bool', 'file': 'str' } }
+{ 'command': 'dump',
+  'data': { 'detach': 'bool', 'paging': 'bool', 'file': 'str' } }
 
 ##
 # @dump_cancel
qmp-commands.hx +4 -2
index c532561..e2accb2 100644
@@ -589,8 +589,8 @@ EQMP
 #if defined(CONFIG_HAVE_CORE_DUMP)
     {
         .name       = "dump",
-        .args_type  = "paging:-p,file:s",
-        .params     = "[-p] file",
+        .args_type  = "detach:-d,paging:-p,file:s",
+        .params     = "[-d] [-p] file",
         .help       = "dump to file",
         .user_print = monitor_user_noop,
         .mhandler.cmd_new = qmp_marshal_input_dump,
@@ -618,6 +618,8 @@ Notes:
 (1) All boolean arguments default to false
 (2) The 'info dump' command should be used to check dumping's progress
     and final result (this information is provided by the 'status' member)
+(3) The user Monitor's "detach" argument is invalid in QMP and should not
+    be used
 
 EQMP
 #endif
Signature · 1 line
1.7.1
#33 lore raw

RFC PATCH v8 16/16 allow user to dump a fraction of the memory

In reply to Wen Congyang
---
 dump.c           |  124 +++++++++++++++++++++++++++++++++++++++++++++++------
 hmp-commands.hx  |   14 ++++--
 hmp.c            |   14 ++++++-
 memory_mapping.c |   27 ++++++++++++
 memory_mapping.h |    2 +
 qapi-schema.json |    5 ++-
 qmp-commands.hx  |    8 +++-
 7 files changed, 172 insertions(+), 22 deletions(-)
dump.c +110 -14
index 40eefb9..52df041 100644
@@ -93,6 +93,9 @@ typedef struct DumpState {
     void *opaque;
     RAMBlock *block;
     ram_addr_t start;
+    bool has_filter;
+    int64_t begin;
+    int64_t length;
     target_phys_addr_t offset;
     VMChangeStateEntry *handler;
 } DumpState;
@@ -463,17 +466,47 @@ static int write_memory(DumpState *s, RAMBlock *block, ram_addr_t start,
 
 /* get the memory's offset in the vmcore */
 static target_phys_addr_t get_offset(target_phys_addr_t phys_addr,
-                                     target_phys_addr_t memory_offset)
+                                     DumpState *s)
 {
     RAMBlock *block;
-    target_phys_addr_t offset = memory_offset;
+    target_phys_addr_t offset = s->memory_offset;
+    int64_t size_in_block, start;
+
+    if (s->has_filter) {
+        if (phys_addr < s->begin || phys_addr >= s->begin + s->length) {
+            return -1;
+        }
+    }
 
     QLIST_FOREACH(block, &ram_list.blocks, next) {
-        if (phys_addr >= block->offset &&
-            phys_addr < block->offset + block->length) {
-            return phys_addr - block->offset + offset;
+        if (s->has_filter) {
+            if (block->offset >= s->begin + s->length ||
+                block->offset + block->length <= s->begin) {
+                /* This block is out of the range */
+                continue;
+            }
+
+            if (s->begin <= block->offset) {
+                start = block->offset;
+            } else {
+                start = s->begin;
+            }
+
+            size_in_block = block->length - (start - block->offset);
+            if (s->begin + s->length < block->offset + block->length) {
+                size_in_block -= block->offset + block->length -
+                                 (s->begin + s->length);
+            }
+        } else {
+            start = block->offset;
+            size_in_block = block->length;
+        }
+
+        if (phys_addr >= start && phys_addr < start + size_in_block) {
+            return phys_addr - start + offset;
         }
-        offset += block->length;
+
+        offset += size_in_block;
     }
 
     return -1;
@@ -561,7 +594,7 @@ static int dump_completed(DumpState *s)
     int phdr_index = 1, ret;
 
     QTAILQ_FOREACH(memory_mapping, &s->list.head, next) {
-        offset = get_offset(memory_mapping->phys_addr, s->memory_offset);
+        offset = get_offset(memory_mapping->phys_addr, s);
         if (s->dump_info.d_class == ELFCLASS64) {
             ret = write_elf64_load(s, memory_mapping, phdr_index++, offset);
         } else {
@@ -588,6 +621,17 @@ static int get_next_block(DumpState *s, RAMBlock *block)
 
         s->start = 0;
         s->block = block;
+        if (s->has_filter) {
+            if (block->offset >= s->begin + s->length ||
+                block->offset + block->length <= s->begin) {
+                /* This block is out of the range */
+                continue;
+            }
+
+            if (s->begin > block->offset) {
+                s->start = s->begin - block->offset;
+            }
+        }
 
         return 0;
     }
@@ -666,7 +710,36 @@ static void dump_vm_state_change(void *opaque, int running, RunState state)
     }
 }
 
-static DumpState *dump_init(bool paging, Error **errp)
+static ram_addr_t get_start_block(DumpState *s)
+{
+    RAMBlock *block;
+
+    if (!s->has_filter) {
+        s->block = QLIST_FIRST(&ram_list.blocks);
+        return 0;
+    }
+
+    QLIST_FOREACH(block, &ram_list.blocks, next) {
+        if (block->offset >= s->begin + s->length ||
+            block->offset + block->length <= s->begin) {
+            /* This block is out of the range */
+            continue;
+        }
+
+        s->block = block;
+        if (s->begin > block->offset ) {
+            s->start = s->begin - block->offset;
+        } else {
+            s->start = 0;
+        }
+        return s->start;
+    }
+
+    return -1;
+}
+
+static DumpState *dump_init(bool paging, bool has_filter, int64_t begin,
+                            int64_t length, Error **errp)
 {
     CPUState *env;
     DumpState *s = dump_get_current();
@@ -683,8 +756,16 @@ static DumpState *dump_init(bool paging, Error **errp)
         g_free(s->error);
         s->error = NULL;
     }
-    s->block = QLIST_FIRST(&ram_list.blocks);
-    s->start = 0;
+
+    s->has_filter = has_filter;
+    s->begin = begin;
+    s->length = length;
+    s->start = get_start_block(s);
+    if (s->start == -1) {
+        error_set(errp, QERR_INVALID_PARAMETER, "begin");
+        return NULL;
+    }
+
     s->handler = qemu_add_vm_change_state_handler(dump_vm_state_change, s);
 
     /*
@@ -713,6 +794,10 @@ static DumpState *dump_init(bool paging, Error **errp)
         qemu_get_guest_simple_memory_mapping(&s->list);
     }
 
+    if (s->has_filter) {
+        memory_mapping_filter(&s->list, s->begin, s->length);
+    }
+
     /*
      * calculate phdr_num
      *
@@ -783,9 +868,10 @@ static int fd_dump_begin_iterate(DumpState *s, void *opaque)
     return qemu_set_fd_handler(fd, NULL, dump_iterate, s);
 }
 
-static DumpState *dump_init_fd(int fd, bool paging, Error **errp)
+static DumpState *dump_init_fd(int fd, bool paging, bool has_filter,
+                               int64_t begin, int64_t length, Error **errp)
 {
-    DumpState *s = dump_init(paging, errp);
+    DumpState *s = dump_init(paging, has_filter, begin, length, errp);
 
     if (s == NULL) {
         return NULL;
@@ -800,12 +886,22 @@ static DumpState *dump_init_fd(int fd, bool paging, Error **errp)
     return s;
 }
 
-void qmp_dump(bool detach, bool paging, const char *file, Error **errp)
+void qmp_dump(bool detach, bool paging, const char *file, bool has_begin,
+              int64_t begin, bool has_length, int64_t length, Error **errp)
 {
     const char *p;
     int fd = -1;
     DumpState *s;
 
+    if (has_begin && !has_length) {
+        error_set(errp, QERR_MISSING_PARAMETER, "length");
+        return;
+    }
+    if (!has_begin && has_length) {
+        error_set(errp, QERR_MISSING_PARAMETER, "begin");
+        return;
+    }
+
 #if !defined(WIN32)
     if (strstart(file, "fd:", &p)) {
         fd = qemu_get_fd(p);
@@ -829,7 +925,7 @@ void qmp_dump(bool detach, bool paging, const char *file, Error **errp)
         return;
     }
 
-    s = dump_init_fd(fd, paging, errp);
+    s = dump_init_fd(fd, paging, has_begin, begin, length, errp);
     if (!s) {
         return;
     }
hmp-commands.hx +10 -4
index fd6f9f1..e108780 100644
@@ -883,22 +883,28 @@ ETEXI
 #if defined(CONFIG_HAVE_CORE_DUMP)
     {
         .name       = "dump",
-        .args_type  = "detach:-d,paging:-p,file:s",
-        .params     = "[-d] [-p] file",
-        .help       = "dump to file (using -d to not wait for completion)",
+        .args_type  = "detach:-d,paging:-p,file:s,begin:i?,length:i?",
+        .params     = "[-d] [-p] file [begin] [length]",
+        .help       = "dump to file (using -d to not wait for completion)"
+                      "\n\t\t\t begin(optional): the starting physical address"
+                      "\n\t\t\t length(optional): the memory size, in bytes",
         .user_print = monitor_user_noop,
         .mhandler.cmd = hmp_dump,
     },
 
 
 STEXI
-@item dump [-d] [-p] @var{file}
+@item dump [-d] [-p] @var{file} @var{begin} @var{length}
 @findex dump
 Dump to @var{file}. The file can be processed with crash or gdb.
     file: destination file(started with "file:") or destination file descriptor
           (started with "fd:")
   paging: do paging to get guest's memory mapping
       -d: donot wait for completion.
+   begin: the starting physical address. It's optional, and should be specified
+          with length together.
+  length: the memory size, in bytes. It's optional, and should be specified with
+          begin together.
 ETEXI
 #endif
 
hmp.c +13 -1
index 8652b20..05e30e1 100644
@@ -886,8 +886,20 @@ void hmp_dump(Monitor *mon, const QDict *qdict)
     int paging = qdict_get_try_bool(qdict, "paging", 0);
     int detach = qdict_get_try_bool(qdict, "detach", 0);
     const char *file = qdict_get_str(qdict, "file");
+    bool has_begin = qdict_haskey(qdict, "begin");
+    bool has_length = qdict_haskey(qdict, "length");
+    int64_t begin = 0;
+    int64_t length = 0;
 
-    qmp_dump(!!detach, !!paging, file, &errp);
+    if (has_begin) {
+        begin = qdict_get_int(qdict, "begin");
+    }
+    if (has_length) {
+        length = qdict_get_int(qdict, "length");
+    }
+
+    qmp_dump(!!detach, !!paging, file, has_begin, begin, has_length, length,
+             &errp);
     if (errp) {
         hmp_handle_error(mon, &errp);
         return;
memory_mapping.c +27 -0
index 7f4193d..2d17a9a 100644
@@ -261,3 +261,30 @@ void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list)
         create_new_memory_mapping(list, block->offset, 0, block->length);
     }
 }
+
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+                           int64_t length)
+{
+    MemoryMapping *cur, *next;
+
+    QTAILQ_FOREACH_SAFE(cur, &list->head, next, next) {
+        if (cur->phys_addr >= begin + length ||
+            cur->phys_addr + cur->length <= begin) {
+            QTAILQ_REMOVE(&list->head, cur, next);
+            list->num--;
+            continue;
+        }
+
+        if (cur->phys_addr < begin) {
+            cur->length -= begin - cur->phys_addr;
+            if (cur->virt_addr) {
+                cur->virt_addr += begin - cur->phys_addr;
+            }
+            cur->phys_addr = begin;
+        }
+
+        if (cur->phys_addr + cur->length > begin + length) {
+            cur->length -= cur->phys_addr + cur->length - begin - length;
+        }
+    }
+}
memory_mapping.h +2 -0
index 50b1f25..6b454e1 100644
@@ -55,4 +55,6 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list);
 /* get guest's memory mapping without do paging(virtual address is 0). */
 void qemu_get_guest_simple_memory_mapping(MemoryMappingList *list);
 
+void memory_mapping_filter(MemoryMappingList *list, int64_t begin,
+                           int64_t length);
 #endif
qapi-schema.json +4 -1
index bd258cb..f981e8d 100644
@@ -1640,13 +1640,16 @@
 # @detach: detached dumping.
 # @paging: if true, do paging to get guest's memory mapping
 # @file: the filename or file descriptor of the vmcore.
+# @begin: if specified, the starting physical address.
+# @length: if specified, the memory size, in bytes.
 #
 # Returns: nothing on success
 #
 # Since: 1.1
 ##
 { 'command': 'dump',
-  'data': { 'detach': 'bool', 'paging': 'bool', 'file': 'str' } }
+  'data': { 'detach': 'bool', 'paging': 'bool', 'file': 'str', '*begin': 'int',
+            '*length': 'int' } }
 
 ##
 # @dump_cancel
qmp-commands.hx +6 -2
index e2accb2..cb2a3f1 100644
@@ -589,8 +589,8 @@ EQMP
 #if defined(CONFIG_HAVE_CORE_DUMP)
     {
         .name       = "dump",
-        .args_type  = "detach:-d,paging:-p,file:s",
-        .params     = "[-d] [-p] file",
+        .args_type  = "detach:-d,paging:-p,file:s,begin:i?,end:i?",
+        .params     = "[-d] [-p] file [begin] [length]",
         .help       = "dump to file",
         .user_print = monitor_user_noop,
         .mhandler.cmd_new = qmp_marshal_input_dump,
@@ -607,6 +607,10 @@ Arguments:
 - "paging": do paging to get guest's memory mapping (json-bool)
 - "file": destination file(started with "file:") or destination file descriptor
           (started with "fd:") (json-string)
+- "begin": the starting physical address. It's optional, and should be specified
+           with length together (json-int)
+- "length": the memory size, in bytes. It's optional, and should be specified
+            with begin together (json-int)
 
 Example:
 
Signature · 1 line
1.7.1
#34 lore raw
In reply to Wen Congyang

At 03/02/2012 05:59 PM, Wen Congyang Wrote:

Quoted 12 lines

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

The last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg04228.html

We have determined to introduce a new command dump to dump memory. The core file's format can be elf.

Quoted 14 lines

Note:
1. The guest should be x86 or x86_64. The other arch is not supported now.
2. If you use old gdb, gdb may crash. I use gdb-7.3.1, and it does not crash.
3. If the OS is in the second kernel, gdb may not work well, and crash can work by specifying '--machdep phys_addr=xxx' in the command line. The reason is that the second kernel will update the page table, and we can not get the page table for the first kernel.
4. The cpu's state is stored in QEMU note. You neet to modify crash to use it to calculate phys_base.
5. If the guest OS is 32 bit and the memory size is larger than 4G, the vmcore is elf64 format. You should use the gdb which is built with --enable-64-bit-bfd.
6. This patchset is based on the upstream tree, and apply one patch that is still in Luiz Capitulino's tree, because I use the API qemu_get_fd() in this patchset.

Hi, Jan, Luiz Capitulino
Do you have any comments?

Thanks
Wen Congyang

Quoted 78 lines

Changes from v7 to v8:
1. addressed Hatayama's comments

Changes from v6 to v7:
1. addressed Jan's comments
2. fix some bugs
3. store cpu's state into the vmcore

Changes from v5 to v6:
1. allow user to dump a fraction of the memory
2. fix some bugs

Changes from v4 to v5:
1. convert the new command dump to QAPI

Changes from v3 to v4:
1. support it to run asynchronously
2. add API to cancel dumping and query dumping progress
3. add API to control dumping speed
4. auto cancel dumping when the user resumes vm, and the status is failed.

Changes from v2 to v3:
1. address Jan Kiszka's comment

Changes from v1 to v2:
1. fix virt addr in the vmcore.

Wen Congyang (16):
Add API to create memory mapping list
Add API to check whether a physical address is I/O address implement cpu_get_memory_mapping()
Add API to check whether paging mode is enabled
Add API to get memory mapping
Add API to get memory mapping without do paging
target-i386: Add API to write elf notes to core file
target-i386: Add API to write cpu status to core file
target-i386: add API to get dump info
make gdb_id() generally avialable
introduce a new monitor command 'dump' to dump guest's memory support to cancel the current dumping
support to query dumping status
run dump at the background
support detached dump
allow user to dump a fraction of the memory

 Makefile.target                   |    3 +
 configure                         |    8 +
 cpu-all.h                         |   66 +++
 cpu-common.h                      |    2 +
 dump.c                            |  980 +++++++++++++++++++++++++++++++++++++
 dump.h                            |   23 +
 elf.h                             |    5 +
 exec.c                            |   11 +
 gdbstub.c                         |    9 -
 gdbstub.h                         |    9 +
 hmp-commands.hx                   |   44 ++
 hmp.c                             |   89 ++++
 hmp.h                             |    3 +
 memory_mapping.c                  |  290 +++++++++++
 memory_mapping.h                  |   60 +++
 monitor.c                         |    7 +
 qapi-schema.json                  |   58 +++
 qmp-commands.hx                   |  110 +++++
 target-i386/arch_dump.c           |  433 ++++++++++++++++
 target-i386/arch_memory_mapping.c |  271 ++++++++++
 vl.c                              |    5 +-
 21 files changed, 2475 insertions(+), 11 deletions(-)
 create mode 100644 dump.c
 create mode 100644 dump.h
 create mode 100644 memory_mapping.c
 create mode 100644 memory_mapping.h
 create mode 100644 target-i386/arch_dump.c
 create mode 100644 target-i386/arch_memory_mapping.c
#35 lore raw
Quoted 28 lines · On Mon, 05 Mar 2012 17:12:00 +0800 Wen Congyang <[email protected]> wrote:

At 03/02/2012 05:59 PM, Wen Congyang Wrote:

Quoted 12 lines

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

The last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg04228.html

We have determined to introduce a new command dump to dump memory. The core file's format can be elf.

Quoted 14 lines

Note:
1. The guest should be x86 or x86_64. The other arch is not supported now.
2. If you use old gdb, gdb may crash. I use gdb-7.3.1, and it does not crash.
3. If the OS is in the second kernel, gdb may not work well, and crash can work by specifying '--machdep phys_addr=xxx' in the command line. The reason is that the second kernel will update the page table, and we can not get the page table for the first kernel.
4. The cpu's state is stored in QEMU note. You neet to modify crash to use it to calculate phys_base.
5. If the guest OS is 32 bit and the memory size is larger than 4G, the vmcore is elf64 format. You should use the gdb which is built with --enable-64-bit-bfd.
6. This patchset is based on the upstream tree, and apply one patch that is still in Luiz Capitulino's tree, because I use the API qemu_get_fd() in this patchset.

Quoted 2 lines

Hi, Jan, Luiz Capitulino
Do you have any comments?

I haven't had a chance to review it yet, will do in the next few days.

#36 lore raw
Quoted 31 lines · On Mon, 5 Mar 2012 21:41:02 -0300 Luiz Capitulino <[email protected]>…
Quoted 28 lines · On Mon, 05 Mar 2012 17:12:00 +0800 Wen Congyang <[email protected]> wrote:

At 03/02/2012 05:59 PM, Wen Congyang Wrote:

Quoted 26 lines

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

The last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg04228.html

We have determined to introduce a new command dump to dump memory. The core file's format can be elf.

Note:
1. The guest should be x86 or x86_64. The other arch is not supported now.
2. If you use old gdb, gdb may crash. I use gdb-7.3.1, and it does not crash.
3. If the OS is in the second kernel, gdb may not work well, and crash can work by specifying '--machdep phys_addr=xxx' in the command line. The reason is that the second kernel will update the page table, and we can not get the page table for the first kernel.
4. The cpu's state is stored in QEMU note. You neet to modify crash to use it to calculate phys_base.
5. If the guest OS is 32 bit and the memory size is larger than 4G, the vmcore is elf64 format. You should use the gdb which is built with --enable-64-bit-bfd.
6. This patchset is based on the upstream tree, and apply one patch that is still in Luiz Capitulino's tree, because I use the API qemu_get_fd() in this patchset.

Quoted 4 lines
Quoted 2 lines

Hi, Jan, Luiz Capitulino
Do you have any comments?

I haven't had a chance to review it yet, will do in the next few days.

Wen, I've started reviewing this but before I ask you to make more changes to this series, it's better to wait for a conclusion of the asynchronous command discussion thread:

http://lists.gnu.org/archive/html/qemu-devel/2012-03/msg01067.html

#37 lore raw

At 03/08/2012 01:38 AM, Luiz Capitulino Wrote:

Quoted 37 lines
Quoted 34 lines · On Mon, 5 Mar 2012 21:41:02 -0300 Luiz Capitulino <[email protected]>…
Quoted 30 lines · On Mon, 05 Mar 2012 17:12:00 +0800 Wen Congyang <[email protected]> wrote:

At 03/02/2012 05:59 PM, Wen Congyang Wrote:

Quoted 12 lines

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

The last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg04228.html

We have determined to introduce a new command dump to dump memory. The core file's format can be elf.

Quoted 14 lines

Note:
1. The guest should be x86 or x86_64. The other arch is not supported now.
2. If you use old gdb, gdb may crash. I use gdb-7.3.1, and it does not crash.
3. If the OS is in the second kernel, gdb may not work well, and crash can work by specifying '--machdep phys_addr=xxx' in the command line. The reason is that the second kernel will update the page table, and we can not get the page table for the first kernel.
4. The cpu's state is stored in QEMU note. You neet to modify crash to use it to calculate phys_base.
5. If the guest OS is 32 bit and the memory size is larger than 4G, the vmcore is elf64 format. You should use the gdb which is built with --enable-64-bit-bfd.
6. This patchset is based on the upstream tree, and apply one patch that is still in Luiz Capitulino's tree, because I use the API qemu_get_fd() in this patchset.

Hi, Jan, Luiz Capitulino
Do you have any comments?

Quoted 7 lines
Quoted 1 line

I haven't had a chance to review it yet, will do in the next few days.

Wen, I've started reviewing this but before I ask you to make more changes to this series, it's better to wait for a conclusion of the asynchronous command discussion thread:

http://lists.gnu.org/archive/html/qemu-devel/2012-03/msg01067.html

OK. I see this thread.

Thanks
Wen Congyang

Quoted 3 lines