perf_trace_counters.h 4.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164
  1. /* Copyright (c) 2013, The Linux Foundation. All rights reserved.
  2. *
  3. * This program is free software; you can redistribute it and/or modify
  4. * it under the terms of the GNU General Public License version 2 and
  5. * only version 2 as published by the Free Software Foundation.
  6. *
  7. * This program is distributed in the hope that it will be useful,
  8. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. * GNU General Public License for more details.
  11. */
  12. #undef TRACE_SYSTEM
  13. #define TRACE_SYSTEM perf_trace_counters
  14. #if !defined(_PERF_TRACE_COUNTERS_H_) || defined(TRACE_HEADER_MULTI_READ)
  15. #define _PERF_TRACE_COUNTERS_H_
  16. /* Ctr index for PMCNTENSET/CLR */
  17. #define CC 0x80000000
  18. #define C0 0x1
  19. #define C1 0x2
  20. #define C2 0x4
  21. #define C3 0x8
  22. #define C_ALL (CC | C0 | C1 | C2 | C3)
  23. #define NUM_L1_CTRS 4
  24. #define NUM_L2_PERCPU 2
  25. #include <linux/sched.h>
  26. #include <linux/cpumask.h>
  27. #include <linux/tracepoint.h>
  28. #include <mach/msm-krait-l2-accessors.h>
  29. DECLARE_PER_CPU(u32, previous_ccnt);
  30. DECLARE_PER_CPU(u32[NUM_L1_CTRS], previous_l1_cnts);
  31. DECLARE_PER_CPU(u32[NUM_L2_PERCPU], previous_l2_cnts);
  32. TRACE_EVENT(sched_switch_with_ctrs,
  33. TP_PROTO(pid_t prev, pid_t next),
  34. TP_ARGS(prev, next),
  35. TP_STRUCT__entry(
  36. __field(pid_t, old_pid)
  37. __field(pid_t, new_pid)
  38. __field(u32, cctr)
  39. __field(u32, ctr0)
  40. __field(u32, ctr1)
  41. __field(u32, ctr2)
  42. __field(u32, ctr3)
  43. __field(u32, lctr0)
  44. __field(u32, lctr1)
  45. ),
  46. TP_fast_assign(
  47. u32 cpu = smp_processor_id();
  48. u32 idx;
  49. u32 i;
  50. u32 counter_reg;
  51. u32 val;
  52. u32 cnten_val;
  53. u32 num_l2ctrs;
  54. u32 num_cores = nr_cpu_ids;
  55. u32 total_ccnt = 0;
  56. u32 total_cnt = 0;
  57. u32 delta_l1_cnts[NUM_L1_CTRS];
  58. u32 delta_l2_cnts[NUM_L2_PERCPU];
  59. __entry->old_pid = prev;
  60. __entry->new_pid = next;
  61. val = get_l2_indirect_reg(L2PMCR);
  62. num_l2ctrs = ((val >> 11) & 0x1f) + 1;
  63. /* Read PMCNTENSET */
  64. asm volatile("mrc p15, 0, %0, c9, c12, 1"
  65. : "=r"(cnten_val));
  66. /* Disable all the counters that were enabled */
  67. asm volatile("mcr p15, 0, %0, c9, c12, 2"
  68. : : "r"(cnten_val));
  69. if (cnten_val & CC) {
  70. /* Read value */
  71. asm volatile("mrc p15, 0, %0, c9, c13, 0"
  72. : "=r"(total_ccnt));
  73. __entry->cctr = total_ccnt -
  74. per_cpu(previous_ccnt, cpu);
  75. per_cpu(previous_ccnt, cpu) = total_ccnt;
  76. }
  77. for (i = 0; i < NUM_L1_CTRS; i++) {
  78. if (cnten_val & (1 << i)) {
  79. /* Select */
  80. asm volatile(
  81. "mcr p15, 0, %0, c9, c12, 5"
  82. : : "r"(i));
  83. /* Read value */
  84. asm volatile(
  85. "mrc p15, 0, %0, c9, c13, 2"
  86. : "=r"(total_cnt));
  87. delta_l1_cnts[i] = total_cnt -
  88. per_cpu(previous_l1_cnts[i], cpu);
  89. per_cpu(previous_l1_cnts[i], cpu) =
  90. total_cnt;
  91. } else
  92. delta_l1_cnts[i] = 0;
  93. }
  94. /* Enable all the counters that were disabled */
  95. asm volatile("mcr p15, 0, %0, c9, c12, 1"
  96. : : "r"(cnten_val));
  97. /* L2 counters */
  98. /* Assign L2 counters to cores sequentially starting
  99. * from zero. A core could have multiple L2 counters
  100. * allocated if # L2 counters is more than the # cores
  101. */
  102. cnten_val = get_l2_indirect_reg(L2PMCNTENSET);
  103. for (i = 0; i < NUM_L2_PERCPU; i++) {
  104. idx = cpu + (num_cores * i);
  105. if (idx < num_l2ctrs &&
  106. (cnten_val & (1 << idx))) {
  107. /* Disable */
  108. set_l2_indirect_reg(L2PMCNTENCLR,
  109. (1 << idx));
  110. /* L2PMEVCNTR values go from 0x421,
  111. * 0x431..
  112. * So we multiply idx by 16 to get the
  113. * counter reg value
  114. */
  115. counter_reg = (idx * 16) +
  116. IA_L2PMXEVCNTR_BASE;
  117. total_cnt =
  118. get_l2_indirect_reg(counter_reg);
  119. /* Enable */
  120. set_l2_indirect_reg(L2PMCNTENSET,
  121. (1 << idx));
  122. delta_l2_cnts[i] = total_cnt -
  123. per_cpu(previous_l2_cnts[i], cpu);
  124. per_cpu(previous_l2_cnts[i], cpu) =
  125. total_cnt;
  126. } else
  127. delta_l2_cnts[i] = 0;
  128. }
  129. __entry->ctr0 = delta_l1_cnts[0];
  130. __entry->ctr1 = delta_l1_cnts[1];
  131. __entry->ctr2 = delta_l1_cnts[2];
  132. __entry->ctr3 = delta_l1_cnts[3];
  133. __entry->lctr0 = delta_l2_cnts[0];
  134. __entry->lctr1 = delta_l2_cnts[1];
  135. ),
  136. TP_printk("prev_pid=%d, next_pid=%d, CCNTR: %u, CTR0: %u," \
  137. " CTR1: %u, CTR2: %u, CTR3: %u," \
  138. " L2CTR0: %u, L2CTR1: %u",
  139. __entry->old_pid, __entry->new_pid,
  140. __entry->cctr, __entry->ctr0, __entry->ctr1,
  141. __entry->ctr2, __entry->ctr3,
  142. __entry->lctr0, __entry->lctr1)
  143. );
  144. #endif
  145. #undef TRACE_INCLUDE_PATH
  146. #define TRACE_INCLUDE_PATH ../../arch/arm/mach-msm
  147. #define TRACE_INCLUDE_FILE perf_trace_counters
  148. #include <trace/define_trace.h>