... | ... | ||
---|---|---|---|
5 | 5 | ||
6 | Patches 02 and 03 change the ETMv4 driver to prepare callback functions | 6 | Patches 02 and 03 change the ETMv4 driver to prepare callback functions |
7 | for AUX pause and resume. | 7 | for AUX pause and resume. |
8 | 8 | ||
9 | Patch 04 changes the ETM perf layer to support AUX pause and resume in a | 9 | Patch 04 changes the ETM perf layer to support AUX pause and resume in a |
10 | perf session. The patches 05 and 06 offers an extra feature for | 10 | perf session. The patch 05 re-enables sinks after buffer update, based |
11 | updating buffer on AUX pause occasion, which can mitigate the trace data | 11 | on it, the patch 06 updates buffer on AUX pause occasion, which can |
12 | lose issue. | 12 | mitigate the trace data lose issue. |
13 | 13 | ||
14 | Patch 07 documents the AUX pause usages with Arm CoreSight. The last | 14 | Patch 07 documents the AUX pause usages with Arm CoreSight. |
15 | patch syncs headers between user space and the kernel. | ||
16 | 15 | ||
17 | This patch set has been verified on the Hikey960 board and TC platform. | 16 | This patch set has been verified on the Hikey960 board. |
18 | The previous one uses ETR and the later uses TRBE as sink. | ||
19 | 17 | ||
20 | It is suggested to disable CPUIdle (add `nohlt` option in Linux command | 18 | It is suggested to disable CPUIdle (add `nohlt` option in Linux command |
21 | line) when verifying this series. ETM and funnel drivers are found | 19 | line) when verifying this series. ETM and funnel drivers are found |
22 | issues during CPU suspend and resume which will be addressed separately. | 20 | issues during CPU suspend and resume which will be addressed separately. |
23 | 21 | ||
22 | Changes from v3: | ||
23 | - Re-enabled sink in buffer update callbacks (Suzuki). | ||
24 | 24 | ||
25 | Leo Yan (8): | 25 | Changes from v2: |
26 | - Rebased on CoreSight next branch. | ||
27 | - Dropped the uAPI 'update_buf_on_pause' and updated document | ||
28 | respectively (Suzuki). | ||
29 | - Renamed ETM callbacks to .pause_perf() and .resume_perf() (Suzuki). | ||
30 | - Minor improvement for error handling in the AUX resume flow. | ||
31 | |||
32 | Changes from v1: | ||
33 | - Added validation function pointers in pause and resume APIs (Mike). | ||
34 | |||
35 | |||
36 | Leo Yan (7): | ||
26 | coresight: etm4x: Extract the trace unit controlling | 37 | coresight: etm4x: Extract the trace unit controlling |
27 | coresight: Introduce pause and resume APIs for source | 38 | coresight: Introduce pause and resume APIs for source |
28 | coresight: etm4x: Hook pause and resume callbacks | 39 | coresight: etm4x: Hook pause and resume callbacks |
29 | coresight: perf: Support AUX trace pause and resume | 40 | coresight: perf: Support AUX trace pause and resume |
30 | coresight: etm: Add an attribute for updating buffer | 41 | coresight: tmc: Re-enable sink after buffer update |
31 | coresight: perf: Update buffer on AUX pause | 42 | coresight: perf: Update buffer on AUX pause |
32 | Documentation: coresight: Document AUX pause and resume | 43 | Documentation: coresight: Document AUX pause and resume |
33 | perf cs-etm: Sync kernel coresight-pmu.h header | ||
34 | 44 | ||
35 | .../trace/coresight/coresight-perf.rst | 50 ++++++ | 45 | Documentation/trace/coresight/coresight-perf.rst | 31 +++++++++ |
36 | drivers/hwtracing/coresight/coresight-core.c | 12 ++ | 46 | drivers/hwtracing/coresight/coresight-core.c | 22 +++++++ |
37 | .../hwtracing/coresight/coresight-etm-perf.c | 94 +++++++++- | 47 | drivers/hwtracing/coresight/coresight-etm-perf.c | 84 +++++++++++++++++++++++- |
38 | .../hwtracing/coresight/coresight-etm-perf.h | 2 + | 48 | drivers/hwtracing/coresight/coresight-etm4x-core.c | 143 +++++++++++++++++++++++++++++------------ |
39 | .../coresight/coresight-etm4x-core.c | 166 ++++++++++++------ | 49 | drivers/hwtracing/coresight/coresight-etm4x.h | 2 + |
40 | drivers/hwtracing/coresight/coresight-etm4x.h | 2 + | 50 | drivers/hwtracing/coresight/coresight-priv.h | 2 + |
41 | drivers/hwtracing/coresight/coresight-priv.h | 2 + | 51 | drivers/hwtracing/coresight/coresight-tmc-etf.c | 9 +++ |
42 | include/linux/coresight-pmu.h | 1 + | 52 | drivers/hwtracing/coresight/coresight-tmc-etr.c | 10 +++ |
43 | include/linux/coresight.h | 4 + | 53 | include/linux/coresight.h | 4 ++ |
44 | tools/include/linux/coresight-pmu.h | 1 + | 54 | 9 files changed, 265 insertions(+), 42 deletions(-) |
45 | 10 files changed, 281 insertions(+), 53 deletions(-) | ||
46 | 55 | ||
47 | -- | 56 | -- |
48 | 2.34.1 | 57 | 2.34.1 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
5 | Extract the operations in the etm4_{enable|disable}_trace_unit() | 5 | Extract the operations in the etm4_{enable|disable}_trace_unit() |
6 | functions. A minor improvement in etm4_enable_trace_unit() is for | 6 | functions. A minor improvement in etm4_enable_trace_unit() is for |
7 | returning the timeout error to callers. | 7 | returning the timeout error to callers. |
8 | 8 | ||
9 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 9 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
10 | Reviewed-by: Mike Leach <mike.leach@linaro.org> | ||
10 | --- | 11 | --- |
11 | .../coresight/coresight-etm4x-core.c | 126 ++++++++++-------- | 12 | drivers/hwtracing/coresight/coresight-etm4x-core.c | 103 +++++++++++++++++++++++++---------------- |
12 | 1 file changed, 74 insertions(+), 52 deletions(-) | 13 | 1 file changed, 62 insertions(+), 41 deletions(-) |
13 | 14 | ||
14 | diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c | 15 | diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c |
15 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c | 17 | --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c |
17 | +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c | 18 | +++ b/drivers/hwtracing/coresight/coresight-etm4x-core.c |
18 | @@ -XXX,XX +XXX,XX @@ static void etm4_check_arch_features(struct etmv4_drvdata *drvdata, | 19 | @@ -XXX,XX +XXX,XX @@ static int etm4x_wait_status(struct csdev_access *csa, int pos, int val) |
20 | return coresight_timeout(csa, TRCSTATR, pos, val); | ||
19 | } | 21 | } |
20 | #endif /* CONFIG_ETM4X_IMPDEF_FEATURE */ | ||
21 | 22 | ||
22 | +static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata) | 23 | +static int etm4_enable_trace_unit(struct etmv4_drvdata *drvdata) |
23 | +{ | 24 | +{ |
24 | + struct coresight_device *csdev = drvdata->csdev; | 25 | + struct coresight_device *csdev = drvdata->csdev; |
25 | + struct device *etm_dev = &csdev->dev; | 26 | + struct device *etm_dev = &csdev->dev; |
... | ... | ||
39 | + /* Synchronize the register updates for sysreg access */ | 40 | + /* Synchronize the register updates for sysreg access */ |
40 | + if (!csa->io_mem) | 41 | + if (!csa->io_mem) |
41 | + isb(); | 42 | + isb(); |
42 | + | 43 | + |
43 | + /* wait for TRCSTATR.IDLE to go back down to '0' */ | 44 | + /* wait for TRCSTATR.IDLE to go back down to '0' */ |
44 | + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) { | 45 | + if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0)) { |
45 | + dev_err(etm_dev, | 46 | + dev_err(etm_dev, |
46 | + "timeout while waiting for Idle Trace Status\n"); | 47 | + "timeout while waiting for Idle Trace Status\n"); |
47 | + return -ETIME; | 48 | + return -ETIME; |
48 | + } | 49 | + } |
49 | + | 50 | + |
... | ... | ||
55 | + isb(); | 56 | + isb(); |
56 | + | 57 | + |
57 | + return 0; | 58 | + return 0; |
58 | +} | 59 | +} |
59 | + | 60 | + |
60 | +static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata) | ||
61 | +{ | ||
62 | + u32 control; | ||
63 | + struct coresight_device *csdev = drvdata->csdev; | ||
64 | + struct device *etm_dev = &csdev->dev; | ||
65 | + struct csdev_access *csa = &csdev->access; | ||
66 | + | ||
67 | + control = etm4x_relaxed_read32(csa, TRCPRGCTLR); | ||
68 | + | ||
69 | + /* EN, bit[0] Trace unit enable bit */ | ||
70 | + control &= ~0x1; | ||
71 | + | ||
72 | + /* | ||
73 | + * If the CPU supports v8.4 Trace filter Control, | ||
74 | + * set the ETM to trace prohibited region. | ||
75 | + */ | ||
76 | + etm4x_prohibit_trace(drvdata); | ||
77 | + /* | ||
78 | + * Make sure everything completes before disabling, as recommended | ||
79 | + * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register, | ||
80 | + * SSTATUS") of ARM IHI 0064D | ||
81 | + */ | ||
82 | + dsb(sy); | ||
83 | + isb(); | ||
84 | + /* Trace synchronization barrier, is a nop if not supported */ | ||
85 | + tsb_csync(); | ||
86 | + etm4x_relaxed_write32(csa, control, TRCPRGCTLR); | ||
87 | + | ||
88 | + /* wait for TRCSTATR.PMSTABLE to go to '1' */ | ||
89 | + if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) | ||
90 | + dev_err(etm_dev, | ||
91 | + "timeout while waiting for PM stable Trace Status\n"); | ||
92 | +} | ||
93 | + | ||
94 | static int etm4_enable_hw(struct etmv4_drvdata *drvdata) | 61 | static int etm4_enable_hw(struct etmv4_drvdata *drvdata) |
95 | { | 62 | { |
96 | int i, rc; | 63 | int i, rc; |
97 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) | 64 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable_hw(struct etmv4_drvdata *drvdata) |
98 | etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR); | 65 | etm4x_relaxed_write32(csa, trcpdcr | TRCPDCR_PU, TRCPDCR); |
... | ... | ||
112 | - /* Synchronize the register updates for sysreg access */ | 79 | - /* Synchronize the register updates for sysreg access */ |
113 | - if (!csa->io_mem) | 80 | - if (!csa->io_mem) |
114 | - isb(); | 81 | - isb(); |
115 | - | 82 | - |
116 | - /* wait for TRCSTATR.IDLE to go back down to '0' */ | 83 | - /* wait for TRCSTATR.IDLE to go back down to '0' */ |
117 | - if (coresight_timeout(csa, TRCSTATR, TRCSTATR_IDLE_BIT, 0)) | 84 | - if (etm4x_wait_status(csa, TRCSTATR_IDLE_BIT, 0)) |
118 | - dev_err(etm_dev, | 85 | - dev_err(etm_dev, |
119 | - "timeout while waiting for Idle Trace Status\n"); | 86 | - "timeout while waiting for Idle Trace Status\n"); |
120 | - | 87 | - |
121 | - /* | 88 | - /* |
122 | - * As recommended by section 4.3.7 ("Synchronization when using the | 89 | - * As recommended by section 4.3.7 ("Synchronization when using the |
... | ... | ||
127 | - | 94 | - |
128 | + rc = etm4_enable_trace_unit(drvdata); | 95 | + rc = etm4_enable_trace_unit(drvdata); |
129 | done: | 96 | done: |
130 | etm4_cs_lock(drvdata, csa); | 97 | etm4_cs_lock(drvdata, csa); |
131 | 98 | ||
99 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable(struct coresight_device *csdev, struct perf_event *event, | ||
100 | return ret; | ||
101 | } | ||
102 | |||
103 | -static void etm4_disable_hw(void *info) | ||
104 | +static void etm4_disable_trace_unit(struct etmv4_drvdata *drvdata) | ||
105 | { | ||
106 | u32 control; | ||
107 | - struct etmv4_drvdata *drvdata = info; | ||
108 | - struct etmv4_config *config = &drvdata->config; | ||
109 | struct coresight_device *csdev = drvdata->csdev; | ||
110 | struct device *etm_dev = &csdev->dev; | ||
111 | struct csdev_access *csa = &csdev->access; | ||
112 | - int i; | ||
113 | - | ||
114 | - etm4_cs_unlock(drvdata, csa); | ||
115 | - etm4_disable_arch_specific(drvdata); | ||
116 | - | ||
117 | - if (!drvdata->skip_power_up) { | ||
118 | - /* power can be removed from the trace unit now */ | ||
119 | - control = etm4x_relaxed_read32(csa, TRCPDCR); | ||
120 | - control &= ~TRCPDCR_PU; | ||
121 | - etm4x_relaxed_write32(csa, control, TRCPDCR); | ||
122 | - } | ||
123 | |||
124 | control = etm4x_relaxed_read32(csa, TRCPRGCTLR); | ||
125 | |||
132 | @@ -XXX,XX +XXX,XX @@ static void etm4_disable_hw(void *info) | 126 | @@ -XXX,XX +XXX,XX @@ static void etm4_disable_hw(void *info) |
133 | struct etmv4_drvdata *drvdata = info; | 127 | * of ARM IHI 0064H.b. |
134 | struct etmv4_config *config = &drvdata->config; | 128 | */ |
135 | struct coresight_device *csdev = drvdata->csdev; | 129 | isb(); |
136 | - struct device *etm_dev = &csdev->dev; | 130 | +} |
137 | struct csdev_access *csa = &csdev->access; | 131 | + |
138 | int i; | 132 | +static void etm4_disable_hw(void *info) |
139 | 133 | +{ | |
140 | @@ -XXX,XX +XXX,XX @@ static void etm4_disable_hw(void *info) | 134 | + u32 control; |
141 | etm4x_relaxed_write32(csa, control, TRCPDCR); | 135 | + struct etmv4_drvdata *drvdata = info; |
142 | } | 136 | + struct etmv4_config *config = &drvdata->config; |
143 | 137 | + struct coresight_device *csdev = drvdata->csdev; | |
144 | - control = etm4x_relaxed_read32(csa, TRCPRGCTLR); | 138 | + struct csdev_access *csa = &csdev->access; |
139 | + int i; | ||
140 | + | ||
141 | + etm4_cs_unlock(drvdata, csa); | ||
142 | + etm4_disable_arch_specific(drvdata); | ||
143 | + | ||
144 | + if (!drvdata->skip_power_up) { | ||
145 | + /* power can be removed from the trace unit now */ | ||
146 | + control = etm4x_relaxed_read32(csa, TRCPDCR); | ||
147 | + control &= ~TRCPDCR_PU; | ||
148 | + etm4x_relaxed_write32(csa, control, TRCPDCR); | ||
149 | + } | ||
150 | + | ||
145 | + etm4_disable_trace_unit(drvdata); | 151 | + etm4_disable_trace_unit(drvdata); |
146 | 152 | ||
147 | - /* EN, bit[0] Trace unit enable bit */ | ||
148 | - control &= ~0x1; | ||
149 | - | ||
150 | - /* | ||
151 | - * If the CPU supports v8.4 Trace filter Control, | ||
152 | - * set the ETM to trace prohibited region. | ||
153 | - */ | ||
154 | - etm4x_prohibit_trace(drvdata); | ||
155 | - /* | ||
156 | - * Make sure everything completes before disabling, as recommended | ||
157 | - * by section 7.3.77 ("TRCVICTLR, ViewInst Main Control Register, | ||
158 | - * SSTATUS") of ARM IHI 0064D | ||
159 | - */ | ||
160 | - dsb(sy); | ||
161 | - isb(); | ||
162 | - /* Trace synchronization barrier, is a nop if not supported */ | ||
163 | - tsb_csync(); | ||
164 | - etm4x_relaxed_write32(csa, control, TRCPRGCTLR); | ||
165 | - | ||
166 | - /* wait for TRCSTATR.PMSTABLE to go to '1' */ | ||
167 | - if (coresight_timeout(csa, TRCSTATR, TRCSTATR_PMSTABLE_BIT, 1)) | ||
168 | - dev_err(etm_dev, | ||
169 | - "timeout while waiting for PM stable Trace Status\n"); | ||
170 | /* read the status of the single shot comparators */ | 153 | /* read the status of the single shot comparators */ |
171 | for (i = 0; i < drvdata->nr_ss_cmp; i++) { | 154 | for (i = 0; i < drvdata->nr_ss_cmp; i++) { |
172 | config->ss_status[i] = | ||
173 | -- | 155 | -- |
174 | 2.34.1 | 156 | 2.34.1 | diff view generated by jsdifflib |
1 | Introduce APIs for pausing and resuming trace source and export as GPL | 1 | Introduce APIs for pausing and resuming trace source and export as GPL |
---|---|---|---|
2 | symbols. | 2 | symbols. |
3 | 3 | ||
4 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 4 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
5 | Reviewed-by: Mike Leach <mike.leach@linaro.org> | ||
5 | --- | 6 | --- |
6 | drivers/hwtracing/coresight/coresight-core.c | 12 ++++++++++++ | 7 | drivers/hwtracing/coresight/coresight-core.c | 22 ++++++++++++++++++++++ |
7 | drivers/hwtracing/coresight/coresight-priv.h | 2 ++ | 8 | drivers/hwtracing/coresight/coresight-priv.h | 2 ++ |
8 | include/linux/coresight.h | 4 ++++ | 9 | include/linux/coresight.h | 4 ++++ |
9 | 3 files changed, 18 insertions(+) | 10 | 3 files changed, 28 insertions(+) |
10 | 11 | ||
11 | diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c | 12 | diff --git a/drivers/hwtracing/coresight/coresight-core.c b/drivers/hwtracing/coresight/coresight-core.c |
12 | index XXXXXXX..XXXXXXX 100644 | 13 | index XXXXXXX..XXXXXXX 100644 |
13 | --- a/drivers/hwtracing/coresight/coresight-core.c | 14 | --- a/drivers/hwtracing/coresight/coresight-core.c |
14 | +++ b/drivers/hwtracing/coresight/coresight-core.c | 15 | +++ b/drivers/hwtracing/coresight/coresight-core.c |
15 | @@ -XXX,XX +XXX,XX @@ void coresight_disable_source(struct coresight_device *csdev, void *data) | 16 | @@ -XXX,XX +XXX,XX @@ void coresight_disable_source(struct coresight_device *csdev, void *data) |
16 | } | 17 | } |
17 | EXPORT_SYMBOL_GPL(coresight_disable_source); | 18 | EXPORT_SYMBOL_GPL(coresight_disable_source); |
18 | 19 | ||
19 | +void coresight_pause_source(struct coresight_device *csdev) | 20 | +void coresight_pause_source(struct coresight_device *csdev) |
20 | +{ | 21 | +{ |
21 | + source_ops(csdev)->pause(csdev); | 22 | + if (!coresight_is_percpu_source(csdev)) |
23 | + return; | ||
24 | + | ||
25 | + if (source_ops(csdev)->pause_perf) | ||
26 | + source_ops(csdev)->pause_perf(csdev); | ||
22 | +} | 27 | +} |
23 | +EXPORT_SYMBOL_GPL(coresight_pause_source); | 28 | +EXPORT_SYMBOL_GPL(coresight_pause_source); |
24 | + | 29 | + |
25 | +void coresight_resume_source(struct coresight_device *csdev) | 30 | +int coresight_resume_source(struct coresight_device *csdev) |
26 | +{ | 31 | +{ |
27 | + source_ops(csdev)->resume(csdev); | 32 | + if (!coresight_is_percpu_source(csdev)) |
33 | + return -EOPNOTSUPP; | ||
34 | + | ||
35 | + if (!source_ops(csdev)->resume_perf) | ||
36 | + return -EOPNOTSUPP; | ||
37 | + | ||
38 | + return source_ops(csdev)->resume_perf(csdev); | ||
28 | +} | 39 | +} |
29 | +EXPORT_SYMBOL_GPL(coresight_resume_source); | 40 | +EXPORT_SYMBOL_GPL(coresight_resume_source); |
30 | + | 41 | + |
31 | /* | 42 | /* |
32 | * coresight_disable_path_from : Disable components in the given path beyond | 43 | * coresight_disable_path_from : Disable components in the given path beyond |
... | ... | ||
38 | @@ -XXX,XX +XXX,XX @@ void coresight_add_helper(struct coresight_device *csdev, | 49 | @@ -XXX,XX +XXX,XX @@ void coresight_add_helper(struct coresight_device *csdev, |
39 | void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); | 50 | void coresight_set_percpu_sink(int cpu, struct coresight_device *csdev); |
40 | struct coresight_device *coresight_get_percpu_sink(int cpu); | 51 | struct coresight_device *coresight_get_percpu_sink(int cpu); |
41 | void coresight_disable_source(struct coresight_device *csdev, void *data); | 52 | void coresight_disable_source(struct coresight_device *csdev, void *data); |
42 | +void coresight_pause_source(struct coresight_device *csdev); | 53 | +void coresight_pause_source(struct coresight_device *csdev); |
43 | +void coresight_resume_source(struct coresight_device *csdev); | 54 | +int coresight_resume_source(struct coresight_device *csdev); |
44 | 55 | ||
45 | #endif | 56 | #endif |
46 | diff --git a/include/linux/coresight.h b/include/linux/coresight.h | 57 | diff --git a/include/linux/coresight.h b/include/linux/coresight.h |
47 | index XXXXXXX..XXXXXXX 100644 | 58 | index XXXXXXX..XXXXXXX 100644 |
48 | --- a/include/linux/coresight.h | 59 | --- a/include/linux/coresight.h |
49 | +++ b/include/linux/coresight.h | 60 | +++ b/include/linux/coresight.h |
50 | @@ -XXX,XX +XXX,XX @@ struct coresight_ops_link { | 61 | @@ -XXX,XX +XXX,XX @@ struct coresight_ops_link { |
51 | * is associated to. | 62 | * is associated to. |
52 | * @enable: enables tracing for a source. | 63 | * @enable: enables tracing for a source. |
53 | * @disable: disables tracing for a source. | 64 | * @disable: disables tracing for a source. |
54 | + * @resume: resumes tracing for a source. | 65 | + * @resume_perf: resumes tracing for a source in perf session. |
55 | + * @pause: pauses tracing for a source. | 66 | + * @pause_perf: pauses tracing for a source in perf session. |
56 | */ | 67 | */ |
57 | struct coresight_ops_source { | 68 | struct coresight_ops_source { |
58 | int (*cpu_id)(struct coresight_device *csdev); | 69 | int (*cpu_id)(struct coresight_device *csdev); |
59 | @@ -XXX,XX +XXX,XX @@ struct coresight_ops_source { | 70 | @@ -XXX,XX +XXX,XX @@ struct coresight_ops_source { |
60 | enum cs_mode mode, struct coresight_trace_id_map *id_map); | 71 | enum cs_mode mode, struct coresight_path *path); |
61 | void (*disable)(struct coresight_device *csdev, | 72 | void (*disable)(struct coresight_device *csdev, |
62 | struct perf_event *event); | 73 | struct perf_event *event); |
63 | + int (*resume)(struct coresight_device *csdev); | 74 | + int (*resume_perf)(struct coresight_device *csdev); |
64 | + void (*pause)(struct coresight_device *csdev); | 75 | + void (*pause_perf)(struct coresight_device *csdev); |
65 | }; | 76 | }; |
66 | 77 | ||
67 | /** | 78 | /** |
68 | -- | 79 | -- |
69 | 2.34.1 | 80 | 2.34.1 | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
4 | paused. If the flag is set, the driver will skip starting the hardware | 4 | paused. If the flag is set, the driver will skip starting the hardware |
5 | trace. The flag is always set to false for the sysfs mode, meaning the | 5 | trace. The flag is always set to false for the sysfs mode, meaning the |
6 | tracer will never be paused in the case. | 6 | tracer will never be paused in the case. |
7 | 7 | ||
8 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 8 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
9 | Reviewed-by: Mike Leach <mike.leach@linaro.org> | ||
9 | --- | 10 | --- |
10 | .../coresight/coresight-etm4x-core.c | 42 ++++++++++++++++++- | 11 | drivers/hwtracing/coresight/coresight-etm4x-core.c | 42 +++++++++++++++++++++++++++++++++++++++++- |
11 | drivers/hwtracing/coresight/coresight-etm4x.h | 2 + | 12 | drivers/hwtracing/coresight/coresight-etm4x.h | 2 ++ |
12 | 2 files changed, 43 insertions(+), 1 deletion(-) | 13 | 2 files changed, 43 insertions(+), 1 deletion(-) |
13 | 14 | ||
14 | diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c | 15 | diff --git a/drivers/hwtracing/coresight/coresight-etm4x-core.c b/drivers/hwtracing/coresight/coresight-etm4x-core.c |
15 | index XXXXXXX..XXXXXXX 100644 | 16 | index XXXXXXX..XXXXXXX 100644 |
16 | --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c | 17 | --- a/drivers/hwtracing/coresight/coresight-etm4x-core.c |
... | ... | ||
24 | + rc = etm4_enable_trace_unit(drvdata); | 25 | + rc = etm4_enable_trace_unit(drvdata); |
25 | done: | 26 | done: |
26 | etm4_cs_lock(drvdata, csa); | 27 | etm4_cs_lock(drvdata, csa); |
27 | 28 | ||
28 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable_perf(struct coresight_device *csdev, | 29 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable_perf(struct coresight_device *csdev, |
29 | } | 30 | |
30 | drvdata->trcid = (u8)trace_id; | 31 | drvdata->trcid = path->trace_id; |
31 | 32 | ||
32 | + /* Populate pause state */ | 33 | + /* Populate pause state */ |
33 | + drvdata->paused = !!READ_ONCE(event->hw.aux_paused); | 34 | + drvdata->paused = !!READ_ONCE(event->hw.aux_paused); |
34 | + | 35 | + |
35 | /* And enable it */ | 36 | /* And enable it */ |
36 | ret = etm4_enable_hw(drvdata); | 37 | ret = etm4_enable_hw(drvdata); |
37 | 38 | ||
38 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable_sysfs(struct coresight_device *csdev) | 39 | @@ -XXX,XX +XXX,XX @@ static int etm4_enable_sysfs(struct coresight_device *csdev, struct coresight_pa |
39 | if (ret < 0) | 40 | |
40 | goto unlock_sysfs_enable; | 41 | drvdata->trcid = path->trace_id; |
41 | 42 | ||
42 | + /* Tracer will never be paused in sysfs mode */ | 43 | + /* Tracer will never be paused in sysfs mode */ |
43 | + drvdata->paused = false; | 44 | + drvdata->paused = false; |
44 | + | 45 | + |
45 | /* | 46 | /* |
46 | * Executing etm4_enable_hw on the cpu whose ETM is being enabled | 47 | * Executing etm4_enable_hw on the cpu whose ETM is being enabled |
47 | * ensures that register writes occur when cpu is powered. | 48 | * ensures that register writes occur when cpu is powered. |
48 | @@ -XXX,XX +XXX,XX @@ static void etm4_disable(struct coresight_device *csdev, | 49 | @@ -XXX,XX +XXX,XX @@ static void etm4_disable(struct coresight_device *csdev, |
49 | coresight_set_mode(csdev, CS_MODE_DISABLED); | 50 | coresight_set_mode(csdev, CS_MODE_DISABLED); |
50 | } | 51 | } |
51 | 52 | ||
52 | +static int etm4_resume(struct coresight_device *csdev) | 53 | +static int etm4_resume_perf(struct coresight_device *csdev) |
53 | +{ | 54 | +{ |
54 | + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); | 55 | + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); |
55 | + struct csdev_access *csa = &csdev->access; | 56 | + struct csdev_access *csa = &csdev->access; |
56 | + | 57 | + |
57 | + if (coresight_get_mode(csdev) != CS_MODE_PERF) | 58 | + if (coresight_get_mode(csdev) != CS_MODE_PERF) |
... | ... | ||
63 | + | 64 | + |
64 | + drvdata->paused = false; | 65 | + drvdata->paused = false; |
65 | + return 0; | 66 | + return 0; |
66 | +} | 67 | +} |
67 | + | 68 | + |
68 | +static void etm4_pause(struct coresight_device *csdev) | 69 | +static void etm4_pause_perf(struct coresight_device *csdev) |
69 | +{ | 70 | +{ |
70 | + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); | 71 | + struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); |
71 | + struct csdev_access *csa = &csdev->access; | 72 | + struct csdev_access *csa = &csdev->access; |
72 | + | 73 | + |
73 | + if (coresight_get_mode(csdev) != CS_MODE_PERF) | 74 | + if (coresight_get_mode(csdev) != CS_MODE_PERF) |
... | ... | ||
82 | + | 83 | + |
83 | static const struct coresight_ops_source etm4_source_ops = { | 84 | static const struct coresight_ops_source etm4_source_ops = { |
84 | .cpu_id = etm4_cpu_id, | 85 | .cpu_id = etm4_cpu_id, |
85 | .enable = etm4_enable, | 86 | .enable = etm4_enable, |
86 | .disable = etm4_disable, | 87 | .disable = etm4_disable, |
87 | + .resume = etm4_resume, | 88 | + .resume_perf = etm4_resume_perf, |
88 | + .pause = etm4_pause, | 89 | + .pause_perf = etm4_pause_perf, |
89 | }; | 90 | }; |
90 | 91 | ||
91 | static const struct coresight_ops etm4_cs_ops = { | 92 | static const struct coresight_ops etm4_cs_ops = { |
92 | diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h | 93 | diff --git a/drivers/hwtracing/coresight/coresight-etm4x.h b/drivers/hwtracing/coresight/coresight-etm4x.h |
93 | index XXXXXXX..XXXXXXX 100644 | 94 | index XXXXXXX..XXXXXXX 100644 |
... | ... | diff view generated by jsdifflib |
... | ... | ||
---|---|---|---|
14 | To achieve fine-grained control of the pause and resume, only the tracer | 14 | To achieve fine-grained control of the pause and resume, only the tracer |
15 | is disabled and enabled. This avoids the unnecessary complexity and | 15 | is disabled and enabled. This avoids the unnecessary complexity and |
16 | latency caused by manipulating the entire link path. | 16 | latency caused by manipulating the entire link path. |
17 | 17 | ||
18 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 18 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
19 | Reviewed-by: Mike Leach <mike.leach@linaro.org> | ||
19 | --- | 20 | --- |
20 | .../hwtracing/coresight/coresight-etm-perf.c | 40 ++++++++++++++++++- | 21 | drivers/hwtracing/coresight/coresight-etm-perf.c | 45 +++++++++++++++++++++++++++++++++++++++++++- |
21 | 1 file changed, 39 insertions(+), 1 deletion(-) | 22 | 1 file changed, 44 insertions(+), 1 deletion(-) |
22 | 23 | ||
23 | diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c | 24 | diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c |
24 | index XXXXXXX..XXXXXXX 100644 | 25 | index XXXXXXX..XXXXXXX 100644 |
25 | --- a/drivers/hwtracing/coresight/coresight-etm-perf.c | 26 | --- a/drivers/hwtracing/coresight/coresight-etm-perf.c |
26 | +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c | 27 | +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c |
... | ... | ||
32 | + * If AUX pause feature is enabled but the ETM driver does not | 33 | + * If AUX pause feature is enabled but the ETM driver does not |
33 | + * support the operations, clear this CPU from the mask and | 34 | + * support the operations, clear this CPU from the mask and |
34 | + * continue to next one. | 35 | + * continue to next one. |
35 | + */ | 36 | + */ |
36 | + if (event->attr.aux_start_paused && | 37 | + if (event->attr.aux_start_paused && |
37 | + (!source_ops(csdev)->pause || !source_ops(csdev)->resume)) { | 38 | + (!source_ops(csdev)->pause_perf || !source_ops(csdev)->resume_perf)) { |
38 | + dev_err_once(&csdev->dev, "AUX pause is not supported.\n"); | 39 | + dev_err_once(&csdev->dev, "AUX pause is not supported.\n"); |
39 | + cpumask_clear_cpu(cpu, mask); | 40 | + cpumask_clear_cpu(cpu, mask); |
40 | + continue; | 41 | + continue; |
41 | + } | 42 | + } |
42 | + | 43 | + |
... | ... | ||
45 | * where this event can be scheduled. | 46 | * where this event can be scheduled. |
46 | @@ -XXX,XX +XXX,XX @@ static void *etm_setup_aux(struct perf_event *event, void **pages, | 47 | @@ -XXX,XX +XXX,XX @@ static void *etm_setup_aux(struct perf_event *event, void **pages, |
47 | goto out; | 48 | goto out; |
48 | } | 49 | } |
49 | 50 | ||
50 | +static void etm_event_resume(struct coresight_device *csdev, | 51 | +static int etm_event_resume(struct coresight_device *csdev, |
51 | + struct etm_ctxt *ctxt) | 52 | + struct etm_ctxt *ctxt) |
52 | +{ | 53 | +{ |
53 | + if (!ctxt->event_data) | 54 | + if (!ctxt->event_data) |
54 | + return; | 55 | + return 0; |
55 | + | 56 | + |
56 | + coresight_resume_source(csdev); | 57 | + return coresight_resume_source(csdev); |
57 | +} | 58 | +} |
58 | + | 59 | + |
59 | static void etm_event_start(struct perf_event *event, int flags) | 60 | static void etm_event_start(struct perf_event *event, int flags) |
60 | { | 61 | { |
61 | int cpu = smp_processor_id(); | 62 | int cpu = smp_processor_id(); |
62 | @@ -XXX,XX +XXX,XX @@ static void etm_event_start(struct perf_event *event, int flags) | 63 | @@ -XXX,XX +XXX,XX @@ static void etm_event_start(struct perf_event *event, int flags) |
63 | if (!csdev) | 64 | if (!csdev) |
64 | goto fail; | 65 | goto fail; |
65 | 66 | ||
66 | + if (flags & PERF_EF_RESUME) | 67 | + if (flags & PERF_EF_RESUME) { |
67 | + return etm_event_resume(csdev, ctxt); | 68 | + if (etm_event_resume(csdev, ctxt) < 0) { |
69 | + dev_err(&csdev->dev, "Failed to resume ETM event.\n"); | ||
70 | + goto fail; | ||
71 | + } | ||
72 | + return; | ||
73 | + } | ||
68 | + | 74 | + |
69 | /* Have we messed up our tracking ? */ | 75 | /* Have we messed up our tracking ? */ |
70 | if (WARN_ON(ctxt->event_data)) | 76 | if (WARN_ON(ctxt->event_data)) |
71 | goto fail; | 77 | goto fail; |
72 | @@ -XXX,XX +XXX,XX @@ static void etm_event_start(struct perf_event *event, int flags) | 78 | @@ -XXX,XX +XXX,XX @@ static void etm_event_start(struct perf_event *event, int flags) |
... | ... | ||
86 | static void etm_event_stop(struct perf_event *event, int mode) | 92 | static void etm_event_stop(struct perf_event *event, int mode) |
87 | { | 93 | { |
88 | int cpu = smp_processor_id(); | 94 | int cpu = smp_processor_id(); |
89 | @@ -XXX,XX +XXX,XX @@ static void etm_event_stop(struct perf_event *event, int mode) | 95 | @@ -XXX,XX +XXX,XX @@ static void etm_event_stop(struct perf_event *event, int mode) |
90 | struct etm_event_data *event_data; | 96 | struct etm_event_data *event_data; |
91 | struct list_head *path; | 97 | struct coresight_path *path; |
92 | 98 | ||
93 | + if (mode & PERF_EF_PAUSE) | 99 | + if (mode & PERF_EF_PAUSE) |
94 | + return etm_event_pause(csdev, ctxt); | 100 | + return etm_event_pause(csdev, ctxt); |
95 | + | 101 | + |
96 | /* | 102 | /* |
... | ... | diff view generated by jsdifflib |
Deleted patch | |||
---|---|---|---|
1 | Add an attribute for updating buffer when the AUX trace is paused. And | ||
2 | populate the value to the 'update_buf_on_pause' flag during the AUX | ||
3 | setting up. | ||
4 | 1 | ||
5 | If the AUX pause operation is attached to a PMU counter, when the | ||
6 | counter is overflow and if the PMU interrupt in an NMI, then AUX pause | ||
7 | operation will be triggered in the NMI context. On the other hand, the | ||
8 | per CPU sink has its own interrupt handling. Thus, there will be a race | ||
9 | condition between the updating buffer in NMI and sink's interrupt | ||
10 | handler. | ||
11 | |||
12 | To avoid the race condition, this commit disallows updating buffer on | ||
13 | AUX pause for the per CPU sink. Currently, this is only applied for | ||
14 | TRBE. | ||
15 | |||
16 | Signed-off-by: Leo Yan <leo.yan@arm.com> | ||
17 | --- | ||
18 | .../hwtracing/coresight/coresight-etm-perf.c | 20 +++++++++++++++++++ | ||
19 | .../hwtracing/coresight/coresight-etm-perf.h | 2 ++ | ||
20 | include/linux/coresight-pmu.h | 1 + | ||
21 | 3 files changed, 23 insertions(+) | ||
22 | |||
23 | diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c | ||
24 | index XXXXXXX..XXXXXXX 100644 | ||
25 | --- a/drivers/hwtracing/coresight/coresight-etm-perf.c | ||
26 | +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c | ||
27 | @@ -XXX,XX +XXX,XX @@ PMU_FORMAT_ATTR(contextid1, "config:" __stringify(ETM_OPT_CTXTID)); | ||
28 | PMU_FORMAT_ATTR(contextid2, "config:" __stringify(ETM_OPT_CTXTID2)); | ||
29 | PMU_FORMAT_ATTR(timestamp, "config:" __stringify(ETM_OPT_TS)); | ||
30 | PMU_FORMAT_ATTR(retstack, "config:" __stringify(ETM_OPT_RETSTK)); | ||
31 | +PMU_FORMAT_ATTR(update_buf_on_pause, | ||
32 | + "config:" __stringify(ETM_OPT_UPDATE_BUF_ON_PAUSE)); | ||
33 | /* preset - if sink ID is used as a configuration selector */ | ||
34 | PMU_FORMAT_ATTR(preset, "config:0-3"); | ||
35 | /* Sink ID - same for all ETMs */ | ||
36 | @@ -XXX,XX +XXX,XX @@ static struct attribute *etm_config_formats_attr[] = { | ||
37 | &format_attr_configid.attr, | ||
38 | &format_attr_branch_broadcast.attr, | ||
39 | &format_attr_cc_threshold.attr, | ||
40 | + &format_attr_update_buf_on_pause.attr, | ||
41 | NULL, | ||
42 | }; | ||
43 | |||
44 | @@ -XXX,XX +XXX,XX @@ static void *etm_setup_aux(struct perf_event *event, void **pages, | ||
45 | if (!sink) | ||
46 | goto err; | ||
47 | |||
48 | + /* Populate the flag for updating buffer on AUX pause */ | ||
49 | + event_data->update_buf_on_pause = | ||
50 | + !!(event->attr.config & BIT(ETM_OPT_UPDATE_BUF_ON_PAUSE)); | ||
51 | + | ||
52 | + if (event_data->update_buf_on_pause) { | ||
53 | + /* | ||
54 | + * The per CPU sink has own interrupt handling, it might have | ||
55 | + * race condition with updating buffer on AUX trace pause if | ||
56 | + * it is invoked from NMI. To avoid the race condition, | ||
57 | + * disallows updating buffer for the per CPU sink case. | ||
58 | + */ | ||
59 | + if (coresight_is_percpu_sink(sink)) { | ||
60 | + dev_err(&sink->dev, "update_buf_on_pause is not permitted.\n"); | ||
61 | + goto err; | ||
62 | + } | ||
63 | + } | ||
64 | + | ||
65 | /* If we don't have any CPUs ready for tracing, abort */ | ||
66 | cpu = cpumask_first(mask); | ||
67 | if (cpu >= nr_cpu_ids) | ||
68 | diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.h b/drivers/hwtracing/coresight/coresight-etm-perf.h | ||
69 | index XXXXXXX..XXXXXXX 100644 | ||
70 | --- a/drivers/hwtracing/coresight/coresight-etm-perf.h | ||
71 | +++ b/drivers/hwtracing/coresight/coresight-etm-perf.h | ||
72 | @@ -XXX,XX +XXX,XX @@ struct etm_filters { | ||
73 | * @aux_hwid_done: Whether a CPU has emitted the TraceID packet or not. | ||
74 | * @snk_config: The sink configuration. | ||
75 | * @cfg_hash: The hash id of any coresight config selected. | ||
76 | + * @update_buf_on_pause: The flag to indicate updating buffer on AUX pause. | ||
77 | * @path: An array of path, each slot for one CPU. | ||
78 | */ | ||
79 | struct etm_event_data { | ||
80 | @@ -XXX,XX +XXX,XX @@ struct etm_event_data { | ||
81 | cpumask_t aux_hwid_done; | ||
82 | void *snk_config; | ||
83 | u32 cfg_hash; | ||
84 | + bool update_buf_on_pause; | ||
85 | struct list_head * __percpu *path; | ||
86 | }; | ||
87 | |||
88 | diff --git a/include/linux/coresight-pmu.h b/include/linux/coresight-pmu.h | ||
89 | index XXXXXXX..XXXXXXX 100644 | ||
90 | --- a/include/linux/coresight-pmu.h | ||
91 | +++ b/include/linux/coresight-pmu.h | ||
92 | @@ -XXX,XX +XXX,XX @@ | ||
93 | #define ETM_OPT_CTXTID2 15 | ||
94 | #define ETM_OPT_TS 28 | ||
95 | #define ETM_OPT_RETSTK 29 | ||
96 | +#define ETM_OPT_UPDATE_BUF_ON_PAUSE 30 | ||
97 | |||
98 | /* ETMv4 CONFIGR programming bits for the ETM OPTs */ | ||
99 | #define ETM4_CFG_BIT_BB 3 | ||
100 | -- | ||
101 | 2.34.1 | diff view generated by jsdifflib |
1 | Update the header in the tools to align with the kernel header. | 1 | The buffer update callbacks disable the sink before syncing data but |
---|---|---|---|
2 | misses to re-enable it afterward. This is fine in the general flow, | ||
3 | because the sink will be re-enabled the next time the PMU event is | ||
4 | activated. | ||
5 | |||
6 | However, during AUX pause and resume, if the sink is disabled in the | ||
7 | buffer update callback, there is no chance to re-enable it when AUX | ||
8 | resumes. | ||
9 | |||
10 | To address this, the callbacks now check the event state | ||
11 | 'event->hw.state'. If the event is an active state (0), the sink is | ||
12 | re-enabled. | ||
13 | |||
14 | For the TMC ETR driver, buffer updates are not fully protected by | ||
15 | the driver's spinlock. In this case, the sink is not re-enabled if its | ||
16 | reference counter is 0, in order to avoid race conditions where the sink | ||
17 | may have been completely disabled. | ||
2 | 18 | ||
3 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 19 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
4 | --- | 20 | --- |
5 | tools/include/linux/coresight-pmu.h | 1 + | 21 | drivers/hwtracing/coresight/coresight-tmc-etf.c | 9 +++++++++ |
6 | 1 file changed, 1 insertion(+) | 22 | drivers/hwtracing/coresight/coresight-tmc-etr.c | 10 ++++++++++ |
23 | 2 files changed, 19 insertions(+) | ||
7 | 24 | ||
8 | diff --git a/tools/include/linux/coresight-pmu.h b/tools/include/linux/coresight-pmu.h | 25 | diff --git a/drivers/hwtracing/coresight/coresight-tmc-etf.c b/drivers/hwtracing/coresight/coresight-tmc-etf.c |
9 | index XXXXXXX..XXXXXXX 100644 | 26 | index XXXXXXX..XXXXXXX 100644 |
10 | --- a/tools/include/linux/coresight-pmu.h | 27 | --- a/drivers/hwtracing/coresight/coresight-tmc-etf.c |
11 | +++ b/tools/include/linux/coresight-pmu.h | 28 | +++ b/drivers/hwtracing/coresight/coresight-tmc-etf.c |
12 | @@ -XXX,XX +XXX,XX @@ | 29 | @@ -XXX,XX +XXX,XX @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, |
13 | #define ETM_OPT_CTXTID2 15 | 30 | unsigned long offset, to_read = 0, flags; |
14 | #define ETM_OPT_TS 28 | 31 | struct cs_buffers *buf = sink_config; |
15 | #define ETM_OPT_RETSTK 29 | 32 | struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); |
16 | +#define ETM_OPT_UPDATE_BUF_ON_PAUSE 30 | 33 | + struct perf_event *event = handle->event; |
17 | 34 | ||
18 | /* ETMv4 CONFIGR programming bits for the ETM OPTs */ | 35 | if (!buf) |
19 | #define ETM4_CFG_BIT_BB 3 | 36 | return 0; |
37 | @@ -XXX,XX +XXX,XX @@ static unsigned long tmc_update_etf_buffer(struct coresight_device *csdev, | ||
38 | * is expected by the perf ring buffer. | ||
39 | */ | ||
40 | CS_LOCK(drvdata->base); | ||
41 | + | ||
42 | + /* | ||
43 | + * If the event is active, it is triggered during an AUX pause. | ||
44 | + * Re-enable the sink so that it is ready when AUX resume is invoked. | ||
45 | + */ | ||
46 | + if (!event->hw.state) | ||
47 | + __tmc_etb_enable_hw(drvdata); | ||
48 | + | ||
49 | out: | ||
50 | raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); | ||
51 | |||
52 | diff --git a/drivers/hwtracing/coresight/coresight-tmc-etr.c b/drivers/hwtracing/coresight/coresight-tmc-etr.c | ||
53 | index XXXXXXX..XXXXXXX 100644 | ||
54 | --- a/drivers/hwtracing/coresight/coresight-tmc-etr.c | ||
55 | +++ b/drivers/hwtracing/coresight/coresight-tmc-etr.c | ||
56 | @@ -XXX,XX +XXX,XX @@ tmc_update_etr_buffer(struct coresight_device *csdev, | ||
57 | struct tmc_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); | ||
58 | struct etr_perf_buffer *etr_perf = config; | ||
59 | struct etr_buf *etr_buf = etr_perf->etr_buf; | ||
60 | + struct perf_event *event = handle->event; | ||
61 | |||
62 | raw_spin_lock_irqsave(&drvdata->spinlock, flags); | ||
63 | |||
64 | @@ -XXX,XX +XXX,XX @@ tmc_update_etr_buffer(struct coresight_device *csdev, | ||
65 | */ | ||
66 | smp_wmb(); | ||
67 | |||
68 | + /* | ||
69 | + * If the event is active, it is triggered during an AUX pause. | ||
70 | + * Re-enable the sink so that it is ready when AUX resume is invoked. | ||
71 | + */ | ||
72 | + raw_spin_lock_irqsave(&drvdata->spinlock, flags); | ||
73 | + if (csdev->refcnt && !event->hw.state) | ||
74 | + __tmc_etr_enable_hw(drvdata); | ||
75 | + raw_spin_unlock_irqrestore(&drvdata->spinlock, flags); | ||
76 | + | ||
77 | out: | ||
78 | /* | ||
79 | * Don't set the TRUNCATED flag in snapshot mode because 1) the | ||
20 | -- | 80 | -- |
21 | 2.34.1 | 81 | 2.34.1 | diff view generated by jsdifflib |
1 | Due to sinks like ETR and ETB don't support interrupt handling, the | 1 | Due to sinks like ETR and ETB don't support interrupt handling, the |
---|---|---|---|
2 | hardware trace data might be lost for continuous running tasks. | 2 | hardware trace data might be lost for continuous running tasks. |
3 | 3 | ||
4 | This commit takes advantage of the AUX pause for updating trace buffer | 4 | This commit takes advantage of the AUX pause for updating trace buffer |
5 | to mitigate the trace data losing issue. | 5 | to mitigate the trace data losing issue. |
6 | 6 | ||
7 | The per CPU sink has its own interrupt handling. Thus, there will be a | ||
8 | race condition between the updating buffer in NMI and sink's interrupt | ||
9 | handler. To avoid the race condition, this commit disallows updating | ||
10 | buffer on AUX pause for the per CPU sink. Currently, this is only | ||
11 | applied for TRBE. | ||
12 | |||
7 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 13 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
8 | --- | 14 | --- |
9 | .../hwtracing/coresight/coresight-etm-perf.c | 38 ++++++++++++++++++- | 15 | drivers/hwtracing/coresight/coresight-etm-perf.c | 43 +++++++++++++++++++++++++++++++++++++++++-- |
10 | 1 file changed, 36 insertions(+), 2 deletions(-) | 16 | 1 file changed, 41 insertions(+), 2 deletions(-) |
11 | 17 | ||
12 | diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c | 18 | diff --git a/drivers/hwtracing/coresight/coresight-etm-perf.c b/drivers/hwtracing/coresight/coresight-etm-perf.c |
13 | index XXXXXXX..XXXXXXX 100644 | 19 | index XXXXXXX..XXXXXXX 100644 |
14 | --- a/drivers/hwtracing/coresight/coresight-etm-perf.c | 20 | --- a/drivers/hwtracing/coresight/coresight-etm-perf.c |
15 | +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c | 21 | +++ b/drivers/hwtracing/coresight/coresight-etm-perf.c |
... | ... | ||
23 | struct etm_ctxt *ctxt) | 29 | struct etm_ctxt *ctxt) |
24 | { | 30 | { |
25 | + int cpu = smp_processor_id(); | 31 | + int cpu = smp_processor_id(); |
26 | + struct coresight_device *sink; | 32 | + struct coresight_device *sink; |
27 | + struct perf_output_handle *handle = &ctxt->handle; | 33 | + struct perf_output_handle *handle = &ctxt->handle; |
28 | + struct list_head *path; | 34 | + struct coresight_path *path; |
29 | + unsigned long size; | 35 | + unsigned long size; |
30 | + | 36 | + |
31 | if (!ctxt->event_data) | 37 | if (!ctxt->event_data) |
32 | return; | 38 | return; |
33 | 39 | ||
34 | /* Stop tracer */ | 40 | /* Stop tracer */ |
35 | coresight_pause_source(csdev); | 41 | coresight_pause_source(csdev); |
36 | + | ||
37 | + /* Bail out if no need update buffer */ | ||
38 | + if (!ctxt->event_data->update_buf_on_pause) | ||
39 | + return; | ||
40 | + | ||
41 | + if (WARN_ON_ONCE(handle->event != event)) | ||
42 | + return; | ||
43 | + | 42 | + |
44 | + path = etm_event_cpu_path(ctxt->event_data, cpu); | 43 | + path = etm_event_cpu_path(ctxt->event_data, cpu); |
45 | + sink = coresight_get_sink(path); | 44 | + sink = coresight_get_sink(path); |
46 | + if (WARN_ON_ONCE(!sink)) | 45 | + if (WARN_ON_ONCE(!sink)) |
46 | + return; | ||
47 | + | ||
48 | + /* | ||
49 | + * The per CPU sink has own interrupt handling, it might have | ||
50 | + * race condition with updating buffer on AUX trace pause if | ||
51 | + * it is invoked from NMI. To avoid the race condition, | ||
52 | + * disallows updating buffer for the per CPU sink case. | ||
53 | + */ | ||
54 | + if (coresight_is_percpu_sink(sink)) | ||
55 | + return; | ||
56 | + | ||
57 | + if (WARN_ON_ONCE(handle->event != event)) | ||
47 | + return; | 58 | + return; |
48 | + | 59 | + |
49 | + if (!sink_ops(sink)->update_buffer) | 60 | + if (!sink_ops(sink)->update_buffer) |
50 | + return; | 61 | + return; |
51 | + | 62 | + |
... | ... | ||
62 | + } | 73 | + } |
63 | } | 74 | } |
64 | 75 | ||
65 | static void etm_event_stop(struct perf_event *event, int mode) | 76 | static void etm_event_stop(struct perf_event *event, int mode) |
66 | @@ -XXX,XX +XXX,XX @@ static void etm_event_stop(struct perf_event *event, int mode) | 77 | @@ -XXX,XX +XXX,XX @@ static void etm_event_stop(struct perf_event *event, int mode) |
67 | struct list_head *path; | 78 | struct coresight_path *path; |
68 | 79 | ||
69 | if (mode & PERF_EF_PAUSE) | 80 | if (mode & PERF_EF_PAUSE) |
70 | - return etm_event_pause(csdev, ctxt); | 81 | - return etm_event_pause(csdev, ctxt); |
71 | + return etm_event_pause(event, csdev, ctxt); | 82 | + return etm_event_pause(event, csdev, ctxt); |
72 | 83 | ||
73 | /* | 84 | /* |
74 | * If we still have access to the event_data via handle, | 85 | * If we still have access to the event_data via handle, |
75 | -- | 86 | -- |
76 | 2.34.1 | 87 | 2.34.1 | diff view generated by jsdifflib |
1 | This adds description for AUX pause and resume. It gives introduction | 1 | This adds description for AUX pause and resume. It gives introduction |
---|---|---|---|
2 | for what's AUX pause and resume and how to use the configuration terms. | 2 | for what's AUX pause and resume and records usage examples. |
3 | As last, it records several usage examples. | ||
4 | 3 | ||
5 | Signed-off-by: Leo Yan <leo.yan@arm.com> | 4 | Signed-off-by: Leo Yan <leo.yan@arm.com> |
6 | --- | 5 | --- |
7 | .../trace/coresight/coresight-perf.rst | 50 +++++++++++++++++++ | 6 | Documentation/trace/coresight/coresight-perf.rst | 31 +++++++++++++++++++++++++++++++ |
8 | 1 file changed, 50 insertions(+) | 7 | 1 file changed, 31 insertions(+) |
9 | 8 | ||
10 | diff --git a/Documentation/trace/coresight/coresight-perf.rst b/Documentation/trace/coresight/coresight-perf.rst | 9 | diff --git a/Documentation/trace/coresight/coresight-perf.rst b/Documentation/trace/coresight/coresight-perf.rst |
11 | index XXXXXXX..XXXXXXX 100644 | 10 | index XXXXXXX..XXXXXXX 100644 |
12 | --- a/Documentation/trace/coresight/coresight-perf.rst | 11 | --- a/Documentation/trace/coresight/coresight-perf.rst |
13 | +++ b/Documentation/trace/coresight/coresight-perf.rst | 12 | +++ b/Documentation/trace/coresight/coresight-perf.rst |
... | ... | ||
34 | +- "aux-action=pause": an associated event is specified with this term | 33 | +- "aux-action=pause": an associated event is specified with this term |
35 | + to pause AUX trace. | 34 | + to pause AUX trace. |
36 | +- "aux-action=resume": an associated event is specified with this term | 35 | +- "aux-action=resume": an associated event is specified with this term |
37 | + to resume AUX trace. | 36 | + to resume AUX trace. |
38 | + | 37 | + |
39 | +Some Arm CoreSight sinks (e.g., ETR, ETB) do not support interrupt | ||
40 | +mechanism. As a result, trace data might be lost if it cannot be copied | ||
41 | +to the user space tool in a timely manner. To mitigate trace data lose, | ||
42 | +a configuration term "update_buf_on_pause" can be used for the cs_etm | ||
43 | +PMU event. As its name suggests, it directs the driver to update the | ||
44 | +buffer when the AUX trace is paused. By default, this feature is | ||
45 | +disabled until users explicitly specify "update_buf_on_pause=1". | ||
46 | + | ||
47 | +TRBE has interrupt handling. To avoid the race condition between the | ||
48 | +AUX pause or resume invoked in NMI and TRBE interrupt handler, the | ||
49 | +driver reports a failure if users try to use "update_buf_on_pause=1" on | ||
50 | +TRBE. | ||
51 | + | ||
52 | +Example for triggering AUX pause and resume with ftrace tracepoints:: | 38 | +Example for triggering AUX pause and resume with ftrace tracepoints:: |
53 | + | 39 | + |
54 | + perf record -e cs_etm/aux-action=start-paused/k,syscalls:sys_enter_openat/aux-action=resume/,syscalls:sys_exit_openat/aux-action=pause/ ls | 40 | + perf record -e cs_etm/aux-action=start-paused/k,syscalls:sys_enter_openat/aux-action=resume/,syscalls:sys_exit_openat/aux-action=pause/ ls |
55 | + | 41 | + |
56 | +Example for triggering AUX pause and resume with PMU event:: | 42 | +Example for triggering AUX pause and resume with PMU event:: |
57 | + | 43 | + |
58 | + perf record -a -e cs_etm/aux-action=start-paused/k \ | 44 | + perf record -a -e cs_etm/aux-action=start-paused/k \ |
59 | + -e cycles/aux-action=pause,period=10000000/ \ | 45 | + -e cycles/aux-action=pause,period=10000000/ \ |
60 | + -e cycles/aux-action=resume,period=1050000/ -- sleep 1 | 46 | + -e cycles/aux-action=resume,period=1050000/ -- sleep 1 |
61 | + | 47 | + |
62 | +Example for updating buffer on AUX pause:: | ||
63 | + | ||
64 | + perf record -a -e cs_etm/aux-action=start-paused,update_buf_on_pause=1/ \ | ||
65 | + -e cycles/aux-action=pause,period=10000000/ \ | ||
66 | + -e cycles/aux-action=resume,period=1050000/ -- sleep 1 | ||
67 | + | ||
68 | Perf test - Verify kernel and userspace perf CoreSight work | 48 | Perf test - Verify kernel and userspace perf CoreSight work |
69 | ----------------------------------------------------------- | 49 | ----------------------------------------------------------- |
70 | 50 | ||
71 | -- | 51 | -- |
72 | 2.34.1 | 52 | 2.34.1 | diff view generated by jsdifflib |