aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-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;