Skip to content

Commit 946904e

Browse files
author
Marc Zyngier
committed
Merge branch kvm-arm64/coresight-6.14 into kvmarm-master/next
* kvm-arm64/coresight-6.14: : . : Trace filtering update from James Clark. From the cover letter: : : "The guest filtering rules from the Perf session are now honored for both : nVHE and VHE modes. This is done by either writing to TRFCR_EL12 at the : start of the Perf session and doing nothing else further, or caching the : guest value and writing it at guest switch for nVHE. In pKVM, trace is : now be disabled for both protected and unprotected guests." : . KVM: arm64: Fix selftests after sysreg field name update coresight: Pass guest TRFCR value to KVM KVM: arm64: Support trace filtering for guests KVM: arm64: coresight: Give TRBE enabled state to KVM coresight: trbe: Remove redundant disable call arm64/sysreg/tools: Move TRFCR definitions to sysreg tools: arm64: Update sysreg.h header files Signed-off-by: Marc Zyngier <[email protected]>
2 parents 5e68d2e + 9fb4267 commit 946904e

File tree

14 files changed

+599
-80
lines changed

14 files changed

+599
-80
lines changed

arch/arm64/include/asm/kvm_host.h

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -617,6 +617,8 @@ struct kvm_host_data {
617617
#define KVM_HOST_DATA_FLAG_HAS_TRBE 1
618618
#define KVM_HOST_DATA_FLAG_HOST_SVE_ENABLED 2
619619
#define KVM_HOST_DATA_FLAG_HOST_SME_ENABLED 3
620+
#define KVM_HOST_DATA_FLAG_TRBE_ENABLED 4
621+
#define KVM_HOST_DATA_FLAG_EL1_TRACING_CONFIGURED 5
620622
unsigned long flags;
621623

622624
struct kvm_cpu_context host_ctxt;
@@ -662,6 +664,9 @@ struct kvm_host_data {
662664
u64 mdcr_el2;
663665
} host_debug_state;
664666

667+
/* Guest trace filter value */
668+
u64 trfcr_while_in_guest;
669+
665670
/* Number of programmable event counters (PMCR_EL0.N) for this CPU */
666671
unsigned int nr_event_counters;
667672

@@ -1389,13 +1394,19 @@ static inline bool kvm_pmu_counter_deferred(struct perf_event_attr *attr)
13891394
void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr);
13901395
void kvm_clr_pmu_events(u64 clr);
13911396
bool kvm_set_pmuserenr(u64 val);
1397+
void kvm_enable_trbe(void);
1398+
void kvm_disable_trbe(void);
1399+
void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest);
13921400
#else
13931401
static inline void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr) {}
13941402
static inline void kvm_clr_pmu_events(u64 clr) {}
13951403
static inline bool kvm_set_pmuserenr(u64 val)
13961404
{
13971405
return false;
13981406
}
1407+
static inline void kvm_enable_trbe(void) {}
1408+
static inline void kvm_disable_trbe(void) {}
1409+
static inline void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest) {}
13991410
#endif
14001411

14011412
void kvm_vcpu_load_vhe(struct kvm_vcpu *vcpu);

arch/arm64/include/asm/sysreg.h

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -283,8 +283,6 @@
283283
#define SYS_RGSR_EL1 sys_reg(3, 0, 1, 0, 5)
284284
#define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6)
285285

286-
#define SYS_TRFCR_EL1 sys_reg(3, 0, 1, 2, 1)
287-
288286
#define SYS_TCR_EL1 sys_reg(3, 0, 2, 0, 2)
289287

290288
#define SYS_APIAKEYLO_EL1 sys_reg(3, 0, 2, 1, 0)
@@ -523,7 +521,6 @@
523521
#define SYS_VTTBR_EL2 sys_reg(3, 4, 2, 1, 0)
524522
#define SYS_VTCR_EL2 sys_reg(3, 4, 2, 1, 2)
525523

526-
#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)
527524
#define SYS_VNCR_EL2 sys_reg(3, 4, 2, 2, 0)
528525
#define SYS_HAFGRTR_EL2 sys_reg(3, 4, 3, 1, 6)
529526
#define SYS_SPSR_EL2 sys_reg(3, 4, 4, 0, 0)
@@ -987,15 +984,6 @@
987984
/* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
988985
#define SYS_MPIDR_SAFE_VAL (BIT(31))
989986

990-
#define TRFCR_ELx_TS_SHIFT 5
991-
#define TRFCR_ELx_TS_MASK ((0x3UL) << TRFCR_ELx_TS_SHIFT)
992-
#define TRFCR_ELx_TS_VIRTUAL ((0x1UL) << TRFCR_ELx_TS_SHIFT)
993-
#define TRFCR_ELx_TS_GUEST_PHYSICAL ((0x2UL) << TRFCR_ELx_TS_SHIFT)
994-
#define TRFCR_ELx_TS_PHYSICAL ((0x3UL) << TRFCR_ELx_TS_SHIFT)
995-
#define TRFCR_EL2_CX BIT(3)
996-
#define TRFCR_ELx_ExTRE BIT(1)
997-
#define TRFCR_ELx_E0TRE BIT(0)
998-
999987
/* GIC Hypervisor interface registers */
1000988
/* ICH_MISR_EL2 bit definitions */
1001989
#define ICH_MISR_EOI (1 << 0)

