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 <min.yeol.lim@intel.com>
Acked-by: Eddie Dong <eddie.dong@intel.com>
This commit is contained in:
Min Lim 2018-12-12 15:12:42 -08:00 committed by wenlingz
parent 302494cb80
commit 9e917057e9
4 changed files with 26 additions and 7 deletions

View File

@ -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);
}

View File

@ -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) {

View File

@ -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 */

View File

@ -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) {}