hv-gpci.c 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. * Hypervisor supplied "gpci" ("get performance counter info") performance
  4. * counter support
  5. *
  6. * Author: Cody P Schafer <[email protected]>
  7. * Copyright 2014 IBM Corporation.
  8. */
  9. #define pr_fmt(fmt) "hv-gpci: " fmt
  10. #include <linux/init.h>
  11. #include <linux/perf_event.h>
  12. #include <asm/firmware.h>
  13. #include <asm/hvcall.h>
  14. #include <asm/io.h>
  15. #include "hv-gpci.h"
  16. #include "hv-common.h"
  17. /*
  18. * Example usage:
  19. * perf stat -e 'hv_gpci/counter_info_version=3,offset=0,length=8,
  20. * secondary_index=0,starting_index=0xffffffff,request=0x10/' ...
  21. */
  22. /* u32 */
  23. EVENT_DEFINE_RANGE_FORMAT(request, config, 0, 31);
  24. /* u32 */
  25. /*
  26. * Note that starting_index, phys_processor_idx, sibling_part_id,
  27. * hw_chip_id, partition_id all refer to the same bit range. They
  28. * are basically aliases for the starting_index. The specific alias
  29. * used depends on the event. See REQUEST_IDX_KIND in hv-gpci-requests.h
  30. */
  31. EVENT_DEFINE_RANGE_FORMAT(starting_index, config, 32, 63);
  32. EVENT_DEFINE_RANGE_FORMAT_LITE(phys_processor_idx, config, 32, 63);
  33. EVENT_DEFINE_RANGE_FORMAT_LITE(sibling_part_id, config, 32, 63);
  34. EVENT_DEFINE_RANGE_FORMAT_LITE(hw_chip_id, config, 32, 63);
  35. EVENT_DEFINE_RANGE_FORMAT_LITE(partition_id, config, 32, 63);
  36. /* u16 */
  37. EVENT_DEFINE_RANGE_FORMAT(secondary_index, config1, 0, 15);
  38. /* u8 */
  39. EVENT_DEFINE_RANGE_FORMAT(counter_info_version, config1, 16, 23);
  40. /* u8, bytes of data (1-8) */
  41. EVENT_DEFINE_RANGE_FORMAT(length, config1, 24, 31);
  42. /* u32, byte offset */
  43. EVENT_DEFINE_RANGE_FORMAT(offset, config1, 32, 63);
  44. static cpumask_t hv_gpci_cpumask;
  45. static struct attribute *format_attrs[] = {
  46. &format_attr_request.attr,
  47. &format_attr_starting_index.attr,
  48. &format_attr_phys_processor_idx.attr,
  49. &format_attr_sibling_part_id.attr,
  50. &format_attr_hw_chip_id.attr,
  51. &format_attr_partition_id.attr,
  52. &format_attr_secondary_index.attr,
  53. &format_attr_counter_info_version.attr,
  54. &format_attr_offset.attr,
  55. &format_attr_length.attr,
  56. NULL,
  57. };
  58. static const struct attribute_group format_group = {
  59. .name = "format",
  60. .attrs = format_attrs,
  61. };
  62. static struct attribute_group event_group = {
  63. .name = "events",
  64. /* .attrs is set in init */
  65. };
  66. #define HV_CAPS_ATTR(_name, _format) \
  67. static ssize_t _name##_show(struct device *dev, \
  68. struct device_attribute *attr, \
  69. char *page) \
  70. { \
  71. struct hv_perf_caps caps; \
  72. unsigned long hret = hv_perf_caps_get(&caps); \
  73. if (hret) \
  74. return -EIO; \
  75. \
  76. return sprintf(page, _format, caps._name); \
  77. } \
  78. static struct device_attribute hv_caps_attr_##_name = __ATTR_RO(_name)
  79. static ssize_t kernel_version_show(struct device *dev,
  80. struct device_attribute *attr,
  81. char *page)
  82. {
  83. return sprintf(page, "0x%x\n", COUNTER_INFO_VERSION_CURRENT);
  84. }
  85. static ssize_t cpumask_show(struct device *dev,
  86. struct device_attribute *attr, char *buf)
  87. {
  88. return cpumap_print_to_pagebuf(true, buf, &hv_gpci_cpumask);
  89. }
  90. static DEVICE_ATTR_RO(kernel_version);
  91. static DEVICE_ATTR_RO(cpumask);
  92. HV_CAPS_ATTR(version, "0x%x\n");
  93. HV_CAPS_ATTR(ga, "%d\n");
  94. HV_CAPS_ATTR(expanded, "%d\n");
  95. HV_CAPS_ATTR(lab, "%d\n");
  96. HV_CAPS_ATTR(collect_privileged, "%d\n");
  97. static struct attribute *interface_attrs[] = {
  98. &dev_attr_kernel_version.attr,
  99. &hv_caps_attr_version.attr,
  100. &hv_caps_attr_ga.attr,
  101. &hv_caps_attr_expanded.attr,
  102. &hv_caps_attr_lab.attr,
  103. &hv_caps_attr_collect_privileged.attr,
  104. NULL,
  105. };
  106. static struct attribute *cpumask_attrs[] = {
  107. &dev_attr_cpumask.attr,
  108. NULL,
  109. };
  110. static const struct attribute_group cpumask_attr_group = {
  111. .attrs = cpumask_attrs,
  112. };
  113. static const struct attribute_group interface_group = {
  114. .name = "interface",
  115. .attrs = interface_attrs,
  116. };
  117. static const struct attribute_group *attr_groups[] = {
  118. &format_group,
  119. &event_group,
  120. &interface_group,
  121. &cpumask_attr_group,
  122. NULL,
  123. };
  124. static DEFINE_PER_CPU(char, hv_gpci_reqb[HGPCI_REQ_BUFFER_SIZE]) __aligned(sizeof(uint64_t));
  125. static unsigned long single_gpci_request(u32 req, u32 starting_index,
  126. u16 secondary_index, u8 version_in, u32 offset, u8 length,
  127. u64 *value)
  128. {
  129. unsigned long ret;
  130. size_t i;
  131. u64 count;
  132. struct hv_gpci_request_buffer *arg;
  133. arg = (void *)get_cpu_var(hv_gpci_reqb);
  134. memset(arg, 0, HGPCI_REQ_BUFFER_SIZE);
  135. arg->params.counter_request = cpu_to_be32(req);
  136. arg->params.starting_index = cpu_to_be32(starting_index);
  137. arg->params.secondary_index = cpu_to_be16(secondary_index);
  138. arg->params.counter_info_version_in = version_in;
  139. ret = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
  140. virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
  141. if (ret) {
  142. pr_devel("hcall failed: 0x%lx\n", ret);
  143. goto out;
  144. }
  145. /*
  146. * we verify offset and length are within the zeroed buffer at event
  147. * init.
  148. */
  149. count = 0;
  150. for (i = offset; i < offset + length; i++)
  151. count |= (u64)(arg->bytes[i]) << ((length - 1 - (i - offset)) * 8);
  152. *value = count;
  153. out:
  154. put_cpu_var(hv_gpci_reqb);
  155. return ret;
  156. }
  157. static u64 h_gpci_get_value(struct perf_event *event)
  158. {
  159. u64 count;
  160. unsigned long ret = single_gpci_request(event_get_request(event),
  161. event_get_starting_index(event),
  162. event_get_secondary_index(event),
  163. event_get_counter_info_version(event),
  164. event_get_offset(event),
  165. event_get_length(event),
  166. &count);
  167. if (ret)
  168. return 0;
  169. return count;
  170. }
  171. static void h_gpci_event_update(struct perf_event *event)
  172. {
  173. s64 prev;
  174. u64 now = h_gpci_get_value(event);
  175. prev = local64_xchg(&event->hw.prev_count, now);
  176. local64_add(now - prev, &event->count);
  177. }
  178. static void h_gpci_event_start(struct perf_event *event, int flags)
  179. {
  180. local64_set(&event->hw.prev_count, h_gpci_get_value(event));
  181. }
  182. static void h_gpci_event_stop(struct perf_event *event, int flags)
  183. {
  184. h_gpci_event_update(event);
  185. }
  186. static int h_gpci_event_add(struct perf_event *event, int flags)
  187. {
  188. if (flags & PERF_EF_START)
  189. h_gpci_event_start(event, flags);
  190. return 0;
  191. }
  192. static int h_gpci_event_init(struct perf_event *event)
  193. {
  194. u64 count;
  195. u8 length;
  196. /* Not our event */
  197. if (event->attr.type != event->pmu->type)
  198. return -ENOENT;
  199. /* config2 is unused */
  200. if (event->attr.config2) {
  201. pr_devel("config2 set when reserved\n");
  202. return -EINVAL;
  203. }
  204. /* no branch sampling */
  205. if (has_branch_stack(event))
  206. return -EOPNOTSUPP;
  207. length = event_get_length(event);
  208. if (length < 1 || length > 8) {
  209. pr_devel("length invalid\n");
  210. return -EINVAL;
  211. }
  212. /* last byte within the buffer? */
  213. if ((event_get_offset(event) + length) > HGPCI_MAX_DATA_BYTES) {
  214. pr_devel("request outside of buffer: %zu > %zu\n",
  215. (size_t)event_get_offset(event) + length,
  216. HGPCI_MAX_DATA_BYTES);
  217. return -EINVAL;
  218. }
  219. /* check if the request works... */
  220. if (single_gpci_request(event_get_request(event),
  221. event_get_starting_index(event),
  222. event_get_secondary_index(event),
  223. event_get_counter_info_version(event),
  224. event_get_offset(event),
  225. length,
  226. &count)) {
  227. pr_devel("gpci hcall failed\n");
  228. return -EINVAL;
  229. }
  230. return 0;
  231. }
  232. static struct pmu h_gpci_pmu = {
  233. .task_ctx_nr = perf_invalid_context,
  234. .name = "hv_gpci",
  235. .attr_groups = attr_groups,
  236. .event_init = h_gpci_event_init,
  237. .add = h_gpci_event_add,
  238. .del = h_gpci_event_stop,
  239. .start = h_gpci_event_start,
  240. .stop = h_gpci_event_stop,
  241. .read = h_gpci_event_update,
  242. .capabilities = PERF_PMU_CAP_NO_EXCLUDE,
  243. };
  244. static int ppc_hv_gpci_cpu_online(unsigned int cpu)
  245. {
  246. if (cpumask_empty(&hv_gpci_cpumask))
  247. cpumask_set_cpu(cpu, &hv_gpci_cpumask);
  248. return 0;
  249. }
  250. static int ppc_hv_gpci_cpu_offline(unsigned int cpu)
  251. {
  252. int target;
  253. /* Check if exiting cpu is used for collecting gpci events */
  254. if (!cpumask_test_and_clear_cpu(cpu, &hv_gpci_cpumask))
  255. return 0;
  256. /* Find a new cpu to collect gpci events */
  257. target = cpumask_last(cpu_active_mask);
  258. if (target < 0 || target >= nr_cpu_ids) {
  259. pr_err("hv_gpci: CPU hotplug init failed\n");
  260. return -1;
  261. }
  262. /* Migrate gpci events to the new target */
  263. cpumask_set_cpu(target, &hv_gpci_cpumask);
  264. perf_pmu_migrate_context(&h_gpci_pmu, cpu, target);
  265. return 0;
  266. }
  267. static int hv_gpci_cpu_hotplug_init(void)
  268. {
  269. return cpuhp_setup_state(CPUHP_AP_PERF_POWERPC_HV_GPCI_ONLINE,
  270. "perf/powerpc/hv_gcpi:online",
  271. ppc_hv_gpci_cpu_online,
  272. ppc_hv_gpci_cpu_offline);
  273. }
  274. static int hv_gpci_init(void)
  275. {
  276. int r;
  277. unsigned long hret;
  278. struct hv_perf_caps caps;
  279. struct hv_gpci_request_buffer *arg;
  280. hv_gpci_assert_offsets_correct();
  281. if (!firmware_has_feature(FW_FEATURE_LPAR)) {
  282. pr_debug("not a virtualized system, not enabling\n");
  283. return -ENODEV;
  284. }
  285. hret = hv_perf_caps_get(&caps);
  286. if (hret) {
  287. pr_debug("could not obtain capabilities, not enabling, rc=%ld\n",
  288. hret);
  289. return -ENODEV;
  290. }
  291. /* init cpuhotplug */
  292. r = hv_gpci_cpu_hotplug_init();
  293. if (r)
  294. return r;
  295. /* sampling not supported */
  296. h_gpci_pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
  297. arg = (void *)get_cpu_var(hv_gpci_reqb);
  298. memset(arg, 0, HGPCI_REQ_BUFFER_SIZE);
  299. /*
  300. * hcall H_GET_PERF_COUNTER_INFO populates the output
  301. * counter_info_version value based on the system hypervisor.
  302. * Pass the counter request 0x10 corresponds to request type
  303. * 'Dispatch_timebase_by_processor', to get the supported
  304. * counter_info_version.
  305. */
  306. arg->params.counter_request = cpu_to_be32(0x10);
  307. r = plpar_hcall_norets(H_GET_PERF_COUNTER_INFO,
  308. virt_to_phys(arg), HGPCI_REQ_BUFFER_SIZE);
  309. if (r) {
  310. pr_devel("hcall failed, can't get supported counter_info_version: 0x%x\n", r);
  311. arg->params.counter_info_version_out = 0x8;
  312. }
  313. /*
  314. * Use counter_info_version_out value to assign
  315. * required hv-gpci event list.
  316. */
  317. if (arg->params.counter_info_version_out >= 0x8)
  318. event_group.attrs = hv_gpci_event_attrs;
  319. else
  320. event_group.attrs = hv_gpci_event_attrs_v6;
  321. put_cpu_var(hv_gpci_reqb);
  322. r = perf_pmu_register(&h_gpci_pmu, h_gpci_pmu.name, -1);
  323. if (r)
  324. return r;
  325. return 0;
  326. }
  327. device_initcall(hv_gpci_init);