Re: [PATCH v6 7/8] KVM: x86/pmu: Emulate RDPMC on performance metrics

From: Mi, Dapeng

Date: Mon Jun 29 2026 - 22:24:16 EST


Reviewed-by: Dapeng Mi <dapeng1.mi@xxxxxxxxxxxxxxx>


On 6/30/2026 7:19 AM, Zide Chen wrote:
> If the host has the PERF_METRICS capability but it's not present on
> the guest, RDPMC interception must be enabled and KVM should inject
> an #GP when the guest attempts a PERF_METRICS RDPMC.
>
> If the guest has PERF_METRICS but RDPMC interception is enabled for
> other reasons, KVM needs to emulate RDPMC with type 2000H.
>
> For simplicity, Metrics Clear Mode is not supported.
>
> Signed-off-by: Zide Chen <zide.chen@xxxxxxxxx>
> ---
> v6:
> - Merge kvm_pmu_rdpmc_metrics() into intel_emulate_rdpmc().
> - Reject non-zero index.
> v5:
> - new patch.
> ---
> arch/x86/kvm/pmu.c | 7 +++++++
> arch/x86/kvm/vmx/pmu_intel.c | 14 ++++++++++++++
> 2 files changed, 21 insertions(+)
>
> diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
> index 8ef2d4761790..04b9c840f218 100644
> --- a/arch/x86/kvm/pmu.c
> +++ b/arch/x86/kvm/pmu.c
> @@ -806,6 +806,12 @@ bool kvm_need_perf_global_ctrl_intercept(struct kvm_vcpu *vcpu)
> }
> EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_need_perf_global_ctrl_intercept);
>
> +static bool kvm_need_perf_metrics_intercept(struct kvm_vcpu *vcpu)
> +{
> + return (kvm_host.perf_capabilities & PERF_CAP_PERF_METRICS) &&
> + !kvm_vcpu_has_perf_metrics(vcpu);
> +}
> +
> bool kvm_need_rdpmc_intercept(struct kvm_vcpu *vcpu)
> {
> struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
> @@ -818,6 +824,7 @@ bool kvm_need_rdpmc_intercept(struct kvm_vcpu *vcpu)
> return true;
>
> return kvm_need_any_pmc_intercept(vcpu) ||
> + kvm_need_perf_metrics_intercept(vcpu) ||
> pmu->counter_bitmask[KVM_PMC_GP] != (BIT_ULL(kvm_host_pmu.bit_width_gp) - 1) ||
> pmu->counter_bitmask[KVM_PMC_FIXED] != (BIT_ULL(kvm_host_pmu.bit_width_fixed) - 1);
> }
> diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
> index 080677372c9b..93b5a8360377 100644
> --- a/arch/x86/kvm/vmx/pmu_intel.c
> +++ b/arch/x86/kvm/vmx/pmu_intel.c
> @@ -30,6 +30,7 @@
> */
> #define INTEL_RDPMC_GP 0
> #define INTEL_RDPMC_FIXED INTEL_PMC_FIXED_RDPMC_BASE
> +#define INTEL_RDPMC_METRICS INTEL_PMC_FIXED_RDPMC_METRICS
>
> #define INTEL_RDPMC_TYPE_MASK GENMASK(31, 16)
> #define INTEL_RDPMC_INDEX_MASK GENMASK(15, 0)
> @@ -124,6 +125,19 @@ static int intel_emulate_rdpmc(struct kvm_vcpu *vcpu, unsigned int idx,
> counters = pmu->gp_counters;
> num_counters = pmu->nr_arch_gp_counters;
> break;
> + case INTEL_RDPMC_METRICS:
> + if (!kvm_vcpu_has_perf_metrics(vcpu))
> + return 1;
> +
> + /*
> + * The index in ECX[15:0] is implementation specific, but no
> + * platform currently supports a non-zero index.
> + */
> + if (idx)
> + return 1;
> +
> + *data = pmu->perf_metrics;
> + return 0;
> default:
> return 1;
> }