]> asedeno.scripts.mit.edu Git - linux.git/blob - drivers/iommu/intel-iommu-debugfs.c
iommu/vt-d: Add debugfs support to show register contents
[linux.git] / drivers / iommu / intel-iommu-debugfs.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  * Copyright © 2018 Intel Corporation.
4  *
5  * Authors: Gayatri Kammela <gayatri.kammela@intel.com>
6  *          Sohil Mehta <sohil.mehta@intel.com>
7  *          Jacob Pan <jacob.jun.pan@linux.intel.com>
8  */
9
10 #include <linux/debugfs.h>
11 #include <linux/dmar.h>
12 #include <linux/intel-iommu.h>
13 #include <linux/pci.h>
14
15 #include <asm/irq_remapping.h>
16
17 struct iommu_regset {
18         int offset;
19         const char *regs;
20 };
21
22 #define IOMMU_REGSET_ENTRY(_reg_)                                       \
23         { DMAR_##_reg_##_REG, __stringify(_reg_) }
24 static const struct iommu_regset iommu_regs[] = {
25         IOMMU_REGSET_ENTRY(VER),
26         IOMMU_REGSET_ENTRY(CAP),
27         IOMMU_REGSET_ENTRY(ECAP),
28         IOMMU_REGSET_ENTRY(GCMD),
29         IOMMU_REGSET_ENTRY(GSTS),
30         IOMMU_REGSET_ENTRY(RTADDR),
31         IOMMU_REGSET_ENTRY(CCMD),
32         IOMMU_REGSET_ENTRY(FSTS),
33         IOMMU_REGSET_ENTRY(FECTL),
34         IOMMU_REGSET_ENTRY(FEDATA),
35         IOMMU_REGSET_ENTRY(FEADDR),
36         IOMMU_REGSET_ENTRY(FEUADDR),
37         IOMMU_REGSET_ENTRY(AFLOG),
38         IOMMU_REGSET_ENTRY(PMEN),
39         IOMMU_REGSET_ENTRY(PLMBASE),
40         IOMMU_REGSET_ENTRY(PLMLIMIT),
41         IOMMU_REGSET_ENTRY(PHMBASE),
42         IOMMU_REGSET_ENTRY(PHMLIMIT),
43         IOMMU_REGSET_ENTRY(IQH),
44         IOMMU_REGSET_ENTRY(IQT),
45         IOMMU_REGSET_ENTRY(IQA),
46         IOMMU_REGSET_ENTRY(ICS),
47         IOMMU_REGSET_ENTRY(IRTA),
48         IOMMU_REGSET_ENTRY(PQH),
49         IOMMU_REGSET_ENTRY(PQT),
50         IOMMU_REGSET_ENTRY(PQA),
51         IOMMU_REGSET_ENTRY(PRS),
52         IOMMU_REGSET_ENTRY(PECTL),
53         IOMMU_REGSET_ENTRY(PEDATA),
54         IOMMU_REGSET_ENTRY(PEADDR),
55         IOMMU_REGSET_ENTRY(PEUADDR),
56         IOMMU_REGSET_ENTRY(MTRRCAP),
57         IOMMU_REGSET_ENTRY(MTRRDEF),
58         IOMMU_REGSET_ENTRY(MTRR_FIX64K_00000),
59         IOMMU_REGSET_ENTRY(MTRR_FIX16K_80000),
60         IOMMU_REGSET_ENTRY(MTRR_FIX16K_A0000),
61         IOMMU_REGSET_ENTRY(MTRR_FIX4K_C0000),
62         IOMMU_REGSET_ENTRY(MTRR_FIX4K_C8000),
63         IOMMU_REGSET_ENTRY(MTRR_FIX4K_D0000),
64         IOMMU_REGSET_ENTRY(MTRR_FIX4K_D8000),
65         IOMMU_REGSET_ENTRY(MTRR_FIX4K_E0000),
66         IOMMU_REGSET_ENTRY(MTRR_FIX4K_E8000),
67         IOMMU_REGSET_ENTRY(MTRR_FIX4K_F0000),
68         IOMMU_REGSET_ENTRY(MTRR_FIX4K_F8000),
69         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE0),
70         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK0),
71         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE1),
72         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK1),
73         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE2),
74         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK2),
75         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE3),
76         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK3),
77         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE4),
78         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK4),
79         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE5),
80         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK5),
81         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE6),
82         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK6),
83         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE7),
84         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK7),
85         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE8),
86         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK8),
87         IOMMU_REGSET_ENTRY(MTRR_PHYSBASE9),
88         IOMMU_REGSET_ENTRY(MTRR_PHYSMASK9),
89         IOMMU_REGSET_ENTRY(VCCAP),
90         IOMMU_REGSET_ENTRY(VCMD),
91         IOMMU_REGSET_ENTRY(VCRSP),
92 };
93
94 static int iommu_regset_show(struct seq_file *m, void *unused)
95 {
96         struct dmar_drhd_unit *drhd;
97         struct intel_iommu *iommu;
98         unsigned long flag;
99         int i, ret = 0;
100         u64 value;
101
102         rcu_read_lock();
103         for_each_active_iommu(iommu, drhd) {
104                 if (!drhd->reg_base_addr) {
105                         seq_puts(m, "IOMMU: Invalid base address\n");
106                         ret = -EINVAL;
107                         goto out;
108                 }
109
110                 seq_printf(m, "IOMMU: %s Register Base Address: %llx\n",
111                            iommu->name, drhd->reg_base_addr);
112                 seq_puts(m, "Name\t\t\tOffset\t\tContents\n");
113                 /*
114                  * Publish the contents of the 64-bit hardware registers
115                  * by adding the offset to the pointer (virtual address).
116                  */
117                 raw_spin_lock_irqsave(&iommu->register_lock, flag);
118                 for (i = 0 ; i < ARRAY_SIZE(iommu_regs); i++) {
119                         value = dmar_readq(iommu->reg + iommu_regs[i].offset);
120                         seq_printf(m, "%-16s\t0x%02x\t\t0x%016llx\n",
121                                    iommu_regs[i].regs, iommu_regs[i].offset,
122                                    value);
123                 }
124                 raw_spin_unlock_irqrestore(&iommu->register_lock, flag);
125                 seq_putc(m, '\n');
126         }
127 out:
128         rcu_read_unlock();
129
130         return ret;
131 }
132 DEFINE_SHOW_ATTRIBUTE(iommu_regset);
133
134 void __init intel_iommu_debugfs_init(void)
135 {
136         struct dentry *intel_iommu_debug = debugfs_create_dir("intel",
137                                                 iommu_debugfs_dir);
138
139         debugfs_create_file("iommu_regset", 0444, intel_iommu_debug, NULL,
140                             &iommu_regset_fops);
141 }