Coresight integration with perf
Subsystems (6)
v8 cover Coresight integration with perf
This patchset aims to integrate configuration and control of the Coresight tracers with the perf sub-system.
The goal is to use PMUs to represent tracers and the auxiliary buffer enhancement to collect processor traces. As such a lot of work is done to move the current Coresight sysFS oriented configuration and control commands to perf's AUX API.
For the time being the work concentrates on ETMv3 and ETB1.0 sink buffer. Work on ETMv4 and other type of sink buffers will follow once a foundation has been established.
This patchset is based on [1] and assumes [2] has been applied.
Best regards,
Mathieu
Changes since V7:
* Moved coresight_release_path() a workqueue context, preventing pm_runtime_put_sync() from being called from an invalid (i.e interrupt) context.
* Fixed wrong 'buf_ptr' type in function etb_update_buffer().
* In function auxtrace_record__init(), no longer setting the 'err' pointer to '-EINVAL'.
* Removing erroneous call to kfree() in function etm_disable_sysfs().
[1]. https://git.linaro.org/kernel/coresight.git/shortlog/refs/heads/next
[2]. http://www.spinics.net/lists/arm-kernel/msg474573.html
Changes since V6:
* Rebased to 4.4-rc5.
* Thanks to [1], all tracer configuration now happens when events are scheduled.
[1]. https://lwn.net/Articles/667573/
Changes since V5:
* Addressed Arnaldo's comment about using a struct perf_evlist rather than a struct perf_session.
* Addressed kbuild test robot's anomaly report [1].
* Moved perf_aux_output_{begin|end} to etm_event_{start|stop} in accordance with [2].
[1]. https://lkml.org/lkml/2015/11/30/46
[2]. http://thread.gmane.org/gmane.linux.kernel/2099328/focus=2099343
Changes since V4:
* Reworked the way event configuration information is kept, fixing a few corner cases when doing per CPU tracing.
* Rebased on 4.4-rc1.
* Added 'Cc' to specific perf related patches in the hope of suscitating interest from reviewers, i.e perf maintainers.
Changes since V3:
* Rebased to GKH's char-misc-next tree (e2d8680741ed).
Changes since V2:
* Rebased to v4.3.
* Used the -M option to "git format-patch".
* Decoupled tracers and path - both are now completely independent.
* Moved path enablement/release to Perf's add/del functions.
* Moved PM runtime operations to the coresight core rather than individual drivers.
* Enhanced mutual exclusion scheme between perf and sysFS.
* Removed architecture specific define in perf cmd line tool.
* Got rid of unused fields in structure 'cs_buffers'.
* Enhanced changelog for patch 16/26.
Changes since V1:
* Fixed typos in typographical error in documentation.
* Moved to a multi session support scheme.
* Split static and dynamic tracer configuration.
* Fixed configuration for user and kernel space tracing.
* Using WARN_ON_ONCE() rather than WARN_ON().
* Implemented strategy to prevent tracers from being used simultaneously.
* Changed sink_ops::unset_buffer() to sink_ops::reset_buffer().
* Moves ETM's sysFS interface from driver core to dedicated file.
* Removed spinlock in "etm_cpu_id()".
* Aggregated PMU driver pieces in a single patch.
* Added user space changes and rebased everything to v4.3-rc5.
Mathieu Poirier (23):
coresight: associating path with session rather than tracer
coresight: add API to get sink from path
coresight: moving PM runtime operations to core framework
coresight: etm3x: moving etm_readl/writel to header file
coresight: etm3x: moving sysFS entries to dedicated file
coresight: etm3x: unlocking tracers in default arch init
coresight: etm3x: splitting struct etm_drvdata
coresight: etm3x: adding operation mode for etm_enable()
coresight: etm3x: set progbit to stop trace collection
coresight: etm3x: changing default trace configuration
coresight: etm3x: consolidating initial config
coresight: etm3x: implementing user/kernel mode tracing
coresight: etm3x: implementing perf_enable/disable() API
coresight: etb10: moving to local atomic operations
coresight: etb10: adding operation mode for sink->enable()
coresight: etb10: implementing AUX API
coresight: updating documentation to reflect integration with perf
coresight: etm-perf: new PMU driver for ETM tracers
coresight: introducing a global trace ID function
perf tools: making function set_max_cpu_num() non static perf tools: adding perf_evlist to *info_priv_size() perf tools: making coresight PMU listable
perf tools: adding coresight etm PMU record capabilities
Documentation/trace/coresight.txt | 138 +- MAINTAINERS | 4 + drivers/hwtracing/coresight/Kconfig | 1 + drivers/hwtracing/coresight/Makefile | 4 +- drivers/hwtracing/coresight/coresight-etb10.c | 276 ++- drivers/hwtracing/coresight/coresight-etm-perf.c | 398 +++++ drivers/hwtracing/coresight/coresight-etm-perf.h | 32 + drivers/hwtracing/coresight/coresight-etm.h | 142 +- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 1272 ++++++++++++++ drivers/hwtracing/coresight/coresight-etm3x.c | 1816 +++++--------------- drivers/hwtracing/coresight/coresight-etm4x.c | 10 +- drivers/hwtracing/coresight/coresight-funnel.c | 2 - drivers/hwtracing/coresight/coresight-priv.h | 15 + .../coresight/coresight-replicator-qcom.c | 4 - drivers/hwtracing/coresight/coresight-replicator.c | 2 - drivers/hwtracing/coresight/coresight-tmc.c | 7 +- drivers/hwtracing/coresight/coresight-tpiu.c | 4 +- drivers/hwtracing/coresight/coresight.c | 326 ++-- include/linux/coresight-pmu.h | 39 + include/linux/coresight.h | 31 +- tools/perf/arch/arm/util/Build | 2 + tools/perf/arch/arm/util/auxtrace.c | 54 + tools/perf/arch/arm/util/cs_etm.c | 466 +++++ tools/perf/arch/arm/util/cs_etm.h | 44 + tools/perf/arch/arm/util/pmu.c | 34 + tools/perf/arch/x86/util/intel-bts.c | 4 +- tools/perf/arch/x86/util/intel-pt.c | 4 +- tools/perf/config/Makefile | 17 +- tools/perf/util/auxtrace.c | 8 +- tools/perf/util/auxtrace.h | 7 +- tools/perf/util/cpumap.c | 2 +- tools/perf/util/cpumap.h | 1 + 32 files changed, 3522 insertions(+), 1644 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-etm-perf.c create mode 100644 drivers/hwtracing/coresight/coresight-etm-perf.h create mode 100644 drivers/hwtracing/coresight/coresight-etm3x-sysfs.c create mode 100644 include/linux/coresight-pmu.h create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.h create mode 100644 tools/perf/arch/arm/util/pmu.c
Signature · 1 line
2.1.4
PATCH v8 1/23 coresight: associating path with session rather than tracer
When using the Coresight framework from the sysFS interface a tracer is always handling a single session and as such, a path can be associated with a tracer. But when supporting multiple session per tracer there is no guarantee that sessions will always have the same path from source to sink.
This patch is removing the automatic association between path and tracers. The building of a path and enablement of the components in the path are decoupled, allowing for the association of a path with a session rather than a tracer.
To keep backward functionality with the current sysFS access methods a per-cpu place holder is used to keep a handle on the path built when tracers are enabled. Lastly APIs to build paths and enable tracers are made public so that other subsystem can interact with the Coresight framework.
--- drivers/hwtracing/coresight/coresight-priv.h | 5 + drivers/hwtracing/coresight/coresight.c | 296 ++++++++++++++++++--------- include/linux/coresight.h | 2 - 3 files changed, 206 insertions(+), 97 deletions(-)
drivers/hwtracing/coresight/coresight-priv.h +5 -0
@@ -52,6 +52,11 @@ static inline void CS_UNLOCK(void __iomem *addr) }while (0 ); } +void coresight_disable_path (struct list_head *path); +int coresight_enable_path (struct list_head *path); +struct list_head *coresight_build_path (struct coresight_device *csdev); +void coresight_release_path (struct list_head *path); +#ifdef CONFIG_CORESIGHT_SOURCE_ETM3X extern int etm_readl_cp14 (u32 off,unsigned int *val);extern int etm_writel_cp14 (u32 off,u32 val);
drivers/hwtracing/coresight/coresight.c +201 -95
405 lines not on this page · raw message
include/linux/coresight.h +0 -2
@@ -152,7 +152,6 @@ struct coresight_connection { by @coresight_ops. * @dev: The device entity associated to this component. * @refcnt: keep track of what is in use. - * @path_link: link of current component into the path being enabled. * @orphan: true if the component has connections that haven't been linked. * @enable: 'true' if component is currently part of an active path. * @activated: 'true' only if a _sink_ has been activated. A sink can be
@@ -168,7 +167,6 @@ struct coresight_device {const struct coresight_ops *ops;struct device dev;atomic_t *refcnt; -struct list_head path_link;bool orphan;bool enable;/* true only if configured as part of a path */ bool activated;/* true only if a sink is part of a path */
Signature · 1 line
2.1.4
PATCH v8 2/23 coresight: add API to get sink from path
In reply to Mathieu PoirierAdd an API allowing external code to quickly get a handle on the sink within a path. The sink is always last, but adding an API allows to keep the path's node structure private and remove redundant checks.
--- drivers/hwtracing/coresight/coresight-priv.h | 1 + drivers/hwtracing/coresight/coresight.c | 15 +++++++++++++++ 2 files changed, 16 insertions(+)
drivers/hwtracing/coresight/coresight-priv.h +1 -0
@@ -54,6 +54,7 @@ static inline void CS_UNLOCK(void __iomem *addr)void coresight_disable_path (struct list_head *path);int coresight_enable_path (struct list_head *path); +struct coresight_device *coresight_get_sink (struct list_head *path);struct list_head *coresight_build_path (struct coresight_device *csdev);void coresight_release_path (struct list_head *path);
drivers/hwtracing/coresight/coresight.c +15 -0
@@ -321,6 +321,21 @@ err: goto out; } +struct coresight_device *coresight_get_sink (struct list_head *path) +{ +struct coresight_device *csdev; + +if (!path) +return NULL ; + + csdev = list_last_entry(path, struct coresight_node, link)->csdev; +if (csdev->type !=CORESIGHT_DEV_TYPE_SINK && + csdev->type !=CORESIGHT_DEV_TYPE_LINKSINK ) +return NULL ; + +return csdev; +} +/** * _coresight_build_path - recursively build a path from a @csdev to a sink. * @csdev: The device to start from.
Signature · 1 line
2.1.4
PATCH v8 3/23 coresight: moving PM runtime operations to core framework
In reply to Mathieu PoirierMoving PM runtime operations in Coresight devices enable() and disable() API to the framework core when a path is setup. That way the runtime core doesn't have to be involved everytime a path is enabled. It also avoids calling runtime PM operations in IRQ context.
--- drivers/hwtracing/coresight/coresight-etb10.c | 4 ---- drivers/hwtracing/coresight/coresight-etm3x.c | 3 --- drivers/hwtracing/coresight/coresight-etm4x.c | 6 ------ drivers/hwtracing/coresight/coresight-funnel.c | 2 -- drivers/hwtracing/coresight/coresight-replicator-qcom.c | 4 ---- drivers/hwtracing/coresight/coresight-replicator.c | 2 -- drivers/hwtracing/coresight/coresight-tmc.c | 5 ----- drivers/hwtracing/coresight/coresight-tpiu.c | 2 -- drivers/hwtracing/coresight/coresight.c | 9 ++++++++- 9 files changed, 8 insertions(+), 29 deletions(-)
drivers/hwtracing/coresight/coresight-etb10.c +0 -4
@@ -137,8 +137,6 @@ static int etb_enable(struct coresight_device *csdev)struct etb_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);unsigned long flags; -pm_runtime_get_sync (drvdata->dev); -spin_lock_irqsave (&drvdata->spinlock, flags);etb_enable_hw (drvdata); drvdata->enable = true;
@@ -247,8 +245,6 @@ static void etb_disable(struct coresight_device *csdev) drvdata->enable = false;spin_unlock_irqrestore (&drvdata->spinlock, flags); -pm_runtime_put (drvdata->dev); -dev_info (drvdata->dev,"ETB disabled\n" ); }
drivers/hwtracing/coresight/coresight-etm3x.c +0 -3
@@ -349,7 +349,6 @@ static int etm_enable(struct coresight_device *csdev)struct etm_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);int ret; -pm_runtime_get_sync (csdev->dev.parent);spin_lock (&drvdata->spinlock);/*
@@ -373,7 +372,6 @@ static int etm_enable(struct coresight_device *csdev)return 0 ; err:spin_unlock (&drvdata->spinlock); -pm_runtime_put (csdev->dev.parent);return ret; }
@@ -422,7 +420,6 @@ static void etm_disable(struct coresight_device *csdev)spin_unlock (&drvdata->spinlock);put_online_cpus (); -pm_runtime_put (csdev->dev.parent);dev_info (drvdata->dev,"ETM tracing disabled\n" ); }
drivers/hwtracing/coresight/coresight-etm4x.c +0 -6
@@ -72,7 +72,6 @@ static int etm4_trace_id(struct coresight_device *csdev)if (!drvdata->enable)return drvdata->trcid; -pm_runtime_get_sync (drvdata->dev);spin_lock_irqsave (&drvdata->spinlock, flags);CS_UNLOCK (drvdata->base);
@@ -81,7 +80,6 @@ static int etm4_trace_id(struct coresight_device *csdev)CS_LOCK (drvdata->base);spin_unlock_irqrestore (&drvdata->spinlock, flags); -pm_runtime_put (drvdata->dev);return trace_id; }
@@ -187,7 +185,6 @@ static int etm4_enable(struct coresight_device *csdev)struct etmv4_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);int ret; -pm_runtime_get_sync (drvdata->dev);spin_lock (&drvdata->spinlock);/*
@@ -207,7 +204,6 @@ static int etm4_enable(struct coresight_device *csdev)return 0 ; err:spin_unlock (&drvdata->spinlock); -pm_runtime_put (drvdata->dev);return ret; }
@@ -256,8 +252,6 @@ static void etm4_disable(struct coresight_device *csdev)spin_unlock (&drvdata->spinlock);put_online_cpus (); -pm_runtime_put (drvdata->dev); -dev_info (drvdata->dev,"ETM tracing disabled\n" ); }
drivers/hwtracing/coresight/coresight-funnel.c +0 -2
@@ -69,7 +69,6 @@ static int funnel_enable(struct coresight_device *csdev, int inport, {struct funnel_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); -pm_runtime_get_sync (drvdata->dev);funnel_enable_hw (drvdata, inport);dev_info (drvdata->dev,"FUNNEL inport %d enabled\n" , inport);
@@ -95,7 +94,6 @@ static void funnel_disable(struct coresight_device *csdev, int inport,struct funnel_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);funnel_disable_hw (drvdata, inport); -pm_runtime_put (drvdata->dev);dev_info (drvdata->dev,"FUNNEL inport %d disabled\n" , inport); }
drivers/hwtracing/coresight/coresight-replicator-qcom.c +0 -4
@@ -48,8 +48,6 @@ static int replicator_enable(struct coresight_device *csdev, int inport, {struct replicator_state *drvdata =dev_get_drvdata (csdev->dev.parent); -pm_runtime_get_sync (drvdata->dev); -CS_UNLOCK (drvdata->base);/*
@@ -86,8 +84,6 @@ static void replicator_disable(struct coresight_device *csdev, int inport,CS_LOCK (drvdata->base); -pm_runtime_put (drvdata->dev); -dev_info (drvdata->dev,"REPLICATOR disabled\n" ); }
drivers/hwtracing/coresight/coresight-replicator.c +0 -2
@@ -41,7 +41,6 @@ static int replicator_enable(struct coresight_device *csdev, int inport, {struct replicator_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); -pm_runtime_get_sync (drvdata->dev);dev_info (drvdata->dev,"REPLICATOR enabled\n" );return 0 ; }
@@ -51,7 +50,6 @@ static void replicator_disable(struct coresight_device *csdev, int inport, {struct replicator_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); -pm_runtime_put (drvdata->dev);dev_info (drvdata->dev,"REPLICATOR disabled\n" ); }
drivers/hwtracing/coresight/coresight-tmc.c +0 -5
@@ -242,12 +242,9 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode) {unsigned long flags; -pm_runtime_get_sync (drvdata->dev); -spin_lock_irqsave (&drvdata->spinlock, flags);if (drvdata->reading) {spin_unlock_irqrestore (&drvdata->spinlock, flags); -pm_runtime_put (drvdata->dev);return -EBUSY ; }
@@ -381,8 +378,6 @@ out: drvdata->enable = false;spin_unlock_irqrestore (&drvdata->spinlock, flags); -pm_runtime_put (drvdata->dev); -dev_info (drvdata->dev,"TMC disabled\n" ); }
drivers/hwtracing/coresight/coresight-tpiu.c +0 -2
@@ -74,7 +74,6 @@ static int tpiu_enable(struct coresight_device *csdev) {struct tpiu_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); -pm_runtime_get_sync (csdev->dev.parent);tpiu_enable_hw (drvdata);dev_info (drvdata->dev,"TPIU enabled\n" );
@@ -98,7 +97,6 @@ static void tpiu_disable(struct coresight_device *csdev)struct tpiu_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);tpiu_disable_hw (drvdata); -pm_runtime_put (csdev->dev.parent);dev_info (drvdata->dev,"TPIU disabled\n" ); }
drivers/hwtracing/coresight/coresight.c +8 -1
@@ -24,6 +24,7 @@#include <linux/coresight.h> #include <linux/of_platform.h> #include <linux/delay.h> +#include <linux/pm_runtime.h> #include "coresight-priv.h"
@@ -376,7 +377,8 @@ out:/* * A path from this element to a sink has been found. The elements * leading to the sink are already enqueued, all that is left to do -* is add a node for this element. +* is tell the PM runtime core we need this element and add a node +* for it. */ node =kzalloc (sizeof (struct coresight_node ),GFP_KERNEL );if (!node)
@@ -384,6 +386,7 @@ out: node->csdev = csdev;list_add (&node->link, path); +pm_runtime_get_sync (csdev->dev.parent);return 0 ; }
@@ -415,9 +418,13 @@ struct list_head *coresight_build_path(struct coresight_device *csdev)*/ void coresight_release_path (struct list_head *path) { +struct coresight_device *csdev;struct coresight_node *nd, *next;list_for_each_entry_safe (nd, next, path, link) { + csdev = nd->csdev; + +pm_runtime_put_sync (csdev->dev.parent);list_del (&nd->link);kfree (nd); }
Signature · 1 line
2.1.4
PATCH v8 4/23 coresight: etm3x: moving etm_readl/writel to header file
In reply to Mathieu PoirierMoving functions etm_readl/writel to file "coresight-etm.h" so that the main ETM3x driver can be split in more than one file.
--- drivers/hwtracing/coresight/coresight-etm.h | 29 +++++++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-etm3x.c | 29 --------------------------- 2 files changed, 29 insertions(+), 29 deletions(-)
drivers/hwtracing/coresight/coresight-etm.h +29 -0
@@ -251,4 +251,33 @@ enum etm_addr_type {ETM_ADDR_TYPE_START , ETM_ADDR_TYPE_STOP, }; + +static inline void etm_writel (struct etm_drvdata *drvdata, +u32 val,u32 off) +{ +if (drvdata->use_cp14) { +if (etm_writel_cp14 (off, val)) { +dev_err (drvdata->dev, +"invalid CP14 access to ETM reg: %#x" , off); + } + }else { +writel_relaxed (val, drvdata->base + off); + } +} + +static inline unsigned int etm_readl (struct etm_drvdata *drvdata,u32 off) +{ +u32 val; + +if (drvdata->use_cp14) { +if (etm_readl_cp14 (off, &val)) { +dev_err (drvdata->dev, +"invalid CP14 access to ETM reg: %#x" , off); + } + }else { + val =readl_relaxed (drvdata->base + off); + } + +return val; +}#endif
drivers/hwtracing/coresight/coresight-etm3x.c +0 -29
@@ -42,35 +42,6 @@ module_param_named(boot_enable, boot_enable, int, S_IRUGO);static int etm_count;static struct etm_drvdata *etmdrvdata[NR_CPUS ]; -static inline void etm_writel (struct etm_drvdata *drvdata, -u32 val,u32 off) -{ -if (drvdata->use_cp14) { -if (etm_writel_cp14 (off, val)) { -dev_err (drvdata->dev, -"invalid CP14 access to ETM reg: %#x" , off); - } - }else { -writel_relaxed (val, drvdata->base + off); - } -} - -static inline unsigned int etm_readl (struct etm_drvdata *drvdata,u32 off) -{ -u32 val; - -if (drvdata->use_cp14) { -if (etm_readl_cp14 (off, &val)) { -dev_err (drvdata->dev, -"invalid CP14 access to ETM reg: %#x" , off); - } - }else { - val =readl_relaxed (drvdata->base + off); - } - -return val; -} -/* * Memory mapped writes to clear os lock are not supported on some processors * and OS lock must be unlocked before any memory mapped access on such
Signature · 1 line
2.1.4
PATCH v8 5/23 coresight: etm3x: moving sysFS entries to dedicated file
In reply to Mathieu PoirierSysFS entries are big enough to justify their own file. As such moving all sysFS related declarations to a dedicated location.
--- drivers/hwtracing/coresight/Makefile | 3 +- drivers/hwtracing/coresight/coresight-etm.h | 4 + .../hwtracing/coresight/coresight-etm3x-sysfs.c | 1218 +++++++++++++++++++ drivers/hwtracing/coresight/coresight-etm3x.c | 1234 +------------------- 4 files changed, 1241 insertions(+), 1218 deletions(-) create mode 100644 drivers/hwtracing/coresight/coresight-etm3x-sysfs.c
drivers/hwtracing/coresight/Makefile +2 -1
@@ -8,6 +8,7 @@ obj-$(CONFIG_CORESIGHT_SINK_TPIU) += coresight-tpiu.o obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \ coresight-replicator.o -obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o +obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o \ + coresight-etm3x-sysfs.o obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
drivers/hwtracing/coresight/coresight-etm.h +4 -0
@@ -280,4 +280,8 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off) return val; } + +extern const struct attribute_group *coresight_etm_groups[]; +int etm_get_trace_id (struct etm_drvdata *drvdata); +void etm_set_default (struct etm_drvdata *drvdata);#endif
drivers/hwtracing/coresight/coresight-etm3x-sysfs.c new file +1218 -0
1,218 lines not on this page · raw message
drivers/hwtracing/coresight/coresight-etm3x.c +17 -1217
1,266 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v8 6/23 coresight: etm3x: unlocking tracers in default arch init
In reply to Mathieu PoirierCalling function 'smp_call_function_single()' to unlock a tracer and calling it again right after to perform the default initialisation doesn't make sense.
Moving 'etm_os_unlock()' just before making the default initialisation results in the same outcome while saving one call to 'smp_call_function_single()'.
--- drivers/hwtracing/coresight/coresight-etm3x.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-)
drivers/hwtracing/coresight/coresight-etm3x.c +5 -5
@@ -47,11 +47,11 @@ static struct etm_drvdata *etmdrvdata[NR_CPUS];* and OS lock must be unlocked before any memory mapped access on such * processors, otherwise memory mapped reads/writes will be invalid. */ -static void etm_os_unlock (void *info) +static void etm_os_unlock (struct etm_drvdata *drvdata) { -struct etm_drvdata *drvdata = (struct etm_drvdata *)info;/* Writing any value to ETMOSLAR unlocks the trace registers */ etm_writel (drvdata,0x0 ,ETMOSLAR ); + drvdata->os_unlock = true;isb (); }
@@ -483,6 +483,9 @@ static void etm_init_arch_data(void *info)u32 etmccr;struct etm_drvdata *drvdata = info; +/* Make sure all registers are accessible */ +etm_os_unlock (drvdata); +CS_UNLOCK (drvdata->base);/* First dummy read */
@@ -607,9 +610,6 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id)get_online_cpus (); etmdrvdata[drvdata->cpu] = drvdata; -if (!smp_call_function_single (drvdata->cpu, etm_os_unlock, drvdata,1 )) - drvdata->os_unlock = true; -if (smp_call_function_single (drvdata->cpu, etm_init_arch_data, drvdata,1 ))dev_err (dev,"ETM arch init failed\n" );
Signature · 1 line
2.1.4
PATCH v8 7/23 coresight: etm3x: splitting struct etm_drvdata
In reply to Mathieu PoirierSplitting "etm_drvdata" in two sections, one for the HW specific data and another for user configuration.
That way it is easier to manipulate and zero out the configuration data when more than one concurrent tracing session configuration is active.
Also taking care of up-lifting all the code affected by this new arrangement. No loss or gain of functionality (other than what is mentioned above) is introduced by this patch.
--- drivers/hwtracing/coresight/coresight-etm.h | 102 ++++---- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 290 ++++++++++++--------- drivers/hwtracing/coresight/coresight-etm3x.c | 153 +++++------ 3 files changed, 305 insertions(+), 240 deletions(-)
drivers/hwtracing/coresight/coresight-etm.h +56 -46
@@ -136,29 +136,9 @@#define ETM_DEFAULT_EVENT_VAL (ETM_HARD_WIRE_RES_A | \ ETM_ADD_COMP_0 | \ ETM_EVENT_NOT_A) +/** -* struct etm_drvdata - specifics associated to an ETM component -* @base: memory mapped base address for this component. -* @dev: the device entity associated to this component. -* @atclk: optional clock for the core parts of the ETM. -* @csdev: component vitals needed by the framework. -* @spinlock: only one at a time pls. -* @cpu: the cpu this component is affined to. -* @port_size: port size as reported by ETMCR bit 4-6 and 21. -* @arch: ETM/PTM version number. -* @use_cpu14: true if management registers need to be accessed via CP14. -* @enable: is this ETM/PTM currently tracing. -* @sticky_enable: true if ETM base configuration has been done. -* @boot_enable:true if we should start tracing at boot time. -* @os_unlock: true if access to management registers is allowed. -* @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR. -* @nr_cntr: Number of counters as found in ETMCCR bit 13-15. -* @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19. -* @nr_ext_out: Number of external output as found in ETMCCR bit 20-22. -* @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25. -* @etmccr: value of register ETMCCR. -* @etmccer: value of register ETMCCER. -* @traceid: value of the current ID for this component. +* struct etm_config - configuration information related to an ETM * @mode: controls various modes supported by this ETM/PTM. * @ctrl: used in conjunction with @mode. * @trigger_event: setting for register ETMTRIGGER.
@@ -189,30 +169,9 @@* @ctxid_mask: mask applicable to all the context IDs. * @sync_freq: Synchronisation frequency. * @timestamp_event: Defines an event that requests the insertion -of a timestamp into the trace stream. +* of a timestamp into the trace stream. */ -struct etm_drvdata { -void __iomem *base; -struct device *dev; -struct clk *atclk; -struct coresight_device *csdev; -spinlock_t spinlock; -int cpu; -int port_size; -u8 arch; -bool use_cp14; -bool enable; -bool sticky_enable; -bool boot_enable; -bool os_unlock; -u8 nr_addr_cmp; -u8 nr_cntr; -u8 nr_ext_inp; -u8 nr_ext_out; -u8 nr_ctxid_cmp; -u32 etmccr; -u32 etmccer; -u32 traceid; +struct etm_config {u32 mode;u32 ctrl;u32 trigger_event;
@@ -244,6 +203,56 @@ struct etm_drvdata {u32 timestamp_event; }; +/** +* struct etm_drvdata - specifics associated to an ETM component +* @base: memory mapped base address for this component. +* @dev: the device entity associated to this component. +* @atclk: optional clock for the core parts of the ETM. +* @csdev: component vitals needed by the framework. +* @spinlock: only one at a time pls. +* @cpu: the cpu this component is affined to. +* @port_size: port size as reported by ETMCR bit 4-6 and 21. +* @arch: ETM/PTM version number. +* @use_cpu14: true if management registers need to be accessed via CP14. +* @enable: is this ETM/PTM currently tracing. +* @sticky_enable: true if ETM base configuration has been done. +* @boot_enable:true if we should start tracing at boot time. +* @os_unlock: true if access to management registers is allowed. +* @nr_addr_cmp:Number of pairs of address comparators as found in ETMCCR. +* @nr_cntr: Number of counters as found in ETMCCR bit 13-15. +* @nr_ext_inp: Number of external input as found in ETMCCR bit 17-19. +* @nr_ext_out: Number of external output as found in ETMCCR bit 20-22. +* @nr_ctxid_cmp: Number of contextID comparators as found in ETMCCR bit 24-25. +* @etmccr: value of register ETMCCR. +* @etmccer: value of register ETMCCER. +* @traceid: value of the current ID for this component. +* @config: structure holding configuration parameters. +*/ +struct etm_drvdata { +void __iomem *base; +struct device *dev; +struct clk *atclk; +struct coresight_device *csdev; +spinlock_t spinlock; +int cpu; +int port_size; +u8 arch; +bool use_cp14; +bool enable; +bool sticky_enable; +bool boot_enable; +bool os_unlock; +u8 nr_addr_cmp; +u8 nr_cntr; +u8 nr_ext_inp; +u8 nr_ext_out; +u8 nr_ctxid_cmp; +u32 etmccr; +u32 etmccer; +u32 traceid; +struct etm_config config; +}; +enum etm_addr_type {ETM_ADDR_TYPE_NONE ,ETM_ADDR_TYPE_SINGLE ,
@@ -283,5 +292,6 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)extern const struct attribute_group *coresight_etm_groups[];int etm_get_trace_id (struct etm_drvdata *drvdata); -void etm_set_default (struct etm_drvdata *drvdata); +void etm_set_default (struct etm_config *config); +struct etm_config *get_etm_config (struct etm_drvdata *drvdata);#endif
drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +170 -120
880 lines not on this page · raw message
drivers/hwtracing/coresight/coresight-etm3x.c +79 -74
235 lines not on this page · raw message
Signature · 1 line
2.1.4
PATCH v8 8/23 coresight: etm3x: adding operation mode for etm_enable()
In reply to Mathieu PoirierAdding a new mode to source API enable() in order to distinguish where the request comes from. That way it is possible to perform different operations based on where the request was issued from.
The ETM4x driver is also modified to keep in sync with the new interface.
--- drivers/hwtracing/coresight/coresight-etm.h | 5 +- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 4 +- drivers/hwtracing/coresight/coresight-etm3x.c | 68 +++++++++++++++++++--- drivers/hwtracing/coresight/coresight-etm4x.c | 2 +- drivers/hwtracing/coresight/coresight-priv.h | 6 ++ drivers/hwtracing/coresight/coresight.c | 6 +- include/linux/coresight.h | 2 +- 7 files changed, 76 insertions(+), 17 deletions(-)
drivers/hwtracing/coresight/coresight-etm.h +3 -2
@@ -13,6 +13,7 @@#ifndef _CORESIGHT_CORESIGHT_ETM_H#define _CORESIGHT_CORESIGHT_ETM_H +#include <asm/local.h> #include <linux/spinlock.h> #include "coresight-priv.h"
@@ -214,7 +215,7 @@ struct etm_config {* @port_size: port size as reported by ETMCR bit 4-6 and 21. * @arch: ETM/PTM version number. * @use_cpu14: true if management registers need to be accessed via CP14. -* @enable: is this ETM/PTM currently tracing. +* @mode: this tracer's mode, i.e sysFS, Perf or disabled. * @sticky_enable: true if ETM base configuration has been done. * @boot_enable:true if we should start tracing at boot time. * @os_unlock: true if access to management registers is allowed.
@@ -238,7 +239,7 @@ struct etm_drvdata {int port_size;u8 arch;bool use_cp14; -bool enable; +local_t mode;bool sticky_enable;bool boot_enable;bool os_unlock;
drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +2 -2
@@ -716,7 +716,7 @@ static ssize_t cntr_val_show(struct device *dev,struct etm_drvdata *drvdata =dev_get_drvdata (dev->parent);struct etm_config *config = &drvdata->config; -if (!drvdata->enable) { +if (!local_read (&drvdata->mode)) {spin_lock (&drvdata->spinlock);for (i =0 ; i < drvdata->nr_cntr; i++) ret += sprintf(buf, "counter %d: %x\n",
@@ -935,7 +935,7 @@ static ssize_t seq_curr_state_show(struct device *dev,struct etm_drvdata *drvdata =dev_get_drvdata (dev->parent);struct etm_config *config = &drvdata->config; -if (!drvdata->enable) { +if (!local_read (&drvdata->mode)) { val = config->seq_curr_state; goto out; }
drivers/hwtracing/coresight/coresight-etm3x.c +60 -8
126 lines not on this page · raw message
drivers/hwtracing/coresight/coresight-etm4x.c +1 -1
@@ -180,7 +180,7 @@ static void etm4_enable_hw(void *info)dev_dbg (drvdata->dev,"cpu: %d enable smp call done\n" , drvdata->cpu); } -static int etm4_enable (struct coresight_device *csdev) +static int etm4_enable (struct coresight_device *csdev,u32 mode) {struct etmv4_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);int ret;
drivers/hwtracing/coresight/coresight-priv.h +6 -0
@@ -34,6 +34,12 @@#define TIMEOUT_US 100#define BMVAL (val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb) +enum cs_mode { +CS_MODE_DISABLED , +CS_MODE_SYSFS , +CS_MODE_PERF , +}; +static inline void CS_LOCK (void __iomem *addr) { do {
drivers/hwtracing/coresight/coresight.c +3 -3
@@ -222,7 +222,7 @@ static void coresight_disable_link(struct coresight_device *csdev, csdev->enable = false; } -static int coresight_enable_source (struct coresight_device *csdev) +static int coresight_enable_source (struct coresight_device *csdev,u32 mode) {int ret;
@@ -234,7 +234,7 @@ static int coresight_enable_source(struct coresight_device *csdev)if (!csdev->enable) {if (source_ops (csdev)->enable) { - ret =source_ops (csdev)->enable (csdev); + ret =source_ops (csdev)->enable (csdev, mode);if (ret)return ret; }
@@ -458,7 +458,7 @@ int coresight_enable(struct coresight_device *csdev)if (ret) goto err_path; - ret =coresight_enable_source (csdev); + ret =coresight_enable_source (csdev,CS_MODE_SYSFS );if (ret) goto err_source;
include/linux/coresight.h +1 -1
@@ -213,7 +213,7 @@ struct coresight_ops_link {struct coresight_ops_source {int (*cpu_id)(struct coresight_device *csdev);int (*trace_id)(struct coresight_device *csdev); -int (*enable)(struct coresight_device *csdev); +int (*enable)(struct coresight_device *csdev,u32 mode);void (*disable)(struct coresight_device *csdev); };
Signature · 1 line
2.1.4
PATCH v8 9/23 coresight: etm3x: set progbit to stop trace collection
In reply to Mathieu PoirierThere is no need to use the event enable's "always false" event to stop trace collection. For that purpose setting the programming bit (ETMCR:10) is enough.
--- drivers/hwtracing/coresight/coresight-etm3x.c | 3 --- 1 file changed, 3 deletions(-)
drivers/hwtracing/coresight/coresight-etm3x.c +0 -3
@@ -398,9 +398,6 @@ static void etm_disable_hw(void *info)CS_UNLOCK (drvdata->base);etm_set_prog (drvdata); -/* Program trace enable to low by using always false event */ -etm_writel (drvdata,ETM_HARD_WIRE_RES_A |ETM_EVENT_NOT_A ,ETMTEEVR ); -/* Read back sequencer and counters for post trace analysis */ config->seq_curr_state = (etm_readl (drvdata,ETMSQR ) &ETM_SQR_MASK );
Signature · 1 line
2.1.4
PATCH v8 10/23 coresight: etm3x: changing default trace configuration
In reply to Mathieu PoirierChanging default configuration to include the entire address range rather than just the kernel. That way traces are more inclusive and it is easier to narrow down if needed.
--- drivers/hwtracing/coresight/coresight-etm.h | 2 ++ drivers/hwtracing/coresight/coresight-etm3x.c | 29 ++++++++++++--------------- 2 files changed, 15 insertions(+), 16 deletions(-)
drivers/hwtracing/coresight/coresight-etm.h +2 -0
@@ -146,6 +146,7 @@* @startstop_ctrl: setting for register ETMTSSCR. * @enable_event: setting for register ETMTEEVR. * @enable_ctrl1: setting for register ETMTECR1. +* @enable_ctrl2: setting for register ETMTECR2. * @fifofull_level: setting for register ETMFFLR. * @addr_idx: index for the address comparator selection. * @addr_val: value for address comparator register.
@@ -179,6 +180,7 @@ struct etm_config {u32 startstop_ctrl;u32 enable_event;u32 enable_ctrl1; +u32 enable_ctrl2;u32 fifofull_level;u8 addr_idx;u32 addr_val[ETM_MAX_ADDR_CMP ];
drivers/hwtracing/coresight/coresight-etm3x.c +13 -16
@@ -579,26 +579,23 @@ static void etm_init_arch_data(void *info)static void etm_init_default_data (struct etm_config *config) { -u32 flags = (1 <<0 |/* instruction execute*/ -3 <<3 |/* ARM instruction */ -0 <<5 |/* No data value comparison */ -0 <<7 |/* No exact mach */ -0 <<8 |/* Ignore context ID */ -0 <<10 );/* Security ignored */ -if (WARN_ON_ONCE (!config))return ; - config->ctrl = (ETMCR_CYC_ACC |ETMCR_TIMESTAMP_EN ); - config->enable_ctrl1 =ETMTECR1_ADDR_COMP_1 ; - config->addr_val[0 ] = (u32 ) _stext; - config->addr_val[1 ] = (u32 ) _etext; - config->addr_acctype[0 ] = flags; - config->addr_acctype[1 ] = flags; - config->addr_type[0 ] =ETM_ADDR_TYPE_RANGE ; - config->addr_type[1 ] =ETM_ADDR_TYPE_RANGE ; -etm_set_default (config); + +/* +* Taken verbatim from the TRM: +* +* To trace all memory: +* set bit [24] in register 0x009, the ETMTECR1, to 1 +* set all other bits in register 0x009, the ETMTECR1, to 0 +* set all bits in register 0x007, the ETMTECR2, to 0 +* set register 0x008, the ETMTEEVR, to 0x6F (TRUE). +*/ + config->enable_ctrl1 =BIT (24 ); + config->enable_ctrl2 =0x0 ; + config->enable_event =ETM_HARD_WIRE_RES_A ; }static void etm_init_trace_id (struct etm_drvdata *drvdata)
Signature · 1 line
2.1.4
PATCH v8 11/23 coresight: etm3x: consolidating initial config
In reply to Mathieu PoirierThere is really no point in having two functions to take care of doing the initial tracer configuration. As such moving everything to 'etm_set_default()'.
--- drivers/hwtracing/coresight/coresight-etm3x.c | 37 ++++++++++----------------- 1 file changed, 14 insertions(+), 23 deletions(-)
drivers/hwtracing/coresight/coresight-etm3x.c +14 -23
@@ -41,7 +41,6 @@ module_param_named(boot_enable, boot_enable, int, S_IRUGO);/* The number of ETM/PTM currently registered */ static int etm_count;static struct etm_drvdata *etmdrvdata[NR_CPUS ]; -static void etm_init_default_data (struct etm_config *config);/* * Memory mapped writes to clear os lock are not supported on some processors
@@ -194,6 +193,19 @@ void etm_set_default(struct etm_config *config)if (WARN_ON_ONCE (!config))return ; +/* +* Taken verbatim from the TRM: +* +* To trace all memory: +* set bit [24] in register 0x009, the ETMTECR1, to 1 +* set all other bits in register 0x009, the ETMTECR1, to 0 +* set all bits in register 0x007, the ETMTECR2, to 0 +* set register 0x008, the ETMTEEVR, to 0x6F (TRUE). +*/ + config->enable_ctrl1 =BIT (24 ); + config->enable_ctrl2 =0x0 ; + config->enable_event =ETM_HARD_WIRE_RES_A ; + config->trigger_event =ETM_DEFAULT_EVENT_VAL ; config->enable_event =ETM_HARD_WIRE_RES_A ;
@@ -577,27 +589,6 @@ static void etm_init_arch_data(void *info)CS_LOCK (drvdata->base); } -static void etm_init_default_data (struct etm_config *config) -{ -if (WARN_ON_ONCE (!config)) -return ; - -etm_set_default (config); - -/* -* Taken verbatim from the TRM: -* -* To trace all memory: -* set bit [24] in register 0x009, the ETMTECR1, to 1 -* set all other bits in register 0x009, the ETMTECR1, to 0 -* set all bits in register 0x007, the ETMTECR2, to 0 -* set register 0x008, the ETMTEEVR, to 0x6F (TRUE). -*/ - config->enable_ctrl1 =BIT (24 ); - config->enable_ctrl2 =0x0 ; - config->enable_event =ETM_HARD_WIRE_RES_A ; -} -static void etm_init_trace_id (struct etm_drvdata *drvdata) {/*
@@ -674,7 +665,7 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) }etm_init_trace_id (drvdata); -etm_init_default_data (&drvdata->config); +etm_set_default (&drvdata->config); desc->type =CORESIGHT_DEV_TYPE_SOURCE ; desc->subtype.source_subtype =CORESIGHT_DEV_SUBTYPE_SOURCE_PROC ;
Signature · 1 line
2.1.4
PATCH v8 12/23 coresight: etm3x: implementing user/kernel mode tracing
In reply to Mathieu PoirierAdding new mode to limit tracing to kernel or user space.
--- drivers/hwtracing/coresight/coresight-etm.h | 6 ++- .../hwtracing/coresight/coresight-etm3x-sysfs.c | 4 ++ drivers/hwtracing/coresight/coresight-etm3x.c | 63 ++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-priv.h | 3 ++ 4 files changed, 75 insertions(+), 1 deletion(-)
drivers/hwtracing/coresight/coresight-etm.h +5 -1
@@ -110,7 +110,10 @@#define ETM_MODE_STALL BIT(2)#define ETM_MODE_TIMESTAMP BIT(3)#define ETM_MODE_CTXID BIT(4) -#define ETM_MODE_ALL 0x1f +#define ETM_MODE_ALL (ETM_MODE_EXCLUDE | ETM_MODE_CYCACC | \ + ETM_MODE_STALL | ETM_MODE_TIMESTAMP | \ + ETM_MODE_CTXID | ETM_MODE_EXCL_KERN | \ + ETM_MODE_EXCL_USER)#define ETM_SQR_MASK 0x3#define ETM_TRACEID_MASK 0x3f
@@ -296,5 +299,6 @@ static inline unsigned int etm_readl(struct etm_drvdata *drvdata, u32 off)extern const struct attribute_group *coresight_etm_groups[];int etm_get_trace_id (struct etm_drvdata *drvdata);void etm_set_default (struct etm_config *config); +void etm_config_trace_mode (struct etm_config *config);struct etm_config *get_etm_config (struct etm_drvdata *drvdata);#endif
drivers/hwtracing/coresight/coresight-etm3x-sysfs.c +4 -0
@@ -162,6 +162,10 @@ static ssize_t mode_store(struct device *dev, config->ctrl |=ETMCR_CTXID_SIZE ; else config->ctrl &= ~ETMCR_CTXID_SIZE; + +if (config->mode & (ETM_MODE_EXCL_KERN |ETM_MODE_EXCL_USER )) +etm_config_trace_mode (config); +spin_unlock (&drvdata->spinlock);return size;
drivers/hwtracing/coresight/coresight-etm3x.c +63 -0
69 lines not on this page · raw message
drivers/hwtracing/coresight/coresight-priv.h +3 -0
@@ -34,6 +34,9 @@#define TIMEOUT_US 100#define BMVAL (val, lsb, msb) ((val & GENMASK(msb, lsb)) >> lsb) +#define ETM_MODE_EXCL_KERN BIT(30) +#define ETM_MODE_EXCL_USER BIT(31) +enum cs_mode {CS_MODE_DISABLED ,CS_MODE_SYSFS ,
Signature · 1 line
2.1.4
PATCH v8 13/23 coresight: etm3x: implementing perf_enable/disable() API
In reply to Mathieu PoirierThat way traces can be enabled and disabled automatically from the Perf subystem using the PMU abstraction.
--- drivers/hwtracing/coresight/Kconfig | 1 + drivers/hwtracing/coresight/coresight-etm3x.c | 95 +++++++++++++++++++++++++-- drivers/hwtracing/coresight/coresight-etm4x.c | 4 +- drivers/hwtracing/coresight/coresight.c | 2 +- include/linux/coresight.h | 6 +- 5 files changed, 99 insertions(+), 9 deletions(-)
drivers/hwtracing/coresight/Kconfig +1 -0
@@ -4,6 +4,7 @@ menuconfig CORESIGHT bool "CoreSight Tracing Support" select ARM_AMBA + select PERF_EVENTS help This framework provides a kernel interface for the CoreSight debug and trace drivers to register themselves with. It's intended to build
drivers/hwtracing/coresight/coresight-etm3x.c +90 -5
150 lines not on this page · raw message
drivers/hwtracing/coresight/coresight-etm4x.c +3 -1
@@ -32,6 +32,7 @@#include <linux/seq_file.h> #include <linux/uaccess.h> #include <linux/pm_runtime.h> +#include <linux/perf_event.h> #include <asm/sections.h> #include "coresight-etm4x.h"
@@ -180,7 +181,8 @@ static void etm4_enable_hw(void *info)dev_dbg (drvdata->dev,"cpu: %d enable smp call done\n" , drvdata->cpu); } -static int etm4_enable (struct coresight_device *csdev,u32 mode) +static int etm4_enable (struct coresight_device *csdev, +struct perf_event_attr *attr,u32 mode) {struct etmv4_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);int ret;
drivers/hwtracing/coresight/coresight.c +1 -1
@@ -234,7 +234,7 @@ static int coresight_enable_source(struct coresight_device *csdev, u32 mode)if (!csdev->enable) {if (source_ops (csdev)->enable) { - ret =source_ops (csdev)->enable (csdev, mode); + ret =source_ops (csdev)->enable (csdev,NULL , mode);if (ret)return ret; }
include/linux/coresight.h +4 -2
@@ -14,6 +14,7 @@#define _LINUX_CORESIGHT_H#include <linux/device.h> +#include <linux/perf_event.h> #include <linux/sched.h> /* Peripheral id registers (0xFD0-0xFEC) */
@@ -206,14 +207,15 @@ struct coresight_ops_link {* @cpu_id: returns the value of the CPU number this component * is associated to. * @trace_id: returns the value of the component's trace ID as known -to the HW. +* to the HW. * @enable: enables tracing for a source. * @disable: disables tracing for a source. */ struct coresight_ops_source {int (*cpu_id)(struct coresight_device *csdev);int (*trace_id)(struct coresight_device *csdev); -int (*enable)(struct coresight_device *csdev,u32 mode); +int (*enable)(struct coresight_device *csdev, +struct perf_event_attr *attr,u32 mode);void (*disable)(struct coresight_device *csdev); };
Signature · 1 line
2.1.4
PATCH v8 14/23 coresight: etb10: moving to local atomic operations
In reply to Mathieu PoirierMoving to use local atomic operations to take advantage of the lockless implementation, something that will come handy when the ETB is accessed from the Perf subsystem. Also changing the name of the variable to something more meaningful.
--- drivers/hwtracing/coresight/coresight-etb10.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-)
drivers/hwtracing/coresight/coresight-etb10.c +5 -4
@@ -10,6 +10,7 @@* GNU General Public License for more details. */ +#include <asm/local.h> #include <linux/kernel.h> #include <linux/module.h> #include <linux/init.h>
@@ -71,7 +72,7 @@* @csdev: component vitals needed by the framework. * @miscdev: specifics to handle "/dev/xyz.etb" entry. * @spinlock: only one at a time pls. -* @in_use: synchronise user space access to etb buffer. +* @reading: synchronise user space access to etb buffer. * @buf: area of memory where ETB buffer content gets sent. * @buffer_depth: size of @buf. * @enable: this ETB is being used.
@@ -84,7 +85,7 @@ struct etb_drvdata {struct coresight_device *csdev;struct miscdevice miscdev;spinlock_t spinlock; -atomic_t in_use; +local_t reading;u8 *buf;u32 buffer_depth;bool enable;
@@ -277,7 +278,7 @@ static int etb_open(struct inode *inode, struct file *file)struct etb_drvdata *drvdata =container_of (file->private_data, struct etb_drvdata, miscdev); -if (atomic_cmpxchg (&drvdata->in_use,0 ,1 )) +if (local_cmpxchg (&drvdata->reading,0 ,1 ))return -EBUSY ;dev_dbg (drvdata->dev,"%s: successfully opened\n" , __func__);
@@ -313,7 +314,7 @@ static int etb_release(struct inode *inode, struct file *file) {struct etb_drvdata *drvdata =container_of (file->private_data, struct etb_drvdata, miscdev); -atomic_set (&drvdata->in_use,0 ); +local_set (&drvdata->reading,0 );dev_dbg (drvdata->dev,"%s: released\n" , __func__);return 0 ;
Signature · 1 line
2.1.4
PATCH v8 15/23 coresight: etb10: adding operation mode for sink->enable()
In reply to Mathieu PoirierAdding an operation mode to the sink->enable() API in order to prevent simultaneous access from different callers.
TPIU and TMC won't be supplemented with the AUX area API immediately and as such ignore the new mode.
--- drivers/hwtracing/coresight/coresight-etb10.c | 30 ++++++++++++++++++++------- drivers/hwtracing/coresight/coresight-priv.h | 2 +- drivers/hwtracing/coresight/coresight-tmc.c | 2 +- drivers/hwtracing/coresight/coresight-tpiu.c | 2 +- drivers/hwtracing/coresight/coresight.c | 10 ++++----- include/linux/coresight.h | 2 +- 6 files changed, 32 insertions(+), 16 deletions(-)
drivers/hwtracing/coresight/coresight-etb10.c +23 -7
@@ -73,9 +73,9 @@* @miscdev: specifics to handle "/dev/xyz.etb" entry. * @spinlock: only one at a time pls. * @reading: synchronise user space access to etb buffer. +* @mode: this ETB is being used. * @buf: area of memory where ETB buffer content gets sent. * @buffer_depth: size of @buf. -* @enable: this ETB is being used. * @trigger_cntr: amount of words to store after a trigger. */ struct etb_drvdata {
@@ -86,9 +86,9 @@ struct etb_drvdata {struct miscdevice miscdev;spinlock_t spinlock;local_t reading; +local_t mode;u8 *buf;u32 buffer_depth; -bool enable;u32 trigger_cntr; };
@@ -133,16 +133,31 @@ static void etb_enable_hw(struct etb_drvdata *drvdata)CS_LOCK (drvdata->base); } -static int etb_enable (struct coresight_device *csdev) +static int etb_enable (struct coresight_device *csdev,u32 mode) { -struct etb_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); +u32 val;unsigned long flags; +struct etb_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); + + val =local_cmpxchg (&drvdata->mode, +CS_MODE_DISABLED , mode); +/* +* When accessing from Perf, a HW buffer can be handled +* by a single trace entity. In sysFS mode many tracers +* can be logging to the same HW buffer. +*/ +if (val ==CS_MODE_PERF ) +return -EBUSY ; + +/* Nothing to do, the tracer is already enabled. */ +if (val ==CS_MODE_SYSFS ) + goto out;spin_lock_irqsave (&drvdata->spinlock, flags);etb_enable_hw (drvdata); - drvdata->enable = true;spin_unlock_irqrestore (&drvdata->spinlock, flags); +out:dev_info (drvdata->dev,"ETB enabled\n" );return 0 ; }
@@ -243,9 +258,10 @@ static void etb_disable(struct coresight_device *csdev)spin_lock_irqsave (&drvdata->spinlock, flags);etb_disable_hw (drvdata);etb_dump_hw (drvdata); - drvdata->enable = false;spin_unlock_irqrestore (&drvdata->spinlock, flags); +local_set (&drvdata->mode,CS_MODE_DISABLED ); +dev_info (drvdata->dev,"ETB disabled\n" ); }
@@ -263,7 +279,7 @@ static void etb_dump(struct etb_drvdata *drvdata)unsigned long flags;spin_lock_irqsave (&drvdata->spinlock, flags); -if (drvdata->enable) { +if (local_read (&drvdata->mode) ==CS_MODE_SYSFS ) {etb_disable_hw (drvdata);etb_dump_hw (drvdata);etb_enable_hw (drvdata);
drivers/hwtracing/coresight/coresight-priv.h +1 -1
@@ -62,7 +62,7 @@ static inline void CS_UNLOCK(void __iomem *addr) }void coresight_disable_path (struct list_head *path); -int coresight_enable_path (struct list_head *path); +int coresight_enable_path (struct list_head *path,u32 mode);struct coresight_device *coresight_get_sink (struct list_head *path);struct list_head *coresight_build_path (struct coresight_device *csdev);void coresight_release_path (struct list_head *path);
drivers/hwtracing/coresight/coresight-tmc.c +1 -1
@@ -265,7 +265,7 @@ static int tmc_enable(struct tmc_drvdata *drvdata, enum tmc_mode mode)return 0 ; } -static int tmc_enable_sink (struct coresight_device *csdev) +static int tmc_enable_sink (struct coresight_device *csdev,u32 mode) {struct tmc_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);
drivers/hwtracing/coresight/coresight-tpiu.c +1 -1
@@ -70,7 +70,7 @@ static void tpiu_enable_hw(struct tpiu_drvdata *drvdata)CS_LOCK (drvdata->base); } -static int tpiu_enable (struct coresight_device *csdev) +static int tpiu_enable (struct coresight_device *csdev,u32 mode) {struct tpiu_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent);
drivers/hwtracing/coresight/coresight.c +5 -5
@@ -121,13 +121,13 @@ static int coresight_find_link_outport(struct coresight_device *csdev,return 0 ; } -static int coresight_enable_sink (struct coresight_device *csdev) +static int coresight_enable_sink (struct coresight_device *csdev,u32 mode) {int ret;if (!csdev->enable) {if (sink_ops (csdev)->enable) { - ret =sink_ops (csdev)->enable (csdev); + ret =sink_ops (csdev)->enable (csdev, mode);if (ret)return ret; }
@@ -283,7 +283,7 @@ void coresight_disable_path(struct list_head *path) } } -int coresight_enable_path (struct list_head *path) +int coresight_enable_path (struct list_head *path,u32 mode) {int ret =0 ;
@@ -296,7 +296,7 @@ int coresight_enable_path(struct list_head *path)switch (csdev->type) {case CORESIGHT_DEV_TYPE_SINK :case CORESIGHT_DEV_TYPE_LINKSINK : - ret =coresight_enable_sink (csdev); + ret =coresight_enable_sink (csdev, mode);if (ret) goto err;break ;
@@ -454,7 +454,7 @@ int coresight_enable(struct coresight_device *csdev) goto out; } - ret =coresight_enable_path (path); + ret =coresight_enable_path (path,CS_MODE_SYSFS );if (ret) goto err_path;
include/linux/coresight.h +1 -1
@@ -186,7 +186,7 @@ struct coresight_device {* @disable: disables the sink. */ struct coresight_ops_sink { -int (*enable)(struct coresight_device *csdev); +int (*enable)(struct coresight_device *csdev,u32 mode);void (*disable)(struct coresight_device *csdev); };
Signature · 1 line
2.1.4
PATCH v8 16/23 coresight: etb10: implementing AUX API
In reply to Mathieu PoirierAdding an ETB10 specific AUX area operations to be used by the perf framework when events are initialised.
Part of this operation involves modeling the mmap'ed area based on the specific ways a sink buffer gathers information.
--- drivers/hwtracing/coresight/coresight-etb10.c | 237 ++++++++++++++++++++++++++ include/linux/coresight.h | 21 ++- 2 files changed, 256 insertions(+), 2 deletions(-)
drivers/hwtracing/coresight/coresight-etb10.c +237 -0
@@ -28,6 +28,11 @@#include <linux/coresight.h> #include <linux/amba/bus.h> #include <linux/clk.h> +#include <linux/circ_buf.h> +#include <linux/mm.h> +#include <linux/perf_event.h> + +#include <asm/local.h> #include "coresight-priv.h"
@@ -65,6 +70,26 @@#define ETB_FRAME_SIZE_WORDS 4/** +* struct cs_buffer - keep track of a recording session' specifics +* @cur: index of the current buffer +* @nr_pages: max number of pages granted to us +* @offset: offset within the current buffer +* @data_size: how much we collected in this run +* @lost: other than zero if we had a HW buffer wrap around +* @snapshot: is this run in snapshot mode +* @data_pages: a handle the ring buffer +*/ +struct cs_buffers { +unsigned int cur; +unsigned int nr_pages; +unsigned long offset; +local_t data_size; +local_t lost; +bool snapshot; +void **data_pages; +}; + +/** * struct etb_drvdata - specifics associated to an ETB component * @base: memory mapped base address for this component. * @dev: the device entity associated to this component.
@@ -265,9 +290,221 @@ static void etb_disable(struct coresight_device *csdev)dev_info (drvdata->dev,"ETB disabled\n" ); } +static void *etb_alloc_buffer (struct coresight_device *csdev,int cpu, +void **pages,int nr_pages,bool overwrite) +{ +int node; +struct cs_buffers *buf; + +if (cpu ==-1 ) + cpu =smp_processor_id (); + node =cpu_to_node (cpu); + + buf =kzalloc_node (sizeof (struct cs_buffers ),GFP_KERNEL , node); +if (!buf) +return NULL ; + + buf->snapshot = overwrite; + buf->nr_pages = nr_pages; + buf->data_pages = pages; + +return buf; +} + +static void etb_free_buffer (void *config) +{ +struct cs_buffers *buf = config; + +kfree (buf); +} + +static int etb_set_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config) +{ +int ret =0 ; +unsigned long head; +struct cs_buffers *buf = sink_config; + +/* wrap head around to the amount of space we have */ + head = handle->head & ((buf->nr_pages <<PAGE_SHIFT ) -1 ); + +/* find the page to write to */ + buf->cur = head /PAGE_SIZE ; + +/* and offset within that page */ + buf->offset = head %PAGE_SIZE ; + +local_set (&buf->data_size,0 ); + +return ret; +} + +static unsigned long etb_reset_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config,bool *lost) +{ +unsigned long size =0 ; +struct cs_buffers *buf = sink_config; + +if (buf) { +/* +* In snapshot mode ->data_size holds the new address of the +* ring buffer's head. The size itself is the whole address +* range since we want the latest information. +*/ +if (buf->snapshot) + handle->head =local_xchg (&buf->data_size, + buf->nr_pages <<PAGE_SHIFT ); + +/* +* Tell the tracer PMU how much we got in this run and if +* something went wrong along the way. Nobody else can use +* this cs_buffers instance until we are done. As such +* resetting parameters here and squaring off with the ring +* buffer API in the tracer PMU is fine. +*/ + *lost =local_xchg (&buf->lost,0 ); + size =local_xchg (&buf->data_size,0 ); + } + +return size; +} + +static void etb_update_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config) +{ +int i, cur; +u8 *buf_ptr; +u32 read_ptr, write_ptr, capacity; +u32 status, read_data, to_read; +unsigned long flags, offset; +struct cs_buffers *buf = sink_config; +struct etb_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); + +if (!buf) +return ; + + capacity = drvdata->buffer_depth *ETB_FRAME_SIZE_WORDS ; + +spin_lock_irqsave (&drvdata->spinlock, flags); + +CS_UNLOCK (drvdata->base); +etb_disable_hw (drvdata); + +/* unit is in words, not bytes */ + read_ptr =readl_relaxed (drvdata->base +ETB_RAM_READ_POINTER ); + write_ptr =readl_relaxed (drvdata->base +ETB_RAM_WRITE_POINTER ); + +/* +* Entries should be aligned to the frame size. If they are not +* go back to the last alignement point to give decoding tools a +* chance to fix things. +*/ +if (write_ptr %ETB_FRAME_SIZE_WORDS ) { +dev_err (drvdata->dev, +"write_ptr: %lu not aligned to formatter frame size\n" , + (unsigned long )write_ptr); + + write_ptr &= ~(ETB_FRAME_SIZE_WORDS -1 ); +local_inc (&buf->lost); + } + +/* +* Get a hold of the status register and see if a wrap around +* has occurred. If so adjust things accordingly. Otherwise +* start at the beginning and go until the write pointer has +* been reached. +*/ + status =readl_relaxed (drvdata->base +ETB_STATUS_REG ); +if (status &ETB_STATUS_RAM_FULL ) { +local_inc (&buf->lost); + to_read = capacity; + read_ptr = write_ptr; + }else { + to_read =CIRC_CNT (write_ptr, read_ptr, drvdata->buffer_depth); + to_read *=ETB_FRAME_SIZE_WORDS ; + } + +/* +* Make sure we don't overwrite data that hasn't been consumed yet. +* It is entirely possible that the HW buffer has more data than the +* ring buffer can currently handle. If so adjust the start address +* to take only the last traces. +* +* In snapshot mode we are looking to get the latest traces only and as +* such, we don't care about not overwriting data that hasn't been +* processed by user space. +*/ +if (!buf->snapshot && to_read > handle->size) { +u32 mask = ~(ETB_FRAME_SIZE_WORDS -1 ); + +/* The new read pointer must be frame size aligned */ + to_read -= handle->size & mask; +/* +* Move the RAM read pointer up, keeping in mind that +* everything is in frame size units. +*/ + read_ptr = (write_ptr + drvdata->buffer_depth) - + to_read /ETB_FRAME_SIZE_WORDS ; +/* Wrap around if need be*/ + read_ptr &= ~(drvdata->buffer_depth -1 ); +/* let the decoder know we've skipped ahead */ +local_inc (&buf->lost); + } + +/* finally tell HW where we want to start reading from */ +writel_relaxed (read_ptr, drvdata->base +ETB_RAM_READ_POINTER ); + + cur = buf->cur; + offset = buf->offset; +for (i =0 ; i < to_read; i +=4 ) { + buf_ptr = buf->data_pages[cur] + offset; + read_data =readl_relaxed (drvdata->base + +ETB_RAM_READ_DATA_REG ); + *buf_ptr++ = read_data >>0 ; + *buf_ptr++ = read_data >>8 ; + *buf_ptr++ = read_data >>16 ; + *buf_ptr++ = read_data >>24 ; + + offset +=4 ; +if (offset >=PAGE_SIZE ) { + offset =0 ; + cur++; +/* wrap around at the end of the buffer */ + cur &= buf->nr_pages -1 ; + } + } + +/* reset ETB buffer for next run */ +writel_relaxed (0x0 , drvdata->base +ETB_RAM_READ_POINTER ); +writel_relaxed (0x0 , drvdata->base +ETB_RAM_WRITE_POINTER ); + +/* +* In snapshot mode all we have to do is communicate to +* perf_aux_output_end() the address of the current head. In full +* trace mode the same function expects a size to move rb->aux_head +* forward. +*/ +if (buf->snapshot) +local_set (&buf->data_size, (cur *PAGE_SIZE ) + offset); +else +local_add (to_read, &buf->data_size); + +etb_enable_hw (drvdata); +CS_LOCK (drvdata->base); +spin_unlock_irqrestore (&drvdata->spinlock, flags); +} +static const struct coresight_ops_sink etb_sink_ops = { .enable = etb_enable, .disable = etb_disable, + .alloc_buffer = etb_alloc_buffer, + .free_buffer = etb_free_buffer, + .set_buffer = etb_set_buffer, + .reset_buffer = etb_reset_buffer, + .update_buffer = etb_update_buffer, };static const struct coresight_ops etb_cs_ops = {
include/linux/coresight.h +19 -2
@@ -182,12 +182,29 @@ struct coresight_device {/** * struct coresight_ops_sink - basic operations for a sink * Operations available for sinks -* @enable: enables the sink. -* @disable: disables the sink. +* @enable: enables the sink. +* @disable: disables the sink. +* @alloc_buffer: initialises perf's ring buffer for trace collection. +* @free_buffer: release memory allocated in @get_config. +* @set_buffer: initialises buffer mechanic before a trace session. +* @reset_buffer: finalises buffer mechanic after a trace session. +* @update_buffer: update buffer pointers after a trace session. */ struct coresight_ops_sink {int (*enable)(struct coresight_device *csdev,u32 mode);void (*disable)(struct coresight_device *csdev); +void *(*alloc_buffer)(struct coresight_device *csdev,int cpu, +void **pages,int nr_pages,bool overwrite); +void (*free_buffer)(void *config); +int (*set_buffer)(struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config); +unsigned long (*reset_buffer)(struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config,bool *lost); +void (*update_buffer)(struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config); };/**
Signature · 1 line
2.1.4
Alexander Shishkin
maintainerRe: [PATCH V8 16/23] coresight: etb10: implementing AUX API
Quoted 5 lines · Mathieu Poirier
Adding an ETB10 specific AUX area operations to be used by the perf framework when events are initialised.
Part of this operation involves modeling the mmap'ed area based on the specific ways a sink buffer gathers information.
I don't mind being CC'd on the rest of the patches too, btw. :)
Quoted 15 lines
drivers/hwtracing/coresight/coresight-etb10.c +15
-0+static unsigned long etb_reset_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config,bool *lost) +{ +unsigned long size =0 ; +struct cs_buffers *buf = sink_config; + +if (buf) { +/* +* In snapshot mode ->data_size holds the new address of the +* ring buffer's head. The size itself is the whole address +* range since we want the latest information. +*/ +if (buf->snapshot) + handle->head = local_xchg(&buf->data_size,
drivers/hwtracing/coresight/coresight-etb10.c static void etb_disable(struct coresight_device *csdev) · line 367
Quoted 10 lines
drivers/hwtracing/coresight/coresight-etb10.c +10
-0+ buf->nr_pages << PAGE_SHIFT); + +/* +* Tell the tracer PMU how much we got in this run and if +* something went wrong along the way. Nobody else can use +* this cs_buffers instance until we are done. As such +* resetting parameters here and squaring off with the ring +* buffer API in the tracer PMU is fine. +*/ + *lost =local_xchg (&buf->lost,0 );
This is a thin ice, you can't really make assumptions about bool's storage size or even type, afaict.
Quoted 14 lines
drivers/hwtracing/coresight/coresight-etb10.c +14
-0+ size =local_xchg (&buf->data_size,0 ); + } + +return size; +} + +static void etb_update_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config) +{ +int i, cur; +u8 *buf_ptr; +u32 read_ptr, write_ptr, capacity; +u32 status, read_data, to_read;
drivers/hwtracing/coresight/coresight-etb10.c static void etb_disable(struct coresight_device *csdev) · line 391
Quoted 10 lines
drivers/hwtracing/coresight/coresight-etb10.c +10
-0+unsigned long flags, offset; +struct cs_buffers *buf = sink_config; +struct etb_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); + +if (!buf) +return ; + + capacity = drvdata->buffer_depth *ETB_FRAME_SIZE_WORDS ; + +spin_lock_irqsave (&drvdata->spinlock, flags);
This spinlock seems to be held over the entire readout operation, however, I can't find clear rules wrt what structures etc are serialized on it. Instead, the comment says "only one at a time pls". Same for etm's big drvdata spinlock.
Regards,
--
Alex
Re: [PATCH V8 16/23] coresight: etb10: implementing AUX API
Quoted 9 lines · Alexander Shishkin
Quoted 5 lines · Mathieu Poirier
Adding an ETB10 specific AUX area operations to be used by the perf framework when events are initialised.
Part of this operation involves modeling the mmap'ed area based on the specific ways a sink buffer gathers information.
I don't mind being CC'd on the rest of the patches too, btw. :)
Most definitely.
Quoted 21 lines
Quoted 21 lines
drivers/hwtracing/coresight/coresight-etb10.c +20
-0+static unsigned long etb_reset_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config,bool *lost) +{ +unsigned long size =0 ; +struct cs_buffers *buf = sink_config; + +if (buf) { +/* +* In snapshot mode ->data_size holds the new address of the +* ring buffer's head. The size itself is the whole address +* range since we want the latest information. +*/ +if (buf->snapshot) + handle->head =local_xchg (&buf->data_size, + buf->nr_pages <<PAGE_SHIFT ); + +/* +* Tell the tracer PMU how much we got in this run and if +* something went wrong along the way. Nobody else can use
Quoted 8 lines
drivers/hwtracing/coresight/coresight-etb10.c static void etb_disable(struct coresight_device *csdev) · line 367
Quoted 5 lines
drivers/hwtracing/coresight/coresight-etb10.c +5
-0+* this cs_buffers instance until we are done. As such +* resetting parameters here and squaring off with the ring +* buffer API in the tracer PMU is fine. +*/ + *lost =local_xchg (&buf->lost,0 );This is a thin ice, you can't really make assumptions about bool's storage size or even type, afaict.
You are theoretically correct but I wonder if the value of &buf->lost can get to a size where it won't fit in *lost... Nevertheless I'll fix it with:
*lost = !!local_xchg(&buf->lost, 0);
Quoted 22 lines
Quoted 22 lines
drivers/hwtracing/coresight/coresight-etb10.c +21
-0+ size =local_xchg (&buf->data_size,0 ); + } + +return size; +} + +static void etb_update_buffer (struct coresight_device *csdev, +struct perf_output_handle *handle, +void *sink_config) +{ +int i, cur; +u8 *buf_ptr; +u32 read_ptr, write_ptr, capacity; +u32 status, read_data, to_read; +unsigned long flags, offset; +struct cs_buffers *buf = sink_config; +struct etb_drvdata *drvdata =dev_get_drvdata (csdev->dev.parent); + +if (!buf) +return ; +
Quoted 8 lines
drivers/hwtracing/coresight/coresight-etb10.c static void etb_disable(struct coresight_device *csdev) · line 391
Quoted 3 lines
drivers/hwtracing/coresight/coresight-etb10.c +3
-0+ capacity = drvdata->buffer_depth *ETB_FRAME_SIZE_WORDS ; + +spin_lock_irqsave (&drvdata->spinlock, flags);This spinlock seems to be held over the entire readout operation, however, I can't find clear rules wrt what structures etc are serialized on it. Instead, the comment says "only one at a time pls". Same for etm's big drvdata spinlock.
That spinlock is there to serialise actions coming from sysFS. I originally added the spinlock to 'etb_update_buffer()' to guard against reading the internal RAM buffer from sysfs while a perf session is active. But after supplementing 'etb_dump()' with 'mode' awareness this spinlock it is no longer required.
Quoted 4 lines
Regards,
--
Alex
PATCH v8 17/23 coresight: updating documentation to reflect integration with perf
In reply to Mathieu PoirierAdding a new section giving information on how coresight has been integrated with the perf subsystem along with a general idea of how to control tracing from the perf tool cmd line.
--- Documentation/trace/coresight.txt | 138 ++++++++++++++++++++++++++++++++++---- 1 file changed, 124 insertions(+), 14 deletions(-)
Documentation/trace/coresight.txt +124 -14
@@ -20,13 +20,13 @@ Components are generally categorised as source, link and sinks and are "Sources" generate a compressed stream representing the processor instruction path based on tracing scenarios as configured by users. From there the stream -flows through the coresight system (via ATB bus) using links that are connecting -the emanating source to a sink(s). Sinks serve as endpoints to the coresight +flows through the Coresight system (via ATB bus) using links that are connecting +the emanating source to a sink(s). Sinks serve as endpoints to the Coresight implementation, either storing the compressed stream in a memory buffer or creating an interface to the outside world where data can be transferred to a -host without fear of filling up the onboard coresight memory buffer. +host without fear of filling up the onboard Coresight memory buffer. -At typical coresight system would look like this: +At typical Coresight system would look like this: ***************************************************************** **************************** AMBA AXI ****************************===||
@@ -83,8 +83,8 @@ While on target configuration of the components is done via the APB bus, all trace data are carried out-of-band on the ATB bus. The CTM provides a way to aggregate and distribute signals between CoreSight components. -The coresight framework provides a central point to represent, configure and -manage coresight devices on a platform. This first implementation centers on +The Coresight framework provides a central point to represent, configure and +manage Coresight devices on a platform. This first implementation centers on the basic tracing functionality, enabling components such ETM/PTM, funnel, replicator, TMC, TPIU and ETB. Future work will enable more intricate IP blocks such as STM and CTI.
@@ -129,11 +129,11 @@ expected to be added as the solution matures. Framework and implementation ---------------------------- -The coresight framework provides a central point to represent, configure and -manage coresight devices on a platform. Any coresight compliant device can +The Coresight framework provides a central point to represent, configure and +manage Coresight devices on a platform. Any Coresight compliant device can register with the framework for as long as they use the right APIs: -struct coresight_device *coresight_register(struct coresight_desc *desc); +struct Coresight_device *coresight_register(struct coresight_desc *desc); void coresight_unregister(struct coresight_device *csdev); The registering function is taking a "struct coresight_device *csdev" and
@@ -193,10 +193,120 @@ the information carried in "THIS_MODULE". How to use ---------- -Before trace collection can start, a coresight sink needs to be identify. -There is no limit on the amount of sinks (nor sources) that can be enabled at -any given moment. As a generic operation, all device pertaining to the sink -class will have an "active" entry in sysfs: +There is two ways to use the Coresight framework: 1) using the perf cmd line +tool and 2) interacting directly with the Coresight devices using the sysFS +interface. The latter will slowly be faded out as more functionality become +available from the perf cmd line tool but for the time being both are still +supported. The following sections provide details on using both methods. + +1) Using perf framework: + +Coresight tracers like ETM and PTM are represented using the Perf framework's +Performance Monitoring Unit (PMU). As such the perf framework takes charge of +controlling when tracing happens based on when the process(es) of interest are +scheduled. When configure in a system, Coresight PMUs will be listed when +queried by the perf command line tool: + +linaro at linaro-nano:~$ ./perf list pmu + +List of pre-defined events (to be used in -e): + + cs_etm// [Kernel PMU event] + +linaro at linaro-nano:~$ + +Regardless of the amount ETM/PTM IP block in a system (usually equal to the +amount of processor core), the "cs_etm" PMU will be listed only once. + +Before a trace can be configured and started a Coresight sink needs to be +selected using the sysFS method (see below). This is only temporary until +sink selection can be made from the command line tool. + +linaro at linaro-nano:~$ ls /sys/bus/coresight/devices +20010000.etb 20030000.tpiu 20040000.funnel 2201c000.ptm +2201d000.ptm 2203c000.etm 2203d000.etm 2203e000.etm replicator + +linaro at linaro-nano:~$ echo 1 > /sys/bus/coresight/devices/20010000.etb/enable_sink + +Once a sink has been selected configuring a Coresight PMU works the same way as +any other PMU. As such tracing can happen for a single CPU, a group of CPU, per +thread or a combination of those: + +linaro at linaro-nano:~$ perf record -e cs_etm// --per-thread <command> + +linaro at linaro-nano:~$ perf record -C 0,2-3 -e cs_etm// <command> + +Tracing limited to user and kernel space can also be used to narrow the amount +of collected traces: + +linaro at linaro-nano:~$ perf record -e cs_etm//u --per-thread <command> + +linaro at linaro-nano:~$ perf record -C 0,2-3 -e cs_etm//k <command> + +As of this writing two ETM/PTM specific options have are available: cycle +accurate and timestamp (please refer to the Embedded Trace Macrocell reference +manual for details on these options). By default both are disabled but using +the "cycacc" and "timestamp" mnemonic within the double '/' will see those +options configure for the upcoming trace run: + +linaro at linaro-nano:~$ perf record -e cs_etm/cycacc/ --per-thread <command> + +linaro at linaro-nano:~$ perf record -C 0,2-3 -e cs_etm/cycacc,timestamp/ <command> + +The Coresight PMUs can be configured to work in "full trace" or "snapshot" mode. +In full trace mode trace acquisition is enabled from beginning to end with trace +data being recorded continuously: + +linaro at linaro-nano:~$ perf record -e cs_etm// dd if=/dev/random of=./test.txt bs=1k count=1000 + +Since this can lead to a significant amount of data and because some devices are +limited in disk space snapshot mode can be used instead. In snapshot mode +traces are still collected in the ring buffer but not communicated to user +space. The ring buffer is allowed to wrap around, providing the latest +information before an event of interest happens. Significant events are +communicated by sending a USR2 signal to the user space command line tool. +From there the tool will stop trace collection and harvest data from the ring +buffer before re-enabling traces. Snapshot mode can be invoked using '-S' when +launching a trace collection: + +linaro at linaro-nano:~$ perf record -S -e cs_etm// dd if=/dev/random of=./test.txt bs=1k count=1000 + +Trace data collected during trace runs ends up in the "perf.data" file. Trace +configuration information necessary for trace decoding is also embedded in the +"perf.data" file. Two new headers, 'PERF_RECORD_AUXTRACE_INFO' and +'PERF_RECORD_AUXTRACE' have been added to the list of event types in order to +find out where the different sections start. + +It is worth noting that a set of metadata information exists for each tracer +that participated in a trace run. As such if 5 processors have been engaged, +5 sets of metadata will be found in the perf.data file. This is to ensure that +tracer decompression tools have all the information they need in order to +process the trace data. + +Metadata information is collected directly from the ETM/PTM management registers +using the sysFS interface. Since there is no way for the perf command line +tool to associate a CPU with a tracer, a symbolic link has been created between +the cs_etm sysFS event directory and each Coresight tracer: + +linaro at linaro-nano:~$ ls /sys/bus/event_source/devices/cs_etm +cpu0 cpu1 cpu2 cpu3 cpu4 format perf_event_mux_interval_ms +power subsystem type uevent + +linaro at linaro-nano:~$ ls /sys/bus/event_source/devices/cs_etm/cpu0/mgmt/ +etmccer etmccr etmcr etmidr etmscr etmtecr1 etmtecr2 +etmteevr etmtraceidr etmtssvr + +2) Using the sysFS interface: + +Most, if not all, configuration registers are made available to users via the +sysFS interface. Until all Coresight ETM drivers have been converted to perf, +it will also be possible to start and stop traces from sysFS. + +As with the perf method described above, a Coresight sink needs to be identify +before trace collection can commence. Using the sysFS method _only_, there is +no limit on the amount of sinks (nor sources) that can be enabled at +any given moment. As a generic operation, all devices pertaining to the sink +class will have an "enable_sink" entry in sysfs: root:/sys/bus/coresight/devices# ls replicator 20030000.tpiu 2201c000.ptm 2203c000.etm 2203e000.etm
@@ -246,7 +356,7 @@ The file cstrace.bin can be decompressed using "ptm2human", DS-5 or Trace32. Following is a DS-5 output of an experimental loop that increments a variable up to a certain value. The example is simple and yet provides a glimpse of the -wealth of possibilities that coresight provides. +wealth of possibilities that Coresight provides. Info Tracing enabled Instruction 106378866 0x8026B53C E52DE004 false PUSH {lr}
Signature · 1 line
2.1.4
PATCH v8 18/23 coresight: etm-perf: new PMU driver for ETM tracers
In reply to Mathieu PoirierPerf is a well known and used tool for performance monitoring and much more. A such it is an ideal candidate for integration with coresight based HW tracing.
This patch introduces a PMU that represent a coresight tracer to the Perf core.
--- drivers/hwtracing/coresight/Makefile | 3 +- drivers/hwtracing/coresight/coresight-etm-perf.c | 398 +++++++++++++++++++++++ drivers/hwtracing/coresight/coresight-etm-perf.h | 32 ++ drivers/hwtracing/coresight/coresight-etm3x.c | 7 + include/linux/coresight-pmu.h | 27 ++ 5 files changed, 466 insertions(+), 1 deletion(-) create mode 100644 drivers/hwtracing/coresight/coresight-etm-perf.c create mode 100644 drivers/hwtracing/coresight/coresight-etm-perf.h create mode 100644 include/linux/coresight-pmu.h
drivers/hwtracing/coresight/Makefile +2 -1
@@ -9,6 +9,7 @@ obj-$(CONFIG_CORESIGHT_SINK_ETBV10) += coresight-etb10.o obj-$(CONFIG_CORESIGHT_LINKS_AND_SINKS) += coresight-funnel.o \ coresight-replicator.o obj-$(CONFIG_CORESIGHT_SOURCE_ETM3X) += coresight-etm3x.o coresight-etm-cp14.o \ - coresight-etm3x-sysfs.o + coresight-etm3x-sysfs.o \ + coresight-etm-perf.o obj-$(CONFIG_CORESIGHT_SOURCE_ETM4X) += coresight-etm4x.o obj-$(CONFIG_CORESIGHT_QCOM_REPLICATOR) += coresight-replicator-qcom.o
drivers/hwtracing/coresight/coresight-etm-perf.c new file +398 -0
398 lines not on this page · raw message
drivers/hwtracing/coresight/coresight-etm-perf.h new file +32 -0
@@ -0,0 +1,32 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _CORESIGHT_ETM_PERF_H +#define _CORESIGHT_ETM_PERF_H + +struct coresight_device ; + +#ifdef CONFIG_CORESIGHT +int etm_perf_symlink (struct coresight_device *csdev,bool link); + +#else +static inline int etm_perf_symlink (struct coresight_device *csdev,bool link) +{return -EINVAL ; } + +#endif /* CONFIG_CORESIGHT */ + +#endif
drivers/hwtracing/coresight/coresight-etm3x.c +7 -0
@@ -35,6 +35,7 @@#include <asm/sections.h> #include "coresight-etm.h" +#include "coresight-etm-perf.h" static int boot_enable;module_param_named (boot_enable, boot_enable, int,S_IRUGO );
@@ -827,6 +828,12 @@ static int etm_probe(struct amba_device *adev, const struct amba_id *id) goto err_arch_supported; } + ret =etm_perf_symlink (drvdata->csdev, true); +if (ret) { +coresight_unregister (drvdata->csdev); + goto err_arch_supported; + } +pm_runtime_put (&adev->dev);dev_info (dev,"%s initialized\n" , (char *)id->data);
include/linux/coresight-pmu.h new file +27 -0
@@ -0,0 +1,27 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef _LINUX_CORESIGHT_PMU_H +#define _LINUX_CORESIGHT_PMU_H + +#define CORESIGHT_ETM_PMU_NAME "cs_etm" + +/* ETMv3.5/PTM's ETMCR config bit */ +#define ETM_OPT_CYCACC 12 +#define ETM_OPT_TS 28 + +#endif
Signature · 1 line
2.1.4
Alexander Shishkin
maintainerRe: [PATCH V8 18/23] coresight: etm-perf: new PMU driver for ETM tracers
drivers/hwtracing/coresight/coresight-etm-perf.c line 80
Quoted 7 lines · Mathieu Poirier
drivers/hwtracing/coresight/coresight-etm-perf.c new file +7
-0+static int etm_event_init (struct perf_event *event) +{ +if (event->attr.type != etm_pmu.type) +return -ENOENT ; + +if (event->cpu >= nr_cpu_ids) +return -EINVAL ;
perf_event_alloc() already does this. Except for this one doesn't cover the negative space.
[snip]
drivers/hwtracing/coresight/coresight-etm-perf.c line 159
Quoted 5 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +5
-0+static void etm_free_aux (void *data) +{ +struct etm_event_data *event_data = data; + +pr_err ("Queing work\n" );
Probably not pr_err().
Quoted 2 lines
(quoted diff) +2
-0+ schedule_work(&event_data->work); +}
[snip]
Quoted 7 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +7
-0+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 coresight_device *sink, *csdev =per_cpu (csdev_src, cpu); +
drivers/hwtracing/coresight/coresight-etm-perf.c line 246
Quoted 10 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +10
-0+if (!csdev) + goto fail; + +/* +* Deal with the ring buffer API and get a handle on the +* session's information. +*/ + event_data =perf_aux_output_begin (handle, event); +if (WARN_ON_ONCE (!event_data)) + goto fail;
There really shouldn't be a warning here. I understand that the 'no buffer' case is taped over by the !csdev check above, but there are other ligitimate reasons for perf_aux_output_begin() to return NULL, like no-space-left.
drivers/hwtracing/coresight/coresight-etm-perf.c line 251
Quoted 5 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +5
-0+ +/* We need a sink, no need to continue without one */ + sink =coresight_get_sink (event_data->path[cpu]); +if (!sink || !sink_ops (sink)->set_buffer) + goto fail_end_stop;
Is this possible after the coresight_build_path() things in setup_aux? Might be a better candidate for WARN_*ONCE().
drivers/hwtracing/coresight/coresight-etm-perf.c line 260
Quoted 9 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +9
-0+ +/* Configure the sink */ +if (sink_ops (sink)->set_buffer (sink, handle, + event_data->snk_config)) + goto fail_end_stop; + +/* Nothing will happen without a path */ +if (coresight_enable_path (event_data->path[cpu],CS_MODE_PERF )) + goto fail_end_stop;
I'd like to understand all the potential failures here, because it's really a good idea to keep those to a minimum for the sake of consistency. That is, if the user succeeded in creating an event, about the only good reason for the event not starting is a filled up buffer.
This is why it makes a lot of sense to keep all the coresight_build_path()/coresight_enable_path() to the .event_init() phase and let them fail early, if they should fail.
Regards,
--
Alex
Re: [PATCH V8 18/23] coresight: etm-perf: new PMU driver for ETM tracers
Quoted 12 lines · Alexander Shishkin
drivers/hwtracing/coresight/coresight-etm-perf.c line 80
Quoted 7 lines · Mathieu Poirier
drivers/hwtracing/coresight/coresight-etm-perf.c new file +7
-0+static int etm_event_init (struct perf_event *event) +{ +if (event->attr.type != etm_pmu.type) +return -ENOENT ; + +if (event->cpu >= nr_cpu_ids) +return -EINVAL ;
perf_event_alloc()already does this. Except for this one doesn't cover the negative space.
Ack
Quoted 10 lines
[snip]
drivers/hwtracing/coresight/coresight-etm-perf.c line 159
Quoted 5 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +5
-0+static void etm_free_aux (void *data) +{ +struct etm_event_data *event_data = data; + +pr_err ("Queing work\n" );Probably not
pr_err().
That's an old debug message - I've removed it already.
Quoted 20 lines
Quoted 3 lines
(quoted diff) +2
-0+ schedule_work(&event_data->work); +}[snip]
Quoted 14 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +14
-0+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 coresight_device *sink, *csdev =per_cpu (csdev_src, cpu); + +if (!csdev) + goto fail; + +/* +* Deal with the ring buffer API and get a handle on the +* session's information. +*/
Quoted 8 lines
drivers/hwtracing/coresight/coresight-etm-perf.c line 246
Quoted 3 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +3
-0+ event_data =perf_aux_output_begin (handle, event); +if (WARN_ON_ONCE (!event_data)) + goto fail;There really shouldn't be a warning here. I understand that the 'no buffer' case is taped over by the !csdev check above, but there are other ligitimate reasons for
perf_aux_output_begin()to return NULL, like no-space-left.
That's too harsh yes.
Quoted 10 lines
drivers/hwtracing/coresight/coresight-etm-perf.c line 251
Quoted 6 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +5
-0+ +/* We need a sink, no need to continue without one */ + sink =coresight_get_sink (event_data->path[cpu]); +if (!sink || !sink_ops (sink)->set_buffer) + goto fail_end_stop;Is this possible after the
coresight_build_path()things insetup_aux? Might be a better candidate for WARN_*ONCE().
Quoted 14 lines
drivers/hwtracing/coresight/coresight-etm-perf.c line 260
Quoted 9 lines
drivers/hwtracing/coresight/coresight-etm-perf.c new file +9
-0+ +/* Configure the sink */ +if (sink_ops (sink)->set_buffer (sink, handle, + event_data->snk_config)) + goto fail_end_stop; + +/* Nothing will happen without a path */ +if (coresight_enable_path (event_data->path[cpu],CS_MODE_PERF )) + goto fail_end_stop;I'd like to understand all the potential failures here, because it's really a good idea to keep those to a minimum for the sake of consistency. That is, if the user succeeded in creating an event, about the only good reason for the event not starting is a filled up buffer.
Enabling a path should fail when one or many components of that path are already enabled by an ongoing trace session. This situation is quite likely to happen since in a lot of design tracers share the link and sinks.
Quoted 4 lines
This is why it makes a lot of sense to keep all the coresight_build_path()/coresight_enable_path() to the .event_init() phase and let them fail early, if they should fail.
If we do enable enable paths in .event_init() we can't support multiple concurrent trace session (see explanation above). The ultimate design is to have a source directly connected to a sink but so far none of the coresight topologies I've seen have been wired like that.
Quoted 4 lines
Regards,
--
Alex
Alexander Shishkin
maintainerRe: [PATCH V8 18/23] coresight: etm-perf: new PMU driver for ETM tracers
Quoted 9 lines · Mathieu Poirier
Quoted 4 lines
I'd like to understand all the potential failures here, because it's really a good idea to keep those to a minimum for the sake of consistency. That is, if the user succeeded in creating an event, about the only good reason for the event not starting is a filled up buffer.
Enabling a path should fail when one or many components of that path are already enabled by an ongoing trace session. This situation is quite likely to happen since in a lot of design tracers share the link and sinks.
Yes, but provided that we don't get interference from sysfs users (which, I guess, could be blocked out while etm perf events exist), this part shouldn't fail, as nobody else should be using these links and sinks but etm events and those are safe from overlapping because of PERF_PMU_CAP_EXCLUSIVE. Or am I missing something?
Quoted 9 lines
Quoted 3 lines
This is why it makes a lot of sense to keep all the coresight_build_path()/coresight_enable_path() to the .event_init() phase and let them fail early, if they should fail.
If we do enable enable paths in .event_init() we can't support multiple concurrent trace session (see explanation above). The ultimate design is to have a source directly connected to a sink but so far none of the coresight topologies I've seen have been wired like that.
So if we call dibs on those paths early (like event_init early), in such a way that nobody but other etm events can use them, we should be ok, I think.
Regards,
--
Alex
Re: [PATCH V8 18/23] coresight: etm-perf: new PMU driver for ETM tracers
Quoted 12 lines · Alexander Shishkin
Quoted 9 lines · Mathieu Poirier
Quoted 4 lines
I'd like to understand all the potential failures here, because it's really a good idea to keep those to a minimum for the sake of consistency. That is, if the user succeeded in creating an event, about the only good reason for the event not starting is a filled up buffer.
Enabling a path should fail when one or many components of that path are already enabled by an ongoing trace session. This situation is quite likely to happen since in a lot of design tracers share the link and sinks.
Quoted 5 lines
Yes, but provided that we don't get interference from sysfs users (which, I guess, could be blocked out while etm perf events exist), this part shouldn't fail, as nobody else should be using these links and sinks but etm events and those are safe from overlapping because of
PERF_PMU_CAP_EXCLUSIVE. Or am I missing something?
Interference from sysfs are being dealt with by drvdata->mode. As such a user can't muddle with perf sessions so things are good on that front.
Reading the comment in [1], mutual exclusion rules aren't that clear to me. Perf is aware of the context and CPUs a session is slated for but has no insight on the path from source to sink. Tracing an "ls" command on CPU1 and "uname" on CPU3 might look very distinct to Perf but can easily share the same plumbing. If setting PERF_PMU_CAP_EXCLUSIVE in the PMU definition guarantees that a single session on that PMU can be active at any given time, then yes, the only cause of failutre is a buffer full condition.
[1]. http://lxr.free-electrons.com/source/kernel/events/core.c#L3608
Quoted 11 lines
Quoted 10 lines
Quoted 4 lines
This is why it makes a lot of sense to keep all the coresight_build_path()/coresight_enable_path() to the .event_init() phase and let them fail early, if they should fail.
If we do enable enable paths in .event_init() we can't support multiple concurrent trace session (see explanation above). The ultimate design is to have a source directly connected to a sink but so far none of the coresight topologies I've seen have been wired like that.
Quoted 3 lines
So if we call dibs on those paths early (like
event_initearly), in such a way that nobody but other etm events can use them, we should be ok, I think.
Elements get out of reach from sysfs as soon as a path is built, so we are already covered there.
Quoted 4 lines
Regards,
--
Alex
PATCH v8 19/23 coresight: introducing a global trace ID function
In reply to Mathieu PoirierTraceID values have to be unique for all tracers and consistent between drivers and user space. As such introducing a central function to be used whenever a traceID value is required.
The patch also account for data traceIDs, which are usually I(N) + 1.
--- drivers/hwtracing/coresight/coresight-etm3x.c | 7 ++----- include/linux/coresight-pmu.h | 12 ++++++++++++ 2 files changed, 14 insertions(+), 5 deletions(-)
drivers/hwtracing/coresight/coresight-etm3x.c +2 -5
@@ -27,6 +27,7 @@#include <linux/cpu.h> #include <linux/of.h> #include <linux/coresight.h> +#include <linux/coresight-pmu.h> #include <linux/amba/bus.h> #include <linux/seq_file.h> #include <linux/uaccess.h>
@@ -740,11 +741,7 @@ static void etm_init_arch_data(void *info)static void etm_init_trace_id (struct etm_drvdata *drvdata) { -/* -* A trace ID of value 0 is invalid, so let's start at some -* random value that fits in 7 bits and go from there. -*/ - drvdata->traceid =0x10 + drvdata->cpu; + drvdata->traceid =coresight_get_trace_id (drvdata->cpu); }static int etm_probe (struct amba_device *adev,const struct amba_id *id)
include/linux/coresight-pmu.h +12 -0
@@ -19,9 +19,21 @@#define _LINUX_CORESIGHT_PMU_H#define CORESIGHT_ETM_PMU_NAME "cs_etm" +#define CORESIGHT_ETM_PMU_SEED 0x10/* ETMv3.5/PTM's ETMCR config bit */ #define ETM_OPT_CYCACC 12#define ETM_OPT_TS 28 +static inline int coresight_get_trace_id (int cpu) +{ +/* +* A trace ID of value 0 is invalid, so let's start at some +* random value that fits in 7 bits and go from there. Since +* 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 )); +} +#endif
Signature · 1 line
2.1.4
PATCH v8 20/23 perf tools: making function set_max_cpu_num() non static
In reply to Mathieu PoirierFor memory allocation purposes, code located in other places then util/cpumap.c may want to know how many CPUs the system has.
This patch is making function set_max_cpu_num() available to other parts of the perf tool so that global variable 'max_cpu_num' gets the right value when referenced by cpu__max_cpu().
--- tools/perf/util/cpumap.c | 2 +- tools/perf/util/cpumap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)
tools/perf/util/cpumap.c +1 -1
@@ -380,7 +380,7 @@ out: }/* Determine highest possible cpu in the system for sparse allocation */ -static void set_max_cpu_num (void ) +void set_max_cpu_num (void ) {const char *mnt;char path[PATH_MAX ];
tools/perf/util/cpumap.h +1 -0
@@ -14,6 +14,7 @@ struct cpu_map {int map[]; }; +void set_max_cpu_num (void );struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void );
Signature · 1 line
2.1.4
Re: [PATCH V8 20/23] perf tools: making function set_max_cpu_num() non static
Quoted 42 lines · Mathieu Poirier
For memory allocation purposes, code located in other places then
util/cpumap.cmay want to know how many CPUs the system has.This patch is making function
set_max_cpu_num()available to other parts of the perf tool so that global variable 'max_cpu_num' gets the right value when referenced bycpu__max_cpu().Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/util/cpumap.c | 2 +- tools/perf/util/cpumap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)tools/perf/util/cpumap.c +1
-1@@ -380,7 +380,7 @@ out: }/* Determine highest possible cpu in the system for sparse allocation */ -static void set_max_cpu_num (void ) +void set_max_cpu_num (void ) {const char *mnt;char path[PATH_MAX ];tools/perf/util/cpumap.h +1
-1@@ -14,6 +14,7 @@ struct cpu_map {int map[]; }; +void set_max_cpu_num (void );struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void ); --
Quoted 2 lines
2.1.4
Arnaldo,
I can't queue this patch for 4.6 without at least a reviewed by from you.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you. The same goes for [2]
Thanks,
Mathieu
[1]. https://git.linaro.org/people/mathieu.poirier/coresight.git/shortlog/refs/heads/perf-v4.5-rc1-V8
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 20/23] perf tools: making function set_max_cpu_num() non static
Em Mon, Jan 25, 2016 at 01:46:22PM -0700, Mathieu Poirier escreveu:
Quoted 48 lines · Mathieu Poirier
Quoted 42 lines
For memory allocation purposes, code located in other places then
util/cpumap.cmay want to know how many CPUs the system has.This patch is making function
set_max_cpu_num()available to other parts of the perf tool so that global variable 'max_cpu_num' gets the right value when referenced bycpu__max_cpu().Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/util/cpumap.c | 2 +- tools/perf/util/cpumap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)tools/perf/util/cpumap.c +1
-1@@ -380,7 +380,7 @@ out: }/* Determine highest possible cpu in the system for sparse allocation */ -static void set_max_cpu_num (void ) +void set_max_cpu_num (void ) {const char *mnt;char path[PATH_MAX ];tools/perf/util/cpumap.h +1
-1@@ -14,6 +14,7 @@ struct cpu_map {int map[]; }; +void set_max_cpu_num (void );struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void ); --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 1 line
I can't queue this patch for 4.6 without at least a reviewed by from you.
This one I remember, looks ugly, the name set_max_cpu_num() looks strange, when that was restricted (static) to that cpumap.c file, it wasn't a problem, exporting it for wider usage looks bad.
You've been waiting for this for quite a while, it seems, lemme stop what I am doing to check this...
- Arnaldo
Quoted 8 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you. The same goes for [2]
Thanks,
Mathieu[1]. https://git.linaro.org/people/mathieu.poirier/coresight.git/shortlog/refs/heads/perf-v4.5-rc1-V8
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 20/23] perf tools: making function set_max_cpu_num() non static
Em Mon, Jan 25, 2016 at 06:12:42PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 49 lines
Em Mon, Jan 25, 2016 at 01:46:22PM -0700, Mathieu Poirier escreveu:
Quoted 48 lines · Mathieu Poirier
Quoted 42 lines
For memory allocation purposes, code located in other places then
util/cpumap.cmay want to know how many CPUs the system has.This patch is making function
set_max_cpu_num()available to other parts of the perf tool so that global variable 'max_cpu_num' gets the right value when referenced bycpu__max_cpu().Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/util/cpumap.c | 2 +- tools/perf/util/cpumap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)tools/perf/util/cpumap.c +1
-1@@ -380,7 +380,7 @@ out: }/* Determine highest possible cpu in the system for sparse allocation */ -static void set_max_cpu_num (void ) +void set_max_cpu_num (void ) {const char *mnt;char path[PATH_MAX ];tools/perf/util/cpumap.h +1
-1@@ -14,6 +14,7 @@ struct cpu_map {int map[]; }; +void set_max_cpu_num (void );struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void ); --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 8 lines
Quoted 1 line
I can't queue this patch for 4.6 without at least a reviewed by from you.
This one I remember, looks ugly, the name
set_max_cpu_num()looks strange, when that was restricted (static) to thatcpumap.cfile, it wasn't a problem, exporting it for wider usage looks bad.You've been waiting for this for quite a while, it seems, lemme stop what I am doing to check this...
So, please check the patch below, what you need then is just to use cpu__max_cpu().
- Arnaldo
tools/perf/util/cpumap.c +30 -0
@@ -8,6 +8,10 @@#include <linux/bitmap.h> #include "asm/bug.h" +static int max_cpu_num; +static int max_node_num; +static int *cpunode_map; +static struct cpu_map *cpu_map__default_new (void ) {struct cpu_map *cpus;
@@ -486,6 +490,32 @@ out:pr_err ("Failed to read max nodes, using default of %d\n" , max_node_num); } +int cpu__max_node (void ) +{ +if (unlikely (!max_node_num)) +set_max_node_num (); + +return max_node_num; +} + +int cpu__max_cpu (void ) +{ +if (unlikely (!max_cpu_num)) +set_max_cpu_num (); + +return max_cpu_num; +} + +int cpu__get_node (int cpu) +{ +if (unlikely (cpunode_map ==NULL )) { +pr_debug ("cpu_map not initialized\n" ); +return -1 ; + } + +return cpunode_map[cpu]; +} +static int init_cpunode_map (void ) {int i;
tools/perf/util/cpumap.h +3 -29
@@ -57,37 +57,11 @@ static inline bool cpu_map__empty(const struct cpu_map *map)return map ? map->map[0 ] ==-1 : true; } -int max_cpu_num; -int max_node_num; -int *cpunode_map; -int cpu__setup_cpunode_map (void ); -static inline int cpu__max_node (void ) -{ -if (unlikely (!max_node_num)) -pr_debug ("cpu_map not initialized\n" ); - -return max_node_num; -} - -static inline int cpu__max_cpu (void ) -{ -if (unlikely (!max_cpu_num)) -pr_debug ("cpu_map not initialized\n" ); - -return max_cpu_num; -} - -static inline int cpu__get_node (int cpu) -{ -if (unlikely (cpunode_map ==NULL )) { -pr_debug ("cpu_map not initialized\n" ); -return -1 ; - } - -return cpunode_map[cpu]; -} +int cpu__max_node (void ); +int cpu__max_cpu (void ); +int cpu__get_node (int cpu); int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, int (*f)(struct cpu_map *map, int cpu, void *data),
Re: [PATCH V8 20/23] perf tools: making function set_max_cpu_num() non static
Quoted 56 lines · Arnaldo Carvalho de Melo
Em Mon, Jan 25, 2016 at 06:12:42PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 55 lines
Em Mon, Jan 25, 2016 at 01:46:22PM -0700, Mathieu Poirier escreveu:
Quoted 48 lines · Mathieu Poirier
Quoted 42 lines
For memory allocation purposes, code located in other places then
util/cpumap.cmay want to know how many CPUs the system has.This patch is making function
set_max_cpu_num()available to other parts of the perf tool so that global variable 'max_cpu_num' gets the right value when referenced bycpu__max_cpu().Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/util/cpumap.c | 2 +- tools/perf/util/cpumap.h | 1 + 2 files changed, 2 insertions(+), 1 deletion(-)tools/perf/util/cpumap.c +1
-1@@ -380,7 +380,7 @@ out: }/* Determine highest possible cpu in the system for sparse allocation */ -static void set_max_cpu_num (void ) +void set_max_cpu_num (void ) {const char *mnt;char path[PATH_MAX ];tools/perf/util/cpumap.h +1
-1@@ -14,6 +14,7 @@ struct cpu_map {int map[]; }; +void set_max_cpu_num (void );struct cpu_map *cpu_map__new (const char *cpu_list);struct cpu_map *cpu_map__empty_new (int nr);struct cpu_map *cpu_map__dummy_new (void ); --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 1 line
I can't queue this patch for 4.6 without at least a reviewed by from you.
This one I remember, looks ugly, the name
set_max_cpu_num()looks strange, when that was restricted (static) to thatcpumap.cfile, it wasn't a problem, exporting it for wider usage looks bad.
Quoted 5 lines
Quoted 2 lines
You've been waiting for this for quite a while, it seems, lemme stop what I am doing to check this...
So, please check the patch below, what you need then is just to use
cpu__max_cpu().
I like your approach - thanks for the review. I will spin V9 when I have received Adrian's comments.
Mathieu
Quoted 96 lines
- Arnaldo
tools/perf/util/cpumap.c +30
-0@@ -8,6 +8,10 @@#include <linux/bitmap.h> #include "asm/bug.h" +static int max_cpu_num; +static int max_node_num; +static int *cpunode_map; +static struct cpu_map *cpu_map__default_new (void ) {struct cpu_map *cpus;@@ -486,6 +490,32 @@ out:pr_err ("Failed to read max nodes, using default of %d\n" , max_node_num); } +int cpu__max_node (void ) +{ +if (unlikely (!max_node_num)) +set_max_node_num (); + +return max_node_num; +} + +int cpu__max_cpu (void ) +{ +if (unlikely (!max_cpu_num)) +set_max_cpu_num (); + +return max_cpu_num; +} + +int cpu__get_node (int cpu) +{ +if (unlikely (cpunode_map ==NULL )) { +pr_debug ("cpu_map not initialized\n" ); +return -1 ; + } + +return cpunode_map[cpu]; +} +static int init_cpunode_map (void ) {int i;tools/perf/util/cpumap.h +3
-29@@ -57,37 +57,11 @@ static inline bool cpu_map__empty(const struct cpu_map *map)return map ? map->map[0 ] ==-1 : true; } -int max_cpu_num; -int max_node_num; -int *cpunode_map; -int cpu__setup_cpunode_map (void ); -static inline int cpu__max_node (void ) -{ -if (unlikely (!max_node_num)) -pr_debug ("cpu_map not initialized\n" ); - -return max_node_num; -} - -static inline int cpu__max_cpu (void ) -{ -if (unlikely (!max_cpu_num)) -pr_debug ("cpu_map not initialized\n" ); - -return max_cpu_num; -} - -static inline int cpu__get_node (int cpu) -{ -if (unlikely (cpunode_map ==NULL )) { -pr_debug ("cpu_map not initialized\n" ); -return -1 ; - } - -return cpunode_map[cpu]; -} +int cpu__max_node (void ); +int cpu__max_cpu (void ); +int cpu__get_node (int cpu); int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, int (*f)(struct cpu_map *map, int cpu, void *data),
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 20/23] perf tools: making function set_max_cpu_num() non static
Em Tue, Jan 26, 2016 at 10:08:21AM -0700, Mathieu Poirier escreveu:
Quoted 10 lines · Arnaldo Carvalho de Melo
Quoted 9 lines
Em Mon, Jan 25, 2016 at 06:12:42PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 8 lines
Em Mon, Jan 25, 2016 at 01:46:22PM -0700, Mathieu Poirier escreveu:
Quoted 2 lines · Mathieu Poirier
I can't queue this patch for 4.6 without at least a reviewed by from you.
This one I remember, looks ugly, the name
set_max_cpu_num()looks strange, when that was restricted (static) to thatcpumap.cfile, it wasn't a problem, exporting it for wider usage looks bad.
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
You've been waiting for this for quite a while, it seems, lemme stop what I am doing to check this...
So, please check the patch below, what you need then is just to use
cpu__max_cpu().I like your approach - thanks for the review. I will spin V9 when I have received Adrian's comments.
I'll take that as an Acked-by: and since this improves the current situation by hiding needlessly exported global variables, I'll get it in now, thanks.
- Arnaldo
Re: [PATCH V8 20/23] perf tools: making function set_max_cpu_num() non static
Quoted 17 lines · Arnaldo Carvalho de Melo
Em Tue, Jan 26, 2016 at 10:08:21AM -0700, Mathieu Poirier escreveu:
Quoted 16 lines · Arnaldo Carvalho de Melo
Quoted 14 lines
Em Mon, Jan 25, 2016 at 06:12:42PM -0300, Arnaldo Carvalho de Melo escreveu:
Quoted 10 lines
Em Mon, Jan 25, 2016 at 01:46:22PM -0700, Mathieu Poirier escreveu:
Quoted 2 lines · Mathieu Poirier
I can't queue this patch for 4.6 without at least a reviewed by from you.
This one I remember, looks ugly, the name
set_max_cpu_num()looks strange, when that was restricted (static) to thatcpumap.cfile, it wasn't a problem, exporting it for wider usage looks bad.You've been waiting for this for quite a while, it seems, lemme stop what I am doing to check this...
So, please check the patch below, what you need then is just to use
cpu__max_cpu().
Quoted 6 lines
Quoted 2 lines
I like your approach - thanks for the review. I will spin V9 when I have received Adrian's comments.
I'll take that as an Acked-by: and since this improves the current situation by hiding needlessly exported global variables, I'll get it in now, thanks.
I would have added this code in my patchset with the right authorship
- whatever works best for you.
Thanks,
Mathieu
Quoted 2 lines
- Arnaldo
tip-bot for Arnaldo Carvalho de Melo
merge bot[tip:perf/core] perf cpumap: Auto initialize cpu__max_{node,cpu}
In reply to Arnaldo Carvalho de Meloperf cpumap: Auto initialize cpu__max_{node,cpu}
Commit-ID: 5ac76283b32b116c58e362e99542182ddcfc8262 Gitweb: http://git.kernel.org/tip/5ac76283b32b116c58e362e99542182ddcfc8262 Author: Arnaldo Carvalho de Melo <[email protected]> AuthorDate: Tue, 26 Jan 2016 15:51:46 -0300 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Tue, 26 Jan 2016 16:08:36 -0300
perf cpumap: Auto initialize cpu__max_{node,cpu}
Since it was always checking if the initialization was done, use that branch to do the initialization if not done already.
With this we reduce the number of exported globals from these files.
--- tools/perf/util/cpumap.c | 30 ++++++++++++++++++++++++++++++ tools/perf/util/cpumap.h | 32 +++----------------------------- 2 files changed, 33 insertions(+), 29 deletions(-)
tools/perf/util/cpumap.c +30 -0
@@ -8,6 +8,10 @@#include <linux/bitmap.h> #include "asm/bug.h" +static int max_cpu_num; +static int max_node_num; +static int *cpunode_map; +static struct cpu_map *cpu_map__default_new (void ) {struct cpu_map *cpus;
@@ -486,6 +490,32 @@ out:pr_err ("Failed to read max nodes, using default of %d\n" , max_node_num); } +int cpu__max_node (void ) +{ +if (unlikely (!max_node_num)) +set_max_node_num (); + +return max_node_num; +} + +int cpu__max_cpu (void ) +{ +if (unlikely (!max_cpu_num)) +set_max_cpu_num (); + +return max_cpu_num; +} + +int cpu__get_node (int cpu) +{ +if (unlikely (cpunode_map ==NULL )) { +pr_debug ("cpu_map not initialized\n" ); +return -1 ; + } + +return cpunode_map[cpu]; +} +static int init_cpunode_map (void ) {int i;
tools/perf/util/cpumap.h +3 -29
@@ -57,37 +57,11 @@ static inline bool cpu_map__empty(const struct cpu_map *map)return map ? map->map[0 ] ==-1 : true; } -int max_cpu_num; -int max_node_num; -int *cpunode_map; -int cpu__setup_cpunode_map (void ); -static inline int cpu__max_node (void ) -{ -if (unlikely (!max_node_num)) -pr_debug ("cpu_map not initialized\n" ); - -return max_node_num; -} - -static inline int cpu__max_cpu (void ) -{ -if (unlikely (!max_cpu_num)) -pr_debug ("cpu_map not initialized\n" ); - -return max_cpu_num; -} - -static inline int cpu__get_node (int cpu) -{ -if (unlikely (cpunode_map ==NULL )) { -pr_debug ("cpu_map not initialized\n" ); -return -1 ; - } - -return cpunode_map[cpu]; -} +int cpu__max_node (void ); +int cpu__max_cpu (void ); +int cpu__get_node (int cpu); int cpu_map__build_map(struct cpu_map *cpus, struct cpu_map **res, int (*f)(struct cpu_map *map, int cpu, void *data),
PATCH v8 21/23 perf tools: adding perf_evlist to *info_priv_size()
In reply to Mathieu PoirierOn some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct perf_evlist *" parameter, which should contain all the required information.
Also adjusting the existing client of the interface to take the new parameter into account.
--- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-)
tools/perf/arch/x86/util/intel-bts.c +3 -1
@@ -60,7 +60,9 @@ struct branch {u64 misc; }; -static size_t intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_BTS_AUXTRACE_PRIV_SIZE ; }
tools/perf/arch/x86/util/intel-pt.c +3 -1
@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } -static size_t intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_PT_AUXTRACE_PRIV_SIZE ; }
tools/perf/util/auxtrace.c +4 -3
@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist) {if (itr) -return itr->info_priv_size (itr); +return itr->info_priv_size (itr, evlist);return 0 ; }
@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,int err;pr_debug2 ("Synthesizing auxtrace information\n" ); - priv_size =auxtrace_record__info_priv_size (itr); + priv_size =auxtrace_record__info_priv_size (itr, session->evlist); ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size);if (!ev)return -ENOMEM ;
tools/perf/util/auxtrace.h +4 -2
@@ -293,7 +293,8 @@ struct auxtrace_record {int (*recording_options)(struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t (*info_priv_size)(struct auxtrace_record *itr); +size_t (*info_priv_size)(struct auxtrace_record *itr, +struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,
@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,int auxtrace_record__options (struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,
Signature · 1 line
2.1.4
Re: [PATCH V8 21/23] perf tools: adding perf_evlist to *info_priv_size()
Quoted 101 lines · Mathieu Poirier
On some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct
perf_evlist*" parameter, which should contain all the required information.Also adjusting the existing client of the interface to take the new parameter into account.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-)tools/perf/arch/x86/util/intel-bts.c +3
-1@@ -60,7 +60,9 @@ struct branch {u64 misc; }; -static size_t intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_BTS_AUXTRACE_PRIV_SIZE ; }tools/perf/arch/x86/util/intel-pt.c +3
-1@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } -static size_t intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_PT_AUXTRACE_PRIV_SIZE ; }tools/perf/util/auxtrace.c +4
-3@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist) {if (itr) -return itr->info_priv_size (itr); +return itr->info_priv_size (itr, evlist);return 0 ; }@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,int err;pr_debug2 ("Synthesizing auxtrace information\n" ); - priv_size =auxtrace_record__info_priv_size (itr); + priv_size =auxtrace_record__info_priv_size (itr, session->evlist); ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size);if (!ev)return -ENOMEM ;tools/perf/util/auxtrace.h +4
-3@@ -293,7 +293,8 @@ struct auxtrace_record {int (*recording_options)(struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t (*info_priv_size)(struct auxtrace_record *itr); +size_t (*info_priv_size)(struct auxtrace_record *itr, +struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,int auxtrace_record__options (struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, --
Quoted 2 lines
2.1.4
Arnaldo,
As with my previous email, I can't queue this patch for 4.6 without at least a reviewed by from you.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Thanks,
Mathieu
[1]. https://git.linaro.org/people/mathieu.poirier/coresight.git/shortlog/refs/heads/perf-v4.5-rc1-V8
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 21/23] perf tools: adding perf_evlist to *info_priv_size()
Em Mon, Jan 25, 2016 at 01:48:28PM -0700, Mathieu Poirier escreveu:
Quoted 107 lines · Mathieu Poirier
Quoted 101 lines
On some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct
perf_evlist*" parameter, which should contain all the required information.Also adjusting the existing client of the interface to take the new parameter into account.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-)tools/perf/arch/x86/util/intel-bts.c +3
-1@@ -60,7 +60,9 @@ struct branch {u64 misc; }; -static size_t intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_BTS_AUXTRACE_PRIV_SIZE ; }tools/perf/arch/x86/util/intel-pt.c +3
-1@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } -static size_t intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_PT_AUXTRACE_PRIV_SIZE ; }tools/perf/util/auxtrace.c +4
-3@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist) {if (itr) -return itr->info_priv_size (itr); +return itr->info_priv_size (itr, evlist);return 0 ; }@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,int err;pr_debug2 ("Synthesizing auxtrace information\n" ); - priv_size =auxtrace_record__info_priv_size (itr); + priv_size =auxtrace_record__info_priv_size (itr, session->evlist); ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size);if (!ev)return -ENOMEM ;tools/perf/util/auxtrace.h +4
-3@@ -293,7 +293,8 @@ struct auxtrace_record {int (*recording_options)(struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t (*info_priv_size)(struct auxtrace_record *itr); +size_t (*info_priv_size)(struct auxtrace_record *itr, +struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,int auxtrace_record__options (struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 5 lines
As with my previous email, I can't queue this patch for 4.6 without at least a reviewed by from you.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian, are you ok with this?
- Arnaldo
Adrian Hunter
reviewerRe: [PATCH V8 21/23] perf tools: adding perf_evlist to *info_priv_size()
Quoted 108 lines · Arnaldo Carvalho de Melo
Em Mon, Jan 25, 2016 at 01:48:28PM -0700, Mathieu Poirier escreveu:
Quoted 107 lines · Mathieu Poirier
Quoted 101 lines
On some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct
perf_evlist*" parameter, which should contain all the required information.Also adjusting the existing client of the interface to take the new parameter into account.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-)tools/perf/arch/x86/util/intel-bts.c +3
-1@@ -60,7 +60,9 @@ struct branch {u64 misc; }; -static size_t intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_BTS_AUXTRACE_PRIV_SIZE ; }tools/perf/arch/x86/util/intel-pt.c +3
-1@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } -static size_t intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_PT_AUXTRACE_PRIV_SIZE ; }tools/perf/util/auxtrace.c +4
-3@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist) {if (itr) -return itr->info_priv_size (itr); +return itr->info_priv_size (itr, evlist);return 0 ; }@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,int err;pr_debug2 ("Synthesizing auxtrace information\n" ); - priv_size =auxtrace_record__info_priv_size (itr); + priv_size =auxtrace_record__info_priv_size (itr, session->evlist); ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size);if (!ev)return -ENOMEM ;tools/perf/util/auxtrace.h +4
-3@@ -293,7 +293,8 @@ struct auxtrace_record {int (*recording_options)(struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t (*info_priv_size)(struct auxtrace_record *itr); +size_t (*info_priv_size)(struct auxtrace_record *itr, +struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,int auxtrace_record__options (struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 7 lines
Quoted 5 lines
As with my previous email, I can't queue this patch for 4.6 without at least a reviewed by from you.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian, are you ok with this?
I will try to look at this and the others in the next day or two.
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 21/23] perf tools: adding perf_evlist to *info_priv_size()
Em Tue, Jan 26, 2016 at 04:27:52PM +0200, Adrian Hunter escreveu:
Quoted 9 lines · Arnaldo Carvalho de Melo
Quoted 8 lines
Em Mon, Jan 25, 2016 at 01:48:28PM -0700, Mathieu Poirier escreveu:
Quoted 7 lines · Mathieu Poirier
Quoted 1 line
On some architecture the size of the private header may
Arnaldo,
As with my previous email, I can't queue this patch for 4.6 without at least a reviewed by from you.
Quoted 7 lines
Quoted 4 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian, are you ok with this?
I will try to look at this and the others in the next day or two.
Thanks, that will help,
- Arnaldo
Re: [PATCH V8 21/23] perf tools: adding perf_evlist to *info_priv_size()
In reply to Adrian HunterQuoted 112 lines · Adrian Hunter
Quoted 111 lines · Arnaldo Carvalho de Melo
Em Mon, Jan 25, 2016 at 01:48:28PM -0700, Mathieu Poirier escreveu:
Quoted 110 lines · Mathieu Poirier
Quoted 101 lines
On some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct
perf_evlist*" parameter, which should contain all the required information.Also adjusting the existing client of the interface to take the new parameter into account.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-)tools/perf/arch/x86/util/intel-bts.c +3
-1@@ -60,7 +60,9 @@ struct branch {u64 misc; }; -static size_t intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_BTS_AUXTRACE_PRIV_SIZE ; }tools/perf/arch/x86/util/intel-pt.c +3
-1@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } -static size_t intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_PT_AUXTRACE_PRIV_SIZE ; }tools/perf/util/auxtrace.c +4
-3@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist) {if (itr) -return itr->info_priv_size (itr); +return itr->info_priv_size (itr, evlist);return 0 ; }@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,int err;pr_debug2 ("Synthesizing auxtrace information\n" ); - priv_size =auxtrace_record__info_priv_size (itr); + priv_size =auxtrace_record__info_priv_size (itr, session->evlist); ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size);if (!ev)return -ENOMEM ;tools/perf/util/auxtrace.h +4
-3@@ -293,7 +293,8 @@ struct auxtrace_record {int (*recording_options)(struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t (*info_priv_size)(struct auxtrace_record *itr); +size_t (*info_priv_size)(struct auxtrace_record *itr, +struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,int auxtrace_record__options (struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info, --Quoted 2 lines
2.1.4
Arnaldo,
As with my previous email, I can't queue this patch for 4.6 without at least a reviewed by from you.
Quoted 6 lines
Quoted 4 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian, are you ok with this?
I will try to look at this and the others in the next day or two.
tip-bot for Mathieu Poirier
merge bot[tip:perf/core] perf auxtrace: Add perf_evlist pointer to *info_priv_size()
In reply to Mathieu Poirierperf auxtrace: Add perf_evlist pointer to *info_priv_size()
Commit-ID: 14a05e13a044c1cd6aaa3eb1a5fcdad7b4f6c990 Gitweb: http://git.kernel.org/tip/14a05e13a044c1cd6aaa3eb1a5fcdad7b4f6c990 Author: Mathieu Poirier <[email protected]> AuthorDate: Thu, 14 Jan 2016 14:46:15 -0700 Committer: Arnaldo Carvalho de Melo <[email protected]> CommitDate: Fri, 29 Jan 2016 17:14:30 -0300
perf auxtrace: Add perf_evlist pointer to *info_priv_size()
On some architecture the size of the private header may be dependent on the number of tracers used in the session. As such adding a "struct perf_evlist *" parameter, which should contain all the required information.
Also adjusting the existing client of the interface to take the new parameter into account.
--- tools/perf/arch/x86/util/intel-bts.c | 4 +++- tools/perf/arch/x86/util/intel-pt.c | 4 +++- tools/perf/util/auxtrace.c | 7 ++++--- tools/perf/util/auxtrace.h | 6 ++++-- 4 files changed, 14 insertions(+), 7 deletions(-)
tools/perf/arch/x86/util/intel-bts.c +3 -1
@@ -60,7 +60,9 @@ struct branch {u64 misc; }; -static size_t intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_bts_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_BTS_AUXTRACE_PRIV_SIZE ; }
tools/perf/arch/x86/util/intel-pt.c +3 -1
@@ -273,7 +273,9 @@ intel_pt_pmu_default_config(struct perf_pmu *intel_pt_pmu)return attr; } -static size_t intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused ) +static size_t +intel_pt_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) {return INTEL_PT_AUXTRACE_PRIV_SIZE ; }
tools/perf/util/auxtrace.c +4 -3
@@ -478,10 +478,11 @@ void auxtrace_heap__pop(struct auxtrace_heap *heap) heap_array[last].ordinal); } -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr) +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist) {if (itr) -return itr->info_priv_size (itr); +return itr->info_priv_size (itr, evlist);return 0 ; }
@@ -852,7 +853,7 @@ int perf_event__synthesize_auxtrace_info(struct auxtrace_record *itr,int err;pr_debug2 ("Synthesizing auxtrace information\n" ); - priv_size =auxtrace_record__info_priv_size (itr); + priv_size =auxtrace_record__info_priv_size (itr, session->evlist); ev =zalloc (sizeof (struct auxtrace_info_event ) + priv_size);if (!ev)return -ENOMEM ;
tools/perf/util/auxtrace.h +4 -2
@@ -293,7 +293,8 @@ struct auxtrace_record {int (*recording_options)(struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t (*info_priv_size)(struct auxtrace_record *itr); +size_t (*info_priv_size)(struct auxtrace_record *itr, +struct perf_evlist *evlist); int (*info_fill)(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,
@@ -429,7 +430,8 @@ int auxtrace_parse_snapshot_options(struct auxtrace_record *itr,int auxtrace_record__options (struct auxtrace_record *itr,struct perf_evlist *evlist,struct record_opts *opts); -size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr); +size_t auxtrace_record__info_priv_size (struct auxtrace_record *itr, +struct perf_evlist *evlist); int auxtrace_record__info_fill(struct auxtrace_record *itr, struct perf_session *session, struct auxtrace_info_event *auxtrace_info,
PATCH v8 22/23 perf tools: making coresight PMU listable
In reply to Mathieu PoirierAdding the required mechanic allowing 'perf list pmu' to discover coresight ETM/PTM tracers.
--- MAINTAINERS | 1 + tools/perf/arch/arm/util/Build | 2 ++ tools/perf/arch/arm/util/pmu.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/config/Makefile | 17 ++++++++++++----- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tools/perf/arch/arm/util/pmu.c
MAINTAINERS +1 -0
@@ -1007,6 +1007,7 @@ F: drivers/hwtracing/coresight/* F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* +F: tools/perf/arch/arm/util/pmu.c ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>
tools/perf/arch/arm/util/Build +2 -0
@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o + +libperf-$(CONFIG_AUXTRACE) += pmu.o
tools/perf/arch/arm/util/pmu.c new file +34 -0
@@ -0,0 +1,34 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <linux/coresight-pmu.h> +#include <linux/perf_event.h> + +#include "../../util/pmu.h" + +struct perf_event_attr +*perf_pmu__get_default_config (struct perf_pmu *pmu__maybe_unused ) +{ +#ifdef HAVE_AUXTRACE_SUPPORT +if (!strcmp (pmu->name,CORESIGHT_ETM_PMU_NAME )) { +/* add ETM default config here */ + pmu->selectable = true; + } +#endif +return NULL ; +}
tools/perf/config/Makefile +12 -5
@@ -647,12 +647,19 @@ ifdef LIBBABELTRACE endif ifndef NO_AUXTRACE - ifeq ($(feature-get_cpuid), 0) - msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); - NO_AUXTRACE := 1 + ifeq ($(ARCH),x86) + ifeq ($(feature-get_cpuid), 0) + msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); + NO_AUXTRACE := 1 + else + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif else - $(call detected,CONFIG_AUXTRACE) - CFLAGS += -DHAVE_AUXTRACE_SUPPORT + ifeq ($(ARCH),$(filter $(ARCH), arm arm64)) + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif endif endif
Signature · 1 line
2.1.4
Re: [PATCH V8 22/23] perf tools: making coresight PMU listable
Quoted 107 lines · Mathieu Poirier
Adding the required mechanic allowing 'perf list pmu' to discover coresight ETM/PTM tracers.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 1 + tools/perf/arch/arm/util/Build | 2 ++ tools/perf/arch/arm/util/pmu.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/config/Makefile | 17 ++++++++++++----- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tools/perf/arch/arm/util/pmu.cMAINTAINERS +1
-0@@ -1007,6 +1007,7 @@ F: drivers/hwtracing/coresight/* F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* +F: tools/perf/arch/arm/util/pmu.c ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +2
-0@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o + +libperf-$(CONFIG_AUXTRACE) += pmu.otools/perf/arch/arm/util/pmu.c new file +34
-0@@ -0,0 +1,34 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <linux/coresight-pmu.h> +#include <linux/perf_event.h> + +#include "../../util/pmu.h" + +struct perf_event_attr +*perf_pmu__get_default_config (struct perf_pmu *pmu__maybe_unused ) +{ +#ifdef HAVE_AUXTRACE_SUPPORT +if (!strcmp (pmu->name,CORESIGHT_ETM_PMU_NAME )) { +/* add ETM default config here */ + pmu->selectable = true; + } +#endif +return NULL ; +}tools/perf/config/Makefile +12
-6@@ -647,12 +647,19 @@ ifdef LIBBABELTRACE endif ifndef NO_AUXTRACE - ifeq ($(feature-get_cpuid), 0) - msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); - NO_AUXTRACE := 1 + ifeq ($(ARCH),x86) + ifeq ($(feature-get_cpuid), 0) + msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); + NO_AUXTRACE := 1 + else + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif else - $(call detected,CONFIG_AUXTRACE) - CFLAGS += -DHAVE_AUXTRACE_SUPPORT + ifeq ($(ARCH),$(filter $(ARCH), arm arm64)) + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif endif endif --
Quoted 2 lines
2.1.4
Arnaldo,
This is the third (of four) patch that I can't queue without a reviewed by from you.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Thanks,
Mathieu
[1]. https://git.linaro.org/people/mathieu.poirier/coresight.git/shortlog/refs/heads/perf-v4.5-rc1-V8
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 22/23] perf tools: making coresight PMU listable
Em Mon, Jan 25, 2016 at 01:49:47PM -0700, Mathieu Poirier escreveu:
Quoted 113 lines · Mathieu Poirier
Quoted 107 lines
Adding the required mechanic allowing 'perf list pmu' to discover coresight ETM/PTM tracers.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 1 + tools/perf/arch/arm/util/Build | 2 ++ tools/perf/arch/arm/util/pmu.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/config/Makefile | 17 ++++++++++++----- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tools/perf/arch/arm/util/pmu.cMAINTAINERS +1
-0@@ -1007,6 +1007,7 @@ F: drivers/hwtracing/coresight/* F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* +F: tools/perf/arch/arm/util/pmu.c ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +2
-0@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o + +libperf-$(CONFIG_AUXTRACE) += pmu.otools/perf/arch/arm/util/pmu.c new file +34
-0@@ -0,0 +1,34 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <linux/coresight-pmu.h> +#include <linux/perf_event.h> + +#include "../../util/pmu.h" + +struct perf_event_attr +*perf_pmu__get_default_config (struct perf_pmu *pmu__maybe_unused ) +{ +#ifdef HAVE_AUXTRACE_SUPPORT +if (!strcmp (pmu->name,CORESIGHT_ETM_PMU_NAME )) { +/* add ETM default config here */ + pmu->selectable = true; + } +#endif +return NULL ; +}tools/perf/config/Makefile +12
-6@@ -647,12 +647,19 @@ ifdef LIBBABELTRACE endif ifndef NO_AUXTRACE - ifeq ($(feature-get_cpuid), 0) - msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); - NO_AUXTRACE := 1 + ifeq ($(ARCH),x86) + ifeq ($(feature-get_cpuid), 0) + msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); + NO_AUXTRACE := 1 + else + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif else - $(call detected,CONFIG_AUXTRACE) - CFLAGS += -DHAVE_AUXTRACE_SUPPORT + ifeq ($(ARCH),$(filter $(ARCH), arm arm64)) + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif endif endif --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 5 lines
This is the third (of four) patch that I can't queue without a reviewed by from you.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
Are you ok with this?
- Arnaldo
Adrian Hunter
reviewerRe: [PATCH V8 22/23] perf tools: making coresight PMU listable
Quoted 56 lines · Arnaldo Carvalho de Melo
Em Mon, Jan 25, 2016 at 01:49:47PM -0700, Mathieu Poirier escreveu:
Quoted 55 lines · Mathieu Poirier
Quoted 54 lines
Adding the required mechanic allowing 'perf list pmu' to discover coresight ETM/PTM tracers.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 1 + tools/perf/arch/arm/util/Build | 2 ++ tools/perf/arch/arm/util/pmu.c | 34 ++++++++++++++++++++++++++++++++++ tools/perf/config/Makefile | 17 ++++++++++++----- 4 files changed, 49 insertions(+), 5 deletions(-) create mode 100644 tools/perf/arch/arm/util/pmu.cMAINTAINERS +1
-0@@ -1007,6 +1007,7 @@ F: drivers/hwtracing/coresight/* F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* +F: tools/perf/arch/arm/util/pmu.c ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +2
-0@@ -2,3 +2,5 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o + +libperf-$(CONFIG_AUXTRACE) += pmu.otools/perf/arch/arm/util/pmu.c new file +11
-0@@ -0,0 +1,34 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
Quoted 8 lines
Quoted 8 lines
tools/perf/arch/arm/util/pmu.c line 19
Quoted 8 lines
tools/perf/arch/arm/util/pmu.c new file +8
-0+* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <string.h> +#include <linux/coresight-pmu.h>
Probably need to add include/linux/coresight-pmu.h it to tools/perf/MANIFEST
Quoted 33 lines
Quoted 33 lines
Quoted 33 lines
tools/perf/arch/arm/util/pmu.c new file +15
-0+#include <linux/perf_event.h> + +#include "../../util/pmu.h" + +struct perf_event_attr +*perf_pmu__get_default_config (struct perf_pmu *pmu__maybe_unused ) +{ +#ifdef HAVE_AUXTRACE_SUPPORT +if (!strcmp (pmu->name,CORESIGHT_ETM_PMU_NAME )) { +/* add ETM default config here */ + pmu->selectable = true; + } +#endif +return NULL ; +}tools/perf/config/Makefile +7
-3@@ -647,12 +647,19 @@ ifdef LIBBABELTRACE endif ifndef NO_AUXTRACE - ifeq ($(feature-get_cpuid), 0) - msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); - NO_AUXTRACE := 1 + ifeq ($(ARCH),x86) + ifeq ($(feature-get_cpuid), 0) + msg := $(warning Your gcc lacks the __get_cpuid() builtin, disables support for auxtrace/Intel PT, please install a newer gcc); + NO_AUXTRACE := 1 + else + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT
Quoted 8 lines
Quoted 8 lines
tools/perf/config/Makefile ifdef LIBBABELTRACE · line 662
Quoted 8 lines
tools/perf/config/Makefile +5
-2+ endif else - $(call detected,CONFIG_AUXTRACE) - CFLAGS += -DHAVE_AUXTRACE_SUPPORT + ifeq ($(ARCH),$(filter $(ARCH), arm arm64)) + $(call detected,CONFIG_AUXTRACE) + CFLAGS += -DHAVE_AUXTRACE_SUPPORT + endif
We still want AUXTRACE support by default, to support being able to decode a trace from one machine on any other machine, so this should not exclude HAVE_AUXTRACE_SUPPORT from every arch except x86 and arm.
Quoted 12 lines
Quoted 12 lines
Quoted 6 lines
tools/perf/config/Makefile +0
-1endif endif --2.1.4
Arnaldo,
This is the third (of four) patch that I can't queue without a reviewed by from you.
Quoted 6 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
Are you ok with this?
See comments
PATCH v8 23/23 perf tools: adding coresight etm PMU record capabilities
In reply to Mathieu PoirierCoresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.h
MAINTAINERS +3 -0
@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>
tools/perf/arch/arm/util/Build +1 -1
@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.o
tools/perf/arch/arm/util/auxtrace.c new file +54 -0
54 lines not on this page · raw message
tools/perf/arch/arm/util/cs_etm.c new file +466 -0
466 lines not on this page · raw message
tools/perf/arch/arm/util/cs_etm.h new file +44 -0
44 lines not on this page · raw message
tools/perf/util/auxtrace.c +1 -0
@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;
tools/perf/util/auxtrace.h +1 -0
@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type {
Signature · 1 line
2.1.4
Re: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Quoted 652 lines · Mathieu Poirier
Coresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.hMAINTAINERS +3
-0@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +1
-1@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.otools/perf/arch/arm/util/auxtrace.c new file +54
-0@@ -0,0 +1,54 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <linux/coresight-pmu.h> + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init (struct perf_evlist *evlist,int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct perf_evsel *evsel; +bool found_etm = false; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (evlist) { +evlist__for_each (evlist, evsel) { +if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + +if (found_etm) +return cs_etm_record_init (err); + +/* +* Clear 'err' even if we haven't found a cs_etm event - that way perf +* record can still be used even if tracers aren't present. The NULL +* return value will take care of telling the infrastructure HW tracing +* isn't available. +*/ + *err =0 ; +return NULL ; +}tools/perf/arch/arm/util/cs_etm.c new file +466
-0@@ -0,0 +1,466 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <api/fs/fs.h> +#include <linux/bitops.h> +#include <linux/coresight-pmu.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/types.h> + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include <stdlib.h> + +#define KiB (x) ((x) * 1024) +#define MiB (x) ((x) * 1024 * 1024) + +struct cs_etm_recording { +struct auxtrace_record itr; +struct perf_pmu *cs_etm_pmu; +struct perf_evlist *evlist; +bool snapshot_mode; +size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options (struct auxtrace_record *itr, +struct record_opts *opts, +const char *str) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +unsigned long long snapshot_size =0 ; +char *endptr; + +if (str) { + snapshot_size =strtoull (str, &endptr,0 ); +if (*endptr || snapshot_size >SIZE_MAX ) +return -1 ; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + +return 0 ; +} + +static int cs_etm_recording_options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evsel *evsel, *cs_etm_evsel =NULL ; +const struct cpu_map *cpus = evlist->cpus; +bool privileged = (geteuid () ==0 ||perf_event_paranoid () <0 ); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +if (cs_etm_evsel) { +pr_err ("There may be only one %s event\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + evsel->attr.freq =0 ; + evsel->attr.sample_period =1 ; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + +/* no need to continue if at least one event of interest was found */ +if (!cs_etm_evsel) +return 0 ; + +if (opts->use_clockid) { +pr_err ("Cannot use clockid (-k option) with %s\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + +/* we are in snapshot mode */ +if (opts->auxtrace_snapshot_mode) { +/* +* No size were given to '-S' or '-m,', so go with +* the default +*/ +if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages = +KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + }else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages ==UINT_MAX ) { + opts->mmap_pages =KiB (256 ) / page_size; + } + +/* +* '-m,xyz' was specified but no snapshot size, so make the +* snapshot size as big as the auxtrace mmap area. +*/ +if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t )page_size; + } + +/* +* -Sxyz was specified but no auxtrace mmap area, so make the +* auxtrace mmap area big enough to fit the requested snapshot +* size. +*/ +if (!opts->auxtrace_mmap_pages) { +size_t sz = opts->auxtrace_snapshot_size; + + sz =round_up (sz, page_size) / page_size; + opts->auxtrace_mmap_pages =roundup_pow_of_two (sz); + } + +/* Snapshost size can't be bigger than the auxtrace area */ +if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t )page_size) { +pr_err ("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n" , + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t )page_size); +return -EINVAL ; + } + +/* Something went wrong somewhere - this shouldn't happen */ +if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { +pr_err ("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n" ); +return -EINVAL ; + } + } + +/* We are in full trace mode but '-m,xyz' wasn't specified */ +if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages =KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + + } + +/* Validate auxtrace_mmap_pages provided by user */ +if (opts->auxtrace_mmap_pages) { +unsigned int max_page = (KiB (128 ) / page_size); +size_t sz = opts->auxtrace_mmap_pages * (size_t )page_size; + +if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; +pr_err ("auxtrace too big, truncating to %d\n" , + max_page); + } + +if (!is_power_of_2 (sz)) { +pr_err ("Invalid mmap size for %s: must be a power of 2\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + } + +if (opts->auxtrace_snapshot_mode) +pr_debug2 ("%s snapshot size: %zu\n" ,CORESIGHT_ETM_PMU_NAME , + opts->auxtrace_snapshot_size); + +if (cs_etm_evsel) { +/* +* To obtain the auxtrace buffer file descriptor, the auxtrace +* event must come first. +*/ +perf_evlist__to_front (evlist, cs_etm_evsel); +/* +* In the case of per-cpu mmaps, we need the CPU on the +* AUX event. +*/ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (cs_etm_evsel,CPU ); + } + +/* Add dummy event to keep tracking */ +if (opts->full_auxtrace) { +struct perf_evsel *tracking_evsel; +int err; + + err =parse_events (evlist,"dummy:u" ,NULL ); +if (err) +return err; + + tracking_evsel =perf_evlist__last (evlist); +perf_evlist__set_tracking_event (evlist, tracking_evsel); + + tracking_evsel->attr.freq =0 ; + tracking_evsel->attr.sample_period =1 ; + +/* In per-cpu case, always need the time of mmap events etc */ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (tracking_evsel,TIME ); + } + +return 0 ; +} + +static u64 cs_etm_get_config (struct auxtrace_record *itr) +{ +u64 config =0 ; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evlist *evlist = ptr->evlist; +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +/* +* Variable perf_event_attr::config is assigned to +* ETMv3/PTM. The bit fields have been made to match +* the ETMv3.5 ETRMCR register specification. See the +* PMU_FORMAT_ATTR() declarations in +* drivers/hwtracing/coresight/coresight-perf.c for +* details. +*/ + config = evsel->attr.config; +break ; + } + } + +return config; +} + +static size_t +cs_etm_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +int records; +const struct cpu_map *cpus = evlist->cpus; + +if (!cpu_map__empty (cpus)) { + records =cpu_map__nr (cpus); + goto out; + } + +set_max_cpu_num (); + records =cpu__max_cpu (); +out: +return records *CS_ETM_PRIV_SIZE ; +} + +static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX ] = { + [CS_ETM_ETMCCER ] ="mgmt/etmccer" , + [CS_ETM_ETMIDR ] ="mgmt/etmidr" , +}; + +static int cs_etm_get_metadata (int cpu,int index, +struct auxtrace_record *itr, +struct auxtrace_info_event *info) +{ +char path[PATH_MAX ]; +int offset =0 , ret =0 ; +int i, scan; +unsigned int val; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + + offset = index *CS_ETM_PRIV_MAX ; + +/* Build generic header portion */ + info->priv[offset +CS_ETM_MAGIC ] = __perf_cs_etm_magic; + info->priv[offset +CS_ETM_CPU ] = cpu; + info->priv[offset +CS_ETM_SNAPSHOT ] = ptr->snapshot_mode; + +/* Get user configurables from the session */ + info->priv[offset +CS_ETM_ETMCR ] =cs_etm_get_config (itr); + info->priv[offset +CS_ETM_ETMTRACEIDR ] =coresight_get_trace_id (cpu); + +/* Get RO metadata from sysfs */ +for (i =CS_ETM_ETMCCER ; i <CS_ETM_PRIV_MAX ; i++) { +snprintf (path,PATH_MAX ,"cpu%d/%s" , cpu, metadata_etmv3_ro[i]); + + scan =perf_pmu__scan_file (cs_etm_pmu, path,"%x" , &val); +if (scan !=1 ) { + ret = -EINVAL ; +break ; + } + + info->priv[offset + i] = val; + } + +return ret; +} + +static int cs_etm_info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +int i, nr_cpu, ret =0 ; +const struct cpu_map *cpus = session->evlist->cpus; + +if (priv_size !=cs_etm_info_priv_size (itr, session->evlist)) +return -EINVAL ; + +if (!session->evlist->nr_mmaps) +return -EINVAL ; + + auxtrace_info->type =PERF_AUXTRACE_CS_ETM ; + +/* cpu map is not empty, we have specific CPUs to work with */ +if (!cpu_map__empty (cpus)) { +for (i =0 ; i <cpu_map__nr (cpus); i++) { + ret =cs_etm_get_metadata (cpus->map[i], i, + itr, auxtrace_info); +if (ret) + goto out; + } + }else { +/* get configuration for all CPUs in the system */ + nr_cpu =cpu__max_cpu (); +for (i =0 ; i < nr_cpu; i++) { + ret =cs_etm_get_metadata (i, i, itr, auxtrace_info); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int cs_etm_find_snapshot (struct auxtrace_record *itr__maybe_unused , +int idx,struct auxtrace_mmap *mm, +unsigned char *data__maybe_unused , +u64 *head,u64 *old) +{ +pr_debug3 ("%s: mmap index %d old head %zu new head %zu size %zu\n" , + __func__, idx, (size_t )*old, (size_t )*head, mm->len); + + *old = *head; + *head += mm->len; + +return 0 ; +} + +static int cs_etm_snapshot_start (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__disable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static int cs_etm_snapshot_finish (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static u64 cs_etm_reference (struct auxtrace_record *itr__maybe_unused ) +{ +return (((u64 )rand () <<0 ) &0x00000000FFFFFFFFull ) | + (((u64 )rand () <<32 ) &0xFFFFFFFF00000000ull ); +} + +static void cs_etm_recording_free (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +free (ptr); +} + +static int cs_etm_read_finish (struct auxtrace_record *itr,int idx) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event_idx (ptr->evlist, + evsel, idx); + } + +return -EINVAL ; +} + +struct auxtrace_record *cs_etm_record_init (int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct cs_etm_recording *ptr; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (!cs_etm_pmu) { + *err = -EINVAL ; + goto out; + } + + ptr =zalloc (sizeof (struct cs_etm_recording )); +if (!ptr) { + *err = -ENOMEM ; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err =0 ; +return &ptr->itr; +out: +return NULL ; +}tools/perf/arch/arm/util/cs_etm.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +/* Beginning of header common to both ETMv3 and V4 */ +enum { +CS_ETM_MAGIC , +CS_ETM_CPU , +CS_ETM_SNAPSHOT , +}; + +/* ETMv3/PTM metadata */ +enum { +/* Dynamic, configurable parameters */ +CS_ETM_ETMCR =CS_ETM_SNAPSHOT +1 , +CS_ETM_ETMTRACEIDR , +/* RO, taken from sysFS */ +CS_ETM_ETMCCER , +CS_ETM_ETMIDR , +CS_ETM_PRIV_MAX , +}; + +static const u64 __perf_cs_etm_magic =0x3030303030303030ULL ; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init (int *err); + +#endif tools/perf/util/auxtrace.c +1
-0@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;tools/perf/util/auxtrace.h +1
-1@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type { --
Quoted 2 lines
2.1.4
Arnaldo,
Last but not least, this is the final patch that I would like you to review before queing.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Thanks,
Mathieu
[1]. https://git.linaro.org/people/mathieu.poirier/coresight.git/shortlog/refs/heads/perf-v4.5-rc1-V8
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Em Mon, Jan 25, 2016 at 01:51:18PM -0700, Mathieu Poirier escreveu:
Quoted 658 lines · Mathieu Poirier
Quoted 652 lines
Coresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.hMAINTAINERS +3
-0@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +1
-1@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.otools/perf/arch/arm/util/auxtrace.c new file +54
-0@@ -0,0 +1,54 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <linux/coresight-pmu.h> + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init (struct perf_evlist *evlist,int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct perf_evsel *evsel; +bool found_etm = false; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (evlist) { +evlist__for_each (evlist, evsel) { +if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + +if (found_etm) +return cs_etm_record_init (err); + +/* +* Clear 'err' even if we haven't found a cs_etm event - that way perf +* record can still be used even if tracers aren't present. The NULL +* return value will take care of telling the infrastructure HW tracing +* isn't available. +*/ + *err =0 ; +return NULL ; +}tools/perf/arch/arm/util/cs_etm.c new file +466
-0@@ -0,0 +1,466 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <api/fs/fs.h> +#include <linux/bitops.h> +#include <linux/coresight-pmu.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/types.h> + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include <stdlib.h> + +#define KiB (x) ((x) * 1024) +#define MiB (x) ((x) * 1024 * 1024) + +struct cs_etm_recording { +struct auxtrace_record itr; +struct perf_pmu *cs_etm_pmu; +struct perf_evlist *evlist; +bool snapshot_mode; +size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options (struct auxtrace_record *itr, +struct record_opts *opts, +const char *str) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +unsigned long long snapshot_size =0 ; +char *endptr; + +if (str) { + snapshot_size =strtoull (str, &endptr,0 ); +if (*endptr || snapshot_size >SIZE_MAX ) +return -1 ; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + +return 0 ; +} + +static int cs_etm_recording_options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evsel *evsel, *cs_etm_evsel =NULL ; +const struct cpu_map *cpus = evlist->cpus; +bool privileged = (geteuid () ==0 ||perf_event_paranoid () <0 ); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +if (cs_etm_evsel) { +pr_err ("There may be only one %s event\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + evsel->attr.freq =0 ; + evsel->attr.sample_period =1 ; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + +/* no need to continue if at least one event of interest was found */ +if (!cs_etm_evsel) +return 0 ; + +if (opts->use_clockid) { +pr_err ("Cannot use clockid (-k option) with %s\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + +/* we are in snapshot mode */ +if (opts->auxtrace_snapshot_mode) { +/* +* No size were given to '-S' or '-m,', so go with +* the default +*/ +if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages = +KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + }else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages ==UINT_MAX ) { + opts->mmap_pages =KiB (256 ) / page_size; + } + +/* +* '-m,xyz' was specified but no snapshot size, so make the +* snapshot size as big as the auxtrace mmap area. +*/ +if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t )page_size; + } + +/* +* -Sxyz was specified but no auxtrace mmap area, so make the +* auxtrace mmap area big enough to fit the requested snapshot +* size. +*/ +if (!opts->auxtrace_mmap_pages) { +size_t sz = opts->auxtrace_snapshot_size; + + sz =round_up (sz, page_size) / page_size; + opts->auxtrace_mmap_pages =roundup_pow_of_two (sz); + } + +/* Snapshost size can't be bigger than the auxtrace area */ +if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t )page_size) { +pr_err ("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n" , + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t )page_size); +return -EINVAL ; + } + +/* Something went wrong somewhere - this shouldn't happen */ +if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { +pr_err ("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n" ); +return -EINVAL ; + } + } + +/* We are in full trace mode but '-m,xyz' wasn't specified */ +if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages =KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + + } + +/* Validate auxtrace_mmap_pages provided by user */ +if (opts->auxtrace_mmap_pages) { +unsigned int max_page = (KiB (128 ) / page_size); +size_t sz = opts->auxtrace_mmap_pages * (size_t )page_size; + +if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; +pr_err ("auxtrace too big, truncating to %d\n" , + max_page); + } + +if (!is_power_of_2 (sz)) { +pr_err ("Invalid mmap size for %s: must be a power of 2\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + } + +if (opts->auxtrace_snapshot_mode) +pr_debug2 ("%s snapshot size: %zu\n" ,CORESIGHT_ETM_PMU_NAME , + opts->auxtrace_snapshot_size); + +if (cs_etm_evsel) { +/* +* To obtain the auxtrace buffer file descriptor, the auxtrace +* event must come first. +*/ +perf_evlist__to_front (evlist, cs_etm_evsel); +/* +* In the case of per-cpu mmaps, we need the CPU on the +* AUX event. +*/ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (cs_etm_evsel,CPU ); + } + +/* Add dummy event to keep tracking */ +if (opts->full_auxtrace) { +struct perf_evsel *tracking_evsel; +int err; + + err =parse_events (evlist,"dummy:u" ,NULL ); +if (err) +return err; + + tracking_evsel =perf_evlist__last (evlist); +perf_evlist__set_tracking_event (evlist, tracking_evsel); + + tracking_evsel->attr.freq =0 ; + tracking_evsel->attr.sample_period =1 ; + +/* In per-cpu case, always need the time of mmap events etc */ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (tracking_evsel,TIME ); + } + +return 0 ; +} + +static u64 cs_etm_get_config (struct auxtrace_record *itr) +{ +u64 config =0 ; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evlist *evlist = ptr->evlist; +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +/* +* Variable perf_event_attr::config is assigned to +* ETMv3/PTM. The bit fields have been made to match +* the ETMv3.5 ETRMCR register specification. See the +* PMU_FORMAT_ATTR() declarations in +* drivers/hwtracing/coresight/coresight-perf.c for +* details. +*/ + config = evsel->attr.config; +break ; + } + } + +return config; +} + +static size_t +cs_etm_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +int records; +const struct cpu_map *cpus = evlist->cpus; + +if (!cpu_map__empty (cpus)) { + records =cpu_map__nr (cpus); + goto out; + } + +set_max_cpu_num (); + records =cpu__max_cpu (); +out: +return records *CS_ETM_PRIV_SIZE ; +} + +static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX ] = { + [CS_ETM_ETMCCER ] ="mgmt/etmccer" , + [CS_ETM_ETMIDR ] ="mgmt/etmidr" , +}; + +static int cs_etm_get_metadata (int cpu,int index, +struct auxtrace_record *itr, +struct auxtrace_info_event *info) +{ +char path[PATH_MAX ]; +int offset =0 , ret =0 ; +int i, scan; +unsigned int val; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + + offset = index *CS_ETM_PRIV_MAX ; + +/* Build generic header portion */ + info->priv[offset +CS_ETM_MAGIC ] = __perf_cs_etm_magic; + info->priv[offset +CS_ETM_CPU ] = cpu; + info->priv[offset +CS_ETM_SNAPSHOT ] = ptr->snapshot_mode; + +/* Get user configurables from the session */ + info->priv[offset +CS_ETM_ETMCR ] =cs_etm_get_config (itr); + info->priv[offset +CS_ETM_ETMTRACEIDR ] =coresight_get_trace_id (cpu); + +/* Get RO metadata from sysfs */ +for (i =CS_ETM_ETMCCER ; i <CS_ETM_PRIV_MAX ; i++) { +snprintf (path,PATH_MAX ,"cpu%d/%s" , cpu, metadata_etmv3_ro[i]); + + scan =perf_pmu__scan_file (cs_etm_pmu, path,"%x" , &val); +if (scan !=1 ) { + ret = -EINVAL ; +break ; + } + + info->priv[offset + i] = val; + } + +return ret; +} + +static int cs_etm_info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +int i, nr_cpu, ret =0 ; +const struct cpu_map *cpus = session->evlist->cpus; + +if (priv_size !=cs_etm_info_priv_size (itr, session->evlist)) +return -EINVAL ; + +if (!session->evlist->nr_mmaps) +return -EINVAL ; + + auxtrace_info->type =PERF_AUXTRACE_CS_ETM ; + +/* cpu map is not empty, we have specific CPUs to work with */ +if (!cpu_map__empty (cpus)) { +for (i =0 ; i <cpu_map__nr (cpus); i++) { + ret =cs_etm_get_metadata (cpus->map[i], i, + itr, auxtrace_info); +if (ret) + goto out; + } + }else { +/* get configuration for all CPUs in the system */ + nr_cpu =cpu__max_cpu (); +for (i =0 ; i < nr_cpu; i++) { + ret =cs_etm_get_metadata (i, i, itr, auxtrace_info); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int cs_etm_find_snapshot (struct auxtrace_record *itr__maybe_unused , +int idx,struct auxtrace_mmap *mm, +unsigned char *data__maybe_unused , +u64 *head,u64 *old) +{ +pr_debug3 ("%s: mmap index %d old head %zu new head %zu size %zu\n" , + __func__, idx, (size_t )*old, (size_t )*head, mm->len); + + *old = *head; + *head += mm->len; + +return 0 ; +} + +static int cs_etm_snapshot_start (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__disable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static int cs_etm_snapshot_finish (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static u64 cs_etm_reference (struct auxtrace_record *itr__maybe_unused ) +{ +return (((u64 )rand () <<0 ) &0x00000000FFFFFFFFull ) | + (((u64 )rand () <<32 ) &0xFFFFFFFF00000000ull ); +} + +static void cs_etm_recording_free (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +free (ptr); +} + +static int cs_etm_read_finish (struct auxtrace_record *itr,int idx) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event_idx (ptr->evlist, + evsel, idx); + } + +return -EINVAL ; +} + +struct auxtrace_record *cs_etm_record_init (int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct cs_etm_recording *ptr; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (!cs_etm_pmu) { + *err = -EINVAL ; + goto out; + } + + ptr =zalloc (sizeof (struct cs_etm_recording )); +if (!ptr) { + *err = -ENOMEM ; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err =0 ; +return &ptr->itr; +out: +return NULL ; +}tools/perf/arch/arm/util/cs_etm.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +/* Beginning of header common to both ETMv3 and V4 */ +enum { +CS_ETM_MAGIC , +CS_ETM_CPU , +CS_ETM_SNAPSHOT , +}; + +/* ETMv3/PTM metadata */ +enum { +/* Dynamic, configurable parameters */ +CS_ETM_ETMCR =CS_ETM_SNAPSHOT +1 , +CS_ETM_ETMTRACEIDR , +/* RO, taken from sysFS */ +CS_ETM_ETMCCER , +CS_ETM_ETMIDR , +CS_ETM_PRIV_MAX , +}; + +static const u64 __perf_cs_etm_magic =0x3030303030303030ULL ; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init (int *err); + +#endif tools/perf/util/auxtrace.c +1
-0@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;tools/perf/util/auxtrace.h +1
-1@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type { --Quoted 2 lines
2.1.4
Arnaldo,
Quoted 5 lines
Last but not least, this is the final patch that I would like you to review before queing.
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
One more, are you ok with this?
- Arnaldo
Re: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Quoted 662 lines · Arnaldo Carvalho de Melo
Em Mon, Jan 25, 2016 at 01:51:18PM -0700, Mathieu Poirier escreveu:
Quoted 661 lines · Mathieu Poirier
Quoted 652 lines
Coresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.hMAINTAINERS +3
-0@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +1
-1@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.otools/perf/arch/arm/util/auxtrace.c new file +54
-0@@ -0,0 +1,54 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <linux/coresight-pmu.h> + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init (struct perf_evlist *evlist,int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct perf_evsel *evsel; +bool found_etm = false; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (evlist) { +evlist__for_each (evlist, evsel) { +if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + +if (found_etm) +return cs_etm_record_init (err); + +/* +* Clear 'err' even if we haven't found a cs_etm event - that way perf +* record can still be used even if tracers aren't present. The NULL +* return value will take care of telling the infrastructure HW tracing +* isn't available. +*/ + *err =0 ; +return NULL ; +}tools/perf/arch/arm/util/cs_etm.c new file +466
-0@@ -0,0 +1,466 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <api/fs/fs.h> +#include <linux/bitops.h> +#include <linux/coresight-pmu.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/types.h> + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include <stdlib.h> + +#define KiB (x) ((x) * 1024) +#define MiB (x) ((x) * 1024 * 1024) + +struct cs_etm_recording { +struct auxtrace_record itr; +struct perf_pmu *cs_etm_pmu; +struct perf_evlist *evlist; +bool snapshot_mode; +size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options (struct auxtrace_record *itr, +struct record_opts *opts, +const char *str) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +unsigned long long snapshot_size =0 ; +char *endptr; + +if (str) { + snapshot_size =strtoull (str, &endptr,0 ); +if (*endptr || snapshot_size >SIZE_MAX ) +return -1 ; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + +return 0 ; +} + +static int cs_etm_recording_options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evsel *evsel, *cs_etm_evsel =NULL ; +const struct cpu_map *cpus = evlist->cpus; +bool privileged = (geteuid () ==0 ||perf_event_paranoid () <0 ); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +if (cs_etm_evsel) { +pr_err ("There may be only one %s event\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + evsel->attr.freq =0 ; + evsel->attr.sample_period =1 ; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + +/* no need to continue if at least one event of interest was found */ +if (!cs_etm_evsel) +return 0 ; + +if (opts->use_clockid) { +pr_err ("Cannot use clockid (-k option) with %s\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + +/* we are in snapshot mode */ +if (opts->auxtrace_snapshot_mode) { +/* +* No size were given to '-S' or '-m,', so go with +* the default +*/ +if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages = +KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + }else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages ==UINT_MAX ) { + opts->mmap_pages =KiB (256 ) / page_size; + } + +/* +* '-m,xyz' was specified but no snapshot size, so make the +* snapshot size as big as the auxtrace mmap area. +*/ +if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t )page_size; + } + +/* +* -Sxyz was specified but no auxtrace mmap area, so make the +* auxtrace mmap area big enough to fit the requested snapshot +* size. +*/ +if (!opts->auxtrace_mmap_pages) { +size_t sz = opts->auxtrace_snapshot_size; + + sz =round_up (sz, page_size) / page_size; + opts->auxtrace_mmap_pages =roundup_pow_of_two (sz); + } + +/* Snapshost size can't be bigger than the auxtrace area */ +if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t )page_size) { +pr_err ("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n" , + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t )page_size); +return -EINVAL ; + } + +/* Something went wrong somewhere - this shouldn't happen */ +if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { +pr_err ("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n" ); +return -EINVAL ; + } + } + +/* We are in full trace mode but '-m,xyz' wasn't specified */ +if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages =KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + + } + +/* Validate auxtrace_mmap_pages provided by user */ +if (opts->auxtrace_mmap_pages) { +unsigned int max_page = (KiB (128 ) / page_size); +size_t sz = opts->auxtrace_mmap_pages * (size_t )page_size; + +if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; +pr_err ("auxtrace too big, truncating to %d\n" , + max_page); + } + +if (!is_power_of_2 (sz)) { +pr_err ("Invalid mmap size for %s: must be a power of 2\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + } + +if (opts->auxtrace_snapshot_mode) +pr_debug2 ("%s snapshot size: %zu\n" ,CORESIGHT_ETM_PMU_NAME , + opts->auxtrace_snapshot_size); + +if (cs_etm_evsel) { +/* +* To obtain the auxtrace buffer file descriptor, the auxtrace +* event must come first. +*/ +perf_evlist__to_front (evlist, cs_etm_evsel); +/* +* In the case of per-cpu mmaps, we need the CPU on the +* AUX event. +*/ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (cs_etm_evsel,CPU ); + } + +/* Add dummy event to keep tracking */ +if (opts->full_auxtrace) { +struct perf_evsel *tracking_evsel; +int err; + + err =parse_events (evlist,"dummy:u" ,NULL ); +if (err) +return err; + + tracking_evsel =perf_evlist__last (evlist); +perf_evlist__set_tracking_event (evlist, tracking_evsel); + + tracking_evsel->attr.freq =0 ; + tracking_evsel->attr.sample_period =1 ; + +/* In per-cpu case, always need the time of mmap events etc */ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (tracking_evsel,TIME ); + } + +return 0 ; +} + +static u64 cs_etm_get_config (struct auxtrace_record *itr) +{ +u64 config =0 ; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evlist *evlist = ptr->evlist; +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +/* +* Variable perf_event_attr::config is assigned to +* ETMv3/PTM. The bit fields have been made to match +* the ETMv3.5 ETRMCR register specification. See the +* PMU_FORMAT_ATTR() declarations in +* drivers/hwtracing/coresight/coresight-perf.c for +* details. +*/ + config = evsel->attr.config; +break ; + } + } + +return config; +} + +static size_t +cs_etm_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +int records; +const struct cpu_map *cpus = evlist->cpus; + +if (!cpu_map__empty (cpus)) { + records =cpu_map__nr (cpus); + goto out; + } + +set_max_cpu_num (); + records =cpu__max_cpu (); +out: +return records *CS_ETM_PRIV_SIZE ; +} + +static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX ] = { + [CS_ETM_ETMCCER ] ="mgmt/etmccer" , + [CS_ETM_ETMIDR ] ="mgmt/etmidr" , +}; + +static int cs_etm_get_metadata (int cpu,int index, +struct auxtrace_record *itr, +struct auxtrace_info_event *info) +{ +char path[PATH_MAX ]; +int offset =0 , ret =0 ; +int i, scan; +unsigned int val; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + + offset = index *CS_ETM_PRIV_MAX ; + +/* Build generic header portion */ + info->priv[offset +CS_ETM_MAGIC ] = __perf_cs_etm_magic; + info->priv[offset +CS_ETM_CPU ] = cpu; + info->priv[offset +CS_ETM_SNAPSHOT ] = ptr->snapshot_mode; + +/* Get user configurables from the session */ + info->priv[offset +CS_ETM_ETMCR ] =cs_etm_get_config (itr); + info->priv[offset +CS_ETM_ETMTRACEIDR ] =coresight_get_trace_id (cpu); + +/* Get RO metadata from sysfs */ +for (i =CS_ETM_ETMCCER ; i <CS_ETM_PRIV_MAX ; i++) { +snprintf (path,PATH_MAX ,"cpu%d/%s" , cpu, metadata_etmv3_ro[i]); + + scan =perf_pmu__scan_file (cs_etm_pmu, path,"%x" , &val); +if (scan !=1 ) { + ret = -EINVAL ; +break ; + } + + info->priv[offset + i] = val; + } + +return ret; +} + +static int cs_etm_info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +int i, nr_cpu, ret =0 ; +const struct cpu_map *cpus = session->evlist->cpus; + +if (priv_size !=cs_etm_info_priv_size (itr, session->evlist)) +return -EINVAL ; + +if (!session->evlist->nr_mmaps) +return -EINVAL ; + + auxtrace_info->type =PERF_AUXTRACE_CS_ETM ; + +/* cpu map is not empty, we have specific CPUs to work with */ +if (!cpu_map__empty (cpus)) { +for (i =0 ; i <cpu_map__nr (cpus); i++) { + ret =cs_etm_get_metadata (cpus->map[i], i, + itr, auxtrace_info); +if (ret) + goto out; + } + }else { +/* get configuration for all CPUs in the system */ + nr_cpu =cpu__max_cpu (); +for (i =0 ; i < nr_cpu; i++) { + ret =cs_etm_get_metadata (i, i, itr, auxtrace_info); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int cs_etm_find_snapshot (struct auxtrace_record *itr__maybe_unused , +int idx,struct auxtrace_mmap *mm, +unsigned char *data__maybe_unused , +u64 *head,u64 *old) +{ +pr_debug3 ("%s: mmap index %d old head %zu new head %zu size %zu\n" , + __func__, idx, (size_t )*old, (size_t )*head, mm->len); + + *old = *head; + *head += mm->len; + +return 0 ; +} + +static int cs_etm_snapshot_start (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__disable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static int cs_etm_snapshot_finish (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static u64 cs_etm_reference (struct auxtrace_record *itr__maybe_unused ) +{ +return (((u64 )rand () <<0 ) &0x00000000FFFFFFFFull ) | + (((u64 )rand () <<32 ) &0xFFFFFFFF00000000ull ); +} + +static void cs_etm_recording_free (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +free (ptr); +} + +static int cs_etm_read_finish (struct auxtrace_record *itr,int idx) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event_idx (ptr->evlist, + evsel, idx); + } + +return -EINVAL ; +} + +struct auxtrace_record *cs_etm_record_init (int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct cs_etm_recording *ptr; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (!cs_etm_pmu) { + *err = -EINVAL ; + goto out; + } + + ptr =zalloc (sizeof (struct cs_etm_recording )); +if (!ptr) { + *err = -ENOMEM ; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err =0 ; +return &ptr->itr; +out: +return NULL ; +}tools/perf/arch/arm/util/cs_etm.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +/* Beginning of header common to both ETMv3 and V4 */ +enum { +CS_ETM_MAGIC , +CS_ETM_CPU , +CS_ETM_SNAPSHOT , +}; + +/* ETMv3/PTM metadata */ +enum { +/* Dynamic, configurable parameters */ +CS_ETM_ETMCR =CS_ETM_SNAPSHOT +1 , +CS_ETM_ETMTRACEIDR , +/* RO, taken from sysFS */ +CS_ETM_ETMCCER , +CS_ETM_ETMIDR , +CS_ETM_PRIV_MAX , +}; + +static const u64 __perf_cs_etm_magic =0x3030303030303030ULL ; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init (int *err); + +#endif tools/perf/util/auxtrace.c +1
-0@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;tools/perf/util/auxtrace.h +1
-1@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type { --Quoted 2 lines
2.1.4
Arnaldo,
Last but not least, this is the final patch that I would like you to review before queing.
Quoted 6 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
One more, are you ok with this?
Looks OK, apart from adding linux/coresight-pmu.h to the manifest, but I mentioned that on another patch.
However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
Nevertheless, for what is there now:
Re: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Quoted 670 lines · Adrian Hunter
Quoted 662 lines · Arnaldo Carvalho de Melo
Em Mon, Jan 25, 2016 at 01:51:18PM -0700, Mathieu Poirier escreveu:
Quoted 661 lines · Mathieu Poirier
Quoted 652 lines
Coresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.hMAINTAINERS +3
-0@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +1
-1@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.otools/perf/arch/arm/util/auxtrace.c new file +54
-0@@ -0,0 +1,54 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <linux/coresight-pmu.h> + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init (struct perf_evlist *evlist,int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct perf_evsel *evsel; +bool found_etm = false; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (evlist) { +evlist__for_each (evlist, evsel) { +if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + +if (found_etm) +return cs_etm_record_init (err); + +/* +* Clear 'err' even if we haven't found a cs_etm event - that way perf +* record can still be used even if tracers aren't present. The NULL +* return value will take care of telling the infrastructure HW tracing +* isn't available. +*/ + *err =0 ; +return NULL ; +}tools/perf/arch/arm/util/cs_etm.c new file +466
-0@@ -0,0 +1,466 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <api/fs/fs.h> +#include <linux/bitops.h> +#include <linux/coresight-pmu.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/types.h> + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include <stdlib.h> + +#define KiB (x) ((x) * 1024) +#define MiB (x) ((x) * 1024 * 1024) + +struct cs_etm_recording { +struct auxtrace_record itr; +struct perf_pmu *cs_etm_pmu; +struct perf_evlist *evlist; +bool snapshot_mode; +size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options (struct auxtrace_record *itr, +struct record_opts *opts, +const char *str) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +unsigned long long snapshot_size =0 ; +char *endptr; + +if (str) { + snapshot_size =strtoull (str, &endptr,0 ); +if (*endptr || snapshot_size >SIZE_MAX ) +return -1 ; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + +return 0 ; +} + +static int cs_etm_recording_options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evsel *evsel, *cs_etm_evsel =NULL ; +const struct cpu_map *cpus = evlist->cpus; +bool privileged = (geteuid () ==0 ||perf_event_paranoid () <0 ); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +if (cs_etm_evsel) { +pr_err ("There may be only one %s event\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + evsel->attr.freq =0 ; + evsel->attr.sample_period =1 ; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + +/* no need to continue if at least one event of interest was found */ +if (!cs_etm_evsel) +return 0 ; + +if (opts->use_clockid) { +pr_err ("Cannot use clockid (-k option) with %s\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + +/* we are in snapshot mode */ +if (opts->auxtrace_snapshot_mode) { +/* +* No size were given to '-S' or '-m,', so go with +* the default +*/ +if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages = +KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + }else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages ==UINT_MAX ) { + opts->mmap_pages =KiB (256 ) / page_size; + } + +/* +* '-m,xyz' was specified but no snapshot size, so make the +* snapshot size as big as the auxtrace mmap area. +*/ +if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t )page_size; + } + +/* +* -Sxyz was specified but no auxtrace mmap area, so make the +* auxtrace mmap area big enough to fit the requested snapshot +* size. +*/ +if (!opts->auxtrace_mmap_pages) { +size_t sz = opts->auxtrace_snapshot_size; + + sz =round_up (sz, page_size) / page_size; + opts->auxtrace_mmap_pages =roundup_pow_of_two (sz); + } + +/* Snapshost size can't be bigger than the auxtrace area */ +if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t )page_size) { +pr_err ("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n" , + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t )page_size); +return -EINVAL ; + } + +/* Something went wrong somewhere - this shouldn't happen */ +if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { +pr_err ("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n" ); +return -EINVAL ; + } + } + +/* We are in full trace mode but '-m,xyz' wasn't specified */ +if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages =KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + + } + +/* Validate auxtrace_mmap_pages provided by user */ +if (opts->auxtrace_mmap_pages) { +unsigned int max_page = (KiB (128 ) / page_size); +size_t sz = opts->auxtrace_mmap_pages * (size_t )page_size; + +if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; +pr_err ("auxtrace too big, truncating to %d\n" , + max_page); + } + +if (!is_power_of_2 (sz)) { +pr_err ("Invalid mmap size for %s: must be a power of 2\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + } + +if (opts->auxtrace_snapshot_mode) +pr_debug2 ("%s snapshot size: %zu\n" ,CORESIGHT_ETM_PMU_NAME , + opts->auxtrace_snapshot_size); + +if (cs_etm_evsel) { +/* +* To obtain the auxtrace buffer file descriptor, the auxtrace +* event must come first. +*/ +perf_evlist__to_front (evlist, cs_etm_evsel); +/* +* In the case of per-cpu mmaps, we need the CPU on the +* AUX event. +*/ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (cs_etm_evsel,CPU ); + } + +/* Add dummy event to keep tracking */ +if (opts->full_auxtrace) { +struct perf_evsel *tracking_evsel; +int err; + + err =parse_events (evlist,"dummy:u" ,NULL ); +if (err) +return err; + + tracking_evsel =perf_evlist__last (evlist); +perf_evlist__set_tracking_event (evlist, tracking_evsel); + + tracking_evsel->attr.freq =0 ; + tracking_evsel->attr.sample_period =1 ; + +/* In per-cpu case, always need the time of mmap events etc */ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (tracking_evsel,TIME ); + } + +return 0 ; +} + +static u64 cs_etm_get_config (struct auxtrace_record *itr) +{ +u64 config =0 ; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evlist *evlist = ptr->evlist; +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +/* +* Variable perf_event_attr::config is assigned to +* ETMv3/PTM. The bit fields have been made to match +* the ETMv3.5 ETRMCR register specification. See the +* PMU_FORMAT_ATTR() declarations in +* drivers/hwtracing/coresight/coresight-perf.c for +* details. +*/ + config = evsel->attr.config; +break ; + } + } + +return config; +} + +static size_t +cs_etm_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +int records; +const struct cpu_map *cpus = evlist->cpus; + +if (!cpu_map__empty (cpus)) { + records =cpu_map__nr (cpus); + goto out; + } + +set_max_cpu_num (); + records =cpu__max_cpu (); +out: +return records *CS_ETM_PRIV_SIZE ; +} + +static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX ] = { + [CS_ETM_ETMCCER ] ="mgmt/etmccer" , + [CS_ETM_ETMIDR ] ="mgmt/etmidr" , +}; + +static int cs_etm_get_metadata (int cpu,int index, +struct auxtrace_record *itr, +struct auxtrace_info_event *info) +{ +char path[PATH_MAX ]; +int offset =0 , ret =0 ; +int i, scan; +unsigned int val; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + + offset = index *CS_ETM_PRIV_MAX ; + +/* Build generic header portion */ + info->priv[offset +CS_ETM_MAGIC ] = __perf_cs_etm_magic; + info->priv[offset +CS_ETM_CPU ] = cpu; + info->priv[offset +CS_ETM_SNAPSHOT ] = ptr->snapshot_mode; + +/* Get user configurables from the session */ + info->priv[offset +CS_ETM_ETMCR ] =cs_etm_get_config (itr); + info->priv[offset +CS_ETM_ETMTRACEIDR ] =coresight_get_trace_id (cpu); + +/* Get RO metadata from sysfs */ +for (i =CS_ETM_ETMCCER ; i <CS_ETM_PRIV_MAX ; i++) { +snprintf (path,PATH_MAX ,"cpu%d/%s" , cpu, metadata_etmv3_ro[i]); + + scan =perf_pmu__scan_file (cs_etm_pmu, path,"%x" , &val); +if (scan !=1 ) { + ret = -EINVAL ; +break ; + } + + info->priv[offset + i] = val; + } + +return ret; +} + +static int cs_etm_info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +int i, nr_cpu, ret =0 ; +const struct cpu_map *cpus = session->evlist->cpus; + +if (priv_size !=cs_etm_info_priv_size (itr, session->evlist)) +return -EINVAL ; + +if (!session->evlist->nr_mmaps) +return -EINVAL ; + + auxtrace_info->type =PERF_AUXTRACE_CS_ETM ; + +/* cpu map is not empty, we have specific CPUs to work with */ +if (!cpu_map__empty (cpus)) { +for (i =0 ; i <cpu_map__nr (cpus); i++) { + ret =cs_etm_get_metadata (cpus->map[i], i, + itr, auxtrace_info); +if (ret) + goto out; + } + }else { +/* get configuration for all CPUs in the system */ + nr_cpu =cpu__max_cpu (); +for (i =0 ; i < nr_cpu; i++) { + ret =cs_etm_get_metadata (i, i, itr, auxtrace_info); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int cs_etm_find_snapshot (struct auxtrace_record *itr__maybe_unused , +int idx,struct auxtrace_mmap *mm, +unsigned char *data__maybe_unused , +u64 *head,u64 *old) +{ +pr_debug3 ("%s: mmap index %d old head %zu new head %zu size %zu\n" , + __func__, idx, (size_t )*old, (size_t )*head, mm->len); + + *old = *head; + *head += mm->len; + +return 0 ; +} + +static int cs_etm_snapshot_start (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__disable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static int cs_etm_snapshot_finish (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static u64 cs_etm_reference (struct auxtrace_record *itr__maybe_unused ) +{ +return (((u64 )rand () <<0 ) &0x00000000FFFFFFFFull ) | + (((u64 )rand () <<32 ) &0xFFFFFFFF00000000ull ); +} + +static void cs_etm_recording_free (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +free (ptr); +} + +static int cs_etm_read_finish (struct auxtrace_record *itr,int idx) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event_idx (ptr->evlist, + evsel, idx); + } + +return -EINVAL ; +} + +struct auxtrace_record *cs_etm_record_init (int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct cs_etm_recording *ptr; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (!cs_etm_pmu) { + *err = -EINVAL ; + goto out; + } + + ptr =zalloc (sizeof (struct cs_etm_recording )); +if (!ptr) { + *err = -ENOMEM ; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err =0 ; +return &ptr->itr; +out: +return NULL ; +}tools/perf/arch/arm/util/cs_etm.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +/* Beginning of header common to both ETMv3 and V4 */ +enum { +CS_ETM_MAGIC , +CS_ETM_CPU , +CS_ETM_SNAPSHOT , +}; + +/* ETMv3/PTM metadata */ +enum { +/* Dynamic, configurable parameters */ +CS_ETM_ETMCR =CS_ETM_SNAPSHOT +1 , +CS_ETM_ETMTRACEIDR , +/* RO, taken from sysFS */ +CS_ETM_ETMCCER , +CS_ETM_ETMIDR , +CS_ETM_PRIV_MAX , +}; + +static const u64 __perf_cs_etm_magic =0x3030303030303030ULL ; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init (int *err); + +#endif tools/perf/util/auxtrace.c +1
-0@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;tools/perf/util/auxtrace.h +1
-1@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type { --Quoted 2 lines
2.1.4
Arnaldo,
Last but not least, this is the final patch that I would like you to review before queing.
Quoted 6 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
One more, are you ok with this?
Quoted 7 lines
Looks OK, apart from adding
linux/coresight-pmu.hto the manifest, but I mentioned that on another patch.However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
We are working on a decoding library in parallel to this work.
Quoted 4 lines
Nevertheless, for what is there now:
Acked-by Adrian Hunter <[email protected]>
Thanks for the review.
Mathieu
Quoted 1 line
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Em Fri, Jan 29, 2016 at 10:37:48AM -0700, Mathieu Poirier escreveu:
Quoted 674 lines · Adrian Hunter
Quoted 673 lines · Arnaldo Carvalho de Melo
Quoted 662 lines
Em Mon, Jan 25, 2016 at 01:51:18PM -0700, Mathieu Poirier escreveu:
Quoted 661 lines · Mathieu Poirier
Quoted 652 lines
Coresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.hMAINTAINERS +3
-0@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +1
-1@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.otools/perf/arch/arm/util/auxtrace.c new file +54
-0@@ -0,0 +1,54 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <linux/coresight-pmu.h> + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init (struct perf_evlist *evlist,int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct perf_evsel *evsel; +bool found_etm = false; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (evlist) { +evlist__for_each (evlist, evsel) { +if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + +if (found_etm) +return cs_etm_record_init (err); + +/* +* Clear 'err' even if we haven't found a cs_etm event - that way perf +* record can still be used even if tracers aren't present. The NULL +* return value will take care of telling the infrastructure HW tracing +* isn't available. +*/ + *err =0 ; +return NULL ; +}tools/perf/arch/arm/util/cs_etm.c new file +466
-0@@ -0,0 +1,466 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <api/fs/fs.h> +#include <linux/bitops.h> +#include <linux/coresight-pmu.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/types.h> + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include <stdlib.h> + +#define KiB (x) ((x) * 1024) +#define MiB (x) ((x) * 1024 * 1024) + +struct cs_etm_recording { +struct auxtrace_record itr; +struct perf_pmu *cs_etm_pmu; +struct perf_evlist *evlist; +bool snapshot_mode; +size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options (struct auxtrace_record *itr, +struct record_opts *opts, +const char *str) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +unsigned long long snapshot_size =0 ; +char *endptr; + +if (str) { + snapshot_size =strtoull (str, &endptr,0 ); +if (*endptr || snapshot_size >SIZE_MAX ) +return -1 ; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + +return 0 ; +} + +static int cs_etm_recording_options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evsel *evsel, *cs_etm_evsel =NULL ; +const struct cpu_map *cpus = evlist->cpus; +bool privileged = (geteuid () ==0 ||perf_event_paranoid () <0 ); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +if (cs_etm_evsel) { +pr_err ("There may be only one %s event\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + evsel->attr.freq =0 ; + evsel->attr.sample_period =1 ; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + +/* no need to continue if at least one event of interest was found */ +if (!cs_etm_evsel) +return 0 ; + +if (opts->use_clockid) { +pr_err ("Cannot use clockid (-k option) with %s\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + +/* we are in snapshot mode */ +if (opts->auxtrace_snapshot_mode) { +/* +* No size were given to '-S' or '-m,', so go with +* the default +*/ +if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages = +KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + }else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages ==UINT_MAX ) { + opts->mmap_pages =KiB (256 ) / page_size; + } + +/* +* '-m,xyz' was specified but no snapshot size, so make the +* snapshot size as big as the auxtrace mmap area. +*/ +if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t )page_size; + } + +/* +* -Sxyz was specified but no auxtrace mmap area, so make the +* auxtrace mmap area big enough to fit the requested snapshot +* size. +*/ +if (!opts->auxtrace_mmap_pages) { +size_t sz = opts->auxtrace_snapshot_size; + + sz =round_up (sz, page_size) / page_size; + opts->auxtrace_mmap_pages =roundup_pow_of_two (sz); + } + +/* Snapshost size can't be bigger than the auxtrace area */ +if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t )page_size) { +pr_err ("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n" , + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t )page_size); +return -EINVAL ; + } + +/* Something went wrong somewhere - this shouldn't happen */ +if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { +pr_err ("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n" ); +return -EINVAL ; + } + } + +/* We are in full trace mode but '-m,xyz' wasn't specified */ +if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages =KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + + } + +/* Validate auxtrace_mmap_pages provided by user */ +if (opts->auxtrace_mmap_pages) { +unsigned int max_page = (KiB (128 ) / page_size); +size_t sz = opts->auxtrace_mmap_pages * (size_t )page_size; + +if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; +pr_err ("auxtrace too big, truncating to %d\n" , + max_page); + } + +if (!is_power_of_2 (sz)) { +pr_err ("Invalid mmap size for %s: must be a power of 2\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + } + +if (opts->auxtrace_snapshot_mode) +pr_debug2 ("%s snapshot size: %zu\n" ,CORESIGHT_ETM_PMU_NAME , + opts->auxtrace_snapshot_size); + +if (cs_etm_evsel) { +/* +* To obtain the auxtrace buffer file descriptor, the auxtrace +* event must come first. +*/ +perf_evlist__to_front (evlist, cs_etm_evsel); +/* +* In the case of per-cpu mmaps, we need the CPU on the +* AUX event. +*/ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (cs_etm_evsel,CPU ); + } + +/* Add dummy event to keep tracking */ +if (opts->full_auxtrace) { +struct perf_evsel *tracking_evsel; +int err; + + err =parse_events (evlist,"dummy:u" ,NULL ); +if (err) +return err; + + tracking_evsel =perf_evlist__last (evlist); +perf_evlist__set_tracking_event (evlist, tracking_evsel); + + tracking_evsel->attr.freq =0 ; + tracking_evsel->attr.sample_period =1 ; + +/* In per-cpu case, always need the time of mmap events etc */ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (tracking_evsel,TIME ); + } + +return 0 ; +} + +static u64 cs_etm_get_config (struct auxtrace_record *itr) +{ +u64 config =0 ; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evlist *evlist = ptr->evlist; +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +/* +* Variable perf_event_attr::config is assigned to +* ETMv3/PTM. The bit fields have been made to match +* the ETMv3.5 ETRMCR register specification. See the +* PMU_FORMAT_ATTR() declarations in +* drivers/hwtracing/coresight/coresight-perf.c for +* details. +*/ + config = evsel->attr.config; +break ; + } + } + +return config; +} + +static size_t +cs_etm_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +int records; +const struct cpu_map *cpus = evlist->cpus; + +if (!cpu_map__empty (cpus)) { + records =cpu_map__nr (cpus); + goto out; + } + +set_max_cpu_num (); + records =cpu__max_cpu (); +out: +return records *CS_ETM_PRIV_SIZE ; +} + +static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX ] = { + [CS_ETM_ETMCCER ] ="mgmt/etmccer" , + [CS_ETM_ETMIDR ] ="mgmt/etmidr" , +}; + +static int cs_etm_get_metadata (int cpu,int index, +struct auxtrace_record *itr, +struct auxtrace_info_event *info) +{ +char path[PATH_MAX ]; +int offset =0 , ret =0 ; +int i, scan; +unsigned int val; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + + offset = index *CS_ETM_PRIV_MAX ; + +/* Build generic header portion */ + info->priv[offset +CS_ETM_MAGIC ] = __perf_cs_etm_magic; + info->priv[offset +CS_ETM_CPU ] = cpu; + info->priv[offset +CS_ETM_SNAPSHOT ] = ptr->snapshot_mode; + +/* Get user configurables from the session */ + info->priv[offset +CS_ETM_ETMCR ] =cs_etm_get_config (itr); + info->priv[offset +CS_ETM_ETMTRACEIDR ] =coresight_get_trace_id (cpu); + +/* Get RO metadata from sysfs */ +for (i =CS_ETM_ETMCCER ; i <CS_ETM_PRIV_MAX ; i++) { +snprintf (path,PATH_MAX ,"cpu%d/%s" , cpu, metadata_etmv3_ro[i]); + + scan =perf_pmu__scan_file (cs_etm_pmu, path,"%x" , &val); +if (scan !=1 ) { + ret = -EINVAL ; +break ; + } + + info->priv[offset + i] = val; + } + +return ret; +} + +static int cs_etm_info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +int i, nr_cpu, ret =0 ; +const struct cpu_map *cpus = session->evlist->cpus; + +if (priv_size !=cs_etm_info_priv_size (itr, session->evlist)) +return -EINVAL ; + +if (!session->evlist->nr_mmaps) +return -EINVAL ; + + auxtrace_info->type =PERF_AUXTRACE_CS_ETM ; + +/* cpu map is not empty, we have specific CPUs to work with */ +if (!cpu_map__empty (cpus)) { +for (i =0 ; i <cpu_map__nr (cpus); i++) { + ret =cs_etm_get_metadata (cpus->map[i], i, + itr, auxtrace_info); +if (ret) + goto out; + } + }else { +/* get configuration for all CPUs in the system */ + nr_cpu =cpu__max_cpu (); +for (i =0 ; i < nr_cpu; i++) { + ret =cs_etm_get_metadata (i, i, itr, auxtrace_info); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int cs_etm_find_snapshot (struct auxtrace_record *itr__maybe_unused , +int idx,struct auxtrace_mmap *mm, +unsigned char *data__maybe_unused , +u64 *head,u64 *old) +{ +pr_debug3 ("%s: mmap index %d old head %zu new head %zu size %zu\n" , + __func__, idx, (size_t )*old, (size_t )*head, mm->len); + + *old = *head; + *head += mm->len; + +return 0 ; +} + +static int cs_etm_snapshot_start (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__disable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static int cs_etm_snapshot_finish (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static u64 cs_etm_reference (struct auxtrace_record *itr__maybe_unused ) +{ +return (((u64 )rand () <<0 ) &0x00000000FFFFFFFFull ) | + (((u64 )rand () <<32 ) &0xFFFFFFFF00000000ull ); +} + +static void cs_etm_recording_free (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +free (ptr); +} + +static int cs_etm_read_finish (struct auxtrace_record *itr,int idx) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event_idx (ptr->evlist, + evsel, idx); + } + +return -EINVAL ; +} + +struct auxtrace_record *cs_etm_record_init (int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct cs_etm_recording *ptr; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (!cs_etm_pmu) { + *err = -EINVAL ; + goto out; + } + + ptr =zalloc (sizeof (struct cs_etm_recording )); +if (!ptr) { + *err = -ENOMEM ; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err =0 ; +return &ptr->itr; +out: +return NULL ; +}tools/perf/arch/arm/util/cs_etm.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +/* Beginning of header common to both ETMv3 and V4 */ +enum { +CS_ETM_MAGIC , +CS_ETM_CPU , +CS_ETM_SNAPSHOT , +}; + +/* ETMv3/PTM metadata */ +enum { +/* Dynamic, configurable parameters */ +CS_ETM_ETMCR =CS_ETM_SNAPSHOT +1 , +CS_ETM_ETMTRACEIDR , +/* RO, taken from sysFS */ +CS_ETM_ETMCCER , +CS_ETM_ETMIDR , +CS_ETM_PRIV_MAX , +}; + +static const u64 __perf_cs_etm_magic =0x3030303030303030ULL ; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init (int *err); + +#endif tools/perf/util/auxtrace.c +1
-0@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;tools/perf/util/auxtrace.h +1
-1@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type { --Quoted 2 lines
2.1.4
Arnaldo,
Last but not least, this is the final patch that I would like you to review before queing.
Quoted 6 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
One more, are you ok with this?
Looks OK, apart from adding
linux/coresight-pmu.hto the manifest, but I mentioned that on another patch.
Quoted 6 lines
Quoted 4 lines
However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
We are working on a decoding library in parallel to this work.
Would be nice to be able to get both in the same patch kit, no? So that one can both record and process the traces, verifying it all works.
- Arnaldo
Quoted 9 lines
Quoted 4 lines
Nevertheless, for what is there now:
Acked-by Adrian Hunter <[email protected]>Thanks for the review.
MathieuQuoted 1 line
Re: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Quoted 680 lines · Arnaldo Carvalho de Melo
Em Fri, Jan 29, 2016 at 10:37:48AM -0700, Mathieu Poirier escreveu:
Quoted 679 lines · Adrian Hunter
Quoted 677 lines · Arnaldo Carvalho de Melo
Quoted 662 lines
Em Mon, Jan 25, 2016 at 01:51:18PM -0700, Mathieu Poirier escreveu:
Quoted 661 lines · Mathieu Poirier
Quoted 652 lines
Coresight ETMs are IP blocks used to perform HW assisted tracing on a CPU core. This patch introduce the required auxiliary API functions allowing the perf core to interact with a tracer.
Cc Peter Zijlstra <[email protected]>Cc Ingo Molnar <[email protected]>Cc Arnaldo Carvalho de Melo <[email protected]>Signed-off-by Mathieu Poirier <[email protected]>--- MAINTAINERS | 3 + tools/perf/arch/arm/util/Build | 2 +- tools/perf/arch/arm/util/auxtrace.c | 54 +++++ tools/perf/arch/arm/util/cs_etm.c | 466 ++++++++++++++++++++++++++++++++++++ tools/perf/arch/arm/util/cs_etm.h | 44 ++++ tools/perf/util/auxtrace.c | 1 + tools/perf/util/auxtrace.h | 1 + 7 files changed, 570 insertions(+), 1 deletion(-) create mode 100644 tools/perf/arch/arm/util/auxtrace.c create mode 100644 tools/perf/arch/arm/util/cs_etm.c create mode 100644 tools/perf/arch/arm/util/cs_etm.hMAINTAINERS +3
-0@@ -1008,6 +1008,9 @@ F: Documentation/trace/coresight.txt F: Documentation/devicetree/bindings/arm/coresight.txt F: Documentation/ABI/testing/sysfs-bus-coresight-devices-* F: tools/perf/arch/arm/util/pmu.c +F: tools/perf/arch/arm/util/auxtrace.c +F: tools/perf/arch/arm/util/cs_etm.c +F: tools/perf/arch/arm/util/cs_etm.h ARM/CORGI MACHINE SUPPORT M: Richard Purdie <[email protected]>tools/perf/arch/arm/util/Build +1
-1@@ -3,4 +3,4 @@ libperf-$(CONFIG_DWARF) += dwarf-regs.o libperf-$(CONFIG_LIBUNWIND) += unwind-libunwind.o libperf-$(CONFIG_LIBDW_DWARF_UNWIND) += unwind-libdw.o -libperf-$(CONFIG_AUXTRACE) += pmu.o +libperf-$(CONFIG_AUXTRACE) += pmu.o auxtrace.o cs_etm.otools/perf/arch/arm/util/auxtrace.c new file +54
-0@@ -0,0 +1,54 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <stdbool.h> +#include <linux/coresight-pmu.h> + +#include "../../util/auxtrace.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "cs_etm.h" + +struct auxtrace_record +*auxtrace_record__init (struct perf_evlist *evlist,int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct perf_evsel *evsel; +bool found_etm = false; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (evlist) { +evlist__for_each (evlist, evsel) { +if (cs_etm_pmu && + evsel->attr.type == cs_etm_pmu->type) + found_etm = true; + } + } + +if (found_etm) +return cs_etm_record_init (err); + +/* +* Clear 'err' even if we haven't found a cs_etm event - that way perf +* record can still be used even if tracers aren't present. The NULL +* return value will take care of telling the infrastructure HW tracing +* isn't available. +*/ + *err =0 ; +return NULL ; +}tools/perf/arch/arm/util/cs_etm.c new file +466
-0@@ -0,0 +1,466 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#include <api/fs/fs.h> +#include <linux/bitops.h> +#include <linux/coresight-pmu.h> +#include <linux/kernel.h> +#include <linux/log2.h> +#include <linux/types.h> + +#include "../../perf.h" +#include "../../util/auxtrace.h" +#include "../../util/cpumap.h" +#include "../../util/evlist.h" +#include "../../util/pmu.h" +#include "../../util/thread_map.h" +#include "cs_etm.h" + +#include <stdlib.h> + +#define KiB (x) ((x) * 1024) +#define MiB (x) ((x) * 1024 * 1024) + +struct cs_etm_recording { +struct auxtrace_record itr; +struct perf_pmu *cs_etm_pmu; +struct perf_evlist *evlist; +bool snapshot_mode; +size_t snapshot_size; +}; + +static int cs_etm_parse_snapshot_options (struct auxtrace_record *itr, +struct record_opts *opts, +const char *str) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +unsigned long long snapshot_size =0 ; +char *endptr; + +if (str) { + snapshot_size =strtoull (str, &endptr,0 ); +if (*endptr || snapshot_size >SIZE_MAX ) +return -1 ; + } + + opts->auxtrace_snapshot_mode = true; + opts->auxtrace_snapshot_size = snapshot_size; + ptr->snapshot_size = snapshot_size; + +return 0 ; +} + +static int cs_etm_recording_options (struct auxtrace_record *itr, +struct perf_evlist *evlist, +struct record_opts *opts) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evsel *evsel, *cs_etm_evsel =NULL ; +const struct cpu_map *cpus = evlist->cpus; +bool privileged = (geteuid () ==0 ||perf_event_paranoid () <0 ); + + ptr->evlist = evlist; + ptr->snapshot_mode = opts->auxtrace_snapshot_mode; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +if (cs_etm_evsel) { +pr_err ("There may be only one %s event\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + evsel->attr.freq =0 ; + evsel->attr.sample_period =1 ; + cs_etm_evsel = evsel; + opts->full_auxtrace = true; + } + } + +/* no need to continue if at least one event of interest was found */ +if (!cs_etm_evsel) +return 0 ; + +if (opts->use_clockid) { +pr_err ("Cannot use clockid (-k option) with %s\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + +/* we are in snapshot mode */ +if (opts->auxtrace_snapshot_mode) { +/* +* No size were given to '-S' or '-m,', so go with +* the default +*/ +if (!opts->auxtrace_snapshot_size && + !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages = +KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + }else if (!opts->auxtrace_mmap_pages && !privileged && + opts->mmap_pages ==UINT_MAX ) { + opts->mmap_pages =KiB (256 ) / page_size; + } + +/* +* '-m,xyz' was specified but no snapshot size, so make the +* snapshot size as big as the auxtrace mmap area. +*/ +if (!opts->auxtrace_snapshot_size) { + opts->auxtrace_snapshot_size = + opts->auxtrace_mmap_pages * (size_t )page_size; + } + +/* +* -Sxyz was specified but no auxtrace mmap area, so make the +* auxtrace mmap area big enough to fit the requested snapshot +* size. +*/ +if (!opts->auxtrace_mmap_pages) { +size_t sz = opts->auxtrace_snapshot_size; + + sz =round_up (sz, page_size) / page_size; + opts->auxtrace_mmap_pages =roundup_pow_of_two (sz); + } + +/* Snapshost size can't be bigger than the auxtrace area */ +if (opts->auxtrace_snapshot_size > + opts->auxtrace_mmap_pages * (size_t )page_size) { +pr_err ("Snapshot size %zu must not be greater than AUX area tracing mmap size %zu\n" , + opts->auxtrace_snapshot_size, + opts->auxtrace_mmap_pages * (size_t )page_size); +return -EINVAL ; + } + +/* Something went wrong somewhere - this shouldn't happen */ +if (!opts->auxtrace_snapshot_size || + !opts->auxtrace_mmap_pages) { +pr_err ("Failed to calculate default snapshot size and/or AUX area tracing mmap pages\n" ); +return -EINVAL ; + } + } + +/* We are in full trace mode but '-m,xyz' wasn't specified */ +if (opts->full_auxtrace && !opts->auxtrace_mmap_pages) { +if (privileged) { + opts->auxtrace_mmap_pages =MiB (4 ) / page_size; + }else { + opts->auxtrace_mmap_pages =KiB (128 ) / page_size; +if (opts->mmap_pages ==UINT_MAX ) + opts->mmap_pages =KiB (256 ) / page_size; + } + + } + +/* Validate auxtrace_mmap_pages provided by user */ +if (opts->auxtrace_mmap_pages) { +unsigned int max_page = (KiB (128 ) / page_size); +size_t sz = opts->auxtrace_mmap_pages * (size_t )page_size; + +if (!privileged && + opts->auxtrace_mmap_pages > max_page) { + opts->auxtrace_mmap_pages = max_page; +pr_err ("auxtrace too big, truncating to %d\n" , + max_page); + } + +if (!is_power_of_2 (sz)) { +pr_err ("Invalid mmap size for %s: must be a power of 2\n" , +CORESIGHT_ETM_PMU_NAME ); +return -EINVAL ; + } + } + +if (opts->auxtrace_snapshot_mode) +pr_debug2 ("%s snapshot size: %zu\n" ,CORESIGHT_ETM_PMU_NAME , + opts->auxtrace_snapshot_size); + +if (cs_etm_evsel) { +/* +* To obtain the auxtrace buffer file descriptor, the auxtrace +* event must come first. +*/ +perf_evlist__to_front (evlist, cs_etm_evsel); +/* +* In the case of per-cpu mmaps, we need the CPU on the +* AUX event. +*/ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (cs_etm_evsel,CPU ); + } + +/* Add dummy event to keep tracking */ +if (opts->full_auxtrace) { +struct perf_evsel *tracking_evsel; +int err; + + err =parse_events (evlist,"dummy:u" ,NULL ); +if (err) +return err; + + tracking_evsel =perf_evlist__last (evlist); +perf_evlist__set_tracking_event (evlist, tracking_evsel); + + tracking_evsel->attr.freq =0 ; + tracking_evsel->attr.sample_period =1 ; + +/* In per-cpu case, always need the time of mmap events etc */ +if (!cpu_map__empty (cpus)) +perf_evsel__set_sample_bit (tracking_evsel,TIME ); + } + +return 0 ; +} + +static u64 cs_etm_get_config (struct auxtrace_record *itr) +{ +u64 config =0 ; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; +struct perf_evlist *evlist = ptr->evlist; +struct perf_evsel *evsel; + +evlist__for_each (evlist, evsel) { +if (evsel->attr.type == cs_etm_pmu->type) { +/* +* Variable perf_event_attr::config is assigned to +* ETMv3/PTM. The bit fields have been made to match +* the ETMv3.5 ETRMCR register specification. See the +* PMU_FORMAT_ATTR() declarations in +* drivers/hwtracing/coresight/coresight-perf.c for +* details. +*/ + config = evsel->attr.config; +break ; + } + } + +return config; +} + +static size_t +cs_etm_info_priv_size (struct auxtrace_record *itr__maybe_unused , +struct perf_evlist *evlist__maybe_unused ) +{ +int records; +const struct cpu_map *cpus = evlist->cpus; + +if (!cpu_map__empty (cpus)) { + records =cpu_map__nr (cpus); + goto out; + } + +set_max_cpu_num (); + records =cpu__max_cpu (); +out: +return records *CS_ETM_PRIV_SIZE ; +} + +static const char *metadata_etmv3_ro[CS_ETM_PRIV_MAX ] = { + [CS_ETM_ETMCCER ] ="mgmt/etmccer" , + [CS_ETM_ETMIDR ] ="mgmt/etmidr" , +}; + +static int cs_etm_get_metadata (int cpu,int index, +struct auxtrace_record *itr, +struct auxtrace_info_event *info) +{ +char path[PATH_MAX ]; +int offset =0 , ret =0 ; +int i, scan; +unsigned int val; +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_pmu *cs_etm_pmu = ptr->cs_etm_pmu; + + offset = index *CS_ETM_PRIV_MAX ; + +/* Build generic header portion */ + info->priv[offset +CS_ETM_MAGIC ] = __perf_cs_etm_magic; + info->priv[offset +CS_ETM_CPU ] = cpu; + info->priv[offset +CS_ETM_SNAPSHOT ] = ptr->snapshot_mode; + +/* Get user configurables from the session */ + info->priv[offset +CS_ETM_ETMCR ] =cs_etm_get_config (itr); + info->priv[offset +CS_ETM_ETMTRACEIDR ] =coresight_get_trace_id (cpu); + +/* Get RO metadata from sysfs */ +for (i =CS_ETM_ETMCCER ; i <CS_ETM_PRIV_MAX ; i++) { +snprintf (path,PATH_MAX ,"cpu%d/%s" , cpu, metadata_etmv3_ro[i]); + + scan =perf_pmu__scan_file (cs_etm_pmu, path,"%x" , &val); +if (scan !=1 ) { + ret = -EINVAL ; +break ; + } + + info->priv[offset + i] = val; + } + +return ret; +} + +static int cs_etm_info_fill (struct auxtrace_record *itr, +struct perf_session *session, +struct auxtrace_info_event *auxtrace_info, +size_t priv_size) +{ +int i, nr_cpu, ret =0 ; +const struct cpu_map *cpus = session->evlist->cpus; + +if (priv_size !=cs_etm_info_priv_size (itr, session->evlist)) +return -EINVAL ; + +if (!session->evlist->nr_mmaps) +return -EINVAL ; + + auxtrace_info->type =PERF_AUXTRACE_CS_ETM ; + +/* cpu map is not empty, we have specific CPUs to work with */ +if (!cpu_map__empty (cpus)) { +for (i =0 ; i <cpu_map__nr (cpus); i++) { + ret =cs_etm_get_metadata (cpus->map[i], i, + itr, auxtrace_info); +if (ret) + goto out; + } + }else { +/* get configuration for all CPUs in the system */ + nr_cpu =cpu__max_cpu (); +for (i =0 ; i < nr_cpu; i++) { + ret =cs_etm_get_metadata (i, i, itr, auxtrace_info); +if (ret) + goto out; + } + } + +out: +return ret; +} + +static int cs_etm_find_snapshot (struct auxtrace_record *itr__maybe_unused , +int idx,struct auxtrace_mmap *mm, +unsigned char *data__maybe_unused , +u64 *head,u64 *old) +{ +pr_debug3 ("%s: mmap index %d old head %zu new head %zu size %zu\n" , + __func__, idx, (size_t )*old, (size_t )*head, mm->len); + + *old = *head; + *head += mm->len; + +return 0 ; +} + +static int cs_etm_snapshot_start (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__disable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static int cs_etm_snapshot_finish (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event (ptr->evlist, evsel); + } +return -EINVAL ; +} + +static u64 cs_etm_reference (struct auxtrace_record *itr__maybe_unused ) +{ +return (((u64 )rand () <<0 ) &0x00000000FFFFFFFFull ) | + (((u64 )rand () <<32 ) &0xFFFFFFFF00000000ull ); +} + +static void cs_etm_recording_free (struct auxtrace_record *itr) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +free (ptr); +} + +static int cs_etm_read_finish (struct auxtrace_record *itr,int idx) +{ +struct cs_etm_recording *ptr = + container_of(itr, struct cs_etm_recording, itr); +struct perf_evsel *evsel; + +evlist__for_each (ptr->evlist, evsel) { +if (evsel->attr.type == ptr->cs_etm_pmu->type) +return perf_evlist__enable_event_idx (ptr->evlist, + evsel, idx); + } + +return -EINVAL ; +} + +struct auxtrace_record *cs_etm_record_init (int *err) +{ +struct perf_pmu *cs_etm_pmu; +struct cs_etm_recording *ptr; + + cs_etm_pmu =perf_pmu__find (CORESIGHT_ETM_PMU_NAME ); + +if (!cs_etm_pmu) { + *err = -EINVAL ; + goto out; + } + + ptr =zalloc (sizeof (struct cs_etm_recording )); +if (!ptr) { + *err = -ENOMEM ; + goto out; + } + + ptr->cs_etm_pmu = cs_etm_pmu; + ptr->itr.parse_snapshot_options = cs_etm_parse_snapshot_options; + ptr->itr.recording_options = cs_etm_recording_options; + ptr->itr.info_priv_size = cs_etm_info_priv_size; + ptr->itr.info_fill = cs_etm_info_fill; + ptr->itr.find_snapshot = cs_etm_find_snapshot; + ptr->itr.snapshot_start = cs_etm_snapshot_start; + ptr->itr.snapshot_finish = cs_etm_snapshot_finish; + ptr->itr.reference = cs_etm_reference; + ptr->itr.free = cs_etm_recording_free; + ptr->itr.read_finish = cs_etm_read_finish; + + *err =0 ; +return &ptr->itr; +out: +return NULL ; +}tools/perf/arch/arm/util/cs_etm.h new file +44
-0@@ -0,0 +1,44 @@ +/* +* Copyright(C) 2015 Linaro Limited. All rights reserved. +* Author: Mathieu Poirier <[email protected]> +* +* This program is free software; you can redistribute it and/or modify it +* under the terms of the GNU General Public License version 2 as published by +* the Free Software Foundation. +* +* This program is distributed in the hope that it will be useful, but WITHOUT +* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or +* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for +* more details. +* +* You should have received a copy of the GNU General Public License along with +* this program. If not, see <http://www.gnu.org/licenses/>. +*/ + +#ifndef INCLUDE__PERF_CS_ETM_H__ +#define INCLUDE__PERF_CS_ETM_H__ + +/* Beginning of header common to both ETMv3 and V4 */ +enum { +CS_ETM_MAGIC , +CS_ETM_CPU , +CS_ETM_SNAPSHOT , +}; + +/* ETMv3/PTM metadata */ +enum { +/* Dynamic, configurable parameters */ +CS_ETM_ETMCR =CS_ETM_SNAPSHOT +1 , +CS_ETM_ETMTRACEIDR , +/* RO, taken from sysFS */ +CS_ETM_ETMCCER , +CS_ETM_ETMIDR , +CS_ETM_PRIV_MAX , +}; + +static const u64 __perf_cs_etm_magic =0x3030303030303030ULL ; +#define CS_ETM_PRIV_SIZE (CS_ETM_PRIV_MAX * sizeof(u64)) + +struct auxtrace_record *cs_etm_record_init (int *err); + +#endif tools/perf/util/auxtrace.c +1
-0@@ -892,6 +892,7 @@ int perf_event__process_auxtrace_info(struct perf_tool *tool __maybe_unused,return intel_pt_process_auxtrace_info (event, session);case PERF_AUXTRACE_INTEL_BTS :return intel_bts_process_auxtrace_info (event, session); +case PERF_AUXTRACE_CS_ETM :case PERF_AUXTRACE_UNKNOWN :default :return -EINVAL ;tools/perf/util/auxtrace.h +1
-1@@ -41,6 +41,7 @@ enum auxtrace_type {PERF_AUXTRACE_UNKNOWN ,PERF_AUXTRACE_INTEL_PT ,PERF_AUXTRACE_INTEL_BTS , + PERF_AUXTRACE_CS_ETM, }; enum itrace_period_type { --Quoted 2 lines
2.1.4
Arnaldo,
Last but not least, this is the final patch that I would like you to review before queing.
Quoted 6 lines
Quoted 2 lines
It has been rebased to 4.5-rc1 here [1] for your convenience. I will be happy to use another baseline should that be more adequate for you.
Adrian,
One more, are you ok with this?
Looks OK, apart from adding
linux/coresight-pmu.hto the manifest, but I mentioned that on another patch.However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
Quoted 4 lines
Quoted 1 line
We are working on a decoding library in parallel to this work.
Would be nice to be able to get both in the same patch kit, no? So that one can both record and process the traces, verifying it all works.
We are still a few weeks away from being in a position where the community can start playing with the decoding library. I can hold off on the "perf tools" patches when I queue the kernel side of the work for 4.6 but since you and Adrian have already reviewed the work it would be nice to have that part included as well.
We've been playing with the perf.data files for a couple of months now and things look at the right place. This isn't surprising since we are using the same framework as X86.
I think the generation of the perf.data file should be coupled with the submission of the kernel driver but would also respect a diverging point of view. Simply let me know what you prefer and I will adjust V9 accordingly.
Regards,
Mathieu
Quoted 12 lines
- Arnaldo
Quoted 9 lines
Quoted 4 lines
Nevertheless, for what is there now:
Acked-by Adrian Hunter <[email protected]>Thanks for the review.
MathieuQuoted 1 line
Re: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
[...]
Quoted 20 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Looks OK, apart from adding
linux/coresight-pmu.hto the manifest, but I mentioned that on another patch.However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
Quoted 4 lines
Quoted 1 line
We are working on a decoding library in parallel to this work.
Would be nice to be able to get both in the same patch kit, no? So that one can both record and process the traces, verifying it all works.
We are still a few weeks away from being in a position where the community can start playing with the decoding library. I can hold off on the "perf tools" patches when I queue the kernel side of the work for 4.6 but since you and Adrian have already reviewed the work it would be nice to have that part included as well.
Quoted 8 lines
We've been playing with the perf.data files for a couple of months now and things look at the right place. This isn't surprising since we are using the same framework as X86.
I think the generation of the perf.data file should be coupled with the submission of the kernel driver but would also respect a diverging point of view. Simply let me know what you prefer and I will adjust V9 accordingly.
Arnaldo,
I'm preparing V9 at this time - what's your view on the above?
Thanks,
Mathieu
Arnaldo Carvalho de Melo
maintainerRe: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Em Tue, Feb 02, 2016 at 09:20:51AM -0700, Mathieu Poirier escreveu:
Quoted 26 lines
[...]
Quoted 24 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Looks OK, apart from adding
linux/coresight-pmu.hto the manifest, but I mentioned that on another patch.However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
Quoted 4 lines
Quoted 1 line
We are working on a decoding library in parallel to this work.
Would be nice to be able to get both in the same patch kit, no? So that one can both record and process the traces, verifying it all works.
We are still a few weeks away from being in a position where the community can start playing with the decoding library. I can hold off on the "perf tools" patches when I queue the kernel side of the work for 4.6 but since you and Adrian have already reviewed the work it would be nice to have that part included as well.
We've been playing with the perf.data files for a couple of months now and things look at the right place. This isn't surprising since we are using the same framework as X86.
Quoted 8 lines
Quoted 4 lines
I think the generation of the perf.data file should be coupled with the submission of the kernel driver but would also respect a diverging point of view. Simply let me know what you prefer and I will adjust V9 accordingly.
Arnaldo,
I'm preparing V9 at this time - what's your view on the above?
I'd say go with something we can test, i.e. if we generate a perf.data file we can't then process to figure out if what was inserted is right, how can we decide if it is ok?
Otherwise please describe how you test it, preferably by having this in the commit log, i.e. if you decide that using plain 'perf report -D' is enough, state that and show the output, etc.
- Arnaldo
Re: [PATCH V8 23/23] perf tools: adding coresight etm PMU record capabilities
Quoted 32 lines · Arnaldo Carvalho de Melo
Em Tue, Feb 02, 2016 at 09:20:51AM -0700, Mathieu Poirier escreveu:
Quoted 31 lines
[...]
Quoted 28 lines
Quoted 9 lines
Quoted 9 lines
Quoted 8 lines
Looks OK, apart from adding
linux/coresight-pmu.hto the manifest, but I mentioned that on another patch.However there is no decoder, which begs the question, is there anything you can actually do with the perf.data file? Might be a bit confusing for users if they can capture traces but not use perf tools on the resulting perf.data file?
Quoted 4 lines
Quoted 1 line
We are working on a decoding library in parallel to this work.
Would be nice to be able to get both in the same patch kit, no? So that one can both record and process the traces, verifying it all works.
We are still a few weeks away from being in a position where the community can start playing with the decoding library. I can hold off on the "perf tools" patches when I queue the kernel side of the work for 4.6 but since you and Adrian have already reviewed the work it would be nice to have that part included as well.
We've been playing with the perf.data files for a couple of months now and things look at the right place. This isn't surprising since we are using the same framework as X86.
I think the generation of the perf.data file should be coupled with the submission of the kernel driver but would also respect a diverging point of view. Simply let me know what you prefer and I will adjust V9 accordingly.
Quoted 7 lines
Quoted 3 lines
Arnaldo,
I'm preparing V9 at this time - what's your view on the above?
I'd say go with something we can test, i.e. if we generate a perf.data file we can't then process to figure out if what was inserted is right, how can we decide if it is ok?
Very well - I'll hold off on the perf tools patches for now. We can make a submission of all the user space components when things are in a working order.
Mathieu
Quoted 6 lines
Otherwise please describe how you test it, preferably by having this in the commit log, i.e. if you decide that using plain 'perf report -D' is enough, state that and show the output, etc.
- Arnaldo