debug-sr.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2015 - ARM Ltd
  4. * Author: Marc Zyngier <[email protected]>
  5. */
  6. #include <hyp/debug-sr.h>
  7. #include <linux/compiler.h>
  8. #include <linux/kvm_host.h>
  9. #include <asm/debug-monitors.h>
  10. #include <asm/kvm_asm.h>
  11. #include <asm/kvm_hyp.h>
  12. #include <asm/kvm_mmu.h>
  13. static void __debug_save_spe(u64 *pmscr_el1)
  14. {
  15. u64 reg;
  16. /* Clear pmscr in case of early return */
  17. *pmscr_el1 = 0;
  18. /*
  19. * At this point, we know that this CPU implements
  20. * SPE and is available to the host.
  21. * Check if the host is actually using it ?
  22. */
  23. reg = read_sysreg_s(SYS_PMBLIMITR_EL1);
  24. if (!(reg & BIT(SYS_PMBLIMITR_EL1_E_SHIFT)))
  25. return;
  26. /* Yes; save the control register and disable data generation */
  27. *pmscr_el1 = read_sysreg_s(SYS_PMSCR_EL1);
  28. write_sysreg_s(0, SYS_PMSCR_EL1);
  29. isb();
  30. /* Now drain all buffered data to memory */
  31. psb_csync();
  32. dsb(nsh);
  33. }
  34. static void __debug_restore_spe(u64 pmscr_el1)
  35. {
  36. if (!pmscr_el1)
  37. return;
  38. /* The host page table is installed, but not yet synchronised */
  39. isb();
  40. /* Re-enable data generation */
  41. write_sysreg_s(pmscr_el1, SYS_PMSCR_EL1);
  42. }
  43. static void __debug_save_trace(u64 *trfcr_el1)
  44. {
  45. *trfcr_el1 = 0;
  46. /* Check if the TRBE is enabled */
  47. if (!(read_sysreg_s(SYS_TRBLIMITR_EL1) & TRBLIMITR_ENABLE))
  48. return;
  49. /*
  50. * Prohibit trace generation while we are in guest.
  51. * Since access to TRFCR_EL1 is trapped, the guest can't
  52. * modify the filtering set by the host.
  53. */
  54. *trfcr_el1 = read_sysreg_s(SYS_TRFCR_EL1);
  55. write_sysreg_s(0, SYS_TRFCR_EL1);
  56. isb();
  57. /* Drain the trace buffer to memory */
  58. tsb_csync();
  59. dsb(nsh);
  60. }
  61. static void __debug_restore_trace(u64 trfcr_el1)
  62. {
  63. if (!trfcr_el1)
  64. return;
  65. /* Restore trace filter controls */
  66. write_sysreg_s(trfcr_el1, SYS_TRFCR_EL1);
  67. }
  68. void __debug_save_host_buffers_nvhe(struct kvm_vcpu *vcpu)
  69. {
  70. /* Disable and flush SPE data generation */
  71. if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE))
  72. __debug_save_spe(&vcpu->arch.host_debug_state.pmscr_el1);
  73. /* Disable and flush Self-Hosted Trace generation */
  74. if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
  75. __debug_save_trace(&vcpu->arch.host_debug_state.trfcr_el1);
  76. }
  77. void __debug_switch_to_guest(struct kvm_vcpu *vcpu)
  78. {
  79. __debug_switch_to_guest_common(vcpu);
  80. }
  81. void __debug_restore_host_buffers_nvhe(struct kvm_vcpu *vcpu)
  82. {
  83. if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_SPE))
  84. __debug_restore_spe(vcpu->arch.host_debug_state.pmscr_el1);
  85. if (vcpu_get_flag(vcpu, DEBUG_STATE_SAVE_TRBE))
  86. __debug_restore_trace(vcpu->arch.host_debug_state.trfcr_el1);
  87. }
  88. void __debug_switch_to_host(struct kvm_vcpu *vcpu)
  89. {
  90. __debug_switch_to_host_common(vcpu);
  91. }
  92. u64 __kvm_get_mdcr_el2(void)
  93. {
  94. return read_sysreg(mdcr_el2);
  95. }