GNU Linux-libre 4.14.302-gnu1
[releases.git] / virt / kvm / arm / vgic / vgic-debug.c
1 /*
2  * Copyright (C) 2016 Linaro
3  * Author: Christoffer Dall <christoffer.dall@linaro.org>
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License version 2 as
7  * published by the Free Software Foundation.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16  */
17
18 #include <linux/cpu.h>
19 #include <linux/debugfs.h>
20 #include <linux/interrupt.h>
21 #include <linux/kvm_host.h>
22 #include <linux/seq_file.h>
23 #include <kvm/arm_vgic.h>
24 #include <asm/kvm_mmu.h>
25 #include "vgic.h"
26
27 /*
28  * Structure to control looping through the entire vgic state.  We start at
29  * zero for each field and move upwards.  So, if dist_id is 0 we print the
30  * distributor info.  When dist_id is 1, we have already printed it and move
31  * on.
32  *
33  * When vcpu_id < nr_cpus we print the vcpu info until vcpu_id == nr_cpus and
34  * so on.
35  */
36 struct vgic_state_iter {
37         int nr_cpus;
38         int nr_spis;
39         int dist_id;
40         int vcpu_id;
41         int intid;
42 };
43
44 static void iter_next(struct vgic_state_iter *iter)
45 {
46         if (iter->dist_id == 0) {
47                 iter->dist_id++;
48                 return;
49         }
50
51         iter->intid++;
52         if (iter->intid == VGIC_NR_PRIVATE_IRQS &&
53             ++iter->vcpu_id < iter->nr_cpus)
54                 iter->intid = 0;
55 }
56
57 static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
58                       loff_t pos)
59 {
60         int nr_cpus = atomic_read(&kvm->online_vcpus);
61
62         memset(iter, 0, sizeof(*iter));
63
64         iter->nr_cpus = nr_cpus;
65         iter->nr_spis = kvm->arch.vgic.nr_spis;
66
67         /* Fast forward to the right position if needed */
68         while (pos--)
69                 iter_next(iter);
70 }
71
72 static bool end_of_vgic(struct vgic_state_iter *iter)
73 {
74         return iter->dist_id > 0 &&
75                 iter->vcpu_id == iter->nr_cpus &&
76                 (iter->intid - VGIC_NR_PRIVATE_IRQS) == iter->nr_spis;
77 }
78
79 static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
80 {
81         struct kvm *kvm = (struct kvm *)s->private;
82         struct vgic_state_iter *iter;
83
84         mutex_lock(&kvm->lock);
85         iter = kvm->arch.vgic.iter;
86         if (iter) {
87                 iter = ERR_PTR(-EBUSY);
88                 goto out;
89         }
90
91         iter = kmalloc(sizeof(*iter), GFP_KERNEL);
92         if (!iter) {
93                 iter = ERR_PTR(-ENOMEM);
94                 goto out;
95         }
96
97         iter_init(kvm, iter, *pos);
98         kvm->arch.vgic.iter = iter;
99
100         if (end_of_vgic(iter))
101                 iter = NULL;
102 out:
103         mutex_unlock(&kvm->lock);
104         return iter;
105 }
106
107 static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
108 {
109         struct kvm *kvm = (struct kvm *)s->private;
110         struct vgic_state_iter *iter = kvm->arch.vgic.iter;
111
112         ++*pos;
113         iter_next(iter);
114         if (end_of_vgic(iter))
115                 iter = NULL;
116         return iter;
117 }
118
119 static void vgic_debug_stop(struct seq_file *s, void *v)
120 {
121         struct kvm *kvm = (struct kvm *)s->private;
122         struct vgic_state_iter *iter;
123
124         /*
125          * If the seq file wasn't properly opened, there's nothing to clearn
126          * up.
127          */
128         if (IS_ERR(v))
129                 return;
130
131         mutex_lock(&kvm->lock);
132         iter = kvm->arch.vgic.iter;
133         kfree(iter);
134         kvm->arch.vgic.iter = NULL;
135         mutex_unlock(&kvm->lock);
136 }
137
138 static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
139 {
140         seq_printf(s, "Distributor\n");
141         seq_printf(s, "===========\n");
142         seq_printf(s, "vgic_model:\t%s\n",
143                    (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) ?
144                    "GICv3" : "GICv2");
145         seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis);
146         seq_printf(s, "enabled:\t%d\n", dist->enabled);
147         seq_printf(s, "\n");
148
149         seq_printf(s, "P=pending_latch, L=line_level, A=active\n");
150         seq_printf(s, "E=enabled, H=hw, C=config (level=1, edge=0)\n");
151 }
152
153 static void print_header(struct seq_file *s, struct vgic_irq *irq,
154                          struct kvm_vcpu *vcpu)
155 {
156         int id = 0;
157         char *hdr = "SPI ";
158
159         if (vcpu) {
160                 hdr = "VCPU";
161                 id = vcpu->vcpu_id;
162         }
163
164         seq_printf(s, "\n");
165         seq_printf(s, "%s%2d TYP   ID TGT_ID PLAEHC     HWID   TARGET SRC PRI VCPU_ID\n", hdr, id);
166         seq_printf(s, "---------------------------------------------------------------\n");
167 }
168
169 static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
170                             struct kvm_vcpu *vcpu)
171 {
172         char *type;
173         if (irq->intid < VGIC_NR_SGIS)
174                 type = "SGI";
175         else if (irq->intid < VGIC_NR_PRIVATE_IRQS)
176                 type = "PPI";
177         else
178                 type = "SPI";
179
180         if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS)
181                 print_header(s, irq, vcpu);
182
183         seq_printf(s, "       %s %4d "
184                       "    %2d "
185                       "%d%d%d%d%d%d "
186                       "%8d "
187                       "%8x "
188                       " %2x "
189                       "%3d "
190                       "     %2d "
191                       "\n",
192                         type, irq->intid,
193                         (irq->target_vcpu) ? irq->target_vcpu->vcpu_id : -1,
194                         irq->pending_latch,
195                         irq->line_level,
196                         irq->active,
197                         irq->enabled,
198                         irq->hw,
199                         irq->config == VGIC_CONFIG_LEVEL,
200                         irq->hwintid,
201                         irq->mpidr,
202                         irq->source,
203                         irq->priority,
204                         (irq->vcpu) ? irq->vcpu->vcpu_id : -1);
205
206 }
207
208 static int vgic_debug_show(struct seq_file *s, void *v)
209 {
210         struct kvm *kvm = (struct kvm *)s->private;
211         struct vgic_state_iter *iter = (struct vgic_state_iter *)v;
212         struct vgic_irq *irq;
213         struct kvm_vcpu *vcpu = NULL;
214
215         if (iter->dist_id == 0) {
216                 print_dist_state(s, &kvm->arch.vgic);
217                 return 0;
218         }
219
220         if (!kvm->arch.vgic.initialized)
221                 return 0;
222
223         if (iter->vcpu_id < iter->nr_cpus) {
224                 vcpu = kvm_get_vcpu(kvm, iter->vcpu_id);
225                 irq = &vcpu->arch.vgic_cpu.private_irqs[iter->intid];
226         } else {
227                 irq = &kvm->arch.vgic.spis[iter->intid - VGIC_NR_PRIVATE_IRQS];
228         }
229
230         spin_lock(&irq->irq_lock);
231         print_irq_state(s, irq, vcpu);
232         spin_unlock(&irq->irq_lock);
233
234         return 0;
235 }
236
237 static const struct seq_operations vgic_debug_seq_ops = {
238         .start = vgic_debug_start,
239         .next  = vgic_debug_next,
240         .stop  = vgic_debug_stop,
241         .show  = vgic_debug_show
242 };
243
244 static int debug_open(struct inode *inode, struct file *file)
245 {
246         int ret;
247         ret = seq_open(file, &vgic_debug_seq_ops);
248         if (!ret) {
249                 struct seq_file *seq;
250                 /* seq_open will have modified file->private_data */
251                 seq = file->private_data;
252                 seq->private = inode->i_private;
253         }
254
255         return ret;
256 };
257
258 static const struct file_operations vgic_debug_fops = {
259         .owner   = THIS_MODULE,
260         .open    = debug_open,
261         .read    = seq_read,
262         .llseek  = seq_lseek,
263         .release = seq_release
264 };
265
266 int vgic_debug_init(struct kvm *kvm)
267 {
268         if (!kvm->debugfs_dentry)
269                 return -ENOENT;
270
271         if (!debugfs_create_file("vgic-state", 0444,
272                                  kvm->debugfs_dentry,
273                                  kvm,
274                                  &vgic_debug_fops))
275                 return -ENOMEM;
276
277         return 0;
278 }
279
280 int vgic_debug_destroy(struct kvm *kvm)
281 {
282         return 0;
283 }