introducing a new, dedicated memory dump mechanism
v7 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/msg01007.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 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 (14):
Add API to create memory mapping list
Add API to check whether a physical address is I/O address
target-i386: implement cpu_get_memory_mapping()
Add API to get memory mapping
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 | 60 +++ cpu-common.h | 2 + dump.c | 904 +++++++++++++++++++++++++++++++++++++ dump.h | 23 + exec.c | 11 + gdbstub.c | 9 - gdbstub.h | 9 + hmp-commands.hx | 43 ++ hmp.c | 87 ++++ hmp.h | 3 + memory_mapping.c | 232 ++++++++++ memory_mapping.h | 54 +++ monitor.c | 7 + qapi-schema.json | 57 +++ qmp-commands.hx | 109 +++++ target-i386/arch_dump.c | 437 ++++++++++++++++++ target-i386/arch_memory_mapping.c | 256 +++++++++++ vl.c | 5 +- 20 files changed, 2308 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
RFC PATCH v7 1/14 Add API to create memory mapping list
The memory mapping list stores virtual address and physical address mapping. The folloing patch will use this information to create PT_LOAD in the vmcore.
--- Makefile.target | 1 + memory_mapping.c | 134 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ memory_mapping.h | 44 ++++++++++++++++++ 3 files changed, 179 insertions(+), 0 deletions(-) create mode 100644 memory_mapping.c create mode 100644 memory_mapping.h
Makefile.target +1 -0
@@ -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 +134 -0
134 lines not on this page · raw message
memory_mapping.h new file +44 -0
44 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [Qemu-devel] [RFC][PATCH 01/14 v7] Add API to create memory mapping list
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 01/14 v7] Add API to create memory mapping list
Date: Thu, 01 Mar 2012 10:39:35 +0800
memory_mapping.c line 48
Quoted 4 lines
memory_mapping.c new file +3
-0+static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, + MemoryMapping *mapping) +void memory_mapping_list_add_sorted(MemoryMappingList *list,
These functions not only sort but also merge elements of mapping list. Is there another name that represents what these are doing more properly?
Quoted 18 lines
memory_mapping.c new file +18
-0+target_phys_addr_t phys_addr, + target_phys_addr_t virt_addr, + ram_addr_t length) +{ + MemoryMapping *memory_mapping, *last_mapping; + +if (QTAILQ_EMPTY (&list->head)) { +create_new_memory_mapping (list, phys_addr, virt_addr, length); +return ; + } + + last_mapping = list->last_mapping; +if (last_mapping) { +if ((phys_addr == (last_mapping->phys_addr + last_mapping->length)) && + (virt_addr == (last_mapping->virt_addr + last_mapping->length))) { + last_mapping->length += length; +return ; + }
memory_mapping.c line 76
Quoted 10 lines
memory_mapping.c new file +10
-0+ } + + QTAILQ_FOREACH(memory_mapping, &list->head, next) { + last_mapping = memory_mapping; +if ((phys_addr == (last_mapping->phys_addr + last_mapping->length)) && + (virt_addr == (last_mapping->virt_addr + last_mapping->length))) { + last_mapping->length += length; + list->last_mapping = last_mapping; +return ; + }
Please don't use a single variable in multiple meanings in the same function. It appears to me that the variable last_mapping is used as n-th entry connected to the list->head within this for loop. So this_mapping, for example, is reasonable rather than last_mapping. All use of last_mapping within the for loop can be replaced with memory_mapping, right?
Quoted 9 lines
memory_mapping.c new file +9
-0+ +if (phys_addr + length < last_mapping->phys_addr) { +/* create a new region before last_mapping */ +break ; + } + +if (phys_addr >= (last_mapping->phys_addr + last_mapping->length)) { +/* last_mapping does not contain this region */ +continue ;
memory_mapping.c line 95
Quoted 10 lines
memory_mapping.c new file +10
-0+ } + +if ((virt_addr - last_mapping->virt_addr) != + (phys_addr - last_mapping->phys_addr)) { +/* +* last_mapping contains this region, but we cannot merge this +* region into last_mapping. Try the next memory mapping. +*/ +continue ; + }
Does this condition means the current mapping and the last mapping are contiguous both phisically and viurtually? If so, it's better to write the condition so readers can understand that more easily.
Quoted 9 lines
memory_mapping.c new file +9
-0+ +/* merge this region into last_mapping */ +if (virt_addr < last_mapping->virt_addr) { + last_mapping->length += last_mapping->virt_addr - virt_addr; + last_mapping->virt_addr = virt_addr; + } + +if ((virt_addr + length) > + (last_mapping->virt_addr + last_mapping->length)) {
memory_mapping.c line 114
Quoted 10 lines
memory_mapping.c new file +10
-0+ last_mapping->length = virt_addr + length - last_mapping->virt_addr; + } + + list->last_mapping = last_mapping; +return ; + } + +/* this region can not be merged into any existed memory mapping. */ +create_new_memory_mapping (list, phys_addr, virt_addr, length); +}
How about adding helper functions for expressing each conditionals? Just like below. Then I think the code gets more readable.
bool mapping_proper_succeor(MemoryMapping *map,
target_phys_addr_t phys_addr,
target_virt_addr_t virt_addr);
bool mapping_physically_contains(MemoryMapping *map,
target_phys_addr_t phys_addr);
bool mapping_physically_virtually_contiguous(MemoryMapping *map,
target_phys_addr_t phys_addr,
target_virt_addr_t virt_addr);
void mapping_merge(MemoryMapping *map, target_phys_addr_t phys_addr,
target_virt_addr_t virt_addr);I'm not confident of the naming, these are example, and assuming define all as static inline functions.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 01/14 v7] Add API to create memory mapping list
At 03/01/2012 04:33 PM, HATAYAMA Daisuke Wrote:
Quoted 40 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 01/14 v7] Add API to create memory mapping list
Date: Thu, 01 Mar 2012 10:39:35 +0800memory_mapping.c line 48
Quoted 4 lines
memory_mapping.c new file +3
-0+static void memory_mapping_list_add_mapping_sorted(MemoryMappingList *list, + MemoryMapping *mapping) +void memory_mapping_list_add_sorted(MemoryMappingList *list,These functions not only sort but also merge elements of mapping list. Is there another name that represents what these are doing more properly?
Quoted 27 lines
memory_mapping.c new file +27
-0+target_phys_addr_t phys_addr, + target_phys_addr_t virt_addr, + ram_addr_t length) +{ + MemoryMapping *memory_mapping, *last_mapping; + +if (QTAILQ_EMPTY (&list->head)) { +create_new_memory_mapping (list, phys_addr, virt_addr, length); +return ; + } + + last_mapping = list->last_mapping; +if (last_mapping) { +if ((phys_addr == (last_mapping->phys_addr + last_mapping->length)) && + (virt_addr == (last_mapping->virt_addr + last_mapping->length))) { + last_mapping->length += length; +return ; + } + } + + QTAILQ_FOREACH(memory_mapping, &list->head, next) { + last_mapping = memory_mapping; +if ((phys_addr == (last_mapping->phys_addr + last_mapping->length)) && + (virt_addr == (last_mapping->virt_addr + last_mapping->length))) { + last_mapping->length += length; + list->last_mapping = last_mapping; +return ;
Quoted 8 lines
Quoted 1 line
+ }
Please don't use a single variable in multiple meanings in the same function. It appears to me that the variable
last_mappingis used as n-th entry connected to thelist->headwithin this for loop. Sothis_mapping, for example, is reasonable rather thanlast_mapping. All use oflast_mappingwithin the for loop can be replaced withmemory_mapping, right?
OK
Quoted 16 lines
Quoted 16 lines
memory_mapping.c new file +15
-0+ +if (phys_addr + length < last_mapping->phys_addr) { +/* create a new region before last_mapping */ +break ; + } + +if (phys_addr >= (last_mapping->phys_addr + last_mapping->length)) { +/* last_mapping does not contain this region */ +continue ; + } + +if ((virt_addr - last_mapping->virt_addr) != + (phys_addr - last_mapping->phys_addr)) { +/* +* last_mapping contains this region, but we cannot merge this
Quoted 8 lines
memory_mapping.c line 95
Quoted 4 lines
memory_mapping.c new file +4
-0+* region into last_mapping. Try the next memory mapping. +*/ +continue ; + }Does this condition means the current mapping and the last mapping are contiguous both phisically and viurtually? If so, it's better to write the condition so readers can understand that more easily.
current mapping and last mapping are always contiguous both phisically and virtually.
Quoted 35 lines
Quoted 10 lines
memory_mapping.c new file +9
-0+ +/* merge this region into last_mapping */ +if (virt_addr < last_mapping->virt_addr) { + last_mapping->length += last_mapping->virt_addr - virt_addr; + last_mapping->virt_addr = virt_addr; + } + +if ((virt_addr + length) > + (last_mapping->virt_addr + last_mapping->length)) {memory_mapping.c line 114
Quoted 10 lines
memory_mapping.c new file +10
-0+ last_mapping->length = virt_addr + length - last_mapping->virt_addr; + } + + list->last_mapping = last_mapping; +return ; + } + +/* this region can not be merged into any existed memory mapping. */ +create_new_memory_mapping (list, phys_addr, virt_addr, length); +}How about adding helper functions for expressing each conditionals? Just like below. Then I think the code gets more readable.
bool mapping_proper_succeor(MemoryMapping *map,
target_phys_addr_t phys_addr, target_virt_addr_t virt_addr); bool mapping_physically_contains(MemoryMapping *map, target_phys_addr_t phys_addr); bool mapping_physically_virtually_contiguous(MemoryMapping *map, target_phys_addr_t phys_addr, target_virt_addr_t virt_addr); void mapping_merge(MemoryMapping *map, target_phys_addr_t phys_addr, target_virt_addr_t virt_addr);
Quoted 2 lines
I'm not confident of the naming, these are example, and assuming define all as static inline functions.
Hmm, I think this inline functions make the code more readable. So I will modify my code.
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
RFC PATCH v7 2/14 Add API to check whether a physical address is I/O address
In reply to Wen CongyangThis 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
@@ -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
@@ -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
RFC PATCH v7 3/14 target-i386: implement cpu_get_memory_mapping()
In reply to Wen CongyangWalk cpu's page table and collect all virtual address and physical address mapping. Then, add these mapping into memory mapping list.
--- Makefile.target | 1 + configure | 4 + cpu-all.h | 10 ++ target-i386/arch_memory_mapping.c | 256 +++++++++++++++++++++++++++++++++++++ 4 files changed, 271 insertions(+), 0 deletions(-) create mode 100644 target-i386/arch_memory_mapping.c
Makefile.target +1 -0
@@ -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
@@ -3630,6 +3630,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
@@ -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 +256 -0
256 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [Qemu-devel] [RFC][PATCH 03/14 v7] target-i386: implement cpu_get_memory_mapping()
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 03/14 v7] target-i386: implement cpu_get_memory_mapping()
Date: Thu, 01 Mar 2012 10:41:47 +0800
Quoted 18 lines
target-i386/arch_memory_mapping.c new file +18
-0+int cpu_get_memory_mapping (MemoryMappingList *list,CPUState *env) +{ +if (env->cr[4 ] &CR4_PAE_MASK ) { +#ifdef TARGET_X86_64 +if (env->hflags &HF_LMA_MASK ) { +target_phys_addr_t pml4e_addr; + + pml4e_addr = (env->cr[3 ] & ~0xfff ) & env->a20_mask; +walk_pml4e (list, pml4e_addr, env->a20_mask); + } else +#endif + { +target_phys_addr_t pdpe_addr; + + pdpe_addr = (env->cr[3 ] & ~0x1f ) & env->a20_mask; +walk_pdpe2 (list, pdpe_addr, env->a20_mask); + } + }else {
target-i386/arch_memory_mapping.c line 256
Quoted 10 lines
target-i386/arch_memory_mapping.c new file +10
-0+target_phys_addr_t pde_addr; +bool pse; + + pde_addr = (env->cr[3 ] & ~0xfff ) & env->a20_mask; + pse = !!(env->cr[4 ] &CR4_PSE_MASK ); +walk_pde2 (list, pde_addr, env->a20_mask, pse); + } + +return 0 ; +}
Does this assume paging mode? I don't know qemu very well, but qemu dump command runs externally to guest machine, so I think the machine could be in the state with paging disabled where CR4 doesn't refer to page table as expected.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 03/14 v7] target-i386: implement cpu_get_memory_mapping()
At 03/01/2012 02:13 PM, HATAYAMA Daisuke Wrote:
Quoted 29 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 03/14 v7] target-i386: implementcpu_get_memory_mapping()
Date: Thu, 01 Mar 2012 10:41:47 +0800Quoted 25 lines
target-i386/arch_memory_mapping.c new file +25
-0+int cpu_get_memory_mapping (MemoryMappingList *list,CPUState *env) +{ +if (env->cr[4 ] &CR4_PAE_MASK ) { +#ifdef TARGET_X86_64 +if (env->hflags &HF_LMA_MASK ) { +target_phys_addr_t pml4e_addr; + + pml4e_addr = (env->cr[3 ] & ~0xfff ) & env->a20_mask; +walk_pml4e (list, pml4e_addr, env->a20_mask); + } else +#endif + { +target_phys_addr_t pdpe_addr; + + pdpe_addr = (env->cr[3 ] & ~0x1f ) & env->a20_mask; +walk_pdpe2 (list, pdpe_addr, env->a20_mask); + } + }else { +target_phys_addr_t pde_addr; +bool pse; + + pde_addr = (env->cr[3 ] & ~0xfff ) & env->a20_mask; + pse = !!(env->cr[4 ] &CR4_PSE_MASK ); +walk_pde2 (list, pde_addr, env->a20_mask, pse); + }
Quoted 8 lines
target-i386/arch_memory_mapping.c line 256
Quoted 3 lines
target-i386/arch_memory_mapping.c new file +3
-0+ +return 0 ; +}Does this assume paging mode? I don't know qemu very well, but qemu dump command runs externally to guest machine, so I think the machine could be in the state with paging disabled where CR4 doesn't refer to page table as expected.
CR4? I think you want to say CR3.
Yes, the guest may be in the state without paging mode. I will fix it.
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 03/14 v7] target-i386: implement cpu_get_memory_mapping()
From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 03/14 v7] target-i386: implement cpu_get_memory_mapping()
Date: Thu, 01 Mar 2012 14:21:37 +0800
Quoted 39 lines
At 03/01/2012 02:13 PM, HATAYAMA Daisuke Wrote:
Quoted 29 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 03/14 v7] target-i386: implementcpu_get_memory_mapping()
Date: Thu, 01 Mar 2012 10:41:47 +0800Quoted 25 lines
target-i386/arch_memory_mapping.c new file +25
-0+int cpu_get_memory_mapping (MemoryMappingList *list,CPUState *env) +{ +if (env->cr[4 ] &CR4_PAE_MASK ) { +#ifdef TARGET_X86_64 +if (env->hflags &HF_LMA_MASK ) { +target_phys_addr_t pml4e_addr; + + pml4e_addr = (env->cr[3 ] & ~0xfff ) & env->a20_mask; +walk_pml4e (list, pml4e_addr, env->a20_mask); + } else +#endif + { +target_phys_addr_t pdpe_addr; + + pdpe_addr = (env->cr[3 ] & ~0x1f ) & env->a20_mask; +walk_pdpe2 (list, pdpe_addr, env->a20_mask); + } + }else { +target_phys_addr_t pde_addr; +bool pse; + + pde_addr = (env->cr[3 ] & ~0xfff ) & env->a20_mask; + pse = !!(env->cr[4 ] &CR4_PSE_MASK ); +walk_pde2 (list, pde_addr, env->a20_mask, pse); + }Quoted 8 lines
target-i386/arch_memory_mapping.c line 256
Quoted 3 lines
target-i386/arch_memory_mapping.c new file +3
-0+ +return 0 ; +}Does this assume paging mode? I don't know qemu very well, but qemu dump command runs externally to guest machine, so I think the machine could be in the state with paging disabled where CR4 doesn't refer to page table as expected.
Quoted 4 lines
CR4? I think you want to say CR3.
Yes, the guest may be in the state without paging mode. I will fix it.
Hmmm, now I think dump command needs to have a option to specify whether to do paging or not during dumping. Doing always paging is problematic. Also generated formats should be as simple as possible, different from the format this current version generates. The reasons I have are as follows:
- The qemu dump command runs outside of guest machine. If machine is in the state with paging disabled and CR3 doesn't has page table address, qemu dump command cannot do paging.
- We cannot do paging if guest machine state is severe. For example, when page table data is corrupted in some reason. In general, we should use minimum kinds of data only during dumping.
- There's also kdump specific issue. On kdump there are two kinds of kernels, 1st kernel and 2nd kernel, and when crash happens, execution is transmitted from the 1st to the 2nd, and then the 2nd kernel copies the 1st kernel's kernel image. The problem is that at catastrophic situation, kdump can also hang even in the 2nd kernel. At this point, the 2nd kernel refers to the 2nd kernel's page table. So paging at the situation leads to lost of the 1st kernel's memory.
- OTOH, gdb cannot perform paging, so, for gdb support, qemu dump needs to have paging mode. The period when qemu dump can produce the dump gdb can read is limited to the machine state with paging enabled and the 1st krenel, but I think no choise.
* There's a way of getting the 1st kernel's image as linear image from the dumpfile generated at the 2nd kernel generated without paging. But it uses kenrel's specific information, so I don't think qemu should do this.
- Well, it's possible to generate dumpfile while enabling both physical and linear address access together. It's just what Wen is doing now. But I think it better to do that more simply: that is, if non-paging mode, produce dumpfile as raw format; if paging mode, produce as linear format.
* For example, the current implementation assigns both virtual and physical address to a single PT_LOAD entry. But the memory areas mapped to by a single PT_LOAD is restricted to the ones contiguous both physically and virtually. Due to this, I guess there's a case where the number of program headers grows seriously in the worst case. It might reach ELF's limit size.
* Also, by this, it's necessary to reduce the number of program headers as much as possible, and now qemu dump tries to merge them in PATCH 01, but it looks to me too complicated.
How do other people think?
Thanks.
HATAYAMA, Daisuke
RFC PATCH v7 4/14 Add API to get memory mapping
In reply to Wen CongyangAdd 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 | 71 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ memory_mapping.h | 8 ++++++ 2 files changed, 79 insertions(+), 0 deletions(-)
memory_mapping.c +71 -0
@@ -132,3 +132,74 @@ 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; +int ret; + +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING ) +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 mapped, add them into memory mapping's list */ + QLIST_FOREACH(block, &ram_list.blocks, next) { + offset = block->offset; + length = block->length; + + QTAILQ_FOREACH(memory_mapping, &list->head, next) { +if (memory_mapping->phys_addr >= (offset + length)) { +/* +* memory_mapping's list does not conatin the region +* [offset, offset+length) +*/ +create_new_memory_mapping (list, offset,0 , length); + length =0 ; +break ; + } + +if ((memory_mapping->phys_addr + memory_mapping->length) <= + offset) { +continue ; + } + +if (memory_mapping->phys_addr > offset) { +/* +* memory_mapping's list does not conatin the region +* [offset, memory_mapping->phys_addr) +*/ +create_new_memory_mapping (list, offset,0 , + memory_mapping->phys_addr - offset); + } + +if ((offset + length) <= + (memory_mapping->phys_addr + memory_mapping->length)) { + length =0 ; +break ; + } + length -= memory_mapping->phys_addr + memory_mapping->length - + offset; + offset = memory_mapping->phys_addr + memory_mapping->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
@@ -41,4 +41,12 @@ void memory_mapping_list_add_sorted(MemoryMappingList *list,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
Re: [Qemu-devel] [RFC][PATCH 04/14 v7] Add API to get memory mapping
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 10:43:13 +0800
Quoted 10 lines
memory_mapping.c +10
-0+int qemu_get_guest_memory_mapping (MemoryMappingList *list) +{ +CPUState *env; +MemoryMapping *memory_mapping; +RAMBlock *block; +ram_addr_t offset, length; +int ret; + +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING ) +for (env = first_cpu; env !=NULL ; env = env->next_cpu) {
memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 155
Quoted 10 lines
memory_mapping.c +10
-0+ ret =cpu_get_memory_mapping (list, env); +if (ret <0 ) { +return -1 ; + } + } +#else +return -2 ; +#endif + +/* some memory may be not mapped, add them into memory mapping's list */
The part from here is logic fully for 2nd kernel? If so, I think it better to describe why this addtional mapping is needed; we should assume most people doesn't know kdump mechanism.
Quoted 40 lines
memory_mapping.c +40
-0+ QLIST_FOREACH(block, &ram_list.blocks, next) { + offset = block->offset; + length = block->length; + + QTAILQ_FOREACH(memory_mapping, &list->head, next) { +if (memory_mapping->phys_addr >= (offset + length)) { +/* +* memory_mapping's list does not conatin the region +* [offset, offset+length) +*/ +create_new_memory_mapping (list, offset,0 , length); + length =0 ; +break ; + } + +if ((memory_mapping->phys_addr + memory_mapping->length) <= + offset) { +continue ; + } + +if (memory_mapping->phys_addr > offset) { +/* +* memory_mapping's list does not conatin the region +* [offset, memory_mapping->phys_addr) +*/ +create_new_memory_mapping (list, offset,0 , + memory_mapping->phys_addr - offset); + } + +if ((offset + length) <= + (memory_mapping->phys_addr + memory_mapping->length)) { + length =0 ; +break ; + } + length -= memory_mapping->phys_addr + memory_mapping->length - + offset; + offset = memory_mapping->phys_addr + memory_mapping->length; + } + +if (length >0 ) {
memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 205
Quoted 10 lines
memory_mapping.c +10
-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 ; +}
I think it more readable if shortening memory_mapping->phys_addr and memmory_maping->length at the berinning of the innermost foreach loop.
m_phys_addr = memory_mapping->phys_addr; m_length = memory_mapping->length;
Then, each conditionals becomes compact.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 04/14 v7] Add API to get memory mapping
At 03/01/2012 02:01 PM, HATAYAMA Daisuke Wrote:
Quoted 20 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 10:43:13 +0800Quoted 16 lines
memory_mapping.c +16
-0+int qemu_get_guest_memory_mapping (MemoryMappingList *list) +{ +CPUState *env; +MemoryMapping *memory_mapping; +RAMBlock *block; +ram_addr_t offset, length; +int ret; + +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING ) +for (env = first_cpu; env !=NULL ; env = env->next_cpu) { + ret =cpu_get_memory_mapping (list, env); +if (ret <0 ) { +return -1 ; + } + } +#else
Quoted 8 lines
memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 155
Quoted 4 lines
memory_mapping.c +4
-0+return -2 ; +#endif + +/* some memory may be not mapped, add them into memory mapping's list */ The part from here is logic fully for 2nd kernel? If so, I think it better to describe why this addtional mapping is needed; we should assume most people doesn't know kdump mechanism.
Not only for 2nd kernel. If the guest has 1 vcpu, and is in the 2nd kernel, we need this logic for 1st kernel.
Thanks
Wen Congyang
Quoted 64 lines
Quoted 41 lines
memory_mapping.c +40
-0+ QLIST_FOREACH(block, &ram_list.blocks, next) { + offset = block->offset; + length = block->length; + + QTAILQ_FOREACH(memory_mapping, &list->head, next) { +if (memory_mapping->phys_addr >= (offset + length)) { +/* +* memory_mapping's list does not conatin the region +* [offset, offset+length) +*/ +create_new_memory_mapping (list, offset,0 , length); + length =0 ; +break ; + } + +if ((memory_mapping->phys_addr + memory_mapping->length) <= + offset) { +continue ; + } + +if (memory_mapping->phys_addr > offset) { +/* +* memory_mapping's list does not conatin the region +* [offset, memory_mapping->phys_addr) +*/ +create_new_memory_mapping (list, offset,0 , + memory_mapping->phys_addr - offset); + } + +if ((offset + length) <= + (memory_mapping->phys_addr + memory_mapping->length)) { + length =0 ; +break ; + } + length -= memory_mapping->phys_addr + memory_mapping->length - + offset; + offset = memory_mapping->phys_addr + memory_mapping->length; + } + +if (length >0 ) {memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 205
Quoted 10 lines
memory_mapping.c +10
-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 ; +}I think it more readable if shortening
memory_mapping->phys_addrandmemmory_maping->lengthat the berinning of the innermost foreach loop.m_phys_addr = memory_mapping->phys_addr; m_length = memory_mapping->length;Then, each conditionals becomes compact.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 04/14 v7] Add API to get memory mapping
From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 14:17:53 +0800
Quoted 30 lines
At 03/01/2012 02:01 PM, HATAYAMA Daisuke Wrote:
Quoted 20 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 10:43:13 +0800Quoted 16 lines
memory_mapping.c +16
-0+int qemu_get_guest_memory_mapping (MemoryMappingList *list) +{ +CPUState *env; +MemoryMapping *memory_mapping; +RAMBlock *block; +ram_addr_t offset, length; +int ret; + +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING ) +for (env = first_cpu; env !=NULL ; env = env->next_cpu) { + ret =cpu_get_memory_mapping (list, env); +if (ret <0 ) { +return -1 ; + } + } +#else Quoted 8 lines
memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 155
Quoted 4 lines
memory_mapping.c +4
-0+return -2 ; +#endif + +/* some memory may be not mapped, add them into memory mapping's list */ The part from here is logic fully for 2nd kernel? If so, I think it better to describe why this addtional mapping is needed; we should assume most people doesn't know kdump mechanism.
Quoted 3 lines
Not only for 2nd kernel. If the guest has 1 vcpu, and is in the 2nd kernel, we need this logic for 1st kernel.
So you should describe two cases explicitly. I don't understand them from ``some memory''.
and please consider cleanup below too. Conditionals over two lines are hard to read.
Quoted 8 lines
Quoted 8 lines
I think it more readable if shortening
memory_mapping->phys_addrandmemmory_maping->lengthat the berinning of the innermost foreach loop.m_phys_addr = memory_mapping->phys_addr; m_length = memory_mapping->length;Then, each conditionals becomes compact.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 04/14 v7] Add API to get memory mapping
At 03/01/2012 03:11 PM, HATAYAMA Daisuke Wrote:
Quoted 38 lines
From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 14:17:53 +0800Quoted 30 lines
At 03/01/2012 02:01 PM, HATAYAMA Daisuke Wrote:
Quoted 20 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 04/14 v7] Add API to get memory mapping
Date: Thu, 01 Mar 2012 10:43:13 +0800Quoted 16 lines
memory_mapping.c +16
-0+int qemu_get_guest_memory_mapping (MemoryMappingList *list) +{ +CPUState *env; +MemoryMapping *memory_mapping; +RAMBlock *block; +ram_addr_t offset, length; +int ret; + +#if defined(CONFIG_HAVE_GET_MEMORY_MAPPING ) +for (env = first_cpu; env !=NULL ; env = env->next_cpu) { + ret =cpu_get_memory_mapping (list, env); +if (ret <0 ) { +return -1 ; + } + } +#else Quoted 8 lines
memory_mapping.c void memory_mapping_list_init(MemoryMappingList *list) · line 155
Quoted 4 lines
memory_mapping.c +4
-0+return -2 ; +#endif + +/* some memory may be not mapped, add them into memory mapping's list */ The part from here is logic fully for 2nd kernel? If so, I think it better to describe why this addtional mapping is needed; we should assume most people doesn't know kdump mechanism.
Quoted 3 lines
Not only for 2nd kernel. If the guest has 1 vcpu, and is in the 2nd kernel, we need this logic for 1st kernel.
Quoted 5 lines
So you should describe two cases explicitly. I don't understand them from ``some memory''.
and please consider cleanup below too. Conditionals over two lines are hard to read.
OK. I will fix it.
Thanks
Wen Congyang
Quoted 14 lines
Quoted 9 lines
Quoted 9 lines
I think it more readable if shortening
memory_mapping->phys_addrandmemmory_maping->lengthat the berinning of the innermost foreach loop.m_phys_addr = memory_mapping->phys_addr; m_length = memory_mapping->length;Then, each conditionals becomes compact.
Thanks.
HATAYAMA, Daisuke
RFC PATCH v7 5/14 target-i386: Add API to write elf notes to core file
In reply to Wen CongyangThe 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
@@ -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
@@ -3649,6 +3649,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
@@ -533,4 +533,27 @@ static inline int cpu_get_memory_mapping(MemoryMappingList *list, 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
RFC PATCH v7 6/14 target-i386: Add API to write cpu status to core file
In reply to Wen CongyangThe 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.
--- cpu-all.h | 20 ++++++ target-i386/arch_dump.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 174 insertions(+), 0 deletions(-)
cpu-all.h +20 -0
@@ -540,6 +540,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,
@@ -554,6 +558,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 +154 -0
157 lines not on this page · raw message
Signature · 1 line
1.7.1
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800
Quoted 12 lines
target-i386/arch_dump.c +12
-0+struct QEMUCPUState { +uint32_t version; +uint32_t size; +uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; +uint64_t r8, r9, r10, r11, r12, r13, r14, r15; +uint64_t rip, rflags; +QEMUCPUSegment cs, ds, es, fs, gs, ss; +QEMUCPUSegment ldt, tr, gdt, idt; +uint64_t cr[5 ]; +}; + +typedef struct QEMUCPUState QEMUCPUState ;
<cut>
target-i386/arch_dump.c int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, · line 287
Quoted 5 lines
target-i386/arch_dump.c +5
-0+static void qemu_get_cpustate (QEMUCPUState *s,CPUState *env) +{ +memset (s,0 ,sizeof (QEMUCPUState)); + + s->version =1 ;
It seems to me better to prepare a macro:
#define QEMUCPUSTATE_VERSION (1)
and use it as:
s->version = QEMUCPUSTATE_VERSION;
and add comment above the macro definition indicating: please count up QEMUCPUSTATE_VERSION if you have changed definition of QEMUCPUState, and modify the tools using this information accordingly.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
At 03/01/2012 01:01 PM, HATAYAMA Daisuke Wrote:
Quoted 27 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800Quoted 12 lines
target-i386/arch_dump.c +12
-0+struct QEMUCPUState { +uint32_t version; +uint32_t size; +uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; +uint64_t r8, r9, r10, r11, r12, r13, r14, r15; +uint64_t rip, rflags; +QEMUCPUSegment cs, ds, es, fs, gs, ss; +QEMUCPUSegment ldt, tr, gdt, idt; +uint64_t cr[5 ]; +}; + +typedef struct QEMUCPUState QEMUCPUState ;<cut>
target-i386/arch_dump.c int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, · line 287
Quoted 5 lines
target-i386/arch_dump.c +5
-0+static void qemu_get_cpustate (QEMUCPUState *s,CPUState *env) +{ +memset (s,0 ,sizeof (QEMUCPUState)); + + s->version =1 ;It seems to me better to prepare a macro:
#define QEMUCPUSTATE_VERSION (1)
Quoted 7 lines
and use it as:
s->version = QEMUCPUSTATE_VERSION;and add comment above the macro definition indicating: please count up
QEMUCPUSTATE_VERSIONif you have changed definition of QEMUCPUState, and modify the tools using this information accordingly.
Yes, I will fix it.
PS: Do you have any comment about QEMUCPUState? I think the content is enough to calculate phys_base now.
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 13:05:31 +0800
Quoted 32 lines
At 03/01/2012 01:01 PM, HATAYAMA Daisuke Wrote:
Quoted 31 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800Quoted 12 lines
target-i386/arch_dump.c +12
-0+struct QEMUCPUState { +uint32_t version; +uint32_t size; +uint64_t rax, rbx, rcx, rdx, rsi, rdi, rsp, rbp; +uint64_t r8, r9, r10, r11, r12, r13, r14, r15; +uint64_t rip, rflags; +QEMUCPUSegment cs, ds, es, fs, gs, ss; +QEMUCPUSegment ldt, tr, gdt, idt; +uint64_t cr[5 ]; +}; + +typedef struct QEMUCPUState QEMUCPUState ;<cut>
target-i386/arch_dump.c int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, · line 287
Quoted 5 lines
target-i386/arch_dump.c +5
-0+static void qemu_get_cpustate (QEMUCPUState *s,CPUState *env) +{ +memset (s,0 ,sizeof (QEMUCPUState)); + + s->version =1 ;It seems to me better to prepare a macro:
#define QEMUCPUSTATE_VERSION (1)and use it as:
s->version = QEMUCPUSTATE_VERSION;
Quoted 9 lines
Quoted 3 lines
and add comment above the macro definition indicating: please count up
QEMUCPUSTATE_VERSIONif you have changed definition of QEMUCPUState, and modify the tools using this information accordingly.Yes, I will fix it.
PS: Do you have any comment about QEMUCPUState? I think the content is enough to calculate
phys_basenow.
Yes, for the purpose it might be enough. But looking at CPUX86State, there are still useful states for debugging to know guest machine state at crash, such as device states, NMI states, TSC, etc.
For now, I think it's OK to pick up minimum kinds of registers only. If they are classified sufficiently in their types such as general registers, floating-point registers, control registers, processor features and so on, it's possible to add new note later easily.
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
In reply to Wen CongyangFrom: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800
Quoted 16 lines
target-i386/arch_dump.c +16
-0+int cpu_write_elf64_qemunote (write_core_dump_function f,CPUState *env, +target_phys_addr_t *offset,void *opaque) +{ +QEMUCPUState state; +Elf64_Nhdr *note; +char *buf; +int descsz, note_size, name_size =5 ; +const char *name ="QEMU" ; +int ret; + +qemu_get_cpustate (&state, env); + + descsz =sizeof (state); + note_size = ((sizeof (Elf32_Nhdr) +3 ) /4 + (name_size +3 ) /4 + + (descsz +3 ) /4 ) *4 ; + note =g_malloc (note_size);
target-i386/arch_dump.c int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, · line 354
Quoted 10 lines
target-i386/arch_dump.c +10
-0+ +memset (note,0 , note_size); + note->n_namesz =cpu_to_le32 (name_size); + note->n_descsz =cpu_to_le32 (descsz); + note->n_type =0 ; + buf = (char *)note; + buf += ((sizeof (Elf32_Nhdr) +3 ) /4 ) *4 ; +memcpy (buf, name, name_size); + buf += ((name_size +3 ) /4 ) *4 ; +memcpy (buf, &state,sizeof (state));
x86_64_write_elf64_note() and x86_write_elf64_note() does the same processing for note data. Is it better to do this in helper functions in common?
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
At 03/01/2012 01:10 PM, HATAYAMA Daisuke Wrote:
Quoted 26 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800Quoted 22 lines
target-i386/arch_dump.c +22
-0+int cpu_write_elf64_qemunote (write_core_dump_function f,CPUState *env, +target_phys_addr_t *offset,void *opaque) +{ +QEMUCPUState state; +Elf64_Nhdr *note; +char *buf; +int descsz, note_size, name_size =5 ; +const char *name ="QEMU" ; +int ret; + +qemu_get_cpustate (&state, env); + + descsz =sizeof (state); + note_size = ((sizeof (Elf32_Nhdr) +3 ) /4 + (name_size +3 ) /4 + + (descsz +3 ) /4 ) *4 ; + note =g_malloc (note_size); + +memset (note,0 , note_size); + note->n_namesz =cpu_to_le32 (name_size); + note->n_descsz =cpu_to_le32 (descsz); + note->n_type =0 ; + buf = (char *)note;
Quoted 8 lines
target-i386/arch_dump.c int cpu_write_elf32_note(write_core_dump_function f, CPUState *env, int cpuid, · line 354
Quoted 4 lines
target-i386/arch_dump.c +4
-0+ buf += ((sizeof (Elf32_Nhdr) +3 ) /4 ) *4 ; +memcpy (buf, name, name_size); + buf += ((name_size +3 ) /4 ) *4 ; +memcpy (buf, &state,sizeof (state));
x86_64_write_elf64_note()andx86_write_elf64_note()does the same processing for note data. Is it better to do this in helper functions in common?
I forgot to merge them. I will fix it.
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
In reply to Wen CongyangFrom: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800
Quoted 5 lines
target-i386/arch_dump.c +5
-0+int cpu_write_elf64_qemunote (write_core_dump_function f,CPUState *env, +target_phys_addr_t *offset,void *opaque) +{ +QEMUCPUState state; +Elf64_Nhdr *note;
<cut>
Quoted 1 line
+
note_size= ((sizeof(Elf32_Nhdr)+ 3) / 4 + (name_size+ 3) / 4 +
ELF64_Nhdr?
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
At 03/02/2012 09:09 AM, HATAYAMA Daisuke Wrote:
Quoted 12 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 06/14 v7] target-i386: Add API to write cpu status to core file
Date: Thu, 01 Mar 2012 10:48:17 +0800Quoted 5 lines
target-i386/arch_dump.c +5
-0+int cpu_write_elf64_qemunote (write_core_dump_function f,CPUState *env, +target_phys_addr_t *offset,void *opaque) +{ +QEMUCPUState state; +Elf64_Nhdr *note;<cut>
Quoted 3 lines
Quoted 1 line
+
note_size= ((sizeof(Elf32_Nhdr)+ 3) / 4 + (name_size+ 3) / 4 +ELF64_Nhdr?
Yes, it's my misss, and I will fix it.
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
RFC PATCH v7 7/14 target-i386: add API to get dump info
In reply to Wen CongyangDump 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
@@ -23,6 +23,7 @@#include "qemu-tls.h" #include "cpu-common.h" #include "memory_mapping.h" +#include "dump.h" /* some important defines: *
@@ -544,6 +545,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,
@@ -574,6 +576,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
@@ -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
@@ -13,6 +13,7 @@#include "cpu.h" #include "cpu-all.h" +#include "dump.h" #include "elf.h" #ifdef TARGET_X86_64
@@ -401,3 +402,36 @@ int cpu_write_elf32_qemunote(write_core_dump_function f, CPUState *env,return 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
RFC PATCH v7 8/14 make gdb_id() generally avialable
In reply to Wen CongyangThe 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
@@ -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
@@ -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
RFC PATCH v7 9/14 introduce a new monitor command 'dump' to dump guest's memory
In reply to Wen Congyang--- Makefile.target | 2 +- dump.c | 637 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ hmp-commands.hx | 20 ++ hmp.c | 9 + hmp.h | 1 + qapi-schema.json | 13 ++ qmp-commands.hx | 29 +++ 7 files changed, 710 insertions(+), 1 deletions(-) create mode 100644 dump.c
Makefile.target +1 -1
@@ -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 +637 -0
637 lines not on this page · raw message
hmp-commands.hx +20 -0
@@ -880,6 +880,26 @@ 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 = "file:s", + .params = "file", + .help = "dump to file", + .user_print = monitor_user_noop, + .mhandler.cmd = hmp_dump, + }, + + +STEXI +@item dump @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:") +ETEXI +#endif + { .name = "snapshot_blkdev", .args_type = "device:B,snapshot-file:s?,format:s?",
hmp.c +9 -0
@@ -856,3 +856,12 @@ 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 ; +const char *file =qdict_get_str (qdict,"file" ); + +qmp_dump (file, &errp); +hmp_handle_error (mon, &errp); +}
hmp.h +1 -0
@@ -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 +13 -0
@@ -1593,3 +1593,16 @@ { 'command': 'qom-list-types', 'data': { '*implements': 'str', '*abstract': 'bool' }, 'returns': [ 'ObjectTypeInfo' ] } + +## +# @dump +# +# Dump guest's memory to vmcore. +# +# @file: the filename or file descriptor of the vmcore. +# +# Returns: nothing on success +# +# Since: 1.1 +## +{ 'command': 'dump', 'data': { 'file': 'str' } }
qmp-commands.hx +29 -0
@@ -586,6 +586,35 @@ Example: EQMP +#if defined(CONFIG_HAVE_CORE_DUMP) + { + .name = "dump", + .args_type = "file:s", + .params = "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: + +- "file": destination file(started with "file:") or destination file descriptor + (started with "fd:") (json-string) + +Example: + +-> { "execute": "dump", "arguments": { "file": "fd:dump" } } +<- { "return": {} } + +EQMP +#endif + { .name = "netdev_add", .args_type = "netdev:O",
Signature · 1 line
1.7.1
Re: [Qemu-devel] [RFC][PATCH 09/14 v7] introduce a new monitor command 'dump' to dump guest's memory
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 09/14 v7] introduce a new monitor command 'dump' to dump guest's memory
Date: Thu, 01 Mar 2012 10:51:42 +0800
Quoted 4 lines
dump.c new file +4
-0+/* +* calculate phdr_num +* +* the type of phdr->num is uint16_t, so we should avoid overflow
dump.c line 553
Quoted 10 lines
dump.c new file +10
-0+*/ + s->phdr_num =1 ;/* PT_NOTE */ +if (s->list.num > (1 <<16 ) -2 ) { + s->phdr_num = (1 <<16 ) -1 ; + }else { + s->phdr_num += s->list.num; + } + +return s; +}
Though e_phnum is uint16_t at default, there's extension up to uint32_t. Look at relatively new manual page. This is from FC14's.
e_phnum This member holds the number of entries in the
program header table. Thus the product of
e_phentsize and e_phnum gives the table's size in bytes. If a file has no program header, e_phnum holds the value zero.
If the number of entries in the program header
table is larger than or equal to PN_XNUM
(0xffff), this member holds PN_XNUM (0xffff) and the real number of entries in the program header table is held in the sh_info member of the
initial entry in section header table.
Otherwise, the sh_info member of the initial entry contains the value zero.
PN_XNUM This is defined as 0xffff, the largest
number e_phnum can have, specifying where the actual number of program headers is assigned.
Recent kernel, gdb and tools in binutils supports this. But crash doesn't, so you need to fix this.
I'm interested in the number of program headers at worst case. According to Intel Programming Guide 3A, Table 4-1. shows physical-address width on IA-32e is up to 52 and linear-address width is 48. Can the number exceed this limit in theory? Also how many program headers are created typically?
Thanks.
HATAYAMA, Daisuke
Re: [Qemu-devel] [RFC][PATCH 09/14 v7] introduce a new monitor command 'dump' to dump guest's memory
At 03/01/2012 03:04 PM, HATAYAMA Daisuke Wrote:
Quoted 37 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 09/14 v7] introduce a new monitor command 'dump' to dump guest's memory
Date: Thu, 01 Mar 2012 10:51:42 +0800Quoted 4 lines
dump.c new file +4
-0+/* +* calculate phdr_num +* +* the type of phdr->num is uint16_t, so we should avoid overflow dump.c line 553
Quoted 10 lines
dump.c new file +10
-0+*/ + s->phdr_num =1 ;/* PT_NOTE */ +if (s->list.num > (1 <<16 ) -2 ) { + s->phdr_num = (1 <<16 ) -1 ; + }else { + s->phdr_num += s->list.num; + } + +return s; +}Though
e_phnumisuint16_tat default, there's extension up touint32_t. Look at relatively new manual page. This is from FC14's.
e_phnumThis member holds the number of entries in the
program header table. Thus the product of
e_phentsizeande_phnumgives the table's size in bytes. If a file has no program header,e_phnumholds the value zero.If the number of entries in the program header
table is larger than or equal toPN_XNUM
(0xffff), this member holdsPN_XNUM(0xffff) and the real number of entries in the program header table is held in thesh_infomember of the
initial entry in section header table.
Otherwise, thesh_infomember of the initial entry contains the value zero.
Quoted 4 lines
PN_XNUMThis is defined as0xffff, the largest
numbere_phnumcan have, specifying where the actual number of program headers is assigned.
Good news.
Quoted 3 lines
Recent kernel, gdb and tools in binutils supports this. But crash doesn't, so you need to fix this.
I think it can be easily fixed.
Quoted 6 lines
I'm interested in the number of program headers at worst case. According to Intel Programming Guide 3A, Table 4-1. shows physical-address width on IA-32e is up to 52 and linear-address width is 48. Can the number exceed this limit in theory? Also how many program headers are created typically?
In my test, the guest has 512M memory, and it contains about 1000~2000 program headers.
In theory, if the guest has 2^52 memory, the number can still exceed this limit. Tha maxnium number is 2^52/2^12
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
RFC PATCH v7 10/14 support to cancel the current dumping
In reply to Wen CongyangAdd API to allow the user to cancel the current dumping.
--- dump.c | 13 +++++++++++++ hmp-commands.hx | 14 ++++++++++++++ hmp.c | 5 +++++ hmp.h | 1 + qapi-schema.json | 13 +++++++++++++ qmp-commands.hx | 21 +++++++++++++++++++++ 6 files changed, 67 insertions(+), 0 deletions(-)
dump.c +13 -0
@@ -635,3 +635,16 @@ void qmp_dump(const char *file, Error **errp)return ; } + +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); +return ; +}
hmp-commands.hx +14 -0
@@ -901,6 +901,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
@@ -865,3 +865,8 @@ void hmp_dump(Monitor *mon, const QDict *qdict)qmp_dump (file, &errp);hmp_handle_error (mon, &errp); } + +void hmp_dump_cancel (Monitor *mon,const QDict *qdict) +{ +qmp_dump_cancel (NULL ); +}
hmp.h +1 -0
@@ -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
@@ -1606,3 +1606,16 @@ # Since: 1.1 ## { 'command': 'dump', 'data': { '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
@@ -616,6 +616,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
RFC PATCH v7 11/14 support to query dumping status
In reply to Wen CongyangAdd 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 | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 137 insertions(+), 0 deletions(-)
dump.c +32 -0
@@ -648,3 +648,35 @@ void qmp_dump_cancel(Error **errp)dump_cleanup (s);return ; } + +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
@@ -1434,6 +1434,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
@@ -870,3 +870,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
@@ -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
@@ -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
@@ -1619,3 +1619,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 +52 -0
64 lines not on this page · raw message
Signature · 1 line
1.7.1
RFC PATCH v7 12/14 run dump at the background
In reply to Wen CongyangThe 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
@@ -78,9 +78,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 )
@@ -98,6 +110,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 (); }
@@ -323,40 +341,70 @@ static int write_elf32_notes(DumpState *s, int phdr_index,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 ; } }
@@ -435,6 +483,7 @@ static int dump_begin(DumpState *s) } s->memory_offset = offset; + s->offset = offset;return 0 ; }
@@ -462,22 +511,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)
@@ -489,7 +581,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 ; }
@@ -497,6 +589,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 (Error **errp) {CPUState *env;
@@ -514,6 +617,9 @@ static DumpState *dump_init(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.
@@ -560,14 +666,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 ; }
@@ -576,10 +692,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,Error **errp) {DumpState *s =dump_init (errp);
@@ -590,7 +714,9 @@ static DumpState *dump_init_fd(int fd, 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
@@ -1248,11 +1248,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
RFC PATCH v7 13/14 support detached dump
In reply to Wen CongyangLet 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 | 3 ++- qmp-commands.hx | 7 +++++-- 5 files changed, 60 insertions(+), 10 deletions(-)
dump.c +1 -1
@@ -721,7 +721,7 @@ static DumpState *dump_init_fd(int fd, Error **errp)return s; } -void qmp_dump (const char *file,Error **errp) +void qmp_dump (bool detach,const char *file,Error **errp) {const char *p;int fd =-1 ;
hmp-commands.hx +5 -4
@@ -883,20 +883,21 @@ ETEXI #if defined(CONFIG_HAVE_CORE_DUMP) { .name = "dump", - .args_type = "file:s", - .params = "file", - .help = "dump to file", + .args_type = "detach:-d,file:s", + .params = "[-d] file", + .help = "dump to file (using -d to not wait for completion)", .user_print = monitor_user_noop, .mhandler.cmd = hmp_dump, }, STEXI -@item dump @var{file} +@item dump [-d] @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:") + -d: donot wait for completion. ETEXI #endif
hmp.c +47 -2
60 lines not on this page · raw message
qapi-schema.json +2 -1
@@ -1599,13 +1599,14 @@ # # Dump guest's memory to vmcore. # +# @detach: detached dumping. # @file: the filename or file descriptor of the vmcore. # # Returns: nothing on success # # Since: 1.1 ## -{ 'command': 'dump', 'data': { 'file': 'str' } } +{ 'command': 'dump', 'data': { 'detach': 'bool', 'file': 'str' } } ## # @dump_cancel
qmp-commands.hx +5 -2
@@ -589,8 +589,8 @@ EQMP #if defined(CONFIG_HAVE_CORE_DUMP) { .name = "dump", - .args_type = "file:s", - .params = "file", + .args_type = "detach:-d,file:s", + .params = "[-d] file", .help = "dump to file", .user_print = monitor_user_noop, .mhandler.cmd_new = qmp_marshal_input_dump,
@@ -616,6 +616,9 @@ Notes: (1) The 'info dump' command should be used to check dumping's progress and final result (this information is provided by the 'status' member) +(2) All boolean arguments default to false +(3) The user Monitor's "detach" argument is invalid in QMP and should not + be used EQMP #endif
Signature · 1 line
1.7.1
RFC PATCH v7 14/14 allow user to dump a fraction of the memory
In reply to Wen Congyang--- dump.c | 124 +++++++++++++++++++++++++++++++++++++++++++++++------ hmp-commands.hx | 14 ++++-- hmp.c | 13 +++++- memory_mapping.c | 27 ++++++++++++ memory_mapping.h | 2 + qapi-schema.json | 6 ++- qmp-commands.hx | 8 +++- 7 files changed, 172 insertions(+), 22 deletions(-)
dump.c +110 -14
@@ -91,6 +91,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;
@@ -413,17 +416,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; } - offset += block->length; + +if (phys_addr >= start && phys_addr < start + size_in_block) { +return phys_addr - start + offset; + } + + offset += size_in_block; }return -1 ;
@@ -495,7 +528,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 {
@@ -522,6 +555,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 ; }
@@ -600,7 +644,36 @@ static void dump_vm_state_change(void *opaque, int running, RunState state) } } -static DumpState *dump_init (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 has_filter,int64_t begin,int64_t length, +Error **errp) {CPUState *env;DumpState *s =dump_get_current ();
@@ -617,8 +690,16 @@ static DumpState *dump_init(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);/*
@@ -643,6 +724,10 @@ static DumpState *dump_init(Error **errp)memory_mapping_list_init (&s->list);qemu_get_guest_memory_mapping (&s->list); +if (s->has_filter) { +memory_mapping_filter (&s->list, s->begin, s->length); + } +/* * calculate phdr_num *
@@ -704,9 +789,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,Error **errp) +static DumpState *dump_init_fd (int fd,bool has_filter,int64_t begin, +int64_t length,Error **errp) { -DumpState *s =dump_init (errp); +DumpState *s =dump_init (has_filter, begin, length, errp);if (s ==NULL ) {return NULL ;
@@ -721,12 +807,22 @@ static DumpState *dump_init_fd(int fd, Error **errp)return s; } -void qmp_dump (bool detach,const char *file,Error **errp) +void qmp_dump (bool detach,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);
@@ -750,7 +846,7 @@ void qmp_dump(bool detach, const char *file, Error **errp)return ; } - s =dump_init_fd (fd, errp); + s =dump_init_fd (fd, has_begin, begin, length, errp);if (!s) {return ; }
hmp-commands.hx +10 -4
@@ -883,21 +883,27 @@ ETEXI #if defined(CONFIG_HAVE_CORE_DUMP) { .name = "dump", - .args_type = "detach:-d,file:s", - .params = "[-d] file", - .help = "dump to file (using -d to not wait for completion)", + .args_type = "detach:-d,file:s,begin:i?,length:i?", + .params = "[-d] 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] @var{file} +@item dump [-d] @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:") -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 +12 -1
@@ -885,8 +885,19 @@ void hmp_dump(Monitor *mon, const QDict *qdict)Error *errp =NULL ;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, file, &errp); +if (has_begin) { + begin =qdict_get_int (qdict,"begin" ); + } +if (has_length) { + length =qdict_get_int (qdict,"length" ); + } + +qmp_dump (!!detach, file, has_begin, begin, has_length, length, &errp);if (errp) {hmp_handle_error (mon, &errp);return ;
memory_mapping.c +27 -0
@@ -203,3 +203,30 @@ int qemu_get_guest_memory_mapping(MemoryMappingList *list)return 0 ; } + +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
@@ -49,4 +49,6 @@ void memory_mapping_list_init(MemoryMappingList *list);*/ int qemu_get_guest_memory_mapping (MemoryMappingList *list); +void memory_mapping_filter (MemoryMappingList *list,int64_t begin, +int64_t length);#endif
qapi-schema.json +5 -1
@@ -1601,12 +1601,16 @@ # # @detach: detached dumping. # @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', 'file': 'str' } } +{ 'command': 'dump', + 'data': { 'detach': 'bool', 'file': 'str', '*begin': 'int', + '*length': 'int' } } ## # @dump_cancel
qmp-commands.hx +6 -2
@@ -589,8 +589,8 @@ EQMP #if defined(CONFIG_HAVE_CORE_DUMP) { .name = "dump", - .args_type = "detach:-d,file:s", - .params = "[-d] file", + .args_type = "detach:-d,file:s,begin:i?,end:i?", + .params = "[-d] file [begin] [length]", .help = "dump to file", .user_print = monitor_user_noop, .mhandler.cmd_new = qmp_marshal_input_dump,
@@ -606,6 +606,10 @@ Arguments: - "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
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 00/14 v7] introducing a new, dedicated memory dump mechanism
Date: Thu, 01 Mar 2012 10:35:44 +0800
Quoted 9 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.htmlThe last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg01007.html
Quoted 6 lines
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 orx86_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.
Does this say the thing caused by gdb versions with no Dwarf V3 support? If so, it's better to write that too explicitly here.
Quoted 6 lines
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 calculatephys_base.
Again, you still need to fix crash utility to recover the 1st kernel's first 640kB physical memory that has been reserved during switch from 1st kernel to 2nd kernel.
Thanks.
HATAYAMA, Daisuke
At 03/01/2012 12:42 PM, HATAYAMA Daisuke Wrote:
Quoted 16 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 00/14 v7] introducing a new, dedicated memory dump mechanism
Date: Thu, 01 Mar 2012 10:35:44 +0800Quoted 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.htmlThe last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg01007.htmlWe have determined to introduce a new command dump to dump memory. The core file's format can be elf.
Quoted 6 lines
Quoted 3 lines
Note:
1. The guest should be x86 orx86_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.Does this say the thing caused by gdb versions with no Dwarf V3 support? If so, it's better to write that too explicitly here.
I donot know why gdb crashed, and I cannot reproduce this problem now.
Quoted 11 lines
Quoted 7 lines
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 calculatephys_base.Again, you still need to fix crash utility to recover the 1st kernel's first 640kB physical memory that has been reserved during switch from 1st kernel to 2nd kernel.
It is another work, I will try to do it in the future.
Thanks
Wen Congyang
Quoted 5 lines
Thanks.
HATAYAMA, Daisuke
From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 00/14 v7] introducing a new, dedicated memory dump mechanism
Date: Thu, 01 Mar 2012 13:16:47 +0800
Quoted 17 lines
At 03/01/2012 12:42 PM, HATAYAMA Daisuke Wrote:
Quoted 16 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 00/14 v7] introducing a new, dedicated memory dump mechanism
Date: Thu, 01 Mar 2012 10:35:44 +0800Quoted 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.htmlThe last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg01007.htmlWe have determined to introduce a new command dump to dump memory. The core file's format can be elf.
Quoted 9 lines
Quoted 6 lines
Quoted 3 lines
Note:
1. The guest should be x86 orx86_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.Does this say the thing caused by gdb versions with no Dwarf V3 support? If so, it's better to write that too explicitly here.
I donot know why gdb crashed, and I cannot reproduce this problem now.
Sorry. I meant Dwarf4. Recent GCC emits binary with Dwarf4 in default, and older GDBs cannot handle them although I don't know this is the same as what you saw.
Quoted 7 lines
Quoted 7 lines
Quoted 6 lines
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 calculatephys_base.
Quoted 6 lines
Quoted 3 lines
Again, you still need to fix crash utility to recover the 1st kernel's first 640kB physical memory that has been reserved during switch from 1st kernel to 2nd kernel.
It is another work, I will try to do it in the future.
Please.
Thanks.
HATAYAMA, Daisuke
At 03/02/2012 08:49 AM, HATAYAMA Daisuke Wrote:
Quoted 28 lines
From: Wen Congyang <[email protected]>
Subject: Re: [RFC][PATCH 00/14 v7] introducing a new, dedicated memory dump mechanism
Date: Thu, 01 Mar 2012 13:16:47 +0800Quoted 24 lines
At 03/01/2012 12:42 PM, HATAYAMA Daisuke Wrote:
Quoted 22 lines
From: Wen Congyang <[email protected]>
Subject: [RFC][PATCH 00/14 v7] introducing a new, dedicated memory dump mechanism
Date: Thu, 01 Mar 2012 10:35:44 +0800Quoted 9 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.htmlThe last version is here:
http://lists.nongnu.org/archive/html/qemu-devel/2012-02/msg01007.htmlQuoted 6 lines
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 orx86_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.Does this say the thing caused by gdb versions with no Dwarf V3 support? If so, it's better to write that too explicitly here.
Quoted 6 lines
Quoted 2 lines
I donot know why gdb crashed, and I cannot reproduce this problem now.
Sorry. I meant Dwarf4. Recent GCC emits binary with Dwarf4 in default, and older GDBs cannot handle them although I don't know this is the same as what you saw.
I guess it is not, as I cannot reproduce this problem.
Thanks
Wen Congyang
Quoted 21 lines
Quoted 8 lines
Quoted 8 lines
Quoted 7 lines
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 calculatephys_base.Quoted 6 lines
Quoted 3 lines
Again, you still need to fix crash utility to recover the 1st kernel's first 640kB physical memory that has been reserved during switch from 1st kernel to 2nd kernel.
It is another work, I will try to do it in the future.
Please.
Thanks.
HATAYAMA, Daisuke