PageRenderTime 48ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/arch/x86/events/amd/iommu.c

https://github.com/tiwai/sound
C | 489 lines | 345 code | 89 blank | 55 comment | 32 complexity | 704b54d2b9ac9a987cd5500ad09ad824 MD5 | raw file
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2013 Advanced Micro Devices, Inc.
  4. *
  5. * Author: Steven Kinney <Steven.Kinney@amd.com>
  6. * Author: Suravee Suthikulpanit <Suraveee.Suthikulpanit@amd.com>
  7. *
  8. * Perf: amd_iommu - AMD IOMMU Performance Counter PMU implementation
  9. */
  10. #define pr_fmt(fmt) "perf/amd_iommu: " fmt
  11. #include <linux/perf_event.h>
  12. #include <linux/init.h>
  13. #include <linux/cpumask.h>
  14. #include <linux/slab.h>
  15. #include <linux/amd-iommu.h>
  16. #include "../perf_event.h"
  17. #include "iommu.h"
  18. /* iommu pmu conf masks */
  19. #define GET_CSOURCE(x) ((x)->conf & 0xFFULL)
  20. #define GET_DEVID(x) (((x)->conf >> 8) & 0xFFFFULL)
  21. #define GET_DOMID(x) (((x)->conf >> 24) & 0xFFFFULL)
  22. #define GET_PASID(x) (((x)->conf >> 40) & 0xFFFFFULL)
  23. /* iommu pmu conf1 masks */
  24. #define GET_DEVID_MASK(x) ((x)->conf1 & 0xFFFFULL)
  25. #define GET_DOMID_MASK(x) (((x)->conf1 >> 16) & 0xFFFFULL)
  26. #define GET_PASID_MASK(x) (((x)->conf1 >> 32) & 0xFFFFFULL)
  27. #define IOMMU_NAME_SIZE 16
  28. struct perf_amd_iommu {
  29. struct list_head list;
  30. struct pmu pmu;
  31. struct amd_iommu *iommu;
  32. char name[IOMMU_NAME_SIZE];
  33. u8 max_banks;
  34. u8 max_counters;
  35. u64 cntr_assign_mask;
  36. raw_spinlock_t lock;
  37. };
  38. static LIST_HEAD(perf_amd_iommu_list);
  39. /*---------------------------------------------
  40. * sysfs format attributes
  41. *---------------------------------------------*/
  42. PMU_FORMAT_ATTR(csource, "config:0-7");
  43. PMU_FORMAT_ATTR(devid, "config:8-23");
  44. PMU_FORMAT_ATTR(domid, "config:24-39");
  45. PMU_FORMAT_ATTR(pasid, "config:40-59");
  46. PMU_FORMAT_ATTR(devid_mask, "config1:0-15");
  47. PMU_FORMAT_ATTR(domid_mask, "config1:16-31");
  48. PMU_FORMAT_ATTR(pasid_mask, "config1:32-51");
  49. static struct attribute *iommu_format_attrs[] = {
  50. &format_attr_csource.attr,
  51. &format_attr_devid.attr,
  52. &format_attr_pasid.attr,
  53. &format_attr_domid.attr,
  54. &format_attr_devid_mask.attr,
  55. &format_attr_pasid_mask.attr,
  56. &format_attr_domid_mask.attr,
  57. NULL,
  58. };
  59. static struct attribute_group amd_iommu_format_group = {
  60. .name = "format",
  61. .attrs = iommu_format_attrs,
  62. };
  63. /*---------------------------------------------
  64. * sysfs events attributes
  65. *---------------------------------------------*/
  66. static struct attribute_group amd_iommu_events_group = {
  67. .name = "events",
  68. };
  69. struct amd_iommu_event_desc {
  70. struct device_attribute attr;
  71. const char *event;
  72. };
  73. static ssize_t _iommu_event_show(struct device *dev,
  74. struct device_attribute *attr, char *buf)
  75. {
  76. struct amd_iommu_event_desc *event =
  77. container_of(attr, struct amd_iommu_event_desc, attr);
  78. return sprintf(buf, "%s\n", event->event);
  79. }
  80. #define AMD_IOMMU_EVENT_DESC(_name, _event) \
  81. { \
  82. .attr = __ATTR(_name, 0444, _iommu_event_show, NULL), \
  83. .event = _event, \
  84. }
  85. static struct amd_iommu_event_desc amd_iommu_v2_event_descs[] = {
  86. AMD_IOMMU_EVENT_DESC(mem_pass_untrans, "csource=0x01"),
  87. AMD_IOMMU_EVENT_DESC(mem_pass_pretrans, "csource=0x02"),
  88. AMD_IOMMU_EVENT_DESC(mem_pass_excl, "csource=0x03"),
  89. AMD_IOMMU_EVENT_DESC(mem_target_abort, "csource=0x04"),
  90. AMD_IOMMU_EVENT_DESC(mem_trans_total, "csource=0x05"),
  91. AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pte_hit, "csource=0x06"),
  92. AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pte_mis, "csource=0x07"),
  93. AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pde_hit, "csource=0x08"),
  94. AMD_IOMMU_EVENT_DESC(mem_iommu_tlb_pde_mis, "csource=0x09"),
  95. AMD_IOMMU_EVENT_DESC(mem_dte_hit, "csource=0x0a"),
  96. AMD_IOMMU_EVENT_DESC(mem_dte_mis, "csource=0x0b"),
  97. AMD_IOMMU_EVENT_DESC(page_tbl_read_tot, "csource=0x0c"),
  98. AMD_IOMMU_EVENT_DESC(page_tbl_read_nst, "csource=0x0d"),
  99. AMD_IOMMU_EVENT_DESC(page_tbl_read_gst, "csource=0x0e"),
  100. AMD_IOMMU_EVENT_DESC(int_dte_hit, "csource=0x0f"),
  101. AMD_IOMMU_EVENT_DESC(int_dte_mis, "csource=0x10"),
  102. AMD_IOMMU_EVENT_DESC(cmd_processed, "csource=0x11"),
  103. AMD_IOMMU_EVENT_DESC(cmd_processed_inv, "csource=0x12"),
  104. AMD_IOMMU_EVENT_DESC(tlb_inv, "csource=0x13"),
  105. AMD_IOMMU_EVENT_DESC(ign_rd_wr_mmio_1ff8h, "csource=0x14"),
  106. AMD_IOMMU_EVENT_DESC(vapic_int_non_guest, "csource=0x15"),
  107. AMD_IOMMU_EVENT_DESC(vapic_int_guest, "csource=0x16"),
  108. AMD_IOMMU_EVENT_DESC(smi_recv, "csource=0x17"),
  109. AMD_IOMMU_EVENT_DESC(smi_blk, "csource=0x18"),
  110. { /* end: all zeroes */ },
  111. };
  112. /*---------------------------------------------
  113. * sysfs cpumask attributes
  114. *---------------------------------------------*/
  115. static cpumask_t iommu_cpumask;
  116. static ssize_t _iommu_cpumask_show(struct device *dev,
  117. struct device_attribute *attr,
  118. char *buf)
  119. {
  120. return cpumap_print_to_pagebuf(true, buf, &iommu_cpumask);
  121. }
  122. static DEVICE_ATTR(cpumask, S_IRUGO, _iommu_cpumask_show, NULL);
  123. static struct attribute *iommu_cpumask_attrs[] = {
  124. &dev_attr_cpumask.attr,
  125. NULL,
  126. };
  127. static struct attribute_group amd_iommu_cpumask_group = {
  128. .attrs = iommu_cpumask_attrs,
  129. };
  130. /*---------------------------------------------*/
  131. static int get_next_avail_iommu_bnk_cntr(struct perf_event *event)
  132. {
  133. struct perf_amd_iommu *piommu = container_of(event->pmu, struct perf_amd_iommu, pmu);
  134. int max_cntrs = piommu->max_counters;
  135. int max_banks = piommu->max_banks;
  136. u32 shift, bank, cntr;
  137. unsigned long flags;
  138. int retval;
  139. raw_spin_lock_irqsave(&piommu->lock, flags);
  140. for (bank = 0; bank < max_banks; bank++) {
  141. for (cntr = 0; cntr < max_cntrs; cntr++) {
  142. shift = bank + (bank*3) + cntr;
  143. if (piommu->cntr_assign_mask & BIT_ULL(shift)) {
  144. continue;
  145. } else {
  146. piommu->cntr_assign_mask |= BIT_ULL(shift);
  147. event->hw.iommu_bank = bank;
  148. event->hw.iommu_cntr = cntr;
  149. retval = 0;
  150. goto out;
  151. }
  152. }
  153. }
  154. retval = -ENOSPC;
  155. out:
  156. raw_spin_unlock_irqrestore(&piommu->lock, flags);
  157. return retval;
  158. }
  159. static int clear_avail_iommu_bnk_cntr(struct perf_amd_iommu *perf_iommu,
  160. u8 bank, u8 cntr)
  161. {
  162. unsigned long flags;
  163. int max_banks, max_cntrs;
  164. int shift = 0;
  165. max_banks = perf_iommu->max_banks;
  166. max_cntrs = perf_iommu->max_counters;
  167. if ((bank > max_banks) || (cntr > max_cntrs))
  168. return -EINVAL;
  169. shift = bank + cntr + (bank*3);
  170. raw_spin_lock_irqsave(&perf_iommu->lock, flags);
  171. perf_iommu->cntr_assign_mask &= ~(1ULL<<shift);
  172. raw_spin_unlock_irqrestore(&perf_iommu->lock, flags);
  173. return 0;
  174. }
  175. static int perf_iommu_event_init(struct perf_event *event)
  176. {
  177. struct hw_perf_event *hwc = &event->hw;
  178. /* test the event attr type check for PMU enumeration */
  179. if (event->attr.type != event->pmu->type)
  180. return -ENOENT;
  181. /*
  182. * IOMMU counters are shared across all cores.
  183. * Therefore, it does not support per-process mode.
  184. * Also, it does not support event sampling mode.
  185. */
  186. if (is_sampling_event(event) || event->attach_state & PERF_ATTACH_TASK)
  187. return -EINVAL;
  188. if (event->cpu < 0)
  189. return -EINVAL;
  190. /* update the hw_perf_event struct with the iommu config data */
  191. hwc->conf = event->attr.config;
  192. hwc->conf1 = event->attr.config1;
  193. return 0;
  194. }
  195. static inline struct amd_iommu *perf_event_2_iommu(struct perf_event *ev)
  196. {
  197. return (container_of(ev->pmu, struct perf_amd_iommu, pmu))->iommu;
  198. }
  199. static void perf_iommu_enable_event(struct perf_event *ev)
  200. {
  201. struct amd_iommu *iommu = perf_event_2_iommu(ev);
  202. struct hw_perf_event *hwc = &ev->hw;
  203. u8 bank = hwc->iommu_bank;
  204. u8 cntr = hwc->iommu_cntr;
  205. u64 reg = 0ULL;
  206. reg = GET_CSOURCE(hwc);
  207. amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_COUNTER_SRC_REG, &reg);
  208. reg = GET_DEVID_MASK(hwc);
  209. reg = GET_DEVID(hwc) | (reg << 32);
  210. if (reg)
  211. reg |= BIT(31);
  212. amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DEVID_MATCH_REG, &reg);
  213. reg = GET_PASID_MASK(hwc);
  214. reg = GET_PASID(hwc) | (reg << 32);
  215. if (reg)
  216. reg |= BIT(31);
  217. amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_PASID_MATCH_REG, &reg);
  218. reg = GET_DOMID_MASK(hwc);
  219. reg = GET_DOMID(hwc) | (reg << 32);
  220. if (reg)
  221. reg |= BIT(31);
  222. amd_iommu_pc_set_reg(iommu, bank, cntr, IOMMU_PC_DOMID_MATCH_REG, &reg);
  223. }
  224. static void perf_iommu_disable_event(struct perf_event *event)
  225. {
  226. struct amd_iommu *iommu = perf_event_2_iommu(event);
  227. struct hw_perf_event *hwc = &event->hw;
  228. u64 reg = 0ULL;
  229. amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
  230. IOMMU_PC_COUNTER_SRC_REG, &reg);
  231. }
  232. static void perf_iommu_start(struct perf_event *event, int flags)
  233. {
  234. struct hw_perf_event *hwc = &event->hw;
  235. if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
  236. return;
  237. WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
  238. hwc->state = 0;
  239. /*
  240. * To account for power-gating, which prevents write to
  241. * the counter, we need to enable the counter
  242. * before setting up counter register.
  243. */
  244. perf_iommu_enable_event(event);
  245. if (flags & PERF_EF_RELOAD) {
  246. u64 count = 0;
  247. struct amd_iommu *iommu = perf_event_2_iommu(event);
  248. /*
  249. * Since the IOMMU PMU only support counting mode,
  250. * the counter always start with value zero.
  251. */
  252. amd_iommu_pc_set_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
  253. IOMMU_PC_COUNTER_REG, &count);
  254. }
  255. perf_event_update_userpage(event);
  256. }
  257. static void perf_iommu_read(struct perf_event *event)
  258. {
  259. u64 count;
  260. struct hw_perf_event *hwc = &event->hw;
  261. struct amd_iommu *iommu = perf_event_2_iommu(event);
  262. if (amd_iommu_pc_get_reg(iommu, hwc->iommu_bank, hwc->iommu_cntr,
  263. IOMMU_PC_COUNTER_REG, &count))
  264. return;
  265. /* IOMMU pc counter register is only 48 bits */
  266. count &= GENMASK_ULL(47, 0);
  267. /*
  268. * Since the counter always start with value zero,
  269. * simply just accumulate the count for the event.
  270. */
  271. local64_add(count, &event->count);
  272. }
  273. static void perf_iommu_stop(struct perf_event *event, int flags)
  274. {
  275. struct hw_perf_event *hwc = &event->hw;
  276. if (hwc->state & PERF_HES_UPTODATE)
  277. return;
  278. /*
  279. * To account for power-gating, in which reading the counter would
  280. * return zero, we need to read the register before disabling.
  281. */
  282. perf_iommu_read(event);
  283. hwc->state |= PERF_HES_UPTODATE;
  284. perf_iommu_disable_event(event);
  285. WARN_ON_ONCE(hwc->state & PERF_HES_STOPPED);
  286. hwc->state |= PERF_HES_STOPPED;
  287. }
  288. static int perf_iommu_add(struct perf_event *event, int flags)
  289. {
  290. int retval;
  291. event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
  292. /* request an iommu bank/counter */
  293. retval = get_next_avail_iommu_bnk_cntr(event);
  294. if (retval)
  295. return retval;
  296. if (flags & PERF_EF_START)
  297. perf_iommu_start(event, PERF_EF_RELOAD);
  298. return 0;
  299. }
  300. static void perf_iommu_del(struct perf_event *event, int flags)
  301. {
  302. struct hw_perf_event *hwc = &event->hw;
  303. struct perf_amd_iommu *perf_iommu =
  304. container_of(event->pmu, struct perf_amd_iommu, pmu);
  305. perf_iommu_stop(event, PERF_EF_UPDATE);
  306. /* clear the assigned iommu bank/counter */
  307. clear_avail_iommu_bnk_cntr(perf_iommu,
  308. hwc->iommu_bank, hwc->iommu_cntr);
  309. perf_event_update_userpage(event);
  310. }
  311. static __init int _init_events_attrs(void)
  312. {
  313. int i = 0, j;
  314. struct attribute **attrs;
  315. while (amd_iommu_v2_event_descs[i].attr.attr.name)
  316. i++;
  317. attrs = kcalloc(i + 1, sizeof(*attrs), GFP_KERNEL);
  318. if (!attrs)
  319. return -ENOMEM;
  320. for (j = 0; j < i; j++)
  321. attrs[j] = &amd_iommu_v2_event_descs[j].attr.attr;
  322. amd_iommu_events_group.attrs = attrs;
  323. return 0;
  324. }
  325. static const struct attribute_group *amd_iommu_attr_groups[] = {
  326. &amd_iommu_format_group,
  327. &amd_iommu_cpumask_group,
  328. &amd_iommu_events_group,
  329. NULL,
  330. };
  331. static const struct pmu iommu_pmu __initconst = {
  332. .event_init = perf_iommu_event_init,
  333. .add = perf_iommu_add,
  334. .del = perf_iommu_del,
  335. .start = perf_iommu_start,
  336. .stop = perf_iommu_stop,
  337. .read = perf_iommu_read,
  338. .task_ctx_nr = perf_invalid_context,
  339. .attr_groups = amd_iommu_attr_groups,
  340. .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
  341. };
  342. static __init int init_one_iommu(unsigned int idx)
  343. {
  344. struct perf_amd_iommu *perf_iommu;
  345. int ret;
  346. perf_iommu = kzalloc(sizeof(struct perf_amd_iommu), GFP_KERNEL);
  347. if (!perf_iommu)
  348. return -ENOMEM;
  349. raw_spin_lock_init(&perf_iommu->lock);
  350. perf_iommu->pmu = iommu_pmu;
  351. perf_iommu->iommu = get_amd_iommu(idx);
  352. perf_iommu->max_banks = amd_iommu_pc_get_max_banks(idx);
  353. perf_iommu->max_counters = amd_iommu_pc_get_max_counters(idx);
  354. if (!perf_iommu->iommu ||
  355. !perf_iommu->max_banks ||
  356. !perf_iommu->max_counters) {
  357. kfree(perf_iommu);
  358. return -EINVAL;
  359. }
  360. snprintf(perf_iommu->name, IOMMU_NAME_SIZE, "amd_iommu_%u", idx);
  361. ret = perf_pmu_register(&perf_iommu->pmu, perf_iommu->name, -1);
  362. if (!ret) {
  363. pr_info("Detected AMD IOMMU #%d (%d banks, %d counters/bank).\n",
  364. idx, perf_iommu->max_banks, perf_iommu->max_counters);
  365. list_add_tail(&perf_iommu->list, &perf_amd_iommu_list);
  366. } else {
  367. pr_warn("Error initializing IOMMU %d.\n", idx);
  368. kfree(perf_iommu);
  369. }
  370. return ret;
  371. }
  372. static __init int amd_iommu_pc_init(void)
  373. {
  374. unsigned int i, cnt = 0;
  375. int ret;
  376. /* Make sure the IOMMU PC resource is available */
  377. if (!amd_iommu_pc_supported())
  378. return -ENODEV;
  379. ret = _init_events_attrs();
  380. if (ret)
  381. return ret;
  382. /*
  383. * An IOMMU PMU is specific to an IOMMU, and can function independently.
  384. * So we go through all IOMMUs and ignore the one that fails init
  385. * unless all IOMMU are failing.
  386. */
  387. for (i = 0; i < amd_iommu_get_num_iommus(); i++) {
  388. ret = init_one_iommu(i);
  389. if (!ret)
  390. cnt++;
  391. }
  392. if (!cnt) {
  393. kfree(amd_iommu_events_group.attrs);
  394. return -ENODEV;
  395. }
  396. /* Init cpumask attributes to only core 0 */
  397. cpumask_set_cpu(0, &iommu_cpumask);
  398. return 0;
  399. }
  400. device_initcall(amd_iommu_pc_init);