]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
KVM: x86: Treat KVM's virtual PMU as disabled for TDX VMs
authorVishal Annapurve <vannapurve@google.com>
Fri, 22 May 2026 15:15:34 +0000 (15:15 +0000)
committerSean Christopherson <seanjc@google.com>
Tue, 26 May 2026 22:13:54 +0000 (15:13 -0700)
Introduce a "protected PMU" concept, and use it to disable KVM's virtual
PMU for TDX VMs, as the PMU state for TDX VMs is virtualized by the TDX
Module[1], i.e. _can't_ emulated/virtualized by KVM, and KVM doesn't yet
support enabling/exposing PMU functionality for/to TDX VMs.  For now,
simply treat the PMU as disabled, as it's not clear what all needs to be
changed, e.g. KVM needs to do at least:

 1) Configure TD_PARAMS to allow guests to use performance monitoring.
 2) Restrict the TD to a subset of the PEBS counters if supported.
 3) Limit the TD to setup a certain perfmon events using basic/enhanced
    event filtering.

Explicitly disallow enabling the PMU via KVM_CAP_PMU_CAPABILITY for VMs
with a protected PMU to prevent userspace from circumventing KVM's
protections.

Link: https://cdrdv2.intel.com/v1/dl/getContent/733575
Suggested-by: Sean Christopherson <seanjc@google.com>
Signed-off-by: Vishal Annapurve <vannapurve@google.com>
Link: https://patch.msgid.link/20260522151534.652522-1-vannapurve@google.com
[sean: massage shortlog and changelog]
Signed-off-by: Sean Christopherson <seanjc@google.com>
arch/x86/include/asm/kvm_host.h
arch/x86/kvm/vmx/tdx.c
arch/x86/kvm/x86.c

index 7114707b9856bfe091041aa8d7186de8b9a38a34..beb83eea65efaf326d95e17c9ac33c4ec64ad656 100644 (file)
@@ -1442,6 +1442,7 @@ struct kvm_arch {
        bool has_private_mem;
        bool has_protected_state;
        bool has_protected_eoi;
+       bool has_protected_pmu;
        bool pre_fault_allowed;
        struct hlist_head *mmu_page_hash;
        struct list_head active_mmu_pages;
index b8c3d3d8bbfe5f943329e42840c95b174f3d2b17..5fb3f606501ba2138b0c2bded78e9833397fee82 100644 (file)
@@ -638,6 +638,12 @@ int tdx_vm_init(struct kvm *kvm)
        kvm->arch.has_private_mem = true;
        kvm->arch.disabled_quirks |= KVM_X86_QUIRK_IGNORE_GUEST_PAT;
 
+       /*
+        * PMU support is provided by the TDX-Module (if enabled for the VM).
+        * From KVM's perspective, the VM doesn't have a virtual PMU.
+        */
+       kvm->arch.has_protected_pmu = true;
+
        /*
         * Because guest TD is protected, VMM can't parse the instruction in TD.
         * Instead, guest uses MMIO hypercall.  For unmodified device driver,
index 93958df302306f3166bd17329038d6b5bda7fe96..c560c52b95f088d28576d717c0a07bc7bd35c136 100644 (file)
@@ -6920,6 +6920,10 @@ disable_exits_unlock:
                if (!enable_pmu || (cap->args[0] & ~KVM_CAP_PMU_VALID_MASK))
                        break;
 
+               if (kvm->arch.has_protected_pmu &&
+                   cap->args[0] != KVM_PMU_CAP_DISABLE)
+                       break;
+
                mutex_lock(&kvm->lock);
                if (!kvm->created_vcpus && !kvm->arch.created_mediated_pmu) {
                        kvm->arch.enable_pmu = !(cap->args[0] & KVM_PMU_CAP_DISABLE);
@@ -13362,7 +13366,7 @@ int kvm_arch_init_vm(struct kvm *kvm, unsigned long type)
        kvm->arch.default_tsc_khz = max_tsc_khz ? : tsc_khz;
        kvm->arch.apic_bus_cycle_ns = APIC_BUS_CYCLE_NS_DEFAULT;
        kvm->arch.guest_can_read_msr_platform_info = true;
-       kvm->arch.enable_pmu = enable_pmu;
+       kvm->arch.enable_pmu = enable_pmu && !kvm->arch.has_protected_pmu;
 
 #if IS_ENABLED(CONFIG_HYPERV)
        spin_lock_init(&kvm->arch.hv_root_tdp_lock);