little-endian dump for ppc64
v4 cover little-endian dump for ppc64
Hi,
Here are latest bits I have to support ppc64le guest dumps. Changes since v3 are:
- fixed altivec registers support (patch 2)
- kicked "virtio" out of the descriton of patch 3 since it won't rely on LPCR_ILE
The other two patches are unchanged. I resend the whole patch set in case Alex feels like applying it right away :P
Thanks.
---
Bharata B Rao (3):
dump: Make DumpState and endian conversion routines available for arch-specific dump code
target-ppc: Support dump for little endian ppc64
target-ppc: Set the correct endianness in ELF dump header
Greg Kurz (1):
target-ppc: ppc can be either endian
dump.c | 228 ++++++++++++++++--------------------------- include/sysemu/dump-arch.h | 28 +++++ include/sysemu/dump.h | 48 +++++++-- stubs/dump.c | 2 target-ppc/arch_dump.c | 107 +++++++++++++------- target-ppc/cpu-qom.h | 1 target-ppc/translate_init.c | 16 +++ 7 files changed, 241 insertions(+), 189 deletions(-) create mode 100644 include/sysemu/dump-arch.h
Signature · 1 line
Greg
PATCH v4 1/4 dump: Make DumpState and endian conversion routines available for arch-specific dump code
From: Bharata B Rao <[email protected]>
Make DumpState and endian conversion routines available for arch-specific dump code by moving into dump.h. DumpState will be needed by arch-specific dump code to access target endian information from DumpState->ArchDumpInfo. Also break the dependency of dump.h from stubs/dump.c by creating a separate dump-arch.h.
This patch doesn't change any functionality.
[ rebased on top of current master branch,
renamed endian helpers to cpu_to_dump{16,32,64}, pass a DumpState * argument to endian helpers, Greg Kurz <[email protected]> ]
---
No change
dump.c | 228 +++++++++++++++++--------------------------- include/sysemu/dump-arch.h | 28 +++++ include/sysemu/dump.h | 48 +++++++-- stubs/dump.c | 2 4 files changed, 154 insertions(+), 152 deletions(-) create mode 100644 include/sysemu/dump-arch.h
dump.c +87 -141
@@ -36,9 +36,9 @@#define ELF_MACHINE_UNAME "Unknown"#endif -static uint16_t cpu_convert_to_target16 (uint16_t val,int endian) +uint16_t cpu_to_dump16 (DumpState *s,uint16_t val) { -if (endian ==ELFDATA2LSB ) { +if (s->dump_info.d_endian ==ELFDATA2LSB ) { val =cpu_to_le16 (val); }else { val =cpu_to_be16 (val);
@@ -47,9 +47,9 @@ static uint16_t cpu_convert_to_target16(uint16_t val, int endian)return val; } -static uint32_t cpu_convert_to_target32 (uint32_t val,int endian) +uint32_t cpu_to_dump32 (DumpState *s,uint32_t val) { -if (endian ==ELFDATA2LSB ) { +if (s->dump_info.d_endian ==ELFDATA2LSB ) { val =cpu_to_le32 (val); }else { val =cpu_to_be32 (val);
@@ -58,9 +58,9 @@ static uint32_t cpu_convert_to_target32(uint32_t val, int endian)return val; } -static uint64_t cpu_convert_to_target64 (uint64_t val,int endian) +uint64_t cpu_to_dump64 (DumpState *s,uint64_t val) { -if (endian ==ELFDATA2LSB ) { +if (s->dump_info.d_endian ==ELFDATA2LSB ) { val =cpu_to_le64 (val); }else { val =cpu_to_be64 (val);
@@ -69,39 +69,6 @@ static uint64_t cpu_convert_to_target64(uint64_t val, int endian)return val; } -typedef struct DumpState { -GuestPhysBlockList guest_phys_blocks; -ArchDumpInfo dump_info; -MemoryMappingList list; -uint16_t phdr_num; -uint32_t sh_info; -bool have_section; -bool resume; -ssize_t note_size; -hwaddr memory_offset; -int fd; - -GuestPhysBlock *next_block; -ram_addr_t start; -bool has_filter; -int64_t begin; -int64_t length; -Error **errp; - -uint8_t *note_buf;/* buffer for notes */ -size_t note_buf_offset;/* the writing place in note_buf */ -uint32_t nr_cpus;/* number of guest's cpu */ -size_t page_size;/* guest's page size */ -uint32_t page_shift;/* guest's page shift */ -uint64_t max_mapnr;/* the biggest guest's phys-mem's number */ -size_t len_dump_bitmap;/* the size of the place used to store -dump_bitmap in vmcore */ -off_t offset_dump_bitmap;/* offset of dump_bitmap part in vmcore */ -off_t offset_page;/* offset of page part in vmcore */ -size_t num_dumpable;/* number of page that can be dumped */ -uint32_t flag_compress;/* indicate the compression format */ -}DumpState ; -static int dump_cleanup (DumpState *s) {int ret =0 ;
@@ -140,29 +107,25 @@ static int write_elf64_header(DumpState *s) {Elf64_Ehdr elf_header;int ret; -int endian = s->dump_info.d_endian;memset (&elf_header,0 ,sizeof (Elf64_Ehdr));memcpy (&elf_header,ELFMAG ,SELFMAG ); elf_header.e_ident[EI_CLASS ] =ELFCLASS64 ; elf_header.e_ident[EI_DATA ] = s->dump_info.d_endian; elf_header.e_ident[EI_VERSION ] =EV_CURRENT ; - elf_header.e_type =cpu_convert_to_target16 (ET_CORE , endian); - elf_header.e_machine =cpu_convert_to_target16 (s->dump_info.d_machine, - endian); - elf_header.e_version =cpu_convert_to_target32 (EV_CURRENT , endian); - elf_header.e_ehsize =cpu_convert_to_target16 (sizeof (elf_header), endian); - elf_header.e_phoff =cpu_convert_to_target64 (sizeof (Elf64_Ehdr), endian); - elf_header.e_phentsize =cpu_convert_to_target16 (sizeof (Elf64_Phdr), - endian); - elf_header.e_phnum =cpu_convert_to_target16 (s->phdr_num, endian); + elf_header.e_type =cpu_to_dump16 (s,ET_CORE ); + elf_header.e_machine =cpu_to_dump16 (s, s->dump_info.d_machine); + elf_header.e_version =cpu_to_dump32 (s,EV_CURRENT ); + elf_header.e_ehsize =cpu_to_dump16 (s,sizeof (elf_header)); + elf_header.e_phoff =cpu_to_dump64 (s,sizeof (Elf64_Ehdr)); + elf_header.e_phentsize =cpu_to_dump16 (s,sizeof (Elf64_Phdr)); + elf_header.e_phnum =cpu_to_dump16 (s, s->phdr_num);if (s->have_section) {uint64_t shoff =sizeof (Elf64_Ehdr) +sizeof (Elf64_Phdr) * s->sh_info; - elf_header.e_shoff =cpu_convert_to_target64 (shoff, endian); - elf_header.e_shentsize =cpu_convert_to_target16 (sizeof (Elf64_Shdr), - endian); - elf_header.e_shnum =cpu_convert_to_target16 (1 , endian); + elf_header.e_shoff =cpu_to_dump64 (s, shoff); + elf_header.e_shentsize =cpu_to_dump16 (s,sizeof (Elf64_Shdr)); + elf_header.e_shnum =cpu_to_dump16 (s,1 ); } ret =fd_write_vmcore (&elf_header,sizeof (elf_header), s);
@@ -178,29 +141,25 @@ static int write_elf32_header(DumpState *s) {Elf32_Ehdr elf_header;int ret; -int endian = s->dump_info.d_endian;memset (&elf_header,0 ,sizeof (Elf32_Ehdr));memcpy (&elf_header,ELFMAG ,SELFMAG ); elf_header.e_ident[EI_CLASS ] =ELFCLASS32 ; - elf_header.e_ident[EI_DATA ] = endian; + elf_header.e_ident[EI_DATA ] = s->dump_info.d_endian; elf_header.e_ident[EI_VERSION ] =EV_CURRENT ; - elf_header.e_type =cpu_convert_to_target16 (ET_CORE , endian); - elf_header.e_machine =cpu_convert_to_target16 (s->dump_info.d_machine, - endian); - elf_header.e_version =cpu_convert_to_target32 (EV_CURRENT , endian); - elf_header.e_ehsize =cpu_convert_to_target16 (sizeof (elf_header), endian); - elf_header.e_phoff =cpu_convert_to_target32 (sizeof (Elf32_Ehdr), endian); - elf_header.e_phentsize =cpu_convert_to_target16 (sizeof (Elf32_Phdr), - endian); - elf_header.e_phnum =cpu_convert_to_target16 (s->phdr_num, endian); + elf_header.e_type =cpu_to_dump16 (s,ET_CORE ); + elf_header.e_machine =cpu_to_dump16 (s, s->dump_info.d_machine); + elf_header.e_version =cpu_to_dump32 (s,EV_CURRENT ); + elf_header.e_ehsize =cpu_to_dump16 (s,sizeof (elf_header)); + elf_header.e_phoff =cpu_to_dump32 (s,sizeof (Elf32_Ehdr)); + elf_header.e_phentsize =cpu_to_dump16 (s,sizeof (Elf32_Phdr)); + elf_header.e_phnum =cpu_to_dump16 (s, s->phdr_num);if (s->have_section) {uint32_t shoff =sizeof (Elf32_Ehdr) +sizeof (Elf32_Phdr) * s->sh_info; - elf_header.e_shoff =cpu_convert_to_target32 (shoff, endian); - elf_header.e_shentsize =cpu_convert_to_target16 (sizeof (Elf32_Shdr), - endian); - elf_header.e_shnum =cpu_convert_to_target16 (1 , endian); + elf_header.e_shoff =cpu_to_dump32 (s, shoff); + elf_header.e_shentsize =cpu_to_dump16 (s,sizeof (Elf32_Shdr)); + elf_header.e_shnum =cpu_to_dump16 (s,1 ); } ret =fd_write_vmcore (&elf_header,sizeof (elf_header), s);
@@ -218,15 +177,14 @@ static int write_elf64_load(DumpState *s, MemoryMapping *memory_mapping, {Elf64_Phdr phdr;int ret; -int endian = s->dump_info.d_endian;memset (&phdr,0 ,sizeof (Elf64_Phdr)); - phdr.p_type =cpu_convert_to_target32 (PT_LOAD , endian); - phdr.p_offset =cpu_convert_to_target64 (offset, endian); - phdr.p_paddr =cpu_convert_to_target64 (memory_mapping->phys_addr, endian); - phdr.p_filesz =cpu_convert_to_target64 (filesz, endian); - phdr.p_memsz =cpu_convert_to_target64 (memory_mapping->length, endian); - phdr.p_vaddr =cpu_convert_to_target64 (memory_mapping->virt_addr, endian); + phdr.p_type =cpu_to_dump32 (s,PT_LOAD ); + phdr.p_offset =cpu_to_dump64 (s, offset); + phdr.p_paddr =cpu_to_dump64 (s, memory_mapping->phys_addr); + phdr.p_filesz =cpu_to_dump64 (s, filesz); + phdr.p_memsz =cpu_to_dump64 (s, memory_mapping->length); + phdr.p_vaddr =cpu_to_dump64 (s, memory_mapping->virt_addr);assert (memory_mapping->length >= filesz);
@@ -245,15 +203,14 @@ static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping, {Elf32_Phdr phdr;int ret; -int endian = s->dump_info.d_endian;memset (&phdr,0 ,sizeof (Elf32_Phdr)); - phdr.p_type =cpu_convert_to_target32 (PT_LOAD , endian); - phdr.p_offset =cpu_convert_to_target32 (offset, endian); - phdr.p_paddr =cpu_convert_to_target32 (memory_mapping->phys_addr, endian); - phdr.p_filesz =cpu_convert_to_target32 (filesz, endian); - phdr.p_memsz =cpu_convert_to_target32 (memory_mapping->length, endian); - phdr.p_vaddr =cpu_convert_to_target32 (memory_mapping->virt_addr, endian); + phdr.p_type =cpu_to_dump32 (s,PT_LOAD ); + phdr.p_offset =cpu_to_dump32 (s, offset); + phdr.p_paddr =cpu_to_dump32 (s, memory_mapping->phys_addr); + phdr.p_filesz =cpu_to_dump32 (s, filesz); + phdr.p_memsz =cpu_to_dump32 (s, memory_mapping->length); + phdr.p_vaddr =cpu_to_dump32 (s, memory_mapping->virt_addr);assert (memory_mapping->length >= filesz);
@@ -269,16 +226,15 @@ static int write_elf32_load(DumpState *s, MemoryMapping *memory_mapping,static int write_elf64_note (DumpState *s) {Elf64_Phdr phdr; -int endian = s->dump_info.d_endian;hwaddr begin = s->memory_offset - s->note_size;int ret;memset (&phdr,0 ,sizeof (Elf64_Phdr)); - phdr.p_type =cpu_convert_to_target32 (PT_NOTE , endian); - phdr.p_offset =cpu_convert_to_target64 (begin, endian); + phdr.p_type =cpu_to_dump32 (s,PT_NOTE ); + phdr.p_offset =cpu_to_dump64 (s, begin); phdr.p_paddr =0 ; - phdr.p_filesz =cpu_convert_to_target64 (s->note_size, endian); - phdr.p_memsz =cpu_convert_to_target64 (s->note_size, endian); + phdr.p_filesz =cpu_to_dump64 (s, s->note_size); + phdr.p_memsz =cpu_to_dump64 (s, s->note_size); phdr.p_vaddr =0 ; ret =fd_write_vmcore (&phdr,sizeof (Elf64_Phdr), s);
@@ -325,15 +281,14 @@ static int write_elf32_note(DumpState *s) {hwaddr begin = s->memory_offset - s->note_size;Elf32_Phdr phdr; -int endian = s->dump_info.d_endian;int ret;memset (&phdr,0 ,sizeof (Elf32_Phdr)); - phdr.p_type =cpu_convert_to_target32 (PT_NOTE , endian); - phdr.p_offset =cpu_convert_to_target32 (begin, endian); + phdr.p_type =cpu_to_dump32 (s,PT_NOTE ); + phdr.p_offset =cpu_to_dump32 (s, begin); phdr.p_paddr =0 ; - phdr.p_filesz =cpu_convert_to_target32 (s->note_size, endian); - phdr.p_memsz =cpu_convert_to_target32 (s->note_size, endian); + phdr.p_filesz =cpu_to_dump32 (s, s->note_size); + phdr.p_memsz =cpu_to_dump32 (s, s->note_size); phdr.p_vaddr =0 ; ret =fd_write_vmcore (&phdr,sizeof (Elf32_Phdr), s);
@@ -375,7 +330,6 @@ static int write_elf_section(DumpState *s, int type) {Elf32_Shdr shdr32;Elf64_Shdr shdr64; -int endian = s->dump_info.d_endian;int shdr_size;void *shdr;int ret;
@@ -383,12 +337,12 @@ static int write_elf_section(DumpState *s, int type)if (type ==0 ) { shdr_size =sizeof (Elf32_Shdr);memset (&shdr32,0 , shdr_size); - shdr32.sh_info =cpu_convert_to_target32 (s->sh_info, endian); + shdr32.sh_info =cpu_to_dump32 (s, s->sh_info); shdr = &shdr32; }else { shdr_size =sizeof (Elf64_Shdr);memset (&shdr64,0 , shdr_size); - shdr64.sh_info =cpu_convert_to_target32 (s->sh_info, endian); + shdr64.sh_info =cpu_to_dump32 (s, s->sh_info); shdr = &shdr64; }
@@ -796,7 +750,6 @@ static int create_header32(DumpState *s)DiskDumpHeader32 *dh =NULL ;KdumpSubHeader32 *kh =NULL ;size_t size; -int endian = s->dump_info.d_endian;uint32_t block_size;uint32_t sub_hdr_size;uint32_t bitmap_blocks;
@@ -808,18 +761,17 @@ static int create_header32(DumpState *s) dh =g_malloc0 (size);strncpy (dh->signature,KDUMP_SIGNATURE ,strlen (KDUMP_SIGNATURE )); - dh->header_version =cpu_convert_to_target32 (6 , endian); + dh->header_version =cpu_to_dump32 (s,6 ); block_size = s->page_size; - dh->block_size =cpu_convert_to_target32 (block_size, endian); + dh->block_size =cpu_to_dump32 (s, block_size); sub_hdr_size =sizeof (struct KdumpSubHeader32 ) + s->note_size; sub_hdr_size =DIV_ROUND_UP (sub_hdr_size, block_size); - dh->sub_hdr_size =cpu_convert_to_target32 (sub_hdr_size, endian); + dh->sub_hdr_size =cpu_to_dump32 (s, sub_hdr_size);/* dh->max_mapnr may be truncated, full 64bit is in kh.max_mapnr_64 */ - dh->max_mapnr =cpu_convert_to_target32 (MIN (s->max_mapnr,UINT_MAX ), - endian); - dh->nr_cpus =cpu_convert_to_target32 (s->nr_cpus, endian); + dh->max_mapnr =cpu_to_dump32 (s,MIN (s->max_mapnr,UINT_MAX )); + dh->nr_cpus =cpu_to_dump32 (s, s->nr_cpus); bitmap_blocks =DIV_ROUND_UP (s->len_dump_bitmap, block_size) *2 ; - dh->bitmap_blocks =cpu_convert_to_target32 (bitmap_blocks, endian); + dh->bitmap_blocks =cpu_to_dump32 (s, bitmap_blocks);strncpy (dh->utsname.machine,ELF_MACHINE_UNAME ,sizeof (dh->utsname.machine));if (s->flag_compress &DUMP_DH_COMPRESSED_ZLIB ) {
@@ -835,7 +787,7 @@ static int create_header32(DumpState *s) status |= DUMP_DH_COMPRESSED_SNAPPY; }#endif - dh->status =cpu_convert_to_target32 (status, endian); + dh->status =cpu_to_dump32 (s, status);if (write_buffer (s->fd,0 , dh, size) <0 ) {dump_error (s,"dump: failed to write disk dump header.\n" );
@@ -848,13 +800,13 @@ static int create_header32(DumpState *s) kh =g_malloc0 (size);/* 64bit max_mapnr_64 */ - kh->max_mapnr_64 =cpu_convert_to_target64 (s->max_mapnr, endian); - kh->phys_base =cpu_convert_to_target32 (PHYS_BASE , endian); - kh->dump_level =cpu_convert_to_target32 (DUMP_LEVEL , endian); + kh->max_mapnr_64 =cpu_to_dump64 (s, s->max_mapnr); + kh->phys_base =cpu_to_dump32 (s,PHYS_BASE ); + kh->dump_level =cpu_to_dump32 (s,DUMP_LEVEL ); offset_note =DISKDUMP_HEADER_BLOCKS * block_size + size; - kh->offset_note =cpu_convert_to_target64 (offset_note, endian); - kh->note_size =cpu_convert_to_target32 (s->note_size, endian); + kh->offset_note =cpu_to_dump64 (s, offset_note); + kh->note_size =cpu_to_dump32 (s, s->note_size);if (write_buffer (s->fd,DISKDUMP_HEADER_BLOCKS * block_size, kh, size) <0 ) {
@@ -903,7 +855,6 @@ static int create_header64(DumpState *s)DiskDumpHeader64 *dh =NULL ;KdumpSubHeader64 *kh =NULL ;size_t size; -int endian = s->dump_info.d_endian;uint32_t block_size;uint32_t sub_hdr_size;uint32_t bitmap_blocks;
@@ -915,18 +866,17 @@ static int create_header64(DumpState *s) dh =g_malloc0 (size);strncpy (dh->signature,KDUMP_SIGNATURE ,strlen (KDUMP_SIGNATURE )); - dh->header_version =cpu_convert_to_target32 (6 , endian); + dh->header_version =cpu_to_dump32 (s,6 ); block_size = s->page_size; - dh->block_size =cpu_convert_to_target32 (block_size, endian); + dh->block_size =cpu_to_dump32 (s, block_size); sub_hdr_size =sizeof (struct KdumpSubHeader64 ) + s->note_size; sub_hdr_size =DIV_ROUND_UP (sub_hdr_size, block_size); - dh->sub_hdr_size =cpu_convert_to_target32 (sub_hdr_size, endian); + dh->sub_hdr_size =cpu_to_dump32 (s, sub_hdr_size);/* dh->max_mapnr may be truncated, full 64bit is in kh.max_mapnr_64 */ - dh->max_mapnr =cpu_convert_to_target32 (MIN (s->max_mapnr,UINT_MAX ), - endian); - dh->nr_cpus =cpu_convert_to_target32 (s->nr_cpus, endian); + dh->max_mapnr =cpu_to_dump32 (s,MIN (s->max_mapnr,UINT_MAX )); + dh->nr_cpus =cpu_to_dump32 (s, s->nr_cpus); bitmap_blocks =DIV_ROUND_UP (s->len_dump_bitmap, block_size) *2 ; - dh->bitmap_blocks =cpu_convert_to_target32 (bitmap_blocks, endian); + dh->bitmap_blocks =cpu_to_dump32 (s, bitmap_blocks);strncpy (dh->utsname.machine,ELF_MACHINE_UNAME ,sizeof (dh->utsname.machine));if (s->flag_compress &DUMP_DH_COMPRESSED_ZLIB ) {
@@ -942,7 +892,7 @@ static int create_header64(DumpState *s) status |= DUMP_DH_COMPRESSED_SNAPPY; }#endif - dh->status =cpu_convert_to_target32 (status, endian); + dh->status =cpu_to_dump32 (s, status);if (write_buffer (s->fd,0 , dh, size) <0 ) {dump_error (s,"dump: failed to write disk dump header.\n" );
@@ -955,13 +905,13 @@ static int create_header64(DumpState *s) kh =g_malloc0 (size);/* 64bit max_mapnr_64 */ - kh->max_mapnr_64 =cpu_convert_to_target64 (s->max_mapnr, endian); - kh->phys_base =cpu_convert_to_target64 (PHYS_BASE , endian); - kh->dump_level =cpu_convert_to_target32 (DUMP_LEVEL , endian); + kh->max_mapnr_64 =cpu_to_dump64 (s, s->max_mapnr); + kh->phys_base =cpu_to_dump64 (s,PHYS_BASE ); + kh->dump_level =cpu_to_dump32 (s,DUMP_LEVEL ); offset_note =DISKDUMP_HEADER_BLOCKS * block_size + size; - kh->offset_note =cpu_convert_to_target64 (offset_note, endian); - kh->note_size =cpu_convert_to_target64 (s->note_size, endian); + kh->offset_note =cpu_to_dump64 (s, offset_note); + kh->note_size =cpu_to_dump64 (s, s->note_size);if (write_buffer (s->fd,DISKDUMP_HEADER_BLOCKS * block_size, kh, size) <0 ) {
@@ -1283,7 +1233,6 @@ static int write_dump_pages(DumpState *s)off_t offset_desc, offset_data;PageDescriptor pd, pd_zero;uint8_t *buf; -int endian = s->dump_info.d_endian;GuestPhysBlock *block_iter =NULL ;uint64_t pfn_iter;
@@ -1311,10 +1260,10 @@ static int write_dump_pages(DumpState *s)* init zero page's page_desc and page_data, because every zero page * uses the same page_data */ - pd_zero.size =cpu_convert_to_target32 (s->page_size, endian); - pd_zero.flags =cpu_convert_to_target32 (0 , endian); - pd_zero.offset =cpu_convert_to_target64 (offset_data, endian); - pd_zero.page_flags =cpu_convert_to_target64 (0 , endian); + pd_zero.size =cpu_to_dump32 (s, s->page_size); + pd_zero.flags =cpu_to_dump32 (s,0 ); + pd_zero.offset =cpu_to_dump64 (s, offset_data); + pd_zero.page_flags =cpu_to_dump64 (s,0 ); buf =g_malloc0 (s->page_size); ret =write_cache (&page_data, buf, s->page_size, false);g_free (buf);
@@ -1354,9 +1303,8 @@ static int write_dump_pages(DumpState *s)if ((s->flag_compress &DUMP_DH_COMPRESSED_ZLIB ) && (compress2 (buf_out, (uLongf *)&size_out, buf, s->page_size,Z_BEST_SPEED ) ==Z_OK ) && (size_out < s->page_size)) { - pd.flags =cpu_convert_to_target32 (DUMP_DH_COMPRESSED_ZLIB , - endian); - pd.size =cpu_convert_to_target32 (size_out, endian); + pd.flags =cpu_to_dump32 (s,DUMP_DH_COMPRESSED_ZLIB ); + pd.size =cpu_to_dump32 (s, size_out); ret =write_cache (&page_data, buf_out, size_out, false);if (ret <0 ) {
@@ -1368,9 +1316,8 @@ static int write_dump_pages(DumpState *s) (lzo1x_1_compress (buf, s->page_size, buf_out, (lzo_uint *)&size_out, wrkmem) ==LZO_E_OK ) && (size_out < s->page_size)) { - pd.flags = cpu_convert_to_target32(DUMP_DH_COMPRESSED_LZO, - endian); - pd.size =cpu_convert_to_target32 (size_out, endian); + pd.flags = cpu_to_dump32(s, DUMP_DH_COMPRESSED_LZO); + pd.size =cpu_to_dump32 (s, size_out); ret =write_cache (&page_data, buf_out, size_out, false);if (ret <0 ) {
@@ -1383,9 +1330,8 @@ static int write_dump_pages(DumpState *s) (snappy_compress ((char *)buf, s->page_size, (char *)buf_out, &size_out) ==SNAPPY_OK ) && (size_out < s->page_size)) { - pd.flags = cpu_convert_to_target32( -DUMP_DH_COMPRESSED_SNAPPY , endian); - pd.size =cpu_convert_to_target32 (size_out, endian); + pd.flags = cpu_to_dump32(s, DUMP_DH_COMPRESSED_SNAPPY); + pd.size =cpu_to_dump32 (s, size_out); ret =write_cache (&page_data, buf_out, size_out, false);if (ret <0 ) {
@@ -1398,9 +1344,9 @@ static int write_dump_pages(DumpState *s)* fall back to save in plaintext, size_out should be * assigned to s->page_size */ - pd.flags =cpu_convert_to_target32 (0 , endian); + pd.flags =cpu_to_dump32 (s,0 ); size_out = s->page_size; - pd.size =cpu_convert_to_target32 (size_out, endian); + pd.size =cpu_to_dump32 (s, size_out); ret =write_cache (&page_data, buf, s->page_size, false);if (ret <0 ) {
@@ -1410,8 +1356,8 @@ static int write_dump_pages(DumpState *s) }/* get and write page desc here */ - pd.page_flags =cpu_convert_to_target64 (0 , endian); - pd.offset =cpu_convert_to_target64 (offset_data, endian); + pd.page_flags =cpu_to_dump64 (s,0 ); + pd.offset =cpu_to_dump64 (s, offset_data); offset_data += size_out; ret =write_cache (&page_desc, &pd,sizeof (PageDescriptor), false);
include/sysemu/dump-arch.h new file +28 -0
@@ -0,0 +1,28 @@ +/* +* 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 or later. +* See the COPYING file in the top-level directory. +* +*/ + +#ifndef DUMP_ARCH_H +#define DUMP_ARCH_H + +typedef struct ArchDumpInfo { +int d_machine;/* Architecture */ +int d_endian;/* ELFDATA2LSB or ELFDATA2MSB */ +int d_class;/* ELFCLASS32 or ELFCLASS64 */ +}ArchDumpInfo ; + +struct GuestPhysBlockList ;/* memory_mapping.h */ +int cpu_get_dump_info (ArchDumpInfo *info, +const struct GuestPhysBlockList *guest_phys_blocks); +ssize_t cpu_get_note_size (int class,int machine,int nr_cpus); + +#endif
include/sysemu/dump.h +38 -10
58 lines not on this page · raw message
stubs/dump.c +1 -1
@@ -12,7 +12,7 @@*/ #include "qemu-common.h" -#include "sysemu/dump.h" +#include "sysemu/dump-arch.h" #include "qapi/qmp/qerror.h" #include "qmp-commands.h"
PATCH v4 2/4 target-ppc: Support dump for little endian ppc64
In reply to Greg KurzFrom: Bharata B Rao <[email protected]>
Fix ppc64 arch specific dump code to support all combinations of little/big endian hosts/guests. FWIW the current code is broken for altivec registers when guest and host have a different endianness: these 128-bit registers are written to guest memory as a two 64-bit entities and we should also swap them.
Unit testing was done with the following program provided by Tom Musta:
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
int main(int argc, char** argv)
{
__uint128_t v = ((__uint128_t)0x0001020304050607ull << 64) | 0x08090a0b0c0d0e0full;
register void * vptr asm ("r11");
vptr = &v;
for(;;)
asm volatile ("lvx 30,0,11" );
}
When sending SIGABRT to this program and examining the core file, we get:
- ppc64 : 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
- ppc64le: 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
We expect to find the very same layout in the QEMU dump since they are real core files. This is what we get:
- ppc64 host, ppc64 guest : 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
- ppc64 host, ppc64le guest : 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
- x86_64 host, ppc64 guest : 00 01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f
- x86_64 host, ppc64le guest: 0f 0e 0d 0c 0b 0a 09 08 07 06 05 04 03 02 01 00
We introduce a NoteFuncArg type to avoid adding extra arguments to all note functions.
[ rebased on top of current master branch,
introduced NoteFuncArg,
use new cpu_to_dump{16,32,64} endian helpers,
fix altivec support,
Greg Kurz <[email protected]> ]
---
Changes since v3:
Fixed AltiVec.
target-ppc/arch_dump.c | 95 +++++++++++++++++++++++++++++++----------------- 1 file changed, 62 insertions(+), 33 deletions(-)
target-ppc/arch_dump.c +62 -33
@@ -79,94 +79,122 @@ typedef struct noteStruct { } contents; }QEMU_PACKED Note; +typedef struct NoteFuncArg { +Note note; +DumpState *state; +}NoteFuncArg ; -static void ppc64_write_elf64_prstatus (Note *note,PowerPCCPU *cpu) +static void ppc64_write_elf64_prstatus (NoteFuncArg *arg,PowerPCCPU *cpu) {int i;uint64_t cr;struct PPC64ElfPrstatus *prstatus;struct PPC64UserRegStruct *reg; +Note *note = &arg->note; +DumpState *s = arg->state; - note->hdr.n_type =cpu_to_be32 (NT_PRSTATUS ); + note->hdr.n_type =cpu_to_dump32 (s,NT_PRSTATUS ); prstatus = ¬e->contents.prstatus;memset (prstatus,0 ,sizeof (*prstatus)); reg = &prstatus->pr_reg;for (i =0 ; i <32 ; i++) { - reg->gpr[i] =cpu_to_be64 (cpu->env.gpr[i]); + reg->gpr[i] =cpu_to_dump64 (s, cpu->env.gpr[i]); } - reg->nip =cpu_to_be64 (cpu->env.nip); - reg->msr =cpu_to_be64 (cpu->env.msr); - reg->ctr =cpu_to_be64 (cpu->env.ctr); - reg->link =cpu_to_be64 (cpu->env.lr); - reg->xer =cpu_to_be64 (cpu_read_xer (&cpu->env)); + reg->nip =cpu_to_dump64 (s, cpu->env.nip); + reg->msr =cpu_to_dump64 (s, cpu->env.msr); + reg->ctr =cpu_to_dump64 (s, cpu->env.ctr); + reg->link =cpu_to_dump64 (s, cpu->env.lr); + reg->xer =cpu_to_dump64 (s,cpu_read_xer (&cpu->env)); cr =0 ;for (i =0 ; i <8 ; i++) { cr |= (cpu->env.crf[i] &15 ) << (4 * (7 - i)); } - reg->ccr =cpu_to_be64 (cr); + reg->ccr =cpu_to_dump64 (s, cr); } -static void ppc64_write_elf64_fpregset (Note *note,PowerPCCPU *cpu) +static void ppc64_write_elf64_fpregset (NoteFuncArg *arg,PowerPCCPU *cpu) {int i;struct PPC64ElfFpregset *fpregset; +Note *note = &arg->note; +DumpState *s = arg->state; - note->hdr.n_type =cpu_to_be32 (NT_PRFPREG ); + note->hdr.n_type =cpu_to_dump32 (s,NT_PRFPREG ); fpregset = ¬e->contents.fpregset;memset (fpregset,0 ,sizeof (*fpregset));for (i =0 ; i <32 ; i++) { - fpregset->fpr[i] =cpu_to_be64 (cpu->env.fpr[i]); + fpregset->fpr[i] =cpu_to_dump64 (s, cpu->env.fpr[i]); } - fpregset->fpscr =cpu_to_be64 (cpu->env.fpscr); + fpregset->fpscr =cpu_to_dump64 (s, cpu->env.fpscr); } -static void ppc64_write_elf64_vmxregset (Note *note,PowerPCCPU *cpu) +static void ppc64_write_elf64_vmxregset (NoteFuncArg *arg,PowerPCCPU *cpu) {int i;struct PPC64ElfVmxregset *vmxregset; +Note *note = &arg->note; +DumpState *s = arg->state; - note->hdr.n_type =cpu_to_be32 (NT_PPC_VMX ); + note->hdr.n_type =cpu_to_dump32 (s,NT_PPC_VMX ); vmxregset = ¬e->contents.vmxregset;memset (vmxregset,0 ,sizeof (*vmxregset));for (i =0 ; i <32 ; i++) { - vmxregset->avr[i].u64[0 ] =cpu_to_be64 (cpu->env.avr[i].u64[0 ]); - vmxregset->avr[i].u64[1 ] =cpu_to_be64 (cpu->env.avr[i].u64[1 ]); +bool needs_byteswap; + +#ifdef HOST_WORDS_BIGENDIAN + needs_byteswap = s->dump_info.d_endian ==ELFDATA2LSB ; +#else + needs_byteswap = s->dump_info.d_endian ==ELFDATA2MSB ; +#endif + +if (needs_byteswap) { + vmxregset->avr[i].u64[0 ] =bswap64 (cpu->env.avr[i].u64[1 ]); + vmxregset->avr[i].u64[1 ] =bswap64 (cpu->env.avr[i].u64[0 ]); + }else { + vmxregset->avr[i].u64[0 ] = cpu->env.avr[i].u64[0 ]; + vmxregset->avr[i].u64[1 ] = cpu->env.avr[i].u64[1 ]; + } } - vmxregset->vscr.u32[3 ] =cpu_to_be32 (cpu->env.vscr); + vmxregset->vscr.u32[3 ] =cpu_to_dump32 (s, cpu->env.vscr); } -static void ppc64_write_elf64_vsxregset (Note *note,PowerPCCPU *cpu) +static void ppc64_write_elf64_vsxregset (NoteFuncArg *arg,PowerPCCPU *cpu) {int i;struct PPC64ElfVsxregset *vsxregset; +Note *note = &arg->note; +DumpState *s = arg->state; - note->hdr.n_type =cpu_to_be32 (NT_PPC_VSX ); + note->hdr.n_type =cpu_to_dump32 (s,NT_PPC_VSX ); vsxregset = ¬e->contents.vsxregset;memset (vsxregset,0 ,sizeof (*vsxregset));for (i =0 ; i <32 ; i++) { - vsxregset->vsr[i] =cpu_to_be64 (cpu->env.vsr[i]); + vsxregset->vsr[i] =cpu_to_dump64 (s, cpu->env.vsr[i]); } } -static void ppc64_write_elf64_speregset (Note *note,PowerPCCPU *cpu) +static void ppc64_write_elf64_speregset (NoteFuncArg *arg,PowerPCCPU *cpu) {struct PPC64ElfSperegset *speregset; - note->hdr.n_type =cpu_to_be32 (NT_PPC_SPE ); +Note *note = &arg->note; +DumpState *s = arg->state; + + note->hdr.n_type =cpu_to_dump32 (s,NT_PPC_SPE ); speregset = ¬e->contents.speregset;memset (speregset,0 ,sizeof (*speregset)); - speregset->spe_acc =cpu_to_be64 (cpu->env.spe_acc); - speregset->spe_fscr =cpu_to_be32 (cpu->env.spe_fscr); + speregset->spe_acc =cpu_to_dump64 (s, cpu->env.spe_acc); + speregset->spe_fscr =cpu_to_dump32 (s, cpu->env.spe_fscr); }static const struct NoteFuncDescStruct {int contents_size; -void (*note_contents_func)(Note *note,PowerPCCPU *cpu); +void (*note_contents_func)(NoteFuncArg *arg,PowerPCCPU *cpu); } note_func[] = { {sizeof (((Note *)0 )->contents.prstatus), ppc64_write_elf64_prstatus}, {sizeof (((Note *)0 )->contents.fpregset), ppc64_write_elf64_fpregset},
@@ -218,20 +246,21 @@ static int ppc64_write_all_elf64_notes(const char *note_name, PowerPCCPU *cpu, int id, void *opaque) { - Note note; + NoteFuncArg arg = { .state = opaque };int ret =-1 ;int note_size;const NoteFuncDesc *nf;for (nf = note_func; nf->note_contents_func; nf++) { - note.hdr.n_namesz =cpu_to_be32 (sizeof (note.name)); - note.hdr.n_descsz =cpu_to_be32 (nf->contents_size); -strncpy (note.name, note_name,sizeof (note.name)); + arg.note.hdr.n_namesz =cpu_to_dump32 (opaque,sizeof (arg.note.name)); + arg.note.hdr.n_descsz =cpu_to_dump32 (opaque, nf->contents_size); +strncpy (arg.note.name, note_name,sizeof (arg.note.name)); - (*nf->note_contents_func)(¬e, cpu); + (*nf->note_contents_func)(&arg, cpu); - note_size =sizeof (note) -sizeof (note.contents) + nf->contents_size; - ret =f (¬e, note_size, opaque); + note_size = +sizeof (arg.note) -sizeof (arg.note.contents) + nf->contents_size; + ret =f (&arg.note, note_size, opaque);if (ret <0 ) {return -1 ; }
PATCH v4 3/4 target-ppc: ppc can be either endian
In reply to Greg KurzPOWER7, POWER7+ and POWER8 families use the ILE bit of the LPCR special purpose register to decide the endianness to use when entering interrupt handlers. When running a Linux guest, this provides a hint on the endianness used by the kernel. And when it comes to dumping a guest, the information is needed to write ELF headers using the kernel endianness.
---
Changes since v3:
updated description
target-ppc/cpu-qom.h | 1 + target-ppc/translate_init.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+)
target-ppc/cpu-qom.h +1 -0
@@ -76,6 +76,7 @@ typedef struct PowerPCCPUClass {int (*handle_mmu_fault)(PowerPCCPU *cpu,target_ulong eaddr,int rwx,int mmu_idx);#endif +bool (*interrupts_big_endian)(PowerPCCPU *cpu); } PowerPCCPUClass;/**
target-ppc/translate_init.c +16 -0
@@ -3102,6 +3102,18 @@ static int check_pow_hid0_74xx (CPUPPCState *env)return 0 ; } +static bool ppc_cpu_interrupts_big_endian_always (PowerPCCPU *cpu) +{ +return true; +} + +#ifdef TARGET_PPC64 +static bool ppc_cpu_interrupts_big_endian_lpcr (PowerPCCPU *cpu) +{ +return !(cpu->env.spr[SPR_LPCR ] &LPCR_ILE ); +} +#endif +/*****************************************************************************/ /* PowerPC implementations definitions */
@@ -7089,6 +7101,7 @@ POWERPC_FAMILY(POWER7)(ObjectClass *oc, void *data)POWERPC_FLAG_VSX ; pcc->l1_dcache_size =0x8000 ; pcc->l1_icache_size =0x8000 ; + pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; }POWERPC_FAMILY (POWER7P )(ObjectClass *oc, void *data)
@@ -7132,6 +7145,7 @@ POWERPC_FAMILY(POWER7P)(ObjectClass *oc, void *data)POWERPC_FLAG_VSX ; pcc->l1_dcache_size =0x8000 ; pcc->l1_icache_size =0x8000 ; + pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; }static void init_proc_POWER8 (CPUPPCState *env)
@@ -7189,6 +7203,7 @@ POWERPC_FAMILY(POWER8)(ObjectClass *oc, void *data)POWERPC_FLAG_VSX ; pcc->l1_dcache_size =0x8000 ; pcc->l1_icache_size =0x8000 ; + pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_lpcr; }#endif /* defined (TARGET_PPC64) */
@@ -8511,6 +8526,7 @@ static void ppc_cpu_class_init(ObjectClass *oc, void *data) pcc->parent_realize = dc->realize; pcc->pvr =CPU_POWERPC_DEFAULT_MASK ; pcc->pvr_mask =CPU_POWERPC_DEFAULT_MASK ; + pcc->interrupts_big_endian = ppc_cpu_interrupts_big_endian_always; dc->realize = ppc_cpu_realizefn; dc->unrealize = ppc_cpu_unrealizefn;
PATCH v4 4/4 target-ppc: Set the correct endianness in ELF dump header
In reply to Greg KurzFrom: Bharata B Rao <[email protected]>
---
No change.
target-ppc/arch_dump.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-)
target-ppc/arch_dump.c +8 -4
@@ -209,12 +209,16 @@ typedef struct NoteFuncDescStruct NoteFuncDesc;int cpu_get_dump_info (ArchDumpInfo *info,const struct GuestPhysBlockList *guest_phys_blocks) { -/* -* Currently only handling PPC64 big endian. -*/ +PowerPCCPU *cpu =POWERPC_CPU (first_cpu); +PowerPCCPUClass *pcc =POWERPC_CPU_GET_CLASS (cpu); + info->d_machine =EM_PPC64 ; - info->d_endian =ELFDATA2MSB ; info->d_class =ELFCLASS64 ; +if ((*pcc->interrupts_big_endian)(cpu)) { + info->d_endian =ELFDATA2MSB ; + }else { + info->d_endian =ELFDATA2LSB ; + }return 0 ; }
Alexander Graf
AppliedQuoted 10 lines · Greg Kurz
Hi,
Here are latest bits I have to support ppc64le guest dumps. Changes since v3 are:
- fixed altivec registers support (patch 2)
- kicked "virtio" out of the descriton of patch 3 since it won't rely onLPCR_ILEThe other two patches are unchanged. I resend the whole patch set in case Alex feels like applying it right away :P
I've changed the subject line of patch 3/4 to
target-ppc: Introduce callback for interrupt endianness
to make it more clear what the patch is doing. I've also fixed up patch 1/4 to apply on current master.
Thanks, applied to ppc-next.
Alex