Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0-only
0002 /*
0003  * Kernel-based Virtual Machine driver for Linux
0004  *
0005  * Copyright 2016 Red Hat, Inc. and/or its affiliates.
0006  */
0007 #include <linux/kvm_host.h>
0008 #include <linux/debugfs.h>
0009 #include "lapic.h"
0010 #include "mmu.h"
0011 #include "mmu/mmu_internal.h"
0012 
0013 static int vcpu_get_timer_advance_ns(void *data, u64 *val)
0014 {
0015     struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
0016     *val = vcpu->arch.apic->lapic_timer.timer_advance_ns;
0017     return 0;
0018 }
0019 
0020 DEFINE_SIMPLE_ATTRIBUTE(vcpu_timer_advance_ns_fops, vcpu_get_timer_advance_ns, NULL, "%llu\n");
0021 
0022 static int vcpu_get_guest_mode(void *data, u64 *val)
0023 {
0024     struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
0025     *val = vcpu->stat.guest_mode;
0026     return 0;
0027 }
0028 
0029 DEFINE_SIMPLE_ATTRIBUTE(vcpu_guest_mode_fops, vcpu_get_guest_mode, NULL, "%lld\n");
0030 
0031 static int vcpu_get_tsc_offset(void *data, u64 *val)
0032 {
0033     struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
0034     *val = vcpu->arch.tsc_offset;
0035     return 0;
0036 }
0037 
0038 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_offset_fops, vcpu_get_tsc_offset, NULL, "%lld\n");
0039 
0040 static int vcpu_get_tsc_scaling_ratio(void *data, u64 *val)
0041 {
0042     struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data;
0043     *val = vcpu->arch.tsc_scaling_ratio;
0044     return 0;
0045 }
0046 
0047 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_fops, vcpu_get_tsc_scaling_ratio, NULL, "%llu\n");
0048 
0049 static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val)
0050 {
0051     *val = kvm_caps.tsc_scaling_ratio_frac_bits;
0052     return 0;
0053 }
0054 
0055 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_frac_fops, vcpu_get_tsc_scaling_frac_bits, NULL, "%llu\n");
0056 
0057 void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry)
0058 {
0059     debugfs_create_file("guest_mode", 0444, debugfs_dentry, vcpu,
0060                 &vcpu_guest_mode_fops);
0061     debugfs_create_file("tsc-offset", 0444, debugfs_dentry, vcpu,
0062                 &vcpu_tsc_offset_fops);
0063 
0064     if (lapic_in_kernel(vcpu))
0065         debugfs_create_file("lapic_timer_advance_ns", 0444,
0066                     debugfs_dentry, vcpu,
0067                     &vcpu_timer_advance_ns_fops);
0068 
0069     if (kvm_caps.has_tsc_control) {
0070         debugfs_create_file("tsc-scaling-ratio", 0444,
0071                     debugfs_dentry, vcpu,
0072                     &vcpu_tsc_scaling_fops);
0073         debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444,
0074                     debugfs_dentry, vcpu,
0075                     &vcpu_tsc_scaling_frac_fops);
0076     }
0077 }
0078 
0079 /*
0080  * This covers statistics <1024 (11=log(1024)+1), which should be enough to
0081  * cover RMAP_RECYCLE_THRESHOLD.
0082  */
0083 #define  RMAP_LOG_SIZE  11
0084 
0085 static const char *kvm_lpage_str[KVM_NR_PAGE_SIZES] = { "4K", "2M", "1G" };
0086 
0087 static int kvm_mmu_rmaps_stat_show(struct seq_file *m, void *v)
0088 {
0089     struct kvm_rmap_head *rmap;
0090     struct kvm *kvm = m->private;
0091     struct kvm_memory_slot *slot;
0092     struct kvm_memslots *slots;
0093     unsigned int lpage_size, index;
0094     /* Still small enough to be on the stack */
0095     unsigned int *log[KVM_NR_PAGE_SIZES], *cur;
0096     int i, j, k, l, ret;
0097 
0098     if (!kvm_memslots_have_rmaps(kvm))
0099         return 0;
0100 
0101     ret = -ENOMEM;
0102     memset(log, 0, sizeof(log));
0103     for (i = 0; i < KVM_NR_PAGE_SIZES; i++) {
0104         log[i] = kcalloc(RMAP_LOG_SIZE, sizeof(unsigned int), GFP_KERNEL);
0105         if (!log[i])
0106             goto out;
0107     }
0108 
0109     mutex_lock(&kvm->slots_lock);
0110     write_lock(&kvm->mmu_lock);
0111 
0112     for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) {
0113         int bkt;
0114 
0115         slots = __kvm_memslots(kvm, i);
0116         kvm_for_each_memslot(slot, bkt, slots)
0117             for (k = 0; k < KVM_NR_PAGE_SIZES; k++) {
0118                 rmap = slot->arch.rmap[k];
0119                 lpage_size = kvm_mmu_slot_lpages(slot, k + 1);
0120                 cur = log[k];
0121                 for (l = 0; l < lpage_size; l++) {
0122                     index = ffs(pte_list_count(&rmap[l]));
0123                     if (WARN_ON_ONCE(index >= RMAP_LOG_SIZE))
0124                         index = RMAP_LOG_SIZE - 1;
0125                     cur[index]++;
0126                 }
0127             }
0128     }
0129 
0130     write_unlock(&kvm->mmu_lock);
0131     mutex_unlock(&kvm->slots_lock);
0132 
0133     /* index=0 counts no rmap; index=1 counts 1 rmap */
0134     seq_printf(m, "Rmap_Count:\t0\t1\t");
0135     for (i = 2; i < RMAP_LOG_SIZE; i++) {
0136         j = 1 << (i - 1);
0137         k = (1 << i) - 1;
0138         seq_printf(m, "%d-%d\t", j, k);
0139     }
0140     seq_printf(m, "\n");
0141 
0142     for (i = 0; i < KVM_NR_PAGE_SIZES; i++) {
0143         seq_printf(m, "Level=%s:\t", kvm_lpage_str[i]);
0144         cur = log[i];
0145         for (j = 0; j < RMAP_LOG_SIZE; j++)
0146             seq_printf(m, "%d\t", cur[j]);
0147         seq_printf(m, "\n");
0148     }
0149 
0150     ret = 0;
0151 out:
0152     for (i = 0; i < KVM_NR_PAGE_SIZES; i++)
0153         kfree(log[i]);
0154 
0155     return ret;
0156 }
0157 
0158 static int kvm_mmu_rmaps_stat_open(struct inode *inode, struct file *file)
0159 {
0160     struct kvm *kvm = inode->i_private;
0161 
0162     if (!kvm_get_kvm_safe(kvm))
0163         return -ENOENT;
0164 
0165     return single_open(file, kvm_mmu_rmaps_stat_show, kvm);
0166 }
0167 
0168 static int kvm_mmu_rmaps_stat_release(struct inode *inode, struct file *file)
0169 {
0170     struct kvm *kvm = inode->i_private;
0171 
0172     kvm_put_kvm(kvm);
0173 
0174     return single_release(inode, file);
0175 }
0176 
0177 static const struct file_operations mmu_rmaps_stat_fops = {
0178     .open       = kvm_mmu_rmaps_stat_open,
0179     .read       = seq_read,
0180     .llseek     = seq_lseek,
0181     .release    = kvm_mmu_rmaps_stat_release,
0182 };
0183 
0184 int kvm_arch_create_vm_debugfs(struct kvm *kvm)
0185 {
0186     debugfs_create_file("mmu_rmaps_stat", 0644, kvm->debugfs_dentry, kvm,
0187                 &mmu_rmaps_stat_fops);
0188     return 0;
0189 }