Blame SOURCES/v1.0.7_update.patch

8993ab
8993ab
ptdump could fail with the following error message:
8993ab
8993ab
    ptdump: invalid size request: 0 type: "read page for write"
8993ab
8993ab
This is because there is lack of consideration in function
8993ab
write_buffer_wrapped() that there is possibility that current write
8993ab
position in the corresponding ring buffer could be just on
8993ab
page-aligned offset. Then, read size for the 3rd write operation
8993ab
becomes 0 bytes and then readmem() accepting the 0 bytes in the 4th
8993ab
argument results in the error with the above error message.
8993ab
8993ab
More concretely, function write_buffer_wrapped() retrieves and writes
8993ab
data on the corresponding ring buffer in 3 write operations as the
8993ab
following picture:
8993ab
8993ab
           current write position
8993ab
      (2)           (3)  | (1)
8993ab
     <-----------> <---> v <----------->
8993ab
    +-------------+---------+----------+
8993ab
    |             |         |          |
8993ab
    |             |    P    |          |
8993ab
    |             |         |          |
8993ab
    +-------------+---------+----------+
8993ab
8993ab
The largest square is the corresponding ring buffer containing the
8993ab
trace data collected by Intel PT. The downward arrow illustrates the
8993ab
current write position, i.e. the offset of the write operation() at
8993ab
the timing when system panic occurs and crash dump is collected. The
8993ab
small square containing the letter 'P' is the page where the current
8993ab
write position belongs to. ptdump retrieves and writes the data in
8993ab
this ring buffer in the order of (1), (2) and (3), i.e. from old to
8993ab
new data.
8993ab
8993ab
Then, note that when the current write position is on the page-aligned
8993ab
offset, there is no square containing 'P' as:
8993ab
8993ab
          current write position
8993ab
      (2)          | (1)
8993ab
     <------------>v<----------->
8993ab
    +-------------++------------+
8993ab
    |             ||            |
8993ab
    |             ||            |
8993ab
    |             ||            |
8993ab
    +-------------++------------+
8993ab
8993ab
and then the write size for the write operation (3) becomes 0 bytes,
8993ab
meaning that the write operation (3) is unnecessary in this case.
8993ab
8993ab
8993ab
8993ab
--- ptdump-1.0.3/ptdump.c.orig
8993ab
+++ ptdump-1.0.3/ptdump.c
8993ab
@@ -72,7 +72,7 @@ get_member(ulong addr, char *name, char
8993ab
 	size = MEMBER_SIZE(name, member);
8993ab
 
8993ab
 
8993ab
-	if (!readmem(addr + offset, KVADDR, buf, size, name, FAULT_ON_ERROR))
8993ab
+	if (!readmem(addr + offset, KVADDR, buf, size, name, RETURN_ON_ERROR))
8993ab
 		return FALSE;
8993ab
 
8993ab
 	return TRUE;
8993ab
@@ -162,7 +162,7 @@ int init_pt_info(int cpu)
8993ab
 		ulong page;
8993ab
 
8993ab
 		if (!readmem(pgaddr, KVADDR, &page, sizeof(ulong),
8993ab
-			     "struct page", FAULT_ON_ERROR))
8993ab
+			     "struct page", RETURN_ON_ERROR))
8993ab
 			continue;
8993ab
 
8993ab
 		pt_info_ptr->buffer_ptr[i] = page;
8993ab
@@ -194,7 +194,7 @@ int init_pt_info(int cpu)
8993ab
 	/* Read topa entry */
8993ab
 	if (!readmem((topa_base) + topa_idx*(sizeof(struct topa_entry)),
8993ab
 		     KVADDR, &topa, sizeof(topa),
8993ab
-		     "struct topa_entry", FAULT_ON_ERROR)) {
8993ab
+		     "struct topa_entry", RETURN_ON_ERROR)) {
8993ab
 		fprintf(fp, "Cannot read topa table\n");
8993ab
 		goto out_error;
8993ab
 	}
