Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

KVM: arm64: Split hyp/sysreg-sr.c to VHE/nVHE

sysreg-sr.c contains KVM's code for saving/restoring system registers, with
some code shared between VHE/nVHE. These common routines are moved to
a header file, VHE-specific code is moved to vhe/sysreg-sr.c and nVHE-specific
code to nvhe/sysreg-sr.c.

Signed-off-by: David Brazdil <dbrazdil@google.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20200625131420.71444-12-dbrazdil@google.com

authored by

David Brazdil and committed by
Marc Zyngier
13aeb9b4 d400c5b2

+191 -164
+3 -3
arch/arm64/include/asm/kvm_host.h
··· 338 338 struct vcpu_reset_state reset_state; 339 339 340 340 /* True when deferrable sysregs are loaded on the physical CPU, 341 - * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */ 341 + * see kvm_vcpu_load_sysregs_vhe and kvm_vcpu_put_sysregs_vhe. */ 342 342 bool sysregs_loaded_on_cpu; 343 343 344 344 /* Guest PV state */ ··· 639 639 } 640 640 } 641 641 642 - void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu); 643 - void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu); 642 + void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu); 643 + void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu); 644 644 645 645 int kvm_set_ipa_limit(void); 646 646
+3 -2
arch/arm64/include/asm/kvm_hyp.h
··· 66 66 void __timer_enable_traps(struct kvm_vcpu *vcpu); 67 67 void __timer_disable_traps(struct kvm_vcpu *vcpu); 68 68 69 + #ifdef __KVM_NVHE_HYPERVISOR__ 69 70 void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt); 70 71 void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt); 72 + #else 71 73 void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt); 72 74 void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt); 73 75 void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt); 74 76 void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt); 75 - void __sysreg32_save_state(struct kvm_vcpu *vcpu); 76 - void __sysreg32_restore_state(struct kvm_vcpu *vcpu); 77 + #endif 77 78 78 79 void __debug_switch_to_guest(struct kvm_vcpu *vcpu); 79 80 void __debug_switch_to_host(struct kvm_vcpu *vcpu);
-7
arch/arm64/kernel/image-vars.h
··· 76 76 KVM_NVHE_ALIAS(__fpsimd_restore_state); 77 77 KVM_NVHE_ALIAS(__fpsimd_save_state); 78 78 79 - /* Symbols defined in sysreg-sr.c (not yet compiled with nVHE build rules). */ 80 - KVM_NVHE_ALIAS(__kvm_enable_ssbs); 81 - KVM_NVHE_ALIAS(__sysreg32_restore_state); 82 - KVM_NVHE_ALIAS(__sysreg32_save_state); 83 - KVM_NVHE_ALIAS(__sysreg_restore_state_nvhe); 84 - KVM_NVHE_ALIAS(__sysreg_save_state_nvhe); 85 - 86 79 /* Symbols defined in timer-sr.c (not yet compiled with nVHE build rules). */ 87 80 KVM_NVHE_ALIAS(__kvm_timer_set_cntvoff); 88 81 KVM_NVHE_ALIAS(__timer_disable_traps);
+5 -3
arch/arm64/kvm/arm.c
··· 351 351 352 352 kvm_vgic_load(vcpu); 353 353 kvm_timer_vcpu_load(vcpu); 354 - kvm_vcpu_load_sysregs(vcpu); 354 + if (has_vhe()) 355 + kvm_vcpu_load_sysregs_vhe(vcpu); 355 356 kvm_arch_vcpu_load_fp(vcpu); 356 357 kvm_vcpu_pmu_restore_guest(vcpu); 357 358 if (kvm_arm_is_pvtime_enabled(&vcpu->arch)) ··· 370 369 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu) 371 370 { 372 371 kvm_arch_vcpu_put_fp(vcpu); 373 - kvm_vcpu_put_sysregs(vcpu); 372 + if (has_vhe()) 373 + kvm_vcpu_put_sysregs_vhe(vcpu); 374 374 kvm_timer_vcpu_put(vcpu); 375 375 kvm_vgic_put(vcpu); 376 376 kvm_vcpu_pmu_restore_host(vcpu); ··· 1304 1302 */ 1305 1303 if (this_cpu_has_cap(ARM64_SSBS) && 1306 1304 arm64_get_ssbd_state() == ARM64_SSBD_FORCE_DISABLE) { 1307 - kvm_call_hyp(__kvm_enable_ssbs); 1305 + kvm_call_hyp_nvhe(__kvm_enable_ssbs); 1308 1306 } 1309 1307 } 1310 1308
+2 -2
arch/arm64/kvm/hyp/Makefile
··· 13 13 obj-$(CONFIG_KVM) += hyp.o vhe/ nvhe/ 14 14 obj-$(CONFIG_KVM_INDIRECT_VECTORS) += smccc_wa.o 15 15 16 - hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o sysreg-sr.o \ 17 - entry.o fpsimd.o 16 + hyp-y := vgic-v3-sr.o timer-sr.o aarch32.o vgic-v2-cpuif-proxy.o entry.o \ 17 + fpsimd.o 18 18 19 19 # KVM code is run at a different exception code with a different map, so 20 20 # compiler instrumentation that inserts callbacks or checks into the code may
+1 -1
arch/arm64/kvm/hyp/nvhe/Makefile
··· 6 6 asflags-y := -D__KVM_NVHE_HYPERVISOR__ 7 7 ccflags-y := -D__KVM_NVHE_HYPERVISOR__ 8 8 9 - obj-y := debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o 9 + obj-y := sysreg-sr.o debug-sr.o switch.o tlb.o hyp-init.o ../hyp-entry.o 10 10 11 11 obj-y := $(patsubst %.o,%.hyp.o,$(obj-y)) 12 12 extra-y := $(patsubst %.hyp.o,%.hyp.tmp.o,$(obj-y))
+1
arch/arm64/kvm/hyp/nvhe/switch.c
··· 5 5 */ 6 6 7 7 #include <hyp/switch.h> 8 + #include <hyp/sysreg-sr.h> 8 9 9 10 #include <linux/arm-smccc.h> 10 11 #include <linux/kvm_host.h>
+46
arch/arm64/kvm/hyp/nvhe/sysreg-sr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2012-2015 - ARM Ltd 4 + * Author: Marc Zyngier <marc.zyngier@arm.com> 5 + */ 6 + 7 + #include <hyp/sysreg-sr.h> 8 + 9 + #include <linux/compiler.h> 10 + #include <linux/kvm_host.h> 11 + 12 + #include <asm/kprobes.h> 13 + #include <asm/kvm_asm.h> 14 + #include <asm/kvm_emulate.h> 15 + #include <asm/kvm_hyp.h> 16 + 17 + /* 18 + * Non-VHE: Both host and guest must save everything. 19 + */ 20 + 21 + void __hyp_text __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) 22 + { 23 + __sysreg_save_el1_state(ctxt); 24 + __sysreg_save_common_state(ctxt); 25 + __sysreg_save_user_state(ctxt); 26 + __sysreg_save_el2_return_state(ctxt); 27 + } 28 + 29 + void __hyp_text __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) 30 + { 31 + __sysreg_restore_el1_state(ctxt); 32 + __sysreg_restore_common_state(ctxt); 33 + __sysreg_restore_user_state(ctxt); 34 + __sysreg_restore_el2_return_state(ctxt); 35 + } 36 + 37 + void __hyp_text __kvm_enable_ssbs(void) 38 + { 39 + u64 tmp; 40 + 41 + asm volatile( 42 + "mrs %0, sctlr_el2\n" 43 + "orr %0, %0, %1\n" 44 + "msr sctlr_el2, %0" 45 + : "=&r" (tmp) : "L" (SCTLR_ELx_DSSBS)); 46 + }
+14 -144
arch/arm64/kvm/hyp/sysreg-sr.c arch/arm64/kvm/hyp/include/hyp/sysreg-sr.h
··· 4 4 * Author: Marc Zyngier <marc.zyngier@arm.com> 5 5 */ 6 6 7 + #ifndef __ARM64_KVM_HYP_SYSREG_SR_H__ 8 + #define __ARM64_KVM_HYP_SYSREG_SR_H__ 9 + 7 10 #include <linux/compiler.h> 8 11 #include <linux/kvm_host.h> 9 12 ··· 15 12 #include <asm/kvm_emulate.h> 16 13 #include <asm/kvm_hyp.h> 17 14 18 - /* 19 - * Non-VHE: Both host and guest must save everything. 20 - * 21 - * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and 22 - * pstate, which are handled as part of the el2 return state) on every 23 - * switch (sp_el0 is being dealt with in the assembly code). 24 - * tpidr_el0 and tpidrro_el0 only need to be switched when going 25 - * to host userspace or a different VCPU. EL1 registers only need to be 26 - * switched when potentially going to run a different VCPU. The latter two 27 - * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put. 28 - */ 29 - 30 - static void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) 15 + static inline void __hyp_text __sysreg_save_common_state(struct kvm_cpu_context *ctxt) 31 16 { 32 17 ctxt->sys_regs[MDSCR_EL1] = read_sysreg(mdscr_el1); 33 18 } 34 19 35 - static void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt) 20 + static inline void __hyp_text __sysreg_save_user_state(struct kvm_cpu_context *ctxt) 36 21 { 37 22 ctxt->sys_regs[TPIDR_EL0] = read_sysreg(tpidr_el0); 38 23 ctxt->sys_regs[TPIDRRO_EL0] = read_sysreg(tpidrro_el0); 39 24 } 40 25 41 - static void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) 26 + static inline void __hyp_text __sysreg_save_el1_state(struct kvm_cpu_context *ctxt) 42 27 { 43 28 ctxt->sys_regs[CSSELR_EL1] = read_sysreg(csselr_el1); 44 29 ctxt->sys_regs[SCTLR_EL1] = read_sysreg_el1(SYS_SCTLR); ··· 51 60 ctxt->gp_regs.spsr[KVM_SPSR_EL1]= read_sysreg_el1(SYS_SPSR); 52 61 } 53 62 54 - static void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) 63 + static inline void __hyp_text __sysreg_save_el2_return_state(struct kvm_cpu_context *ctxt) 55 64 { 56 65 ctxt->gp_regs.regs.pc = read_sysreg_el2(SYS_ELR); 57 66 ctxt->gp_regs.regs.pstate = read_sysreg_el2(SYS_SPSR); ··· 60 69 ctxt->sys_regs[DISR_EL1] = read_sysreg_s(SYS_VDISR_EL2); 61 70 } 62 71 63 - void __hyp_text __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt) 64 - { 65 - __sysreg_save_el1_state(ctxt); 66 - __sysreg_save_common_state(ctxt); 67 - __sysreg_save_user_state(ctxt); 68 - __sysreg_save_el2_return_state(ctxt); 69 - } 70 - 71 - void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt) 72 - { 73 - __sysreg_save_common_state(ctxt); 74 - } 75 - NOKPROBE_SYMBOL(sysreg_save_host_state_vhe); 76 - 77 - void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt) 78 - { 79 - __sysreg_save_common_state(ctxt); 80 - __sysreg_save_el2_return_state(ctxt); 81 - } 82 - NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe); 83 - 84 - static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) 72 + static inline void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt) 85 73 { 86 74 write_sysreg(ctxt->sys_regs[MDSCR_EL1], mdscr_el1); 87 75 } 88 76 89 - static void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) 77 + static inline void __hyp_text __sysreg_restore_user_state(struct kvm_cpu_context *ctxt) 90 78 { 91 79 write_sysreg(ctxt->sys_regs[TPIDR_EL0], tpidr_el0); 92 80 write_sysreg(ctxt->sys_regs[TPIDRRO_EL0], tpidrro_el0); 93 81 } 94 82 95 - static void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) 83 + static inline void __hyp_text __sysreg_restore_el1_state(struct kvm_cpu_context *ctxt) 96 84 { 97 85 write_sysreg(ctxt->sys_regs[MPIDR_EL1], vmpidr_el2); 98 86 write_sysreg(ctxt->sys_regs[CSSELR_EL1], csselr_el1); ··· 130 160 write_sysreg_el1(ctxt->gp_regs.spsr[KVM_SPSR_EL1],SYS_SPSR); 131 161 } 132 162 133 - static void __hyp_text 134 - __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) 163 + static inline void __hyp_text __sysreg_restore_el2_return_state(struct kvm_cpu_context *ctxt) 135 164 { 136 165 u64 pstate = ctxt->gp_regs.regs.pstate; 137 166 u64 mode = pstate & PSR_AA32_MODE_MASK; ··· 156 187 write_sysreg_s(ctxt->sys_regs[DISR_EL1], SYS_VDISR_EL2); 157 188 } 158 189 159 - void __hyp_text __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt) 160 - { 161 - __sysreg_restore_el1_state(ctxt); 162 - __sysreg_restore_common_state(ctxt); 163 - __sysreg_restore_user_state(ctxt); 164 - __sysreg_restore_el2_return_state(ctxt); 165 - } 166 - 167 - void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt) 168 - { 169 - __sysreg_restore_common_state(ctxt); 170 - } 171 - NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe); 172 - 173 - void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt) 174 - { 175 - __sysreg_restore_common_state(ctxt); 176 - __sysreg_restore_el2_return_state(ctxt); 177 - } 178 - NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe); 179 - 180 - void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) 190 + static inline void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu) 181 191 { 182 192 u64 *spsr, *sysreg; 183 193 ··· 178 230 sysreg[DBGVCR32_EL2] = read_sysreg(dbgvcr32_el2); 179 231 } 180 232 181 - void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) 233 + static inline void __hyp_text __sysreg32_restore_state(struct kvm_vcpu *vcpu) 182 234 { 183 235 u64 *spsr, *sysreg; 184 236 ··· 200 252 write_sysreg(sysreg[DBGVCR32_EL2], dbgvcr32_el2); 201 253 } 202 254 203 - /** 204 - * kvm_vcpu_load_sysregs - Load guest system registers to the physical CPU 205 - * 206 - * @vcpu: The VCPU pointer 207 - * 208 - * Load system registers that do not affect the host's execution, for 209 - * example EL1 system registers on a VHE system where the host kernel 210 - * runs at EL2. This function is called from KVM's vcpu_load() function 211 - * and loading system register state early avoids having to load them on 212 - * every entry to the VM. 213 - */ 214 - void kvm_vcpu_load_sysregs(struct kvm_vcpu *vcpu) 215 - { 216 - struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; 217 - struct kvm_cpu_context *host_ctxt; 218 - 219 - if (!has_vhe()) 220 - return; 221 - 222 - host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; 223 - __sysreg_save_user_state(host_ctxt); 224 - 225 - /* 226 - * Load guest EL1 and user state 227 - * 228 - * We must restore the 32-bit state before the sysregs, thanks 229 - * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72). 230 - */ 231 - __sysreg32_restore_state(vcpu); 232 - __sysreg_restore_user_state(guest_ctxt); 233 - __sysreg_restore_el1_state(guest_ctxt); 234 - 235 - vcpu->arch.sysregs_loaded_on_cpu = true; 236 - 237 - activate_traps_vhe_load(vcpu); 238 - } 239 - 240 - /** 241 - * kvm_vcpu_put_sysregs - Restore host system registers to the physical CPU 242 - * 243 - * @vcpu: The VCPU pointer 244 - * 245 - * Save guest system registers that do not affect the host's execution, for 246 - * example EL1 system registers on a VHE system where the host kernel 247 - * runs at EL2. This function is called from KVM's vcpu_put() function 248 - * and deferring saving system register state until we're no longer running the 249 - * VCPU avoids having to save them on every exit from the VM. 250 - */ 251 - void kvm_vcpu_put_sysregs(struct kvm_vcpu *vcpu) 252 - { 253 - struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; 254 - struct kvm_cpu_context *host_ctxt; 255 - 256 - if (!has_vhe()) 257 - return; 258 - 259 - host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; 260 - deactivate_traps_vhe_put(); 261 - 262 - __sysreg_save_el1_state(guest_ctxt); 263 - __sysreg_save_user_state(guest_ctxt); 264 - __sysreg32_save_state(vcpu); 265 - 266 - /* Restore host user state */ 267 - __sysreg_restore_user_state(host_ctxt); 268 - 269 - vcpu->arch.sysregs_loaded_on_cpu = false; 270 - } 271 - 272 - void __hyp_text __kvm_enable_ssbs(void) 273 - { 274 - u64 tmp; 275 - 276 - asm volatile( 277 - "mrs %0, sctlr_el2\n" 278 - "orr %0, %0, %1\n" 279 - "msr sctlr_el2, %0" 280 - : "=&r" (tmp) : "L" (SCTLR_ELx_DSSBS)); 281 - } 255 + #endif /* __ARM64_KVM_HYP_SYSREG_SR_H__ */
+1 -1
arch/arm64/kvm/hyp/vhe/Makefile
··· 6 6 asflags-y := -D__KVM_VHE_HYPERVISOR__ 7 7 ccflags-y := -D__KVM_VHE_HYPERVISOR__ 8 8 9 - obj-y := debug-sr.o switch.o tlb.o ../hyp-entry.o 9 + obj-y := sysreg-sr.o debug-sr.o switch.o tlb.o ../hyp-entry.o 10 10 11 11 # KVM code is run at a different exception code with a different map, so 12 12 # compiler instrumentation that inserts callbacks or checks into the code may
+1 -1
arch/arm64/kvm/hyp/vhe/switch.c
··· 120 120 * HCR_EL2.TGE. 121 121 * 122 122 * We have already configured the guest's stage 1 translation in 123 - * kvm_vcpu_load_sysregs above. We must now call __activate_vm 123 + * kvm_vcpu_load_sysregs_vhe above. We must now call __activate_vm 124 124 * before __activate_traps, because __activate_vm configures 125 125 * stage 2 translation, and __activate_traps clear HCR_EL2.TGE 126 126 * (among other things).
+114
arch/arm64/kvm/hyp/vhe/sysreg-sr.c
··· 1 + // SPDX-License-Identifier: GPL-2.0-only 2 + /* 3 + * Copyright (C) 2012-2015 - ARM Ltd 4 + * Author: Marc Zyngier <marc.zyngier@arm.com> 5 + */ 6 + 7 + #include <hyp/sysreg-sr.h> 8 + 9 + #include <linux/compiler.h> 10 + #include <linux/kvm_host.h> 11 + 12 + #include <asm/kprobes.h> 13 + #include <asm/kvm_asm.h> 14 + #include <asm/kvm_emulate.h> 15 + #include <asm/kvm_hyp.h> 16 + 17 + /* 18 + * VHE: Host and guest must save mdscr_el1 and sp_el0 (and the PC and 19 + * pstate, which are handled as part of the el2 return state) on every 20 + * switch (sp_el0 is being dealt with in the assembly code). 21 + * tpidr_el0 and tpidrro_el0 only need to be switched when going 22 + * to host userspace or a different VCPU. EL1 registers only need to be 23 + * switched when potentially going to run a different VCPU. The latter two 24 + * classes are handled as part of kvm_arch_vcpu_load and kvm_arch_vcpu_put. 25 + */ 26 + 27 + void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt) 28 + { 29 + __sysreg_save_common_state(ctxt); 30 + } 31 + NOKPROBE_SYMBOL(sysreg_save_host_state_vhe); 32 + 33 + void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt) 34 + { 35 + __sysreg_save_common_state(ctxt); 36 + __sysreg_save_el2_return_state(ctxt); 37 + } 38 + NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe); 39 + 40 + void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt) 41 + { 42 + __sysreg_restore_common_state(ctxt); 43 + } 44 + NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe); 45 + 46 + void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt) 47 + { 48 + __sysreg_restore_common_state(ctxt); 49 + __sysreg_restore_el2_return_state(ctxt); 50 + } 51 + NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe); 52 + 53 + /** 54 + * kvm_vcpu_load_sysregs_vhe - Load guest system registers to the physical CPU 55 + * 56 + * @vcpu: The VCPU pointer 57 + * 58 + * Load system registers that do not affect the host's execution, for 59 + * example EL1 system registers on a VHE system where the host kernel 60 + * runs at EL2. This function is called from KVM's vcpu_load() function 61 + * and loading system register state early avoids having to load them on 62 + * every entry to the VM. 63 + */ 64 + void kvm_vcpu_load_sysregs_vhe(struct kvm_vcpu *vcpu) 65 + { 66 + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; 67 + struct kvm_cpu_context *host_ctxt; 68 + 69 + host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; 70 + __sysreg_save_user_state(host_ctxt); 71 + 72 + /* 73 + * Load guest EL1 and user state 74 + * 75 + * We must restore the 32-bit state before the sysregs, thanks 76 + * to erratum #852523 (Cortex-A57) or #853709 (Cortex-A72). 77 + */ 78 + __sysreg32_restore_state(vcpu); 79 + __sysreg_restore_user_state(guest_ctxt); 80 + __sysreg_restore_el1_state(guest_ctxt); 81 + 82 + vcpu->arch.sysregs_loaded_on_cpu = true; 83 + 84 + activate_traps_vhe_load(vcpu); 85 + } 86 + 87 + /** 88 + * kvm_vcpu_put_sysregs_vhe - Restore host system registers to the physical CPU 89 + * 90 + * @vcpu: The VCPU pointer 91 + * 92 + * Save guest system registers that do not affect the host's execution, for 93 + * example EL1 system registers on a VHE system where the host kernel 94 + * runs at EL2. This function is called from KVM's vcpu_put() function 95 + * and deferring saving system register state until we're no longer running the 96 + * VCPU avoids having to save them on every exit from the VM. 97 + */ 98 + void kvm_vcpu_put_sysregs_vhe(struct kvm_vcpu *vcpu) 99 + { 100 + struct kvm_cpu_context *guest_ctxt = &vcpu->arch.ctxt; 101 + struct kvm_cpu_context *host_ctxt; 102 + 103 + host_ctxt = &__hyp_this_cpu_ptr(kvm_host_data)->host_ctxt; 104 + deactivate_traps_vhe_put(); 105 + 106 + __sysreg_save_el1_state(guest_ctxt); 107 + __sysreg_save_user_state(guest_ctxt); 108 + __sysreg32_save_state(vcpu); 109 + 110 + /* Restore host user state */ 111 + __sysreg_restore_user_state(host_ctxt); 112 + 113 + vcpu->arch.sysregs_loaded_on_cpu = false; 114 + }