blob: cc3f3e781cd732b584a45f9890b670a3e46e2f9e [file] [log] [blame]
Jordan Crouse156cfbc2012-01-24 09:32:04 -07001/* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
2 *
3 * This program is free software; you can redistribute it and/or modify
4 * it under the terms of the GNU General Public License version 2 and
5 * only version 2 as published by the Free Software Foundation.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU General Public License for more details.
11 */
12
13#include "kgsl.h"
14#include "kgsl_sharedmem.h"
15#include "kgsl_snapshot.h"
16
17#include "adreno.h"
18#include "adreno_pm4types.h"
19#include "a2xx_reg.h"
20
21/* Number of dwords of ringbuffer history to record */
22#define NUM_DWORDS_OF_RINGBUFFER_HISTORY 100
23
24/* Maintain a list of the objects we see during parsing */
25
26#define SNAPSHOT_OBJ_BUFSIZE 64
27
28#define SNAPSHOT_OBJ_TYPE_IB 0
29
30static struct kgsl_snapshot_obj {
31 int type;
32 uint32_t gpuaddr;
33 uint32_t ptbase;
34 void *ptr;
35 int dwords;
36} objbuf[SNAPSHOT_OBJ_BUFSIZE];
37
38/* Pointer to the next open entry in the object list */
39static int objbufptr;
40
41/* Push a new buffer object onto the list */
42static void push_object(struct kgsl_device *device, int type, uint32_t ptbase,
43 uint32_t gpuaddr, int dwords)
44{
45 int index;
46 void *ptr;
47
48 /* Go through the list and see that object has already been seen */
49 for (index = 0; index < objbufptr; index++) {
50 if (objbuf[index].gpuaddr == gpuaddr &&
51 objbuf[index].ptbase == ptbase)
52 return;
53 }
54
55 if (objbufptr == SNAPSHOT_OBJ_BUFSIZE) {
56 KGSL_DRV_ERR(device, "snapshot: too many snapshot objects\n");
57 return;
58 }
59
60 /*
61 * adreno_convertaddr verifies that the IB size is valid - at least in
62 * the context of it being smaller then the allocated memory space
63 */
64 ptr = adreno_convertaddr(device, ptbase, gpuaddr, dwords << 2);
65
66 if (ptr == NULL) {
67 KGSL_DRV_ERR(device,
68 "snapshot: Can't find GPU address for %x\n", gpuaddr);
69 return;
70 }
71
72 /* Put it on the list of things to parse */
73 objbuf[objbufptr].type = type;
74 objbuf[objbufptr].gpuaddr = gpuaddr;
75 objbuf[objbufptr].ptbase = ptbase;
76 objbuf[objbufptr].dwords = dwords;
77 objbuf[objbufptr++].ptr = ptr;
78}
79
80/* Snapshot the istore memory */
81static int snapshot_istore(struct kgsl_device *device, void *snapshot,
82 int remain, void *priv)
83{
84 struct kgsl_snapshot_istore *header = snapshot;
85 unsigned int *data = snapshot + sizeof(*header);
86 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
87 int count, i;
88
Jordan Crousec6b3a992012-02-04 10:23:51 -070089 count = adreno_dev->istore_size * adreno_dev->instruction_size;
Jordan Crouse156cfbc2012-01-24 09:32:04 -070090
91 if (remain < (count * 4) + sizeof(*header)) {
92 KGSL_DRV_ERR(device,
93 "snapshot: Not enough memory for the istore section");
94 return 0;
95 }
96
97 header->count = adreno_dev->istore_size;
98
99 for (i = 0; i < count; i++)
100 kgsl_regread(device, ADRENO_ISTORE_START + i, &data[i]);
101
102 return (count * 4) + sizeof(*header);
103}
104
105/* Snapshot the ringbuffer memory */
106static int snapshot_rb(struct kgsl_device *device, void *snapshot,
107 int remain, void *priv)
108{
109 struct kgsl_snapshot_rb *header = snapshot;
110 unsigned int *data = snapshot + sizeof(*header);
111 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
112 struct adreno_ringbuffer *rb = &adreno_dev->ringbuffer;
113 unsigned int rbbase, ptbase, rptr, *rbptr;
114 int start, stop, index;
115 int numitems, size;
116
117 /* Get the GPU address of the ringbuffer */
118 kgsl_regread(device, REG_CP_RB_BASE, &rbbase);
119
120 /* Get the physical address of the MMU pagetable */
121 ptbase = kgsl_mmu_get_current_ptbase(device);
122
123 /* Get the current read pointers for the RB */
124 kgsl_regread(device, REG_CP_RB_RPTR, &rptr);
125
126 /* start the dump at the rptr minus some history */
127 start = (int) rptr - NUM_DWORDS_OF_RINGBUFFER_HISTORY;
128 if (start < 0)
129 start += rb->sizedwords;
130
131 /*
132 * Stop the dump at the point where the software last wrote. Don't use
133 * the hardware value here on the chance that it didn't get properly
134 * updated
135 */
136
137 stop = (int) rb->wptr + 16;
138 if (stop > rb->sizedwords)
139 stop -= rb->sizedwords;
140
141 /* Set up the header for the section */
142
143 numitems = (stop > start) ? stop - start :
144 (rb->sizedwords - start) + stop;
145
146 size = (numitems << 2);
147
148 if (remain < size + sizeof(*header)) {
149 KGSL_DRV_ERR(device,
150 "snapshot: Not enough memory for the rb section");
151 return 0;
152 }
153
154 /* Write the sub-header for the section */
155 header->start = start;
156 header->end = stop;
157 header->wptr = rb->wptr;
158 header->rbsize = rb->sizedwords;
159 header->count = numitems;
160
161 index = start;
162 rbptr = rb->buffer_desc.hostptr;
163
164 /*
165 * Loop through the RB, copying the data and looking for indirect
166 * buffers and MMU pagetable changes
167 */
168
169 while (index != rb->wptr) {
170 *data = rbptr[index];
171
172 if (rbptr[index] == cp_type3_packet(CP_INDIRECT_BUFFER_PFD, 2))
173 push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
174 rbptr[index + 1], rbptr[index + 2]);
175
176 /*
177 * FIXME: Handle upcoming MMU pagetable changes, but only
178 * between the rptr and the wptr
179 */
180
181 index = index + 1;
182
183 if (index == rb->sizedwords)
184 index = 0;
185
186 data++;
187 }
188
189 /* Dump 16 dwords past the wptr, but don't bother interpeting it */
190
191 while (index != stop) {
192 *data = rbptr[index];
193 index = index + 1;
194
195 if (index == rb->sizedwords)
196 index = 0;
197
198 data++;
199 }
200
201 /* Return the size of the section */
202 return size + sizeof(*header);
203}
204
205/* Snapshot the memory for an indirect buffer */
206static int snapshot_ib(struct kgsl_device *device, void *snapshot,
207 int remain, void *priv)
208{
209 struct kgsl_snapshot_ib *header = snapshot;
210 struct kgsl_snapshot_obj *obj = priv;
211 unsigned int *src = obj->ptr;
212 unsigned int *dst = snapshot + sizeof(*header);
213 int i;
214
215 if (remain < (obj->dwords << 2) + sizeof(*header)) {
216 KGSL_DRV_ERR(device,
217 "snapshot: Not enough memory for the ib section");
218 return 0;
219 }
220
221 /* Write the sub-header for the section */
222 header->gpuaddr = obj->gpuaddr;
223 header->ptbase = obj->ptbase;
224 header->size = obj->dwords;
225
226 /* Write the contents of the ib */
227 for (i = 0; i < obj->dwords; i++) {
228 *dst = *src;
229 /* If another IB is discovered, then push it on the list too */
230
231 if (*src == cp_type3_packet(CP_INDIRECT_BUFFER_PFD, 2)) {
232 push_object(device, SNAPSHOT_OBJ_TYPE_IB, obj->ptbase,
233 *(src + 1), *(src + 2));
234 }
235
236 src++;
237 dst++;
238 }
239
240 return (obj->dwords << 2) + sizeof(*header);
241}
242
243/* Dump another item on the current pending list */
244static void *dump_object(struct kgsl_device *device, int obj, void *snapshot,
245 int *remain)
246{
247 switch (objbuf[obj].type) {
248 case SNAPSHOT_OBJ_TYPE_IB:
249 snapshot = kgsl_snapshot_add_section(device,
250 KGSL_SNAPSHOT_SECTION_IB, snapshot, remain,
251 snapshot_ib, &objbuf[obj]);
252 break;
253 default:
254 KGSL_DRV_ERR(device,
255 "snapshot: Invalid snapshot object type: %d\n",
256 objbuf[obj].type);
257 break;
258 }
259
260 return snapshot;
261}
262
263/* adreno_snapshot - Snapshot the Adreno GPU state
264 * @device - KGSL device to snapshot
265 * @snapshot - Pointer to the start of memory to write into
266 * @remain - A pointer to how many bytes of memory are remaining in the snapshot
267 * @hang - set if this snapshot was automatically triggered by a GPU hang
268 * This is a hook function called by kgsl_snapshot to snapshot the
269 * Adreno specific information for the GPU snapshot. In turn, this function
270 * calls the GPU specific snapshot function to get core specific information.
271 */
272
273void *adreno_snapshot(struct kgsl_device *device, void *snapshot, int *remain,
274 int hang)
275{
276 int i;
277 uint32_t ptbase, ibbase, ibsize;
278 struct adreno_device *adreno_dev = ADRENO_DEVICE(device);
279
280 /* Reset the list of objects */
281 objbufptr = 0;
282
283 /* Get the physical address of the MMU pagetable */
284 ptbase = kgsl_mmu_get_current_ptbase(device);
285
286 /* Dump the ringbuffer */
287 snapshot = kgsl_snapshot_add_section(device, KGSL_SNAPSHOT_SECTION_RB,
288 snapshot, remain, snapshot_rb, NULL);
289
290 /*
291 * Make sure that the IBs described in the CP registers are on the
292 * list of objects
293 */
294 kgsl_regread(device, REG_CP_IB1_BASE, &ibbase);
295 kgsl_regread(device, REG_CP_IB1_BUFSZ, &ibsize);
296
297 if (ibsize)
298 push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
299 ibbase, ibsize);
300
301 kgsl_regread(device, REG_CP_IB2_BASE, &ibbase);
302 kgsl_regread(device, REG_CP_IB2_BUFSZ, &ibsize);
303
304 if (ibsize)
305 push_object(device, SNAPSHOT_OBJ_TYPE_IB, ptbase,
306 ibbase, ibsize);
307
308 /*
309 * Go through the list of found objects and dump each one. As the IBs
310 * are parsed, more objects might be found, and objbufptr will increase
311 */
312 for (i = 0; i < objbufptr; i++)
313 snapshot = dump_object(device, i, snapshot, remain);
314
315 /*
316 * Only dump the istore on a hang - reading it on a running system
317 * has a non 0 chance of hanging the GPU
318 */
319
320 if (hang) {
321 snapshot = kgsl_snapshot_add_section(device,
322 KGSL_SNAPSHOT_SECTION_ISTORE, snapshot, remain,
323 snapshot_istore, NULL);
324 }
325
326 /* Add GPU specific sections - registers mainly, but other stuff too */
327 if (adreno_dev->gpudev->snapshot)
328 snapshot = adreno_dev->gpudev->snapshot(adreno_dev, snapshot,
329 remain, hang);
330
331 return snapshot;
332}