sysreg-sr.c 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Copyright (C) 2012-2015 - ARM Ltd
  4. * Author: Marc Zyngier <[email protected]>
  5. */
  6. #include <hyp/sysreg-sr.h>
  7. #include <linux/compiler.h>
  8. #include <linux/kvm_host.h>
  9. #include <asm/kprobes.h>
  10. #include <asm/kvm_asm.h>
  11. #include <asm/kvm_emulate.h>
  12. #include <asm/kvm_hyp.h>
  13. /*
  14. * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and
  15. * pstate, which are handled as part of the el2 return state) on every
  16. * switch (sp_el0 is being dealt with in the assembly code).
  17. * tpidr_el0 and tpidrro_el0 only need to be switched when going
  18. * to host userspace or a different VCPU. EL1 registers only need to be
  19. * switched when potentially going to run a different VCPU. The latter two
  20. * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put.
  21. */
  22. void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt)
  23. {
  24. __sysreg_save_common_state(ctxt);
  25. }
  26. NOKPROBE_SYMBOL(sysreg_save_host_state_vhe);
  27. void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt)
  28. {
  29. __sysreg_save_common_state(ctxt);
  30. __sysreg_save_el2_return_state(ctxt);
  31. }
  32. NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
  33. void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt)
  34. {
  35. __sysreg_restore_common_state(ctxt);
  36. }
  37. NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe);
  38. void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt)
  39. {
  40. __sysreg_restore_common_state(ctxt);
  41. __sysreg_restore_el2_return_state(ctxt);
  42. }
  43. NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
  44. /**
  45. * kvm_vcpu_load_sysregs_vhe - Load guest system registers to the physical CPU
  46. *
  47. * @vcpu: The VCPU pointer
  48. *
  49. * Load system registers that do not affect the host's execution, for
  50. * example EL1 system registers on a VHE system where the host kernel
  51. * runs at EL2. This function is called from KVM's vcpu_load() function
  52. * and loading system register state early avoids having to load them on
  53. * every entry to the VM.
  54. */
  55. void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu)
  56. {
  57. struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
  58. struct kvm_cpu_context *host_ctxt;
  59. host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
  60. __sysreg_save_user_state(host_ctxt);
  61. /*
  62. * Load guest EL1 and user state
  63. *
  64. * We must restore the 32-bit state before the sysregs, thanks
  65. * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72).
  66. */
  67. __sysreg32_restore_state(vcpu);
  68. __sysreg_restore_user_state(guest_ctxt);
  69. __sysreg_restore_el1_state(guest_ctxt);
  70. vcpu_set_flag(vcpu, SYSREGS_ON_CPU);
  71. activate_traps_vhe_load(vcpu);
  72. }
  73. /**
  74. * kvm_vcpu_put_sysregs_vhe - Restore host system registers to the physical CPU
  75. *
  76. * @vcpu: The VCPU pointer
  77. *
  78. * Save guest system registers that do not affect the host's execution, for
  79. * example EL1 system registers on a VHE system where the host kernel
  80. * runs at EL2. This function is called from KVM's vcpu_put() function
  81. * and deferring saving system register state until we're no longer running the
  82. * VCPU avoids having to save them on every exit from the VM.
  83. */
  84. void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu)
  85. {
  86. struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
  87. struct kvm_cpu_context *host_ctxt;
  88. host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
  89. deactivate_traps_vhe_put(vcpu);
  90. __sysreg_save_el1_state(guest_ctxt);
  91. __sysreg_save_user_state(guest_ctxt);
  92. __sysreg32_save_state(vcpu);
  93. /* Restore host user state */
  94. __sysreg_restore_user_state(host_ctxt);
  95. vcpu_clear_flag(vcpu, SYSREGS_ON_CPU);
  96. }