msm: kgsl: Make the snapshot dumper more tolerant of corrupted IBs
If there are a lot of sequential commands in the ringbuffer for the
same context there is a high probablity that some of the memory
for the older commands has been reused and so the contents may not
be reliable. Increase robustness by making sure we don't parse the
same IB over and over again and be more tolerant of errors and
strange sizes.
Change-Id: Ic0dedbade8504ea258ceea40593cb75e7d6211c8
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 08a01b0..93be980 100644
--- a/drivers/gpu/msm/adreno_snapshot.c
+++ b/drivers/gpu/msm/adreno_snapshot.c
@@ -328,8 +328,8 @@
ret = kgsl_snapshot_get_object(device, ptbase,
sp_vs_pvt_mem_addr, 8192,
SNAPSHOT_GPU_OBJECT_GENERIC);
-
snapshot_frozen_objsize += ret;
+ sp_vs_pvt_mem_addr = 0;
}
if (sp_fs_pvt_mem_addr) {
@@ -337,6 +337,7 @@
sp_fs_pvt_mem_addr, 8192,
SNAPSHOT_GPU_OBJECT_GENERIC);
snapshot_frozen_objsize += ret;
+ sp_fs_pvt_mem_addr = 0;
}
/* Finally: VBOs */
@@ -359,7 +360,13 @@
0, SNAPSHOT_GPU_OBJECT_GENERIC);
snapshot_frozen_objsize += ret;
}
+
+ vbo[i].base = 0;
+ vbo[i].stride = 0;
}
+
+ vfd_control_0 = 0;
+ vfd_index_max = 0;
}
/*
@@ -473,21 +480,33 @@
unsigned int gpuaddr, unsigned int dwords)
{
int i, ret, rem = dwords;
- unsigned int *src = (unsigned int *) adreno_convertaddr(device, ptbase,
- gpuaddr, dwords << 2);
+ unsigned int *src;
+
+ /*
+ * If the object is already in the list, we don't need to parse it again
+ */
+
+ if (kgsl_snapshot_have_object(device, ptbase, gpuaddr, dwords << 2))
+ return;
+
+ src = (unsigned int *) adreno_convertaddr(device, ptbase, gpuaddr,
+ dwords << 2);
if (src == NULL)
return;
- for (i = 0; rem != 0; rem--, i++) {
+ for (i = 0; rem > 0; rem--, i++) {
int pktsize;
+ /* If the packet isn't a type 1 or a type 3, then don't bother
+ * parsing it - it is likely corrupted */
+
if (!pkt_is_type0(src[i]) && !pkt_is_type3(src[i]))
- continue;
+ break;
pktsize = type3_pkt_size(src[i]);
- if ((pktsize + 1) > rem)
+ if (!pktsize || (pktsize + 1) > rem)
break;
if (pkt_is_type3(src[i])) {
@@ -650,27 +669,11 @@
*data = rbptr[index];
/*
- * Sometimes the rptr is located in the middle of a packet.
- * try to adust for that by modifying the rptr to match a
- * packet boundary. Unfortunately for us, it is hard to tell
- * which dwords are legitimate type0 header and which are just
- * random data so only do the adjustments for type3 packets
- */
-
- if (pkt_is_type3(rbptr[index])) {
- unsigned int pktsize =
- type3_pkt_size(rbptr[index]);
- if (index + pktsize > rptr)
- rptr = (index + pktsize) %
- rb->sizedwords;
- }
-
- /*
* Only parse IBs between the start and the rptr or the next
* context switch, whichever comes first
*/
- if (index == ib_parse_start)
+ if (parse_ibs == 0 && index == ib_parse_start)
parse_ibs = 1;
else if (index == rptr || adreno_rb_ctxtswitch(&rbptr[index]))
parse_ibs = 0;
diff --git a/drivers/gpu/msm/kgsl_snapshot.c b/drivers/gpu/msm/kgsl_snapshot.c
index a2ab5b1..0bfcfd8 100644
--- a/drivers/gpu/msm/kgsl_snapshot.c
+++ b/drivers/gpu/msm/kgsl_snapshot.c
@@ -289,6 +289,32 @@
kfree(obj);
}
+/* ksgl_snapshot_have_object - Return 1 if the object has been processed
+ *@device - the device that is being snapshotted
+ * @ptbase - the pagetable base of the object to freeze
+ * @gpuaddr - The gpu address of the object to freeze
+ * @size - the size of the object (may not always be the size of the region)
+ *
+ * Return 1 if the object is already in the list - this can save us from
+ * having to parse the sme thing over again.
+*/
+int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase,
+ unsigned int gpuaddr, unsigned int size)
+{
+ struct kgsl_snapshot_object *obj;
+
+ list_for_each_entry(obj, &device->snapshot_obj_list, node) {
+ if (obj->ptbase != ptbase)
+ continue;
+
+ if ((gpuaddr >= obj->gpuaddr) &&
+ ((gpuaddr + size) <= (obj->gpuaddr + obj->size)))
+ return 1;
+ }
+
+ return 0;
+}
+
/* kgsl_snapshot_get_object - Mark a GPU buffer to be frozen
* @device - the device that is being snapshotted
* @ptbase - the pagetable base of the object to freeze
diff --git a/drivers/gpu/msm/kgsl_snapshot.h b/drivers/gpu/msm/kgsl_snapshot.h
index 6d81bcf..bc29863 100644
--- a/drivers/gpu/msm/kgsl_snapshot.h
+++ b/drivers/gpu/msm/kgsl_snapshot.h
@@ -311,5 +311,8 @@
int kgsl_snapshot_get_object(struct kgsl_device *device, unsigned int ptbase,
unsigned int gpuaddr, unsigned int size, unsigned int type);
+int kgsl_snapshot_have_object(struct kgsl_device *device, unsigned int ptbase,
+ unsigned int gpuaddr, unsigned int size);
+
#endif
#endif