cregit-Linux how code gets into the kernel

Release 4.11 virt/kvm/arm/vgic/vgic-debug.c

/*
 * Copyright (C) 2016 Linaro
 * Author: Christoffer Dall <christoffer.dall@linaro.org>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <linux/cpu.h>
#include <linux/debugfs.h>
#include <linux/interrupt.h>
#include <linux/kvm_host.h>
#include <linux/seq_file.h>
#include <kvm/arm_vgic.h>
#include <asm/kvm_mmu.h>
#include "vgic.h"

/*
 * Structure to control looping through the entire vgic state.  We start at
 * zero for each field and move upwards.  So, if dist_id is 0 we print the
 * distributor info.  When dist_id is 1, we have already printed it and move
 * on.
 *
 * When vcpu_id < nr_cpus we print the vcpu info until vcpu_id == nr_cpus and
 * so on.
 */

struct vgic_state_iter {
	
int nr_cpus;
	
int nr_spis;
	
int dist_id;
	
int vcpu_id;
	
int intid;
};


static void iter_next(struct vgic_state_iter *iter) { if (iter->dist_id == 0) { iter->dist_id++; return; } iter->intid++; if (iter->intid == VGIC_NR_PRIVATE_IRQS && ++iter->vcpu_id < iter->nr_cpus) iter->intid = 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall55100.00%1100.00%
Total55100.00%1100.00%


static void iter_init(struct kvm *kvm, struct vgic_state_iter *iter, loff_t pos) { int nr_cpus = atomic_read(&kvm->online_vcpus); memset(iter, 0, sizeof(*iter)); iter->nr_cpus = nr_cpus; iter->nr_spis = kvm->arch.vgic.nr_spis; /* Fast forward to the right position if needed */ while (pos--) iter_next(iter); }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall72100.00%1100.00%
Total72100.00%1100.00%


static bool end_of_vgic(struct vgic_state_iter *iter) { return iter->dist_id > 0 && iter->vcpu_id == iter->nr_cpus && (iter->intid - VGIC_NR_PRIVATE_IRQS) == iter->nr_spis; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall38100.00%1100.00%
Total38100.00%1100.00%


static void *vgic_debug_start(struct seq_file *s, loff_t *pos) { struct kvm *kvm = (struct kvm *)s->private; struct vgic_state_iter *iter; mutex_lock(&kvm->lock); iter = kvm->arch.vgic.iter; if (iter) { iter = ERR_PTR(-EBUSY); goto out; } iter = kmalloc(sizeof(*iter), GFP_KERNEL); if (!iter) { iter = ERR_PTR(-ENOMEM); goto out; } iter_init(kvm, iter, *pos); kvm->arch.vgic.iter = iter; if (end_of_vgic(iter)) iter = NULL; out: mutex_unlock(&kvm->lock); return iter; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall145100.00%1100.00%
Total145100.00%1100.00%


static void *vgic_debug_next(struct seq_file *s, void *v, loff_t *pos) { struct kvm *kvm = (struct kvm *)s->private; struct vgic_state_iter *iter = kvm->arch.vgic.iter; ++*pos; iter_next(iter); if (end_of_vgic(iter)) iter = NULL; return iter; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall70100.00%1100.00%
Total70100.00%1100.00%


static void vgic_debug_stop(struct seq_file *s, void *v) { struct kvm *kvm = (struct kvm *)s->private; struct vgic_state_iter *iter; /* * If the seq file wasn't properly opened, there's nothing to clearn * up. */ if (IS_ERR(v)) return; mutex_lock(&kvm->lock); iter = kvm->arch.vgic.iter; kfree(iter); kvm->arch.vgic.iter = NULL; mutex_unlock(&kvm->lock); }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall84100.00%1100.00%
Total84100.00%1100.00%


static void print_dist_state(struct seq_file *s, struct vgic_dist *dist) { seq_printf(s, "Distributor\n"); seq_printf(s, "===========\n"); seq_printf(s, "vgic_model:\t%s\n", (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) ? "GICv3" : "GICv2"); seq_printf(s, "nr_spis:\t%d\n", dist->nr_spis); seq_printf(s, "enabled:\t%d\n", dist->enabled); seq_printf(s, "\n"); seq_printf(s, "P=pending_latch, L=line_level, A=active\n"); seq_printf(s, "E=enabled, H=hw, C=config (level=1, edge=0)\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall92100.00%1100.00%
Total92100.00%1100.00%


static void print_header(struct seq_file *s, struct vgic_irq *irq, struct kvm_vcpu *vcpu) { int id = 0; char *hdr = "SPI "; if (vcpu) { hdr = "VCPU"; id = vcpu->vcpu_id; } seq_printf(s, "\n"); seq_printf(s, "%s%2d TYP ID TGT_ID PLAEHC HWID TARGET SRC PRI VCPU_ID\n", hdr, id); seq_printf(s, "---------------------------------------------------------------\n"); }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall73100.00%1100.00%
Total73100.00%1100.00%


static void print_irq_state(struct seq_file *s, struct vgic_irq *irq, struct kvm_vcpu *vcpu) { char *type; if (irq->intid < VGIC_NR_SGIS) type = "SGI"; else if (irq->intid < VGIC_NR_PRIVATE_IRQS) type = "PPI"; else type = "SPI"; if (irq->intid ==0 || irq->intid == VGIC_NR_PRIVATE_IRQS) print_header(s, irq, vcpu); seq_printf(s, " %s %4d " " %2d " "%d%d%d%d%d%d " "%8d " "%8x " " %2x " "%3d " " %2d " "\n", type, irq->intid, (irq->target_vcpu) ? irq->target_vcpu->vcpu_id : -1, irq->pending_latch, irq->line_level, irq->active, irq->enabled, irq->hw, irq->config == VGIC_CONFIG_LEVEL, irq->hwintid, irq->mpidr, irq->source, irq->priority, (irq->vcpu) ? irq->vcpu->vcpu_id : -1); }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall171100.00%1100.00%
Total171100.00%1100.00%


static int vgic_debug_show(struct seq_file *s, void *v) { struct kvm *kvm = (struct kvm *)s->private; struct vgic_state_iter *iter = (struct vgic_state_iter *)v; struct vgic_irq *irq; struct kvm_vcpu *vcpu = NULL; if (iter->dist_id == 0) { print_dist_state(s, &kvm->arch.vgic); return 0; } if (!kvm->arch.vgic.initialized) return 0; if (iter->vcpu_id < iter->nr_cpus) { vcpu = kvm_get_vcpu(kvm, iter->vcpu_id); irq = &vcpu->arch.vgic_cpu.private_irqs[iter->intid]; } else { irq = &kvm->arch.vgic.spis[iter->intid - VGIC_NR_PRIVATE_IRQS]; } spin_lock(&irq->irq_lock); print_irq_state(s, irq, vcpu); spin_unlock(&irq->irq_lock); return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall180100.00%1100.00%
Total180100.00%1100.00%

static struct seq_operations vgic_debug_seq_ops = { .start = vgic_debug_start, .next = vgic_debug_next, .stop = vgic_debug_stop, .show = vgic_debug_show };
static int debug_open(struct inode *inode, struct file *file) { int ret; ret = seq_open(file, &vgic_debug_seq_ops); if (!ret) { struct seq_file *seq; /* seq_open will have modified file->private_data */ seq = file->private_data; seq->private = inode->i_private; } return ret; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall59100.00%1100.00%
Total59100.00%1100.00%

; static struct file_operations vgic_debug_fops = { .owner = THIS_MODULE, .open = debug_open, .read = seq_read, .llseek = seq_lseek, .release = seq_release };
int vgic_debug_init(struct kvm *kvm) { if (!kvm->debugfs_dentry) return -ENOENT; if (!debugfs_create_file("vgic-state", 0444, kvm->debugfs_dentry, kvm, &vgic_debug_fops)) return -ENOMEM; return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall47100.00%1100.00%
Total47100.00%1100.00%


int vgic_debug_destroy(struct kvm *kvm) { return 0; }

Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall13100.00%1100.00%
Total13100.00%1100.00%


Overall Contributors

PersonTokensPropCommitsCommitProp
Christoffer Dall1205100.00%1100.00%
Total1205100.00%1100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.