All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH v1 0/4] Linear and Logarithmic histogram statistics
@ 2021-07-06 18:03 ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

This patchset adds linear and logarithmic histogram stats support and extend
some halt polling stats with histogram.
Histogram stats is very useful when we need to know the distribution of some
latencies or any other stuff like used memory size, huge page size, etc.
Below is a snapshot for three logarithmic histogram stats added in this
patchset. halt_poll_success_hist shows the distribution of wait time before a
success polling. halt_poll_fail_hist shows the distribution of wait time before
a fail polling. halt_wait_hist shows the distribution of wait time of a VCPU
spending on wait after it is halted. The halt polling parameters is halt_poll_ns
= 500000, halt_poll_ns_grow = 2, halt_poll_ns_grow_start = 10000,
halt_poll_ns_shrink = 2;
From the snapshot, not only we can get an intuitive overview of those latencies,
but also we can tune the polling parameters based on this; For example, it shows
that about 80% of successful polling is less than 132000 nanoseconds from
halt_poll_success_hist, then it might be a good option to set halt_poll_ns as
132000 instead of 500000.

halt_poll_success_hist:
Range		Bucket Value	Percent     Cumulative Percent
[0, 1)		 0		 0.000%      0.000%
[1, 2)		 0		 0.000%      0.000%
[2, 4)		 0		 0.000%      0.000%
[4, 8)		 0		 0.000%      0.000%
[8, 16)		 0		 0.000%      0.000%
[16, 32)	 0		 0.000%      0.000%
[32, 64)	 0		 0.000%      0.000%
[64, 128)	 0		 0.000%      0.000%
[128, 256)	 3		 0.093%      0.093%
[256, 512)	 21		 0.650%      0.743%
[512, 1024)	 43		 1.330%      2.073%
[1024, 2048)	 279		 8.632%      10.705%
[2048, 4096)	 253		 7.828%      18.533%
[4096, 8192)	 595		 18.410%     36.943%
[8192, 16384)	 274		 8.478%      45.421%
[16384, 32768)	 351		 10.860%     56.281%
[32768, 65536)	 343		 10.613%     66.894%
[65536, 131072)  421		 13.026%     79.920%
[131072, 262144) 459		 14.202%     94.121%
[262144, 524288) 190		 5.879%      100.000%


halt_poll_fail_hist:
Range		Bucket Value	Percent     Cumulative Percent
[0, 1)		 0		 0.000%      0.000%
[1, 2)		 0		 0.000%      0.000%
[2, 4)		 0		 0.000%      0.000%
[4, 8)		 0		 0.000%      0.000%
[8, 16)		 0		 0.000%      0.000%
[16, 32)	 0		 0.000%      0.000%
[32, 64)	 0		 0.000%      0.000%
[64, 128)	 21		 0.529%      0.529%
[128, 256)	 398		 10.020%     10.549%
[256, 512)	 613		 15.433%     25.982%
[512, 1024)	 437		 11.002%     36.984%
[1024, 2048)	 264		 6.647%      43.630%
[2048, 4096)	 302		 7.603%      51.234%
[4096, 8192)	 350		 8.812%      60.045%
[8192, 16384)	 488		 12.286%     72.331%
[16384, 32768)	 258		 6.495%      78.827%
[32768, 65536)	 227		 5.715%      84.542%
[65536, 131072)  232		 5.841%      90.383%
[131072, 262144) 246		 6.193%      96.576%
[262144, 524288) 136		 3.424%      100.000%


halt_wait_hist:
Range			    Bucket Value    Percent	Cumulative Percent
[0, 1)			     0		     0.000%	 0.000%
[1, 2)			     0		     0.000%	 0.000%
[2, 4)			     0		     0.000%	 0.000%
[4, 8)			     0		     0.000%	 0.000%
[8, 16)			     0		     0.000%	 0.000%
[16, 32)		     0		     0.000%	 0.000%
[32, 64)		     0		     0.000%	 0.000%
[64, 128)		     0		     0.000%	 0.000%
[128, 256)		     0		     0.000%	 0.000%
[256, 512)		     0		     0.000%	 0.000%
[512, 1024)		     0		     0.000%	 0.000%
[1024, 2048)		     0		     0.000%	 0.000%
[2048, 4096)		     7		     0.127%	 0.127%
[4096, 8192)		     37		     0.671%	 0.798%
[8192, 16384)		     69		     1.251%	 2.049%
[16384, 32768)		     94		     1.704%	 3.753%
[32768, 65536)		     150	     2.719%	 6.472%
[65536, 131072)		     233	     4.224%	 10.696%
[131072, 262144)	     276	     5.004%	 15.700%
[262144, 524288)	     236	     4.278%	 19.978%
[524288, 1.04858e+06)	     176	     3.191%	 23.169%
[1.04858e+06, 2.09715e+06)   94		     16.207%	 39.376%
[2.09715e+06, 4.1943e+06)    1667	     30.221%	 69.598%
[4.1943e+06, 8.38861e+06)    825	     14.956%	 84.554%
[8.38861e+06, 1.67772e+07)   111	     2.012%	 86.566%
[1.67772e+07, 3.35544e+07)   76		     1.378%	 87.944%
[3.35544e+07, 6.71089e+07)   65		     1.178%	 89.123%
[6.71089e+07, 1.34218e+08)   161	     2.919%	 92.041%
[1.34218e+08, 2.68435e+08)   250	     4.532%	 96.574%
[2.68435e+08, 5.36871e+08)   188	     3.408%	 99.982%
[5.36871e+08, 1.07374e+09)   1		     0.018%	 100.000%

---

Jing Zhang (4):
  KVM: stats: Support linear and logarithmic histogram statistics
  KVM: stats: Update doc for histogram statistics
  KVM: selftests: Add checks for histogram stats parameters
  KVM: stats: Add halt polling related histogram stats

 Documentation/virt/kvm/api.rst                | 36 ++++++++++-
 arch/arm64/kvm/guest.c                        |  4 --
 arch/mips/kvm/mips.c                          |  4 --
 arch/powerpc/include/asm/kvm_host.h           |  1 -
 arch/powerpc/kvm/book3s.c                     |  5 --
 arch/powerpc/kvm/book3s_hv.c                  | 20 +++++-
 arch/powerpc/kvm/booke.c                      |  5 --
 arch/s390/kvm/kvm-s390.c                      |  4 --
 arch/x86/kvm/x86.c                            |  4 --
 include/linux/kvm_host.h                      | 62 ++++++++++++++-----
 include/linux/kvm_types.h                     | 20 ++++++
 include/uapi/linux/kvm.h                      | 11 +++-
 .../selftests/kvm/kvm_binary_stats_test.c     | 17 +++++
 virt/kvm/binary_stats.c                       | 36 +++++++++++
 virt/kvm/kvm_main.c                           | 19 ++++++
 15 files changed, 196 insertions(+), 52 deletions(-)


base-commit: 7caa04b36f204a01dac65582b71d26d190a1e022
-- 
2.32.0.93.g670b81a890-goog


^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH v1 0/4] Linear and Logarithmic histogram statistics
@ 2021-07-06 18:03 ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

This patchset adds linear and logarithmic histogram stats support and extend
some halt polling stats with histogram.
Histogram stats is very useful when we need to know the distribution of some
latencies or any other stuff like used memory size, huge page size, etc.
Below is a snapshot for three logarithmic histogram stats added in this
patchset. halt_poll_success_hist shows the distribution of wait time before a
success polling. halt_poll_fail_hist shows the distribution of wait time before
a fail polling. halt_wait_hist shows the distribution of wait time of a VCPU
spending on wait after it is halted. The halt polling parameters is halt_poll_ns
= 500000, halt_poll_ns_grow = 2, halt_poll_ns_grow_start = 10000,
halt_poll_ns_shrink = 2;
From the snapshot, not only we can get an intuitive overview of those latencies,
but also we can tune the polling parameters based on this; For example, it shows
that about 80% of successful polling is less than 132000 nanoseconds from
halt_poll_success_hist, then it might be a good option to set halt_poll_ns as
132000 instead of 500000.

halt_poll_success_hist:
Range		Bucket Value	Percent     Cumulative Percent
[0, 1)		 0		 0.000%      0.000%
[1, 2)		 0		 0.000%      0.000%
[2, 4)		 0		 0.000%      0.000%
[4, 8)		 0		 0.000%      0.000%
[8, 16)		 0		 0.000%      0.000%
[16, 32)	 0		 0.000%      0.000%
[32, 64)	 0		 0.000%      0.000%
[64, 128)	 0		 0.000%      0.000%
[128, 256)	 3		 0.093%      0.093%
[256, 512)	 21		 0.650%      0.743%
[512, 1024)	 43		 1.330%      2.073%
[1024, 2048)	 279		 8.632%      10.705%
[2048, 4096)	 253		 7.828%      18.533%
[4096, 8192)	 595		 18.410%     36.943%
[8192, 16384)	 274		 8.478%      45.421%
[16384, 32768)	 351		 10.860%     56.281%
[32768, 65536)	 343		 10.613%     66.894%
[65536, 131072)  421		 13.026%     79.920%
[131072, 262144) 459		 14.202%     94.121%
[262144, 524288) 190		 5.879%      100.000%


halt_poll_fail_hist:
Range		Bucket Value	Percent     Cumulative Percent
[0, 1)		 0		 0.000%      0.000%
[1, 2)		 0		 0.000%      0.000%
[2, 4)		 0		 0.000%      0.000%
[4, 8)		 0		 0.000%      0.000%
[8, 16)		 0		 0.000%      0.000%
[16, 32)	 0		 0.000%      0.000%
[32, 64)	 0		 0.000%      0.000%
[64, 128)	 21		 0.529%      0.529%
[128, 256)	 398		 10.020%     10.549%
[256, 512)	 613		 15.433%     25.982%
[512, 1024)	 437		 11.002%     36.984%
[1024, 2048)	 264		 6.647%      43.630%
[2048, 4096)	 302		 7.603%      51.234%
[4096, 8192)	 350		 8.812%      60.045%
[8192, 16384)	 488		 12.286%     72.331%
[16384, 32768)	 258		 6.495%      78.827%
[32768, 65536)	 227		 5.715%      84.542%
[65536, 131072)  232		 5.841%      90.383%
[131072, 262144) 246		 6.193%      96.576%
[262144, 524288) 136		 3.424%      100.000%


halt_wait_hist:
Range			    Bucket Value    Percent	Cumulative Percent
[0, 1)			     0		     0.000%	 0.000%
[1, 2)			     0		     0.000%	 0.000%
[2, 4)			     0		     0.000%	 0.000%
[4, 8)			     0		     0.000%	 0.000%
[8, 16)			     0		     0.000%	 0.000%
[16, 32)		     0		     0.000%	 0.000%
[32, 64)		     0		     0.000%	 0.000%
[64, 128)		     0		     0.000%	 0.000%
[128, 256)		     0		     0.000%	 0.000%
[256, 512)		     0		     0.000%	 0.000%
[512, 1024)		     0		     0.000%	 0.000%
[1024, 2048)		     0		     0.000%	 0.000%
[2048, 4096)		     7		     0.127%	 0.127%
[4096, 8192)		     37		     0.671%	 0.798%
[8192, 16384)		     69		     1.251%	 2.049%
[16384, 32768)		     94		     1.704%	 3.753%
[32768, 65536)		     150	     2.719%	 6.472%
[65536, 131072)		     233	     4.224%	 10.696%
[131072, 262144)	     276	     5.004%	 15.700%
[262144, 524288)	     236	     4.278%	 19.978%
[524288, 1.04858e+06)	     176	     3.191%	 23.169%
[1.04858e+06, 2.09715e+06)   94		     16.207%	 39.376%
[2.09715e+06, 4.1943e+06)    1667	     30.221%	 69.598%
[4.1943e+06, 8.38861e+06)    825	     14.956%	 84.554%
[8.38861e+06, 1.67772e+07)   111	     2.012%	 86.566%
[1.67772e+07, 3.35544e+07)   76		     1.378%	 87.944%
[3.35544e+07, 6.71089e+07)   65		     1.178%	 89.123%
[6.71089e+07, 1.34218e+08)   161	     2.919%	 92.041%
[1.34218e+08, 2.68435e+08)   250	     4.532%	 96.574%
[2.68435e+08, 5.36871e+08)   188	     3.408%	 99.982%
[5.36871e+08, 1.07374e+09)   1		     0.018%	 100.000%

---

Jing Zhang (4):
  KVM: stats: Support linear and logarithmic histogram statistics
  KVM: stats: Update doc for histogram statistics
  KVM: selftests: Add checks for histogram stats parameters
  KVM: stats: Add halt polling related histogram stats

 Documentation/virt/kvm/api.rst                | 36 ++++++++++-
 arch/arm64/kvm/guest.c                        |  4 --
 arch/mips/kvm/mips.c                          |  4 --
 arch/powerpc/include/asm/kvm_host.h           |  1 -
 arch/powerpc/kvm/book3s.c                     |  5 --
 arch/powerpc/kvm/book3s_hv.c                  | 20 +++++-
 arch/powerpc/kvm/booke.c                      |  5 --
 arch/s390/kvm/kvm-s390.c                      |  4 --
 arch/x86/kvm/x86.c                            |  4 --
 include/linux/kvm_host.h                      | 62 ++++++++++++++-----
 include/linux/kvm_types.h                     | 20 ++++++
 include/uapi/linux/kvm.h                      | 11 +++-
 .../selftests/kvm/kvm_binary_stats_test.c     | 17 +++++
 virt/kvm/binary_stats.c                       | 36 +++++++++++
 virt/kvm/kvm_main.c                           | 19 ++++++
 15 files changed, 196 insertions(+), 52 deletions(-)


base-commit: 7caa04b36f204a01dac65582b71d26d190a1e022
-- 
2.32.0.93.g670b81a890-goog

^ permalink raw reply	[flat|nested] 55+ messages in thread

* [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-06 18:03 ` Jing Zhang
@ 2021-07-06 18:03   ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

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>
---
 arch/arm64/kvm/guest.c    |  4 ---
 arch/mips/kvm/mips.c      |  4 ---
 arch/powerpc/kvm/book3s.c |  4 ---
 arch/powerpc/kvm/booke.c  |  4 ---
 arch/s390/kvm/kvm-s390.c  |  4 ---
 arch/x86/kvm/x86.c        |  4 ---
 include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
 include/linux/kvm_types.h | 16 ++++++++++++
 include/uapi/linux/kvm.h  | 11 +++++---
 virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
 10 files changed, 98 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 1512a8007a78..cb44d8756fa7 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -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,
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index af9dd029a4e1..75c6f264c626 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -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,
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 79833f78d1da..5cc6e90095b0 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -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,
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 551b30d84aee..5ed6c235e059 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -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,
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 1695f0ced5ba..7610d33d319b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -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, 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,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8166ad113fb2..b94a80ad5b8d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
 	STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
 	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,
@@ -280,8 +278,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,
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ae7735b490b4..356af173114d 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1273,56 +1273,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, param)		       \
 	.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,							       \
+	.hist_param = param
 
-#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)		       \
+#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)	       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)	       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)		       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)		       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)	       \
+	SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
 
 #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, param)   \
+	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,		       \
+		unit, base, exponent, sz, param)
+#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
+	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,		       \
+		unit, base, exponent, sz, param)
 
 /* Cumulative counter, read/write */
 #define STATS_DESC_COUNTER(SCOPE, name)					       \
@@ -1341,6 +1351,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, bucket_size)	       \
+	STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,	       \
+		KVM_STATS_BASE_POW10, -9, sz, bucket_size)
+/* 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, LOGHIST_BASE_2)
 
 #define KVM_GENERIC_VM_STATS()						       \
 	STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
@@ -1354,10 +1372,15 @@ 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);
+void kvm_stats_linear_hist_update(u64 *data, size_t size,
+				  u64 value, size_t bucket_size);
+void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index ed6a985c5680..cc88cd676775 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
 };
 #endif
 
+/* Constants used for histogram stats */
+#define LINHIST_SIZE_SMALL		10
+#define LINHIST_SIZE_MEDIUM		20
+#define LINHIST_SIZE_LARGE		50
+#define LINHIST_SIZE_XLARGE		100
+#define LINHIST_BUCKET_SIZE_SMALL	10
+#define LINHIST_BUCKET_SIZE_MEDIUM	100
+#define LINHIST_BUCKET_SIZE_LARGE	1000
+#define LINHIST_BUCKET_SIZE_XLARGE	10000
+
+#define LOGHIST_SIZE_SMALL		8
+#define LOGHIST_SIZE_MEDIUM		16
+#define LOGHIST_SIZE_LARGE		32
+#define LOGHIST_SIZE_XLARGE		64
+#define LOGHIST_BASE_2			2
+
 struct kvm_vm_stat_generic {
 	u64 remote_tlb_flush;
 };
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 68c9e6d8bbda..ff34a471d9ef 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1963,7 +1963,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)
@@ -1987,7 +1989,10 @@ struct kvm_stats_header {
  *        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.
+ * @hist_param: A parameter value used for histogram stats. For linear
+ *              histogram stats, it indicates the size of the bucket;
+ *              For logarithmic histogram stats, it indicates the base
+ *              of the logarithm. Only base of 2 is supported.
  * @name: The name string for the stats. Its size is indicated by the
  *        &kvm_stats_header->name_size.
  */
@@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
 	__s16 exponent;
 	__u16 size;
 	__u32 offset;
-	__u32 unused;
+	__u32 hist_param;
 	char name[];
 };
 
diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
index e609d428811a..6eead6979a7f 100644
--- a/virt/kvm/binary_stats.c
+++ b/virt/kvm/binary_stats.c
@@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
 	*offset = pos;
 	return len;
 }
+
+/**
+ * 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
+ */
+void kvm_stats_linear_hist_update(u64 *data, size_t size,
+				  u64 value, size_t bucket_size)
+{
+	size_t index = value / bucket_size;
+
+	if (index >= size)
+		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
+ */
+void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
+{
+	size_t index = fls64(value);
+
+	if (index >= size)
+		index = size - 1;
+	++data[index];
+}
-- 
2.32.0.93.g670b81a890-goog


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-06 18:03   ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

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>
---
 arch/arm64/kvm/guest.c    |  4 ---
 arch/mips/kvm/mips.c      |  4 ---
 arch/powerpc/kvm/book3s.c |  4 ---
 arch/powerpc/kvm/booke.c  |  4 ---
 arch/s390/kvm/kvm-s390.c  |  4 ---
 arch/x86/kvm/x86.c        |  4 ---
 include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
 include/linux/kvm_types.h | 16 ++++++++++++
 include/uapi/linux/kvm.h  | 11 +++++---
 virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
 10 files changed, 98 insertions(+), 42 deletions(-)

diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
index 1512a8007a78..cb44d8756fa7 100644
--- a/arch/arm64/kvm/guest.c
+++ b/arch/arm64/kvm/guest.c
@@ -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,
diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
index af9dd029a4e1..75c6f264c626 100644
--- a/arch/mips/kvm/mips.c
+++ b/arch/mips/kvm/mips.c
@@ -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,
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 79833f78d1da..5cc6e90095b0 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -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,
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 551b30d84aee..5ed6c235e059 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -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,
diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
index 1695f0ced5ba..7610d33d319b 100644
--- a/arch/s390/kvm/kvm-s390.c
+++ b/arch/s390/kvm/kvm-s390.c
@@ -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, 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,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 8166ad113fb2..b94a80ad5b8d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
 	STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
 	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,
@@ -280,8 +278,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,
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index ae7735b490b4..356af173114d 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1273,56 +1273,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, param)		       \
 	.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,							       \
+	.hist_param = param
 
-#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)		       \
+#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)	       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)	       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)		       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)		       \
 	{								       \
 		{							       \
-			STATS_DESC_COMMON(type, unit, base, exp),	       \
+			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
 			.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, param)	       \
+	SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
 
 #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, param)   \
+	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,		       \
+		unit, base, exponent, sz, param)
+#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
+	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,		       \
+		unit, base, exponent, sz, param)
 
 /* Cumulative counter, read/write */
 #define STATS_DESC_COUNTER(SCOPE, name)					       \
@@ -1341,6 +1351,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, bucket_size)	       \
+	STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,	       \
+		KVM_STATS_BASE_POW10, -9, sz, bucket_size)
+/* 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, LOGHIST_BASE_2)
 
 #define KVM_GENERIC_VM_STATS()						       \
 	STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
@@ -1354,10 +1372,15 @@ 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);
+void kvm_stats_linear_hist_update(u64 *data, size_t size,
+				  u64 value, size_t bucket_size);
+void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index ed6a985c5680..cc88cd676775 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
 };
 #endif
 
+/* Constants used for histogram stats */
+#define LINHIST_SIZE_SMALL		10
+#define LINHIST_SIZE_MEDIUM		20
+#define LINHIST_SIZE_LARGE		50
+#define LINHIST_SIZE_XLARGE		100
+#define LINHIST_BUCKET_SIZE_SMALL	10
+#define LINHIST_BUCKET_SIZE_MEDIUM	100
+#define LINHIST_BUCKET_SIZE_LARGE	1000
+#define LINHIST_BUCKET_SIZE_XLARGE	10000
+
+#define LOGHIST_SIZE_SMALL		8
+#define LOGHIST_SIZE_MEDIUM		16
+#define LOGHIST_SIZE_LARGE		32
+#define LOGHIST_SIZE_XLARGE		64
+#define LOGHIST_BASE_2			2
+
 struct kvm_vm_stat_generic {
 	u64 remote_tlb_flush;
 };
diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
index 68c9e6d8bbda..ff34a471d9ef 100644
--- a/include/uapi/linux/kvm.h
+++ b/include/uapi/linux/kvm.h
@@ -1963,7 +1963,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)
@@ -1987,7 +1989,10 @@ struct kvm_stats_header {
  *        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.
+ * @hist_param: A parameter value used for histogram stats. For linear
+ *              histogram stats, it indicates the size of the bucket;
+ *              For logarithmic histogram stats, it indicates the base
+ *              of the logarithm. Only base of 2 is supported.
  * @name: The name string for the stats. Its size is indicated by the
  *        &kvm_stats_header->name_size.
  */
@@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
 	__s16 exponent;
 	__u16 size;
 	__u32 offset;
-	__u32 unused;
+	__u32 hist_param;
 	char name[];
 };
 
diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
index e609d428811a..6eead6979a7f 100644
--- a/virt/kvm/binary_stats.c
+++ b/virt/kvm/binary_stats.c
@@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
 	*offset = pos;
 	return len;
 }
+
+/**
+ * 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
+ */
+void kvm_stats_linear_hist_update(u64 *data, size_t size,
+				  u64 value, size_t bucket_size)
+{
+	size_t index = value / bucket_size;
+
+	if (index >= size)
+		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
+ */
+void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
+{
+	size_t index = fls64(value);
+
+	if (index >= size)
+		index = size - 1;
+	++data[index];
+}
-- 
2.32.0.93.g670b81a890-goog

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-06 18:03 ` Jing Zhang
@ 2021-07-06 18:03   ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

Add documentations for linear and logarithmic histogram statistics.
Add binary stats capability text which is missing during merge of
the binary stats patch.

Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
 Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 3b6e3b1628b4..948d33c26704 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
 	#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_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)
@@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
 	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
 	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
 	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
+	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
 
 	#define KVM_STATS_BASE_SHIFT		8
 	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
 	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
 	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
+	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2
 
 	struct kvm_stats_desc {
 		__u32 flags;
@@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
     represents a peak value for a measurement, for example the maximum number
     of items in a hash table bucket, the longest time waited and so on.
     The corresponding ``size`` field for this type is always 1.
+  * ``KVM_STATS_TYPE_LINEAR_HIST``
+    The statistics data is in the form of linear histogram. The number of
+    buckets is specified by the ``size`` field. The size of buckets is specified
+    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
+    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
+    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
+    value.) The bucket value indicates how many times the statistics data is in
+    the bucket's range.
+  * ``KVM_STATS_TYPE_LOG_HIST``
+    The statistics data is in the form of logarithmic histogram. The number of
+    buckets is specified by the ``size`` field. The base of logarithm is
+    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
+    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
+    of the first bucket is [0, 1), while the range of the last bucket is
+    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
+    times the statistics data is in the bucket's range.
 
 Bits 4-7 of ``flags`` encode the unit:
   * ``KVM_STATS_UNIT_NONE``
@@ -5246,9 +5267,10 @@ unsigned 64bit data.
 The ``offset`` field is the offset from the start of Data Block to the start of
 the corresponding statistics data.
 
-The ``unused`` field is reserved for future support for other types of
-statistics data, like log/linear histogram. Its value is always 0 for the types
-defined above.
+The ``hist_param`` field is used as a parameter for histogram statistics data.
+For linear histogram statistics data, it indicates the size of a bucket. For
+logarithmic histogram statistics data, it indicates the base of the logarithm.
+Only base of 2 is supported fo logarithmic histogram.
 
 The ``name`` field is the name string of the statistics data. The name string
 starts at the end of ``struct kvm_stats_desc``.  The maximum length including
@@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
 of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
 the hypercalls whose corresponding bit is in the argument, and return
 ENOSYS for the others.
+
+8.35 KVM_CAP_STATS_BINARY_FD
+----------------------------
+
+:Architectures: all
+
+This capability indicates the feature that userspace can get a file descriptor
+for every VM and VCPU to read statistics data in binary format.
-- 
2.32.0.93.g670b81a890-goog


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-06 18:03   ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

Add documentations for linear and logarithmic histogram statistics.
Add binary stats capability text which is missing during merge of
the binary stats patch.

Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
 Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
 1 file changed, 33 insertions(+), 3 deletions(-)

diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
index 3b6e3b1628b4..948d33c26704 100644
--- a/Documentation/virt/kvm/api.rst
+++ b/Documentation/virt/kvm/api.rst
@@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
 	#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_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)
@@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
 	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
 	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
 	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
+	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
 
 	#define KVM_STATS_BASE_SHIFT		8
 	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
 	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
 	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
+	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2
 
 	struct kvm_stats_desc {
 		__u32 flags;
@@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
     represents a peak value for a measurement, for example the maximum number
     of items in a hash table bucket, the longest time waited and so on.
     The corresponding ``size`` field for this type is always 1.
+  * ``KVM_STATS_TYPE_LINEAR_HIST``
+    The statistics data is in the form of linear histogram. The number of
+    buckets is specified by the ``size`` field. The size of buckets is specified
+    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
+    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
+    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
+    value.) The bucket value indicates how many times the statistics data is in
+    the bucket's range.
+  * ``KVM_STATS_TYPE_LOG_HIST``
+    The statistics data is in the form of logarithmic histogram. The number of
+    buckets is specified by the ``size`` field. The base of logarithm is
+    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
+    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
+    of the first bucket is [0, 1), while the range of the last bucket is
+    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
+    times the statistics data is in the bucket's range.
 
 Bits 4-7 of ``flags`` encode the unit:
   * ``KVM_STATS_UNIT_NONE``
@@ -5246,9 +5267,10 @@ unsigned 64bit data.
 The ``offset`` field is the offset from the start of Data Block to the start of
 the corresponding statistics data.
 
-The ``unused`` field is reserved for future support for other types of
-statistics data, like log/linear histogram. Its value is always 0 for the types
-defined above.
+The ``hist_param`` field is used as a parameter for histogram statistics data.
+For linear histogram statistics data, it indicates the size of a bucket. For
+logarithmic histogram statistics data, it indicates the base of the logarithm.
+Only base of 2 is supported fo logarithmic histogram.
 
 The ``name`` field is the name string of the statistics data. The name string
 starts at the end of ``struct kvm_stats_desc``.  The maximum length including
@@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
 of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
 the hypercalls whose corresponding bit is in the argument, and return
 ENOSYS for the others.
+
+8.35 KVM_CAP_STATS_BINARY_FD
+----------------------------
+
+:Architectures: all
+
+This capability indicates the feature that userspace can get a file descriptor
+for every VM and VCPU to read statistics data in binary format.
-- 
2.32.0.93.g670b81a890-goog

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 3/4] KVM: selftests: Add checks for histogram stats parameters
  2021-07-06 18:03 ` Jing Zhang
@ 2021-07-06 18:03   ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

The hist_param field should be zero for simple stats and 2 for
logarithmic histogram. It shouldbe non-zero for linear histogram stats.

Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
 .../selftests/kvm/kvm_binary_stats_test.c       | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
index 5906bbc08483..03c7842fcb26 100644
--- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c
+++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
@@ -109,6 +109,23 @@ static void stats_test(int stats_fd)
 		/* Check size field, which should not be zero */
 		TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0",
 				pdesc->name);
+		/* Check hist_param field */
+		switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
+		case KVM_STATS_TYPE_LINEAR_HIST:
+			TEST_ASSERT(pdesc->hist_param,
+			    "Bucket size of Linear Histogram stats (%s) is zero",
+			    pdesc->name);
+			break;
+		case KVM_STATS_TYPE_LOG_HIST:
+			TEST_ASSERT(pdesc->hist_param == 2,
+				"Base of Log Histogram stats (%s) is not 2",
+				pdesc->name);
+			break;
+		default:
+			TEST_ASSERT(!pdesc->hist_param,
+			    "Simple stats (%s) with hist_param of nonzero",
+			    pdesc->name);
+		}
 		size_data += pdesc->size * sizeof(*stats_data);
 	}
 	/* Check overlap */
-- 
2.32.0.93.g670b81a890-goog


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 3/4] KVM: selftests: Add checks for histogram stats parameters
@ 2021-07-06 18:03   ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

The hist_param field should be zero for simple stats and 2 for
logarithmic histogram. It shouldbe non-zero for linear histogram stats.

Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
 .../selftests/kvm/kvm_binary_stats_test.c       | 17 +++++++++++++++++
 1 file changed, 17 insertions(+)

diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
index 5906bbc08483..03c7842fcb26 100644
--- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c
+++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
@@ -109,6 +109,23 @@ static void stats_test(int stats_fd)
 		/* Check size field, which should not be zero */
 		TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0",
 				pdesc->name);
+		/* Check hist_param field */
+		switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
+		case KVM_STATS_TYPE_LINEAR_HIST:
+			TEST_ASSERT(pdesc->hist_param,
+			    "Bucket size of Linear Histogram stats (%s) is zero",
+			    pdesc->name);
+			break;
+		case KVM_STATS_TYPE_LOG_HIST:
+			TEST_ASSERT(pdesc->hist_param = 2,
+				"Base of Log Histogram stats (%s) is not 2",
+				pdesc->name);
+			break;
+		default:
+			TEST_ASSERT(!pdesc->hist_param,
+			    "Simple stats (%s) with hist_param of nonzero",
+			    pdesc->name);
+		}
 		size_data += pdesc->size * sizeof(*stats_data);
 	}
 	/* Check overlap */
-- 
2.32.0.93.g670b81a890-goog

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
  2021-07-06 18:03 ` Jing Zhang
@ 2021-07-06 18:03   ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

Add simple stats halt_wait_ns to record the time a VCPU has spent on
waiting for all architectures (not just powerpc).
Add three log histogram stats to record the distribution of time spent
on successful polling, failed polling and VCPU wait.
halt_poll_success_hist: Distribution of time spent before a successful
polling.
halt_poll_fail_hist: Distribution of time spent before a failed polling.
halt_wait_hist: Distribution of time a VCPU has spent on waiting.

Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
 arch/powerpc/include/asm/kvm_host.h |  1 -
 arch/powerpc/kvm/book3s.c           |  1 -
 arch/powerpc/kvm/book3s_hv.c        | 20 +++++++++++++++++---
 arch/powerpc/kvm/booke.c            |  1 -
 include/linux/kvm_host.h            |  9 ++++++++-
 include/linux/kvm_types.h           |  4 ++++
 virt/kvm/kvm_main.c                 | 19 +++++++++++++++++++
 7 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 9f52f282b1aa..4931d03e5799 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
 	u64 emulated_inst_exits;
 	u64 dec_exits;
 	u64 ext_intr_exits;
-	u64 halt_wait_ns;
 	u64 halt_successful_wait;
 	u64 dbell_exits;
 	u64 gdbell_exits;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 5cc6e90095b0..b785f6772391 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -69,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
 	STATS_DESC_COUNTER(VCPU, dec_exits),
 	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
-	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
 	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
 	STATS_DESC_COUNTER(VCPU, dbell_exits),
 	STATS_DESC_COUNTER(VCPU, gdbell_exits),
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cd544a46183e..103f998cee75 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4144,19 +4144,33 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 
 	/* Attribute wait time */
 	if (do_sleep) {
-		vc->runner->stat.halt_wait_ns +=
+		vc->runner->stat.generic.halt_wait_ns +=
 			ktime_to_ns(cur) - ktime_to_ns(start_wait);
+		kvm_stats_log_hist_update(
+				vc->runner->stat.generic.halt_wait_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(cur) - ktime_to_ns(start_wait));
 		/* Attribute failed poll time */
-		if (vc->halt_poll_ns)
+		if (vc->halt_poll_ns) {
 			vc->runner->stat.generic.halt_poll_fail_ns +=
 				ktime_to_ns(start_wait) -
 				ktime_to_ns(start_poll);
+			kvm_stats_log_hist_update(
+				vc->runner->stat.generic.halt_poll_fail_hist,
+				LOGHIST_SIZE_LARGE, ktime_to_ns(start_wait) -
+				ktime_to_ns(start_poll));
+		}
 	} else {
 		/* Attribute successful poll time */
-		if (vc->halt_poll_ns)
+		if (vc->halt_poll_ns) {
 			vc->runner->stat.generic.halt_poll_success_ns +=
 				ktime_to_ns(cur) -
 				ktime_to_ns(start_poll);
+			kvm_stats_log_hist_update(
+				vc->runner->stat.generic.halt_poll_success_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(cur) - ktime_to_ns(start_poll));
+		}
 	}
 
 	/* Adjust poll time */
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 5ed6c235e059..977801c83aff 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -67,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
 	STATS_DESC_COUNTER(VCPU, dec_exits),
 	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
-	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
 	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
 	STATS_DESC_COUNTER(VCPU, dbell_exits),
 	STATS_DESC_COUNTER(VCPU, gdbell_exits),
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 356af173114d..268a0ccc9c5f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1369,7 +1369,14 @@ struct _kvm_stats_desc {
 	STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid),		       \
 	STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup),			       \
 	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns),	       \
-	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
+	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns),		       \
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist,     \
+			LOGHIST_SIZE_LARGE),				       \
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist,	       \
+			LOGHIST_SIZE_LARGE),				       \
+	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns),		       \
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist,	       \
+			LOGHIST_SIZE_LARGE)
 
 extern struct dentry *kvm_debugfs_dir;
 
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index cc88cd676775..7838a42932c8 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -103,6 +103,10 @@ struct kvm_vcpu_stat_generic {
 	u64 halt_wakeup;
 	u64 halt_poll_success_ns;
 	u64 halt_poll_fail_ns;
+	u64 halt_poll_success_hist[LOGHIST_SIZE_LARGE];
+	u64 halt_poll_fail_hist[LOGHIST_SIZE_LARGE];
+	u64 halt_wait_ns;
+	u64 halt_wait_hist[LOGHIST_SIZE_LARGE];
 };
 
 #define KVM_STATS_NAME_SIZE	48
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 3dcc2abbfc60..840b5bece080 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3093,12 +3093,24 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
 				++vcpu->stat.generic.halt_successful_poll;
 				if (!vcpu_valid_wakeup(vcpu))
 					++vcpu->stat.generic.halt_poll_invalid;
+
+				kvm_stats_log_hist_update(
+				      vcpu->stat.generic.halt_poll_success_hist,
+				      LOGHIST_SIZE_LARGE,
+				      ktime_to_ns(ktime_get()) -
+				      ktime_to_ns(start));
 				goto out;
 			}
 			poll_end = cur = ktime_get();
 		} while (kvm_vcpu_can_poll(cur, stop));
+
+		kvm_stats_log_hist_update(
+				vcpu->stat.generic.halt_poll_fail_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(ktime_get()) - ktime_to_ns(start));
 	}
 
+
 	prepare_to_rcuwait(&vcpu->wait);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -3111,6 +3123,13 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
 	}
 	finish_rcuwait(&vcpu->wait);
 	cur = ktime_get();
+	if (waited) {
+		vcpu->stat.generic.halt_wait_ns +=
+			ktime_to_ns(cur) - ktime_to_ns(poll_end);
+		kvm_stats_log_hist_update(vcpu->stat.generic.halt_wait_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(cur) - ktime_to_ns(poll_end));
+	}
 out:
 	kvm_arch_vcpu_unblocking(vcpu);
 	block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
-- 
2.32.0.93.g670b81a890-goog


^ permalink raw reply related	[flat|nested] 55+ messages in thread

* [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
@ 2021-07-06 18:03   ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-06 18:03 UTC (permalink / raw)
  To: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack
  Cc: Jing Zhang

Add simple stats halt_wait_ns to record the time a VCPU has spent on
waiting for all architectures (not just powerpc).
Add three log histogram stats to record the distribution of time spent
on successful polling, failed polling and VCPU wait.
halt_poll_success_hist: Distribution of time spent before a successful
polling.
halt_poll_fail_hist: Distribution of time spent before a failed polling.
halt_wait_hist: Distribution of time a VCPU has spent on waiting.

Signed-off-by: Jing Zhang <jingzhangos@google.com>
---
 arch/powerpc/include/asm/kvm_host.h |  1 -
 arch/powerpc/kvm/book3s.c           |  1 -
 arch/powerpc/kvm/book3s_hv.c        | 20 +++++++++++++++++---
 arch/powerpc/kvm/booke.c            |  1 -
 include/linux/kvm_host.h            |  9 ++++++++-
 include/linux/kvm_types.h           |  4 ++++
 virt/kvm/kvm_main.c                 | 19 +++++++++++++++++++
 7 files changed, 48 insertions(+), 7 deletions(-)

diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
index 9f52f282b1aa..4931d03e5799 100644
--- a/arch/powerpc/include/asm/kvm_host.h
+++ b/arch/powerpc/include/asm/kvm_host.h
@@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
 	u64 emulated_inst_exits;
 	u64 dec_exits;
 	u64 ext_intr_exits;
-	u64 halt_wait_ns;
 	u64 halt_successful_wait;
 	u64 dbell_exits;
 	u64 gdbell_exits;
diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
index 5cc6e90095b0..b785f6772391 100644
--- a/arch/powerpc/kvm/book3s.c
+++ b/arch/powerpc/kvm/book3s.c
@@ -69,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
 	STATS_DESC_COUNTER(VCPU, dec_exits),
 	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
-	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
 	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
 	STATS_DESC_COUNTER(VCPU, dbell_exits),
 	STATS_DESC_COUNTER(VCPU, gdbell_exits),
diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
index cd544a46183e..103f998cee75 100644
--- a/arch/powerpc/kvm/book3s_hv.c
+++ b/arch/powerpc/kvm/book3s_hv.c
@@ -4144,19 +4144,33 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
 
 	/* Attribute wait time */
 	if (do_sleep) {
-		vc->runner->stat.halt_wait_ns ++		vc->runner->stat.generic.halt_wait_ns + 			ktime_to_ns(cur) - ktime_to_ns(start_wait);
+		kvm_stats_log_hist_update(
+				vc->runner->stat.generic.halt_wait_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(cur) - ktime_to_ns(start_wait));
 		/* Attribute failed poll time */
-		if (vc->halt_poll_ns)
+		if (vc->halt_poll_ns) {
 			vc->runner->stat.generic.halt_poll_fail_ns + 				ktime_to_ns(start_wait) -
 				ktime_to_ns(start_poll);
+			kvm_stats_log_hist_update(
+				vc->runner->stat.generic.halt_poll_fail_hist,
+				LOGHIST_SIZE_LARGE, ktime_to_ns(start_wait) -
+				ktime_to_ns(start_poll));
+		}
 	} else {
 		/* Attribute successful poll time */
-		if (vc->halt_poll_ns)
+		if (vc->halt_poll_ns) {
 			vc->runner->stat.generic.halt_poll_success_ns + 				ktime_to_ns(cur) -
 				ktime_to_ns(start_poll);
+			kvm_stats_log_hist_update(
+				vc->runner->stat.generic.halt_poll_success_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(cur) - ktime_to_ns(start_poll));
+		}
 	}
 
 	/* Adjust poll time */
diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
index 5ed6c235e059..977801c83aff 100644
--- a/arch/powerpc/kvm/booke.c
+++ b/arch/powerpc/kvm/booke.c
@@ -67,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
 	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
 	STATS_DESC_COUNTER(VCPU, dec_exits),
 	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
-	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
 	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
 	STATS_DESC_COUNTER(VCPU, dbell_exits),
 	STATS_DESC_COUNTER(VCPU, gdbell_exits),
diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
index 356af173114d..268a0ccc9c5f 100644
--- a/include/linux/kvm_host.h
+++ b/include/linux/kvm_host.h
@@ -1369,7 +1369,14 @@ struct _kvm_stats_desc {
 	STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid),		       \
 	STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup),			       \
 	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns),	       \
-	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
+	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns),		       \
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist,     \
+			LOGHIST_SIZE_LARGE),				       \
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist,	       \
+			LOGHIST_SIZE_LARGE),				       \
+	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns),		       \
+	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist,	       \
+			LOGHIST_SIZE_LARGE)
 
 extern struct dentry *kvm_debugfs_dir;
 
diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
index cc88cd676775..7838a42932c8 100644
--- a/include/linux/kvm_types.h
+++ b/include/linux/kvm_types.h
@@ -103,6 +103,10 @@ struct kvm_vcpu_stat_generic {
 	u64 halt_wakeup;
 	u64 halt_poll_success_ns;
 	u64 halt_poll_fail_ns;
+	u64 halt_poll_success_hist[LOGHIST_SIZE_LARGE];
+	u64 halt_poll_fail_hist[LOGHIST_SIZE_LARGE];
+	u64 halt_wait_ns;
+	u64 halt_wait_hist[LOGHIST_SIZE_LARGE];
 };
 
 #define KVM_STATS_NAME_SIZE	48
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 3dcc2abbfc60..840b5bece080 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -3093,12 +3093,24 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
 				++vcpu->stat.generic.halt_successful_poll;
 				if (!vcpu_valid_wakeup(vcpu))
 					++vcpu->stat.generic.halt_poll_invalid;
+
+				kvm_stats_log_hist_update(
+				      vcpu->stat.generic.halt_poll_success_hist,
+				      LOGHIST_SIZE_LARGE,
+				      ktime_to_ns(ktime_get()) -
+				      ktime_to_ns(start));
 				goto out;
 			}
 			poll_end = cur = ktime_get();
 		} while (kvm_vcpu_can_poll(cur, stop));
+
+		kvm_stats_log_hist_update(
+				vcpu->stat.generic.halt_poll_fail_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(ktime_get()) - ktime_to_ns(start));
 	}
 
+
 	prepare_to_rcuwait(&vcpu->wait);
 	for (;;) {
 		set_current_state(TASK_INTERRUPTIBLE);
@@ -3111,6 +3123,13 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
 	}
 	finish_rcuwait(&vcpu->wait);
 	cur = ktime_get();
+	if (waited) {
+		vcpu->stat.generic.halt_wait_ns ++			ktime_to_ns(cur) - ktime_to_ns(poll_end);
+		kvm_stats_log_hist_update(vcpu->stat.generic.halt_wait_hist,
+				LOGHIST_SIZE_LARGE,
+				ktime_to_ns(cur) - ktime_to_ns(poll_end));
+	}
 out:
 	kvm_arch_vcpu_unblocking(vcpu);
 	block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
-- 
2.32.0.93.g670b81a890-goog

^ permalink raw reply related	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-07 23:31     ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-07 23:31 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> Add documentations for linear and logarithmic histogram statistics.
> Add binary stats capability text which is missing during merge of
> the binary stats patch.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>
> ---
>  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 3b6e3b1628b4..948d33c26704 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
>  	#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_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)
> @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
>  	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
> +	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
>  
>  	#define KVM_STATS_BASE_SHIFT		8
>  	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
> +	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2
>  
>  	struct kvm_stats_desc {
>  		__u32 flags;
> @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
>      represents a peak value for a measurement, for example the maximum number
>      of items in a hash table bucket, the longest time waited and so on.
>      The corresponding ``size`` field for this type is always 1.
> +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> +    The statistics data is in the form of linear histogram. The number of
> +    buckets is specified by the ``size`` field. The size of buckets is specified
> +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> +    value.) The bucket value indicates how many times the statistics data is in
> +    the bucket's range.
> +  * ``KVM_STATS_TYPE_LOG_HIST``
> +    The statistics data is in the form of logarithmic histogram. The number of
> +    buckets is specified by the ``size`` field. The base of logarithm is
> +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> +    of the first bucket is [0, 1), while the range of the last bucket is
> +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> +    times the statistics data is in the bucket's range.
>  
>  Bits 4-7 of ``flags`` encode the unit:
>    * ``KVM_STATS_UNIT_NONE``
> @@ -5246,9 +5267,10 @@ unsigned 64bit data.
>  The ``offset`` field is the offset from the start of Data Block to the start of
>  the corresponding statistics data.
>  
> -The ``unused`` field is reserved for future support for other types of
> -statistics data, like log/linear histogram. Its value is always 0 for the types
> -defined above.
> +The ``hist_param`` field is used as a parameter for histogram statistics data.
> +For linear histogram statistics data, it indicates the size of a bucket. For
> +logarithmic histogram statistics data, it indicates the base of the logarithm.
> +Only base of 2 is supported fo logarithmic histogram.
>  
>  The ``name`` field is the name string of the statistics data. The name string
>  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
>  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
>  the hypercalls whose corresponding bit is in the argument, and return
>  ENOSYS for the others.
> +
> +8.35 KVM_CAP_STATS_BINARY_FD
> +----------------------------
> +
> +:Architectures: all
> +
> +This capability indicates the feature that userspace can get a file descriptor
> +for every VM and VCPU to read statistics data in binary format.

This should probably be in a separate patch with a Fixes tag.

Fixes: fdc09ddd4064 ("KVM: stats: Add documentation for binary statistics interface")

> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-07 23:31     ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-07 23:31 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> Add documentations for linear and logarithmic histogram statistics.
> Add binary stats capability text which is missing during merge of
> the binary stats patch.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>
> ---
>  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 3b6e3b1628b4..948d33c26704 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
>  	#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_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)
> @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
>  	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
> +	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
>  
>  	#define KVM_STATS_BASE_SHIFT		8
>  	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
> +	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2
>  
>  	struct kvm_stats_desc {
>  		__u32 flags;
> @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
>      represents a peak value for a measurement, for example the maximum number
>      of items in a hash table bucket, the longest time waited and so on.
>      The corresponding ``size`` field for this type is always 1.
> +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> +    The statistics data is in the form of linear histogram. The number of
> +    buckets is specified by the ``size`` field. The size of buckets is specified
> +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> +    value.) The bucket value indicates how many times the statistics data is in
> +    the bucket's range.
> +  * ``KVM_STATS_TYPE_LOG_HIST``
> +    The statistics data is in the form of logarithmic histogram. The number of
> +    buckets is specified by the ``size`` field. The base of logarithm is
> +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> +    of the first bucket is [0, 1), while the range of the last bucket is
> +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> +    times the statistics data is in the bucket's range.
>  
>  Bits 4-7 of ``flags`` encode the unit:
>    * ``KVM_STATS_UNIT_NONE``
> @@ -5246,9 +5267,10 @@ unsigned 64bit data.
>  The ``offset`` field is the offset from the start of Data Block to the start of
>  the corresponding statistics data.
>  
> -The ``unused`` field is reserved for future support for other types of
> -statistics data, like log/linear histogram. Its value is always 0 for the types
> -defined above.
> +The ``hist_param`` field is used as a parameter for histogram statistics data.
> +For linear histogram statistics data, it indicates the size of a bucket. For
> +logarithmic histogram statistics data, it indicates the base of the logarithm.
> +Only base of 2 is supported fo logarithmic histogram.
>  
>  The ``name`` field is the name string of the statistics data. The name string
>  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
>  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
>  the hypercalls whose corresponding bit is in the argument, and return
>  ENOSYS for the others.
> +
> +8.35 KVM_CAP_STATS_BINARY_FD
> +----------------------------
> +
> +:Architectures: all
> +
> +This capability indicates the feature that userspace can get a file descriptor
> +for every VM and VCPU to read statistics data in binary format.

This should probably be in a separate patch with a Fixes tag.

Fixes: fdc09ddd4064 ("KVM: stats: Add documentation for binary statistics interface")

> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-07 23:31     ` David Matlack
@ 2021-07-08 14:29       ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-08 14:29 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Wed, Jul 7, 2021 at 6:31 PM David Matlack <dmatlack@google.com> wrote:
>
> On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> > Add documentations for linear and logarithmic histogram statistics.
> > Add binary stats capability text which is missing during merge of
> > the binary stats patch.
> >
> > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > ---
> >  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
> >  1 file changed, 33 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index 3b6e3b1628b4..948d33c26704 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
> >       #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_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)
> > @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
> >       #define KVM_STATS_UNIT_BYTES            (0x1 << KVM_STATS_UNIT_SHIFT)
> >       #define KVM_STATS_UNIT_SECONDS          (0x2 << KVM_STATS_UNIT_SHIFT)
> >       #define KVM_STATS_UNIT_CYCLES           (0x3 << KVM_STATS_UNIT_SHIFT)
> > +     #define KVM_STATS_UNIT_MAX              KVM_STATS_UNIT_CYCLES
> >
> >       #define KVM_STATS_BASE_SHIFT            8
> >       #define KVM_STATS_BASE_MASK             (0xF << KVM_STATS_BASE_SHIFT)
> >       #define KVM_STATS_BASE_POW10            (0x0 << KVM_STATS_BASE_SHIFT)
> >       #define KVM_STATS_BASE_POW2             (0x1 << KVM_STATS_BASE_SHIFT)
> > +     #define KVM_STATS_BASE_MAX              KVM_STATS_BASE_POW2
> >
> >       struct kvm_stats_desc {
> >               __u32 flags;
> > @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
> >      represents a peak value for a measurement, for example the maximum number
> >      of items in a hash table bucket, the longest time waited and so on.
> >      The corresponding ``size`` field for this type is always 1.
> > +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> > +    The statistics data is in the form of linear histogram. The number of
> > +    buckets is specified by the ``size`` field. The size of buckets is specified
> > +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> > +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> > +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> > +    value.) The bucket value indicates how many times the statistics data is in
> > +    the bucket's range.
> > +  * ``KVM_STATS_TYPE_LOG_HIST``
> > +    The statistics data is in the form of logarithmic histogram. The number of
> > +    buckets is specified by the ``size`` field. The base of logarithm is
> > +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> > +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> > +    of the first bucket is [0, 1), while the range of the last bucket is
> > +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> > +    times the statistics data is in the bucket's range.
> >
> >  Bits 4-7 of ``flags`` encode the unit:
> >    * ``KVM_STATS_UNIT_NONE``
> > @@ -5246,9 +5267,10 @@ unsigned 64bit data.
> >  The ``offset`` field is the offset from the start of Data Block to the start of
> >  the corresponding statistics data.
> >
> > -The ``unused`` field is reserved for future support for other types of
> > -statistics data, like log/linear histogram. Its value is always 0 for the types
> > -defined above.
> > +The ``hist_param`` field is used as a parameter for histogram statistics data.
> > +For linear histogram statistics data, it indicates the size of a bucket. For
> > +logarithmic histogram statistics data, it indicates the base of the logarithm.
> > +Only base of 2 is supported fo logarithmic histogram.
> >
> >  The ``name`` field is the name string of the statistics data. The name string
> >  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> > @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
> >  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
> >  the hypercalls whose corresponding bit is in the argument, and return
> >  ENOSYS for the others.
> > +
> > +8.35 KVM_CAP_STATS_BINARY_FD
> > +----------------------------
> > +
> > +:Architectures: all
> > +
> > +This capability indicates the feature that userspace can get a file descriptor
> > +for every VM and VCPU to read statistics data in binary format.
>
> This should probably be in a separate patch with a Fixes tag.
>
> Fixes: fdc09ddd4064 ("KVM: stats: Add documentation for binary statistics interface")
>
> > --
> > 2.32.0.93.g670b81a890-goog
> >
Thanks David.
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-08 14:29       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-08 14:29 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Wed, Jul 7, 2021 at 6:31 PM David Matlack <dmatlack@google.com> wrote:
>
> On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> > Add documentations for linear and logarithmic histogram statistics.
> > Add binary stats capability text which is missing during merge of
> > the binary stats patch.
> >
> > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > ---
> >  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
> >  1 file changed, 33 insertions(+), 3 deletions(-)
> >
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index 3b6e3b1628b4..948d33c26704 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
> >       #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_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)
> > @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
> >       #define KVM_STATS_UNIT_BYTES            (0x1 << KVM_STATS_UNIT_SHIFT)
> >       #define KVM_STATS_UNIT_SECONDS          (0x2 << KVM_STATS_UNIT_SHIFT)
> >       #define KVM_STATS_UNIT_CYCLES           (0x3 << KVM_STATS_UNIT_SHIFT)
> > +     #define KVM_STATS_UNIT_MAX              KVM_STATS_UNIT_CYCLES
> >
> >       #define KVM_STATS_BASE_SHIFT            8
> >       #define KVM_STATS_BASE_MASK             (0xF << KVM_STATS_BASE_SHIFT)
> >       #define KVM_STATS_BASE_POW10            (0x0 << KVM_STATS_BASE_SHIFT)
> >       #define KVM_STATS_BASE_POW2             (0x1 << KVM_STATS_BASE_SHIFT)
> > +     #define KVM_STATS_BASE_MAX              KVM_STATS_BASE_POW2
> >
> >       struct kvm_stats_desc {
> >               __u32 flags;
> > @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
> >      represents a peak value for a measurement, for example the maximum number
> >      of items in a hash table bucket, the longest time waited and so on.
> >      The corresponding ``size`` field for this type is always 1.
> > +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> > +    The statistics data is in the form of linear histogram. The number of
> > +    buckets is specified by the ``size`` field. The size of buckets is specified
> > +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> > +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> > +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> > +    value.) The bucket value indicates how many times the statistics data is in
> > +    the bucket's range.
> > +  * ``KVM_STATS_TYPE_LOG_HIST``
> > +    The statistics data is in the form of logarithmic histogram. The number of
> > +    buckets is specified by the ``size`` field. The base of logarithm is
> > +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> > +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> > +    of the first bucket is [0, 1), while the range of the last bucket is
> > +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> > +    times the statistics data is in the bucket's range.
> >
> >  Bits 4-7 of ``flags`` encode the unit:
> >    * ``KVM_STATS_UNIT_NONE``
> > @@ -5246,9 +5267,10 @@ unsigned 64bit data.
> >  The ``offset`` field is the offset from the start of Data Block to the start of
> >  the corresponding statistics data.
> >
> > -The ``unused`` field is reserved for future support for other types of
> > -statistics data, like log/linear histogram. Its value is always 0 for the types
> > -defined above.
> > +The ``hist_param`` field is used as a parameter for histogram statistics data.
> > +For linear histogram statistics data, it indicates the size of a bucket. For
> > +logarithmic histogram statistics data, it indicates the base of the logarithm.
> > +Only base of 2 is supported fo logarithmic histogram.
> >
> >  The ``name`` field is the name string of the statistics data. The name string
> >  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> > @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
> >  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
> >  the hypercalls whose corresponding bit is in the argument, and return
> >  ENOSYS for the others.
> > +
> > +8.35 KVM_CAP_STATS_BINARY_FD
> > +----------------------------
> > +
> > +:Architectures: all
> > +
> > +This capability indicates the feature that userspace can get a file descriptor
> > +for every VM and VCPU to read statistics data in binary format.
>
> This should probably be in a separate patch with a Fixes tag.
>
> Fixes: fdc09ddd4064 ("KVM: stats: Add documentation for binary statistics interface")
>
> > --
> > 2.32.0.93.g670b81a890-goog
> >
Thanks David.
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-08 21:01     ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:01 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:47PM +0000, Jing Zhang wrote:
> 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>
> ---
>  arch/arm64/kvm/guest.c    |  4 ---
>  arch/mips/kvm/mips.c      |  4 ---
>  arch/powerpc/kvm/book3s.c |  4 ---
>  arch/powerpc/kvm/booke.c  |  4 ---
>  arch/s390/kvm/kvm-s390.c  |  4 ---
>  arch/x86/kvm/x86.c        |  4 ---
>  include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
>  include/linux/kvm_types.h | 16 ++++++++++++
>  include/uapi/linux/kvm.h  | 11 +++++---
>  virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
>  10 files changed, 98 insertions(+), 42 deletions(-)
> 
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 1512a8007a78..cb44d8756fa7 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -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,
> diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> index af9dd029a4e1..75c6f264c626 100644
> --- a/arch/mips/kvm/mips.c
> +++ b/arch/mips/kvm/mips.c
> @@ -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,
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 79833f78d1da..5cc6e90095b0 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -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,
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 551b30d84aee..5ed6c235e059 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -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,
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 1695f0ced5ba..7610d33d319b 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -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, 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,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8166ad113fb2..b94a80ad5b8d 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
>  	STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
>  	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,
> @@ -280,8 +278,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,
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index ae7735b490b4..356af173114d 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1273,56 +1273,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, param)		       \
>  	.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,							       \
> +	.hist_param = param
>  
> -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)		       \
> +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)	       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)	       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)		       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)		       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)	       \
> +	SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
>  
>  #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, param)   \
> +	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,		       \
> +		unit, base, exponent, sz, param)
> +#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
> +	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,		       \
> +		unit, base, exponent, sz, param)
>  
>  /* Cumulative counter, read/write */
>  #define STATS_DESC_COUNTER(SCOPE, name)					       \
> @@ -1341,6 +1351,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, bucket_size)	       \
> +	STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,	       \
> +		KVM_STATS_BASE_POW10, -9, sz, bucket_size)
> +/* 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, LOGHIST_BASE_2)
>  
>  #define KVM_GENERIC_VM_STATS()						       \
>  	STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
> @@ -1354,10 +1372,15 @@ 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);
> +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> +				  u64 value, size_t bucket_size);
> +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
> diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> index ed6a985c5680..cc88cd676775 100644
> --- a/include/linux/kvm_types.h
> +++ b/include/linux/kvm_types.h
> @@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
>  };
>  #endif
>  
> +/* Constants used for histogram stats */
> +#define LINHIST_SIZE_SMALL		10
> +#define LINHIST_SIZE_MEDIUM		20
> +#define LINHIST_SIZE_LARGE		50
> +#define LINHIST_SIZE_XLARGE		100

nit: s/SIZE/BUCKET_COUNT/

> +#define LINHIST_BUCKET_SIZE_SMALL	10
> +#define LINHIST_BUCKET_SIZE_MEDIUM	100
> +#define LINHIST_BUCKET_SIZE_LARGE	1000
> +#define LINHIST_BUCKET_SIZE_XLARGE	10000
> +
> +#define LOGHIST_SIZE_SMALL		8
> +#define LOGHIST_SIZE_MEDIUM		16
> +#define LOGHIST_SIZE_LARGE		32
> +#define LOGHIST_SIZE_XLARGE		64

Ditto here.

> +#define LOGHIST_BASE_2			2
> +
>  struct kvm_vm_stat_generic {
>  	u64 remote_tlb_flush;
>  };
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 68c9e6d8bbda..ff34a471d9ef 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1963,7 +1963,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)
> @@ -1987,7 +1989,10 @@ struct kvm_stats_header {
>   *        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.
> + * @hist_param: A parameter value used for histogram stats. For linear
> + *              histogram stats, it indicates the size of the bucket;
> + *              For logarithmic histogram stats, it indicates the base
> + *              of the logarithm. Only base of 2 is supported.
>   * @name: The name string for the stats. Its size is indicated by the
>   *        &kvm_stats_header->name_size.
>   */
> @@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
>  	__s16 exponent;
>  	__u16 size;
>  	__u32 offset;
> -	__u32 unused;
> +	__u32 hist_param;

`hist_param` is vague. What about making this an anonymous union to make
the dual meaning explicit?

        union {
                /* Only used for KVM_STATS_TYPE_LOG_HIST. */
                __u32 base;
                /* Only used for KVM_STATS_TYPE_LINEAR_HIST. */
                __u32 bucket_size;
        };

It may make the STATS_DESC code a bit more complicated but the rest of
the code that uses it will be much more clear.

>  	char name[];
>  };
>  
> diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
> index e609d428811a..6eead6979a7f 100644
> --- a/virt/kvm/binary_stats.c
> +++ b/virt/kvm/binary_stats.c
> @@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
>  	*offset = pos;
>  	return len;
>  }
> +
> +/**
> + * 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
> + */
> +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> +				  u64 value, size_t bucket_size)
> +{
> +	size_t index = value / bucket_size;
> +
> +	if (index >= size)
> +		index = size - 1;

nit: It would be simpler to use max().

        size_t index = max(value / bucket_size, 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
> + */
> +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
> +{
> +	size_t index = fls64(value);
> +
> +	if (index >= size)
> +		index = size - 1;

Ditto here about using max().

> +	++data[index];
> +}
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-08 21:01     ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:01 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:47PM +0000, Jing Zhang wrote:
> 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>
> ---
>  arch/arm64/kvm/guest.c    |  4 ---
>  arch/mips/kvm/mips.c      |  4 ---
>  arch/powerpc/kvm/book3s.c |  4 ---
>  arch/powerpc/kvm/booke.c  |  4 ---
>  arch/s390/kvm/kvm-s390.c  |  4 ---
>  arch/x86/kvm/x86.c        |  4 ---
>  include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
>  include/linux/kvm_types.h | 16 ++++++++++++
>  include/uapi/linux/kvm.h  | 11 +++++---
>  virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
>  10 files changed, 98 insertions(+), 42 deletions(-)
> 
> diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> index 1512a8007a78..cb44d8756fa7 100644
> --- a/arch/arm64/kvm/guest.c
> +++ b/arch/arm64/kvm/guest.c
> @@ -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,
> diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> index af9dd029a4e1..75c6f264c626 100644
> --- a/arch/mips/kvm/mips.c
> +++ b/arch/mips/kvm/mips.c
> @@ -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,
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 79833f78d1da..5cc6e90095b0 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -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,
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 551b30d84aee..5ed6c235e059 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -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,
> diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> index 1695f0ced5ba..7610d33d319b 100644
> --- a/arch/s390/kvm/kvm-s390.c
> +++ b/arch/s390/kvm/kvm-s390.c
> @@ -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, 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,
> diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> index 8166ad113fb2..b94a80ad5b8d 100644
> --- a/arch/x86/kvm/x86.c
> +++ b/arch/x86/kvm/x86.c
> @@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
>  	STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
>  	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,
> @@ -280,8 +278,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,
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index ae7735b490b4..356af173114d 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1273,56 +1273,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, param)		       \
>  	.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,							       \
> +	.hist_param = param
>  
> -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)		       \
> +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)	       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)	       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)		       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)		       \
>  	{								       \
>  		{							       \
> -			STATS_DESC_COMMON(type, unit, base, exp),	       \
> +			STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
>  			.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, param)	       \
> +	SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
>  
>  #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, param)   \
> +	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,		       \
> +		unit, base, exponent, sz, param)
> +#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
> +	STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,		       \
> +		unit, base, exponent, sz, param)
>  
>  /* Cumulative counter, read/write */
>  #define STATS_DESC_COUNTER(SCOPE, name)					       \
> @@ -1341,6 +1351,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, bucket_size)	       \
> +	STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,	       \
> +		KVM_STATS_BASE_POW10, -9, sz, bucket_size)
> +/* 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, LOGHIST_BASE_2)
>  
>  #define KVM_GENERIC_VM_STATS()						       \
>  	STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
> @@ -1354,10 +1372,15 @@ 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);
> +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> +				  u64 value, size_t bucket_size);
> +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
> diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> index ed6a985c5680..cc88cd676775 100644
> --- a/include/linux/kvm_types.h
> +++ b/include/linux/kvm_types.h
> @@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
>  };
>  #endif
>  
> +/* Constants used for histogram stats */
> +#define LINHIST_SIZE_SMALL		10
> +#define LINHIST_SIZE_MEDIUM		20
> +#define LINHIST_SIZE_LARGE		50
> +#define LINHIST_SIZE_XLARGE		100

nit: s/SIZE/BUCKET_COUNT/

> +#define LINHIST_BUCKET_SIZE_SMALL	10
> +#define LINHIST_BUCKET_SIZE_MEDIUM	100
> +#define LINHIST_BUCKET_SIZE_LARGE	1000
> +#define LINHIST_BUCKET_SIZE_XLARGE	10000
> +
> +#define LOGHIST_SIZE_SMALL		8
> +#define LOGHIST_SIZE_MEDIUM		16
> +#define LOGHIST_SIZE_LARGE		32
> +#define LOGHIST_SIZE_XLARGE		64

Ditto here.

> +#define LOGHIST_BASE_2			2
> +
>  struct kvm_vm_stat_generic {
>  	u64 remote_tlb_flush;
>  };
> diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> index 68c9e6d8bbda..ff34a471d9ef 100644
> --- a/include/uapi/linux/kvm.h
> +++ b/include/uapi/linux/kvm.h
> @@ -1963,7 +1963,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)
> @@ -1987,7 +1989,10 @@ struct kvm_stats_header {
>   *        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.
> + * @hist_param: A parameter value used for histogram stats. For linear
> + *              histogram stats, it indicates the size of the bucket;
> + *              For logarithmic histogram stats, it indicates the base
> + *              of the logarithm. Only base of 2 is supported.
>   * @name: The name string for the stats. Its size is indicated by the
>   *        &kvm_stats_header->name_size.
>   */
> @@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
>  	__s16 exponent;
>  	__u16 size;
>  	__u32 offset;
> -	__u32 unused;
> +	__u32 hist_param;

`hist_param` is vague. What about making this an anonymous union to make
the dual meaning explicit?

        union {
                /* Only used for KVM_STATS_TYPE_LOG_HIST. */
                __u32 base;
                /* Only used for KVM_STATS_TYPE_LINEAR_HIST. */
                __u32 bucket_size;
        };

It may make the STATS_DESC code a bit more complicated but the rest of
the code that uses it will be much more clear.

>  	char name[];
>  };
>  
> diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
> index e609d428811a..6eead6979a7f 100644
> --- a/virt/kvm/binary_stats.c
> +++ b/virt/kvm/binary_stats.c
> @@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
>  	*offset = pos;
>  	return len;
>  }
> +
> +/**
> + * 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
> + */
> +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> +				  u64 value, size_t bucket_size)
> +{
> +	size_t index = value / bucket_size;
> +
> +	if (index >= size)
> +		index = size - 1;

nit: It would be simpler to use max().

        size_t index = max(value / bucket_size, 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
> + */
> +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
> +{
> +	size_t index = fls64(value);
> +
> +	if (index >= size)
> +		index = size - 1;

Ditto here about using max().

> +	++data[index];
> +}
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-08 21:14     ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:14 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> Add documentations for linear and logarithmic histogram statistics.
> Add binary stats capability text which is missing during merge of
> the binary stats patch.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>
> ---
>  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 3b6e3b1628b4..948d33c26704 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
>  	#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_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)
> @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
>  	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
> +	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
>  
>  	#define KVM_STATS_BASE_SHIFT		8
>  	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
> +	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2

Should these FOO_MAX additions go in a separate commit too?

>  
>  	struct kvm_stats_desc {
>  		__u32 flags;
> @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
>      represents a peak value for a measurement, for example the maximum number
>      of items in a hash table bucket, the longest time waited and so on.
>      The corresponding ``size`` field for this type is always 1.
> +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> +    The statistics data is in the form of linear histogram. The number of
> +    buckets is specified by the ``size`` field. The size of buckets is specified
> +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)

Using 1-based indexes is a little jarring but maybe that's just me :).

> +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> +    value.) The bucket value indicates how many times the statistics data is in
> +    the bucket's range.
> +  * ``KVM_STATS_TYPE_LOG_HIST``
> +    The statistics data is in the form of logarithmic histogram. The number of
> +    buckets is specified by the ``size`` field. The base of logarithm is
> +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <

Should 1 be 2 here? The first bucket uses a slightly differen formula as
you mention in the next sentence.

Actually it may be clearer if you re-ordered the sentences a bit:

  The range of the first bucket is [0, 1), while the range of the last
  bucket is [pow(hist_param, size-1), +INF). Otherwise the Nth bucket
  (1-indexed) covers [pow(hist_param, N-2), pow(histparam, N-1)).

> +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> +    of the first bucket is [0, 1), while the range of the last bucket is
> +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> +    times the statistics data is in the bucket's range.
>  
>  Bits 4-7 of ``flags`` encode the unit:
>    * ``KVM_STATS_UNIT_NONE``
> @@ -5246,9 +5267,10 @@ unsigned 64bit data.
>  The ``offset`` field is the offset from the start of Data Block to the start of
>  the corresponding statistics data.
>  
> -The ``unused`` field is reserved for future support for other types of
> -statistics data, like log/linear histogram. Its value is always 0 for the types
> -defined above.
> +The ``hist_param`` field is used as a parameter for histogram statistics data.
> +For linear histogram statistics data, it indicates the size of a bucket. For
> +logarithmic histogram statistics data, it indicates the base of the logarithm.
> +Only base of 2 is supported fo logarithmic histogram.

s/fo/for/

>  
>  The ``name`` field is the name string of the statistics data. The name string
>  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
>  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
>  the hypercalls whose corresponding bit is in the argument, and return
>  ENOSYS for the others.
> +
> +8.35 KVM_CAP_STATS_BINARY_FD
> +----------------------------
> +
> +:Architectures: all
> +
> +This capability indicates the feature that userspace can get a file descriptor
> +for every VM and VCPU to read statistics data in binary format.
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-08 21:14     ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:14 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> Add documentations for linear and logarithmic histogram statistics.
> Add binary stats capability text which is missing during merge of
> the binary stats patch.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>
> ---
>  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
>  1 file changed, 33 insertions(+), 3 deletions(-)
> 
> diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> index 3b6e3b1628b4..948d33c26704 100644
> --- a/Documentation/virt/kvm/api.rst
> +++ b/Documentation/virt/kvm/api.rst
> @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
>  	#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_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)
> @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
>  	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
>  	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
> +	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
>  
>  	#define KVM_STATS_BASE_SHIFT		8
>  	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
>  	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
> +	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2

Should these FOO_MAX additions go in a separate commit too?

>  
>  	struct kvm_stats_desc {
>  		__u32 flags;
> @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
>      represents a peak value for a measurement, for example the maximum number
>      of items in a hash table bucket, the longest time waited and so on.
>      The corresponding ``size`` field for this type is always 1.
> +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> +    The statistics data is in the form of linear histogram. The number of
> +    buckets is specified by the ``size`` field. The size of buckets is specified
> +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)

Using 1-based indexes is a little jarring but maybe that's just me :).

> +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> +    value.) The bucket value indicates how many times the statistics data is in
> +    the bucket's range.
> +  * ``KVM_STATS_TYPE_LOG_HIST``
> +    The statistics data is in the form of logarithmic histogram. The number of
> +    buckets is specified by the ``size`` field. The base of logarithm is
> +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <

Should 1 be 2 here? The first bucket uses a slightly differen formula as
you mention in the next sentence.

Actually it may be clearer if you re-ordered the sentences a bit:

  The range of the first bucket is [0, 1), while the range of the last
  bucket is [pow(hist_param, size-1), +INF). Otherwise the Nth bucket
  (1-indexed) covers [pow(hist_param, N-2), pow(histparam, N-1)).

> +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> +    of the first bucket is [0, 1), while the range of the last bucket is
> +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> +    times the statistics data is in the bucket's range.
>  
>  Bits 4-7 of ``flags`` encode the unit:
>    * ``KVM_STATS_UNIT_NONE``
> @@ -5246,9 +5267,10 @@ unsigned 64bit data.
>  The ``offset`` field is the offset from the start of Data Block to the start of
>  the corresponding statistics data.
>  
> -The ``unused`` field is reserved for future support for other types of
> -statistics data, like log/linear histogram. Its value is always 0 for the types
> -defined above.
> +The ``hist_param`` field is used as a parameter for histogram statistics data.
> +For linear histogram statistics data, it indicates the size of a bucket. For
> +logarithmic histogram statistics data, it indicates the base of the logarithm.
> +Only base of 2 is supported fo logarithmic histogram.

s/fo/for/

>  
>  The ``name`` field is the name string of the statistics data. The name string
>  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
>  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
>  the hypercalls whose corresponding bit is in the argument, and return
>  ENOSYS for the others.
> +
> +8.35 KVM_CAP_STATS_BINARY_FD
> +----------------------------
> +
> +:Architectures: all
> +
> +This capability indicates the feature that userspace can get a file descriptor
> +for every VM and VCPU to read statistics data in binary format.
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-08 21:14     ` David Matlack
@ 2021-07-08 21:16       ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:16 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 08, 2021 at 09:14:38PM +0000, David Matlack wrote:
> On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> > Add documentations for linear and logarithmic histogram statistics.
> > Add binary stats capability text which is missing during merge of
> > the binary stats patch.
> > 
> > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > ---
> >  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
> >  1 file changed, 33 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index 3b6e3b1628b4..948d33c26704 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
> >  	#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_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)
> > @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
> >  	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
> >  	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
> >  	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
> > +	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
> >  
> >  	#define KVM_STATS_BASE_SHIFT		8
> >  	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
> >  	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
> >  	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
> > +	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2
> 
> Should these FOO_MAX additions go in a separate commit too?
> 
> >  
> >  	struct kvm_stats_desc {
> >  		__u32 flags;
> > @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
> >      represents a peak value for a measurement, for example the maximum number
> >      of items in a hash table bucket, the longest time waited and so on.
> >      The corresponding ``size`` field for this type is always 1.
> > +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> > +    The statistics data is in the form of linear histogram. The number of
> > +    buckets is specified by the ``size`` field. The size of buckets is specified
> > +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> 
> Using 1-based indexes is a little jarring but maybe that's just me :).
> 
> > +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> > +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> > +    value.) The bucket value indicates how many times the statistics data is in
> > +    the bucket's range.
> > +  * ``KVM_STATS_TYPE_LOG_HIST``
> > +    The statistics data is in the form of logarithmic histogram. The number of
> > +    buckets is specified by the ``size`` field. The base of logarithm is
> > +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> 
> Should 1 be 2 here? The first bucket uses a slightly differen formula as
> you mention in the next sentence.

Oops I see you used "<" instead of "<=" so what you have is correct. I
think reordering the sentences would still be helpfull though.

> 
> Actually it may be clearer if you re-ordered the sentences a bit:
> 
>   The range of the first bucket is [0, 1), while the range of the last
>   bucket is [pow(hist_param, size-1), +INF). Otherwise the Nth bucket
>   (1-indexed) covers [pow(hist_param, N-2), pow(histparam, N-1)).
> 
> > +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> > +    of the first bucket is [0, 1), while the range of the last bucket is
> > +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> > +    times the statistics data is in the bucket's range.
> >  
> >  Bits 4-7 of ``flags`` encode the unit:
> >    * ``KVM_STATS_UNIT_NONE``
> > @@ -5246,9 +5267,10 @@ unsigned 64bit data.
> >  The ``offset`` field is the offset from the start of Data Block to the start of
> >  the corresponding statistics data.
> >  
> > -The ``unused`` field is reserved for future support for other types of
> > -statistics data, like log/linear histogram. Its value is always 0 for the types
> > -defined above.
> > +The ``hist_param`` field is used as a parameter for histogram statistics data.
> > +For linear histogram statistics data, it indicates the size of a bucket. For
> > +logarithmic histogram statistics data, it indicates the base of the logarithm.
> > +Only base of 2 is supported fo logarithmic histogram.
> 
> s/fo/for/
> 
> >  
> >  The ``name`` field is the name string of the statistics data. The name string
> >  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> > @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
> >  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
> >  the hypercalls whose corresponding bit is in the argument, and return
> >  ENOSYS for the others.
> > +
> > +8.35 KVM_CAP_STATS_BINARY_FD
> > +----------------------------
> > +
> > +:Architectures: all
> > +
> > +This capability indicates the feature that userspace can get a file descriptor
> > +for every VM and VCPU to read statistics data in binary format.
> > -- 
> > 2.32.0.93.g670b81a890-goog
> > 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-08 21:16       ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:16 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 08, 2021 at 09:14:38PM +0000, David Matlack wrote:
> On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> > Add documentations for linear and logarithmic histogram statistics.
> > Add binary stats capability text which is missing during merge of
> > the binary stats patch.
> > 
> > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > ---
> >  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
> >  1 file changed, 33 insertions(+), 3 deletions(-)
> > 
> > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > index 3b6e3b1628b4..948d33c26704 100644
> > --- a/Documentation/virt/kvm/api.rst
> > +++ b/Documentation/virt/kvm/api.rst
> > @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
> >  	#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_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)
> > @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
> >  	#define KVM_STATS_UNIT_BYTES		(0x1 << KVM_STATS_UNIT_SHIFT)
> >  	#define KVM_STATS_UNIT_SECONDS		(0x2 << KVM_STATS_UNIT_SHIFT)
> >  	#define KVM_STATS_UNIT_CYCLES		(0x3 << KVM_STATS_UNIT_SHIFT)
> > +	#define KVM_STATS_UNIT_MAX		KVM_STATS_UNIT_CYCLES
> >  
> >  	#define KVM_STATS_BASE_SHIFT		8
> >  	#define KVM_STATS_BASE_MASK		(0xF << KVM_STATS_BASE_SHIFT)
> >  	#define KVM_STATS_BASE_POW10		(0x0 << KVM_STATS_BASE_SHIFT)
> >  	#define KVM_STATS_BASE_POW2		(0x1 << KVM_STATS_BASE_SHIFT)
> > +	#define KVM_STATS_BASE_MAX		KVM_STATS_BASE_POW2
> 
> Should these FOO_MAX additions go in a separate commit too?
> 
> >  
> >  	struct kvm_stats_desc {
> >  		__u32 flags;
> > @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
> >      represents a peak value for a measurement, for example the maximum number
> >      of items in a hash table bucket, the longest time waited and so on.
> >      The corresponding ``size`` field for this type is always 1.
> > +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> > +    The statistics data is in the form of linear histogram. The number of
> > +    buckets is specified by the ``size`` field. The size of buckets is specified
> > +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> 
> Using 1-based indexes is a little jarring but maybe that's just me :).
> 
> > +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> > +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> > +    value.) The bucket value indicates how many times the statistics data is in
> > +    the bucket's range.
> > +  * ``KVM_STATS_TYPE_LOG_HIST``
> > +    The statistics data is in the form of logarithmic histogram. The number of
> > +    buckets is specified by the ``size`` field. The base of logarithm is
> > +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> 
> Should 1 be 2 here? The first bucket uses a slightly differen formula as
> you mention in the next sentence.

Oops I see you used "<" instead of "<=" so what you have is correct. I
think reordering the sentences would still be helpfull though.

> 
> Actually it may be clearer if you re-ordered the sentences a bit:
> 
>   The range of the first bucket is [0, 1), while the range of the last
>   bucket is [pow(hist_param, size-1), +INF). Otherwise the Nth bucket
>   (1-indexed) covers [pow(hist_param, N-2), pow(histparam, N-1)).
> 
> > +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> > +    of the first bucket is [0, 1), while the range of the last bucket is
> > +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> > +    times the statistics data is in the bucket's range.
> >  
> >  Bits 4-7 of ``flags`` encode the unit:
> >    * ``KVM_STATS_UNIT_NONE``
> > @@ -5246,9 +5267,10 @@ unsigned 64bit data.
> >  The ``offset`` field is the offset from the start of Data Block to the start of
> >  the corresponding statistics data.
> >  
> > -The ``unused`` field is reserved for future support for other types of
> > -statistics data, like log/linear histogram. Its value is always 0 for the types
> > -defined above.
> > +The ``hist_param`` field is used as a parameter for histogram statistics data.
> > +For linear histogram statistics data, it indicates the size of a bucket. For
> > +logarithmic histogram statistics data, it indicates the base of the logarithm.
> > +Only base of 2 is supported fo logarithmic histogram.
> 
> s/fo/for/
> 
> >  
> >  The ``name`` field is the name string of the statistics data. The name string
> >  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> > @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
> >  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
> >  the hypercalls whose corresponding bit is in the argument, and return
> >  ENOSYS for the others.
> > +
> > +8.35 KVM_CAP_STATS_BINARY_FD
> > +----------------------------
> > +
> > +:Architectures: all
> > +
> > +This capability indicates the feature that userspace can get a file descriptor
> > +for every VM and VCPU to read statistics data in binary format.
> > -- 
> > 2.32.0.93.g670b81a890-goog
> > 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 3/4] KVM: selftests: Add checks for histogram stats parameters
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-08 21:26     ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:26 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:49PM +0000, Jing Zhang wrote:
> The hist_param field should be zero for simple stats and 2 for
> logarithmic histogram. It shouldbe non-zero for linear histogram stats.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>

Reviewed-by: David Matlack <dmatlack@google.com>

> ---
>  .../selftests/kvm/kvm_binary_stats_test.c       | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
> index 5906bbc08483..03c7842fcb26 100644
> --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c
> +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
> @@ -109,6 +109,23 @@ static void stats_test(int stats_fd)
>  		/* Check size field, which should not be zero */
>  		TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0",
>  				pdesc->name);
> +		/* Check hist_param field */
> +		switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
> +		case KVM_STATS_TYPE_LINEAR_HIST:
> +			TEST_ASSERT(pdesc->hist_param,
> +			    "Bucket size of Linear Histogram stats (%s) is zero",
> +			    pdesc->name);
> +			break;
> +		case KVM_STATS_TYPE_LOG_HIST:
> +			TEST_ASSERT(pdesc->hist_param == 2,
> +				"Base of Log Histogram stats (%s) is not 2",
> +				pdesc->name);
> +			break;
> +		default:
> +			TEST_ASSERT(!pdesc->hist_param,
> +			    "Simple stats (%s) with hist_param of nonzero",
> +			    pdesc->name);
> +		}
>  		size_data += pdesc->size * sizeof(*stats_data);
>  	}
>  	/* Check overlap */
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 3/4] KVM: selftests: Add checks for histogram stats parameters
@ 2021-07-08 21:26     ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:26 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:49PM +0000, Jing Zhang wrote:
> The hist_param field should be zero for simple stats and 2 for
> logarithmic histogram. It shouldbe non-zero for linear histogram stats.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>

Reviewed-by: David Matlack <dmatlack@google.com>

