123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114 |
- // SPDX-License-Identifier: GPL-2.0-only
- /*
- * Copyright (C) 2012-2015 - ARM Ltd
- * Author: Marc Zyngier <[email protected]>
- */
- #include <hyp/sysreg-sr.h>
- #include <linux/compiler.h>
- #include <linux/kvm_host.h>
- #include <asm/kprobes.h>
- #include <asm/kvm_asm.h>
- #include <asm/kvm_emulate.h>
- #include <asm/kvm_hyp.h>
- /*
- * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and
- * pstate, which are handled as part of the el2 return state) on every
- * switch (sp_el0 is being dealt with in the assembly code).
- * tpidr_el0 and tpidrro_el0 only need to be switched when going
- * to host userspace or a different VCPU. EL1 registers only need to be
- * switched when potentially going to run a different VCPU. The latter two
- * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put.
- */
- void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt)
- {
- __sysreg_save_common_state(ctxt);
- }
- NOKPROBE_SYMBOL(sysreg_save_host_state_vhe);
- void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt)
- {
- __sysreg_save_common_state(ctxt);
- __sysreg_save_el2_return_state(ctxt);
- }
- NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
- void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt)
- {
- __sysreg_restore_common_state(ctxt);
- }
- NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe);
- void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt)
- {
- __sysreg_restore_common_state(ctxt);
- __sysreg_restore_el2_return_state(ctxt);
- }
- NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
- /**
- * kvm_vcpu_load_sysregs_vhe - Load guest system registers to the physical CPU
- *
- * @vcpu: The VCPU pointer
- *
- * Load system registers that do not affect the host's execution, for
- * example EL1 system registers on a VHE system where the host kernel
- * runs at EL2. This function is called from KVM's vcpu_load() function
- * and loading system register state early avoids having to load them on
- * every entry to the VM.
- */
- void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu)
- {
- struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
- struct kvm_cpu_context *host_ctxt;
- host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
- __sysreg_save_user_state(host_ctxt);
- /*
- * Load guest EL1 and user state
- *
- * We must restore the 32-bit state before the sysregs, thanks
- * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72).
- */
- __sysreg32_restore_state(vcpu);
- __sysreg_restore_user_state(guest_ctxt);
- __sysreg_restore_el1_state(guest_ctxt);
- vcpu_set_flag(vcpu, SYSREGS_ON_CPU);
- activate_traps_vhe_load(vcpu);
- }
- /**
- * kvm_vcpu_put_sysregs_vhe - Restore host system registers to the physical CPU
- *
- * @vcpu: The VCPU pointer
- *
- * Save guest system registers that do not affect the host's execution, for
- * example EL1 system registers on a VHE system where the host kernel
- * runs at EL2. This function is called from KVM's vcpu_put() function
- * and deferring saving system register state until we're no longer running the
- * VCPU avoids having to save them on every exit from the VM.
- */
- void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu)
- {
- struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt;
- struct kvm_cpu_context *host_ctxt;
- host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt;
- deactivate_traps_vhe_put(vcpu);
- __sysreg_save_el1_state(guest_ctxt);
- __sysreg_save_user_state(guest_ctxt);
- __sysreg32_save_state(vcpu);
- /* Restore host user state */
- __sysreg_restore_user_state(host_ctxt);
- vcpu_clear_flag(vcpu, SYSREGS_ON_CPU);
- }
|