[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20241112103717.589952-12-james.clark@linaro.org>
Date: Tue, 12 Nov 2024 10:37:10 +0000
From: James Clark <james.clark@...aro.org>
To: suzuki.poulose@....com,
oliver.upton@...ux.dev,
coresight@...ts.linaro.org,
kvmarm@...ts.linux.dev
Cc: James Clark <james.clark@...aro.org>,
Marc Zyngier <maz@...nel.org>,
Joey Gouly <joey.gouly@....com>,
Zenghui Yu <yuzenghui@...wei.com>,
Catalin Marinas <catalin.marinas@....com>,
Will Deacon <will@...nel.org>,
Mike Leach <mike.leach@...aro.org>,
Alexander Shishkin <alexander.shishkin@...ux.intel.com>,
Mark Rutland <mark.rutland@....com>,
Anshuman Khandual <anshuman.khandual@....com>,
"Rob Herring (Arm)" <robh@...nel.org>,
Shiqi Liu <shiqiliu@...t.edu.cn>,
Fuad Tabba <tabba@...gle.com>,
James Morse <james.morse@....com>,
Mark Brown <broonie@...nel.org>,
Raghavendra Rao Ananta <rananta@...gle.com>,
linux-arm-kernel@...ts.infradead.org,
linux-kernel@...r.kernel.org
Subject: [PATCH v7 11/12] KVM: arm64: Swap TRFCR on guest switch
This implements exclude/include guest rules of the active tracing
session. Only do it if a different value is required for the guest,
otherwise the filters remain untouched.
In VHE we can just directly write the value.
Signed-off-by: James Clark <james.clark@...aro.org>
---
arch/arm64/include/asm/kvm_host.h | 4 ++++
arch/arm64/kvm/debug.c | 16 ++++++++++++++++
arch/arm64/kvm/hyp/nvhe/debug-sr.c | 17 +++++++++++++++--
3 files changed, 35 insertions(+), 2 deletions(-)
diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
index a8846689512b..9109d10c656e 100644
--- a/arch/arm64/include/asm/kvm_host.h
+++ b/arch/arm64/include/asm/kvm_host.h
@@ -949,6 +949,8 @@ struct kvm_vcpu_arch {
#define HOST_STATE_TRBE_EN __kvm_single_flag(state, BIT(1))
/* Hyp modified TRFCR */
#define HOST_STATE_RESTORE_TRFCR __kvm_single_flag(state, BIT(2))
+/* Host wants a different trace filters for the guest */
+#define HOST_STATE_SWAP_TRFCR __kvm_single_flag(state, BIT(3))
/* Pointer to the vcpu's SVE FFR for sve_{save,load}_state() */
#define vcpu_sve_pffr(vcpu) (kern_hyp_va((vcpu)->arch.sve_state) + \
@@ -1392,6 +1394,7 @@ void kvm_clr_pmu_events(u64 clr);
bool kvm_set_pmuserenr(u64 val);
void kvm_set_pmblimitr(u64 pmblimitr);
void kvm_set_trblimitr(u64 trblimitr);
+void kvm_set_trfcr(u64 host_trfcr, u64 guest_trfcr);
#else
static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr) {}
static inline void kvm_clr_pmu_events(u64 clr) {}
@@ -1401,6 +1404,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
}
static inline void kvm_set_pmblimitr(u64 pmblimitr) {}
static inline void kvm_set_trblimitr(u64 trblimitr) {}
+static inline void kvm_set_trfcr(u64 host_trfcr, u64 guest_trfcr) {}
#endif
void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);
diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c
index e99df2c3f62a..9acec1b67d5f 100644
--- a/arch/arm64/kvm/debug.c
+++ b/arch/arm64/kvm/debug.c
@@ -380,3 +380,19 @@ void kvm_set_trblimitr(u64 trblimitr)
host_data_clear_flag(HOST_STATE_TRBE_EN);
}
EXPORT_SYMBOL_GPL(kvm_set_trblimitr);
+
+void kvm_set_trfcr(u64 host_trfcr, u64 guest_trfcr)
+{
+ if (kvm_arm_skip_trace_state())
+ return;
+
+ if (has_vhe())
+ write_sysreg_s(guest_trfcr, SYS_TRFCR_EL12);
+ else
+ if (host_trfcr != guest_trfcr) {
+ *host_data_ptr(host_debug_state.trfcr_el1) = guest_trfcr;
+ host_data_set_flag(HOST_STATE_SWAP_TRFCR);
+ } else
+ host_data_clear_flag(HOST_STATE_SWAP_TRFCR);
+}
+EXPORT_SYMBOL_GPL(kvm_set_trfcr);
diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
index 17c23e52f5f4..47602c4d160a 100644
--- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c
+++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
@@ -100,6 +100,15 @@ static void __debug_save_trace(void)
host_data_set_flag(HOST_STATE_RESTORE_TRFCR);
}
+static void __debug_swap_trace(void)
+{
+ u64 trfcr = read_sysreg_el1(SYS_TRFCR);
+
+ write_sysreg_el1(*host_data_ptr(host_debug_state.trfcr_el1), SYS_TRFCR);
+ *host_data_ptr(host_debug_state.trfcr_el1) = trfcr;
+ host_data_set_flag(HOST_STATE_RESTORE_TRFCR);
+}
+
static void __debug_restore_trace(void)
{
u64 trfcr_el1;
@@ -124,10 +133,14 @@ void __debug_save_host_buffers_nvhe(void)
if (!host_data_get_flag(HOST_FEAT_HAS_TRF))
return;
- /* Disable and flush Self-Hosted Trace generation */
+ /*
+ * Disable and flush Self-Hosted Trace generation for pKVM and TRBE,
+ * or swap if host requires different guest filters.
+ */
if (__debug_should_save_trace())
__debug_save_trace();
-
+ else if (host_data_get_flag(HOST_STATE_SWAP_TRFCR))
+ __debug_swap_trace();
}
void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
--
2.34.1
Powered by blists - more mailing lists