> ---
>  .../selftests/kvm/kvm_binary_stats_test.c       | 17 +++++++++++++++++
>  1 file changed, 17 insertions(+)
> 
> diff --git a/tools/testing/selftests/kvm/kvm_binary_stats_test.c b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
> index 5906bbc08483..03c7842fcb26 100644
> --- a/tools/testing/selftests/kvm/kvm_binary_stats_test.c
> +++ b/tools/testing/selftests/kvm/kvm_binary_stats_test.c
> @@ -109,6 +109,23 @@ static void stats_test(int stats_fd)
>  		/* Check size field, which should not be zero */
>  		TEST_ASSERT(pdesc->size, "KVM descriptor(%s) with size of 0",
>  				pdesc->name);
> +		/* Check hist_param field */
> +		switch (pdesc->flags & KVM_STATS_TYPE_MASK) {
> +		case KVM_STATS_TYPE_LINEAR_HIST:
> +			TEST_ASSERT(pdesc->hist_param,
> +			    "Bucket size of Linear Histogram stats (%s) is zero",
> +			    pdesc->name);
> +			break;
> +		case KVM_STATS_TYPE_LOG_HIST:
> +			TEST_ASSERT(pdesc->hist_param = 2,
> +				"Base of Log Histogram stats (%s) is not 2",
> +				pdesc->name);
> +			break;
> +		default:
> +			TEST_ASSERT(!pdesc->hist_param,
> +			    "Simple stats (%s) with hist_param of nonzero",
> +			    pdesc->name);
> +		}
>  		size_data += pdesc->size * sizeof(*stats_data);
>  	}
>  	/* Check overlap */
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-08 21:01     ` David Matlack
@ 2021-07-08 21:40       ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-08 21:40 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 8, 2021 at 4:01 PM David Matlack <dmatlack@google.com> wrote:
>
> On Tue, Jul 06, 2021 at 06:03:47PM +0000, Jing Zhang wrote:
> > 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>
> > ---
> >  arch/arm64/kvm/guest.c    |  4 ---
> >  arch/mips/kvm/mips.c      |  4 ---
> >  arch/powerpc/kvm/book3s.c |  4 ---
> >  arch/powerpc/kvm/booke.c  |  4 ---
> >  arch/s390/kvm/kvm-s390.c  |  4 ---
> >  arch/x86/kvm/x86.c        |  4 ---
> >  include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
> >  include/linux/kvm_types.h | 16 ++++++++++++
> >  include/uapi/linux/kvm.h  | 11 +++++---
> >  virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
> >  10 files changed, 98 insertions(+), 42 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> > index 1512a8007a78..cb44d8756fa7 100644
> > --- a/arch/arm64/kvm/guest.c
> > +++ b/arch/arm64/kvm/guest.c
> > @@ -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,
> > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> > index af9dd029a4e1..75c6f264c626 100644
> > --- a/arch/mips/kvm/mips.c
> > +++ b/arch/mips/kvm/mips.c
> > @@ -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,
> > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> > index 79833f78d1da..5cc6e90095b0 100644
> > --- a/arch/powerpc/kvm/book3s.c
> > +++ b/arch/powerpc/kvm/book3s.c
> > @@ -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,
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > index 551b30d84aee..5ed6c235e059 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -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,
> > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> > index 1695f0ced5ba..7610d33d319b 100644
> > --- a/arch/s390/kvm/kvm-s390.c
> > +++ b/arch/s390/kvm/kvm-s390.c
> > @@ -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, 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,
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index 8166ad113fb2..b94a80ad5b8d 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
> >       STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
> >       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,
> > @@ -280,8 +278,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,
> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > index ae7735b490b4..356af173114d 100644
> > --- a/include/linux/kvm_host.h
> > +++ b/include/linux/kvm_host.h
> > @@ -1273,56 +1273,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, param)                 \
> >       .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,                                                            \
> > +     .hist_param = param
> >
> > -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)                  \
> > +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)               \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)             \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)                       \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)                     \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)           \
> > +     SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
> >
> >  #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, param)   \
> > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,                    \
> > +             unit, base, exponent, sz, param)
> > +#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
> > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,                       \
> > +             unit, base, exponent, sz, param)
> >
> >  /* Cumulative counter, read/write */
> >  #define STATS_DESC_COUNTER(SCOPE, name)                                             \
> > @@ -1341,6 +1351,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, bucket_size)          \
> > +     STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,            \
> > +             KVM_STATS_BASE_POW10, -9, sz, bucket_size)
> > +/* 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, LOGHIST_BASE_2)
> >
> >  #define KVM_GENERIC_VM_STATS()                                                      \
> >       STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
> > @@ -1354,10 +1372,15 @@ 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);
> > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > +                               u64 value, size_t bucket_size);
> > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
> > diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> > index ed6a985c5680..cc88cd676775 100644
> > --- a/include/linux/kvm_types.h
> > +++ b/include/linux/kvm_types.h
> > @@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
> >  };
> >  #endif
> >
> > +/* Constants used for histogram stats */
> > +#define LINHIST_SIZE_SMALL           10
> > +#define LINHIST_SIZE_MEDIUM          20
> > +#define LINHIST_SIZE_LARGE           50
> > +#define LINHIST_SIZE_XLARGE          100
>
> nit: s/SIZE/BUCKET_COUNT/
>
Sure, it makes more sense.
> > +#define LINHIST_BUCKET_SIZE_SMALL    10
> > +#define LINHIST_BUCKET_SIZE_MEDIUM   100
> > +#define LINHIST_BUCKET_SIZE_LARGE    1000
> > +#define LINHIST_BUCKET_SIZE_XLARGE   10000
> > +
> > +#define LOGHIST_SIZE_SMALL           8
> > +#define LOGHIST_SIZE_MEDIUM          16
> > +#define LOGHIST_SIZE_LARGE           32
> > +#define LOGHIST_SIZE_XLARGE          64
>
> Ditto here.
>
Will do.
> > +#define LOGHIST_BASE_2                       2
> > +
> >  struct kvm_vm_stat_generic {
> >       u64 remote_tlb_flush;
> >  };
> > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > index 68c9e6d8bbda..ff34a471d9ef 100644
> > --- a/include/uapi/linux/kvm.h
> > +++ b/include/uapi/linux/kvm.h
> > @@ -1963,7 +1963,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)
> > @@ -1987,7 +1989,10 @@ struct kvm_stats_header {
> >   *        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.
> > + * @hist_param: A parameter value used for histogram stats. For linear
> > + *              histogram stats, it indicates the size of the bucket;
> > + *              For logarithmic histogram stats, it indicates the base
> > + *              of the logarithm. Only base of 2 is supported.
> >   * @name: The name string for the stats. Its size is indicated by the
> >   *        &kvm_stats_header->name_size.
> >   */
> > @@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
> >       __s16 exponent;
> >       __u16 size;
> >       __u32 offset;
> > -     __u32 unused;
> > +     __u32 hist_param;
>
> `hist_param` is vague. What about making this an anonymous union to make
> the dual meaning explicit?
>
>         union {
>                 /* Only used for KVM_STATS_TYPE_LOG_HIST. */
>                 __u32 base;
>                 /* Only used for KVM_STATS_TYPE_LINEAR_HIST. */
>                 __u32 bucket_size;
>         };
>
> It may make the STATS_DESC code a bit more complicated but the rest of
> the code that uses it will be much more clear.
>
Since we only support base-2 log hist, maybe it is not necessary to
have the base field.
The reason to only support base-2 log hist is that its range is
already large enough for
any stats.
Will just change hist_param to bucket_size.
> >       char name[];
> >  };
> >
> > diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
> > index e609d428811a..6eead6979a7f 100644
> > --- a/virt/kvm/binary_stats.c
> > +++ b/virt/kvm/binary_stats.c
> > @@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
> >       *offset = pos;
> >       return len;
> >  }
> > +
> > +/**
> > + * 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
> > + */
> > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > +                               u64 value, size_t bucket_size)
> > +{
> > +     size_t index = value / bucket_size;
> > +
> > +     if (index >= size)
> > +             index = size - 1;
>
> nit: It would be simpler to use max().
>
>         size_t index = max(value / bucket_size, size - 1);
>
Will do.
> > +     ++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
> > + */
> > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
> > +{
> > +     size_t index = fls64(value);
> > +
> > +     if (index >= size)
> > +             index = size - 1;
>
> Ditto here about using max().
>
Will do.
> > +     ++data[index];
> > +}
> > --
> > 2.32.0.93.g670b81a890-goog
> >
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-08 21:40       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-08 21:40 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 8, 2021 at 4:01 PM David Matlack <dmatlack@google.com> wrote:
>
> On Tue, Jul 06, 2021 at 06:03:47PM +0000, Jing Zhang wrote:
> > 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>
> > ---
> >  arch/arm64/kvm/guest.c    |  4 ---
> >  arch/mips/kvm/mips.c      |  4 ---
> >  arch/powerpc/kvm/book3s.c |  4 ---
> >  arch/powerpc/kvm/booke.c  |  4 ---
> >  arch/s390/kvm/kvm-s390.c  |  4 ---
> >  arch/x86/kvm/x86.c        |  4 ---
> >  include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
> >  include/linux/kvm_types.h | 16 ++++++++++++
> >  include/uapi/linux/kvm.h  | 11 +++++---
> >  virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
> >  10 files changed, 98 insertions(+), 42 deletions(-)
> >
> > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> > index 1512a8007a78..cb44d8756fa7 100644
> > --- a/arch/arm64/kvm/guest.c
> > +++ b/arch/arm64/kvm/guest.c
> > @@ -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,
> > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> > index af9dd029a4e1..75c6f264c626 100644
> > --- a/arch/mips/kvm/mips.c
> > +++ b/arch/mips/kvm/mips.c
> > @@ -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,
> > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> > index 79833f78d1da..5cc6e90095b0 100644
> > --- a/arch/powerpc/kvm/book3s.c
> > +++ b/arch/powerpc/kvm/book3s.c
> > @@ -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,
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > index 551b30d84aee..5ed6c235e059 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -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,
> > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> > index 1695f0ced5ba..7610d33d319b 100644
> > --- a/arch/s390/kvm/kvm-s390.c
> > +++ b/arch/s390/kvm/kvm-s390.c
> > @@ -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, 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,
> > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > index 8166ad113fb2..b94a80ad5b8d 100644
> > --- a/arch/x86/kvm/x86.c
> > +++ b/arch/x86/kvm/x86.c
> > @@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
> >       STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
> >       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,
> > @@ -280,8 +278,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,
> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > index ae7735b490b4..356af173114d 100644
> > --- a/include/linux/kvm_host.h
> > +++ b/include/linux/kvm_host.h
> > @@ -1273,56 +1273,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, param)                 \
> >       .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,                                                            \
> > +     .hist_param = param
> >
> > -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)                  \
> > +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)               \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)             \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)                       \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)                     \
> >       {                                                                      \
> >               {                                                              \
> > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> >                       .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, param)           \
> > +     SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
> >
> >  #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, param)   \
> > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,                    \
> > +             unit, base, exponent, sz, param)
> > +#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
> > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,                       \
> > +             unit, base, exponent, sz, param)
> >
> >  /* Cumulative counter, read/write */
> >  #define STATS_DESC_COUNTER(SCOPE, name)                                             \
> > @@ -1341,6 +1351,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, bucket_size)          \
> > +     STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,            \
> > +             KVM_STATS_BASE_POW10, -9, sz, bucket_size)
> > +/* 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, LOGHIST_BASE_2)
> >
> >  #define KVM_GENERIC_VM_STATS()                                                      \
> >       STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
> > @@ -1354,10 +1372,15 @@ 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);
> > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > +                               u64 value, size_t bucket_size);
> > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
> > diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> > index ed6a985c5680..cc88cd676775 100644
> > --- a/include/linux/kvm_types.h
> > +++ b/include/linux/kvm_types.h
> > @@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
> >  };
> >  #endif
> >
> > +/* Constants used for histogram stats */
> > +#define LINHIST_SIZE_SMALL           10
> > +#define LINHIST_SIZE_MEDIUM          20
> > +#define LINHIST_SIZE_LARGE           50
> > +#define LINHIST_SIZE_XLARGE          100
>
> nit: s/SIZE/BUCKET_COUNT/
>
Sure, it makes more sense.
> > +#define LINHIST_BUCKET_SIZE_SMALL    10
> > +#define LINHIST_BUCKET_SIZE_MEDIUM   100
> > +#define LINHIST_BUCKET_SIZE_LARGE    1000
> > +#define LINHIST_BUCKET_SIZE_XLARGE   10000
> > +
> > +#define LOGHIST_SIZE_SMALL           8
> > +#define LOGHIST_SIZE_MEDIUM          16
> > +#define LOGHIST_SIZE_LARGE           32
> > +#define LOGHIST_SIZE_XLARGE          64
>
> Ditto here.
>
Will do.
> > +#define LOGHIST_BASE_2                       2
> > +
> >  struct kvm_vm_stat_generic {
> >       u64 remote_tlb_flush;
> >  };
> > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > index 68c9e6d8bbda..ff34a471d9ef 100644
> > --- a/include/uapi/linux/kvm.h
> > +++ b/include/uapi/linux/kvm.h
> > @@ -1963,7 +1963,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)
> > @@ -1987,7 +1989,10 @@ struct kvm_stats_header {
> >   *        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.
> > + * @hist_param: A parameter value used for histogram stats. For linear
> > + *              histogram stats, it indicates the size of the bucket;
> > + *              For logarithmic histogram stats, it indicates the base
> > + *              of the logarithm. Only base of 2 is supported.
> >   * @name: The name string for the stats. Its size is indicated by the
> >   *        &kvm_stats_header->name_size.
> >   */
> > @@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
> >       __s16 exponent;
> >       __u16 size;
> >       __u32 offset;
> > -     __u32 unused;
> > +     __u32 hist_param;
>
> `hist_param` is vague. What about making this an anonymous union to make
> the dual meaning explicit?
>
>         union {
>                 /* Only used for KVM_STATS_TYPE_LOG_HIST. */
>                 __u32 base;
>                 /* Only used for KVM_STATS_TYPE_LINEAR_HIST. */
>                 __u32 bucket_size;
>         };
>
> It may make the STATS_DESC code a bit more complicated but the rest of
> the code that uses it will be much more clear.
>
Since we only support base-2 log hist, maybe it is not necessary to
have the base field.
The reason to only support base-2 log hist is that its range is
already large enough for
any stats.
Will just change hist_param to bucket_size.
> >       char name[];
> >  };
> >
> > diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
> > index e609d428811a..6eead6979a7f 100644
> > --- a/virt/kvm/binary_stats.c
> > +++ b/virt/kvm/binary_stats.c
> > @@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
> >       *offset = pos;
> >       return len;
> >  }
> > +
> > +/**
> > + * 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
> > + */
> > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > +                               u64 value, size_t bucket_size)
> > +{
> > +     size_t index = value / bucket_size;
> > +
> > +     if (index >= size)
> > +             index = size - 1;
>
> nit: It would be simpler to use max().
>
>         size_t index = max(value / bucket_size, size - 1);
>
Will do.
> > +     ++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
> > + */
> > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
> > +{
> > +     size_t index = fls64(value);
> > +
> > +     if (index >= size)
> > +             index = size - 1;
>
> Ditto here about using max().
>
Will do.
> > +     ++data[index];
> > +}
> > --
> > 2.32.0.93.g670b81a890-goog
> >
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-08 21:42     ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:42 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:50PM +0000, Jing Zhang wrote:
> Add simple stats halt_wait_ns to record the time a VCPU has spent on
> waiting for all architectures (not just powerpc).
> Add three log histogram stats to record the distribution of time spent
> on successful polling, failed polling and VCPU wait.
> halt_poll_success_hist: Distribution of time spent before a successful
> polling.
> halt_poll_fail_hist: Distribution of time spent before a failed polling.
> halt_wait_hist: Distribution of time a VCPU has spent on waiting.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>
> ---
>  arch/powerpc/include/asm/kvm_host.h |  1 -
>  arch/powerpc/kvm/book3s.c           |  1 -
>  arch/powerpc/kvm/book3s_hv.c        | 20 +++++++++++++++++---
>  arch/powerpc/kvm/booke.c            |  1 -
>  include/linux/kvm_host.h            |  9 ++++++++-
>  include/linux/kvm_types.h           |  4 ++++
>  virt/kvm/kvm_main.c                 | 19 +++++++++++++++++++
>  7 files changed, 48 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index 9f52f282b1aa..4931d03e5799 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
>  	u64 emulated_inst_exits;
>  	u64 dec_exits;
>  	u64 ext_intr_exits;
> -	u64 halt_wait_ns;

The halt_wait_ns refactor should be a separate patch.

>  	u64 halt_successful_wait;
>  	u64 dbell_exits;
>  	u64 gdbell_exits;
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 5cc6e90095b0..b785f6772391 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -69,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
>  	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
>  	STATS_DESC_COUNTER(VCPU, dec_exits),
>  	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> -	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
>  	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
>  	STATS_DESC_COUNTER(VCPU, dbell_exits),
>  	STATS_DESC_COUNTER(VCPU, gdbell_exits),
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index cd544a46183e..103f998cee75 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -4144,19 +4144,33 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
>  
>  	/* Attribute wait time */
>  	if (do_sleep) {
> -		vc->runner->stat.halt_wait_ns +=
> +		vc->runner->stat.generic.halt_wait_ns +=
>  			ktime_to_ns(cur) - ktime_to_ns(start_wait);
> +		kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_wait_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(start_wait));
>  		/* Attribute failed poll time */
> -		if (vc->halt_poll_ns)
> +		if (vc->halt_poll_ns) {
>  			vc->runner->stat.generic.halt_poll_fail_ns +=
>  				ktime_to_ns(start_wait) -
>  				ktime_to_ns(start_poll);
> +			kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_poll_fail_hist,
> +				LOGHIST_SIZE_LARGE, ktime_to_ns(start_wait) -
> +				ktime_to_ns(start_poll));
> +		}
>  	} else {
>  		/* Attribute successful poll time */
> -		if (vc->halt_poll_ns)
> +		if (vc->halt_poll_ns) {
>  			vc->runner->stat.generic.halt_poll_success_ns +=
>  				ktime_to_ns(cur) -
>  				ktime_to_ns(start_poll);
> +			kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_poll_success_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(start_poll));
> +		}
>  	}
>  
>  	/* Adjust poll time */
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 5ed6c235e059..977801c83aff 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -67,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
>  	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
>  	STATS_DESC_COUNTER(VCPU, dec_exits),
>  	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> -	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
>  	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
>  	STATS_DESC_COUNTER(VCPU, dbell_exits),
>  	STATS_DESC_COUNTER(VCPU, gdbell_exits),
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 356af173114d..268a0ccc9c5f 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1369,7 +1369,14 @@ struct _kvm_stats_desc {
>  	STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid),		       \
>  	STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup),			       \
>  	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns),	       \
> -	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
> +	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns),		       \
> +	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist,     \
> +			LOGHIST_SIZE_LARGE),				       \

This should probably be a new macro rather than using LOGHIST_SIZE_LARGE
everywhere.

#define HALT_POLL_HIST_SIZE LOGHIST_SIZE_LARGE

> +	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist,	       \
> +			LOGHIST_SIZE_LARGE),				       \
> +	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns),		       \
> +	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist,	       \
> +			LOGHIST_SIZE_LARGE)
>  
>  extern struct dentry *kvm_debugfs_dir;
>  
> diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> index cc88cd676775..7838a42932c8 100644
> --- a/include/linux/kvm_types.h
> +++ b/include/linux/kvm_types.h
> @@ -103,6 +103,10 @@ struct kvm_vcpu_stat_generic {
>  	u64 halt_wakeup;
>  	u64 halt_poll_success_ns;
>  	u64 halt_poll_fail_ns;
> +	u64 halt_poll_success_hist[LOGHIST_SIZE_LARGE];
> +	u64 halt_poll_fail_hist[LOGHIST_SIZE_LARGE];
> +	u64 halt_wait_ns;
> +	u64 halt_wait_hist[LOGHIST_SIZE_LARGE];
>  };
>  
>  #define KVM_STATS_NAME_SIZE	48
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 3dcc2abbfc60..840b5bece080 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -3093,12 +3093,24 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
>  				++vcpu->stat.generic.halt_successful_poll;
>  				if (!vcpu_valid_wakeup(vcpu))
>  					++vcpu->stat.generic.halt_poll_invalid;
> +
> +				kvm_stats_log_hist_update(
> +				      vcpu->stat.generic.halt_poll_success_hist,
> +				      LOGHIST_SIZE_LARGE,
> +				      ktime_to_ns(ktime_get()) -
> +				      ktime_to_ns(start));
>  				goto out;
>  			}
>  			poll_end = cur = ktime_get();
>  		} while (kvm_vcpu_can_poll(cur, stop));
> +
> +		kvm_stats_log_hist_update(
> +				vcpu->stat.generic.halt_poll_fail_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(ktime_get()) - ktime_to_ns(start));

nit: Consider creating a wrapper for kvm_stats_log_hist_update() since
there are so many call sites. You can save a line at every call site by
avoiding passing in the histogram size.

        void halt_poll_hist_update(u64 *histogram, ktime_t time)
        {
                kvm_stats_log_hist_update(histogram, LOGHIST_SIZE_LARGE, time);
        }


>  	}
>  
> +
>  	prepare_to_rcuwait(&vcpu->wait);
>  	for (;;) {
>  		set_current_state(TASK_INTERRUPTIBLE);
> @@ -3111,6 +3123,13 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
>  	}
>  	finish_rcuwait(&vcpu->wait);
>  	cur = ktime_get();
> +	if (waited) {
> +		vcpu->stat.generic.halt_wait_ns +=
> +			ktime_to_ns(cur) - ktime_to_ns(poll_end);
> +		kvm_stats_log_hist_update(vcpu->stat.generic.halt_wait_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(poll_end));
> +	}
>  out:
>  	kvm_arch_vcpu_unblocking(vcpu);
>  	block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
@ 2021-07-08 21:42     ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:42 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Tue, Jul 06, 2021 at 06:03:50PM +0000, Jing Zhang wrote:
> Add simple stats halt_wait_ns to record the time a VCPU has spent on
> waiting for all architectures (not just powerpc).
> Add three log histogram stats to record the distribution of time spent
> on successful polling, failed polling and VCPU wait.
> halt_poll_success_hist: Distribution of time spent before a successful
> polling.
> halt_poll_fail_hist: Distribution of time spent before a failed polling.
> halt_wait_hist: Distribution of time a VCPU has spent on waiting.
> 
> Signed-off-by: Jing Zhang <jingzhangos@google.com>
> ---
>  arch/powerpc/include/asm/kvm_host.h |  1 -
>  arch/powerpc/kvm/book3s.c           |  1 -
>  arch/powerpc/kvm/book3s_hv.c        | 20 +++++++++++++++++---
>  arch/powerpc/kvm/booke.c            |  1 -
>  include/linux/kvm_host.h            |  9 ++++++++-
>  include/linux/kvm_types.h           |  4 ++++
>  virt/kvm/kvm_main.c                 | 19 +++++++++++++++++++
>  7 files changed, 48 insertions(+), 7 deletions(-)
> 
> diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> index 9f52f282b1aa..4931d03e5799 100644
> --- a/arch/powerpc/include/asm/kvm_host.h
> +++ b/arch/powerpc/include/asm/kvm_host.h
> @@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
>  	u64 emulated_inst_exits;
>  	u64 dec_exits;
>  	u64 ext_intr_exits;
> -	u64 halt_wait_ns;

The halt_wait_ns refactor should be a separate patch.

>  	u64 halt_successful_wait;
>  	u64 dbell_exits;
>  	u64 gdbell_exits;
> diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> index 5cc6e90095b0..b785f6772391 100644
> --- a/arch/powerpc/kvm/book3s.c
> +++ b/arch/powerpc/kvm/book3s.c
> @@ -69,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
>  	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
>  	STATS_DESC_COUNTER(VCPU, dec_exits),
>  	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> -	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
>  	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
>  	STATS_DESC_COUNTER(VCPU, dbell_exits),
>  	STATS_DESC_COUNTER(VCPU, gdbell_exits),
> diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> index cd544a46183e..103f998cee75 100644
> --- a/arch/powerpc/kvm/book3s_hv.c
> +++ b/arch/powerpc/kvm/book3s_hv.c
> @@ -4144,19 +4144,33 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
>  
>  	/* Attribute wait time */
>  	if (do_sleep) {
> -		vc->runner->stat.halt_wait_ns +> +		vc->runner->stat.generic.halt_wait_ns +>  			ktime_to_ns(cur) - ktime_to_ns(start_wait);
> +		kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_wait_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(start_wait));
>  		/* Attribute failed poll time */
> -		if (vc->halt_poll_ns)
> +		if (vc->halt_poll_ns) {
>  			vc->runner->stat.generic.halt_poll_fail_ns +>  				ktime_to_ns(start_wait) -
>  				ktime_to_ns(start_poll);
> +			kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_poll_fail_hist,
> +				LOGHIST_SIZE_LARGE, ktime_to_ns(start_wait) -
> +				ktime_to_ns(start_poll));
> +		}
>  	} else {
>  		/* Attribute successful poll time */
> -		if (vc->halt_poll_ns)
> +		if (vc->halt_poll_ns) {
>  			vc->runner->stat.generic.halt_poll_success_ns +>  				ktime_to_ns(cur) -
>  				ktime_to_ns(start_poll);
> +			kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_poll_success_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(start_poll));
> +		}
>  	}
>  
>  	/* Adjust poll time */
> diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> index 5ed6c235e059..977801c83aff 100644
> --- a/arch/powerpc/kvm/booke.c
> +++ b/arch/powerpc/kvm/booke.c
> @@ -67,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
>  	STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
>  	STATS_DESC_COUNTER(VCPU, dec_exits),
>  	STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> -	STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
>  	STATS_DESC_COUNTER(VCPU, halt_successful_wait),
>  	STATS_DESC_COUNTER(VCPU, dbell_exits),
>  	STATS_DESC_COUNTER(VCPU, gdbell_exits),
> diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> index 356af173114d..268a0ccc9c5f 100644
> --- a/include/linux/kvm_host.h
> +++ b/include/linux/kvm_host.h
> @@ -1369,7 +1369,14 @@ struct _kvm_stats_desc {
>  	STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid),		       \
>  	STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup),			       \
>  	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns),	       \
> -	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
> +	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns),		       \
> +	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist,     \
> +			LOGHIST_SIZE_LARGE),				       \

This should probably be a new macro rather than using LOGHIST_SIZE_LARGE
everywhere.

#define HALT_POLL_HIST_SIZE LOGHIST_SIZE_LARGE

> +	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist,	       \
> +			LOGHIST_SIZE_LARGE),				       \
> +	STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns),		       \
> +	STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist,	       \
> +			LOGHIST_SIZE_LARGE)
>  
>  extern struct dentry *kvm_debugfs_dir;
>  
> diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> index cc88cd676775..7838a42932c8 100644
> --- a/include/linux/kvm_types.h
> +++ b/include/linux/kvm_types.h
> @@ -103,6 +103,10 @@ struct kvm_vcpu_stat_generic {
>  	u64 halt_wakeup;
>  	u64 halt_poll_success_ns;
>  	u64 halt_poll_fail_ns;
> +	u64 halt_poll_success_hist[LOGHIST_SIZE_LARGE];
> +	u64 halt_poll_fail_hist[LOGHIST_SIZE_LARGE];
> +	u64 halt_wait_ns;
> +	u64 halt_wait_hist[LOGHIST_SIZE_LARGE];
>  };
>  
>  #define KVM_STATS_NAME_SIZE	48
> diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> index 3dcc2abbfc60..840b5bece080 100644
> --- a/virt/kvm/kvm_main.c
> +++ b/virt/kvm/kvm_main.c
> @@ -3093,12 +3093,24 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
>  				++vcpu->stat.generic.halt_successful_poll;
>  				if (!vcpu_valid_wakeup(vcpu))
>  					++vcpu->stat.generic.halt_poll_invalid;
> +
> +				kvm_stats_log_hist_update(
> +				      vcpu->stat.generic.halt_poll_success_hist,
> +				      LOGHIST_SIZE_LARGE,
> +				      ktime_to_ns(ktime_get()) -
> +				      ktime_to_ns(start));
>  				goto out;
>  			}
>  			poll_end = cur = ktime_get();
>  		} while (kvm_vcpu_can_poll(cur, stop));
> +
> +		kvm_stats_log_hist_update(
> +				vcpu->stat.generic.halt_poll_fail_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(ktime_get()) - ktime_to_ns(start));

nit: Consider creating a wrapper for kvm_stats_log_hist_update() since
there are so many call sites. You can save a line at every call site by
avoiding passing in the histogram size.

        void halt_poll_hist_update(u64 *histogram, ktime_t time)
        {
                kvm_stats_log_hist_update(histogram, LOGHIST_SIZE_LARGE, time);
        }


>  	}
>  
> +
>  	prepare_to_rcuwait(&vcpu->wait);
>  	for (;;) {
>  		set_current_state(TASK_INTERRUPTIBLE);
> @@ -3111,6 +3123,13 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
>  	}
>  	finish_rcuwait(&vcpu->wait);
>  	cur = ktime_get();
> +	if (waited) {
> +		vcpu->stat.generic.halt_wait_ns +> +			ktime_to_ns(cur) - ktime_to_ns(poll_end);
> +		kvm_stats_log_hist_update(vcpu->stat.generic.halt_wait_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(poll_end));
> +	}
>  out:
>  	kvm_arch_vcpu_unblocking(vcpu);
>  	block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
> -- 
> 2.32.0.93.g670b81a890-goog
> 

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-08 21:16       ` David Matlack
@ 2021-07-08 21:43         ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-08 21:43 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 8, 2021 at 4:16 PM David Matlack <dmatlack@google.com> wrote:
>
> On Thu, Jul 08, 2021 at 09:14:38PM +0000, David Matlack wrote:
> > On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> > > Add documentations for linear and logarithmic histogram statistics.
> > > Add binary stats capability text which is missing during merge of
> > > the binary stats patch.
> > >
> > > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > > ---
> > >  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
> > >  1 file changed, 33 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > > index 3b6e3b1628b4..948d33c26704 100644
> > > --- a/Documentation/virt/kvm/api.rst
> > > +++ b/Documentation/virt/kvm/api.rst
> > > @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
> > >     #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_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)
> > > @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
> > >     #define KVM_STATS_UNIT_BYTES            (0x1 << KVM_STATS_UNIT_SHIFT)
> > >     #define KVM_STATS_UNIT_SECONDS          (0x2 << KVM_STATS_UNIT_SHIFT)
> > >     #define KVM_STATS_UNIT_CYCLES           (0x3 << KVM_STATS_UNIT_SHIFT)
> > > +   #define KVM_STATS_UNIT_MAX              KVM_STATS_UNIT_CYCLES
> > >
> > >     #define KVM_STATS_BASE_SHIFT            8
> > >     #define KVM_STATS_BASE_MASK             (0xF << KVM_STATS_BASE_SHIFT)
> > >     #define KVM_STATS_BASE_POW10            (0x0 << KVM_STATS_BASE_SHIFT)
> > >     #define KVM_STATS_BASE_POW2             (0x1 << KVM_STATS_BASE_SHIFT)
> > > +   #define KVM_STATS_BASE_MAX              KVM_STATS_BASE_POW2
> >
> > Should these FOO_MAX additions go in a separate commit too?
> >
> > >
> > >     struct kvm_stats_desc {
> > >             __u32 flags;
> > > @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
> > >      represents a peak value for a measurement, for example the maximum number
> > >      of items in a hash table bucket, the longest time waited and so on.
> > >      The corresponding ``size`` field for this type is always 1.
> > > +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> > > +    The statistics data is in the form of linear histogram. The number of
> > > +    buckets is specified by the ``size`` field. The size of buckets is specified
> > > +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> >
> > Using 1-based indexes is a little jarring but maybe that's just me :).
> >
> > > +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> > > +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> > > +    value.) The bucket value indicates how many times the statistics data is in
> > > +    the bucket's range.
> > > +  * ``KVM_STATS_TYPE_LOG_HIST``
> > > +    The statistics data is in the form of logarithmic histogram. The number of
> > > +    buckets is specified by the ``size`` field. The base of logarithm is
> > > +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> >
> > Should 1 be 2 here? The first bucket uses a slightly differen formula as
> > you mention in the next sentence.
>
> Oops I see you used "<" instead of "<=" so what you have is correct. I
> think reordering the sentences would still be helpfull though.
>
Sure, will reorder the sentences as you suggested.
> >
> > Actually it may be clearer if you re-ordered the sentences a bit:
> >
> >   The range of the first bucket is [0, 1), while the range of the last
> >   bucket is [pow(hist_param, size-1), +INF). Otherwise the Nth bucket
> >   (1-indexed) covers [pow(hist_param, N-2), pow(histparam, N-1)).
> >
> > > +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> > > +    of the first bucket is [0, 1), while the range of the last bucket is
> > > +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> > > +    times the statistics data is in the bucket's range.
> > >
> > >  Bits 4-7 of ``flags`` encode the unit:
> > >    * ``KVM_STATS_UNIT_NONE``
> > > @@ -5246,9 +5267,10 @@ unsigned 64bit data.
> > >  The ``offset`` field is the offset from the start of Data Block to the start of
> > >  the corresponding statistics data.
> > >
> > > -The ``unused`` field is reserved for future support for other types of
> > > -statistics data, like log/linear histogram. Its value is always 0 for the types
> > > -defined above.
> > > +The ``hist_param`` field is used as a parameter for histogram statistics data.
> > > +For linear histogram statistics data, it indicates the size of a bucket. For
> > > +logarithmic histogram statistics data, it indicates the base of the logarithm.
> > > +Only base of 2 is supported fo logarithmic histogram.
> >
> > s/fo/for/
> >
> > >
> > >  The ``name`` field is the name string of the statistics data. The name string
> > >  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> > > @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
> > >  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
> > >  the hypercalls whose corresponding bit is in the argument, and return
> > >  ENOSYS for the others.
> > > +
> > > +8.35 KVM_CAP_STATS_BINARY_FD
> > > +----------------------------
> > > +
> > > +:Architectures: all
> > > +
> > > +This capability indicates the feature that userspace can get a file descriptor
> > > +for every VM and VCPU to read statistics data in binary format.
> > > --
> > > 2.32.0.93.g670b81a890-goog
> > >

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-08 21:43         ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-08 21:43 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 8, 2021 at 4:16 PM David Matlack <dmatlack@google.com> wrote:
>
> On Thu, Jul 08, 2021 at 09:14:38PM +0000, David Matlack wrote:
> > On Tue, Jul 06, 2021 at 06:03:48PM +0000, Jing Zhang wrote:
> > > Add documentations for linear and logarithmic histogram statistics.
> > > Add binary stats capability text which is missing during merge of
> > > the binary stats patch.
> > >
> > > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > > ---
> > >  Documentation/virt/kvm/api.rst | 36 +++++++++++++++++++++++++++++++---
> > >  1 file changed, 33 insertions(+), 3 deletions(-)
> > >
> > > diff --git a/Documentation/virt/kvm/api.rst b/Documentation/virt/kvm/api.rst
> > > index 3b6e3b1628b4..948d33c26704 100644
> > > --- a/Documentation/virt/kvm/api.rst
> > > +++ b/Documentation/virt/kvm/api.rst
> > > @@ -5171,6 +5171,9 @@ by a string of size ``name_size``.
> > >     #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_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)
> > > @@ -5178,11 +5181,13 @@ by a string of size ``name_size``.
> > >     #define KVM_STATS_UNIT_BYTES            (0x1 << KVM_STATS_UNIT_SHIFT)
> > >     #define KVM_STATS_UNIT_SECONDS          (0x2 << KVM_STATS_UNIT_SHIFT)
> > >     #define KVM_STATS_UNIT_CYCLES           (0x3 << KVM_STATS_UNIT_SHIFT)
> > > +   #define KVM_STATS_UNIT_MAX              KVM_STATS_UNIT_CYCLES
> > >
> > >     #define KVM_STATS_BASE_SHIFT            8
> > >     #define KVM_STATS_BASE_MASK             (0xF << KVM_STATS_BASE_SHIFT)
> > >     #define KVM_STATS_BASE_POW10            (0x0 << KVM_STATS_BASE_SHIFT)
> > >     #define KVM_STATS_BASE_POW2             (0x1 << KVM_STATS_BASE_SHIFT)
> > > +   #define KVM_STATS_BASE_MAX              KVM_STATS_BASE_POW2
> >
> > Should these FOO_MAX additions go in a separate commit too?
> >
> > >
> > >     struct kvm_stats_desc {
> > >             __u32 flags;
> > > @@ -5214,6 +5219,22 @@ Bits 0-3 of ``flags`` encode the type:
> > >      represents a peak value for a measurement, for example the maximum number
> > >      of items in a hash table bucket, the longest time waited and so on.
> > >      The corresponding ``size`` field for this type is always 1.
> > > +  * ``KVM_STATS_TYPE_LINEAR_HIST``
> > > +    The statistics data is in the form of linear histogram. The number of
> > > +    buckets is specified by the ``size`` field. The size of buckets is specified
> > > +    by the ``hist_param`` field. The range of the Nth bucket (1 <= N < ``size``)
> >
> > Using 1-based indexes is a little jarring but maybe that's just me :).
> >
> > > +    is [``hist_param``*(N-1), ``hist_param``*N), while the range of the last
> > > +    bucket is [``hist_param``*(``size``-1), +INF). (+INF means positive infinity
> > > +    value.) The bucket value indicates how many times the statistics data is in
> > > +    the bucket's range.
> > > +  * ``KVM_STATS_TYPE_LOG_HIST``
> > > +    The statistics data is in the form of logarithmic histogram. The number of
> > > +    buckets is specified by the ``size`` field. The base of logarithm is
> > > +    specified by the ``hist_param`` field. The range of the Nth bucket (1 < N <
> >
> > Should 1 be 2 here? The first bucket uses a slightly differen formula as
> > you mention in the next sentence.
>
> Oops I see you used "<" instead of "<=" so what you have is correct. I
> think reordering the sentences would still be helpfull though.
>
Sure, will reorder the sentences as you suggested.
> >
> > Actually it may be clearer if you re-ordered the sentences a bit:
> >
> >   The range of the first bucket is [0, 1), while the range of the last
> >   bucket is [pow(hist_param, size-1), +INF). Otherwise the Nth bucket
> >   (1-indexed) covers [pow(hist_param, N-2), pow(histparam, N-1)).
> >
> > > +    ``size``) is [pow(``hist_param``, N-2), pow(``hist_param``, N-1)). The range
> > > +    of the first bucket is [0, 1), while the range of the last bucket is
> > > +    [pow(``hist_param``, ``size``-2), +INF). The bucket value indicates how many
> > > +    times the statistics data is in the bucket's range.
> > >
> > >  Bits 4-7 of ``flags`` encode the unit:
> > >    * ``KVM_STATS_UNIT_NONE``
> > > @@ -5246,9 +5267,10 @@ unsigned 64bit data.
> > >  The ``offset`` field is the offset from the start of Data Block to the start of
> > >  the corresponding statistics data.
> > >
> > > -The ``unused`` field is reserved for future support for other types of
> > > -statistics data, like log/linear histogram. Its value is always 0 for the types
> > > -defined above.
> > > +The ``hist_param`` field is used as a parameter for histogram statistics data.
> > > +For linear histogram statistics data, it indicates the size of a bucket. For
> > > +logarithmic histogram statistics data, it indicates the base of the logarithm.
> > > +Only base of 2 is supported fo logarithmic histogram.
> >
> > s/fo/for/
> >
> > >
> > >  The ``name`` field is the name string of the statistics data. The name string
> > >  starts at the end of ``struct kvm_stats_desc``.  The maximum length including
> > > @@ -7182,3 +7204,11 @@ The argument to KVM_ENABLE_CAP is also a bitmask, and must be a subset
> > >  of the result of KVM_CHECK_EXTENSION.  KVM will forward to userspace
> > >  the hypercalls whose corresponding bit is in the argument, and return
> > >  ENOSYS for the others.
> > > +
> > > +8.35 KVM_CAP_STATS_BINARY_FD
> > > +----------------------------
> > > +
> > > +:Architectures: all
> > > +
> > > +This capability indicates the feature that userspace can get a file descriptor
> > > +for every VM and VCPU to read statistics data in binary format.
> > > --
> > > 2.32.0.93.g670b81a890-goog
> > >

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-08 21:40       ` Jing Zhang
@ 2021-07-08 21:45         ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:45 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 08, 2021 at 04:40:16PM -0500, Jing Zhang wrote:
> On Thu, Jul 8, 2021 at 4:01 PM David Matlack <dmatlack@google.com> wrote:
> >
> > On Tue, Jul 06, 2021 at 06:03:47PM +0000, Jing Zhang wrote:
> > > 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>
> > > ---
> > >  arch/arm64/kvm/guest.c    |  4 ---
> > >  arch/mips/kvm/mips.c      |  4 ---
> > >  arch/powerpc/kvm/book3s.c |  4 ---
> > >  arch/powerpc/kvm/booke.c  |  4 ---
> > >  arch/s390/kvm/kvm-s390.c  |  4 ---
> > >  arch/x86/kvm/x86.c        |  4 ---
> > >  include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
> > >  include/linux/kvm_types.h | 16 ++++++++++++
> > >  include/uapi/linux/kvm.h  | 11 +++++---
> > >  virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
> > >  10 files changed, 98 insertions(+), 42 deletions(-)
> > >
> > > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> > > index 1512a8007a78..cb44d8756fa7 100644
> > > --- a/arch/arm64/kvm/guest.c
> > > +++ b/arch/arm64/kvm/guest.c
> > > @@ -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,
> > > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> > > index af9dd029a4e1..75c6f264c626 100644
> > > --- a/arch/mips/kvm/mips.c
> > > +++ b/arch/mips/kvm/mips.c
> > > @@ -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,
> > > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> > > index 79833f78d1da..5cc6e90095b0 100644
> > > --- a/arch/powerpc/kvm/book3s.c
> > > +++ b/arch/powerpc/kvm/book3s.c
> > > @@ -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,
> > > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > > index 551b30d84aee..5ed6c235e059 100644
> > > --- a/arch/powerpc/kvm/booke.c
> > > +++ b/arch/powerpc/kvm/booke.c
> > > @@ -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,
> > > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> > > index 1695f0ced5ba..7610d33d319b 100644
> > > --- a/arch/s390/kvm/kvm-s390.c
> > > +++ b/arch/s390/kvm/kvm-s390.c
> > > @@ -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, 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,
> > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > index 8166ad113fb2..b94a80ad5b8d 100644
> > > --- a/arch/x86/kvm/x86.c
> > > +++ b/arch/x86/kvm/x86.c
> > > @@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
> > >       STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
> > >       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,
> > > @@ -280,8 +278,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,
> > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > > index ae7735b490b4..356af173114d 100644
> > > --- a/include/linux/kvm_host.h
> > > +++ b/include/linux/kvm_host.h
> > > @@ -1273,56 +1273,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, param)                 \
> > >       .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,                                                            \
> > > +     .hist_param = param
> > >
> > > -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)                  \
> > > +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)               \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)             \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)                       \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)                     \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)           \
> > > +     SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
> > >
> > >  #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, param)   \
> > > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,                    \
> > > +             unit, base, exponent, sz, param)
> > > +#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
> > > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,                       \
> > > +             unit, base, exponent, sz, param)
> > >
> > >  /* Cumulative counter, read/write */
> > >  #define STATS_DESC_COUNTER(SCOPE, name)                                             \
> > > @@ -1341,6 +1351,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, bucket_size)          \
> > > +     STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,            \
> > > +             KVM_STATS_BASE_POW10, -9, sz, bucket_size)
> > > +/* 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, LOGHIST_BASE_2)
> > >
> > >  #define KVM_GENERIC_VM_STATS()                                                      \
> > >       STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
> > > @@ -1354,10 +1372,15 @@ 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);
> > > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > > +                               u64 value, size_t bucket_size);
> > > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
> > > diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> > > index ed6a985c5680..cc88cd676775 100644
> > > --- a/include/linux/kvm_types.h
> > > +++ b/include/linux/kvm_types.h
> > > @@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
> > >  };
> > >  #endif
> > >
> > > +/* Constants used for histogram stats */
> > > +#define LINHIST_SIZE_SMALL           10
> > > +#define LINHIST_SIZE_MEDIUM          20
> > > +#define LINHIST_SIZE_LARGE           50
> > > +#define LINHIST_SIZE_XLARGE          100
> >
> > nit: s/SIZE/BUCKET_COUNT/
> >
> Sure, it makes more sense.
> > > +#define LINHIST_BUCKET_SIZE_SMALL    10
> > > +#define LINHIST_BUCKET_SIZE_MEDIUM   100
> > > +#define LINHIST_BUCKET_SIZE_LARGE    1000
> > > +#define LINHIST_BUCKET_SIZE_XLARGE   10000
> > > +
> > > +#define LOGHIST_SIZE_SMALL           8
> > > +#define LOGHIST_SIZE_MEDIUM          16
> > > +#define LOGHIST_SIZE_LARGE           32
> > > +#define LOGHIST_SIZE_XLARGE          64
> >
> > Ditto here.
> >
> Will do.
> > > +#define LOGHIST_BASE_2                       2
> > > +
> > >  struct kvm_vm_stat_generic {
> > >       u64 remote_tlb_flush;
> > >  };
> > > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > > index 68c9e6d8bbda..ff34a471d9ef 100644
> > > --- a/include/uapi/linux/kvm.h
> > > +++ b/include/uapi/linux/kvm.h
> > > @@ -1963,7 +1963,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)
> > > @@ -1987,7 +1989,10 @@ struct kvm_stats_header {
> > >   *        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.
> > > + * @hist_param: A parameter value used for histogram stats. For linear
> > > + *              histogram stats, it indicates the size of the bucket;
> > > + *              For logarithmic histogram stats, it indicates the base
> > > + *              of the logarithm. Only base of 2 is supported.
> > >   * @name: The name string for the stats. Its size is indicated by the
> > >   *        &kvm_stats_header->name_size.
> > >   */
> > > @@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
> > >       __s16 exponent;
> > >       __u16 size;
> > >       __u32 offset;
> > > -     __u32 unused;
> > > +     __u32 hist_param;
> >
> > `hist_param` is vague. What about making this an anonymous union to make
> > the dual meaning explicit?
> >
> >         union {
> >                 /* Only used for KVM_STATS_TYPE_LOG_HIST. */
> >                 __u32 base;
> >                 /* Only used for KVM_STATS_TYPE_LINEAR_HIST. */
> >                 __u32 bucket_size;
> >         };
> >
> > It may make the STATS_DESC code a bit more complicated but the rest of
> > the code that uses it will be much more clear.
> >
> Since we only support base-2 log hist, maybe it is not necessary to
> have the base field.
> The reason to only support base-2 log hist is that its range is
> already large enough for
> any stats.
> Will just change hist_param to bucket_size.

Cool sounds good. We can always add a custom base in the future without
breaking userspace by adding the anonymous union and guarding it behind
the flag field.

> > >       char name[];
> > >  };
> > >
> > > diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
> > > index e609d428811a..6eead6979a7f 100644
> > > --- a/virt/kvm/binary_stats.c
> > > +++ b/virt/kvm/binary_stats.c
> > > @@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
> > >       *offset = pos;
> > >       return len;
> > >  }
> > > +
> > > +/**
> > > + * 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
> > > + */
> > > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > > +                               u64 value, size_t bucket_size)
> > > +{
> > > +     size_t index = value / bucket_size;
> > > +
> > > +     if (index >= size)
> > > +             index = size - 1;
> >
> > nit: It would be simpler to use max().
> >
> >         size_t index = max(value / bucket_size, size - 1);
> >
> Will do.
> > > +     ++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
> > > + */
> > > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
> > > +{
> > > +     size_t index = fls64(value);
> > > +
> > > +     if (index >= size)
> > > +             index = size - 1;
> >
> > Ditto here about using max().
> >
> Will do.
> > > +     ++data[index];
> > > +}
> > > --
> > > 2.32.0.93.g670b81a890-goog
> > >
> Thanks,
> Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-08 21:45         ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-08 21:45 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 08, 2021 at 04:40:16PM -0500, Jing Zhang wrote:
> On Thu, Jul 8, 2021 at 4:01 PM David Matlack <dmatlack@google.com> wrote:
> >
> > On Tue, Jul 06, 2021 at 06:03:47PM +0000, Jing Zhang wrote:
> > > 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>
> > > ---
> > >  arch/arm64/kvm/guest.c    |  4 ---
> > >  arch/mips/kvm/mips.c      |  4 ---
> > >  arch/powerpc/kvm/book3s.c |  4 ---
> > >  arch/powerpc/kvm/booke.c  |  4 ---
> > >  arch/s390/kvm/kvm-s390.c  |  4 ---
> > >  arch/x86/kvm/x86.c        |  4 ---
> > >  include/linux/kvm_host.h  | 53 ++++++++++++++++++++++++++++-----------
> > >  include/linux/kvm_types.h | 16 ++++++++++++
> > >  include/uapi/linux/kvm.h  | 11 +++++---
> > >  virt/kvm/binary_stats.c   | 36 ++++++++++++++++++++++++++
> > >  10 files changed, 98 insertions(+), 42 deletions(-)
> > >
> > > diff --git a/arch/arm64/kvm/guest.c b/arch/arm64/kvm/guest.c
> > > index 1512a8007a78..cb44d8756fa7 100644
> > > --- a/arch/arm64/kvm/guest.c
> > > +++ b/arch/arm64/kvm/guest.c
> > > @@ -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,
> > > diff --git a/arch/mips/kvm/mips.c b/arch/mips/kvm/mips.c
> > > index af9dd029a4e1..75c6f264c626 100644
> > > --- a/arch/mips/kvm/mips.c
> > > +++ b/arch/mips/kvm/mips.c
> > > @@ -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,
> > > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> > > index 79833f78d1da..5cc6e90095b0 100644
> > > --- a/arch/powerpc/kvm/book3s.c
> > > +++ b/arch/powerpc/kvm/book3s.c
> > > @@ -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,
> > > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > > index 551b30d84aee..5ed6c235e059 100644
> > > --- a/arch/powerpc/kvm/booke.c
> > > +++ b/arch/powerpc/kvm/booke.c
> > > @@ -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,
> > > diff --git a/arch/s390/kvm/kvm-s390.c b/arch/s390/kvm/kvm-s390.c
> > > index 1695f0ced5ba..7610d33d319b 100644
> > > --- a/arch/s390/kvm/kvm-s390.c
> > > +++ b/arch/s390/kvm/kvm-s390.c
> > > @@ -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, 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,
> > > diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
> > > index 8166ad113fb2..b94a80ad5b8d 100644
> > > --- a/arch/x86/kvm/x86.c
> > > +++ b/arch/x86/kvm/x86.c
> > > @@ -239,8 +239,6 @@ const struct _kvm_stats_desc kvm_vm_stats_desc[] = {
> > >       STATS_DESC_ICOUNTER(VM, nx_lpage_splits),
> > >       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,
> > > @@ -280,8 +278,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,
> > > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > > index ae7735b490b4..356af173114d 100644
> > > --- a/include/linux/kvm_host.h
> > > +++ b/include/linux/kvm_host.h
> > > @@ -1273,56 +1273,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, param)                 \
> > >       .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,                                                            \
> > > +     .hist_param = param
> > >
> > > -#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp)                  \
> > > +#define VM_GENERIC_STATS_DESC(stat, type, unit, base, exp, sz, param)               \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)             \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)                       \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)                     \
> > >       {                                                                      \
> > >               {                                                              \
> > > -                     STATS_DESC_COMMON(type, unit, base, exp),              \
> > > +                     STATS_DESC_COMMON(type, unit, base, exp, sz, param),   \
> > >                       .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, param)           \
> > > +     SCOPE##_STATS_DESC(stat, type, unit, base, exp, sz, param)
> > >
> > >  #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, param)   \
> > > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LINEAR_HIST,                    \
> > > +             unit, base, exponent, sz, param)
> > > +#define STATS_DESC_LOG_HIST(SCOPE, name, unit, base, exponent, sz, param)      \
> > > +     STATS_DESC(SCOPE, name, KVM_STATS_TYPE_LOG_HIST,                       \
> > > +             unit, base, exponent, sz, param)
> > >
> > >  /* Cumulative counter, read/write */
> > >  #define STATS_DESC_COUNTER(SCOPE, name)                                             \
> > > @@ -1341,6 +1351,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, bucket_size)          \
> > > +     STATS_DESC_LINEAR_HIST(SCOPE, name, KVM_STATS_UNIT_SECONDS,            \
> > > +             KVM_STATS_BASE_POW10, -9, sz, bucket_size)
> > > +/* 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, LOGHIST_BASE_2)
> > >
> > >  #define KVM_GENERIC_VM_STATS()                                                      \
> > >       STATS_DESC_COUNTER(VM_GENERIC, remote_tlb_flush)
> > > @@ -1354,10 +1372,15 @@ 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);
> > > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > > +                               u64 value, size_t bucket_size);
> > > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 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;
> > > diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> > > index ed6a985c5680..cc88cd676775 100644
> > > --- a/include/linux/kvm_types.h
> > > +++ b/include/linux/kvm_types.h
> > > @@ -76,6 +76,22 @@ struct kvm_mmu_memory_cache {
> > >  };
> > >  #endif
> > >
> > > +/* Constants used for histogram stats */
> > > +#define LINHIST_SIZE_SMALL           10
> > > +#define LINHIST_SIZE_MEDIUM          20
> > > +#define LINHIST_SIZE_LARGE           50
> > > +#define LINHIST_SIZE_XLARGE          100
> >
> > nit: s/SIZE/BUCKET_COUNT/
> >
> Sure, it makes more sense.
> > > +#define LINHIST_BUCKET_SIZE_SMALL    10
> > > +#define LINHIST_BUCKET_SIZE_MEDIUM   100
> > > +#define LINHIST_BUCKET_SIZE_LARGE    1000
> > > +#define LINHIST_BUCKET_SIZE_XLARGE   10000
> > > +
> > > +#define LOGHIST_SIZE_SMALL           8
> > > +#define LOGHIST_SIZE_MEDIUM          16
> > > +#define LOGHIST_SIZE_LARGE           32
> > > +#define LOGHIST_SIZE_XLARGE          64
> >
> > Ditto here.
> >
> Will do.
> > > +#define LOGHIST_BASE_2                       2
> > > +
> > >  struct kvm_vm_stat_generic {
> > >       u64 remote_tlb_flush;
> > >  };
> > > diff --git a/include/uapi/linux/kvm.h b/include/uapi/linux/kvm.h
> > > index 68c9e6d8bbda..ff34a471d9ef 100644
> > > --- a/include/uapi/linux/kvm.h
> > > +++ b/include/uapi/linux/kvm.h
> > > @@ -1963,7 +1963,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)
> > > @@ -1987,7 +1989,10 @@ struct kvm_stats_header {
> > >   *        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.
> > > + * @hist_param: A parameter value used for histogram stats. For linear
> > > + *              histogram stats, it indicates the size of the bucket;
> > > + *              For logarithmic histogram stats, it indicates the base
> > > + *              of the logarithm. Only base of 2 is supported.
> > >   * @name: The name string for the stats. Its size is indicated by the
> > >   *        &kvm_stats_header->name_size.
> > >   */
> > > @@ -1996,7 +2001,7 @@ struct kvm_stats_desc {
> > >       __s16 exponent;
> > >       __u16 size;
> > >       __u32 offset;
> > > -     __u32 unused;
> > > +     __u32 hist_param;
> >
> > `hist_param` is vague. What about making this an anonymous union to make
> > the dual meaning explicit?
> >
> >         union {
> >                 /* Only used for KVM_STATS_TYPE_LOG_HIST. */
> >                 __u32 base;
> >                 /* Only used for KVM_STATS_TYPE_LINEAR_HIST. */
> >                 __u32 bucket_size;
> >         };
> >
> > It may make the STATS_DESC code a bit more complicated but the rest of
> > the code that uses it will be much more clear.
> >
> Since we only support base-2 log hist, maybe it is not necessary to
> have the base field.
> The reason to only support base-2 log hist is that its range is
> already large enough for
> any stats.
> Will just change hist_param to bucket_size.

Cool sounds good. We can always add a custom base in the future without
breaking userspace by adding the anonymous union and guarding it behind
the flag field.

> > >       char name[];
> > >  };
> > >
> > > diff --git a/virt/kvm/binary_stats.c b/virt/kvm/binary_stats.c
> > > index e609d428811a..6eead6979a7f 100644
> > > --- a/virt/kvm/binary_stats.c
> > > +++ b/virt/kvm/binary_stats.c
> > > @@ -144,3 +144,39 @@ ssize_t kvm_stats_read(char *id, const struct kvm_stats_header *header,
> > >       *offset = pos;
> > >       return len;
> > >  }
> > > +
> > > +/**
> > > + * 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
> > > + */
> > > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > > +                               u64 value, size_t bucket_size)
> > > +{
> > > +     size_t index = value / bucket_size;
> > > +
> > > +     if (index >= size)
> > > +             index = size - 1;
> >
> > nit: It would be simpler to use max().
> >
> >         size_t index = max(value / bucket_size, size - 1);
> >
> Will do.
> > > +     ++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
> > > + */
> > > +void kvm_stats_log_hist_update(u64 *data, size_t size, u64 value)
> > > +{
> > > +     size_t index = fls64(value);
> > > +
> > > +     if (index >= size)
> > > +             index = size - 1;
> >
> > Ditto here about using max().
> >
> Will do.
> > > +     ++data[index];
> > > +}
> > > --
> > > 2.32.0.93.g670b81a890-goog
> > >
> Thanks,
> Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
  2021-07-08 21:42     ` David Matlack
@ 2021-07-09 15:18       ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-09 15:18 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 8, 2021 at 4:42 PM David Matlack <dmatlack@google.com> wrote:
>
> On Tue, Jul 06, 2021 at 06:03:50PM +0000, Jing Zhang wrote:
> > Add simple stats halt_wait_ns to record the time a VCPU has spent on
> > waiting for all architectures (not just powerpc).
> > Add three log histogram stats to record the distribution of time spent
> > on successful polling, failed polling and VCPU wait.
> > halt_poll_success_hist: Distribution of time spent before a successful
> > polling.
> > halt_poll_fail_hist: Distribution of time spent before a failed polling.
> > halt_wait_hist: Distribution of time a VCPU has spent on waiting.
> >
> > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > ---
> >  arch/powerpc/include/asm/kvm_host.h |  1 -
> >  arch/powerpc/kvm/book3s.c           |  1 -
> >  arch/powerpc/kvm/book3s_hv.c        | 20 +++++++++++++++++---
> >  arch/powerpc/kvm/booke.c            |  1 -
> >  include/linux/kvm_host.h            |  9 ++++++++-
> >  include/linux/kvm_types.h           |  4 ++++
> >  virt/kvm/kvm_main.c                 | 19 +++++++++++++++++++
> >  7 files changed, 48 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> > index 9f52f282b1aa..4931d03e5799 100644
> > --- a/arch/powerpc/include/asm/kvm_host.h
> > +++ b/arch/powerpc/include/asm/kvm_host.h
> > @@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
> >       u64 emulated_inst_exits;
> >       u64 dec_exits;
> >       u64 ext_intr_exits;
> > -     u64 halt_wait_ns;
>
> The halt_wait_ns refactor should be a separate patch.
>
How about putting it into a separate commit? Just want to keep all
halt related change in the
same patch series.
> >       u64 halt_successful_wait;
> >       u64 dbell_exits;
> >       u64 gdbell_exits;
> > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> > index 5cc6e90095b0..b785f6772391 100644
> > --- a/arch/powerpc/kvm/book3s.c
> > +++ b/arch/powerpc/kvm/book3s.c
> > @@ -69,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
> >       STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
> >       STATS_DESC_COUNTER(VCPU, dec_exits),
> >       STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> > -     STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
> >       STATS_DESC_COUNTER(VCPU, halt_successful_wait),
> >       STATS_DESC_COUNTER(VCPU, dbell_exits),
> >       STATS_DESC_COUNTER(VCPU, gdbell_exits),
> > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> > index cd544a46183e..103f998cee75 100644
> > --- a/arch/powerpc/kvm/book3s_hv.c
> > +++ b/arch/powerpc/kvm/book3s_hv.c
> > @@ -4144,19 +4144,33 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
> >
> >       /* Attribute wait time */
> >       if (do_sleep) {
> > -             vc->runner->stat.halt_wait_ns +=
> > +             vc->runner->stat.generic.halt_wait_ns +=
> >                       ktime_to_ns(cur) - ktime_to_ns(start_wait);
> > +             kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_wait_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(start_wait));
> >               /* Attribute failed poll time */
> > -             if (vc->halt_poll_ns)
> > +             if (vc->halt_poll_ns) {
> >                       vc->runner->stat.generic.halt_poll_fail_ns +=
> >                               ktime_to_ns(start_wait) -
> >                               ktime_to_ns(start_poll);
> > +                     kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_poll_fail_hist,
> > +                             LOGHIST_SIZE_LARGE, ktime_to_ns(start_wait) -
> > +                             ktime_to_ns(start_poll));
> > +             }
> >       } else {
> >               /* Attribute successful poll time */
> > -             if (vc->halt_poll_ns)
> > +             if (vc->halt_poll_ns) {
> >                       vc->runner->stat.generic.halt_poll_success_ns +=
> >                               ktime_to_ns(cur) -
> >                               ktime_to_ns(start_poll);
> > +                     kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_poll_success_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(start_poll));
> > +             }
> >       }
> >
> >       /* Adjust poll time */
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > index 5ed6c235e059..977801c83aff 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -67,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
> >       STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
> >       STATS_DESC_COUNTER(VCPU, dec_exits),
> >       STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> > -     STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
> >       STATS_DESC_COUNTER(VCPU, halt_successful_wait),
> >       STATS_DESC_COUNTER(VCPU, dbell_exits),
> >       STATS_DESC_COUNTER(VCPU, gdbell_exits),
> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > index 356af173114d..268a0ccc9c5f 100644
> > --- a/include/linux/kvm_host.h
> > +++ b/include/linux/kvm_host.h
> > @@ -1369,7 +1369,14 @@ struct _kvm_stats_desc {
> >       STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid),                   \
> >       STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup),                         \
> >       STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns),              \
> > -     STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
> > +     STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns),                 \
> > +     STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist,     \
> > +                     LOGHIST_SIZE_LARGE),                                   \
>
> This should probably be a new macro rather than using LOGHIST_SIZE_LARGE
> everywhere.
>
> #define HALT_POLL_HIST_SIZE LOGHIST_SIZE_LARGE
>
Will double check the new halt polling stats with this idea.
> > +     STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist,        \
> > +                     LOGHIST_SIZE_LARGE),                                   \
> > +     STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns),                      \
> > +     STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist,             \
> > +                     LOGHIST_SIZE_LARGE)
> >
> >  extern struct dentry *kvm_debugfs_dir;
> >
> > diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> > index cc88cd676775..7838a42932c8 100644
> > --- a/include/linux/kvm_types.h
> > +++ b/include/linux/kvm_types.h
> > @@ -103,6 +103,10 @@ struct kvm_vcpu_stat_generic {
> >       u64 halt_wakeup;
> >       u64 halt_poll_success_ns;
> >       u64 halt_poll_fail_ns;
> > +     u64 halt_poll_success_hist[LOGHIST_SIZE_LARGE];
> > +     u64 halt_poll_fail_hist[LOGHIST_SIZE_LARGE];
> > +     u64 halt_wait_ns;
> > +     u64 halt_wait_hist[LOGHIST_SIZE_LARGE];
> >  };
> >
> >  #define KVM_STATS_NAME_SIZE  48
> > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> > index 3dcc2abbfc60..840b5bece080 100644
> > --- a/virt/kvm/kvm_main.c
> > +++ b/virt/kvm/kvm_main.c
> > @@ -3093,12 +3093,24 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
> >                               ++vcpu->stat.generic.halt_successful_poll;
> >                               if (!vcpu_valid_wakeup(vcpu))
> >                                       ++vcpu->stat.generic.halt_poll_invalid;
> > +
> > +                             kvm_stats_log_hist_update(
> > +                                   vcpu->stat.generic.halt_poll_success_hist,
> > +                                   LOGHIST_SIZE_LARGE,
> > +                                   ktime_to_ns(ktime_get()) -
> > +                                   ktime_to_ns(start));
> >                               goto out;
> >                       }
> >                       poll_end = cur = ktime_get();
> >               } while (kvm_vcpu_can_poll(cur, stop));
> > +
> > +             kvm_stats_log_hist_update(
> > +                             vcpu->stat.generic.halt_poll_fail_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(ktime_get()) - ktime_to_ns(start));
>
> nit: Consider creating a wrapper for kvm_stats_log_hist_update() since
> there are so many call sites. You can save a line at every call site by
> avoiding passing in the histogram size.
>
>         void halt_poll_hist_update(u64 *histogram, ktime_t time)
>         {
>                 kvm_stats_log_hist_update(histogram, LOGHIST_SIZE_LARGE, time);
>         }
>
>
Will double check the new halt polling stats with this idea.
> >       }
> >
> > +
> >       prepare_to_rcuwait(&vcpu->wait);
> >       for (;;) {
> >               set_current_state(TASK_INTERRUPTIBLE);
> > @@ -3111,6 +3123,13 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
> >       }
> >       finish_rcuwait(&vcpu->wait);
> >       cur = ktime_get();
> > +     if (waited) {
> > +             vcpu->stat.generic.halt_wait_ns +=
> > +                     ktime_to_ns(cur) - ktime_to_ns(poll_end);
> > +             kvm_stats_log_hist_update(vcpu->stat.generic.halt_wait_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(poll_end));
> > +     }
> >  out:
> >       kvm_arch_vcpu_unblocking(vcpu);
> >       block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
> > --
> > 2.32.0.93.g670b81a890-goog
> >
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
@ 2021-07-09 15:18       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-09 15:18 UTC (permalink / raw)
  To: David Matlack
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Thu, Jul 8, 2021 at 4:42 PM David Matlack <dmatlack@google.com> wrote:
>
> On Tue, Jul 06, 2021 at 06:03:50PM +0000, Jing Zhang wrote:
> > Add simple stats halt_wait_ns to record the time a VCPU has spent on
> > waiting for all architectures (not just powerpc).
> > Add three log histogram stats to record the distribution of time spent
> > on successful polling, failed polling and VCPU wait.
> > halt_poll_success_hist: Distribution of time spent before a successful
> > polling.
> > halt_poll_fail_hist: Distribution of time spent before a failed polling.
> > halt_wait_hist: Distribution of time a VCPU has spent on waiting.
> >
> > Signed-off-by: Jing Zhang <jingzhangos@google.com>
> > ---
> >  arch/powerpc/include/asm/kvm_host.h |  1 -
> >  arch/powerpc/kvm/book3s.c           |  1 -
> >  arch/powerpc/kvm/book3s_hv.c        | 20 +++++++++++++++++---
> >  arch/powerpc/kvm/booke.c            |  1 -
> >  include/linux/kvm_host.h            |  9 ++++++++-
> >  include/linux/kvm_types.h           |  4 ++++
> >  virt/kvm/kvm_main.c                 | 19 +++++++++++++++++++
> >  7 files changed, 48 insertions(+), 7 deletions(-)
> >
> > diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> > index 9f52f282b1aa..4931d03e5799 100644
> > --- a/arch/powerpc/include/asm/kvm_host.h
> > +++ b/arch/powerpc/include/asm/kvm_host.h
> > @@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
> >       u64 emulated_inst_exits;
> >       u64 dec_exits;
> >       u64 ext_intr_exits;
> > -     u64 halt_wait_ns;
>
> The halt_wait_ns refactor should be a separate patch.
>
How about putting it into a separate commit? Just want to keep all
halt related change in the
same patch series.
> >       u64 halt_successful_wait;
> >       u64 dbell_exits;
> >       u64 gdbell_exits;
> > diff --git a/arch/powerpc/kvm/book3s.c b/arch/powerpc/kvm/book3s.c
> > index 5cc6e90095b0..b785f6772391 100644
> > --- a/arch/powerpc/kvm/book3s.c
> > +++ b/arch/powerpc/kvm/book3s.c
> > @@ -69,7 +69,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
> >       STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
> >       STATS_DESC_COUNTER(VCPU, dec_exits),
> >       STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> > -     STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
> >       STATS_DESC_COUNTER(VCPU, halt_successful_wait),
> >       STATS_DESC_COUNTER(VCPU, dbell_exits),
> >       STATS_DESC_COUNTER(VCPU, gdbell_exits),
> > diff --git a/arch/powerpc/kvm/book3s_hv.c b/arch/powerpc/kvm/book3s_hv.c
> > index cd544a46183e..103f998cee75 100644
> > --- a/arch/powerpc/kvm/book3s_hv.c
> > +++ b/arch/powerpc/kvm/book3s_hv.c
> > @@ -4144,19 +4144,33 @@ static void kvmppc_vcore_blocked(struct kvmppc_vcore *vc)
> >
> >       /* Attribute wait time */
> >       if (do_sleep) {
> > -             vc->runner->stat.halt_wait_ns +> > +             vc->runner->stat.generic.halt_wait_ns +> >                       ktime_to_ns(cur) - ktime_to_ns(start_wait);
> > +             kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_wait_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(start_wait));
> >               /* Attribute failed poll time */
> > -             if (vc->halt_poll_ns)
> > +             if (vc->halt_poll_ns) {
> >                       vc->runner->stat.generic.halt_poll_fail_ns +> >                               ktime_to_ns(start_wait) -
> >                               ktime_to_ns(start_poll);
> > +                     kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_poll_fail_hist,
> > +                             LOGHIST_SIZE_LARGE, ktime_to_ns(start_wait) -
> > +                             ktime_to_ns(start_poll));
> > +             }
> >       } else {
> >               /* Attribute successful poll time */
> > -             if (vc->halt_poll_ns)
> > +             if (vc->halt_poll_ns) {
> >                       vc->runner->stat.generic.halt_poll_success_ns +> >                               ktime_to_ns(cur) -
> >                               ktime_to_ns(start_poll);
> > +                     kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_poll_success_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(start_poll));
> > +             }
> >       }
> >
> >       /* Adjust poll time */
> > diff --git a/arch/powerpc/kvm/booke.c b/arch/powerpc/kvm/booke.c
> > index 5ed6c235e059..977801c83aff 100644
> > --- a/arch/powerpc/kvm/booke.c
> > +++ b/arch/powerpc/kvm/booke.c
> > @@ -67,7 +67,6 @@ const struct _kvm_stats_desc kvm_vcpu_stats_desc[] = {
> >       STATS_DESC_COUNTER(VCPU, emulated_inst_exits),
> >       STATS_DESC_COUNTER(VCPU, dec_exits),
> >       STATS_DESC_COUNTER(VCPU, ext_intr_exits),
> > -     STATS_DESC_TIME_NSEC(VCPU, halt_wait_ns),
> >       STATS_DESC_COUNTER(VCPU, halt_successful_wait),
> >       STATS_DESC_COUNTER(VCPU, dbell_exits),
> >       STATS_DESC_COUNTER(VCPU, gdbell_exits),
> > diff --git a/include/linux/kvm_host.h b/include/linux/kvm_host.h
> > index 356af173114d..268a0ccc9c5f 100644
> > --- a/include/linux/kvm_host.h
> > +++ b/include/linux/kvm_host.h
> > @@ -1369,7 +1369,14 @@ struct _kvm_stats_desc {
> >       STATS_DESC_COUNTER(VCPU_GENERIC, halt_poll_invalid),                   \
> >       STATS_DESC_COUNTER(VCPU_GENERIC, halt_wakeup),                         \
> >       STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_success_ns),              \
> > -     STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns)
> > +     STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_ns),                 \
> > +     STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_success_hist,     \
> > +                     LOGHIST_SIZE_LARGE),                                   \
>
> This should probably be a new macro rather than using LOGHIST_SIZE_LARGE
> everywhere.
>
> #define HALT_POLL_HIST_SIZE LOGHIST_SIZE_LARGE
>
Will double check the new halt polling stats with this idea.
> > +     STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_poll_fail_hist,        \
> > +                     LOGHIST_SIZE_LARGE),                                   \
> > +     STATS_DESC_TIME_NSEC(VCPU_GENERIC, halt_wait_ns),                      \
> > +     STATS_DESC_LOGHIST_TIME_NSEC(VCPU_GENERIC, halt_wait_hist,             \
> > +                     LOGHIST_SIZE_LARGE)
> >
> >  extern struct dentry *kvm_debugfs_dir;
> >
> > diff --git a/include/linux/kvm_types.h b/include/linux/kvm_types.h
> > index cc88cd676775..7838a42932c8 100644
> > --- a/include/linux/kvm_types.h
> > +++ b/include/linux/kvm_types.h
> > @@ -103,6 +103,10 @@ struct kvm_vcpu_stat_generic {
> >       u64 halt_wakeup;
> >       u64 halt_poll_success_ns;
> >       u64 halt_poll_fail_ns;
> > +     u64 halt_poll_success_hist[LOGHIST_SIZE_LARGE];
> > +     u64 halt_poll_fail_hist[LOGHIST_SIZE_LARGE];
> > +     u64 halt_wait_ns;
> > +     u64 halt_wait_hist[LOGHIST_SIZE_LARGE];
> >  };
> >
> >  #define KVM_STATS_NAME_SIZE  48
> > diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
> > index 3dcc2abbfc60..840b5bece080 100644
> > --- a/virt/kvm/kvm_main.c
> > +++ b/virt/kvm/kvm_main.c
> > @@ -3093,12 +3093,24 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
> >                               ++vcpu->stat.generic.halt_successful_poll;
> >                               if (!vcpu_valid_wakeup(vcpu))
> >                                       ++vcpu->stat.generic.halt_poll_invalid;
> > +
> > +                             kvm_stats_log_hist_update(
> > +                                   vcpu->stat.generic.halt_poll_success_hist,
> > +                                   LOGHIST_SIZE_LARGE,
> > +                                   ktime_to_ns(ktime_get()) -
> > +                                   ktime_to_ns(start));
> >                               goto out;
> >                       }
> >                       poll_end = cur = ktime_get();
> >               } while (kvm_vcpu_can_poll(cur, stop));
> > +
> > +             kvm_stats_log_hist_update(
> > +                             vcpu->stat.generic.halt_poll_fail_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(ktime_get()) - ktime_to_ns(start));
>
> nit: Consider creating a wrapper for kvm_stats_log_hist_update() since
> there are so many call sites. You can save a line at every call site by
> avoiding passing in the histogram size.
>
>         void halt_poll_hist_update(u64 *histogram, ktime_t time)
>         {
>                 kvm_stats_log_hist_update(histogram, LOGHIST_SIZE_LARGE, time);
>         }
>
>
Will double check the new halt polling stats with this idea.
> >       }
> >
> > +
> >       prepare_to_rcuwait(&vcpu->wait);
> >       for (;;) {
> >               set_current_state(TASK_INTERRUPTIBLE);
> > @@ -3111,6 +3123,13 @@ void kvm_vcpu_block(struct kvm_vcpu *vcpu)
> >       }
> >       finish_rcuwait(&vcpu->wait);
> >       cur = ktime_get();
> > +     if (waited) {
> > +             vcpu->stat.generic.halt_wait_ns +> > +                     ktime_to_ns(cur) - ktime_to_ns(poll_end);
> > +             kvm_stats_log_hist_update(vcpu->stat.generic.halt_wait_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(poll_end));
> > +     }
> >  out:
> >       kvm_arch_vcpu_unblocking(vcpu);
> >       block_ns = ktime_to_ns(cur) - ktime_to_ns(start);
> > --
> > 2.32.0.93.g670b81a890-goog
> >
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
  2021-07-09 15:18       ` Jing Zhang
@ 2021-07-09 15:25         ` David Matlack
  -1 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-09 15:25 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Fri, Jul 09, 2021 at 10:18:20AM -0500, Jing Zhang wrote:
> On Thu, Jul 8, 2021 at 4:42 PM David Matlack <dmatlack@google.com> wrote:
> >
> > On Tue, Jul 06, 2021 at 06:03:50PM +0000, Jing Zhang wrote:
> > >
> > > diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> > > index 9f52f282b1aa..4931d03e5799 100644
> > > --- a/arch/powerpc/include/asm/kvm_host.h
> > > +++ b/arch/powerpc/include/asm/kvm_host.h
> > > @@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
> > >       u64 emulated_inst_exits;
> > >       u64 dec_exits;
> > >       u64 ext_intr_exits;
> > > -     u64 halt_wait_ns;
> >
> > The halt_wait_ns refactor should be a separate patch.
> >
> How about putting it into a separate commit? Just want to keep all
> halt related change in the
> same patch series.

I think we're on the same page: move the halt_wait_ns changes to a
separate patch but still part of this series.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
@ 2021-07-09 15:25         ` David Matlack
  0 siblings, 0 replies; 55+ messages in thread
From: David Matlack @ 2021-07-09 15:25 UTC (permalink / raw)
  To: Jing Zhang
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Fri, Jul 09, 2021 at 10:18:20AM -0500, Jing Zhang wrote:
> On Thu, Jul 8, 2021 at 4:42 PM David Matlack <dmatlack@google.com> wrote:
> >
> > On Tue, Jul 06, 2021 at 06:03:50PM +0000, Jing Zhang wrote:
> > >
> > > diff --git a/arch/powerpc/include/asm/kvm_host.h b/arch/powerpc/include/asm/kvm_host.h
> > > index 9f52f282b1aa..4931d03e5799 100644
> > > --- a/arch/powerpc/include/asm/kvm_host.h
> > > +++ b/arch/powerpc/include/asm/kvm_host.h
> > > @@ -103,7 +103,6 @@ struct kvm_vcpu_stat {
> > >       u64 emulated_inst_exits;
> > >       u64 dec_exits;
> > >       u64 ext_intr_exits;
> > > -     u64 halt_wait_ns;
> >
> > The halt_wait_ns refactor should be a separate patch.
> >
> How about putting it into a separate commit? Just want to keep all
> halt related change in the
> same patch series.

I think we're on the same page: move the halt_wait_ns changes to a
separate patch but still part of this series.

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-06 18:03   ` Jing Zhang
  (?)
