pmu.c 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. // SPDX-License-Identifier: GPL-2.0
  2. /*
  3. * Copyright 2019 Arm Limited
  4. * Author: Andrew Murray <Andrew.Murray@arm.com>
  5. */
  6. #include <linux/kvm_host.h>
  7. #include <linux/perf_event.h>
  8. #include <linux/perf/arm_pmu.h>
  9. #include <linux/perf/arm_pmuv3.h>
  10. static DEFINE_PER_CPU(struct kvm_pmu_events, kvm_pmu_events);
  11. /*
  12. * Given the perf event attributes and system type, determine
  13. * if we are going to need to switch counters at guest entry/exit.
  14. */
  15. static bool kvm_pmu_switch_needed(struct perf_event_attr *attr)
  16. {
  17. /**
  18. * With VHE the guest kernel runs at EL1 and the host at EL2,
  19. * where user (EL0) is excluded then we have no reason to switch
  20. * counters.
  21. */
  22. if (has_vhe() && attr->exclude_user)
  23. return false;
  24. /* Only switch if attributes are different */
  25. return (attr->exclude_host != attr->exclude_guest);
  26. }
  27. struct kvm_pmu_events *kvm_get_pmu_events(void)
  28. {
  29. return this_cpu_ptr(&kvm_pmu_events);
  30. }
  31. /*
  32. * Add events to track that we may want to switch at guest entry/exit
  33. * time.
  34. */
  35. void kvm_set_pmu_events(u64 set, struct perf_event_attr *attr)
  36. {
  37. struct kvm_pmu_events *pmu = kvm_get_pmu_events();
  38. if (!system_supports_pmuv3() || !kvm_pmu_switch_needed(attr))
  39. return;
  40. if (!attr->exclude_host)
  41. pmu->events_host |= set;
  42. if (!attr->exclude_guest)
  43. pmu->events_guest |= set;
  44. }
  45. /*
  46. * Stop tracking events
  47. */
  48. void kvm_clr_pmu_events(u64 clr)
  49. {
  50. struct kvm_pmu_events *pmu = kvm_get_pmu_events();
  51. if (!system_supports_pmuv3())
  52. return;
  53. pmu->events_host &= ~clr;
  54. pmu->events_guest &= ~clr;
  55. }
  56. /*
  57. * Read a value direct from PMEVTYPER<idx> where idx is 0-30
  58. * or PMxCFILTR_EL0 where idx is 31-32.
  59. */
  60. static u64 kvm_vcpu_pmu_read_evtype_direct(int idx)
  61. {
  62. if (idx == ARMV8_PMU_CYCLE_IDX)
  63. return read_pmccfiltr();
  64. else if (idx == ARMV8_PMU_INSTR_IDX)
  65. return read_pmicfiltr();
  66. return read_pmevtypern(idx);
  67. }
  68. /*
  69. * Write a value direct to PMEVTYPER<idx> where idx is 0-30
  70. * or PMxCFILTR_EL0 where idx is 31-32.
  71. */
  72. static void kvm_vcpu_pmu_write_evtype_direct(int idx, u32 val)
  73. {
  74. if (idx == ARMV8_PMU_CYCLE_IDX)
  75. write_pmccfiltr(val);
  76. else if (idx == ARMV8_PMU_INSTR_IDX)
  77. write_pmicfiltr(val);
  78. else
  79. write_pmevtypern(idx, val);
  80. }
  81. /*
  82. * Modify ARMv8 PMU events to include EL0 counting
  83. */
  84. static void kvm_vcpu_pmu_enable_el0(unsigned long events)
  85. {
  86. u64 typer;
  87. u32 counter;
  88. for_each_set_bit(counter, &events, ARMPMU_MAX_HWEVENTS) {
  89. typer = kvm_vcpu_pmu_read_evtype_direct(counter);
  90. typer &= ~ARMV8_PMU_EXCLUDE_EL0;
  91. kvm_vcpu_pmu_write_evtype_direct(counter, typer);
  92. }
  93. }
  94. /*
  95. * Modify ARMv8 PMU events to exclude EL0 counting
  96. */
  97. static void kvm_vcpu_pmu_disable_el0(unsigned long events)
  98. {
  99. u64 typer;
  100. u32 counter;
  101. for_each_set_bit(counter, &events, ARMPMU_MAX_HWEVENTS) {
  102. typer = kvm_vcpu_pmu_read_evtype_direct(counter);
  103. typer |= ARMV8_PMU_EXCLUDE_EL0;
  104. kvm_vcpu_pmu_write_evtype_direct(counter, typer);
  105. }
  106. }
  107. /*
  108. * On VHE ensure that only guest events have EL0 counting enabled.
  109. * This is called from both vcpu_{load,put} and the sysreg handling.
  110. * Since the latter is preemptible, special care must be taken to
  111. * disable preemption.
  112. */
  113. void kvm_vcpu_pmu_restore_guest(struct kvm_vcpu *vcpu)
  114. {
  115. struct kvm_pmu_events *pmu;
  116. u64 events_guest, events_host;
  117. if (!system_supports_pmuv3() || !has_vhe())
  118. return;
  119. preempt_disable();
  120. pmu = kvm_get_pmu_events();
  121. events_guest = pmu->events_guest;
  122. events_host = pmu->events_host;
  123. kvm_vcpu_pmu_enable_el0(events_guest);
  124. kvm_vcpu_pmu_disable_el0(events_host);
  125. preempt_enable();
  126. }
  127. /*
  128. * On VHE ensure that only host events have EL0 counting enabled
  129. */
  130. void kvm_vcpu_pmu_restore_host(struct kvm_vcpu *vcpu)
  131. {
  132. struct kvm_pmu_events *pmu;
  133. u64 events_guest, events_host;
  134. if (!system_supports_pmuv3() || !has_vhe())
  135. return;
  136. pmu = kvm_get_pmu_events();
  137. events_guest = pmu->events_guest;
  138. events_host = pmu->events_host;
  139. kvm_vcpu_pmu_enable_el0(events_host);
  140. kvm_vcpu_pmu_disable_el0(events_guest);
  141. }
  142. /*
  143. * With VHE, keep track of the PMUSERENR_EL0 value for the host EL0 on the pCPU
  144. * where PMUSERENR_EL0 for the guest is loaded, since PMUSERENR_EL0 is switched
  145. * to the value for the guest on vcpu_load(). The value for the host EL0
  146. * will be restored on vcpu_put(), before returning to userspace.
  147. * This isn't necessary for nVHE, as the register is context switched for
  148. * every guest enter/exit.
  149. *
  150. * Return true if KVM takes care of the register. Otherwise return false.
  151. */
  152. bool kvm_set_pmuserenr(u64 val)
  153. {
  154. struct kvm_cpu_context *hctxt;
  155. struct kvm_vcpu *vcpu;
  156. if (!system_supports_pmuv3() || !has_vhe())
  157. return false;
  158. vcpu = kvm_get_running_vcpu();
  159. if (!vcpu || !vcpu_get_flag(vcpu, PMUSERENR_ON_CPU))
  160. return false;
  161. hctxt = host_data_ptr(host_ctxt);
  162. ctxt_sys_reg(hctxt, PMUSERENR_EL0) = val;
  163. return true;
  164. }
  165. /*
  166. * If we interrupted the guest to update the host PMU context, make
  167. * sure we re-apply the guest EL0 state.
  168. */
  169. void kvm_vcpu_pmu_resync_el0(void)
  170. {
  171. struct kvm_vcpu *vcpu;
  172. if (!has_vhe() || !in_interrupt())
  173. return;
  174. vcpu = kvm_get_running_vcpu();
  175. if (!vcpu)
  176. return;
  177. kvm_make_request(KVM_REQ_RESYNC_PMU_EL0, vcpu);
  178. }