xref: /openbmc/linux/arch/arm64/include/asm/kvm_hyp.h (revision 1e4448c5ddbe93ab6070160f094f49e7c95477e6)
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>
23*1e4448c5SMarc Zyngier #include <asm/alternative.h>
2413720a56SMarc Zyngier #include <asm/sysreg.h>
2513720a56SMarc Zyngier 
2613720a56SMarc Zyngier #define __hyp_text __section(.hyp.text) notrace
2713720a56SMarc Zyngier 
2813720a56SMarc Zyngier #define read_sysreg_elx(r,nvh,vh)					\
2913720a56SMarc Zyngier 	({								\
3013720a56SMarc Zyngier 		u64 reg;						\
3113720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##nvh),\
3213720a56SMarc Zyngier 					 "mrs_s %0, " __stringify(r##vh),\
3313720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
3413720a56SMarc Zyngier 			     : "=r" (reg));				\
3513720a56SMarc Zyngier 		reg;							\
3613720a56SMarc Zyngier 	})
3713720a56SMarc Zyngier 
3813720a56SMarc Zyngier #define write_sysreg_elx(v,r,nvh,vh)					\
3913720a56SMarc Zyngier 	do {								\
4013720a56SMarc Zyngier 		u64 __val = (u64)(v);					\
4113720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("msr " __stringify(r##nvh) ", %x0",\
4213720a56SMarc Zyngier 					 "msr_s " __stringify(r##vh) ", %x0",\
4313720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
4413720a56SMarc Zyngier 					 : : "rZ" (__val));		\
4513720a56SMarc Zyngier 	} while (0)
4613720a56SMarc Zyngier 
4713720a56SMarc Zyngier /*
4813720a56SMarc Zyngier  * Unified accessors for registers that have a different encoding
4913720a56SMarc Zyngier  * between VHE and non-VHE. They must be specified without their "ELx"
5013720a56SMarc Zyngier  * encoding.
5113720a56SMarc Zyngier  */
5213720a56SMarc Zyngier #define read_sysreg_el2(r)						\
5313720a56SMarc Zyngier 	({								\
5413720a56SMarc Zyngier 		u64 reg;						\
5513720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##_EL2),\
5613720a56SMarc Zyngier 					 "mrs %0, " __stringify(r##_EL1),\
5713720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
5813720a56SMarc Zyngier 			     : "=r" (reg));				\
5913720a56SMarc Zyngier 		reg;							\
6013720a56SMarc Zyngier 	})
6113720a56SMarc Zyngier 
6213720a56SMarc Zyngier #define write_sysreg_el2(v,r)						\
6313720a56SMarc Zyngier 	do {								\
6413720a56SMarc Zyngier 		u64 __val = (u64)(v);					\
6513720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("msr " __stringify(r##_EL2) ", %x0",\
6613720a56SMarc Zyngier 					 "msr " __stringify(r##_EL1) ", %x0",\
6713720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
6813720a56SMarc Zyngier 					 : : "rZ" (__val));		\
6913720a56SMarc Zyngier 	} while (0)
7013720a56SMarc Zyngier 
7113720a56SMarc Zyngier #define read_sysreg_el0(r)	read_sysreg_elx(r, _EL0, _EL02)
7213720a56SMarc Zyngier #define write_sysreg_el0(v,r)	write_sysreg_elx(v, r, _EL0, _EL02)
7313720a56SMarc Zyngier #define read_sysreg_el1(r)	read_sysreg_elx(r, _EL1, _EL12)
7413720a56SMarc Zyngier #define write_sysreg_el1(v,r)	write_sysreg_elx(v, r, _EL1, _EL12)
7513720a56SMarc Zyngier 
7613720a56SMarc Zyngier /* The VHE specific system registers and their encoding */
7713720a56SMarc Zyngier #define sctlr_EL12              sys_reg(3, 5, 1, 0, 0)
7813720a56SMarc Zyngier #define cpacr_EL12              sys_reg(3, 5, 1, 0, 2)
7913720a56SMarc Zyngier #define ttbr0_EL12              sys_reg(3, 5, 2, 0, 0)
8013720a56SMarc Zyngier #define ttbr1_EL12              sys_reg(3, 5, 2, 0, 1)
8113720a56SMarc Zyngier #define tcr_EL12                sys_reg(3, 5, 2, 0, 2)
8213720a56SMarc Zyngier #define afsr0_EL12              sys_reg(3, 5, 5, 1, 0)
8313720a56SMarc Zyngier #define afsr1_EL12              sys_reg(3, 5, 5, 1, 1)
8413720a56SMarc Zyngier #define esr_EL12                sys_reg(3, 5, 5, 2, 0)
8513720a56SMarc Zyngier #define far_EL12                sys_reg(3, 5, 6, 0, 0)
8613720a56SMarc Zyngier #define mair_EL12               sys_reg(3, 5, 10, 2, 0)
8713720a56SMarc Zyngier #define amair_EL12              sys_reg(3, 5, 10, 3, 0)
8813720a56SMarc Zyngier #define vbar_EL12               sys_reg(3, 5, 12, 0, 0)
8913720a56SMarc Zyngier #define contextidr_EL12         sys_reg(3, 5, 13, 0, 1)
9013720a56SMarc Zyngier #define cntkctl_EL12            sys_reg(3, 5, 14, 1, 0)
9113720a56SMarc Zyngier #define cntp_tval_EL02          sys_reg(3, 5, 14, 2, 0)
9213720a56SMarc Zyngier #define cntp_ctl_EL02           sys_reg(3, 5, 14, 2, 1)
9313720a56SMarc Zyngier #define cntp_cval_EL02          sys_reg(3, 5, 14, 2, 2)
9413720a56SMarc Zyngier #define cntv_tval_EL02          sys_reg(3, 5, 14, 3, 0)
9513720a56SMarc Zyngier #define cntv_ctl_EL02           sys_reg(3, 5, 14, 3, 1)
9613720a56SMarc Zyngier #define cntv_cval_EL02          sys_reg(3, 5, 14, 3, 2)
9713720a56SMarc Zyngier #define spsr_EL12               sys_reg(3, 5, 4, 0, 0)
9813720a56SMarc Zyngier #define elr_EL12                sys_reg(3, 5, 4, 0, 1)
9913720a56SMarc Zyngier 
10013720a56SMarc Zyngier /**
10113720a56SMarc Zyngier  * hyp_alternate_select - Generates patchable code sequences that are
10213720a56SMarc Zyngier  * used to switch between two implementations of a function, depending
10313720a56SMarc Zyngier  * on the availability of a feature.
10413720a56SMarc Zyngier  *
10513720a56SMarc Zyngier  * @fname: a symbol name that will be defined as a function returning a
10613720a56SMarc Zyngier  * function pointer whose type will match @orig and @alt
10713720a56SMarc Zyngier  * @orig: A pointer to the default function, as returned by @fname when
10813720a56SMarc Zyngier  * @cond doesn't hold
10913720a56SMarc Zyngier  * @alt: A pointer to the alternate function, as returned by @fname
11013720a56SMarc Zyngier  * when @cond holds
11113720a56SMarc Zyngier  * @cond: a CPU feature (as described in asm/cpufeature.h)
11213720a56SMarc Zyngier  */
11313720a56SMarc Zyngier #define hyp_alternate_select(fname, orig, alt, cond)			\
11413720a56SMarc Zyngier typeof(orig) * __hyp_text fname(void)					\
11513720a56SMarc Zyngier {									\
11613720a56SMarc Zyngier 	typeof(alt) *val = orig;					\
11713720a56SMarc Zyngier 	asm volatile(ALTERNATIVE("nop		\n",			\
11813720a56SMarc Zyngier 				 "mov	%0, %1	\n",			\
11913720a56SMarc Zyngier 				 cond)					\
12013720a56SMarc Zyngier 		     : "+r" (val) : "r" (alt));				\
12113720a56SMarc Zyngier 	return val;							\
12213720a56SMarc Zyngier }
12313720a56SMarc Zyngier 
1243272f0d0SMarc Zyngier int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
12513720a56SMarc Zyngier 
12613720a56SMarc Zyngier void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
12713720a56SMarc Zyngier void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
1282d0e63e0SChristoffer Dall void __vgic_v3_activate_traps(struct kvm_vcpu *vcpu);
1292d0e63e0SChristoffer Dall void __vgic_v3_deactivate_traps(struct kvm_vcpu *vcpu);
130923a2e30SChristoffer Dall void __vgic_v3_save_aprs(struct kvm_vcpu *vcpu);
131923a2e30SChristoffer Dall void __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu);
13259da1cbfSMarc Zyngier int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
13313720a56SMarc Zyngier 
134688c50aaSChristoffer Dall void __timer_enable_traps(struct kvm_vcpu *vcpu);
135688c50aaSChristoffer Dall void __timer_disable_traps(struct kvm_vcpu *vcpu);
13613720a56SMarc Zyngier 
1374cdecabaSChristoffer Dall void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
1384cdecabaSChristoffer Dall void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
139f837453dSChristoffer Dall void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
140f837453dSChristoffer Dall void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
141f837453dSChristoffer Dall void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
142f837453dSChristoffer Dall void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt);
14313720a56SMarc Zyngier void __sysreg32_save_state(struct kvm_vcpu *vcpu);
14413720a56SMarc Zyngier void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
14513720a56SMarc Zyngier 
146014c4c77SChristoffer Dall void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
147014c4c77SChristoffer Dall void __debug_switch_to_host(struct kvm_vcpu *vcpu);
14813720a56SMarc Zyngier 
14913720a56SMarc Zyngier void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
15013720a56SMarc Zyngier void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
15113720a56SMarc Zyngier bool __fpsimd_enabled(void);
15213720a56SMarc Zyngier 
153a2465629SChristoffer Dall void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
154a2465629SChristoffer Dall void deactivate_traps_vhe_put(void);
155a2465629SChristoffer Dall 
15613720a56SMarc Zyngier u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
15713720a56SMarc Zyngier void __noreturn __hyp_do_panic(unsigned long, ...);
15813720a56SMarc Zyngier 
1599f98ddd6SSuzuki K Poulose /*
1609f98ddd6SSuzuki K Poulose  * Must be called from hyp code running at EL2 with an updated VTTBR
1619f98ddd6SSuzuki K Poulose  * and interrupts disabled.
1629f98ddd6SSuzuki K Poulose  */
1639f98ddd6SSuzuki K Poulose static __always_inline void __hyp_text __load_guest_stage2(struct kvm *kvm)
1649f98ddd6SSuzuki K Poulose {
1657665f3a8SSuzuki K Poulose 	write_sysreg(kvm->arch.vtcr, vtcr_el2);
1669f98ddd6SSuzuki K Poulose 	write_sysreg(kvm->arch.vttbr, vttbr_el2);
167*1e4448c5SMarc Zyngier 
168*1e4448c5SMarc Zyngier 	/*
169*1e4448c5SMarc Zyngier 	 * ARM erratum 1165522 requires the actual execution of the above
170*1e4448c5SMarc Zyngier 	 * before we can switch to the EL1/EL0 translation regime used by
171*1e4448c5SMarc Zyngier 	 * the guest.
172*1e4448c5SMarc Zyngier 	 */
173*1e4448c5SMarc Zyngier 	asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_1165522));
1749f98ddd6SSuzuki K Poulose }
1759f98ddd6SSuzuki K Poulose 
17613720a56SMarc Zyngier #endif /* __ARM64_KVM_HYP_H__ */
17713720a56SMarc Zyngier 
178