msr.c 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316
  1. // SPDX-License-Identifier: GPL-2.0
  2. #include <linux/perf_event.h>
  3. #include <linux/sysfs.h>
  4. #include <linux/nospec.h>
  5. #include <asm/intel-family.h>
  6. #include "probe.h"
  7. enum perf_msr_id {
  8. PERF_MSR_TSC = 0,
  9. PERF_MSR_APERF = 1,
  10. PERF_MSR_MPERF = 2,
  11. PERF_MSR_PPERF = 3,
  12. PERF_MSR_SMI = 4,
  13. PERF_MSR_PTSC = 5,
  14. PERF_MSR_IRPERF = 6,
  15. PERF_MSR_THERM = 7,
  16. PERF_MSR_EVENT_MAX,
  17. };
  18. static bool test_aperfmperf(int idx, void *data)
  19. {
  20. return boot_cpu_has(X86_FEATURE_APERFMPERF);
  21. }
  22. static bool test_ptsc(int idx, void *data)
  23. {
  24. return boot_cpu_has(X86_FEATURE_PTSC);
  25. }
  26. static bool test_irperf(int idx, void *data)
  27. {
  28. return boot_cpu_has(X86_FEATURE_IRPERF);
  29. }
  30. static bool test_therm_status(int idx, void *data)
  31. {
  32. return boot_cpu_has(X86_FEATURE_DTHERM);
  33. }
  34. static bool test_intel(int idx, void *data)
  35. {
  36. if (boot_cpu_data.x86_vendor != X86_VENDOR_INTEL ||
  37. boot_cpu_data.x86 != 6)
  38. return false;
  39. switch (boot_cpu_data.x86_model) {
  40. case INTEL_FAM6_NEHALEM:
  41. case INTEL_FAM6_NEHALEM_G:
  42. case INTEL_FAM6_NEHALEM_EP:
  43. case INTEL_FAM6_NEHALEM_EX:
  44. case INTEL_FAM6_WESTMERE:
  45. case INTEL_FAM6_WESTMERE_EP:
  46. case INTEL_FAM6_WESTMERE_EX:
  47. case INTEL_FAM6_SANDYBRIDGE:
  48. case INTEL_FAM6_SANDYBRIDGE_X:
  49. case INTEL_FAM6_IVYBRIDGE:
  50. case INTEL_FAM6_IVYBRIDGE_X:
  51. case INTEL_FAM6_HASWELL:
  52. case INTEL_FAM6_HASWELL_X:
  53. case INTEL_FAM6_HASWELL_L:
  54. case INTEL_FAM6_HASWELL_G:
  55. case INTEL_FAM6_BROADWELL:
  56. case INTEL_FAM6_BROADWELL_D:
  57. case INTEL_FAM6_BROADWELL_G:
  58. case INTEL_FAM6_BROADWELL_X:
  59. case INTEL_FAM6_SAPPHIRERAPIDS_X:
  60. case INTEL_FAM6_EMERALDRAPIDS_X:
  61. case INTEL_FAM6_ATOM_SILVERMONT:
  62. case INTEL_FAM6_ATOM_SILVERMONT_D:
  63. case INTEL_FAM6_ATOM_AIRMONT:
  64. case INTEL_FAM6_ATOM_GOLDMONT:
  65. case INTEL_FAM6_ATOM_GOLDMONT_D:
  66. case INTEL_FAM6_ATOM_GOLDMONT_PLUS:
  67. case INTEL_FAM6_ATOM_TREMONT_D:
  68. case INTEL_FAM6_ATOM_TREMONT:
  69. case INTEL_FAM6_ATOM_TREMONT_L:
  70. case INTEL_FAM6_XEON_PHI_KNL:
  71. case INTEL_FAM6_XEON_PHI_KNM:
  72. if (idx == PERF_MSR_SMI)
  73. return true;
  74. break;
  75. case INTEL_FAM6_SKYLAKE_L:
  76. case INTEL_FAM6_SKYLAKE:
  77. case INTEL_FAM6_SKYLAKE_X:
  78. case INTEL_FAM6_KABYLAKE_L:
  79. case INTEL_FAM6_KABYLAKE:
  80. case INTEL_FAM6_COMETLAKE_L:
  81. case INTEL_FAM6_COMETLAKE:
  82. case INTEL_FAM6_ICELAKE_L:
  83. case INTEL_FAM6_ICELAKE:
  84. case INTEL_FAM6_ICELAKE_X:
  85. case INTEL_FAM6_ICELAKE_D:
  86. case INTEL_FAM6_TIGERLAKE_L:
  87. case INTEL_FAM6_TIGERLAKE:
  88. case INTEL_FAM6_ROCKETLAKE:
  89. case INTEL_FAM6_ALDERLAKE:
  90. case INTEL_FAM6_ALDERLAKE_L:
  91. case INTEL_FAM6_ALDERLAKE_N:
  92. case INTEL_FAM6_RAPTORLAKE:
  93. case INTEL_FAM6_RAPTORLAKE_P:
  94. case INTEL_FAM6_RAPTORLAKE_S:
  95. case INTEL_FAM6_METEORLAKE:
  96. case INTEL_FAM6_METEORLAKE_L:
  97. if (idx == PERF_MSR_SMI || idx == PERF_MSR_PPERF)
  98. return true;
  99. break;
  100. }
  101. return false;
  102. }
  103. PMU_EVENT_ATTR_STRING(tsc, attr_tsc, "event=0x00" );
  104. PMU_EVENT_ATTR_STRING(aperf, attr_aperf, "event=0x01" );
  105. PMU_EVENT_ATTR_STRING(mperf, attr_mperf, "event=0x02" );
  106. PMU_EVENT_ATTR_STRING(pperf, attr_pperf, "event=0x03" );
  107. PMU_EVENT_ATTR_STRING(smi, attr_smi, "event=0x04" );
  108. PMU_EVENT_ATTR_STRING(ptsc, attr_ptsc, "event=0x05" );
  109. PMU_EVENT_ATTR_STRING(irperf, attr_irperf, "event=0x06" );
  110. PMU_EVENT_ATTR_STRING(cpu_thermal_margin, attr_therm, "event=0x07" );
  111. PMU_EVENT_ATTR_STRING(cpu_thermal_margin.snapshot, attr_therm_snap, "1" );
  112. PMU_EVENT_ATTR_STRING(cpu_thermal_margin.unit, attr_therm_unit, "C" );
  113. static unsigned long msr_mask;
  114. PMU_EVENT_GROUP(events, aperf);
  115. PMU_EVENT_GROUP(events, mperf);
  116. PMU_EVENT_GROUP(events, pperf);
  117. PMU_EVENT_GROUP(events, smi);
  118. PMU_EVENT_GROUP(events, ptsc);
  119. PMU_EVENT_GROUP(events, irperf);
  120. static struct attribute *attrs_therm[] = {
  121. &attr_therm.attr.attr,
  122. &attr_therm_snap.attr.attr,
  123. &attr_therm_unit.attr.attr,
  124. NULL,
  125. };
  126. static struct attribute_group group_therm = {
  127. .name = "events",
  128. .attrs = attrs_therm,
  129. };
  130. static struct perf_msr msr[] = {
  131. [PERF_MSR_TSC] = { .no_check = true, },
  132. [PERF_MSR_APERF] = { MSR_IA32_APERF, &group_aperf, test_aperfmperf, },
  133. [PERF_MSR_MPERF] = { MSR_IA32_MPERF, &group_mperf, test_aperfmperf, },
  134. [PERF_MSR_PPERF] = { MSR_PPERF, &group_pperf, test_intel, },
  135. [PERF_MSR_SMI] = { MSR_SMI_COUNT, &group_smi, test_intel, },
  136. [PERF_MSR_PTSC] = { MSR_F15H_PTSC, &group_ptsc, test_ptsc, },
  137. [PERF_MSR_IRPERF] = { MSR_F17H_IRPERF, &group_irperf, test_irperf, },
  138. [PERF_MSR_THERM] = { MSR_IA32_THERM_STATUS, &group_therm, test_therm_status, },
  139. };
  140. static struct attribute *events_attrs[] = {
  141. &attr_tsc.attr.attr,
  142. NULL,
  143. };
  144. static struct attribute_group events_attr_group = {
  145. .name = "events",
  146. .attrs = events_attrs,
  147. };
  148. PMU_FORMAT_ATTR(event, "config:0-63");
  149. static struct attribute *format_attrs[] = {
  150. &format_attr_event.attr,
  151. NULL,
  152. };
  153. static struct attribute_group format_attr_group = {
  154. .name = "format",
  155. .attrs = format_attrs,
  156. };
  157. static const struct attribute_group *attr_groups[] = {
  158. &events_attr_group,
  159. &format_attr_group,
  160. NULL,
  161. };
  162. static const struct attribute_group *attr_update[] = {
  163. &group_aperf,
  164. &group_mperf,
  165. &group_pperf,
  166. &group_smi,
  167. &group_ptsc,
  168. &group_irperf,
  169. &group_therm,
  170. NULL,
  171. };
  172. static int msr_event_init(struct perf_event *event)
  173. {
  174. u64 cfg = event->attr.config;
  175. if (event->attr.type != event->pmu->type)
  176. return -ENOENT;
  177. /* unsupported modes and filters */
  178. if (event->attr.sample_period) /* no sampling */
  179. return -EINVAL;
  180. if (cfg >= PERF_MSR_EVENT_MAX)
  181. return -EINVAL;
  182. cfg = array_index_nospec((unsigned long)cfg, PERF_MSR_EVENT_MAX);
  183. if (!(msr_mask & (1 << cfg)))
  184. return -EINVAL;
  185. event->hw.idx = -1;
  186. event->hw.event_base = msr[cfg].msr;
  187. event->hw.config = cfg;
  188. return 0;
  189. }
  190. static inline u64 msr_read_counter(struct perf_event *event)
  191. {
  192. u64 now;
  193. if (event->hw.event_base)
  194. rdmsrl(event->hw.event_base, now);
  195. else
  196. now = rdtsc_ordered();
  197. return now;
  198. }
  199. static void msr_event_update(struct perf_event *event)
  200. {
  201. u64 prev, now;
  202. s64 delta;
  203. /* Careful, an NMI might modify the previous event value: */
  204. again:
  205. prev = local64_read(&event->hw.prev_count);
  206. now = msr_read_counter(event);
  207. if (local64_cmpxchg(&event->hw.prev_count, prev, now) != prev)
  208. goto again;
  209. delta = now - prev;
  210. if (unlikely(event->hw.event_base == MSR_SMI_COUNT)) {
  211. delta = sign_extend64(delta, 31);
  212. local64_add(delta, &event->count);
  213. } else if (unlikely(event->hw.event_base == MSR_IA32_THERM_STATUS)) {
  214. /* If valid, extract digital readout, otherwise set to -1: */
  215. now = now & (1ULL << 31) ? (now >> 16) & 0x3f : -1;
  216. local64_set(&event->count, now);
  217. } else {
  218. local64_add(delta, &event->count);
  219. }
  220. }
  221. static void msr_event_start(struct perf_event *event, int flags)
  222. {
  223. u64 now = msr_read_counter(event);
  224. local64_set(&event->hw.prev_count, now);
  225. }
  226. static void msr_event_stop(struct perf_event *event, int flags)
  227. {
  228. msr_event_update(event);
  229. }
  230. static void msr_event_del(struct perf_event *event, int flags)
  231. {
  232. msr_event_stop(event, PERF_EF_UPDATE);
  233. }
  234. static int msr_event_add(struct perf_event *event, int flags)
  235. {
  236. if (flags & PERF_EF_START)
  237. msr_event_start(event, flags);
  238. return 0;
  239. }
  240. static struct pmu pmu_msr = {
  241. .task_ctx_nr = perf_sw_context,
  242. .attr_groups = attr_groups,
  243. .event_init = msr_event_init,
  244. .add = msr_event_add,
  245. .del = msr_event_del,
  246. .start = msr_event_start,
  247. .stop = msr_event_stop,
  248. .read = msr_event_update,
  249. .capabilities = PERF_PMU_CAP_NO_INTERRUPT | PERF_PMU_CAP_NO_EXCLUDE,
  250. .attr_update = attr_update,
  251. };
  252. static int __init msr_init(void)
  253. {
  254. if (!boot_cpu_has(X86_FEATURE_TSC)) {
  255. pr_cont("no MSR PMU driver.\n");
  256. return 0;
  257. }
  258. msr_mask = perf_msr_probe(msr, PERF_MSR_EVENT_MAX, true, NULL);
  259. perf_pmu_register(&pmu_msr, "msr", -1);
  260. return 0;
  261. }
  262. device_initcall(msr_init);