Introduction of TPDM CMB(Continuous Multi Bit) subunit
CMB subunit is responsible for creating a dataset element, and is also
optionally responsible for packing it to fit multiple elements on a
single ATB transfer if possible in the configuration. The TPDM Core
Datapath requests timestamps be stored by the TPDA and then delivering
ATB sized data (depending on ATB width and element size, this could
be smaller or larger than a dataset element) to the ATB Mast FSM.
The CMB makes trace elements in two modes. In �continuous� mode, every
valid data cycle creates an element. In �trace on change� mode, when
valid data changes on the bus, a trace element is created. In
continuous mode, all cycles where this condition is true create trace
elements. In trace on change mode, a data element is only when the
previously sampled input is different from the current sampled input.
The CMB subunit must be configured prior to enablement. This series
adds support for TPDM to configure the configure CMB subunit.
Once this series patches are applied properly, the new tpdm nodes for
should be observed at the tpdm path /sys/bus/coresight/devices/tpdm*
which supports CMB subunit.
e.g.
root@qemuarm64:/sys/devices/platform/soc@0/684c000.tpdm/tpdm0# ls -l
-rw-r--r-- 1 root root 4096 Jan 1 00:00 cmb_mode
drwxr-xr-x 2 root root 0 Jan 1 00:00 cmb_msr
drwxr-xr-x 2 root root 0 Jan 1 00:00 cmb_patt
drwxr-xr-x 2 root root 0 Jan 1 00:00 cmb_trig_patt
-rw-r--r-- 1 root root 4096 Jan 1 00:00 cmb_trig_ts
-rw-r--r-- 1 root root 4096 Jan 1 00:00 cmb_ts_all
drwxr-xr-x 2 root root 0 Jan 1 00:00 connections
drwxr-xr-x 2 root root 0 Jan 1 00:00 dsb_edge
drwxr-xr-x 2 root root 0 Jan 1 00:00 dsb_msr
drwxr-xr-x 2 root root 0 Jan 1 00:00 dsb_patt
drwxr-xr-x 2 root root 0 Jan 1 00:00 dsb_trig_patt
-rw-r--r-- 1 root root 4096 Jan 1 00:00 enable_source
--w------- 1 root root 4096 Jan 1 00:00 integration_test
drwxr-xr-x 2 root root 0 Ja? 1 00:00 power
--w------- 1 root root 4096 Jan 1 00:00 reset_dataset
lrwxrwxrwx 1 root root 0 Apr 5 2021 subsystem -> ../../../../../bus/coresight
-rw-r--r-- 1 root root 4096 Apr 5 2021 uevent
-r--r--r-- 1 root root 4096 Jan 1 00:00 waiting_for_supplier
We can use the commands are similar to the below to configure the
TPDMs which support CMB subunit. Enable coresight sink first.
echo 1 > /sys/bus/coresight/devices/tmc_etf0/enable_sink
echo 1 > /sys/bus/coresight/devices/tpdm0/reset_dataset
echo 1 > /sys/bus/coresight/devices/tpdm0/cmb_mode
echo 1 > /sys/bus/coresight/devices/tpdm0/cmb_patt/enable_ts
echo 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/cmb_patt/tpmr0
echo 0 > /sys/bus/coresight/devices/tpdm0/cmb_trig_ts
echo 0xFFFFFFFF > /sys/bus/coresight/devices/tpdm0/cmb_trig_patt/xpr1
echo 1 > /sys/bus/coresight/devices/tpdm0/enable_source
codelinaro link:
https://git.codelinaro.org/clo/linux-kernel/coresight/-/commits/tpdm-cmb-v3
Changes in V3:
1. Add 8-bit support to the description in the TPDM devicetree document.
-- Rob Herring
2. Change how the result is produced in "tpdm_read_element_size".
-- James Clark
3. Calling "tpdm_clear_element_size" at the beginning of
"tpda_enable_port".
-- James Clark
4. Use "dsb_esize" and "cmb_esize" to determine whether multiple TPDMs
are detected on a TPDA input port in "tpda_get_element_size".
-- James Clark
5. Modify the judgment logic in "tpda_enable_port".
-- James Clark
6. Add more description of "cmb_mode" to TPDM SysFS document.
-- James Clark
Changes in V2:
1. Optimizate and modify this patch series based on the patch series
"Add support to configure TPDM CMB subunit".
2. Modify the functions that read the element size of DSB/CMB in TPDA driver.
Tao Zhang (8):
dt-bindings: arm: Add support for CMB element size
coresight-tpda: Add support to configure CMB element
coresight-tpdm: Add CMB dataset support
coresight-tpdm: Add support to configure CMB
coresight-tpdm: Add pattern registers support for CMB
coresight-tpdm: Add timestamp control register support for the CMB
dt-bindings: arm: Add support for TPDM CMB MSR register
coresight-tpdm: Add msr register support for CMB
.../testing/sysfs-bus-coresight-devices-tpdm | 87 ++++
.../bindings/arm/qcom,coresight-tpdm.yaml | 38 ++
drivers/hwtracing/coresight/coresight-tpda.c | 117 +++---
drivers/hwtracing/coresight/coresight-tpda.h | 6 +
drivers/hwtracing/coresight/coresight-tpdm.c | 390 +++++++++++++++++-
drivers/hwtracing/coresight/coresight-tpdm.h | 87 ++++
6 files changed, 673 insertions(+), 52 deletions(-)
--
2.17.1
On 15/01/2024 05:05, Randy Dunlap wrote:
> Change an empty line inside of kernel-doc to a " *" (kernel-doc
> blank line) to prevent a kernel-doc warning:
>
> drivers/hwtracing/coresight/coresight-etm3x-core.c:118: warning: bad line:
>
> Signed-off-by: Randy Dunlap <rdunlap(a)infradead.org>
> Cc: Pratik Patel <pratikp(a)codeaurora.org>
> Cc: Mathieu Poirier <mathieu.poirier(a)linaro.org>
> Cc: Suzuki K Poulose <suzuki.poulose(a)arm.com>
> Cc: Mike Leach <mike.leach(a)linaro.org>
> Cc: James Clark <james.clark(a)arm.com>
> Cc: Alexander Shishkin <alexander.shishkin(a)linux.intel.com>
> Cc: coresight(a)lists.linaro.org
> Cc: linux-arm-kernel(a)lists.infradead.org
> ---
> drivers/hwtracing/coresight/coresight-etm3x-core.c | 2 +-
> 1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff -- a/drivers/hwtracing/coresight/coresight-etm3x-core.c b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> --- a/drivers/hwtracing/coresight/coresight-etm3x-core.c
> +++ b/drivers/hwtracing/coresight/coresight-etm3x-core.c
> @@ -115,7 +115,7 @@ static void etm_clr_pwrup(struct etm_drv
> *
> * Basically the same as @coresight_timeout except for the register access
> * method where we have to account for CP14 configurations.
> -
> + *
> * Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
> * TIMEOUT_US has elapsed, which ever happens first.
> */
Duplicate of
https://lore.kernel.org/linux-arm-kernel/20231123120459.287578-3-james.clar…
which should appear in coresight-next soon. But either way, thanks for
the fix.
James
Hi Krzysztof,
> -----Original Message-----
> From: Krzysztof Kozlowski <krzysztof.kozlowski(a)linaro.org>
> Sent: Friday, January 5, 2024 3:24 PM
> To: Linu Cherian <lcherian(a)marvell.com>; suzuki.poulose(a)arm.com;
> mike.leach(a)linaro.org; james.clark(a)arm.com; leo.yan(a)linaro.org
> Cc: linux-arm-kernel(a)lists.infradead.org; coresight(a)lists.linaro.org; linux-
> kernel(a)vger.kernel.org; robh+dt(a)kernel.org;
> krzysztof.kozlowski+dt(a)linaro.org; conor+dt(a)kernel.org;
> devicetree(a)vger.kernel.org; Sunil Kovvuri Goutham
> <sgoutham(a)marvell.com>; George Cherian <gcherian(a)marvell.com>; Rob
> Herring <robh(a)kernel.org>
> Subject: [EXT] Re: [PATCH v6 1/7] dt-bindings: arm: coresight-tmc: Add
> "memory-region" property
>
> External Email
>
> ----------------------------------------------------------------------
> On 05/01/2024 06:58, Linu Cherian wrote:
> > memory-region 0: Reserved trace buffer memory
> >
> > TMC ETR: When available, use this reserved memory region for
> > trace data capture. Same region is used for trace data
> > retention after a panic or watchdog reset.
> >
> > TMC ETF: When available, use this reserved memory region for
> > trace data retention synced from internal SRAM after a panic or
> > watchdog reset.
> >
> > memory-region 1: Reserved meta data memory
> >
> > TMC ETR, ETF: When available, use this memory for register
> > snapshot retention synced from hardware registers after a panic
> > or watchdog reset.
> >
> > Reviewed-by: Rob Herring <robh(a)kernel.org>
>
> ...
>
> > + memory-region:
> > + items:
> > + - description: Reserved trace buffer memory for ETR and ETF sinks.
> > + For ETR, this reserved memory region is used for trace data capture.
> > + Same region is used for trace data retention as well after a panic
> > + or watchdog reset.
> > + This reserved memory region is used as trace buffer or used for
> trace
> > + data retention only if specifically selected by the user in sysfs
> > + interface.
> > + The default memory usage models for ETR in sysfs/perf modes are
> > + otherwise unaltered.
> > +
> > + For ETF, this reserved memory region is used by default for
> > + retention of trace data synced from internal SRAM after a panic
> > + or watchdog reset.
> > + - description: Reserved meta data memory. Used for ETR and ETF sinks
> > + for storing metadata.
>
> If there is going to be new version/resend, add a blank line here. Keep the Rb
> tag.
>
Okay. Will take care in next version.
Linu Cherian.
On 1/3/2024 11:32 PM, Rob Herring wrote:
> On Tue, Jan 2, 2024 at 5:05 AM Mike Leach <mike.leach(a)linaro.org> wrote:
>>
>> As James mentions this is clearly a V2 of a previous patch - please
>> mark as such in future.
>>
>> Adding to what James has already said:-
>>
>> 1) Mapping between the canonical names used in the drivers and the
>> information as to the precise device is as easy as running 'ls' on
>> /sys/bus/coresight/devices:-
>>
>> root@linaro-developer:/home/linaro/cs-mods# ls -al /sys/bus/coresight/devices/
>> total 0
>> drwxr-xr-x 2 root root 0 Jan 2 11:27 .
>> drwxr-xr-x 4 root root 0 Jan 2 11:27 ..
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 cti_cpu0 ->
>> ../../../devices/platform/soc(a)0/858000.cti/cti_cpu0
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 cti_cpu1 ->
>> ../../../devices/platform/soc(a)0/859000.cti/cti_cpu1
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 cti_cpu2 ->
>> ../../../devices/platform/soc(a)0/85a000.cti/cti_cpu2
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 cti_cpu3 ->
>> ../../../devices/platform/soc(a)0/85b000.cti/cti_cpu3
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 cti_sys0 ->
>> ../../../devices/platform/soc(a)0/810000.cti/cti_sys0
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 cti_sys1 ->
>> ../../../devices/platform/soc(a)0/811000.cti/cti_sys1
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 etm0 ->
>> ../../../devices/platform/soc(a)0/85c000.etm/etm0
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 etm1 ->
>> ../../../devices/platform/soc(a)0/85d000.etm/etm1
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 etm2 ->
>> ../../../devices/platform/soc(a)0/85e000.etm/etm2
>> lrwxrwxrwx 1 root root 0 Jan 2 11:27 etm3 ->
>> ../../../devices/platform/soc(a)0/85f000.etm/etm3
>> lrwxrwxrwx 1 root root 0 Jan 2 11:42 funnel0 ->
>> ../../../devices/platform/soc(a)0/821000.funnel/funnel0
>> lrwxrwxrwx 1 root root 0 Jan 2 11:42 funnel1 ->
>> ../../../devices/platform/soc(a)0/841000.funnel/funnel1
>> lrwxrwxrwx 1 root root 0 Jan 2 11:42 replicator0 ->
>> ../../../devices/platform/soc(a)0/824000.replicator/replicator0
>> lrwxrwxrwx 1 root root 0 Jan 2 11:42 tmc_etf0 ->
>> ../../../devices/platform/soc(a)0/825000.etf/tmc_etf0
>> lrwxrwxrwx 1 root root 0 Jan 2 11:42 tmc_etr0 ->
>> ../../../devices/platform/soc(a)0/826000.etr/tmc_etr0
>>
>>
>> 2) The patch set must contain the usage and specification in the .yaml
>> file(s) of the property used.
>
> For the record, I don't like "coresight-name". I don't have another
> suggestion because "easy" is not sufficient reasoning for why this is
> needed.
For example, if we want to configure the trigger and HW events for
modem, we can't know which cti or TPDM is for modem from current names.
lrwxrwxrwx 1 root 0 0 Jan 1 00:01 cti_sys0 ->
../../../devices/platform/soc(a)0/138f0000.cti/cti_sys0
lrwxrwxrwx 1 root 0 0 Jan 1 00:01 cti_sys1 ->
../../../devices/platform/soc(a)0/13900000.cti/cti_sys1
lrwxrwxrwx 1 root 0 0 Jan 1 00:01 tpdm0 ->
../../../devices/platform/soc(a)0/10b0d000.tpdm/tpdm0
lrwxrwxrwx 1 root 0 0 Jan 1 00:01 tpdm1 ->
../../../devices/platform/soc(a)0/10c28000.tpdm/tpdm1
lrwxrwxrwx 1 root 0 0 Jan 1 00:01 tpdm2 ->
../../../devices/platform/soc(a)0/10c29000.tpdm/tpdm2
Thanks
Jinlong Mao
>
>> However, there was a standard property called 'name' which is
>> deprecated - see
>> https://devicetree-specification.readthedocs.io/en/latest/chapter2-devicetr…
>> section 2.3.11. I do not believe that adding another 'name' property
>> would be accepted by the DT maintainers.
>
> "name" is just the node name for anything in the last 15 years. They
> used to be separate, but would still mostly be the same. The only case
> I found with them different was old PowerPC Macs.
>
>> 3) the 'device_node' structure has a 'name' field that contains the
>> node name in the DT approved "node-name@unit-address" format.
>
> Actually, it is without the unit-address. full_name is with the unit-address.
>
>> This
>> contains whatever node names you used in the dt. Why not use this if
>> a change has to be made and find some conditional to activate it.
>
> Don't go accessing "name" or "full_name" directly. I intend to get rid
> of "name" and generate it from full_name. So use the accessors and
> printk specifiers if you need node names.
>
> Rob
On 04/01/2024 16:27, James Clark wrote:
> The guest value for TRFCR requested by the Coresight driver is saved in
> kvm_host_global_state. On guest switch this value needs to be written to
> the register. Currently TRFCR is only modified when we want to disable
> trace completely in guests due to an issue with TRBE. Expand the
> __debug_save_trace() function to always write to the register if a
> different value for guests is required, but also keep the existing TRBE
> disable behavior if that's required.
>
> The TRFCR restore function remains functionally the same, except a value
> of 0 doesn't mean "don't restore" anymore. Now that we save both guest
> and host values the register is restored any time the guest and host
> values differ.
>
> Signed-off-by: James Clark <james.clark(a)arm.com>
> ---
> arch/arm64/kvm/hyp/nvhe/debug-sr.c | 55 ++++++++++++++++++------------
> 1 file changed, 34 insertions(+), 21 deletions(-)
>
> diff --git a/arch/arm64/kvm/hyp/nvhe/debug-sr.c b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
> index 4558c02eb352..7fd876d4f034 100644
> --- a/arch/arm64/kvm/hyp/nvhe/debug-sr.c
> +++ b/arch/arm64/kvm/hyp/nvhe/debug-sr.c
> @@ -51,32 +51,45 @@ static void __debug_restore_spe(u64 pmscr_el1)
> write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1);
> }
>
> -static void __debug_save_trace(u64 *trfcr_el1)
> +/*
> + * Save TRFCR and disable trace completely if TRBE is being used, otherwise
> + * apply required guest TRFCR value.
> + */
> +static void __debug_save_trace(struct kvm_vcpu *vcpu)
> {
> - *trfcr_el1 = 0;
> + u64 host_trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1);
> + u64 guest_trfcr_el1;
> +
> + vcpu->arch.host_debug_state.trfcr_el1 = host_trfcr_el1;
>
> /* Check if the TRBE is enabled */
> - if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E))
> - return;
> - /*
> - * Prohibit trace generation while we are in guest.
> - * Since access to TRFCR_EL1 is trapped, the guest can't
> - * modify the filtering set by the host.
> - */
> - *trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1);
> - write_sysreg_s(0, SYS_TRFCR_EL1);
> - isb();
> - /* Drain the trace buffer to memory */
> - tsb_csync();
> + if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE) &&
> + (read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_EL1_E)) {
> + /*
> + * Prohibit trace generation while we are in guest. Since access
> + * to TRFCR_EL1 is trapped, the guest can't modify the filtering
> + * set by the host.
> + */
> + write_sysreg_s(0, SYS_TRFCR_EL1);
> + isb();
> + /* Drain the trace buffer to memory */
> + tsb_csync();
> + } else {
> + /*
> + * Not using TRBE, so guest trace works. Apply the guest filters
> + * provided by the Coresight driver, if different.
> + */
> + guest_trfcr_el1 = kvm_host_global_state[vcpu->cpu].guest_trfcr_el1;
> + if (host_trfcr_el1 != guest_trfcr_el1)
> + write_sysreg_s(guest_trfcr_el1, SYS_TRFCR_EL1);
> + }
> }
>
> static void __debug_restore_trace(u64 trfcr_el1)
> {
> - if (!trfcr_el1)
> - return;
> -
> /* Restore trace filter controls */
> - write_sysreg_s(trfcr_el1, SYS_TRFCR_EL1);
> + if (trfcr_el1 != read_sysreg_s(SYS_TRFCR_EL1))
> + write_sysreg_s(trfcr_el1, SYS_TRFCR_EL1);
Could we not write it unconditionally here ? In the saving step, we have
to save the host setting. But while restoring, we could skip the check.
A read and write is probably the same cost, as the value is implicitly
synchronized by a later ISB.
Eitherways,
Reviewed-by: Suzuki K Poulose <suzuki.poulose(a)arm.com>
> }
>
> void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
> @@ -85,8 +98,8 @@ void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
> if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE))
> __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1);
> /* Disable and flush Self-Hosted Trace generation */
> - if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
> - __debug_save_trace(&vcpu->arch.host_debug_state.trfcr_el1);
> + if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRFCR))
> + __debug_save_trace(vcpu);
> }
>
> void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
> @@ -98,7 +111,7 @@ void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
> {
> if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE))
> __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1);
> - if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
> + if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRFCR))
> __debug_restore_trace(vcpu->arch.host_debug_state.trfcr_el1);
> }
>
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.
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 <james.clark(a)arm.com>
---
.../coresight/coresight-etm4x-core.c | 42 ++++++++++++++++---
drivers/hwtracing/coresight/coresight-etm4x.h | 2 +-
drivers/hwtracing/coresight/coresight-priv.h | 3 ++
3 files changed, 40 insertions(+), 7 deletions(-)
diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c
index 34aee59dd147..885d70fd6f40 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x-core.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c
@@ -6,6 +6,7 @@
#include <linux/acpi.h>
#include <linux/bitops.h>
#include <linux/kernel.h>
+#include <linux/kvm_host.h>
#include <linux/moduleparam.h>
#include <linux/init.h>
#include <linux/types.h>
@@ -271,9 +272,22 @@ static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
/* If the CPU doesn't support FEAT_TRF, nothing to do */
if (!drvdata->trfcr)
return;
+ kvm_etm_set_guest_trfcr(0);
cpu_prohibit_trace();
}
+static u64 etm4x_get_kern_user_filter(struct etmv4_drvdata *drvdata)
+{
+ u64 trfcr = drvdata->trfcr;
+
+ if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
+ trfcr &= ~TRFCR_ELx_ExTRE;
+ if (drvdata->config.mode & ETM_MODE_EXCL_USER)
+ trfcr &= ~TRFCR_ELx_E0TRE;
+
+ return trfcr;
+}
+
/*
* etm4x_allow_trace - Allow CPU tracing in the respective ELs,
* as configured by the drvdata->config.mode for the current
@@ -286,18 +300,28 @@ static void etm4x_prohibit_trace(struct etmv4_drvdata *drvdata)
*/
static void etm4x_allow_trace(struct etmv4_drvdata *drvdata)
{
- u64 trfcr = drvdata->trfcr;
+ u64 trfcr;
/* If the CPU doesn't support FEAT_TRF, nothing to do */
- if (!trfcr)
+ if (!drvdata->trfcr)
return;
- if (drvdata->config.mode & ETM_MODE_EXCL_KERN)
- trfcr &= ~TRFCR_ELx_ExTRE;
- if (drvdata->config.mode & ETM_MODE_EXCL_USER)
- trfcr &= ~TRFCR_ELx_E0TRE;
+ if (drvdata->config.mode & ETM_MODE_EXCL_HOST)
+ trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
+ else
+ trfcr = etm4x_get_kern_user_filter(drvdata);
write_trfcr(trfcr);
+
+ /* Set filters for guests and pass to KVM */
+ if (drvdata->config.mode & ETM_MODE_EXCL_GUEST)
+ trfcr = drvdata->trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE);
+ else
+ trfcr = etm4x_get_kern_user_filter(drvdata);
+
+ /* TRFCR_EL1 doesn't have CX so mask it out. */
+ trfcr &= ~TRFCR_EL2_CX;
+ kvm_etm_set_guest_trfcr(trfcr);
}
#ifdef CONFIG_ETM4X_IMPDEF_FEATURE
@@ -655,6 +679,12 @@ static int etm4_parse_event_config(struct coresight_device *csdev,
if (attr->exclude_user)
config->mode = ETM_MODE_EXCL_USER;
+ if (attr->exclude_host)
+ config->mode |= ETM_MODE_EXCL_HOST;
+
+ if (attr->exclude_guest)
+ config->mode |= ETM_MODE_EXCL_GUEST;
+
/* Always start from the default config */
etm4_set_default_config(config);
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h
index 20e2e4cb7614..3f170599822f 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.h
+++ b/drivers/hwtracing/coresight/coresight-etm4x.h
@@ -841,7 +841,7 @@ enum etm_impdef_type {
* @s_ex_level: Secure ELs where tracing is supported.
*/
struct etmv4_config {
- u32 mode;
+ u64 mode;
u32 pe_sel;
u32 cfg;
u32 eventctrl0;
diff --git a/drivers/hwtracing/coresight/coresight-priv.h b/drivers/hwtracing/coresight/coresight-priv.h
index 767076e07970..727dd27ba800 100644
--- a/drivers/hwtracing/coresight/coresight-priv.h
+++ b/drivers/hwtracing/coresight/coresight-priv.h
@@ -39,6 +39,9 @@
#define ETM_MODE_EXCL_KERN BIT(30)
#define ETM_MODE_EXCL_USER BIT(31)
+#define ETM_MODE_EXCL_HOST BIT(32)
+#define ETM_MODE_EXCL_GUEST BIT(33)
+
struct cs_pair_attribute {
struct device_attribute attr;
u32 lo_off;
--
2.34.1
On 04/01/2024 16:27, James Clark wrote:
> Add an interface for the Coresight driver to use to set the value of the
> TRFCR register for the guest. This register controls the exclude
> settings for trace at different exception levels, and is used to honor
> the exclude_host and exclude_guest parameters from the Perf session.
> This will be used to later write TRFCR_EL1 on nVHE at guest switch. For
> VHE, the host trace is controlled by TRFCR_EL2 and thus we can write to
> the TRFCR_EL1 immediately. Because guest writes to the register are
> trapped, the value will persist and can't be modified.
>
> Signed-off-by: James Clark <james.clark(a)arm.com>
> ---
> arch/arm64/include/asm/kvm_host.h | 3 +++
> arch/arm64/kvm/debug.c | 24 ++++++++++++++++++++++++
> 2 files changed, 27 insertions(+)
>
> diff --git a/arch/arm64/include/asm/kvm_host.h b/arch/arm64/include/asm/kvm_host.h
> index 4864a1fcdf89..ee6cba7ee6ee 100644
> --- a/arch/arm64/include/asm/kvm_host.h
> +++ b/arch/arm64/include/asm/kvm_host.h
> @@ -471,6 +471,7 @@ struct kvm_host_global_state {
> u32 events_host;
> u32 events_guest;
> } pmu_events;
> + u64 guest_trfcr_el1;
> } ____cacheline_aligned;
> extern struct kvm_host_global_state kvm_host_global_state[NR_CPUS];
>
> @@ -1145,6 +1146,7 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu);
> void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr);
> void kvm_clr_pmu_events(u32 clr);
> bool kvm_set_pmuserenr(u64 val);
> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest);
> #else
> static inline void kvm_set_pmu_events(u32 set, struct perf_event_attr *attr) {}
> static inline void kvm_clr_pmu_events(u32 clr) {}
> @@ -1152,6 +1154,7 @@ static inline bool kvm_set_pmuserenr(u64 val)
> {
> return false;
> }
> +static inline void kvm_etm_set_guest_trfcr(u64 trfcr_guest) {}
> #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 f86cbfae60f3..d69a0b9d9575 100644
> --- a/arch/arm64/kvm/debug.c
> +++ b/arch/arm64/kvm/debug.c
> @@ -358,3 +358,27 @@ void kvm_arch_vcpu_put_debug_state_flags(struct kvm_vcpu *vcpu)
> vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRBE);
> vcpu_clear_flag(vcpu, DEBUG_STATE_SAVE_TRFCR);
> }
> +
> +/*
> + * Interface for the Coresight driver to use to set the value of the TRFCR
> + * register for the guest. This register controls the exclude settings for trace
> + * at different exception levels, and is used to honor the exclude_host and
> + * exclude_guest parameters from the Perf session.
> + *
> + * This will be used to later write TRFCR_EL1 on nVHE at guest switch. For VHE,
> + * the host trace is controlled by TRFCR_EL2 and thus we can write to the
> + * TRFCR_EL1 immediately. Because guest writes to the register are trapped, the
> + * value will persist and can't be modified.
> + */
> +void kvm_etm_set_guest_trfcr(u64 trfcr_guest)
> +{
> + if (!cpuid_feature_extract_unsigned_field(read_sysreg(id_aa64dfr0_el1),
> + ID_AA64DFR0_EL1_TraceFilt_SHIFT))
Perhaps WARN_ON_ONCE() ?
Otherwise,
Reviewed-by: Suzuki K Poulose <suzuki.poulose(a)arm.com>
> + return;
> +
> + if (has_vhe())
> + write_sysreg_s(trfcr_guest, SYS_TRFCR_EL12);
> + else
> + kvm_host_global_state[smp_processor_id()].guest_trfcr_el1 = trfcr_guest;
> +}
> +EXPORT_SYMBOL_GPL(kvm_etm_set_guest_trfcr);