1// SPDX-License-Identifier: GPL-2.0-only
2/*
3 * Guest PC manipulation helpers
4 *
5 * Copyright (C) 2012,2013 - ARM Ltd
6 * Copyright (C) 2020 - Google LLC
7 * Author: Marc Zyngier <maz@kernel.org>
8 */
9
10#ifndef __ARM64_KVM_HYP_ADJUST_PC_H__
11#define __ARM64_KVM_HYP_ADJUST_PC_H__
12
13#include <asm/kvm_emulate.h>
14#include <asm/kvm_host.h>
15
16static inline void kvm_skip_instr(struct kvm_vcpu *vcpu)
17{
18 if (vcpu_mode_is_32bit(vcpu)) {
19 kvm_skip_instr32(vcpu);
20 } else {
21 *vcpu_pc(vcpu) += 4;
22 *vcpu_cpsr(vcpu) &= ~PSR_BTYPE_MASK;
23 }
24
25 /* advance the singlestep state machine */
26 *vcpu_cpsr(vcpu) &= ~DBG_SPSR_SS;
27}
28
29/*
30 * Skip an instruction which has been emulated at hyp while most guest sysregs
31 * are live.
32 */
33static inline void __kvm_skip_instr(struct kvm_vcpu *vcpu)
34{
35 *vcpu_pc(vcpu) = read_sysreg_el2(SYS_ELR);
36 vcpu_gp_regs(vcpu)->pstate = read_sysreg_el2(SYS_SPSR);
37
38 kvm_skip_instr(vcpu);
39
40 write_sysreg_el2(vcpu_gp_regs(vcpu)->pstate, SYS_SPSR);
41 write_sysreg_el2(*vcpu_pc(vcpu), SYS_ELR);
42}
43
44/*
45 * Skip an instruction while host sysregs are live.
46 * Assumes host is always 64-bit.
47 */
48static inline void kvm_skip_host_instr(void)
49{
50 write_sysreg_el2(read_sysreg_el2(SYS_ELR) + 4, SYS_ELR);
51}
52
53#endif
54

source code of linux/arch/arm64/kvm/hyp/include/hyp/adjust_pc.h