cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

vgic-debug.c (6260B)


      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 */
     25struct 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
     36static 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
     55static 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
     75static 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
     83static void *vgic_debug_start(struct seq_file *s, loff_t *pos)
     84{
     85	struct kvm *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;
    106out:
    107	mutex_unlock(&kvm->lock);
    108	return iter;
    109}
    110
    111static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos)
    112{
    113	struct kvm *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
    123static void vgic_debug_stop(struct seq_file *s, void *v)
    124{
    125	struct kvm *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
    143static 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
    161static 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
    177static 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
    230static int vgic_debug_show(struct seq_file *s, void *v)
    231{
    232	struct kvm *kvm = s->private;
    233	struct vgic_state_iter *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
    263static 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
    270DEFINE_SEQ_ATTRIBUTE(vgic_debug);
    271
    272void vgic_debug_init(struct kvm *kvm)
    273{
    274	debugfs_create_file("vgic-state", 0444, kvm->debugfs_dentry, kvm,
    275			    &vgic_debug_fops);
    276}
    277
    278void vgic_debug_destroy(struct kvm *kvm)
    279{
    280}