Skip to content

Commit

Permalink
profiling: split profiling_vmexit_handler into two functions
Browse files Browse the repository at this point in the history
This patch fixes incorrect vm_id captured when sampling PMU data. Currently,
the vm_id gets attributed to ACRN hypervisor, rather than actual guest vm_id.

The issue is identified that the existing code captures the guest vm info
after vmexit_hander function is completed, in which the profiling module
points its context to VMM. When the vmexit happens by PMI, the guest context
should be captured so that the attribution to proper guest vm can happen.

This change will also allow to capture more accurate TSC when vmexit happens.

Tracked-On: #2043
Signed-off-by: Min Lim <min.yeol.lim@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
  • Loading branch information
mlim19 authored and wenlingz committed Dec 14, 2018
1 parent 302494c commit 9e91705
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 7 deletions.
4 changes: 3 additions & 1 deletion hypervisor/common/hv_main.c
Expand Up @@ -70,6 +70,8 @@ void vcpu_thread(struct acrn_vcpu *vcpu)

vcpu->arch.nrexits++;

profiling_pre_vmexit_handler(vcpu);

CPU_IRQ_ENABLE();
/* Dispatch handler */
ret = vmexit_handler(vcpu);
Expand All @@ -83,6 +85,6 @@ void vcpu_thread(struct acrn_vcpu *vcpu)

TRACE_2L(TRACE_VM_EXIT, basic_exit_reason, vcpu_get_rip(vcpu));

profiling_vmexit_handler(vcpu, basic_exit_reason);
profiling_post_vmexit_handler(vcpu);
} while (1);
}
23 changes: 19 additions & 4 deletions hypervisor/debug/profiling.c
Expand Up @@ -1305,15 +1305,18 @@ void profiling_vmenter_handler(__unused struct acrn_vcpu *vcpu)
/*
* Save the VCPU info on vmexit
*/
void profiling_vmexit_handler(struct acrn_vcpu *vcpu, uint64_t exit_reason)
void profiling_pre_vmexit_handler(struct acrn_vcpu *vcpu)
{
per_cpu(profiling_info.sep_state, vcpu->pcpu_id).total_vmexit_count++;
uint64_t exit_reason = 0UL;

exit_reason = vcpu->arch.exit_reason & 0xFFFFUL;

if ((get_cpu_var(profiling_info.sep_state).pmu_state == PMU_RUNNING) ||
(get_cpu_var(profiling_info.soc_state) == SW_RUNNING)) {

get_cpu_var(profiling_info.vm_info).vmexit_tsc = rdtsc();
get_cpu_var(profiling_info.vm_info).vmexit_reason = exit_reason;
get_cpu_var(profiling_info.vm_info).vmexit_reason
= exit_reason;
if (exit_reason == VMX_EXIT_REASON_EXTERNAL_INTERRUPT) {
get_cpu_var(profiling_info.vm_info).external_vector
= (int32_t)(exec_vmread(VMX_EXIT_INT_INFO) & 0xFFUL);
Expand All @@ -1330,6 +1333,18 @@ void profiling_vmexit_handler(struct acrn_vcpu *vcpu, uint64_t exit_reason)
= exec_vmread64(VMX_GUEST_CS_SEL);

get_cpu_var(profiling_info.vm_info).guest_vm_id = (int32_t)vcpu->vm->vm_id;
}
}

/*
* Generate vmexit data
*/
void profiling_post_vmexit_handler(struct acrn_vcpu *vcpu)
{
per_cpu(profiling_info.sep_state, vcpu->pcpu_id).total_vmexit_count++;

if ((get_cpu_var(profiling_info.sep_state).pmu_state == PMU_RUNNING) ||
(get_cpu_var(profiling_info.soc_state) == SW_RUNNING)) {

/* Generate vmswitch sample */
if (((sep_collection_switch &
Expand All @@ -1343,7 +1358,7 @@ void profiling_vmexit_handler(struct acrn_vcpu *vcpu, uint64_t exit_reason)
get_cpu_var(profiling_info.vm_switch_trace).vm_exit_tsc
= get_cpu_var(profiling_info.vm_info).vmexit_tsc;
get_cpu_var(profiling_info.vm_switch_trace).vm_exit_reason
= exit_reason;
= get_cpu_var(profiling_info.vm_info).vmexit_reason;

if ((sep_collection_switch &
(1UL << (uint64_t)VM_SWITCH_TRACING)) > 0UL) {
Expand Down
3 changes: 2 additions & 1 deletion hypervisor/include/debug/profiling.h
Expand Up @@ -12,7 +12,8 @@
#endif

void profiling_vmenter_handler(struct acrn_vcpu *vcpu);
void profiling_vmexit_handler(struct acrn_vcpu *vcpu, uint64_t exit_reason);
void profiling_pre_vmexit_handler(struct acrn_vcpu *vcpu);
void profiling_post_vmexit_handler(struct acrn_vcpu *vcpu);
void profiling_setup(void);

#endif /* PROFILING_H */
3 changes: 2 additions & 1 deletion hypervisor/release/profiling.c
Expand Up @@ -7,5 +7,6 @@
#include <hypervisor.h>

void profiling_vmenter_handler(__unused struct acrn_vcpu *vcpu) {}
void profiling_vmexit_handler(__unused struct acrn_vcpu *vcpu, __unused uint64_t exit_reason) {}
void profiling_pre_vmexit_handler(__unused struct acrn_vcpu *vcpu) {}
void profiling_post_vmexit_handler(__unused struct acrn_vcpu *vcpu) {}
void profiling_setup(void) {}

0 comments on commit 9e91705

Please sign in to comment.