Blame diskdump.c

Packit Service 501009
/* 
Packit Service 501009
 * diskdump.c 
Packit Service 501009
 * 
Packit Service 501009
 * The diskdump module optionally creates either ELF vmcore 
Packit Service 501009
 * dumpfiles, or compressed dumpfiles derived from the LKCD format.
Packit Service 501009
 * In the case of ELF vmcore files, since they are identical to 
Packit Service 501009
 * netdump dumpfiles, the facilities in netdump.c are used.  For
Packit Service 501009
 * compressed dumpfiles, the facilities in this file are used.
Packit Service 501009
 *
Packit Service 501009
 * Copyright (C) 2004-2015 David Anderson
Packit Service 501009
 * Copyright (C) 2004-2015 Red Hat, Inc. All rights reserved.
Packit Service 501009
 * Copyright (C) 2005  FUJITSU LIMITED
Packit Service 501009
 * Copyright (C) 2005  NEC Corporation
Packit Service 501009
 *
Packit Service 501009
 * This program is free software; you can redistribute it and/or modify
Packit Service 501009
 * it under the terms of the GNU General Public License as published by
Packit Service 501009
 * the Free Software Foundation; either version 2 of the License, or
Packit Service 501009
 * (at your option) any later version.
Packit Service 501009
 *
Packit Service 501009
 * This program is distributed in the hope that it will be useful,
Packit Service 501009
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 501009
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
Packit Service 501009
 * GNU General Public License for more details.
Packit Service 501009
 */