arch/arm64/kvm/debug.c

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -81,9 +81,15 @@ void kvm_init_host_debug_data(void)
8181
!(read_sysreg_s(SYS_PMBIDR_EL1) & PMBIDR_EL1_P))
8282
host_data_set_flag(HAS_SPE);
8383

84-
if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) &&
85-
!(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P))
86-
host_data_set_flag(HAS_TRBE);
84+
if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) {
85+
/* Force disable trace in protected mode in case of no TRBE */
86+
if (is_protected_kvm_enabled())
87+
host_data_set_flag(EL1_TRACING_CONFIGURED);
88+
89+
if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) &&
90+
!(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P))
91+
host_data_set_flag(HAS_TRBE);
92+
}
8793
}
8894

8995
/*
@@ -219,3 +225,41 @@ void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val)
219225
kvm_arch_vcpu_load(vcpu, smp_processor_id());
220226
preempt_enable();
221227
}
228+
229+
void kvm_enable_trbe(void)
230+
{
231+
if (has_vhe() || is_protected_kvm_enabled() ||
232+
WARN_ON_ONCE(preemptible()))
233+
return;
234+
235+
host_data_set_flag(TRBE_ENABLED);
236+
}
237+
EXPORT_SYMBOL_GPL(kvm_enable_trbe);
238+
239+
void kvm_disable_trbe(void)
240+
{
241+
if (has_vhe() || is_protected_kvm_enabled() ||
242+
WARN_ON_ONCE(preemptible()))
243+
return;
244+
245+
host_data_clear_flag(TRBE_ENABLED);
246+
}
247+
EXPORT_SYMBOL_GPL(kvm_disable_trbe);
248+
249+
void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest)
250+
{
251+
if (is_protected_kvm_enabled() || WARN_ON_ONCE(preemptible()))
252+
return;
253+
254+
if (has_vhe()) {
255+
write_sysreg_s(trfcr_while_in_guest, SYS_TRFCR_EL12);
256+
return;
257+
}
258+
259+
*host_data_ptr(trfcr_while_in_guest) = trfcr_while_in_guest;
260+
if (read_sysreg_s(SYS_TRFCR_EL1) != trfcr_while_in_guest)
261+
host_data_set_flag(EL1_TRACING_CONFIGURED);
262+
else
263+
host_data_clear_flag(EL1_TRACING_CONFIGURED);
264+
}
265+
EXPORT_SYMBOL_GPL(kvm_tracing_set_el1_configuration);

arch/arm64/kvm/hyp/nvhe/debug-sr.c

Lines changed: 38 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -51,42 +51,55 @@ static void __debug_restore_spe(u64 pmscr_el1)
5151
write_sysreg_el1(pmscr_el1, SYS_PMSCR);
5252
}
5353

54-
static void __debug_save_trace(u64 *trfcr_el1)
54+
static void __trace_do_switch(u64 *saved_trfcr, u64 new_trfcr)
5555
{
56-
*trfcr_el1 = 0;
56+
*saved_trfcr = read_sysreg_el1(SYS_TRFCR);
57+
write_sysreg_el1(new_trfcr, SYS_TRFCR);
58+
}
5759

58-
/* Check if the TRBE is enabled */
59-
if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E))
60-
return;
61-
/*
62-
* Prohibit trace generation while we are in guest.
63-
* Since access to TRFCR_EL1 is trapped, the guest can't
64-
* modify the filtering set by the host.
65-
*/
66-
*trfcr_el1 = read_sysreg_el1(SYS_TRFCR);
67-
write_sysreg_el1(0, SYS_TRFCR);
68-
isb();
69-
/* Drain the trace buffer to memory */
70-
tsb_csync();
60+
static bool __trace_needs_drain(void)
61+
{
62+
if (is_protected_kvm_enabled() && host_data_test_flag(HAS_TRBE))
63+
return read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E;
64+
65+
return host_data_test_flag(TRBE_ENABLED);
7166
}
7267

