msr.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263
  1. #include <linux/perf_event.h>
  2. #include <asm/intel-family.h>
  3. enum perf_msr_id {
  4. PERF_MSR_TSC = 0,
  5. PERF_MSR_APERF = 1,
  6. PERF_MSR_MPERF = 2,
  7. PERF_MSR_PPERF = 3,
  8. PERF_MSR_SMI = 4,
  9. PERF_MSR_PTSC = 5,
  10. PERF_MSR_IRPERF = 6,
  11. PERF_MSR_EVENT_MAX,
  12. };
  13. static bool test_aperfmperf(int idx)
  14. {
  15. return boot_cpu_has(X86_FEATURE_APERFMPERF);
  16. }
  17. static bool test_ptsc(int idx)
  18. {
  19. return boot_cpu_has(X86_FEATURE_PTSC);
  20. }
  21. static bool test_irperf(int idx)
  22. {
  23. return boot_cpu_has(X86_FEATURE_IRPERF);
  24. }
  25. static bool test_intel(int idx)
  26. {
  27. if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
  28. boot_cpu_data.x86 != 6)
  29. return false;
  30. switch (boot_cpu_data.x86_model) {
  31. case INTEL_FAM6_NEHALEM:
  32. case INTEL_FAM6_NEHALEM_G:
  33. case INTEL_FAM6_NEHALEM_EP:
  34. case INTEL_FAM6_NEHALEM_EX:
  35. case INTEL_FAM6_WESTMERE:
  36. case INTEL_FAM6_WESTMERE_EP:
  37. case INTEL_FAM6_WESTMERE_EX:
  38. case INTEL_FAM6_SANDYBRIDGE:
  39. case INTEL_FAM6_SANDYBRIDGE_X:
  40. case INTEL_FAM6_IVYBRIDGE:
  41. case INTEL_FAM6_IVYBRIDGE_X:
  42. case INTEL_FAM6_HASWELL_CORE:
  43. case INTEL_FAM6_HASWELL_X:
  44. case INTEL_FAM6_HASWELL_ULT:
  45. case INTEL_FAM6_HASWELL_GT3E:
  46. case INTEL_FAM6_BROADWELL_CORE:
  47. case INTEL_FAM6_BROADWELL_XEON_D:
  48. case INTEL_FAM6_BROADWELL_GT3E:
  49. case INTEL_FAM6_BROADWELL_X:
  50. case INTEL_FAM6_ATOM_SILVERMONT1:
  51. case INTEL_FAM6_ATOM_SILVERMONT2:
  52. case INTEL_FAM6_ATOM_AIRMONT:
  53. if (idx == PERF_MSR_SMI)
  54. return true;
  55. break;
  56. case INTEL_FAM6_SKYLAKE_MOBILE:
  57. case INTEL_FAM6_SKYLAKE_DESKTOP:
  58. case INTEL_FAM6_SKYLAKE_X:
  59. case INTEL_FAM6_KABYLAKE_MOBILE:
  60. case INTEL_FAM6_KABYLAKE_DESKTOP:
  61. if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
  62. return true;
  63. break;
  64. }
  65. return false;
  66. }
  67. struct perf_msr {
  68. u64 msr;
  69. struct perf_pmu_events_attr *attr;
  70. bool (*test)(int idx);
  71. };
  72. PMU_EVENT_ATTR_STRING(tsc, evattr_tsc, "event=0x00");
  73. PMU_EVENT_ATTR_STRING(aperf, evattr_aperf, "event=0x01");
  74. PMU_EVENT_ATTR_STRING(mperf, evattr_mperf, "event=0x02");
  75. PMU_EVENT_ATTR_STRING(pperf, evattr_pperf, "event=0x03");
  76. PMU_EVENT_ATTR_STRING(smi, evattr_smi, "event=0x04");
  77. PMU_EVENT_ATTR_STRING(ptsc, evattr_ptsc, "event=0x05");
  78. PMU_EVENT_ATTR_STRING(irperf, evattr_irperf, "event=0x06");
  79. static struct perf_msr msr[] = {
  80. [PERF_MSR_TSC] = { 0, &evattr_tsc, NULL, },
  81. [PERF_MSR_APERF] = { MSR_IA32_APERF, &evattr_aperf, test_aperfmperf, },
  82. [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &evattr_mperf, test_aperfmperf, },
  83. [PERF_MSR_PPERF] = { MSR_PPERF, &evattr_pperf, test_intel, },
  84. [PERF_MSR_SMI] = { MSR_SMI_COUNT, &evattr_smi, test_intel, },
  85. [PERF_MSR_PTSC] = { MSR_F15H_PTSC, &evattr_ptsc, test_ptsc, },
  86. [PERF_MSR_IRPERF] = { MSR_F17H_IRPERF, &evattr_irperf, test_irperf, },
  87. };
  88. static struct attribute *events_attrs[PERF_MSR_EVENT_MAX + 1] = {
  89. NULL,
  90. };
  91. static struct attribute_group events_attr_group = {
  92. .name = "events",
  93. .attrs = events_attrs,
  94. };
  95. PMU_FORMAT_ATTR(event, "config:0-63");
  96. static struct attribute *format_attrs[] = {
  97. &format_attr_event.attr,
  98. NULL,
  99. };
  100. static struct attribute_group format_attr_group = {
  101. .name = "format",
  102. .attrs = format_attrs,
  103. };
  104. static const struct attribute_group *attr_groups[] = {
  105. &events_attr_group,
  106. &format_attr_group,
  107. NULL,
  108. };
  109. static int msr_event_init(struct perf_event *event)
  110. {
  111. u64 cfg = event->attr.config;
  112. if (event->attr.type != event->pmu->type)
  113. return -ENOENT;
  114. if (cfg >= PERF_MSR_EVENT_MAX)
  115. return -EINVAL;
  116. /* unsupported modes and filters */
  117. if (event->attr.exclude_user ||
  118. event->attr.exclude_kernel ||
  119. event->attr.exclude_hv ||
  120. event->attr.exclude_idle ||
  121. event->attr.exclude_host ||
  122. event->attr.exclude_guest ||
  123. event->attr.sample_period) /* no sampling */
  124. return -EINVAL;
  125. if (!msr[cfg].attr)
  126. return -EINVAL;
  127. event->hw.idx = -1;
  128. event->hw.event_base = msr[cfg].msr;
  129. event->hw.config = cfg;
  130. return 0;
  131. }
  132. static inline u64 msr_read_counter(struct perf_event *event)
  133. {
  134. u64 now;
  135. if (event->hw.event_base)
  136. rdmsrl(event->hw.event_base, now);
  137. else
  138. rdtscll(now);
  139. return now;
  140. }
  141. static void msr_event_update(struct perf_event *event)
  142. {
  143. u64 prev, now;
  144. s64 delta;
  145. /* Careful, an NMI might modify the previous event value. */
  146. again:
  147. prev = local64_read(&event->hw.prev_count);
  148. now = msr_read_counter(event);
  149. if (local64_cmpxchg(&event->hw.prev_count, prev, now) != prev)
  150. goto again;
  151. delta = now - prev;
  152. if (unlikely(event->hw.event_base == MSR_SMI_COUNT))
  153. delta = sign_extend64(delta, 31);
  154. local64_add(delta, &event->count);
  155. }
  156. static void msr_event_start(struct perf_event *event, int flags)
  157. {
  158. u64 now;
  159. now = msr_read_counter(event);
  160. local64_set(&event->hw.prev_count, now);
  161. }
  162. static void msr_event_stop(struct perf_event *event, int flags)
  163. {
  164. msr_event_update(event);
  165. }
  166. static void msr_event_del(struct perf_event *event, int flags)
  167. {
  168. msr_event_stop(event, PERF_EF_UPDATE);
  169. }
  170. static int msr_event_add(struct perf_event *event, int flags)
  171. {
  172. if (flags & PERF_EF_START)
  173. msr_event_start(event, flags);
  174. return 0;
  175. }
  176. static struct pmu pmu_msr = {
  177. .task_ctx_nr = perf_sw_context,
  178. .attr_groups = attr_groups,
  179. .event_init = msr_event_init,
  180. .add = msr_event_add,
  181. .del = msr_event_del,
  182. .start = msr_event_start,
  183. .stop = msr_event_stop,
  184. .read = msr_event_update,
  185. .capabilities = PERF_PMU_CAP_NO_INTERRUPT,
  186. };
  187. static int __init msr_init(void)
  188. {
  189. int i, j = 0;
  190. if (!boot_cpu_has(X86_FEATURE_TSC)) {
  191. pr_cont("no MSR PMU driver.\n");
  192. return 0;
  193. }
  194. /* Probe the MSRs. */
  195. for (i = PERF_MSR_TSC + 1; i < PERF_MSR_EVENT_MAX; i++) {
  196. u64 val;
  197. /*
  198. * Virt sucks arse; you cannot tell if a R/O MSR is present :/
  199. */
  200. if (!msr[i].test(i) || rdmsrl_safe(msr[i].msr, &val))
  201. msr[i].attr = NULL;
  202. }
  203. /* List remaining MSRs in the sysfs attrs. */
  204. for (i = 0; i < PERF_MSR_EVENT_MAX; i++) {
  205. if (msr[i].attr)
  206. events_attrs[j++] = &msr[i].attr->attr.attr;
  207. }
  208. events_attrs[j] = NULL;
  209. perf_pmu_register(&pmu_msr, "msr", -1);
  210. return 0;
  211. }
  212. device_initcall(msr_init);