From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:50498) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W6LIK-0005jP-1E for qemu-devel@nongnu.org; Thu, 23 Jan 2014 09:30:19 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1W6LI8-0005C2-Vd for qemu-devel@nongnu.org; Thu, 23 Jan 2014 09:30:11 -0500 Received: from e06smtp18.uk.ibm.com ([195.75.94.114]:37203) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1W6LI8-0005Bo-BJ for qemu-devel@nongnu.org; Thu, 23 Jan 2014 09:30:00 -0500 Received: from /spool/local by e06smtp18.uk.ibm.com with IBM ESMTP SMTP Gateway: Authorized Use Only! Violators will be prosecuted for from ; Thu, 23 Jan 2014 14:29:58 -0000 Received: from b06cxnps4074.portsmouth.uk.ibm.com (d06relay11.portsmouth.uk.ibm.com [9.149.109.196]) by d06dlp03.portsmouth.uk.ibm.com (Postfix) with ESMTP id 728381B0806B for ; Thu, 23 Jan 2014 14:29:20 +0000 (GMT) Received: from d06av07.portsmouth.uk.ibm.com (d06av07.portsmouth.uk.ibm.com [9.149.37.248]) by b06cxnps4074.portsmouth.uk.ibm.com (8.13.8/8.13.8/NCO v10.0) with ESMTP id s0NETgxl4325854 for ; Thu, 23 Jan 2014 14:29:42 GMT Received: from d06av07.portsmouth.uk.ibm.com (localhost [127.0.0.1]) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVout) with ESMTP id s0NETsRp020182 for ; Thu, 23 Jan 2014 09:29:54 -0500 Received: from [9.156.34.41] (tumanova.moscow-rstl.ru.ibm.com [9.156.34.41] (may be forged)) by d06av07.portsmouth.uk.ibm.com (8.14.4/8.14.4/NCO v10.0 AVin) with ESMTP id s0NETr2M020166 for ; Thu, 23 Jan 2014 09:29:53 -0500 Message-ID: <52E12761.70302@linux.vnet.ibm.com> Date: Thu, 23 Jan 2014 18:29:53 +0400 From: Ekaterina Tumanova MIME-Version: 1.0 References: <1389944779-31899-1-git-send-email-qiaonuohan@cn.fujitsu.com> <1389944779-31899-9-git-send-email-qiaonuohan@cn.fujitsu.com> In-Reply-To: <1389944779-31899-9-git-send-email-qiaonuohan@cn.fujitsu.com> Content-Type: text/plain; charset=ISO-8859-1; format=flowed Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [PATCH 08/13 v7] dump: add API to write dump header List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org On 01/17/2014 11:46 AM, qiaonuohan wrote: > the functions are used to write header of kdump-compressed format to vmcore. > Header of kdump-compressed format includes: > 1. common header: DiskDumpHeader32 / DiskDumpHeader64 > 2. sub header: KdumpSubHeader32 / KdumpSubHeader64 > 3. extra information: only elf notes here > > Signed-off-by: Qiao Nuohan > Reviewed-by: Laszlo Ersek > --- > dump.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++ > include/sysemu/dump.h | 96 +++++++++++++++++++++ > 2 files changed, 319 insertions(+), 0 deletions(-) > > diff --git a/dump.c b/dump.c > index bf7d31d..a7fdc3f 100644 > --- a/dump.c > +++ b/dump.c > @@ -778,6 +778,229 @@ static int buf_write_note(const void *buf, size_t size, void *opaque) > return 0; > } > > +/* write common header, sub header and elf note to vmcore */ > +static int create_header32(DumpState *s) > +{ > + int ret = 0; > + 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; > + uint32_t status = 0; > + uint64_t offset_note; > + > + /* write common header, the version of kdump-compressed format is 6th */ > + size = sizeof(DiskDumpHeader32); > + dh = g_malloc0(size); > + > + strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE)); > + dh->header_version = cpu_convert_to_target32(6, endian); > + block_size = s->page_size; > + dh->block_size = cpu_convert_to_target32(block_size, endian); > + 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->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); > + bitmap_blocks = DIV_ROUND_UP(s->len_dump_bitmap, block_size) * 2; > + dh->bitmap_blocks = cpu_convert_to_target32(bitmap_blocks, endian); > + memcpy(&(dh->utsname.machine), "i686", 4); I actually tried to use your patch on s390x, and the only problem I found is that you hardcode the architecture into the header in arch-independent dump.c file here. Then it becomes unreadable for crash utility on different architecture. If would be great, if you could somehow get rid of hardcoding the arch in create_header32/create_header64 and instead use the target arch. > + > + if (s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) { > + status |= DUMP_DH_COMPRESSED_ZLIB; > + } > +#ifdef CONFIG_LZO > + if (s->flag_compress & DUMP_DH_COMPRESSED_LZO) { > + status |= DUMP_DH_COMPRESSED_LZO; > + } > +#endif > +#ifdef CONFIG_SNAPPY > + if (s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) { > + status |= DUMP_DH_COMPRESSED_SNAPPY; > + } > +#endif > + dh->status = cpu_convert_to_target32(status, endian); > + > + if (write_buffer(s->fd, 0, dh, size) < 0) { > + dump_error(s, "dump: failed to write disk dump header.\n"); > + ret = -1; > + goto out; > + } > + > + /* write sub header */ > + size = sizeof(KdumpSubHeader32); > + 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); > + > + 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); > + > + if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS * > + block_size, kh, size) < 0) { > + dump_error(s, "dump: failed to write kdump sub header.\n"); > + ret = -1; > + goto out; > + } > + > + /* write note */ > + s->note_buf = g_malloc0(s->note_size); > + s->note_buf_offset = 0; > + > + /* use s->note_buf to store notes temporarily */ > + if (write_elf32_notes(buf_write_note, s) < 0) { > + ret = -1; > + goto out; > + } > + > + if (write_buffer(s->fd, offset_note, s->note_buf, > + s->note_size) < 0) { > + dump_error(s, "dump: failed to write notes"); > + ret = -1; > + goto out; > + } > + > + /* get offset of dump_bitmap */ > + s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size) * > + block_size; > + > + /* get offset of page */ > + s->offset_page = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size + bitmap_blocks) * > + block_size; > + > +out: > + g_free(dh); > + g_free(kh); > + g_free(s->note_buf); > + > + return ret; > +} > + > +/* write common header, sub header and elf note to vmcore */ > +static int create_header64(DumpState *s) > +{ > + int ret = 0; > + 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; > + uint32_t status = 0; > + uint64_t offset_note; > + > + /* write common header, the version of kdump-compressed format is 6th */ > + size = sizeof(DiskDumpHeader64); > + dh = g_malloc0(size); > + > + strncpy(dh->signature, KDUMP_SIGNATURE, strlen(KDUMP_SIGNATURE)); > + dh->header_version = cpu_convert_to_target32(6, endian); > + block_size = s->page_size; > + dh->block_size = cpu_convert_to_target32(block_size, endian); > + sub_hdr_size = sizeof(struct KdumpSubHeader64) + s->note_size; > + sub_hdr_size = DIV_ROUND_UP(sub_hdr_size, dh->block_size); > + dh->sub_hdr_size = cpu_convert_to_target32(sub_hdr_size, endian); > + /* 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); > + bitmap_blocks = DIV_ROUND_UP(s->len_dump_bitmap, dh->block_size) * 2; > + dh->bitmap_blocks = cpu_convert_to_target32(bitmap_blocks, endian); > + memcpy(&(dh->utsname.machine), "x86_64", 6); Same problem here > + > + if (s->flag_compress & DUMP_DH_COMPRESSED_ZLIB) { > + status |= DUMP_DH_COMPRESSED_ZLIB; > + } > +#ifdef CONFIG_LZO > + if (s->flag_compress & DUMP_DH_COMPRESSED_LZO) { > + status |= DUMP_DH_COMPRESSED_LZO; > + } > +#endif > +#ifdef CONFIG_SNAPPY > + if (s->flag_compress & DUMP_DH_COMPRESSED_SNAPPY) { > + status |= DUMP_DH_COMPRESSED_SNAPPY; > + } > +#endif > + dh->status = cpu_convert_to_target32(status, endian); > + > + if (write_buffer(s->fd, 0, dh, size) < 0) { > + dump_error(s, "dump: failed to write disk dump header.\n"); > + ret = -1; > + goto out; > + } > + > + /* write sub header */ > + size = sizeof(KdumpSubHeader64); > + 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); > + > + offset_note = DISKDUMP_HEADER_BLOCKS * dh->block_size + size; > + kh->offset_note = cpu_convert_to_target64(offset_note, endian); > + kh->note_size = cpu_convert_to_target64(s->note_size, endian); > + > + if (write_buffer(s->fd, DISKDUMP_HEADER_BLOCKS * > + dh->block_size, kh, size) < 0) { > + dump_error(s, "dump: failed to write kdump sub header.\n"); > + ret = -1; > + goto out; > + } > + > + /* write note */ > + s->note_buf = g_malloc0(s->note_size); > + s->note_buf_offset = 0; > + > + /* use s->note_buf to store notes temporarily */ > + if (write_elf64_notes(buf_write_note, s) < 0) { > + ret = -1; > + goto out; > + } > + > + if (write_buffer(s->fd, offset_note, s->note_buf, > + s->note_size) < 0) { > + dump_error(s, "dump: failed to write notes"); > + ret = -1; > + goto out; > + } > + > + /* get offset of dump_bitmap */ > + s->offset_dump_bitmap = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size) * > + block_size; > + > + /* get offset of page */ > + s->offset_page = (DISKDUMP_HEADER_BLOCKS + sub_hdr_size + bitmap_blocks) * > + block_size; > + > +out: > + g_free(dh); > + g_free(kh); > + g_free(s->note_buf); > + > + return ret; > +} > + > +static int write_dump_header(DumpState *s) > +{ > + if (s->dump_info.d_machine == EM_386) { > + return create_header32(s); > + } else { > + return create_header64(s); > + } > +} > + > static ram_addr_t get_start_block(DumpState *s) > { > GuestPhysBlock *block; > diff --git a/include/sysemu/dump.h b/include/sysemu/dump.h > index 995bf47..dfee238 100644 > --- a/include/sysemu/dump.h > +++ b/include/sysemu/dump.h > @@ -27,6 +27,19 @@ > #define pfn_to_paddr(X, page_shift) \ > (((unsigned long long)(X) + ARCH_PFN_OFFSET) << (page_shift)) > > +/* > + * flag for compressed format > + */ > +#define DUMP_DH_COMPRESSED_ZLIB (0x1) > +#define DUMP_DH_COMPRESSED_LZO (0x2) > +#define DUMP_DH_COMPRESSED_SNAPPY (0x4) > + > +#define KDUMP_SIGNATURE "KDUMP " > +#define SIG_LEN (sizeof(KDUMP_SIGNATURE) - 1) > +#define PHYS_BASE (0) > +#define DUMP_LEVEL (1) > +#define DISKDUMP_HEADER_BLOCKS (1) > + > typedef struct ArchDumpInfo { > int d_machine; /* Architecture */ > int d_endian; /* ELFDATA2LSB or ELFDATA2MSB */ > @@ -44,6 +57,89 @@ typedef struct QEMU_PACKED MakedumpfileDataHeader { > int64_t buf_size; > } MakedumpfileDataHeader; > > +typedef struct QEMU_PACKED NewUtsname { > + char sysname[65]; > + char nodename[65]; > + char release[65]; > + char version[65]; > + char machine[65]; > + char domainname[65]; > +} NewUtsname; > + > +typedef struct QEMU_PACKED DiskDumpHeader32 { > + char signature[SIG_LEN]; /* = "KDUMP " */ > + uint32_t header_version; /* Dump header version */ > + NewUtsname utsname; /* copy of system_utsname */ > + char timestamp[10]; /* Time stamp */ > + uint32_t status; /* Above flags */ > + uint32_t block_size; /* Size of a block in byte */ > + uint32_t sub_hdr_size; /* Size of arch dependent header in block */ > + uint32_t bitmap_blocks; /* Size of Memory bitmap in block */ > + uint32_t max_mapnr; /* = max_mapnr , > + obsoleted in header_version 6 */ > + uint32_t total_ram_blocks; /* Number of blocks should be written */ > + uint32_t device_blocks; /* Number of total blocks in dump device */ > + uint32_t written_blocks; /* Number of written blocks */ > + uint32_t current_cpu; /* CPU# which handles dump */ > + uint32_t nr_cpus; /* Number of CPUs */ > +} DiskDumpHeader32; > + > +typedef struct QEMU_PACKED DiskDumpHeader64 { > + char signature[SIG_LEN]; /* = "KDUMP " */ > + uint32_t header_version; /* Dump header version */ > + NewUtsname utsname; /* copy of system_utsname */ > + char timestamp[22]; /* Time stamp */ > + uint32_t status; /* Above flags */ > + uint32_t block_size; /* Size of a block in byte */ > + uint32_t sub_hdr_size; /* Size of arch dependent header in block */ > + uint32_t bitmap_blocks; /* Size of Memory bitmap in block */ > + uint32_t max_mapnr; /* = max_mapnr, > + obsoleted in header_version 6 */ > + uint32_t total_ram_blocks; /* Number of blocks should be written */ > + uint32_t device_blocks; /* Number of total blocks in dump device */ > + uint32_t written_blocks; /* Number of written blocks */ > + uint32_t current_cpu; /* CPU# which handles dump */ > + uint32_t nr_cpus; /* Number of CPUs */ > +} DiskDumpHeader64; > + > +typedef struct QEMU_PACKED KdumpSubHeader32 { > + uint32_t phys_base; > + uint32_t dump_level; /* header_version 1 and later */ > + uint32_t split; /* header_version 2 and later */ > + uint32_t start_pfn; /* header_version 2 and later, > + obsoleted in header_version 6 */ > + uint32_t end_pfn; /* header_version 2 and later, > + obsoleted in header_version 6 */ > + uint64_t offset_vmcoreinfo; /* header_version 3 and later */ > + uint32_t size_vmcoreinfo; /* header_version 3 and later */ > + uint64_t offset_note; /* header_version 4 and later */ > + uint32_t note_size; /* header_version 4 and later */ > + uint64_t offset_eraseinfo; /* header_version 5 and later */ > + uint32_t size_eraseinfo; /* header_version 5 and later */ > + uint64_t start_pfn_64; /* header_version 6 and later */ > + uint64_t end_pfn_64; /* header_version 6 and later */ > + uint64_t max_mapnr_64; /* header_version 6 and later */ > +} KdumpSubHeader32; > + > +typedef struct QEMU_PACKED KdumpSubHeader64 { > + uint64_t phys_base; > + uint32_t dump_level; /* header_version 1 and later */ > + uint32_t split; /* header_version 2 and later */ > + uint64_t start_pfn; /* header_version 2 and later, > + obsoleted in header_version 6 */ > + uint64_t end_pfn; /* header_version 2 and later, > + obsoleted in header_version 6 */ > + uint64_t offset_vmcoreinfo; /* header_version 3 and later */ > + uint64_t size_vmcoreinfo; /* header_version 3 and later */ > + uint64_t offset_note; /* header_version 4 and later */ > + uint64_t note_size; /* header_version 4 and later */ > + uint64_t offset_eraseinfo; /* header_version 5 and later */ > + uint64_t size_eraseinfo; /* header_version 5 and later */ > + uint64_t start_pfn_64; /* header_version 6 and later */ > + uint64_t end_pfn_64; /* header_version 6 and later */ > + uint64_t max_mapnr_64; /* header_version 6 and later */ > +} KdumpSubHeader64; > + > struct GuestPhysBlockList; /* memory_mapping.h */ > int cpu_get_dump_info(ArchDumpInfo *info, > const struct GuestPhysBlockList *guest_phys_blocks); >