@ 2021-07-12 14:10     ` kernel test robot
  -1 siblings, 0 replies; 55+ messages in thread
From: kernel test robot @ 2021-07-12 14:10 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Paolo Bonzini, Sean Christopherson,
	Jim Mattson, Peter Shier, Oliver Upton, David Rientjes,
	David Matlack
  Cc: kbuild-all, Jing Zhang

[-- Attachment #1: Type: text/plain, Size: 1325 bytes --]

Hi Jing,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]

url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
base:   7caa04b36f204a01dac65582b71d26d190a1e022
config: i386-randconfig-a005-20210712 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
        git checkout aba26c018828dadbff3f53e058c161fab2b09d35
        # save the attached .config to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ld: arch/x86/../../virt/kvm/binary_stats.o: in function `kvm_stats_linear_hist_update':
>> binary_stats.c:(.text+0x1ac): undefined reference to `__udivdi3'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 42864 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-12 14:10     ` kernel test robot
  0 siblings, 0 replies; 55+ messages in thread
From: kernel test robot @ 2021-07-12 14:10 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 1357 bytes --]

Hi Jing,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]

url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
base:   7caa04b36f204a01dac65582b71d26d190a1e022
config: i386-randconfig-a005-20210712 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
        git checkout aba26c018828dadbff3f53e058c161fab2b09d35
        # save the attached .config to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ld: arch/x86/../../virt/kvm/binary_stats.o: in function `kvm_stats_linear_hist_update':
>> binary_stats.c:(.text+0x1ac): undefined reference to `__udivdi3'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 42864 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-12 14:10     ` kernel test robot
  0 siblings, 0 replies; 55+ messages in thread
From: kernel test robot @ 2021-07-12 14:10 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Paolo Bonzini, Sean Christopherson,
	Jim Mattson, Peter Shier, Oliver Upton, David Rientjes,
	David Matlack
  Cc: kbuild-all, Jing Zhang

[-- Attachment #1: Type: text/plain, Size: 1325 bytes --]

Hi Jing,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]