Packit Service 501009
Packit Service f083ce
#define LZO
Packit Service f083ce
#define SNAPPY
Packit Service 501009
#include "defs.h"
Packit Service 501009
#include "diskdump.h"
Packit Service 501009
#include "xen_dom0.h"
Packit Service 501009
#include "vmcore.h"
Packit Service 501009
Packit Service 501009
#define BITMAP_SECT_LEN	4096
Packit Service 501009
Packit Service 501009
struct diskdump_data {
Packit Service 501009
	char *filename;
Packit Service 501009
	ulong flags;       /* DISKDUMP_LOCAL, plus anything else... */
Packit Service 501009
        int dfd;           /* dumpfile file descriptor */
Packit Service 501009
        FILE *ofp;         /* fprintf(dd->ofp, "xxx"); */
Packit Service 501009
	int machine_type;  /* machine type identifier */
Packit Service 501009
Packit Service 501009
	/* header */
Packit Service 501009
	struct disk_dump_header		*header;
Packit Service 501009
	struct disk_dump_sub_header	*sub_header;
Packit Service 501009
	struct kdump_sub_header		*sub_header_kdump;
Packit Service 501009
Packit Service 501009
	unsigned long long	max_mapnr;	/* 64bit max_mapnr */
Packit Service 501009
Packit Service 501009
	size_t	data_offset;
Packit Service 501009
	int	block_size;
Packit Service 501009
	int	block_shift;
Packit Service 501009
	char	*bitmap;
Packit Service 501009
	off_t	bitmap_len;
Packit Service 501009
	char	*dumpable_bitmap;
Packit Service 501009
	int	byte, bit;
Packit Service 501009
	char	*compressed_page;	/* copy of compressed page data */
Packit Service 501009
	char	*curbufptr;		/* ptr to uncompressed page buffer */
Packit Service 501009
	unsigned char *notes_buf;	/* copy of elf notes */
Packit Service 501009
	void	**nt_prstatus_percpu;
Packit Service 501009
	uint	num_prstatus_notes;
Packit Service 501009
	void	**nt_qemu_percpu;
Packit Service 501009
	void	**nt_qemucs_percpu;
Packit Service 501009
	uint	num_qemu_notes;
Packit Service 501009
	void	**nt_vmcoredd_array;
Packit Service 501009
	uint	num_vmcoredd_notes;
Packit Service 501009
Packit Service 501009
	/* page cache */
Packit Service 501009
	struct page_cache_hdr {		/* header for each cached page */
Packit Service 501009
		uint32_t pg_flags;
Packit Service 501009
		uint64_t pg_addr;
Packit Service 501009
		char *pg_bufptr;
Packit Service 501009
		ulong pg_hit_count;
Packit Service 501009
	} page_cache_hdr[DISKDUMP_CACHED_PAGES];
Packit Service 501009
	char	*page_cache_buf;	/* base of cached buffer pages */
Packit Service 501009
	int	evict_index;		/* next page to evict */
Packit Service 501009
	ulong	evictions;		/* total evictions done */
Packit Service 501009
	ulong	cached_reads;
Packit Service 501009
	ulong  *valid_pages;
Packit Service 501009
	ulong   accesses;
Packit Service 501009
	ulong	snapshot_task;
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static struct diskdump_data diskdump_data = { 0 };
Packit Service 501009
static struct diskdump_data *dd = &diskdump_data;
Packit Service 501009
Packit Service 501009
ulong *diskdump_flags = &diskdump_data.flags;
Packit Service 501009
Packit Service 501009
static int __diskdump_memory_dump(FILE *);
Packit Service 501009
static void dump_vmcoreinfo(FILE *);
Packit Service 501009
static void dump_note_offsets(FILE *);
Packit Service 501009
static char *vmcoreinfo_read_string(const char *);
Packit Service 501009
static void diskdump_get_osrelease(void);
Packit Service 501009
static int valid_note_address(unsigned char *);
Packit Service 501009
Packit Service 501009
/* For split dumpfile */
Packit Service 501009
static struct diskdump_data **dd_list = NULL;
Packit Service 501009
static int num_dd = 0;
Packit Service 501009
static int num_dumpfiles = 0;
Packit Service 501009
Packit Service 501009
int dumpfile_is_split(void)
Packit Service 501009
{
Packit Service 501009
	return KDUMP_SPLIT();
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
map_cpus_to_prstatus_kdump_cmprs(void)
Packit Service 501009
{
Packit Service 501009
	void **nt_ptr;
Packit Service 501009
	int online, i, j, nrcpus;
Packit Service 501009
	size_t size;
Packit Service 501009
Packit Service 501009
	if (pc->flags2 & QEMU_MEM_DUMP_COMPRESSED)  /* notes exist for all cpus */
Packit Service 501009
		goto resize_note_pointers;
Packit Service 501009
Packit Service 501009
	if (!(online = get_cpus_online()) || (online == kt->cpus) || 
Packit Service 501009
	    machine_type("ARM64"))
Packit Service 501009
		goto resize_note_pointers;
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		error(INFO,
Packit Service 501009
		    "cpus: %d online: %d NT_PRSTATUS notes: %d (remapping)\n",
Packit Service 501009
			kt->cpus, online, dd->num_prstatus_notes);
Packit Service 501009
Packit Service 501009
	size = NR_CPUS * sizeof(void *);
Packit Service 501009
Packit Service 501009
	nt_ptr = (void **)GETBUF(size);
Packit Service 501009
	BCOPY(dd->nt_prstatus_percpu, nt_ptr, size);
Packit Service 501009
	BZERO(dd->nt_prstatus_percpu, size);
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 *  Re-populate the array with the notes mapping to online cpus
Packit Service 501009
	 */
Packit Service 501009
	nrcpus = (kt->kernel_NR_CPUS ? kt->kernel_NR_CPUS : NR_CPUS);
Packit Service 501009
Packit Service 501009
	for (i = 0, j = 0; i < nrcpus; i++) {
Packit Service 501009
		if (in_cpu_map(ONLINE_MAP, i)) {
Packit Service 501009
			dd->nt_prstatus_percpu[i] = nt_ptr[j++];
Packit Service 501009
			dd->num_prstatus_notes = 
Packit Service 501009
				MAX(dd->num_prstatus_notes, i+1);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	FREEBUF(nt_ptr);
Packit Service 501009
Packit Service 501009
resize_note_pointers:
Packit Service 501009
	/*
Packit Service 501009
	 *  For architectures that only utilize the note pointers
Packit Service 501009
	 *  within this file, resize the arrays accordingly.
Packit Service 501009
	 */
Packit Service 501009
	if (machine_type("X86_64") || machine_type("X86") || 
Packit Service 501009
	    machine_type("ARM64")) {
Packit Service 501009
		if ((dd->nt_prstatus_percpu = realloc(dd->nt_prstatus_percpu, 
Packit Service 501009
		    dd->num_prstatus_notes * sizeof(void *))) == NULL)
Packit Service 501009
			error(FATAL, 
Packit Service 501009
			    "compressed kdump: cannot realloc NT_PRSTATUS note pointers\n");
Packit Service 501009
		if (dd->num_qemu_notes) {
Packit Service 501009
			if  ((dd->nt_qemu_percpu = realloc(dd->nt_qemu_percpu, 
Packit Service 501009
		    	    dd->num_qemu_notes * sizeof(void *))) == NULL)
Packit Service 501009
				error(FATAL, 
Packit Service 501009
				    "compressed kdump: cannot realloc QEMU note pointers\n");
Packit Service 501009
			if  ((dd->nt_qemucs_percpu = realloc(dd->nt_qemucs_percpu,
Packit Service 501009
			    dd->num_qemu_notes * sizeof(void *))) == NULL)
Packit Service 501009
				error(FATAL,
Packit Service 501009
				    "compressed kdump: cannot realloc QEMU note pointers\n");
Packit Service 501009
		} else {
Packit Service 501009
			free(dd->nt_qemu_percpu);
Packit Service 501009
			free(dd->nt_qemucs_percpu);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
add_diskdump_data(char* name)
Packit Service 501009
{
Packit Service 501009
#define DDL_SIZE 16
Packit Service 501009
	int i;
Packit Service 501009
	int sz = sizeof(void *);
Packit Service 501009
	struct diskdump_data *ddp;
Packit Service 501009
Packit Service 501009
	if (dd_list == NULL) {
Packit Service 501009
		dd_list = calloc(DDL_SIZE, sz);
Packit Service 501009
		num_dd = DDL_SIZE;
Packit Service 501009
	} else {
Packit Service 501009
		for (i = 0; i < num_dumpfiles; i++) {
Packit Service 501009
			ddp = dd_list[i];
Packit Service 501009
                	if (same_file(ddp->filename, name))
Packit Service 501009
				error(FATAL, 
Packit Service 501009
				    "split dumpfiles are identical:\n"
Packit Service 501009
				    "  %s\n  %s\n",
Packit Service 501009
					ddp->filename, name);
Packit Service 501009
			if (memcmp(ddp->header, dd->header,
Packit Service 501009
			    sizeof(struct disk_dump_header)))
Packit Service 501009
				error(FATAL, 
Packit Service 501009
				    "split dumpfiles derived from different vmcores:\n"
Packit Service 501009
				    "  %s\n  %s\n",
Packit Service 501009
					ddp->filename, name);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (num_dumpfiles == num_dd) {
Packit Service 501009
		/* expand list */
Packit Service 501009
		struct diskdump_data **tmp;
Packit Service 501009
		tmp = calloc(num_dd*2, sz);
Packit Service 501009
		memcpy(tmp, dd_list, sz*num_dd);
Packit Service 501009
		free(dd_list);
Packit Service 501009
		dd_list = tmp;
Packit Service 501009
		num_dd *= 2;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	dd_list[num_dumpfiles] = dd;
Packit Service 501009
	dd->flags |= DUMPFILE_SPLIT;
Packit Service 501009
	dd->filename = name;
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		fprintf(fp, "%s: start_pfn=%llu, end_pfn=%llu\n", name,
Packit Service 501009
			dd->sub_header_kdump->start_pfn_64,
Packit Service 501009
			dd->sub_header_kdump->end_pfn_64);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
clean_diskdump_data(void)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	if (dd_list == NULL)
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	for (i=1; i
Packit Service 501009
		free(dd_list[i]); /* NOTE: dd_list[0] is static dd */
Packit Service 501009
Packit Service 501009
	free(dd_list);
Packit Service 501009
	dd_list = NULL;
Packit Service 501009
	num_dumpfiles = 0;
Packit Service 501009
	dd = &diskdump_data;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int 
Packit Service ef2397
get_bit(char *map, unsigned long byte, int bit)
Packit Service 501009
{
Packit Service 501009
	return map[byte] & (1<
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int 
Packit Service 501009
page_is_ram(unsigned long nr)
Packit Service 501009
{
Packit Service 501009
	return get_bit(dd->bitmap, nr >> 3, nr & 7);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int 
Packit Service 501009
page_is_dumpable(unsigned long nr)
Packit Service 501009
{
Packit Service 501009
	return dd->dumpable_bitmap[nr>>3] & (1 << (nr & 7));
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int 
Packit Service 501009
dump_is_partial(const struct disk_dump_header *header)
Packit Service 501009
{
Packit Service 501009
	return header->bitmap_blocks >=
Packit Service 501009
	    divideup(divideup(dd->max_mapnr, 8), dd->block_size) * 2;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int 
Packit Service 501009
open_dump_file(char *file)
Packit Service 501009
{
Packit Service 501009
	int fd;
Packit Service 501009
Packit Service 501009
	fd = open(file, O_RDONLY);
Packit Service 501009
	if (fd < 0) {
Packit Service 501009
		error(INFO, "diskdump / compressed kdump: unable to open dump file %s\n", file);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (KDUMP_SPLIT())
Packit Service 501009
		dd = calloc(1, sizeof(*dd));
Packit Service 501009
Packit Service 501009
	dd->dfd = fd;
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
process_elf32_notes(void *note_buf, unsigned long size_note)
Packit Service 501009
{
Packit Service 501009
	Elf32_Nhdr *nt;
Packit Service 501009
	size_t index, len = 0;
Packit Service 501009
	int num = 0;
Packit Service 501009
	int vmcoredd_num = 0;
Packit Service 501009
	int qemu_num = 0;
Packit Service 501009
Packit Service 501009
	for (index = 0; index < size_note; index += len) {
Packit Service 501009
		nt = note_buf + index;
Packit Service 501009
Packit Service 501009
		if (nt->n_type == NT_PRSTATUS) {
Packit Service 501009
			dd->nt_prstatus_percpu[num] = nt;
Packit Service 501009
			num++;
Packit Service 501009
		}
Packit Service 501009
		len = sizeof(Elf32_Nhdr);
Packit Service 501009
		if (STRNEQ((char *)nt + len, "QEMU")) {
Packit Service 501009
			ulong *ptr =
Packit Service 501009
			    (ulong *)((char *)nt + sizeof(Elf32_Nhdr) + nt->n_namesz);
Packit Service 501009
			dd->nt_qemucs_percpu[qemu_num] =
Packit Service 501009
			    (ulong *)roundup((ulong) ptr, 4);
Packit Service 501009
			dd->nt_qemu_percpu[qemu_num] = nt;
Packit Service 501009
			qemu_num++;
Packit Service 501009
		}
Packit Service 501009
		if (nt->n_type == NT_XEN_KDUMP_CR3 ||
Packit Service 501009
		    nt->n_type == XEN_ELFNOTE_CRASH_INFO) {
Packit Service 501009
			void *data = (char*)(nt + 1) +
Packit Service 501009
				roundup(nt->n_namesz, 4);
Packit Service 501009
			process_xen_note(nt->n_type, data, nt->n_descsz);
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (nt->n_type == NT_VMCOREDD &&
Packit Service 501009
		    vmcoredd_num < NR_DEVICE_DUMPS) {
Packit Service 501009
			dd->nt_vmcoredd_array[vmcoredd_num] = nt;
Packit Service 501009
			vmcoredd_num++;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		len = roundup(len + nt->n_namesz, 4);
Packit Service 501009
		len = roundup(len + nt->n_descsz, 4);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (num > 0) {
Packit Service 501009
		pc->flags2 |= ELF_NOTES;
Packit Service 501009
		dd->num_prstatus_notes = num;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (qemu_num > 0) {
Packit Service 501009
		pc->flags2 |= QEMU_MEM_DUMP_COMPRESSED;
Packit Service 501009
		dd->num_qemu_notes = qemu_num;
Packit Service 501009
	}
Packit Service 501009
	if (vmcoredd_num > 0)
Packit Service 501009
		dd->num_vmcoredd_notes = vmcoredd_num;
Packit Service 501009
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
process_elf64_notes(void *note_buf, unsigned long size_note)
Packit Service 501009
{
Packit Service 501009
	Elf64_Nhdr *nt;
Packit Service 501009
	size_t index, len = 0;
Packit Service 501009
	int num = 0;
Packit Service 501009
	int vmcoredd_num = 0;
Packit Service 501009
	int qemu_num = 0;
Packit Service 501009
Packit Service 501009
	for (index = 0; index < size_note; index += len) {
Packit Service 501009
		nt = note_buf + index;
Packit Service 501009
Packit Service 501009
		if (nt->n_type == NT_PRSTATUS) {
Packit Service 501009
			dd->nt_prstatus_percpu[num] = nt;
Packit Service 501009
			num++;
Packit Service 501009
		}
Packit Service 501009
		if ((nt->n_type == NT_TASKSTRUCT) && 
Packit Service 501009
		    (STRNEQ((char *)nt + sizeof(Elf64_Nhdr), "SNAP"))) {
Packit Service 501009
			pc->flags2 |= (LIVE_DUMP|SNAP);
Packit Service 501009
			dd->snapshot_task = 
Packit Service 501009
			    *((ulong *)((char *)nt + sizeof(Elf64_Nhdr) + nt->n_namesz));
Packit Service 501009
		}
Packit Service 501009
		len = sizeof(Elf64_Nhdr);
Packit Service 501009
		if (STRNEQ((char *)nt + len, "QEMU")) {
Packit Service 501009
			ulong *ptr =
Packit Service 501009
			    (ulong *)((char *)nt + sizeof(Elf64_Nhdr) + nt->n_namesz);
Packit Service 501009
			dd->nt_qemucs_percpu[qemu_num] =
Packit Service 501009
			    (ulong *)roundup((ulong) ptr, 4);
Packit Service 501009
			dd->nt_qemu_percpu[qemu_num] = nt;
Packit Service 501009
			qemu_num++;
Packit Service 501009
		}
Packit Service 501009
		if (nt->n_type == NT_XEN_KDUMP_CR3 ||
Packit Service 501009
		    nt->n_type == XEN_ELFNOTE_CRASH_INFO) {
Packit Service 501009
			void *data = (char*)(nt + 1) +
Packit Service 501009
				roundup(nt->n_namesz, 4);
Packit Service 501009
			process_xen_note(nt->n_type, data, nt->n_descsz);
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (nt->n_type == NT_VMCOREDD &&
Packit Service 501009
		    vmcoredd_num < NR_DEVICE_DUMPS) {
Packit Service 501009
			dd->nt_vmcoredd_array[vmcoredd_num] = nt;
Packit Service 501009
			vmcoredd_num++;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		len = roundup(len + nt->n_namesz, 4);
Packit Service 501009
		len = roundup(len + nt->n_descsz, 4);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (num > 0) {
Packit Service 501009
		pc->flags2 |= ELF_NOTES;
Packit Service 501009
		dd->num_prstatus_notes = num;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (qemu_num > 0) {
Packit Service 501009
		pc->flags2 |= QEMU_MEM_DUMP_COMPRESSED;
Packit Service 501009
		dd->num_qemu_notes = qemu_num;
Packit Service 501009
	}
Packit Service 501009
	if (vmcoredd_num > 0)
Packit Service 501009
		dd->num_vmcoredd_notes = vmcoredd_num;
Packit Service 501009
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void 
Packit Service 501009
x86_process_elf_notes(void *note_ptr, unsigned long size_note)
Packit Service 501009
{
Packit Service 501009
	if (machine_type("X86_64"))
Packit Service 501009
		process_elf64_notes(note_ptr, size_note);
Packit Service 501009
	else if (machine_type("X86"))
Packit Service 501009
		process_elf32_notes(note_ptr, size_note);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
#if defined(__i386__) && (defined(ARM) || defined(MIPS))
Packit Service 501009
/*
Packit Service 501009
 * The kdump_sub_header member offsets are different when the crash 
Packit Service 501009
 * binary is built natively on an ARM host vs. when built with  
Packit Service 501009
 * "make target=ARM" on an x86/x86_64 host.  This is because the
Packit Service 501009
 * off_t structure members will be aligned on an 8-byte boundary when
Packit Service 501009
 * compiled as an ARM binary -- which will be reflected in the 
Packit Service 501009
 * kdump_sub_header in a compressed ARM kdump.  
Packit Service 501009
 *
Packit Service 501009
 * When crash is compiled as an x86 binary, these are the 
Packit Service 501009
 * structure's offsets:
Packit Service 501009
 * 
Packit Service 501009
 * struct kdump_sub_header {
Packit Service 501009
 * [0]     unsigned long   phys_base;
Packit Service 501009
 * [4]     int             dump_level;         /  header_version 1 and later  /
Packit Service 501009
 * [8]     int             split;              /  header_version 2 and later  /
Packit Service 501009
 * [12]    unsigned long   start_pfn;          /  header_version 2 and later  /
Packit Service 501009
 * [16]    unsigned long   end_pfn;            /  header_version 2 and later  /
Packit Service 501009
 * [20]    off_t           offset_vmcoreinfo;  /  header_version 3 and later  /
Packit Service 501009
 * [28]    unsigned long   size_vmcoreinfo;    /  header_version 3 and later  /
Packit Service 501009
 * [32]    off_t           offset_note;        /  header_version 4 and later  /
Packit Service 501009
 * [40]    unsigned long   size_note;          /  header_version 4 and later  /
Packit Service 501009
 * [44]    off_t           offset_eraseinfo;   /  header_version 5 and later  /
Packit Service 501009
 * [52]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
Packit Service 501009
 * [56]    unsigned long long   start_pfn_64;  /  header_version 6 and later  /
Packit Service 501009
 * [64]    unsigned long long   end_pfn_64;    /  header_version 6 and later  /
Packit Service 501009
 * [72]    unsigned long long   max_mapnr_64;  /  header_version 6 and later  /
Packit Service 501009
 * };
Packit Service 501009
 * 
Packit Service 501009
 * But when compiled on an ARM processor, each 64-bit "off_t" would be pushed
Packit Service 501009
 * up to an 8-byte boundary:
Packit Service 501009
 * 
Packit Service 501009
 * struct kdump_sub_header {
Packit Service 501009
 * [0]     unsigned long   phys_base;
Packit Service 501009
 * [4]     int             dump_level;         /  header_version 1 and later  /
Packit Service 501009
 * [8]     int             split;              /  header_version 2 and later  /
Packit Service 501009
 * [12]    unsigned long   start_pfn;          /  header_version 2 and later  /
Packit Service 501009
 * [16]    unsigned long   end_pfn;            /  header_version 2 and later  /
Packit Service 501009
 * [24]    off_t           offset_vmcoreinfo;  /  header_version 3 and later  /
Packit Service 501009
 * [32]    unsigned long   size_vmcoreinfo;    /  header_version 3 and later  /
Packit Service 501009
 * [40]    off_t           offset_note;        /  header_version 4 and later  /
Packit Service 501009
 * [48]    unsigned long   size_note;          /  header_version 4 and later  /
Packit Service 501009
 * [56]    off_t           offset_eraseinfo;   /  header_version 5 and later  /
Packit Service 501009
 * [64]    unsigned long   size_eraseinfo;     /  header_version 5 and later  /
Packit Service 501009
 * [72]    unsigned long long   start_pfn_64;  /  header_version 6 and later  /
Packit Service 501009
 * [80]    unsigned long long   end_pfn_64;    /  header_version 6 and later  /
Packit Service 501009
 * [88]    unsigned long long   max_mapnr_64;  /  header_version 6 and later  /
Packit Service 501009
 * };
Packit Service 501009
 * 
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
struct kdump_sub_header_ARM_target {
Packit Service 501009
        unsigned long   phys_base;
Packit Service 501009
        int             dump_level;         /* header_version 1 and later */
Packit Service 501009
        int             split;              /* header_version 2 and later */
Packit Service 501009
        unsigned long   start_pfn;          /* header_version 2 and later */
Packit Service 501009
        unsigned long   end_pfn;            /* header_version 2 and later */
Packit Service 501009
	int		pad1;
Packit Service 501009
        off_t           offset_vmcoreinfo;  /* header_version 3 and later */
Packit Service 501009
        unsigned long   size_vmcoreinfo;    /* header_version 3 and later */
Packit Service 501009
	int 		pad2;	
Packit Service 501009
        off_t           offset_note;        /* header_version 4 and later */
Packit Service 501009
        unsigned long   size_note;          /* header_version 4 and later */
Packit Service 501009
	int 		pad3;	
Packit Service 501009
        off_t           offset_eraseinfo;   /* header_version 5 and later */
Packit Service 501009
        unsigned long   size_eraseinfo;     /* header_version 5 and later */
Packit Service 501009
	int		pad4;
Packit Service 501009
	unsigned long long start_pfn_64;    /* header_version 6 and later */
Packit Service 501009
	unsigned long long end_pfn_64;      /* header_version 6 and later */
Packit Service 501009
	unsigned long long max_mapnr_64;    /* header_version 6 and later */
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
arm_kdump_header_adjust(int header_version)
Packit Service 501009
{
Packit Service 501009
	struct kdump_sub_header *kdsh;
Packit Service 501009
	struct kdump_sub_header_ARM_target *kdsh_ARM_target;
Packit Service 501009
Packit Service 501009
	kdsh = dd->sub_header_kdump;
Packit Service 501009
	kdsh_ARM_target = (struct kdump_sub_header_ARM_target *)kdsh;
Packit Service 501009
Packit Service 501009
	if (header_version >= 3) {
Packit Service 501009
		kdsh->offset_vmcoreinfo = kdsh_ARM_target->offset_vmcoreinfo; 
Packit Service 501009
		kdsh->size_vmcoreinfo = kdsh_ARM_target->size_vmcoreinfo;
Packit Service 501009
	}
Packit Service 501009
	if (header_version >= 4) {
Packit Service 501009
		kdsh->offset_note = kdsh_ARM_target->offset_note;
Packit Service 501009
		kdsh->size_note = kdsh_ARM_target->size_note;
Packit Service 501009
	}
Packit Service 501009
	if (header_version >= 5) {
Packit Service 501009
		kdsh->offset_eraseinfo = kdsh_ARM_target->offset_eraseinfo;
Packit Service 501009
		kdsh->size_eraseinfo = kdsh_ARM_target->size_eraseinfo;
Packit Service 501009
	}
Packit Service 501009
	if (header_version >= 6) {
Packit Service 501009
		kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn_64;
Packit Service 501009
		kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn_64;
Packit Service 501009
		kdsh->max_mapnr_64 = kdsh_ARM_target->max_mapnr_64;
Packit Service 501009
	} else {
Packit Service 501009
		kdsh->start_pfn_64 = kdsh_ARM_target->start_pfn;
Packit Service 501009
		kdsh->end_pfn_64 = kdsh_ARM_target->end_pfn;
Packit Service 501009
		kdsh->max_mapnr_64 = dd->max_mapnr;
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
#endif  /* __i386__ && (ARM || MIPS) */
Packit Service 501009
Packit Service 501009
static int 
Packit Service 501009
read_dump_header(char *file)
Packit Service 501009
{
Packit Service 501009
	struct disk_dump_header *header = NULL;
Packit Service 501009
	struct disk_dump_sub_header *sub_header = NULL;
Packit Service 501009
	struct kdump_sub_header *sub_header_kdump = NULL;
Packit Service 501009
	size_t size;
Packit Service 501009
	off_t bitmap_len;
Packit Service 501009
	char *bufptr;
Packit Service 501009
	size_t len;
Packit Service 501009
	ssize_t bytes_read;
Packit Service 501009
	int block_size = (int)sysconf(_SC_PAGESIZE);
Packit Service 501009
	off_t offset;
Packit Service 501009
	const off_t failed = (off_t)-1;
Packit Service 501009
	ulong pfn;
Packit Service 501009
	int i, j, max_sect_len;
Packit Service 501009
	int is_split = 0;
Packit Service 501009
Packit Service 501009
	if (block_size < 0)
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
restart:
Packit Service 501009
	if ((header = realloc(header, block_size)) == NULL)
Packit Service 501009
		error(FATAL, "diskdump / compressed kdump: cannot malloc block_size buffer\n");
Packit Service 501009
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, 0, header, block_size)) {
Packit Service 501009
			error(FATAL, "diskdump / compressed kdump: cannot read header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, 0, SEEK_SET) == failed) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "diskdump / compressed kdump: cannot lseek dump header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
		if (read(dd->dfd, header, block_size) < block_size) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "diskdump / compressed kdump: cannot read dump header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	/* validate dump header */
Packit Service 501009
	if (!memcmp(header->signature, DISK_DUMP_SIGNATURE,
Packit Service 501009
				sizeof(header->signature))) {
Packit Service 501009
		dd->flags |= DISKDUMP_LOCAL;
Packit Service 501009
	} else if (!memcmp(header->signature, KDUMP_SIGNATURE,
Packit Service 501009
				sizeof(header->signature))) {
Packit Service 501009
		dd->flags |= KDUMP_CMPRS_LOCAL;
Packit Service 501009
		if (header->header_version >= 1)
Packit Service 501009
			dd->flags |= ERROR_EXCLUDED;
Packit Service 501009
	} else {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, 
Packit Service 501009
			    "diskdump / compressed kdump: dump does not have panic dump header\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		fprintf(fp, "%s: header->utsname.machine: %s\n", 
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
			header->utsname.machine);
Packit Service 501009
Packit Service 501009
	if (STRNEQ(header->utsname.machine, "i686") &&
Packit Service 501009
	    machine_type_mismatch(file, "X86", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "x86_64") &&
Packit Service 501009
	    machine_type_mismatch(file, "X86_64", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "ia64") &&
Packit Service 501009
	    machine_type_mismatch(file, "IA64", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STREQ(header->utsname.machine, "ppc") &&
Packit Service 501009
	    machine_type_mismatch(file, "PPC", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "ppc64") &&
Packit Service 501009
	    machine_type_mismatch(file, "PPC64", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "arm") &&
Packit Service 501009
	    machine_type_mismatch(file, "ARM", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "mips") &&
Packit Service 501009
	    machine_type_mismatch(file, "MIPS", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "s390x") &&
Packit Service 501009
	    machine_type_mismatch(file, "S390X", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
	else if (STRNEQ(header->utsname.machine, "aarch64") &&
Packit Service 501009
	    machine_type_mismatch(file, "ARM64", NULL, 0))
Packit Service 501009
		goto err;
Packit Service 501009
Packit Service 501009
	if (header->block_size != block_size) {
Packit Service 501009
		block_size = header->block_size;
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			fprintf(fp, 
Packit Service 501009
			    "retrying with different block/page size: %d\n", 
Packit Service 501009
				header->block_size);
Packit Service 501009
		goto restart;
Packit Service 501009
	}
Packit Service 501009
	dd->block_size  = header->block_size;
Packit Service 501009
	dd->block_shift = ffs(header->block_size) - 1;
Packit Service 501009
Packit Service 501009
	if ((DISKDUMP_VALID() &&
Packit Service 501009
             (sizeof(*header) + sizeof(void *) * header->nr_cpus > block_size)) ||
Packit Service 501009
             header->nr_cpus <= 0) {
Packit Service 501009
                error(WARNING, "%s: invalid nr_cpus value: %d\n",
Packit Service 501009
                        DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
                        header->nr_cpus);
Packit Service 501009
		if (!machine_type("S390") && !machine_type("S390X") &&
Packit Service 501009
		    !machine_type("X86") && !machine_type("X86_64")) {
Packit Service 501009
			if (DISKDUMP_VALID())
Packit Service 501009
				goto err;
Packit Service 501009
		}
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
	/* read sub header */
Packit Service 501009
	offset = (off_t)block_size;
Packit Service 501009
Packit Service 501009
	if (DISKDUMP_VALID()) {
Packit Service 501009
		if ((sub_header = malloc(block_size)) == NULL)
Packit Service 501009
			error(FATAL, "diskdump: cannot malloc sub_header buffer\n");
Packit Service 501009
Packit Service 501009
		if (FLAT_FORMAT()) {
Packit Service 501009
			if (!read_flattened_format(dd->dfd, offset, sub_header, block_size)) {
Packit Service 501009
				error(INFO, "diskdump: cannot read dump sub header\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
		} else {
Packit Service 501009
			if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
				error(INFO, "diskdump: cannot lseek dump sub header\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
			if (read(dd->dfd, sub_header, block_size) < block_size) {
Packit Service 501009
				error(INFO, "diskdump: cannot read dump sub header\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		dd->sub_header = sub_header;
Packit Service 501009
Packit Service 501009
		/* the 64bit max_mapnr only exists in sub-header of compressed
Packit Service 501009
		 * kdump file, if it's not a compressed kdump file, we have to
Packit Service 501009
		 * use the old 32bit max_mapnr in dumpfile header.
Packit Service 501009
		 * max_mapnr may be truncated here.
Packit Service 501009
		 */
Packit Service 501009
		dd->max_mapnr = header->max_mapnr;
Packit Service 501009
	} else if (KDUMP_CMPRS_VALID()) {
Packit Service 501009
		if ((sub_header_kdump = malloc(block_size)) == NULL)
Packit Service 501009
			error(FATAL, "compressed kdump: cannot malloc sub_header_kdump buffer\n");
Packit Service 501009
Packit Service 501009
		if (FLAT_FORMAT()) {
Packit Service 501009
			if (!read_flattened_format(dd->dfd, offset, sub_header_kdump, block_size)) {
Packit Service 501009
				error(INFO, "compressed kdump: cannot read dump sub header\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
		} else {
Packit Service 501009
			if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
				error(INFO, "compressed kdump: cannot lseek dump sub header\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
			if (read(dd->dfd, sub_header_kdump, block_size) < block_size) {
Packit Service 501009
				error(INFO, "compressed kdump: cannot read dump sub header\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		dd->sub_header_kdump = sub_header_kdump;
Packit Service 501009
Packit Service 501009
#if defined(__i386__) && (defined(ARM) || defined(MIPS))
Packit Service 501009
		arm_kdump_header_adjust(header->header_version);
Packit Service 501009
#endif
Packit Service 501009
		/* use 64bit max_mapnr in compressed kdump file sub-header */
Packit Service 501009
		if (header->header_version >= 6)
Packit Service 501009
			dd->max_mapnr = dd->sub_header_kdump->max_mapnr_64;
Packit Service 501009
		else {
Packit Service 501009
			dd->sub_header_kdump->start_pfn_64
Packit Service 501009
				= dd->sub_header_kdump->start_pfn;
Packit Service 501009
			dd->sub_header_kdump->end_pfn_64
Packit Service 501009
				= dd->sub_header_kdump->end_pfn;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (header->header_version < 6)
Packit Service 501009
		dd->max_mapnr = header->max_mapnr;
Packit Service 501009
Packit Service 501009
	/* read memory bitmap */
Packit Service ef2397
	bitmap_len = (off_t)block_size * header->bitmap_blocks;
Packit Service 501009
	dd->bitmap_len = bitmap_len;
Packit Service 501009
Packit Service 501009
	offset = (off_t)block_size * (1 + header->sub_hdr_size);
Packit Service 501009
Packit Service 501009
	if ((dd->bitmap = malloc(bitmap_len)) == NULL)
Packit Service 501009
		error(FATAL, "%s: cannot malloc bitmap buffer\n",
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
Packit Service 501009
	dd->dumpable_bitmap = calloc(bitmap_len, 1);
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(8))
Packit Service 501009
		fprintf(fp, "%s: memory bitmap offset: %llx\n",
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
			(ulonglong)offset);
Packit Service 501009
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, offset, dd->bitmap, bitmap_len)) {
Packit Service 501009
			error(INFO, "%s: cannot read memory bitmap\n",
Packit Service 501009
				DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
			error(INFO, "%s: cannot lseek memory bitmap\n",
Packit Service 501009
				DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
		bufptr = dd->bitmap;
Packit Service 501009
		len = bitmap_len;
Packit Service 501009
		while (len) {
Packit Service 501009
			bytes_read = read(dd->dfd, bufptr, len);
Packit Service 501009
			if (bytes_read <= 0) {
Packit Service 501009
				error(INFO, "%s: cannot read memory bitmap\n",
Packit Service 501009
					DISKDUMP_VALID() ? "diskdump"
Packit Service 501009
					: "compressed kdump");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
			len -= bytes_read;
Packit Service 501009
			bufptr += bytes_read;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (dump_is_partial(header))
Packit Service 501009
		memcpy(dd->dumpable_bitmap, dd->bitmap + bitmap_len/2,
Packit Service 501009
		       bitmap_len/2);
Packit Service 501009
	else
Packit Service 501009
		memcpy(dd->dumpable_bitmap, dd->bitmap, bitmap_len);
Packit Service 501009
Packit Service 501009
	dd->data_offset
Packit Service ef2397
		= (1UL + header->sub_hdr_size + header->bitmap_blocks)
Packit Service 501009
		* header->block_size;
Packit Service 501009
Packit Service 501009
	dd->header = header;
Packit Service 501009
Packit Service 501009
	if (machine_type("ARM"))
Packit Service 501009
		dd->machine_type = EM_ARM;
Packit Service 501009
	else if (machine_type("MIPS"))
Packit Service 501009
		dd->machine_type = EM_MIPS;
Packit Service 501009
	else if (machine_type("X86"))
Packit Service 501009
		dd->machine_type = EM_386;
Packit Service 501009
	else if (machine_type("X86_64"))
Packit Service 501009
		dd->machine_type = EM_X86_64;
Packit Service 501009
	else if (machine_type("IA64"))
Packit Service 501009
		dd->machine_type = EM_IA_64;
Packit Service 501009
	else if (machine_type("PPC"))
Packit Service 501009
		dd->machine_type = EM_PPC;
Packit Service 501009
	else if (machine_type("PPC64"))
Packit Service 501009
		dd->machine_type = EM_PPC64;
Packit Service 501009
	else if (machine_type("S390X"))
Packit Service 501009
		dd->machine_type = EM_S390;
Packit Service 501009
	else if (machine_type("ARM64"))
Packit Service 501009
		dd->machine_type = EM_AARCH64;
Packit Service 501009
	else if (machine_type("SPARC64"))
Packit Service 501009
		dd->machine_type = EM_SPARCV9;
Packit Service 501009
	else {
Packit Service 501009
		error(INFO, "%s: unsupported machine type: %s\n", 
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
			MACHINE_TYPE);
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	/* process elf notes data */
Packit Service 501009
	if (KDUMP_CMPRS_VALID() && !(dd->flags & NO_ELF_NOTES) &&
Packit Service 501009
		(dd->header->header_version >= 4) &&
Packit Service 501009
		(sub_header_kdump->offset_note) &&
Packit Service 501009
		(sub_header_kdump->size_note) && (machdep->process_elf_notes)) {
Packit Service 501009
		size = sub_header_kdump->size_note;
Packit Service 501009
		offset = sub_header_kdump->offset_note;
Packit Service 501009
Packit Service 501009
		if ((dd->notes_buf = malloc(size)) == NULL)
Packit Service 501009
			error(FATAL, "compressed kdump: cannot malloc notes"
Packit Service 501009
				" buffer\n");
Packit Service 501009
Packit Service 501009
		if ((dd->nt_prstatus_percpu = malloc(NR_CPUS * sizeof(void *))) == NULL)
Packit Service 501009
			error(FATAL, "compressed kdump: cannot malloc pointer"
Packit Service 501009
				" to NT_PRSTATUS notes\n");
Packit Service 501009
Packit Service 501009
		if ((dd->nt_qemu_percpu = malloc(NR_CPUS * sizeof(void *))) == NULL)
Packit Service 501009
			error(FATAL, "qemu mem dump compressed: cannot malloc pointer"
Packit Service 501009
				" to QEMU notes\n");
Packit Service 501009
Packit Service 501009
		if ((dd->nt_qemucs_percpu = malloc(NR_CPUS * sizeof(void *))) == NULL)
Packit Service 501009
			error(FATAL, "qemu mem dump compressed: cannot malloc pointer"
Packit Service 501009
				" to QEMUCS notes\n");
Packit Service 501009
Packit Service 501009
		if ((dd->nt_vmcoredd_array = malloc(NR_DEVICE_DUMPS * sizeof(void *))) == NULL)
Packit Service 501009
			error(FATAL, "compressed kdump: cannot malloc array for "
Packit Service 501009
				     "vmcore device dump notes\n");
Packit Service 501009
Packit Service 501009
		if (FLAT_FORMAT()) {
Packit Service 501009
			if (!read_flattened_format(dd->dfd, offset, dd->notes_buf, size)) {
Packit Service 501009
				error(INFO, "compressed kdump: cannot read notes data"
Packit Service 501009
					"\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
		} else {
Packit Service 501009
			if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
				error(INFO, "compressed kdump: cannot lseek notes data\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
			if (read(dd->dfd, dd->notes_buf, size) < size) {
Packit Service 501009
				error(INFO, "compressed kdump: cannot read notes data"
Packit Service 501009
					"\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		machdep->process_elf_notes(dd->notes_buf, size);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	/* Check if dump file contains erasesinfo data */
Packit Service 501009
	if (KDUMP_CMPRS_VALID() && (dd->header->header_version >= 5) &&
Packit Service 501009
		(sub_header_kdump->offset_eraseinfo) &&
Packit Service 501009
		(sub_header_kdump->size_eraseinfo))
Packit Service 501009
		pc->flags2 |= ERASEINFO_DATA;
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID() && (dd->header->header_version >= 3) &&
Packit Service 501009
		dd->sub_header_kdump->offset_vmcoreinfo &&
Packit Service 501009
		dd->sub_header_kdump->size_vmcoreinfo)
Packit Service 501009
		pc->flags2 |= VMCOREINFO;
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID() && 
Packit Service 501009
	    (dd->header->status & DUMP_DH_COMPRESSED_INCOMPLETE))
Packit Service 501009
		pc->flags2 |= INCOMPLETE_DUMP;
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID() && 
Packit Service 501009
	    (dd->header->status & DUMP_DH_EXCLUDED_VMEMMAP))
Packit Service 501009
		pc->flags2 |= EXCLUDED_VMEMMAP;
Packit Service 501009
Packit Service 501009
	/* For split dumpfile */
Packit Service 501009
	if (KDUMP_CMPRS_VALID()) {
Packit Service 501009
		is_split = ((dd->header->header_version >= 2) &&
Packit Service 501009
		            (sub_header_kdump->split));
Packit Service 501009
Packit Service 501009
		if ((is_split && (num_dumpfiles != 0) && (dd_list == NULL))||
Packit Service 501009
		    (!is_split && (num_dumpfiles != 0))) {
Packit Service 501009
			clean_diskdump_data();
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (is_split)
Packit Service 501009
			add_diskdump_data(file);
Packit Service 501009
Packit Service 501009
		num_dumpfiles++;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!is_split) {
Packit Service 501009
		max_sect_len = divideup(dd->max_mapnr, BITMAP_SECT_LEN);
Packit Service 501009
		pfn = 0;
Packit Service 501009
		dd->filename = file;
Packit Service 501009
	}
Packit Service 501009
	else {
Packit Service 501009
		unsigned long long start = sub_header_kdump->start_pfn_64;
Packit Service 501009
		unsigned long long end = sub_header_kdump->end_pfn_64;
Packit Service 501009
		max_sect_len = divideup(end - start + 1, BITMAP_SECT_LEN);
Packit Service 501009
		pfn = start;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	dd->valid_pages = calloc(sizeof(ulong), max_sect_len + 1);
Packit Service 501009
	for (i = 1; i < max_sect_len + 1; i++) {
Packit Service 501009
		dd->valid_pages[i] = dd->valid_pages[i - 1];
Packit Service 501009
		for (j = 0; j < BITMAP_SECT_LEN; j++, pfn++)
Packit Service 501009
			if (page_is_dumpable(pfn))
Packit Service 501009
				dd->valid_pages[i]++;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
        return TRUE;
Packit Service 501009
Packit Service 501009
err:
Packit Service 501009
	free(header);
Packit Service 501009
	if (sub_header)
Packit Service 501009
		free(sub_header);
Packit Service 501009
	if (sub_header_kdump)
Packit Service 501009
		free(sub_header_kdump);
Packit Service 501009
	if (dd->bitmap)
Packit Service 501009
		free(dd->bitmap);
Packit Service 501009
	if (dd->dumpable_bitmap)
Packit Service 501009
		free(dd->dumpable_bitmap);
Packit Service 501009
	if (dd->notes_buf)
Packit Service 501009
		free(dd->notes_buf);
Packit Service 501009
	if (dd->nt_prstatus_percpu)
Packit Service 501009
		free(dd->nt_prstatus_percpu);
Packit Service 501009
	if (dd->nt_qemu_percpu)
Packit Service 501009
		free(dd->nt_qemu_percpu);
Packit Service 501009
	if (dd->nt_qemucs_percpu)
Packit Service 501009
		free(dd->nt_qemucs_percpu);
Packit Service 501009
	if (dd->nt_vmcoredd_array)
Packit Service 501009
		free(dd->nt_vmcoredd_array);
Packit Service 501009
Packit Service 501009
	dd->flags &= ~(DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL);
Packit Service 501009
	pc->flags2 &= ~ELF_NOTES;
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
pfn_to_pos(ulong pfn)
Packit Service 501009
{
Packit Service 501009
	ulong desc_pos, j, valid;
Packit Service 501009
	ulong p1, p2;
Packit Service 501009
Packit Service 501009
	if (KDUMP_SPLIT()) {
Packit Service 501009
		p1 = pfn - dd->sub_header_kdump->start_pfn_64;
Packit Service 501009
		p2 = round(p1, BITMAP_SECT_LEN)
Packit Service 501009
			+ dd->sub_header_kdump->start_pfn_64;
Packit Service 501009
	}
Packit Service 501009
	else {
Packit Service 501009
		p1 = pfn; 
Packit Service 501009
		p2 = round(pfn, BITMAP_SECT_LEN); 
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	valid = dd->valid_pages[p1 / BITMAP_SECT_LEN];
Packit Service 501009
Packit Service 501009
	for (j = p2, desc_pos = valid; j <= pfn; j++)
Packit Service 501009
			if (page_is_dumpable(j))
Packit Service 501009
				desc_pos++;
Packit Service 501009
Packit Service 501009
	return desc_pos;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Determine whether a file is a diskdump creation, and if TRUE,
Packit Service 501009
 *  initialize the diskdump_data structure based upon the contents
Packit Service 501009
 *  of the diskdump header data.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
is_diskdump(char *file)
Packit Service 501009
{
Packit Service 501009
	int sz, i;
Packit Service 501009
Packit Service 501009
	if (!open_dump_file(file) || !read_dump_header(file))
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	sz = dd->block_size * (DISKDUMP_CACHED_PAGES);
Packit Service 501009
	if ((dd->page_cache_buf = malloc(sz)) == NULL)
Packit Service 501009
		error(FATAL, "%s: cannot malloc compressed page_cache_buf\n",
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
Packit Service 501009
	for (i = 0; i < DISKDUMP_CACHED_PAGES; i++)
Packit Service 501009
		dd->page_cache_hdr[i].pg_bufptr =
Packit Service 501009
			&dd->page_cache_buf[i * dd->block_size];
Packit Service 501009
Packit Service 501009
	if ((dd->compressed_page = (char *)malloc(dd->block_size)) == NULL)
Packit Service 501009
		error(FATAL, "%s: cannot malloc compressed page space\n",
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		__diskdump_memory_dump(fp);
Packit Service 501009
Packit Service 501009
	if (pc->flags2 & GET_OSRELEASE) 
Packit Service 501009
		diskdump_get_osrelease();
Packit Service 501009
Packit Service 501009
#ifdef LZO
Packit Service 501009
	if (lzo_init() == LZO_E_OK)
Packit Service 501009
		dd->flags |= LZO_SUPPORTED;
Packit Service 501009
#endif
Packit Service 501009
Packit Service 501009
#ifdef SNAPPY
Packit Service 501009
	dd->flags |= SNAPPY_SUPPORTED;
Packit Service 501009
#endif
Packit Service 501009
Packit Service 501009
	pc->read_vmcoreinfo = vmcoreinfo_read_string;
Packit Service 501009
Packit Service 501009
	if ((pc->flags2 & GET_LOG) && KDUMP_CMPRS_VALID()) {
Packit Service 501009
		pc->dfd = dd->dfd;
Packit Service 501009
		pc->readmem = read_diskdump;
Packit Service 501009
		pc->flags |= DISKDUMP;
Packit Service 501009
		get_log_from_vmcoreinfo(file);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Perform any post-dumpfile determination stuff here.
Packit Service 501009
 *  At a minimum
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
diskdump_init(char *unused, FILE *fptr)
Packit Service 501009
{
Packit Service 501009
	if (!DISKDUMP_VALID() && !KDUMP_CMPRS_VALID())
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	dd->ofp = fptr;
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Get the relocational offset from the sub header of kdump.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
diskdump_phys_base(unsigned long *phys_base)
Packit Service 501009
{
Packit Service 501009
	if (KDUMP_CMPRS_VALID()) {
Packit Service 501009
		*phys_base = dd->sub_header_kdump->phys_base;
Packit Service 501009
		return TRUE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
diskdump_set_phys_base(unsigned long phys_base)
Packit Service 501009
{
Packit Service 501009
	if (diskdump_kaslr_check()) {
Packit Service 501009
		dd->sub_header_kdump->phys_base = phys_base;
Packit Service 501009
		return TRUE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Check whether paddr is already cached.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
page_is_cached(physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
	struct page_cache_hdr *pgc;
Packit Service 501009
Packit Service 501009
	dd->accesses++;
Packit Service 501009
Packit Service 501009
	for (i = 0; i < DISKDUMP_CACHED_PAGES; i++) {
Packit Service 501009
Packit Service 501009
		pgc = &dd->page_cache_hdr[i];
Packit Service 501009
Packit Service 501009
		if (!DISKDUMP_VALID_PAGE(pgc->pg_flags))
Packit Service 501009
			continue;
Packit Service 501009
Packit Service 501009
		if (pgc->pg_addr == paddr) {
Packit Service 501009
			pgc->pg_hit_count++;
Packit Service 501009
			dd->curbufptr = pgc->pg_bufptr;
Packit Service 501009
			dd->cached_reads++;
Packit Service 501009
			return TRUE;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * Translate physical address in paddr to PFN number. This means normally that
Packit Service 501009
 * we just shift paddr by some constant. Some architectures need special
Packit Service 501009
 * handling for this, however.
Packit Service 501009
 */
Packit Service 501009
static ulong
Packit Service 501009
paddr_to_pfn(physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
#ifdef ARM
Packit Service 501009
	/*
Packit Service 501009
	 * In ARM, PFN 0 means first page in kernel direct-mapped view.
Packit Service 501009
	 * This is also first page in mem_map as well.
Packit Service 501009
	 */
Packit Service 501009
	return (paddr - machdep->machspec->phys_base) >> dd->block_shift;
Packit Service 501009
#else
Packit Service 501009
	return paddr >> dd->block_shift;
Packit Service 501009
#endif
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Cache the page's data.
Packit Service 501009
 *
Packit Service 501009
 *  If an empty page cache location is available, take it.  Otherwise, evict
Packit Service 501009
 *  the entry indexed by evict_index, and then bump evict index.  The hit_count
Packit Service 501009
 *  is only gathered for dump_diskdump_environment().
Packit Service 501009
 *
Packit Service 501009
 *  If the page is compressed, uncompress it into the selected page cache entry.
Packit Service 501009
 *  If the page is raw, just copy it into the selected page cache entry.
Packit Service 501009
 *  If all works OK, update diskdump->curbufptr to point to the page's
Packit Service 501009
 *  uncompressed data.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
cache_page(physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
	int i, ret;
Packit Service 501009
	int found;
Packit Service 501009
	ulong pfn;
Packit Service 501009
	ulong desc_pos;
Packit Service 501009
	off_t seek_offset;
Packit Service 501009
	page_desc_t pd;
Packit Service 501009
	const int block_size = dd->block_size;
Packit Service 501009
	const off_t failed = (off_t)-1;
Packit Service 501009
	ulong retlen;
Packit Service 501009
Packit Service 501009
	for (i = found = 0; i < DISKDUMP_CACHED_PAGES; i++) {
Packit Service 501009
		if (DISKDUMP_VALID_PAGE(dd->page_cache_hdr[i].pg_flags))
Packit Service 501009
			continue;
Packit Service 501009
		found = TRUE;
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!found) {
Packit Service 501009
		i = dd->evict_index;
Packit Service 501009
		dd->page_cache_hdr[i].pg_hit_count = 0;
Packit Service 501009
		dd->evict_index =
Packit Service 501009
			(dd->evict_index+1) % DISKDUMP_CACHED_PAGES;
Packit Service 501009
		dd->evictions++;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	dd->page_cache_hdr[i].pg_flags = 0;
Packit Service 501009
	dd->page_cache_hdr[i].pg_addr = paddr;
Packit Service 501009
	dd->page_cache_hdr[i].pg_hit_count++;
Packit Service 501009
Packit Service 501009
	/* find page descriptor */
Packit Service 501009
	pfn = paddr_to_pfn(paddr);
Packit Service 501009
	desc_pos = pfn_to_pos(pfn);
Packit Service 501009
	seek_offset = dd->data_offset
Packit Service 501009
			+ (off_t)(desc_pos - 1)*sizeof(page_desc_t);
Packit Service 501009
Packit Service 501009
	/* read page descriptor */
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, seek_offset, &pd, sizeof(pd)))
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, seek_offset, SEEK_SET) == failed)
Packit Service 501009
			return SEEK_ERROR;
Packit Service 501009
		if (read(dd->dfd, &pd, sizeof(pd)) != sizeof(pd))
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	/* sanity check */
Packit Service 501009
	if (pd.size > block_size)
Packit Service 501009
		return READ_ERROR;
Packit Service 501009
Packit Service 501009
	/* read page data */
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, pd.offset, dd->compressed_page, pd.size))
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
	} else if (is_incomplete_dump() && (0 == pd.offset)) {
Packit Service 501009
		/*
Packit Service 501009
		 *  If the incomplete flag has been set in the header, 
Packit Service 501009
		 *  first check whether zero_excluded has been set.
Packit Service 501009
		 */
Packit Service 501009
		if (*diskdump_flags & ZERO_EXCLUDED) {
Packit Service 501009
			if (CRASHDEBUG(8))
Packit Service 501009
				fprintf(fp, 
Packit Service 501009
			    	    "read_diskdump/cache_page: zero-fill: "
Packit Service 501009
				    "paddr/pfn: %llx/%lx\n", 
Packit Service 501009
					(ulonglong)paddr, pfn);
Packit Service 501009
			memset(dd->compressed_page, 0, dd->block_size);
Packit Service 501009
		} else
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, pd.offset, SEEK_SET) == failed)
Packit Service 501009
			return SEEK_ERROR;
Packit Service 501009
		if (read(dd->dfd, dd->compressed_page, pd.size) != pd.size)
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (pd.flags & DUMP_DH_COMPRESSED_ZLIB) {
Packit Service 501009
		retlen = block_size;
Packit Service 501009
		ret = uncompress((unsigned char *)dd->page_cache_hdr[i].pg_bufptr,
Packit Service 501009
		                 &retlen,
Packit Service 501009
		                 (unsigned char *)dd->compressed_page,
Packit Service 501009
		                 pd.size);
Packit Service 501009
		if ((ret != Z_OK) || (retlen != block_size)) {
Packit Service 501009
			error(INFO, "%s: uncompress failed: %d\n", 
Packit Service 501009
				DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
				ret);
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
	} else if (pd.flags & DUMP_DH_COMPRESSED_LZO) {
Packit Service 501009
Packit Service 501009
		if (!(dd->flags & LZO_SUPPORTED)) {
Packit Service 501009
			error(INFO, "%s: uncompress failed: no lzo compression support\n",
Packit Service 501009
			      DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
#ifdef LZO
Packit Service 501009
		retlen = block_size;
Packit Service 501009
		ret = lzo1x_decompress_safe((unsigned char *)dd->compressed_page,
Packit Service 501009
					    pd.size,
Packit Service 501009
					    (unsigned char *)dd->page_cache_hdr[i].pg_bufptr,
Packit Service 501009
					    &retlen,
Packit Service 501009
					    LZO1X_MEM_DECOMPRESS);
Packit Service 501009
		if ((ret != LZO_E_OK) || (retlen != block_size)) {
Packit Service 501009
			error(INFO, "%s: uncompress failed: %d\n", 
Packit Service 501009
				DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
				ret);
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
#endif
Packit Service 501009
	} else if (pd.flags & DUMP_DH_COMPRESSED_SNAPPY) {
Packit Service 501009
Packit Service 501009
		if (!(dd->flags & SNAPPY_SUPPORTED)) {
Packit Service 501009
			error(INFO, "%s: uncompress failed: no snappy compression support\n",
Packit Service 501009
			      DISKDUMP_VALID() ? "diskdump" : "compressed kdump");
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
#ifdef SNAPPY
Packit Service 501009
		ret = snappy_uncompressed_length((char *)dd->compressed_page,
Packit Service 501009
						 pd.size, (size_t *)&retlen);
Packit Service 501009
		if (ret != SNAPPY_OK) {
Packit Service 501009
			error(INFO, "%s: uncompress failed: %d\n",
Packit Service 501009
			      DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
			      ret);
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		ret = snappy_uncompress((char *)dd->compressed_page, pd.size,
Packit Service 501009
					(char *)dd->page_cache_hdr[i].pg_bufptr,
Packit Service 501009
					(size_t *)&retlen);
Packit Service 501009
		if ((ret != SNAPPY_OK) || (retlen != block_size)) {
Packit Service 501009
			error(INFO, "%s: uncompress failed: %d\n", 
Packit Service 501009
			      DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
			      ret);
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
#endif
Packit Service 501009
	} else
Packit Service 501009
		memcpy(dd->page_cache_hdr[i].pg_bufptr,
Packit Service 501009
		       dd->compressed_page, block_size);
Packit Service 501009
Packit Service 501009
	dd->page_cache_hdr[i].pg_flags |= PAGE_VALID;
Packit Service 501009
	dd->curbufptr = dd->page_cache_hdr[i].pg_bufptr;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Read from a diskdump-created dumpfile.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
read_diskdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
	int ret;
Packit Service 501009
	physaddr_t curpaddr;
Packit Service 501009
	ulong pfn, page_offset;
Packit Service 501009
	physaddr_t paddr_in = paddr;
Packit Service 501009
Packit Service 501009
	if (XEN_CORE_DUMPFILE() && !XEN_HYPER_MODE()) {
Packit Service 501009
		if ((paddr = xen_kdump_p2m(paddr)) == P2M_FAILURE) {
Packit Service 501009
			if (CRASHDEBUG(8))
Packit Service 501009
				fprintf(fp, "read_diskdump: xen_kdump_p2m(%llx): "
Packit Service 501009
					"P2M_FAILURE\n", (ulonglong)paddr_in);
Packit Service 501009
			return READ_ERROR;
Packit Service 501009
		}
Packit Service 501009
		if (CRASHDEBUG(8))
Packit Service 501009
			fprintf(fp, "read_diskdump: xen_kdump_p2m(%llx): %llx\n",
Packit Service 501009
				(ulonglong)paddr_in, (ulonglong)paddr);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	pfn = paddr_to_pfn(paddr);
Packit Service 501009
Packit Service 501009
	if (KDUMP_SPLIT()) {
Packit Service 501009
		/* Find proper dd */
Packit Service 501009
		int i;
Packit Service 501009
		unsigned long long start_pfn;
Packit Service 501009
		unsigned long long end_pfn;
Packit Service 501009
Packit Service 501009
		for (i=0; i
Packit Service 501009
			start_pfn = dd_list[i]->sub_header_kdump->start_pfn_64;
Packit Service 501009
			end_pfn = dd_list[i]->sub_header_kdump->end_pfn_64;
Packit Service 501009
			if ((pfn >= start_pfn) && (pfn < end_pfn))	{
Packit Service 501009
				dd = dd_list[i];
Packit Service 501009
				break;
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (i == num_dumpfiles) {
Packit Service 501009
			if (CRASHDEBUG(8))
Packit Service 501009
				fprintf(fp, "read_diskdump: SEEK_ERROR: "
Packit Service 501009
				    "paddr/pfn %llx/%lx beyond last dumpfile\n",
Packit Service 501009
					(ulonglong)paddr, pfn);
Packit Service 501009
			return SEEK_ERROR;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	curpaddr = paddr & ~((physaddr_t)(dd->block_size-1));
Packit Service 501009
	page_offset = paddr & ((physaddr_t)(dd->block_size-1));
Packit Service 501009
Packit Service 501009
	if ((pfn >= dd->max_mapnr) || !page_is_ram(pfn)) {
Packit Service 501009
		if (CRASHDEBUG(8)) {
Packit Service 501009
			fprintf(fp, "read_diskdump: SEEK_ERROR: "
Packit Service 501009
			    "paddr/pfn: %llx/%lx ",
Packit Service 501009
				(ulonglong)paddr, pfn);
Packit Service 501009
			if (pfn >= dd->max_mapnr)
Packit Service 501009
				fprintf(fp, "max_mapnr: %llx\n",
Packit Service 501009
					dd->max_mapnr);
Packit Service 501009
			else
Packit Service 501009
				fprintf(fp, "!page_is_ram\n");
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		return SEEK_ERROR;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!page_is_dumpable(pfn)) {
Packit Service 501009
		if ((dd->flags & (ZERO_EXCLUDED|ERROR_EXCLUDED)) ==
Packit Service 501009
		    ERROR_EXCLUDED) {
Packit Service 501009
			if (CRASHDEBUG(8))
Packit Service 501009
				fprintf(fp, "read_diskdump: PAGE_EXCLUDED: "
Packit Service 501009
			    	    "paddr/pfn: %llx/%lx\n",
Packit Service 501009
					(ulonglong)paddr, pfn);
Packit Service 501009
			return PAGE_EXCLUDED;
Packit Service 501009
		}
Packit Service 501009
		if (CRASHDEBUG(8))
Packit Service 501009
			fprintf(fp, "read_diskdump: zero-fill: "
Packit Service 501009
		    	    "paddr/pfn: %llx/%lx\n",
Packit Service 501009
				(ulonglong)paddr, pfn);
Packit Service 501009
		memset(bufptr, 0, cnt);
Packit Service 501009
		return cnt;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!page_is_cached(curpaddr)) {
Packit Service 501009
		if (CRASHDEBUG(8))
Packit Service 501009
			fprintf(fp, "read_diskdump: paddr/pfn: %llx/%lx"
Packit Service 501009
			    " -> cache physical page: %llx\n",
Packit Service 501009
				(ulonglong)paddr, pfn, (ulonglong)curpaddr);
Packit Service 501009
Packit Service 501009
		if ((ret = cache_page(curpaddr)) < 0) {
Packit Service 501009
			if (CRASHDEBUG(8))
Packit Service 501009
				fprintf(fp, "read_diskdump: " 
Packit Service 501009
				    "%s: cannot cache page: %llx\n",
Packit Service 501009
					ret == SEEK_ERROR ?  
Packit Service 501009
					"SEEK_ERROR" : "READ_ERROR",
Packit Service 501009
					(ulonglong)curpaddr);
Packit Service 501009
			return ret;
Packit Service 501009
		}
Packit Service 501009
	} else if (CRASHDEBUG(8))
Packit Service 501009
		fprintf(fp, "read_diskdump: paddr/pfn: %llx/%lx"
Packit Service 501009
		    " -> physical page is cached: %llx\n", 
Packit Service 501009
			(ulonglong)paddr, pfn, (ulonglong)curpaddr);
Packit Service 501009
	
Packit Service 501009
	memcpy(bufptr, dd->curbufptr + page_offset, cnt);
Packit Service 501009
	return cnt;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Write to a diskdump-created dumpfile.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
write_diskdump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
ulong
Packit Service 501009
get_diskdump_panic_task(void)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	if ((!DISKDUMP_VALID() && !KDUMP_CMPRS_VALID())
Packit Service 501009
	    || !get_active_set())
Packit Service 501009
		return NO_TASK;
Packit Service 501009
Packit Service 501009
	if (pc->flags2 & SNAP)
Packit Service 501009
		return (task_exists(dd->snapshot_task) ? dd->snapshot_task : NO_TASK);
Packit Service 501009
Packit Service 501009
	if (DISKDUMP_VALID())
Packit Service 501009
		return (ulong)dd->header->tasks[dd->header->current_cpu];
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID()) {
Packit Service 501009
		if (kernel_symbol_exists("crashing_cpu") &&
Packit Service 501009
		    cpu_map_addr("online")) {
Packit Service 501009
			get_symbol_data("crashing_cpu", sizeof(int), &i);
Packit Service 501009
			if ((i >= 0) && in_cpu_map(ONLINE_MAP, i)) {
Packit Service 501009
				if (CRASHDEBUG(1))
Packit Service 501009
					error(INFO, "get_diskdump_panic_task: "
Packit Service 501009
					    "active_set[%d]: %lx\n", 
Packit Service 501009
						i, tt->active_set[i]);
Packit Service 501009
				return (tt->active_set[i]);
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return NO_TASK;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
extern void get_netdump_regs_x86(struct bt_info *, ulong *, ulong *);
Packit Service 501009
extern void get_netdump_regs_x86_64(struct bt_info *, ulong *, ulong *);
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
get_diskdump_regs_32(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	Elf32_Nhdr *note;
Packit Service 501009
	int len;
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID() &&
Packit Service 501009
		(bt->task == tt->panic_task || 
Packit Service 501009
		(is_task_active(bt->task) && dd->num_prstatus_notes > 1))) {
Packit Service 501009
		note  = (Elf32_Nhdr*) dd->nt_prstatus_percpu[bt->tc->processor];
Packit Service 501009
		if (!note)
Packit Service 501009
			error(FATAL,
Packit Service 501009
				    "cannot determine NT_PRSTATUS ELF note "
Packit Service 501009
				    "for %s task: %lx\n",
Packit Service 501009
					(bt->task == tt->panic_task) ?
Packit Service 501009
					"panic" : "active", bt->task);
Packit Service 501009
		len = sizeof(Elf32_Nhdr);
Packit Service 501009
		len = roundup(len + note->n_namesz, 4);
Packit Service 501009
		bt->machdep = (void *)((char *)note + len +
Packit Service 501009
			MEMBER_OFFSET("elf_prstatus", "pr_reg"));
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
get_diskdump_regs_ppc(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	if (KDUMP_CMPRS_VALID())
Packit Service 501009
		ppc_relocate_nt_prstatus_percpu(dd->nt_prstatus_percpu,
Packit Service 501009
						&dd->num_prstatus_notes);
Packit Service 501009
Packit Service 501009
	get_diskdump_regs_32(bt, eip, esp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
get_diskdump_regs_ppc64(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	int cpu;
Packit Service 501009
	Elf64_Nhdr *note;
Packit Service 501009
	size_t len;
Packit Service 501009
Packit Service 501009
	if ((bt->task == tt->panic_task) && DISKDUMP_VALID())
Packit Service 501009
		bt->machdep = &dd->sub_header->elf_regs;
Packit Service 501009
	else if (KDUMP_CMPRS_VALID() &&
Packit Service 501009
		(bt->task == tt->panic_task ||
Packit Service 501009
		(is_task_active(bt->task) && dd->num_prstatus_notes > 1))) {
Packit Service 501009
		cpu = bt->tc->processor;
Packit Service 501009
		if (dd->nt_prstatus_percpu[cpu] == NULL) {
Packit Service 501009
			if(CRASHDEBUG(1))
Packit Service 501009
				error(INFO,
Packit Service 501009
				      "registers not collected for cpu %d\n",
Packit Service 501009
				      cpu);
Packit Service 501009
		} else {
Packit Service 501009
			note = (Elf64_Nhdr *)
Packit Service 501009
				dd->nt_prstatus_percpu[cpu];
Packit Service 501009
			len = sizeof(Elf64_Nhdr);
Packit Service 501009
			len = roundup(len + note->n_namesz, 4);
Packit Service 501009
			bt->machdep = (void *)((char *)note + len +
Packit Service 501009
				MEMBER_OFFSET("elf_prstatus", "pr_reg"));
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
get_diskdump_regs_arm(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
get_diskdump_regs_arm64(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
get_diskdump_regs_sparc64(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	Elf64_Nhdr *note;
Packit Service 501009
	int len;
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID() &&
Packit Service 501009
		(bt->task == tt->panic_task ||
Packit Service 501009
		(is_task_active(bt->task) && dd->num_prstatus_notes > 1))) {
Packit Service 501009
		note  = (Elf64_Nhdr *)dd->nt_prstatus_percpu[bt->tc->processor];
Packit Service 501009
		if (!note)
Packit Service 501009
			error(FATAL,
Packit Service 501009
				    "cannot determine NT_PRSTATUS ELF note "
Packit Service 501009
				    "for %s task: %lx\n",
Packit Service 501009
					(bt->task == tt->panic_task) ?
Packit Service 501009
					"panic" : "active", bt->task);
Packit Service 501009
		len = sizeof(Elf64_Nhdr);
Packit Service 501009
		len = roundup(len + note->n_namesz, 4);
Packit Service 501009
		bt->machdep = (void *)((char *)note + len +
Packit Service 501009
			MEMBER_OFFSET("elf_prstatus", "pr_reg"));
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Send the request to the proper architecture hander.
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
get_diskdump_regs(struct bt_info *bt, ulong *eip, ulong *esp)
Packit Service 501009
{
Packit Service 501009
	switch (dd->machine_type) 
Packit Service 501009
	{
Packit Service 501009
	case EM_ARM:
Packit Service 501009
		get_diskdump_regs_arm(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_MIPS:
Packit Service 501009
		return get_diskdump_regs_32(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_386:
Packit Service 501009
		return get_netdump_regs_x86(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_IA_64:
Packit Service 501009
	       /* For normal backtraces, this information will be obtained
Packit Service 501009
		* frome the switch_stack structure, which is pointed to by
Packit Service 501009
		* the thread.ksp field of the task_struct. But it's still
Packit Service 501009
		* needed by the "bt -t" option.
Packit Service 501009
		*/
Packit Service 501009
		machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_PPC:
Packit Service 501009
		return get_diskdump_regs_ppc(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_PPC64:
Packit Service 501009
		return get_diskdump_regs_ppc64(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_X86_64:
Packit Service 501009
		return get_netdump_regs_x86_64(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_S390:
Packit Service 501009
		return machdep->get_stack_frame(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_AARCH64:
Packit Service 501009
		get_diskdump_regs_arm64(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	case EM_SPARCV9:
Packit Service 501009
		get_diskdump_regs_sparc64(bt, eip, esp);
Packit Service 501009
		break;
Packit Service 501009
Packit Service 501009
	default:
Packit Service 501009
		error(FATAL, "%s: unsupported machine type: %s\n",
Packit Service 501009
			DISKDUMP_VALID() ? "diskdump" : "compressed kdump",
Packit Service 501009
			MACHINE_TYPE);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Return the processor page size.
Packit Service 501009
 */
Packit Service 501009
uint
Packit Service 501009
diskdump_page_size(void)
Packit Service 501009
{
Packit Service 501009
	if (!DISKDUMP_VALID() && !KDUMP_CMPRS_VALID())
Packit Service 501009
		return 0;
Packit Service 501009
Packit Service 501009
	return dd->header->block_size;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  diskdump_free_memory(), and diskdump_memory_used() 
Packit Service 501009
 *  are debug only, and probably unnecessary to implement.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
diskdump_free_memory(void)
Packit Service 501009
{
Packit Service 501009
        return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int 
Packit Service 501009
diskdump_memory_used(void)
Packit Service 501009
{
Packit Service 501009
        return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
dump_vmcoreinfo(FILE *fp)
Packit Service 501009
{
Packit Service 501009
	char *buf = NULL;
Packit Service 501009
	unsigned long i = 0;
Packit Service 501009
	unsigned long size_vmcoreinfo = dd->sub_header_kdump->size_vmcoreinfo;
Packit Service 501009
	off_t offset = dd->sub_header_kdump->offset_vmcoreinfo;
Packit Service 501009
	const off_t failed = (off_t)-1;
Packit Service 501009
Packit Service 501009
	if ((buf = malloc(size_vmcoreinfo)) == NULL) {
Packit Service 501009
		error(FATAL, "compressed kdump: cannot malloc vmcoreinfo"
Packit Service 501009
				" buffer\n");
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, offset, buf, size_vmcoreinfo)) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot read vmcoreinfo data\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot lseek dump vmcoreinfo\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
		if (read(dd->dfd, buf, size_vmcoreinfo) < size_vmcoreinfo) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot read vmcoreinfo data\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(fp, "                      ");
Packit Service 501009
	for (i = 0; i < size_vmcoreinfo; i++) {
Packit Service 501009
		fprintf(fp, "%c", buf[i]);
Packit Service 501009
		if ((buf[i] == '\n') && ((i+1) != size_vmcoreinfo))
Packit Service 501009
			fprintf(fp, "                      ");
Packit Service 501009
	}
Packit Service 501009
	if (buf[i-1] != '\n')
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
err:
Packit Service 501009
	if (buf)
Packit Service 501009
		free(buf);
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void 
Packit Service 501009
dump_eraseinfo(FILE *fp)
Packit Service 501009
{
Packit Service 501009
	char *buf = NULL;
Packit Service 501009
	unsigned long i = 0;
Packit Service 501009
	unsigned long size_eraseinfo = dd->sub_header_kdump->size_eraseinfo;
Packit Service 501009
	off_t offset = dd->sub_header_kdump->offset_eraseinfo;
Packit Service 501009
	const off_t failed = (off_t)-1;
Packit Service 501009
Packit Service 501009
	if ((buf = malloc(size_eraseinfo)) == NULL) {
Packit Service 501009
		error(FATAL, "compressed kdump: cannot malloc eraseinfo"
Packit Service 501009
				" buffer\n");
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, offset, buf, size_eraseinfo)) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot read eraseinfo data\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot lseek dump eraseinfo\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
		if (read(dd->dfd, buf, size_eraseinfo) < size_eraseinfo) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot read eraseinfo data\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(fp, "                      ");
Packit Service 501009
	for (i = 0; i < size_eraseinfo; i++) {
Packit Service 501009
		fprintf(fp, "%c", buf[i]);
Packit Service 501009
		if (buf[i] == '\n')
Packit Service 501009
			fprintf(fp, "                      ");
Packit Service 501009
	}
Packit Service 501009
	if (buf[i - 1] != '\n')
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
err:
Packit Service 501009
	if (buf)
Packit Service 501009
		free(buf);
Packit Service 501009
	return;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
dump_note_offsets(FILE *fp)
Packit Service 501009
{
Packit Service 501009
	struct kdump_sub_header *sub_header_kdump = dd->sub_header_kdump;
Packit Service 501009
	size_t size;
Packit Service 501009
	off_t offset;
Packit Service 501009
	Elf32_Nhdr *note32 = NULL;
Packit Service 501009
	Elf64_Nhdr *note64 = NULL;
Packit Service 501009
	size_t tot, len = 0;
Packit Service 501009
	int qemu, cnt;
Packit Service 501009
Packit Service 501009
	if (KDUMP_CMPRS_VALID() && !(dd->flags & NO_ELF_NOTES) &&
Packit Service 501009
	    (dd->header->header_version >= 4) &&
Packit Service 501009
	    (sub_header_kdump->offset_note) &&
Packit Service 501009
	    (sub_header_kdump->size_note) && (machdep->process_elf_notes)) {
Packit Service 501009
		size = sub_header_kdump->size_note;
Packit Service 501009
		offset = sub_header_kdump->offset_note;
Packit Service 501009
Packit Service 501009
		fprintf(fp, "        NOTE offsets: ");
Packit Service 501009
		for (tot = cnt = 0; tot < size; tot += len) {
Packit Service 501009
			qemu = FALSE;
Packit Service 501009
			if (machine_type("X86_64") || machine_type("S390X") ||
Packit Service 501009
			    machine_type("ARM64") || machine_type("PPC64") ||
Packit Service 501009
			    machine_type("SPARC64")) {
Packit Service 501009
				note64 = (void *)dd->notes_buf + tot;
Packit Service 501009
				len = sizeof(Elf64_Nhdr);
Packit Service 501009
				if (STRNEQ((char *)note64 + len, "QEMU"))
Packit Service 501009
					qemu = TRUE;
Packit Service 501009
				len = roundup(len + note64->n_namesz, 4);
Packit Service 501009
				len = roundup(len + note64->n_descsz, 4);
Packit Service 501009
Packit Service 501009
				if (note64->n_type == NT_PRSTATUS) {
Packit Service 501009
					fprintf(fp, "%s%lx (NT_PRSTATUS)\n",
Packit Service 501009
						tot ? space(22) : "",
Packit Service 501009
						(ulong)(offset + tot));
Packit Service 501009
					cnt++;
Packit Service 501009
				} 
Packit Service 501009
				if (qemu) {
Packit Service 501009
					fprintf(fp, "%s%lx (QEMU)\n",
Packit Service 501009
						tot ? space(22) : "",
Packit Service 501009
						(ulong)(offset + tot));
Packit Service 501009
					cnt++;
Packit Service 501009
				}
Packit Service 501009
Packit Service 501009
			} else if (machine_type("X86") || machine_type("PPC")) {
Packit Service 501009
				note32 = (void *)dd->notes_buf + tot;
Packit Service 501009
				len = sizeof(Elf32_Nhdr);
Packit Service 501009
				if (STRNEQ((char *)note32 + len, "QEMU"))
Packit Service 501009
					qemu = TRUE;
Packit Service 501009
				len = roundup(len + note32->n_namesz, 4);
Packit Service 501009
				len = roundup(len + note32->n_descsz, 4);
Packit Service 501009
Packit Service 501009
				if (note32->n_type == NT_PRSTATUS) {
Packit Service 501009
					fprintf(fp, "%s%lx (NT_PRSTATUS)\n",
Packit Service 501009
						tot ? space(22) : "",
Packit Service 501009
						(ulong)(offset + tot));
Packit Service 501009
					cnt++;
Packit Service 501009
				}
Packit Service 501009
				if (qemu) {
Packit Service 501009
					fprintf(fp, "%s%lx (QEMU)\n",
Packit Service 501009
						tot ? space(22) : "",
Packit Service 501009
						(ulong)(offset + tot));
Packit Service 501009
					cnt++;
Packit Service 501009
				}
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		if (!cnt)
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  This function is dump-type independent, and could be used
Packit Service 501009
 *  to dump the diskdump_data structure contents and perhaps
Packit Service 501009
 *  the diskdump header data.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
__diskdump_memory_dump(FILE *fp)
Packit Service 501009
{
Packit Service 501009
	int i, others, dump_level;
Packit Service 501009
	struct disk_dump_header *dh;
Packit Service 501009
	struct disk_dump_sub_header *dsh;
Packit Service 501009
	struct kdump_sub_header *kdsh;
Packit Service 501009
	ulong *tasks;
Packit Service 501009
Packit Service 501009
	if (FLAT_FORMAT())
Packit Service 501009
		dump_flat_header(fp);
Packit Service 501009
Packit Service 501009
        fprintf(fp, "diskdump_data: \n");
Packit Service 501009
	fprintf(fp, "          filename: %s\n", dd->filename);
Packit Service 501009
        fprintf(fp, "             flags: %lx (", dd->flags);
Packit Service 501009
        others = 0;
Packit Service 501009
        if (dd->flags & DISKDUMP_LOCAL)
Packit Service 501009
                fprintf(fp, "%sDISKDUMP_LOCAL", others++ ? "|" : "");
Packit Service 501009
        if (dd->flags & KDUMP_CMPRS_LOCAL)
Packit Service 501009
                fprintf(fp, "%sKDUMP_CMPRS_LOCAL", others++ ? "|" : "");
Packit Service 501009
        if (dd->flags & ERROR_EXCLUDED)
Packit Service 501009
                fprintf(fp, "%sERROR_EXCLUDED", others++ ? "|" : "");
Packit Service 501009
        if (dd->flags & ZERO_EXCLUDED)
Packit Service 501009
                fprintf(fp, "%sZERO_EXCLUDED", others++ ? "|" : "");
Packit Service 501009
	if (dd->flags & NO_ELF_NOTES)
Packit Service 501009
		fprintf(fp, "%sNO_ELF_NOTES", others++ ? "|" : "");
Packit Service 501009
	if (dd->flags & LZO_SUPPORTED)
Packit Service 501009
		fprintf(fp, "%sLZO_SUPPORTED", others++ ? "|" : "");
Packit Service 501009
	if (dd->flags & SNAPPY_SUPPORTED)
Packit Service 501009
		fprintf(fp, "%sSNAPPY_SUPPORTED", others++ ? "|" : "");
Packit Service 501009
        fprintf(fp, ") %s\n", FLAT_FORMAT() ? "[FLAT]" : "");
Packit Service 501009
        fprintf(fp, "               dfd: %d\n", dd->dfd);
Packit Service 501009
        fprintf(fp, "               ofp: %lx\n", (ulong)dd->ofp);
Packit Service 501009
        fprintf(fp, "      machine_type: %d ", dd->machine_type);
Packit Service 501009
	switch (dd->machine_type)
Packit Service 501009
	{
Packit Service 501009
	case EM_ARM:
Packit Service 501009
		fprintf(fp, "(EM_ARM)\n"); break;
Packit Service 501009
	case EM_MIPS:
Packit Service 501009
		fprintf(fp, "(EM_MIPS)\n"); break;
Packit Service 501009
	case EM_386:
Packit Service 501009
		fprintf(fp, "(EM_386)\n"); break;
Packit Service 501009
	case EM_X86_64:
Packit Service 501009
		fprintf(fp, "(EM_X86_64)\n"); break;
Packit Service 501009
	case EM_IA_64:
Packit Service 501009
		fprintf(fp, "(EM_IA_64)\n"); break;
Packit Service 501009
	case EM_PPC:
Packit Service 501009
		fprintf(fp, "(EM_PPC)\n"); break;
Packit Service 501009
	case EM_PPC64:
Packit Service 501009
		fprintf(fp, "(EM_PPC64)\n"); break;
Packit Service 501009
	case EM_S390:
Packit Service 501009
		fprintf(fp, "(EM_S390)\n"); break;
Packit Service 501009
	case EM_AARCH64:
Packit Service 501009
		fprintf(fp, "(EM_AARCH64)\n"); break;
Packit Service 501009
	case EM_SPARCV9:
Packit Service 501009
		fprintf(fp, "(EM_SPARCV9)\n"); break;
Packit Service 501009
	default:
Packit Service 501009
		fprintf(fp, "(unknown)\n"); break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
        fprintf(fp, "\n            header: %lx\n", (ulong)dd->header);
Packit Service 501009
	dh = dd->header;
Packit Service 501009
	fprintf(fp, "           signature: \"");
Packit Service 501009
	for (i = 0; i < SIG_LEN; i++)
Packit Service 501009
		if (dh->signature[i])
Packit Service 501009
			fprintf(fp, "%c", dh->signature[i]);
Packit Service 501009
	fprintf(fp, "\"\n");
Packit Service 501009
	fprintf(fp, "      header_version: %d\n", dh->header_version);
Packit Service 501009
	fprintf(fp, "             utsname:\n");
Packit Service 501009
	fprintf(fp, "               sysname: %s\n", dh->utsname.sysname);
Packit Service 501009
	fprintf(fp, "              nodename: %s\n", dh->utsname.nodename);
Packit Service 501009
	fprintf(fp, "               release: %s\n", dh->utsname.release);
Packit Service 501009
	fprintf(fp, "               version: %s\n", dh->utsname.version);
Packit Service 501009
	fprintf(fp, "               machine: %s\n", dh->utsname.machine);
Packit Service 501009
	fprintf(fp, "            domainname: %s\n", dh->utsname.domainname);
Packit Service 501009
	fprintf(fp, "           timestamp:\n");
Packit Service 501009
	fprintf(fp, "                tv_sec: %lx\n", dh->timestamp.tv_sec);
Packit Service 501009
	fprintf(fp, "               tv_usec: %lx\n", dh->timestamp.tv_usec);
Packit Service 501009
	fprintf(fp, "              status: %x (", dh->status);
Packit Service 501009
	switch (dd->flags & (DISKDUMP_LOCAL|KDUMP_CMPRS_LOCAL))
Packit Service 501009
	{
Packit Service 501009
        case DISKDUMP_LOCAL:
Packit Service 501009
		if (dh->status == DUMP_HEADER_COMPLETED)
Packit Service 501009
			fprintf(fp, "DUMP_HEADER_COMPLETED");
Packit Service 501009
		else if (dh->status == DUMP_HEADER_INCOMPLETED)
Packit Service 501009
			fprintf(fp, "DUMP_HEADER_INCOMPLETED");
Packit Service 501009
		else if (dh->status == DUMP_HEADER_COMPRESSED)
Packit Service 501009
			fprintf(fp, "DUMP_HEADER_COMPRESSED");
Packit Service 501009
		break;
Packit Service 501009
	case KDUMP_CMPRS_LOCAL:
Packit Service 501009
		if (dh->status & DUMP_DH_COMPRESSED_ZLIB)
Packit Service 501009
			fprintf(fp, "DUMP_DH_COMPRESSED_ZLIB");
Packit Service 501009
		if (dh->status & DUMP_DH_COMPRESSED_LZO)
Packit Service 501009
			fprintf(fp, "DUMP_DH_COMPRESSED_LZO");
Packit Service 501009
		if (dh->status & DUMP_DH_COMPRESSED_SNAPPY)
Packit Service 501009
			fprintf(fp, "DUMP_DH_COMPRESSED_SNAPPY");
Packit Service 501009
		if (dh->status & DUMP_DH_COMPRESSED_INCOMPLETE)
Packit Service 501009
			fprintf(fp, "DUMP_DH_COMPRESSED_INCOMPLETE");
Packit Service 501009
		if (dh->status & DUMP_DH_EXCLUDED_VMEMMAP)
Packit Service 501009
			fprintf(fp, "DUMP_DH_EXCLUDED_VMEMMAP");
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
	fprintf(fp, ")\n");
Packit Service 501009
	fprintf(fp, "          block_size: %d\n", dh->block_size);
Packit Service 501009
	fprintf(fp, "        sub_hdr_size: %d\n", dh->sub_hdr_size);
Packit Service 501009
	fprintf(fp, "       bitmap_blocks: %u\n", dh->bitmap_blocks);
Packit Service 501009
	fprintf(fp, "           max_mapnr: %u\n", dh->max_mapnr);
Packit Service 501009
	fprintf(fp, "    total_ram_blocks: %u\n", dh->total_ram_blocks);
Packit Service 501009
	fprintf(fp, "       device_blocks: %u\n", dh->device_blocks);
Packit Service 501009
	fprintf(fp, "      written_blocks: %u\n", dh->written_blocks);
Packit Service 501009
	fprintf(fp, "         current_cpu: %u\n", dh->current_cpu);
Packit Service 501009
	fprintf(fp, "             nr_cpus: %d\n", dh->nr_cpus);
Packit Service 501009
	tasks = (ulong *)&dh->tasks[0];
Packit Service 501009
	fprintf(fp, "      tasks[nr_cpus]: %lx\n", *tasks);
Packit Service 501009
	for (tasks++, i = 1; i < dh->nr_cpus; i++) {
Packit Service 501009
		fprintf(fp, "                      %lx\n", *tasks);
Packit Service 501009
		tasks++;
Packit Service 501009
	}
Packit Service 501009
        fprintf(fp, "\n");
Packit Service 501009
	fprintf(fp, "        sub_header: %lx ", (ulong)dd->sub_header);
Packit Service 501009
	if ((dsh = dd->sub_header)) {
Packit Service 501009
		fprintf(fp, "\n            elf_regs: %lx\n", 
Packit Service 501009
			(ulong)&dsh->elf_regs);
Packit Service 501009
		fprintf(fp, "          dump_level: ");
Packit Service 501009
		if ((pc->flags & RUNTIME) && 
Packit Service 501009
		    ((dump_level = get_dump_level()) >= 0)) {
Packit Service 501009
			fprintf(fp, "%d (0x%x) %s", dump_level, dump_level, 
Packit Service 501009
				dump_level ? "(" : "");
Packit Service 501009
Packit Service 501009
#define DUMP_EXCLUDE_CACHE 0x00000001   /* Exclude LRU & SwapCache pages*/
Packit Service 501009
#define DUMP_EXCLUDE_CLEAN 0x00000002   /* Exclude all-zero pages */
Packit Service 501009
#define DUMP_EXCLUDE_FREE  0x00000004   /* Exclude free pages */
Packit Service 501009
#define DUMP_EXCLUDE_ANON  0x00000008   /* Exclude Anon pages */
Packit Service 501009
#define DUMP_SAVE_PRIVATE  0x00000010   /* Save private pages */
Packit Service 501009
Packit Service 501009
		        others = 0;
Packit Service 501009
        		if (dump_level & DUMP_EXCLUDE_CACHE)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_CACHE", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DUMP_EXCLUDE_CLEAN)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_CLEAN", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DUMP_EXCLUDE_FREE)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_FREE", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DUMP_EXCLUDE_ANON)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_ANON", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DUMP_SAVE_PRIVATE)
Packit Service 501009
                		fprintf(fp, "%sDUMP_SAVE_PRIVATE", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
			fprintf(fp, "%s\n\n", dump_level ? ")" : "");
Packit Service 501009
		} else
Packit Service 501009
			fprintf(fp, "%s\n\n", pc->flags & RUNTIME ? 
Packit Service 501009
				"(unknown)" : "(undetermined)");
Packit Service 501009
Packit Service 501009
	} else
Packit Service 501009
        	fprintf(fp, "(n/a)\n\n");
Packit Service 501009
Packit Service 501009
	fprintf(fp, "  sub_header_kdump: %lx ", (ulong)dd->sub_header_kdump);
Packit Service 501009
	if ((kdsh = dd->sub_header_kdump)) {
Packit Service 501009
		fprintf(fp, "\n           phys_base: %lx\n", 
Packit Service 501009
			(ulong)kdsh->phys_base);
Packit Service 501009
		fprintf(fp, "          dump_level: ");
Packit Service 501009
		if ((dump_level = get_dump_level()) >= 0) {
Packit Service 501009
			fprintf(fp, "%d (0x%x) %s", dump_level, dump_level, 
Packit Service 501009
				dump_level ? "(" : "");
Packit Service 501009
Packit Service 501009
#define DL_EXCLUDE_ZERO         (0x001) /* Exclude Pages filled with Zeros */
Packit Service 501009
#define DL_EXCLUDE_CACHE        (0x002) /* Exclude Cache Pages without Private Pages */
Packit Service 501009
#define DL_EXCLUDE_CACHE_PRI    (0x004) /* Exclude Cache Pages with Private Pages */
Packit Service 501009
#define DL_EXCLUDE_USER_DATA    (0x008) /* Exclude UserProcessData Pages */
Packit Service 501009
#define DL_EXCLUDE_FREE         (0x010) /* Exclude Free Pages */
Packit Service 501009
Packit Service 501009
			others = 0;
Packit Service 501009
        		if (dump_level & DL_EXCLUDE_ZERO)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_ZERO", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DL_EXCLUDE_CACHE)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_CACHE", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DL_EXCLUDE_CACHE_PRI)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_CACHE_PRI", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DL_EXCLUDE_USER_DATA)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_USER_DATA", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
        		if (dump_level & DL_EXCLUDE_FREE)
Packit Service 501009
                		fprintf(fp, "%sDUMP_EXCLUDE_FREE", 
Packit Service 501009
					others++ ? "|" : "");
Packit Service 501009
			others = 0;
Packit Service 501009
Packit Service 501009
			fprintf(fp, "%s\n", dump_level ? ")" : "");
Packit Service 501009
		} else
Packit Service 501009
			fprintf(fp, "(unknown)\n");
Packit Service 501009
Packit Service 501009
		if (dh->header_version >= 2) {
Packit Service 501009
			fprintf(fp, "               split: %d\n", kdsh->split);
Packit Service 501009
			fprintf(fp, "           start_pfn: ");
Packit Service 501009
			if (KDUMP_SPLIT())
Packit Service 501009
				fprintf(fp, "%ld (0x%lx)\n", 
Packit Service 501009
					kdsh->start_pfn, kdsh->start_pfn);
Packit Service 501009
			else
Packit Service 501009
				fprintf(fp, "(unused)\n");
Packit Service 501009
			fprintf(fp, "             end_pfn: ");
Packit Service 501009
			if (KDUMP_SPLIT())
Packit Service 501009
				fprintf(fp, "%ld (0x%lx)\n", 
Packit Service 501009
					kdsh->end_pfn, kdsh->end_pfn);
Packit Service 501009
			else
Packit Service 501009
				fprintf(fp, "(unused)\n");
Packit Service 501009
		}
Packit Service 501009
		if (dh->header_version >= 3) {
Packit Service 501009
			fprintf(fp, "   offset_vmcoreinfo: %llu (0x%llx)\n",
Packit Service 501009
				(ulonglong)dd->sub_header_kdump->offset_vmcoreinfo,
Packit Service 501009
				(ulonglong)dd->sub_header_kdump->offset_vmcoreinfo);
Packit Service 501009
			fprintf(fp, "     size_vmcoreinfo: %lu (0x%lx)\n",
Packit Service 501009
				dd->sub_header_kdump->size_vmcoreinfo,
Packit Service 501009
				dd->sub_header_kdump->size_vmcoreinfo);
Packit Service 501009
			if (dd->sub_header_kdump->offset_vmcoreinfo &&
Packit Service 501009
				dd->sub_header_kdump->size_vmcoreinfo) {
Packit Service 501009
				dump_vmcoreinfo(fp);
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		if (dh->header_version >= 4) {
Packit Service 501009
			fprintf(fp, "         offset_note: %llu (0x%llx)\n",
Packit Service 501009
				(ulonglong)dd->sub_header_kdump->offset_note,
Packit Service 501009
				(ulonglong)dd->sub_header_kdump->offset_note);
Packit Service 501009
			fprintf(fp, "           size_note: %lu (0x%lx)\n",
Packit Service 501009
				dd->sub_header_kdump->size_note,
Packit Service 501009
				dd->sub_header_kdump->size_note);
Packit Service 501009
			fprintf(fp, "           notes_buf: %lx\n",
Packit Service 501009
				(ulong)dd->notes_buf);
Packit Service 501009
			fprintf(fp, "  num_vmcoredd_notes: %d\n",
Packit Service 501009
				dd->num_vmcoredd_notes);
Packit Service 501009
			for (i = 0; i < dd->num_vmcoredd_notes; i++) {
Packit Service 501009
				fprintf(fp, "            notes[%d]: %lx %s\n",
Packit Service 501009
					i, (ulong)dd->nt_vmcoredd_array[i],
Packit Service 501009
					dd->nt_vmcoredd_array[i] ? "(NT_VMCOREDD)" : "");
Packit Service 501009
				display_vmcoredd_note(dd->nt_vmcoredd_array[i], fp);
Packit Service 501009
			}
Packit Service 501009
Packit Service 501009
			fprintf(fp, "  num_prstatus_notes: %d\n",
Packit Service 501009
				dd->num_prstatus_notes);
Packit Service 501009
			for (i = 0; i < dd->num_prstatus_notes; i++) {
Packit Service 501009
				fprintf(fp, "            notes[%d]: %lx %s\n",
Packit Service 501009
					i, (ulong)dd->nt_prstatus_percpu[i],
Packit Service 501009
					dd->nt_prstatus_percpu[i] ? "(NT_PRSTATUS)" : ""); 
Packit Service 501009
				display_ELF_note(dd->machine_type, PRSTATUS_NOTE,
Packit Service 501009
					 dd->nt_prstatus_percpu[i], fp);
Packit Service 501009
			}
Packit Service 501009
			fprintf(fp, "       snapshot_task: %lx %s\n", dd->snapshot_task, 
Packit Service 501009
				dd->snapshot_task ? "(NT_TASKSTRUCT)" : "");
Packit Service 501009
			fprintf(fp, "      num_qemu_notes: %d\n",
Packit Service 501009
				dd->num_qemu_notes);
Packit Service 501009
			for (i = 0; i < dd->num_qemu_notes; i++) {
Packit Service 501009
				fprintf(fp, "            notes[%d]: %lx (QEMUCPUState)\n",
Packit Service 501009
					i, (ulong)dd->nt_qemu_percpu[i]);
Packit Service 501009
				display_ELF_note(dd->machine_type, QEMU_NOTE,
Packit Service 501009
					dd->nt_qemu_percpu[i], fp);
Packit Service 501009
			}
Packit Service 501009
			dump_note_offsets(fp);
Packit Service 501009
		}
Packit Service 501009
		if (dh->header_version >= 5) {
Packit Service 501009
			fprintf(fp, "    offset_eraseinfo: %llu (0x%llx)\n",
Packit Service 501009
				(ulonglong)dd->sub_header_kdump->offset_eraseinfo,
Packit Service 501009
				(ulonglong)dd->sub_header_kdump->offset_eraseinfo);
Packit Service 501009
			fprintf(fp, "      size_eraseinfo: %lu (0x%lx)\n",
Packit Service 501009
				dd->sub_header_kdump->size_eraseinfo,
Packit Service 501009
				dd->sub_header_kdump->size_eraseinfo);
Packit Service 501009
			if (dd->sub_header_kdump->offset_eraseinfo &&
Packit Service 501009
				dd->sub_header_kdump->size_eraseinfo) {
Packit Service 501009
				dump_eraseinfo(fp);
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
		if (dh->header_version >= 6) {
Packit Service 501009
			fprintf(fp, "        start_pfn_64: ");
Packit Service 501009
			if (KDUMP_SPLIT())
Packit Service 501009
				fprintf(fp, "%lld (0x%llx)\n",
Packit Service 501009
					kdsh->start_pfn_64, kdsh->start_pfn_64);
Packit Service 501009
			else
Packit Service 501009
				fprintf(fp, "(unused)\n");
Packit Service 501009
			fprintf(fp, "          end_pfn_64: ");
Packit Service 501009
			if (KDUMP_SPLIT())
Packit Service 501009
				fprintf(fp, "%lld (0x%llx)\n",
Packit Service 501009
					kdsh->end_pfn_64, kdsh->end_pfn_64);
Packit Service 501009
			else
Packit Service 501009
				fprintf(fp, "(unused)\n");
Packit Service 501009
Packit Service 501009
			fprintf(fp, "        max_mapnr_64: %llu (0x%llx)\n",
Packit Service 501009
				kdsh->max_mapnr_64, kdsh->max_mapnr_64);
Packit Service 501009
		}
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
	} else
Packit Service 501009
        	fprintf(fp, "(n/a)\n\n");
Packit Service 501009
Packit Service 501009
	fprintf(fp, "       data_offset: %lx\n", (ulong)dd->data_offset);
Packit Service 501009
	fprintf(fp, "        block_size: %d\n", dd->block_size);
Packit Service 501009
	fprintf(fp, "       block_shift: %d\n", dd->block_shift);
Packit Service 501009
	fprintf(fp, "            bitmap: %lx\n", (ulong)dd->bitmap);
Packit Service 501009
	fprintf(fp, "        bitmap_len: %lld\n", (ulonglong)dd->bitmap_len);
Packit Service 501009
	fprintf(fp, "         max_mapnr: %lld (0x%llx)\n", dd->max_mapnr, dd->max_mapnr);
Packit Service 501009
	fprintf(fp, "   dumpable_bitmap: %lx\n", (ulong)dd->dumpable_bitmap);
Packit Service 501009
	fprintf(fp, "              byte: %d\n", dd->byte);
Packit Service 501009
	fprintf(fp, "               bit: %d\n", dd->bit);
Packit Service 501009
	fprintf(fp, "   compressed_page: %lx\n", (ulong)dd->compressed_page);
Packit Service 501009
	fprintf(fp, "         curbufptr: %lx\n\n", (ulong)dd->curbufptr);
Packit Service 501009
Packit Service 501009
	for (i = 0; i < DISKDUMP_CACHED_PAGES; i++) {
Packit Service 501009
		fprintf(fp, "%spage_cache_hdr[%d]:\n", i < 10 ? " " : "", i);
Packit Service 501009
		fprintf(fp, "            pg_flags: %x (", dd->page_cache_hdr[i].pg_flags);
Packit Service 501009
		others = 0;
Packit Service 501009
		if (dd->page_cache_hdr[i].pg_flags & PAGE_VALID)
Packit Service 501009
                	fprintf(fp, "%sPAGE_VALID", others++ ? "|" : "");
Packit Service 501009
		fprintf(fp, ")\n");
Packit Service 501009
		fprintf(fp, "             pg_addr: %llx\n", (ulonglong)dd->page_cache_hdr[i].pg_addr);
Packit Service 501009
		fprintf(fp, "           pg_bufptr: %lx\n", (ulong)dd->page_cache_hdr[i].pg_bufptr);
Packit Service 501009
		fprintf(fp, "        pg_hit_count: %ld\n", dd->page_cache_hdr[i].pg_hit_count);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(fp, "\n    page_cache_buf: %lx\n", (ulong)dd->page_cache_buf);
Packit Service 501009
	fprintf(fp, "       evict_index: %d\n", dd->evict_index);
Packit Service 501009
	fprintf(fp, "         evictions: %ld\n", dd->evictions);
Packit Service 501009
	fprintf(fp, "          accesses: %ld\n", dd->accesses);
Packit Service 501009
	fprintf(fp, "      cached_reads: %ld ", dd->cached_reads);
Packit Service 501009
	if (dd->accesses)
Packit Service 501009
		fprintf(fp, "(%ld%%)\n",
Packit Service 501009
			dd->cached_reads * 100 / dd->accesses);
Packit Service 501009
	else
Packit Service 501009
		fprintf(fp, "\n");
Packit Service 501009
	fprintf(fp, "       valid_pages: %lx\n", (ulong)dd->valid_pages);
Packit Service 501009
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * Wrapper of __diskdump_memory_dump()
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
diskdump_memory_dump(FILE *fp)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	if (KDUMP_SPLIT() && (dd_list != NULL))
Packit Service 501009
		for (i = 0; i < num_dumpfiles; i++) {
Packit Service 501009
			dd = dd_list[i];
Packit Service 501009
			__diskdump_memory_dump(fp);
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
		}
Packit Service 501009
	else
Packit Service 501009
		__diskdump_memory_dump(fp);
Packit Service 501009
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Get the switch_stack address of the passed-in task.  
Packit Service 501009
 */
Packit Service 501009
ulong
Packit Service 501009
get_diskdump_switch_stack(ulong task)
Packit Service 501009
{
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Versions of disk_dump that support it contain the "dump_level" symbol.
Packit Service 501009
 *  Version 1 and later compressed kdump dumpfiles contain the dump level
Packit Service 501009
 *  in an additional field of the sub_header_kdump structure.
Packit Service 501009
 */
Packit Service 501009
int
Packit Service 501009
get_dump_level(void)
Packit Service 501009
{
Packit Service 501009
	int dump_level;
Packit Service 501009
Packit Service 501009
	if (DISKDUMP_VALID()) {
Packit Service 501009
		if (symbol_exists("dump_level") &&
Packit Service 501009
		    readmem(symbol_value("dump_level"), KVADDR, &dump_level,
Packit Service 501009
		    sizeof(dump_level), "dump_level", QUIET|RETURN_ON_ERROR))
Packit Service 501009
                 	return dump_level;
Packit Service 501009
	} else if (KDUMP_CMPRS_VALID()) {
Packit Service 501009
		if (dd->header->header_version >= 1)
Packit Service 501009
			return dd->sub_header_kdump->dump_level;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return -1;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Used by the "sys" command to display [PARTIAL DUMP] 
Packit Service 501009
 *  after the dumpfile name.
Packit Service 501009
 */
Packit Service 501009
int 
Packit Service 501009
is_partial_diskdump(void) 
Packit Service 501009
{
Packit Service 501009
	return (get_dump_level() > 0 ? TRUE : FALSE);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Used by "sys" command to dump multiple split dumpfiles.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
show_split_dumpfiles(void)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
	struct diskdump_data *ddp;
Packit Service 501009
	struct disk_dump_header *dh;
Packit Service 501009
Packit Service 501009
        for (i = 0; i < num_dumpfiles; i++) {
Packit Service 501009
        	ddp = dd_list[i];
Packit Service 501009
		dh = ddp->header;
Packit Service 501009
		fprintf(fp, "%s%s%s%s%s", 
Packit Service 501009
			i ? "              " : "", 
Packit Service 501009
			ddp->filename, 
Packit Service 501009
			is_partial_diskdump() ? " [PARTIAL DUMP]" : "",
Packit Service 501009
			dh->status & DUMP_DH_COMPRESSED_INCOMPLETE ? 
Packit Service 501009
			" [INCOMPLETE]" : "",
Packit Service 501009
			dh->status & DUMP_DH_EXCLUDED_VMEMMAP ? 
Packit Service 501009
			" [EXCLUDED VMEMMAP]" : "");
Packit Service 501009
		if ((i+1) < num_dumpfiles)
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void *
Packit Service 501009
diskdump_get_prstatus_percpu(int cpu)
Packit Service 501009
{
Packit Service 501009
	int online;
Packit Service 501009
Packit Service 501009
	if ((cpu < 0) || (cpu >= dd->num_prstatus_notes))
Packit Service 501009
		return NULL;
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 * If no cpu mapping was done, then there must be
Packit Service 501009
	 * a one-to-one relationship between the number
Packit Service 501009
	 * of online cpus and the number of notes.
Packit Service 501009
	 */
Packit Service 501009
        if ((online = get_cpus_online()) && 
Packit Service 501009
	    (online == kt->cpus) &&
Packit Service 501009
	    (online != dd->num_prstatus_notes))
Packit Service 501009
                return NULL;
Packit Service 501009
Packit Service 501009
	return dd->nt_prstatus_percpu[cpu];
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * Reads a string value from VMCOREINFO.
Packit Service 501009
 *
Packit Service 501009
 * Returns a string (that has to be freed by the caller) that contains the
Packit Service 501009
 * value for key or NULL if the key has not been found.
Packit Service 501009
 */
Packit Service 501009
static char *
Packit Service 501009
vmcoreinfo_read_string(const char *key)
Packit Service 501009
{
Packit Service 501009
	char *buf, *value_string, *p1, *p2;
Packit Service 501009
	size_t value_length;
Packit Service 501009
	ulong size_vmcoreinfo;
Packit Service 501009
	off_t offset;
Packit Service 501009
	char keybuf[BUFSIZE];
Packit Service 501009
	const off_t failed = (off_t)-1;
Packit Service 501009
Packit Service 501009
	if (dd->header->header_version < 3)
Packit Service 501009
		return NULL;
Packit Service 501009
Packit Service 501009
	buf = value_string = NULL;
Packit Service 501009
	size_vmcoreinfo = dd->sub_header_kdump->size_vmcoreinfo;
Packit Service 501009
	offset = dd->sub_header_kdump->offset_vmcoreinfo;
Packit Service 501009
	sprintf(keybuf, "%s=", key);
Packit Service 501009
Packit Service 501009
	if ((buf = malloc(size_vmcoreinfo+1)) == NULL) {
Packit Service 501009
		error(INFO, "compressed kdump: cannot malloc vmcoreinfo"
Packit Service 501009
			    " buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (FLAT_FORMAT()) {
Packit Service 501009
		if (!read_flattened_format(dd->dfd, offset, buf, size_vmcoreinfo)) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot read vmcoreinfo data\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	} else {
Packit Service 501009
		if (lseek(dd->dfd, offset, SEEK_SET) == failed) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot lseek dump vmcoreinfo\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
		if (read(dd->dfd, buf, size_vmcoreinfo) < size_vmcoreinfo) {
Packit Service 501009
			error(INFO, "compressed kdump: cannot read vmcoreinfo data\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	buf[size_vmcoreinfo] = '\n';
Packit Service 501009
Packit Service 501009
	if ((p1 = strstr(buf, keybuf))) {
Packit Service 501009
		p2 = p1 + strlen(keybuf);
Packit Service 501009
		p1 = strstr(p2, "\n");
Packit Service 501009
		value_length = p1-p2;
Packit Service 501009
		value_string = calloc(value_length+1, sizeof(char));
Packit Service 501009
		strncpy(value_string, p2, value_length);
Packit Service 501009
		value_string[value_length] = NULLCHAR;
Packit Service 501009
	}
Packit Service 501009
err:
Packit Service 501009
	if (buf)
Packit Service 501009
		free(buf);
Packit Service 501009
Packit Service 501009
	return value_string;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
diskdump_get_osrelease(void)
Packit Service 501009
{
Packit Service 501009
	char *string;
Packit Service 501009
Packit Service 501009
	if ((string = vmcoreinfo_read_string("OSRELEASE"))) {
Packit Service 501009
		fprintf(fp, "%s\n", string);
Packit Service 501009
		free(string);
Packit Service 501009
	}
Packit Service 501009
	else
Packit Service 501009
		pc->flags2 &= ~GET_OSRELEASE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
valid_note_address(unsigned char *offset)
Packit Service 501009
{
Packit Service 501009
	if (offset > (dd->notes_buf + dd->sub_header_kdump->size_note))
Packit Service 501009
		return FALSE;
Packit Service 501009
	
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
diskdump_display_regs(int cpu, FILE *ofp)
Packit Service 501009
{
Packit Service 501009
	Elf32_Nhdr *note32;
Packit Service 501009
	Elf64_Nhdr *note64;
Packit Service 501009
	char *user_regs;
Packit Service 501009
	size_t len;
Packit Service 501009
Packit Service 501009
	if ((cpu < 0) || (cpu >= dd->num_prstatus_notes) ||
Packit Service 501009
	    (dd->nt_prstatus_percpu[cpu] == NULL)) {
Packit Service 501009
		error(INFO, "registers not collected for cpu %d\n", cpu);
Packit Service 501009
                return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (machine_type("X86_64")) {
Packit Service 501009
		note64 = dd->nt_prstatus_percpu[cpu];
Packit Service 501009
		len = sizeof(Elf64_Nhdr);
Packit Service 501009
		len = roundup(len + note64->n_namesz, 4);
Packit Service 501009
		len = roundup(len + note64->n_descsz, 4);
Packit Service 501009
		if (!valid_note_address((unsigned char *)note64 + len)) {
Packit Service 501009
			error(INFO, "invalid NT_PRSTATUS note for cpu %d\n", cpu);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
		user_regs = (char *)note64 + len - SIZE(user_regs_struct) - sizeof(long);
Packit Service 501009
		fprintf(ofp,
Packit Service 501009
		    "    RIP: %016llx  RSP: %016llx  RFLAGS: %08llx\n"
Packit Service 501009
		    "    RAX: %016llx  RBX: %016llx  RCX: %016llx\n"
Packit Service 501009
		    "    RDX: %016llx  RSI: %016llx  RDI: %016llx\n"
Packit Service 501009
		    "    RBP: %016llx   R8: %016llx   R9: %016llx\n"
Packit Service 501009
		    "    R10: %016llx  R11: %016llx  R12: %016llx\n"
Packit Service 501009
		    "    R13: %016llx  R14: %016llx  R15: %016llx\n"
Packit Service 501009
		    "    CS: %04x  SS: %04x\n",
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rip)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rsp)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_eflags)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rax)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rbx)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rcx)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rdx)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rsi)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rdi)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_rbp)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r8)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r9)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r10)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r11)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r12)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r13)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r14)),
Packit Service 501009
		    ULONGLONG(user_regs + OFFSET(user_regs_struct_r15)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_cs)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_ss))
Packit Service 501009
		);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (machine_type("PPC64")) {
Packit Service 501009
		struct ppc64_elf_prstatus *prs;
Packit Service 501009
		struct ppc64_pt_regs *pr;
Packit Service 501009
Packit Service 501009
		note64 = dd->nt_prstatus_percpu[cpu];
Packit Service 501009
		len = sizeof(Elf64_Nhdr);
Packit Service 501009
		len = roundup(len + note64->n_namesz, 4);
Packit Service 501009
		len = roundup(len + note64->n_descsz, 4);
Packit Service 501009
		if (!valid_note_address((unsigned char *)note64 + len)) {
Packit Service 501009
			error(INFO, "invalid NT_PRSTATUS note for cpu %d\n", cpu);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		prs = (struct ppc64_elf_prstatus *)
Packit Service 501009
			((char *)note64 + sizeof(Elf64_Nhdr) + note64->n_namesz);
Packit Service 501009
		prs = (struct ppc64_elf_prstatus *)roundup((ulong)prs, 4);
Packit Service 501009
		pr = &prs->pr_reg;
Packit Service 501009
Packit Service 501009
		fprintf(ofp, 
Packit Service 501009
			"     R0: %016lx   R1: %016lx   R2: %016lx\n"
Packit Service 501009
			"     R3: %016lx   R4: %016lx   R5: %016lx\n"
Packit Service 501009
			"     R6: %016lx   R7: %016lx   R8: %016lx\n"
Packit Service 501009
			"     R9: %016lx  R10: %016lx  R11: %016lx\n"
Packit Service 501009
			"    R12: %016lx  R13: %016lx  R14: %016lx\n"
Packit Service 501009
			"    R15: %016lx  R16: %016lx  R16: %016lx\n"
Packit Service 501009
			"    R18: %016lx  R19: %016lx  R20: %016lx\n"
Packit Service 501009
			"    R21: %016lx  R22: %016lx  R23: %016lx\n"
Packit Service 501009
			"    R24: %016lx  R25: %016lx  R26: %016lx\n"
Packit Service 501009
			"    R27: %016lx  R28: %016lx  R29: %016lx\n"
Packit Service 501009
			"    R30: %016lx  R31: %016lx\n"
Packit Service 501009
			"      NIP: %016lx     MSR: %016lx\n"
Packit Service 501009
			"    OGPR3: %016lx     CTR: %016lx\n"  
Packit Service 501009
			"     LINK: %016lx     XER: %016lx\n"
Packit Service 501009
			"      CCR: %016lx      MQ: %016lx\n"
Packit Service 501009
			"     TRAP: %016lx     DAR: %016lx\n"
Packit Service 501009
			"    DSISR: %016lx  RESULT: %016lx\n",
Packit Service 501009
			pr->gpr[0], pr->gpr[1], pr->gpr[2],
Packit Service 501009
			pr->gpr[3], pr->gpr[4], pr->gpr[5],
Packit Service 501009
			pr->gpr[6], pr->gpr[7], pr->gpr[8],
Packit Service 501009
			pr->gpr[9], pr->gpr[10], pr->gpr[11],
Packit Service 501009
			pr->gpr[12], pr->gpr[13], pr->gpr[14],
Packit Service 501009
			pr->gpr[15], pr->gpr[16], pr->gpr[17],
Packit Service 501009
			pr->gpr[18], pr->gpr[19], pr->gpr[20],
Packit Service 501009
			pr->gpr[21], pr->gpr[22], pr->gpr[23],
Packit Service 501009
			pr->gpr[24], pr->gpr[25], pr->gpr[26],
Packit Service 501009
			pr->gpr[27], pr->gpr[28], pr->gpr[29],
Packit Service 501009
			pr->gpr[30], pr->gpr[31],
Packit Service 501009
			pr->nip, pr->msr, 
Packit Service 501009
			pr->orig_gpr3, pr->ctr,
Packit Service 501009
			pr->link, pr->xer,
Packit Service 501009
			pr->ccr, pr->mq,
Packit Service 501009
			pr->trap,  pr->dar, 
Packit Service 501009
			pr->dsisr, pr->result);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (machine_type("ARM64")) {
Packit Service 501009
		note64 = dd->nt_prstatus_percpu[cpu];
Packit Service 501009
		len = sizeof(Elf64_Nhdr);
Packit Service 501009
		len = roundup(len + note64->n_namesz, 4);
Packit Service 501009
		len = roundup(len + note64->n_descsz, 4);
Packit Service 501009
		if (!valid_note_address((unsigned char *)note64 + len)) {
Packit Service 501009
			error(INFO, "invalid NT_PRSTATUS note for cpu %d\n", cpu);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
		user_regs = (char *)note64 + len - SIZE(elf_prstatus) + OFFSET(elf_prstatus_pr_reg);
Packit Service 501009
		fprintf(ofp,
Packit Service 501009
			"    X0: %016lx   X1: %016lx   X2: %016lx\n"
Packit Service 501009
			"    X3: %016lx   X4: %016lx   X5: %016lx\n"
Packit Service 501009
			"    X6: %016lx   X7: %016lx   X8: %016lx\n"
Packit Service 501009
			"    X9: %016lx  X10: %016lx  X11: %016lx\n"
Packit Service 501009
			"   X12: %016lx  X13: %016lx  X14: %016lx\n"
Packit Service 501009
			"   X15: %016lx  X16: %016lx  X17: %016lx\n"
Packit Service 501009
			"   X18: %016lx  X19: %016lx  X20: %016lx\n"
Packit Service 501009
			"   X21: %016lx  X22: %016lx  X23: %016lx\n"
Packit Service 501009
			"   X24: %016lx  X25: %016lx  X26: %016lx\n"
Packit Service 501009
			"   X27: %016lx  X28: %016lx  X29: %016lx\n"
Packit Service 501009
			"    LR: %016lx   SP: %016lx   PC: %016lx\n"
Packit Service 501009
			"   PSTATE: %08lx   FPVALID: %08x\n", 
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 0),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 1),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 2),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 3),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 4),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 5),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 6),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 7),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 8),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 9),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 10),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 11),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 12),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 13),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 14),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 15),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 16),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 17),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 18),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 19),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 20),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 21),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 22),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 23),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 24),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 25),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 26),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 27),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 28),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 29),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 30),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 31),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 32),
Packit Service 501009
			ULONG(user_regs + sizeof(ulong) * 33),
Packit Service 501009
			UINT(user_regs + sizeof(ulong) * 34));
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (machine_type("X86")) {
Packit Service 501009
		note32 = dd->nt_prstatus_percpu[cpu];
Packit Service 501009
		len = sizeof(Elf32_Nhdr);
Packit Service 501009
		len = roundup(len + note32->n_namesz, 4);
Packit Service 501009
		len = roundup(len + note32->n_descsz, 4);
Packit Service 501009
		user_regs = (char *)note32 + len - SIZE(user_regs_struct) - sizeof(int);
Packit Service 501009
		if (!valid_note_address((unsigned char *)note32 + len)) {
Packit Service 501009
			error(INFO, "invalid NT_PRSTATUS note for cpu %d\n", cpu);
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
		fprintf(ofp,
Packit Service 501009
		    "    EAX: %08x  EBX: %08x  ECX: %08x  EDX: %08x\n"
Packit Service 501009
		    "    ESP: %08x  EIP: %08x  ESI: %08x  EDI: %08x\n"
Packit Service 501009
		    "    CS: %04x       DS: %04x       ES: %04x       FS: %04x\n"
Packit Service 501009
		    "    GS: %04x       SS: %04x\n"
Packit Service 501009
		    "    EBP: %08x  EFLAGS: %08x\n",
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_eax)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_ebx)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_ecx)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_edx)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_esp)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_eip)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_esi)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_edi)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_cs)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_ds)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_es)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_fs)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_gs)),
Packit Service 501009
		    USHORT(user_regs + OFFSET(user_regs_struct_ss)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_ebp)),
Packit Service 501009
		    UINT(user_regs + OFFSET(user_regs_struct_eflags))
Packit Service 501009
		);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
dump_registers_for_compressed_kdump(void)
Packit Service 501009
{
Packit Service 501009
	int c;
Packit Service 501009
Packit Service 501009
	if (!KDUMP_CMPRS_VALID() || (dd->header->header_version < 4) ||
Packit Service 501009
	    !(machine_type("X86") || machine_type("X86_64") || 
Packit Service 501009
	      machine_type("ARM64") || machine_type("PPC64")))
Packit Service 501009
		error(FATAL, "-r option not supported for this dumpfile\n");
Packit Service 501009
Packit Service 501009
	if (machine_type("ARM64") && (kt->cpus != dd->num_prstatus_notes))
Packit Service 501009
		fprintf(fp, "NOTE: cpus: %d  NT_PRSTATUS notes: %d  "
Packit Service 501009
			"(note-to-cpu mapping is questionable)\n\n", 
Packit Service 501009
			kt->cpus, dd->num_prstatus_notes);
Packit Service 501009
Packit Service 501009
	for (c = 0; c < kt->cpus; c++) {
Packit Service 501009
		if (hide_offline_cpu(c)) {
Packit Service 501009
			fprintf(fp, "%sCPU %d: [OFFLINE]\n", c ? "\n" : "", c);
Packit Service 501009
			continue;
Packit Service 501009
		} else
Packit Service 501009
			fprintf(fp, "%sCPU %d:\n", c ? "\n" : "", c);
Packit Service 501009
		diskdump_display_regs(c, fp);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
diskdump_kaslr_check()
Packit Service 501009
{
Packit Service 501009
	if (!QEMU_MEM_DUMP_NO_VMCOREINFO())
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if (dd->num_qemu_notes)
Packit Service 501009
		return TRUE;
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
#ifdef X86_64
Packit Service 501009
QEMUCPUState *
Packit Service 501009
diskdump_get_qemucpustate(int cpu)
Packit Service 501009
{
Packit Service 501009
        if (cpu >= dd->num_qemu_notes) {
Packit Service 501009
                if (CRASHDEBUG(1))
Packit Service 501009
                        error(INFO,
Packit Service 501009
                            "Invalid index for QEMU Note: %d (>= %d)\n",
Packit Service 501009
                            cpu, dd->num_qemu_notes);
Packit Service 501009
                return NULL;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        if (dd->machine_type != EM_X86_64) {
Packit Service 501009
                if (CRASHDEBUG(1))
Packit Service 501009
                        error(INFO, "Only x86_64 64bit is supported.\n");
Packit Service 501009
                return NULL;
Packit Service 501009
        }
Packit Service 501009
Packit Service 501009
        return (QEMUCPUState *)dd->nt_qemucs_percpu[cpu];
Packit Service 501009
}
Packit Service 501009
#endif
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * extract hardware specific device dumps from coredump.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
diskdump_device_dump_extract(int index, char *outfile, FILE *ofp)
Packit Service 501009
{
Packit Service 501009
	ulonglong offset;
Packit Service 501009
Packit Service 501009
	if (!dd->num_vmcoredd_notes)
Packit Service 501009
		error(FATAL, "no device dumps found in this dumpfile\n");
Packit Service 501009
	else if (index >= dd->num_vmcoredd_notes)
Packit Service 501009
		error(FATAL, "no device dump found at index: %d", index);
Packit Service 501009
Packit Service 501009
	offset = dd->sub_header_kdump->offset_note +
Packit Service 501009
		 ((unsigned char *)dd->nt_vmcoredd_array[index] -
Packit Service 501009
		  dd->notes_buf);
Packit Service 501009
Packit Service 501009
	devdump_extract(dd->nt_vmcoredd_array[index], offset, outfile, ofp);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * list all hardware specific device dumps present in coredump.
Packit Service 501009
 */
Packit Service 501009
void
Packit Service 501009
diskdump_device_dump_info(FILE *ofp)
Packit Service 501009
{
Packit Service 501009
	ulonglong offset;
Packit Service 501009
	char buf[BUFSIZE];
Packit Service 501009
	ulong i;
Packit Service 501009
Packit Service 501009
	if (!dd->num_vmcoredd_notes)
Packit Service 501009
		error(FATAL, "no device dumps found in this dumpfile\n");
Packit Service 501009
Packit Service 501009
	fprintf(fp, "%s ", mkstring(buf, strlen("INDEX"), LJUST, "INDEX"));
Packit Service 501009
	fprintf(fp, " %s ", mkstring(buf, LONG_LONG_PRLEN, LJUST, "OFFSET"));
Packit Service 501009
	fprintf(fp, "  %s ", mkstring(buf, LONG_PRLEN, LJUST, "SIZE"));
Packit Service 501009
	fprintf(fp, "NAME\n");
Packit Service 501009
Packit Service 501009
	for (i = 0; i < dd->num_vmcoredd_notes; i++) {
Packit Service 501009
		fprintf(fp, "%s  ", mkstring(buf, strlen("INDEX"), CENTER | INT_DEC, MKSTR(i)));
Packit Service 501009
		offset = dd->sub_header_kdump->offset_note +
Packit Service 501009
			 ((unsigned char *)dd->nt_vmcoredd_array[i] -
Packit Service 501009
			  dd->notes_buf);
Packit Service 501009
		devdump_info(dd->nt_vmcoredd_array[i], offset, ofp);
Packit Service 501009
	}
Packit Service 501009
}