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, Andi Kleen <ak@linux.intel.com>,
Jim Mattson <jmattson@google.com>,
Stephane Eranian <eranian@google.com>,
linux-kernel@vger.kernel.org, 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>,
Xudong Hao <xudong.hao@intel.com>
Subject: [PATCH 02/23] perf, perf/x86: Pass partition mask from KVM to perf/x86
Date: Fri, 21 Aug 2026 15:19:41 -0700 [thread overview]
Message-ID: <20260821222002.54907-3-zide.chen@intel.com> (raw)
In-Reply-To: <20260821222002.54907-1-zide.chen@intel.com>
x86 PMU partitioning support requires mediated vPMU and is supported
only on Intel platforms. KVM is responsible for determining if PMU
partitioning can be enabled, and if so, it passes the mask to perf
core when creating a mediated PMU VM. The mask is host-wide state
shared by all mediated PMU guests.
Perf core passes the mask down to perf/x86 via the new callback
arch_perf_set_pmu_partition_mask(), which sanitizes it before applying
it to the newly added x86_pmu. The mask is cleared when the last
mediated PMU VM is released.
Note: PMU partitioning technically allows the host to run certain
!exclude_guest events while partitioned guests are running, as long as
such events don't use exclusive resources reserved for the guests. The
current behavior is kept: reject the creation of a partitioned guest
as long as any !exclude_guest host events exist.
Introduce PERF_PMU_CAP_PMU_PARTITION to indicate that the pmu supports
PMU partitioning. Note that virtualization of Intel PT and BTS is
currently unsupported; even if it were, this flag would not apply to
those PMUs, since their exclusive resources can't be shared between
host and guest, and their events are not subject to PMU partitioning
scheduling.
perf_create_mediated_pmu() is called with 0 for now; this will be
replaced with the actual partition_mask in a later patch.
Signed-off-by: Zide Chen <zide.chen@intel.com>
---
arch/x86/events/core.c | 58 ++++++++++++++++++++++++++++++++++++
arch/x86/events/perf_event.h | 9 ++++++
arch/x86/kvm/x86.c | 2 +-
include/linux/perf_event.h | 4 ++-
kernel/events/core.c | 19 +++++++++---
5 files changed, 86 insertions(+), 6 deletions(-)
diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c
index 9b6df8bc9059..8032311c0a47 100644
--- a/arch/x86/events/core.c
+++ b/arch/x86/events/core.c
@@ -2773,6 +2773,64 @@ static bool x86_pmu_filter(struct pmu *pmu, int cpu)
return ret;
}
+/**
+ * arch_perf_set_pmu_partition_mask - Validate and set the VM-owned counter
+ * mask for mediated vPMU
+ * @partition_mask: Bitmask of PMU counters or other hardware resources
+ * to hand over to mediated vPMU guests. 0 disables PMU
+ * partitioning, as in the legacy model.
+ *
+ * Called via perf_create_mediated_pmu() to validate @partition_mask and,
+ * if valid, record it in x86_pmu.partition_mask for use by the
+ * scheduler, and set PERF_PMU_CAP_PMU_PARTITION on the generic PMU so
+ * perf core can check it without reaching into x86-private state.
+ *
+ * Return: 0 on success, -errno otherwise.
+ */
+int arch_perf_set_pmu_partition_mask(u64 partition_mask)
+{
+ u64 current_mask = READ_ONCE(x86_pmu.partition_mask);
+ struct pmu *pmu;
+
+ /* Non-paritioned mediated guests fall into this case. */
+ if (current_mask == partition_mask)
+ return 0;
+
+ /*
+ * AMD does not yet implement the hardware support for PMU partitioning
+ * between host and guest. Thus limit it to Intel platforms with the
+ * PerfMon masking VMX extension. Leave it to KVM to check the VMX
+ * feature. KVM doesn't support vPMU on Hybrid CPUs at all.
+ */
+ if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL || is_hybrid())
+ return -EOPNOTSUPP;
+
+ pmu = x86_get_pmu(raw_smp_processor_id());
+ if (!(pmu->capabilities & PERF_PMU_CAP_MEDIATED_VPMU))
+ return -EOPNOTSUPP;
+
+ /*
+ * If a mediated-PMU VM was already created, the configured mask
+ * cannot be changed.
+ */
+ if (current_mask && partition_mask)
+ return -EINVAL;
+
+ /*
+ * perf/core guarantees that this path is reached only after all
+ * partitioned guests have been released.
+ */
+ if (!partition_mask) {
+ WRITE_ONCE(x86_pmu.partition_mask, 0);
+ pmu->capabilities &= ~PERF_PMU_CAP_PMU_PARTITION;
+ return 0;
+ }
+
+ WRITE_ONCE(x86_pmu.partition_mask, partition_mask);
+ pmu->capabilities |= PERF_PMU_CAP_PMU_PARTITION;
+ return 0;
+}
+
static struct pmu pmu = {
.pmu_enable = x86_pmu_enable,
.pmu_disable = x86_pmu_disable,
diff --git a/arch/x86/events/perf_event.h b/arch/x86/events/perf_event.h
index eae24bb35dc1..19beb16baa8e 100644
--- a/arch/x86/events/perf_event.h
+++ b/arch/x86/events/perf_event.h
@@ -883,6 +883,15 @@ struct x86_pmu {
int events_mask_len;
int apic;
u64 max_period;
+
+ /*
+ * Bitmask of PMU resources that may be assigned to a guest.
+ *
+ * The mask is set when the first mediated vPMU is created and is
+ * cleared when the last mediated vPMU is torn down.
+ */
+ u64 partition_mask;
+
struct event_constraint *
(*get_event_constraints)(struct cpu_hw_events *cpuc,
int idx,
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index d349224d2734..5f3215915c76 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -9328,7 +9328,7 @@ int kvm_arch_vcpu_precreate(struct kvm *kvm, unsigned int id)
if (enable_mediated_pmu && kvm->arch.enable_pmu &&
!kvm->arch.created_mediated_pmu) {
if (irqchip_in_kernel(kvm)) {
- r = perf_create_mediated_pmu();
+ r = perf_create_mediated_pmu(0);
if (r) {
pr_warn_ratelimited(PERF_MEDIATED_PMU_MSG);
return r;
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 48d851fbd8ea..bd952e09055d 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -306,6 +306,7 @@ struct perf_event_pmu_context;
#define PERF_PMU_CAP_AUX_PAUSE 0x0200
#define PERF_PMU_CAP_AUX_PREFER_LARGE 0x0400
#define PERF_PMU_CAP_MEDIATED_VPMU 0x0800
+#define PERF_PMU_CAP_PMU_PARTITION 0x1000
/**
* pmu::scope
@@ -1931,10 +1932,11 @@ extern int perf_event_period(struct perf_event *event, u64 value);
extern u64 perf_event_pause(struct perf_event *event, bool reset);
#ifdef CONFIG_PERF_GUEST_MEDIATED_PMU
-int perf_create_mediated_pmu(void);
+int perf_create_mediated_pmu(u64 pmu_partition_mask);
void perf_release_mediated_pmu(void);
void perf_load_guest_context(void);
void perf_put_guest_context(void);
+int arch_perf_set_pmu_partition_mask(u64 pmu_partition_mask);
#endif
#else /* !CONFIG_PERF_EVENTS: */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index d7f3e2c2ecb1..9ce27cd83e04 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -6340,6 +6340,11 @@ static atomic_t nr_include_guest_events __read_mostly;
static atomic_t nr_mediated_pmu_vms __read_mostly;
static DEFINE_MUTEX(perf_mediated_pmu_mutex);
+int __weak arch_perf_set_pmu_partition_mask(u64 partition_mask)
+{
+ return partition_mask ? -EOPNOTSUPP : 0;
+}
+
/* !exclude_guest event of PMU with PERF_PMU_CAP_MEDIATED_VPMU */
static inline bool is_include_guest_event(struct perf_event *event)
{
@@ -6387,15 +6392,18 @@ static void mediated_pmu_unaccount_event(struct perf_event *event)
* No impact for the PMU without PERF_PMU_CAP_MEDIATED_VPMU. The perf
* still owns all the PMU resources.
*/
-int perf_create_mediated_pmu(void)
+int perf_create_mediated_pmu(u64 partition_mask)
{
- if (atomic_inc_not_zero(&nr_mediated_pmu_vms))
- return 0;
+ int ret;
guard(mutex)(&perf_mediated_pmu_mutex);
if (atomic_read(&nr_include_guest_events))
return -EBUSY;
+ ret = arch_perf_set_pmu_partition_mask(partition_mask);
+ if (ret)
+ return ret;
+
atomic_inc(&nr_mediated_pmu_vms);
return 0;
}
@@ -6403,10 +6411,13 @@ EXPORT_SYMBOL_FOR_KVM(perf_create_mediated_pmu);
void perf_release_mediated_pmu(void)
{
+ guard(mutex)(&perf_mediated_pmu_mutex);
+
if (WARN_ON_ONCE(!atomic_read(&nr_mediated_pmu_vms)))
return;
- atomic_dec(&nr_mediated_pmu_vms);
+ if (atomic_dec_and_test(&nr_mediated_pmu_vms))
+ arch_perf_set_pmu_partition_mask(0);
}
EXPORT_SYMBOL_FOR_KVM(perf_release_mediated_pmu);
--
2.55.0
next prev parent reply other threads:[~2026-08-21 22:30 UTC|newest]
Thread overview: 24+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-21 22:19 [PATCH 00/23] perf/KVM: Support PMU partitioning for x86 platforms Zide Chen
2026-08-21 22:19 ` [PATCH 01/23] perf/x86/intel: Guard counter masks against zero counters Zide Chen
2026-08-21 22:19 ` Zide Chen [this message]
2026-08-21 22:19 ` [PATCH 03/23] perf/x86: Add GUEST_PMU states for PMU partitioning Zide Chen
2026-08-21 22:19 ` [PATCH 04/23] perf/x86: Split host/guest PMI handling under " Zide Chen
2026-08-21 22:19 ` [PATCH 05/23] perf/x86: Allow exclude_host events to run in non-root mode Zide Chen
2026-08-21 22:19 ` [PATCH 06/23] perf/x86: Restrict !exclude_guest events to host-owned counters Zide Chen
2026-08-21 22:19 ` [PATCH 07/23] perf/x86: Apply PMU partition mask on static constraints Zide Chen
2026-08-21 22:19 ` [PATCH 08/23] perf/x86: Export available PMU counters to sysfs Zide Chen
2026-08-21 22:19 ` [PATCH 09/23] perf: Skip exclude_guest events on PMU partitioned counters Zide Chen
2026-08-21 22:19 ` [PATCH 10/23] perf: Reschedule events across PMU partition transitions Zide Chen
2026-08-21 22:19 ` [PATCH 11/23] perf, perf/x86: Allow host !exclude_guest events in PMU partitioning Zide Chen
2026-08-21 22:19 ` [PATCH 12/23] KVM: x86/pmu: Add the perfmon_mask module parameter Zide Chen
2026-08-21 22:19 ` [PATCH 13/23] KVM: x86/pmu: Set up the PERFMON_MASK VMCS field Zide Chen
2026-08-21 22:19 ` [PATCH 14/23] KVM: x86/pmu, perf/x86: Update effective PMU partition mask Zide Chen
2026-08-21 22:19 ` [PATCH 15/23] KVM: x86/pmu: Relax MSR intercept policy under PerfMon masking Zide Chen
2026-08-21 22:19 ` [PATCH 16/23] KVM: x86/pmu: Handle FIXED_CTR_CTRL " Zide Chen
2026-08-21 22:19 ` [PATCH 17/23] KVM: x86/pmu: Handle GLOBAL_CTRL " Zide Chen
2026-08-21 22:19 ` [PATCH 18/23] KVM: x86/pmu: Handle GLOBAL_STATUS MSRs " Zide Chen
2026-08-21 22:19 ` [PATCH 19/23] KVM: x86/pmu: Always intercept GLOBAL_INUSE " Zide Chen
2026-08-21 22:19 ` [PATCH 20/23] KVM: x86/pmu: Request guest PMI for guest-induced PMIs Zide Chen
2026-08-21 22:20 ` [PATCH 21/23] KVM: x86/pmu: Enable PerfMon masking Zide Chen
2026-08-21 22:20 ` [PATCH 22/23] KVM: selftests: Fix PERF_METRICS test by checking FC3 availability Zide Chen
2026-08-21 22:20 ` [PATCH 23/23] KVM: selftests: Allow no general purpose counters on the host 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=20260821222002.54907-3-zide.chen@intel.com \
--to=zide.chen@intel.com \
--cc=Manali.Shukla@amd.com \
--cc=Sandipan.Das@amd.com \
--cc=ak@linux.intel.com \
--cc=dapeng1.mi@linux.intel.com \
--cc=eranian@google.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=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.