>From 40599aa830e6fa709ce7b2ceb87bbcabe93f857b Mon Sep 17 00:00:00 2001
From: HATAYAMA Daisuke <d.hatayama@jp.fujitsu.com>
Date: Tue, 13 Sep 2011 15:28:03 +0900
Subject: [PATCH 11/12] memory: Add sadump related memory interface

sadump_memory_used() and sadump_free_memory() do nothing.

sadump_memory_dump() dumps sadump_data, users can call this function through
help -D command.
---
 defs.h   |    3 +
 memory.c |    6 ++
 sadump.c |  253 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 262 insertions(+), 0 deletions(-)

diff --git a/defs.h b/defs.h
index cb47072..7ad46c9 100755
--- a/defs.h
+++ b/defs.h
@@ -4728,6 +4728,9 @@ int sadump_init(char *, FILE *);
 int sadump_is_diskset(void);
 ulong get_sadump_panic_task(void);
 ulong get_sadump_switch_stack(ulong);
+int sadump_memory_used(void);
+int sadump_free_memory(void);
+int sadump_memory_dump(FILE *);
 FILE *set_sadump_fp(FILE *);
 void get_sadump_regs(struct bt_info *bt, ulong *ipp, ulong *spp);
 void sadump_display_regs(int, FILE *);
diff --git a/memory.c b/memory.c
index 8e3d695..fa1746f 100755
--- a/memory.c
+++ b/memory.c
@@ -14082,6 +14082,8 @@ dumpfile_memory(int cmd)
                         retval = vas_memory_used();
 		else if (pc->flags & S390D)
 			retval = s390_memory_used();
+		else if (pc->flags2 & SADUMP)
+			retval = sadump_memory_used();
 		break;
 
 	case DUMPFILE_FREE_MEM:
@@ -14103,6 +14105,8 @@ dumpfile_memory(int cmd)
                         retval = vas_free_memory(NULL);
                 else if (pc->flags & S390D)
                         retval = s390_free_memory();
+		else if (pc->flags2 & SADUMP)
+			retval = sadump_free_memory();
 		break;
 
 	case DUMPFILE_MEM_DUMP:
@@ -14126,6 +14130,8 @@ dumpfile_memory(int cmd)
                         retval = s390_memory_dump(fp);
                 else if (pc->flags & PROC_KCORE)
                         retval = kcore_memory_dump(fp);
+		else if (pc->flags2 & SADUMP)
+			retval = sadump_memory_dump(fp);
 		break;
 	
 	case DUMPFILE_ENVIRONMENT:
diff --git a/sadump.c b/sadump.c
index a892c72..9736d9e 100644
--- a/sadump.c
+++ b/sadump.c
@@ -44,6 +44,7 @@ static ulong per_cpu_ptr(ulong ptr, int cpu);
 static ulong early_per_cpu_ptr(char *symbol, struct syment *sym, int cpu);
 static ulong legacy_per_cpu_ptr(ulong ptr, int cpu);
 static int get_prstatus_from_crash_notes(int cpu, char *prstatus);
+static void display_smram_cpu_state(int apicid, struct sadump_smram_cpu_state *s);
 static int cpu_to_apicid(int cpu, int *apicid);
 static int get_sadump_smram_cpu_state(int cpu, struct sadump_smram_cpu_state *smram);
 static int block_table_init(void);
@@ -836,6 +837,212 @@ verify_magic_number(uint32_t magicnum[DUMP_PART_HEADER_MAGICNUM_SIZE])
 	return TRUE;
 }
 
