forked from Minki/linux
KVM: stats: Support linear and logarithmic histogram statistics
Add new types of KVM stats, linear and logarithmic histogram. Histogram are very useful for observing the value distribution of time or size related stats. Signed-off-by: Jing Zhang <jingzhangos@google.com> Message-Id: <20210802165633.1866976-2-jingzhangos@google.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
73143035c2
commit
f95937ccf5
@ -31,8 +31,6 @@
|
||||
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
|
||||
KVM_GENERIC_VM_STATS()
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
|
||||
sizeof(struct kvm_vm_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vm_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
@ -52,8 +50,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VCPU, mmio_exit_kernel),
|
||||
STATS_DESC_COUNTER(VCPU, exits)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
sizeof(struct kvm_vcpu_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vcpu_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
|
@ -41,8 +41,6 @@
|
||||
const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
|
||||
KVM_GENERIC_VM_STATS()
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
|
||||
sizeof(struct kvm_vm_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vm_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
@ -85,8 +83,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VCPU, vz_cpucfg_exits),
|
||||
#endif
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
sizeof(struct kvm_vcpu_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vcpu_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
|
@ -43,8 +43,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
|
||||
STATS_DESC_ICOUNTER(VM, num_2M_pages),
|
||||
STATS_DESC_ICOUNTER(VM, num_1G_pages)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
|
||||
sizeof(struct kvm_vm_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vm_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
@ -88,8 +86,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VCPU, pthru_host),
|
||||
STATS_DESC_COUNTER(VCPU, pthru_bad_aff)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
sizeof(struct kvm_vcpu_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vcpu_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
|
@ -41,8 +41,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
|
||||
STATS_DESC_ICOUNTER(VM, num_2M_pages),
|
||||
STATS_DESC_ICOUNTER(VM, num_1G_pages)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
|
||||
sizeof(struct kvm_vm_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vm_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
@ -79,8 +77,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VCPU, pthru_host),
|
||||
STATS_DESC_COUNTER(VCPU, pthru_bad_aff)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
sizeof(struct kvm_vcpu_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vcpu_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
|
@ -66,8 +66,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VM, inject_service_signal),
|
||||
STATS_DESC_COUNTER(VM, inject_virtio)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
|
||||
sizeof(struct kvm_vm_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vm_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
@ -174,8 +172,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VCPU, instruction_diagnose_other),
|
||||
STATS_DESC_COUNTER(VCPU, pfault_sync)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
sizeof(struct kvm_vcpu_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vcpu_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
|
@ -238,8 +238,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
|
||||
STATS_DESC_PCOUNTER(VM, max_mmu_rmap_size),
|
||||
STATS_DESC_PCOUNTER(VM, max_mmu_page_hash_collisions)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vm_stats_desc) ==
|
||||
sizeof(struct kvm_vm_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vm_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
@ -279,8 +277,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
|
||||
STATS_DESC_COUNTER(VCPU, directed_yield_successful),
|
||||
STATS_DESC_ICOUNTER(VCPU, guest_mode)
|
||||
};
|
||||
static_assert(ARRAY_SIZE(kvm_vcpu_stats_desc) ==
|
||||
sizeof(struct kvm_vcpu_stat) / sizeof(u64));
|
||||
|
||||
const struct kvm_stats_header kvm_vcpu_stats_header = {
|
||||
.name_size = KVM_STATS_NAME_SIZE,
|
||||
|
@ -1356,56 +1356,66 @@ struct _kvm_stats_desc {
|
||||
char name[KVM_STATS_NAME_SIZE];
|
||||
};
|
||||
|
||||
#define STATS_DESC_COMMON(type, unit, base, exp) \
|
||||
#define STATS_DESC_COMMON(type, unit, base, exp, sz, bsz) \
|
||||
.flags = type | unit | base | \
|
||||
BUILD_BUG_ON_ZERO(type & ~KVM_STATS_TYPE_MASK) | \
|
||||
BUILD_BUG_ON_ZERO(unit & ~KVM_STATS_UNIT_MASK) | \
|
||||
BUILD_BUG_ON_ZERO(base & ~KVM_STATS_BASE_MASK), \
|
||||
.exponent = exp, \
|
||||
.size = 1
|
||||
.size = sz, \
|
||||
.bucket_size = bsz
|
||||
|
||||
#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp) \
|
||||
#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
|
||||
{ \
|
||||
{ \
|
||||
STATS_DESC_COMMON(type, unit, base, exp), \
|
||||
STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
|
||||
.offset = offsetof(struct kvm_vm_stat, generic.stat) \
|
||||
}, \
|
||||
.name = #stat, \
|
||||
}
|
||||
#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp) \
|
||||
#define VCPU_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
|
||||
{ \
|
||||
{ \
|
||||
STATS_DESC_COMMON(type, unit, base, exp), \
|
||||
STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
|
||||
.offset = offsetof(struct kvm_vcpu_stat, generic.stat) \
|
||||
}, \
|
||||
.name = #stat, \
|
||||
}
|
||||
#define VM_STATS_DESC(stat, type, unit, base, exp) \
|
||||
#define VM_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
|
||||
{ \
|
||||
{ \
|
||||
STATS_DESC_COMMON(type, unit, base, exp), \
|
||||
STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
|
||||
.offset = offsetof(struct kvm_vm_stat, stat) \
|
||||
}, \
|
||||
.name = #stat, \
|
||||
}
|
||||
#define VCPU_STATS_DESC(stat, type, unit, base, exp) \
|
||||
#define VCPU_STATS_DESC(stat, type, unit, base, exp, sz, bsz) \
|
||||
{ \
|
||||
{ \
|
||||
STATS_DESC_COMMON(type, unit, base, exp), \
|
||||
STATS_DESC_COMMON(type, unit, base, exp, sz, bsz), \
|
||||
.offset = offsetof(struct kvm_vcpu_stat, stat) \
|
||||
}, \
|
||||
.name = #stat, \
|
||||
}
|
||||
/* SCOPE: VM, VM_GENERIC, VCPU, VCPU_GENERIC */
|
||||
#define STATS_DESC(SCOPE, stat, type, unit, base, exp) \
|
||||
SCOPE##_STATS_DESC(stat, type, unit, base, exp)
|
||||
#define STATS_DESC(SCOPE, stat, type, unit, base, exp, sz, bsz) \
|
||||
SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, bsz)
|
||||
|
||||
#define STATS_DESC_CUMULATIVE(SCOPE, name, unit, base, exponent) \
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_CUMULATIVE, unit, base, exponent)
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_CUMULATIVE, \
|
||||
unit, base, exponent, 1, 0)
|
||||
#define STATS_DESC_INSTANT(SCOPE, name, unit, base, exponent) \
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_INSTANT, unit, base, exponent)
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_INSTANT, \
|
||||
unit, base, exponent, 1, 0)
|
||||
#define STATS_DESC_PEAK(SCOPE, name, unit, base, exponent) \
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_PEAK, unit, base, exponent)
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_PEAK, \
|
||||
unit, base, exponent, 1, 0)
|
||||
#define STATS_DESC_LINEAR_HIST(SCOPE, name, unit, base, exponent, sz, bsz) \
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST, \
|
||||
unit, base, exponent, sz, bsz)
|
||||
#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz) \
|
||||
STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST, \
|
||||
unit, base, exponent, sz, 0)
|
||||
|
||||
/* Cumulative counter, read/write */
|
||||
#define STATS_DESC_COUNTER(SCOPE, name) \
|
||||
@ -1424,6 +1434,14 @@ struct _kvm_stats_desc {
|
||||
#define STATS_DESC_TIME_NSEC(SCOPE, name) \
|
||||
STATS_DESC_CUMULATIVE(SCOPE, name, KVM_STATS_UNIT_SECONDS, \
|
||||
KVM_STATS_BASE_POW10, -9)
|
||||
/* Linear histogram for time in nanosecond */
|
||||
#define STATS_DESC_LINHIST_TIME_NSEC(SCOPE, name, sz, bsz) \
|
||||
STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS, \
|
||||
KVM_STATS_BASE_POW10, -9, sz, bsz)
|
||||
/* Logarithmic histogram for time in nanosecond */
|
||||
#define STATS_DESC_LOGHIST_TIME_NSEC(SCOPE, name, sz) \
|
||||
STATS_DESC_LOG_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS, \
|
||||
KVM_STATS_BASE_POW10, -9, sz)
|
||||
|
||||
#define KVM_GENERIC_VM_STATS() \
|
||||
STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
|
||||
@ -1437,10 +1455,52 @@ struct _kvm_stats_desc {
|
||||
STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
|
||||
|
||||
extern struct dentry *kvm_debugfs_dir;
|
||||
|
||||
ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
|
||||
const struct _kvm_stats_desc *desc,
|
||||
void *stats, size_t size_stats,
|
||||
char __user *user_buffer, size_t size, loff_t *offset);
|
||||
|
||||
/**
|
||||
* kvm_stats_linear_hist_update() - Update bucket value for linear histogram
|
||||
* statistics data.
|
||||
*
|
||||
* @data: start address of the stats data
|
||||
* @size: the number of bucket of the stats data
|
||||
* @value: the new value used to update the linear histogram's bucket
|
||||
* @bucket_size: the size (width) of a bucket
|
||||
*/
|
||||
static inline void kvm_stats_linear_hist_update(u64 *data, size_t size,
|
||||
u64 value, size_t bucket_size)
|
||||
{
|
||||
size_t index = div64_u64(value, bucket_size);
|
||||
|
||||
index = min(index, size - 1);
|
||||
++data[index];
|
||||
}
|
||||
|
||||
/**
|
||||
* kvm_stats_log_hist_update() - Update bucket value for logarithmic histogram
|
||||
* statistics data.
|
||||
*
|
||||
* @data: start address of the stats data
|
||||
* @size: the number of bucket of the stats data
|
||||
* @value: the new value used to update the logarithmic histogram's bucket
|
||||
*/
|
||||
static inline void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
|
||||
{
|
||||
size_t index = fls64(value);
|
||||
|
||||
index = min(index, size - 1);
|
||||
++data[index];
|
||||
}
|
||||
|
||||
#define KVM_STATS_LINEAR_HIST_UPDATE(array, value, bsize) \
|
||||
kvm_stats_linear_hist_update(array, ARRAY_SIZE(array), value, bsize)
|
||||
#define KVM_STATS_LOG_HIST_UPDATE(array, value) \
|
||||
kvm_stats_log_hist_update(array, ARRAY_SIZE(array), value)
|
||||
|
||||
|
||||
extern const struct kvm_stats_header kvm_vm_stats_header;
|
||||
extern const struct _kvm_stats_desc kvm_vm_stats_desc[];
|
||||
extern const struct kvm_stats_header kvm_vcpu_stats_header;
|
||||
|
@ -1965,7 +1965,9 @@ struct kvm_stats_header {
|
||||
#define KVM_STATS_TYPE_CUMULATIVE (0x0 << KVM_STATS_TYPE_SHIFT)
|
||||
#define KVM_STATS_TYPE_INSTANT (0x1 << KVM_STATS_TYPE_SHIFT)
|
||||
#define KVM_STATS_TYPE_PEAK (0x2 << KVM_STATS_TYPE_SHIFT)
|
||||
#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_PEAK
|
||||
#define KVM_STATS_TYPE_LINEAR_HIST (0x3 << KVM_STATS_TYPE_SHIFT)
|
||||
#define KVM_STATS_TYPE_LOG_HIST (0x4 << KVM_STATS_TYPE_SHIFT)
|
||||
#define KVM_STATS_TYPE_MAX KVM_STATS_TYPE_LOG_HIST
|
||||
|
||||
#define KVM_STATS_UNIT_SHIFT 4
|
||||
#define KVM_STATS_UNIT_MASK (0xF << KVM_STATS_UNIT_SHIFT)
|
||||
@ -1988,8 +1990,9 @@ struct kvm_stats_header {
|
||||
* @size: The number of data items for this stats.
|
||||
* Every data item is of type __u64.
|
||||
* @offset: The offset of the stats to the start of stat structure in
|
||||
* struture kvm or kvm_vcpu.
|
||||
* @unused: Unused field for future usage. Always 0 for now.
|
||||
* structure kvm or kvm_vcpu.
|
||||
* @bucket_size: A parameter value used for histogram stats. It is only used
|
||||
* for linear histogram stats, specifying the size of the bucket;
|
||||
* @name: The name string for the stats. Its size is indicated by the
|
||||
* &kvm_stats_header->name_size.
|
||||
*/
|
||||
@ -1998,7 +2001,7 @@ struct kvm_stats_desc {
|
||||
__s16 exponent;
|
||||
__u16 size;
|
||||
__u32 offset;
|
||||
__u32 unused;
|
||||
__u32 bucket_size;
|
||||
char name[];
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user