ACPI: sysfs: Fix BERT error region memory mapping
[linux-2.6-microblaze.git] / arch / arm64 / kvm / vgic / vgic-debug.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  * Copyright (C) 2016 Linaro
4  * Author: Christoffer Dall <christoffer.dall@linaro.org>
5  */
6
7 #include <linux/cpu.h>
8 #include <linux/debugfs.h>
9 #include <linux/interrupt.h>
10 #include <linux/kvm_host.h>
11 #include <linux/seq_file.h>
12 #include <kvm/arm_vgic.h>
13 #include <asm/kvm_mmu.h>
14 #include "vgic.h"
15
16 /*
17  * Structure to control looping through the entire vgic state.  We start at
18  * zero for each field and move upwards.  So, if dist_id is 0 we print the
19  * distributor info.  When dist_id is 1, we have already printed it and move
20  * on.
21  *
22  * When vcpu_id < nr_cpus we print the vcpu info until vcpu_id == nr_cpus and
23  * so on.
24  */
25 struct vgic_state_iter {
26         int nr_cpus;
27         int nr_spis;
28         int nr_lpis;
29         int dist_id;
30         int vcpu_id;
31         int intid;
32         int lpi_idx;
33         u32 *lpi_array;
34 };
35
36 static void iter_next(struct vgic_state_iter *iter)
37 {
38         if (iter->dist_id == 0) {
39                 iter->dist_id++;
40                 return;
41         }
42
43         iter->intid++;
44         if (iter->intid == VGIC_NR_PRIVATE_IRQS &&
45             ++iter->vcpu_id < iter->nr_cpus)
46                 iter->intid = 0;
47
48         if (iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS)) {
49                 if (iter->lpi_idx < iter->nr_lpis)
50                         iter->intid = iter->lpi_array[iter->lpi_idx];
51                 iter->lpi_idx++;
52         }
53 }
54
55 static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter,
56                       loff_t pos)
57 {
58         int nr_cpus = atomic_read(&kvm->online_vcpus);
59
60         memset(iter, 0, sizeof(*iter));
61
62         iter->nr_cpus = nr_cpus;
63         iter->nr_spis = kvm->arch.vgic.nr_spis;
64         if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
65                 iter->nr_lpis = vgic_copy_lpi_list(kvm, NULL, &iter->lpi_array);
66                 if (iter->nr_lpis < 0)
67                         iter->nr_lpis = 0;
68         }
69
70         /* Fast forward to the right position if needed */
71         while (pos--)
72                 iter_next(iter);
73 }
74
75 static bool end_of_vgic(struct vgic_state_iter *iter)
76 {
77         return iter->dist_id > 0 &&
78                 iter->vcpu_id == iter->nr_cpus &&
79                 iter->intid >= (iter->nr_spis + VGIC_NR_PRIVATE_IRQS) &&
80                 iter->lpi_idx > iter->nr_lpis;
81 }
82
83 static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
84 {
85         struct kvm *kvm = (struct kvm *)s->private;
86         struct vgic_state_iter *iter;
87
88         mutex_lock(&kvm->lock);
89         iter = kvm->arch.vgic.iter;
90         if (iter) {
91                 iter = ERR_PTR(-EBUSY);
92                 goto out;
93         }
94
95         iter = kmalloc(sizeof(*iter), GFP_KERNEL);
96         if (!iter) {
97                 iter = ERR_PTR(-ENOMEM);
98                 goto out;
99         }
100
101         iter_init(kvm, iter, *pos);
102         kvm->arch.vgic.iter = iter;
103
104         if (end_of_vgic(iter))
105                 iter = NULL;
106 out:
107         mutex_unlock(&kvm->lock);
108         return iter;
109 }
110
111 static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
112 {
113         struct kvm *kvm = (struct kvm *)s->private;
114         struct vgic_state_iter *iter = kvm->arch.vgic.iter;
115
116         ++*pos;
117         iter_next(iter);
118         if (end_of_vgic(iter))
119                 iter = NULL;
120         return iter;
121 }
122
123 static void vgic_debug_stop(struct seq_file *s, void *v)
124 {
125         struct kvm *kvm = (struct kvm *)s->private;
126         struct vgic_state_iter *iter;
127
128         /*
129          * If the seq file wasn't properly opened, there's nothing to clearn
130          * up.
131          */
132         if (IS_ERR(v))
133                 return;
134
135         mutex_lock(&kvm->lock);
136         iter = kvm->arch.vgic.iter;
137         kfree(iter->lpi_array);
138         kfree(iter);
139         kvm->arch.vgic.iter = NULL;
140         mutex_unlock(&kvm->lock);
141 }
142
143 static void print_dist_state(struct seq_file *s, struct vgic_dist *dist)
144 {
145         bool v3 = dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3;
146
147         seq_printf(s, "Distributor\n");
148         seq_printf(s, "===========\n");
149         seq_printf(s, "vgic_model:\t%s\n", v3 ? "GICv3" : "GICv2");
150         seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis);
151         if (v3)
152                 seq_printf(s, "nr_lpis:\t%d\n", dist->lpi_list_count);
153         seq_printf(s, "enabled:\t%d\n", dist->enabled);
154         seq_printf(s, "\n");
155
156         seq_printf(s, "P=pending_latch, L=line_level, A=active\n");
157         seq_printf(s, "E=enabled, H=hw, C=config (level=1, edge=0)\n");
158         seq_printf(s, "G=group\n");
159 }
160
161 static void print_header(struct seq_file *s, struct vgic_irq *irq,
162                          struct kvm_vcpu *vcpu)
163 {
164         int id = 0;
165         char *hdr = "SPI ";
166
167         if (vcpu) {
168                 hdr = "VCPU";
169                 id = vcpu->vcpu_id;
170         }
171
172         seq_printf(s, "\n");
173         seq_printf(s, "%s%2d TYP   ID TGT_ID PLAEHCG     HWID   TARGET SRC PRI VCPU_ID\n", hdr, id);
174         seq_printf(s, "----------------------------------------------------------------\n");
175 }
176
177 static void print_irq_state(struct seq_file *s, struct vgic_irq *irq,
178                             struct kvm_vcpu *vcpu)
179 {
180         char *type;
181         bool pending;
182
183         if (irq->intid < VGIC_NR_SGIS)
184                 type = "SGI";
185         else if (irq->intid < VGIC_NR_PRIVATE_IRQS)
186                 type = "PPI";
187         else if (irq->intid < VGIC_MAX_SPI)
188                 type = "SPI";
189         else
190                 type = "LPI";
191
192         if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS)
193                 print_header(s, irq, vcpu);
194
195         pending = irq->pending_latch;
196         if (irq->hw && vgic_irq_is_sgi(irq->intid)) {
197                 int err;
198
199                 err = irq_get_irqchip_state(irq->host_irq,
200                                             IRQCHIP_STATE_PENDING,
201                                             &pending);
202                 WARN_ON_ONCE(err);
203         }
204
205         seq_printf(s, "       %s %4d "
206                       "    %2d "
207                       "%d%d%d%d%d%d%d "
208                       "%8d "
209                       "%8x "
210                       " %2x "
211                       "%3d "
212                       "     %2d "
213                       "\n",
214                         type, irq->intid,
215                         (irq->target_vcpu) ? irq->target_vcpu->vcpu_id : -1,
216                         pending,
217                         irq->line_level,
218                         irq->active,
219                         irq->enabled,
220                         irq->hw,
221                         irq->config == VGIC_CONFIG_LEVEL,
222                         irq->group,
223                         irq->hwintid,
224                         irq->mpidr,
225                         irq->source,
226                         irq->priority,
227                         (irq->vcpu) ? irq->vcpu->vcpu_id : -1);
228 }
229
230 static int vgic_debug_show(struct seq_file *s, void *v)
231 {
232         struct kvm *kvm = (struct kvm *)s->private;
233         struct vgic_state_iter *iter = (struct vgic_state_iter *)v;
234         struct vgic_irq *irq;
235         struct kvm_vcpu *vcpu = NULL;
236         unsigned long flags;
237
238         if (iter->dist_id == 0) {
239                 print_dist_state(s, &kvm->arch.vgic);
240                 return 0;
241         }
242
243         if (!kvm->arch.vgic.initialized)
244                 return 0;
245
246         if (iter->vcpu_id < iter->nr_cpus)
247                 vcpu = kvm_get_vcpu(kvm, iter->vcpu_id);
248
249         irq = vgic_get_irq(kvm, vcpu, iter->intid);
250         if (!irq) {
251                 seq_printf(s, "       LPI %4d freed\n", iter->intid);
252                 return 0;
253         }
254
255         raw_spin_lock_irqsave(&irq->irq_lock, flags);
256         print_irq_state(s, irq, vcpu);
257         raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
258
259         vgic_put_irq(kvm, irq);
260         return 0;
261 }
262
263 static const struct seq_operations vgic_debug_sops = {
264         .start = vgic_debug_start,
265         .next  = vgic_debug_next,
266         .stop  = vgic_debug_stop,
267         .show  = vgic_debug_show
268 };
269
270 DEFINE_SEQ_ATTRIBUTE(vgic_debug);
271
272 void vgic_debug_init(struct kvm *kvm)
273 {
274         debugfs_create_file("vgic-state", 0444, kvm->debugfs_dentry, kvm,
275                             &vgic_debug_fops);
276 }
277
278 void vgic_debug_destroy(struct kvm *kvm)
279 {
280 }