未验证 提交 fc4cda52 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!225 Synchronize the coresight code of the Linux mainline to support HiSilicon tracing

Merge Pull Request from: @hejunhao3 
 

```
Synchronize the coresight code of the Linux mainline to support HiSilicon tracing

[Testing]
kernel config
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=m
CONFIG_CORESIGHT_TRBE=m

[test log]
insmod coresight.ko coresight-etm4x.ko coresight-funnel.ko coresight-tmc.ko
estuary:/$ ls /sys/bus/coresight/devices/
ete0      ete12     ete2      ete6      funnel0   tmc_etf0  tmc_etr0
ete1      ete13     ete3      ete7      funnel1   tmc_etf1
ete10     ete14     ete4      ete8      funnel2   tmc_etf2
ete11     ete15     ete5      ete9      funnel3   tmc_etf3
estuary:/$ echo 1 > /sys/bus/coresight/devices/tmc_etr0/enable_sink
estuary:/$ echo 1 > /sys/bus/coresight/devices/ete3/enable_source
estuary:/$ cat /sys/bus/coresight/devices/tmc_etr0/mgmt/rwp
0x79100000
estuary:/$ cat /sys/bus/coresight/devices/tmc_etr0/mgmt/rwp
0x79106e00
estuary:/$ echo 0 > /sys/bus/coresight/devices/ete3/enable_source
estuary:/$ insmod /lib/modules/5.10.0+/ram_blk_drv.ko p_addr=0x79100000 p_size=0x3000
estuary:/$ dd if=/dev/ramblock  of=sys_c1_range.data bs=4k count=48
3+0 records in
3+0 records out
12288 bytes (12.0KB) copied, 0.028941 seconds, 414.6KB/s
estuary:/$ ptm2human -e -i sys_c1_range.data >sys_c1_range.data.log 2>&1
estuary:/$ grep sys_c1_range.data.log | "Decode trace stream of ID"
[22;1HDecode trace stream of ID 21
estuary:/$ 
estuary:/$ perf record -e /cs_etm/@tmc_etr0/ -C 7 taskset -c 7 uname -a
Linux (none) 5.10.0+ #3 SMP Thu Oct 27 14:51:05 CST 2022 aarch64 GNU/Linux
[ 2900.563565][  T306] coresight tmc_etr0: timeout while waiting for completion of Manual Flush
[ perf record: Woken up 1 times to write data ]
[ perf record: Captured and wrote 0.588 MB perf.data ]
estuary:/$ perf report --stdio -D > report.txt
estuary:/$ grep -rn "I_ASYNC : Alignment Synchronisation" report.txt
4244:	Idx:0; ID:1e;	I_ASYNC : Alignment Synchronisation.
6913:	Idx:4429; ID:1e;	I_ASYNC : Alignment Synchronisation.
9279:	Idx:8833; ID:1e;	I_ASYNC : Alignment Synchronisation.
```
 
 
Link:https://gitee.com/openeuler/kernel/pulls/225 
Reviewed-by: Zheng Zengkai <zhengzengkai@huawei.com> 
Reviewed-by: Ling Mingqiang <lingmingqiang@huawei.com> 
Reviewed-by: Xie XiuQi <xiexiuqi@huawei.com> 
Signed-off-by: Zheng Zengkai <zhengzengkai@huawei.com> 
......@@ -371,6 +371,14 @@ Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (Read) Print the content of the Device ID Register
(0xFC8). The value is taken directly from the HW.
What: /sys/bus/coresight/devices/etm<N>/mgmt/trcdevarch
Date: January 2021
KernelVersion: 5.12
Contact: Mathieu Poirier <mathieu.poirier@linaro.org>
Description: (Read) Print the content of the Device Architecture Register
(offset 0xFBC). The value is taken directly read
from the HW.
What: /sys/bus/coresight/devices/etm<N>/mgmt/trcdevtype
Date: April 2015
KernelVersion: 4.01
......
......@@ -7244,7 +7244,7 @@ CONFIG_IO_STRICT_DEVMEM=y
# CONFIG_ARM64_RELOC_TEST is not set
CONFIG_CORESIGHT=m
CONFIG_CORESIGHT_LINKS_AND_SINKS=m
# CONFIG_CORESIGHT_LINK_AND_SINK_TMC is not set
CONFIG_CORESIGHT_LINK_AND_SINK_TMC=m
# CONFIG_CORESIGHT_SINK_TPIU is not set
# CONFIG_CORESIGHT_SINK_ETBV10 is not set
CONFIG_CORESIGHT_SOURCE_ETM4X=m
......@@ -7252,7 +7252,7 @@ CONFIG_ETM4X_IMPDEF_FEATURE=y
# CONFIG_CORESIGHT_STM is not set
# CONFIG_CORESIGHT_CPU_DEBUG is not set
# CONFIG_CORESIGHT_CTI is not set
# CONFIG_CORESIGHT_TRBE is not set
CONFIG_CORESIGHT_TRBE=m
CONFIG_ULTRASOC_SMB=m
# end of arm64 Debugging
......
......@@ -23,6 +23,7 @@
#define dsb(opt) asm volatile("dsb " #opt : : : "memory")
#define psb_csync() asm volatile("hint #17" : : : "memory")
#define tsb_csync() asm volatile("hint #18" : : : "memory")
#define csdb() asm volatile("hint #20" : : : "memory")
/*
......
......@@ -192,6 +192,7 @@
#define SYS_GCR_EL1 sys_reg(3, 0, 1, 0, 6)
#define SYS_ZCR_EL1 sys_reg(3, 0, 1, 2, 0)
#define SYS_TRFCR_EL1 sys_reg(3, 0, 1, 2, 1)
#define SYS_TTBR0_EL1 sys_reg(3, 0, 2, 0, 0)
#define SYS_TTBR1_EL1 sys_reg(3, 0, 2, 0, 1)
......@@ -333,6 +334,55 @@
/*** End of Statistical Profiling Extension ***/
/*
* TRBE Registers
*/
#define SYS_TRBLIMITR_EL1 sys_reg(3, 0, 9, 11, 0)
#define SYS_TRBPTR_EL1 sys_reg(3, 0, 9, 11, 1)
#define SYS_TRBBASER_EL1 sys_reg(3, 0, 9, 11, 2)
#define SYS_TRBSR_EL1 sys_reg(3, 0, 9, 11, 3)
#define SYS_TRBMAR_EL1 sys_reg(3, 0, 9, 11, 4)
#define SYS_TRBTRG_EL1 sys_reg(3, 0, 9, 11, 6)
#define SYS_TRBIDR_EL1 sys_reg(3, 0, 9, 11, 7)
#define TRBLIMITR_LIMIT_MASK GENMASK_ULL(51, 0)
#define TRBLIMITR_LIMIT_SHIFT 12
#define TRBLIMITR_NVM BIT(5)
#define TRBLIMITR_TRIG_MODE_MASK GENMASK(1, 0)
#define TRBLIMITR_TRIG_MODE_SHIFT 3
#define TRBLIMITR_FILL_MODE_MASK GENMASK(1, 0)
#define TRBLIMITR_FILL_MODE_SHIFT 1
#define TRBLIMITR_ENABLE BIT(0)
#define TRBPTR_PTR_MASK GENMASK_ULL(63, 0)
#define TRBPTR_PTR_SHIFT 0
#define TRBBASER_BASE_MASK GENMASK_ULL(51, 0)
#define TRBBASER_BASE_SHIFT 12
#define TRBSR_EC_MASK GENMASK(5, 0)
#define TRBSR_EC_SHIFT 26
#define TRBSR_IRQ BIT(22)
#define TRBSR_TRG BIT(21)
#define TRBSR_WRAP BIT(20)
#define TRBSR_ABORT BIT(18)
#define TRBSR_STOP BIT(17)
#define TRBSR_MSS_MASK GENMASK(15, 0)
#define TRBSR_MSS_SHIFT 0
#define TRBSR_BSC_MASK GENMASK(5, 0)
#define TRBSR_BSC_SHIFT 0
#define TRBSR_FSC_MASK GENMASK(5, 0)
#define TRBSR_FSC_SHIFT 0
#define TRBMAR_SHARE_MASK GENMASK(1, 0)
#define TRBMAR_SHARE_SHIFT 8
#define TRBMAR_OUTER_MASK GENMASK(3, 0)
#define TRBMAR_OUTER_SHIFT 4
#define TRBMAR_INNER_MASK GENMASK(3, 0)
#define TRBMAR_INNER_SHIFT 0
#define TRBTRG_TRG_MASK GENMASK(31, 0)
#define TRBTRG_TRG_SHIFT 0
#define TRBIDR_FLAG BIT(5)
#define TRBIDR_PROG BIT(4)
#define TRBIDR_ALIGN_MASK GENMASK(3, 0)
#define TRBIDR_ALIGN_SHIFT 0
#define SYS_PMINTENSET_EL1 sys_reg(3, 0, 9, 14, 1)
#define SYS_PMINTENCLR_EL1 sys_reg(3, 0, 9, 14, 2)
......@@ -478,6 +528,7 @@
#define SYS_PMCCFILTR_EL0 sys_reg(3, 3, 14, 15, 7)
#define SYS_ZCR_EL2 sys_reg(3, 4, 1, 2, 0)
#define SYS_TRFCR_EL2 sys_reg(3, 4, 1, 2, 1)
#define SYS_DACR32_EL2 sys_reg(3, 4, 3, 0, 0)
#define SYS_SPSR_EL2 sys_reg(3, 4, 4, 0, 0)
#define SYS_ELR_EL2 sys_reg(3, 4, 4, 0, 1)
......@@ -855,6 +906,8 @@
#define ID_AA64MMFR2_CNP_SHIFT 0
/* id_aa64dfr0 */
#define ID_AA64DFR0_TRBE_SHIFT 44
#define ID_AA64DFR0_TRACE_FILT_SHIFT 40
#define ID_AA64DFR0_DOUBLELOCK_SHIFT 36
#define ID_AA64DFR0_PMSVER_SHIFT 32
#define ID_AA64DFR0_CTX_CMPS_SHIFT 28
......@@ -1032,6 +1085,14 @@
/* Safe value for MPIDR_EL1: Bit31:RES1, Bit30:U:0, Bit24:MT:0 */
#define SYS_MPIDR_SAFE_VAL (BIT(31))
#define TRFCR_ELx_TS_SHIFT 5
#define TRFCR_ELx_TS_VIRTUAL ((0x1UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_ELx_TS_GUEST_PHYSICAL ((0x2UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_ELx_TS_PHYSICAL ((0x3UL) << TRFCR_ELx_TS_SHIFT)
#define TRFCR_EL2_CX BIT(3)
#define TRFCR_ELx_ExTRE BIT(1)
#define TRFCR_ELx_E0TRE BIT(0)
#ifdef __ASSEMBLY__
.irp num,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30
......
......@@ -1573,6 +1573,7 @@ static const struct sys_reg_desc sys_reg_descs[] = {
{ SYS_DESC(SYS_GCR_EL1), undef_access },
{ SYS_DESC(SYS_ZCR_EL1), NULL, reset_val, ZCR_EL1, 0, .visibility = sve_visibility },
{ SYS_DESC(SYS_TRFCR_EL1), undef_access },
{ SYS_DESC(SYS_TTBR0_EL1), access_vm_reg, reset_unknown, TTBR0_EL1 },
{ SYS_DESC(SYS_TTBR1_EL1), access_vm_reg, reset_unknown, TTBR1_EL1 },
{ SYS_DESC(SYS_TCR_EL1), access_vm_reg, reset_val, TCR_EL1, 0 },
......
......@@ -97,15 +97,15 @@ config CORESIGHT_SOURCE_ETM3X
module will be called coresight-etm3x.
config CORESIGHT_SOURCE_ETM4X
tristate "CoreSight Embedded Trace Macrocell 4.x driver"
tristate "CoreSight ETMv4.x / ETE driver"
depends on ARM64
select CORESIGHT_LINKS_AND_SINKS
select PID_IN_CONTEXTIDR
help
This driver provides support for the ETM4.x tracer module, tracing the
instructions that a processor is executing. This is primarily useful
for instruction level tracing. Depending on the implemented version
data tracing may also be available.
This driver provides support for the CoreSight Embedded Trace Macrocell
version 4.x and the Embedded Trace Extensions (ETE). Both are CPU tracer
modules, tracing the instructions that a processor is executing. This is
primarily useful for instruction level tracing.
To compile this driver as a module, choose M here: the
module will be called coresight-etm4x.
......@@ -174,6 +174,20 @@ config CORESIGHT_CTI_INTEGRATION_REGS
registers are not used in normal operation and can leave devices in
an inconsistent state.
config CORESIGHT_TRBE
tristate "Trace Buffer Extension (TRBE) driver"
depends on ARM64 && CORESIGHT_SOURCE_ETM4X
help
This driver provides support for percpu Trace Buffer Extension (TRBE).
TRBE always needs to be used along with it's corresponding percpu ETE
component. ETE generates trace data which is then captured with TRBE.
Unlike traditional sink devices, TRBE is a CPU feature accessible via
system registers. But it's explicit dependency with trace unit (ETE)
requires it to be plugged in as a coresight sink device.
To compile this driver as a module, choose M here: the module will be
called coresight-trbe.
config ULTRASOC_SMB
tristate "Ultrasoc system memory buffer drivers"
depends on ARM64 && CORESIGHT_LINKS_AND_SINKS
......
......@@ -21,6 +21,7 @@ obj-$(CONFIG_CORESIGHT_STM) += coresight-stm.o
obj-$(CONFIG_CORESIGHT_CPU_DEBUG) += coresight-cpu-debug.o
obj-$(CONFIG_CORESIGHT_CATU) += coresight-catu.o
obj-$(CONFIG_CORESIGHT_CTI) += coresight-cti.o
obj-$(CONFIG_CORESIGHT_TRBE) += coresight-trbe.o
coresight-cti-y := coresight-cti-core.o coresight-cti-platform.o \
coresight-cti-sysfs.o
obj-$(CONFIG_ULTRASOC_SMB) += ultrasoc-smb.o
......@@ -401,8 +401,9 @@ static const struct attribute_group *catu_groups[] = {
static inline int catu_wait_for_ready(struct catu_drvdata *drvdata)
{
return coresight_timeout(drvdata->base,
CATU_STATUS, CATU_STATUS_READY, 1);
struct csdev_access *csa = &drvdata->csdev->access;
return coresight_timeout(csa, CATU_STATUS, CATU_STATUS_READY, 1);
}
static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
......@@ -411,6 +412,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
u32 control, mode;
struct etr_buf *etr_buf = data;
struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev;
if (catu_wait_for_ready(drvdata))
dev_warn(dev, "Timeout while waiting for READY\n");
......@@ -421,7 +423,7 @@ static int catu_enable_hw(struct catu_drvdata *drvdata, void *data)
return -EBUSY;
}
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev);
if (rc)
return rc;
......@@ -465,9 +467,10 @@ static int catu_disable_hw(struct catu_drvdata *drvdata)
{
int rc = 0;
struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev;
catu_write_control(drvdata, 0);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
if (catu_wait_for_ready(drvdata)) {
dev_info(dev, "Timeout while waiting for READY\n");
rc = -EAGAIN;
......@@ -551,6 +554,7 @@ static int catu_probe(struct amba_device *adev, const struct amba_id *id)
dev->platform_data = pdata;
drvdata->base = base;
catu_desc.access = CSDEV_ACCESS_IOMEM(base);
catu_desc.pdata = pdata;
catu_desc.dev = dev;
catu_desc.groups = catu_groups;
......
......@@ -23,6 +23,7 @@
#include "coresight-priv.h"
static DEFINE_MUTEX(coresight_mutex);
DEFINE_PER_CPU(struct coresight_device *, csdev_sink);
/**
* struct coresight_node - elements of a path, from source to sink
......@@ -70,6 +71,18 @@ void coresight_remove_cti_ops(void)
}
EXPORT_SYMBOL_GPL(coresight_remove_cti_ops);
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev)
{
per_cpu(csdev_sink, cpu) = csdev;
}
EXPORT_SYMBOL_GPL(coresight_set_percpu_sink);
struct coresight_device *coresight_get_percpu_sink(int cpu)
{
return per_cpu(csdev_sink, cpu);
}
EXPORT_SYMBOL_GPL(coresight_get_percpu_sink);
static int coresight_id_match(struct device *dev, void *data)
{
int trace_id, i_trace_id;
......@@ -145,30 +158,32 @@ static int coresight_find_link_outport(struct coresight_device *csdev,
return -ENODEV;
}
static inline u32 coresight_read_claim_tags(void __iomem *base)
static inline u32 coresight_read_claim_tags(struct coresight_device *csdev)
{
return readl_relaxed(base + CORESIGHT_CLAIMCLR);
return csdev_access_relaxed_read32(&csdev->access, CORESIGHT_CLAIMCLR);
}
static inline bool coresight_is_claimed_self_hosted(void __iomem *base)
static inline bool coresight_is_claimed_self_hosted(struct coresight_device *csdev)
{
return coresight_read_claim_tags(base) == CORESIGHT_CLAIM_SELF_HOSTED;
return coresight_read_claim_tags(csdev) == CORESIGHT_CLAIM_SELF_HOSTED;
}
static inline bool coresight_is_claimed_any(void __iomem *base)
static inline bool coresight_is_claimed_any(struct coresight_device *csdev)
{
return coresight_read_claim_tags(base) != 0;
return coresight_read_claim_tags(csdev) != 0;
}
static inline void coresight_set_claim_tags(void __iomem *base)
static inline void coresight_set_claim_tags(struct coresight_device *csdev)
{
writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMSET);
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
CORESIGHT_CLAIMSET);
isb();
}
static inline void coresight_clear_claim_tags(void __iomem *base)
static inline void coresight_clear_claim_tags(struct coresight_device *csdev)
{
writel_relaxed(CORESIGHT_CLAIM_SELF_HOSTED, base + CORESIGHT_CLAIMCLR);
csdev_access_relaxed_write32(&csdev->access, CORESIGHT_CLAIM_SELF_HOSTED,
CORESIGHT_CLAIMCLR);
isb();
}
......@@ -182,27 +197,33 @@ static inline void coresight_clear_claim_tags(void __iomem *base)
* Called with CS_UNLOCKed for the component.
* Returns : 0 on success
*/
int coresight_claim_device_unlocked(void __iomem *base)
int coresight_claim_device_unlocked(struct coresight_device *csdev)
{
if (coresight_is_claimed_any(base))
if (WARN_ON(!csdev))
return -EINVAL;
if (coresight_is_claimed_any(csdev))
return -EBUSY;
coresight_set_claim_tags(base);
if (coresight_is_claimed_self_hosted(base))
coresight_set_claim_tags(csdev);
if (coresight_is_claimed_self_hosted(csdev))
return 0;
/* There was a race setting the tags, clean up and fail */
coresight_clear_claim_tags(base);
coresight_clear_claim_tags(csdev);
return -EBUSY;
}
EXPORT_SYMBOL_GPL(coresight_claim_device_unlocked);
int coresight_claim_device(void __iomem *base)
int coresight_claim_device(struct coresight_device *csdev)
{
int rc;
CS_UNLOCK(base);
rc = coresight_claim_device_unlocked(base);
CS_LOCK(base);
if (WARN_ON(!csdev))
return -EINVAL;
CS_UNLOCK(csdev->access.base);
rc = coresight_claim_device_unlocked(csdev);
CS_LOCK(csdev->access.base);
return rc;
}
......@@ -212,11 +233,14 @@ EXPORT_SYMBOL_GPL(coresight_claim_device);
* coresight_disclaim_device_unlocked : Clear the claim tags for the device.
* Called with CS_UNLOCKed for the component.
*/
void coresight_disclaim_device_unlocked(void __iomem *base)
void coresight_disclaim_device_unlocked(struct coresight_device *csdev)
{
if (coresight_is_claimed_self_hosted(base))
coresight_clear_claim_tags(base);
if (WARN_ON(!csdev))
return;
if (coresight_is_claimed_self_hosted(csdev))
coresight_clear_claim_tags(csdev);
else
/*
* The external agent may have not honoured our claim
......@@ -227,11 +251,14 @@ void coresight_disclaim_device_unlocked(void __iomem *base)
}
EXPORT_SYMBOL_GPL(coresight_disclaim_device_unlocked);
void coresight_disclaim_device(void __iomem *base)
void coresight_disclaim_device(struct coresight_device *csdev)
{
CS_UNLOCK(base);
coresight_disclaim_device_unlocked(base);
CS_LOCK(base);
if (WARN_ON(!csdev))
return;
CS_UNLOCK(csdev->access.base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(csdev->access.base);
}
EXPORT_SYMBOL_GPL(coresight_disclaim_device);
......@@ -764,6 +791,14 @@ static int _coresight_build_path(struct coresight_device *csdev,
if (csdev == sink)
goto out;
if (coresight_is_percpu_source(csdev) && coresight_is_percpu_sink(sink) &&
sink == per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev))) {
if (_coresight_build_path(sink, sink, path) == 0) {
found = true;
goto out;
}
}
/* Not a sink - recursively explore each port found on this element */
for (i = 0; i < csdev->pdata->nr_outport; i++) {
struct coresight_device *child_dev;
......@@ -979,8 +1014,12 @@ coresight_find_default_sink(struct coresight_device *csdev)
int depth = 0;
/* look for a default sink if we have not found for this device */
if (!csdev->def_sink)
csdev->def_sink = coresight_find_sink(csdev, &depth);
if (!csdev->def_sink) {
if (coresight_is_percpu_source(csdev))
csdev->def_sink = per_cpu(csdev_sink, source_ops(csdev)->cpu_id(csdev));
if (!csdev->def_sink)
csdev->def_sink = coresight_find_sink(csdev, &depth);
}
return csdev->def_sink;
}
......@@ -1413,23 +1452,24 @@ static void coresight_remove_conns(struct coresight_device *csdev)
}
/**
* coresight_timeout - loop until a bit has changed to a specific state.
* @addr: base address of the area of interest.
* @offset: address of a register, starting from @addr.
* coresight_timeout - loop until a bit has changed to a specific register
* state.
* @csa: coresight device access for the device
* @offset: Offset of the register from the base of the device.
* @position: the position of the bit of interest.
* @value: the value the bit should have.
*
* Return: 0 as soon as the bit has taken the desired state or -EAGAIN if
* TIMEOUT_US has elapsed, which ever happens first.
*/
int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
int coresight_timeout(struct csdev_access *csa, u32 offset,
int position, int value)
{
int i;
u32 val;
for (i = TIMEOUT_US; i > 0; i--) {
val = __raw_readl(addr + offset);
val = csdev_access_read32(csa, offset);
/* waiting on the bit to go from 0 to 1 */
if (value) {
if (val & BIT(position))
......@@ -1453,6 +1493,48 @@ int coresight_timeout(void __iomem *addr, u32 offset, int position, int value)
}
EXPORT_SYMBOL_GPL(coresight_timeout);
u32 coresight_relaxed_read32(struct coresight_device *csdev, u32 offset)
{
return csdev_access_relaxed_read32(&csdev->access, offset);
}
u32 coresight_read32(struct coresight_device *csdev, u32 offset)
{
return csdev_access_read32(&csdev->access, offset);
}
void coresight_relaxed_write32(struct coresight_device *csdev,
u32 val, u32 offset)
{
csdev_access_relaxed_write32(&csdev->access, val, offset);
}
void coresight_write32(struct coresight_device *csdev, u32 val, u32 offset)
{
csdev_access_write32(&csdev->access, val, offset);
}
u64 coresight_relaxed_read64(struct coresight_device *csdev, u32 offset)
{
return csdev_access_relaxed_read64(&csdev->access, offset);
}
u64 coresight_read64(struct coresight_device *csdev, u32 offset)
{
return csdev_access_read64(&csdev->access, offset);
}
void coresight_relaxed_write64(struct coresight_device *csdev,
u64 val, u32 offset)
{
csdev_access_relaxed_write64(&csdev->access, val, offset);
}
void coresight_write64(struct coresight_device *csdev, u64 val, u32 offset)
{
csdev_access_write64(&csdev->access, val, offset);
}
/*
* coresight_release_platform_data: Release references to the devices connected
* to the output port of this device.
......@@ -1519,6 +1601,7 @@ struct coresight_device *coresight_register(struct coresight_desc *desc)
csdev->type = desc->type;
csdev->subtype = desc->subtype;
csdev->ops = desc->ops;
csdev->access = desc->access;
csdev->orphan = false;
csdev->dev.type = &coresight_dev_type[desc->type];
......
......@@ -102,7 +102,7 @@ static int cti_enable_hw(struct cti_drvdata *drvdata)
goto cti_state_unchanged;
/* claim the device */
rc = coresight_claim_device(drvdata->base);
rc = coresight_claim_device(drvdata->csdev);
if (rc)
goto cti_err_not_enabled;
......@@ -136,7 +136,7 @@ static void cti_cpuhp_enable_hw(struct cti_drvdata *drvdata)
goto cti_hp_not_enabled;
/* try to claim the device */
if (coresight_claim_device(drvdata->base))
if (coresight_claim_device(drvdata->csdev))
goto cti_hp_not_enabled;
cti_write_all_hw_regs(drvdata);
......@@ -154,6 +154,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
{
struct cti_config *config = &drvdata->config;
struct device *dev = &drvdata->csdev->dev;
struct coresight_device *csdev = drvdata->csdev;
spin_lock(&drvdata->spinlock);
......@@ -171,7 +172,7 @@ static int cti_disable_hw(struct cti_drvdata *drvdata)
writel_relaxed(0, drvdata->base + CTICONTROL);
config->hw_enabled = false;
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
spin_unlock(&drvdata->spinlock);
pm_runtime_put(dev->parent);
......@@ -655,6 +656,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
void *v)
{
struct cti_drvdata *drvdata;
struct coresight_device *csdev;
unsigned int cpu = smp_processor_id();
int notify_res = NOTIFY_OK;
......@@ -662,6 +664,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
return NOTIFY_OK;
drvdata = cti_cpu_drvdata[cpu];
csdev = drvdata->csdev;
if (WARN_ON_ONCE(drvdata->ctidev.cpu != cpu))
return NOTIFY_BAD;
......@@ -673,13 +676,13 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
/* CTI regs all static - we have a copy & nothing to save */
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(csdev);
break;
case CPU_PM_ENTER_FAILED:
drvdata->config.hw_powered = true;
if (drvdata->config.hw_enabled) {
if (coresight_claim_device(drvdata->base))
if (coresight_claim_device(csdev))
drvdata->config.hw_enabled = false;
}
break;
......@@ -692,7 +695,7 @@ static int cti_cpu_pm_notify(struct notifier_block *nb, unsigned long cmd,
/* check enable reference count to enable HW */
if (atomic_read(&drvdata->config.enable_req_count)) {
/* check we can claim the device as we re-power */
if (coresight_claim_device(drvdata->base))
if (coresight_claim_device(csdev))
goto cti_notify_exit;
drvdata->config.hw_enabled = true;
......@@ -736,7 +739,7 @@ static int cti_dying_cpu(unsigned int cpu)
spin_lock(&drvdata->spinlock);
drvdata->config.hw_powered = false;
if (drvdata->config.hw_enabled)
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev);
spin_unlock(&drvdata->spinlock);
return 0;
}
......@@ -868,6 +871,7 @@ static int cti_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(base);
drvdata->base = base;
cti_desc.access = CSDEV_ACCESS_IOMEM(base);
dev_set_drvdata(dev, drvdata);
......
......@@ -132,7 +132,7 @@ static void __etb_enable_hw(struct etb_drvdata *drvdata)
static int etb_enable_hw(struct etb_drvdata *drvdata)
{
int rc = coresight_claim_device(drvdata->base);
int rc = coresight_claim_device(drvdata->csdev);
if (rc)
return rc;
......@@ -252,6 +252,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
{
u32 ffcr;
struct device *dev = &drvdata->csdev->dev;
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
......@@ -263,7 +264,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
ffcr |= ETB_FFCR_FON_MAN;
writel_relaxed(ffcr, drvdata->base + ETB_FFCR);
if (coresight_timeout(drvdata->base, ETB_FFCR, ETB_FFCR_BIT, 0)) {
if (coresight_timeout(csa, ETB_FFCR, ETB_FFCR_BIT, 0)) {
dev_err(dev,
"timeout while waiting for completion of Manual Flush\n");
}
......@@ -271,7 +272,7 @@ static void __etb_disable_hw(struct etb_drvdata *drvdata)
/* disable trace capture */
writel_relaxed(0x0, drvdata->base + ETB_CTL_REG);
if (coresight_timeout(drvdata->base, ETB_FFSR, ETB_FFSR_BIT, 1)) {
if (coresight_timeout(csa, ETB_FFSR, ETB_FFSR_BIT, 1)) {
dev_err(dev,
"timeout while waiting for Formatter to Stop\n");
}
......@@ -344,7 +345,7 @@ static void etb_disable_hw(struct etb_drvdata *drvdata)
{
__etb_disable_hw(drvdata);
etb_dump_hw(drvdata);
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev);
}
static int etb_disable(struct coresight_device *csdev)
......@@ -757,6 +758,7 @@ static int etb_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
......
......@@ -24,7 +24,26 @@
static struct pmu etm_pmu;
static bool etm_perf_up;
static DEFINE_PER_CPU(struct perf_output_handle, ctx_handle);
/*
* An ETM context for a running event includes the perf aux handle
* and aux_data. For ETM, the aux_data (etm_event_data), consists of
* the trace path and the sink configuration. The event data is accessible
* via perf_get_aux(handle). However, a sink could "end" a perf output
* handle via the IRQ handler. And if the "sink" encounters a failure
* to "begin" another session (e.g due to lack of space in the buffer),
* the handle will be cleared. Thus, the event_data may not be accessible
* from the handle when we get to the etm_event_stop(), which is required
* for stopping the trace path. The event_data is guaranteed to stay alive
* until "free_aux()", which cannot happen as long as the event is active on
* the ETM. Thus the event_data for the session must be part of the ETM context
* to make sure we can disable the trace path.
*/
struct etm_ctxt {
struct perf_output_handle handle;
struct etm_event_data *event_data;
};
static DEFINE_PER_CPU(struct etm_ctxt, etm_ctxt);
static DEFINE_PER_CPU(struct coresight_device *, csdev_src);
/* ETMv3.5/PTM's ETMCR is 'config' */
......@@ -304,13 +323,18 @@ static void etm_event_start(struct perf_event *event, int flags)
{
int cpu = smp_processor_id();
struct etm_event_data *event_data;
struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle);
struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt);
struct perf_output_handle *handle = &ctxt->handle;
struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
struct list_head *path;
if (!csdev)
goto fail;
/* Have we messed up our tracking ? */
if (WARN_ON(ctxt->event_data))
goto fail;
/*
* Deal with the ring buffer API and get a handle on the
* session's information.
......@@ -325,9 +349,14 @@ static void etm_event_start(struct perf_event *event, int flags)
* sink from this ETM. We can't do much in this case if
* the sink was specified or hinted to the driver. For
* now, simply don't record anything on this ETM.
*
* As such we pretend that everything is fine, and let
* it continue without actually tracing. The event could
* continue tracing when it moves to a CPU where it is
* reachable to a sink.
*/
if (!cpumask_test_cpu(cpu, &event_data->mask))
goto fail_end_stop;
goto out;
path = etm_event_cpu_path(event_data, cpu);
/* We need a sink, no need to continue without one */
......@@ -339,24 +368,32 @@ static void etm_event_start(struct perf_event *event, int flags)
if (coresight_enable_path(path, CS_MODE_PERF, handle))
goto fail_end_stop;
/* Tell the perf core the event is alive */
event->hw.state = 0;
/* Finally enable the tracer */
if (source_ops(csdev)->enable(csdev, event, CS_MODE_PERF))
goto fail_disable_path;
out:
/* Tell the perf core the event is alive */
event->hw.state = 0;
/* Save the event_data for this ETM */
ctxt->event_data = event_data;
return;
fail_disable_path:
coresight_disable_path(path);
fail_end_stop:
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
perf_aux_output_end(handle, 0);
/*
* Check if the handle is still associated with the event,
* to handle cases where if the sink failed to start the
* trace and TRUNCATED the handle already.
*/
if (READ_ONCE(handle->event)) {
perf_aux_output_flag(handle, PERF_AUX_FLAG_TRUNCATED);
perf_aux_output_end(handle, 0);
}
fail:
event->hw.state = PERF_HES_STOPPED;
goto out;
return;
}
static void etm_event_stop(struct perf_event *event, int mode)
......@@ -364,13 +401,43 @@ static void etm_event_stop(struct perf_event *event, int mode)
int cpu = smp_processor_id();
unsigned long size;
struct coresight_device *sink, *csdev = per_cpu(csdev_src, cpu);
struct perf_output_handle *handle = this_cpu_ptr(&ctx_handle);
struct etm_event_data *event_data = perf_get_aux(handle);
struct etm_ctxt *ctxt = this_cpu_ptr(&etm_ctxt);
struct perf_output_handle *handle = &ctxt->handle;
struct etm_event_data *event_data;
struct list_head *path;
/*
* If we still have access to the event_data via handle,
* confirm that we haven't messed up the tracking.
*/
if (handle->event &&
WARN_ON(perf_get_aux(handle) != ctxt->event_data))
return;
event_data = ctxt->event_data;
/* Clear the event_data as this ETM is stopping the trace. */
ctxt->event_data = NULL;
if (event->hw.state == PERF_HES_STOPPED)
return;
/* We must have a valid event_data for a running event */
if (WARN_ON(!event_data))
return;
/*
* Check if this ETM was allowed to trace, as decided at
* etm_setup_aux(). If it wasn't allowed to trace, then
* nothing needs to be torn down other than outputting a
* zero sized record.
*/
if (handle->event && (mode & PERF_EF_UPDATE) &&
!cpumask_test_cpu(cpu, &event_data->mask)) {
event->hw.state = PERF_HES_STOPPED;
perf_aux_output_end(handle, 0);
return;
}
if (!csdev)
return;
......@@ -388,7 +455,13 @@ static void etm_event_stop(struct perf_event *event, int mode)
/* tell the core */
event->hw.state = PERF_HES_STOPPED;
if (mode & PERF_EF_UPDATE) {
/*
* If the handle is not bound to an event anymore
* (e.g, the sink driver was unable to restart the
* handle due to lack of buffer space), we don't
* have to do anything here.
*/
if (handle->event && (mode & PERF_EF_UPDATE)) {
if (WARN_ON_ONCE(handle->event != event))
return;
......@@ -398,7 +471,21 @@ static void etm_event_stop(struct perf_event *event, int mode)
size = sink_ops(sink)->update_buffer(sink, handle,
event_data->snk_config);
perf_aux_output_end(handle, size);
/*
* Make sure the handle is still valid as the
* sink could have closed it from an IRQ.
* The sink driver must handle the race with
* update_buffer() and IRQ. Thus either we
* should get a valid handle and valid size
* (which may be 0).
*
* But we should never get a non-zero size with
* an invalid handle.
*/
if (READ_ONCE(handle->event))
perf_aux_output_end(handle, size);
else
WARN_ON(size);
}
/* Disabling the path make its elements available to other sessions */
......
......@@ -358,10 +358,11 @@ static int etm_enable_hw(struct etm_drvdata *drvdata)
int i, rc;
u32 etmcr;
struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev);
if (rc)
goto done;
......@@ -566,6 +567,7 @@ static void etm_disable_hw(void *info)
int i;
struct etm_drvdata *drvdata = info;
struct etm_config *config = &drvdata->config;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
etm_set_prog(drvdata);
......@@ -577,7 +579,7 @@ static void etm_disable_hw(void *info)
config->cntr_val[i] = etm_readl(drvdata, ETMCNTVRn(i));
etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
......@@ -602,7 +604,7 @@ static void etm_disable_perf(struct coresight_device *csdev)
* power down the tracer.
*/
etm_set_pwrdwn(drvdata);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}
......@@ -839,6 +841,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
......
......@@ -2323,7 +2323,8 @@ static struct attribute *coresight_etmv4_attrs[] = {
};
struct etmv4_reg {
void __iomem *addr;
struct coresight_device *csdev;
u32 offset;
u32 data;
};
......@@ -2331,15 +2332,16 @@ static void do_smp_cross_read(void *data)
{
struct etmv4_reg *reg = data;
reg->data = readl_relaxed(reg->addr);
reg->data = etm4x_relaxed_read32(&reg->csdev->access, reg->offset);
}
static u32 etmv4_cross_read(const struct device *dev, u32 offset)
static u32 etmv4_cross_read(const struct etmv4_drvdata *drvdata, u32 offset)
{
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev);
struct etmv4_reg reg;
reg.addr = drvdata->base + offset;
reg.offset = offset;
reg.csdev = drvdata->csdev;
/*
* smp cross call ensures the CPU will be powered up before
* accessing the ETMv4 trace core registers
......@@ -2348,72 +2350,133 @@ static u32 etmv4_cross_read(const struct device *dev, u32 offset)
return reg.data;
}
#define coresight_etm4x_reg(name, offset) \
coresight_simple_reg32(struct etmv4_drvdata, name, offset)
static inline u32 coresight_etm4x_attr_to_offset(struct device_attribute *attr)
{
struct dev_ext_attribute *eattr;
eattr = container_of(attr, struct dev_ext_attribute, attr);
return (u32)(unsigned long)eattr->var;
}
static ssize_t coresight_etm4x_reg_show(struct device *dev,
struct device_attribute *d_attr,
char *buf)
{
u32 val, offset;
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
offset = coresight_etm4x_attr_to_offset(d_attr);
pm_runtime_get_sync(dev->parent);
val = etmv4_cross_read(drvdata, offset);
pm_runtime_put_sync(dev->parent);
return scnprintf(buf, PAGE_SIZE, "0x%x\n", val);
}
static inline bool
etm4x_register_implemented(struct etmv4_drvdata *drvdata, u32 offset)
{
switch (offset) {
ETM_COMMON_SYSREG_LIST_CASES
/*
* Common registers to ETE & ETM4x accessible via system
* instructions are always implemented.
*/
return true;
ETM4x_ONLY_SYSREG_LIST_CASES
/*
* We only support etm4x and ete. So if the device is not
* ETE, it must be ETMv4x.
*/
return !etm4x_is_ete(drvdata);
ETM4x_MMAP_LIST_CASES
/*
* Registers accessible only via memory-mapped registers
* must not be accessed via system instructions.
* We cannot access the drvdata->csdev here, as this
* function is called during the device creation, via
* coresight_register() and the csdev is not initialized
* until that is done. So rely on the drvdata->base to
* detect if we have a memory mapped access.
* Also ETE doesn't implement memory mapped access, thus
* it is sufficient to check that we are using mmio.
*/
return !!drvdata->base;
ETE_ONLY_SYSREG_LIST_CASES
return etm4x_is_ete(drvdata);
}
return false;
}
/*
* Hide the ETM4x registers that may not be available on the
* hardware.
* There are certain management registers unavailable via system
* instructions. Make those sysfs attributes hidden on such
* systems.
*/
static umode_t
coresight_etm4x_attr_reg_implemented(struct kobject *kobj,
struct attribute *attr, int unused)
{
struct device *dev = kobj_to_dev(kobj);
struct etmv4_drvdata *drvdata = dev_get_drvdata(dev->parent);
struct device_attribute *d_attr;
u32 offset;
#define coresight_etm4x_cross_read(name, offset) \
coresight_simple_func(struct etmv4_drvdata, etmv4_cross_read, \
name, offset)
d_attr = container_of(attr, struct device_attribute, attr);
offset = coresight_etm4x_attr_to_offset(d_attr);
coresight_etm4x_reg(trcpdcr, TRCPDCR);
coresight_etm4x_reg(trcpdsr, TRCPDSR);
coresight_etm4x_reg(trclsr, TRCLSR);
coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS);
coresight_etm4x_reg(trcdevid, TRCDEVID);
coresight_etm4x_reg(trcdevtype, TRCDEVTYPE);
coresight_etm4x_reg(trcpidr0, TRCPIDR0);
coresight_etm4x_reg(trcpidr1, TRCPIDR1);
coresight_etm4x_reg(trcpidr2, TRCPIDR2);
coresight_etm4x_reg(trcpidr3, TRCPIDR3);
coresight_etm4x_cross_read(trcoslsr, TRCOSLSR);
coresight_etm4x_cross_read(trcconfig, TRCCONFIGR);
coresight_etm4x_cross_read(trctraceid, TRCTRACEIDR);
if (etm4x_register_implemented(drvdata, offset))
return attr->mode;
return 0;
}
#define coresight_etm4x_reg(name, offset) \
&((struct dev_ext_attribute[]) { \
{ \
__ATTR(name, 0444, coresight_etm4x_reg_show, NULL), \
(void *)(unsigned long)offset \
} \
})[0].attr.attr
static struct attribute *coresight_etmv4_mgmt_attrs[] = {
&dev_attr_trcoslsr.attr,
&dev_attr_trcpdcr.attr,
&dev_attr_trcpdsr.attr,
&dev_attr_trclsr.attr,
&dev_attr_trcconfig.attr,
&dev_attr_trctraceid.attr,
&dev_attr_trcauthstatus.attr,
&dev_attr_trcdevid.attr,
&dev_attr_trcdevtype.attr,
&dev_attr_trcpidr0.attr,
&dev_attr_trcpidr1.attr,
&dev_attr_trcpidr2.attr,
&dev_attr_trcpidr3.attr,
coresight_etm4x_reg(trcpdcr, TRCPDCR),
coresight_etm4x_reg(trcpdsr, TRCPDSR),
coresight_etm4x_reg(trclsr, TRCLSR),
coresight_etm4x_reg(trcauthstatus, TRCAUTHSTATUS),
coresight_etm4x_reg(trcdevid, TRCDEVID),
coresight_etm4x_reg(trcdevtype, TRCDEVTYPE),
coresight_etm4x_reg(trcpidr0, TRCPIDR0),
coresight_etm4x_reg(trcpidr1, TRCPIDR1),
coresight_etm4x_reg(trcpidr2, TRCPIDR2),
coresight_etm4x_reg(trcpidr3, TRCPIDR3),
coresight_etm4x_reg(trcoslsr, TRCOSLSR),
coresight_etm4x_reg(trcconfig, TRCCONFIGR),
coresight_etm4x_reg(trctraceid, TRCTRACEIDR),
coresight_etm4x_reg(trcdevarch, TRCDEVARCH),
NULL,
};
coresight_etm4x_cross_read(trcidr0, TRCIDR0);
coresight_etm4x_cross_read(trcidr1, TRCIDR1);
coresight_etm4x_cross_read(trcidr2, TRCIDR2);
coresight_etm4x_cross_read(trcidr3, TRCIDR3);
coresight_etm4x_cross_read(trcidr4, TRCIDR4);
coresight_etm4x_cross_read(trcidr5, TRCIDR5);
/* trcidr[6,7] are reserved */
coresight_etm4x_cross_read(trcidr8, TRCIDR8);
coresight_etm4x_cross_read(trcidr9, TRCIDR9);
coresight_etm4x_cross_read(trcidr10, TRCIDR10);
coresight_etm4x_cross_read(trcidr11, TRCIDR11);
coresight_etm4x_cross_read(trcidr12, TRCIDR12);
coresight_etm4x_cross_read(trcidr13, TRCIDR13);
static struct attribute *coresight_etmv4_trcidr_attrs[] = {
&dev_attr_trcidr0.attr,
&dev_attr_trcidr1.attr,
&dev_attr_trcidr2.attr,
&dev_attr_trcidr3.attr,
&dev_attr_trcidr4.attr,
&dev_attr_trcidr5.attr,
coresight_etm4x_reg(trcidr0, TRCIDR0),
coresight_etm4x_reg(trcidr1, TRCIDR1),
coresight_etm4x_reg(trcidr2, TRCIDR2),
coresight_etm4x_reg(trcidr3, TRCIDR3),
coresight_etm4x_reg(trcidr4, TRCIDR4),
coresight_etm4x_reg(trcidr5, TRCIDR5),
/* trcidr[6,7] are reserved */
&dev_attr_trcidr8.attr,
&dev_attr_trcidr9.attr,
&dev_attr_trcidr10.attr,
&dev_attr_trcidr11.attr,
&dev_attr_trcidr12.attr,
&dev_attr_trcidr13.attr,
coresight_etm4x_reg(trcidr8, TRCIDR8),
coresight_etm4x_reg(trcidr9, TRCIDR9),
coresight_etm4x_reg(trcidr10, TRCIDR10),
coresight_etm4x_reg(trcidr11, TRCIDR11),
coresight_etm4x_reg(trcidr12, TRCIDR12),
coresight_etm4x_reg(trcidr13, TRCIDR13),
NULL,
};
......@@ -2422,6 +2485,7 @@ static const struct attribute_group coresight_etmv4_group = {
};
static const struct attribute_group coresight_etmv4_mgmt_group = {
.is_visible = coresight_etm4x_attr_reg_implemented,
.attrs = coresight_etmv4_mgmt_attrs,
.name = "mgmt",
};
......
......@@ -7,6 +7,7 @@
#define _CORESIGHT_CORESIGHT_ETM_H
#include <asm/local.h>
#include <linux/const.h>
#include <linux/spinlock.h>
#include <linux/types.h>
#include "coresight-priv.h"
......@@ -29,6 +30,7 @@
#define TRCAUXCTLR 0x018
#define TRCEVENTCTL0R 0x020
#define TRCEVENTCTL1R 0x024
#define TRCRSR 0x028
#define TRCSTALLCTLR 0x02C
#define TRCTSCTLR 0x030
#define TRCSYNCPR 0x034
......@@ -49,6 +51,7 @@
#define TRCSEQRSTEVR 0x118
#define TRCSEQSTR 0x11C
#define TRCEXTINSELR 0x120
#define TRCEXTINSELRn(n) (0x120 + (n * 4)) /* n = 0-3 */
#define TRCCNTRLDVRn(n) (0x140 + (n * 4))
#define TRCCNTCTLRn(n) (0x150 + (n * 4))
#define TRCCNTVRn(n) (0x160 + (n * 4))
......@@ -121,6 +124,367 @@
#define TRCCIDR2 0xFF8
#define TRCCIDR3 0xFFC
#define TRCRSR_TA BIT(12)
/*
* System instructions to access ETM registers.
* See ETMv4.4 spec ARM IHI0064F section 4.3.6 System instructions
*/
#define ETM4x_OFFSET_TO_REG(x) ((x) >> 2)
#define ETM4x_CRn(n) (((n) >> 7) & 0x7)
#define ETM4x_Op2(n) (((n) >> 4) & 0x7)
#define ETM4x_CRm(n) ((n) & 0xf)
#include <asm/sysreg.h>
#define ETM4x_REG_NUM_TO_SYSREG(n) \
sys_reg(2, 1, ETM4x_CRn(n), ETM4x_CRm(n), ETM4x_Op2(n))
#define READ_ETM4x_REG(reg) \
read_sysreg_s(ETM4x_REG_NUM_TO_SYSREG((reg)))
#define WRITE_ETM4x_REG(val, reg) \
write_sysreg_s(val, ETM4x_REG_NUM_TO_SYSREG((reg)))
#define read_etm4x_sysreg_const_offset(offset) \
READ_ETM4x_REG(ETM4x_OFFSET_TO_REG(offset))
#define write_etm4x_sysreg_const_offset(val, offset) \
WRITE_ETM4x_REG(val, ETM4x_OFFSET_TO_REG(offset))
#define CASE_READ(res, x) \
case (x): { (res) = read_etm4x_sysreg_const_offset((x)); break; }
#define CASE_WRITE(val, x) \
case (x): { write_etm4x_sysreg_const_offset((val), (x)); break; }
#define CASE_NOP(__unused, x) \
case (x):
#define ETE_ONLY_SYSREG_LIST(op, val) \
CASE_##op((val), TRCRSR) \
CASE_##op((val), TRCEXTINSELRn(1)) \
CASE_##op((val), TRCEXTINSELRn(2)) \
CASE_##op((val), TRCEXTINSELRn(3))
/* List of registers accessible via System instructions */
#define ETM4x_ONLY_SYSREG_LIST(op, val) \
CASE_##op((val), TRCPROCSELR) \
CASE_##op((val), TRCVDCTLR) \
CASE_##op((val), TRCVDSACCTLR) \
CASE_##op((val), TRCVDARCCTLR) \
CASE_##op((val), TRCOSLAR)
#define ETM_COMMON_SYSREG_LIST(op, val) \
CASE_##op((val), TRCPRGCTLR) \
CASE_##op((val), TRCSTATR) \
CASE_##op((val), TRCCONFIGR) \
CASE_##op((val), TRCAUXCTLR) \
CASE_##op((val), TRCEVENTCTL0R) \
CASE_##op((val), TRCEVENTCTL1R) \
CASE_##op((val), TRCSTALLCTLR) \
CASE_##op((val), TRCTSCTLR) \
CASE_##op((val), TRCSYNCPR) \
CASE_##op((val), TRCCCCTLR) \
CASE_##op((val), TRCBBCTLR) \
CASE_##op((val), TRCTRACEIDR) \
CASE_##op((val), TRCQCTLR) \
CASE_##op((val), TRCVICTLR) \
CASE_##op((val), TRCVIIECTLR) \
CASE_##op((val), TRCVISSCTLR) \
CASE_##op((val), TRCVIPCSSCTLR) \
CASE_##op((val), TRCSEQEVRn(0)) \
CASE_##op((val), TRCSEQEVRn(1)) \
CASE_##op((val), TRCSEQEVRn(2)) \
CASE_##op((val), TRCSEQRSTEVR) \
CASE_##op((val), TRCSEQSTR) \
CASE_##op((val), TRCEXTINSELR) \
CASE_##op((val), TRCCNTRLDVRn(0)) \
CASE_##op((val), TRCCNTRLDVRn(1)) \
CASE_##op((val), TRCCNTRLDVRn(2)) \
CASE_##op((val), TRCCNTRLDVRn(3)) \
CASE_##op((val), TRCCNTCTLRn(0)) \
CASE_##op((val), TRCCNTCTLRn(1)) \
CASE_##op((val), TRCCNTCTLRn(2)) \
CASE_##op((val), TRCCNTCTLRn(3)) \
CASE_##op((val), TRCCNTVRn(0)) \
CASE_##op((val), TRCCNTVRn(1)) \
CASE_##op((val), TRCCNTVRn(2)) \
CASE_##op((val), TRCCNTVRn(3)) \
CASE_##op((val), TRCIDR8) \
CASE_##op((val), TRCIDR9) \
CASE_##op((val), TRCIDR10) \
CASE_##op((val), TRCIDR11) \
CASE_##op((val), TRCIDR12) \
CASE_##op((val), TRCIDR13) \
CASE_##op((val), TRCIMSPECn(0)) \
CASE_##op((val), TRCIMSPECn(1)) \
CASE_##op((val), TRCIMSPECn(2)) \
CASE_##op((val), TRCIMSPECn(3)) \
CASE_##op((val), TRCIMSPECn(4)) \
CASE_##op((val), TRCIMSPECn(5)) \
CASE_##op((val), TRCIMSPECn(6)) \
CASE_##op((val), TRCIMSPECn(7)) \
CASE_##op((val), TRCIDR0) \
CASE_##op((val), TRCIDR1) \
CASE_##op((val), TRCIDR2) \
CASE_##op((val), TRCIDR3) \
CASE_##op((val), TRCIDR4) \
CASE_##op((val), TRCIDR5) \
CASE_##op((val), TRCIDR6) \
CASE_##op((val), TRCIDR7) \
CASE_##op((val), TRCRSCTLRn(2)) \
CASE_##op((val), TRCRSCTLRn(3)) \
CASE_##op((val), TRCRSCTLRn(4)) \
CASE_##op((val), TRCRSCTLRn(5)) \
CASE_##op((val), TRCRSCTLRn(6)) \
CASE_##op((val), TRCRSCTLRn(7)) \
CASE_##op((val), TRCRSCTLRn(8)) \
CASE_##op((val), TRCRSCTLRn(9)) \
CASE_##op((val), TRCRSCTLRn(10)) \
CASE_##op((val), TRCRSCTLRn(11)) \
CASE_##op((val), TRCRSCTLRn(12)) \
CASE_##op((val), TRCRSCTLRn(13)) \
CASE_##op((val), TRCRSCTLRn(14)) \
CASE_##op((val), TRCRSCTLRn(15)) \
CASE_##op((val), TRCRSCTLRn(16)) \
CASE_##op((val), TRCRSCTLRn(17)) \
CASE_##op((val), TRCRSCTLRn(18)) \
CASE_##op((val), TRCRSCTLRn(19)) \
CASE_##op((val), TRCRSCTLRn(20)) \
CASE_##op((val), TRCRSCTLRn(21)) \
CASE_##op((val), TRCRSCTLRn(22)) \
CASE_##op((val), TRCRSCTLRn(23)) \
CASE_##op((val), TRCRSCTLRn(24)) \
CASE_##op((val), TRCRSCTLRn(25)) \
CASE_##op((val), TRCRSCTLRn(26)) \
CASE_##op((val), TRCRSCTLRn(27)) \
CASE_##op((val), TRCRSCTLRn(28)) \
CASE_##op((val), TRCRSCTLRn(29)) \
CASE_##op((val), TRCRSCTLRn(30)) \
CASE_##op((val), TRCRSCTLRn(31)) \
CASE_##op((val), TRCSSCCRn(0)) \
CASE_##op((val), TRCSSCCRn(1)) \
CASE_##op((val), TRCSSCCRn(2)) \
CASE_##op((val), TRCSSCCRn(3)) \
CASE_##op((val), TRCSSCCRn(4)) \
CASE_##op((val), TRCSSCCRn(5)) \
CASE_##op((val), TRCSSCCRn(6)) \
CASE_##op((val), TRCSSCCRn(7)) \
CASE_##op((val), TRCSSCSRn(0)) \
CASE_##op((val), TRCSSCSRn(1)) \
CASE_##op((val), TRCSSCSRn(2)) \
CASE_##op((val), TRCSSCSRn(3)) \
CASE_##op((val), TRCSSCSRn(4)) \
CASE_##op((val), TRCSSCSRn(5)) \
CASE_##op((val), TRCSSCSRn(6)) \
CASE_##op((val), TRCSSCSRn(7)) \
CASE_##op((val), TRCSSPCICRn(0)) \
CASE_##op((val), TRCSSPCICRn(1)) \
CASE_##op((val), TRCSSPCICRn(2)) \
CASE_##op((val), TRCSSPCICRn(3)) \
CASE_##op((val), TRCSSPCICRn(4)) \
CASE_##op((val), TRCSSPCICRn(5)) \
CASE_##op((val), TRCSSPCICRn(6)) \
CASE_##op((val), TRCSSPCICRn(7)) \
CASE_##op((val), TRCOSLSR) \
CASE_##op((val), TRCACVRn(0)) \
CASE_##op((val), TRCACVRn(1)) \
CASE_##op((val), TRCACVRn(2)) \
CASE_##op((val), TRCACVRn(3)) \
CASE_##op((val), TRCACVRn(4)) \
CASE_##op((val), TRCACVRn(5)) \
CASE_##op((val), TRCACVRn(6)) \
CASE_##op((val), TRCACVRn(7)) \
CASE_##op((val), TRCACVRn(8)) \
CASE_##op((val), TRCACVRn(9)) \
CASE_##op((val), TRCACVRn(10)) \
CASE_##op((val), TRCACVRn(11)) \
CASE_##op((val), TRCACVRn(12)) \
CASE_##op((val), TRCACVRn(13)) \
CASE_##op((val), TRCACVRn(14)) \
CASE_##op((val), TRCACVRn(15)) \
CASE_##op((val), TRCACATRn(0)) \
CASE_##op((val), TRCACATRn(1)) \
CASE_##op((val), TRCACATRn(2)) \
CASE_##op((val), TRCACATRn(3)) \
CASE_##op((val), TRCACATRn(4)) \
CASE_##op((val), TRCACATRn(5)) \
CASE_##op((val), TRCACATRn(6)) \
CASE_##op((val), TRCACATRn(7)) \
CASE_##op((val), TRCACATRn(8)) \
CASE_##op((val), TRCACATRn(9)) \
CASE_##op((val), TRCACATRn(10)) \
CASE_##op((val), TRCACATRn(11)) \
CASE_##op((val), TRCACATRn(12)) \
CASE_##op((val), TRCACATRn(13)) \
CASE_##op((val), TRCACATRn(14)) \
CASE_##op((val), TRCACATRn(15)) \
CASE_##op((val), TRCDVCVRn(0)) \
CASE_##op((val), TRCDVCVRn(1)) \
CASE_##op((val), TRCDVCVRn(2)) \
CASE_##op((val), TRCDVCVRn(3)) \
CASE_##op((val), TRCDVCVRn(4)) \
CASE_##op((val), TRCDVCVRn(5)) \
CASE_##op((val), TRCDVCVRn(6)) \
CASE_##op((val), TRCDVCVRn(7)) \
CASE_##op((val), TRCDVCMRn(0)) \
CASE_##op((val), TRCDVCMRn(1)) \
CASE_##op((val), TRCDVCMRn(2)) \
CASE_##op((val), TRCDVCMRn(3)) \
CASE_##op((val), TRCDVCMRn(4)) \
CASE_##op((val), TRCDVCMRn(5)) \
CASE_##op((val), TRCDVCMRn(6)) \
CASE_##op((val), TRCDVCMRn(7)) \
CASE_##op((val), TRCCIDCVRn(0)) \
CASE_##op((val), TRCCIDCVRn(1)) \
CASE_##op((val), TRCCIDCVRn(2)) \
CASE_##op((val), TRCCIDCVRn(3)) \
CASE_##op((val), TRCCIDCVRn(4)) \
CASE_##op((val), TRCCIDCVRn(5)) \
CASE_##op((val), TRCCIDCVRn(6)) \
CASE_##op((val), TRCCIDCVRn(7)) \
CASE_##op((val), TRCVMIDCVRn(0)) \
CASE_##op((val), TRCVMIDCVRn(1)) \
CASE_##op((val), TRCVMIDCVRn(2)) \
CASE_##op((val), TRCVMIDCVRn(3)) \
CASE_##op((val), TRCVMIDCVRn(4)) \
CASE_##op((val), TRCVMIDCVRn(5)) \
CASE_##op((val), TRCVMIDCVRn(6)) \
CASE_##op((val), TRCVMIDCVRn(7)) \
CASE_##op((val), TRCCIDCCTLR0) \
CASE_##op((val), TRCCIDCCTLR1) \
CASE_##op((val), TRCVMIDCCTLR0) \
CASE_##op((val), TRCVMIDCCTLR1) \
CASE_##op((val), TRCCLAIMSET) \
CASE_##op((val), TRCCLAIMCLR) \
CASE_##op((val), TRCAUTHSTATUS) \
CASE_##op((val), TRCDEVARCH) \
CASE_##op((val), TRCDEVID)
/* List of registers only accessible via memory-mapped interface */
#define ETM_MMAP_LIST(op, val) \
CASE_##op((val), TRCDEVTYPE) \
CASE_##op((val), TRCPDCR) \
CASE_##op((val), TRCPDSR) \
CASE_##op((val), TRCDEVAFF0) \
CASE_##op((val), TRCDEVAFF1) \
CASE_##op((val), TRCLAR) \
CASE_##op((val), TRCLSR) \
CASE_##op((val), TRCITCTRL) \
CASE_##op((val), TRCPIDR4) \
CASE_##op((val), TRCPIDR0) \
CASE_##op((val), TRCPIDR1) \
CASE_##op((val), TRCPIDR2) \
CASE_##op((val), TRCPIDR3)
#define ETM4x_READ_SYSREG_CASES(res) \
ETM_COMMON_SYSREG_LIST(READ, (res)) \
ETM4x_ONLY_SYSREG_LIST(READ, (res))
#define ETM4x_WRITE_SYSREG_CASES(val) \
ETM_COMMON_SYSREG_LIST(WRITE, (val)) \
ETM4x_ONLY_SYSREG_LIST(WRITE, (val))
#define ETM_COMMON_SYSREG_LIST_CASES \
ETM_COMMON_SYSREG_LIST(NOP, __unused)
#define ETM4x_ONLY_SYSREG_LIST_CASES \
ETM4x_ONLY_SYSREG_LIST(NOP, __unused)
#define ETM4x_SYSREG_LIST_CASES \
ETM_COMMON_SYSREG_LIST_CASES \
ETM4x_ONLY_SYSREG_LIST(NOP, __unused)
#define ETM4x_MMAP_LIST_CASES ETM_MMAP_LIST(NOP, __unused)
/* ETE only supports system register access */
#define ETE_READ_CASES(res) \
ETM_COMMON_SYSREG_LIST(READ, (res)) \
ETE_ONLY_SYSREG_LIST(READ, (res))
#define ETE_WRITE_CASES(val) \
ETM_COMMON_SYSREG_LIST(WRITE, (val)) \
ETE_ONLY_SYSREG_LIST(WRITE, (val))
#define ETE_ONLY_SYSREG_LIST_CASES \
ETE_ONLY_SYSREG_LIST(NOP, __unused)
#define read_etm4x_sysreg_offset(offset, _64bit) \
({ \
u64 __val; \
\
if (__is_constexpr((offset))) \
__val = read_etm4x_sysreg_const_offset((offset)); \
else \
__val = etm4x_sysreg_read((offset), true, (_64bit)); \
__val; \
})
#define write_etm4x_sysreg_offset(val, offset, _64bit) \
do { \
if (__builtin_constant_p((offset))) \
write_etm4x_sysreg_const_offset((val), \
(offset)); \
else \
etm4x_sysreg_write((val), (offset), true, \
(_64bit)); \
} while (0)
#define etm4x_relaxed_read32(csa, offset) \
((u32)((csa)->io_mem ? \
readl_relaxed((csa)->base + (offset)) : \
read_etm4x_sysreg_offset((offset), false)))
#define etm4x_relaxed_read64(csa, offset) \
((u64)((csa)->io_mem ? \
readq_relaxed((csa)->base + (offset)) : \
read_etm4x_sysreg_offset((offset), true)))
#define etm4x_read32(csa, offset) \
({ \
u32 __val = etm4x_relaxed_read32((csa), (offset)); \
__iormb(__val); \
__val; \
})
#define etm4x_read64(csa, offset) \
({ \
u64 __val = etm4x_relaxed_read64((csa), (offset)); \
__iormb(__val); \
__val; \
})
#define etm4x_relaxed_write32(csa, val, offset) \
do { \
if ((csa)->io_mem) \
writel_relaxed((val), (csa)->base + (offset)); \
else \
write_etm4x_sysreg_offset((val), (offset), \
false); \
} while (0)
#define etm4x_relaxed_write64(csa, val, offset) \
do { \
if ((csa)->io_mem) \
writeq_relaxed((val), (csa)->base + (offset)); \
else \
write_etm4x_sysreg_offset((val), (offset), \
true); \
} while (0)
#define etm4x_write32(csa, val, offset) \
do { \
__iowmb(); \
etm4x_relaxed_write32((csa), (val), (offset)); \
} while (0)
#define etm4x_write64(csa, val, offset) \
do { \
__iowmb(); \
etm4x_relaxed_write64((csa), (val), (offset)); \
} while (0)
/* ETMv4 resources */
#define ETM_MAX_NR_PE 8
#define ETMv4_MAX_CNTR 4
......@@ -137,7 +501,6 @@
#define ETM_MAX_RES_SEL 32
#define ETM_MAX_SS_CMP 8
#define ETM_ARCH_V4 0x40
#define ETMv4_SYNC_MASK 0x1F
#define ETM_CYC_THRESHOLD_MASK 0xFFF
#define ETM_CYC_THRESHOLD_DEFAULT 0x100
......@@ -175,6 +538,65 @@
ETM_MODE_EXCL_KERN | \
ETM_MODE_EXCL_USER)
/*
* TRCOSLSR.OSLM advertises the OS Lock model.
* OSLM[2:0] = TRCOSLSR[4:3,0]
*
* 0b000 - Trace OS Lock is not implemented.
* 0b010 - Trace OS Lock is implemented.
* 0b100 - Trace OS Lock is not implemented, unit is controlled by PE OS Lock.
*/
#define ETM_OSLOCK_NI 0b000
#define ETM_OSLOCK_PRESENT 0b010
#define ETM_OSLOCK_PE 0b100
#define ETM_OSLSR_OSLM(oslsr) ((((oslsr) & GENMASK(4, 3)) >> 2) | (oslsr & 0x1))
/*
* TRCDEVARCH Bit field definitions
* Bits[31:21] - ARCHITECT = Always Arm Ltd.
* * Bits[31:28] = 0x4
* * Bits[27:21] = 0b0111011
* Bit[20] - PRESENT, Indicates the presence of this register.
*
* Bit[19:16] - REVISION, Revision of the architecture.
*
* Bit[15:0] - ARCHID, Identifies this component as an ETM
* * Bits[15:12] - architecture version of ETM
* * = 4 for ETMv4
* * Bits[11:0] = 0xA13, architecture part number for ETM.
*/
#define ETM_DEVARCH_ARCHITECT_MASK GENMASK(31, 21)
#define ETM_DEVARCH_ARCHITECT_ARM ((0x4 << 28) | (0b0111011 << 21))
#define ETM_DEVARCH_PRESENT BIT(20)
#define ETM_DEVARCH_REVISION_SHIFT 16
#define ETM_DEVARCH_REVISION_MASK GENMASK(19, 16)
#define ETM_DEVARCH_REVISION(x) \
(((x) & ETM_DEVARCH_REVISION_MASK) >> ETM_DEVARCH_REVISION_SHIFT)
#define ETM_DEVARCH_ARCHID_MASK GENMASK(15, 0)
#define ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT 12
#define ETM_DEVARCH_ARCHID_ARCH_VER_MASK GENMASK(15, 12)
#define ETM_DEVARCH_ARCHID_ARCH_VER(x) \
(((x) & ETM_DEVARCH_ARCHID_ARCH_VER_MASK) >> ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT)
#define ETM_DEVARCH_MAKE_ARCHID_ARCH_VER(ver) \
(((ver) << ETM_DEVARCH_ARCHID_ARCH_VER_SHIFT) & ETM_DEVARCH_ARCHID_ARCH_VER_MASK)
#define ETM_DEVARCH_ARCHID_ARCH_PART(x) ((x) & 0xfffUL)
#define ETM_DEVARCH_MAKE_ARCHID(major) \
((ETM_DEVARCH_MAKE_ARCHID_ARCH_VER(major)) | ETM_DEVARCH_ARCHID_ARCH_PART(0xA13))
#define ETM_DEVARCH_ARCHID_ETMv4x ETM_DEVARCH_MAKE_ARCHID(0x4)
#define ETM_DEVARCH_ARCHID_ETE ETM_DEVARCH_MAKE_ARCHID(0x5)
#define ETM_DEVARCH_ID_MASK \
(ETM_DEVARCH_ARCHITECT_MASK | ETM_DEVARCH_ARCHID_MASK | ETM_DEVARCH_PRESENT)
#define ETM_DEVARCH_ETMv4x_ARCH \
(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETMv4x | ETM_DEVARCH_PRESENT)
#define ETM_DEVARCH_ETE_ARCH \
(ETM_DEVARCH_ARCHITECT_ARM | ETM_DEVARCH_ARCHID_ETE | ETM_DEVARCH_PRESENT)
#define TRCSTATR_IDLE_BIT 0
#define TRCSTATR_PMSTABLE_BIT 1
#define ETM_DEFAULT_ADDR_COMP 0
......@@ -201,8 +623,65 @@
/* NS MON (EL3) mode never implemented */
#define ETM_EXLEVEL_NS_VICTLR_MASK GENMASK(22, 20)
#define ETM_TRCIDR1_ARCH_MAJOR_SHIFT 8
#define ETM_TRCIDR1_ARCH_MAJOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
#define ETM_TRCIDR1_ARCH_MAJOR(x) \
(((x) & ETM_TRCIDR1_ARCH_MAJOR_MASK) >> ETM_TRCIDR1_ARCH_MAJOR_SHIFT)
#define ETM_TRCIDR1_ARCH_MINOR_SHIFT 4
#define ETM_TRCIDR1_ARCH_MINOR_MASK (0xfU << ETM_TRCIDR1_ARCH_MINOR_SHIFT)
#define ETM_TRCIDR1_ARCH_MINOR(x) \
(((x) & ETM_TRCIDR1_ARCH_MINOR_MASK) >> ETM_TRCIDR1_ARCH_MINOR_SHIFT)
#define ETM_TRCIDR1_ARCH_SHIFT ETM_TRCIDR1_ARCH_MINOR_SHIFT
#define ETM_TRCIDR1_ARCH_MASK \
(ETM_TRCIDR1_ARCH_MAJOR_MASK | ETM_TRCIDR1_ARCH_MINOR_MASK)
#define ETM_TRCIDR1_ARCH_ETMv4 0x4
/*
* Driver representation of the ETM architecture.
* The version of an ETM component can be detected from
*
* TRCDEVARCH - CoreSight architected register
* - Bits[15:12] - Major version
* - Bits[19:16] - Minor version
* TRCIDR1 - ETM architected register
* - Bits[11:8] - Major version
* - Bits[7:4] - Minor version
* We must rely on TRCDEVARCH for the version information,
* however we don't want to break the support for potential
* old implementations which might not implement it. Thus
* we fall back to TRCIDR1 if TRCDEVARCH is not implemented
* for memory mapped components.
* Now to make certain decisions easier based on the version
* we use an internal representation of the version in the
* driver, as follows :
*
* ETM_ARCH_VERSION[7:0], where :
* Bits[7:4] - Major version
* Bits[3:0] - Minro version
*/
#define ETM_ARCH_VERSION(major, minor) \
((((major) & 0xfU) << 4) | (((minor) & 0xfU)))
#define ETM_ARCH_MAJOR_VERSION(arch) (((arch) >> 4) & 0xfU)
#define ETM_ARCH_MINOR_VERSION(arch) ((arch) & 0xfU)
#define ETM_ARCH_V4 ETM_ARCH_VERSION(4, 0)
#define ETM_ARCH_ETE ETM_ARCH_VERSION(5, 0)
/* Interpretation of resource numbers change at ETM v4.3 architecture */
#define ETM4X_ARCH_4V3 0x43
#define ETM_ARCH_V4_3 ETM_ARCH_VERSION(4, 3)
static inline u8 etm_devarch_to_arch(u32 devarch)
{
return ETM_ARCH_VERSION(ETM_DEVARCH_ARCHID_ARCH_VER(devarch),
ETM_DEVARCH_REVISION(devarch));
}
static inline u8 etm_trcidr_to_arch(u32 trcidr1)
{
return ETM_ARCH_VERSION(ETM_TRCIDR1_ARCH_MAJOR(trcidr1),
ETM_TRCIDR1_ARCH_MINOR(trcidr1));
}
enum etm_impdef_type {
ETM4_IMPDEF_HISI_CORE_COMMIT,
......@@ -370,7 +849,7 @@ struct etmv4_save_state {
* @spinlock: Only one at a time pls.
* @mode: This tracer's mode, i.e sysFS, Perf or disabled.
* @cpu: The cpu this component is affined to.
* @arch: ETM version number.
* @arch: ETM architecture version.
* @nr_pe: The number of processing entity available for tracing.
* @nr_pe_cmp: The number of processing entity comparator inputs that are
* available for tracing.
......@@ -417,7 +896,12 @@ struct etmv4_save_state {
* @nooverflow: Indicate if overflow prevention is supported.
* @atbtrig: If the implementation can support ATB triggers
* @lpoverride: If the implementation can support low-power state over.
* @trfcr: If the CPU supports FEAT_TRF, value of the TRFCR_ELx that
* allows tracing at all ELs. We don't want to compute this
* at runtime, due to the additional setting of TRFCR_CX when
* in EL2. Otherwise, 0.
* @config: structure holding configuration parameters.
* @save_trfcr: Saved TRFCR_EL1 register during a CPU PM event.
* @save_state: State to be preserved across power loss
* @state_needs_restore: True when there is context to restore after PM exit
* @skip_power_up: Indicates if an implementation can skip powering up
......@@ -452,6 +936,7 @@ struct etmv4_drvdata {
u8 s_ex_level;
u8 ns_ex_level;
u8 q_support;
u8 os_lock_model;
bool sticky_enable;
bool boot_enable;
bool os_unlock;
......@@ -467,7 +952,9 @@ struct etmv4_drvdata {
bool nooverflow;
bool atbtrig;
bool lpoverride;
u32 trfcr;
struct etmv4_config config;
u64 save_trfcr;
struct etmv4_save_state *save_state;
bool state_needs_restore;
bool skip_power_up;
......@@ -492,4 +979,12 @@ enum etm_addr_ctxtype {
extern const struct attribute_group *coresight_etmv4_groups[];
void etm4_config_trace_mode(struct etmv4_config *config);
u64 etm4x_sysreg_read(u32 offset, bool _relaxed, bool _64bit);
void etm4x_sysreg_write(u64 val, u32 offset, bool _relaxed, bool _64bit);
static inline bool etm4x_is_ete(struct etmv4_drvdata *drvdata)
{
return drvdata->arch >= ETM_ARCH_ETE;
}
#endif
......@@ -52,13 +52,14 @@ static int dynamic_funnel_enable_hw(struct funnel_drvdata *drvdata, int port)
{
u32 functl;
int rc = 0;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
functl = readl_relaxed(drvdata->base + FUNNEL_FUNCTL);
/* Claim the device only when we enable the first slave */
if (!(functl & FUNNEL_ENSx_MASK)) {
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev);
if (rc)
goto done;
}
......@@ -101,6 +102,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
int inport)
{
u32 functl;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
......@@ -110,7 +112,7 @@ static void dynamic_funnel_disable_hw(struct funnel_drvdata *drvdata,
/* Disclaim the device if none of the slaves are now active */
if (!(functl & FUNNEL_ENSx_MASK))
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}
......@@ -242,6 +244,7 @@ static int funnel_probe(struct device *dev, struct resource *res)
}
drvdata->base = base;
desc.groups = coresight_funnel_groups;
desc.access = CSDEV_ACCESS_IOMEM(base);
}
dev_set_drvdata(dev, drvdata);
......
......@@ -232,4 +232,7 @@ coresight_find_csdev_by_fwnode(struct fwnode_handle *r_fwnode);
void coresight_set_assoc_ectdev_mutex(struct coresight_device *csdev,
struct coresight_device *ect_csdev);
void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev);
struct coresight_device *coresight_get_percpu_sink(int cpu);
#endif
......@@ -45,12 +45,14 @@ struct replicator_drvdata {
static void dynamic_replicator_reset(struct replicator_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
if (!coresight_claim_device_unlocked(drvdata->base)) {
if (!coresight_claim_device_unlocked(csdev)) {
writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER0);
writel_relaxed(0xff, drvdata->base + REPLICATOR_IDFILTER1);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
}
CS_LOCK(drvdata->base);
......@@ -70,6 +72,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
{
int rc = 0;
u32 id0val, id1val;
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
......@@ -84,7 +87,7 @@ static int dynamic_replicator_enable(struct replicator_drvdata *drvdata,
id0val = id1val = 0xff;
if (id0val == 0xff && id1val == 0xff)
rc = coresight_claim_device_unlocked(drvdata->base);
rc = coresight_claim_device_unlocked(csdev);
if (!rc) {
switch (outport) {
......@@ -140,6 +143,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
int inport, int outport)
{
u32 reg;
struct coresight_device *csdev = drvdata->csdev;
switch (outport) {
case 0:
......@@ -160,7 +164,7 @@ static void dynamic_replicator_disable(struct replicator_drvdata *drvdata,
if ((readl_relaxed(drvdata->base + REPLICATOR_IDFILTER0) == 0xff) &&
(readl_relaxed(drvdata->base + REPLICATOR_IDFILTER1) == 0xff))
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}
......@@ -254,6 +258,7 @@ static int replicator_probe(struct device *dev, struct resource *res)
}
drvdata->base = base;
desc.groups = replicator_groups;
desc.access = CSDEV_ACCESS_IOMEM(base);
}
if (fwnode_property_present(dev_fwnode(dev),
......
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Arm v8 Self-Hosted trace support.
*
* Copyright (C) 2021 ARM Ltd.
*/
#ifndef __CORESIGHT_SELF_HOSTED_TRACE_H
#define __CORESIGHT_SELF_HOSTED_TRACE_H
#include <asm/sysreg.h>
static inline u64 read_trfcr(void)
{
return read_sysreg_s(SYS_TRFCR_EL1);
}
static inline void write_trfcr(u64 val)
{
write_sysreg_s(val, SYS_TRFCR_EL1);
isb();
}
static inline u64 cpu_prohibit_trace(void)
{
u64 trfcr = read_trfcr();
/* Prohibit tracing at EL0 & the kernel EL */
write_trfcr(trfcr & ~(TRFCR_ELx_ExTRE | TRFCR_ELx_E0TRE));
/* Return the original value of the TRFCR */
return trfcr;
}
#endif /* __CORESIGHT_SELF_HOSTED_TRACE_H */
......@@ -258,6 +258,7 @@ static void stm_disable(struct coresight_device *csdev,
struct perf_event *event)
{
struct stm_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
struct csdev_access *csa = &csdev->access;
/*
* For as long as the tracer isn't disabled another entity can't
......@@ -270,7 +271,7 @@ static void stm_disable(struct coresight_device *csdev,
spin_unlock(&drvdata->spinlock);
/* Wait until the engine has completely stopped */
coresight_timeout(drvdata->base, STMTCSR, STMTCSR_BUSY_BIT, 0);
coresight_timeout(csa, STMTCSR, STMTCSR_BUSY_BIT, 0);
pm_runtime_put(csdev->dev.parent);
......@@ -884,6 +885,7 @@ static int stm_probe(struct amba_device *adev, const struct amba_id *id)
if (IS_ERR(base))
return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
ret = stm_get_stimulus_area(dev, &ch_res);
if (ret)
......
......@@ -33,16 +33,20 @@ DEFINE_CORESIGHT_DEVLIST(etr_devs, "tmc_etr");
void tmc_wait_for_tmcready(struct tmc_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
/* Ensure formatter, unformatter and hardware fifo are empty */
if (coresight_timeout(drvdata->base,
TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
dev_err(&drvdata->csdev->dev,
if (coresight_timeout(csa, TMC_STS, TMC_STS_TMCREADY_BIT, 1)) {
dev_err(&csdev->dev,
"timeout while waiting for TMC to be Ready\n");
}
}
void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
struct csdev_access *csa = &csdev->access;
u32 ffcr;
ffcr = readl_relaxed(drvdata->base + TMC_FFCR);
......@@ -51,9 +55,8 @@ void tmc_flush_and_stop(struct tmc_drvdata *drvdata)
ffcr |= BIT(TMC_FFCR_FLUSHMAN_BIT);
writel_relaxed(ffcr, drvdata->base + TMC_FFCR);
/* Ensure flush completes */
if (coresight_timeout(drvdata->base,
TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
dev_err(&drvdata->csdev->dev,
if (coresight_timeout(csa, TMC_FFCR, TMC_FFCR_FLUSHMAN_BIT, 0)) {
dev_err(&csdev->dev,
"timeout while waiting for completion of Manual Flush\n");
}
......@@ -456,6 +459,7 @@ static int tmc_probe(struct amba_device *adev, const struct amba_id *id)
}
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
spin_lock_init(&drvdata->spinlock);
......
......@@ -37,7 +37,7 @@ static void __tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_etb_enable_hw(struct tmc_drvdata *drvdata)
{
int rc = coresight_claim_device(drvdata->base);
int rc = coresight_claim_device(drvdata->csdev);
if (rc)
return rc;
......@@ -88,7 +88,7 @@ static void __tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
static void tmc_etb_disable_hw(struct tmc_drvdata *drvdata)
{
__tmc_etb_disable_hw(drvdata);
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev);
}
static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
......@@ -109,7 +109,7 @@ static void __tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
{
int rc = coresight_claim_device(drvdata->base);
int rc = coresight_claim_device(drvdata->csdev);
if (rc)
return rc;
......@@ -120,11 +120,13 @@ static int tmc_etf_enable_hw(struct tmc_drvdata *drvdata)
static void tmc_etf_disable_hw(struct tmc_drvdata *drvdata)
{
struct coresight_device *csdev = drvdata->csdev;
CS_UNLOCK(drvdata->base);
tmc_flush_and_stop(drvdata);
tmc_disable_hw(drvdata);
coresight_disclaim_device_unlocked(drvdata->base);
coresight_disclaim_device_unlocked(csdev);
CS_LOCK(drvdata->base);
}
......
......@@ -609,8 +609,9 @@ static int tmc_etr_alloc_flat_buf(struct tmc_drvdata *drvdata,
if (!flat_buf)
return -ENOMEM;
flat_buf->vaddr = dma_alloc_coherent(real_dev, etr_buf->size,
&flat_buf->daddr, GFP_KERNEL);
flat_buf->vaddr = dma_alloc_noncoherent(real_dev, etr_buf->size,
&flat_buf->daddr,
DMA_FROM_DEVICE, GFP_KERNEL);
if (!flat_buf->vaddr) {
kfree(flat_buf);
return -ENOMEM;
......@@ -631,14 +632,18 @@ static void tmc_etr_free_flat_buf(struct etr_buf *etr_buf)
if (flat_buf && flat_buf->daddr) {
struct device *real_dev = flat_buf->dev->parent;
dma_free_coherent(real_dev, flat_buf->size,
flat_buf->vaddr, flat_buf->daddr);
dma_free_noncoherent(real_dev, etr_buf->size,
flat_buf->vaddr, flat_buf->daddr,
DMA_FROM_DEVICE);
}
kfree(flat_buf);
}
static void tmc_etr_sync_flat_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
{
struct etr_flat_buf *flat_buf = etr_buf->private;
struct device *real_dev = flat_buf->dev->parent;
/*
* Adjust the buffer to point to the beginning of the trace data
* and update the available trace data.
......@@ -648,6 +653,19 @@ static void tmc_etr_sync_flat_buf(struct etr_buf *etr_buf, u64 rrp, u64 rwp)
etr_buf->len = etr_buf->size;
else
etr_buf->len = rwp - rrp;
/*
* The driver always starts tracing at the beginning of the buffer,
* the only reason why we would get a wrap around is when the buffer
* is full. Sync the entire buffer in one go for this case.
*/
if (etr_buf->offset + etr_buf->len > etr_buf->size)
dma_sync_single_for_cpu(real_dev, flat_buf->daddr,
etr_buf->size, DMA_FROM_DEVICE);
else
dma_sync_single_for_cpu(real_dev,
flat_buf->daddr + etr_buf->offset,
etr_buf->len, DMA_FROM_DEVICE);
}
static ssize_t tmc_etr_get_data_flat_buf(struct etr_buf *etr_buf,
......@@ -1040,7 +1058,7 @@ static int tmc_etr_enable_hw(struct tmc_drvdata *drvdata,
rc = tmc_etr_enable_catu(drvdata, etr_buf);
if (rc)
return rc;
rc = coresight_claim_device(drvdata->base);
rc = coresight_claim_device(drvdata->csdev);
if (!rc) {
drvdata->etr_buf = etr_buf;
__tmc_etr_enable_hw(drvdata);
......@@ -1134,7 +1152,7 @@ void tmc_etr_disable_hw(struct tmc_drvdata *drvdata)
__tmc_etr_disable_hw(drvdata);
/* Disable CATU device if this ETR is connected to one */
tmc_etr_disable_catu(drvdata);
coresight_disclaim_device(drvdata->base);
coresight_disclaim_device(drvdata->csdev);
/* Reset the ETR buf used by hardware */
drvdata->etr_buf = NULL;
}
......
......@@ -81,6 +81,8 @@ static int tpiu_enable(struct coresight_device *csdev, u32 mode, void *__unused)
static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
{
struct csdev_access *csa = &drvdata->csdev->access;
CS_UNLOCK(drvdata->base);
/* Clear formatter and stop on flush */
......@@ -88,9 +90,9 @@ static void tpiu_disable_hw(struct tpiu_drvdata *drvdata)
/* Generate manual flush */
writel_relaxed(FFCR_STOP_FI | FFCR_FON_MAN, drvdata->base + TPIU_FFCR);
/* Wait for flush to complete */
coresight_timeout(drvdata->base, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
coresight_timeout(csa, TPIU_FFCR, FFCR_FON_MAN_BIT, 0);
/* Wait for formatter to stop */
coresight_timeout(drvdata->base, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
coresight_timeout(csa, TPIU_FFSR, FFSR_FT_STOPPED_BIT, 1);
CS_LOCK(drvdata->base);
}
......@@ -149,6 +151,7 @@ static int tpiu_probe(struct amba_device *adev, const struct amba_id *id)
return PTR_ERR(base);
drvdata->base = base;
desc.access = CSDEV_ACCESS_IOMEM(base);
/* Disable tpiu to support older devices */
tpiu_disable_hw(drvdata);
......
此差异已折叠。
/* SPDX-License-Identifier: GPL-2.0 */
/*
* This contains all required hardware related helper functions for
* Trace Buffer Extension (TRBE) driver in the coresight framework.
*
* Copyright (C) 2020 ARM Ltd.
*
* Author: Anshuman Khandual <anshuman.khandual@arm.com>
*/
#include <linux/coresight.h>
#include <linux/device.h>
#include <linux/irq.h>
#include <linux/kernel.h>
#include <linux/of.h>
#include <linux/platform_device.h>
#include <linux/smp.h>
#include "coresight-etm-perf.h"
static inline bool is_trbe_available(void)
{
u64 aa64dfr0 = read_sysreg_s(SYS_ID_AA64DFR0_EL1);
unsigned int trbe = cpuid_feature_extract_unsigned_field(aa64dfr0, ID_AA64DFR0_TRBE_SHIFT);
return trbe >= 0b0001;
}
static inline bool is_trbe_enabled(void)
{
u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
return trblimitr & TRBLIMITR_ENABLE;
}
#define TRBE_EC_OTHERS 0
#define TRBE_EC_STAGE1_ABORT 36
#define TRBE_EC_STAGE2_ABORT 37
static inline int get_trbe_ec(u64 trbsr)
{
return (trbsr >> TRBSR_EC_SHIFT) & TRBSR_EC_MASK;
}
#define TRBE_BSC_NOT_STOPPED 0
#define TRBE_BSC_FILLED 1
#define TRBE_BSC_TRIGGERED 2
static inline int get_trbe_bsc(u64 trbsr)
{
return (trbsr >> TRBSR_BSC_SHIFT) & TRBSR_BSC_MASK;
}
static inline void clr_trbe_irq(void)
{
u64 trbsr = read_sysreg_s(SYS_TRBSR_EL1);
trbsr &= ~TRBSR_IRQ;
write_sysreg_s(trbsr, SYS_TRBSR_EL1);
}
static inline bool is_trbe_irq(u64 trbsr)
{
return trbsr & TRBSR_IRQ;
}
static inline bool is_trbe_trg(u64 trbsr)
{
return trbsr & TRBSR_TRG;
}
static inline bool is_trbe_wrap(u64 trbsr)
{
return trbsr & TRBSR_WRAP;
}
static inline bool is_trbe_abort(u64 trbsr)
{
return trbsr & TRBSR_ABORT;
}
static inline bool is_trbe_running(u64 trbsr)
{
return !(trbsr & TRBSR_STOP);
}
#define TRBE_TRIG_MODE_STOP 0
#define TRBE_TRIG_MODE_IRQ 1
#define TRBE_TRIG_MODE_IGNORE 3
#define TRBE_FILL_MODE_FILL 0
#define TRBE_FILL_MODE_WRAP 1
#define TRBE_FILL_MODE_CIRCULAR_BUFFER 3
static inline void set_trbe_disabled(void)
{
u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
trblimitr &= ~TRBLIMITR_ENABLE;
write_sysreg_s(trblimitr, SYS_TRBLIMITR_EL1);
}
static inline bool get_trbe_flag_update(u64 trbidr)
{
return trbidr & TRBIDR_FLAG;
}
static inline bool is_trbe_programmable(u64 trbidr)
{
return !(trbidr & TRBIDR_PROG);
}
static inline int get_trbe_address_align(u64 trbidr)
{
return (trbidr >> TRBIDR_ALIGN_SHIFT) & TRBIDR_ALIGN_MASK;
}
static inline unsigned long get_trbe_write_pointer(void)
{
return read_sysreg_s(SYS_TRBPTR_EL1);
}
static inline void set_trbe_write_pointer(unsigned long addr)
{
WARN_ON(is_trbe_enabled());
write_sysreg_s(addr, SYS_TRBPTR_EL1);
}
static inline unsigned long get_trbe_limit_pointer(void)
{
u64 trblimitr = read_sysreg_s(SYS_TRBLIMITR_EL1);
unsigned long addr = trblimitr & (TRBLIMITR_LIMIT_MASK << TRBLIMITR_LIMIT_SHIFT);
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
return addr;
}
static inline unsigned long get_trbe_base_pointer(void)
{
u64 trbbaser = read_sysreg_s(SYS_TRBBASER_EL1);
unsigned long addr = trbbaser & (TRBBASER_BASE_MASK << TRBBASER_BASE_SHIFT);
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
return addr;
}
static inline void set_trbe_base_pointer(unsigned long addr)
{
WARN_ON(is_trbe_enabled());
WARN_ON(!IS_ALIGNED(addr, (1UL << TRBBASER_BASE_SHIFT)));
WARN_ON(!IS_ALIGNED(addr, PAGE_SIZE));
write_sysreg_s(addr, SYS_TRBBASER_EL1);
}
......@@ -8,7 +8,8 @@
#define _LINUX_CORESIGHT_PMU_H
#define CORESIGHT_ETM_PMU_NAME "cs_etm"
#define CORESIGHT_ETM_PMU_SEED 0x10
#define CORESIGHT_ETM_PMU_SEED 0x1
#define CORESIGHT_ETM_CSID_MAX 0x70
/* ETMv3.5/PTM's ETMCR config bit */
#define ETM_OPT_CYCACC 12
......@@ -30,7 +31,7 @@ static inline int coresight_get_trace_id(int cpu)
* the common convention is to have data trace IDs be I(N) + 1,
* set instruction trace IDs as a function of the CPU number.
*/
return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
return (CORESIGHT_ETM_PMU_SEED + (cpu * 2)) % CORESIGHT_ETM_CSID_MAX;
}
#endif
此差异已折叠。
......@@ -1101,10 +1101,15 @@ enum perf_callchain_context {
/**
* PERF_RECORD_AUX::flags bits
*/
#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */
#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */
#define PERF_AUX_FLAG_PARTIAL 0x04 /* record contains gaps */
#define PERF_AUX_FLAG_COLLISION 0x08 /* sample collided with another */
#define PERF_AUX_FLAG_TRUNCATED 0x01 /* record was truncated to fit */
#define PERF_AUX_FLAG_OVERWRITE 0x02 /* snapshot from overwrite mode */
#define PERF_AUX_FLAG_PARTIAL 0x04 /* record contains gaps */
#define PERF_AUX_FLAG_COLLISION 0x08 /* sample collided with another */
#define PERF_AUX_FLAG_PMU_FORMAT_TYPE_MASK 0xff00 /* PMU specific trace format type */
/* CoreSight PMU AUX buffer formats */
#define PERF_AUX_FLAG_CORESIGHT_FORMAT_CORESIGHT 0x0000 /* Default for backward compatibility */
#define PERF_AUX_FLAG_CORESIGHT_FORMAT_RAW 0x0100 /* Raw format of the source */
#define PERF_FLAG_FD_NO_GROUP (1UL << 0)
#define PERF_FLAG_FD_OUTPUT (1UL << 1)
......
......@@ -4,9 +4,9 @@
/*
* Check OpenCSD library version is sufficient to provide required features
*/
#define OCSD_MIN_VER ((0 << 16) | (14 << 8) | (0))
#define OCSD_MIN_VER ((1 << 16) | (0 << 8) | (0))
#if !defined(OCSD_VER_NUM) || (OCSD_VER_NUM < OCSD_MIN_VER)
#error "OpenCSD >= 0.14.0 is required"
#error "OpenCSD >= 1.0.0 is required"
#endif
int main(void)
......
......@@ -8,7 +8,8 @@
#define _LINUX_CORESIGHT_PMU_H
#define CORESIGHT_ETM_PMU_NAME "cs_etm"
#define CORESIGHT_ETM_PMU_SEED 0x10
#define CORESIGHT_ETM_PMU_SEED 0x1
#define CORESIGHT_ETM_CSID_MAX 0x70
/* ETMv3.5/PTM's ETMCR config bit */
#define ETM_OPT_CYCACC 12
......@@ -30,7 +31,7 @@ static inline int coresight_get_trace_id(int cpu)
* the common convention is to have data trace IDs be I(N) + 1,
* set instruction trace IDs as a function of the CPU number.
*/
return (CORESIGHT_ETM_PMU_SEED + (cpu * 2));
return (CORESIGHT_ETM_PMU_SEED + (cpu * 2)) % CORESIGHT_ETM_CSID_MAX;
}
#endif
......@@ -419,19 +419,10 @@ cs_etm_decoder__buffer_range(struct cs_etm_queue *etmq,
packet->last_instr_subtype = elem->last_i_subtype;
packet->last_instr_cond = elem->last_instr_cond;
switch (elem->last_i_type) {
case OCSD_INSTR_BR:
case OCSD_INSTR_BR_INDIRECT:
if (elem->last_i_type == OCSD_INSTR_BR || elem->last_i_type == OCSD_INSTR_BR_INDIRECT)
packet->last_instr_taken_branch = elem->last_instr_exec;
break;
case OCSD_INSTR_ISB:
case OCSD_INSTR_DSB_DMB:
case OCSD_INSTR_WFI_WFE:
case OCSD_INSTR_OTHER:
default:
else
packet->last_instr_taken_branch = false;
break;
}
packet->last_instr_size = elem->last_instr_sz;
......@@ -572,6 +563,8 @@ static ocsd_datapath_resp_t cs_etm_decoder__gen_trace_elem_printer(
case OCSD_GEN_TRC_ELEM_EVENT:
case OCSD_GEN_TRC_ELEM_SWTRACE:
case OCSD_GEN_TRC_ELEM_CUSTOM:
case OCSD_GEN_TRC_ELEM_SYNC_MARKER:
case OCSD_GEN_TRC_ELEM_MEMTRANS:
default:
break;
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册