Skip to contentSkip to conversation

KVM: perf: a smart tool to analyse kvm events

RFC PATCH Superseded Xiao Guangrong 5 participants 25 messages Jan 16, 2012 – Jan 24, 2012

Subsystems (5)
x86 KVM perf events Tracing +1 more subsystems

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

RFC PATCH 1/1 KVM: perf: a smart tool to analyse kvm events

This tool is very like xenoprof(if i remember correctly), and traces kvm events smartly. currently, it supports vmexit/mmio/ioport events.

Usage:
- to trace kvm events:

# ./perf kvm-events record

- show the result

# ./perf kvm-events report

Some output are as follow:

# ./perf kvm-events report
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

APIC_ACCESS 438107 44.89% 6.20% 17.91us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
                 HLT      15424         1.58%        82.12%      6735.06us
           CR_ACCESS       4089         0.42%         0.02%         6.08us

Total Samples:975981, Total events handled time:126502464.88us.

The default event to be analysed is vmexit, we can use --event to specify it, for example, if we want to trace mmio event:

# ./perf kvm-events report --event mmio
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W     196589        64.95%        70.01%         3.83us
        0xfee00310:W      35356        11.68%         6.48%         1.97us
        0xfee00300:W      35356        11.68%        16.37%         4.97us
        0xfee00300:R      35356        11.68%         7.14%         2.17us

Total Samples:302657, Total events handled time:1074746.01us.

We can use --vcpu to specify which vcpu is traced:
root@localhost perf]# ./perf kvm-events report --event mmio --vcpu 1
Warning: Error: expected type 5 but read 4
Warning: Error: expected type 5 but read 0
Warning: unknown op '}'

Analyze events for VCPU 1:

         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W      58041        71.20%        74.90%         3.70us
        0xfee00310:W       7826         9.60%         5.28%         1.93us
        0xfee00300:W       7826         9.60%        13.82%         5.06us
        0xfee00300:R       7826         9.60%         6.01%         2.20us

Total Samples:81519, Total events handled time:286577.81us.

And, '--key' is used to sort the result, the possible value sample (default, the result is sorted by samples number), time(the result is sorted by time%):

# ./perf kvm-events report --key time
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

HLT 15424 1.58% 82.12% 6735.06us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
         APIC_ACCESS     438107        44.89%         6.20%        17.91us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
           CR_ACCESS       4089         0.42%         0.02%         6.08us

Total Samples:975981, Total events handled time:126502464.88us.

I hope guys will like it and any comments are welcome! :)

#1 lore raw

PATCH 1/3 KVM: trace mmio read event properly

In current code, we use KVM_TRACE_MMIO_READ to trace mmio read event which only can be completed immediately, instead of it, we trace the time when read event occur, then cooperate with then later patch, we can know the time of mmio read emulation

---
 arch/x86/kvm/x86.c |    6 ++----
 1 files changed, 2 insertions(+), 4 deletions(-)
arch/x86/kvm/x86.c +2 -4
index c95ca2d..0d41cfc 100644
@@ -3432,7 +3432,6 @@ static int vcpu_mmio_read(struct kvm_vcpu *vcpu, gpa_t addr, int len, void *v)
 		      !kvm_iodevice_read(&vcpu->arch.apic->dev, addr, n, v))
 		    && kvm_io_bus_read(vcpu->kvm, KVM_MMIO_BUS, addr, n, v))
 			break;
-		trace_kvm_mmio(KVM_TRACE_MMIO_READ, n, addr, *(u64 *)v);
 		handled += n;
 		addr += n;
 		len -= n;
