[Crash-utility] patch to add vmss memory regions support

Dyno (Hongjun) Fu hfu at vmware.com
Mon Mar 23 22:22:55 UTC 2015


Dave,
 
    attached patch is to  add vmss memroy regions support.

    There might be holes in the memory address saved for PCI etc.
    In such case memory dump is divided into regions. Currently
    up to 3 regions are supported.

    Memory dump larger than 3GB will have the first hole.
    My dropbox space used up, I cannot attach a 4GB memory dump.
    and here is how it looks like in the vmss meta data dump.

3GB:
===
- Group: memory pos=0x1f6f6 size=0xc000090c ------------------------------------
align_mask[0, 0]                         => 0x00ffff
regionsCount                             => 0x000000
Memory[0, 0]                             => BLOCK, pos=0x20000, size=0xc0000000

4GB:
=== 
- Group: memory pos=0x1f6f6 size=0x10000090c -----------------------------------
align_mask[0, 0]                         => 0x00ffff
regionsCount                             => 0x000002
regionPageNum[0]                         => 0x000000
regionPPN[0]                             => 0x000000
regionSize[0]                            => 0x0c0000
regionPageNum[1]                         => 0x0c0000
regionPPN[1]                             => 0x100000
regionSize[1]                            => 0x040000
Memory[0, 0]                             => BLOCK, pos=0x20000, size=0x100000000

rgds,
Dyno
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://listman.redhat.com/archives/crash-utility/attachments/20150323/df9700ad/attachment.htm>
-------------- next part --------------
diff --git a/vmware_vmss.c b/vmware_vmss.c
index 9a98832..a836221 100644
--- a/vmware_vmss.c
+++ b/vmware_vmss.c
@@ -40,6 +40,8 @@ is_vmware_vmss(char *filename)
 		return FALSE;
 	}
 
+	fclose(fp);
+
 	if (hdr.id != CPTDUMP_OLD_MAGIC_NUMBER &&
 	    hdr.id != CPTDUMP_MAGIC_NUMBER &&
 	    hdr.id != CPTDUMP_PARTIAL_MAGIC_NUMBER &&
@@ -137,8 +139,7 @@ vmware_vmss_init(char *filename, FILE *ofp)
 				break;
 			}
 			name[nameLen] = 0;
