perf_cpum_cf.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691
  1. /*
  2. * Performance event support for s390x - CPU-measurement Counter Facility
  3. *
  4. * Copyright IBM Corp. 2012
  5. * Author(s): Hendrik Brueckner <brueckner@linux.vnet.ibm.com>
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License (version 2 only)
  9. * as published by the Free Software Foundation.
  10. */
  11. #define KMSG_COMPONENT "cpum_cf"
  12. #define pr_fmt(fmt) KMSG_COMPONENT ": " fmt
  13. #include <linux/kernel.h>
  14. #include <linux/kernel_stat.h>
  15. #include <linux/perf_event.h>
  16. #include <linux/percpu.h>
  17. #include <linux/notifier.h>
  18. #include <linux/init.h>
  19. #include <linux/export.h>
  20. #include <asm/ctl_reg.h>
  21. #include <asm/irq.h>
  22. #include <asm/cpu_mf.h>
  23. /* CPU-measurement counter facility supports these CPU counter sets:
  24. * For CPU counter sets:
  25. * Basic counter set: 0-31
  26. * Problem-state counter set: 32-63
  27. * Crypto-activity counter set: 64-127
  28. * Extented counter set: 128-159
  29. */
  30. enum cpumf_ctr_set {
  31. /* CPU counter sets */
  32. CPUMF_CTR_SET_BASIC = 0,
  33. CPUMF_CTR_SET_USER = 1,
  34. CPUMF_CTR_SET_CRYPTO = 2,
  35. CPUMF_CTR_SET_EXT = 3,
  36. /* Maximum number of counter sets */
  37. CPUMF_CTR_SET_MAX,
  38. };
  39. #define CPUMF_LCCTL_ENABLE_SHIFT 16
  40. #define CPUMF_LCCTL_ACTCTL_SHIFT 0
  41. static const u64 cpumf_state_ctl[CPUMF_CTR_SET_MAX] = {
  42. [CPUMF_CTR_SET_BASIC] = 0x02,
  43. [CPUMF_CTR_SET_USER] = 0x04,
  44. [CPUMF_CTR_SET_CRYPTO] = 0x08,
  45. [CPUMF_CTR_SET_EXT] = 0x01,
  46. };
  47. static void ctr_set_enable(u64 *state, int ctr_set)
  48. {
  49. *state |= cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT;
  50. }
  51. static void ctr_set_disable(u64 *state, int ctr_set)
  52. {
  53. *state &= ~(cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ENABLE_SHIFT);
  54. }
  55. static void ctr_set_start(u64 *state, int ctr_set)
  56. {
  57. *state |= cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT;
  58. }
  59. static void ctr_set_stop(u64 *state, int ctr_set)
  60. {
  61. *state &= ~(cpumf_state_ctl[ctr_set] << CPUMF_LCCTL_ACTCTL_SHIFT);
  62. }
  63. /* Local CPUMF event structure */
  64. struct cpu_hw_events {
  65. struct cpumf_ctr_info info;
  66. atomic_t ctr_set[CPUMF_CTR_SET_MAX];
  67. u64 state, tx_state;
  68. unsigned int flags;
  69. };
  70. static DEFINE_PER_CPU(struct cpu_hw_events, cpu_hw_events) = {
  71. .ctr_set = {
  72. [CPUMF_CTR_SET_BASIC] = ATOMIC_INIT(0),
  73. [CPUMF_CTR_SET_USER] = ATOMIC_INIT(0),
  74. [CPUMF_CTR_SET_CRYPTO] = ATOMIC_INIT(0),
  75. [CPUMF_CTR_SET_EXT] = ATOMIC_INIT(0),
  76. },
  77. .state = 0,
  78. .flags = 0,
  79. };
  80. static int get_counter_set(u64 event)
  81. {
  82. int set = -1;
  83. if (event < 32)
  84. set = CPUMF_CTR_SET_BASIC;
  85. else if (event < 64)
  86. set = CPUMF_CTR_SET_USER;
  87. else if (event < 128)
  88. set = CPUMF_CTR_SET_CRYPTO;
  89. else if (event < 160)
  90. set = CPUMF_CTR_SET_EXT;
  91. return set;
  92. }
  93. static int validate_event(const struct hw_perf_event *hwc)
  94. {
  95. switch (hwc->config_base) {
  96. case CPUMF_CTR_SET_BASIC:
  97. case CPUMF_CTR_SET_USER:
  98. case CPUMF_CTR_SET_CRYPTO:
  99. case CPUMF_CTR_SET_EXT:
  100. /* check for reserved counters */
  101. if ((hwc->config >= 6 && hwc->config <= 31) ||
  102. (hwc->config >= 38 && hwc->config <= 63) ||
  103. (hwc->config >= 80 && hwc->config <= 127))
  104. return -EOPNOTSUPP;
  105. break;
  106. default:
  107. return -EINVAL;
  108. }
  109. return 0;
  110. }
  111. static int validate_ctr_version(const struct hw_perf_event *hwc)
  112. {
  113. struct cpu_hw_events *cpuhw;
  114. int err = 0;
  115. cpuhw = &get_cpu_var(cpu_hw_events);
  116. /* check required version for counter sets */
  117. switch (hwc->config_base) {
  118. case CPUMF_CTR_SET_BASIC:
  119. case CPUMF_CTR_SET_USER:
  120. if (cpuhw->info.cfvn < 1)
  121. err = -EOPNOTSUPP;
  122. break;
  123. case CPUMF_CTR_SET_CRYPTO:
  124. case CPUMF_CTR_SET_EXT:
  125. if (cpuhw->info.csvn < 1)
  126. err = -EOPNOTSUPP;
  127. break;
  128. }
  129. put_cpu_var(cpu_hw_events);
  130. return err;
  131. }
  132. static int validate_ctr_auth(const struct hw_perf_event *hwc)
  133. {
  134. struct cpu_hw_events *cpuhw;
  135. u64 ctrs_state;
  136. int err = 0;
  137. cpuhw = &get_cpu_var(cpu_hw_events);
  138. /* check authorization for cpu counter sets */
  139. ctrs_state = cpumf_state_ctl[hwc->config_base];
  140. if (!(ctrs_state & cpuhw->info.auth_ctl))
  141. err = -EPERM;
  142. put_cpu_var(cpu_hw_events);
  143. return err;
  144. }
  145. /*
  146. * Change the CPUMF state to active.
  147. * Enable and activate the CPU-counter sets according
  148. * to the per-cpu control state.
  149. */
  150. static void cpumf_pmu_enable(struct pmu *pmu)
  151. {
  152. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  153. int err;
  154. if (cpuhw->flags & PMU_F_ENABLED)
  155. return;
  156. err = lcctl(cpuhw->state);
  157. if (err) {
  158. pr_err("Enabling the performance measuring unit "
  159. "failed with rc=%x\n", err);
  160. return;
  161. }
  162. cpuhw->flags |= PMU_F_ENABLED;
  163. }
  164. /*
  165. * Change the CPUMF state to inactive.
  166. * Disable and enable (inactive) the CPU-counter sets according
  167. * to the per-cpu control state.
  168. */
  169. static void cpumf_pmu_disable(struct pmu *pmu)
  170. {
  171. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  172. int err;
  173. u64 inactive;
  174. if (!(cpuhw->flags & PMU_F_ENABLED))
  175. return;
  176. inactive = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
  177. err = lcctl(inactive);
  178. if (err) {
  179. pr_err("Disabling the performance measuring unit "
  180. "failed with rc=%x\n", err);
  181. return;
  182. }
  183. cpuhw->flags &= ~PMU_F_ENABLED;
  184. }
  185. /* Number of perf events counting hardware events */
  186. static atomic_t num_events = ATOMIC_INIT(0);
  187. /* Used to avoid races in calling reserve/release_cpumf_hardware */
  188. static DEFINE_MUTEX(pmc_reserve_mutex);
  189. /* CPU-measurement alerts for the counter facility */
  190. static void cpumf_measurement_alert(struct ext_code ext_code,
  191. unsigned int alert, unsigned long unused)
  192. {
  193. struct cpu_hw_events *cpuhw;
  194. if (!(alert & CPU_MF_INT_CF_MASK))
  195. return;
  196. kstat_cpu(smp_processor_id()).irqs[EXTINT_CPM]++;
  197. cpuhw = &__get_cpu_var(cpu_hw_events);
  198. /* Measurement alerts are shared and might happen when the PMU
  199. * is not reserved. Ignore these alerts in this case. */
  200. if (!(cpuhw->flags & PMU_F_RESERVED))
  201. return;
  202. /* counter authorization change alert */
  203. if (alert & CPU_MF_INT_CF_CACA)
  204. qctri(&cpuhw->info);
  205. /* loss of counter data alert */
  206. if (alert & CPU_MF_INT_CF_LCDA)
  207. pr_err("CPU[%i] Counter data was lost\n", smp_processor_id());
  208. }
  209. #define PMC_INIT 0
  210. #define PMC_RELEASE 1
  211. static void setup_pmc_cpu(void *flags)
  212. {
  213. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  214. switch (*((int *) flags)) {
  215. case PMC_INIT:
  216. memset(&cpuhw->info, 0, sizeof(cpuhw->info));
  217. qctri(&cpuhw->info);
  218. cpuhw->flags |= PMU_F_RESERVED;
  219. break;
  220. case PMC_RELEASE:
  221. cpuhw->flags &= ~PMU_F_RESERVED;
  222. break;
  223. }
  224. /* Disable CPU counter sets */
  225. lcctl(0);
  226. }
  227. /* Initialize the CPU-measurement facility */
  228. static int reserve_pmc_hardware(void)
  229. {
  230. int flags = PMC_INIT;
  231. on_each_cpu(setup_pmc_cpu, &flags, 1);
  232. measurement_alert_subclass_register();
  233. return 0;
  234. }
  235. /* Release the CPU-measurement facility */
  236. static void release_pmc_hardware(void)
  237. {
  238. int flags = PMC_RELEASE;
  239. on_each_cpu(setup_pmc_cpu, &flags, 1);
  240. measurement_alert_subclass_unregister();
  241. }
  242. /* Release the PMU if event is the last perf event */
  243. static void hw_perf_event_destroy(struct perf_event *event)
  244. {
  245. if (!atomic_add_unless(&num_events, -1, 1)) {
  246. mutex_lock(&pmc_reserve_mutex);
  247. if (atomic_dec_return(&num_events) == 0)
  248. release_pmc_hardware();
  249. mutex_unlock(&pmc_reserve_mutex);
  250. }
  251. }
  252. /* CPUMF <-> perf event mappings for kernel+userspace (basic set) */
  253. static const int cpumf_generic_events_basic[] = {
  254. [PERF_COUNT_HW_CPU_CYCLES] = 0,
  255. [PERF_COUNT_HW_INSTRUCTIONS] = 1,
  256. [PERF_COUNT_HW_CACHE_REFERENCES] = -1,
  257. [PERF_COUNT_HW_CACHE_MISSES] = -1,
  258. [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = -1,
  259. [PERF_COUNT_HW_BRANCH_MISSES] = -1,
  260. [PERF_COUNT_HW_BUS_CYCLES] = -1,
  261. };
  262. /* CPUMF <-> perf event mappings for userspace (problem-state set) */
  263. static const int cpumf_generic_events_user[] = {
  264. [PERF_COUNT_HW_CPU_CYCLES] = 32,
  265. [PERF_COUNT_HW_INSTRUCTIONS] = 33,
  266. [PERF_COUNT_HW_CACHE_REFERENCES] = -1,
  267. [PERF_COUNT_HW_CACHE_MISSES] = -1,
  268. [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = -1,
  269. [PERF_COUNT_HW_BRANCH_MISSES] = -1,
  270. [PERF_COUNT_HW_BUS_CYCLES] = -1,
  271. };
  272. static int __hw_perf_event_init(struct perf_event *event)
  273. {
  274. struct perf_event_attr *attr = &event->attr;
  275. struct hw_perf_event *hwc = &event->hw;
  276. int err;
  277. u64 ev;
  278. switch (attr->type) {
  279. case PERF_TYPE_RAW:
  280. /* Raw events are used to access counters directly,
  281. * hence do not permit excludes */
  282. if (attr->exclude_kernel || attr->exclude_user ||
  283. attr->exclude_hv)
  284. return -EOPNOTSUPP;
  285. ev = attr->config;
  286. break;
  287. case PERF_TYPE_HARDWARE:
  288. ev = attr->config;
  289. /* Count user space (problem-state) only */
  290. if (!attr->exclude_user && attr->exclude_kernel) {
  291. if (ev >= ARRAY_SIZE(cpumf_generic_events_user))
  292. return -EOPNOTSUPP;
  293. ev = cpumf_generic_events_user[ev];
  294. /* No support for kernel space counters only */
  295. } else if (!attr->exclude_kernel && attr->exclude_user) {
  296. return -EOPNOTSUPP;
  297. /* Count user and kernel space */
  298. } else {
  299. if (ev >= ARRAY_SIZE(cpumf_generic_events_basic))
  300. return -EOPNOTSUPP;
  301. ev = cpumf_generic_events_basic[ev];
  302. }
  303. break;
  304. default:
  305. return -ENOENT;
  306. }
  307. if (ev == -1)
  308. return -ENOENT;
  309. if (ev >= PERF_CPUM_CF_MAX_CTR)
  310. return -EINVAL;
  311. /* The CPU measurement counter facility does not have any interrupts
  312. * to do sampling. Sampling must be provided by external means,
  313. * for example, by timers.
  314. */
  315. if (hwc->sample_period)
  316. return -EINVAL;
  317. /* Use the hardware perf event structure to store the counter number
  318. * in 'config' member and the counter set to which the counter belongs
  319. * in the 'config_base'. The counter set (config_base) is then used
  320. * to enable/disable the counters.
  321. */
  322. hwc->config = ev;
  323. hwc->config_base = get_counter_set(ev);
  324. /* Validate the counter that is assigned to this event.
  325. * Because the counter facility can use numerous counters at the
  326. * same time without constraints, it is not necessary to explicity
  327. * validate event groups (event->group_leader != event).
  328. */
  329. err = validate_event(hwc);
  330. if (err)
  331. return err;
  332. /* Initialize for using the CPU-measurement counter facility */
  333. if (!atomic_inc_not_zero(&num_events)) {
  334. mutex_lock(&pmc_reserve_mutex);
  335. if (atomic_read(&num_events) == 0 && reserve_pmc_hardware())
  336. err = -EBUSY;
  337. else
  338. atomic_inc(&num_events);
  339. mutex_unlock(&pmc_reserve_mutex);
  340. }
  341. event->destroy = hw_perf_event_destroy;
  342. /* Finally, validate version and authorization of the counter set */
  343. err = validate_ctr_auth(hwc);
  344. if (!err)
  345. err = validate_ctr_version(hwc);
  346. return err;
  347. }
  348. static int cpumf_pmu_event_init(struct perf_event *event)
  349. {
  350. int err;
  351. switch (event->attr.type) {
  352. case PERF_TYPE_HARDWARE:
  353. case PERF_TYPE_HW_CACHE:
  354. case PERF_TYPE_RAW:
  355. err = __hw_perf_event_init(event);
  356. break;
  357. default:
  358. return -ENOENT;
  359. }
  360. if (unlikely(err) && event->destroy)
  361. event->destroy(event);
  362. return err;
  363. }
  364. static int hw_perf_event_reset(struct perf_event *event)
  365. {
  366. u64 prev, new;
  367. int err;
  368. do {
  369. prev = local64_read(&event->hw.prev_count);
  370. err = ecctr(event->hw.config, &new);
  371. if (err) {
  372. if (err != 3)
  373. break;
  374. /* The counter is not (yet) available. This
  375. * might happen if the counter set to which
  376. * this counter belongs is in the disabled
  377. * state.
  378. */
  379. new = 0;
  380. }
  381. } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev);
  382. return err;
  383. }
  384. static int hw_perf_event_update(struct perf_event *event)
  385. {
  386. u64 prev, new, delta;
  387. int err;
  388. do {
  389. prev = local64_read(&event->hw.prev_count);
  390. err = ecctr(event->hw.config, &new);
  391. if (err)
  392. goto out;
  393. } while (local64_cmpxchg(&event->hw.prev_count, prev, new) != prev);
  394. delta = (prev <= new) ? new - prev
  395. : (-1ULL - prev) + new + 1; /* overflow */
  396. local64_add(delta, &event->count);
  397. out:
  398. return err;
  399. }
  400. static void cpumf_pmu_read(struct perf_event *event)
  401. {
  402. if (event->hw.state & PERF_HES_STOPPED)
  403. return;
  404. hw_perf_event_update(event);
  405. }
  406. static void cpumf_pmu_start(struct perf_event *event, int flags)
  407. {
  408. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  409. struct hw_perf_event *hwc = &event->hw;
  410. if (WARN_ON_ONCE(!(hwc->state & PERF_HES_STOPPED)))
  411. return;
  412. if (WARN_ON_ONCE(hwc->config == -1))
  413. return;
  414. if (flags & PERF_EF_RELOAD)
  415. WARN_ON_ONCE(!(hwc->state & PERF_HES_UPTODATE));
  416. hwc->state = 0;
  417. /* (Re-)enable and activate the counter set */
  418. ctr_set_enable(&cpuhw->state, hwc->config_base);
  419. ctr_set_start(&cpuhw->state, hwc->config_base);
  420. /* The counter set to which this counter belongs can be already active.
  421. * Because all counters in a set are active, the event->hw.prev_count
  422. * needs to be synchronized. At this point, the counter set can be in
  423. * the inactive or disabled state.
  424. */
  425. hw_perf_event_reset(event);
  426. /* increment refcount for this counter set */
  427. atomic_inc(&cpuhw->ctr_set[hwc->config_base]);
  428. }
  429. static void cpumf_pmu_stop(struct perf_event *event, int flags)
  430. {
  431. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  432. struct hw_perf_event *hwc = &event->hw;
  433. if (!(hwc->state & PERF_HES_STOPPED)) {
  434. /* Decrement reference count for this counter set and if this
  435. * is the last used counter in the set, clear activation
  436. * control and set the counter set state to inactive.
  437. */
  438. if (!atomic_dec_return(&cpuhw->ctr_set[hwc->config_base]))
  439. ctr_set_stop(&cpuhw->state, hwc->config_base);
  440. event->hw.state |= PERF_HES_STOPPED;
  441. }
  442. if ((flags & PERF_EF_UPDATE) && !(hwc->state & PERF_HES_UPTODATE)) {
  443. hw_perf_event_update(event);
  444. event->hw.state |= PERF_HES_UPTODATE;
  445. }
  446. }
  447. static int cpumf_pmu_add(struct perf_event *event, int flags)
  448. {
  449. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  450. /* Check authorization for the counter set to which this
  451. * counter belongs.
  452. * For group events transaction, the authorization check is
  453. * done in cpumf_pmu_commit_txn().
  454. */
  455. if (!(cpuhw->flags & PERF_EVENT_TXN))
  456. if (validate_ctr_auth(&event->hw))
  457. return -EPERM;
  458. ctr_set_enable(&cpuhw->state, event->hw.config_base);
  459. event->hw.state = PERF_HES_UPTODATE | PERF_HES_STOPPED;
  460. if (flags & PERF_EF_START)
  461. cpumf_pmu_start(event, PERF_EF_RELOAD);
  462. perf_event_update_userpage(event);
  463. return 0;
  464. }
  465. static void cpumf_pmu_del(struct perf_event *event, int flags)
  466. {
  467. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  468. cpumf_pmu_stop(event, PERF_EF_UPDATE);
  469. /* Check if any counter in the counter set is still used. If not used,
  470. * change the counter set to the disabled state. This also clears the
  471. * content of all counters in the set.
  472. *
  473. * When a new perf event has been added but not yet started, this can
  474. * clear enable control and resets all counters in a set. Therefore,
  475. * cpumf_pmu_start() always has to reenable a counter set.
  476. */
  477. if (!atomic_read(&cpuhw->ctr_set[event->hw.config_base]))
  478. ctr_set_disable(&cpuhw->state, event->hw.config_base);
  479. perf_event_update_userpage(event);
  480. }
  481. /*
  482. * Start group events scheduling transaction.
  483. * Set flags to perform a single test at commit time.
  484. */
  485. static void cpumf_pmu_start_txn(struct pmu *pmu)
  486. {
  487. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  488. perf_pmu_disable(pmu);
  489. cpuhw->flags |= PERF_EVENT_TXN;
  490. cpuhw->tx_state = cpuhw->state;
  491. }
  492. /*
  493. * Stop and cancel a group events scheduling tranctions.
  494. * Assumes cpumf_pmu_del() is called for each successful added
  495. * cpumf_pmu_add() during the transaction.
  496. */
  497. static void cpumf_pmu_cancel_txn(struct pmu *pmu)
  498. {
  499. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  500. WARN_ON(cpuhw->tx_state != cpuhw->state);
  501. cpuhw->flags &= ~PERF_EVENT_TXN;
  502. perf_pmu_enable(pmu);
  503. }
  504. /*
  505. * Commit the group events scheduling transaction. On success, the
  506. * transaction is closed. On error, the transaction is kept open
  507. * until cpumf_pmu_cancel_txn() is called.
  508. */
  509. static int cpumf_pmu_commit_txn(struct pmu *pmu)
  510. {
  511. struct cpu_hw_events *cpuhw = &__get_cpu_var(cpu_hw_events);
  512. u64 state;
  513. /* check if the updated state can be scheduled */
  514. state = cpuhw->state & ~((1 << CPUMF_LCCTL_ENABLE_SHIFT) - 1);
  515. state >>= CPUMF_LCCTL_ENABLE_SHIFT;
  516. if ((state & cpuhw->info.auth_ctl) != state)
  517. return -EPERM;
  518. cpuhw->flags &= ~PERF_EVENT_TXN;
  519. perf_pmu_enable(pmu);
  520. return 0;
  521. }
  522. /* Performance monitoring unit for s390x */
  523. static struct pmu cpumf_pmu = {
  524. .pmu_enable = cpumf_pmu_enable,
  525. .pmu_disable = cpumf_pmu_disable,
  526. .event_init = cpumf_pmu_event_init,
  527. .add = cpumf_pmu_add,
  528. .del = cpumf_pmu_del,
  529. .start = cpumf_pmu_start,
  530. .stop = cpumf_pmu_stop,
  531. .read = cpumf_pmu_read,
  532. .start_txn = cpumf_pmu_start_txn,
  533. .commit_txn = cpumf_pmu_commit_txn,
  534. .cancel_txn = cpumf_pmu_cancel_txn,
  535. };
  536. static int __cpuinit cpumf_pmu_notifier(struct notifier_block *self,
  537. unsigned long action, void *hcpu)
  538. {
  539. unsigned int cpu = (long) hcpu;
  540. int flags;
  541. switch (action & ~CPU_TASKS_FROZEN) {
  542. case CPU_ONLINE:
  543. flags = PMC_INIT;
  544. smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
  545. break;
  546. case CPU_DOWN_PREPARE:
  547. flags = PMC_RELEASE;
  548. smp_call_function_single(cpu, setup_pmc_cpu, &flags, 1);
  549. break;
  550. default:
  551. break;
  552. }
  553. return NOTIFY_OK;
  554. }
  555. static int __init cpumf_pmu_init(void)
  556. {
  557. int rc;
  558. if (!cpum_cf_avail())
  559. return -ENODEV;
  560. /* clear bit 15 of cr0 to unauthorize problem-state to
  561. * extract measurement counters */
  562. ctl_clear_bit(0, 48);
  563. /* register handler for measurement-alert interruptions */
  564. rc = register_external_interrupt(0x1407, cpumf_measurement_alert);
  565. if (rc) {
  566. pr_err("Registering for CPU-measurement alerts "
  567. "failed with rc=%i\n", rc);
  568. goto out;
  569. }
  570. rc = perf_pmu_register(&cpumf_pmu, "cpum_cf", PERF_TYPE_RAW);
  571. if (rc) {
  572. pr_err("Registering the cpum_cf PMU failed with rc=%i\n", rc);
  573. unregister_external_interrupt(0x1407, cpumf_measurement_alert);
  574. goto out;
  575. }
  576. perf_cpu_notifier(cpumf_pmu_notifier);
  577. out:
  578. return rc;
  579. }
  580. early_initcall(cpumf_pmu_init);