Blame sadump.c

Packit Service 501009
/*
Packit Service 501009
 * sadump.h - core analysis suite
Packit Service 501009
 *
Packit Service 501009
 * Copyright (c) 2011 FUJITSU LIMITED
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
 * Author: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Packit Service 501009
 */
Packit Service 501009
Packit Service 501009
#include "defs.h"
Packit Service 501009
#include "sadump.h"
Packit Service 501009
#include <arpa/inet.h> /* htonl, htons */
Packit Service 501009
#include <elf.h>
Packit Service 501009
#include <inttypes.h>
Packit Service 501009
Packit Service 501009
enum {
Packit Service 501009
	failed = -1
Packit Service 501009
};
Packit Service 501009
Packit Service 501009
static struct sadump_data sadump_data = { 0 };
Packit Service 501009
static struct sadump_data *sd = &sadump_data;
Packit Service 501009
Packit Service 501009
static int read_device(void *buf, size_t bytes, ulong *offset);
Packit Service 501009
static int read_dump_header(char *file);
Packit Service 501009
static int add_disk(char *file);
Packit Service 501009
static int open_dump_file(char *file);
Packit Service 501009
static int open_disk(char *file);
Packit Service 501009
static uint64_t paddr_to_pfn(physaddr_t paddr);
Packit Service 501009
static inline int is_set_bit(char *bitmap, uint64_t pfn);
Packit Service 501009
static inline int page_is_ram(uint64_t nr);
Packit Service 501009
static inline int page_is_dumpable(uint64_t nr);
Packit Service 501009
static int lookup_diskset(uint64_t whole_offset, int *diskid, uint64_t *disk_offset);
Packit Service 501009
static struct tm *efi_time_t_to_tm(const efi_time_t *e);
Packit Service 501009
static char * guid_to_str(efi_guid_t *guid, char *buf, size_t buflen);
Packit Service 501009
static int verify_magic_number(uint32_t magicnum[DUMP_PART_HEADER_MAGICNUM_SIZE]);
Packit Service 501009
static ulong per_cpu_ptr(ulong ptr, int cpu);
Packit Service 501009
static ulong early_per_cpu_ptr(char *symbol, struct syment *sym, int cpu);
Packit Service 501009
static ulong legacy_per_cpu_ptr(ulong ptr, int cpu);
Packit Service 501009
static int get_prstatus_from_crash_notes(int cpu, char *prstatus);
Packit Service 501009
static void display_smram_cpu_state(int apicid, struct sadump_smram_cpu_state *s);
Packit Service 501009
static int cpu_to_apicid(int cpu, int *apicid);
Packit Service 501009
static int get_sadump_smram_cpu_state(int cpu, struct sadump_smram_cpu_state *smram);
Packit Service 501009
static int block_table_init(void);
Packit Service 501009
static uint64_t pfn_to_block(uint64_t pfn);
Packit Service 501009
Packit Service 501009
struct sadump_data *
Packit Service 501009
sadump_get_sadump_data(void)
Packit Service 501009
{
Packit Service 501009
	if (!SADUMP_VALID() || !SADUMP_DUMPFILE())
Packit Service 501009
		return NULL;
Packit Service 501009
Packit Service 501009
	return &sadump_data;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
sadump_cleanup_sadump_data(void)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	if (!SADUMP_VALID() || !SADUMP_DUMPFILE())
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if (sd->flags & SADUMP_DISKSET) {
Packit Service 501009
		for (i = 1; i < sd->sd_list_len; ++i) {
Packit Service 501009
			if (sd->sd_list[i]->dfd)
Packit Service 501009
				close(sd->sd_list[i]->dfd);
Packit Service 501009
			free(sd->sd_list[i]->header);
Packit Service 501009
			free(sd->sd_list[i]);
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	close(sd->dfd);
Packit Service 501009
	free(sd->header);
Packit Service 501009
	free(sd->dump_header);
Packit Service 501009
	free(sd->diskset_header);
Packit Service 501009
	free(sd->bitmap);
Packit Service 501009
	free(sd->dumpable_bitmap);
Packit Service 501009
	free(sd->page_buf);
Packit Service 501009
	free(sd->block_table);
Packit Service 501009
	if (sd->sd_list[0])
Packit Service 501009
		free(sd->sd_list[0]);
Packit Service 501009
	free(sd->sd_list);
Packit Service 501009
Packit Service 501009
	memset(&sadump_data, 0, sizeof(sadump_data));
Packit Service 501009
Packit Service 501009
	pc->flags &= ~SADUMP;
Packit Service 501009
	pc->dumpfile = NULL;
Packit Service 501009
	pc->readmem = NULL;
Packit Service 501009
	pc->writemem = NULL;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
read_device(void *buf, size_t bytes, ulong *offset)
Packit Service 501009
{
Packit Service 501009
	if (lseek(sd->dfd, *offset, SEEK_SET) == failed) {
Packit Service 501009
		error(INFO, "sadump: cannot lseek dump device\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
	if (read(sd->dfd, buf, bytes) < bytes) {
Packit Service 501009
		error(INFO, "sadump: cannot read dump device\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
	*offset += bytes;
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
read_dump_header(char *file)
Packit Service 501009
{
Packit Service 501009
	struct sadump_part_header *sph = NULL;
Packit Service 501009
	struct sadump_header *sh = NULL;
Packit Service 501009
	struct sadump_disk_set_header *new, *sdh = NULL;
Packit Service 501009
	struct sadump_media_header *smh = NULL;
Packit Service 501009
	struct sadump_diskset_data *sd_list_len_0 = NULL;
Packit Service 501009
	size_t block_size = SADUMP_DEFAULT_BLOCK_SIZE;
Packit Service 501009
	ulong flags = 0;
Packit Service 501009
	ulong offset = 0, sub_hdr_offset, data_offset;
Packit Service 501009
	uint32_t smram_cpu_state_size = 0;
Packit Service 501009
	ulong bitmap_len, dumpable_bitmap_len;
Packit Service 501009
	char *bitmap = NULL, *dumpable_bitmap = NULL, *page_buf = NULL;
Packit Service 501009
	char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
Packit Service 501009
	char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
Packit Service 501009
Packit Service 501009
	sph = malloc(block_size);
Packit Service 501009
	if (!sph) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate partition header buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sdh = malloc(block_size);
Packit Service 501009
	if (!sdh) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate disk set header buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sh = malloc(block_size);
Packit Service 501009
	if (!sh) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate dump header buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	smh = malloc(block_size);
Packit Service 501009
	if (!smh) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate media header buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
restart:
Packit Service 501009
	if (!read_device(sph, block_size, &offset)) {
Packit Service 501009
		error(INFO, "sadump: cannot read partition header\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (sph->signature1 != SADUMP_SIGNATURE1 ||
Packit Service 501009
	    sph->signature2 != SADUMP_SIGNATURE2) {
Packit Service 501009
Packit Service 501009
		flags |= SADUMP_MEDIA;
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: read dump device as media "
Packit Service 501009
			      "format\n");
Packit Service 501009
Packit Service 501009
		offset = 0;
Packit Service 501009
Packit Service 501009
		if (!read_device(smh, block_size, &offset)) {
Packit Service 501009
			error(INFO, "sadump: cannot read media header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (!read_device(sph, block_size, &offset)) {
Packit Service 501009
			error(INFO, "sadump: cannot read partition header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (sph->signature1 != SADUMP_SIGNATURE1 ||
Packit Service 501009
		    sph->signature2 != SADUMP_SIGNATURE2) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "sadump: does not have partition "
Packit Service 501009
				      "header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!verify_magic_number(sph->magicnum)) {
Packit Service 501009
		error(INFO, "sadump: invalid magic number\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!(flags & SADUMP_MEDIA) && sph->set_disk_set) {
Packit Service 501009
		uint32_t header_blocks;
Packit Service 501009
		size_t header_size;
Packit Service 501009
Packit Service 501009
		flags |= SADUMP_DISKSET;
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: read dump device as diskset\n");
Packit Service 501009
Packit Service 501009
		if (sph->set_disk_set != 1 ||
Packit Service 501009
		    sph->set_disk_set > SADUMP_MAX_DISK_SET_NUM) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "sadump: invalid disk set number: "
Packit Service 501009
				      "%d\n",
Packit Service 501009
				      sph->set_disk_set);
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (!read_device(&header_blocks, sizeof(uint32_t), &offset)) {
Packit Service 501009
			error(INFO, "sadump: cannot read disk set header "
Packit Service 501009
			      "size\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		offset -= sizeof(uint32_t);
Packit Service 501009
		header_size = header_blocks * block_size;
Packit Service 501009
Packit Service 501009
		if (header_size > block_size) {
Packit Service 501009
			new = realloc(sdh, header_size);
Packit Service 501009
			if (!new) {
Packit Service 501009
				error(INFO, "sadump: cannot re-allocate disk "
Packit Service 501009
				      "set buffer\n");
Packit Service 501009
				goto err;
Packit Service 501009
			}
Packit Service 501009
			sdh = new;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (!read_device(sdh, header_size, &offset)) {
Packit Service 501009
			error(INFO, "sadump: cannot read disk set header\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!read_device(sh, block_size, &offset)) {
Packit Service 501009
		error(INFO, "sadump: cannot read dump header\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sub_hdr_offset = offset;
Packit Service 501009
Packit Service 501009
	if (strncmp(sh->signature, SADUMP_SIGNATURE, 8) != 0) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: does not have dump header\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (flags & SADUMP_MEDIA) {
Packit Service 501009
Packit Service 501009
		if (memcmp(&sph->sadump_id, &smh->sadump_id,
Packit Service 501009
			   sizeof(efi_guid_t)) != 0) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "sadump: system ID mismatch\n"
Packit Service 501009
				      "  partition header: %s\n"
Packit Service 501009
				      "  media header: %s\n",
Packit Service 501009
				      guid_to_str(&sph->sadump_id, guid1, sizeof(guid1)),
Packit Service 501009
				      guid_to_str(&smh->sadump_id, guid2, sizeof(guid2)));
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (memcmp(&sph->disk_set_id, &smh->disk_set_id,
Packit Service 501009
			   sizeof(efi_guid_t)) != 0) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "sadump: disk set ID mismatch\n"
Packit Service 501009
				      "  partition header: %s\n"
Packit Service 501009
				      "  media header: %s\n",
Packit Service 501009
				      guid_to_str(&sph->disk_set_id, guid1, sizeof(guid1)),
Packit Service 501009
				      guid_to_str(&smh->disk_set_id, guid2, sizeof(guid2)));
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (memcmp(&sph->time_stamp, &smh->time_stamp,
Packit Service 501009
			   sizeof(efi_time_t)) != 0) {
Packit Service 501009
			if (CRASHDEBUG(1)) {
Packit Service 501009
				error(INFO, "sadump: time stamp mismatch\n");
Packit Service 501009
				error(INFO, "sadump:   partition header: %s\n",
Packit Service 501009
				      strip_linefeeds(asctime
Packit Service 501009
						      (efi_time_t_to_tm
Packit Service 501009
						       (&sph->time_stamp))));
Packit Service 501009
				error(INFO, "sadump:   media header: %s\n",
Packit Service 501009
				      strip_linefeeds(asctime
Packit Service 501009
						      (efi_time_t_to_tm
Packit Service 501009
						       (&smh->time_stamp))));
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (smh->sequential_num != 1) {
Packit Service 501009
			error(INFO, "sadump: first media file has sequential "
Packit Service 501009
			      "number %d\n", smh->sequential_num);
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (sh->block_size != block_size) {
Packit Service 501009
		block_size = sh->block_size;
Packit Service 501009
		offset = 0;
Packit Service 501009
		goto restart;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1)) {
Packit Service 501009
		if (flags & SADUMP_MEDIA)
Packit Service 501009
			error(INFO, "sadump: media backup file\n");
Packit Service 501009
Packit Service 501009
		else if (flags & SADUMP_DISKSET)
Packit Service 501009
			error(INFO, "sadump: diskset configuration with %d "
Packit Service 501009
			      "disks\n", sdh->disk_num);
Packit Service 501009
Packit Service 501009
		else
Packit Service 501009
			error(INFO, "sadump: single partition "
Packit Service 501009
			      "configuration\n");
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	flags |= SADUMP_LOCAL;
Packit Service 501009
Packit Service 501009
	switch (sh->header_version) {
Packit Service 501009
	case 0:
Packit Service 501009
		sd->max_mapnr = (uint64_t)sh->max_mapnr;
Packit Service 501009
		break;
Packit Service 501009
	default:
Packit Service 501009
		error(WARNING,
Packit Service 501009
		      "sadump: unsupported header version: %u\n"
Packit Service 501009
		      "sadump: assuming header version: 1\n",
Packit Service 501009
		      sh->header_version);
Packit Service 501009
	case 1:
Packit Service 501009
		sd->max_mapnr = sh->max_mapnr_64;
Packit Service 501009
		break;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (sh->sub_hdr_size > 0) {
Packit Service 501009
		if (!read_device(&smram_cpu_state_size, sizeof(uint32_t),
Packit Service 501009
				 &offset)) {
Packit Service 501009
			error(INFO,
Packit Service 501009
			      "sadump: cannot read SMRAM CPU STATE size\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
		smram_cpu_state_size /= sh->nr_cpus;
Packit Service 501009
Packit Service 501009
		offset -= sizeof(uint32_t);
Packit Service 501009
		offset += sh->sub_hdr_size * block_size;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!sh->bitmap_blocks) {
Packit Service 501009
		error(INFO, "sadump: bitmap_blocks is zero\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
	bitmap_len = block_size * sh->bitmap_blocks;
Packit Service 501009
	bitmap = calloc(bitmap_len, 1);
Packit Service 501009
	if (!bitmap) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate memory for bitmap "
Packit Service 501009
		      "buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
	if (!read_device(bitmap, bitmap_len, &offset)) {
Packit Service 501009
		error(INFO, "sadump: cannot read bitmap\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!sh->dumpable_bitmap_blocks) {
Packit Service 501009
		error(INFO, "sadump: dumpable_bitmap_blocks is zero\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
	dumpable_bitmap_len = block_size * sh->dumpable_bitmap_blocks;
Packit Service 501009
	dumpable_bitmap = calloc(dumpable_bitmap_len, 1);
Packit Service 501009
	if (!dumpable_bitmap) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate memory for "
Packit Service 501009
		      "dumpable_bitmap buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
	if (!read_device(dumpable_bitmap, dumpable_bitmap_len, &offset)) {
Packit Service 501009
		error(INFO, "sadump: cannot read dumpable bitmap\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	data_offset = offset;
Packit Service 501009
Packit Service 501009
	page_buf = malloc(block_size);
Packit Service 501009
	if (!page_buf) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate page buffer\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sd->filename = file;
Packit Service 501009
Packit Service 501009
	/*
Packit Service 501009
	 * Switch to zero excluded mode by default on sadump-related
Packit Service 501009
	 * formats because some Fujitsu troubleshooting software
Packit Service 501009
	 * assumes the behavior.
Packit Service 501009
	 */
Packit Service 501009
	sd->flags = flags | SADUMP_ZERO_EXCLUDED;
Packit Service 501009
Packit Service 501009
	if (machine_type("X86"))
Packit Service 501009
		sd->machine_type = EM_386;
Packit Service 501009
	else if (machine_type("X86_64"))
Packit Service 501009
		sd->machine_type = EM_X86_64;
Packit Service 501009
	else {
Packit Service 501009
		error(INFO, "sadump: unsupported machine type: %s\n",
Packit Service 501009
		      MACHINE_TYPE);
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sd->data_offset = data_offset;
Packit Service 501009
	sd->block_size = block_size;
Packit Service 501009
	sd->block_shift = ffs(sd->block_size) - 1;
Packit Service 501009
Packit Service 501009
	sd->bitmap = bitmap;
Packit Service 501009
	sd->dumpable_bitmap = dumpable_bitmap;
Packit Service 501009
Packit Service 501009
	sd->sub_hdr_offset = sub_hdr_offset;
Packit Service 501009
	sd->smram_cpu_state_size = smram_cpu_state_size;
Packit Service 501009
Packit Service 501009
	sd->header = sph;
Packit Service 501009
	sd->dump_header = sh;
Packit Service 501009
	if (flags & SADUMP_DISKSET)
Packit Service 501009
		sd->diskset_header = sdh;
Packit Service 501009
	if (flags & SADUMP_MEDIA)
Packit Service 501009
		sd->media_header = smh;
Packit Service 501009
Packit Service 501009
	sd->page_buf = page_buf;
Packit Service 501009
Packit Service 501009
	if (flags & SADUMP_DISKSET) {
Packit Service 501009
Packit Service 501009
		sd_list_len_0 = malloc(sizeof(struct sadump_diskset_data));
Packit Service 501009
		if (!sd_list_len_0) {
Packit Service 501009
			error(INFO,
Packit Service 501009
			      "sadump: cannot allocate diskset data buffer\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		sd_list_len_0->filename = sd->filename;
Packit Service 501009
		sd_list_len_0->dfd = sd->dfd;
Packit Service 501009
		sd_list_len_0->header = sd->header;
Packit Service 501009
		sd_list_len_0->data_offset = sd->data_offset;
Packit Service 501009
Packit Service 501009
		sd->sd_list = malloc(sizeof(struct sadump_diskset_data *));
Packit Service 501009
		if (!sd->sd_list) {
Packit Service 501009
			error(INFO,
Packit Service 501009
			      "sadump: cannot allocate diskset list buffer\n");
Packit Service 501009
			goto err;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		sd->sd_list_len = 1;
Packit Service 501009
		sd->sd_list[0] = sd_list_len_0;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!block_table_init()) {
Packit Service 501009
		error(INFO, "sadump: cannot initialize block hash table\n");
Packit Service 501009
		goto err;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!(flags & SADUMP_DISKSET))
Packit Service 501009
		free(sdh);
Packit Service 501009
Packit Service 501009
	if (!(flags & SADUMP_MEDIA))
Packit Service 501009
		free(smh);
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
Packit Service 501009
err:
Packit Service 501009
	close(sd->dfd);
Packit Service 501009
Packit Service 501009
	free(sph);
Packit Service 501009
	free(sdh);
Packit Service 501009
	free(sh);
Packit Service 501009
	free(smh);
Packit Service 501009
	free(bitmap);
Packit Service 501009
	free(dumpable_bitmap);
Packit Service 501009
	free(page_buf);
Packit Service 501009
	free(sd_list_len_0);
Packit Service 501009
Packit Service 501009
	free(sd->sd_list);
Packit Service 501009
Packit Service 501009
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
add_disk(char *file)
Packit Service 501009
{
Packit Service 501009
	struct sadump_part_header *ph;
Packit Service 501009
	struct sadump_diskset_data *this_disk;
Packit Service 501009
	int diskid;
Packit Service 501009
	char guid1[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
Packit Service 501009
	char guid2[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
Packit Service 501009
Packit Service 501009
	diskid = sd->sd_list_len - 1;
Packit Service 501009
	this_disk = sd->sd_list[diskid];
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		error(INFO, "sadump: add disk #%d\n", diskid+1);
Packit Service 501009
Packit Service 501009
	ph = malloc(sd->block_size);
Packit Service 501009
	if (!ph) {
Packit Service 501009
		error(INFO, "sadump: cannot malloc block_size buffer\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (lseek(this_disk->dfd, 0, SEEK_SET) == failed) {
Packit Service 501009
		error(INFO, "sadump: cannot lseek dump partition header\n");
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
	if (read(this_disk->dfd, ph, sd->block_size) < sd->block_size) {
Packit Service 501009
		error(INFO, "sadump: cannot read dump partition header\n");
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (ph->signature1 != SADUMP_SIGNATURE1 ||
Packit Service 501009
	    ph->signature2 != SADUMP_SIGNATURE2) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: does not have partition header\n");
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (memcmp(&sd->header->sadump_id, &ph->sadump_id,
Packit Service 501009
		   sizeof(efi_guid_t)) != 0) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: system ID mismatch\n"
Packit Service 501009
			      "  partition header on disk #1: %s\n"
Packit Service 501009
			      "  partition header on disk #%d: %s\n",
Packit Service 501009
			      guid_to_str(&sd->header->sadump_id, guid1,
Packit Service 501009
					  sizeof(guid1)),
Packit Service 501009
			      diskid+1,
Packit Service 501009
			      guid_to_str(&ph->sadump_id, guid2,
Packit Service 501009
					  sizeof(guid2)));
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (memcmp(&sd->header->disk_set_id, &ph->disk_set_id, sizeof(efi_guid_t)) != 0) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: disk set ID mismatch\n"
Packit Service 501009
			      "  partition header on disk #1: %s\n"
Packit Service 501009
			      "  partition header on disk #%d: %s\n",
Packit Service 501009
			      guid_to_str(&sd->header->disk_set_id, guid1,
Packit Service 501009
					  sizeof(guid1)),
Packit Service 501009
			      diskid+1,
Packit Service 501009
			      guid_to_str(&ph->disk_set_id, guid2,
Packit Service 501009
					  sizeof(guid2)));
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (memcmp(&sd->diskset_header->vol_info[diskid - 1].id, &ph->vol_id,
Packit Service 501009
		   sizeof(efi_guid_t)) != 0) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: volume ID mismatch\n"
Packit Service 501009
			      "  disk set header on disk #1: %s\n"
Packit Service 501009
			      "  partition header on disk #%d: %s\n",
Packit Service 501009
			      guid_to_str(&sd->diskset_header->vol_info[diskid-1].id,
Packit Service 501009
					  guid1, sizeof(guid1)),
Packit Service 501009
			      diskid+1,
Packit Service 501009
			      guid_to_str(&ph->vol_id, guid2, sizeof(guid2)));
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (memcmp(&sd->header->time_stamp, &ph->time_stamp,
Packit Service 501009
		   sizeof(efi_time_t)) != 0) {
Packit Service 501009
		if (CRASHDEBUG(1)) {
Packit Service 501009
			error(INFO, "sadump: time stamp mismatch\n");
Packit Service 501009
			error(INFO,
Packit Service 501009
			      "sadump:   partition header on disk #1: %s\n",
Packit Service 501009
			      strip_linefeeds(asctime
Packit Service 501009
					      (efi_time_t_to_tm
Packit Service 501009
					       (&sd->header->time_stamp))));
Packit Service 501009
			error(INFO,
Packit Service 501009
			      "sadump:   partition header on disk #%d: %s\n",
Packit Service 501009
			      diskid+1,
Packit Service 501009
			      strip_linefeeds(asctime
Packit Service 501009
					      (efi_time_t_to_tm
Packit Service 501009
					       (&ph->time_stamp))));
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (diskid != ph->set_disk_set - 1) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: wrong disk order; "
Packit Service 501009
			      "#%d expected but #%d given\n",
Packit Service 501009
			      diskid+1, ph->set_disk_set);
Packit Service 501009
		free(ph);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	this_disk->header = ph;
Packit Service 501009
	this_disk->data_offset = sd->block_size;
Packit Service 501009
	this_disk->filename = file;
Packit Service 501009
Packit Service 501009
	return TRUE;
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, "sadump: unable to open dump file %s", file);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sd->dfd = fd;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
open_disk(char *file)
Packit Service 501009
{
Packit Service 501009
	struct sadump_diskset_data *this_disk;
Packit Service 501009
Packit Service 501009
	sd->sd_list_len++;
Packit Service 501009
Packit Service 501009
	if (CRASHDEBUG(1))
Packit Service 501009
		error(INFO, "sadump: open disk #%d\n", sd->sd_list_len);
Packit Service 501009
Packit Service 501009
	if (sd->sd_list_len > sd->diskset_header->disk_num) {
Packit Service 501009
		error(INFO, "sadump: too many diskset arguments; "
Packit Service 501009
		      "this diskset consists of %d disks\n",
Packit Service 501009
		      sd->diskset_header->disk_num);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sd->sd_list = realloc(sd->sd_list,
Packit Service 501009
			      sd->sd_list_len *
Packit Service 501009
			      sizeof(struct sadump_diskset_data *));
Packit Service 501009
	if (!sd->sd_list) {
Packit Service 501009
		if (CRASHDEBUG(1)) {
Packit Service 501009
			error(INFO, "sadump: cannot malloc diskset list buffer\n");
Packit Service 501009
		}
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	this_disk = malloc(sizeof(struct sadump_diskset_data));
Packit Service 501009
	if (!this_disk) {
Packit Service 501009
		if (CRASHDEBUG(1)) {
Packit Service 501009
			error(INFO, "sadump: cannot malloc diskset data buffer\n");
Packit Service 501009
		}
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
	memset(this_disk, 0, sizeof(*this_disk));
Packit Service 501009
	sd->sd_list[sd->sd_list_len - 1] = this_disk;
Packit Service 501009
Packit Service 501009
	this_disk->dfd = open(file, O_RDONLY);
Packit Service 501009
	if (!this_disk->dfd) {
Packit Service 501009
		free(this_disk);
Packit Service 501009
		error(INFO, "sadump: unable to open dump file %s", file);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int is_sadump(char *file)
Packit Service 501009
{
Packit Service 501009
	if (SADUMP_VALID()) {
Packit Service 501009
Packit Service 501009
		if (!(sd->flags & SADUMP_DISKSET)) {
Packit Service 501009
			if (CRASHDEBUG(1))
Packit Service 501009
				error(INFO, "sadump: does not support multiple"
Packit Service 501009
				      " file formats\n");
Packit Service 501009
			(void) sadump_cleanup_sadump_data();
Packit Service 501009
			return FALSE;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		if (!open_disk(file) || !add_disk(file)) {
Packit Service 501009
			(void) sadump_cleanup_sadump_data();
Packit Service 501009
			return FALSE;
Packit Service 501009
		}
Packit Service 501009
Packit Service 501009
		return TRUE;
Packit Service 501009
	}
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
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int sadump_is_diskset(void)
Packit Service 501009
{
Packit Service 501009
	if (!SADUMP_VALID())
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	return !!(sd->flags & SADUMP_DISKSET);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
uint sadump_page_size(void)
Packit Service 501009
{
Packit Service 501009
	return sd->dump_header->block_size;
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.
Packit Service 501009
 */
Packit Service 501009
static uint64_t
Packit Service 501009
paddr_to_pfn(physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
	return paddr >> sd->block_shift;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int
Packit Service 501009
is_set_bit(char *bitmap, uint64_t pfn)
Packit Service 501009
{
Packit Service 501009
	ulong index, bit;
Packit Service 501009
Packit Service 501009
	index = pfn >> 3;
Packit Service 501009
	bit = 7 - (pfn & 7);
Packit Service 501009
Packit Service 501009
	return !!(bitmap[index] & (1UL << bit));
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int
Packit Service 501009
page_is_ram(uint64_t nr)
Packit Service 501009
{
Packit Service 501009
	return is_set_bit(sd->bitmap, nr);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static inline int
Packit Service 501009
page_is_dumpable(uint64_t nr)
Packit Service 501009
{
Packit Service 501009
	return is_set_bit(sd->dumpable_bitmap, nr);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
lookup_diskset(uint64_t whole_offset, int *diskid, uint64_t *disk_offset)
Packit Service 501009
{
Packit Service 501009
	uint64_t offset = whole_offset;
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	for (i = 0; i < sd->sd_list_len; ++i) {
Packit Service 501009
		uint64_t used_device_i, ram_size;
Packit Service 501009
		ulong data_offset_i;
Packit Service 501009
Packit Service 501009
		used_device_i = sd->sd_list[i]->header->used_device;
Packit Service 501009
		data_offset_i = sd->sd_list[i]->data_offset;
Packit Service 501009
Packit Service 501009
		ram_size = used_device_i - data_offset_i;
Packit Service 501009
Packit Service 501009
		if (offset < ram_size)
Packit Service 501009
			break;
Packit Service 501009
		offset -= ram_size;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (i == sd->sd_list_len)
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	*diskid = i;
Packit Service 501009
	*disk_offset = offset;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int read_sadump(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
Packit Service 501009
{
Packit Service 501009
	physaddr_t curpaddr ATTRIBUTE_UNUSED;
Packit Service 501009
	uint64_t pfn, whole_offset, perdisk_offset, block;
Packit Service 501009
	ulong page_offset;
Packit Service 501009
	int dfd;
Packit Service 501009
Packit Service 501009
	if (sd->flags & SADUMP_KDUMP_BACKUP &&
Packit Service 501009
	    paddr >= sd->backup_src_start &&
Packit Service 501009
	    paddr < sd->backup_src_start + sd->backup_src_size) {
Packit Service 501009
		ulong orig_paddr;
Packit Service 501009
Packit Service 501009
		orig_paddr = paddr;
Packit Service 501009
		paddr += sd->backup_offset - sd->backup_src_start;
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: kdump backup region: %#llx => %#llx\n",
Packit Service 501009
			      orig_paddr, paddr);
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	pfn = paddr_to_pfn(paddr);
Packit Service 501009
Packit Service 501009
	curpaddr = paddr & ~((physaddr_t)(sd->block_size-1));
Packit Service 501009
	page_offset = paddr & ((physaddr_t)(sd->block_size-1));
Packit Service 501009
Packit Service 501009
	if ((pfn >= sd->max_mapnr) || !page_is_ram(pfn))
Packit Service 501009
		return SEEK_ERROR;
Packit Service 501009
	if (!page_is_dumpable(pfn)) {
Packit Service 501009
		if (!(sd->flags & SADUMP_ZERO_EXCLUDED))
Packit Service 501009
			return PAGE_EXCLUDED;
Packit Service 501009
		memset(bufptr, 0, cnt);
Packit Service 501009
		return cnt;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	block = pfn_to_block(pfn);
Packit Service 501009
Packit Service 501009
	whole_offset = block * sd->block_size;
Packit Service 501009
Packit Service 501009
	if (sd->flags & SADUMP_DISKSET) {
Packit Service 501009
		int diskid;
Packit Service 501009
Packit Service 501009
		if (!lookup_diskset(whole_offset, &diskid, &perdisk_offset))
Packit Service 501009
			return SEEK_ERROR;
Packit Service 501009
Packit Service 501009
		dfd = sd->sd_list[diskid]->dfd;
Packit Service 501009
		perdisk_offset += sd->sd_list[diskid]->data_offset;
Packit Service 501009
Packit Service 501009
	} else {
Packit Service 501009
		dfd = sd->dfd;
Packit Service 501009
		perdisk_offset = whole_offset + sd->data_offset;
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (lseek(dfd, perdisk_offset, SEEK_SET) == failed)
Packit Service 501009
		return SEEK_ERROR;
Packit Service 501009
Packit Service 501009
	if (read(dfd, sd->page_buf, sd->block_size) != sd->block_size)
Packit Service 501009
		return READ_ERROR;
Packit Service 501009
Packit Service 501009
	memcpy(bufptr, sd->page_buf + page_offset, cnt);
Packit Service 501009
Packit Service 501009
	return cnt;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int write_sadump(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
int sadump_init(char *unused, FILE *fptr)
Packit Service 501009
{
Packit Service 501009
	if (!SADUMP_VALID())
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
ulong get_sadump_panic_task(void)
Packit Service 501009
{
Packit Service 501009
	return NO_TASK;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
ulong get_sadump_switch_stack(ulong task)
Packit Service 501009
{
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static struct tm *
Packit Service 501009
efi_time_t_to_tm(const efi_time_t *e)
Packit Service 501009
{
Packit Service 501009
	static struct tm t;
Packit Service 501009
	time_t ti;
Packit Service 501009
Packit Service 501009
	memset(&t, 0, sizeof(t));
Packit Service 501009
Packit Service 501009
	t.tm_sec  = e->second;
Packit Service 501009
	t.tm_min  = e->minute;
Packit Service 501009
	t.tm_hour = e->hour;
Packit Service 501009
	t.tm_mday = e->day;
Packit Service 501009
	t.tm_mon  = e->month - 1;
Packit Service 501009
	t.tm_year = e->year - 1900;
Packit Service 501009
Packit Service 501009
	if (e->timezone != EFI_UNSPECIFIED_TIMEZONE)
Packit Service 501009
		t.tm_hour += e->timezone;
Packit Service 501009
Packit Service 501009
	else if (CRASHDEBUG(1))
Packit Service 501009
		error(INFO, "sadump: timezone information is missing\n");
Packit Service 501009
Packit Service 501009
	ti = mktime(&t);
Packit Service 501009
	if (ti == (time_t)-1)
Packit Service 501009
		return &t;
Packit Service 501009
Packit Service 501009
	return localtime_r(&ti, &t);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static char *
Packit Service 501009
guid_to_str(efi_guid_t *guid, char *buf, size_t buflen)
Packit Service 501009
{
Packit Service 501009
	snprintf(buf, buflen,
Packit Service 501009
		 "%08x-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x",
Packit Service 501009
		 htonl(guid->data1), htons(guid->data2), htons(guid->data3),
Packit Service 501009
		 guid->data4[0], guid->data4[1], guid->data4[2],
Packit Service 501009
		 guid->data4[3], guid->data4[4], guid->data4[5],
Packit Service 501009
		 guid->data4[6], guid->data4[7]);
Packit Service 501009
Packit Service 501009
	return buf;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
verify_magic_number(uint32_t magicnum[DUMP_PART_HEADER_MAGICNUM_SIZE])
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	for (i = 1; i < DUMP_PART_HEADER_MAGICNUM_SIZE; ++i)
Packit Service 501009
		if (magicnum[i] != (magicnum[i - 1] + 7) * 11)
Packit Service 501009
			return FALSE;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int sadump_memory_used(void)
Packit Service 501009
{
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int sadump_free_memory(void)
Packit Service 501009
{
Packit Service 501009
	return 0;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  This function is dump-type independent, and could be used to dump
Packit Service 501009
 *  the diskdump_data structure contents and perhaps the sadump header
Packit Service 501009
 *  data.
Packit Service 501009
 */
Packit Service 501009
int sadump_memory_dump(FILE *fp)
Packit Service 501009
{
Packit Service 501009
	struct sadump_part_header *sph;
Packit Service 501009
	struct sadump_disk_set_header *sdh;
Packit Service 501009
	struct sadump_header *sh;
Packit Service 501009
	struct sadump_media_header *smh;
Packit Service 501009
	int i, others;
Packit Service 501009
	char guid[SADUMP_EFI_GUID_TEXT_REPR_LEN+1];
Packit Service 501009
Packit Service 501009
	fprintf(fp, "sadump_data: \n");
Packit Service 501009
	fprintf(fp, "          filename: %s\n", sd->filename);
Packit Service 501009
	fprintf(fp, "             flags: %lx (", sd->flags);
Packit Service 501009
	others = 0;
Packit Service 501009
	if (sd->flags & SADUMP_LOCAL)
Packit Service 501009
		fprintf(fp, "%sSADUMP_LOCAL", others++ ? "|" : "");
Packit Service 501009
	if (sd->flags & SADUMP_DISKSET)
Packit Service 501009
		fprintf(fp, "%sSADUMP_DISKSET", others++ ? "|" : "");
Packit Service 501009
	if (sd->flags & SADUMP_MEDIA)
Packit Service 501009
		fprintf(fp, "%sSADUMP_MEDIA", others++ ? "|" : "");
Packit Service 501009
	if (sd->flags & SADUMP_ZERO_EXCLUDED)
Packit Service 501009
		fprintf(fp, "%sSADUMP_ZERO_EXCLUDED", others++ ? "|" : "");
Packit Service 501009
	if (sd->flags & SADUMP_KDUMP_BACKUP)
Packit Service 501009
		fprintf(fp, "%sSADUMP_KDUMP_BACKUP", others++ ? "|" : "");
Packit Service 501009
	fprintf(fp, ") \n");
Packit Service 501009
        fprintf(fp, "               dfd: %d\n", sd->dfd);
Packit Service 501009
        fprintf(fp, "      machine_type: %d ", sd->machine_type);
Packit Service 501009
	switch (sd->machine_type)
Packit Service 501009
	{
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
	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)sd->header);
Packit Service 501009
	sph = sd->header;
Packit Service 501009
	fprintf(fp, "          signature1: %x\n", sph->signature1);
Packit Service 501009
	fprintf(fp, "          signature2: %x\n", sph->signature2);
Packit Service 501009
	fprintf(fp, "              enable: %u\n", sph->enable);
Packit Service 501009
	fprintf(fp, "              reboot: %u\n", sph->reboot);
Packit Service 501009
	fprintf(fp, "            compress: %u\n", sph->compress);
Packit Service 501009
	fprintf(fp, "             recycle: %u\n", sph->recycle);
Packit Service 501009
	fprintf(fp, "               label: (unused)\n");
Packit Service 501009
	fprintf(fp, "           sadump_id: %s\n", guid_to_str(&sph->sadump_id, guid, sizeof(guid)));
Packit Service 501009
	fprintf(fp, "         disk_set_id: %s\n", guid_to_str(&sph->disk_set_id, guid, sizeof(guid)));
Packit Service 501009
	fprintf(fp, "              vol_id: %s\n", guid_to_str(&sph->vol_id, guid, sizeof(guid)));
Packit Service 501009
	fprintf(fp, "          time_stamp: %s\n",
Packit Service 501009
		strip_linefeeds(asctime(efi_time_t_to_tm(&sph->time_stamp))));
Packit Service 501009
	fprintf(fp, "        set_disk_set: %u\n", sph->set_disk_set);
Packit Service 501009
	fprintf(fp, "             reserve: %u\n", sph->reserve);
Packit Service 501009
	fprintf(fp, "         used_device: %llu\n", (ulonglong)sph->used_device);
Packit Service 501009
	fprintf(fp, "            magicnum: %s\n",
Packit Service 501009
		verify_magic_number(sph->magicnum)
Packit Service 501009
		? "(valid)" : "(invalid)");
Packit Service 501009
Packit Service 501009
        fprintf(fp, "\n       dump header: %lx\n", (ulong)sd->dump_header);
Packit Service 501009
	sh = sd->dump_header;
Packit Service 501009
	fprintf(fp, "           signature: %s\n", sh->signature);
Packit Service 501009
	fprintf(fp, "      header_version: %u\n", sh->header_version);
Packit Service 501009
	fprintf(fp, "             reserve: %u\n", sh->reserve);
Packit Service 501009
	fprintf(fp, "           timestamp: %s\n",
Packit Service 501009
		strip_linefeeds(asctime(efi_time_t_to_tm(&sh->timestamp))));
Packit Service 501009
	fprintf(fp, "              status: %u\n", sh->status);
Packit Service 501009
	fprintf(fp, "            compress: %u\n", sh->compress);
Packit Service 501009
	fprintf(fp, "          block_size: %u\n", sh->block_size);
Packit Service 501009
	fprintf(fp, "      extra_hdr_size: %u\n", sh->extra_hdr_size);
Packit Service 501009
	fprintf(fp, "        sub_hdr_size: %u\n", sh->sub_hdr_size);
Packit Service 501009
	fprintf(fp, "       bitmap_blocks: %u\n", sh->bitmap_blocks);
Packit Service 501009
	fprintf(fp, "dumpable_bitmap_blocks: %u\n", sh->dumpable_bitmap_blocks);
Packit Service 501009
	fprintf(fp, "           max_mapnr: %u\n", sh->max_mapnr);
Packit Service 501009
	fprintf(fp, "    total_ram_blocks: %u\n", sh->total_ram_blocks);
Packit Service 501009
	fprintf(fp, "       device_blocks: %u\n", sh->device_blocks);
Packit Service 501009
	fprintf(fp, "      written_blocks: %u\n", sh->written_blocks);
Packit Service 501009
	fprintf(fp, "         current_cpu: %u\n", sh->current_cpu);
Packit Service 501009
	fprintf(fp, "             nr_cpus: %u\n", sh->nr_cpus);
Packit Service 501009
	if (sh->header_version >= 1) {
Packit Service 501009
		fprintf(fp,
Packit Service 501009
			"        max_mapnr_64: %" PRIu64 "\n"
Packit Service 501009
			" total_ram_blocks_64: %" PRIu64 "\n"
Packit Service 501009
			"    device_blocks_64: %" PRIu64 "\n"
Packit Service 501009
			"   written_blocks_64: %" PRIu64 "\n",
Packit Service 501009
			sh->max_mapnr_64,
Packit Service 501009
			sh->total_ram_blocks_64,
Packit Service 501009
			sh->device_blocks_64,
Packit Service 501009
			sh->written_blocks_64);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	fprintf(fp, "\n    dump sub heaer: ");
Packit Service 501009
	if (sh->sub_hdr_size > 0) {
Packit Service 501009
		ulong offset = sd->sub_hdr_offset;
Packit Service 501009
		struct sadump_apic_state as;
Packit Service 501009
		struct sadump_smram_cpu_state scs, zero;
Packit Service 501009
		uint32_t size;
Packit Service 501009
		uint aid;
Packit Service 501009
Packit Service 501009
		memset(&zero, 0, sizeof(zero));
Packit Service 501009
Packit Service 501009
		if (!read_device(&size, sizeof(uint32_t), &offset)) {
Packit Service 501009
			error(INFO, "sadump: cannot read sub header size\n");
Packit Service 501009
			return FALSE;
Packit Service 501009
		}
Packit Service 501009
		fprintf(fp, "\n                size: %u\n", size);
Packit Service 501009
		for (aid = 0; aid < sh->nr_cpus; ++aid) {
Packit Service 501009
			if (!read_device(&as, sizeof(as), &offset)) {
Packit Service 501009
				error(INFO, "sadump: cannot read sub header "
Packit Service 501009
				      "apic_id\n");
Packit Service 501009
				return FALSE;
Packit Service 501009
			}
Packit Service 501009
			fprintf(fp, "          "
Packit Service 501009
				"apic_id[%u]: ApicId %llu: Ldr: %llu\n",
Packit Service 501009
				aid, (ulonglong)as.ApicId, (ulonglong)as.Ldr);
Packit Service 501009
		}
Packit Service 501009
		for (aid = 0; aid < sh->nr_cpus; ++aid) {
Packit Service 501009
			if (!read_device(&scs, sizeof(scs), &offset)) {
Packit Service 501009
				error(INFO, "sadump: cannot read sub header "
Packit Service 501009
				      "cpu_state\n");
Packit Service 501009
				return FALSE;
Packit Service 501009
			}
Packit Service 501009
			if (memcmp(&scs, &zero, sizeof(scs)) != 0) {
Packit Service 501009
				fprintf(fp, "\n");
Packit Service 501009
				display_smram_cpu_state(aid, &scs);
Packit Service 501009
			}
Packit Service 501009
		}
Packit Service 501009
	} else
Packit Service 501009
		fprintf(fp, "(n/a)\n");
Packit Service 501009
Packit Service 501009
        fprintf(fp, "\n   disk set header: %lx ", (ulong)sd->diskset_header);
Packit Service 501009
	if ((sdh = sd->diskset_header)) {
Packit Service 501009
		fprintf(fp, "\ndisk_set_header_size: %u\n", sdh->disk_set_header_size);
Packit Service 501009
		fprintf(fp, "            disk_num: %u\n", sdh->disk_num);
Packit Service 501009
		fprintf(fp, "       disk_set_size: %llu\n", (ulonglong)sdh->disk_set_size);
Packit Service 501009
		for (i = 0; i < sdh->disk_num - 1; ++i) {
Packit Service 501009
			struct sadump_volume_info *vol = &sdh->vol_info[i];
Packit Service 501009
Packit Service 501009
			fprintf(fp, "         vol_info[%d]: \n", i);
Packit Service 501009
			fprintf(fp, "                     id: %s\n", guid_to_str(&vol->id, guid, sizeof(guid)));
Packit Service 501009
			fprintf(fp, "               vol_size: %llu\n", (ulonglong)vol->vol_size);
Packit Service 501009
			fprintf(fp, "                 status: %u\n", vol->status);
Packit Service 501009
			fprintf(fp, "             cache_size: %u\n", vol->cache_size);
Packit Service 501009
		}
Packit Service 501009
	} else
Packit Service 501009
		fprintf(fp, "(n/a)\n");
Packit Service 501009
Packit Service 501009
        fprintf(fp, "\n      media header: %lx ", (ulong)sd->media_header);
Packit Service 501009
	if ((smh = sd->media_header)) {
Packit Service 501009
		fprintf(fp, "\n           sadump_id: %s\n", guid_to_str(&smh->sadump_id, guid, sizeof(guid)));
Packit Service 501009
		fprintf(fp, "         disk_set_id: %s\n", guid_to_str(&smh->disk_set_id, guid, sizeof(guid)));
Packit Service 501009
		fprintf(fp, "          time_stamp: %s\n",
Packit Service 501009
			strip_linefeeds(asctime(efi_time_t_to_tm(&smh->time_stamp))));
Packit Service 501009
		fprintf(fp, "      sequential_num: %d\n", smh->sequential_num);
Packit Service 501009
		fprintf(fp, "           term_cord: %d\n", smh->term_cord);
Packit Service 501009
		fprintf(fp, "disk_set_header_size: %d\n", smh->disk_set_header_size);
Packit Service 501009
		fprintf(fp, "        disks_in_use: %d\n", smh->disks_in_use);
Packit Service 501009
		fprintf(fp, "             reserve: (not displayed) \n");
Packit Service 501009
	} else
Packit Service 501009
		fprintf(fp, "(n/a)\n");
Packit Service 501009
Packit Service 501009
        fprintf(fp, "\n            bitmap: %lx\n", (ulong)sd->bitmap);
Packit Service 501009
        fprintf(fp, "   dumpable_bitmap: %lx\n", (ulong)sd->dumpable_bitmap);
Packit Service 501009
        fprintf(fp, "    sub_hdr_offset: %lx\n", (ulong)sd->sub_hdr_offset);
Packit Service 501009
        fprintf(fp, "smram_cpu_state_size: %lx\n", (ulong)sd->smram_cpu_state_size);
Packit Service 501009
        fprintf(fp, "       data_offset: %lx\n", sd->data_offset);
Packit Service 501009
        fprintf(fp, "        block_size: %d\n", sd->block_size);
Packit Service 501009
        fprintf(fp, "       block_shift: %d\n", sd->block_shift);
Packit Service 501009
	fprintf(fp, "          page_buf: %lx\n", (ulong)sd->page_buf);
Packit Service 501009
	fprintf(fp, "       block_table: %lx\n", (ulong)sd->block_table);
Packit Service 501009
	fprintf(fp, "       sd_list_len: %d\n", sd->sd_list_len);
Packit Service 501009
	fprintf(fp, "           sd_list: %lx\n", (ulong)sd->sd_list);
Packit Service 501009
	fprintf(fp, "  backup_src_start: %llx\n", sd->backup_src_start);
Packit Service 501009
	fprintf(fp, "   backup_src_size: %lx\n", sd->backup_src_size);
Packit Service 501009
	fprintf(fp, "     backup_offset: %llx\n", (ulonglong)sd->backup_src_size);
Packit Service 501009
Packit Service 501009
	for (i = 0; i < sd->sd_list_len; ++i) {
Packit Service 501009
		struct sadump_diskset_data *sdd = sd->sd_list[i];
Packit Service 501009
Packit Service 501009
		fprintf(fp, "\n        sd_list[%d]: \n", i);
Packit Service 501009
		fprintf(fp, "            filename: %s\n", sdd->filename);
Packit Service 501009
		fprintf(fp, "                 dfd: %d\n", sdd->dfd);
Packit Service 501009
Packit Service 501009
		fprintf(fp, "              header: %lx\n", (ulong)sdd->header);
Packit Service 501009
		sph = sdd->header;
Packit Service 501009
		fprintf(fp, "            signature1: %x\n", sph->signature1);
Packit Service 501009
		fprintf(fp, "            signature2: %x\n", sph->signature2);
Packit Service 501009
		fprintf(fp, "                enable: %u\n", sph->enable);
Packit Service 501009
		fprintf(fp, "                reboot: %u\n", sph->reboot);
Packit Service 501009
		fprintf(fp, "              compress: %u\n", sph->compress);
Packit Service 501009
		fprintf(fp, "               recycle: %u\n", sph->recycle);
Packit Service 501009
		fprintf(fp, "                 label: (unused)\n");
Packit Service 501009
		fprintf(fp, "             sadump_id: %s\n", guid_to_str(&sph->sadump_id, guid, sizeof(guid)));
Packit Service 501009
		fprintf(fp, "           disk_set_id: %s\n", guid_to_str(&sph->disk_set_id, guid, sizeof(guid)));
Packit Service 501009
		fprintf(fp, "                vol_id: %s\n", guid_to_str(&sph->vol_id, guid, sizeof(guid)));
Packit Service 501009
		fprintf(fp, "            time_stamp: %s\n",
Packit Service 501009
			strip_linefeeds(asctime(efi_time_t_to_tm(&sph->time_stamp))));
Packit Service 501009
		fprintf(fp, "          set_disk_set: %u\n", sph->set_disk_set);
Packit Service 501009
		fprintf(fp, "               reserve: %u\n", sph->reserve);
Packit Service 501009
		fprintf(fp, "           used_device: %llu\n", (ulonglong)sph->used_device);
Packit Service 501009
		fprintf(fp, "              magicnum: %s\n",
Packit Service 501009
			verify_magic_number(sph->magicnum)
Packit Service 501009
			? "(valid)" : "(invalid)");
Packit Service 501009
Packit Service 501009
		fprintf(fp, "         data_offset: %lx\n", sdd->data_offset);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
per_cpu_ptr(ulong ptr, int cpu)
Packit Service 501009
{
Packit Service 501009
	if (cpu < 0 || cpu >= kt->cpus)
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	if (kt->cpus == 1)
Packit Service 501009
		return ptr;
Packit Service 501009
Packit Service 501009
	if (!(kt->flags & PER_CPU_OFF))
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	if (machine_type("X86_64")) {
Packit Service 501009
		ulong __per_cpu_load;
Packit Service 501009
Packit Service 501009
		readmem(symbol_value("__per_cpu_load"), KVADDR,
Packit Service 501009
			&__per_cpu_load, sizeof(__per_cpu_load),
Packit Service 501009
			"__per_cpu_load", FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
		if (kt->__per_cpu_offset[cpu] == __per_cpu_load)
Packit Service 501009
			return 0UL;
Packit Service 501009
Packit Service 501009
	} else if (machine_type("X86")) {
Packit Service 501009
		if (kt->__per_cpu_offset[cpu] == 0)
Packit Service 501009
			return 0UL;
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return ptr + kt->__per_cpu_offset[cpu];
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
early_per_cpu_ptr(char *symbol, struct syment *sym, int cpu)
Packit Service 501009
{
Packit Service 501009
	char sym_early_ptr[BUFSIZE], sym_early_map[BUFSIZE];
Packit Service 501009
	ulong early_ptr;
Packit Service 501009
Packit Service 501009
	if (cpu < 0 || cpu >= kt->cpus)
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	if (!sym && !(sym = per_cpu_symbol_search(symbol)))
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	if (!(kt->flags & SMP))
Packit Service 501009
		return per_cpu_ptr(sym->value, cpu);
Packit Service 501009
Packit Service 501009
	snprintf(sym_early_ptr, BUFSIZE, "%s_early_ptr", symbol);
Packit Service 501009
	snprintf(sym_early_map, BUFSIZE, "%s_early_map", symbol);
Packit Service 501009
Packit Service 501009
	if (!symbol_exists(sym_early_ptr) || !symbol_exists(sym_early_map))
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	readmem(symbol_value(sym_early_ptr), KVADDR, &early_ptr,
Packit Service 501009
		sizeof(early_ptr), sym_early_ptr, FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
	return early_ptr
Packit Service 501009
		? symbol_value(sym_early_map)+cpu*sizeof(uint16_t)
Packit Service 501009
		: per_cpu_ptr(sym->value, cpu);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static ulong
Packit Service 501009
legacy_per_cpu_ptr(ulong ptr, int cpu)
Packit Service 501009
{
Packit Service 501009
	ulong addr;
Packit Service 501009
Packit Service 501009
	if (!(kt->flags & SMP))
Packit Service 501009
		return ptr;
Packit Service 501009
Packit Service 501009
	if (cpu < 0 || cpu >= kt->cpus)
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	if (!readmem(~ptr + cpu * sizeof(ulong), KVADDR, &addr, sizeof(ulong),
Packit Service 501009
		     "search percpu_data", FAULT_ON_ERROR))
Packit Service 501009
		return 0UL;
Packit Service 501009
Packit Service 501009
	return addr;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/**
Packit Service 501009
 * Retrieve eip and esp register values from crash_notes saved by
Packit Service 501009
 * kdump at crash. If register values has not been saved yet, set 0 to
Packit Service 501009
 * eip and esp instead.
Packit Service 501009
 */
Packit Service 501009
static int
Packit Service 501009
get_prstatus_from_crash_notes(int cpu, char *prstatus)
Packit Service 501009
{
Packit Service 501009
	ulong crash_notes, crash_notes_ptr, percpu_addr;
Packit Service 501009
	char *prstatus_ptr, *note_buf, *zero_buf, *name;
Packit Service 501009
	uint32_t *buf;
Packit Service 501009
Packit Service 501009
	if (cpu < 0 || kt->cpus <= cpu) {
Packit Service 501009
		error(INFO, "sadump: given cpu is invalid: %d\n", cpu);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!symbol_exists("crash_notes")) {
Packit Service 501009
		error(INFO, "sadump: symbol crash_notes doesn't exist\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	crash_notes = symbol_value("crash_notes");
Packit Service 501009
Packit Service 501009
	readmem(crash_notes, KVADDR, &crash_notes_ptr, sizeof(ulong),
Packit Service 501009
		"dereference crash_notes", FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
	if (!crash_notes_ptr) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO,
Packit Service 501009
			      "sadump: buffer for crash_notes is NULL\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	percpu_addr = VALID_STRUCT(percpu_data)
Packit Service 501009
		? legacy_per_cpu_ptr(crash_notes_ptr, cpu)
Packit Service 501009
		: per_cpu_ptr(crash_notes_ptr, cpu);
Packit Service 501009
Packit Service 501009
	zero_buf = GETBUF(SIZE(note_buf));
Packit Service 501009
	BZERO(zero_buf, SIZE(note_buf));
Packit Service 501009
Packit Service 501009
	note_buf = GETBUF(SIZE(note_buf));
Packit Service 501009
Packit Service 501009
	readmem(percpu_addr, KVADDR, note_buf, SIZE(note_buf),
Packit Service 501009
		"read crash_notes", FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
	if (memcmp(note_buf, zero_buf, SIZE(note_buf)) == 0)
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	if (BITS64()) {
Packit Service 501009
		Elf64_Nhdr *note64;
Packit Service 501009
Packit Service 501009
		note64 = (Elf64_Nhdr *)note_buf;
Packit Service 501009
		buf = (uint32_t *)note_buf;
Packit Service 501009
		name = (char *)(note64 + 1);
Packit Service 501009
Packit Service 501009
		if (note64->n_type != NT_PRSTATUS ||
Packit Service 501009
		    note64->n_namesz != strlen("CORE") + 1 ||
Packit Service 501009
		    strncmp(name, "CORE", note64->n_namesz) ||
Packit Service 501009
		    note64->n_descsz != SIZE(elf_prstatus))
Packit Service 501009
			return FALSE;
Packit Service 501009
Packit Service 501009
		prstatus_ptr = (char *)(buf + (sizeof(*note64) + 3) / 4 +
Packit Service 501009
					(note64->n_namesz + 3) / 4);
Packit Service 501009
Packit Service 501009
	} else {
Packit Service 501009
		Elf32_Nhdr *note32;
Packit Service 501009
Packit Service 501009
		note32 = (Elf32_Nhdr *)note_buf;
Packit Service 501009
		buf = (uint32_t *)note_buf;
Packit Service 501009
		name = (char *)(note32 + 1);
Packit Service 501009
Packit Service 501009
		if ((note32->n_type != NT_PRSTATUS) &&
Packit Service 501009
		    (note32->n_namesz != strlen("CORE") + 1 ||
Packit Service 501009
		     strncmp(name, "CORE", note32->n_namesz) ||
Packit Service 501009
		     note32->n_descsz != SIZE(elf_prstatus)))
Packit Service 501009
			return FALSE;
Packit Service 501009
Packit Service 501009
		prstatus_ptr = (char *)(buf + (sizeof(*note32) + 3) / 4 +
Packit Service 501009
					(note32->n_namesz + 3) / 4);
Packit Service 501009
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	memcpy(prstatus, prstatus_ptr, SIZE(elf_prstatus));
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
sadump_get_smram_cpu_state(int apicid,
Packit Service 501009
			   struct sadump_smram_cpu_state *smram)
Packit Service 501009
{
Packit Service 501009
	ulong offset;
Packit Service 501009
Packit Service 501009
	if (!sd->sub_hdr_offset || !sd->smram_cpu_state_size ||
Packit Service 501009
	    apicid >= sd->dump_header->nr_cpus)
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	offset = sd->sub_hdr_offset + sizeof(uint32_t) +
Packit Service 501009
		sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state);
Packit Service 501009
Packit Service 501009
	if (lseek(sd->dfd, offset + apicid * sd->smram_cpu_state_size,
Packit Service 501009
		  SEEK_SET) == failed)
Packit Service 501009
		error(FATAL,
Packit Service 501009
		      "sadump: cannot lseek smram cpu state in dump sub header\n");
Packit Service 501009
Packit Service 501009
	if (read(sd->dfd, smram, sd->smram_cpu_state_size) != sd->smram_cpu_state_size)
Packit Service 501009
		error(FATAL, "sadump: cannot read smram cpu state in dump sub "
Packit Service 501009
		      "header\n");
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static void
Packit Service 501009
display_smram_cpu_state(int apicid, struct sadump_smram_cpu_state *s)
Packit Service 501009
{
Packit Service 501009
	fprintf(fp,
Packit Service 501009
		"APIC ID: %d\n"
Packit Service 501009
		"    RIP: %016llx RSP: %08x%08x RBP: %08x%08x\n"
Packit Service 501009
		"    RAX: %08x%08x RBX: %08x%08x RCX: %08x%08x\n"
Packit Service 501009
		"    RDX: %08x%08x RSI: %08x%08x RDI: %08x%08x\n"
Packit Service 501009
		"    R08: %08x%08x R09: %08x%08x R10: %08x%08x\n"
Packit Service 501009
		"    R11: %08x%08x R12: %08x%08x R13: %08x%08x\n"
Packit Service 501009
		"    R14: %08x%08x R15: %08x%08x\n"
Packit Service 501009
		"    SMM REV: %08x SMM BASE %08x\n"
Packit Service 501009
		"    CS : %08x DS: %08x SS: %08x ES: %08x FS: %08x\n"
Packit Service 501009
		"    GS : %08x\n"
Packit Service 501009
		"    CR0: %016llx CR3: %016llx CR4: %08x\n"
Packit Service 501009
		"    GDT: %08x%08x LDT: %08x%08x IDT: %08x%08x\n"
Packit Service 501009
		"    GDTlim: %08x LDTlim: %08x IDTlim: %08x\n"
Packit Service 501009
		"    LDTR: %08x TR: %08x RFLAGS: %016llx\n"
Packit Service 501009
		"    EPTP: %016llx EPTP_SETTING: %08x\n"
Packit Service 501009
		"    DR6: %016llx DR7: %016llx\n"
Packit Service 501009
		"    Ia32Efer: %016llx\n"
Packit Service 501009
		"    IoMemAddr: %08x%08x IoEip: %016llx\n"
Packit Service 501009
		"    IoMisc: %08x LdtInfo: %08x\n"
Packit Service 501009
		"    IoInstructionRestart: %04x AutoHaltRestart: %04x\n",
Packit Service 501009
		apicid,
Packit Service 501009
		(ulonglong)s->Rip, s->RspUpper, s->RspLower, s->RbpUpper, s->RbpLower,
Packit Service 501009
		s->RaxUpper, s->RaxLower, s->RbxUpper, s->RbxLower, s->RcxUpper, s->RcxLower,
Packit Service 501009
		s->RdxUpper, s->RdxLower, s->RsiUpper, s->RsiLower, s->RdiUpper, s->RdiLower,
Packit Service 501009
		s->R8Upper, s->R8Lower,	s->R9Upper, s->R9Lower,	s->R10Upper, s->R10Lower,
Packit Service 501009
		s->R11Upper, s->R11Lower, s->R12Upper, s->R12Lower, s->R13Upper, s->R13Lower,
Packit Service 501009
		s->R14Upper, s->R14Lower, s->R15Upper, s->R15Lower,
Packit Service 501009
		s->SmmRevisionId, s->Smbase,
Packit Service 501009
		s->Cs, s->Ds, s->Ss, s->Es, s->Fs, s->Gs,
Packit Service 501009
		(ulonglong)s->Cr0, (ulonglong)s->Cr3, s->Cr4,
Packit Service 501009
		s->GdtUpper, s->GdtLower, s->LdtUpper, s->LdtLower, s->IdtUpper, s->IdtLower,
Packit Service 501009
		s->GdtLimit, s->LdtLimit, s->IdtLimit,
Packit Service 501009
		s->Ldtr, s->Tr, (ulonglong)s->Rflags,
Packit Service 501009
		(ulonglong)s->Eptp, s->EptpSetting,
Packit Service 501009
		(ulonglong)s->Dr6, (ulonglong)s->Dr7,
Packit Service 501009
		(ulonglong)s->Ia32Efer,
Packit Service 501009
		s->IoMemAddrUpper, s->IoMemAddrLower, (ulonglong)s->IoEip,
Packit Service 501009
		s->IoMisc, s->LdtInfo,
Packit Service 501009
		s->IoInstructionRestart,
Packit Service 501009
		s->AutoHaltRestart);
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int cpu_to_apicid(int cpu, int *apicid)
Packit Service 501009
{
Packit Service 501009
	struct syment *sym;
Packit Service 501009
Packit Service 501009
	if (symbol_exists("bios_cpu_apicid")) {
Packit Service 501009
		uint8_t apicid_u8;
Packit Service 501009
Packit Service 501009
		readmem(symbol_value("bios_cpu_apicid") + cpu*sizeof(uint8_t),
Packit Service 501009
			KVADDR, &apicid_u8, sizeof(uint8_t), "bios_cpu_apicid",
Packit Service 501009
			FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
		*apicid = (int)apicid_u8;
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: apicid %u for cpu %d from "
Packit Service 501009
			      "bios_cpu_apicid\n", apicid_u8, cpu);
Packit Service 501009
Packit Service 501009
	} else if ((sym = per_cpu_symbol_search("x86_bios_cpu_apicid"))) {
Packit Service 501009
		uint16_t apicid_u16;
Packit Service 501009
Packit Service 501009
		readmem(early_per_cpu_ptr("x86_bios_cpu_apicid", sym, cpu),
Packit Service 501009
			KVADDR, &apicid_u16, sizeof(uint16_t),
Packit Service 501009
			"x86_bios_cpu_apicid", FAULT_ON_ERROR);
Packit Service 501009
Packit Service 501009
		*apicid = (int)apicid_u16;
Packit Service 501009
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: apicid %u for cpu %d from "
Packit Service 501009
			      "x86_bios_cpu_apicid\n", apicid_u16, cpu);
Packit Service 501009
Packit Service 501009
	} else {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(INFO, "sadump: no symbols for access to apicid\n");
Packit Service 501009
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int
Packit Service 501009
get_sadump_smram_cpu_state(int cpu, struct sadump_smram_cpu_state *smram)
Packit Service 501009
{
Packit Service 501009
	int apicid = 0;
Packit Service 501009
Packit Service 501009
	if (cpu < 0 || kt->cpus <= cpu) {
Packit Service 501009
		error(INFO, "sadump: given cpu is invalid: %d\n", cpu);
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!cpu_to_apicid(cpu, &apicid))
Packit Service 501009
		return FALSE;
Packit Service 501009
Packit Service 501009
	sadump_get_smram_cpu_state(apicid, smram);
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void get_sadump_regs(struct bt_info *bt, ulong *ipp, ulong *spp)
Packit Service 501009
{
Packit Service 501009
	ulong ip, sp;
Packit Service 501009
	struct sadump_smram_cpu_state smram;
Packit Service 501009
	char *prstatus;
Packit Service 501009
	int cpu = bt->tc->processor;
Packit Service 501009
Packit Service 501009
	if (!is_task_active(bt->task)) {
Packit Service 501009
		machdep->get_stack_frame(bt, ipp, spp);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	bt->flags |= BT_DUMPFILE_SEARCH;
Packit Service 501009
	if (machine_type("X86_64"))
Packit Service 501009
		machdep->get_stack_frame(bt, ipp, spp);
Packit Service 501009
	else if (machine_type("X86"))
Packit Service 501009
		get_netdump_regs_x86(bt, ipp, spp);
Packit Service 501009
	if (bt->flags & BT_DUMPFILE_SEARCH)
Packit Service 501009
		return;
Packit Service 501009
Packit Service 501009
	prstatus = GETBUF(SIZE(elf_prstatus));
Packit Service 501009
Packit Service 501009
	if (get_prstatus_from_crash_notes(cpu, prstatus)) {
Packit Service 501009
		ip = ULONG(prstatus +
Packit Service 501009
			   OFFSET(elf_prstatus_pr_reg) +
Packit Service 501009
			   (BITS64()
Packit Service 501009
			    ? OFFSET(user_regs_struct_rip)
Packit Service 501009
			    : OFFSET(user_regs_struct_eip)));
Packit Service 501009
		sp = ULONG(prstatus +
Packit Service 501009
			   OFFSET(elf_prstatus_pr_reg) +
Packit Service 501009
			   (BITS64()
Packit Service 501009
			    ? OFFSET(user_regs_struct_rsp)
Packit Service 501009
			    : OFFSET(user_regs_struct_eip)));
Packit Service 501009
		if (ip || sp) {
Packit Service 501009
			*ipp = ip;
Packit Service 501009
			*spp = sp;
Packit Service 501009
			return;
Packit Service 501009
		}
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	get_sadump_smram_cpu_state(cpu, &smram);
Packit Service 501009
	ip = smram.Rip;
Packit Service 501009
	sp = ((uint64_t)smram.RspUpper << 32) + smram.RspLower;
Packit Service 501009
Packit Service 501009
	if (is_kernel_text(ip) &&
Packit Service 501009
	    (((sp >= GET_STACKBASE(bt->task)) &&
Packit Service 501009
	      (sp < GET_STACKTOP(bt->task))) ||
Packit Service 501009
	     in_alternate_stack(bt->tc->processor, sp))) {
Packit Service 501009
		*ipp = ip;
Packit Service 501009
		*spp = sp;
Packit Service 501009
		bt->flags |= BT_KERNEL_SPACE;
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (!is_kernel_text(ip) &&
Packit Service 501009
	    in_user_stack(bt->tc->task, sp))
Packit Service 501009
		bt->flags |= BT_USER_SPACE;
Packit Service 501009
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void
Packit Service 501009
sadump_display_regs(int cpu, FILE *ofp)
Packit Service 501009
{
Packit Service 501009
	struct sadump_smram_cpu_state smram;
Packit Service 501009
Packit Service 501009
	if (cpu < 0 || cpu >= kt->cpus) {
Packit Service 501009
		error(INFO, "sadump: given cpu is invalid: %d\n", cpu);
Packit Service 501009
		return;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	get_sadump_smram_cpu_state(cpu, &smram);
Packit Service 501009
Packit Service 501009
	if (machine_type("X86_64")) {
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)(smram.Rip),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RspUpper<<32)+smram.RspLower),
Packit Service 501009
			(ulonglong)(smram.Rflags),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RaxUpper<<32)+smram.RaxLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RbxUpper<<32)+smram.RbxLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RcxUpper<<32)+smram.RcxLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RdxUpper<<32)+smram.RdxLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RsiUpper<<32)+smram.RsiLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RdiUpper<<32)+smram.RdiLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.RbpUpper<<32)+smram.RbpLower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R8Upper<<32)+smram.R8Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R9Upper<<32)+smram.R9Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R10Upper<<32)+smram.R10Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R11Upper<<32)+smram.R11Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R12Upper<<32)+smram.R12Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R13Upper<<32)+smram.R13Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R14Upper<<32)+smram.R14Lower),
Packit Service 501009
			(ulonglong)(((uint64_t)smram.R15Upper<<32)+smram.R15Lower),
Packit Service 501009
			smram.Cs,
Packit Service 501009
			smram.Ss);
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (machine_type("X86")) {
Packit Service 501009
		fprintf(ofp,
Packit Service 501009
			"    EAX: %08llx  EBX: %08llx  ECX: %08llx  EDX: %08llx\n"
Packit Service 501009
			"    DS:  %04x      ESI: %08llx  ES:  %04x      EDI: %08llx\n"
Packit Service 501009
			"    SS:  %04x      ESP: %08llx  EBP: %08llx  GS:  %04x\n"
Packit Service 501009
			"    CS:  %04x      EIP: %08llx  EFLAGS: %08llx\n",
Packit Service 501009
			(ulonglong)smram.RaxLower,
Packit Service 501009
			(ulonglong)smram.RbxLower,
Packit Service 501009
			(ulonglong)smram.RcxLower,
Packit Service 501009
			(ulonglong)smram.RdxLower,
Packit Service 501009
			smram.Ds & 0xffff,
Packit Service 501009
			(ulonglong)smram.RsiLower,
Packit Service 501009
			smram.Es & 0xffff,
Packit Service 501009
			(ulonglong)smram.RdiLower,
Packit Service 501009
			smram.Ss,
Packit Service 501009
			(ulonglong)smram.RspLower,
Packit Service 501009
			(ulonglong)smram.RbpLower,
Packit Service 501009
			smram.Gs,
Packit Service 501009
			smram.Cs,
Packit Service 501009
			(ulonglong)smram.Rip,
Packit Service 501009
			(ulonglong)smram.Rflags);
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 * sadump does not save phys_base; it must resort to another way.
Packit Service 501009
 */
Packit Service 501009
int sadump_phys_base(ulong *phys_base)
Packit Service 501009
{
Packit Service 501009
	if (SADUMP_VALID() && !sd->phys_base) {
Packit Service 501009
		if (CRASHDEBUG(1))
Packit Service 501009
			error(NOTE, "sadump: does not save phys_base.\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	if (sd->phys_base) {
Packit Service 501009
		*phys_base = sd->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
sadump_set_phys_base(ulong phys_base)
Packit Service 501009
{
Packit Service 501009
	sd->phys_base = phys_base;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
/*
Packit Service 501009
 *  Used by "sys" command to show diskset disk names.
Packit Service 501009
 */
Packit Service 501009
void sadump_show_diskset(void)
Packit Service 501009
{
Packit Service 501009
	int i;
Packit Service 501009
Packit Service 501009
	for (i = 0; i < sd->sd_list_len; ++i) {
Packit Service 501009
		char *filename = sd->sd_list[i]->filename;
Packit Service 501009
Packit Service 501009
		fprintf(fp, "%s%s", i ? "              " : "",
Packit Service 501009
			filename);
Packit Service 501009
		if ((i+1) < sd->sd_list_len)
Packit Service 501009
			fprintf(fp, "\n");
Packit Service 501009
	}
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static int block_table_init(void)
Packit Service 501009
{
Packit Service 501009
	uint64_t pfn, section, max_section, *block_table;
Packit Service 501009
Packit Service 501009
	max_section = divideup(sd->max_mapnr, SADUMP_PF_SECTION_NUM);
Packit Service 501009
Packit Service 501009
	block_table = calloc(sizeof(uint64_t), max_section);
Packit Service 501009
	if (!block_table) {
Packit Service 501009
		error(INFO, "sadump: cannot allocate memory for block_table\n");
Packit Service 501009
		return FALSE;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	for (section = 0; section < max_section; ++section) {
Packit Service 501009
		if (section > 0)
Packit Service 501009
			block_table[section] = block_table[section-1];
Packit Service 501009
		for (pfn = section * SADUMP_PF_SECTION_NUM;
Packit Service 501009
		     pfn < (section + 1) * SADUMP_PF_SECTION_NUM;
Packit Service 501009
		     ++pfn)
Packit Service 501009
			if (page_is_dumpable(pfn))
Packit Service 501009
				block_table[section]++;
Packit Service 501009
	}
Packit Service 501009
Packit Service 501009
	sd->block_table = block_table;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
static uint64_t pfn_to_block(uint64_t pfn)
Packit Service 501009
{
Packit Service 501009
	uint64_t block, section, p;
Packit Service 501009
Packit Service 501009
	section = pfn / SADUMP_PF_SECTION_NUM;
Packit Service 501009
Packit Service 501009
	if (section)
Packit Service 501009
		block = sd->block_table[section - 1];
Packit Service 501009
	else
Packit Service 501009
		block = 0;
Packit Service 501009
Packit Service 501009
	for (p = section * SADUMP_PF_SECTION_NUM; p < pfn; ++p)
Packit Service 501009
		if (page_is_dumpable(p))
Packit Service 501009
			block++;
Packit Service 501009
Packit Service 501009
	return block;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int sadump_is_zero_excluded(void)
Packit Service 501009
{
Packit Service 501009
	return (sd->flags & SADUMP_ZERO_EXCLUDED) ? TRUE : FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void sadump_set_zero_excluded(void)
Packit Service 501009
{
Packit Service 501009
	sd->flags |= SADUMP_ZERO_EXCLUDED;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
void sadump_unset_zero_excluded(void)
Packit Service 501009
{
Packit Service 501009
	sd->flags &= ~SADUMP_ZERO_EXCLUDED;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
struct sadump_data *
Packit Service 501009
get_sadump_data(void)
Packit Service 501009
{
Packit Service 501009
	return sd;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
#ifdef X86_64
Packit Service 501009
static int
Packit Service 501009
get_sadump_smram_cpu_state_any(struct sadump_smram_cpu_state *smram)
Packit Service 501009
{
Packit Service 2efe25
	ulong offset;
Packit Service 2efe25
	struct sadump_header *sh = sd->dump_header;
Packit Service 2efe25
	static int apicid;
Packit Service 2efe25
	struct sadump_smram_cpu_state scs;
Packit Service 2efe25
Packit Service 2efe25
	if (apicid >= sh->nr_cpus)
Packit Service 2efe25
		return FALSE;
Packit Service 2efe25
Packit Service 2efe25
	offset = sd->sub_hdr_offset + sizeof(uint32_t) +
Packit Service 2efe25
		 sd->dump_header->nr_cpus * sizeof(struct sadump_apic_state) +
Packit Service 2efe25
		 apicid * sizeof(scs);
Packit Service 2efe25
Packit Service 2efe25
	while (apicid < sh->nr_cpus) {
Packit Service 2efe25
		apicid++;
Packit Service 2efe25
		if (!read_device(&scs, sizeof(scs), &offset)) {
Packit Service 2efe25
			error(INFO, "sadump: cannot read sub header "
Packit Service 2efe25
				"cpu_state\n");
Packit Service 2efe25
			return FALSE;
Packit Service 2efe25
		}
Packit Service 2efe25
		if (scs.Cr3 && (scs.IdtUpper || scs.IdtLower)) {
Packit Service 2efe25
			*smram = scs;
Packit Service 2efe25
			return TRUE;
Packit Service 2efe25
		}
Packit Service 2efe25
	}
Packit Service 2efe25
Packit Service 2efe25
	return FALSE;
Packit Service 501009
}
Packit Service 501009
Packit Service 501009
int
Packit Service 501009
sadump_get_cr3_idtr(ulong *cr3, ulong *idtr)
Packit Service 501009
{
Packit Service 501009
	struct sadump_smram_cpu_state scs;
Packit Service 501009
Packit Service 501009
	memset(&scs, 0, sizeof(scs));
Packit Service 2efe25
	if (!get_sadump_smram_cpu_state_any(&scs))
Packit Service 2efe25
		return FALSE;
Packit Service 501009
Packit Service 501009
	*cr3 = scs.Cr3;
Packit Service 501009
	*idtr = ((uint64_t)scs.IdtUpper)<<32 | (uint64_t)scs.IdtLower;
Packit Service 501009
Packit Service 501009
	return TRUE;
Packit Service 501009
}
Packit Service 501009
#endif /* X86_64 */