xref: /linux/arch/arm64/kvm/hyp/hyp-entry.S (revision 5f05a72aed023e5824eebb2542b5397cb89188f4)
1/*
2 * Copyright (C) 2015 - ARM Ltd
3 * Author: Marc Zyngier <marc.zyngier@arm.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
16 */
17
18#include <linux/linkage.h>
19
20#include <asm/alternative.h>
21#include <asm/assembler.h>
22#include <asm/cpufeature.h>
23#include <asm/kvm_arm.h>
24#include <asm/kvm_asm.h>
25#include <asm/kvm_mmu.h>
26
27	.text
28	.pushsection	.hyp.text, "ax"
29
30.macro	save_x0_to_x3
31	stp	x0, x1, [sp, #-16]!
32	stp	x2, x3, [sp, #-16]!
33.endm
34
35.macro	restore_x0_to_x3
36	ldp	x2, x3, [sp], #16
37	ldp	x0, x1, [sp], #16
38.endm
39
40.macro do_el2_call
41	/*
42	 * Shuffle the parameters before calling the function
43	 * pointed to in x0. Assumes parameters in x[1,2,3].
44	 */
45	sub	sp, sp, #16
46	str	lr, [sp]
47	mov	lr, x0
48	mov	x0, x1
49	mov	x1, x2
50	mov	x2, x3
51	blr	lr
52	ldr	lr, [sp]
53	add	sp, sp, #16
54.endm
55
56ENTRY(__vhe_hyp_call)
57	do_el2_call
58	/*
59	 * We used to rely on having an exception return to get
60	 * an implicit isb. In the E2H case, we don't have it anymore.
61	 * rather than changing all the leaf functions, just do it here
62	 * before returning to the rest of the kernel.
63	 */
64	isb
65	ret
66ENDPROC(__vhe_hyp_call)
67
68el1_sync:				// Guest trapped into EL2
69	save_x0_to_x3
70
71alternative_if_not ARM64_HAS_VIRT_HOST_EXTN
72	mrs	x1, esr_el2
73alternative_else
74	mrs	x1, esr_el1
75alternative_endif
76	lsr	x2, x1, #ESR_ELx_EC_SHIFT
77
78	cmp	x2, #ESR_ELx_EC_HVC64
79	b.ne	el1_trap
80
81	mrs	x3, vttbr_el2		// If vttbr is valid, the 64bit guest
82	cbnz	x3, el1_trap		// called HVC
83
84	/* Here, we're pretty sure the host called HVC. */
85	restore_x0_to_x3
86
87	/* Check for __hyp_get_vectors */
88	cbnz	x0, 1f
89	mrs	x0, vbar_el2
90	b	2f
91
921:
93	/*
94	 * Perform the EL2 call
95	 */
96	kern_hyp_va	x0
97	do_el2_call
98
992:	eret
100
101el1_trap:
102	/*
103	 * x1: ESR
104	 * x2: ESR_EC
105	 */
106
107	/* Guest accessed VFP/SIMD registers, save host, restore Guest */
108	cmp	x2, #ESR_ELx_EC_FP_ASIMD
109	b.eq	__fpsimd_guest_restore
110
111	mrs	x0, tpidr_el2
112	mov	x1, #ARM_EXCEPTION_TRAP
113	b	__guest_exit
114
115el1_irq:
116	save_x0_to_x3
117	mrs	x0, tpidr_el2
118	mov	x1, #ARM_EXCEPTION_IRQ
119	b	__guest_exit
120
121ENTRY(__hyp_do_panic)
122	mov	lr, #(PSR_F_BIT | PSR_I_BIT | PSR_A_BIT | PSR_D_BIT |\
123		      PSR_MODE_EL1h)
124	msr	spsr_el2, lr
125	ldr	lr, =panic
126	msr	elr_el2, lr
127	eret
128ENDPROC(__hyp_do_panic)
129
130.macro invalid_vector	label, target = __hyp_panic
131	.align	2
132\label:
133	b \target
134ENDPROC(\label)
135.endm
136
137	/* None of these should ever happen */
138	invalid_vector	el2t_sync_invalid
139	invalid_vector	el2t_irq_invalid
140	invalid_vector	el2t_fiq_invalid
141	invalid_vector	el2t_error_invalid
142	invalid_vector	el2h_sync_invalid
143	invalid_vector	el2h_irq_invalid
144	invalid_vector	el2h_fiq_invalid
145	invalid_vector	el2h_error_invalid
146	invalid_vector	el1_sync_invalid
147	invalid_vector	el1_irq_invalid
148	invalid_vector	el1_fiq_invalid
149	invalid_vector	el1_error_invalid
150
151	.ltorg
152
153	.align 11
154
155ENTRY(__kvm_hyp_vector)
156	ventry	el2t_sync_invalid		// Synchronous EL2t
157	ventry	el2t_irq_invalid		// IRQ EL2t
158	ventry	el2t_fiq_invalid		// FIQ EL2t
159	ventry	el2t_error_invalid		// Error EL2t
160
161	ventry	el2h_sync_invalid		// Synchronous EL2h
162	ventry	el2h_irq_invalid		// IRQ EL2h
163	ventry	el2h_fiq_invalid		// FIQ EL2h
164	ventry	el2h_error_invalid		// Error EL2h
165
166	ventry	el1_sync			// Synchronous 64-bit EL1
167	ventry	el1_irq				// IRQ 64-bit EL1
168	ventry	el1_fiq_invalid			// FIQ 64-bit EL1
169	ventry	el1_error_invalid		// Error 64-bit EL1
170
171	ventry	el1_sync			// Synchronous 32-bit EL1
172	ventry	el1_irq				// IRQ 32-bit EL1
173	ventry	el1_fiq_invalid			// FIQ 32-bit EL1
174	ventry	el1_error_invalid		// Error 32-bit EL1
175ENDPROC(__kvm_hyp_vector)
176