18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * Copyright (C) 2012-2015 - ARM Ltd 48c2ecf20Sopenharmony_ci * Author: Marc Zyngier <marc.zyngier@arm.com> 58c2ecf20Sopenharmony_ci */ 68c2ecf20Sopenharmony_ci 78c2ecf20Sopenharmony_ci#include <hyp/sysreg-sr.h> 88c2ecf20Sopenharmony_ci 98c2ecf20Sopenharmony_ci#include <linux/compiler.h> 108c2ecf20Sopenharmony_ci#include <linux/kvm_host.h> 118c2ecf20Sopenharmony_ci 128c2ecf20Sopenharmony_ci#include <asm/kprobes.h> 138c2ecf20Sopenharmony_ci#include <asm/kvm_asm.h> 148c2ecf20Sopenharmony_ci#include <asm/kvm_emulate.h> 158c2ecf20Sopenharmony_ci#include <asm/kvm_hyp.h> 168c2ecf20Sopenharmony_ci 178c2ecf20Sopenharmony_ci/* 188c2ecf20Sopenharmony_ci * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and 198c2ecf20Sopenharmony_ci * pstate, which are handled as part of the el2 return state) on every 208c2ecf20Sopenharmony_ci * switch (sp_el0 is being dealt with in the assembly code). 218c2ecf20Sopenharmony_ci * tpidr_el0 and tpidrro_el0 only need to be switched when going 228c2ecf20Sopenharmony_ci * to host userspace or a different VCPU. EL1 registers only need to be 238c2ecf20Sopenharmony_ci * switched when potentially going to run a different VCPU. The latter two 248c2ecf20Sopenharmony_ci * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put. 258c2ecf20Sopenharmony_ci */ 268c2ecf20Sopenharmony_ci 278c2ecf20Sopenharmony_civoid sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt) 288c2ecf20Sopenharmony_ci{ 298c2ecf20Sopenharmony_ci __sysreg_save_common_state(ctxt); 308c2ecf20Sopenharmony_ci} 318c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(sysreg_save_host_state_vhe); 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_civoid sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt) 348c2ecf20Sopenharmony_ci{ 358c2ecf20Sopenharmony_ci __sysreg_save_common_state(ctxt); 368c2ecf20Sopenharmony_ci __sysreg_save_el2_return_state(ctxt); 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(sysreg_save_guest_state_vhe); 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_civoid sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci __sysreg_restore_common_state(ctxt); 438c2ecf20Sopenharmony_ci} 448c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(sysreg_restore_host_state_vhe); 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_civoid sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt) 478c2ecf20Sopenharmony_ci{ 488c2ecf20Sopenharmony_ci __sysreg_restore_common_state(ctxt); 498c2ecf20Sopenharmony_ci __sysreg_restore_el2_return_state(ctxt); 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ciNOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe); 528c2ecf20Sopenharmony_ci 538c2ecf20Sopenharmony_ci/** 548c2ecf20Sopenharmony_ci * kvm_vcpu_load_sysregs_vhe - Load guest system registers to the physical CPU 558c2ecf20Sopenharmony_ci * 568c2ecf20Sopenharmony_ci * @vcpu: The VCPU pointer 578c2ecf20Sopenharmony_ci * 588c2ecf20Sopenharmony_ci * Load system registers that do not affect the host's execution, for 598c2ecf20Sopenharmony_ci * example EL1 system registers on a VHE system where the host kernel 608c2ecf20Sopenharmony_ci * runs at EL2. This function is called from KVM's vcpu_load() function 618c2ecf20Sopenharmony_ci * and loading system register state early avoids having to load them on 628c2ecf20Sopenharmony_ci * every entry to the VM. 638c2ecf20Sopenharmony_ci */ 648c2ecf20Sopenharmony_civoid kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu) 658c2ecf20Sopenharmony_ci{ 668c2ecf20Sopenharmony_ci struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; 678c2ecf20Sopenharmony_ci struct kvm_cpu_context *host_ctxt; 688c2ecf20Sopenharmony_ci 698c2ecf20Sopenharmony_ci host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; 708c2ecf20Sopenharmony_ci __sysreg_save_user_state(host_ctxt); 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci /* 738c2ecf20Sopenharmony_ci * Load guest EL1 and user state 748c2ecf20Sopenharmony_ci * 758c2ecf20Sopenharmony_ci * We must restore the 32-bit state before the sysregs, thanks 768c2ecf20Sopenharmony_ci * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72). 778c2ecf20Sopenharmony_ci */ 788c2ecf20Sopenharmony_ci __sysreg32_restore_state(vcpu); 798c2ecf20Sopenharmony_ci __sysreg_restore_user_state(guest_ctxt); 808c2ecf20Sopenharmony_ci __sysreg_restore_el1_state(guest_ctxt); 818c2ecf20Sopenharmony_ci 828c2ecf20Sopenharmony_ci vcpu->arch.sysregs_loaded_on_cpu = true; 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci activate_traps_vhe_load(vcpu); 858c2ecf20Sopenharmony_ci} 868c2ecf20Sopenharmony_ci 878c2ecf20Sopenharmony_ci/** 888c2ecf20Sopenharmony_ci * kvm_vcpu_put_sysregs_vhe - Restore host system registers to the physical CPU 898c2ecf20Sopenharmony_ci * 908c2ecf20Sopenharmony_ci * @vcpu: The VCPU pointer 918c2ecf20Sopenharmony_ci * 928c2ecf20Sopenharmony_ci * Save guest system registers that do not affect the host's execution, for 938c2ecf20Sopenharmony_ci * example EL1 system registers on a VHE system where the host kernel 948c2ecf20Sopenharmony_ci * runs at EL2. This function is called from KVM's vcpu_put() function 958c2ecf20Sopenharmony_ci * and deferring saving system register state until we're no longer running the 968c2ecf20Sopenharmony_ci * VCPU avoids having to save them on every exit from the VM. 978c2ecf20Sopenharmony_ci */ 988c2ecf20Sopenharmony_civoid kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu) 998c2ecf20Sopenharmony_ci{ 1008c2ecf20Sopenharmony_ci struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; 1018c2ecf20Sopenharmony_ci struct kvm_cpu_context *host_ctxt; 1028c2ecf20Sopenharmony_ci 1038c2ecf20Sopenharmony_ci host_ctxt = &this_cpu_ptr(&kvm_host_data)->host_ctxt; 1048c2ecf20Sopenharmony_ci deactivate_traps_vhe_put(); 1058c2ecf20Sopenharmony_ci 1068c2ecf20Sopenharmony_ci __sysreg_save_el1_state(guest_ctxt); 1078c2ecf20Sopenharmony_ci __sysreg_save_user_state(guest_ctxt); 1088c2ecf20Sopenharmony_ci __sysreg32_save_state(vcpu); 1098c2ecf20Sopenharmony_ci 1108c2ecf20Sopenharmony_ci /* Restore host user state */ 1118c2ecf20Sopenharmony_ci __sysreg_restore_user_state(host_ctxt); 1128c2ecf20Sopenharmony_ci 1138c2ecf20Sopenharmony_ci vcpu->arch.sysregs_loaded_on_cpu = false; 1148c2ecf20Sopenharmony_ci} 115