debug.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Debug and Guest Debug support
  4. *
  5. * Copyright (C) 2015 - Linaro Ltd
  6. * Authors: Alex Bennée <alex.bennee@linaro.org>
  7. * Oliver Upton <oliver.upton@linux.dev>
  8. */
  9. #include <linux/kvm_host.h>
  10. #include <linux/hw_breakpoint.h>
  11. #include <asm/debug-monitors.h>
  12. #include <asm/kvm_asm.h>
  13. #include <asm/kvm_arm.h>
  14. #include <asm/kvm_emulate.h>
  15. static int cpu_has_spe(u64 dfr0)
  16. {
  17. return cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_PMSVer_SHIFT) &&
  18. !(read_sysreg_s(SYS_PMBIDR_EL1) & PMBIDR_EL1_P);
  19. }
  20. /**
  21. * kvm_arm_setup_mdcr_el2 - configure vcpu mdcr_el2 value
  22. *
  23. * @vcpu: the vcpu pointer
  24. *
  25. * This ensures we will trap access to:
  26. * - Performance monitors (MDCR_EL2_TPM/MDCR_EL2_TPMCR)
  27. * - Debug ROM Address (MDCR_EL2_TDRA)
  28. * - OS related registers (MDCR_EL2_TDOSA)
  29. * - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB)
  30. * - Self-hosted Trace Filter controls (MDCR_EL2_TTRF)
  31. * - Self-hosted Trace (MDCR_EL2_TTRF/MDCR_EL2_E2TB)
  32. */
  33. static void kvm_arm_setup_mdcr_el2(struct kvm_vcpu *vcpu)
  34. {
  35. preempt_disable();
  36. /*
  37. * This also clears MDCR_EL2_E2PB_MASK and MDCR_EL2_E2TB_MASK
  38. * to disable guest access to the profiling and trace buffers
  39. */
  40. vcpu->arch.mdcr_el2 = FIELD_PREP(MDCR_EL2_HPMN,
  41. *host_data_ptr(nr_event_counters));
  42. vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM |
  43. MDCR_EL2_TPMS |
  44. MDCR_EL2_TTRF |
  45. MDCR_EL2_TPMCR |
  46. MDCR_EL2_TDRA |
  47. MDCR_EL2_TDOSA);
  48. /* Is the VM being debugged by userspace? */
  49. if (vcpu->guest_debug)
  50. /* Route all software debug exceptions to EL2 */
  51. vcpu->arch.mdcr_el2 |= MDCR_EL2_TDE;
  52. /*
  53. * Trap debug registers if the guest doesn't have ownership of them.
  54. */
  55. if (!kvm_guest_owns_debug_regs(vcpu))
  56. vcpu->arch.mdcr_el2 |= MDCR_EL2_TDA;
  57. if (vcpu_has_nv(vcpu))
  58. kvm_nested_setup_mdcr_el2(vcpu);
  59. /* Write MDCR_EL2 directly if we're already at EL2 */
  60. if (has_vhe())
  61. write_sysreg(vcpu->arch.mdcr_el2, mdcr_el2);
  62. preempt_enable();
  63. }
  64. void kvm_init_host_debug_data(void)
  65. {
  66. u64 dfr0 = read_sysreg(id_aa64dfr0_el1);
  67. if (cpuid_feature_extract_signed_field(dfr0, ID_AA64DFR0_EL1_PMUVer_SHIFT) > 0)
  68. *host_data_ptr(nr_event_counters) = FIELD_GET(ARMV8_PMU_PMCR_N,
  69. read_sysreg(pmcr_el0));
  70. *host_data_ptr(debug_brps) = SYS_FIELD_GET(ID_AA64DFR0_EL1, BRPs, dfr0);
  71. *host_data_ptr(debug_wrps) = SYS_FIELD_GET(ID_AA64DFR0_EL1, WRPs, dfr0);
  72. if (cpu_has_spe(dfr0))
  73. host_data_set_flag(HAS_SPE);
  74. if (has_vhe())
  75. return;
  76. /* Check if we have BRBE implemented and available at the host */
  77. if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_BRBE_SHIFT))
  78. host_data_set_flag(HAS_BRBE);
  79. if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceFilt_SHIFT)) {
  80. /* Force disable trace in protected mode in case of no TRBE */
  81. if (is_protected_kvm_enabled())
  82. host_data_set_flag(EL1_TRACING_CONFIGURED);
  83. if (cpuid_feature_extract_unsigned_field(dfr0, ID_AA64DFR0_EL1_TraceBuffer_SHIFT) &&
  84. !(read_sysreg_s(SYS_TRBIDR_EL1) & TRBIDR_EL1_P))
  85. host_data_set_flag(HAS_TRBE);
  86. }
  87. }
  88. void kvm_debug_init_vhe(void)
  89. {
  90. /* Clear PMSCR_EL1.E{0,1}SPE which reset to UNKNOWN values. */
  91. if (host_data_test_flag(HAS_SPE))
  92. write_sysreg_el1(0, SYS_PMSCR);
  93. }
  94. /*
  95. * Configures the 'external' MDSCR_EL1 value for the guest, i.e. when the host
  96. * has taken over MDSCR_EL1.
  97. *
  98. * - Userspace is single-stepping the guest, and MDSCR_EL1.SS is forced to 1.
  99. *
  100. * - Userspace is using the breakpoint/watchpoint registers to debug the
  101. * guest, and MDSCR_EL1.MDE is forced to 1.
  102. *
  103. * - The guest has enabled the OS Lock, and KVM is forcing MDSCR_EL1.MDE to 0,
  104. * masking all debug exceptions affected by the OS Lock.
  105. */
  106. static void setup_external_mdscr(struct kvm_vcpu *vcpu)
  107. {
  108. /*
  109. * Use the guest's MDSCR_EL1 as a starting point, since there are
  110. * several other features controlled by MDSCR_EL1 that are not relevant
  111. * to the host.
  112. *
  113. * Clear the bits that KVM may use which also satisfies emulation of
  114. * the OS Lock as MDSCR_EL1.MDE is cleared.
  115. */
  116. u64 mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1) & ~(MDSCR_EL1_SS |
  117. MDSCR_EL1_MDE |
  118. MDSCR_EL1_KDE);
  119. if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
  120. mdscr |= MDSCR_EL1_SS;
  121. if (vcpu->guest_debug & KVM_GUESTDBG_USE_HW)
  122. mdscr |= MDSCR_EL1_MDE | MDSCR_EL1_KDE;
  123. vcpu->arch.external_mdscr_el1 = mdscr;
  124. }
  125. void kvm_vcpu_load_debug(struct kvm_vcpu *vcpu)
  126. {
  127. u64 mdscr;
  128. /* Must be called before kvm_vcpu_load_vhe() */
  129. KVM_BUG_ON(vcpu_get_flag(vcpu, SYSREGS_ON_CPU), vcpu->kvm);
  130. if (has_vhe())
  131. *host_data_ptr(host_debug_state.mdcr_el2) = read_sysreg(mdcr_el2);
  132. /*
  133. * Determine which of the possible debug states we're in:
  134. *
  135. * - VCPU_DEBUG_HOST_OWNED: KVM has taken ownership of the guest's
  136. * breakpoint/watchpoint registers, or needs to use MDSCR_EL1 to do
  137. * software step or emulate the effects of the OS Lock being enabled.
  138. *
  139. * - VCPU_DEBUG_GUEST_OWNED: The guest has debug exceptions enabled, and
  140. * the breakpoint/watchpoint registers need to be loaded eagerly.
  141. *
  142. * - VCPU_DEBUG_FREE: Neither of the above apply, no breakpoint/watchpoint
  143. * context needs to be loaded on the CPU.
  144. */
  145. if (vcpu->guest_debug || kvm_vcpu_os_lock_enabled(vcpu)) {
  146. vcpu->arch.debug_owner = VCPU_DEBUG_HOST_OWNED;
  147. setup_external_mdscr(vcpu);
  148. /*
  149. * Steal the guest's single-step state machine if userspace wants
  150. * single-step the guest.
  151. */
  152. if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP) {
  153. if (*vcpu_cpsr(vcpu) & DBG_SPSR_SS)
  154. vcpu_clear_flag(vcpu, GUEST_SS_ACTIVE_PENDING);
  155. else
  156. vcpu_set_flag(vcpu, GUEST_SS_ACTIVE_PENDING);
  157. if (!vcpu_get_flag(vcpu, HOST_SS_ACTIVE_PENDING))
  158. *vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
  159. else
  160. *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
  161. }
  162. } else {
  163. mdscr = vcpu_read_sys_reg(vcpu, MDSCR_EL1);
  164. if (mdscr & (MDSCR_EL1_KDE | MDSCR_EL1_MDE))
  165. vcpu->arch.debug_owner = VCPU_DEBUG_GUEST_OWNED;
  166. else
  167. vcpu->arch.debug_owner = VCPU_DEBUG_FREE;
  168. }
  169. kvm_arm_setup_mdcr_el2(vcpu);
  170. }
  171. void kvm_vcpu_put_debug(struct kvm_vcpu *vcpu)
  172. {
  173. if (has_vhe())
  174. write_sysreg(*host_data_ptr(host_debug_state.mdcr_el2), mdcr_el2);
  175. if (likely(!(vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
  176. return;
  177. /*
  178. * Save the host's software step state and restore the guest's before
  179. * potentially returning to userspace.
  180. */
  181. if (!(*vcpu_cpsr(vcpu) & DBG_SPSR_SS))
  182. vcpu_set_flag(vcpu, HOST_SS_ACTIVE_PENDING);
  183. else
  184. vcpu_clear_flag(vcpu, HOST_SS_ACTIVE_PENDING);
  185. if (vcpu_get_flag(vcpu, GUEST_SS_ACTIVE_PENDING))
  186. *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
  187. else
  188. *vcpu_cpsr(vcpu) |= DBG_SPSR_SS;
  189. }
  190. /*
  191. * Updates ownership of the debug registers after a trapped guest access to a
  192. * breakpoint/watchpoint register. Host ownership of the debug registers is of
  193. * strictly higher priority, and it is the responsibility of the VMM to emulate
  194. * guest debug exceptions in this configuration.
  195. */
  196. void kvm_debug_set_guest_ownership(struct kvm_vcpu *vcpu)
  197. {
  198. if (kvm_host_owns_debug_regs(vcpu))
  199. return;
  200. vcpu->arch.debug_owner = VCPU_DEBUG_GUEST_OWNED;
  201. kvm_arm_setup_mdcr_el2(vcpu);
  202. }
  203. void kvm_debug_handle_oslar(struct kvm_vcpu *vcpu, u64 val)
  204. {
  205. if (val & OSLAR_EL1_OSLK)
  206. __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, |=, OSLSR_EL1_OSLK);
  207. else
  208. __vcpu_rmw_sys_reg(vcpu, OSLSR_EL1, &=, ~OSLSR_EL1_OSLK);
  209. preempt_disable();
  210. kvm_arch_vcpu_put(vcpu);
  211. kvm_arch_vcpu_load(vcpu, smp_processor_id());
  212. preempt_enable();
  213. }
  214. static bool skip_trbe_access(bool skip_condition)
  215. {
  216. return (WARN_ON_ONCE(preemptible()) || skip_condition ||
  217. is_protected_kvm_enabled() || !is_kvm_arm_initialised());
  218. }
  219. void kvm_enable_trbe(void)
  220. {
  221. if (!skip_trbe_access(has_vhe()))
  222. host_data_set_flag(TRBE_ENABLED);
  223. }
  224. EXPORT_SYMBOL_GPL(kvm_enable_trbe);
  225. void kvm_disable_trbe(void)
  226. {
  227. if (!skip_trbe_access(has_vhe()))
  228. host_data_clear_flag(TRBE_ENABLED);
  229. }
  230. EXPORT_SYMBOL_GPL(kvm_disable_trbe);
  231. void kvm_tracing_set_el1_configuration(u64 trfcr_while_in_guest)
  232. {
  233. if (skip_trbe_access(false))
  234. return;
  235. if (has_vhe()) {
  236. write_sysreg_s(trfcr_while_in_guest, SYS_TRFCR_EL12);
  237. return;
  238. }
  239. *host_data_ptr(trfcr_while_in_guest) = trfcr_while_in_guest;
  240. if (read_sysreg_s(SYS_TRFCR_EL1) != trfcr_while_in_guest)
  241. host_data_set_flag(EL1_TRACING_CONFIGURED);
  242. else
  243. host_data_clear_flag(EL1_TRACING_CONFIGURED);
  244. }
  245. EXPORT_SYMBOL_GPL(kvm_tracing_set_el1_configuration);