xref: /linux/drivers/gpu/drm/etnaviv/etnaviv_dump.c (revision a8c21a5451d831e67b7a6fb910f9ca8bc7b43554)
1*a8c21a54SThe etnaviv authors /*
2*a8c21a54SThe etnaviv authors  * Copyright (C) 2015 Etnaviv Project
3*a8c21a54SThe etnaviv authors  *
4*a8c21a54SThe etnaviv authors  * This program is free software; you can redistribute it and/or modify it
5*a8c21a54SThe etnaviv authors  * under the terms of the GNU General Public License version 2 as published by
6*a8c21a54SThe etnaviv authors  * the Free Software Foundation.
7*a8c21a54SThe etnaviv authors  *
8*a8c21a54SThe etnaviv authors  * This program is distributed in the hope that it will be useful, but WITHOUT
9*a8c21a54SThe etnaviv authors  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10*a8c21a54SThe etnaviv authors  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
11*a8c21a54SThe etnaviv authors  * more details.
12*a8c21a54SThe etnaviv authors  *
13*a8c21a54SThe etnaviv authors  * You should have received a copy of the GNU General Public License along with
14*a8c21a54SThe etnaviv authors  * this program.  If not, see <http://www.gnu.org/licenses/>.
15*a8c21a54SThe etnaviv authors  */
16*a8c21a54SThe etnaviv authors 
17*a8c21a54SThe etnaviv authors #include <linux/devcoredump.h>
18*a8c21a54SThe etnaviv authors #include "etnaviv_dump.h"
19*a8c21a54SThe etnaviv authors #include "etnaviv_gem.h"
20*a8c21a54SThe etnaviv authors #include "etnaviv_gpu.h"
21*a8c21a54SThe etnaviv authors #include "etnaviv_mmu.h"
22*a8c21a54SThe etnaviv authors #include "state.xml.h"
23*a8c21a54SThe etnaviv authors #include "state_hi.xml.h"
24*a8c21a54SThe etnaviv authors 
25*a8c21a54SThe etnaviv authors struct core_dump_iterator {
26*a8c21a54SThe etnaviv authors 	void *start;
27*a8c21a54SThe etnaviv authors 	struct etnaviv_dump_object_header *hdr;
28*a8c21a54SThe etnaviv authors 	void *data;
29*a8c21a54SThe etnaviv authors };
30*a8c21a54SThe etnaviv authors 
31*a8c21a54SThe etnaviv authors static const unsigned short etnaviv_dump_registers[] = {
32*a8c21a54SThe etnaviv authors 	VIVS_HI_AXI_STATUS,
33*a8c21a54SThe etnaviv authors 	VIVS_HI_CLOCK_CONTROL,
34*a8c21a54SThe etnaviv authors 	VIVS_HI_IDLE_STATE,
35*a8c21a54SThe etnaviv authors 	VIVS_HI_AXI_CONFIG,
36*a8c21a54SThe etnaviv authors 	VIVS_HI_INTR_ENBL,
37*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_IDENTITY,
38*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_FEATURE,
39*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_MODEL,
40*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_REV,
41*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_DATE,
42*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_TIME,
43*a8c21a54SThe etnaviv authors 	VIVS_HI_CHIP_MINOR_FEATURE_0,
44*a8c21a54SThe etnaviv authors 	VIVS_HI_CACHE_CONTROL,
45*a8c21a54SThe etnaviv authors 	VIVS_HI_AXI_CONTROL,
46*a8c21a54SThe etnaviv authors 	VIVS_PM_POWER_CONTROLS,
47*a8c21a54SThe etnaviv authors 	VIVS_PM_MODULE_CONTROLS,
48*a8c21a54SThe etnaviv authors 	VIVS_PM_MODULE_STATUS,
49*a8c21a54SThe etnaviv authors 	VIVS_PM_PULSE_EATER,
50*a8c21a54SThe etnaviv authors 	VIVS_MC_MMU_FE_PAGE_TABLE,
51*a8c21a54SThe etnaviv authors 	VIVS_MC_MMU_TX_PAGE_TABLE,
52*a8c21a54SThe etnaviv authors 	VIVS_MC_MMU_PE_PAGE_TABLE,
53*a8c21a54SThe etnaviv authors 	VIVS_MC_MMU_PEZ_PAGE_TABLE,
54*a8c21a54SThe etnaviv authors 	VIVS_MC_MMU_RA_PAGE_TABLE,
55*a8c21a54SThe etnaviv authors 	VIVS_MC_DEBUG_MEMORY,
56*a8c21a54SThe etnaviv authors 	VIVS_MC_MEMORY_BASE_ADDR_RA,
57*a8c21a54SThe etnaviv authors 	VIVS_MC_MEMORY_BASE_ADDR_FE,
58*a8c21a54SThe etnaviv authors 	VIVS_MC_MEMORY_BASE_ADDR_TX,
59*a8c21a54SThe etnaviv authors 	VIVS_MC_MEMORY_BASE_ADDR_PEZ,
60*a8c21a54SThe etnaviv authors 	VIVS_MC_MEMORY_BASE_ADDR_PE,
61*a8c21a54SThe etnaviv authors 	VIVS_MC_MEMORY_TIMING_CONTROL,
62*a8c21a54SThe etnaviv authors 	VIVS_MC_BUS_CONFIG,
63*a8c21a54SThe etnaviv authors 	VIVS_FE_DMA_STATUS,
64*a8c21a54SThe etnaviv authors 	VIVS_FE_DMA_DEBUG_STATE,
65*a8c21a54SThe etnaviv authors 	VIVS_FE_DMA_ADDRESS,
66*a8c21a54SThe etnaviv authors 	VIVS_FE_DMA_LOW,
67*a8c21a54SThe etnaviv authors 	VIVS_FE_DMA_HIGH,
68*a8c21a54SThe etnaviv authors 	VIVS_FE_AUTO_FLUSH,
69*a8c21a54SThe etnaviv authors };
70*a8c21a54SThe etnaviv authors 
71*a8c21a54SThe etnaviv authors static void etnaviv_core_dump_header(struct core_dump_iterator *iter,
72*a8c21a54SThe etnaviv authors 	u32 type, void *data_end)
73*a8c21a54SThe etnaviv authors {
74*a8c21a54SThe etnaviv authors 	struct etnaviv_dump_object_header *hdr = iter->hdr;
75*a8c21a54SThe etnaviv authors 
76*a8c21a54SThe etnaviv authors 	hdr->magic = cpu_to_le32(ETDUMP_MAGIC);
77*a8c21a54SThe etnaviv authors 	hdr->type = cpu_to_le32(type);
78*a8c21a54SThe etnaviv authors 	hdr->file_offset = cpu_to_le32(iter->data - iter->start);
79*a8c21a54SThe etnaviv authors 	hdr->file_size = cpu_to_le32(data_end - iter->data);
80*a8c21a54SThe etnaviv authors 
81*a8c21a54SThe etnaviv authors 	iter->hdr++;
82*a8c21a54SThe etnaviv authors 	iter->data += hdr->file_size;
83*a8c21a54SThe etnaviv authors }
84*a8c21a54SThe etnaviv authors 
85*a8c21a54SThe etnaviv authors static void etnaviv_core_dump_registers(struct core_dump_iterator *iter,
86*a8c21a54SThe etnaviv authors 	struct etnaviv_gpu *gpu)
87*a8c21a54SThe etnaviv authors {
88*a8c21a54SThe etnaviv authors 	struct etnaviv_dump_registers *reg = iter->data;
89*a8c21a54SThe etnaviv authors 	unsigned int i;
90*a8c21a54SThe etnaviv authors 
91*a8c21a54SThe etnaviv authors 	for (i = 0; i < ARRAY_SIZE(etnaviv_dump_registers); i++, reg++) {
92*a8c21a54SThe etnaviv authors 		reg->reg = etnaviv_dump_registers[i];
93*a8c21a54SThe etnaviv authors 		reg->value = gpu_read(gpu, etnaviv_dump_registers[i]);
94*a8c21a54SThe etnaviv authors 	}
95*a8c21a54SThe etnaviv authors 
96*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_header(iter, ETDUMP_BUF_REG, reg);
97*a8c21a54SThe etnaviv authors }
98*a8c21a54SThe etnaviv authors 
99*a8c21a54SThe etnaviv authors static void etnaviv_core_dump_mmu(struct core_dump_iterator *iter,
100*a8c21a54SThe etnaviv authors 	struct etnaviv_gpu *gpu, size_t mmu_size)
101*a8c21a54SThe etnaviv authors {
102*a8c21a54SThe etnaviv authors 	etnaviv_iommu_dump(gpu->mmu, iter->data);
103*a8c21a54SThe etnaviv authors 
104*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_header(iter, ETDUMP_BUF_MMU, iter->data + mmu_size);
105*a8c21a54SThe etnaviv authors }
106*a8c21a54SThe etnaviv authors 
107*a8c21a54SThe etnaviv authors static void etnaviv_core_dump_mem(struct core_dump_iterator *iter, u32 type,
108*a8c21a54SThe etnaviv authors 	void *ptr, size_t size, u64 iova)
109*a8c21a54SThe etnaviv authors {
110*a8c21a54SThe etnaviv authors 	memcpy(iter->data, ptr, size);
111*a8c21a54SThe etnaviv authors 
112*a8c21a54SThe etnaviv authors 	iter->hdr->iova = cpu_to_le64(iova);
113*a8c21a54SThe etnaviv authors 
114*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_header(iter, type, iter->data + size);
115*a8c21a54SThe etnaviv authors }
116*a8c21a54SThe etnaviv authors 
117*a8c21a54SThe etnaviv authors void etnaviv_core_dump(struct etnaviv_gpu *gpu)
118*a8c21a54SThe etnaviv authors {
119*a8c21a54SThe etnaviv authors 	struct core_dump_iterator iter;
120*a8c21a54SThe etnaviv authors 	struct etnaviv_vram_mapping *vram;
121*a8c21a54SThe etnaviv authors 	struct etnaviv_gem_object *obj;
122*a8c21a54SThe etnaviv authors 	struct etnaviv_cmdbuf *cmd;
123*a8c21a54SThe etnaviv authors 	unsigned int n_obj, n_bomap_pages;
124*a8c21a54SThe etnaviv authors 	size_t file_size, mmu_size;
125*a8c21a54SThe etnaviv authors 	__le64 *bomap, *bomap_start;
126*a8c21a54SThe etnaviv authors 
127*a8c21a54SThe etnaviv authors 	mmu_size = etnaviv_iommu_dump_size(gpu->mmu);
128*a8c21a54SThe etnaviv authors 
129*a8c21a54SThe etnaviv authors 	/* We always dump registers, mmu, ring and end marker */
130*a8c21a54SThe etnaviv authors 	n_obj = 4;
131*a8c21a54SThe etnaviv authors 	n_bomap_pages = 0;
132*a8c21a54SThe etnaviv authors 	file_size = ARRAY_SIZE(etnaviv_dump_registers) *
133*a8c21a54SThe etnaviv authors 			sizeof(struct etnaviv_dump_registers) +
134*a8c21a54SThe etnaviv authors 		    mmu_size + gpu->buffer->size;
135*a8c21a54SThe etnaviv authors 
136*a8c21a54SThe etnaviv authors 	/* Add in the active command buffers */
137*a8c21a54SThe etnaviv authors 	list_for_each_entry(cmd, &gpu->active_cmd_list, node) {
138*a8c21a54SThe etnaviv authors 		file_size += cmd->size;
139*a8c21a54SThe etnaviv authors 		n_obj++;
140*a8c21a54SThe etnaviv authors 	}
141*a8c21a54SThe etnaviv authors 
142*a8c21a54SThe etnaviv authors 	/* Add in the active buffer objects */
143*a8c21a54SThe etnaviv authors 	list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {
144*a8c21a54SThe etnaviv authors 		if (!vram->use)
145*a8c21a54SThe etnaviv authors 			continue;
146*a8c21a54SThe etnaviv authors 
147*a8c21a54SThe etnaviv authors 		obj = vram->object;
148*a8c21a54SThe etnaviv authors 		file_size += obj->base.size;
149*a8c21a54SThe etnaviv authors 		n_bomap_pages += obj->base.size >> PAGE_SHIFT;
150*a8c21a54SThe etnaviv authors 		n_obj++;
151*a8c21a54SThe etnaviv authors 	}
152*a8c21a54SThe etnaviv authors 
153*a8c21a54SThe etnaviv authors 	/* If we have any buffer objects, add a bomap object */
154*a8c21a54SThe etnaviv authors 	if (n_bomap_pages) {
155*a8c21a54SThe etnaviv authors 		file_size += n_bomap_pages * sizeof(__le64);
156*a8c21a54SThe etnaviv authors 		n_obj++;
157*a8c21a54SThe etnaviv authors 	}
158*a8c21a54SThe etnaviv authors 
159*a8c21a54SThe etnaviv authors 	/* Add the size of the headers */
160*a8c21a54SThe etnaviv authors 	file_size += sizeof(*iter.hdr) * n_obj;
161*a8c21a54SThe etnaviv authors 
162*a8c21a54SThe etnaviv authors 	/* Allocate the file in vmalloc memory, it's likely to be big */
163*a8c21a54SThe etnaviv authors 	iter.start = vmalloc(file_size);
164*a8c21a54SThe etnaviv authors 	if (!iter.start) {
165*a8c21a54SThe etnaviv authors 		dev_warn(gpu->dev, "failed to allocate devcoredump file\n");
166*a8c21a54SThe etnaviv authors 		return;
167*a8c21a54SThe etnaviv authors 	}
168*a8c21a54SThe etnaviv authors 
169*a8c21a54SThe etnaviv authors 	/* Point the data member after the headers */
170*a8c21a54SThe etnaviv authors 	iter.hdr = iter.start;
171*a8c21a54SThe etnaviv authors 	iter.data = &iter.hdr[n_obj];
172*a8c21a54SThe etnaviv authors 
173*a8c21a54SThe etnaviv authors 	memset(iter.hdr, 0, iter.data - iter.start);
174*a8c21a54SThe etnaviv authors 
175*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_registers(&iter, gpu);
176*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_mmu(&iter, gpu, mmu_size);
177*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_mem(&iter, ETDUMP_BUF_RING, gpu->buffer->vaddr,
178*a8c21a54SThe etnaviv authors 			      gpu->buffer->size, gpu->buffer->paddr);
179*a8c21a54SThe etnaviv authors 
180*a8c21a54SThe etnaviv authors 	list_for_each_entry(cmd, &gpu->active_cmd_list, node)
181*a8c21a54SThe etnaviv authors 		etnaviv_core_dump_mem(&iter, ETDUMP_BUF_CMD, cmd->vaddr,
182*a8c21a54SThe etnaviv authors 				      cmd->size, cmd->paddr);
183*a8c21a54SThe etnaviv authors 
184*a8c21a54SThe etnaviv authors 	/* Reserve space for the bomap */
185*a8c21a54SThe etnaviv authors 	if (n_bomap_pages) {
186*a8c21a54SThe etnaviv authors 		bomap_start = bomap = iter.data;
187*a8c21a54SThe etnaviv authors 		memset(bomap, 0, sizeof(*bomap) * n_bomap_pages);
188*a8c21a54SThe etnaviv authors 		etnaviv_core_dump_header(&iter, ETDUMP_BUF_BOMAP,
189*a8c21a54SThe etnaviv authors 					 bomap + n_bomap_pages);
190*a8c21a54SThe etnaviv authors 	} else {
191*a8c21a54SThe etnaviv authors 		/* Silence warning */
192*a8c21a54SThe etnaviv authors 		bomap_start = bomap = NULL;
193*a8c21a54SThe etnaviv authors 	}
194*a8c21a54SThe etnaviv authors 
195*a8c21a54SThe etnaviv authors 	list_for_each_entry(vram, &gpu->mmu->mappings, mmu_node) {
196*a8c21a54SThe etnaviv authors 		struct page **pages;
197*a8c21a54SThe etnaviv authors 		void *vaddr;
198*a8c21a54SThe etnaviv authors 
199*a8c21a54SThe etnaviv authors 		if (vram->use == 0)
200*a8c21a54SThe etnaviv authors 			continue;
201*a8c21a54SThe etnaviv authors 
202*a8c21a54SThe etnaviv authors 		obj = vram->object;
203*a8c21a54SThe etnaviv authors 
204*a8c21a54SThe etnaviv authors 		pages = etnaviv_gem_get_pages(obj);
205*a8c21a54SThe etnaviv authors 		if (pages) {
206*a8c21a54SThe etnaviv authors 			int j;
207*a8c21a54SThe etnaviv authors 
208*a8c21a54SThe etnaviv authors 			iter.hdr->data[0] = bomap - bomap_start;
209*a8c21a54SThe etnaviv authors 
210*a8c21a54SThe etnaviv authors 			for (j = 0; j < obj->base.size >> PAGE_SHIFT; j++)
211*a8c21a54SThe etnaviv authors 				*bomap++ = cpu_to_le64(page_to_phys(*pages++));
212*a8c21a54SThe etnaviv authors 		}
213*a8c21a54SThe etnaviv authors 
214*a8c21a54SThe etnaviv authors 		iter.hdr->iova = cpu_to_le64(vram->iova);
215*a8c21a54SThe etnaviv authors 
216*a8c21a54SThe etnaviv authors 		vaddr = etnaviv_gem_vaddr(&obj->base);
217*a8c21a54SThe etnaviv authors 		if (vaddr && !IS_ERR(vaddr))
218*a8c21a54SThe etnaviv authors 			memcpy(iter.data, vaddr, obj->base.size);
219*a8c21a54SThe etnaviv authors 
220*a8c21a54SThe etnaviv authors 		etnaviv_core_dump_header(&iter, ETDUMP_BUF_BO, iter.data +
221*a8c21a54SThe etnaviv authors 					 obj->base.size);
222*a8c21a54SThe etnaviv authors 	}
223*a8c21a54SThe etnaviv authors 
224*a8c21a54SThe etnaviv authors 	etnaviv_core_dump_header(&iter, ETDUMP_BUF_END, iter.data);
225*a8c21a54SThe etnaviv authors 
226*a8c21a54SThe etnaviv authors 	dev_coredumpv(gpu->dev, iter.start, iter.data - iter.start, GFP_KERNEL);
227*a8c21a54SThe etnaviv authors }
228