Re: [PATCH] KVM: nVMX: nSVM: Show guest mode in kvm_{entry,exit} tracepoints

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Mon, Jun 21, 2021, Krish Sadhukhan wrote:
> From debugging point of view, KVM entry and exit tracepoints are important
> in that they indicate when a guest starts and exits. When L1 runs L2, there
> is no way we can determine from KVM tracing when L1 starts/exits and when
> L2 starts/exits as there is no marker in place today in those tracepoints.
> Debugging becomes even more difficult when more than one L2 run in an L1 and
> there is no way of determining which L2 from which L1 made the entries/exits.
> Therefore, showing guest mode in the entry and exit tracepoints
> will make debugging much easier.

> If an L1 runs multiple L2s, though we can not identify the specific L2 from
> the entry and exit tracepoints, we still will be able to determine whether it
> was L1 or an L2 that made the entries and the exits.

Hmm, this is a solvable problem, and might even be worth solving immediately,
e.g. kvm_x86_ops.get_vmcx12 to retrieve the L1 GPA of the vmcs12/vmcb12.
More below.

> With this patch KVM entry and exit tracepoints will show "guest_mode = 0" if
> it is a guest and "guest_mode = 1" if it is a nested guest.

Uber pedantry, but technically not true, as trace_kvm_entry() doesn't have the
'=', and in the exit tracepoint, the '=' should be dropped to be consistent with
the existing format.  Might be a moot point though.

> Signed-off-by: Krish Sdhukhan <krish.sadhukhan@xxxxxxxxxx>
> ---
>  arch/x86/kvm/trace.h | 16 +++++++++++-----
>  1 file changed, 11 insertions(+), 5 deletions(-)
> 
> diff --git a/arch/x86/kvm/trace.h b/arch/x86/kvm/trace.h
> index b484141ea15b..44dba26c6be2 100644
> --- a/arch/x86/kvm/trace.h
> +++ b/arch/x86/kvm/trace.h
> @@ -21,14 +21,17 @@ TRACE_EVENT(kvm_entry,
>  	TP_STRUCT__entry(
>  		__field(	unsigned int,	vcpu_id		)
>  		__field(	unsigned long,	rip		)
> +		__field(        bool,           guest_mode      )
>  	),
>  
>  	TP_fast_assign(
>  		__entry->vcpu_id        = vcpu->vcpu_id;
>  		__entry->rip		= kvm_rip_read(vcpu);
> +		__entry->guest_mode     = is_guest_mode(vcpu);
>  	),
>  
> -	TP_printk("vcpu %u, rip 0x%lx", __entry->vcpu_id, __entry->rip)
> +	TP_printk("vcpu %u, rip 0x%lx, guest_mode %d", __entry->vcpu_id,
> +		  __entry->rip, __entry->guest_mode)
>  );
>  
>  /*
> @@ -285,6 +288,7 @@ TRACE_EVENT(name,							     \
>  		__field(	u32,	        intr_info	)	     \
>  		__field(	u32,	        error_code	)	     \
>  		__field(	unsigned int,	vcpu_id         )	     \
> +		__field(        bool,           guest_mode      )            \
>  	),								     \
>  									     \
>  	TP_fast_assign(							     \
> @@ -295,15 +299,17 @@ TRACE_EVENT(name,							     \
>  		static_call(kvm_x86_get_exit_info)(vcpu, &__entry->info1,    \
>  					  &__entry->info2,		     \
>  					  &__entry->intr_info,		     \
> -					  &__entry->error_code);	     \
> +					  &__entry->error_code);     	     \
> +		__entry->guest_mode      = is_guest_mode(vcpu);		     \
>  	),								     \
>  									     \
>  	TP_printk("vcpu %u reason %s%s%s rip 0x%lx info1 0x%016llx "	     \
> -		  "info2 0x%016llx intr_info 0x%08x error_code 0x%08x",	     \
> -		  __entry->vcpu_id,					     \
> +		  "info2 0x%016llx intr_info 0x%08x error_code 0x%08x "	     \
> +		  "guest_mode = %d", __entry->vcpu_id,          	     \

I'm biased because I've never really liked is_guest_mode(), but I think guest_mode
will be confusing to users.  KVM developers are familiar with guest_mode() == L2,
but random debuggers/users are unlikely to make that connection.

A clever/heinous way to "solve" this issue and display vmcx12 iff L2 is active
would be to bastardize the L1/L2 strings and vmcx12 value formatting to yield:

  vcpu 0 reason <reason> guest L1 rip 0xfffff ...

and

  vcpu 0 reason <reason> guest L2 vmcx12 0xaaaaa rip 0xfffff ...

 
#define TRACE_EVENT_KVM_EXIT(name)					     \
TRACE_EVENT(name,							     \
	TP_PROTO(unsigned int exit_reason, struct kvm_vcpu *vcpu, u32 isa),  \
	TP_ARGS(exit_reason, vcpu, isa),				     \
									     \
	TP_STRUCT__entry(						     \
		__field(	unsigned int,	exit_reason	)	     \
		__field(	unsigned long,	guest_rip	)	     \
		__field(	u32,	        isa             )	     \
		__field(	u64,	        info1           )	     \
		__field(	u64,	        info2           )	     \
		__field(	u32,	        intr_info	)	     \
		__field(	u32,	        error_code	)	     \
		__field(	unsigned int,	vcpu_id         )	     \
		__field(	u64,	        vmcx12          )	     \
	),								     \
									     \
	TP_fast_assign(							     \
		__entry->exit_reason	= exit_reason;			     \
		__entry->guest_rip	= kvm_rip_read(vcpu);		     \
		__entry->isa            = isa;				     \
		__entry->vcpu_id        = vcpu->vcpu_id;		     \
		static_call(kvm_x86_get_exit_info)(vcpu, &__entry->info1,    \
					  &__entry->info2,		     \
					  &__entry->intr_info,		     \
					  &__entry->error_code);	     \
		__entry->vmcx12		= is_guest_mode(vcpu) ?		     \
					  static_call(kvm_x86_get_vmcx12) :  \
					  INVALID_PAGE;			     \
	),								     \
									     \
	TP_printk("vcpu %u reason %s%s%s guest %s%llx rip 0x%lx "	     \
		  "info1 0x%016llx info2 0x%016llx "			     \
		  "intr_info 0x%08x error_code 0x%08x",			     \
		  __entry->vcpu_id,					     \
		  kvm_print_exit_reason(__entry->exit_reason, __entry->isa), \
		  __entry->vmcx12 == INVALID_PAGE ? "L" : "L2 vmcx12 0x",    \
		  __entry->vmcx12 == INVALID_PAGE ? 1 : __entry->vmcx12,     \
		  __entry->guest_rip, __entry->info1, __entry->info2,	     \
		  __entry->intr_info, __entry->error_code)		     \
)



[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux