aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
authorSean Christopherson <seanjc@google.com>2026-09-21 12:14:11 -0700
committerIngo Molnar <mingo@kernel.org>2026-09-22 11:09:14 +0200
commitd06260e99eb93d2942b7af4ccd789eb8a6c829d3 (patch)
treee2a70d5caf47e8f9d1873d81ef7afb5212ea03c4
parentperf/x86/intel: Don't write PEBS_ENABLED on host<=>guest xfers if CPU has PEBS isolation, to fix stuck PEBS_ENABLED (diff)
perf/x86/intel: Don't pointlessly context switch DS_AREA (and PEBS config) if PEBS is unused
When filling the list of MSRs to be loaded by KVM on VM-Enter and VM-Exit, load the guest values for DS_AREA and (conditionally) MSR_PEBS_DATA_CFG if and only if PEBS will be active in the guest, i.e. only if a PEBS record may be generated while running the guest. As shown by the !pebs_ept path, it's perfectly safe to run with the host's DS_AREA, so long as PEBS-enabled counters are disabled via PERF_GLOBAL_CTRL. Omitting DS_AREA and MSR_PEBS_DATA_CFG when PEBS is unused saves two MSR writes per MSR on each VMX transition, i.e. eliminates two/four pointless MSR writes on each VMX roundtrip when PEBS isn't being used by the guest. Fixes: c59a1f106f5c ("KVM: x86/pmu: Add IA32_PEBS_ENABLE MSR emulation for extended PEBS") Signed-off-by: Sean Christopherson <seanjc@google.com> Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org> Signed-off-by: Ingo Molnar <mingo@kernel.org> Reviewed-by: Jim Mattson <jmattson@google.com> Reviewed-by: Dapeng Mi <dapeng1.mi@linux.intel.com> Link: https://patch.msgid.link/20260921191418.950933-4-seanjc@google.com
-rw-r--r--arch/x86/events/intel/core.c39
1 files changed, 25 insertions, 14 deletions
diff --git a/arch/x86/events/intel/core.c b/arch/x86/events/intel/core.c
index 5ac8fe31871b..75c74e8fe2f4 100644
--- a/arch/x86/events/intel/core.c
+++ b/arch/x86/events/intel/core.c
@@ -5330,23 +5330,14 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
return arr;
}
+ /*
+ * If the guest won't use PEBS or the CPU doesn't support PEBS in the
+ * guest, then there's nothing more to do as disabling PMCs via
+ * PERF_GLOBAL_CTRL is sufficient on CPUs with guest/host isolation.
+ */
if (!kvm_pmu || !x86_pmu.pebs_ept)
return arr;
- arr[(*nr)++] = (struct perf_guest_switch_msr){
- .msr = MSR_IA32_DS_AREA,
- .host = (unsigned long)cpuc->ds,
- .guest = kvm_pmu->ds_area,
- };
-
- if (x86_pmu.intel_cap.pebs_baseline) {
- arr[(*nr)++] = (struct perf_guest_switch_msr){
- .msr = MSR_PEBS_DATA_CFG,
- .host = cpuc->active_pebs_data_cfg,
- .guest = kvm_pmu->pebs_data_cfg,
- };
- }
-
/*
* Restrict guest PEBS events to counters that (a) perf supports, (b)
* the guest wants to use for PEBS, (c) are not excluded from counting
@@ -5374,6 +5365,26 @@ static struct perf_guest_switch_msr *intel_guest_get_msrs(int *nr, void *data)
guest_pebs_mask = 0;
/*
+ * Context switch DS_AREA and PEBS_DATA_CFG if and only if PEBS will be
+ * active in the guest; if no records will be generated while the guest
+ * is running, then simply keep the host values resident in hardware.
+ */
+ arr[(*nr)++] = (struct perf_guest_switch_msr){
+ .msr = MSR_IA32_DS_AREA,
+ .host = (unsigned long)cpuc->ds,
+ .guest = guest_pebs_mask ? kvm_pmu->ds_area : (unsigned long)cpuc->ds,
+ };
+
+ if (x86_pmu.intel_cap.pebs_baseline) {
+ arr[(*nr)++] = (struct perf_guest_switch_msr){
+ .msr = MSR_PEBS_DATA_CFG,
+ .host = cpuc->active_pebs_data_cfg,
+ .guest = guest_pebs_mask ? kvm_pmu->pebs_data_cfg :
+ cpuc->active_pebs_data_cfg,
+ };
+ }
+
+ /*
* Do NOT mess with PEBS_ENABLED. As above, disabling counters via
* PERF_GLOBAL_CTRL is sufficient, and loading a stale PEBS_ENABLED,
* e.g. on VM-Exit, can put the system in a bad state. Simply enable