+int sadump_memory_used(void)
+{
+	return 0;
+}
+
+int sadump_free_memory(void)
+{
+	return 0;
+}
+
+/*
+ *  This function is dump-type independent, and could be used to dump
+ *  the diskdump_data structure contents and perhaps the sadump header
+ *  data.
+ */
+int sadump_memory_dump(FILE *fp)
+{
+	struct sadump_part_header *sph;
+	struct sadump_disk_set_header *sdh;
+	struct sadump_header *sh;
+	struct sadump_media_header *smh;
+	int i, others;
+	struct tm tm;
+	char guid[33];
+
+	fprintf(fp, "sadump_data: \n");
+	fprintf(fp, "          filename: %s\n", sd->filename);
+	fprintf(fp, "             flags: %lx (", sd->flags);
+	others = 0;
+	if (sd->flags & SADUMP_LOCAL)
+		fprintf(fp, "%sSADUMP_LOCAL", others++ ? "|" : "");
+	if (sd->flags & SADUMP_DISKSET)
+		fprintf(fp, "%sSADUMP_DISKSET", others++ ? "|" : "");
+	if (sd->flags & SADUMP_MEDIA)
+		fprintf(fp, "%sSADUMP_MEDIA", others++ ? "|" : "");
+	fprintf(fp, ") \n");
+        fprintf(fp, "               dfd: %d\n", sd->dfd);
+        fprintf(fp, "      machine_type: %d ", sd->machine_type);
+	switch (sd->machine_type)
+	{
+	case EM_386:
+		fprintf(fp, "(EM_386)\n"); break;
+	case EM_X86_64:
+		fprintf(fp, "(EM_X86_64)\n"); break;
+	default:
+		fprintf(fp, "(unknown)\n"); break;
+	}
+
+        fprintf(fp, "\n            header: %lx\n", (ulong)sd->header);
+	sph = sd->header;
+	fprintf(fp, "          signature1: %x\n", sph->signature1);
+	fprintf(fp, "          signature2: %x\n", sph->signature2);
+	fprintf(fp, "              enable: %u\n", sph->enable);
+	fprintf(fp, "              reboot: %u\n", sph->reboot);
+	fprintf(fp, "            compress: %u\n", sph->compress);
+	fprintf(fp, "             recycle: %u\n", sph->recycle);
+	fprintf(fp, "               label: (unused)\n");
+	fprintf(fp, "           sadump_id: %s\n", guid_to_str(&sph->sadump_id, guid, sizeof(guid)));
+	fprintf(fp, "         disk_set_id: %s\n", guid_to_str(&sph->disk_set_id, guid, sizeof(guid)));
+	fprintf(fp, "              vol_id: %s\n", guid_to_str(&sph->vol_id, guid, sizeof(guid)));
+	fprintf(fp, "          time_stamp: %s\n",
+		strip_linefeeds(asctime(efi_time_t_to_tm(&sph->time_stamp, &tm))));
+	fprintf(fp, "        set_disk_set: %u\n", sph->set_disk_set);
+	fprintf(fp, "             reserve: %u\n", sph->reserve);
+	fprintf(fp, "         used_device: %llu\n", (ulonglong)sph->used_device);
+	fprintf(fp, "            magicnum: %s\n",
+		verify_magic_number(sph->magicnum)
+		? "(valid)" : "(invalid)");
+
+        fprintf(fp, "\n       dump header: %lx\n", (ulong)sd->dump_header);
+	sh = sd->dump_header;
+	fprintf(fp, "           signature: %s\n", sh->signature);
+	fprintf(fp, "      header_version: %u\n", sh->header_version);
+	fprintf(fp, "             reserve: %u\n", sh->reserve);
+	fprintf(fp, "           timestamp: %s\n",
+		strip_linefeeds(asctime(efi_time_t_to_tm(&sh->timestamp, &tm))));
+	fprintf(fp, "              status: %u\n", sh->status);
+	fprintf(fp, "            compress: %u\n", sh->compress);
+	fprintf(fp, "          block_size: %u\n", sh->block_size);
+	fprintf(fp, "      extra_hdr_size: %u\n", sh->extra_hdr_size);
+	fprintf(fp, "        sub_hdr_size: %u\n", sh->sub_hdr_size);
+	fprintf(fp, "       bitmap_blocks: %u\n", sh->bitmap_blocks);
+	fprintf(fp, "dumpable_bitmap_blocks: %u\n", sh->dumpable_bitmap_blocks);
+	fprintf(fp, "           max_mapnr: %u\n", sh->max_mapnr);
+	fprintf(fp, "    total_ram_blocks: %u\n", sh->total_ram_blocks);
+	fprintf(fp, "       device_blocks: %u\n", sh->device_blocks);
+	fprintf(fp, "      written_blocks: %u\n", sh->written_blocks);
+	fprintf(fp, "         current_cpu: %u\n", sh->current_cpu);
+	fprintf(fp, "             nr_cpus: %u\n", sh->nr_cpus);
+
+	fprintf(fp, "\n    dump sub heaer: ");
+	if (sh->sub_hdr_size > 0) {
+		ulong offset = sd->sub_hdr_offset;
+		struct sadump_apic_state as;
+		struct sadump_smram_cpu_state scs, zero;
+		uint32_t size;
+		uint aid;
+
+		memset(&zero, 0, sizeof(zero));
+
+		if (!read_device(&size, sizeof(uint32_t), &offset)) {
+			error(INFO, "sadump: cannot read sub header size\n");
+			return FALSE;
+		}
+		fprintf(fp, "\n                size: %u\n", size);
+		for (aid = 0; aid < sh->nr_cpus; ++aid) {
+			if (!read_device(&as, sizeof(as), &offset)) {
+				error(INFO, "sadump: cannot read sub header "
+				      "apic_id\n");
+				return FALSE;
+			}
+			fprintf(fp, "          "
+				"apic_id[%u]: ApicId %llu: Ldr: %llu\n",
+				aid, (ulonglong)as.ApicId, (ulonglong)as.Ldr);
+		}
+		for (aid = 0; aid < sh->nr_cpus; ++aid) {
+			if (!read_device(&scs, sizeof(scs), &offset)) {
+				error(INFO, "sadump: cannot read sub header "
+				      "cpu_state\n");
+				return FALSE;
+			}
+			if (memcmp(&scs, &zero, sizeof(scs)) != 0) {
+				fprintf(fp, "\n");
+				display_smram_cpu_state(aid, &scs);
+			}
+		}
+	} else
+		fprintf(fp, "(n/a)\n");
+
+        fprintf(fp, "\n   disk set header: %lx ", (ulong)sd->diskset_header);
+	if ((sdh = sd->diskset_header)) {
+		fprintf(fp, "\ndisk_set_header_size: %u\n", sdh->disk_set_header_size);
+		fprintf(fp, "            disk_num: %u\n", sdh->disk_num);
+		fprintf(fp, "       disk_set_size: %llu\n", (ulonglong)sdh->disk_set_size);
+		for (i = 0; i < sdh->disk_num - 1; ++i) {
+			struct sadump_volume_info *vol = &sdh->vol_info[i];
+
+			fprintf(fp, "         vol_info[%d]: \n", i);
+			fprintf(fp, "                     id: %s\n", guid_to_str(&vol->id, guid, sizeof(guid)));
+			fprintf(fp, "               vol_size: %llu\n", (ulonglong)vol->vol_size);
+			fprintf(fp, "                 status: %u\n", vol->status);
+			fprintf(fp, "             cache_size: %u\n", vol->cache_size);
+		}
+	} else
+		fprintf(fp, "(n/a)\n");
+
+        fprintf(fp, "\n      media header: %lx ", (ulong)sd->media_header);
+	if ((smh = sd->media_header)) {
+		fprintf(fp, "\n           sadump_id: %s\n", guid_to_str(&smh->sadump_id, guid, sizeof(guid)));
+		fprintf(fp, "         disk_set_id: %s\n", guid_to_str(&smh->disk_set_id, guid, sizeof(guid)));
+		fprintf(fp, "          time_stamp: %s\n",
+			strip_linefeeds(asctime(efi_time_t_to_tm(&smh->time_stamp, &tm))));
+		fprintf(fp, "      sequential_num: %d\n", smh->sequential_num);
+		fprintf(fp, "           term_cord: %d\n", smh->term_cord);
+		fprintf(fp, "disk_set_header_size: %d\n", smh->disk_set_header_size);
+		fprintf(fp, "        disks_in_use: %d\n", smh->disks_in_use);
+		fprintf(fp, "             reserve: (not displayed) \n");
+	} else
+		fprintf(fp, "(n/a)\n");
+
+        fprintf(fp, "\n            bitmap: %lx\n", (ulong)sd->bitmap);
+        fprintf(fp, "   dumpable_bitmap: %lx\n", (ulong)sd->dumpable_bitmap);
+        fprintf(fp, "    sub_hdr_offset: %lx\n", (ulong)sd->sub_hdr_offset);
+        fprintf(fp, "smram_cpu_state_size: %lx\n", (ulong)sd->smram_cpu_state_size);
+        fprintf(fp, "       data_offset: %lx\n", sd->data_offset);
+        fprintf(fp, "        block_size: %d\n", sd->block_size);
+        fprintf(fp, "       block_shift: %d\n", sd->block_shift);
+	fprintf(fp, "          page_buf: %lx\n", (ulong)sd->page_buf);
+	fprintf(fp, "       block_table: %lx\n", (ulong)sd->block_table);
+	fprintf(fp, "       sd_list_len: %d\n", sd->sd_list_len);
+	fprintf(fp, "           sd_list: %lx\n", (ulong)sd->sd_list);
+
+	for (i = 0; i < sd->sd_list_len; ++i) {
+		struct sadump_diskset_data *sdd = sd->sd_list[i];
+
+		fprintf(fp, "\n        sd_list[%d]: \n", i);
+		fprintf(fp, "            filename: %s\n", sdd->filename);
+		fprintf(fp, "                 dfd: %d\n", sdd->dfd);
+
+		fprintf(fp, "              header: %lx\n", (ulong)sdd->header);
+		sph = sdd->header;
+		fprintf(fp, "            signature1: %x\n", sph->signature1);
+		fprintf(fp, "            signature2: %x\n", sph->signature2);
+		fprintf(fp, "                enable: %u\n", sph->enable);
+		fprintf(fp, "                reboot: %u\n", sph->reboot);
+		fprintf(fp, "              compress: %u\n", sph->compress);
+		fprintf(fp, "               recycle: %u\n", sph->recycle);
+		fprintf(fp, "                 label: (unused)\n");
+		fprintf(fp, "             sadump_id: %s\n", guid_to_str(&sph->sadump_id, guid, sizeof(guid)));
+		fprintf(fp, "           disk_set_id: %s\n", guid_to_str(&sph->disk_set_id, guid, sizeof(guid)));
+		fprintf(fp, "                vol_id: %s\n", guid_to_str(&sph->vol_id, guid, sizeof(guid)));
+		fprintf(fp, "            time_stamp: %s\n",
+			strip_linefeeds(asctime(efi_time_t_to_tm(&sph->time_stamp, &tm))));
+		fprintf(fp, "          set_disk_set: %u\n", sph->set_disk_set);
+		fprintf(fp, "               reserve: %u\n", sph->reserve);
+		fprintf(fp, "           used_device: %llu\n", (ulonglong)sph->used_device);
+		fprintf(fp, "              magicnum: %s\n",
+			verify_magic_number(sph->magicnum)
+			? "(valid)" : "(invalid)");
+
+		fprintf(fp, "         data_offset: %lx\n", sdd->data_offset);
+	}
+
+	return TRUE;
+}
+
 static ulong
 per_cpu_ptr(ulong ptr, int cpu)
 {
@@ -1023,6 +1230,52 @@ sadump_get_smram_cpu_state(int apicid,
 	return TRUE;
 }
 
+static void
+display_smram_cpu_state(int apicid, struct sadump_smram_cpu_state *s)
+{
+	fprintf(fp,
+		"APIC ID: %d\n"
+		"    RIP: %016llx RSP: %08x%08x RBP: %08x%08x\n"
+		"    RAX: %08x%08x RBX: %08x%08x RCX: %08x%08x\n"
+		"    RDX: %08x%08x RSI: %08x%08x RDI: %08x%08x\n"
+		"    R08: %08x%08x R09: %08x%08x R10: %08x%08x\n"
+		"    R11: %08x%08x R12: %08x%08x R13: %08x%08x\n"
+		"    R14: %08x%08x R15: %08x%08x\n"
+		"    SMM REV: %08x SMM BASE %08x\n"
+		"    CS : %08x DS: %08x SS: %08x ES: %08x FS: %08x\n"
+		"    GS : %08x\n"
+		"    CR0: %016llx CR3: %016llx CR4: %08x\n"
+		"    GDT: %08x%08x LDT: %08x%08x IDT: %08x%08x\n"
+		"    GDTlim: %08x LDTlim: %08x IDTlim: %08x\n"
+		"    LDTR: %08x TR: %08x RFLAGS: %016llx\n"
+		"    EPTP: %016llx EPTP_SETTING: %08x\n"
+		"    DR6: %016llx DR7: %016llx\n"
+		"    Ia32Efer: %016llx\n"
+		"    IoMemAddr: %08x%08x IoEip: %016llx\n"
+		"    IoMisc: %08x LdtInfo: %08x\n"
+		"    IoInstructionRestart: %04x AutoHaltRestart: %04x\n",
+		apicid,
+		(ulonglong)s->Rip, s->RspUpper, s->RspLower, s->RbpUpper, s->RbpLower,
+		s->RaxUpper, s->RaxLower, s->RbxUpper, s->RbxLower, s->RcxUpper, s->RcxLower,
+		s->RdxUpper, s->RdxLower, s->RsiUpper, s->RsiLower, s->RdiUpper, s->RdiLower,
+		s->R8Upper, s->R8Lower,	s->R9Upper, s->R9Lower,	s->R10Upper, s->R10Lower,
+		s->R11Upper, s->R11Lower, s->R12Upper, s->R12Lower, s->R13Upper, s->R13Lower,
+		s->R14Upper, s->R14Lower, s->R15Upper, s->R15Lower,
+		s->SmmRevisionId, s->Smbase,
+		s->Cs, s->Ds, s->Ss, s->Es, s->Fs, s->Gs,
+		(ulonglong)s->Cr0, (ulonglong)s->Cr3, s->Cr4,
+		s->GdtUpper, s->GdtLower, s->LdtUpper, s->LdtLower, s->IdtUpper, s->IdtLower,
+		s->GdtLimit, s->LdtLimit, s->IdtLimit,
+		s->Ldtr, s->Tr, (ulonglong)s->Rflags,
+		(ulonglong)s->Eptp, s->EptpSetting,
+		(ulonglong)s->Dr6, (ulonglong)s->Dr7,
+		(ulonglong)s->Ia32Efer,
+		s->IoMemAddrUpper, s->IoMemAddrLower, (ulonglong)s->IoEip,
+		s->IoMisc, s->LdtInfo,
+		s->IoInstructionRestart,
+		s->AutoHaltRestart);
+}
+
 static int cpu_to_apicid(int cpu, int *apicid)
 {
 	struct syment *sym;
-- 
1.7.4.4