-			DEBUG_PARSE_PRINT((vmss.ofp, LOGPRX"\t Item %20s",
-					   name));
+			DEBUG_PARSE_PRINT((vmss.ofp, LOGPRX"\t Item %20s", name));
 
 			nindx = TAG_NINDX(tag);
 			if (nindx > 3) {
@@ -161,6 +162,9 @@ vmware_vmss_init(char *filename, FILE *ofp)
 				int compressed = IS_BLOCK_COMPRESSED_TAG(tag);
 				uint16_t padsize;
 
+				assert(strcmp(name, "Memory") == 0);
+				assert(!compressed);
+
 				if (fread(&nbytes, sizeof(nbytes), 1, vmss.dfp) != 1) {
 					fprintf(vmss.ofp, LOGPRX"Cannot read block size.\n");
 					break;
@@ -186,11 +190,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
 				}
 
 				/* The things that we really care about...*/
-				if (strcmp(grps[i].name, "memory") == 0 &&
-				    strcmp(name, "Memory") == 0) {
-					vmss.memoffset = blockpos;
-					vmss.memsize = nbytesinmem;
-				}
+				vmss.memoffset = blockpos;
+				vmss.memsize = nbytesinmem;
 
 				DEBUG_PARSE_PRINT((vmss.ofp, "\t=> %sBLOCK: position=%#llx size=%#llx memsize=%#llx\n",
 						  compressed ? "COMPRESSED " : "",
@@ -214,18 +215,21 @@ vmware_vmss_init(char *filename, FILE *ofp)
 
 				if (strcmp(grps[i].name, "memory") == 0) {
 					if (strcmp(name, "regionsCount") == 0) {
-						vmss.regionscount = (uint32_t) *val;
-						if (vmss.regionscount != 0) {
-							fprintf(vmss.ofp, LOGPRX"regionsCount=%d (!= 0) NOT TESTED!",
-							        vmss.regionscount);
-						}
+						vmss.regionscount = *(uint32_t*)val;
+						assert(vmss.regionscount <= MAX_REGIONS);
+					}
+				        if (strcmp(name, "regionPageNum") == 0) {
+						vmss.regions[idx[0]].startpagenum = *(uint32_t*)val;
+					}
+					if (strcmp(name, "regionPPN") == 0) {
+						vmss.regions[idx[0]].startppn = *(uint32_t*)val;
+					}
+					if (strcmp(name, "regionSize") == 0) {
+						vmss.regions[idx[0]].size = *(uint32_t*)val;
 					}
 					if (strcmp(name, "align_mask") == 0) {
-						vmss.alignmask = (uint32_t) *val;
-						if (vmss.alignmask != 0xff) {
-							fprintf(vmss.ofp, LOGPRX"align_mask=%d (!= 0xff) NOT TESTED!",
-							        vmss.regionscount);
-						}
+						vmss.alignmask = *(uint32_t*)val;
+						assert(vmss.alignmask == 0xFFFF);
 					}
 				}
 
@@ -252,8 +256,8 @@ vmware_vmss_init(char *filename, FILE *ofp)
 		}
 		strcpy(p, "vmem");
 		if ((fp = fopen(vmem_filename, "r")) == NULL) {
-			free(vmem_filename);
 			error(INFO, LOGPRX"%s: %s\n", vmem_filename, strerror(errno));
+			free(vmem_filename);
 			return FALSE;
 		}
 		vmss.dfp = fp;
@@ -270,27 +274,35 @@ vmware_vmss_init(char *filename, FILE *ofp)
 
 uint vmware_vmss_page_size(void)
 {
-	return 4096;
+	return PAGE_SIZE;
 }
 
 int
 read_vmware_vmss(int fd, void *bufptr, int cnt, ulong addr, physaddr_t paddr)
 {
-	uint64_t pos = vmss.memoffset + paddr;
+	uint64_t pos = paddr;
+
+	if (vmss.regionscount > 0) {
+		/* Memory is divided into regions and there are holes between them. */
+		uint32_t ppn = (uint32_t) (pos >> PAGE_SHIFT);
+	        int i;
+
+		for (i = 0; i < vmss.regionscount; i++) {
+			if (ppn < vmss.regions[i].startppn)
+				break;
 
-	if (pos + cnt > vmss.memoffset + vmss.memsize) {
-		cnt -= ((pos + cnt) - (vmss.memoffset + vmss.memsize));
-		if (cnt < 0) {
-			error(INFO, LOGPRX"Read beyond the end of file! paddr=%#lx\n",
-			      paddr);
+			/* skip holes. */
+			pos -= ((vmss.regions[i].startppn - vmss.regions[i].startpagenum)
+				<< PAGE_SHIFT);
 		}
 	}
+	assert(pos + cnt <= vmss.memsize);
 
+	pos += vmss.memoffset;
         if (fseek(vmss.dfp, pos, SEEK_SET) != 0)
 		return SEEK_ERROR;
 
-        if (fread(bufptr, 1 , cnt, vmss.dfp) != cnt)
-		return READ_ERROR;
+	cnt = fread(bufptr, 1, cnt, vmss.dfp);
 
 	return cnt;
 }
diff --git a/vmware_vmss.h b/vmware_vmss.h
index dcbde2d..3f46188 100644
--- a/vmware_vmss.h
+++ b/vmware_vmss.h
@@ -82,6 +82,14 @@ struct cptgroupdesc {
 };
 typedef struct cptgroupdesc	cptgroupdesc;
 
+struct memregion {
+   uint32_t startpagenum;
+   uint32_t startppn;
+   uint32_t size;
+};
+typedef struct memregion	memregion;
+
+#define MAX_REGIONS	3
 struct vmssdata {
 	int32_t	cpt64bit;
 	FILE	*dfp;
@@ -89,6 +97,7 @@ struct vmssdata {
 	/* about the memory */
 	uint32_t	alignmask;
 	uint32_t	regionscount;
+        memregion	regions[MAX_REGIONS];
 	uint64_t	memoffset;
 	uint64_t	memsize;
 };


More information about the Crash-utility mailing list