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