xref: /linux/drivers/iommu/amd/debugfs.c (revision 22c55fb9eb92395d999b8404d73e58540d11bdd8)
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * AMD IOMMU driver
4  *
5  * Copyright (C) 2018 Advanced Micro Devices, Inc.
6  *
7  * Author: Gary R Hook <gary.hook@amd.com>
8  */
9 
10 #include <linux/debugfs.h>
11 #include <linux/pci.h>
12 
13 #include "amd_iommu.h"
14 #include "../irq_remapping.h"
15 
16 static struct dentry *amd_iommu_debugfs;
17 
18 #define	MAX_NAME_LEN	20
19 #define	OFS_IN_SZ	8
20 #define	DEVID_IN_SZ	16
21 
22 static int sbdf = -1;
23 
24 static ssize_t iommu_mmio_write(struct file *filp, const char __user *ubuf,
25 				size_t cnt, loff_t *ppos)
26 {
27 	struct seq_file *m = filp->private_data;
28 	struct amd_iommu *iommu = m->private;
29 	int ret;
30 
31 	iommu->dbg_mmio_offset = -1;
32 
33 	if (cnt > OFS_IN_SZ)
34 		return -EINVAL;
35 
36 	ret = kstrtou32_from_user(ubuf, cnt, 0, &iommu->dbg_mmio_offset);
37 	if (ret)
38 		return ret;
39 
40 	if (iommu->dbg_mmio_offset > iommu->mmio_phys_end - 4) {
41 		iommu->dbg_mmio_offset = -1;
42 		return  -EINVAL;
43 	}
44 
45 	return cnt;
46 }
47 
48 static int iommu_mmio_show(struct seq_file *m, void *unused)
49 {
50 	struct amd_iommu *iommu = m->private;
51 	u64 value;
52 
53 	if (iommu->dbg_mmio_offset < 0) {
54 		seq_puts(m, "Please provide mmio register's offset\n");
55 		return 0;
56 	}
57 
58 	value = readq(iommu->mmio_base + iommu->dbg_mmio_offset);
59 	seq_printf(m, "Offset:0x%x Value:0x%016llx\n", iommu->dbg_mmio_offset, value);
60 
61 	return 0;
62 }
63 DEFINE_SHOW_STORE_ATTRIBUTE(iommu_mmio);
64 
65 static ssize_t iommu_capability_write(struct file *filp, const char __user *ubuf,
66 				      size_t cnt, loff_t *ppos)
67 {
68 	struct seq_file *m = filp->private_data;
69 	struct amd_iommu *iommu = m->private;
70 	int ret;
71 
72 	iommu->dbg_cap_offset = -1;
73 
74 	if (cnt > OFS_IN_SZ)
75 		return -EINVAL;
76 
77 	ret = kstrtou32_from_user(ubuf, cnt, 0, &iommu->dbg_cap_offset);
78 	if (ret)
79 		return ret;
80 
81 	/* Capability register at offset 0x14 is the last IOMMU capability register. */
82 	if (iommu->dbg_cap_offset > 0x14) {
83 		iommu->dbg_cap_offset = -1;
84 		return -EINVAL;
85 	}
86 
87 	return cnt;
88 }
89 
90 static int iommu_capability_show(struct seq_file *m, void *unused)
91 {
92 	struct amd_iommu *iommu = m->private;
93 	u32 value;
94 	int err;
95 
96 	if (iommu->dbg_cap_offset < 0) {
97 		seq_puts(m, "Please provide capability register's offset in the range [0x00 - 0x14]\n");
98 		return 0;
99 	}
100 
101 	err = pci_read_config_dword(iommu->dev, iommu->cap_ptr + iommu->dbg_cap_offset, &value);
102 	if (err) {
103 		seq_printf(m, "Not able to read capability register at 0x%x\n",
104 			   iommu->dbg_cap_offset);
105 		return 0;
106 	}
107 
108 	seq_printf(m, "Offset:0x%x Value:0x%08x\n", iommu->dbg_cap_offset, value);
109 
110 	return 0;
111 }
112 DEFINE_SHOW_STORE_ATTRIBUTE(iommu_capability);
113 
114 static int iommu_cmdbuf_show(struct seq_file *m, void *unused)
115 {
116 	struct amd_iommu *iommu = m->private;
117 	struct iommu_cmd *cmd;
118 	unsigned long flag;
119 	u32 head, tail;
120 	int i;
121 
122 	raw_spin_lock_irqsave(&iommu->lock, flag);
123 	head = readl(iommu->mmio_base + MMIO_CMD_HEAD_OFFSET);
124 	tail = readl(iommu->mmio_base + MMIO_CMD_TAIL_OFFSET);
125 	seq_printf(m, "CMD Buffer Head Offset:%d Tail Offset:%d\n",
126 		   (head >> 4) & 0x7fff, (tail >> 4) & 0x7fff);
127 	for (i = 0; i < CMD_BUFFER_ENTRIES; i++) {
128 		cmd = (struct iommu_cmd *)(iommu->cmd_buf + i * sizeof(*cmd));
129 		seq_printf(m, "%3d: %08x %08x %08x %08x\n", i, cmd->data[0],
130 			   cmd->data[1], cmd->data[2], cmd->data[3]);
131 	}
132 	raw_spin_unlock_irqrestore(&iommu->lock, flag);
133 
134 	return 0;
135 }
136 DEFINE_SHOW_ATTRIBUTE(iommu_cmdbuf);
137 
138 static ssize_t devid_write(struct file *filp, const char __user *ubuf,
139 			   size_t cnt, loff_t *ppos)
140 {
141 	struct amd_iommu_pci_seg *pci_seg;
142 	int seg, bus, slot, func;
143 	struct amd_iommu *iommu;
144 	char *srcid_ptr;
145 	u16 devid;
146 	int i;
147 
148 	sbdf = -1;
149 
150 	if (cnt >= DEVID_IN_SZ)
151 		return -EINVAL;
152 
153 	srcid_ptr = memdup_user_nul(ubuf, cnt);
154 	if (IS_ERR(srcid_ptr))
155 		return PTR_ERR(srcid_ptr);
156 
157 	i = sscanf(srcid_ptr, "%x:%x:%x.%x", &seg, &bus, &slot, &func);
158 	if (i != 4) {
159 		i = sscanf(srcid_ptr, "%x:%x.%x", &bus, &slot, &func);
160 		if (i != 3) {
161 			kfree(srcid_ptr);
162 			return -EINVAL;
163 		}
164 		seg = 0;
165 	}
166 
167 	devid = PCI_DEVID(bus, PCI_DEVFN(slot, func));
168 
169 	/* Check if user device id input is a valid input */
170 	for_each_pci_segment(pci_seg) {
171 		if (pci_seg->id != seg)
172 			continue;
173 		if (devid > pci_seg->last_bdf) {
174 			kfree(srcid_ptr);
175 			return -EINVAL;
176 		}
177 		iommu = pci_seg->rlookup_table[devid];
178 		if (!iommu) {
179 			kfree(srcid_ptr);
180 			return -ENODEV;
181 		}
182 		break;
183 	}
184 
185 	if (pci_seg->id != seg) {
186 		kfree(srcid_ptr);
187 		return -EINVAL;
188 	}
189 
190 	sbdf = PCI_SEG_DEVID_TO_SBDF(seg, devid);
191 
192 	kfree(srcid_ptr);
193 
194 	return cnt;
195 }
196 
197 static int devid_show(struct seq_file *m, void *unused)
198 {
199 	u16 devid;
200 
201 	if (sbdf >= 0) {
202 		devid = PCI_SBDF_TO_DEVID(sbdf);
203 		seq_printf(m, "%04x:%02x:%02x.%x\n", PCI_SBDF_TO_SEGID(sbdf),
204 			   PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid));
205 	} else
206 		seq_puts(m, "No or Invalid input provided\n");
207 
208 	return 0;
209 }
210 DEFINE_SHOW_STORE_ATTRIBUTE(devid);
211 
212 static void dump_dte(struct seq_file *m, struct amd_iommu_pci_seg *pci_seg, u16 devid)
213 {
214 	struct dev_table_entry *dev_table;
215 	struct amd_iommu *iommu;
216 
217 	iommu = pci_seg->rlookup_table[devid];
218 	if (!iommu)
219 		return;
220 
221 	dev_table = get_dev_table(iommu);
222 	if (!dev_table) {
223 		seq_puts(m, "Device table not found");
224 		return;
225 	}
226 
227 	seq_printf(m, "%-12s %16s %16s %16s %16s iommu\n", "DeviceId",
228 		   "QWORD[3]", "QWORD[2]", "QWORD[1]", "QWORD[0]");
229 	seq_printf(m, "%04x:%02x:%02x.%x ", pci_seg->id, PCI_BUS_NUM(devid),
230 		   PCI_SLOT(devid), PCI_FUNC(devid));
231 	for (int i = 3; i >= 0; --i)
232 		seq_printf(m, "%016llx ", dev_table[devid].data[i]);
233 	seq_printf(m, "iommu%d\n", iommu->index);
234 }
235 
236 static int iommu_devtbl_show(struct seq_file *m, void *unused)
237 {
238 	struct amd_iommu_pci_seg *pci_seg;
239 	u16 seg, devid;
240 
241 	if (sbdf < 0) {
242 		seq_puts(m, "Enter a valid device ID to 'devid' file\n");
243 		return 0;
244 	}
245 	seg = PCI_SBDF_TO_SEGID(sbdf);
246 	devid = PCI_SBDF_TO_DEVID(sbdf);
247 
248 	for_each_pci_segment(pci_seg) {
249 		if (pci_seg->id != seg)
250 			continue;
251 		dump_dte(m, pci_seg, devid);
252 		break;
253 	}
254 
255 	return 0;
256 }
257 DEFINE_SHOW_ATTRIBUTE(iommu_devtbl);
258 
259 static void dump_128_irte(struct seq_file *m, struct irq_remap_table *table, u16 int_tab_len)
260 {
261 	struct irte_ga *ptr, *irte;
262 	int index;
263 
264 	for (index = 0; index < int_tab_len; index++) {
265 		ptr = (struct irte_ga *)table->table;
266 		irte = &ptr[index];
267 
268 		if (AMD_IOMMU_GUEST_IR_VAPIC(amd_iommu_guest_ir) &&
269 		    !irte->lo.fields_vapic.valid)
270 			continue;
271 		else if (!irte->lo.fields_remap.valid)
272 			continue;
273 		seq_printf(m, "IRT[%04d] %016llx %016llx\n", index, irte->hi.val, irte->lo.val);
274 	}
275 }
276 
277 static void dump_32_irte(struct seq_file *m, struct irq_remap_table *table, u16 int_tab_len)
278 {
279 	union irte *ptr, *irte;
280 	int index;
281 
282 	for (index = 0; index < int_tab_len; index++) {
283 		ptr = (union irte *)table->table;
284 		irte = &ptr[index];
285 
286 		if (!irte->fields.valid)
287 			continue;
288 		seq_printf(m, "IRT[%04d] %08x\n", index, irte->val);
289 	}
290 }
291 
292 static void dump_irte(struct seq_file *m, u16 devid, struct amd_iommu_pci_seg *pci_seg)
293 {
294 	struct dev_table_entry *dev_table;
295 	struct irq_remap_table *table;
296 	struct amd_iommu *iommu;
297 	unsigned long flags;
298 	u16 int_tab_len;
299 
300 	table = pci_seg->irq_lookup_table[devid];
301 	if (!table) {
302 		seq_printf(m, "IRQ lookup table not set for %04x:%02x:%02x:%x\n",
303 			   pci_seg->id, PCI_BUS_NUM(devid), PCI_SLOT(devid), PCI_FUNC(devid));
304 		return;
305 	}
306 
307 	iommu = pci_seg->rlookup_table[devid];
308 	if (!iommu)
309 		return;
310 
311 	dev_table = get_dev_table(iommu);
312 	if (!dev_table) {
313 		seq_puts(m, "Device table not found");
314 		return;
315 	}
316 
317 	int_tab_len = dev_table[devid].data[2] & DTE_INTTABLEN_MASK;
318 	if (int_tab_len != DTE_INTTABLEN_512 && int_tab_len != DTE_INTTABLEN_2K) {
319 		seq_puts(m, "The device's DTE contains an invalid IRT length value.");
320 		return;
321 	}
322 
323 	seq_printf(m, "DeviceId %04x:%02x:%02x.%x\n", pci_seg->id, PCI_BUS_NUM(devid),
324 		   PCI_SLOT(devid), PCI_FUNC(devid));
325 
326 	raw_spin_lock_irqsave(&table->lock, flags);
327 	if (AMD_IOMMU_GUEST_IR_GA(amd_iommu_guest_ir))
328 		dump_128_irte(m, table, BIT(int_tab_len >> 1));
329 	else
330 		dump_32_irte(m, table, BIT(int_tab_len >> 1));
331 	seq_puts(m, "\n");
332 	raw_spin_unlock_irqrestore(&table->lock, flags);
333 }
334 
335 static int iommu_irqtbl_show(struct seq_file *m, void *unused)
336 {
337 	struct amd_iommu_pci_seg *pci_seg;
338 	u16 devid, seg;
339 
340 	if (!irq_remapping_enabled) {
341 		seq_puts(m, "Interrupt remapping is disabled\n");
342 		return 0;
343 	}
344 
345 	if (sbdf < 0) {
346 		seq_puts(m, "Enter a valid device ID to 'devid' file\n");
347 		return 0;
348 	}
349 
350 	seg = PCI_SBDF_TO_SEGID(sbdf);
351 	devid = PCI_SBDF_TO_DEVID(sbdf);
352 
353 	for_each_pci_segment(pci_seg) {
354 		if (pci_seg->id != seg)
355 			continue;
356 		dump_irte(m, devid, pci_seg);
357 		break;
358 	}
359 
360 	return 0;
361 }
362 DEFINE_SHOW_ATTRIBUTE(iommu_irqtbl);
363 
364 void amd_iommu_debugfs_setup(void)
365 {
366 	struct amd_iommu *iommu;
367 	char name[MAX_NAME_LEN + 1];
368 
369 	amd_iommu_debugfs = debugfs_create_dir("amd", iommu_debugfs_dir);
370 
371 	for_each_iommu(iommu) {
372 		iommu->dbg_mmio_offset = -1;
373 		iommu->dbg_cap_offset = -1;
374 
375 		snprintf(name, MAX_NAME_LEN, "iommu%02d", iommu->index);
376 		iommu->debugfs = debugfs_create_dir(name, amd_iommu_debugfs);
377 
378 		debugfs_create_file("mmio", 0644, iommu->debugfs, iommu,
379 				    &iommu_mmio_fops);
380 		debugfs_create_file("capability", 0644, iommu->debugfs, iommu,
381 				    &iommu_capability_fops);
382 		debugfs_create_file("cmdbuf", 0444, iommu->debugfs, iommu,
383 				    &iommu_cmdbuf_fops);
384 	}
385 
386 	debugfs_create_file("devid", 0644, amd_iommu_debugfs, NULL,
387 			    &devid_fops);
388 	debugfs_create_file("devtbl", 0444, amd_iommu_debugfs, NULL,
389 			    &iommu_devtbl_fops);
390 	debugfs_create_file("irqtbl", 0444, amd_iommu_debugfs, NULL,
391 			    &iommu_irqtbl_fops);
392 }
393