url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
base:   7caa04b36f204a01dac65582b71d26d190a1e022
config: i386-randconfig-a005-20210712 (attached as .config)
compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
reproduce (this is a W=1 build):
        # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
        git checkout aba26c018828dadbff3f53e058c161fab2b09d35
        # save the attached .config to linux build tree
        mkdir build_dir
        make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   ld: arch/x86/../../virt/kvm/binary_stats.o: in function `kvm_stats_linear_hist_update':
>> binary_stats.c:(.text+0x1ac): undefined reference to `__udivdi3'

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 42864 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-12 14:10     ` kernel test robot
  (?)
@ 2021-07-12 16:16       ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-12 16:16 UTC (permalink / raw)
  To: kernel test robot
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack,
	kbuild-all

On Mon, Jul 12, 2021 at 9:10 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Jing,
>
> Thank you for the patch! Yet something to improve:
>
> [auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]
>
> url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
> base:   7caa04b36f204a01dac65582b71d26d190a1e022
> config: i386-randconfig-a005-20210712 (attached as .config)
> compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
> reproduce (this is a W=1 build):
>         # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
>         git remote add linux-review https://github.com/0day-ci/linux
>         git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
>         git checkout aba26c018828dadbff3f53e058c161fab2b09d35
>         # save the attached .config to linux build tree
>         mkdir build_dir
>         make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
>    ld: arch/x86/../../virt/kvm/binary_stats.o: in function `kvm_stats_linear_hist_update':
> >> binary_stats.c:(.text+0x1ac): undefined reference to `__udivdi3'
Will fix this.
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-12 16:16       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-12 16:16 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 1516 bytes --]

On Mon, Jul 12, 2021 at 9:10 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Jing,
>
> Thank you for the patch! Yet something to improve:
>
> [auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]
>
> url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
> base:   7caa04b36f204a01dac65582b71d26d190a1e022
> config: i386-randconfig-a005-20210712 (attached as .config)
> compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
> reproduce (this is a W=1 build):
>         # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
>         git remote add linux-review https://github.com/0day-ci/linux
>         git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
>         git checkout aba26c018828dadbff3f53e058c161fab2b09d35
>         # save the attached .config to linux build tree
>         mkdir build_dir
>         make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
>    ld: arch/x86/../../virt/kvm/binary_stats.o: in function `kvm_stats_linear_hist_update':
> >> binary_stats.c:(.text+0x1ac): undefined reference to `__udivdi3'
Will fix this.
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-12 16:16       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-12 16:16 UTC (permalink / raw)
  To: kernel test robot
  Cc: KVM, KVMPPC, Paolo Bonzini, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack,
	kbuild-all

On Mon, Jul 12, 2021 at 9:10 AM kernel test robot <lkp@intel.com> wrote:
>
> Hi Jing,
>
> Thank you for the patch! Yet something to improve:
>
> [auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]
>
> url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
> base:   7caa04b36f204a01dac65582b71d26d190a1e022
> config: i386-randconfig-a005-20210712 (attached as .config)
> compiler: gcc-9 (Debian 9.3.0-22) 9.3.0
> reproduce (this is a W=1 build):
>         # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
>         git remote add linux-review https://github.com/0day-ci/linux
>         git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
>         git checkout aba26c018828dadbff3f53e058c161fab2b09d35
>         # save the attached .config to linux build tree
>         mkdir build_dir
>         make W=1 O=build_dir ARCH=i386 SHELL=/bin/bash
>
> If you fix the issue, kindly add following tag as appropriate
> Reported-by: kernel test robot <lkp@intel.com>
>
> All errors (new ones prefixed by >>):
>
>    ld: arch/x86/../../virt/kvm/binary_stats.o: in function `kvm_stats_linear_hist_update':
> >> binary_stats.c:(.text+0x1ac): undefined reference to `__udivdi3'
Will fix this.
>
> ---
> 0-DAY CI Kernel Test Service, Intel Corporation
> https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-06 18:03   ` Jing Zhang
  (?)
@ 2021-07-12 18:53     ` kernel test robot
  -1 siblings, 0 replies; 55+ messages in thread
From: kernel test robot @ 2021-07-12 18:53 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Paolo Bonzini, Sean Christopherson,
	Jim Mattson, Peter Shier, Oliver Upton, David Rientjes,
	David Matlack
  Cc: kbuild-all, Jing Zhang

[-- Attachment #1: Type: text/plain, Size: 1393 bytes --]

Hi Jing,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]

url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
base:   7caa04b36f204a01dac65582b71d26d190a1e022
config: mips-malta_kvm_defconfig (attached as .config)
compiler: mipsel-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
        git checkout aba26c018828dadbff3f53e058c161fab2b09d35
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "__udivdi3" [arch/mips/kvm/kvm.ko] undefined!

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20937 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-12 18:53     ` kernel test robot
  0 siblings, 0 replies; 55+ messages in thread
From: kernel test robot @ 2021-07-12 18:53 UTC (permalink / raw)
  To: kbuild-all

[-- Attachment #1: Type: text/plain, Size: 1425 bytes --]

Hi Jing,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]

url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
base:   7caa04b36f204a01dac65582b71d26d190a1e022
config: mips-malta_kvm_defconfig (attached as .config)
compiler: mipsel-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
        git checkout aba26c018828dadbff3f53e058c161fab2b09d35
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "__udivdi3" [arch/mips/kvm/kvm.ko] undefined!

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all(a)lists.01.org

[-- Attachment #2: config.gz --]
[-- Type: application/gzip, Size: 20937 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-12 18:53     ` kernel test robot
  0 siblings, 0 replies; 55+ messages in thread
From: kernel test robot @ 2021-07-12 18:53 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Paolo Bonzini, Sean Christopherson,
	Jim Mattson, Peter Shier, Oliver Upton, David Rientjes,
	David Matlack
  Cc: kbuild-all, Jing Zhang

[-- Attachment #1: Type: text/plain, Size: 1393 bytes --]

Hi Jing,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on 7caa04b36f204a01dac65582b71d26d190a1e022]

url:    https://github.com/0day-ci/linux/commits/Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
base:   7caa04b36f204a01dac65582b71d26d190a1e022
config: mips-malta_kvm_defconfig (attached as .config)
compiler: mipsel-linux-gcc (GCC) 9.3.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/aba26c018828dadbff3f53e058c161fab2b09d35
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Jing-Zhang/Linear-and-Logarithmic-histogram-statistics/20210707-020549
        git checkout aba26c018828dadbff3f53e058c161fab2b09d35
        # save the attached .config to linux build tree
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-9.3.0 make.cross ARCH=mips 

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>, old ones prefixed by <<):

>> ERROR: modpost: "__udivdi3" [arch/mips/kvm/kvm.ko] undefined!

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org

[-- Attachment #2: .config.gz --]
[-- Type: application/gzip, Size: 20937 bytes --]

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-28 12:39     ` Paolo Bonzini
  -1 siblings, 0 replies; 55+ messages in thread
From: Paolo Bonzini @ 2021-07-28 12:39 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack

On 06/07/21 20:03, Jing Zhang wrote:
> +#define LINHIST_SIZE_SMALL		10
> +#define LINHIST_SIZE_MEDIUM		20
> +#define LINHIST_SIZE_LARGE		50
> +#define LINHIST_SIZE_XLARGE		100
> +#define LINHIST_BUCKET_SIZE_SMALL	10
> +#define LINHIST_BUCKET_SIZE_MEDIUM	100
> +#define LINHIST_BUCKET_SIZE_LARGE	1000
> +#define LINHIST_BUCKET_SIZE_XLARGE	10000
> +
> +#define LOGHIST_SIZE_SMALL		8
> +#define LOGHIST_SIZE_MEDIUM		16
> +#define LOGHIST_SIZE_LARGE		32
> +#define LOGHIST_SIZE_XLARGE		64
> +#define LOGHIST_BASE_2			2

I'd prefer inlining all of these.  For log histograms use 2 directly in 
STATS_DESC_LOG_HIST, since the update function below uses fls64.

> 
> + */
> +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> +				  u64 value, size_t bucket_size)
> +{
> +	size_t index = value / bucket_size;
> +
> +	if (index >= size)
> +		index = size - 1;
> +	++data[index];
> +}
> +

Please make this function always inline, so that the compiler optimizes 
the division.

Also please use array_index_nospec to clamp the index to the size, in 
case value comes from a memory access as well.  Likewise for 
kvm_stats_log_hist_update.

Paolo


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-28 12:39     ` Paolo Bonzini
  0 siblings, 0 replies; 55+ messages in thread
From: Paolo Bonzini @ 2021-07-28 12:39 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack

On 06/07/21 20:03, Jing Zhang wrote:
> +#define LINHIST_SIZE_SMALL		10
> +#define LINHIST_SIZE_MEDIUM		20
> +#define LINHIST_SIZE_LARGE		50
> +#define LINHIST_SIZE_XLARGE		100
> +#define LINHIST_BUCKET_SIZE_SMALL	10
> +#define LINHIST_BUCKET_SIZE_MEDIUM	100
> +#define LINHIST_BUCKET_SIZE_LARGE	1000
> +#define LINHIST_BUCKET_SIZE_XLARGE	10000
> +
> +#define LOGHIST_SIZE_SMALL		8
> +#define LOGHIST_SIZE_MEDIUM		16
> +#define LOGHIST_SIZE_LARGE		32
> +#define LOGHIST_SIZE_XLARGE		64
> +#define LOGHIST_BASE_2			2

I'd prefer inlining all of these.  For log histograms use 2 directly in 
STATS_DESC_LOG_HIST, since the update function below uses fls64.

> 
> + */
> +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> +				  u64 value, size_t bucket_size)
> +{
> +	size_t index = value / bucket_size;
> +
> +	if (index >= size)
> +		index = size - 1;
> +	++data[index];
> +}
> +

Please make this function always inline, so that the compiler optimizes 
the division.

Also please use array_index_nospec to clamp the index to the size, in 
case value comes from a memory access as well.  Likewise for 
kvm_stats_log_hist_update.

Paolo

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-07 23:31     ` David Matlack
@ 2021-07-28 12:42       ` Paolo Bonzini
  -1 siblings, 0 replies; 55+ messages in thread
From: Paolo Bonzini @ 2021-07-28 12:42 UTC (permalink / raw)
  To: David Matlack, Jing Zhang
  Cc: KVM, KVMPPC, Sean Christopherson, Jim Mattson, Peter Shier,
	Oliver Upton, David Rientjes

On 08/07/21 01:31, David Matlack wrote:
>> +
>> +8.35 KVM_CAP_STATS_BINARY_FD
>> +----------------------------
>> +
>> +:Architectures: all
>> +
>> +This capability indicates the feature that userspace can get a file descriptor
>> +for every VM and VCPU to read statistics data in binary format.
> This should probably be in a separate patch with a Fixes tag.

Generally this chapter (which is probably incomplete, though) only 
includes capabilities for which KVM_CHECK_EXTENSION can return a value 
other than 0 or 1.  So there is no need to include KVM_CAP_STATS_BINARY_FD.

Paolo


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-28 12:42       ` Paolo Bonzini
  0 siblings, 0 replies; 55+ messages in thread
From: Paolo Bonzini @ 2021-07-28 12:42 UTC (permalink / raw)
  To: David Matlack, Jing Zhang
  Cc: KVM, KVMPPC, Sean Christopherson, Jim Mattson, Peter Shier,
	Oliver Upton, David Rientjes

On 08/07/21 01:31, David Matlack wrote:
>> +
>> +8.35 KVM_CAP_STATS_BINARY_FD
>> +----------------------------
>> +
>> +:Architectures: all
>> +
>> +This capability indicates the feature that userspace can get a file descriptor
>> +for every VM and VCPU to read statistics data in binary format.
> This should probably be in a separate patch with a Fixes tag.

Generally this chapter (which is probably incomplete, though) only 
includes capabilities for which KVM_CHECK_EXTENSION can return a value 
other than 0 or 1.  So there is no need to include KVM_CAP_STATS_BINARY_FD.

Paolo

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
  2021-07-06 18:03   ` Jing Zhang
@ 2021-07-28 12:45     ` Paolo Bonzini
  -1 siblings, 0 replies; 55+ messages in thread
From: Paolo Bonzini @ 2021-07-28 12:45 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack

On 06/07/21 20:03, Jing Zhang wrote:
> +		kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_wait_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(start_wait));

Instead of passing the size to the function, perhaps you can wrap it 
with a macro

#define KVM_STATS_LOG_HIST_UPDATE(array, value) \
     kvm_stats_log_hist_update(array, ARRAY_SIZE(array), value)

Paolo


^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
@ 2021-07-28 12:45     ` Paolo Bonzini
  0 siblings, 0 replies; 55+ messages in thread
From: Paolo Bonzini @ 2021-07-28 12:45 UTC (permalink / raw)
  To: Jing Zhang, KVM, KVMPPC, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes, David Matlack

On 06/07/21 20:03, Jing Zhang wrote:
> +		kvm_stats_log_hist_update(
> +				vc->runner->stat.generic.halt_wait_hist,
> +				LOGHIST_SIZE_LARGE,
> +				ktime_to_ns(cur) - ktime_to_ns(start_wait));

Instead of passing the size to the function, perhaps you can wrap it 
with a macro

#define KVM_STATS_LOG_HIST_UPDATE(array, value) \
     kvm_stats_log_hist_update(array, ARRAY_SIZE(array), value)

Paolo

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
  2021-07-28 12:39     ` Paolo Bonzini
@ 2021-07-30 17:31       ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-30 17:31 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: KVM, KVMPPC, Sean Christopherson, Jim Mattson, Peter Shier,
	Oliver Upton, David Rientjes, David Matlack

On Wed, Jul 28, 2021 at 5:39 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 06/07/21 20:03, Jing Zhang wrote:
> > +#define LINHIST_SIZE_SMALL           10
> > +#define LINHIST_SIZE_MEDIUM          20
> > +#define LINHIST_SIZE_LARGE           50
> > +#define LINHIST_SIZE_XLARGE          100
> > +#define LINHIST_BUCKET_SIZE_SMALL    10
> > +#define LINHIST_BUCKET_SIZE_MEDIUM   100
> > +#define LINHIST_BUCKET_SIZE_LARGE    1000
> > +#define LINHIST_BUCKET_SIZE_XLARGE   10000
> > +
> > +#define LOGHIST_SIZE_SMALL           8
> > +#define LOGHIST_SIZE_MEDIUM          16
> > +#define LOGHIST_SIZE_LARGE           32
> > +#define LOGHIST_SIZE_XLARGE          64
> > +#define LOGHIST_BASE_2                       2
>
> I'd prefer inlining all of these.  For log histograms use 2 directly in
> STATS_DESC_LOG_HIST, since the update function below uses fls64.
>
Sure, will inline these values.
Will remove the loghist base, since base 2 log is enough for any
number. No other base is needed.
> >
> > + */
> > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > +                               u64 value, size_t bucket_size)
> > +{
> > +     size_t index = value / bucket_size;
> > +
> > +     if (index >= size)
> > +             index = size - 1;
> > +     ++data[index];
> > +}
> > +
>
> Please make this function always inline, so that the compiler optimizes
> the division.
Sure.
>
> Also please use array_index_nospec to clamp the index to the size, in
> case value comes from a memory access as well.  Likewise for
> kvm_stats_log_hist_update.
Thanks. Will do.
>
> Paolo
>

Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 1/4] KVM: stats: Support linear and logarithmic histogram statistics
@ 2021-07-30 17:31       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-30 17:31 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: KVM, KVMPPC, Sean Christopherson, Jim Mattson, Peter Shier,
	Oliver Upton, David Rientjes, David Matlack

On Wed, Jul 28, 2021 at 5:39 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 06/07/21 20:03, Jing Zhang wrote:
> > +#define LINHIST_SIZE_SMALL           10
> > +#define LINHIST_SIZE_MEDIUM          20
> > +#define LINHIST_SIZE_LARGE           50
> > +#define LINHIST_SIZE_XLARGE          100
> > +#define LINHIST_BUCKET_SIZE_SMALL    10
> > +#define LINHIST_BUCKET_SIZE_MEDIUM   100
> > +#define LINHIST_BUCKET_SIZE_LARGE    1000
> > +#define LINHIST_BUCKET_SIZE_XLARGE   10000
> > +
> > +#define LOGHIST_SIZE_SMALL           8
> > +#define LOGHIST_SIZE_MEDIUM          16
> > +#define LOGHIST_SIZE_LARGE           32
> > +#define LOGHIST_SIZE_XLARGE          64
> > +#define LOGHIST_BASE_2                       2
>
> I'd prefer inlining all of these.  For log histograms use 2 directly in
> STATS_DESC_LOG_HIST, since the update function below uses fls64.
>
Sure, will inline these values.
Will remove the loghist base, since base 2 log is enough for any
number. No other base is needed.
> >
> > + */
> > +void kvm_stats_linear_hist_update(u64 *data, size_t size,
> > +                               u64 value, size_t bucket_size)
> > +{
> > +     size_t index = value / bucket_size;
> > +
> > +     if (index >= size)
> > +             index = size - 1;
> > +     ++data[index];
> > +}
> > +
>
> Please make this function always inline, so that the compiler optimizes
> the division.
Sure.
>
> Also please use array_index_nospec to clamp the index to the size, in
> case value comes from a memory access as well.  Likewise for
> kvm_stats_log_hist_update.
Thanks. Will do.
>
> Paolo
>

Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
  2021-07-28 12:42       ` Paolo Bonzini
@ 2021-07-30 17:32         ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-30 17:32 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: David Matlack, KVM, KVMPPC, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Wed, Jul 28, 2021 at 5:42 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 08/07/21 01:31, David Matlack wrote:
> >> +
> >> +8.35 KVM_CAP_STATS_BINARY_FD
> >> +----------------------------
> >> +
> >> +:Architectures: all
> >> +
> >> +This capability indicates the feature that userspace can get a file descriptor
> >> +for every VM and VCPU to read statistics data in binary format.
> > This should probably be in a separate patch with a Fixes tag.
>
> Generally this chapter (which is probably incomplete, though) only
> includes capabilities for which KVM_CHECK_EXTENSION can return a value
> other than 0 or 1.  So there is no need to include KVM_CAP_STATS_BINARY_FD.
Got it. Will drop this change.
>
> Paolo
>
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 2/4] KVM: stats: Update doc for histogram statistics
@ 2021-07-30 17:32         ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-30 17:32 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: David Matlack, KVM, KVMPPC, Sean Christopherson, Jim Mattson,
	Peter Shier, Oliver Upton, David Rientjes

On Wed, Jul 28, 2021 at 5:42 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 08/07/21 01:31, David Matlack wrote:
> >> +
> >> +8.35 KVM_CAP_STATS_BINARY_FD
> >> +----------------------------
> >> +
> >> +:Architectures: all
> >> +
> >> +This capability indicates the feature that userspace can get a file descriptor
> >> +for every VM and VCPU to read statistics data in binary format.
> > This should probably be in a separate patch with a Fixes tag.
>
> Generally this chapter (which is probably incomplete, though) only
> includes capabilities for which KVM_CHECK_EXTENSION can return a value
> other than 0 or 1.  So there is no need to include KVM_CAP_STATS_BINARY_FD.
Got it. Will drop this change.
>
> Paolo
>
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
  2021-07-28 12:45     ` Paolo Bonzini
@ 2021-07-30 17:34       ` Jing Zhang
  -1 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-30 17:34 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: KVM, KVMPPC, Sean Christopherson, Jim Mattson, Peter Shier,
	Oliver Upton, David Rientjes, David Matlack

On Wed, Jul 28, 2021 at 5:45 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 06/07/21 20:03, Jing Zhang wrote:
> > +             kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_wait_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(start_wait));
>
> Instead of passing the size to the function, perhaps you can wrap it
> with a macro
>
> #define KVM_STATS_LOG_HIST_UPDATE(array, value) \
>      kvm_stats_log_hist_update(array, ARRAY_SIZE(array), value)
That's nice! Will do that.
>
> Paolo
>
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

* Re: [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats
@ 2021-07-30 17:34       ` Jing Zhang
  0 siblings, 0 replies; 55+ messages in thread
From: Jing Zhang @ 2021-07-30 17:34 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: KVM, KVMPPC, Sean Christopherson, Jim Mattson, Peter Shier,
	Oliver Upton, David Rientjes, David Matlack

On Wed, Jul 28, 2021 at 5:45 AM Paolo Bonzini <pbonzini@redhat.com> wrote:
>
> On 06/07/21 20:03, Jing Zhang wrote:
> > +             kvm_stats_log_hist_update(
> > +                             vc->runner->stat.generic.halt_wait_hist,
> > +                             LOGHIST_SIZE_LARGE,
> > +                             ktime_to_ns(cur) - ktime_to_ns(start_wait));
>
> Instead of passing the size to the function, perhaps you can wrap it
> with a macro
>
> #define KVM_STATS_LOG_HIST_UPDATE(array, value) \
>      kvm_stats_log_hist_update(array, ARRAY_SIZE(array), value)
That's nice! Will do that.
>
> Paolo
>
Thanks,
Jing

^ permalink raw reply	[flat|nested] 55+ messages in thread

end of thread, other threads:[~2021-07-30 17:34 UTC | newest]

Thread overview: 55+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-07-06 18:03 [PATCH v1 0/4] Linear and Logarithmic histogram statistics Jing Zhang
2021-07-06 18:03 ` Jing Zhang
2021-07-06 18:03 ` [PATCH v1 1/4] KVM: stats: Support linear and logarithmic " Jing Zhang
2021-07-06 18:03   ` Jing Zhang
2021-07-08 21:01   ` David Matlack
2021-07-08 21:01     ` David Matlack
2021-07-08 21:40     ` Jing Zhang
2021-07-08 21:40       ` Jing Zhang
2021-07-08 21:45       ` David Matlack
2021-07-08 21:45         ` David Matlack
2021-07-12 14:10   ` kernel test robot
2021-07-12 14:10     ` kernel test robot
2021-07-12 14:10     ` kernel test robot
2021-07-12 16:16     ` Jing Zhang
2021-07-12 16:16       ` Jing Zhang
2021-07-12 16:16       ` Jing Zhang
2021-07-12 18:53   ` kernel test robot
2021-07-12 18:53     ` kernel test robot
2021-07-12 18:53     ` kernel test robot
2021-07-28 12:39   ` Paolo Bonzini
2021-07-28 12:39     ` Paolo Bonzini
2021-07-30 17:31     ` Jing Zhang
2021-07-30 17:31       ` Jing Zhang
2021-07-06 18:03 ` [PATCH v1 2/4] KVM: stats: Update doc for " Jing Zhang
2021-07-06 18:03   ` Jing Zhang
2021-07-07 23:31   ` David Matlack
2021-07-07 23:31     ` David Matlack
2021-07-08 14:29     ` Jing Zhang
2021-07-08 14:29       ` Jing Zhang
2021-07-28 12:42     ` Paolo Bonzini
2021-07-28 12:42       ` Paolo Bonzini
2021-07-30 17:32       ` Jing Zhang
2021-07-30 17:32         ` Jing Zhang
2021-07-08 21:14   ` David Matlack
2021-07-08 21:14     ` David Matlack
2021-07-08 21:16     ` David Matlack
2021-07-08 21:16       ` David Matlack
2021-07-08 21:43       ` Jing Zhang
2021-07-08 21:43         ` Jing Zhang
2021-07-06 18:03 ` [PATCH v1 3/4] KVM: selftests: Add checks for histogram stats parameters Jing Zhang
2021-07-06 18:03   ` Jing Zhang
2021-07-08 21:26   ` David Matlack
2021-07-08 21:26     ` David Matlack
2021-07-06 18:03 ` [PATCH v1 4/4] KVM: stats: Add halt polling related histogram stats Jing Zhang
2021-07-06 18:03   ` Jing Zhang
2021-07-08 21:42   ` David Matlack
2021-07-08 21:42     ` David Matlack
2021-07-09 15:18     ` Jing Zhang
2021-07-09 15:18       ` Jing Zhang
2021-07-09 15:25       ` David Matlack
2021-07-09 15:25         ` David Matlack
2021-07-28 12:45   ` Paolo Bonzini
2021-07-28 12:45     ` Paolo Bonzini
2021-07-30 17:34     ` Jing Zhang
2021-07-30 17:34       ` Jing Zhang

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.