From: "Masami Hiramatsu (Google)" <mhiramat@kernel.org>
To: Steven Rostedt <rostedt@goodmis.org>,
Peter Zijlstra <peterz@infradead.org>,
Ingo Molnar <mingo@kernel.org>,
Sean Christopherson <seanjc@google.com>
Cc: Jinchao Wang <wangjinchao600@gmail.com>,
Mathieu Desnoyers <mathieu.desnoyers@efficios.com>,
Masami Hiramatsu <mhiramat@kernel.org>,
Thomas Gleixner <tglx@linutronix.de>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>,
"H . Peter Anvin" <hpa@zytor.com>,
Alexander Shishkin <alexander.shishkin@linux.intel.com>,
Ian Rogers <irogers@google.com>,
linux-kernel@vger.kernel.org, linux-trace-kernel@vger.kernel.org,
linux-doc@vger.kernel.org, linux-perf-users@vger.kernel.org,
x86@kernel.org, Paolo Bonzini <pbonzini@redhat.com>,
kvm@vger.kernel.org
Subject: [PATCH v17 02/13] perf/x86, KVM: Prevent host debug register leak into guest OS on NMI
Date: Tue, 22 Sep 2026 13:25:07 +0900 [thread overview]
Message-ID: <179005110742.388919.1509641807739909065.stgit@devnote2> (raw)
In-Reply-To: <179005108298.388919.4535333252892590932.stgit@devnote2>
From: Masami Hiramatsu (Google) <mhiramat@kernel.org>
When KVM enters a guest OS, host hardware breakpoints are disabled
before running the guest. However, an NMI can occur while executing
in guest mode or during guest transition, where
arch_install_hw_breakpoint() can be invoked from NMI context.
If arch_install_hw_breakpoint() is executed while the CPU is in guest
mode or during the VM entry transition window, hardware debug registers
can be modified with host breakpoint settings, leaking host breakpoints
into the guest OS or clobbering the guest's debug registers.
To prevent this without introducing ad-hoc per-CPU flags, introduce an
.in_guest callback to struct perf_guest_info_callbacks and an inline
helper perf_guest_in_guest(). In KVM, implement .in_guest by checking
whether the current vCPU is in IN_GUEST_MODE or EXITING_GUEST_MODE.
In arch_install_hw_breakpoint(), check perf_guest_in_guest() and return
-EBUSY if the CPU is running or transitioning to/from a guest.
Fixes: f85d40160691 ("KVM: X86: Disable hardware breakpoints unconditionally before kvm_x86->run()")
Assisted-by: Antigravity:gemini-3.8-flash
Signed-off-by: Masami Hiramatsu (Google) <mhiramat@kernel.org>
---
Changes in v17:
- Drop changes to local_db_save() and local_db_restore().
- Drop cpu_dr_in_guest per-CPU flag.
- Introduce .in_guest callback in perf_guest_info_callbacks and
perf_guest_in_guest() helper to query vcpu->mode.
(avoid breaking perf_guest_state() users)
- In arch_install_hw_breakpoint(), check perf_guest_in_guest()
Changes in v16:
- Newly added.
---
arch/x86/kernel/hw_breakpoint.c | 3 +++
include/linux/perf_event.h | 9 ++++++++-
kernel/events/core.c | 5 +++++
virt/kvm/kvm_main.c | 12 ++++++++++++
4 files changed, 28 insertions(+), 1 deletion(-)
diff --git a/arch/x86/kernel/hw_breakpoint.c b/arch/x86/kernel/hw_breakpoint.c
index f846c15f21ca..0473a5c95856 100644
--- a/arch/x86/kernel/hw_breakpoint.c
+++ b/arch/x86/kernel/hw_breakpoint.c
@@ -102,6 +102,9 @@ int arch_install_hw_breakpoint(struct perf_event *bp)
lockdep_assert_irqs_disabled();
+ if (perf_guest_in_guest())
+ return -EBUSY;
+
for (i = 0; i < HBP_NUM; i++) {
struct perf_event **slot = this_cpu_ptr(&bp_per_reg[i]);
diff --git a/include/linux/perf_event.h b/include/linux/perf_event.h
index 5842552294c1..194e69270460 100644
--- a/include/linux/perf_event.h
+++ b/include/linux/perf_event.h
@@ -1677,8 +1677,8 @@ struct perf_guest_info_callbacks {
unsigned int (*state)(void);
unsigned long (*get_ip)(void);
unsigned int (*handle_intel_pt_intr)(void);
-
void (*handle_mediated_pmi)(void);
+ bool (*in_guest)(void);
};
#ifdef CONFIG_GUEST_PERF_EVENTS
@@ -1689,6 +1689,7 @@ DECLARE_STATIC_CALL(__perf_guest_state, *perf_guest_cbs->state);
DECLARE_STATIC_CALL(__perf_guest_get_ip, *perf_guest_cbs->get_ip);
DECLARE_STATIC_CALL(__perf_guest_handle_intel_pt_intr, *perf_guest_cbs->handle_intel_pt_intr);
DECLARE_STATIC_CALL(__perf_guest_handle_mediated_pmi, *perf_guest_cbs->handle_mediated_pmi);
+DECLARE_STATIC_CALL(__perf_guest_in_guest, *perf_guest_cbs->in_guest);
static inline unsigned int perf_guest_state(void)
{
@@ -1710,6 +1711,11 @@ static inline void perf_guest_handle_mediated_pmi(void)
static_call(__perf_guest_handle_mediated_pmi)();
}
+static inline bool perf_guest_in_guest(void)
+{
+ return static_call(__perf_guest_in_guest)();
+}
+
extern void perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs);
extern void perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs);
@@ -1718,6 +1724,7 @@ extern void perf_unregister_guest_info_callbacks(struct perf_guest_info_callback
static inline unsigned int perf_guest_state(void) { return 0; }
static inline unsigned long perf_guest_get_ip(void) { return 0; }
static inline unsigned int perf_guest_handle_intel_pt_intr(void) { return 0; }
+static inline bool perf_guest_in_guest(void) { return false; }
#endif /* !CONFIG_GUEST_PERF_EVENTS */
diff --git a/kernel/events/core.c b/kernel/events/core.c
index a6c8e38a3110..c5dead7c5f71 100644
--- a/kernel/events/core.c
+++ b/kernel/events/core.c
@@ -7749,6 +7749,7 @@ DEFINE_STATIC_CALL_RET0(__perf_guest_state, *perf_guest_cbs->state);
DEFINE_STATIC_CALL_RET0(__perf_guest_get_ip, *perf_guest_cbs->get_ip);
DEFINE_STATIC_CALL_RET0(__perf_guest_handle_intel_pt_intr, *perf_guest_cbs->handle_intel_pt_intr);
DEFINE_STATIC_CALL_RET0(__perf_guest_handle_mediated_pmi, *perf_guest_cbs->handle_mediated_pmi);
+DEFINE_STATIC_CALL_RET0(__perf_guest_in_guest, *perf_guest_cbs->in_guest);
void perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs)
{
@@ -7767,6 +7768,9 @@ void perf_register_guest_info_callbacks(struct perf_guest_info_callbacks *cbs)
if (cbs->handle_mediated_pmi)
static_call_update(__perf_guest_handle_mediated_pmi,
cbs->handle_mediated_pmi);
+
+ if (cbs->in_guest)
+ static_call_update(__perf_guest_in_guest, cbs->in_guest);
}
EXPORT_SYMBOL_GPL(perf_register_guest_info_callbacks);
@@ -7780,6 +7784,7 @@ void perf_unregister_guest_info_callbacks(struct perf_guest_info_callbacks *cbs)
static_call_update(__perf_guest_get_ip, (void *)&__static_call_return0);
static_call_update(__perf_guest_handle_intel_pt_intr, (void *)&__static_call_return0);
static_call_update(__perf_guest_handle_mediated_pmi, (void *)&__static_call_return0);
+ static_call_update(__perf_guest_in_guest, (void *)&__static_call_return0);
synchronize_rcu();
}
EXPORT_SYMBOL_GPL(perf_unregister_guest_info_callbacks);
diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c
index 65eb26a0520d..7779d500fe77 100644
--- a/virt/kvm/kvm_main.c
+++ b/virt/kvm/kvm_main.c
@@ -6476,11 +6476,23 @@ static unsigned long kvm_guest_get_ip(void)
return kvm_arch_vcpu_get_ip(vcpu);
}
+static bool kvm_guest_in_guest(void)
+{
+ struct kvm_vcpu *vcpu = kvm_get_running_vcpu();
+
+ if (!vcpu)
+ return false;
+
+ return READ_ONCE(vcpu->mode) == IN_GUEST_MODE ||
+ READ_ONCE(vcpu->mode) == EXITING_GUEST_MODE;
+}
+
static struct perf_guest_info_callbacks kvm_guest_cbs = {
.state = kvm_guest_state,
.get_ip = kvm_guest_get_ip,
.handle_intel_pt_intr = NULL,
.handle_mediated_pmi = NULL,
+ .in_guest = kvm_guest_in_guest,
};
void __kvm_register_perf_callbacks(unsigned int (*pt_intr_handler)(void),
next prev parent reply other threads:[~2026-09-22 4:25 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 4:24 [PATCH v17 00/13] tracing: wprobe: x86: Add wprobe for watchpoint Masami Hiramatsu (Google)
2026-09-22 4:24 ` [PATCH v17 01/13] x86/mce: Fix hardware debug register corruption on task migration Masami Hiramatsu (Google)
2026-09-23 0:27 ` Borislav Petkov
2026-09-23 8:46 ` Peter Zijlstra
2026-09-23 8:56 ` Masami Hiramatsu
2026-09-23 18:36 ` [tip: x86/urgent] " tip-bot2 for Masami Hiramatsu (Google)
2026-09-22 4:25 ` Masami Hiramatsu (Google) [this message]
2026-09-23 8:51 ` [PATCH v17 02/13] perf/x86, KVM: Prevent host debug register leak into guest OS on NMI Peter Zijlstra
2026-09-23 14:33 ` Sean Christopherson
2026-09-24 1:31 ` Masami Hiramatsu
2026-09-24 9:18 ` Peter Zijlstra
2026-09-23 9:15 ` Peter Zijlstra
2026-09-23 15:32 ` Sean Christopherson
2026-09-24 0:56 ` Masami Hiramatsu
2026-09-24 9:23 ` Peter Zijlstra
2026-09-22 4:25 ` [PATCH v17 03/13] x86/hw_breakpoints: Make DR7 updates NMI safe Masami Hiramatsu (Google)
2026-09-23 9:13 ` Peter Zijlstra
2026-09-24 12:56 ` Masami Hiramatsu
2026-09-22 4:25 ` [PATCH v17 04/13] x86/hw_breakpoints: Add arch_modify_local_hw_breakpoint_addr() API Masami Hiramatsu (Google)
2026-09-22 4:25 ` [PATCH v17 05/13] HWBP: Add modify_local_hw_breakpoint_addr() API Masami Hiramatsu (Google)
2026-09-22 4:25 ` [PATCH v17 06/13] tracing/wprobe: Add wprobe (watchpoint probe) trace event support Masami Hiramatsu (Google)
2026-09-22 4:26 ` [PATCH v17 07/13] x86: hw_breakpoint: Add a kconfig to clarify when a breakpoint fires Masami Hiramatsu (Google)
2026-09-22 4:26 ` [PATCH v17 08/13] selftests: tracing: Add a basic testcase for wprobe Masami Hiramatsu (Google)
2026-09-22 4:26 ` [PATCH v17 09/13] selftests: tracing: Add syntax " Masami Hiramatsu (Google)
2026-09-22 4:26 ` [PATCH v17 10/13] tracing/wprobe: Add set_wprobe and clear_wprobe event triggers Masami Hiramatsu (Google)
2026-09-22 4:26 ` [PATCH v17 11/13] selftests: tracing: Add wprobe trigger testcases Masami Hiramatsu (Google)
2026-09-22 4:27 ` [PATCH v17 12/13] tracing/wprobe: Support BTF typecast in fetchargs Masami Hiramatsu (Google)
2026-09-22 4:27 ` [PATCH v17 13/13] tracing/wprobe: Support BTF struct offset resolution in set_wprobe trigger Masami Hiramatsu (Google)
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=179005110742.388919.1509641807739909065.stgit@devnote2 \
--to=mhiramat@kernel.org \
--cc=alexander.shishkin@linux.intel.com \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=irogers@google.com \
--cc=kvm@vger.kernel.org \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-perf-users@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=mingo@kernel.org \
--cc=pbonzini@redhat.com \
--cc=peterz@infradead.org \
--cc=rostedt@goodmis.org \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=wangjinchao600@gmail.com \
--cc=x86@kernel.org \
/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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®