auxtrace.c 2.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright(C) 2015 Linaro Limited. All rights reserved.
  4. * Author: Mathieu Poirier <mathieu.poirier@linaro.org>
  5. */
  6. #include <stdbool.h>
  7. #include <linux/coresight-pmu.h>
  8. #include "../../util/auxtrace.h"
  9. #include "../../util/evlist.h"
  10. #include "../../util/pmu.h"
  11. #include "cs-etm.h"
  12. #include "arm-spe.h"
  13. static struct perf_pmu **find_all_arm_spe_pmus(int *nr_spes, int *err)
  14. {
  15. struct perf_pmu **arm_spe_pmus = NULL;
  16. int ret, i, nr_cpus = sysconf(_SC_NPROCESSORS_CONF);
  17. /* arm_spe_xxxxxxxxx\0 */
  18. char arm_spe_pmu_name[sizeof(ARM_SPE_PMU_NAME) + 10];
  19. arm_spe_pmus = zalloc(sizeof(struct perf_pmu *) * nr_cpus);
  20. if (!arm_spe_pmus) {
  21. pr_err("spes alloc failed\n");
  22. *err = -ENOMEM;
  23. return NULL;
  24. }
  25. for (i = 0; i < nr_cpus; i++) {
  26. ret = sprintf(arm_spe_pmu_name, "%s%d", ARM_SPE_PMU_NAME, i);
  27. if (ret < 0) {
  28. pr_err("sprintf failed\n");
  29. *err = -ENOMEM;
  30. return NULL;
  31. }
  32. arm_spe_pmus[*nr_spes] = perf_pmu__find(arm_spe_pmu_name);
  33. if (arm_spe_pmus[*nr_spes]) {
  34. pr_debug2("%s %d: arm_spe_pmu %d type %d name %s\n",
  35. __func__, __LINE__, *nr_spes,
  36. arm_spe_pmus[*nr_spes]->type,
  37. arm_spe_pmus[*nr_spes]->name);
  38. (*nr_spes)++;
  39. }
  40. }
  41. return arm_spe_pmus;
  42. }
  43. struct auxtrace_record
  44. *auxtrace_record__init(struct perf_evlist *evlist, int *err)
  45. {
  46. struct perf_pmu *cs_etm_pmu;
  47. struct perf_evsel *evsel;
  48. bool found_etm = false;
  49. bool found_spe = false;
  50. static struct perf_pmu **arm_spe_pmus = NULL;
  51. static int nr_spes = 0;
  52. int i = 0;
  53. if (!evlist)
  54. return NULL;
  55. cs_etm_pmu = perf_pmu__find(CORESIGHT_ETM_PMU_NAME);
  56. if (!arm_spe_pmus)
  57. arm_spe_pmus = find_all_arm_spe_pmus(&nr_spes, err);
  58. evlist__for_each_entry(evlist, evsel) {
  59. if (cs_etm_pmu &&
  60. evsel->attr.type == cs_etm_pmu->type)
  61. found_etm = true;
  62. if (!nr_spes)
  63. continue;
  64. for (i = 0; i < nr_spes; i++) {
  65. if (evsel->attr.type == arm_spe_pmus[i]->type) {
  66. found_spe = true;
  67. break;
  68. }
  69. }
  70. }
  71. if (found_etm && found_spe) {
  72. pr_err("Concurrent ARM Coresight ETM and SPE operation not currently supported\n");
  73. *err = -EOPNOTSUPP;
  74. return NULL;
  75. }
  76. if (found_etm)
  77. return cs_etm_record_init(err);
  78. #if defined(__aarch64__)
  79. if (found_spe)
  80. return arm_spe_recording_init(err, arm_spe_pmus[i]);
  81. #endif
  82. /*
  83. * Clear 'err' even if we haven't found an event - that way perf
  84. * record can still be used even if tracers aren't present. The NULL
  85. * return value will take care of telling the infrastructure HW tracing
  86. * isn't available.
  87. */
  88. *err = 0;
  89. return NULL;
  90. }