1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * Kernel-based Virtual Machine driver for Linux 4 * 5 * Copyright 2016 Red Hat, Inc. and/or its affiliates. 6 */ 7 #include <linux/kvm_host.h> 8 #include <linux/debugfs.h> 9 #include "lapic.h" 10 #include "mmu.h" 11 #include "mmu/mmu_internal.h" 12 13 static int vcpu_get_timer_advance_ns(void *data, u64 *val) 14 { 15 struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data; 16 *val = vcpu->arch.apic->lapic_timer.timer_advance_ns; 17 return 0; 18 } 19 20 DEFINE_SIMPLE_ATTRIBUTE(vcpu_timer_advance_ns_fops, vcpu_get_timer_advance_ns, NULL, "%llu\n"); 21 22 static int vcpu_get_guest_mode(void *data, u64 *val) 23 { 24 struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data; 25 *val = vcpu->stat.guest_mode; 26 return 0; 27 } 28 29 DEFINE_SIMPLE_ATTRIBUTE(vcpu_guest_mode_fops, vcpu_get_guest_mode, NULL, "%lld\n"); 30 31 static int vcpu_get_tsc_offset(void *data, u64 *val) 32 { 33 struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data; 34 *val = vcpu->arch.tsc_offset; 35 return 0; 36 } 37 38 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_offset_fops, vcpu_get_tsc_offset, NULL, "%lld\n"); 39 40 static int vcpu_get_tsc_scaling_ratio(void *data, u64 *val) 41 { 42 struct kvm_vcpu *vcpu = (struct kvm_vcpu *) data; 43 *val = vcpu->arch.tsc_scaling_ratio; 44 return 0; 45 } 46 47 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_fops, vcpu_get_tsc_scaling_ratio, NULL, "%llu\n"); 48 49 static int vcpu_get_tsc_scaling_frac_bits(void *data, u64 *val) 50 { 51 *val = kvm_tsc_scaling_ratio_frac_bits; 52 return 0; 53 } 54 55 DEFINE_SIMPLE_ATTRIBUTE(vcpu_tsc_scaling_frac_fops, vcpu_get_tsc_scaling_frac_bits, NULL, "%llu\n"); 56 57 void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_dentry) 58 { 59 debugfs_create_file("guest_mode", 0444, debugfs_dentry, vcpu, 60 &vcpu_guest_mode_fops); 61 debugfs_create_file("tsc-offset", 0444, debugfs_dentry, vcpu, 62 &vcpu_tsc_offset_fops); 63 64 if (lapic_in_kernel(vcpu)) 65 debugfs_create_file("lapic_timer_advance_ns", 0444, 66 debugfs_dentry, vcpu, 67 &vcpu_timer_advance_ns_fops); 68 69 if (kvm_has_tsc_control) { 70 debugfs_create_file("tsc-scaling-ratio", 0444, 71 debugfs_dentry, vcpu, 72 &vcpu_tsc_scaling_fops); 73 debugfs_create_file("tsc-scaling-ratio-frac-bits", 0444, 74 debugfs_dentry, vcpu, 75 &vcpu_tsc_scaling_frac_fops); 76 } 77 } 78 79 /* 80 * This covers statistics <1024 (11=log(1024)+1), which should be enough to 81 * cover RMAP_RECYCLE_THRESHOLD. 82 */ 83 #define RMAP_LOG_SIZE 11 84 85 static const char *kvm_lpage_str[KVM_NR_PAGE_SIZES] = { "4K", "2M", "1G" }; 86 87 static int kvm_mmu_rmaps_stat_show(struct seq_file *m, void *v) 88 { 89 struct kvm_rmap_head *rmap; 90 struct kvm *kvm = m->private; 91 struct kvm_memory_slot *slot; 92 struct kvm_memslots *slots; 93 unsigned int lpage_size, index; 94 /* Still small enough to be on the stack */ 95 unsigned int *log[KVM_NR_PAGE_SIZES], *cur; 96 int i, j, k, l, ret; 97 98 ret = -ENOMEM; 99 memset(log, 0, sizeof(log)); 100 for (i = 0; i < KVM_NR_PAGE_SIZES; i++) { 101 log[i] = kcalloc(RMAP_LOG_SIZE, sizeof(unsigned int), GFP_KERNEL); 102 if (!log[i]) 103 goto out; 104 } 105 106 mutex_lock(&kvm->slots_lock); 107 write_lock(&kvm->mmu_lock); 108 109 for (i = 0; i < KVM_ADDRESS_SPACE_NUM; i++) { 110 slots = __kvm_memslots(kvm, i); 111 for (j = 0; j < slots->used_slots; j++) { 112 slot = &slots->memslots[j]; 113 for (k = 0; k < KVM_NR_PAGE_SIZES; k++) { 114 rmap = slot->arch.rmap[k]; 115 lpage_size = kvm_mmu_slot_lpages(slot, k + 1); 116 cur = log[k]; 117 for (l = 0; l < lpage_size; l++) { 118 index = ffs(pte_list_count(&rmap[l])); 119 if (WARN_ON_ONCE(index >= RMAP_LOG_SIZE)) 120 index = RMAP_LOG_SIZE - 1; 121 cur[index]++; 122 } 123 } 124 } 125 } 126 127 write_unlock(&kvm->mmu_lock); 128 mutex_unlock(&kvm->slots_lock); 129 130 /* index=0 counts no rmap; index=1 counts 1 rmap */ 131 seq_printf(m, "Rmap_Count:\t0\t1\t"); 132 for (i = 2; i < RMAP_LOG_SIZE; i++) { 133 j = 1 << (i - 1); 134 k = (1 << i) - 1; 135 seq_printf(m, "%d-%d\t", j, k); 136 } 137 seq_printf(m, "\n"); 138 139 for (i = 0; i < KVM_NR_PAGE_SIZES; i++) { 140 seq_printf(m, "Level=%s:\t", kvm_lpage_str[i]); 141 cur = log[i]; 142 for (j = 0; j < RMAP_LOG_SIZE; j++) 143 seq_printf(m, "%d\t", cur[j]); 144 seq_printf(m, "\n"); 145 } 146 147 ret = 0; 148 out: 149 for (i = 0; i < KVM_NR_PAGE_SIZES; i++) 150 kfree(log[i]); 151 152 return ret; 153 } 154 155 static int kvm_mmu_rmaps_stat_open(struct inode *inode, struct file *file) 156 { 157 struct kvm *kvm = inode->i_private; 158 159 if (!kvm_get_kvm_safe(kvm)) 160 return -ENOENT; 161 162 return single_open(file, kvm_mmu_rmaps_stat_show, kvm); 163 } 164 165 static int kvm_mmu_rmaps_stat_release(struct inode *inode, struct file *file) 166 { 167 struct kvm *kvm = inode->i_private; 168 169 kvm_put_kvm(kvm); 170 171 return single_release(inode, file); 172 } 173 174 static const struct file_operations mmu_rmaps_stat_fops = { 175 .open = kvm_mmu_rmaps_stat_open, 176 .read = seq_read, 177 .llseek = seq_lseek, 178 .release = kvm_mmu_rmaps_stat_release, 179 }; 180 181 int kvm_arch_create_vm_debugfs(struct kvm *kvm) 182 { 183 debugfs_create_file("mmu_rmaps_stat", 0644, kvm->debugfs_dentry, kvm, 184 &mmu_rmaps_stat_fops); 185 return 0; 186 } 187