73-
static void __debug_restore_trace(u64 trfcr_el1)
68+
static bool __trace_needs_switch(void)
7469
{
75-
if (!trfcr_el1)
76-
return;
70+
return host_data_test_flag(TRBE_ENABLED) ||
71+
host_data_test_flag(EL1_TRACING_CONFIGURED);
72+
}
73+
74+
static void __trace_switch_to_guest(void)
75+
{
76+
/* Unsupported with TRBE so disable */
77+
if (host_data_test_flag(TRBE_ENABLED))
78+
*host_data_ptr(trfcr_while_in_guest) = 0;
79+
80+
__trace_do_switch(host_data_ptr(host_debug_state.trfcr_el1),
81+
*host_data_ptr(trfcr_while_in_guest));
7782

78-
/* Restore trace filter controls */
79-
write_sysreg_el1(trfcr_el1, SYS_TRFCR);
83+
if (__trace_needs_drain()) {
84+
isb();
85+
tsb_csync();
86+
}
87+
}
88+
89+
static void __trace_switch_to_host(void)
90+
{
91+
__trace_do_switch(host_data_ptr(trfcr_while_in_guest),
92+
*host_data_ptr(host_debug_state.trfcr_el1));
8093
}
8194

8295
void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
8396
{
8497
/* Disable and flush SPE data generation */
8598
if (host_data_test_flag(HAS_SPE))
8699
__debug_save_spe(host_data_ptr(host_debug_state.pmscr_el1));
87-
/* Disable and flush Self-Hosted Trace generation */
88-
if (host_data_test_flag(HAS_TRBE))
89-
__debug_save_trace(host_data_ptr(host_debug_state.trfcr_el1));
100+
101+
if (__trace_needs_switch())
102+
__trace_switch_to_guest();
90103
}
91104

92105
void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
@@ -98,8 +111,8 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
98111
{
99112
if (host_data_test_flag(HAS_SPE))
100113
__debug_restore_spe(*host_data_ptr(host_debug_state.pmscr_el1));
101-
if (host_data_test_flag(HAS_TRBE))
102-
__debug_restore_trace(*host_data_ptr(host_debug_state.trfcr_el1));
114+
if (__trace_needs_switch())
115+
__trace_switch_to_host();
103116
}
104117

105118
void __debug_switch_to_host(struct kvm_vcpu *vcpu)

arch/arm64/tools/sysreg

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1999,6 +1999,22 @@ Field 17:16 ZEN
19991999
Res0 15:0
20002000
EndSysreg
20012001

2002+
SysregFields TRFCR_ELx
2003+
Res0 63:7
2004+
UnsignedEnum 6:5 TS
2005+
0b0001 VIRTUAL
2006+
0b0010 GUEST_PHYSICAL
2007+
0b0011 PHYSICAL
2008+
EndEnum
2009+
Res0 4:2
2010+
Field 1 ExTRE
2011+
Field 0 E0TRE
2012+
EndSysregFields
2013+
2014+
Sysreg TRFCR_EL1 3 0 1 2 1
2015+
Fields TRFCR_ELx
2016+
EndSysreg
2017+
20022018
Sysreg SMPRI_EL1 3 0 1 2 4
20032019
Res0 63:4
20042020
Field 3:0 PRIORITY
@@ -2548,6 +2564,22 @@ Field 1 ICIALLU
25482564
Field 0 ICIALLUIS
25492565
EndSysreg
25502566

2567+
Sysreg TRFCR_EL2 3 4 1 2 1
2568+
Res0 63:7
2569+
UnsignedEnum 6:5 TS
2570+
0b0000 USE_TRFCR_EL1_TS
2571+
0b0001 VIRTUAL
2572+
0b0010 GUEST_PHYSICAL
2573+
0b0011 PHYSICAL
2574+
EndEnum
2575+
Res0 4
2576+
Field 3 CX
2577+
Res0 2
2578+
Field 1 E2TRE
2579+
Field 0 E0HTRE
2580+
EndSysreg
2581+
2582+
25512583
Sysreg HDFGRTR_EL2 3 4 3 1 4
25522584
Field 63 PMBIDR_EL1
25532585
Field 62 nPMSNEVFR_EL1
@@ -2958,6 +2990,10 @@ Sysreg ZCR_EL12 3 5 1 2 0
29582990
Mapping ZCR_EL1
29592991
EndSysreg
29602992

2993+
Sysreg TRFCR_EL12 3 5 1 2 1
2994+
Fields TRFCR_ELx
2995+
EndSysreg
2996+
29612997
Sysreg SMCR_EL12 3 5 1 2 6
29622998
Mapping SMCR_EL1
29632999
EndSysreg

drivers/hwtracing/coresight/coresight-etm4x-core.c