@@ -3658,8 +3657,6 @@ static int read_prepare(struct kvm_vcpu *vcpu, void *val, int bytes)
 {
 	if (vcpu->mmio_read_completed) {
 		memcpy(val, vcpu->mmio_data, bytes);
-		trace_kvm_mmio(KVM_TRACE_MMIO_READ, bytes,
-			       vcpu->mmio_phys_addr, *(u64 *)val);
 		vcpu->mmio_read_completed = 0;
 		return 1;
 	}
@@ -3681,7 +3678,6 @@ static int write_emulate(struct kvm_vcpu *vcpu, gpa_t gpa,
 
 static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
 {
-	trace_kvm_mmio(KVM_TRACE_MMIO_WRITE, bytes, gpa, *(u64 *)val);
 	return vcpu_mmio_write(vcpu, gpa, bytes, val);
 }
 
@@ -3744,6 +3740,8 @@ mmio:
 	/*
 	 * Is this MMIO handled locally?
 	 */
+	trace_kvm_mmio(write ? KVM_TRACE_MMIO_WRITE : KVM_TRACE_MMIO_READ,
+			bytes, gpa, *(u64 *)val);
 	handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
 	if (handled == bytes)
 		return X86EMUL_CONTINUE;
Signature · 1 line
1.7.7.5
#2 lore raw

Re: [PATCH 1/3] KVM: trace mmio read event properly

arch/x86/kvm/x86.c mmio: · line 3743

Quoted 10 lines · Xiao Guangrong

In current code, we use KVM_TRACE_MMIO_READ to trace mmio read event which only can be completed immediately, instead of it, we trace the time when read event occur, then cooperate with then later patch, we can know the time of mmio read emulation

arch/x86/kvm/x86.c +1 -0
@@ -3744,6 +3740,8 @@ mmio:
 	/*
 	 * Is this MMIO handled locally?
 	 */
+	trace_kvm_mmio(write ? KVM_TRACE_MMIO_WRITE : KVM_TRACE_MMIO_READ,

It's better to push the conditional to the trace event itself, so it's only evaluated if tracing is enabled.

arch/x86/kvm/x86.c mmio: · line 3744

Quoted 1 line
arch/x86/kvm/x86.c +1 -0
+			bytes, gpa, *(u64 *)val);

We get the wrong value for reads here, no?

Can't we leave the code as is, and infer the start of the event from the last kvm_exit trace?

Quoted 3 lines
arch/x86/kvm/x86.c +0 -0
 	handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
 	if (handled == bytes)
 		return X86EMUL_CONTINUE;
Signature · 1 line
error compiling committee.c: too many arguments to function
#3 lore raw

Re: [PATCH 1/3] KVM: trace mmio read event properly

Quoted 6 lines · Avi Kivity
Quoted 5 lines · Xiao Guangrong

In current code, we use KVM_TRACE_MMIO_READ to trace mmio read event which only can be completed immediately, instead of it, we trace the time when read event occur, then cooperate with then later patch, we can know the time of mmio read emulation

Quoted 9 lines

arch/x86/kvm/x86.c mmio: · line 3743

Quoted 5 lines
arch/x86/kvm/x86.c +1 -0
@@ -3744,6 +3740,8 @@ mmio:
 	/*
 	 * Is this MMIO handled locally?
 	 */
+	trace_kvm_mmio(write ? KVM_TRACE_MMIO_WRITE : KVM_TRACE_MMIO_READ,

It's better to push the conditional to the trace event itself, so it's only evaluated if tracing is enabled.

Yes.

Quoted 4 lines

arch/x86/kvm/x86.c mmio: · line 3744

Quoted 1 line
arch/x86/kvm/x86.c +1 -0
+			bytes, gpa, *(u64 *)val);

We get the wrong value for reads here, no?

Yes, the value is meaningless in this point.

Quoted 2 lines

Can't we leave the code as is, and infer the start of the event from the last kvm_exit trace?

Yes, we can do it, but the same problems is we need trace vcpu id to get its vmexit, i will do it in the next version if you like this way :)

#4 lore raw

PATCH 2/3 KVM: improve trace events of vmexit/mmio/ioport

In reply to Xiao Guangrong

- trace vcpu_id for these events
- add kvm_mmio_done to trace the time when mmio/ioport emulation is completed

---
 arch/x86/kvm/trace.h       |   33 ++++++++++++++++++++++++++-------
 arch/x86/kvm/x86.c         |   19 +++++++++++++------
 include/trace/events/kvm.h |   32 +++++++++++++++++++++++++-------
 3 files changed, 64 insertions(+), 20 deletions(-)
arch/x86/kvm/trace.h +26 -7
index 911d264..e556458 100644
@@ -91,11 +91,12 @@ TRACE_EVENT(kvm_hv_hypercall,
  * Tracepoint for PIO.
  */
 TRACE_EVENT(kvm_pio,
-	TP_PROTO(unsigned int rw, unsigned int port, unsigned int size,
-		 unsigned int count),
-	TP_ARGS(rw, port, size, count),
+	TP_PROTO(unsigned int vcpu_id, unsigned int rw, unsigned int port,
+		 unsigned int size, unsigned int count),
+	TP_ARGS(vcpu_id, rw, port, size, count),
 
 	TP_STRUCT__entry(
+		__field(	unsigned int,	vcpu_id		)
 		__field(	unsigned int, 	rw		)
 		__field(	unsigned int, 	port		)
 		__field(	unsigned int, 	size		)
@@ -103,17 +104,33 @@ TRACE_EVENT(kvm_pio,
 	),
 
 	TP_fast_assign(
+		__entry->vcpu_id	= vcpu_id;
 		__entry->rw		= rw;
 		__entry->port		= port;
 		__entry->size		= size;
 		__entry->count		= count;
 	),
 
-	TP_printk("pio_%s at 0x%x size %d count %d",
-		  __entry->rw ? "write" : "read",
+	TP_printk("vcpu %u pio_%s at 0x%x size %d count %d",
+		  __entry->vcpu_id, __entry->rw ? "write" : "read",
 		  __entry->port, __entry->size, __entry->count)
 );
 
+TRACE_EVENT(kvm_pio_done,
+	TP_PROTO(unsigned int vcpu_id),
+	TP_ARGS(vcpu_id),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	vcpu_id		)
+	),
+
+	TP_fast_assign(
+		__entry->vcpu_id	= vcpu_id;
+	),
+
+	TP_printk("vcpu %u", __entry->vcpu_id)
+);
+
 /*
  * Tracepoint for cpuid.
  */
@@ -280,6 +297,7 @@ TRACE_EVENT(kvm_exit,
 	TP_ARGS(exit_reason, vcpu, isa),
 
 	TP_STRUCT__entry(
+		__field(	unsigned int,	vcpu_id		)
 		__field(	unsigned int,	exit_reason	)
 		__field(	unsigned long,	guest_rip	)
 		__field(	u32,	        isa             )
@@ -288,6 +306,7 @@ TRACE_EVENT(kvm_exit,
 	),
 
 	TP_fast_assign(
+		__entry->vcpu_id	= vcpu->vcpu_id;
 		__entry->exit_reason	= exit_reason;
 		__entry->guest_rip	= kvm_rip_read(vcpu);
 		__entry->isa            = isa;
@@ -295,8 +314,8 @@ TRACE_EVENT(kvm_exit,
 					   &__entry->info2);
 	),
 
-	TP_printk("reason %s rip 0x%lx info %llx %llx",
-		 (__entry->isa == KVM_ISA_VMX) ?
+	TP_printk("vcpu %u reason %s rip 0x%lx info %llx %llx",
+		 __entry->vcpu_id, (__entry->isa == KVM_ISA_VMX) ?
 		 __print_symbolic(__entry->exit_reason, VMX_EXIT_REASONS) :
 		 __print_symbolic(__entry->exit_reason, SVM_EXIT_REASONS),
 		 __entry->guest_rip, __entry->info1, __entry->info2)
arch/x86/kvm/x86.c +13 -6
index 0d41cfc..cf54478 100644
@@ -3684,7 +3684,8 @@ static int write_mmio(struct kvm_vcpu *vcpu, gpa_t gpa, int bytes, void *val)
 static int read_exit_mmio(struct kvm_vcpu *vcpu, gpa_t gpa,
 			  void *val, int bytes)
 {
-	trace_kvm_mmio(KVM_TRACE_MMIO_READ_UNSATISFIED, bytes, gpa, 0);
+	trace_kvm_mmio(vcpu->vcpu_id, KVM_TRACE_MMIO_READ_UNSATISFIED,
+		       bytes, gpa, 0);
 	return X86EMUL_IO_NEEDED;
 }
 
@@ -3740,11 +3741,14 @@ mmio:
 	/*
 	 * Is this MMIO handled locally?
 	 */
-	trace_kvm_mmio(write ? KVM_TRACE_MMIO_WRITE : KVM_TRACE_MMIO_READ,
-			bytes, gpa, *(u64 *)val);
+	trace_kvm_mmio(vcpu->vcpu_id,
+		       write ? KVM_TRACE_MMIO_WRITE : KVM_TRACE_MMIO_READ,
+		       bytes, gpa, *(u64 *)val);
 	handled = ops->read_write_mmio(vcpu, gpa, bytes, val);
-	if (handled == bytes)
+	if (handled == bytes) {
+		trace_kvm_mmio_done(vcpu->vcpu_id);
 		return X86EMUL_CONTINUE;
+	}
 
 	gpa += handled;
 	bytes -= handled;
@@ -3902,7 +3906,7 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 			       unsigned short port, void *val,
 			       unsigned int count, bool in)
 {
-	trace_kvm_pio(!in, port, size, count);
+	trace_kvm_pio(vcpu->vcpu_id, !in, port, size, count);
 
 	vcpu->arch.pio.port = port;
 	vcpu->arch.pio.in = in;
@@ -3910,6 +3914,7 @@ static int emulator_pio_in_out(struct kvm_vcpu *vcpu, int size,
 	vcpu->arch.pio.size = size;
 
 	if (!kernel_pio(vcpu, vcpu->arch.pio_data)) {
+		trace_kvm_mmio_done(vcpu->vcpu_id);
 		vcpu->arch.pio.count = 0;
 		return 1;
 	}
@@ -5399,7 +5404,7 @@ static int complete_mmio(struct kvm_vcpu *vcpu)
 			return 0;
 		}
 		if (vcpu->mmio_is_write)
-			return 1;
+			goto exit;
 		vcpu->mmio_read_completed = 1;
 	}
 	vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
@@ -5407,6 +5412,8 @@ static int complete_mmio(struct kvm_vcpu *vcpu)
 	srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
 	if (r != EMULATE_DONE)
 		return 0;
+exit:
+	trace_kvm_mmio_done(vcpu->vcpu_id);
 	return 1;
 }
 
include/trace/events/kvm.h +25 -7
index 46e3cd8..20b9f17 100644
@@ -152,28 +152,46 @@ TRACE_EVENT(kvm_ack_irq,
 	{ KVM_TRACE_MMIO_WRITE, "write" }
 
 TRACE_EVENT(kvm_mmio,
-	TP_PROTO(int type, int len, u64 gpa, u64 val),
-	TP_ARGS(type, len, gpa, val),
+	TP_PROTO(unsigned int vcpu_id, int type, int len, u64 gpa, u64 val),
+	TP_ARGS(vcpu_id, type, len, gpa, val),
 
 	TP_STRUCT__entry(
-		__field(	u32,	type		)
-		__field(	u32,	len		)
-		__field(	u64,	gpa		)
-		__field(	u64,	val		)
+		__field(	unsigned int,	vcpu_id	)
+		__field(	u32,		type	)
+		__field(	u32,		len	)
+		__field(	u64,		gpa	)
+		__field(	u64,		val	)
 	),
 
 	TP_fast_assign(
+		__entry->vcpu_id	= vcpu_id;
 		__entry->type		= type;
 		__entry->len		= len;
 		__entry->gpa		= gpa;
 		__entry->val		= val;
 	),
 
-	TP_printk("mmio %s len %u gpa 0x%llx val 0x%llx",
+	TP_printk("vcpu %u mmio %s len %u gpa 0x%llx val 0x%llx",
+		  __entry->vcpu_id,
 		  __print_symbolic(__entry->type, kvm_trace_symbol_mmio),
 		  __entry->len, __entry->gpa, __entry->val)
 );
 
+TRACE_EVENT(kvm_mmio_done,
+	TP_PROTO(unsigned int vcpu_id),
+	TP_ARGS(vcpu_id),
+
+	TP_STRUCT__entry(
+		__field(	unsigned int,	vcpu_id		)
+	),
+
+	TP_fast_assign(
+		__entry->vcpu_id	= vcpu_id;
+	),
+
+	TP_printk("vcpu %u", __entry->vcpu_id)
+);
+
 #define kvm_fpu_load_symbol	\
 	{0, "unload"},		\
 	{1, "load"}
Signature · 1 line
1.7.7.5
#5 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

Quoted 1 line · Xiao Guangrong

- trace vcpu_id for these events

We can infer the vcpu id from the kvm_entry tracepoints, no?

Quoted 1 line

- add kvm_mmio_done to trace the time when mmio/ioport emulation is completed

ditto?

Relying on the existing tracepoints will make the tool work on older kernels.

Signature · 1 line
error compiling committee.c: too many arguments to function
#6 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

Quoted 5 lines · Avi Kivity
Quoted 1 line · Xiao Guangrong

- trace vcpu_id for these events

We can infer the vcpu id from the kvm_entry tracepoints, no?

Thanks for your review, Avi!

Hmm. i think it is hard to do since the vcpu thread can be scheduled anytime, one example is as follow:

CPU 0

kvm_entry vcpu 0
......
kvm_entry vcpu 1
......
event1 occurs
......
event2 occurs

It is hard to know the event belong to which kvm_entry?

Quoted 4 lines
Quoted 1 line

- add kvm_mmio_done to trace the time when mmio/ioport emulation is completed

ditto?

I think is ok to get the event end time by using kvm_entry.

Quoted 4 lines

Relying on the existing tracepoints will make the tool work on older kernels.

We can drop all new events, but unfortunately, the information of the origin tracepoints is not enough, at least vcpu_id need be traced in theses events to match its events. Yes?

#7 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

Quoted 35 lines · Xiao Guangrong
Quoted 5 lines · Avi Kivity
Quoted 1 line · Xiao Guangrong

- trace vcpu_id for these events

We can infer the vcpu id from the kvm_entry tracepoints, no?

Thanks for your review, Avi!

Hmm. i think it is hard to do since the vcpu thread can be scheduled anytime, one example is as follow:

CPU 0

kvm_entry vcpu 0
......
kvm_entry vcpu 1
......
event1 occurs
......
event2 occurs

It is hard to know the event belong to which kvm_entry?

Quoted 4 lines
Quoted 1 line

- add kvm_mmio_done to trace the time when mmio/ioport emulation is completed

ditto?

I think is ok to get the event end time by using kvm_entry.

Quoted 1 line
Quoted 8 lines
Quoted 3 lines

Relying on the existing tracepoints will make the tool work on older kernels.

We can drop all new events, but unfortunately, the information of the origin tracepoints is not enough, at least vcpu_id need be traced in theses events to match its events. Yes?

Yes, and if you don't add completed events, you'll have to use kvm_entry whose collection adds a lot of overhead.

#8 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

Quoted 41 lines · Marcelo Tosatti
Quoted 40 lines · Xiao Guangrong
Quoted 5 lines · Avi Kivity
Quoted 1 line · Xiao Guangrong

- trace vcpu_id for these events

We can infer the vcpu id from the kvm_entry tracepoints, no?

Thanks for your review, Avi!

Hmm. i think it is hard to do since the vcpu thread can be scheduled anytime, one example is as follow:

CPU 0

kvm_entry vcpu 0
......
kvm_entry vcpu 1
......
event1 occurs
......
event2 occurs

It is hard to know the event belong to which kvm_entry?

Quoted 4 lines
Quoted 1 line

- add kvm_mmio_done to trace the time when mmio/ioport emulation is completed

ditto?

I think is ok to get the event end time by using kvm_entry.

Quoted 4 lines

Relying on the existing tracepoints will make the tool work on older kernels.

Quoted 6 lines
Quoted 3 lines

We can drop all new events, but unfortunately, the information of the origin tracepoints is not enough, at least vcpu_id need be traced in theses events to match its events. Yes?

Yes, and if you don't add completed events, you'll have to use kvm_entry whose collection adds a lot of overhead.

vcpus run as threads and hence have their own tid which is available in the perf samples.

There is an ongoing 'discussion' about modifying existing tracepoints which your proposed patch violates. This is the start of it:

https://lkml.org/lkml/2012/1/16/41

David

#9 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

Quoted 10 lines · David Ahern
Quoted 10 lines
Quoted 9 lines
Quoted 4 lines

Relying on the existing tracepoints will make the tool work on older kernels.

We can drop all new events, but unfortunately, the information of the origin tracepoints is not enough, at least vcpu_id need be traced in theses events to match its events. Yes?

Quoted 7 lines
Quoted 2 lines

Yes, and if you don't add completed events, you'll have to use kvm_entry whose collection adds a lot of overhead.

vcpus run as threads and hence have their own tid which is available in the perf samples.

Nice, thanks for your information, David!

Quoted 3 lines

There is an ongoing 'discussion' about modifying existing tracepoints which your proposed patch violates. This is the start of it:

Hmm, i think we can still add completed tracepoints in the new version kernel, if old version kernel is used, we can fall back to use kvm_entry instead?

And there is a exception for mmio read, in current code, the mmio read event is actually used to trace the time when then read emulation is completed, i think we can add a tracepoint like mmio_read_begin to trace the start time of mmio read. So:
- for the new kernel, we use mmio_read_begion and kvm_mmio(READ...) to calculate start time and end time.
- for the old kernel, we use kvm_exit and kvm_mmio(READ...) to calculate start time and end time.

Your idea?

#10 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

Quoted 7 lines · Xiao Guangrong
Quoted 3 lines

There is an ongoing 'discussion' about modifying existing tracepoints which your proposed patch violates. This is the start of it:

Hmm, i think we can still add completed tracepoints in the new version kernel, if old version kernel is used, we can fall back to use kvm_entry instead?

Yes, new ones are ok. I was referring to the tracepoints like kvm_pio where you added the vcpu_id. And it is not really necessary: with kvm_entry tracepoints it is easy to correlate vcpu to tid and even without you still get thread base samples so events happening on a thread are all the sample vcpu (even if you don't know whether that is vcpu 0, 1, 2, etc).

Quoted 10 lines

And there is a exception for mmio read, in current code, the mmio read event is actually used to trace the time when then read emulation is completed, i think we can add a tracepoint like mmio_read_begin to trace the start time of mmio read. So:
- for the new kernel, we use mmio_read_begion and kvm_mmio(READ...) to calculate start time and end time.
- for the old kernel, we use kvm_exit and kvm_mmio(READ...) to calculate start time and end time.

Quoted 2 lines

Your idea?

I did play around with it a bit more today.

My concern would be adding more events may make things more precise, but it adds more overhead and I am not sure the precision is worth it. For example on my laptop (Penryn Core 2; a lab server with a xeon E5560 processor is much faster):

0.000002 kvm_exit reason IO_INSTRUCTION rip 0x806d0e30 info 710048 0

0.000003     kvm_emulate_insn 0:806d0e30: e4 71
0.000001     kvm_pio pio_read at 0x71 size 1 count 1
0.000001     kvm_userspace_exit reason KVM_EXIT_IO (2)
0.000003     kvm_set_irq gsi 8 level 0 source 0
0.000001     kvm_pic_set_irq chip 1 pin 0 (edge|masked)
0.000001     kvm_ioapic_set_irq pin 8 dst 1 vec=209 (Fixed|logical|edge)
         total exit time: 0.000016

The first column is the delta-time between successive events for a vcpu. Most of those events are in the rounded up microsecond range. Moving on to the subsequent kvm_entry shows a total VMENTRY run time of 5 usecs:
ie., 16 usecs on a VMEXIT with 7 tracepoints and 5 usecs spent in a VMENTRY.

What I am getting at is that the cost of the tracepoints becomes a significant overhead. If it costs 500nsec or 1usec to generate an event and the time in a VMENTRY is only 5 usecs the tracepoint is a large part of the time.

David

#11 lore raw

Re: [PATCH 2/3] KVM: improve trace events of vmexit/mmio/ioport

In reply to Xiao Guangrong
Quoted 24 lines · Xiao Guangrong
Quoted 5 lines · Avi Kivity
Quoted 1 line · Xiao Guangrong

- trace vcpu_id for these events

We can infer the vcpu id from the kvm_entry tracepoints, no?

Thanks for your review, Avi!

Hmm. i think it is hard to do since the vcpu thread can be scheduled anytime, one example is as follow:

CPU 0

kvm_entry vcpu 0
......
kvm_entry vcpu 1
......
event1 occurs
......
event2 occurs

Quoted 2 lines

It is hard to know the event belong to which kvm_entry?

Why is it hard? Correlate the task IDs.

Signature · 1 line
error compiling committee.c: too many arguments to function
#12 lore raw

PATCH 3/3 KVM: perf: kvm events analysis tool

In reply to Xiao Guangrong

Add 'perf kvm-events' support to analyze kvm vmexit/mmio/ioport smartly

Usage:
perf kvm-events record
perf kvm-events report

---
 tools/perf/Documentation/perf-kvm-events.txt |   54 ++
 tools/perf/Makefile                          |    1 +
 tools/perf/builtin-kvm-events.c              |  860 ++++++++++++++++++++++++++
 tools/perf/builtin.h                         |    1 +
 tools/perf/perf.c                            |    1 +
 5 files changed, 917 insertions(+), 0 deletions(-)
 create mode 100644 tools/perf/Documentation/perf-kvm-events.txt
 create mode 100644 tools/perf/builtin-kvm-events.c
tools/perf/Documentation/perf-kvm-events.txt new file +54 -0
new file mode 100644
index 0000000..73bcb82
@@ -0,0 +1,54 @@
+perf-kvm-events(1)
+============
+
+NAME
+----
+perf-kvm-events - Analyze kvm events
+
+SYNOPSIS
+--------
+[verse]
+'perf kvm-events' {record|report}
+
+DESCRIPTION
+-----------
+You can analyze some crucial events and statistics with this
+'perf kvm-events' command.
+
+  'perf kvm-events record <command>' records kvm events
+  between start and end <command>. And this command
+  produces the file "perf.data" which contains tracing
+  results of kvm events.
+
+  'perf kvm-events report' reports statistical data.
+
+COMMON OPTIONS
+--------------
+
+-i::
+--input=<file>::
+        Input file name. (default: perf.data unless stdin is a fifo)
+
+-v::
+--verbose::
+        Be more verbose (show symbol address, etc).
+
+-D::
+--dump-raw-trace::
+        Dump raw trace in ASCII.
+
+REPORT OPTIONS
+--------------
+--vcpu=<value>::
+	analyze events which occures on this vcpu
+
+--events=<value>::
+	events to be analyzed. Possible values: vmexit, mmio, ioport.
+-k::
+--key=<value>::
+        Sorting key. Possible values: sample(default, sort by samples number),
+time(sort by time%).
+
+SEE ALSO
+--------
+linkperf:perf[1]
tools/perf/Makefile +1 -0
index ac86d67..ee43451 100644
@@ -382,6 +382,7 @@ BUILTIN_OBJS += $(OUTPUT)builtin-probe.o
 BUILTIN_OBJS += $(OUTPUT)builtin-kmem.o
 BUILTIN_OBJS += $(OUTPUT)builtin-lock.o
 BUILTIN_OBJS += $(OUTPUT)builtin-kvm.o
+BUILTIN_OBJS += $(OUTPUT)builtin-kvm-events.o
 BUILTIN_OBJS += $(OUTPUT)builtin-test.o
 BUILTIN_OBJS += $(OUTPUT)builtin-inject.o
 
tools/perf/builtin-kvm-events.c new file +860 -0

860 lines not on this page · raw message

tools/perf/builtin.h +1 -0
index b382bd5..fb19e3d 100644
@@ -33,6 +33,7 @@ extern int cmd_probe(int argc, const char **argv, const char *prefix);
 extern int cmd_kmem(int argc, const char **argv, const char *prefix);
 extern int cmd_lock(int argc, const char **argv, const char *prefix);
 extern int cmd_kvm(int argc, const char **argv, const char *prefix);
+extern int cmd_kvm_events(int argc, const char **argv, const char *prefix);
 extern int cmd_test(int argc, const char **argv, const char *prefix);
 extern int cmd_inject(int argc, const char **argv, const char *prefix);
 
tools/perf/perf.c +1 -0
index 2b2e225..ab85ea5 100644
@@ -317,6 +317,7 @@ static void handle_internal_command(int argc, const char **argv)
 		{ "kmem",	cmd_kmem,	0 },
 		{ "lock",	cmd_lock,	0 },
 		{ "kvm",	cmd_kvm,	0 },
+		{ "kvm-events", cmd_kvm_events, 0},
 		{ "test",	cmd_test,	0 },
 		{ "inject",	cmd_inject,	0 },
 	};
Signature · 1 line
1.7.7.5
#13 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

Quoted 4 lines · Xiao Guangrong

Add 'perf kvm-events' support to analyze kvm vmexit/mmio/ioport smartly

Usage:
perf kvm-events record

Why not 'perf record -e kvm'?

Quoted 8 lines

perf kvm-events report

tools/perf/builtin-kvm-events.c new file +4 -0
+static const char *get_exit_reason(long isa, u64 exit_code)
+{
+	int table_size = ARRAY_SIZE(svm_exit_reasons);
+	struct exit_reasons_table *table = svm_exit_reasons;

tools/perf/builtin-kvm-events.c line 266

Quoted 10 lines
tools/perf/builtin-kvm-events.c new file +10 -0
+
+
+	if (isa == 1) {
+		table = vmx_exit_reasons;
+		table_size = ARRAY_SIZE(vmx_exit_reasons);
+	}
+
+	while (table_size--) {
+		if (table->exit_code == exit_code)
+			return table->reason;

... table[exit_code] ...

tools/perf/builtin-kvm-events.c line 271

Quoted 5 lines
tools/perf/builtin-kvm-events.c new file +5 -0
+		table++;
+	}
+
+	die("unkonw kvm exit code:%ld on %s\n", exit_code, isa == 1 ?
+						"VMX" : "SVM");

"unknown"

tools/perf/builtin-kvm-events.c line 280

Quoted 3 lines
tools/perf/builtin-kvm-events.c new file +3 -0
+
+struct kvm_events_ops {
+	bool (*is_begain_event)(struct event *event, void *data);

begin

tools/perf/builtin-kvm-events.c line 302

Quoted 13 lines
tools/perf/builtin-kvm-events.c new file +13 -0
+	bool (*is_end_event)(struct event *event);
+	struct event_key (*get_key)(struct event *event, void *data);
+	void (*decode_key)(struct event_key *key, char decode[20]);
+	const char *name;
+};
+
+
+static struct event_key exit_event_get_key(struct event *event, void *data)
+{
+	struct event_key key;
+
+	key.key = raw_field_value(event, "exit_reason", data);
+	key.info = raw_field_value(event, "isa", data);

"isa" is not available on all kernel versions; need to fall back to /proc/cpuid detection.

Quoted 3 lines
(quoted diff) +2 -0
+	return key;
+}
Signature · 1 line
error compiling committee.c: too many arguments to function
#14 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

Quoted 7 lines · Avi Kivity
Quoted 4 lines · Xiao Guangrong

Add 'perf kvm-events' support to analyze kvm vmexit/mmio/ioport smartly

Usage:
perf kvm-events record

Why not 'perf record -e kvm'?

It works, many perf tools have this style, like:
perf lock record,
perf sched record,
perf kmem record,

I think the reason is that only enable the tracepoints we need to avoid unnecessary overload so that the result is more exacter.

Quoted 5 lines
Quoted 2 lines

perf kvm-events report

Quoted 17 lines
Quoted 4 lines
tools/perf/builtin-kvm-events.c new file +4 -0
+static const char *get_exit_reason(long isa, u64 exit_code)
+{
+	int table_size = ARRAY_SIZE(svm_exit_reasons);
+	struct exit_reasons_table *table = svm_exit_reasons;

tools/perf/builtin-kvm-events.c line 266

Quoted 10 lines
tools/perf/builtin-kvm-events.c new file +10 -0
+
+
+	if (isa == 1) {
+		table = vmx_exit_reasons;
+		table_size = ARRAY_SIZE(vmx_exit_reasons);
+	}
+
+	while (table_size--) {
+		if (table->exit_code == exit_code)
+			return table->reason;

... table[exit_code] ...

Actually, this array is not indexed by exit_code, it means:
table[exit_code].exit_code != exit_code.

Quoted 8 lines

tools/perf/builtin-kvm-events.c line 271

Quoted 5 lines
tools/perf/builtin-kvm-events.c new file +5 -0
+		table++;
+	}
+
+	die("unkonw kvm exit code:%ld on %s\n", exit_code, isa == 1 ?
+						"VMX" : "SVM");

"unknown"

......

Quoted 6 lines

tools/perf/builtin-kvm-events.c line 280

Quoted 3 lines
tools/perf/builtin-kvm-events.c new file +3 -0
+
+struct kvm_events_ops {
+	bool (*is_begain_event)(struct event *event, void *data);

begin

Sorry for my careless.

Quoted 8 lines
Quoted 8 lines
tools/perf/builtin-kvm-events.c new file +8 -0
+	bool (*is_end_event)(struct event *event);
+	struct event_key (*get_key)(struct event *event, void *data);
+	void (*decode_key)(struct event_key *key, char decode[20]);
+	const char *name;
+};
+
+
+static struct event_key exit_event_get_key(struct event *event, void *data)
Quoted 9 lines

tools/perf/builtin-kvm-events.c line 302

Quoted 5 lines
tools/perf/builtin-kvm-events.c new file +5 -0
+{
+	struct event_key key;
+
+	key.key = raw_field_value(event, "exit_reason", data);
+	key.info = raw_field_value(event, "isa", data);

"isa" is not available on all kernel versions; need to fall back to /proc/cpuid detection.

Got it, will do it in the next version. Thanks Avi!

#15 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

Quoted 11 lines · Xiao Guangrong
Quoted 7 lines · Avi Kivity
Quoted 4 lines · Xiao Guangrong

Add 'perf kvm-events' support to analyze kvm vmexit/mmio/ioport smartly

Usage:
perf kvm-events record

Why not 'perf record -e kvm'?

Quoted 7 lines

It works, many perf tools have this style, like:
perf lock record,
perf sched record,
perf kmem record,

I think the reason is that only enable the tracepoints we need to avoid unnecessary overload so that the result is more exacter.

Maybe a virtual event list:

perf record -e kvm-pio

This allows us to combine the event list with other events:

perf record -e kvm-pio -e timer

Quoted 11 lines
Quoted 7 lines

tools/perf/builtin-kvm-events.c line 266

Quoted 4 lines
tools/perf/builtin-kvm-events.c new file +4 -0
+
+	while (table_size--) {
+		if (table->exit_code == exit_code)
+			return table->reason;

... table[exit_code] ...

Actually, this array is not indexed by exit_code, it means:
table[exit_code].exit_code != exit_code.

So make it indexed by exit code.

Signature · 1 line
error compiling committee.c: too many arguments to function
#16 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

In reply to Xiao Guangrong

tools/perf/Documentation/perf-kvm-events.txt line 16

Quoted 4 lines · Xiao Guangrong
tools/perf/Documentation/perf-kvm-events.txt new file +4 -0
+DESCRIPTION
+-----------
+You can analyze some crucial events and statistics with this
+'perf kvm-events' command.

This line is very general and does not explain which events/statistics can be collected or how you can use that information. I suggest making this description more specific. Explain that this subcommand observers kvm.ko tracepoints and annotates/decodes them with additional information (this is why I would use this command and not raw perf record -e kvm:\*).

Quoted 4 lines

+       { SVM_EXIT_MONITOR,                     "monitor" }, \
+       { SVM_EXIT_MWAIT,                       "mwait" }, \
+       { SVM_EXIT_XSETBV,                      "xsetbv" }, \
+       { SVM_EXIT_NPF,                         "npf" }

All this copy-paste could be avoided by sharing this stuff with the arch/x86/kvm/ code.

tools/perf/builtin-kvm-events.c line 311

Quoted 6 lines
tools/perf/builtin-kvm-events.c new file +6 -0
+static void exit_event_decode_key(struct event_key *key, char decode[20])
+{
+       const char *exit_reason = get_exit_reason(key->info, key->key);
+
+       memset(decode, 0, 20);
+       strncpy(decode, exit_reason, 20);

This is a bad pattern to follow when using strncpy(3) because if there was a strlen(exit_reason) == 20 string then decode[] would not be NUL-terminated. Right now it's safe but it's better to just use strlcpy() and drop the memset(3).

Quoted 35 lines
tools/perf/builtin-kvm-events.c new file +35 -0
+}
+
+static struct kvm_events_ops exit_events = {
+       .is_begain_event = exit_event_begain,
+       .is_end_event = exit_event_end,
+       .get_key = exit_event_get_key,
+       .decode_key = exit_event_decode_key,
+       .name = "VM-EXIT"
+};
+
+#define KVM_TRACE_MMIO_READ_UNSATISFIED 0
+#define KVM_TRACE_MMIO_READ 1
+#define KVM_TRACE_MMIO_WRITE 2
+static bool mmio_event_begain(struct event *event, void *data)
+{
+       if (!strcmp(event->name, "kvm_mmio")) {
+               long type = raw_field_value(event, "type", data);
+
+               if (type != KVM_TRACE_MMIO_READ_UNSATISFIED)
+                       return true;
+       };
+
+       return false;
+}
+
+static bool mmio_event_end(struct event *event)
+{
+       return !strcmp(event->name, "kvm_mmio_done");
+}
+
+static struct event_key mmio_event_get_key(struct event *event, void *data)
+{
+       struct event_key key;
+
+       key.key = raw_field_value(event, "gpa", data);

tools/perf/builtin-kvm-events.c line 356

Quoted 10 lines
tools/perf/builtin-kvm-events.c new file +10 -0
+       key.info = raw_field_value(event, "type", data);
+
+       return key;
+}
+
+static void mmio_event_decode_key(struct event_key *key, char decode[20])
+{
+       memset(decode, 0, 20);
+       sprintf(decode, "%#lx:%s", key->key,
+               key->info == KVM_TRACE_MMIO_READ ? "R" : "W");

Please drop the memset and use snprintf(3) instead of sprintf(3). It places the NUL-terminator and ensures you don't exceed the buffer size.

Same pattern below.

#17 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

Quoted 14 lines · Stefan Hajnoczi

tools/perf/Documentation/perf-kvm-events.txt line 16

Quoted 4 lines · Xiao Guangrong
tools/perf/Documentation/perf-kvm-events.txt new file +4 -0
+DESCRIPTION
+-----------
+You can analyze some crucial events and statistics with this
+'perf kvm-events' command.

This line is very general and does not explain which events/statistics can be collected or how you can use that information. I suggest making this description more specific. Explain that this subcommand observers kvm.ko tracepoints and annotates/decodes them with additional information (this is why I would use this command and not raw perf record -e kvm:\*).

Okay.

Quoted 8 lines
Quoted 4 lines

+ � � � { SVM_EXIT_MONITOR, � � � � � � � � � � "monitor" }, \
+ � � � { SVM_EXIT_MWAIT, � � � � � � � � � � � "mwait" }, \
+ � � � { SVM_EXIT_XSETBV, � � � � � � � � � � �"xsetbv" }, \
+ � � � { SVM_EXIT_NPF, � � � � � � � � � � � � "npf" }

All this copy-paste could be avoided by sharing this stuff with the arch/x86/kvm/ code.

I will try to combine them in the next version.

Quoted 12 lines

tools/perf/builtin-kvm-events.c

Quoted 6 lines
tools/perf/builtin-kvm-events.c new file +6 -0
+static void exit_event_decode_key(struct event_key *key, char decode[20])
+{
+ � � � const char *exit_reason = get_exit_reason(key->info, key->key);
+
+ � � � memset(decode, 0, 20);
+ � � � strncpy(decode, exit_reason, 20);

This is a bad pattern to follow when using strncpy(3) because if there was a strlen(exit_reason) == 20 string then decode[] would not be NUL-terminated. Right now it's safe but it's better to just use strlcpy() and drop the memset(3).

Good point.

Quoted 10 lines

Review

Quoted 5 lines
(quoted diff) +5 -0
+static void mmio_event_decode_key(struct event_key *key, char decode[20])
+{
+ � � � memset(decode, 0, 20);
+ � � � sprintf(decode, "%#lx:%s", key->key,
+ � � � � � � � key->info == KVM_TRACE_MMIO_READ ? "R" : "W");

Please drop the memset and use snprintf(3) instead of sprintf(3). It places the NUL-terminator and ensures you don't exceed the buffer size.

Quoted 2 lines

Same pattern below.

Will do, thanks Stefan! :)

#18 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

In reply to Stefan Hajnoczi
Quoted 14 lines · Stefan Hajnoczi

tools/perf/Documentation/perf-kvm-events.txt line 16

Quoted 4 lines · Xiao Guangrong
tools/perf/Documentation/perf-kvm-events.txt new file +4 -0
+DESCRIPTION
+-----------
+You can analyze some crucial events and statistics with this
+'perf kvm-events' command.

This line is very general and does not explain which events/statistics can be collected or how you can use that information. I suggest making this description more specific. Explain that this subcommand observers kvm.ko tracepoints and annotates/decodes them with additional information (this is why I would use this command and not raw perf record -e kvm:\*).

Quoted 7 lines
Quoted 4 lines

+       { SVM_EXIT_MONITOR,                     "monitor" }, \
+       { SVM_EXIT_MWAIT,                       "mwait" }, \
+       { SVM_EXIT_XSETBV,                      "xsetbv" }, \
+       { SVM_EXIT_NPF,                         "npf" }

All this copy-paste could be avoided by sharing this stuff with the arch/x86/kvm/ code.

Yes, same for KVM_MAX_VCPUS.

#19 lore raw

Re: [PATCH 3/3] KVM: perf: kvm events analysis tool

Quoted 7 lines · Marcelo Tosatti
Quoted 3 lines

All this copy-paste could be avoided by sharing this stuff with the arch/x86/kvm/ code.

Yes, same for KVM_MAX_VCPUS.

This is an internal define. perf kvm should work with different kernel versions, so it needs to query the value dynamically.

Signature · 1 line
error compiling committee.c: too many arguments to function
#20 lore raw
In reply to Xiao Guangrong
Quoted 31 lines · Xiao Guangrong

This tool is very like xenoprof(if i remember correctly), and traces kvm events smartly. currently, it supports vmexit/mmio/ioport events.

Usage:
- to trace kvm events:

# ./perf kvm-events record

- show the result

# ./perf kvm-events report

Some output are as follow:

# ./perf kvm-events report
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

APIC_ACCESS 438107 44.89% 6.20% 17.91us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
                 HLT      15424         1.58%        82.12%      6735.06us
           CR_ACCESS       4089         0.42%         0.02%         6.08us
Quoted 1 line

Total Samples:975981, Total events handled time:126502464.88us.

Nice! If we can have a live version as well, this can replace kvm_stat.

The average numbers are really high. Like a factor of 3x-4x off. Would be good to print the standard deviation and see why. Maybe it's due to the tracing overhead.

Quoted 8 lines

The default event to be analysed is vmexit, we can use --event to specify it, for example, if we want to trace mmio event:

# ./perf kvm-events report --event mmio
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'
Quoted 8 lines

Analyze events for all VCPUs:

         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W     196589        64.95%        70.01%         3.83us
        0xfee00310:W      35356        11.68%         6.48%         1.97us
        0xfee00300:W      35356        11.68%        16.37%         4.97us
        0xfee00300:R      35356        11.68%         7.14%         2.17us

These are more reasonable (though still high - 5us for an ICR write?)

Quoted 43 lines

Total Samples:302657, Total events handled time:1074746.01us.

We can use --vcpu to specify which vcpu is traced:
root@localhost perf]# ./perf kvm-events report --event mmio --vcpu 1
Warning: Error: expected type 5 but read 4
Warning: Error: expected type 5 but read 0
Warning: unknown op '}'

Analyze events for VCPU 1:

         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W      58041        71.20%        74.90%         3.70us
        0xfee00310:W       7826         9.60%         5.28%         1.93us
        0xfee00300:W       7826         9.60%        13.82%         5.06us
        0xfee00300:R       7826         9.60%         6.01%         2.20us

Total Samples:81519, Total events handled time:286577.81us.

And, '--key' is used to sort the result, the possible value sample (default, the result is sorted by samples number), time(the result is sorted by time%):

# ./perf kvm-events report --key time
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

HLT 15424 1.58% 82.12% 6735.06us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
         APIC_ACCESS     438107        44.89%         6.20%        17.91us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
           CR_ACCESS       4089         0.42%         0.02%         6.08us
Quoted 3 lines

Total Samples:975981, Total events handled time:126502464.88us.

I hope guys will like it and any comments are welcome! :)

I think it's great! A live version would be a nice addition too.

Please copy the perf userspace maintainers to get more detailed review in the next version.

Signature · 1 line
error compiling committee.c: too many arguments to function
#21 lore raw
Quoted 8 lines · Avi Kivity
Quoted 1 line

Total Samples:975981, Total events handled time:126502464.88us.

Nice! If we can have a live version as well, this can replace kvm_stat.

The average numbers are really high. Like a factor of 3x-4x off. Would be good to print the standard deviation and see why. Maybe it's due to the tracing overhead.

It is a good suggestion, i will print stddev in the next version.

Quoted 10 lines
Quoted 10 lines

The default event to be analysed is vmexit, we can use --event to specify it, for example, if we want to trace mmio event:

# ./perf kvm-events report --event mmio
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

Quoted 9 lines
Quoted 6 lines
         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W     196589        64.95%        70.01%         3.83us
        0xfee00310:W      35356        11.68%         6.48%         1.97us
        0xfee00300:W      35356        11.68%        16.37%         4.97us
        0xfee00300:R      35356        11.68%         7.14%         2.17us

These are more reasonable (though still high - 5us for an ICR write?)

Hmm, maybe i need look into it...

Quoted 9 lines
Quoted 3 lines

Total Samples:975981, Total events handled time:126502464.88us.

I hope guys will like it and any comments are welcome! :)

I think it's great! A live version would be a nice addition too.

Please copy the perf userspace maintainers to get more detailed review in the next version.

Okay, Thanks!

#22 lore raw
In reply to Xiao Guangrong
Quoted 7 lines · Xiao Guangrong

This tool is very like xenoprof(if i remember correctly), and traces kvm events smartly. currently, it supports vmexit/mmio/ioport events.

Usage:
- to trace kvm events:

# ./perf kvm-events record
Quoted 8 lines

- show the result

# ./perf kvm-events report

Some output are as follow:

# ./perf kvm-events report
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Integrating the trace-cmd plugins into perf will remedy the above errors:
https://lkml.org/lkml/2011/8/16/352

Unfortunately, that effort is stalled at the moment.

Quoted 16 lines

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

APIC_ACCESS 438107 44.89% 6.20% 17.91us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
                 HLT      15424         1.58%        82.12%      6735.06us
           CR_ACCESS       4089         0.42%         0.02%         6.08us
Quoted 1 line

Total Samples:975981, Total events handled time:126502464.88us.

Have you thought about dumping a time history -- something similar to what perf-script can do with dumping events but adding in kvm-specific analysis like what you are doing in these examples?

David

Quoted 69 lines

The default event to be analysed is vmexit, we can use --event to specify it, for example, if we want to trace mmio event:

# ./perf kvm-events report --event mmio
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W     196589        64.95%        70.01%         3.83us
        0xfee00310:W      35356        11.68%         6.48%         1.97us
        0xfee00300:W      35356        11.68%        16.37%         4.97us
        0xfee00300:R      35356        11.68%         7.14%         2.17us

Total Samples:302657, Total events handled time:1074746.01us.

We can use --vcpu to specify which vcpu is traced:
root@localhost perf]# ./perf kvm-events report --event mmio --vcpu 1
Warning: Error: expected type 5 but read 4
Warning: Error: expected type 5 but read 0
Warning: unknown op '}'

Analyze events for VCPU 1:

         MMIO Access    Samples      Samples%         Time%        Avg time

        0xfee00380:W      58041        71.20%        74.90%         3.70us
        0xfee00310:W       7826         9.60%         5.28%         1.93us
        0xfee00300:W       7826         9.60%        13.82%         5.06us
        0xfee00300:R       7826         9.60%         6.01%         2.20us

Total Samples:81519, Total events handled time:286577.81us.

And, '--key' is used to sort the result, the possible value sample (default, the result is sorted by samples number), time(the result is sorted by time%):

# ./perf kvm-events report --key time
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

HLT 15424 1.58% 82.12% 6735.06us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
         APIC_ACCESS     438107        44.89%         6.20%        17.91us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
           CR_ACCESS       4089         0.42%         0.02%         6.08us

Total Samples:975981, Total events handled time:126502464.88us.

I hope guys will like it and any comments are welcome! :)

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to [email protected]
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

#23 lore raw
Quoted 13 lines · David Ahern
Quoted 10 lines · Xiao Guangrong

This tool is very like xenoprof(if i remember correctly), and traces kvm events smartly. currently, it supports vmexit/mmio/ioport events.

Usage:
- to trace kvm events:

# ./perf kvm-events record

- show the result

# ./perf kvm-events report
Quoted 9 lines
Quoted 5 lines

Some output are as follow:

# ./perf kvm-events report
  Warning: Error: expected type 5 but read 4
  Warning: Error: expected type 5 but read 0
  Warning: unknown op '}'

Integrating the trace-cmd plugins into perf will remedy the above errors:
https://lkml.org/lkml/2011/8/16/352

Yes, it is great!

Quoted 18 lines

Unfortunately, that effort is stalled at the moment.

Quoted 16 lines

Analyze events for all VCPUs:

VM-EXIT Samples Samples% Time% Avg time

APIC_ACCESS 438107 44.89% 6.20% 17.91us

  EXTERNAL_INTERRUPT     219226        22.46%         8.01%        46.20us
      IO_INSTRUCTION     122651        12.57%         1.88%        19.44us
       EPT_VIOLATION      83110         8.52%         1.36%        20.75us
   PENDING_INTERRUPT      37055         3.80%         0.16%         5.38us
               CPUID      32718         3.35%         0.08%         3.15us
       EXCEPTION_NMI      23601         2.42%         0.17%         8.87us
                 HLT      15424         1.58%        82.12%      6735.06us
           CR_ACCESS       4089         0.42%         0.02%         6.08us
Quoted 6 lines
Quoted 1 line

Total Samples:975981, Total events handled time:126502464.88us.

Have you thought about dumping a time history -- something similar to what perf-script can do with dumping events but adding in kvm-specific analysis like what you are doing in these examples?

I will look into it and put it to my todo list if it is possible. Thanks, David!

#24 lore raw
Quoted 9 lines · Xiao Guangrong
Quoted 4 lines

Have you thought about dumping a time history -- something similar to what perf-script can do with dumping events but adding in kvm-specific analysis like what you are doing in these examples?

I will look into it and put it to my todo list if it is possible. Thanks, David!

I've played around with ways to do it as time (and motivation) allowed. Attached is one example using perf with the trace-cmd plugin plus a patch on perf-script to dump time between events:

perf record -e kvm:* -fo /tmp/perf.data -p 2540 -- sleep 1 perf script -i /tmp/perf.data

The output of perf-script is in the attached file. The 5th column is the dt between successive events which is mainly a convenience.

A perf-kvm-events type command would allow more customization in the output -- like correlating specific events and computing total time between exit and entry accounting for HLT reasons -- as well as various statistical dumps (average, stddev, max/min, histograms).

David

qemu-kvm  2542 [001] 20757.662426  0.000001 kvm_cr: cr_write 3 = 0x6f3000
qemu-kvm  2542 [001] 20757.662430  0.000004 kvm_entry: vcpu 0
qemu-kvm  2542 [001] 20757.662432  0.000002 kvm_exit: reason IO_INSTRUCTION rip 0x806d8dbc info b008000b 0
qemu-kvm  2542 [001] 20757.662434  0.000002 kvm_emulate_insn: 0:806d8dbc: ed
qemu-kvm  2542 [001] 20757.662435  0.000001 kvm_pio: pio_read at 0xb008 size 4 count 1
qemu-kvm  2542 [001] 20757.662436  0.000001 kvm_userspace_exit: reason KVM_EXIT_IO (2)
qemu-kvm  2542 [001] 20757.662442  0.000006 kvm_entry: vcpu 0
qemu-kvm  2542 [001] 20757.662444  0.000002 kvm_exit: reason HLT rip 0xf770fd3d info 0 0
qemu-kvm  2540 [000] 20757.666479  0.004287 kvm_set_irq: gsi 9 level 1 source 0
qemu-kvm  2540 [000] 20757.666481  0.000002 kvm_pic_set_irq: chip 1 pin 1 (edge|masked)
qemu-kvm  2540 [000] 20757.666482  0.000001 kvm_apic_accept_irq: apicid 0 vec 177 (LowPrio|level)
qemu-kvm  2540 [000] 20757.666485  0.000003 kvm_ioapic_set_irq: pin 9 dst 1 vec=177 (LowPrio|logical|level)
qemu-kvm  2542 [001] 20757.666505  0.004061 kvm_inj_virq: irq 177
qemu-kvm  2542 [001] 20757.666506  0.000001 kvm_entry: vcpu 0
qemu-kvm  2542 [001] 20757.666512  0.000006 kvm_exit: reason IO_INSTRUCTION rip 0x806d88ca info b0000009 0
qemu-kvm  2542 [001] 20757.666516  0.000004 kvm_emulate_insn: 0:806d88ca: 66 ed
qemu-kvm  2542 [001] 20757.666517  0.000001 kvm_pio: pio_read at 0xb000 size 2 count 1
qemu-kvm  2542 [001] 20757.666519  0.000002 kvm_userspace_exit: reason KVM_EXIT_IO (2)
qemu-kvm  2542 [001] 20757.666528  0.000009 kvm_entry: vcpu 0
qemu-kvm  2542 [001] 20757.666531  0.000003 kvm_exit: reason IO_INSTRUCTION rip 0x806d88be info afe00008 0
qemu-kvm  2542 [001] 20757.666534  0.000003 kvm_emulate_insn: 0:806d88be: ec
qemu-kvm  2542 [001] 20757.666535  0.000001 kvm_pio: pio_read at 0xafe0 size 1 count 1
qemu-kvm  2542 [001] 20757.666537  0.000002 kvm_userspace_exit: reason KVM_EXIT_IO (2)
qemu-kvm  2542 [001] 20757.666544  0.000007 kvm_entry: vcpu 0
qemu-kvm  2542 [001] 20757.666547  0.000003 kvm_exit: reason IO_INSTRUCTION rip 0x806d88be info afe10008 0
qemu-kvm  2542 [001] 20757.666550  0.000003 kvm_emulate_insn: 0:806d88be: ec
qemu-kvm  2542 [001] 20757.666551  0.000001 kvm_pio: pio_read at 0xafe1 size 1 count 1
qemu-kvm  2542 [001] 20757.666552  0.000001 kvm_userspace_exit: reason KVM_EXIT_IO (2)
qemu-kvm  2542 [001] 20757.666558  0.000006 kvm_entry: vcpu 0
qemu-kvm  2542 [001] 20757.666562  0.000004 kvm_exit: reason IO_INSTRUCTION rip 0x806d8934 info b0000001 0