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