1 /*
2 * Copyright © 2020 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 DEALINGS
21 * IN THE SOFTWARE.
22 */
23
24 #include <getopt.h>
25 #include <inttypes.h>
26 #include <stdarg.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <string.h>
30
31 #include <sys/types.h>
32 #include <sys/stat.h>
33 #include <fcntl.h>
34 #include <unistd.h>
35
36 #include "util/libdrm.h"
37
38 #include "dev/intel_device_info.h"
39 #include "dev/intel_device_info_serialize.h"
40 #include "dev/intel_hwconfig.h"
41 #include "compiler/brw_compiler.h"
42
43 static int
error(char * fmt,...)44 error(char *fmt, ...)
45 {
46 va_list ap;
47 va_start(ap, fmt);
48 vfprintf(stderr, fmt, ap);
49 va_end(ap);
50
51 return EXIT_FAILURE;
52 }
53
54 static void
print_base_devinfo(const struct intel_device_info * devinfo)55 print_base_devinfo(const struct intel_device_info *devinfo)
56 {
57 fprintf(stdout, "devinfo struct size = %zu\n", sizeof(*devinfo));
58
59 fprintf(stdout, " name: %s\n", devinfo->name);
60 fprintf(stdout, " gen: %u\n", devinfo->ver);
61 fprintf(stdout, " PCI device id: 0x%x\n", devinfo->pci_device_id);
62 fprintf(stdout, " PCI domain: 0x%x\n", devinfo->pci_domain);
63 fprintf(stdout, " PCI bus: 0x%x\n", devinfo->pci_bus);
64 fprintf(stdout, " PCI dev: 0x%x\n", devinfo->pci_dev);
65 fprintf(stdout, " PCI function: 0x%x\n", devinfo->pci_func);
66 fprintf(stdout, " PCI revision id: 0x%x\n", devinfo->pci_revision_id);
67 fprintf(stdout, " revision: %u\n", devinfo->revision);
68
69 const char *subslice_name = devinfo->ver >= 12 ? "dualsubslice" : "subslice";
70 uint32_t n_s = 0, n_ss = 0, n_eus = 0;
71 for (unsigned s = 0; s < devinfo->max_slices; s++) {
72 n_s += (devinfo->slice_masks & (1u << s)) ? 1 : 0;
73 for (unsigned ss = 0; ss < devinfo->max_subslices_per_slice; ss++) {
74 fprintf(stdout, " slice%u.%s%u: ", s, subslice_name, ss);
75 if (intel_device_info_subslice_available(devinfo, s, ss)) {
76 n_ss++;
77 for (unsigned eu = 0; eu < devinfo->max_eus_per_subslice; eu++) {
78 n_eus += intel_device_info_eu_available(devinfo, s, ss, eu) ? 1 : 0;
79 fprintf(stdout, "%s", intel_device_info_eu_available(devinfo, s, ss, eu) ? "1" : "0");
80 }
81 } else {
82 fprintf(stdout, "fused");
83 }
84 fprintf(stdout, "\n");
85 }
86 }
87 for (uint32_t pp = 0; pp < ARRAY_SIZE(devinfo->ppipe_subslices); pp++) {
88 fprintf(stdout, " pixel pipe %02u: %u\n",
89 pp, devinfo->ppipe_subslices[pp]);
90 }
91
92 fprintf(stdout, " slices: %u\n", n_s);
93 fprintf(stdout, " %s: %u\n", subslice_name, n_ss);
94 fprintf(stdout, " EUs: %u\n", n_eus);
95 fprintf(stdout, " EU threads: %u\n", n_eus * devinfo->num_thread_per_eu);
96
97 fprintf(stdout, " LLC: %u\n", devinfo->has_llc);
98 fprintf(stdout, " threads per EU: %u\n", devinfo->num_thread_per_eu);
99 fprintf(stdout, " L3 banks: %u\n", devinfo->l3_banks);
100 fprintf(stdout, " max VS threads: %u\n", devinfo->max_vs_threads);
101 fprintf(stdout, " max TCS threads: %u\n", devinfo->max_tcs_threads);
102 fprintf(stdout, " max TES threads: %u\n", devinfo->max_tes_threads);
103 fprintf(stdout, " max GS threads: %u\n", devinfo->max_gs_threads);
104 fprintf(stdout, " max WM threads: %u\n", devinfo->max_wm_threads);
105 fprintf(stdout, " max CS threads: %u\n", devinfo->max_cs_threads);
106 fprintf(stdout, " timestamp frequency: %" PRIu64 " / %.4f ns\n",
107 devinfo->timestamp_frequency, 1000000000.0 / devinfo->timestamp_frequency);
108
109 fprintf(stdout, " URB size: %u\n", devinfo->urb.size);
110 static const char *stage_names[4] = {
111 "VS", "HS", "DS", "GS",
112 };
113 for (unsigned s = 0; s < ARRAY_SIZE(devinfo->urb.min_entries); s++) {
114 fprintf(stdout, " URB.entries[%s] = [%4u, %4u]\n",
115 stage_names[s],
116 devinfo->urb.min_entries[s],
117 devinfo->urb.max_entries[s]);
118 }
119 }
120
121 static void
print_regions_info(const struct intel_device_info * devinfo)122 print_regions_info(const struct intel_device_info *devinfo)
123 {
124 if (devinfo->mem.sram.mappable.size > 0 ||
125 devinfo->mem.sram.unmappable.size > 0) {
126 fprintf(stdout, " sram:\n");
127 if (devinfo->mem.use_class_instance) {
128 fprintf(stdout, " class: %d; instance: %d\n",
129 devinfo->mem.sram.mem.klass, devinfo->mem.sram.mem.instance);
130 }
131 fprintf(stdout, " mappable: %" PRId64 "; ",
132 devinfo->mem.sram.mappable.size);
133 fprintf(stdout, "free: %" PRId64 "\n",
134 devinfo->mem.sram.mappable.free);
135 if (devinfo->mem.sram.unmappable.size > 0) {
136 fprintf(stdout, " unmappable: %" PRId64 "; ",
137 devinfo->mem.sram.unmappable.size);
138 fprintf(stdout, "free: %" PRId64 "\n",
139 devinfo->mem.sram.unmappable.free);
140 }
141 }
142
143 if (devinfo->mem.vram.mappable.size > 0 ||
144 devinfo->mem.vram.unmappable.size > 0) {
145 fprintf(stdout, " vram:\n");
146 if (devinfo->mem.use_class_instance) {
147 fprintf(stdout, " class: %d; instance: %d\n",
148 devinfo->mem.vram.mem.klass, devinfo->mem.vram.mem.instance);
149 }
150 fprintf(stdout, " mappable: %" PRId64 "; ",
151 devinfo->mem.vram.mappable.size);
152 fprintf(stdout, "free: %" PRId64 "\n",
153 devinfo->mem.vram.mappable.free);
154 if (devinfo->mem.vram.unmappable.size > 0) {
155 fprintf(stdout, " unmappable: %" PRId64 "; ",
156 devinfo->mem.vram.unmappable.size);
157 fprintf(stdout, "free: %" PRId64 "\n",
158 devinfo->mem.vram.unmappable.free);
159 }
160 }
161 }
162
163 #define INTEL_WA( X ) "WA_"#X
164 static void
print_wa_info(const struct intel_device_info * devinfo)165 print_wa_info(const struct intel_device_info *devinfo)
166 {
167 static const char* all_wa[] = { INTEL_ALL_WA };
168 fprintf(stdout, " required workarounds:\n");
169 for (enum intel_workaround_id id = 0; id < INTEL_WA_NUM; ++id) {
170 if (BITSET_TEST(devinfo->workarounds, id)) {
171 fprintf(stdout, " %s\n", all_wa[id]);
172 }
173 }
174 fprintf(stdout, "\n");
175 }
176 #undef INTEL_WA
177
178 int
main(int argc,char * argv[])179 main(int argc, char *argv[])
180 {
181 drmDevicePtr devices[8];
182 int max_devices, i;
183 char c;
184 bool help = false, print_hwconfig = false, all = false, print_workarounds = false, print_json = false;
185 const char *platform = NULL;
186 const struct option opts[] = {
187 { "help", no_argument, (int *) &help, true },
188 { "platform", required_argument, NULL, false },
189 { "hwconfig", no_argument, (int *) &print_hwconfig, true },
190 { "json", no_argument, (int *) &print_json, true },
191 { "workarounds", no_argument, (int *) &print_workarounds, true },
192 { "all", no_argument, (int *) &all, true },
193 };
194 while ((c = getopt_long(argc, argv, "hap:", opts, &i)) != -1) {
195 switch (c) {
196 case 'h':
197 help = true;
198 break;
199 case 'a':
200 all = true;
201 break;
202 case 'p':
203 platform = optarg;
204 break;
205 default:
206 break;
207 }
208 }
209
210 if (help) {
211 fprintf(stdout,
212 "Usage: intel_dev_info [OPTION]\n"
213 "Print device info for the current system.\n"
214 " --help / h display this help and exit\n"
215 " --platform <name> print a given platform's info (skl, icl, tgl, etc...)\n"
216 " --hwconfig print the hwconfig table\n"
217 " --json print json representation of device info\n"
218 " --workarounds print the list of hardware workarounds for the system\n"
219 " --all / -a print all optional details\n");
220 exit(0);
221 }
222
223 if (all) {
224 print_workarounds = true;
225 print_hwconfig = true;
226 }
227
228 if (platform) {
229 int pci_id;
230
231 if (strstr(platform, "0x") == platform)
232 pci_id = strtol(platform, NULL, 16);
233 else
234 pci_id = intel_device_name_to_pci_device_id(platform);
235
236 struct intel_device_info devinfo;
237 if (!intel_get_device_info_from_pci_id(pci_id, &devinfo))
238 return error("No platform found with name: %s", platform);
239
240 print_base_devinfo(&devinfo);
241 if (print_workarounds)
242 print_wa_info(&devinfo);
243 } else {
244 max_devices = drmGetDevices2(0, devices, ARRAY_SIZE(devices));
245 if (max_devices < 1)
246 return error("Not device found");
247
248 for (int i = 0; i < max_devices; i++) {
249 struct intel_device_info devinfo;
250 const char *path = devices[i]->nodes[DRM_NODE_RENDER];
251 int fd = open(path, O_RDWR | O_CLOEXEC);
252
253 if (fd < 0)
254 continue;
255
256 bool success = intel_get_device_info_from_fd(fd, &devinfo, -1, -1);
257
258 if (!success) {
259 close(fd);
260 continue;
261 }
262
263 if (print_json) {
264 JSON_Value *json = intel_device_info_dump_json(&devinfo);
265
266 /* When available, add the compiler device sha, to allow
267 * deduplication of similar device info files.
268 */
269 if (devinfo.ver >= 9) {
270 JSON_Object *obj = json_object(json);
271 char device_info_sha[41];
272 brw_device_sha1(device_info_sha, &devinfo);
273 json_object_set_string(obj, "shader_cache_sha1", device_info_sha);
274 }
275
276 char *pretty_string = json_serialize_to_string_pretty(json);
277 printf("%s", pretty_string);
278 json_free_serialized_string(pretty_string);
279 json_value_free(json);
280 close(fd);
281 continue;
282 }
283
284 fprintf(stdout, "%s:\n", path);
285
286 print_base_devinfo(&devinfo);
287 print_regions_info(&devinfo);
288 if (print_hwconfig)
289 intel_get_and_print_hwconfig_table(fd, &devinfo);
290 if (print_workarounds)
291 print_wa_info(&devinfo);
292
293 close(fd);
294 }
295 }
296
297 return EXIT_SUCCESS;
298 }
299