8993ab
@@ -230,7 +230,8 @@ int init_pt_info(int cpu)
8993ab
 out_error:
8993ab
 	if (pt_info_ptr->buffer_ptr != NULL)
8993ab
 		free(pt_info_ptr->buffer_ptr);
8993ab
-		return FALSE;
8993ab
+
8993ab
+	return FALSE;
8993ab
 }
8993ab
 
8993ab
 static inline int is_zero_page(ulong page, int offset)
8993ab
@@ -247,8 +248,11 @@ static inline int is_zero_page(ulong pag
8993ab
 
8993ab
 	memset(buf, 0, PAGESIZE());
8993ab
 	dbgprintf(fp, "zero page chk: 0x%016lx, %lu\n", read_addr, read_size);
8993ab
-	readmem(read_addr, KVADDR, buf, read_size, "zero page check",
8993ab
-	        FAULT_ON_ERROR);
8993ab
+	if (!readmem(read_addr, KVADDR, buf, read_size, "zero page check",
8993ab
+		     RETURN_ON_ERROR)) {
8993ab
+		free(buf);
8993ab
+		return FALSE;
8993ab
+	}
8993ab
 
8993ab
 	for (i = 0; i < PAGESIZE() - offset; i++) {
8993ab
 		if (buf[i]) {
8993ab
@@ -312,8 +316,11 @@ int write_buffer_wrapped(int cpu, FILE *
8993ab
 		page = pt_info_ptr->buffer_ptr[idx];
8993ab
 		len = PAGESIZE() - offset;
8993ab
 
8993ab
-		readmem(page + offset, KVADDR, buf, len, "read page for write",
8993ab
-			FAULT_ON_ERROR);
8993ab
+		if (!readmem(page + offset, KVADDR, buf, len, "read page for write",
8993ab
+			     RETURN_ON_ERROR)) {
8993ab
+			free(buf);
8993ab
+			return FALSE;
8993ab
+		}
8993ab
 
8993ab
 		dbgprintf(fp, "[%d] R/W1 buff: p=0x%lx, i=%d, o=%lu, l=%d\n",
8993ab
 			cpu, page + offset, idx, offset, len);
8993ab
@@ -332,8 +339,11 @@ int write_buffer_wrapped(int cpu, FILE *
8993ab
 		page = pt_info_ptr->buffer_ptr[idx];
8993ab
 		len = PAGESIZE() - offset;
8993ab
 
8993ab
-		readmem(page + offset, KVADDR, buf, len, "read page for write",
8993ab
-			FAULT_ON_ERROR);
8993ab
+		if (!readmem(page + offset, KVADDR, buf, len, "read page for write",
8993ab
+			     RETURN_ON_ERROR)) {
8993ab
+			free(buf);
8993ab
+			return FALSE;
8993ab
+		}
8993ab
 
8993ab
 		dbgprintf(fp, "[%d] R/W2 buff: p=0x%lx, i=%d, o=%lu, l=%d\n",
8993ab
 			cpu, page + offset, idx, offset, len);
8993ab
@@ -351,8 +361,14 @@ int write_buffer_wrapped(int cpu, FILE *
8993ab
 	offset = pt_info_ptr->output_off & mask;
8993ab
 	len = offset;
8993ab
 
8993ab
-	readmem(page, KVADDR, buf, len, "read page for write",
8993ab
-		FAULT_ON_ERROR);
8993ab
+	if (!len)
8993ab
+		goto done;
8993ab
+
8993ab
+	if (!readmem(page, KVADDR, buf, len, "read page for write",
8993ab
+		     RETURN_ON_ERROR)) {
8993ab
+		free(buf);
8993ab
+		return FALSE;
8993ab
+	}
8993ab
 
8993ab
 	dbgprintf(fp, "[%d] R/W3 buff: p=0x%lx, i=%d, o=%lu, l=%d\n", cpu,
8993ab
 		page, idx, offset, len);
8993ab
@@ -364,6 +380,7 @@ int write_buffer_wrapped(int cpu, FILE *
8993ab
 		return FALSE;
8993ab
 	}
8993ab
 
8993ab
+done:
8993ab
 	free(buf);
8993ab
 	return TRUE;
8993ab
 }
8993ab
@@ -388,8 +405,11 @@ int write_buffer_nowrapped(int cpu, FILE
8993ab
 		page = pt_info_ptr->buffer_ptr[idx];
8993ab
 		len = PAGESIZE();
8993ab
 
8993ab
-		readmem(page, KVADDR, buf, len, "read page for write",
8993ab
-			FAULT_ON_ERROR);
8993ab
+		if (!readmem(page, KVADDR, buf, len, "read page for write",
8993ab
+			     RETURN_ON_ERROR)) {
8993ab
+			free(buf);
8993ab
+			return FALSE;
8993ab
+		}
8993ab
 
8993ab
 		dbgprintf(fp, "[%d] R/W1 buff: p=0x%lx, i=%d, o=%lu, l=%d\n",
8993ab
 			cpu, page, idx, (ulong)0, len);
8993ab
@@ -406,8 +426,14 @@ int write_buffer_nowrapped(int cpu, FILE
8993ab
 	page = pt_info_ptr->buffer_ptr[idx];
8993ab
 	len = pt_info_ptr->output_off & mask;
8993ab
 
8993ab
-	readmem(page, KVADDR, buf, len, "read page for write",
8993ab
-		FAULT_ON_ERROR);
8993ab
+	if (!len)
8993ab
+		goto done;
8993ab
+
8993ab
+	if (!readmem(page, KVADDR, buf, len, "read page for write",
8993ab
+		     RETURN_ON_ERROR)) {
8993ab
+		free(buf);
8993ab
+		return FALSE;
8993ab
+	}
8993ab
 
8993ab
 	dbgprintf(fp, "[%d] R/W2 buff: p=0x%lx, i=%d, o=%lu, l=%d\n", cpu,
8993ab
 		page, idx, (ulong)0, len);
8993ab
@@ -419,6 +445,7 @@ int write_buffer_nowrapped(int cpu, FILE
8993ab
 		return FALSE;
8993ab
 	}
8993ab
 
8993ab
+done:
8993ab
 	free(buf);
8993ab
 	return TRUE;
8993ab
 }
8993ab
@@ -491,6 +518,9 @@ cmd_ptdump(void)
8993ab
 	if (argcnt != 2)
8993ab
 		cmd_usage(pc->curcmd, SYNOPSIS);
8993ab
 
8993ab
+	if (ACTIVE())
8993ab
+		error(FATAL, "not supported on a live system\n");
8993ab
+
8993ab
 	outdir = args[1];
8993ab
 	if ((ret = mkdir(outdir, mode))) {
8993ab
 		fprintf(fp, "Cannot create directory %s: %d\n", outdir, ret);
8993ab
@@ -502,12 +532,12 @@ cmd_ptdump(void)
8993ab
 		return;
8993ab
 	}
8993ab
 
8993ab
-	/* 
8993ab
-	 * Set the gdb scope to ensure that the appropriate ring_buffer 
8993ab
-	 * structure is selected. 
8993ab
+	/*
8993ab
+	 * Set the gdb scope to ensure that the appropriate ring_buffer
8993ab
+	 * structure is selected.
8993ab
 	 */
8993ab
 	if (kernel_symbol_exists("perf_mmap_to_page"))
8993ab
-		gdb_set_crash_scope(symbol_value("perf_mmap_to_page"), 
8993ab
+		gdb_set_crash_scope(symbol_value("perf_mmap_to_page"),
8993ab
 			"perf_mmap_to_page");
8993ab
 
8993ab
 	online_cpus = get_cpus_online();