Skip to content

Commit aaf69ef

Browse files
James-A-ClarkMarc Zyngier
authored andcommitted
coresight: Pass guest TRFCR value to KVM
Currently the userspace and kernel filters for guests are never set, so no trace will be generated for them. Add support for tracing guests by passing the desired TRFCR value to KVM so it can be applied to the guest. By writing either E1TRE or E0TRE, filtering on either guest kernel or guest userspace is also supported. And if both E1TRE and E0TRE are cleared when exclude_guest is set, that option is supported too. This change also brings exclude_host support which is difficult to add as a separate commit without excess churn and resulting in no trace at all. cpu_prohibit_trace() gets moved to TRBE because the ETM driver doesn't need the read, it already has the base TRFCR value. TRBE only needs the read to disable it and then restore. Testing ======= The addresses were counted with the following: $ perf report -D | grep -Eo 'EL2|EL1|EL0' | sort | uniq -c Guest kernel only: $ perf record -e cs_etm//Gk -a -- true 535 EL1 1 EL2 Guest user only (only 5 addresses because the guest runs slowly in the model): $ perf record -e cs_etm//Gu -a -- true 5 EL0 Host kernel only: $ perf record -e cs_etm//Hk -a -- true 3501 EL2 Host userspace only: $ perf record -e cs_etm//Hu -a -- true 408 EL0 1 EL2 Signed-off-by: James Clark <[email protected]> Link: https://lore.kernel.org/r/[email protected] Signed-off-by: Marc Zyngier <[email protected]>
1 parent 054b883 commit aaf69ef

File tree

5 files changed

+56
-17
lines changed

5 files changed

+56
-17
lines changed

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 */

drivers/hwtracing/coresight/coresight-trbe.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1113,6 +1113,16 @@ static bool is_perf_trbe(struct perf_output_handle *handle)
11131113
return true;
11141114
}
11151115

1116+
static u64 cpu_prohibit_trace(void)
1117+
{
1118+
u64 trfcr = read_trfcr();
1119+
1120+
/* Prohibit tracing at EL0 & the kernel EL */
1121+
write_trfcr(trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE));
1122+
/* Return the original value of the TRFCR */
1123+
return trfcr;
1124+
}
1125+
11161126
static irqreturn_t arm_trbe_irq_handler(int irq, void *dev)
11171127
{
11181128
struct perf_output_handle **handle_ptr = dev;

0 commit comments

Comments
 (0)