aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwtracing
diff options
context:
space:
mode:
authorMathieu Poirier <mathieu.poirier@linaro.org>2016-08-25 17:19:18 -0400
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2016-08-31 07:05:44 -0400
commite97b1c6a8dba967a7c272c3b976ed6d59c7bfad7 (patch)
treefd2e78072c8c8a88c2de724d1842b829c6a7d9fb /drivers/hwtracing
parent2703d74c1313271ba78439b0796444add6a9328f (diff)
coresight: etm4x: adding configurable start/stop filtering
With this patch we add start/stop filtering as specified on the perf cmd line. When the IP matches the start address trace generation gets triggered. The stop condition is achieved when the IP matches the stop address. Signed-off-by: Mathieu Poirier <mathieu.poirier@linaro.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/hwtracing')
-rw-r--r--drivers/hwtracing/coresight/coresight-etm4x.c71
1 files changed, 71 insertions, 0 deletions
diff --git a/drivers/hwtracing/coresight/coresight-etm4x.c b/drivers/hwtracing/coresight/coresight-etm4x.c
index ebaefb45130f..4db8d6a4d0cb 100644
--- a/drivers/hwtracing/coresight/coresight-etm4x.c
+++ b/drivers/hwtracing/coresight/coresight-etm4x.c
@@ -335,12 +335,25 @@ static void etm4_disable_hw(void *info)
335static int etm4_disable_perf(struct coresight_device *csdev, 335static int etm4_disable_perf(struct coresight_device *csdev,
336 struct perf_event *event) 336 struct perf_event *event)
337{ 337{
338 u32 control;
339 struct etm_filters *filters = event->hw.addr_filters;
338 struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent); 340 struct etmv4_drvdata *drvdata = dev_get_drvdata(csdev->dev.parent);
339 341
340 if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id())) 342 if (WARN_ON_ONCE(drvdata->cpu != smp_processor_id()))
341 return -EINVAL; 343 return -EINVAL;
342 344
343 etm4_disable_hw(drvdata); 345 etm4_disable_hw(drvdata);
346
347 /*
348 * Check if the start/stop logic was active when the unit was stopped.
349 * That way we can re-enable the start/stop logic when the process is
350 * scheduled again. Configuration of the start/stop logic happens in
351 * function etm4_set_event_filters().
352 */
353 control = readl_relaxed(drvdata->base + TRCVICTLR);
354 /* TRCVICTLR::SSSTATUS, bit[9] */
355 filters->ssstatus = (control & BIT(9));
356
344 return 0; 357 return 0;
345} 358}
346 359
@@ -657,6 +670,27 @@ static void etm4_set_comparator_filter(struct etmv4_config *config,
657 config->viiectlr |= BIT(comparator / 2); 670 config->viiectlr |= BIT(comparator / 2);
658} 671}
659 672
673static void etm4_set_start_stop_filter(struct etmv4_config *config,
674 u64 address, int comparator,
675 enum etm_addr_type type)
676{
677 int shift;
678 u64 access_type = etm4_get_access_type(config);
679
680 /* Configure the comparator */
681 config->addr_val[comparator] = address;
682 config->addr_acc[comparator] = access_type;
683 config->addr_type[comparator] = type;
684
685 /*
686 * Configure ViewInst Start-Stop control register.
687 * Addresses configured to start tracing go from bit 0 to n-1,
688 * while those configured to stop tracing from 16 to 16 + n-1.
689 */
690 shift = (type == ETM_ADDR_TYPE_START ? 0 : 16);
691 config->vissctlr |= BIT(shift + comparator);
692}
693
660static void etm4_set_default_filter(struct etmv4_config *config) 694static void etm4_set_default_filter(struct etmv4_config *config)
661{ 695{
662 u64 start, stop; 696 u64 start, stop;
@@ -721,6 +755,14 @@ static int etm4_get_next_comparator(struct etmv4_drvdata *drvdata, u32 type)
721 /* Address range comparators go in pairs */ 755 /* Address range comparators go in pairs */
722 index += 2; 756 index += 2;
723 break; 757 break;
758 case ETM_ADDR_TYPE_START:
759 case ETM_ADDR_TYPE_STOP:
760 if (config->addr_type[index] == ETM_ADDR_TYPE_NONE)
761 return index;
762
763 /* Start/stop address can have odd indexes */
764 index += 1;
765 break;
724 default: 766 default:
725 return -EINVAL; 767 return -EINVAL;
726 } 768 }
@@ -734,6 +776,7 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
734 struct perf_event *event) 776 struct perf_event *event)
735{ 777{
736 int i, comparator, ret = 0; 778 int i, comparator, ret = 0;
779 u64 address;
737 struct etmv4_config *config = &drvdata->config; 780 struct etmv4_config *config = &drvdata->config;
738 struct etm_filters *filters = event->hw.addr_filters; 781 struct etm_filters *filters = event->hw.addr_filters;
739 782
@@ -776,6 +819,34 @@ static int etm4_set_event_filters(struct etmv4_drvdata *drvdata,
776 /* No start-stop filtering for ViewInst */ 819 /* No start-stop filtering for ViewInst */
777 config->vissctlr = 0x0; 820 config->vissctlr = 0x0;
778 break; 821 break;
822 case ETM_ADDR_TYPE_START:
823 case ETM_ADDR_TYPE_STOP:
824 /* Get the right start or stop address */
825 address = (type == ETM_ADDR_TYPE_START ?
826 filter->start_addr :
827 filter->stop_addr);
828
829 /* Configure comparator */
830 etm4_set_start_stop_filter(config, address,
831 comparator, type);
832
833 /*
834 * If filters::ssstatus == 1, trace acquisition was
835 * started but the process was yanked away before the
836 * the stop address was hit. As such the start/stop
837 * logic needs to be re-started so that tracing can
838 * resume where it left.
839 *
840 * The start/stop logic status when a process is
841 * scheduled out is checked in function
842 * etm4_disable_perf().
843 */
844 if (filters->ssstatus)
845 config->vinst_ctrl |= BIT(9);
846
847 /* No include/exclude filtering for ViewInst */
848 config->viiectlr = 0x0;
849 break;
779 default: 850 default:
780 ret = -EINVAL; 851 ret = -EINVAL;
781 goto out; 852 goto out;