From b3bd15318032cb0f9f6a37328440af188ef15805 Mon Sep 17 00:00:00 2001 From: Minggui Cao Date: Mon, 13 Dec 2021 15:16:14 +0800 Subject: [PATCH] hv: expose PEBS capability and MSR as PMU_PT flag Requirement: in CPU partition VM (RTVM), vtune or perf can be used to sample hotspot code path to tune the RT performance, It need support PMU/PEBS (Processor Event Based Sampling). Intel TCC asks for it, too. It exposes PEBS related capabilities/features and MSRs to CPU partition VM, like RTVM. PEBS is a part of PMU. Also PEBS needs DS (Debug Store) feature to support. So DS is exposed too. Limitation: current it just support PEBS feature in VM level, when CPU traps to HV, the performance counter will stop. Perf global control MSR is used to do this work. So, the counters shall be close to native. Tracked-On: #6966 Acked-by: Anthony Xu Signed-off-by: Minggui Cao --- hypervisor/arch/x86/guest/vcpuid.c | 21 +++++++++------- hypervisor/arch/x86/guest/vmcs.c | 2 +- hypervisor/arch/x86/guest/vmsr.c | 25 +++++++++++++------- hypervisor/include/arch/x86/asm/guest/vcpu.h | 1 + 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/hypervisor/arch/x86/guest/vcpuid.c b/hypervisor/arch/x86/guest/vcpuid.c index 1ff942cfa..65206bfed 100644 --- a/hypervisor/arch/x86/guest/vcpuid.c +++ b/hypervisor/arch/x86/guest/vcpuid.c @@ -558,7 +558,7 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm) /* These features are disabled */ /* PMU is not supported except for core partition VM, like RTVM */ case 0x0aU: - if (is_lapic_pt_configured(vm)) { + if (is_pmu_pt_configured(vm)) { init_vcpuid_entry(i, 0U, 0U, &entry); result = set_vcpuid_entry(vm, &entry); } @@ -625,15 +625,9 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx *edx &= ~CPUID_EDX_MTRR; } - /* mask Debug Store feature */ - *ecx &= ~(CPUID_ECX_DTES64 | CPUID_ECX_DS_CPL); - /* mask Safer Mode Extension */ *ecx &= ~CPUID_ECX_SMX; - /* mask PDCM: Perfmon and Debug Capability */ - *ecx &= ~CPUID_ECX_PDCM; - /* mask SDBG for silicon debug */ *ecx &= ~CPUID_ECX_SDBG; @@ -693,8 +687,17 @@ static void guest_cpuid_01h(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx *edx &= ~CPUID_EDX_FXSR; } - /* mask Debug Store feature */ - *edx &= ~CPUID_EDX_DTES; + /* DS/PEBS is not supported except for core partition VM, like RTVM */ + if (!is_pmu_pt_configured(vcpu->vm)) { + /* mask Debug Store feature */ + *ecx &= ~(CPUID_ECX_DTES64 | CPUID_ECX_DS_CPL); + + /* mask PDCM: Perfmon and Debug Capability */ + *ecx &= ~CPUID_ECX_PDCM; + + /* mask Debug Store feature */ + *edx &= ~CPUID_EDX_DTES; + } } static void guest_cpuid_0bh(struct acrn_vcpu *vcpu, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index e6df1d9a9..b5c2387b4 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -307,7 +307,7 @@ static void init_exec_ctrl(struct acrn_vcpu *vcpu) /* * Enable VM_EXIT for rdpmc execution except core partition VM, like RTVM */ - if (!is_lapic_pt_configured(vcpu->vm)) { + if (!is_pmu_pt_configured(vcpu->vm)) { value32 |= VMX_PROCBASED_CTLS_RDPMC; } diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c index acae92eb3..06b1ffb15 100644 --- a/hypervisor/arch/x86/guest/vmsr.c +++ b/hypervisor/arch/x86/guest/vmsr.c @@ -148,7 +148,13 @@ static const uint32_t pmc_msrs[] = { /* CPUID.0AH.EDX[4:0] */ MSR_IA32_FIXED_CTR0, MSR_IA32_FIXED_CTR1, - MSR_IA32_FIXED_CTR2 + MSR_IA32_FIXED_CTR2, + + /* Performance Monitoring: CPUID.01H.ECX[15] X86_FEATURE_PDCM */ + MSR_IA32_PERF_CAPABILITIES, + + /* Debug Store disabled: CPUID.01H.EDX[21] X86_FEATURE_DTES */ + MSR_IA32_DS_AREA, }; /* Following MSRs are intercepted, but it throws GPs for any guest accesses */ @@ -223,12 +229,6 @@ static const uint32_t unsupported_msrs[] = { /* Silicon Debug Feature: CPUID.01H.ECX[11] (X86_FEATURE_SDBG) */ MSR_IA32_DEBUG_INTERFACE, - /* Performance Monitoring: CPUID.01H.ECX[15] X86_FEATURE_PDCM */ - MSR_IA32_PERF_CAPABILITIES, - - /* Debug Store disabled: CPUID.01H.EDX[21] X86_FEATURE_DTES */ - MSR_IA32_DS_AREA, - /* Machine Check Exception: CPUID.01H.EDX[5] (X86_FEATURE_MCE) */ MSR_IA32_MCG_CAP, MSR_IA32_MCG_STATUS, @@ -331,6 +331,15 @@ static void prepare_auto_msr_area(struct acrn_vcpu *vcpu) { vcpu->arch.msr_area.count = 0U; + /* in HV, disable perf/PMC counting, just count in guest VM */ + if (is_pmu_pt_configured(vcpu->vm)) { + vcpu->arch.msr_area.guest[MSR_AREA_PERF_CTRL].msr_index = MSR_IA32_PERF_GLOBAL_CTRL; + vcpu->arch.msr_area.guest[MSR_AREA_PERF_CTRL].value = 0; + vcpu->arch.msr_area.host[MSR_AREA_PERF_CTRL].msr_index = MSR_IA32_PERF_GLOBAL_CTRL; + vcpu->arch.msr_area.host[MSR_AREA_PERF_CTRL].value = 0; + vcpu->arch.msr_area.count++; + } + if (is_platform_rdt_capable()) { struct acrn_vm_config *cfg = get_vm_config(vcpu->vm->vm_id); uint16_t vcpu_clos; @@ -472,7 +481,7 @@ void init_msr_emulation(struct acrn_vcpu *vcpu) } /* for core partition VM (like RTVM), passthrou PMC MSRs for performance profiling/tuning; hide to other VMs */ - if (!is_lapic_pt_configured(vcpu->vm)) { + if (!is_pmu_pt_configured(vcpu->vm)) { for (i = 0U; i < ARRAY_SIZE(pmc_msrs); i++) { enable_msr_interception(msr_bitmap, pmc_msrs[i], INTERCEPT_READ_WRITE); } diff --git a/hypervisor/include/arch/x86/asm/guest/vcpu.h b/hypervisor/include/arch/x86/asm/guest/vcpu.h index e34bc472d..bd0a02007 100644 --- a/hypervisor/include/arch/x86/asm/guest/vcpu.h +++ b/hypervisor/include/arch/x86/asm/guest/vcpu.h @@ -214,6 +214,7 @@ struct msr_store_entry { enum { MSR_AREA_IA32_PQR_ASSOC = 0, + MSR_AREA_PERF_CTRL, MSR_AREA_COUNT, };