Lines changed: 42 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
#include <linux/acpi.h>
77
#include <linux/bitops.h>
88
#include <linux/kernel.h>
9+
#include <linux/kvm_host.h>
910
#include <linux/moduleparam.h>
1011
#include <linux/init.h>
1112
#include <linux/types.h>
@@ -268,10 +269,28 @@ struct etm4_enable_arg {
268269
*/
269270
static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
270271
{
272+
u64 trfcr;
273+
271274
/* If the CPU doesn't support FEAT_TRF, nothing to do */
272275
if (!drvdata->trfcr)
273276
return;
274-
cpu_prohibit_trace();
277+
278+
trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
279+
280+
write_trfcr(trfcr);
281+
kvm_tracing_set_el1_configuration(trfcr);
282+
}
283+
284+
static u64 etm4x_get_kern_user_filter(struct etmv4_drvdata *drvdata)
285+
{
286+
u64 trfcr = drvdata->trfcr;
287+
288+
if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
289+
trfcr &= ~TRFCR_ELx_ExTRE;
290+
if (drvdata->config.mode & ETM_MODE_EXCL_USER)
291+
trfcr &= ~TRFCR_ELx_E0TRE;
292+
293+
return trfcr;
275294
}
276295

277296
/*
@@ -286,18 +305,28 @@ static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
286305
*/
287306
static void etm4x_allow_trace(struct etmv4_drvdata *drvdata)
288307
{
289-
u64 trfcr = drvdata->trfcr;
308+
u64 trfcr, guest_trfcr;
290309

291310
/* If the CPU doesn't support FEAT_TRF, nothing to do */
292-
if (!trfcr)
311+
if (!drvdata->trfcr)
293312
return;
294313

295-
if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
296-
trfcr &= ~TRFCR_ELx_ExTRE;
297-
if (drvdata->config.mode & ETM_MODE_EXCL_USER)
298-
trfcr &= ~TRFCR_ELx_E0TRE;
314+
if (drvdata->config.mode & ETM_MODE_EXCL_HOST)
315+
trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
316+
else
317+
trfcr = etm4x_get_kern_user_filter(drvdata);
299318

300319
write_trfcr(trfcr);
320+
321+
/* Set filters for guests and pass to KVM */
322+
if (drvdata->config.mode & ETM_MODE_EXCL_GUEST)
323+
guest_trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
324+
else
325+
guest_trfcr = etm4x_get_kern_user_filter(drvdata);
326+
327+
/* TRFCR_EL1 doesn't have CX so mask it out. */
328+
guest_trfcr &= ~TRFCR_EL2_CX;
329+
kvm_tracing_set_el1_configuration(guest_trfcr);
301330
}
302331

303332
#ifdef CONFIG_ETM4X_IMPDEF_FEATURE
@@ -655,6 +684,12 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
655684
if (attr->exclude_user)
656685
config->mode = ETM_MODE_EXCL_USER;
657686

687+
if (attr->exclude_host)
688+
config->mode |= ETM_MODE_EXCL_HOST;
689+
690+
if (attr->exclude_guest)
691+
config->mode |= ETM_MODE_EXCL_GUEST;
692+
658693
/* Always start from the default config */
659694
etm4_set_default_config(config);
660695

drivers/hwtracing/coresight/coresight-etm4x.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -817,7 +817,7 @@ enum etm_impdef_type {
817817
* @s_ex_level: Secure ELs where tracing is supported.
818818
*/
819819
struct etmv4_config {
820-
u32 mode;
820+
u64 mode;
821821
u32 pe_sel;
822822
u32 cfg;
823823
u32 eventctrl0;

drivers/hwtracing/coresight/coresight-priv.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,9 @@ extern const struct device_type coresight_dev_type[];
4242

4343
#define ETM_MODE_EXCL_KERN BIT(30)
4444
#define ETM_MODE_EXCL_USER BIT(31)
45+
#define ETM_MODE_EXCL_HOST BIT(32)
46+
#define ETM_MODE_EXCL_GUEST BIT(33)
47+
4548
struct cs_pair_attribute {
4649
struct device_attribute attr;
4750
u32 lo_off;

drivers/hwtracing/coresight/coresight-self-hosted-trace.h

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,13 +21,4 @@ static inline void write_trfcr(u64 val)
2121
isb();
2222
}
2323

24-
static inline u64 cpu_prohibit_trace(void)
25-
{
26-
u64 trfcr = read_trfcr();
27-
28-
/* Prohibit tracing at EL0 & the kernel EL */
29-
write_trfcr(trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE));
30-
/* Return the original value of the TRFCR */
31-
return trfcr;
32-
}
3324
#endif /* __CORESIGHT_SELF_HOSTED_TRACE_H */

0 commit comments

Comments
 (0)