|
7 | 7 | #include <linux/kvm_host.h>
|
8 | 8 | #include <linux/debugfs.h>
|
9 | 9 | #include "lapic.h"
|
| 10 | +#include "mmu.h" |
| 11 | +#include "mmu/mmu_internal.h" |
10 | 12 |
|
11 | 13 | static int vcpu_get_timer_advance_ns(void *data, u64 *val)
|
12 | 14 | {
|
@@ -73,3 +75,112 @@ void kvm_arch_create_vcpu_debugfs(struct kvm_vcpu *vcpu, struct dentry *debugfs_
|
73 | 75 | &vcpu_tsc_scaling_frac_fops);
|
74 | 76 | }
|
75 | 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 | +} |
0 commit comments