xref: /openbmc/linux/arch/arm64/include/asm/kvm_hyp.h (revision f837453d0e10e9dd2e4444a940ccef1ed3cb243a)
113720a56SMarc Zyngier /*
213720a56SMarc Zyngier  * Copyright (C) 2015 - ARM Ltd
313720a56SMarc Zyngier  * Author: Marc Zyngier <marc.zyngier@arm.com>
413720a56SMarc Zyngier  *
513720a56SMarc Zyngier  * This program is free software; you can redistribute it and/or modify
613720a56SMarc Zyngier  * it under the terms of the GNU General Public License version 2 as
713720a56SMarc Zyngier  * published by the Free Software Foundation.
813720a56SMarc Zyngier  *
913720a56SMarc Zyngier  * This program is distributed in the hope that it will be useful,
1013720a56SMarc Zyngier  * but WITHOUT ANY WARRANTY; without even the implied warranty of
1113720a56SMarc Zyngier  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1213720a56SMarc Zyngier  * GNU General Public License for more details.
1313720a56SMarc Zyngier  *
1413720a56SMarc Zyngier  * You should have received a copy of the GNU General Public License
1513720a56SMarc Zyngier  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
1613720a56SMarc Zyngier  */
1713720a56SMarc Zyngier 
1813720a56SMarc Zyngier #ifndef __ARM64_KVM_HYP_H__
1913720a56SMarc Zyngier #define __ARM64_KVM_HYP_H__
2013720a56SMarc Zyngier 
2113720a56SMarc Zyngier #include <linux/compiler.h>
2213720a56SMarc Zyngier #include <linux/kvm_host.h>
2313720a56SMarc Zyngier #include <asm/sysreg.h>
2413720a56SMarc Zyngier 
2513720a56SMarc Zyngier #define __hyp_text __section(.hyp.text) notrace
2613720a56SMarc Zyngier 
2713720a56SMarc Zyngier #define read_sysreg_elx(r,nvh,vh)					\
2813720a56SMarc Zyngier 	({								\
2913720a56SMarc Zyngier 		u64 reg;						\
3013720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##nvh),\
3113720a56SMarc Zyngier 					 "mrs_s %0, " __stringify(r##vh),\
3213720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
3313720a56SMarc Zyngier 			     : "=r" (reg));				\
3413720a56SMarc Zyngier 		reg;							\
3513720a56SMarc Zyngier 	})
3613720a56SMarc Zyngier 
3713720a56SMarc Zyngier #define write_sysreg_elx(v,r,nvh,vh)					\
3813720a56SMarc Zyngier 	do {								\
3913720a56SMarc Zyngier 		u64 __val = (u64)(v);					\
4013720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("msr " __stringify(r##nvh) ", %x0",\
4113720a56SMarc Zyngier 					 "msr_s " __stringify(r##vh) ", %x0",\
4213720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
4313720a56SMarc Zyngier 					 : : "rZ" (__val));		\
4413720a56SMarc Zyngier 	} while (0)
4513720a56SMarc Zyngier 
4613720a56SMarc Zyngier /*
4713720a56SMarc Zyngier  * Unified accessors for registers that have a different encoding
4813720a56SMarc Zyngier  * between VHE and non-VHE. They must be specified without their "ELx"
4913720a56SMarc Zyngier  * encoding.
5013720a56SMarc Zyngier  */
5113720a56SMarc Zyngier #define read_sysreg_el2(r)						\
5213720a56SMarc Zyngier 	({								\
5313720a56SMarc Zyngier 		u64 reg;						\
5413720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##_EL2),\
5513720a56SMarc Zyngier 					 "mrs %0, " __stringify(r##_EL1),\
5613720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
5713720a56SMarc Zyngier 			     : "=r" (reg));				\
5813720a56SMarc Zyngier 		reg;							\
5913720a56SMarc Zyngier 	})
6013720a56SMarc Zyngier 
6113720a56SMarc Zyngier #define write_sysreg_el2(v,r)						\
6213720a56SMarc Zyngier 	do {								\
6313720a56SMarc Zyngier 		u64 __val = (u64)(v);					\
6413720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("msr " __stringify(r##_EL2) ", %x0",\
6513720a56SMarc Zyngier 					 "msr " __stringify(r##_EL1) ", %x0",\
6613720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
6713720a56SMarc Zyngier 					 : : "rZ" (__val));		\
6813720a56SMarc Zyngier 	} while (0)
6913720a56SMarc Zyngier 
7013720a56SMarc Zyngier #define read_sysreg_el0(r)	read_sysreg_elx(r, _EL0, _EL02)
7113720a56SMarc Zyngier #define write_sysreg_el0(v,r)	write_sysreg_elx(v, r, _EL0, _EL02)
7213720a56SMarc Zyngier #define read_sysreg_el1(r)	read_sysreg_elx(r, _EL1, _EL12)
7313720a56SMarc Zyngier #define write_sysreg_el1(v,r)	write_sysreg_elx(v, r, _EL1, _EL12)
7413720a56SMarc Zyngier 
7513720a56SMarc Zyngier /* The VHE specific system registers and their encoding */
7613720a56SMarc Zyngier #define sctlr_EL12              sys_reg(3, 5, 1, 0, 0)
7713720a56SMarc Zyngier #define cpacr_EL12              sys_reg(3, 5, 1, 0, 2)
7813720a56SMarc Zyngier #define ttbr0_EL12              sys_reg(3, 5, 2, 0, 0)
7913720a56SMarc Zyngier #define ttbr1_EL12              sys_reg(3, 5, 2, 0, 1)
8013720a56SMarc Zyngier #define tcr_EL12                sys_reg(3, 5, 2, 0, 2)
8113720a56SMarc Zyngier #define afsr0_EL12              sys_reg(3, 5, 5, 1, 0)
8213720a56SMarc Zyngier #define afsr1_EL12              sys_reg(3, 5, 5, 1, 1)
8313720a56SMarc Zyngier #define esr_EL12                sys_reg(3, 5, 5, 2, 0)
8413720a56SMarc Zyngier #define far_EL12                sys_reg(3, 5, 6, 0, 0)
8513720a56SMarc Zyngier #define mair_EL12               sys_reg(3, 5, 10, 2, 0)
8613720a56SMarc Zyngier #define amair_EL12              sys_reg(3, 5, 10, 3, 0)
8713720a56SMarc Zyngier #define vbar_EL12               sys_reg(3, 5, 12, 0, 0)
8813720a56SMarc Zyngier #define contextidr_EL12         sys_reg(3, 5, 13, 0, 1)
8913720a56SMarc Zyngier #define cntkctl_EL12            sys_reg(3, 5, 14, 1, 0)
9013720a56SMarc Zyngier #define cntp_tval_EL02          sys_reg(3, 5, 14, 2, 0)
9113720a56SMarc Zyngier #define cntp_ctl_EL02           sys_reg(3, 5, 14, 2, 1)
9213720a56SMarc Zyngier #define cntp_cval_EL02          sys_reg(3, 5, 14, 2, 2)
9313720a56SMarc Zyngier #define cntv_tval_EL02          sys_reg(3, 5, 14, 3, 0)
9413720a56SMarc Zyngier #define cntv_ctl_EL02           sys_reg(3, 5, 14, 3, 1)
9513720a56SMarc Zyngier #define cntv_cval_EL02          sys_reg(3, 5, 14, 3, 2)
9613720a56SMarc Zyngier #define spsr_EL12               sys_reg(3, 5, 4, 0, 0)
9713720a56SMarc Zyngier #define elr_EL12                sys_reg(3, 5, 4, 0, 1)
9813720a56SMarc Zyngier 
9913720a56SMarc Zyngier /**
10013720a56SMarc Zyngier  * hyp_alternate_select - Generates patchable code sequences that are
10113720a56SMarc Zyngier  * used to switch between two implementations of a function, depending
10213720a56SMarc Zyngier  * on the availability of a feature.
10313720a56SMarc Zyngier  *
10413720a56SMarc Zyngier  * @fname: a symbol name that will be defined as a function returning a
10513720a56SMarc Zyngier  * function pointer whose type will match @orig and @alt
10613720a56SMarc Zyngier  * @orig: A pointer to the default function, as returned by @fname when
10713720a56SMarc Zyngier  * @cond doesn't hold
10813720a56SMarc Zyngier  * @alt: A pointer to the alternate function, as returned by @fname
10913720a56SMarc Zyngier  * when @cond holds
11013720a56SMarc Zyngier  * @cond: a CPU feature (as described in asm/cpufeature.h)
11113720a56SMarc Zyngier  */
11213720a56SMarc Zyngier #define hyp_alternate_select(fname, orig, alt, cond)			\
11313720a56SMarc Zyngier typeof(orig) * __hyp_text fname(void)					\
11413720a56SMarc Zyngier {									\
11513720a56SMarc Zyngier 	typeof(alt) *val = orig;					\
11613720a56SMarc Zyngier 	asm volatile(ALTERNATIVE("nop		\n",			\
11713720a56SMarc Zyngier 				 "mov	%0, %1	\n",			\
11813720a56SMarc Zyngier 				 cond)					\
11913720a56SMarc Zyngier 		     : "+r" (val) : "r" (alt));				\
12013720a56SMarc Zyngier 	return val;							\
12113720a56SMarc Zyngier }
12213720a56SMarc Zyngier 
12313720a56SMarc Zyngier void __vgic_v2_save_state(struct kvm_vcpu *vcpu);
12413720a56SMarc Zyngier void __vgic_v2_restore_state(struct kvm_vcpu *vcpu);
1253272f0d0SMarc Zyngier int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
12613720a56SMarc Zyngier 
12713720a56SMarc Zyngier void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
12813720a56SMarc Zyngier void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
12959da1cbfSMarc Zyngier int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
13013720a56SMarc Zyngier 
131688c50aaSChristoffer Dall void __timer_enable_traps(struct kvm_vcpu *vcpu);
132688c50aaSChristoffer Dall void __timer_disable_traps(struct kvm_vcpu *vcpu);
13313720a56SMarc Zyngier 
134*f837453dSChristoffer Dall void __sysreg_save_host_state_nvhe(struct kvm_cpu_context *ctxt);
135*f837453dSChristoffer Dall void __sysreg_restore_host_state_nvhe(struct kvm_cpu_context *ctxt);
136*f837453dSChristoffer Dall void __sysreg_save_guest_state_nvhe(struct kvm_cpu_context *ctxt);
137*f837453dSChristoffer Dall void __sysreg_restore_guest_state_nvhe(struct kvm_cpu_context *ctxt);
138*f837453dSChristoffer Dall void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
139*f837453dSChristoffer Dall void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
140*f837453dSChristoffer Dall void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
141*f837453dSChristoffer Dall void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt);
14213720a56SMarc Zyngier void __sysreg32_save_state(struct kvm_vcpu *vcpu);
14313720a56SMarc Zyngier void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
14413720a56SMarc Zyngier 
145014c4c77SChristoffer Dall void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
146014c4c77SChristoffer Dall void __debug_switch_to_host(struct kvm_vcpu *vcpu);
14713720a56SMarc Zyngier 
14813720a56SMarc Zyngier void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
14913720a56SMarc Zyngier void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
15013720a56SMarc Zyngier bool __fpsimd_enabled(void);
15113720a56SMarc Zyngier 
15213720a56SMarc Zyngier u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
15313720a56SMarc Zyngier void __noreturn __hyp_do_panic(unsigned long, ...);
15413720a56SMarc Zyngier 
15513720a56SMarc Zyngier #endif /* __ARM64_KVM_HYP_H__ */
15613720a56SMarc Zyngier 
157