From: Vincent Donnefort <vdonnefort@google.com>
To: rostedt@goodmis.org, mhiramat@kernel.org,
mathieu.desnoyers@efficios.com,
linux-trace-kernel@vger.kernel.org, maz@kernel.org,
oliver.upton@linux.dev, joey.gouly@arm.com,
suzuki.poulose@arm.com, yuzenghui@huawei.com
Cc: kvmarm@lists.linux.dev, linux-arm-kernel@lists.infradead.org,
jstultz@google.com, qperret@google.com, will@kernel.org,
aneesh.kumar@kernel.org, kernel-team@android.com,
linux-kernel@vger.kernel.org,
Vincent Donnefort <vdonnefort@google.com>
Subject: [PATCH v11 24/30] KVM: arm64: Add trace remote for the nVHE/pKVM hyp
Date: Sat, 31 Jan 2026 13:28:42 +0000 [thread overview]
Message-ID: <20260131132848.254084-25-vdonnefort@google.com> (raw)
In-Reply-To: <20260131132848.254084-1-vdonnefort@google.com>
In both protected and nVHE mode, the hypervisor is capable of writing
events into tracefs compatible ring-buffers. Create a trace remote so
the kernel can read those buffers.
This currently doesn't provide any event support which will come later.
Signed-off-by: Vincent Donnefort <vdonnefort@google.com>
diff --git a/arch/arm64/kvm/Kconfig b/arch/arm64/kvm/Kconfig
index c7f50492f2cf..aad0228f24db 100644
--- a/arch/arm64/kvm/Kconfig
+++ b/arch/arm64/kvm/Kconfig
@@ -76,6 +76,7 @@ if NVHE_EL2_DEBUG
config NVHE_EL2_TRACING
bool
depends on TRACING
+ select TRACE_REMOTE
default y
config PKVM_DISABLE_STAGE2_ON_PANIC
diff --git a/arch/arm64/kvm/Makefile b/arch/arm64/kvm/Makefile
index 3ebc0570345c..59612d2f277c 100644
--- a/arch/arm64/kvm/Makefile
+++ b/arch/arm64/kvm/Makefile
@@ -30,6 +30,8 @@ kvm-$(CONFIG_HW_PERF_EVENTS) += pmu-emul.o pmu.o
kvm-$(CONFIG_ARM64_PTR_AUTH) += pauth.o
kvm-$(CONFIG_PTDUMP_STAGE2_DEBUGFS) += ptdump.o
+kvm-$(CONFIG_NVHE_EL2_TRACING) += hyp_trace.o
+
always-y := hyp_constants.h hyp-constants.s
define rule_gen_hyp_constants
diff --git a/arch/arm64/kvm/arm.c b/arch/arm64/kvm/arm.c
index be1fd6c5f74c..f7f222ecaf88 100644
--- a/arch/arm64/kvm/arm.c
+++ b/arch/arm64/kvm/arm.c
@@ -24,6 +24,7 @@
#define CREATE_TRACE_POINTS
#include "trace_arm.h"
+#include "hyp_trace.h"
#include <linux/uaccess.h>
#include <asm/ptrace.h>
@@ -2361,6 +2362,10 @@ static int __init init_subsystems(void)
kvm_register_perf_callbacks(NULL);
+ err = kvm_hyp_trace_init();
+ if (err)
+ kvm_err("Failed to initialize Hyp tracing\n");
+
out:
if (err)
hyp_cpu_pm_exit();
diff --git a/arch/arm64/kvm/hyp_trace.c b/arch/arm64/kvm/hyp_trace.c
new file mode 100644
index 000000000000..2866effe28ec
--- /dev/null
+++ b/arch/arm64/kvm/hyp_trace.c
@@ -0,0 +1,219 @@
+// SPDX-License-Identifier: GPL-2.0-only
+/*
+ * Copyright (C) 2025 Google LLC
+ * Author: Vincent Donnefort <vdonnefort@google.com>
+ */
+
+#include <linux/trace_remote.h>
+#include <linux/simple_ring_buffer.h>
+
+#include <asm/kvm_host.h>
+#include <asm/kvm_hyptrace.h>
+#include <asm/kvm_mmu.h>
+
+#include "hyp_trace.h"
+
+/* Access to this struct within the trace_remote_callbacks are protected by the trace_remote lock */
+static struct hyp_trace_buffer {
+ struct hyp_trace_desc *desc;
+ size_t desc_size;
+} trace_buffer;
+
+static int __map_hyp(void *start, size_t size)
+{
+ if (is_protected_kvm_enabled())
+ return 0;
+
+ return create_hyp_mappings(start, start + size, PAGE_HYP);
+}
+
+static int __share_page(unsigned long va)
+{
+ return kvm_share_hyp((void *)va, (void *)va + 1);
+}
+
+static void __unshare_page(unsigned long va)
+{
+ kvm_unshare_hyp((void *)va, (void *)va + 1);
+}
+
+static int hyp_trace_buffer_alloc_bpages_backing(struct hyp_trace_buffer *trace_buffer, size_t size)
+{
+ int nr_bpages = (PAGE_ALIGN(size) / PAGE_SIZE) + 1;
+ size_t backing_size;
+ void *start;
+
+ backing_size = PAGE_ALIGN(sizeof(struct simple_buffer_page) * nr_bpages *
+ num_possible_cpus());
+
+ start = alloc_pages_exact(backing_size, GFP_KERNEL_ACCOUNT);
+ if (!start)
+ return -ENOMEM;
+
+ trace_buffer->desc->bpages_backing_start = (unsigned long)start;
+ trace_buffer->desc->bpages_backing_size = backing_size;
+
+ return __map_hyp(start, backing_size);
+}
+
+static void hyp_trace_buffer_free_bpages_backing(struct hyp_trace_buffer *trace_buffer)
+{
+ free_pages_exact((void *)trace_buffer->desc->bpages_backing_start,
+ trace_buffer->desc->bpages_backing_size);
+}
+
+static void hyp_trace_buffer_unshare_hyp(struct hyp_trace_buffer *trace_buffer, int last_cpu)
+{
+ struct ring_buffer_desc *rb_desc;
+ int cpu, p;
+
+ for_each_ring_buffer_desc(rb_desc, cpu, &trace_buffer->desc->trace_buffer_desc) {
+ if (cpu > last_cpu)
+ break;
+
+ __share_page(rb_desc->meta_va);
+ for (p = 0; p < rb_desc->nr_page_va; p++)
+ __unshare_page(rb_desc->page_va[p]);
+ }
+}
+
+static int hyp_trace_buffer_share_hyp(struct hyp_trace_buffer *trace_buffer)
+{
+ struct ring_buffer_desc *rb_desc;
+ int cpu, p, ret = 0;
+
+ for_each_ring_buffer_desc(rb_desc, cpu, &trace_buffer->desc->trace_buffer_desc) {
+ ret = __share_page(rb_desc->meta_va);
+ if (ret)
+ break;
+
+ for (p = 0; p < rb_desc->nr_page_va; p++) {
+ ret = __share_page(rb_desc->page_va[p]);
+ if (ret)
+ break;
+ }
+
+ if (ret) {
+ for (p--; p >= 0; p--)
+ __unshare_page(rb_desc->page_va[p]);
+ break;
+ }
+ }
+
+ if (ret)
+ hyp_trace_buffer_unshare_hyp(trace_buffer, cpu--);
+
+ return ret;
+}
+
+static struct trace_buffer_desc *hyp_trace_load(unsigned long size, void *priv)
+{
+ struct hyp_trace_buffer *trace_buffer = priv;
+ struct hyp_trace_desc *desc;
+ size_t desc_size;
+ int ret;
+
+ if (WARN_ON(trace_buffer->desc))
+ return ERR_PTR(-EINVAL);
+
+ desc_size = trace_buffer_desc_size(size, num_possible_cpus());
+ if (desc_size == SIZE_MAX)
+ return ERR_PTR(-E2BIG);
+
+ desc_size = PAGE_ALIGN(desc_size);
+ desc = (struct hyp_trace_desc *)alloc_pages_exact(desc_size, GFP_KERNEL);
+ if (!desc)
+ return ERR_PTR(-ENOMEM);
+
+ ret = __map_hyp(desc, desc_size);
+ if (ret)
+ goto err_free_desc;
+
+ trace_buffer->desc = desc;
+
+ ret = hyp_trace_buffer_alloc_bpages_backing(trace_buffer, size);
+ if (ret)
+ goto err_free_desc;
+
+ ret = trace_remote_alloc_buffer(&desc->trace_buffer_desc, desc_size, size,
+ cpu_possible_mask);
+ if (ret)
+ goto err_free_backing;
+
+ ret = hyp_trace_buffer_share_hyp(trace_buffer);
+ if (ret)
+ goto err_free_buffer;
+
+ ret = kvm_call_hyp_nvhe(__tracing_load, (unsigned long)desc, desc_size);
+ if (ret)
+ goto err_unload_pages;
+
+ return &desc->trace_buffer_desc;
+
+err_unload_pages:
+ hyp_trace_buffer_unshare_hyp(trace_buffer, INT_MAX);
+
+err_free_buffer:
+ trace_remote_free_buffer(&desc->trace_buffer_desc);
+
+err_free_backing:
+ hyp_trace_buffer_free_bpages_backing(trace_buffer);
+
+err_free_desc:
+ free_pages_exact(desc, desc_size);
+ trace_buffer->desc = NULL;
+
+ return ERR_PTR(ret);
+}
+
+static void hyp_trace_unload(struct trace_buffer_desc *desc, void *priv)
+{
+ struct hyp_trace_buffer *trace_buffer = priv;
+
+ if (WARN_ON(desc != &trace_buffer->desc->trace_buffer_desc))
+ return;
+
+ kvm_call_hyp_nvhe(__tracing_unload);
+ hyp_trace_buffer_unshare_hyp(trace_buffer, INT_MAX);
+ trace_remote_free_buffer(desc);
+ hyp_trace_buffer_free_bpages_backing(trace_buffer);
+ free_pages_exact(trace_buffer->desc, trace_buffer->desc_size);
+ trace_buffer->desc = NULL;
+}
+
+static int hyp_trace_enable_tracing(bool enable, void *priv)
+{
+ return kvm_call_hyp_nvhe(__tracing_enable, enable);
+}
+
+static int hyp_trace_swap_reader_page(unsigned int cpu, void *priv)
+{
+ return kvm_call_hyp_nvhe(__tracing_swap_reader, cpu);
+}
+
+static int hyp_trace_reset(unsigned int cpu, void *priv)
+{
+ return 0;
+}
+
+static int hyp_trace_enable_event(unsigned short id, bool enable, void *priv)
+{
+ return 0;
+}
+
+static struct trace_remote_callbacks trace_remote_callbacks = {
+ .load_trace_buffer = hyp_trace_load,
+ .unload_trace_buffer = hyp_trace_unload,
+ .enable_tracing = hyp_trace_enable_tracing,
+ .swap_reader_page = hyp_trace_swap_reader_page,
+ .reset = hyp_trace_reset,
+ .enable_event = hyp_trace_enable_event,
+};
+
+int __init kvm_hyp_trace_init(void)
+{
+ if (is_kernel_in_hyp_mode())
+ return 0;
+
+ return trace_remote_register("hypervisor", &trace_remote_callbacks, &trace_buffer, NULL, 0);
+}
diff --git a/arch/arm64/kvm/hyp_trace.h b/arch/arm64/kvm/hyp_trace.h
new file mode 100644
index 000000000000..c991b1ec65f1
--- /dev/null
+++ b/arch/arm64/kvm/hyp_trace.h
@@ -0,0 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifndef __ARM64_KVM_HYP_TRACE_H__
+#define __ARM64_KVM_HYP_TRACE_H__
+
+#ifdef CONFIG_NVHE_EL2_TRACING
+int kvm_hyp_trace_init(void);
+#else
+static inline int kvm_hyp_trace_init(void) { return 0; }
+#endif
+#endif
--
2.53.0.rc1.225.gd81095ad13-goog
next prev parent reply other threads:[~2026-01-31 13:29 UTC|newest]
Thread overview: 43+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-01-31 13:28 [PATCH v11 00/30] Tracefs support for pKVM Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 01/30] ring-buffer: Add page statistics to the meta-page Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 02/30] ring-buffer: Store bpage pointers into subbuf_ids Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 03/30] ring-buffer: Introduce ring-buffer remotes Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 04/30] ring-buffer: Add non-consuming read for " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 05/30] tracing: Introduce trace remotes Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 06/30] tracing: Add reset to " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 07/30] tracing: Add non-consuming read " Vincent Donnefort
2026-02-04 23:52 ` Steven Rostedt
2026-02-10 15:32 ` Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 08/30] tracing: Add init callback " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 09/30] tracing: Add events " Vincent Donnefort
2026-02-05 0:40 ` Steven Rostedt
2026-01-31 13:28 ` [PATCH v11 10/30] tracing: Add events/ root files " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 11/30] tracing: Add helpers to create trace remote events Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 12/30] ring-buffer: Export buffer_data_page and macros Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 13/30] tracing: Introduce simple_ring_buffer Vincent Donnefort
2026-02-05 1:06 ` Steven Rostedt
2026-01-31 13:28 ` [PATCH v11 14/30] tracing: Add a trace remote module for testing Vincent Donnefort
2026-02-05 1:32 ` Steven Rostedt
2026-01-31 13:28 ` [PATCH v11 15/30] tracing: selftests: Add trace remote tests Vincent Donnefort
2026-02-05 17:42 ` Steven Rostedt
2026-02-10 15:54 ` Vincent Donnefort
2026-02-19 14:36 ` Steven Rostedt
2026-01-31 13:28 ` [PATCH v11 16/30] Documentation: tracing: Add tracing remotes Vincent Donnefort
2026-02-05 17:45 ` Steven Rostedt
2026-01-31 13:28 ` [PATCH v11 17/30] tracing: load/unload page callbacks for simple_ring_buffer Vincent Donnefort
2026-02-05 17:47 ` Steven Rostedt
2026-01-31 13:28 ` [PATCH v11 18/30] tracing: Check for undefined symbols in simple_ring_buffer Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 19/30] KVM: arm64: Add PKVM_DISABLE_STAGE2_ON_PANIC Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 20/30] KVM: arm64: Add clock support to nVHE/pKVM hyp Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 21/30] KVM: arm64: Initialise hyp_nr_cpus for nVHE hyp Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 22/30] KVM: arm64: Support unaligned fixmap in the pKVM hyp Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 23/30] KVM: arm64: Add tracing capability for the nVHE/pKVM hyp Vincent Donnefort
2026-01-31 13:28 ` Vincent Donnefort [this message]
2026-01-31 13:28 ` [PATCH v11 25/30] KVM: arm64: Sync boot clock with " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 26/30] KVM: arm64: Add trace reset to " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 27/30] KVM: arm64: Add event support to the nVHE/pKVM hyp and trace remote Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 28/30] KVM: arm64: Add hyp_enter/hyp_exit events to nVHE/pKVM hyp Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 29/30] KVM: arm64: Add selftest event support " Vincent Donnefort
2026-01-31 13:28 ` [PATCH v11 30/30] tracing: selftests: Add hypervisor trace remote tests Vincent Donnefort
2026-02-04 22:45 ` [PATCH v11 00/30] Tracefs support for pKVM Steven Rostedt
2026-02-05 17:51 ` Steven Rostedt
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=20260131132848.254084-25-vdonnefort@google.com \
--to=vdonnefort@google.com \
--cc=aneesh.kumar@kernel.org \
--cc=joey.gouly@arm.com \
--cc=jstultz@google.com \
--cc=kernel-team@android.com \
--cc=kvmarm@lists.linux.dev \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-trace-kernel@vger.kernel.org \
--cc=mathieu.desnoyers@efficios.com \
--cc=maz@kernel.org \
--cc=mhiramat@kernel.org \
--cc=oliver.upton@linux.dev \
--cc=qperret@google.com \
--cc=rostedt@goodmis.org \
--cc=suzuki.poulose@arm.com \
--cc=will@kernel.org \
--cc=yuzenghui@huawei.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox