From 9e917057e9882258d64f1e0e72a61ea72bae2666 Mon Sep 17 00:00:00 2001 From: Min Lim Date: Wed, 12 Dec 2018 15:12:42 -0800 Subject: [PATCH] profiling: split profiling_vmexit_handler into two functions 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 Acked-by: Eddie Dong --- hypervisor/common/hv_main.c | 4 +++- hypervisor/debug/profiling.c | 23 +++++++++++++++++++---- hypervisor/include/debug/profiling.h | 3 ++- hypervisor/release/profiling.c | 3 ++- 4 files changed, 26 insertions(+), 7 deletions(-) diff --git a/hypervisor/common/hv_main.c b/hypervisor/common/hv_main.c index 33a51b0c2..96f1d596e 100644 --- a/hypervisor/common/hv_main.c +++ b/hypervisor/common/hv_main.c @@ -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); @@ -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); } diff --git a/hypervisor/debug/profiling.c b/hypervisor/debug/profiling.c index 9c1490417..7d36897ba 100644 --- a/hypervisor/debug/profiling.c +++ b/hypervisor/debug/profiling.c @@ -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); @@ -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 & @@ -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) { diff --git a/hypervisor/include/debug/profiling.h b/hypervisor/include/debug/profiling.h index 052c11625..4223f4065 100644 --- a/hypervisor/include/debug/profiling.h +++ b/hypervisor/include/debug/profiling.h @@ -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 */ diff --git a/hypervisor/release/profiling.c b/hypervisor/release/profiling.c index 1f5a9b991..21342d3a7 100644 --- a/hypervisor/release/profiling.c +++ b/hypervisor/release/profiling.c @@ -7,5 +7,6 @@ #include 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) {}