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

From: Jim Mattson

Date: Wed Jul 22 2026 - 23:15:53 EST


On Wed, Jul 22, 2026 at 7:53 PM Mi, Dapeng <dapeng1.mi@xxxxxxxxxxxxxxx> wrote:
>
>
> On 7/23/2026 10:25 AM, Jim Mattson wrote:
> > On Wed, Jul 22, 2026 at 6:44 PM Mi, Dapeng <dapeng1.mi@xxxxxxxxxxxxxxx> wrote:
> >>
> >> On 7/23/2026 8:02 AM, Jim Mattson wrote:
> >>> On Mon, Jun 29, 2026 at 4:29 PM Zide Chen <zide.chen@xxxxxxxxx> 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;
> >>> I know we have a strong disagreement here, but I really feel that this
> >>> must be secure and future-proof out of the box.
> >>> What if we added a module parameter, enable_rdpmc_passthrough, which
> >>> defaults to false?
> >>>
> >>> Then:
> >>>
> >>> if (!enable_rdpmc_passthrough)
> >>> return true;
> >>>
> >>> Is that a reasonable compromise?
> >> Yes, this is an option. Another option is to add a helper to explicitly
> >> tell which platforms are secure and can pass-through rdpmc. Maybe like this,
> >>
> >> static bool intel_pmu_can_passthrough_rdpmc()
> >> {
> >> switch (boot_cpu_data.x86_vfm) {
> >> case INTEL_ICELAKE_X:
> >> case INTEL_SAPPHIRERAPIDS_X:
> >> case INTEL_EMERALDRAPIDS_X:
> >> case INTEL_GRANITERAPIDS_X:
> >> ... ...
> >> return true;
> >> default:
> >> return false;
> >> }
> >>
> >> return false;
> >> }
> >>
> >> Then rdpmc can be passed through by default on these known secure
> >> platforms. For any new platforms, the rdpmc would be intercepted out of
> >> box until we confirm it's secured and explicitly support them.
> >>
> >> How about this? At least for me, it looks like an overkill to disable rdpmc
> >> passthrough unconditionally on these known secure platforms.
> > The F/M match would only apply on bare metal, since you can't trust F/M in a VM.
> >
> > What if we combine this with the module parameter, but now the module
> > parameter defaults to true? Somewhere in module load, we have:
> >
> > if (boot_cpu_has(X86_FEATURE_HYPERVISOR) || !intel_pmu_can_passthrough_rdpmc())
> > enable_rdpmc_passthrough = false;
>
> It looks good to me. :)

On second thought, it doesn't really matter if L0 has lied to L1 about
F/M. If the hardware supports more RDPMC types than the L1 virtual CPU
does, L0 must intercept and emulate RDPMC for vmcs01. Even if L1
decides to pass through RDPMC to L2, L0 will still intercept and
emulate RDPMC for vmcs02.

So, we can drop the module parameter and just use
intel_pmu_can_passthrough_rdpmc().

To keep the list short, I assume that any CPU with only three fixed
counters will return true.