HV:Added support to get phy CPU, VM, tool information
This patch includes support to following 1. Collection of physical cpuid information 2. Collection of List of VM's available and information 3. Tool version information 4. Sending tool control information to guest Tracked-On: projectacrn#1409 Acked-by: Eddie Dong <eddie.dong@intel.com> Signed-off-by: Chinthapally, Manisha <manisha.chinthapally@intel.com>
This commit is contained in:
parent
8ba333d275
commit
df549096f2
|
@ -3,15 +3,19 @@
|
|||
*
|
||||
* SPDX-License-Identifier: BSD-3-Clause
|
||||
*/
|
||||
|
||||
#ifdef PROFILING_ON
|
||||
|
||||
#include <hypervisor.h>
|
||||
|
||||
#define ACRN_DBG_PROFILING 5U
|
||||
|
||||
#define MAJOR_VERSION 1
|
||||
#define MINOR_VERSION 0
|
||||
|
||||
#define LVT_PERFCTR_BIT_MASK 0x10000U
|
||||
|
||||
static uint64_t sep_collection_switch;
|
||||
|
||||
static uint32_t profiling_pmi_irq = IRQ_INVALID;
|
||||
|
||||
static void profiling_initialize_vmsw(void)
|
||||
|
@ -62,7 +66,8 @@ static void profiling_pmi_handler(__unused unsigned int irq, __unused void *data
|
|||
/*
|
||||
* Performs MSR operations on all the CPU's
|
||||
*/
|
||||
int32_t profiling_msr_ops_all_cpus(__unused struct vm *vm, __unused uint64_t addr)
|
||||
|
||||
int32_t profiling_msr_ops_all_cpus(__unused struct vm *vm, __unused uint64_t addr)
|
||||
{
|
||||
/* to be implemented
|
||||
* call to smp_call_function profiling_ipi_handler
|
||||
|
@ -73,27 +78,138 @@ static void profiling_pmi_handler(__unused unsigned int irq, __unused void *data
|
|||
/*
|
||||
* Generate VM info list
|
||||
*/
|
||||
int32_t profiling_vm_list_info(__unused struct vm *vm, __unused uint64_t addr)
|
||||
int32_t profiling_vm_list_info(struct vm *vm, uint64_t addr)
|
||||
{
|
||||
/* to be implemented */
|
||||
struct vm *tmp_vm;
|
||||
struct vcpu *vcpu;
|
||||
int32_t vm_idx;
|
||||
uint16_t i, j;
|
||||
struct profiling_vm_info_list vm_info_list;
|
||||
|
||||
(void)memset((void *)&vm_info_list, 0U, sizeof(vm_info_list));
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: entering", __func__);
|
||||
|
||||
if (copy_from_gpa(vm, &vm_info_list, addr, sizeof(vm_info_list)) != 0) {
|
||||
pr_err("%s: Unable to copy addr from vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
vm_idx = 0;
|
||||
vm_info_list.vm_list[vm_idx].vm_id_num = -1;
|
||||
(void)memcpy_s((void *)vm_info_list.vm_list[vm_idx].vm_name, 4U, "VMM\0", 4U);
|
||||
for (i = 0U; i < phys_cpu_num; i++) {
|
||||
vm_info_list.vm_list[vm_idx].cpu_map[i].vcpu_id = (int32_t)i;
|
||||
vm_info_list.vm_list[vm_idx].cpu_map[i].pcpu_id = (int32_t)i;
|
||||
vm_info_list.vm_list[vm_idx].cpu_map[i].apic_id
|
||||
= (int32_t)per_cpu(lapic_id, i);
|
||||
}
|
||||
vm_info_list.vm_list[vm_idx].num_vcpus = (int32_t)i;
|
||||
vm_info_list.num_vms = 1;
|
||||
|
||||
for (j = 0U; j < CONFIG_MAX_VM_NUM; j++) {
|
||||
tmp_vm = get_vm_from_vmid(j);
|
||||
if (tmp_vm == NULL) {
|
||||
break;
|
||||
}
|
||||
vm_info_list.num_vms++;
|
||||
vm_idx++;
|
||||
|
||||
vm_info_list.vm_list[vm_idx].vm_id_num = (int32_t)tmp_vm->vm_id;
|
||||
(void)memcpy_s((void *)vm_info_list.vm_list[vm_idx].guid,
|
||||
16U, tmp_vm->GUID, 16U);
|
||||
snprintf(vm_info_list.vm_list[vm_idx].vm_name, 16U, "vm_%d",
|
||||
tmp_vm->vm_id, 16U);
|
||||
vm_info_list.vm_list[vm_idx].num_vcpus = 0;
|
||||
i = 0U;
|
||||
foreach_vcpu(i, tmp_vm, vcpu) {
|
||||
vm_info_list.vm_list[vm_idx].cpu_map[i].vcpu_id
|
||||
= (int32_t)vcpu->vcpu_id;
|
||||
vm_info_list.vm_list[vm_idx].cpu_map[i].pcpu_id
|
||||
= (int32_t)vcpu->pcpu_id;
|
||||
vm_info_list.vm_list[vm_idx].cpu_map[i].apic_id = 0;
|
||||
vm_info_list.vm_list[vm_idx].num_vcpus++;
|
||||
}
|
||||
}
|
||||
|
||||
if (copy_to_gpa(vm, &vm_info_list, addr, sizeof(vm_info_list)) != 0) {
|
||||
pr_err("%s: Unable to copy addr to vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: exiting", __func__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Sep/socwatch profiling version
|
||||
*/
|
||||
int32_t profiling_get_version_info(__unused struct vm *vm, __unused uint64_t addr)
|
||||
int32_t profiling_get_version_info(struct vm *vm, uint64_t addr)
|
||||
{
|
||||
/* to be implemented */
|
||||
struct profiling_version_info ver_info;
|
||||
|
||||
(void)memset((void *)&ver_info, 0U, sizeof(ver_info));
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: entering", __func__);
|
||||
|
||||
if (copy_from_gpa(vm, &ver_info, addr, sizeof(ver_info)) != 0) {
|
||||
pr_err("%s: Unable to copy addr from vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ver_info.major = MAJOR_VERSION;
|
||||
ver_info.minor = MINOR_VERSION;
|
||||
ver_info.supported_features = (int64_t)
|
||||
((1U << (uint64_t)CORE_PMU_SAMPLING) |
|
||||
(1U << (uint64_t)CORE_PMU_COUNTING) |
|
||||
(1U << (uint64_t)LBR_PMU_SAMPLING) |
|
||||
(1U << (uint64_t)VM_SWITCH_TRACING));
|
||||
|
||||
if (copy_to_gpa(vm, &ver_info, addr, sizeof(ver_info)) != 0) {
|
||||
pr_err("%s: Unable to copy addr to vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: exiting", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Gets type of profiling - sep/socwatch
|
||||
*/
|
||||
int32_t profiling_get_control(__unused struct vm *vm, __unused uint64_t addr)
|
||||
int32_t profiling_get_control(struct vm *vm, uint64_t addr)
|
||||
{
|
||||
/* to be implemented */
|
||||
struct profiling_control prof_control;
|
||||
|
||||
(void)memset((void *)&prof_control, 0U, sizeof(prof_control));
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: entering", __func__);
|
||||
|
||||
if (copy_from_gpa(vm, &prof_control, addr, sizeof(prof_control)) != 0) {
|
||||
pr_err("%s: Unable to copy addr from vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
switch (prof_control.collector_id) {
|
||||
case COLLECT_PROFILE_DATA:
|
||||
prof_control.switches = sep_collection_switch;
|
||||
break;
|
||||
case COLLECT_POWER_DATA:
|
||||
break;
|
||||
default:
|
||||
pr_err("%s: unknown collector %d",
|
||||
__func__, prof_control.collector_id);
|
||||
break;
|
||||
}
|
||||
|
||||
if (copy_to_gpa(vm, &prof_control, addr, sizeof(prof_control)) != 0) {
|
||||
pr_err("%s: Unable to copy addr to vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: exiting", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -131,9 +247,29 @@ int32_t profiling_configure_vmsw(__unused struct vm *vm, __unused uint64_t addr)
|
|||
/*
|
||||
* Get the physical cpu id
|
||||
*/
|
||||
int32_t profiling_get_pcpu_id(__unused struct vm *vm, __unused uint64_t addr)
|
||||
int32_t profiling_get_pcpu_id(struct vm *vm, uint64_t addr)
|
||||
{
|
||||
/* to be implemented */
|
||||
struct profiling_pcpuid pcpuid;
|
||||
|
||||
(void)memset((void *)&pcpuid, 0U, sizeof(pcpuid));
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: entering", __func__);
|
||||
|
||||
if (copy_from_gpa(vm, &pcpuid, addr, sizeof(pcpuid)) != 0) {
|
||||
pr_err("%s: Unable to copy addr from vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
cpuid_subleaf(pcpuid.leaf, pcpuid.subleaf, &pcpuid.eax,
|
||||
&pcpuid.ebx, &pcpuid.ecx, &pcpuid.edx);
|
||||
|
||||
if (copy_to_gpa(vm, &pcpuid, addr, sizeof(pcpuid)) != 0) {
|
||||
pr_err("%s: Unable to copy param to vm\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_dbg(ACRN_DBG_PROFILING, "%s: exiting", __func__);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,13 @@
|
|||
|
||||
#ifdef PROFILING_ON
|
||||
|
||||
typedef enum IPI_COMMANDS {
|
||||
#define MAX_NR_VCPUS 8
|
||||
#define MAX_NR_VMS 6
|
||||
|
||||
#define COLLECT_PROFILE_DATA 0
|
||||
#define COLLECT_POWER_DATA 1
|
||||
|
||||
typedef enum IPI_COMMANDS {
|
||||
IPI_MSR_OP = 0,
|
||||
IPI_PMU_CONFIG,
|
||||
IPI_PMU_START,
|
||||
|
@ -17,7 +23,59 @@
|
|||
IPI_VMSW_CONFIG,
|
||||
IPI_UNKNOWN,
|
||||
} ipi_commands;
|
||||
/*
|
||||
|
||||
typedef enum PROFILING_SEP_FEATURE {
|
||||
CORE_PMU_SAMPLING = 0,
|
||||
CORE_PMU_COUNTING,
|
||||
PEBS_PMU_SAMPLING,
|
||||
LBR_PMU_SAMPLING,
|
||||
UNCORE_PMU_SAMPLING,
|
||||
VM_SWITCH_TRACING,
|
||||
MAX_SEP_FEATURE_ID
|
||||
} profiling_sep_feature;
|
||||
|
||||
struct profiling_version_info {
|
||||
int32_t major;
|
||||
int32_t minor;
|
||||
int64_t supported_features;
|
||||
int64_t reserved;
|
||||
};
|
||||
|
||||
struct profiling_pcpuid {
|
||||
uint32_t leaf;
|
||||
uint32_t subleaf;
|
||||
uint32_t eax;
|
||||
uint32_t ebx;
|
||||
uint32_t ecx;
|
||||
uint32_t edx;
|
||||
};
|
||||
|
||||
struct profiling_control {
|
||||
int32_t collector_id;
|
||||
int32_t reserved;
|
||||
uint64_t switches;
|
||||
};
|
||||
|
||||
struct profiling_vcpu_pcpu_map {
|
||||
int32_t vcpu_id;
|
||||
int32_t pcpu_id;
|
||||
int32_t apic_id;
|
||||
};
|
||||
|
||||
struct profiling_vm_info {
|
||||
int32_t vm_id_num;
|
||||
unsigned char guid[16];
|
||||
char vm_name[16];
|
||||
int32_t num_vcpus;
|
||||
struct profiling_vcpu_pcpu_map cpu_map[MAX_NR_VCPUS];
|
||||
};
|
||||
|
||||
struct profiling_vm_info_list {
|
||||
int32_t num_vms;
|
||||
struct profiling_vm_info vm_list[MAX_NR_VMS];
|
||||
};
|
||||
|
||||
/*
|
||||
* Wrapper containing SEP sampling/profiling related data structures
|
||||
*/
|
||||
struct profiling_info_wrapper {
|
||||
|
|
Loading…
Reference in New Issue