From 9f9750051d5a140e570dc8aec66e45db6b91756a Mon Sep 17 00:00:00 2001 From: Min Lim Date: Fri, 1 Feb 2019 12:11:36 -0800 Subject: [PATCH] profiling: enable to capture dropped samples while buffering Since the profiling utilizes the limited size of buffer to capture sample data, dropping samples could happen while collecting data if data is generated faster than flushing by consumer. Capturing the dropped sample info is critical to understand how much the data is reliable to use. To capture the information, the new hypercall "PROFILING_GET_STATUS" is introduced. Tracked-On: #2474 Signed-off-by: Manisha Chinthapally Signed-off-by: Min Lim Acked-by: Eddie Dong Signed-off-by: Min Lim --- hypervisor/debug/hypercall.c | 3 ++ hypervisor/debug/profiling.c | 43 +++++++++++++++---- hypervisor/include/debug/profiling_internal.h | 7 +++ hypervisor/include/public/acrn_hv_defs.h | 3 +- 4 files changed, 47 insertions(+), 9 deletions(-) diff --git a/hypervisor/debug/hypercall.c b/hypervisor/debug/hypercall.c index fbc055615..e098c9be0 100644 --- a/hypervisor/debug/hypercall.c +++ b/hypervisor/debug/hypercall.c @@ -51,6 +51,9 @@ static int32_t hcall_profiling_ops(struct acrn_vm *vm, uint64_t cmd, uint64_t pa case PROFILING_GET_PCPUID: ret = profiling_get_pcpu_id(vm, param); break; + case PROFILING_GET_STATUS: + ret = profiling_get_status_info(vm, param); + break; default: pr_err("%s: invalid profiling command %llu\n", __func__, cmd); ret = -1; diff --git a/hypervisor/debug/profiling.c b/hypervisor/debug/profiling.c index f9c6419b8..7e8604fd1 100644 --- a/hypervisor/debug/profiling.c +++ b/hypervisor/debug/profiling.c @@ -793,14 +793,6 @@ static void profiling_stop_pmu(void) __func__, i, per_cpu(profiling_info.sep_state, i).samples_logged, per_cpu(profiling_info.sep_state, i).samples_dropped); - per_cpu(profiling_info.sep_state, i).samples_logged = 0U; - per_cpu(profiling_info.sep_state, i).samples_dropped = 0U; - per_cpu(profiling_info.sep_state, i).valid_pmi_count = 0U; - per_cpu(profiling_info.sep_state, i).total_pmi_count = 0U; - per_cpu(profiling_info.sep_state, i).total_vmexit_count = 0U; - per_cpu(profiling_info.sep_state, i).frozen_well = 0U; - per_cpu(profiling_info.sep_state, i).frozen_delayed = 0U; - per_cpu(profiling_info.sep_state, i).nofrozen_pmi = 0U; } smp_call_function(pcpu_active_bitmap, profiling_ipi_handler, NULL); @@ -1269,6 +1261,36 @@ int32_t profiling_get_pcpu_id(struct acrn_vm *vm, uint64_t addr) return 0; } +/* + * Update collection statictics + */ +int32_t profiling_get_status_info(struct acrn_vm *vm, uint64_t gpa) +{ + uint16_t i; + struct profiling_status pstats[phys_cpu_num]; + + (void)memset((void *)&pstats, 0U, phys_cpu_num*sizeof(struct profiling_status)); + + dev_dbg(ACRN_DBG_PROFILING, "%s: entering", __func__); + + for (i = 0U; i < phys_cpu_num; i++) { + pstats[i].samples_logged = + per_cpu(profiling_info.sep_state, i).samples_logged; + pstats[i].samples_dropped = + per_cpu(profiling_info.sep_state, i).samples_dropped; + } + + if (copy_to_gpa(vm, &pstats, gpa, + phys_cpu_num*sizeof(struct profiling_status)) != 0) { + pr_err("%s: Unable to copy param to vm\n", __func__); + return -EINVAL; + } + + dev_dbg(ACRN_DBG_PROFILING, "%s: exiting", __func__); + + return 0; +} + /* * IPI interrupt handler function */ @@ -1412,6 +1434,11 @@ void profiling_setup(void) per_cpu(profiling_info.sep_state, cpu).total_vmexit_count = 0U; per_cpu(profiling_info.sep_state, cpu).pmu_state = PMU_INITIALIZED; per_cpu(profiling_info.sep_state, cpu).vmexit_msr_cnt = 0; + per_cpu(profiling_info.sep_state, cpu).samples_logged = 0U; + per_cpu(profiling_info.sep_state, cpu).samples_dropped = 0U; + per_cpu(profiling_info.sep_state, cpu).frozen_well = 0U; + per_cpu(profiling_info.sep_state, cpu).frozen_delayed = 0U; + per_cpu(profiling_info.sep_state, cpu).nofrozen_pmi = 0U; msr_write(MSR_IA32_EXT_APIC_LVT_PMI, VECTOR_PMI | LVT_PERFCTR_BIT_MASK); diff --git a/hypervisor/include/debug/profiling_internal.h b/hypervisor/include/debug/profiling_internal.h index 557ddca20..bc5e052d1 100644 --- a/hypervisor/include/debug/profiling_internal.h +++ b/hypervisor/include/debug/profiling_internal.h @@ -172,6 +172,12 @@ struct guest_vm_info { uint16_t guest_vm_id; int32_t external_vector; }; + +struct profiling_status { + uint32_t samples_logged; + uint32_t samples_dropped; +}; + struct sep_state { sep_pmu_state pmu_state; @@ -302,6 +308,7 @@ int32_t profiling_set_control(struct acrn_vm *vm, uint64_t addr); int32_t profiling_configure_pmi(struct acrn_vm *vm, uint64_t addr); int32_t profiling_configure_vmsw(struct acrn_vm *vm, uint64_t addr); void profiling_ipi_handler(void *data); +int32_t profiling_get_status_info(struct acrn_vm *vm, uint64_t addr); #endif diff --git a/hypervisor/include/public/acrn_hv_defs.h b/hypervisor/include/public/acrn_hv_defs.h index 3428e225b..7ed55dd61 100644 --- a/hypervisor/include/public/acrn_hv_defs.h +++ b/hypervisor/include/public/acrn_hv_defs.h @@ -331,7 +331,8 @@ enum profiling_cmd_type { PROFILING_SET_CONTROL_SWITCH, PROFILING_CONFIG_PMI, PROFILING_CONFIG_VMSWITCH, - PROFILING_GET_PCPUID + PROFILING_GET_PCPUID, + PROFILING_GET_STATUS }; #endif /* ACRN_HV_DEFS_H */