From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from mail-pj1-f73.google.com (mail-pj1-f73.google.com [209.85.216.73]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AADE02459C9 for ; Sat, 6 Dec 2025 00:17:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.216.73 ARC-Seal:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764980266; cv=none; b=k9kHMPtKP9Dl+AVd1BRgWPRm41G73Jfjtbd/vKuG1+Rcq2+zUPuwziDphOyCsXMZQ7KYYxD6iL0llLKh4DeKZcH13STaf/Ubvnt6ijU6K2m7iDzOaMWRig129a8Q08KZwgC8dYgl4PqomrDgsBplJbXJPcl5F85uvBpisgMVIqY= ARC-Message-Signature:i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1764980266; c=relaxed/simple; bh=tgwd5Esq4wpmewehCZ8NiFmYgLVHlgDnHG/ez6ZtIJc=; h=Date:In-Reply-To:Mime-Version:References:Message-ID:Subject:From: To:Cc:Content-Type; b=Ra9XNhYHxohQ9VJ8QLpX173Ti7y53osDoC87ftgkiCKq85GDzpFZXFf2sIV+tUzpk/sFh+1U9YnyaqQ14op/Nq60zkBjDO56iL9edAEHWf0oLbACPtitVFL9rCknUsfogEU2bnS5wSvPg2pPOdxltmwg5xHjQ/k1L78yUWWiGLI= ARC-Authentication-Results:i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b=DskE6ray; arc=none smtp.client-ip=209.85.216.73 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=google.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=flex--seanjc.bounces.google.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=google.com header.i=@google.com header.b="DskE6ray" Received: by mail-pj1-f73.google.com with SMTP id 98e67ed59e1d1-341616a6fb7so2792729a91.0 for ; Fri, 05 Dec 2025 16:17:44 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1764980264; x=1765585064; darn=vger.kernel.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:from:to:cc:subject:date:message-id:reply-to; bh=b3rwpX75fYsvQxObK18NSjc+CmweVuoOUNJF4J3Ucww=; b=DskE6rayxgJCh16+iTeDIsI6fXNSQV0iczfaKlwm732BE5bWrN0W6QysFfPAUmI4Da /J1pjEhNq+8Mr4Q4IsCNlIujltCq2SoTosP4xHZhE8OzNjbAvWpWEIu91FsOtBwwJodZ gtOZ3uhqjzObJ9526oouzRVw/77Iz5JCMl4MP4Z6nOWKFsXIF6ZVbYC/polyYmGYRlTK 30XwYKCyZxuVsQ5e7tPgc1OwNDcEVGAdUpaKCKofcby/Ju7hbz2cy7tUVyiaIVDVNdsB m9QOG9fQ0vzQQSRhsgn41XKb1XJ67QDLhShOxozCsNcAAdIJI3qfdIi0prXdmtDkepTv T5IA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1764980264; x=1765585064; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:reply-to:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=b3rwpX75fYsvQxObK18NSjc+CmweVuoOUNJF4J3Ucww=; b=j9v/Y6UvjsmjZtuqkZVqSlaGE+9BezdZu4+69amkppJn96Ni+GyISDkxuQaKJPGvIH NSXP56U3eclAqYDS0cdC5v2efwSAArPNskdcbhciI8T/HByR+ZfigWyR/DOvhAuSnOmA b7EP+RdJ6Oc8rPywqx8zx57xWev8Px3aaqqzAw5XErm1RwmL91wzLyhK14x/AM9y2nj+ GQ/8SzKs2yYQun+lPow/U+p6zF5uv+JAApVM2whSjedcmOFnRvRC1HPFisqs5AJj9BxN lnUTZBfvI1W97/JI+CKxMxsjp0DTfDCDwdcw7cL0OjT5J9vud2Pk6K7SQ+6GSE1hRIii /91Q== X-Forwarded-Encrypted: i=1; AJvYcCUw4HF1WXs1Uf25jK3XwJbz9c29Sod0IDifrSqV2Hy/pSui3BSxW3jRxujXBaabSr5YRcBF9/v290FAdsCvA1cb@vger.kernel.org X-Gm-Message-State: AOJu0YzoTP9dOnyT/gS74Ujqhui3uXpRu9cwq/B2r1eew02ENy7cryTD 7MX+4ODJLtxG4WhqYs3qEzuWfLB5DBsAy3YMn7DCVLoskkjyKPh/NanIlPW33tGE9zYoYz6hsj7 hTs/6cA== X-Google-Smtp-Source: AGHT+IHEsD7fkDDlHKveCIETTAnzxygk5RYBYlDb1QrkU4F4qH52QVESGYT3XJZIm6BuCoPrCdtcsD42SZs= X-Received: from pjbbf17.prod.google.com ([2002:a17:90b:b11:b0:33b:dccb:b328]) (user=seanjc job=prod-delivery.src-stubby-dispatcher) by 2002:a17:90b:2750:b0:349:9dc4:fa35 with SMTP id 98e67ed59e1d1-349a2622069mr652583a91.25.1764980263863; Fri, 05 Dec 2025 16:17:43 -0800 (PST) Reply-To: Sean Christopherson Date: Fri, 5 Dec 2025 16:16:45 -0800 In-Reply-To: <20251206001720.468579-1-seanjc@google.com> Precedence: bulk X-Mailing-List: linux-perf-users@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: Mime-Version: 1.0 References: <20251206001720.468579-1-seanjc@google.com> X-Mailer: git-send-email 2.52.0.223.gf5cc29aaa4-goog Message-ID: <20251206001720.468579-10-seanjc@google.com> Subject: [PATCH v6 09/44] perf/x86/core: Add APIs to switch to/from mediated PMI vector (for KVM) From: Sean Christopherson To: Marc Zyngier , Oliver Upton , Tianrui Zhao , Bibo Mao , Huacai Chen , Anup Patel , Paul Walmsley , Palmer Dabbelt , Albert Ou , Xin Li , "H. Peter Anvin" , Andy Lutomirski , Peter Zijlstra , Ingo Molnar , Arnaldo Carvalho de Melo , Namhyung Kim , Sean Christopherson , Paolo Bonzini Cc: linux-arm-kernel@lists.infradead.org, kvmarm@lists.linux.dev, kvm@vger.kernel.org, loongarch@lists.linux.dev, kvm-riscv@lists.infradead.org, linux-riscv@lists.infradead.org, linux-kernel@vger.kernel.org, linux-perf-users@vger.kernel.org, Mingwei Zhang , Xudong Hao , Sandipan Das , Dapeng Mi , Xiong Zhang , Manali Shukla , Jim Mattson Content-Type: text/plain; charset="UTF-8" Add APIs (exported only for KVM) to switch PMIs to the dedicated mediated PMU IRQ vector when loading guest context, and back to perf's standard NMI when the guest context is put. I.e. route PMIs to PERF_GUEST_MEDIATED_PMI_VECTOR when the guest context is active, and to NMIs while the host context is active. While running with guest context loaded, ignore all NMIs (in perf). Any NMI that arrives while the LVTPC points at the mediated PMU IRQ vector can't possibly be due to a host perf event. Signed-off-by: Sean Christopherson --- arch/x86/events/core.c | 32 +++++++++++++++++++++++++++++++ arch/x86/include/asm/perf_event.h | 5 +++++ 2 files changed, 37 insertions(+) diff --git a/arch/x86/events/core.c b/arch/x86/events/core.c index fa6c47b50989..abe6a129a87f 100644 --- a/arch/x86/events/core.c +++ b/arch/x86/events/core.c @@ -55,6 +55,8 @@ DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = { .pmu = &pmu, }; +static DEFINE_PER_CPU(bool, guest_lvtpc_loaded); + DEFINE_STATIC_KEY_FALSE(rdpmc_never_available_key); DEFINE_STATIC_KEY_FALSE(rdpmc_always_available_key); DEFINE_STATIC_KEY_FALSE(perf_is_hybrid); @@ -1749,6 +1751,25 @@ void perf_events_lapic_init(void) apic_write(APIC_LVTPC, APIC_DM_NMI); } +#ifdef CONFIG_PERF_GUEST_MEDIATED_PMU +void perf_load_guest_lvtpc(u32 guest_lvtpc) +{ + u32 masked = guest_lvtpc & APIC_LVT_MASKED; + + apic_write(APIC_LVTPC, + APIC_DM_FIXED | PERF_GUEST_MEDIATED_PMI_VECTOR | masked); + this_cpu_write(guest_lvtpc_loaded, true); +} +EXPORT_SYMBOL_FOR_MODULES(perf_load_guest_lvtpc, "kvm"); + +void perf_put_guest_lvtpc(void) +{ + this_cpu_write(guest_lvtpc_loaded, false); + apic_write(APIC_LVTPC, APIC_DM_NMI); +} +EXPORT_SYMBOL_FOR_MODULES(perf_put_guest_lvtpc, "kvm"); +#endif /* CONFIG_PERF_GUEST_MEDIATED_PMU */ + static int perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) { @@ -1756,6 +1777,17 @@ perf_event_nmi_handler(unsigned int cmd, struct pt_regs *regs) u64 finish_clock; int ret; + /* + * Ignore all NMIs when the CPU's LVTPC is configured to route PMIs to + * PERF_GUEST_MEDIATED_PMI_VECTOR, i.e. when an NMI time can't be due + * to a PMI. Attempting to handle a PMI while the guest's context is + * loaded will generate false positives and clobber guest state. Note, + * the LVTPC is switched to/from the dedicated mediated PMI IRQ vector + * while host events are quiesced. + */ + if (this_cpu_read(guest_lvtpc_loaded)) + return NMI_DONE; + /* * All PMUs/events that share this PMI handler should make sure to * increment active_events for their events. diff --git a/arch/x86/include/asm/perf_event.h b/arch/x86/include/asm/perf_event.h index 49a4d442f3fc..4cd38b9da0ba 100644 --- a/arch/x86/include/asm/perf_event.h +++ b/arch/x86/include/asm/perf_event.h @@ -651,6 +651,11 @@ static inline void perf_events_lapic_init(void) { } static inline void perf_check_microcode(void) { } #endif +#ifdef CONFIG_PERF_GUEST_MEDIATED_PMU +extern void perf_load_guest_lvtpc(u32 guest_lvtpc); +extern void perf_put_guest_lvtpc(void); +#endif + #if defined(CONFIG_PERF_EVENTS) && defined(CONFIG_CPU_SUP_INTEL) extern struct perf_guest_switch_msr *perf_guest_get_msrs(int *nr, void *data); extern void x86_perf_get_lbr(struct x86_pmu_lbr *lbr); -- 2.52.0.223.gf5cc29aaa4-goog