xref: /aosp_15_r20/external/igt-gpu-tools/tools/intel_gtt.c (revision d83cc019efdc2edc6c4b16e9034a3ceb8d35d77c)
1 /*
2  * Copyright © 2008 Intel Corporation
3  *
4  * Permission is hereby granted, free of charge, to any person obtaining a
5  * copy of this software and associated documentation files (the "Software"),
6  * to deal in the Software without restriction, including without limitation
7  * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8  * and/or sell copies of the Software, and to permit persons to whom the
9  * Software is furnished to do so, subject to the following conditions:
10  *
11  * The above copyright notice and this permission notice (including the next
12  * paragraph) shall be included in all copies or substantial portions of the
13  * Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
18  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20  * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21  * DEALINGS IN THE SOFTWARE.
22  *
23  * Authors:
24  *    Eric Anholt <[email protected]>
25  *
26  */
27 
28 #define __STDC_FORMAT_MACROS
29 #include <inttypes.h>
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <string.h>
33 #include <stdarg.h>
34 #include <pciaccess.h>
35 #include <unistd.h>
36 
37 #include "intel_io.h"
38 #include "intel_chipset.h"
39 
40 #define KB(x) ((x) * 1024)
41 #define MB(x) ((x) * 1024 * 1024)
42 unsigned char *gtt;
43 uint32_t devid;
44 
45 typedef uint32_t gen6_gtt_pte_t;
46 typedef uint64_t gen8_gtt_pte_t;
47 
gen6_gtt_pte(const unsigned i)48 static gen6_gtt_pte_t gen6_gtt_pte(const unsigned i)
49 {
50 	return *((volatile gen6_gtt_pte_t *)(gtt) + i);
51 }
52 
gen8_gtt_pte(const unsigned i)53 static gen8_gtt_pte_t gen8_gtt_pte(const unsigned i)
54 {
55 	return *((volatile gen8_gtt_pte_t *)(gtt) + i);
56 }
57 
ingtt(const unsigned offset)58 static uint64_t ingtt(const unsigned offset)
59 {
60 	if (intel_gen(devid) < 8)
61 		return gen6_gtt_pte(offset/KB(4));
62 
63 	return gen8_gtt_pte(offset/KB(4));
64 }
65 
get_phys(uint32_t pt_offset)66 static uint64_t get_phys(uint32_t pt_offset)
67 {
68 	uint64_t pae = 0;
69 	uint64_t phys = ingtt(pt_offset);
70 
71 	if (intel_gen(devid) < 4 && !IS_G33(devid))
72 		return phys & ~0xfff;
73 
74 	switch (intel_gen(devid)) {
75 		case 3:
76 		case 4:
77 		case 5:
78 			pae = (phys & 0xf0) << 28;
79 			break;
80 		case 6:
81 		case 7:
82 			if (IS_HASWELL(devid))
83 				pae = (phys & 0x7f0) << 28;
84 			else
85 				pae = (phys & 0xff0) << 28;
86 			break;
87 		case 8:
88 		case 9:
89 			phys = phys & 0x7ffffff000;
90 			break;
91 		default:
92 			fprintf(stderr, "Unsupported platform\n");
93 			exit(-1);
94 	}
95 
96 	return (phys | pae) & ~0xfff;
97 }
98 
pte_dump(int size,uint32_t offset)99 static void pte_dump(int size, uint32_t offset) {
100 	int pte_size;
101 	int entries;
102 	unsigned int i;
103 
104 	/* Want to print 4 ptes at a time (4b PTE assumed). */
105 	if (size % 16)
106 		size = (size + 16) & ~0xffff;
107 
108 	if (intel_gen(devid) < 8)
109 		pte_size = 4;
110 	else
111 		pte_size = 8;
112 
113 	entries = size / pte_size;
114 
115 	printf("GTT offset   |                 %d PTEs (%d MB)\n", entries,
116 	       entries * 4096 / 1024 / 1024);
117 	printf("----------------------------------------------------------\n");
118 
119 	for (i = 0; i < entries; i += 4) {
120 		if (intel_gen(devid) < 8) {
121 			printf("  0x%08x | 0x%08x 0x%08x 0x%08x 0x%08x\n",
122 			       KB(4 * i),
123 			       gen6_gtt_pte(i + 0),
124 			       gen6_gtt_pte(i + 1),
125 			       gen6_gtt_pte(i + 2),
126 			       gen6_gtt_pte(i + 3) );
127 		} else {
128 			printf("  0x%08x | 0x%016" PRIx64 " 0x%016" PRIx64
129 			       " 0x%016" PRIx64 " 0x%016" PRIx64 " \n",
130 			       KB(4 * i),
131 			       gen8_gtt_pte(i + 0),
132 			       gen8_gtt_pte(i + 1),
133 			       gen8_gtt_pte(i + 2),
134 			       gen8_gtt_pte(i + 3) );
135 		}
136 	}
137 }
138 
main(int argc,char ** argv)139 int main(int argc, char **argv)
140 {
141 	struct pci_device *pci_dev;
142 	unsigned int start, gtt_size;
143 	int flag[] = {
144 		PCI_DEV_MAP_FLAG_WRITE_COMBINE,
145 		PCI_DEV_MAP_FLAG_WRITABLE,
146 		0
147 	}, f;
148 
149 	pci_dev = intel_get_pci_device();
150 	devid = pci_dev->device_id;
151 
152 	if (IS_GEN2(devid)) {
153 		printf("Unsupported chipset for gtt dumper\n");
154 		exit(1);
155 	}
156 
157 	for (f = 0; flag[f] != 0; f++) {
158 		if (IS_GEN3(devid)) {
159 			/* 915/945 chips has GTT range in bar 3 */
160 			if (pci_device_map_range(pci_dev,
161 						 pci_dev->regions[3].base_addr,
162 						 pci_dev->regions[3].size,
163 						 flag[f],
164 						 (void **)&gtt) == 0)
165 				break;
166 		} else {
167 			unsigned offset;
168 
169 			offset = pci_dev->regions[0].size / 2;
170 
171 			if (IS_GEN4(devid))
172 				offset = KB(512);
173 
174 			if (pci_device_map_range(pci_dev,
175 						 pci_dev->regions[0].base_addr + offset,
176 						 offset,
177 						 flag[f],
178 						 (void **)&gtt) == 0)
179 				break;
180 		}
181 	}
182 	if (flag[f] == 0) {
183 		printf("Failed to map gtt\n");
184 		exit(1);
185 	}
186 
187 	gtt_size = pci_dev->regions[0].size / 2;
188 	if (argc > 1 && !strncmp("-d", argv[1], 2)) {
189 		pte_dump(gtt_size, 0);
190 		return 0;
191 	}
192 
193 	for (start = 0; start < gtt_size; start += KB(4)) {
194 		uint64_t start_phys = get_phys(start);
195 		uint32_t end;
196 		int constant_length = 0;
197 		int linear_length = 0;
198 
199 		/* Check if it's a linear sequence */
200 		for (end = start + KB(4); end < gtt_size; end += KB(4)) {
201 			uint64_t end_phys = get_phys(end);
202 			if (end_phys == start_phys + (end - start))
203 				linear_length++;
204 			else
205 				break;
206 		}
207 		if (linear_length > 0) {
208 			printf("0x%08x - 0x%08x: linear from "
209 			       "0x%" PRIx64 " to 0x%" PRIx64 "\n",
210 			       start, end - KB(4),
211 			       start_phys, start_phys + (end - start) - KB(4));
212 			start = end - KB(4);
213 			continue;
214 		}
215 
216 		/* Check if it's a constant sequence */
217 		for (end = start + KB(4); end < gtt_size; end += KB(4)) {
218 			uint64_t end_phys = get_phys(end);
219 			if (end_phys == start_phys)
220 				constant_length++;
221 			else
222 				break;
223 		}
224 		if (constant_length > 0) {
225 			printf("0x%08x - 0x%08x: constant 0x%" PRIx64 "\n",
226 			       start, end - KB(4), start_phys);
227 			start = end - KB(4);
228 			continue;
229 		}
230 
231 		printf("0x%08x: 0x%" PRIx64 "\n", start, start_phys);
232 	}
233 
234 	return 0;
235 }
236