xref: /openbmc/linux/arch/arm64/include/asm/kvm_hyp.h (revision caab277b1de0a22b675c4c95fc7b285ec2eb5bf5)
1*caab277bSThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-only */
213720a56SMarc Zyngier /*
313720a56SMarc Zyngier  * Copyright (C) 2015 - ARM Ltd
413720a56SMarc Zyngier  * Author: Marc Zyngier <marc.zyngier@arm.com>
513720a56SMarc Zyngier  */
613720a56SMarc Zyngier 
713720a56SMarc Zyngier #ifndef __ARM64_KVM_HYP_H__
813720a56SMarc Zyngier #define __ARM64_KVM_HYP_H__
913720a56SMarc Zyngier 
1013720a56SMarc Zyngier #include <linux/compiler.h>
1113720a56SMarc Zyngier #include <linux/kvm_host.h>
121e4448c5SMarc Zyngier #include <asm/alternative.h>
13e329fb75SChristoffer Dall #include <asm/kvm_mmu.h>
1413720a56SMarc Zyngier #include <asm/sysreg.h>
1513720a56SMarc Zyngier 
1613720a56SMarc Zyngier #define __hyp_text __section(.hyp.text) notrace
1713720a56SMarc Zyngier 
1813720a56SMarc Zyngier #define read_sysreg_elx(r,nvh,vh)					\
1913720a56SMarc Zyngier 	({								\
2013720a56SMarc Zyngier 		u64 reg;						\
2113720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##nvh),\
22be604c61SKees Cook 					 __mrs_s("%0", r##vh),		\
2313720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
2413720a56SMarc Zyngier 			     : "=r" (reg));				\
2513720a56SMarc Zyngier 		reg;							\
2613720a56SMarc Zyngier 	})
2713720a56SMarc Zyngier 
2813720a56SMarc Zyngier #define write_sysreg_elx(v,r,nvh,vh)					\
2913720a56SMarc Zyngier 	do {								\
3013720a56SMarc Zyngier 		u64 __val = (u64)(v);					\
3113720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("msr " __stringify(r##nvh) ", %x0",\
32be604c61SKees Cook 					 __msr_s(r##vh, "%x0"),		\
3313720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
3413720a56SMarc Zyngier 					 : : "rZ" (__val));		\
3513720a56SMarc Zyngier 	} while (0)
3613720a56SMarc Zyngier 
3713720a56SMarc Zyngier /*
3813720a56SMarc Zyngier  * Unified accessors for registers that have a different encoding
3913720a56SMarc Zyngier  * between VHE and non-VHE. They must be specified without their "ELx"
4013720a56SMarc Zyngier  * encoding.
4113720a56SMarc Zyngier  */
4213720a56SMarc Zyngier #define read_sysreg_el2(r)						\
4313720a56SMarc Zyngier 	({								\
4413720a56SMarc Zyngier 		u64 reg;						\
4513720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("mrs %0, " __stringify(r##_EL2),\
4613720a56SMarc Zyngier 					 "mrs %0, " __stringify(r##_EL1),\
4713720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
4813720a56SMarc Zyngier 			     : "=r" (reg));				\
4913720a56SMarc Zyngier 		reg;							\
5013720a56SMarc Zyngier 	})
5113720a56SMarc Zyngier 
5213720a56SMarc Zyngier #define write_sysreg_el2(v,r)						\
5313720a56SMarc Zyngier 	do {								\
5413720a56SMarc Zyngier 		u64 __val = (u64)(v);					\
5513720a56SMarc Zyngier 		asm volatile(ALTERNATIVE("msr " __stringify(r##_EL2) ", %x0",\
5613720a56SMarc Zyngier 					 "msr " __stringify(r##_EL1) ", %x0",\
5713720a56SMarc Zyngier 					 ARM64_HAS_VIRT_HOST_EXTN)	\
5813720a56SMarc Zyngier 					 : : "rZ" (__val));		\
5913720a56SMarc Zyngier 	} while (0)
6013720a56SMarc Zyngier 
6113720a56SMarc Zyngier #define read_sysreg_el0(r)	read_sysreg_elx(r, _EL0, _EL02)
6213720a56SMarc Zyngier #define write_sysreg_el0(v,r)	write_sysreg_elx(v, r, _EL0, _EL02)
6313720a56SMarc Zyngier #define read_sysreg_el1(r)	read_sysreg_elx(r, _EL1, _EL12)
6413720a56SMarc Zyngier #define write_sysreg_el1(v,r)	write_sysreg_elx(v, r, _EL1, _EL12)
6513720a56SMarc Zyngier 
6613720a56SMarc Zyngier /* The VHE specific system registers and their encoding */
6713720a56SMarc Zyngier #define sctlr_EL12              sys_reg(3, 5, 1, 0, 0)
6813720a56SMarc Zyngier #define cpacr_EL12              sys_reg(3, 5, 1, 0, 2)
6913720a56SMarc Zyngier #define ttbr0_EL12              sys_reg(3, 5, 2, 0, 0)
7013720a56SMarc Zyngier #define ttbr1_EL12              sys_reg(3, 5, 2, 0, 1)
7113720a56SMarc Zyngier #define tcr_EL12                sys_reg(3, 5, 2, 0, 2)
7213720a56SMarc Zyngier #define afsr0_EL12              sys_reg(3, 5, 5, 1, 0)
7313720a56SMarc Zyngier #define afsr1_EL12              sys_reg(3, 5, 5, 1, 1)
7413720a56SMarc Zyngier #define esr_EL12                sys_reg(3, 5, 5, 2, 0)
7513720a56SMarc Zyngier #define far_EL12                sys_reg(3, 5, 6, 0, 0)
7613720a56SMarc Zyngier #define mair_EL12               sys_reg(3, 5, 10, 2, 0)
7713720a56SMarc Zyngier #define amair_EL12              sys_reg(3, 5, 10, 3, 0)
7813720a56SMarc Zyngier #define vbar_EL12               sys_reg(3, 5, 12, 0, 0)
7913720a56SMarc Zyngier #define contextidr_EL12         sys_reg(3, 5, 13, 0, 1)
8013720a56SMarc Zyngier #define cntkctl_EL12            sys_reg(3, 5, 14, 1, 0)
8113720a56SMarc Zyngier #define cntp_tval_EL02          sys_reg(3, 5, 14, 2, 0)
8213720a56SMarc Zyngier #define cntp_ctl_EL02           sys_reg(3, 5, 14, 2, 1)
8313720a56SMarc Zyngier #define cntp_cval_EL02          sys_reg(3, 5, 14, 2, 2)
8413720a56SMarc Zyngier #define cntv_tval_EL02          sys_reg(3, 5, 14, 3, 0)
8513720a56SMarc Zyngier #define cntv_ctl_EL02           sys_reg(3, 5, 14, 3, 1)
8613720a56SMarc Zyngier #define cntv_cval_EL02          sys_reg(3, 5, 14, 3, 2)
8713720a56SMarc Zyngier #define spsr_EL12               sys_reg(3, 5, 4, 0, 0)
8813720a56SMarc Zyngier #define elr_EL12                sys_reg(3, 5, 4, 0, 1)
8913720a56SMarc Zyngier 
9013720a56SMarc Zyngier /**
9113720a56SMarc Zyngier  * hyp_alternate_select - Generates patchable code sequences that are
9213720a56SMarc Zyngier  * used to switch between two implementations of a function, depending
9313720a56SMarc Zyngier  * on the availability of a feature.
9413720a56SMarc Zyngier  *
9513720a56SMarc Zyngier  * @fname: a symbol name that will be defined as a function returning a
9613720a56SMarc Zyngier  * function pointer whose type will match @orig and @alt
9713720a56SMarc Zyngier  * @orig: A pointer to the default function, as returned by @fname when
9813720a56SMarc Zyngier  * @cond doesn't hold
9913720a56SMarc Zyngier  * @alt: A pointer to the alternate function, as returned by @fname
10013720a56SMarc Zyngier  * when @cond holds
10113720a56SMarc Zyngier  * @cond: a CPU feature (as described in asm/cpufeature.h)
10213720a56SMarc Zyngier  */
10313720a56SMarc Zyngier #define hyp_alternate_select(fname, orig, alt, cond)			\
10413720a56SMarc Zyngier typeof(orig) * __hyp_text fname(void)					\
10513720a56SMarc Zyngier {									\
10613720a56SMarc Zyngier 	typeof(alt) *val = orig;					\
10713720a56SMarc Zyngier 	asm volatile(ALTERNATIVE("nop		\n",			\
10813720a56SMarc Zyngier 				 "mov	%0, %1	\n",			\
10913720a56SMarc Zyngier 				 cond)					\
11013720a56SMarc Zyngier 		     : "+r" (val) : "r" (alt));				\
11113720a56SMarc Zyngier 	return val;							\
11213720a56SMarc Zyngier }
11313720a56SMarc Zyngier 
1143272f0d0SMarc Zyngier int __vgic_v2_perform_cpuif_access(struct kvm_vcpu *vcpu);
11513720a56SMarc Zyngier 
11613720a56SMarc Zyngier void __vgic_v3_save_state(struct kvm_vcpu *vcpu);
11713720a56SMarc Zyngier void __vgic_v3_restore_state(struct kvm_vcpu *vcpu);
1182d0e63e0SChristoffer Dall void __vgic_v3_activate_traps(struct kvm_vcpu *vcpu);
1192d0e63e0SChristoffer Dall void __vgic_v3_deactivate_traps(struct kvm_vcpu *vcpu);
120923a2e30SChristoffer Dall void __vgic_v3_save_aprs(struct kvm_vcpu *vcpu);
121923a2e30SChristoffer Dall void __vgic_v3_restore_aprs(struct kvm_vcpu *vcpu);
12259da1cbfSMarc Zyngier int __vgic_v3_perform_cpuif_access(struct kvm_vcpu *vcpu);
12313720a56SMarc Zyngier 
124688c50aaSChristoffer Dall void __timer_enable_traps(struct kvm_vcpu *vcpu);
125688c50aaSChristoffer Dall void __timer_disable_traps(struct kvm_vcpu *vcpu);
12613720a56SMarc Zyngier 
1274cdecabaSChristoffer Dall void __sysreg_save_state_nvhe(struct kvm_cpu_context *ctxt);
1284cdecabaSChristoffer Dall void __sysreg_restore_state_nvhe(struct kvm_cpu_context *ctxt);
129f837453dSChristoffer Dall void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt);
130f837453dSChristoffer Dall void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt);
131f837453dSChristoffer Dall void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt);
132f837453dSChristoffer Dall void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt);
13313720a56SMarc Zyngier void __sysreg32_save_state(struct kvm_vcpu *vcpu);
13413720a56SMarc Zyngier void __sysreg32_restore_state(struct kvm_vcpu *vcpu);
13513720a56SMarc Zyngier 
136014c4c77SChristoffer Dall void __debug_switch_to_guest(struct kvm_vcpu *vcpu);
137014c4c77SChristoffer Dall void __debug_switch_to_host(struct kvm_vcpu *vcpu);
13813720a56SMarc Zyngier 
13913720a56SMarc Zyngier void __fpsimd_save_state(struct user_fpsimd_state *fp_regs);
14013720a56SMarc Zyngier void __fpsimd_restore_state(struct user_fpsimd_state *fp_regs);
14113720a56SMarc Zyngier 
142a2465629SChristoffer Dall void activate_traps_vhe_load(struct kvm_vcpu *vcpu);
143a2465629SChristoffer Dall void deactivate_traps_vhe_put(void);
144a2465629SChristoffer Dall 
14513720a56SMarc Zyngier u64 __guest_enter(struct kvm_vcpu *vcpu, struct kvm_cpu_context *host_ctxt);
14613720a56SMarc Zyngier void __noreturn __hyp_do_panic(unsigned long, ...);
14713720a56SMarc Zyngier 
1489f98ddd6SSuzuki K Poulose /*
1499f98ddd6SSuzuki K Poulose  * Must be called from hyp code running at EL2 with an updated VTTBR
1509f98ddd6SSuzuki K Poulose  * and interrupts disabled.
1519f98ddd6SSuzuki K Poulose  */
1529f98ddd6SSuzuki K Poulose static __always_inline void __hyp_text __load_guest_stage2(struct kvm *kvm)
1539f98ddd6SSuzuki K Poulose {
1547665f3a8SSuzuki K Poulose 	write_sysreg(kvm->arch.vtcr, vtcr_el2);
155e329fb75SChristoffer Dall 	write_sysreg(kvm_get_vttbr(kvm), vttbr_el2);
1561e4448c5SMarc Zyngier 
1571e4448c5SMarc Zyngier 	/*
1581e4448c5SMarc Zyngier 	 * ARM erratum 1165522 requires the actual execution of the above
1591e4448c5SMarc Zyngier 	 * before we can switch to the EL1/EL0 translation regime used by
1601e4448c5SMarc Zyngier 	 * the guest.
1611e4448c5SMarc Zyngier 	 */
1621e4448c5SMarc Zyngier 	asm(ALTERNATIVE("nop", "isb", ARM64_WORKAROUND_1165522));
1639f98ddd6SSuzuki K Poulose }
1649f98ddd6SSuzuki K Poulose 
16513720a56SMarc Zyngier #endif /* __ARM64_KVM_HYP_H__ */
16613720a56SMarc Zyngier 
167