提交 560c628b 编写于 作者: C chenjiajun 提交者: Xie XiuQi

kvm: debugfs: Export vcpu stat via debugfs

virt inclusion
category: feature
bugzilla: 46853
CVE: NA

This patch create debugfs entry for vcpu stat.
The entry path is /sys/kernel/debug/kvm/vcpu_stat.
And vcpu_stat contains partial kvm exits items of vcpu, include:
	pid, hvc_exit_stat, wfe_exit_stat, wfi_exit_stat,
	mmio_exit_user, mmio_exit_kernel, exits

Currently, The maximum vcpu limit is 1024.

From this vcpu_stat, user can get the number of these kvm exits items
over a period of time, which is helpful to monitor the virtual machine.
Signed-off-by: NZenghui Yu <yuzenghui@huawei.com>
Signed-off-by: Nchenjiajun <chenjiajun8@huawei.com>
Reviewed-by: NXiangyou Xie <xiexiangyou@huawei.com>
Acked-by: NXie XiuQi <xiexiuqi@huawei.com>
Signed-off-by: NChen Jun <chenjun102@huawei.com>
上级 bb420cf9
...@@ -455,6 +455,7 @@ struct kvm_vm_stat { ...@@ -455,6 +455,7 @@ struct kvm_vm_stat {
}; };
struct kvm_vcpu_stat { struct kvm_vcpu_stat {
u64 pid;
u64 halt_successful_poll; u64 halt_successful_poll;
u64 halt_attempted_poll; u64 halt_attempted_poll;
u64 halt_poll_success_ns; u64 halt_poll_success_ns;
......
...@@ -42,6 +42,19 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { ...@@ -42,6 +42,19 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
VCPU_STAT("exits", exits), VCPU_STAT("exits", exits),
VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns), VCPU_STAT("halt_poll_success_ns", halt_poll_success_ns),
VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns), VCPU_STAT("halt_poll_fail_ns", halt_poll_fail_ns),
{ "vcpu_stat", 0, KVM_STAT_DFX },
{ NULL }
};
/* debugfs entries of Detail For vcpu stat EXtension */
struct dfx_kvm_stats_debugfs_item dfx_debugfs_entries[] = {
DFX_STAT("pid", pid),
DFX_STAT("hvc_exit_stat", hvc_exit_stat),
DFX_STAT("wfe_exit_stat", wfe_exit_stat),
DFX_STAT("wfi_exit_stat", wfi_exit_stat),
DFX_STAT("mmio_exit_user", mmio_exit_user),
DFX_STAT("mmio_exit_kernel", mmio_exit_kernel),
DFX_STAT("exits", exits),
{ NULL } { NULL }
}; };
......
...@@ -1028,6 +1028,7 @@ struct kvm_vm_stat { ...@@ -1028,6 +1028,7 @@ struct kvm_vm_stat {
}; };
struct kvm_vcpu_stat { struct kvm_vcpu_stat {
u64 pid;
u64 pf_fixed; u64 pf_fixed;
u64 pf_guest; u64 pf_guest;
u64 tlb_flush; u64 tlb_flush;
......
...@@ -245,6 +245,11 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { ...@@ -245,6 +245,11 @@ struct kvm_stats_debugfs_item debugfs_entries[] = {
{ NULL } { NULL }
}; };
/* debugfs entries of Detail For vcpu stat EXtension */
struct dfx_kvm_stats_debugfs_item dfx_debugfs_entries[] = {
{ NULL }
};
u64 __read_mostly host_xcr0; u64 __read_mostly host_xcr0;
u64 __read_mostly supported_xcr0; u64 __read_mostly supported_xcr0;
EXPORT_SYMBOL_GPL(supported_xcr0); EXPORT_SYMBOL_GPL(supported_xcr0);
......
...@@ -1151,6 +1151,7 @@ static inline bool kvm_is_error_gpa(struct kvm *kvm, gpa_t gpa) ...@@ -1151,6 +1151,7 @@ static inline bool kvm_is_error_gpa(struct kvm *kvm, gpa_t gpa)
enum kvm_stat_kind { enum kvm_stat_kind {
KVM_STAT_VM, KVM_STAT_VM,
KVM_STAT_VCPU, KVM_STAT_VCPU,
KVM_STAT_DFX, /* Detail For vcpu stat EXtension */
}; };
struct kvm_stat_data { struct kvm_stat_data {
...@@ -1172,10 +1173,26 @@ struct kvm_stats_debugfs_item { ...@@ -1172,10 +1173,26 @@ struct kvm_stats_debugfs_item {
{ n, offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__ } { n, offsetof(struct kvm, stat.x), KVM_STAT_VM, ## __VA_ARGS__ }
#define VCPU_STAT(n, x, ...) \ #define VCPU_STAT(n, x, ...) \
{ n, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__ } { n, offsetof(struct kvm_vcpu, stat.x), KVM_STAT_VCPU, ## __VA_ARGS__ }
#define DFX_STAT(n, x, ...) \
{ n, offsetof(struct kvm_vcpu_stat, x), DFX_STAT_U64, ## __VA_ARGS__ }
extern struct kvm_stats_debugfs_item debugfs_entries[]; extern struct kvm_stats_debugfs_item debugfs_entries[];
extern struct dentry *kvm_debugfs_dir; extern struct dentry *kvm_debugfs_dir;
enum dfx_stat_kind {
DFX_STAT_U64,
DFX_STAT_CPUTIME,
};
/* Detail For vcpu stat EXtension debugfs item */
struct dfx_kvm_stats_debugfs_item {
const char *name;
int offset;
enum dfx_stat_kind dfx_kind;
struct dentry *dentry;
};
extern struct dfx_kvm_stats_debugfs_item dfx_debugfs_entries[];
#if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER) #if defined(CONFIG_MMU_NOTIFIER) && defined(KVM_ARCH_WANT_MMU_NOTIFIER)
static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq) static inline int mmu_notifier_retry(struct kvm *kvm, unsigned long mmu_seq)
{ {
......
...@@ -152,6 +152,11 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm); ...@@ -152,6 +152,11 @@ static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm);
static unsigned long long kvm_createvm_count; static unsigned long long kvm_createvm_count;
static unsigned long long kvm_active_vms; static unsigned long long kvm_active_vms;
/* debugfs entries of Detail For vcpu stat EXtension */
__weak struct dfx_kvm_stats_debugfs_item dfx_debugfs_entries[] = {
{ NULL }
};
__weak void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm, __weak void kvm_arch_mmu_notifier_invalidate_range(struct kvm *kvm,
unsigned long start, unsigned long end) unsigned long start, unsigned long end)
{ {
...@@ -3230,6 +3235,9 @@ static long kvm_vcpu_ioctl(struct file *filp, ...@@ -3230,6 +3235,9 @@ static long kvm_vcpu_ioctl(struct file *filp,
if (oldpid) if (oldpid)
synchronize_rcu(); synchronize_rcu();
put_pid(oldpid); put_pid(oldpid);
#if defined(CONFIG_X86) || defined(CONFIG_ARM64)
vcpu->stat.pid = current->pid;
#endif /* defined(CONFIG_X86) || defined (CONFIG_ARM64) */
} }
r = kvm_arch_vcpu_ioctl_run(vcpu); r = kvm_arch_vcpu_ioctl_run(vcpu);
trace_kvm_userspace_exit(vcpu->run->exit_reason, r); trace_kvm_userspace_exit(vcpu->run->exit_reason, r);
...@@ -4488,6 +4496,9 @@ static int kvm_stat_data_get(void *data, u64 *val) ...@@ -4488,6 +4496,9 @@ static int kvm_stat_data_get(void *data, u64 *val)
r = kvm_get_stat_per_vcpu(stat_data->kvm, r = kvm_get_stat_per_vcpu(stat_data->kvm,
stat_data->dbgfs_item->offset, val); stat_data->dbgfs_item->offset, val);
break; break;
case KVM_STAT_DFX:
r = -ENOSYS;
break;
} }
return r; return r;
...@@ -4510,6 +4521,9 @@ static int kvm_stat_data_clear(void *data, u64 val) ...@@ -4510,6 +4521,9 @@ static int kvm_stat_data_clear(void *data, u64 val)
r = kvm_clear_stat_per_vcpu(stat_data->kvm, r = kvm_clear_stat_per_vcpu(stat_data->kvm,
stat_data->dbgfs_item->offset); stat_data->dbgfs_item->offset);
break; break;
case KVM_STAT_DFX:
r = -ENOSYS;
break;
} }
return r; return r;
...@@ -4602,9 +4616,80 @@ static int vcpu_stat_clear(void *_offset, u64 val) ...@@ -4602,9 +4616,80 @@ static int vcpu_stat_clear(void *_offset, u64 val)
DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, vcpu_stat_clear, DEFINE_SIMPLE_ATTRIBUTE(vcpu_stat_fops, vcpu_stat_get, vcpu_stat_clear,
"%llu\n"); "%llu\n");
#define DFX_MAX_VCPU 1024
#define DFX_MAX_VCPU_STAT_SIZE 1024
static int __dfx_vcpu_stats_get(struct seq_file *p, void *v)
{
struct kvm *kvm;
struct kvm_vcpu *vcpu;
struct kvm_vcpu_stat *vcpu_stats;
struct dfx_kvm_stats_debugfs_item *dp;
int vcpu_nr = 0;
int i, index = 0;
mutex_lock(&kvm_lock);
list_for_each_entry(kvm, &vm_list, vm_list)
kvm_for_each_vcpu(i, vcpu, kvm)
vcpu_nr++;
mutex_unlock(&kvm_lock);
vcpu_nr = min(vcpu_nr, DFX_MAX_VCPU);
vcpu_stats = vmalloc(vcpu_nr * sizeof(struct kvm_vcpu_stat));
if (!vcpu_stats)
return -ENOMEM;
mutex_lock(&kvm_lock);
list_for_each_entry(kvm, &vm_list, vm_list)
kvm_for_each_vcpu(i, vcpu, kvm) {
if (index >= vcpu_nr)
break;
memcpy(vcpu_stats + index, &vcpu->stat,
sizeof(struct kvm_vcpu_stat));
++index;
}
mutex_unlock(&kvm_lock);
for (i = 0; i < vcpu_nr; i++) {
for (dp = dfx_debugfs_entries; dp->name; ++dp) {
switch (dp->dfx_kind) {
case DFX_STAT_U64:
seq_put_decimal_ull(p, " ",
*(u64 *)((void *)&vcpu_stats[i] + dp->offset));
break;
case DFX_STAT_CPUTIME:
pr_warn("DFX_STAT_CPUTIME not supported currently!");
break;
default:
pr_warn("Bad dfx_kind in dfx_debugfs_entries!");
break;
}
}
seq_putc(p, '\n');
}
vfree(vcpu_stats);
return 0;
}
static int dfx_vcpu_stats_open(struct inode *inode, struct file *file)
{
size_t size = DFX_MAX_VCPU_STAT_SIZE * (DFX_MAX_VCPU + 1);
return single_open_size(file, __dfx_vcpu_stats_get, NULL, size);
}
static const struct file_operations dfx_stat_fops = {
.open = dfx_vcpu_stats_open,
.read = seq_read,
.llseek = seq_lseek,
.release = single_release,
};
static const struct file_operations *stat_fops[] = { static const struct file_operations *stat_fops[] = {
[KVM_STAT_VCPU] = &vcpu_stat_fops, [KVM_STAT_VCPU] = &vcpu_stat_fops,
[KVM_STAT_VM] = &vm_stat_fops, [KVM_STAT_VM] = &vm_stat_fops,
[KVM_STAT_DFX] = &dfx_stat_fops,
}; };
static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm) static void kvm_uevent_notify_change(unsigned int type, struct kvm *kvm)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册