diff --git a/hypervisor/arch/x86/guest/vcpuid.c b/hypervisor/arch/x86/guest/vcpuid.c index f0f931e84..9619f3d56 100644 --- a/hypervisor/arch/x86/guest/vcpuid.c +++ b/hypervisor/arch/x86/guest/vcpuid.c @@ -360,9 +360,12 @@ int32_t set_vcpuid_entries(struct acrn_vm *vm) case 0x12U: result = set_vcpuid_sgx(vm); break; - /* These features are disabled */ - /* PMU is not supported */ case 0x0aU: + if (is_pmu_pt_configured(vm)) { + init_vcpuid_entry(i, 0U, 0U, &entry); + result = set_vcpuid_entry(vm, &entry); + } + break; /* Intel RDT */ case 0x0fU: case 0x10U: diff --git a/hypervisor/arch/x86/guest/vm.c b/hypervisor/arch/x86/guest/vm.c index 6ebe6396f..aaa4b9e05 100644 --- a/hypervisor/arch/x86/guest/vm.c +++ b/hypervisor/arch/x86/guest/vm.c @@ -124,6 +124,13 @@ bool is_rt_vm(const struct acrn_vm *vm) return ((vm_config->guest_flags & GUEST_FLAG_RT) != 0U); } +bool is_pmu_pt_configured(const struct acrn_vm *vm) +{ + struct acrn_vm_config *vm_config = get_vm_config(vm->vm_id); + + return ((vm_config->guest_flags & GUEST_FLAG_PMU_PASSTHROUGH) != 0U); +} + /** * @brief VT-d PI posted mode can possibly be used for PTDEVs assigned * to this VM if platform supports VT-d PI AND lapic passthru is not configured diff --git a/hypervisor/arch/x86/guest/vmcs.c b/hypervisor/arch/x86/guest/vmcs.c index 28544e82d..ea4f01e80 100644 --- a/hypervisor/arch/x86/guest/vmcs.c +++ b/hypervisor/arch/x86/guest/vmcs.c @@ -286,7 +286,9 @@ static void init_exec_ctrl(struct acrn_vcpu *vcpu) /* * Enable VM_EXIT for rdpmc execution. */ - value32 |= VMX_PROCBASED_CTLS_RDPMC; + if (!is_pmu_pt_configured(vcpu->vm)) { + value32 |= VMX_PROCBASED_CTLS_RDPMC; + } exec_vmwrite32(VMX_PROC_VM_EXEC_CONTROLS, value32); pr_dbg("VMX_PROC_VM_EXEC_CONTROLS: 0x%x ", value32); diff --git a/hypervisor/arch/x86/guest/vmsr.c b/hypervisor/arch/x86/guest/vmsr.c index 438846ae7..dec36dbb3 100644 --- a/hypervisor/arch/x86/guest/vmsr.c +++ b/hypervisor/arch/x86/guest/vmsr.c @@ -347,6 +347,43 @@ void init_msr_emulation(struct acrn_vcpu *vcpu) /* don't need to intercept rdmsr for these MSRs */ enable_msr_interception(msr_bitmap, MSR_IA32_TIME_STAMP_COUNTER, INTERCEPT_WRITE); + + if (is_pmu_pt_configured(vcpu->vm)) { + /* Passthru PMU related MSRs to guest */ + enable_msr_interception(msr_bitmap, MSR_IA32_FIXED_CTR_CTL, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERF_GLOBAL_CTRL, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERF_GLOBAL_STATUS, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERF_GLOBAL_OVF_CTRL, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERF_GLOBAL_STATUS_SET, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERF_GLOBAL_INUSE, INTERCEPT_DISABLE); + + enable_msr_interception(msr_bitmap, MSR_IA32_FIXED_CTR0, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_FIXED_CTR1, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_FIXED_CTR2, INTERCEPT_DISABLE); + + enable_msr_interception(msr_bitmap, MSR_IA32_PMC0, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC1, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC2, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC3, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC4, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC5, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC6, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PMC7, INTERCEPT_DISABLE); + + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC0, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC1, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC2, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC3, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC4, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC5, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC6, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_A_PMC7, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERFEVTSEL0, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERFEVTSEL1, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERFEVTSEL2, INTERCEPT_DISABLE); + enable_msr_interception(msr_bitmap, MSR_IA32_PERFEVTSEL3, INTERCEPT_DISABLE); + } + /* Setup MSR bitmap - Intel SDM Vol3 24.6.9 */ value64 = hva2hpa(vcpu->arch.msr_bitmap); exec_vmwrite64(VMX_MSR_BITMAP_FULL, value64); diff --git a/hypervisor/include/arch/x86/guest/vm.h b/hypervisor/include/arch/x86/guest/vm.h index 8b2d7ca81..b0e5b797b 100644 --- a/hypervisor/include/arch/x86/guest/vm.h +++ b/hypervisor/include/arch/x86/guest/vm.h @@ -241,6 +241,7 @@ void vrtc_init(struct acrn_vm *vm); bool is_lapic_pt_configured(const struct acrn_vm *vm); bool is_rt_vm(const struct acrn_vm *vm); bool is_pi_capable(const struct acrn_vm *vm); +bool is_pmu_pt_configured(const struct acrn_vm *vm); bool has_rt_vm(void); struct acrn_vm *get_highest_severity_vm(bool runtime); bool vm_hide_mtrr(const struct acrn_vm *vm); diff --git a/hypervisor/include/public/acrn_common.h b/hypervisor/include/public/acrn_common.h index 4289f37e9..eddb03401 100644 --- a/hypervisor/include/public/acrn_common.h +++ b/hypervisor/include/public/acrn_common.h @@ -52,6 +52,7 @@ #define GUEST_FLAG_IO_COMPLETION_POLLING (1UL << 2U) /* Whether need hypervisor poll IO completion */ #define GUEST_FLAG_HIDE_MTRR (1UL << 3U) /* Whether hide MTRR from VM */ #define GUEST_FLAG_RT (1UL << 4U) /* Whether the vm is RT-VM */ +#define GUEST_FLAG_PMU_PASSTHROUGH (1UL << 5U) /* Whether passthrough PMU to the VM */ /* TODO: We may need to get this addr from guest ACPI instead of hardcode here */ #define VIRTUAL_PM1A_CNT_ADDR 0x404U diff --git a/hypervisor/scenarios/hybrid/vm_configurations.h b/hypervisor/scenarios/hybrid/vm_configurations.h index 295c61a00..b9090ca26 100644 --- a/hypervisor/scenarios/hybrid/vm_configurations.h +++ b/hypervisor/scenarios/hybrid/vm_configurations.h @@ -11,7 +11,8 @@ /* Bits mask of guest flags that can be programmed by device model. Other bits are set by hypervisor only */ #define DM_OWNED_GUEST_FLAG_MASK (GUEST_FLAG_SECURE_WORLD_ENABLED | GUEST_FLAG_LAPIC_PASSTHROUGH | \ - GUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING) + GUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING | \ + GUEST_FLAG_PMU_PASSTHROUGH) /* SOS_VM_NUM can only be 0U or 1U; * When SOS_VM_NUM is 0U, MAX_POST_VM_NUM must be 0U too; diff --git a/hypervisor/scenarios/industry/vm_configurations.h b/hypervisor/scenarios/industry/vm_configurations.h index 687120224..c7c2b7e22 100644 --- a/hypervisor/scenarios/industry/vm_configurations.h +++ b/hypervisor/scenarios/industry/vm_configurations.h @@ -20,7 +20,8 @@ /* Bits mask of guest flags that can be programmed by device model. Other bits are set by hypervisor only */ #define DM_OWNED_GUEST_FLAG_MASK (GUEST_FLAG_SECURE_WORLD_ENABLED | GUEST_FLAG_LAPIC_PASSTHROUGH | \ - GUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING) + GUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING | \ + GUEST_FLAG_PMU_PASSTHROUGH) #define SOS_VM_BOOTARGS SOS_ROOTFS \ "rw rootwait " \ diff --git a/hypervisor/scenarios/sdc/vm_configurations.h b/hypervisor/scenarios/sdc/vm_configurations.h index ab9456e79..4fd15d1a4 100644 --- a/hypervisor/scenarios/sdc/vm_configurations.h +++ b/hypervisor/scenarios/sdc/vm_configurations.h @@ -20,7 +20,8 @@ /* Bits mask of guest flags that can be programmed by device model. Other bits are set by hypervisor only */ #define DM_OWNED_GUEST_FLAG_MASK (GUEST_FLAG_SECURE_WORLD_ENABLED | GUEST_FLAG_LAPIC_PASSTHROUGH | \ - GUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING) + GUEST_FLAG_RT | GUEST_FLAG_IO_COMPLETION_POLLING | \ + GUEST_FLAG_PMU_PASSTHROUGH) #define SOS_VM_BOOTARGS SOS_ROOTFS \ "rw rootwait " \