msm: kgsl: Improve robustness of snapshot and map frozen GPU objects

Improve the IB parser to be more robust when dealing with terribly
corrupted buffers.  Also, make sure that the frozen GPU objects are
mapped in the kernel prior to being dumped.

Change-Id: Ic0dedbad49c52b9a41915ab36430770cb7b0025c
Signed-off-by: Jordan Crouse <jcrouse@codeaurora.org>
diff --git a/drivers/gpu/msm/adreno_snapshot.c b/drivers/gpu/msm/adreno_snapshot.c
index e8cb734..2dc6f6c 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -454,33 +454,36 @@
 static void ib_add_gpu_object(struct kgsl_device *device, unsigned int ptbase,
 		unsigned int gpuaddr, unsigned int dwords)
 {
-	int i = 0, ret;
+	int i, ret, rem = dwords;
 	unsigned int *src = (unsigned int *) adreno_convertaddr(device, ptbase,
 		gpuaddr, dwords << 2);
 
 	if (src == NULL)
 		return;
 
-	while (i < dwords) {
+	for (i = 0; rem != 0; rem--, i++) {
+		int pktsize;
+
+		if (!pkt_is_type0(src[i]) && !pkt_is_type3(src[i]))
+			continue;
+
+		pktsize = type3_pkt_size(src[i]);
+
+		if ((pktsize + 1) > rem)
+			break;
 
 		if (pkt_is_type3(src[i])) {
-			if ((dwords - i) < type3_pkt_size(src[i]) + 1)
-				goto skip;
-
 			if (adreno_cmd_is_ib(src[i]))
 				ib_add_gpu_object(device, ptbase,
 					src[i + 1], src[i + 2]);
 			else
 				ib_parse_type3(device, &src[i], ptbase);
-
-			i += type3_pkt_size(src[i]);
 		} else if (pkt_is_type0(src[i])) {
 			ib_parse_type0(device, &src[i], ptbase);
-			i += type0_pkt_size(src[i]);
 		}
 
-skip:
-		i++;
+		i += pktsize;
+		rem -= pktsize;
 	}
 
 	ret = kgsl_snapshot_get_object(device, ptbase, gpuaddr, dwords << 2,
@@ -571,7 +574,7 @@
 	while (index != rb->wptr) {
 		index--;
 
-		if (index  < 0) {
+		if (index < 0) {
 			index = rb->sizedwords - 2;
 
 			/*
@@ -587,7 +590,8 @@
 		}
 
 		/* Break if the current packet is a context switch identifier */
-		if (adreno_rb_ctxtswitch(&rbptr[index]))
+		if ((rbptr[index] == cp_nop_packet(1)) &&
+			(rbptr[index + 1] == KGSL_CONTEXT_TO_MEM_IDENTIFIER))
 			break;
 	}
 
diff --git a/drivers/gpu/msm/kgsl.h b/drivers/gpu/msm/kgsl.h
index 5f3d2d0..5212d0f 100644
--- a/drivers/gpu/msm/kgsl.h
+++ b/drivers/gpu/msm/kgsl.h
@@ -208,17 +208,25 @@
 	}
 	return 0;
 }
+
+static inline void *kgsl_memdesc_map(struct kgsl_memdesc *memdesc)
+{
+	if (memdesc->hostptr == NULL && memdesc->ops->map_kernel_mem)
+		memdesc->ops->map_kernel_mem(memdesc);
+
+	return memdesc->hostptr;
+}
+
 static inline uint8_t *kgsl_gpuaddr_to_vaddr(struct kgsl_memdesc *memdesc,
 					     unsigned int gpuaddr)
 {
-	if (memdesc->gpuaddr == 0 ||
-		gpuaddr < memdesc->gpuaddr ||
-		gpuaddr >= (memdesc->gpuaddr + memdesc->size) ||
-		(NULL == memdesc->hostptr && memdesc->ops->map_kernel_mem &&
-			memdesc->ops->map_kernel_mem(memdesc)))
-			return NULL;
+	void *hostptr = NULL;
 
-	return memdesc->hostptr + (gpuaddr - memdesc->gpuaddr);
+	if ((gpuaddr >= memdesc->gpuaddr) &&
+		(gpuaddr < (memdesc->gpuaddr + memdesc->size)))
+		hostptr = kgsl_memdesc_map(memdesc);
+
+	return hostptr != NULL ? hostptr + (gpuaddr - memdesc->gpuaddr) : NULL;
 }
 
 static inline int timestamp_cmp(unsigned int new, unsigned int old)
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index 553dc60..3efafee 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -334,6 +334,12 @@
 		}
 	}
 
+	if (kgsl_memdesc_map(&entry->memdesc) == NULL) {
+		KGSL_DRV_ERR(device, "Unable to map GPU buffer %X\n",
+				gpuaddr);
+		return 0;
+	}
+
 	obj = kzalloc(sizeof(*obj), GFP_KERNEL);
 
 	if (obj == NULL) {