From: Zide Chen <zide.chen@intel.com>
To: Sean Christopherson <seanjc@google.com>,
Paolo Bonzini <pbonzini@redhat.com>,
Peter Zijlstra <peterz@infradead.org>
Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org,
Jim Mattson <jmattson@google.com>,
Mingwei Zhang <mizhang@google.com>,
Zide Chen <zide.chen@intel.com>,
Das Sandipan <Sandipan.Das@amd.com>,
Shukla Manali <Manali.Shukla@amd.com>,
Dapeng Mi <dapeng1.mi@linux.intel.com>,
Falcon Thomas <thomas.falcon@intel.com>,
Xudong Hao <xudong.hao@intel.com>,
Yang Weijiang <weijiang.yang@intel.com>
Subject: [PATCH 10/15] KVM: x86/pmu: Emulate the GLOBAL_STATUS_SET and GLOBAL_INUSE MSRs
Date: Tue, 7 Jul 2026 11:34:00 -0700 [thread overview]
Message-ID: <20260707183405.15571-11-zide.chen@intel.com> (raw)
In-Reply-To: <20260707183405.15571-1-zide.chen@intel.com>
Intel PerfMon v4 introduces IA32_PERF_GLOBAL_STATUS_SET (0x391) to
allow software to set individual bits in the global status MSR. Reads
of IA32_PERF_GLOBAL_STATUS_SET always return zero.
IA32_PERF_GLOBAL_INUSE (0x392) is also introduced in v4, to track
which counters and the PMI are currently claimed by other agents,
allowing independent software agents to check counter availability
without a shared scheduler arbitrating between them.
IA32_PERF_GLOBAL_INUSE is an R/O MSR, and any write attempt results
in a #GP.
Neither MSR is part of the VM state, so they don't need to be
advertised to userspace, nor saved and restored during live
migration.
Originally-by: Yang Weijiang <weijiang.yang@intel.com>
Signed-off-by: Zide Chen <zide.chen@intel.com>
---
arch/x86/include/asm/msr-index.h | 4 ++++
arch/x86/kvm/pmu.c | 9 ++++++++
arch/x86/kvm/vmx/pmu_intel.c | 38 ++++++++++++++++++++++++++++++++
arch/x86/kvm/vmx/vmx.c | 4 ++++
4 files changed, 55 insertions(+)
diff --git a/arch/x86/include/asm/msr-index.h b/arch/x86/include/asm/msr-index.h
index feee92aab504..46ca6b56628b 100644
--- a/arch/x86/include/asm/msr-index.h
+++ b/arch/x86/include/asm/msr-index.h
@@ -1241,6 +1241,10 @@
#define MSR_CORE_PERF_GLOBAL_CTRL 0x0000038f
#define MSR_CORE_PERF_GLOBAL_OVF_CTRL 0x00000390
#define MSR_CORE_PERF_GLOBAL_STATUS_SET 0x00000391
+#define MSR_CORE_PERF_GLOBAL_INUSE 0x00000392
+
+/* Intel IA32_PERF_GLOBAL_INUSE MSR */
+#define PERF_GLOBAL_INUSE_PMI_INUSE BIT_ULL(63)
#define MSR_PERF_METRICS 0x00000329
diff --git a/arch/x86/kvm/pmu.c b/arch/x86/kvm/pmu.c
index bc2ca60114e9..7d58f7a2a2db 100644
--- a/arch/x86/kvm/pmu.c
+++ b/arch/x86/kvm/pmu.c
@@ -834,6 +834,8 @@ bool kvm_pmu_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
case MSR_CORE_PERF_GLOBAL_CTRL:
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
return kvm_pmu_has_perf_global_ctrl(vcpu_to_pmu(vcpu));
+ case MSR_CORE_PERF_GLOBAL_STATUS_SET:
+ return vcpu_to_pmu(vcpu)->version > 3;
default:
break;
}
@@ -867,6 +869,7 @@ int kvm_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_CLR:
case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_SET:
case MSR_CORE_PERF_GLOBAL_OVF_CTRL:
+ case MSR_CORE_PERF_GLOBAL_STATUS_SET:
msr_info->data = 0;
break;
default:
@@ -933,6 +936,12 @@ int kvm_pmu_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
if (!msr_info->host_initiated)
pmu->global_status &= ~data;
break;
+ case MSR_CORE_PERF_GLOBAL_STATUS_SET:
+ if (data & pmu->global_status_rsvd)
+ return 1;
+ if (!msr_info->host_initiated)
+ pmu->global_status |= data;
+ break;
case MSR_AMD64_PERF_CNTR_GLOBAL_STATUS_SET:
if (!msr_info->host_initiated)
pmu->global_status |= data & ~pmu->global_status_rsvd;
diff --git a/arch/x86/kvm/vmx/pmu_intel.c b/arch/x86/kvm/vmx/pmu_intel.c
index 425f17aa9be2..cb6f9c272e03 100644
--- a/arch/x86/kvm/vmx/pmu_intel.c
+++ b/arch/x86/kvm/vmx/pmu_intel.c
@@ -205,6 +205,8 @@ static bool intel_is_valid_msr(struct kvm_vcpu *vcpu, u32 msr)
switch (msr) {
case MSR_CORE_PERF_FIXED_CTR_CTRL:
return kvm_pmu_has_perf_global_ctrl(pmu);
+ case MSR_CORE_PERF_GLOBAL_INUSE:
+ return pmu->version > 3;
case MSR_PERF_METRICS:
return kvm_vcpu_has_perf_metrics(vcpu);
case MSR_IA32_PEBS_ENABLE:
@@ -354,6 +356,40 @@ static bool intel_pmu_handle_lbr_msrs_access(struct kvm_vcpu *vcpu,
return true;
}
+static int intel_pmu_get_global_inuse(struct kvm_vcpu *vcpu,
+ struct msr_data *msr_info)
+{
+ struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
+ unsigned long fixed_mask = kvm_fixed_pmc_mask(pmu);
+ unsigned long gp_mask = kvm_gp_pmc_mask(pmu);
+ bool pmi_inuse = false;
+ u32 fixed_ctrl;
+ u64 eventsel;
+ int i;
+
+ msr_info->data = 0;
+ kvm_for_each_set_pmc_idx(i, gp_mask, INTEL_GP) {
+ eventsel = pmu->gp_counters[i].eventsel;
+
+ if (eventsel & ARCH_PERFMON_EVENTSEL_EVENT)
+ msr_info->data |= BIT_ULL(i);
+ pmi_inuse |= eventsel & ARCH_PERFMON_EVENTSEL_INT;
+ }
+ kvm_for_each_set_pmc_idx(i, fixed_mask, INTEL_FIXED) {
+ fixed_ctrl = fixed_ctrl_field(pmu->fixed_ctr_ctrl, i);
+
+ if (fixed_ctrl & (INTEL_FIXED_0_KERNEL | INTEL_FIXED_0_USER))
+ msr_info->data |= BIT_ULL(KVM_FIXED_PMC_BASE_IDX + i);
+ pmi_inuse |= fixed_ctrl & INTEL_FIXED_0_ENABLE_PMI;
+ }
+ pmi_inuse |= pmu->pebs_enable;
+
+ if (pmi_inuse)
+ msr_info->data |= PERF_GLOBAL_INUSE_PMI_INUSE;
+
+ return 0;
+}
+
static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
{
struct kvm_pmu *pmu = vcpu_to_pmu(vcpu);
@@ -364,6 +400,8 @@ static int intel_pmu_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
case MSR_CORE_PERF_FIXED_CTR_CTRL:
msr_info->data = pmu->fixed_ctr_ctrl;
break;
+ case MSR_CORE_PERF_GLOBAL_INUSE:
+ return intel_pmu_get_global_inuse(vcpu, msr_info);
case MSR_PERF_METRICS:
msr_info->data = pmu->perf_metrics;
break;
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 2a59bbe52bd8..c69cda5bb898 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -4278,6 +4278,10 @@ static void vmx_recalc_pmu_msr_intercepts(struct kvm_vcpu *vcpu)
MSR_TYPE_RW, intercept);
vmx_set_intercept_for_msr(vcpu, MSR_CORE_PERF_GLOBAL_OVF_CTRL,
MSR_TYPE_RW, intercept);
+ vmx_set_intercept_for_msr(vcpu, MSR_CORE_PERF_GLOBAL_STATUS_SET,
+ MSR_TYPE_RW, intercept || pmu->version < 4);
+ vmx_set_intercept_for_msr(vcpu, MSR_CORE_PERF_GLOBAL_INUSE,
+ MSR_TYPE_RW, intercept || pmu->version < 4);
intercept = !has_mediated_pmu || !kvm_vcpu_has_perf_metrics(vcpu);
vmx_set_intercept_for_msr(vcpu, MSR_PERF_METRICS,
--
2.54.0
next prev parent reply other threads:[~2026-07-07 18:44 UTC|newest]
Thread overview: 16+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-07 18:33 [PATCH 00/15] KVM: x86/pmu: Add mediated vPMU PerfMon v5 support Zide Chen
2026-07-07 18:33 ` [PATCH 01/15] KVM: x86/pmu: Remove redundant Perf Global Status MSR bit definitions Zide Chen
2026-07-07 18:33 ` [PATCH 02/15] KVM: x86/pmu: Rename all_valid_pmc_idx to all_valid_pmc_mask Zide Chen
2026-07-07 18:33 ` [PATCH 03/15] KVM: x86/pmu: Rename reserved_bits to eventsel_rsvd in kvm_pmu Zide Chen
2026-07-07 18:33 ` [PATCH 04/15] KVM: x86/pmu: Add PMC bitmap accessor helpers Zide Chen
2026-07-07 18:33 ` [PATCH 05/15] KVM: x86/pmu: Drop nr_arch_{gp,fixed}_counters from kvm_pmu Zide Chen
2026-07-07 18:33 ` [PATCH 06/15] KVM: x86/pmu: Expose kvm_host_pmu to vendor modules Zide Chen
2026-07-07 18:33 ` [PATCH 07/15] perf/x86: Plumb counter bitmap from x86_pmu to x86_pmu_cap Zide Chen
2026-07-07 18:33 ` [PATCH 08/15] KVM: x86/pmu: Switch to bitmask-based KVM PMU capabilities Zide Chen
2026-07-07 18:33 ` [PATCH 09/15] perf/x86: Remove num_counters_{gp,fixed} from x86_pmu_capability Zide Chen
2026-07-07 18:34 ` Zide Chen [this message]
2026-07-07 18:34 ` [PATCH 11/15] KVM: x86/pmu: Emulate streamlined Freeze-LBR-on-PMI Zide Chen
2026-07-07 18:34 ` [PATCH 12/15] KVM: x86/pmu: Populate CPUID.0AH:ECX fixed-counter bitmap Zide Chen
2026-07-07 18:34 ` [PATCH 13/15] KVM: x86/pmu: Ignore AnyThread bit if CPUID.0AH:EDX[15] is not set Zide Chen
2026-07-07 18:34 ` [PATCH 14/15] KVM: x86/pmu: Advertise PerfMon version 5 on Intel hosts Zide Chen
2026-07-07 18:34 ` [PATCH 15/15] KVM: selftests: Support fixed counters bitmap in pmu_counters_test Zide Chen
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20260707183405.15571-11-zide.chen@intel.com \
--to=zide.chen@intel.com \
--cc=Manali.Shukla@amd.com \
--cc=Sandipan.Das@amd.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=jmattson@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mizhang@google.com \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=seanjc@google.com \
--cc=thomas.falcon@intel.com \
--cc=weijiang.yang@intel.com \
--cc=xudong.hao@intel.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.