From a7cbee180226eff07ac4c6eb91a6399089929c7a Mon Sep 17 00:00:00 2001 From: "Chinthapally, Manisha" Date: Mon, 22 Oct 2018 16:17:14 -0700 Subject: [PATCH] HV:Added support to get VM enter and exit information profiling_vmenter_handler:Saves vm information profiling_vmexit_handler: Saves vm information and vm exit reason Tracked-On: projectacrn#1409 Acked-by: Eddie Dong Signed-off-by: Chinthapally, Manisha --- hypervisor/debug/profiling.c | 65 +++++++++++++++++-- hypervisor/include/debug/profiling_internal.h | 21 ++++++ 2 files changed, 80 insertions(+), 6 deletions(-) diff --git a/hypervisor/debug/profiling.c b/hypervisor/debug/profiling.c index 33b82d308..d60243711 100644 --- a/hypervisor/debug/profiling.c +++ b/hypervisor/debug/profiling.c @@ -914,18 +914,71 @@ void profiling_ipi_handler(__unused void *data) */ void profiling_vmenter_handler(__unused struct vcpu *vcpu) { - /* to be implemented */ + if (((get_cpu_var(profiling_info.sep_state).pmu_state == PMU_RUNNING) && + ((sep_collection_switch & + (1UL << (uint64_t)VM_SWITCH_TRACING)) > 0UL)) || + ((get_cpu_var(profiling_info.soc_state) == SW_RUNNING) && + ((socwatch_collection_switch & + (1UL << (uint64_t)SOCWATCH_VM_SWITCH_TRACING)) > 0UL))) { + + get_cpu_var(profiling_info.vm_info).vmenter_tsc = rdtsc(); + } } /* * Save the VCPU info on vmexit */ -void profiling_vmexit_handler(__unused struct vcpu *vcpu, __unused uint64_t exit_reason) +void profiling_vmexit_handler(struct vcpu *vcpu, uint64_t exit_reason) { - if (exit_reason == VMX_EXIT_REASON_EXTERNAL_INTERRUPT) { - /* to be implemented */ - } else { - /* to be implemented */ + 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)) { + + get_cpu_var(profiling_info.vm_info).vmexit_tsc = rdtsc(); + 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); + } else { + get_cpu_var(profiling_info.vm_info).external_vector = -1; + } + get_cpu_var(profiling_info.vm_info).guest_rip + = vcpu_get_rip(vcpu); + + get_cpu_var(profiling_info.vm_info).guest_rflags + = vcpu_get_rflags(vcpu); + + get_cpu_var(profiling_info.vm_info).guest_cs + = exec_vmread64(VMX_GUEST_CS_SEL); + + get_cpu_var(profiling_info.vm_info).guest_vm_id = (int32_t)vcpu->vm->vm_id; + + /* Generate vmswitch sample */ + if (((sep_collection_switch & + (1UL << (uint64_t)VM_SWITCH_TRACING)) > 0UL) || + ((socwatch_collection_switch & + (1UL << (uint64_t)SOCWATCH_VM_SWITCH_TRACING)) > 0UL)) { + get_cpu_var(profiling_info.vm_switch_trace).os_id + = (int32_t)vcpu->vm->vm_id; + get_cpu_var(profiling_info.vm_switch_trace).vm_enter_tsc + = get_cpu_var(profiling_info.vm_info).vmenter_tsc; + 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; + + if ((sep_collection_switch & + (1UL << (uint64_t)VM_SWITCH_TRACING)) > 0UL) { + (void)profiling_generate_data(COLLECT_PROFILE_DATA, + VM_SWITCH_TRACING); + } + if ((socwatch_collection_switch & + (1UL << (uint64_t)SOCWATCH_VM_SWITCH_TRACING)) > 0UL) { + (void)profiling_generate_data(COLLECT_POWER_DATA, + SOCWATCH_VM_SWITCH_TRACING); + } + } } } diff --git a/hypervisor/include/debug/profiling_internal.h b/hypervisor/include/debug/profiling_internal.h index e62332570..56b591629 100644 --- a/hypervisor/include/debug/profiling_internal.h +++ b/hypervisor/include/debug/profiling_internal.h @@ -18,6 +18,7 @@ #define COLLECT_PROFILE_DATA 0 #define COLLECT_POWER_DATA 1 +#define SEP_BUF_ENTRY_SIZE 32U #define SOCWATCH_MSR_OP 100U enum MSR_CMD_STATUS { @@ -159,6 +160,16 @@ struct vmexit_msr { uint64_t msr_data; }; +struct guest_vm_info { + uint64_t vmenter_tsc; + uint64_t vmexit_tsc; + uint64_t vmexit_reason; + uint64_t guest_rip; + uint64_t guest_rflags; + uint64_t guest_cs; + int32_t guest_vm_id; + int32_t external_vector; +}; struct sep_state { sep_pmu_state pmu_state; @@ -201,13 +212,23 @@ struct sep_state { uint64_t saved_debugctl_value; } __aligned(8); + +struct vm_switch_trace { + uint64_t vm_enter_tsc; + uint64_t vm_exit_tsc; + uint64_t vm_exit_reason; + int32_t os_id; +}__aligned(SEP_BUF_ENTRY_SIZE); + /* * Wrapper containing SEP sampling/profiling related data structures */ struct profiling_info_wrapper { struct profiling_msr_ops_list *msr_node; struct sep_state sep_state; + struct guest_vm_info vm_info; ipi_commands ipi_cmd; + struct vm_switch_trace vm_switch_trace; socwatch_state soc_state; struct sw_msr_op_info sw_msr_op_info; } __aligned(8);